Draw and fill triangles in 3d space on a 2D plane

Sorry about the missing *4 multiplier in the example…
It’s hard to tell what’s wrong there from the few lines of code. But since the error occurs in “glDrawArrays”, it might be the case that this function is called with wrong arguments - maybe a wrong size or so…
Have you been able do run “any” example that uses glDrawArrays? (First websearch result: http://www.java-tips.org/other-api-tips/jogl/vertex-arrays-in-jogl.html - may have to be adjusted to new JOGL package names). If the problems persists, I can try to create another example next week.

[QUOTE=Marco13]Sorry about the missing *4 multiplier in the example…
It’s hard to tell what’s wrong there from the few lines of code. [/quote]

Dont worry marco :), it is perfectly normal, you dont have anything to sorry about

The fault was mine :stuck_out_tongue:

[QUOTE=Marco13;16716]
But since the error occurs in „glDrawArrays“, it might be the case that this function is called with wrong arguments - maybe a wrong size or so…
Have you been able do run „any“ example that uses glDrawArrays? (First websearch result: http://www.java-tips.org/other-api-tips/jogl/vertex-arrays-in-jogl.html - may have to be adjusted to new JOGL package names). If the problems persists, I can try to create another example next week.[/QUOTE]

I guess the glDrawArray is not the problem since with

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

It works like a charm (below the 2M triangles)

However, do you think that maybe the VBOs could be a solution when I have a very large number of triangles? Which is actually the limit by using the VBOs?

Wait a moment - it works with GLBuffers.newDirectFloatBuffer, but it does NOT work with the ByteBuffer that was allocated manually? :confused: That’s strange. If this really ist the case, I’ll have to look up what newDirectFloatBuffer actually does - I tried to find the GLBuffers class, but did not find it in the GitHub repo. I assumed that it was basically the same as the ByteBuffer.allocateDirect thing…

Exactly, but dont worry, I am trying now to implement the VBOs…

Which is the size limit for using VBOs? I guess the framebuffer right? And it should correspond to the global memory size, no?

Sorry, I don’t know the size limit of VBOs or how it is related to the global memory. It basically IS the same memory, but I’m not aware of any OpenGL specific limits (but of course, there may be some - similar to the maximum allocation limit for memory in CUDA)

Just a question about the displaying the image over the screen.

I am testing now how a 3d view of my model looks like. I applied a mouse listener and I can rotate and zoom, but I would like that it could rotate only around the X and Y axes. The problem arises when I rotate it first over Y axes, lets say, for 90° in left or right direction and then I try the rotation over X, but in this case the rotation is over Z for me.

I guess when I rotate over Y for 90°, also the model coordinating system rotate with it, and that is why its X axes corresponds to the Z axes in my coordinating system (the viewer).

Yes, it shows this behavior when you use the rotation from the example. I wanted to change that recently, but thought it was not worth an update.
To achive the rotation that you described, you have to multiply each new rotation to the rotation matrix from the left. Some pseudocode:

private Matrix currentRotation;

public void mouseMoved(...)
{
    Matrix newRotation = computeSmallRotationFromMouseMovement(previousMousePoint, currentMousePoint);
    currentRotation = newRotation * currentRotation;
}

If it doesn’t work, I can post a small example later.

[QUOTE=Marco13]Yes, it shows this behavior when you use the rotation from the example. I wanted to change that recently, but thought it was not worth an update.
To achive the rotation that you described, you have to multiply each new rotation to the rotation matrix from the left. Some pseudocode:

private Matrix currentRotation;

public void mouseMoved(...)
{
    Matrix newRotation = computeSmallRotationFromMouseMovement(previousMousePoint, currentMousePoint);
    currentRotation = newRotation * currentRotation;
}

If it doesn’t work, I can post a small example later.[/QUOTE]

Ah ok, however I was using the glRotated and glScalef

Stupid question: how do I set the modelview matrix in gl2?

By googling I just found push/popMatrix(), but this should not have anything to do, because this is something related when you want to apply some modelview transform to specific objects… right?

Edit: I dont get how can I adapt your code to mine. You do

        int modelviewMatrixLocation = 
            gl.glGetUniformLocation(shaderProgramID, "modelviewMatrix");
        gl.glUniformMatrix4fv(
            modelviewMatrixLocation, 1, false, modelviewMatrix, 0);```

Basically you get the pointer to the modelview matrix and then you substitute it, but...I dont know what I should use instead of your **shaderProgramID**

Ok, i tried to do the following:

...
program = gl.glCreateProgram();
...
}

public void display(GLAutoDrawable gLAutoDrawable) {
...
gl.glUseProgram(program);
        int modelviewMatrixLocation = gl.glGetUniformLocation(program, "modelviewMatrix");
        gl.glUniformMatrix4fv(modelviewMatrixLocation, 1?, false?, modelviewMatrix, 0?);     
...
}

But I do not find anything about **

public void glUniformMatrix4fv(int i, int i1, boolean bln, float[] floats, int i2)**

So I am just copying the same i1, bln and i2 of yours without any idea about what they are/mean ^^

Edit: COOL! :smiley: It’s working :stuck_out_tongue: (This actually is your implementation by setting the modelview matrix every time) Although I am using Vertex Array, it is very slow because I am doing all the calculation of the modelview matrix on the java (cpu/host)…? Using Cuda should it be faster, no?

I will now change following your tip about the rotation on x-y only

The problem is how to apply the rotation over x and y

private Matrix currentRotation;

public void mouseMoved(...)
{
    Matrix newRotation = computeSmallRotationFromMouseMovement(previousMousePoint, currentMousePoint);
    currentRotation = newRotation * currentRotation;
}

Inside the computeSmallRotationFromMouseMovement should I compute first rotation over X and then over Y? Why mouseMoved? Shouldnt it be mouseDragged?

Maybe I got it. You said to modify the rotation matrix, that should be this one?

No wait, your currentRotation is the matrix of the current rotation, no matter if xy or yx

Then you say to multiply this matrix for the new matrix

The difference is that in the example when you call the updateModelviewMatrix(), it calls in turn translation, rotationX and rotationY and each of these functions apply the transforms starting from the identity matrix

That’s why!

The computation of the Modelview matrix should not be done with CUDA. It’s only a small 4x4 matrix, and for such small matrices, Java is definitely faster. Multiplying two 100x100 or 1000x1000 matrices would be different, of course :wink:

However, I’m a little bit lost about the current status. When you are using „older“ GL versions without shaders, you don’t have a program ID and so on. You just call pushMatrix/pop/matrix/multMatrix etc. The „computeSmallRotationFromMouseMovement“ should create a Matrix that contains only the rotation that is created from the last change of the mouse position (due to a mouse drag). And as you pointed out, that’s the main difference to the current sample.

So I should figure out which was causing the slowness…

[QUOTE=Marco13;16732]
However, I’m a little bit lost about the current status. When you are using „older“ GL versions without shaders, you don’t have a program ID and so on. You just call pushMatrix/pop/matrix/multMatrix etc. The „computeSmallRotationFromMouseMovement“ should create a Matrix that contains only the rotation that is created from the last change of the mouse position (due to a mouse drag). And as you pointed out, that’s the main difference to the current sample.[/QUOTE]

Ok, but whenever I start any rotation, I dont need to call any push-pop Matrix because I dont need to save the current matrix. I just need to take the current matrix and multiply on the left with the current one.

The problem that should arise is that the multMatrix(M) multiplies the matrix M for the current one C to yeld CM, but regarding what you said, I need MC

(http://www.felixgers.de/teaching/jogl/transfoMatrixOrder.html)

How can I solve it?

Right, the new matrix has to be multiplied to the current one from the left. The current matrix and the new ones are explicitly represented as ‘float[]’ arrays. So you can compute whatever you want - and this is not related to the gl-specific functions.

currentModelviewMatrix = multiply(newMatrix, currentModelviewMatrix);

In the display()-Method, you can use

  • glPushMatrix to store the current state (should be done to maintain a clean structure)
  • glLoadIdentity
  • glMultMatrix or glLoadMatrix to apply the ‘currentModelviewMatrix’
  • draw
  • glPopMatrix

If it doesn’t work, I can try to build an example tomorrow

EDIT: BTW: When you are anyhow using the gl-Matrix functions, you could also do the multiplication like this

  • glPushMatrix
  • glLoadMatrix with the NEW rotation matrix
  • glMultMatrix with the OLD rotation matrix
  • (If necessary: glGetMatrix to obtain the result an load it again later)
  • glPopMatrix

But I’m not sure whether this is easier, assuming that there later may also be a translation matrix and so on…

Here is the code, I tried to clean it as much as possible…

I use the multMatrix to set the matrix, if I use the modelviewMatrix no problem, instead if I use currentRotation I dont see anything…

        
        System.out.println("Init");
        
        fPSAnimator.start();
        GL2 gl = gLAutoDrawable.getGL().getGL2();
                
        gl.glClear(GL.GL_COLOR_BUFFER_BIT);
        gl.glEnable(GL.GL_DEPTH_TEST);        
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        
        
        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
        
        initVertexArray(gl);
        initNormalArray(gl);
        gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertexData);
        gl.glDrawArrays(GL.GL_TRIANGLES, 0, triangleNumber*3);
    }

    @Override
    public void display(GLAutoDrawable gLAutoDrawable) {
        
        System.out.println("Display");
        GL2 gl = gLAutoDrawable.getGL().getGL2();
        GLUT glut = new GLUT();
                
        gl.glMatrixMode(GL2.GL_MODELVIEW);

        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        gl.glShadeModel(GL2.GL_SMOOTH);
        gl.glLoadIdentity();
                
        gl.glMultMatrixf(modelviewMatrix, 0);
                
        gl.glTranslatef((float)translationX/20.0f, (float)translationY/20.0f, 0);
        gl.glScalef(scale%10.0f, scale%10.0f, scale%10.0f);
        
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glDrawArrays(GL.GL_TRIANGLES, 0, triangleNumber*3);
    }

    @Override
    public void reshape(GLAutoDrawable gLAutoDrawable, int x, int y, int width, int height) {
        System.out.println("Reshape");
        
        GL2 gl = gLAutoDrawable.getGL().getGL2();
        
        if (height == 0)
            height = 1; // to avoid division by 0 in aspect ratio below
        gl.glViewport(x, y, width, height); // size of drawing area
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();

        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    private void initVertexArray(GL2 gl)    {
      vertexData = GLBuffers.newDirectFloatBuffer(triangleNumber*3*3);
      for(int i=0; i<triangleNumber; i++) {
          Triangle tmp = triangleArray.get(i);
          vertexData.put(new float[]{tmp.x1/12000.0f, tmp.y1/12000.0f, tmp.z1/12000.0f, 
                                     tmp.x2/12000.0f, tmp.y2/12000.0f, tmp.z2/12000.0f, 
                                     tmp.x3/12000.0f, tmp.y3/12000.0f, tmp.z3/12000.0f  });
      }
      vertexData.flip();
    }
    
    private void initNormalArray(GL2 gl)    {
      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();
    }
    
    private void runExit()    {
        new Thread(new Runnable()     {
            @Override
            public void run()       {
                //animator.stop();
                System.exit(0);
            }
        }).start();
    }

    @Override
    public void mousePressed(MouseEvent me) {
       // throw new UnsupportedOperationException("Not supported yet.");
        System.out.println("mousePressed "+me.getButton());
        mouseMotionStartX = me.getX();
        mouseMotionStartY = me.getY();
        if(me.getButton()==1)
            rotation = true;
        else
            rotation = false;
    }

    @Override
    public void mouseMoved(MouseEvent me) {
        //throw new UnsupportedOperationException("Not supported yet.");
        System.out.println("mouseMoved");       
        previousMousePosition = me.getPoint();
    }

    @Override
    public void mouseDragged(MouseEvent me) {
        //throw new UnsupportedOperationException("Not supported yet.");
        System.out.println("mouseDragged "+me.getButton());
        
        int dx = me.getX() - previousMousePosition.x;
        int dy = me.getY() - previousMousePosition.y;

        // If the left button is held down, move the object
        if ((me.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 
            MouseEvent.BUTTON1_DOWN_MASK)   {
            translationX += dx / 25.0f;
            translationY -= dy / 25.0f;
        }

        // If the right button is held down, rotate the object
        else if ((me.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) == 
            MouseEvent.BUTTON3_DOWN_MASK)   {
            rotationX += dy;
            rotationY += dx;
            newRotation = computeSmallRotationFromMouseMovement
                                                    (previousMousePosition, me.getPoint());
            currentRotation = multiply(newRotation, currentRotation);
        }
        previousMousePosition = me.getPoint();
        updateModelviewMatrix();
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent mwe) {
       // throw new UnsupportedOperationException("Not supported yet.");
        System.out.println("mouseWheelMoved");

        // Translate along the Z-axis
            translationZ += mwe.getWheelRotation() * 0.25f;
            previousMousePosition = mwe.getPoint();
            updateModelviewMatrix();
    }
    
    private void updateModelviewMatrix()    {
        float m0[] = translation(translationX, translationY, translationZ);
        float m1[] = rotationX(rotationX);
        float m2[] = rotationY(rotationY);
        modelviewMatrix = multiply(multiply(m1,m2), m0);
    }
        
    private void setupView(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
        float aspect = (float) drawable.getWidth() / drawable.getHeight();
        projectionMatrix = perspective(50, aspect, 0.1f, 100.0f);
    }
    
    private static float[] perspective(float fovy, float aspect, float zNear, float zFar)   {
        float radians = (float)Math.toRadians(fovy / 2);
        float deltaZ = zFar - zNear;
        float sine = (float)Math.sin(radians);
        if ((deltaZ == 0) || (sine == 0) || (aspect == 0))  {
            return identity();
        }
        float cotangent = (float)Math.cos(radians) / sine;
        float m[] = identity();
        m[0*4+0] = cotangent / aspect;
        m[1*4+1] = cotangent;
        m[2*4+2] = -(zFar + zNear) / deltaZ;
        m[2*4+3] = -1;
        m[3*4+2] = -2 * zNear * zFar / deltaZ;
        m[3*4+3] = 0;
        return m;
    }
    
    private static float[] identity()   {
        float m[] = new float[16];
        Arrays.fill(m, 0);
        m[0] = m[5] = m[10] = m[15] = 1.0f;
        return m;
    }
    
    private static float[] multiply(float m0[], float m1[]) {
        float m[] = new float[16];
        for (int x=0; x < 4; x++)   {
            for(int y=0; y < 4; y++)    {
                m[x*4 + y] = m0[x*4+0] * m1[y+ 0] +
                             m0[x*4+1] * m1[y+ 4] +
                             m0[x*4+2] * m1[y+ 8] +
                             m0[x*4+3] * m1[y+12];
            }
        }
        return m;
    }
    
    private static float[] translation(float x, float y, float z)   {
        float m[] = identity();
        m[12] = x;
        m[13] = y;
        m[14] = z;
        return m;
    }
    
    private static float[] rotationX(float angleDeg)    {
        float m[] = identity();
        float angleRad = (float)Math.toRadians(angleDeg);
        float ca = (float)Math.cos(angleRad);
        float sa = (float)Math.sin(angleRad);
        m[ 5] =  ca;
        m[ 6] =  sa;
        m[ 9] = -sa;
        m[10] =  ca;
        return m;
    }

    private static float[] rotationY(float angleDeg)    {
        float m[] = identity();
        float angleRad = (float)Math.toRadians(angleDeg);
        float ca = (float)Math.cos(angleRad);
        float sa = (float)Math.sin(angleRad);
        m[ 0] =  ca;
        m[ 2] = -sa;
        m[ 8] =  sa;
        m[10] =  ca;
        return m;
    }
    
    private static float[] computeSmallRotationFromMouseMovement
                                (Point previousMousePosition, Point currentMousePosition )  {
       
        int dx = (int)(currentMousePosition.getX() - previousMousePosition.getX());
        int dy = (int)(currentMousePosition.getY() - previousMousePosition.getY());        
       
        float x[] = identity();
        float angleRad = (float)Math.toRadians(dx);
        float ca = (float)Math.cos(angleRad);
        float sa = (float)Math.sin(angleRad);
        x[ 5] =  ca;
        x[ 6] =  sa;
        x[ 9] = -sa;
        x[10] =  ca;
        
        float y[] = identity();
        angleRad = (float)Math.toRadians(dy);
        ca = (float)Math.cos(angleRad);
        sa = (float)Math.sin(angleRad);
        y[ 0] =  ca;
        y[ 2] = -sa;
        y[ 8] =  sa;
        y[10] =  ca;
        
        float m[] = multiply(x, y);
        
        return m;
    }```

BTW: The computeSmallRotationFromMouseMovement was a very… „suggestive“ name :wink: It could roughly contain something like
return multiply(rotationX(dy), rotationY(dx));
to avoid duplicate code.

[QUOTE=Marco13]BTW: The computeSmallRotationFromMouseMovement was a very… „suggestive“ name :wink: It could roughly contain something like
return multiply(rotationX(dy), rotationY(dx));
to avoid duplicate code.[/QUOTE]

lol, you are right :stuck_out_tongue: I just copied it on the fly and pasted :smiley:

[QUOTE=elect]

I use the multMatrix to set the matrix, if I use the modelviewMatrix no problem, instead if I use currentRotation I dont see anything…[/QUOTE]

Initialization problem, I forgot a

**currentRotation = identity();

** in the init()

However the desidered rotation is still not working :confused:

I dont know if you got what I mean Marco

Let us suppose that I have this 3d model

i perform a

gl.glRotatef(90, 0, 1, 0);

But if I do

gl.glRotatef(90, 0, 1, 0);
gl.glRotatef(90, 1, 0, 0);

But I would like to get this one

The second rotation must somehow connected to the first one