Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Converting Rotations to display correctly in OpenGL

  1. #1
    Junior Member
    Join Date
    Jan 2006
    Posts
    15

    Converting Rotations to display correctly in OpenGL

    I am exporting some simple animation of a rotating box using 1 bone. Because of the differences in the coordinate systems between Max and OpenGL, im getting incorrect results.

    <node id="Bone01" sid="Bone01" name="Bone01" type="JOINT">
    <translate sid="Trans">2.68195 -3.34879e-008 0.766113 </translate>
    <rotate sid="RotZ">0 0 1 0</rotate>
    <rotate sid="RotY">0 1 0 -90</rotate>
    <rotate sid="RotX">1 0 0 0.000327849</rotate>
    <rotate sid="ScaleAxisR">1 0 0 0</rotate>
    <scale sid="Scale">1 1 1 </scale>
    <rotate sid="ScaleAxis">1 0 0 0</rotate>
    </node>


    I convert each rotate tag to a quaternion and then multiply z * y * x.
    For animations,

    <source id="Bone01-Rotate-X-value">
    <float_array id="Bone01-Rotate-X-value-array" count="4">-0.000027 -0.000027 -0.000027 -0.000027</float_array>
    <technique_common>
    <accessor source="#Bone01-Rotate-X-value-array" count="4">
    <param name="ROTX.ANGLE" type="float"/>
    </accessor>
    </technique_common>
    </source>
    //etc.. for Rotate-Y/Z

    <channel source="#Bone01-Rotate-X-sampler" target="Bone01/RotX.ANGLE"/>
    <channel source="#Bone01-Rotate-Y-sampler" target="Bone01/RotY.ANGLE"/>
    <channel source="#Bone01-Rotate-Z-sampler" target="Bone01/RotZ.ANGLE"/>

    What is the best way to convert rotations in Max to rotations in OpenGL?

  2. #2
    Senior Member
    Join Date
    Jul 2004
    Location
    Santa Clara
    Posts
    356
    Was this already addressed here?

  3. #3
    Junior Member
    Join Date
    Jan 2006
    Posts
    15
    Quote Originally Posted by remi
    Was this already addressed here?
    In a way my previous problem has been solved in the sense that i get proper rotations now instead of weird numbers.

    I can see my mesh being animated now, but they do not rotate around the proper axis.

    All i need to know is the math to convert a rotation in Max to give equivalent results in OpenGL.

  4. #4
    Senior Member
    Join Date
    Jan 2006
    Location
    Foster City, CA
    Posts
    540
    There could be any number of things going wrong. Can you post the code you're using to pull the transform in from Collada and apply it in OpenGL? In particular, are you using glRotate, glMultMatrix, or glLoadMatrix? Remember that glMultMatrix and glLoadMatrix want a column-major memory layout, whereas C/C++ is row-major, so if you're using a 2-d array as in float m[4][4], you're going to have to transpose that before passing it along to glMultMatrix/glLoadMatrix, or use the transpose matrix functions (glMultMatrixTranspose iirc).

  5. #5
    Senior Member
    Join Date
    Aug 2005
    Location
    California
    Posts
    165
    Are you taking into account the up_axis change.

    A straight up export from max will most likely be exporting geometry and animations and everything using the z axis as the up axis.

    If you have set up your openGL cameras to see things Y up then all your rotations would look wierd.. your geometry would be sideways too but since you are using a cube you can't notice that.

    When loading a COLLADA document you should pay attention to the <asset> tag. It holds some inportant information such as <up_axis> and <units> which you should pay attention to if you don't want to experience things looking or acting different then your DCC tool.

    I believe switching between the two axis is as simple as a 90 degree rotation around x for all the nodes upon loading.

    -Andy

  6. #6
    Junior Member
    Join Date
    Jan 2006
    Posts
    15
    Quote Originally Posted by sthomas
    There could be any number of things going wrong. Can you post the code you're using to pull the transform in from Collada and apply it in OpenGL? In particular, are you using glRotate, glMultMatrix, or glLoadMatrix? Remember that glMultMatrix and glLoadMatrix want a column-major memory layout, whereas C/C++ is row-major, so if you're using a 2-d array as in float m[4][4], you're going to have to transpose that before passing it along to glMultMatrix/glLoadMatrix, or use the transpose matrix functions (glMultMatrixTranspose iirc).

    Code :
    //The Quaternion which will transform Max transformations to OpenGL
    	AngleAxis MaxToGL;
    	MaxToGL.x = 1.0f;
    	MaxToGL.w = -90.0f * (PI/180.0f);//convert to radian
    	MaxToGL = MaxToGL.convertToQuat();
    	MaxToGL.Normalize();

    Code :
    //For every Bone
    	for(PInt sfb=0;sfb<BoneNameArray.size();++sfb)
    		{			
    			domNode* dn;
    			//Try to get the Node with the same name
    			myDae->getDatabase()->getElement((daeElement**)&dn, 0, e.c_str(), COLLADA_ELEMENT_NODE);			
     
    			e = dn->getName();
    			cout<<"\n\n\nNow processing : "<<e<<"\n";			
    			PInt similj = dn->getTranslate_array().getCount();
    //I get my position vector of the bone here, i swap the y and z manually.
    			float x = dn->getTranslate_array().get(0)->getValue().get(0);
    			float z = -dn->getTranslate_array().get(0)->getValue().get(1);
    			float y = dn->getTranslate_array().get(0)->getValue().get(2);
    			b.setPosition(x,y,z);
     
     
    //Here we get the Bone's initial orientation
    			Quat Final;
     
    			//for every Rotate array
    			for(PInt oiu = 0;oiu<dn->getRotate_array().getCount();++oiu)
    			{
    				//YZ SWAP
    				Quat q1;
    				q1.x = dn->getRotate_array().get(oiu)->getValue().get(0);
    				q1.y = dn->getRotate_array().get(oiu)->getValue().get(1);
    				q1.z = dn->getRotate_array().get(oiu)->getValue().get(2);
    				q1.w = dn->getRotate_array().get(oiu)->getValue().get(3);
    //Values read in are angle-axis, therefore we must convert it to a quaternion.
    				q1.w = q1.w * (PI/180.0f);//change to radians becos values are in degrees
    				q1 = q1.convertToQuat();
     
    				q1.Normalize();			
    	//Combine all rotation arrays into 1 quaternion
    				Final =  Final * q1;
    				Final.Normalize();
    			}
    			//Finally apply MaxToGL to reorient coordinate system.
    			Final = Final * MaxToGL ;

    In the same way, MaxToGL is applied to all animation keyframes, i can post the code if needed. But this is basically what im doing in order to reorient the animation.

  7. #7
    Hi GamerSg,

    I can see you swap y and z manually in translation array, then how about the rotation array? The most important thing is what you've done in Quat::convertToQuat(). Hope you did the right thing in this function

  8. #8
    Senior Member
    Join Date
    Jan 2006
    Location
    Foster City, CA
    Posts
    540
    Man this is a toughie to be honest.
    Quote Originally Posted by zhouzhengchun
    I can see you swap y and z manually in translation array, then how about the rotation array?
    I think that's handled by the final *MaxToGL in the last line.

    Some things you might want to check:

    (1) "MaxToGL.w = -90.0f * (PI/180.0f);" Shouldn't that be 90 instead of -90?

    (2) Is your convertToQuat function correct?

    (3) Are you sure you want
    Code :
    Final =  Final * q1;
    ...
    Final = Final * MaxToGL ;
    instead of
    Code :
    Final =  q1 * Final;
    ...
    Final = MaxToGL * Final;
    (4) Are you passing the transform to OpenGL correctly?

    Without actually being able to sit down and debug your code with a simple test case, it's hard . (1) and (3) are my best guesses as to what's going wrong.

  9. #9
    (1) "MaxToGL.w = -90.0f * (PI/180.0f);" Shouldn't that be 90 instead of -90?
    Hi sthomas,

    what's the full expression of MaxToGL?
    like this:
    Quaternion MaxToGL(1,0,0,-90.0f * (PI/180.0f))?

  10. #10
    Senior Member
    Join Date
    Jan 2006
    Location
    Foster City, CA
    Posts
    540
    GamerSg posted it in his last post:
    Code :
    //The Quaternion which will transform Max transformations to OpenGL
       AngleAxis MaxToGL;
       MaxToGL.x = 1.0f;
       MaxToGL.w = -90.0f * (PI/180.0f);//convert to radian
       MaxToGL = MaxToGL.convertToQuat();
       MaxToGL.Normalize();

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •