Problem displaying a triangle array/mesh

Hi all,

I am a beginner in JOGL, I spent almost 2 full days looking online tutorial, examples, etc…

The problem is that there is not so much material about JOGL, and among the results many stuff is outdated, for other programming languages and so on…

Well, I need to display a mesh/array of triangles


public class CudaImplementation implements GLEventListener{
         public static void main(String[] args) throws IOException{
               GLProfile profile = GLProfile.get(GLProfile.GL3);
               final GLCapabilities capabilities = new GLCapabilities(profile);
               GLCanvas canvas = new GLCanvas(capabilities);
        
               SwingUtilities.invokeLater(new Runnable() {
            
               @Override
               public void run() {
                    new CudaImplementation(capabilities);
               }
               });
}

public CudaImplementation(GLCapabilities capabilities) {
            // Initialize the GL component and the animator
        GLCanvas glComponent = new GLCanvas((GLCapabilitiesImmutable)capabilities);
        glComponent.setFocusable(true);
        glComponent.addGLEventListener(this);

        // Create the main frame 
        frame = new JFrame("JCuda / JOGL interaction sample");
        frame.addWindowListener(new WindowAdapter()
        {
            @Override
            public void windowClosing(WindowEvent e)
            {
                runExit();
            }
        });
        frame.setLayout(new BorderLayout());
        glComponent.setPreferredSize(new Dimension(800, 800));
        frame.add(glComponent, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
        glComponent.requestFocus();

    @Override
    public void init(GLAutoDrawable gLAutoDrawable) {
        
        // Perform the default GL initialization 
        GL3 gl = gLAutoDrawable.getGL().getGL3();
        gl.setSwapInterval(0);
        gl.glEnable(GL3.GL_DEPTH_TEST);
        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        //setupView(GLAutoDrawable);

        // Create the VBO containing the vertex data
        initVBO(gl);
    }

    @Override
    public void display(GLAutoDrawable gLAutoDrawable) {
        GL3 gl = gLAutoDrawable.getGL().getGL3();
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexArray);
        gl.glEnableClientState(GL3.GL_VERTEX_ARRAY_BINDING);
        gl.glDrawArrays(GL.GL_TRIANGLES, 0, array.size());
    }

FloatBuffer data = Buffers.newDirectFloatBuffer(size);
    
    private void initVBO(GL3 gl)
    {
        int buffer[] = new int[1];

        // Create the vertex buffer object
        gl.glGenBuffers(1, IntBuffer.wrap(buffer));
        vertexArray = buffer[0];

        // Initialize the vertex buffer object
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexArray);
        
        for(Triangle t : array) {
            data.put(t.x1);
            data.put(t.y1);
            data.put(t.z1);
            data.put(t.x2);
            data.put(t.y2);
            data.put(t.z2);
            data.put(t.x3);
            data.put(t.y3);
            data.put(t.z3);
        }
        data.rewind();
        
        // Fill the vertex buffer object
        gl.glBufferData(GL.GL_ARRAY_BUFFER, size * Sizeof.FLOAT, data, GL.GL_STATIC_DRAW);

        // data are in the GPU, data is no longer necessary
        data = null;
}

The problem is that I dont see anything, I guess the main reasons could be:

  • no color info in the Vertex Buffer Array (but when I used the glBegin/End it was displaying them white)
  • shall I need an animator?
  • shall I need to specify the view? (there is not a default one?)
  • OpenGL does not know which data, or better the memory layout, of the vertex buffer array data.

In OpenGL 2.x you just write

glVertexPointer(3,GL_FLOAT,16,0);

if you have:

  • 3 coordinates
  • float type
  • 16 the total length for triangle (vertex+color)
  • 0 the offset where the 3 coordinates start in this 16 Bytes

But in GL3 I dont have anything like that

Please I would need some help from people more skilled than me (and it is not difficult >.>)

Just discovered that in GL3 a VAO is mandatory although it seems superflous…

But unfortunately it still doesnt work…

  • For OpenGL3, you need a shader. There is no fixed functionality if you haven’t requested the compatibility profile (which defeats the purpose of OpenGL 3 in the first place IMO).
  • Use .flip(), not rewind() (Just make this a habit…).
  • You aren’t using your vertex array object. Just creating one without configuring it is about as productive as creating a texture handle and not allocating it. You need to setup your shader attribute bindings in your vertex array object, so that OpenGL knows what data to put in the shader variables. Obviously, you also have no shader. >_>

If you’re a beginner, drop OGL3 immediately. You don’t want to dive into shaders, buffer objects and vertex array objects when you’re a newbie. Look up some old tutorials on the Internet (preferably does using glBegin()-glEnd()) to get a basic knowledge of how it works. OpenGL 3 has removed 99% of the convenience functions that were in the previous OpenGL versions, forcing you to do everything manually. This is a lot more powerful as you can do everything you could with the earlier OpenGL versions but with a lot more flexibility and better performance, but it takes hundreds of lines of code just to get a triangle on the screen.

PS: I also recommend LWJGL. It is more similar to standard C/C++ OpenGL so it’s easier to port other tutorials to Java with it.

EDIT2: To answer your color question: There is no built-in color variable in OpenGL 3. If you want a color, you create your own shader attribute for it and store bindings between data and variables in your vertex array buffer. When you then call glDrawArrays(…) or whatever, the data is loaded into the shader and you can treat it as whatever you want (in this case a color). This is what OpenGL has always done for you since almost everything needs a color, but now you have to do it manually.

This is something that I should have known before, but I never found, thank! :slight_smile:

However, I already did many tutorials with the glBegin/End and since I have milions of triangles I need to implement some fast method, and I read that VBO is the solution… is it right?

However I think I am forced to use JOGL, since I need also the binding for Cuda

The real problem is interacting too much with the graphics driver, limiting the performance you can get out of your graphics card by the very high CPU overhead of actually issuing commands. glBegin()-glEnd() is especially tricky to implement on the driver side, as there are so many different attributes that have to be buffered and sent to the GPU. So first it’s slow to handle each vertex, then you need an expensive native call to the OpenGL call to submit it to the driver, which then tries store the vertex data as efficiently as possible.

The least intrusive way of implementing this is display lists. Instead of calling all these OpenGL commands, you create a display list which contain those commands and simply tell the driver to run the display list each frame. This allows the driver to optimize the vertex data storing and reduces the number of OpenGL calls to a single call. It’s also very simple to implement.

Let’s say you have the following code. I’ve stripped out all GL.blah to only include the raw OpenGL commands. Some command may be slightly different in JOGL though.


//Draw a red triangle
public void renderTriangle(){
    glColor3f(1, 0, 0);
    glBegin(GL_TRIANGLES);
    glVertex2f(0, 0);
    glVertex2f(1, 0);
    glVertex2f(0, 1);
    glEnd();
}

Let’s say these OpenGL commands do not change between frames. We could optimize this to use a display list instead:


//When initializing the game:
//Save this ID
int listID = glGenLists(1); //This call may look different in JOGL (this is from LWJGL)
glNewList(listID, GL_COMPILE); //This is like glBegin() but for display lists

//Commands between glNewList(...) and glEndList() will not be processed immediately. Instead they will be stored in the display list
renderTriangle(); 

glEndList(); //This is like glEnd() for display lists



//When rendering:

glCallList(listID); //Equal to calling renderTriangle() directly.

This is obviously most effective when rendering big meshes. The above example would not see much of a performance gain, as it’s only 3 vertices. We would however see a noticeable performance if we called this method many times.

At first it might seem like this can only be used for static geometry, but it can be moved around in any way you want by modifying the transformation matrix between calls. For example, to draw two triangles at two different locations, we can glTranslate to the first position, call the display list, restore the matrix and glTranslate to a new position and call the display list again. Note that some special calls can not be stored in a display list. Sadly, display lists have been deprecated in OpenGL 3.0

There are other ways of drawing things faster. You can also use vertex arrays (not the same as vertex array objects). They are very easy to use too, but requires us to completely rewrite the above triangle drawing code:

//When initializing the game:
FloatBuffer vertexData = BufferUtils.createFloatBuffer(3*2); //If you allocate it manually, make sure it has the correct byte order!
vertexData.put(new float[]{
    0, 0,
    1, 0,
    0, 1
});
vertexData.flip(); //DO NOT FORGET THIS!!!!!!!!


//When rendering:
glColor3f(1, 0, 0);

glVertexPointer(2, 0, vertexData); 
//2 means that we have two floats per vertex (glVertex2f() <- that 2)
//0 means that the data is tightly packed, so no data should be skipped
//vertexData contains the coordinates we would've sent with glVertex2f() in a FloatBuffer.

glEnableClientState(GL_VERTEX_ARRAY);
//This tells OpenGL to read data from vertexData instead of the last call to glVertexXX(...).
//For example, we have not enabled GL_COLOR_ARRAY, so we can use glColor3f to set all vertices to red above.

glDrawArrays(GL_TRIANGLES, 0, 3);
//GL_TRIANGLES specifies the primitive type
//0 is the first vertex to process.
//3 is the number of vertices to process, NOT THE NUMBER OF PRIMITIVES.

I may have forgotten something as I haven’t used many of these pre-OpenGL 3 ways of rendering in a while, and I wrote all this in the post (untested), so beware of mistakes from me… xd

Thanks theagentd, you are surprisingly exhaustive! :o

I would decide to use then the Vertex Array…

However I found that the BufferUtils.createFloatBuffer cannot be found and I am using then the GLBuffers.newDirectIntBuffer (http://stackoverflow.com/questions/3746759/java-bufferutil)

I will let you know, however thanks! :wink:

That would be the equivalent class in JOGL, but don’t create an IntBuffer! Create a FloatBuffer! =S

The only performance problem with vertex arrays is that you send the vertex data from RAM to the GPU each frame. This is where vertex buffer objects (VBOs) come in. With them you can store the vertex data in the GPU’s video memory (VRAM), and tell your draw functions to read from it instead. However, you have 4GBs per second in bandwidth to play with, equaling about 68MBs of data per frame at 60 FPS, so you don’t really have to worry about it unless you’re making Crysis.

Graphics is my interest, so I just find it fun to help people when it comes to OpenGL. =D

Yeah sure :stuck_out_tongue:

Ah, that’s why, I really wanted I would have met u before ^^

Not yet baby 8)

xD

Btw, regarding the glVertexPointer, I have three ones:

public void glVertexPointer(GLArrayData glad)

public void glVertexPointer(int i, int i1, int i2, Buffer buffer)

public void glVertexPointer(int i, int i1, int i2, long l)

Which should I use?

( http://download.java.net/media/jogl/jogl-2.x-docs/javax/media/opengl/fixedfunc/GLPointerFunc.html )

I guess the second one since I have a Buffer pointer…

Something like this:

gl.glVertexPointer(size, GL_FLOAT, 0, data);

But damn, GL_FLOAT cannot be found >.>

Edit: I was joking ^^

GL.GL_FLOAT

two things

  • vertexData = GLBuffers.newDirectFloatBuffer(triangleNumber33); fails when there are 2 milions of (float 3d) triangles, out of memory
  • how can I do if I want to add color? I need a normal vector right?

Should I do something like this:



      normalData = GLBuffers.newDirectFloatBuffer(triangleNumber*3);
      
      for(int i=0; i<triangleNumber; i++) {
          Triangle tmp = triangleArray.get(i);
          normalData.put(new float[]{tmp.nx, tmp.ny, tmp.nz});
      }
      normalData.flip();


        gl.glEnableClientState(GL2.GL_NORMAL_ARRAY);
        gl.glNormalPointer(GL.GL_FLOAT, 0, normalData);

?

Direct memory is a different pool from the regular JVM heap, and IIRC defaults to 64Mb. Two million triangles would come to about 68Mb, so that’s probably why it’s failing (I assume you get some kind of out-of-memory exception?).

You can increase the amount of direct memory with a vm arg. Try something like:

-XX:MaxDirectMemorySize=256M

[quote]Init
Exception in thread “AWT-EventQueue-0” java.lang.OutOfMemoryError
at sun.misc.Unsafe.allocateMemory(Native Method)
Reshape
Reshape
Display

A fatal error has been detected by the Java Runtime Environment:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6b2efd37, pid=3872, tid=5584

JRE version: 6.0_18-b07

Java VM: Java HotSpot™ Client VM (16.0-b13 mixed mode windows-x86 )

Problematic frame:

C 0x6b2efd37

An error report file with more information is saved as:

H:\Dokumente und Einstellungen\gbarbieri\Eigene Dateien\NetBeansProjects\JOpenGL with Cuda\hs_err_pid3872.log

at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:99)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:288)
at com.jogamp.common.nio.Buffers.newDirectByteBuffer(Buffers.java:69)
at com.jogamp.common.nio.Buffers.newDirectFloatBuffer(Buffers.java:111)
at Viewer.initVertexArray(Viewer.java:179)
at Viewer.init(Viewer.java:119)
at jogamp.opengl.GLDrawableHelper.init(GLDrawableHelper.java:135)

If you would like to submit a bug report, please visit:

http://java.sun.com/webapps/bugreport/crash.jsp

The crash happened outside the Java Virtual Machine in native code.

See problematic frame for where to report the bug.

at jogamp.opengl.GLDrawableHelper.init(GLDrawableHelper.java:154)
at javax.media.opengl.awt.GLCanvas$InitAction.run(GLCanvas.java:886)
at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:379)
at javax.media.opengl.awt.GLCanvas.maybeDoSingleThreadedWorkaround(GLCanvas.java:799)
at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:400)
at javax.media.opengl.awt.GLCanvas.paint(GLCanvas.java:499)
at sun.awt.RepaintArea.paintComponent(RepaintArea.java:248)
at sun.awt.RepaintArea.paint(RepaintArea.java:224)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:310)java.lang.OutOfMemoryError

at java.awt.Component.dispatchEventImpl(Component.java:4706)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)

Java Result: 1
[/quote]
and the at Viewer.initVertexArray(Viewer.java:179) refers to the line of code:


      vertexData = GLBuffers.newDirectFloatBuffer(triangleNumber*3*3);

I added in the run Option in Netbeans, after -Xmx1500m space -XX:MaxDirectMemorySize=256m (i tried 256M and 256m) but it still fails (also 512m)

these should be “safe” values since 2M(triangle)*3(points)*3(coordinates)4(Bytes) = 72M/(10241024) = 68mb (as you said)

Any other idea?

@glVertexPointer
The first one would be a JOGL specific one. You’ll have to read up on that one by yourself, as I have no idea how it works. The second one is the correct one. It takes a size, type, stride and Buffer object.

size is the number of dimensions (the number you would’ve used in glVertex*f). THIS IS NOT THE SIZE OF THE BUFFER!!!
type is what format your data is. In your case, that is GL_FLOAT.
stride is how far to jump after reading a value in bytes. With 2 floats per vertex, that’d be 8 (2 x 4 byte floats), but setting it to 0 allows OpenGL to calculate it itself.
the buffer is the data you want to send.

The last one is for specifying a pointer position inside the currently bound buffer, and therefore does not take a Buffer object, but a start index instead.

@adding color:
Normals have nothing to do with color. They define the surface normal for lighting, and unless you use 3D and the built-in lighting of OpenGL (which is not very interesting IMO) you don’t need to specify normals. To get colors per vertex, just use glColorPointer() and GL_COLOR_ARRAY. >_>

@buffer size:
You’re pushing it if you want to draw 2 000 000 unique triangles on the screen. Crysis 1 was floating at around 1.0 to 1.2 million triangles if I recall correctly, and you’re not gonna want to stream that much data to the GPU each frame in the first place. You’re actually getting close to the bandwidth of the PCI Express bus, which also has to transmit all the OpenGL commands that are executed on the GPU. Simply put, if you need that much memory, you’re doing it wrong.

Sorry for not explicitely saying, but I solved :stuck_out_tongue:

I copy here, maybe it could be useful for other newbie like me ^^

gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertexData);
gl.glDrawArrays(GL.GL_TRIANGLES, 0, triangleNumber*3);

Ah ok, I would like to somehow perform a (very basic) render, because now I see my model like all white and I would like to see some deep, I guess the normal vectors are needed for this… the graphic cards should calculate somehow the difference between my view vector and the normal vector of each triangle and them color them regarding this difference, the more is the inclination, the darker the triangles should be…

Can I do with something like this:


public void display(GLAutoDrawable glad) {
....
initLight(gl);
...
}

public void initLight(GL gl) {
        // Prepare light parameters.
        float SHINE_ALL_DIRECTIONS = 1;
        float[] lightPos = {1, 1, 2f, SHINE_ALL_DIRECTIONS};
        float[] lightColorAmbient = {0.2f, 0.2f, 0.2f, 1f};
        float[] lightColorSpecular = {0.8f, 0.8f, 0.8f, 1f};

        // Set light parameters.
        gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, lightPos, 0);
        gl.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT, lightColorAmbient, 0);
        gl.glLightfv(GL.GL_LIGHT1, GL.GL_SPECULAR, lightColorSpecular, 0);

        // Enable lighting in GL.
        gl.glEnable(GL.GL_LIGHT1);
        gl.glEnable(GL.GL_LIGHTING);

    }

?

The problem is that I have to visualize 3d models (based on triangles) and some of them reach 5M of triangles…

I guess the VBO should be the solution for these cases?

I guess it’s also possible that while you have >68Mb of direct memory free, there’s not 68Mb in a continuous chunk. Have you tried carving it up into more manageable chunks of (say) 8Mb each?

You think you messed up the memory commands. They are VM-commands, not run commands. Run commands end up in your main(String[] args). Put -Xmx1500m space -XX:MaxDirectMemorySize=256m in the VM command field instead.

And what the heck is SHINE_ALL_DIRECTIONS? >_>

Why not using the default backward compatible profile? Generally, when using JOGL, we don’t ask for a particular profile, we use getMaxFixedFunc() or getMaxProgrammable().

There are some tutorials for JOGL on the official site (JogAmp.org) and you can look at my source code if you still need an example of VBOs.

At first, porting C/C++ OpenGL code to JOGL 2.0 is not difficult and not significantly more difficult than with the competitor of JOGL. Secondly, please don’t use this thread to promote the competitor of JOGL. I remind you that when someone asks for help with it, I answer by looking at its documentation if required, I try to give some help or I don’t answer but I don’t use this opportunity to promote another API as you can see here:

You’re in the JOGL section.

I’m sure I’ve asked before that the JOGL and LWJGL forums are collapsed into a single OpenGL forum to stop this sort of pettiness.

Cas :slight_smile:

Merging the boards won’t help. As soon as JOGL is mentioned in the initial post, it will be the same story all over again.

I wouldn’t know exactly how hard it is, because I have never used JOGL. I’m just trying to help.

EDIT: fixed quote…