Free camera placement and coordinate transformatio

Hey everybody,
thanks in advance to anyone who is willing to help me, I’m really struggling “a bit” with some (I guess) basic stuff….I have a problem concerning the camera placement (aka „scene transformation“) and the transformation of coordinate systems and it seems that I make some wrong transformations or do them in the wrong order… The situation is as follows:
I have modeled a scene in 3DSMax, let’s say this scene contains a teapot at (500 / 200 / 100) (no rotations) and a free camera at (700 / 1800 / 850 ) with the rotations ( 110 / 45 / 0).
Now, I want to recreate the exact same scene with the same camera-view in OpenGL ( via Jogl in java to be precise, but I guess this doesn’t matter here). The input parameters should be the coordinates from 3DSMax, and the render-view should render the same picture (same perspective etc) as the 3DSMax version.
Until now, I have had an implementation via the “glLookAt” – method (with the coordinate origin as target) and a transformation method to change the coordinate system from 3dsmax to opengl:

protected void transformTo3DSMax(GL gl){
       double [] transformmatrix =  { 1, 0, 0, 0,    0, 0, -1, 0,    0, 1, 0, 0,    0, 0, 0, 1};
        gl.glMultMatrixd(transformmatrix,0);
    }

Then I also have separate functions for the individual objects I want to render, in each of those I call the “transformTo3DSMax”, for example

public void drawMarker(GL gl, double x, double y, double z) {
        gl.glPushMatrix();        
        //do translations and rotations  here
        //paint object with glu.FooBar() here        
        transformTo3DSMax(gl;
        gl.glPopMatrix(); 
     }

Also the method to set the camera perspective usesthe transform method:

    protected void setEye(GL gl){
        gl.glLoadIdentity();
        glu.gluLookAt(cam_pos.getX(), cam_pos.getY(), cam_pos.getZ(),            //position eye
                      LOOKAT.getX(), LOOKAT.getY(), LOOKAT.getZ(),               //look at
                      up_vector.getX(), up_vector.getY(), up_vector.getZ());     //up vector
        transformTo3DSMax(gl);
    }

Using these methods, the rendering is correct, the coordinates are transformed correctly ( so the transform matrix must be correct) .
The point is, I want to set the camera “freely”, that means I want to be able to enter the transformation but also the single x y and z angles from 3dsmax. Which basically means I have to get rid of the gluLookAt method and replace it by a method in which I rotate and translate the whole scene ( if I got it right).
So my plan was as follows: Replace the the setEye method by:

protected void setEye(GL gl, tx, ty, tz, r_x,r_y,r_z){
        gl.glLoadIdentity();
        gl.glTranslated(-t_x, -t_y, -t_z);
        gl.glRotated(r_x, 1, 0, 0);
        gl.glRotated(r_y, 0, 1, 0);
        gl.glRotated(r_z, 0, 0, 1);
        transformTo3DSMax(gl);
}

This method should have been the very first that is called in the display method from OpenGL, and I thought it would prepare the whole matrix stack in a way, that every matrix operation afterwards ( for example painting markers, circles, teapots) gets the camera perspective I also have in 3dsmax. But for whatever reason, this doesn’t seem to work. I tried many different combinations of rotations and transformations in the setEye method, but every single one of them produced a wrong perspective / render output -_-
If anyone got my problem – can you tell me where my fault is, or is there any good tutorial how I can place a camera freely in combination with a coordinate transformation?

Thanks a lot!

Binom

Not being familiar with 3dsmax, can you clarify further what you mean by the rotations ( 110 / 45 / 0)? Are these the Euler angles (yaw,pitch,roll) of the camera’s orientation? Or the teapot? You may want to take a look at 9.162 How can I transform an object with a given yaw, pitch, and roll?.

Is [t_x,t_y,t_z] the location of the teapot that you want to look at or is it the vector difference of the position of the teapot - position of camera? or something else?

I suspect your order of operations is incorrect and it might be fixed with


protected void setEye(GL gl, tx, ty, tz, r_x,r_y,r_z){
        gl.glLoadIdentity();
        gl.glRotated(r_z, 0, 0, 1);
        gl.glRotated(r_y, 0, 1, 0);
        gl.glRotated(r_x, 1, 0, 0);
        gl.glTranslated(-t_x, -t_y, -t_z);
        transformTo3DSMax(gl);
}

Hello marshats,

yes - the camera rotation angles are euler angles ( so x=110 , y=45 and z= 0) and 3dsmax also rotates in the order x, then y then z…( so its ZYXEuler I guess). The teapot itself could have a rotation also, but that doesnt matter in this case.

the parameters of the setEye method should be the translation and rotation parameters of the camera-positioning. Meaning that if i get the 3dsmax coordinates t(700 / 1800 / 850 ) and r( 110 / 45 / 0) of the camera, i would want to place it with exact these parameters in OpenGL. The problem is the coordinate transformation i guess…

I also dont know if I have to transform coordinates for every single object I draw after the camera placement or if one single transformTo3DSMax() call does suffice as a modelview matrix preparation?

I need a little more info …

Are you placing your objects thinking in terms of the global 3ds coordinate system or the openGL coordinate system?

In terms of local 3ds coordinates, is the up direction in the y_3ds direction? is the forward direction of the camera pointing along the z_3ds axis?

Hello marshats,

thanks for your reply! What you mentioned is exactly what I also thought how the order of the transformations should be (despite of the camera rotations/translations, which should perhaps be negative angles/translations as of the fact that you actually rotate the scene).

I am placing my objects by taking the coordinates from the 3ds coordinate system, so if i have my teapot at (x=100 / y=200 / z=300), I want to feed my Jogl App with the exact same parameters (which I have the the transformTo3DSMax() method for - or at least I hope so :P)

The default camera viewing direction in 3DS is along the negative z axis, but I changed the local camera coordinate system so that the camera is looking into positive z - should be resulting in the OpenGL coordinate system ( z into screen, x to the left, y upwards).
Unfortunately, I seem to always get a weird/wrong render output in my Jogl application, no matter in which order i call the rotate/translate/transformto3dsmax methods within the setEye method -_- When I tried your suggestion from above, I even get a blank screen…
If you are willing to look into a (short) Java code snippet, I’d be happy to upload it somehow.
All I can think of now is that maybe the camera coordinate change I proceeded in 3ds might falsify something…

I need a little more info …

Are you placing your objects thinking in terms of the global 3ds coordinate system or the openGL coordinate system? If the answer is “3ds coordinates” then put the transformTo3DSMax call at the begining not the end as;


protected void setEye(GL gl, tx, ty, tz, r_x,r_y,r_z){
        gl.glLoadIdentity();
        transformTo3DSMax(gl);
        gl.glRotated(r_z, 0, 0, 1);
        gl.glRotated(r_y, 0, 1, 0);
        gl.glRotated(r_x, 1, 0, 0);
        gl.glTranslated(-t_x, -t_y, -t_z);     
}

and you should remove transformTo3DSMax() from all your


public void drawMarker(GL gl, double x, double y, double z) {
        gl.glPushMatrix();        
        //do translations and rotations  here
        //paint object with glu.FooBar() here        
        /// -- remove this -- not needed transformTo3DSMax(gl;
        gl.glPopMatrix(); 
     }

so any time you place an object it will get processed as


MV = I*T_3ds*Rz*Ry*Rx*T_eye
V_gl = MV*M_object*V_3ds
     = I*T_3ds*Rz*Ry*Rx*T_eye*M_object*V_3ds
where M_object is the rotations/translation/etc of your object in 3ds coordinates

This way everything is processed in 3ds coordinates and at the very end/last matrix operation it is converted back to opengl Coordinates (x=right, y=up, z=out of screen)

In terms of local 3ds coordinates, is the up direction in the y_3ds direction? is the forward direction of the camera pointing along the z_3ds axis? [you answered the camera is pointing along the -z_3ds axis] That means there may need to be an extra step in setEye to flip the z-axis (not 100% certain on this though – I need to think more about it). But here is the code on first thought


protected void setEye(GL gl, tx, ty, tz, r_x,r_y,r_z){
        gl.glLoadIdentity();
        gl.glRotated(180, 0, 1, 0); // take care of looking down -z_3ds axis
        transformTo3DSMax(gl);
        gl.glRotated(r_z, 0, 0, 1);
        gl.glRotated(r_y, 0, 1, 0);
        gl.glRotated(r_x, 1, 0, 0);
        gl.glTranslated(-t_x, -t_y, -t_z);     
}

so


MV = I*R_180*T_3ds*F_z*Rz*Ry*Rx*T_eye
V_gl = MV*M_object*V_3ds
     = I*R_180*T_3ds*Rz*Ry*Rx*T_eye*M_object*V_3ds
where M_object is the rotations/translation/etc of your object in 3ds coordinates


Sure if you have some simple jogl code I could look at that.

My 3ds camera looks into the positive z axis, with x pointing left and y up.
I place my objects using the 3ds coordinates.

Currently, my application looks like this (your latest suggestion included): (open spoiler to view source code)
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>


package testerproject;

import com.sun.opengl.util.GLUT;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
import javax.vecmath.Point3d;

public class GLRenderer implements GLEventListener{
    private GLU glu;
    protected final double FIELDOFVIEW;
    protected final double ASPECT;
    protected final double NEAR_RANGE;
    protected final double FAR_RANGE;

    private Point3d cam_pos, cam_rot;

    public GLRenderer(){
        FIELDOFVIEW = 54.432;
        ASPECT = 4/3;
        NEAR_RANGE= 0.0;
        FAR_RANGE = 15000;
    }


    public void init(GLAutoDrawable arg0)
    {
        GL gl = arg0.getGL();
        glu = new GLU();
        gl.glClearColor(0.7f, 0.7f, 0.7f, 0.0f);
        //Festlegung der Maße von GL-Primitiven
        gl.glPointSize(2.0f); //Größe eines Punktes
        gl.glLineWidth(2.0f); // Dicke von Linien
        gl.glLineStipple(2, (short) 0x00FF); //Mustervorgabe für gestrichelte Linien

        this.setCameraMatrix(gl);
        gl.glEnable(GL.GL_TEXTURE_RECTANGLE_NV);
        gl.glMatrixMode(GL.GL_MODELVIEW);
    }


    public void display(GLAutoDrawable arg0)
    {
      GL gl = arg0.getGL();
      GLUT glut = new GLUT();
      gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
      cam_pos = new Point3d(700,1800,850);
      cam_rot = new Point3d(110,45,0);
      setCamera(gl);
      drawRootCoordinateSystem(gl, 100000.0f);

      drawTeaPot(gl, glut);
      drawSphere(gl, glut);

    }


    protected void setCamera(GL gl){
        gl.glLoadIdentity();

        transformTo3DSMax(gl);
        gl.glRotated(cam_rot.getZ(), 0, 0, 1);
        gl.glRotated(cam_rot.getY(), 0, 1, 0);
        gl.glRotated(cam_rot.getX(), 1, 0, 0);
        gl.glTranslated(-cam_pos.getX(), -cam_pos.getY(), -cam_pos.getZ());
    }


    protected void drawSphere(GL gl, GLUT glut){
        gl.glPushMatrix();
           gl.glColor3f(0.3f, 0.5f, 0.3f);
           gl.glTranslated(160, 110, -1000);
           glut.glutSolidSphere(25,10,5);
        gl.glPopMatrix();
    }


    protected void drawTeaPot(GL gl, GLUT glut){
       gl.glPushMatrix();
           gl.glColor3f(0.3f, 0.5f, 0.3f);
           gl.glTranslated(500, 200, 150);
           glut.glutWireTeapot(150.0f);
       gl.glPopMatrix();
    }


    protected void drawRootCoordinateSystem(GL gl, float length_axis){
        gl.glPushMatrix();
           //x axis red
           gl.glColor3f( 1.0f, 0.0f, 0.0f );
           drawLine(gl, 0.0f, 0.0f, 0.0f, length_axis, 0.0f,0.0f);
           drawDottedLine(gl, -length_axis, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);

           //y axis green
           gl.glColor3f( 0.0f, 1.0f, 0.0f );
           drawLine(gl, 0.0f, 0.0f, 0.0f, 0.0f, length_axis, 0.0f);
           drawDottedLine(gl, 0.0f, -length_axis, 0.0f, 0.0f, 0.0f, 0.0f);

           //z axis blue
           gl.glColor3f( 0.0f, 0.0f, 1.0f );
           drawLine(gl, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, length_axis);
           drawDottedLine(gl, 0.0f, 0.0f, -length_axis, 0.0f, 0.0f, 0.0f);
       gl.glPopMatrix();
    }


    protected void drawLine(GL gl, double x1, double y1, double z1,
                                 double x2, double y2, double z2)
    {
       gl.glBegin(GL.GL_LINES);
            gl.glVertex3d(x1, y1, z1);
            gl.glVertex3d(x2, y2, z2);
       gl.glEnd();
    }


    protected void drawDottedLine(GL gl,double x1, double y1, double z1,
                                      double x2, double y2, double z2)
    {
       gl.glEnable(GL.GL_LINE_STIPPLE);
       gl.glBegin(GL.GL_LINES);
            gl.glVertex3d(x1, y1, z1);
            gl.glVertex3d(x2, y2, z2);
       gl.glEnd();
       gl.glDisable(GL.GL_LINE_STIPPLE);
    }


    protected void transformTo3DSMax(GL gl){
        double [] transformmatrix =  { 1, 0, 0, 0,    0, 0, -1, 0,    0, 1, 0, 0,    0, 0, 0, 1};
        gl.glMultMatrixd(transformmatrix,0);
    }


    protected void setCameraMatrix(GL gl) {
        int w =500, h = 500;

        gl.glViewport(0, 0, w, h);

        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity(); //load identity matrix

        glu.gluPerspective(this.FIELDOFVIEW, this.ASPECT, this.NEAR_RANGE ,this.FAR_RANGE);
    }




    public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4)
    {
    }


    public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2)
    {
    }


}


[/QUOTE]</div>

If I render this, it produces this picture: ( the dotted blue line is a part of the negative z axis).

I used the camera and object coordinates from 3ds, which produces this picture, rendred from the cameras point of view:

What came into my mind while posting this: Could it be possible that theres something wrong with the up vector of the camera or do I not have to care about this when not using gluLookat ?

The up vector along with the forward view of camera and and the direction of the camera side is defined by your euler angles. So you are still taking into account the up vector just as gluLookAt did. Rather than having to explicitly specify up, your 3-angles are implicitly giving you up,side, and fowrard camera directions.

Thanks for the code and pictures … that gives me something to work with.

For debugging purposes you will find it easier to work with glOrtho instead of persepctive so I suggest commenting out the line

glu.gluPerspective(this.FIELDOFVIEW, this.ASPECT, this.NEAR_RANGE ,this.FAR_RANGE)
until things work as expected


    protected void setCameraMatrix(GL gl) {
        int w =500, h = 500;

        gl.glViewport(0, 0, w, h);

        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity(); //load identity matrix

        glOrtho(-2000,2000,-2000,2000,-2000,2000);
        //glu.gluPerspective(this.FIELDOFVIEW, this.ASPECT, this.NEAR_RANGE ,this.FAR_RANGE);
    }

I really suspect the three rotations related to the euler angles are not pointing in the directions that I expect.

If the 3dsmax camera is located a the origin and the euler angles are all zero then what are the 3dsmax axes corresponding to up? right? and into the screen?

Repeat the question but with camera euler angles = (90,0,0)

Repeat the question but with camera euler angles = (0,90,0)

Repeat the question but with camera euler angles = (0,0,90)

Repeat the question but with camera euler angles = (45,45,45)

Pictures there would be very helpful showing the global coordinates as seen thru the 3ds camera.

Does this apply to your 3dsmax model – using viewport coordinates?

Note, because Blender does not have this ambiguity, I decided to check your code against Blender rather than 3dsmax because that is what I have available to view a scene with euler angles. This helped me to understand one thing (still doesn’t completely fix your problem) – whether or not there should be a negative sign in setCamera angles.

To understand this suppose you wanted to place an object in your scene at the same position and orientation as the camera. You would rotate first according to the Euler angles and then translate to the position ie


    void drawCameraTriad(){
        glPushMatrix();
          glTranslated(cam_pos.getX(), cam_pos.getY(), cam_pos.getZ());
          glRotated(cam_rot.getZ(), 0, 0, 1);
          glRotated(cam_rot.getY(), 0, 1, 0);
          glRotated(cam_rot.getX(), 1, 0, 0);
          drawRootCoordinateSystem(1500.);
        glPopMatrix();
     }

Now if you applied the setCamera correctly then this would always display to the screen the object representing the camera axis perfectly aligned to the horizontal, vertical, and normal monitor axis. Well the only way to get that is to do the inverse matrix operation when setting the camera “lookAt” and for glTranslate that means putting a negative sign on all coordinates and for glRotate that means rotate by a negative angle. And the inverse also changes the order of operations. Hence by inspection of drawCameraTriad() the inverse matrix is constructed by setCamera and has to be made by flipping signs and reversing order of operations as


    void setCamera(){
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        //transformTo3DSMax();
        glRotated(-cam_rot.getX(), 1, 0, 0);
        glRotated(-cam_rot.getY(), 0, 1, 0);
        glRotated(-cam_rot.getZ(), 0, 0, 1);
        glTranslated(-cam_pos.getX(), -cam_pos.getY(), -cam_pos.getZ());
    }

This code works perfectly when I compare it against Blender (ie with no need for transformTo3DSMax call). It does not solve your problem of the zy axis flip from 3dsmax to openGL. But this result must be true in either case. So the problem has to either be in one of two places transformTo3DSMax() or the order euler angle rotations defined by 3dsmax. For blender it was easy to figure this out by simply rotating one Euler angle at a time, then two in succession, and determining that blender applies X rotation first! then Y rotation second, and finally z rotation.

Not a complete solution … still looking into 3dsmax euler angle definition as the most likely candidate needing improvement. Hence the motivation for the questions I posed in the previous post where you try different euler sttings and note their effects.

Does this apply to your 3dsmax model – using viewport coordinates?

As I’m not exporting any models, I think I do not have any problems with this kind of problem. I checked the control view in 3dsmax from “view” and “world” perspective - the coordinate axis are the same.

I hope I made the screenshots of the origin camera from the right perspective - what you can see on those pictures is the coordinate system axis of the world. Possibly I misunderstood which view you wanted to see, If so please tell me and I’ll re-upload…

cam-rotations(0 / 0 / 0) (click to zoom)
{ camera-up-vector == world-y-axis AND camera-view-vector == world-z-axis }

cam-rotations(90 / 0 / 0)

cam-rotations(0 / 90 / 0)

cam-rotations(0 / 0 / 90)

cam-rotations(45/ 45 / 45)

As far as i know, 3ds also rotates in the order x then y then z, so I also should rotate like this?

    void setCamera(){
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        //transformTo3DSMax();
        glRotated(-cam_rot.getX(), 1, 0, 0);
        glRotated(-cam_rot.getY(), 0, 1, 0);
        glRotated(-cam_rot.getZ(), 0, 0, 1);
        glTranslated(-cam_pos.getX(), -cam_pos.getY(), -cam_pos.getZ());
    }

Honestly I dont completely understand why the order of operations should be altered by rotating/translating by the negative angles. But If I render my Jogl view with this order of operations and the gl.gluOrtho() method, i get this view:

But if Blender (does Blender natively use the OpenGL coordinate system?) and 3ds rotate in the same order, shouldnt the results be the same? -_-

Those pictures confirmed that that you are correct about the order of operations Rx Ry then Rz.

Blender does use the openGL convention so the net effect of that is that its camera looks in the opposite direction from 3dsmax but looking at your plots it and comparing with blender it appears that the transform matrix has to be applied in the camera cooridinates only: ie only the direction of the camera can flip.


    void transformTo3DSMax(){
        double transformmatrix[] =  { 1, 0, 0, 0,    0, 1, 0, 0,    0, 0, -1, 0,    0, 0, 0, 1};
        glMultMatrixd(transformmatrix);
    }

The other problem appears that your teapot with (0,0,0) rotation in 3dsmax is 90 rotated from the openGL/glut version. You can see this by setting the angles to 0,0,0 and plotting in both 3dsmax and comparing with your code with the same euler values. This seemed to fix the teapot in the wrong orientation – it should be parrallel to the red line from your earlier post.


    void drawTeaPot(){
       glPushMatrix();
           glColor3f(0.3f, 0.5f, 0.3f);
           glTranslated(500, 200, 150);
           glRotated(90, 1, 0, 0); // added to align 3dsmax and glut when 0,0,0 rotation angles
           glutWireTeapot(150.0f);
       glPopMatrix();
    }

You have the right order in set camera but need to add the transforn3dsmax


    void setCamera(){
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

	// tramsform camera for zoom/pan in openGL cooridinates

        transformTo3DSMax();
        glRotated(-cam_rot.getX(), 1, 0, 0);
        glRotated(-cam_rot.getY(), 0, 1, 0);
        glRotated(-cam_rot.getZ(), 0, 0, 1);
        glTranslated(-cam_pos.getX(), -cam_pos.getY(), -cam_pos.getZ());
    }

I checked this by plotting by adding


    void drawCameraTriad(){
        glPushMatrix();
          glTranslated(cam_pos.getX(), cam_pos.getY(), cam_pos.getZ());
          glRotated(cam_rot.getZ(), 0, 0, 1);
          glRotated(cam_rot.getY(), 0, 1, 0);
          glRotated(cam_rot.getX(), 1, 0, 0);
          drawRootCoordinateSystem(1500.);
        glPopMatrix();
     }

With those changes and putting back gluPerspective(FIELDOFVIEW, ASPECT, NEAR_RANGE ,FAR_RANGE);
I see something more like what you saw originally. I was wondering if you make these changes do you see the same … By the way are you reading values from 3dsmax for FIELDOFVIEW, ASPECT, NEAR_RANGE ,FAR_RANGE? or just using some other values?

But if Blender (does Blender natively use the OpenGL coordinate system?) and 3ds rotate in the same order, shouldnt the results be the same? -_-

Yes, except for one thing I mentioned earlier – the direction the camera points is exactly in the opposite direction between openGL and 3dsmax.

Still not quit there yet – but seem to be zooming in on the solution :slight_smile:

Honestly I don’t completely understand why the order of operations should be altered by rotating/translating by the negative angles. But If I render my Jogl view with this order of operations and the gl.gluOrtho() method, i get this view:

If you trace through exactly what all the glTranslate/glRotate/glMult* etc do in your code then you would see a concatenation of matrix multiplies:


(P) (IM) (IRx IRy IRz IT) (T Rz Ry Rx M) C_gl   -- result of multiplication --
|   |    |                 |          |   |
|   |    |                 |          |   |----- coor in gl camera
|   |    |                 |          |--------- coor in 3ds camera
|   |    |                 |-------------------- coor in global 3ds (this is where you start when retrieving 3dsmax positions)
|   |    |-------------------------------------- coor in 3ds camera
|   |------------------------------------------- coor in gl camera
|----------------------------------------------- apply projection 

M is transformTo3DSMax() operation to map GL coordinate to 3dsmax (IM is inverse of M ie IM*M=identity matrix=[1])
Rx is euler rotation about x axis (IRx*Rx=[1])     
Ry is euler rotation about y axis (IRy*Ry=[1])    
Rz is euler rotation about z axis (IRz*Rz=[1])    
T is location of camera in global 3dsmax coordinates (IT*T=[1])

And the matrices in openGL have some nice properties:
inverse of a glTranslate(x,y,z) is glTranslate(-x,-y,-z)
inverse of glRotate(angle,vx,vy,vx) is glRotate(-angle,vx,vy,vx)
and you have to be careful in how inverse of M is computed – you must explicitly satisfy the condition IM*M=[1]

Thanks for your clarification on the matrix multiplication and inversion on matrixes with negative angles, I think I got it now :slight_smile:

You were right about the assumption that the teapot itself must be rotated by 90 degrees before being rendered! Basically this means that every object that has to be painted needs a separate rotation beforehand. Btw another “problem” is that the pivot points of these type of objects (coming from GLUT) dont seem to be equal to the ones from 3ds. 3ds renders from the bottom of the teapot, opengl from the “middle” (or anywhere insider the object) - which can falsify a bit the impression you get from controlling a render-view, for example if in opengl the tea-pot cuts an axis and in 3ds it doesnt. But this is really a minor problem and can be solved by a translation within the object-draw method…

I get the same view as you when I apply the changes you posted. But did you mean that I should use this transform matrix for my application

double transformmatrix[] =  { 1, 0, 0, 0,    0, 1, 0, 0,    0, 0, -1, 0,    0, 0, 0, 1};

or is this just the one you need for the transformation from blender? (but I used this matrix and get the same view you posted).

Parameters like FIELDOFVIEW, ASPECT, NEAR_RANGE ,FAR_RANGE
I can read the (vertical) FIELDOFVIEW of the camera in 3ds from the GUI somewhere, the ASPECT is set by the render setup from 3ds (640*480 in my case). NEARRANGE and FARRANGE is set to unlimited…

Currently Im thinking about the rotation by 90degrees you had to do before drawing the teapot - maybe I have to do something similar to the setCamera method, I will test this out and post my results :slight_smile:

There was by the way a minor fault in the GLRenderer Constructor:

public GLRenderer(){
        FIELDOFVIEW = 54.432;
        ASPECT = 4/3;
        NEAR_RANGE= 0.0;
        FAR_RANGE = 15000;
    }

should be

public GLRenderer(){
        FIELDOFVIEW = 54.432;
        ASPECT = 4.0/3.0; //changed!
        NEAR_RANGE= 0.0;
        FAR_RANGE = 15000;
    }

gnarf

Yes, this is the transform matrix (IM=transformmatrix) you should be using to go from 3dsmax camera cooridinates to opengl camera cooridinates. I came to this conclusion by comparing pictures you sent – the camera side/up/forward directions when the Euler angles are (0,0,0):


in 3sdmax camera view: side=+x, up=+y, forward=+z
in     gl camera view: side=+x, up=+y, forward=-z

Note, this matrix has the interesting property M=IM to satisfy IM*M=[1].

Good news: I think we’ve found a solution :slight_smile:

The transformation matrix i used beforehand was correct:

    double [] transformmatrix =  { 1, 0, 0, 0,    0, 1, 0, 0,    0, 0, -1, 0,    0, 0, 0, 1};

(purpose of this matrix: from now on, you can place objects in opengl using 3ds coordinates)

But: before applying this transformation in the setCamera method, you have to rotate the (OpenGL)camera so that the view and up vectors correspond to the 3ds camera. In my case it looks like this

    protected void setCamera(GL gl){
        gl.glLoadIdentity();

        //2 rotations needed to adjust the opengl camera direction to the 3ds camera direction
        gl.glRotated(180,0,1,0);
        gl.glRotated(90,1,0,0);

        transformTo3DSMax(gl);

        gl.glRotated(-cam_rot.getX(), 1, 0, 0);
        gl.glRotated(-cam_rot.getY(), 0, 1, 0);
        gl.glRotated(-cam_rot.getZ(), 0, 0, 1);
        gl.glTranslated(-cam_pos.getX(), -cam_pos.getY(), -cam_pos.getZ());   }

Notice that the first rotation by 180 degrees only comes from the change I made to the pivot point of the camera in 3dsmax. ( The default 3ds camera looks into the negative z, I had to change this in 3ds to positive z because of special reasons concerning the rest of my application).
This setCamera method produces the correct view!

So - If anyone is willing to define an absolute camera positioning in OpenGL, using 3DSMax coordinates, the setCamera-method should look like this:

protected void setCamera(GL gl){
    gl.glLoadIdentity();
    gl.glRotated(90,1,0,0);
    transformTo3DSMax(gl);
    gl.glRotated(-cam_rot.getX(), 1, 0, 0);
    gl.glRotated(-cam_rot.getY(), 0, 1, 0);
    gl.glRotated(-cam_rot.getZ(), 0, 0, 1);
    gl.glTranslated(-cam_pos.getX(), -cam_pos.getY(), -cam_pos.getZ());
}

with

protected void transformTo3DSMax(GL gl){
    double [] transformmatrix =  { 1, 0, 0, 0,    0, 0, -1, 0,    0, 1, 0, 0,    0, 0, 0, 1};
    gl.glMultMatrixd(transformmatrix,0);
}

marshats, thanks a LOT for helping me with this, you gave lots a very helpful hints:)