# Gah! Right to Left Handed Conversion Driving Me Crazy

## Recommended Posts

I have a 3D studio exporter which works fine, but my models are sideways because max is right handed and has y and z swapped. So, when exporting I swap y and z and negate z. This work fine for the model, but for the animation frames which are exported as translations and euler angles it doesn't seem to work. It seems to be a problem with the euler angles to which I am doing the same conversion. I have tried all permetations of converting the euler angles I can think of, but nothing is working. Any help as to what is going on here would be appreciated. Thanks

##### Share on other sites
Hi Raeldor,

I usually try to avoid giving advice on things I don't have direct experience with, which includes converting animations between coordinate systems. But since no one's answered yet I thought I'd just ask if you could give a more detailed description of the coordinate systems involved. For example you could say (assuming you're looking from behind the model), 'my system has z up, y forward, and x right, and max has y up, z forward, and x left'. Or whatever. That might make it easier to offer a specific suggestion about how to convert between the two systems.

##### Share on other sites
Quote:
 Original post by jykHi Raeldor,I usually try to avoid giving advice on things I don't have direct experience with, which includes converting animations between coordinate systems. But since no one's answered yet I thought I'd just ask if you could give a more detailed description of the coordinate systems involved. For example you could say (assuming you're looking from behind the model), 'my system has z up, y forward, and x right, and max has y up, z forward, and x left'. Or whatever. That might make it easier to offer a specific suggestion about how to convert between the two systems.

Thank you. Any advice right now would be good advice. DirectX seems to have X right, Y up and Z into the distance. Max has X right, Z up and Y into the distance. I have negated one the the axis to convert from right to left handed when exporting vertices and normals which seems to work fine, but taking the euler angles from the conversion and doing the same does not give the desired result.

At this time I am not really sure if it is my math or the idiosynchrocies (spelling?) of Max. I read in the help file for max that taking rotation values from the matrix gives you a left handed rotation where as the rest of max is right handed. How can they use left handed matrices on a right handed system? Besides when I do take the rotation values it looks exactly the same as the rotation values in the interface which are supposed to be right handed.

FYI, I am getting the rotation values down the hierarchy by multiplying the world matrix for the node by the inverse of it's parent. That seems to work ok.

##### Share on other sites
Well, I don't think I have any more ideas - I just don't know enough about max or its format. But, here is a link to a series of articles (note the 'next time' link at the bottom) which appears to be related to the subject. It's several years old and I have no idea if it'll be useful, but who knows...

##### Share on other sites
Quote:
 Original post by RaeldorThank you. Any advice right now would be good advice. DirectX seems to have X right, Y up and Z into the distance. Max has X right, Z up and Y into the distance. I have negated one the the axis to convert from right to left handed when exporting vertices and normals which seems to work fine, but taking the euler angles from the conversion and doing the same does not give the desired result.

Hi Raeldor, the issue is that you do not need to negate the Z axis in your conversion. As you say, the 3ds max Y axis points into the screen and the Z axis up, so swapping the Z and Y axis will make your Z point into the screen and Y up, the way directx likes it to be. You might also want to change the winding order of your triangles or you could change the cullmode. And don't forget to swap the axis on your normals and any transforms you export as well.

hope this helps,
svein

##### Share on other sites
Quote:
Original post by sveinm
Quote:
 Original post by RaeldorThank you. Any advice right now would be good advice. DirectX seems to have X right, Y up and Z into the distance. Max has X right, Z up and Y into the distance. I have negated one the the axis to convert from right to left handed when exporting vertices and normals which seems to work fine, but taking the euler angles from the conversion and doing the same does not give the desired result.

Hi Raeldor, the issue is that you do not need to negate the Z axis in your conversion. As you say, the 3ds max Y axis points into the screen and the Z axis up, so swapping the Z and Y axis will make your Z point into the screen and Y up, the way directx likes it to be. You might also want to change the winding order of your triangles or you could change the cullmode. And don't forget to swap the axis on your normals and any transforms you export as well.

hope this helps,
svein

Thank you. This seems to work for the geometry, but the rotation animations are still wrong somewhere. If I take my rotation information as euler angles, should I just be able to swap the axis in the same way, or is it more complicated than that?

##### Share on other sites
Quote:
 Original post by RaeldorThank you. This seems to work for the geometry, but the rotation animations are still wrong somewhere. If I take my rotation information as euler angles, should I just be able to swap the axis in the same way, or is it more complicated than that?

My guess would be that you should be able to just swap the axis in the same way for your angles and it should work. However, if the animation used to work when the model was on its side (pre y/z swap), you will probably have to change the order you apply the rotations in, and possibly the sign of the angles as well. Sorry about this sounding pretty vague, but these things tend to be a bit confusing. Another thing I would recommend would be to make some simple animations, rotating around each of the axis to see which components you need to swap, and wether the signs are right etc. Also, don't forget to swap the y and z on your translations as well.

good luck,
svein

##### Share on other sites
hi. swapping y with z for direct x and -y with z for opengl works fine for geometry, but it gets complicated when using textures and stuff. the method i use (for opengl, but it would work for directx too) is to apply a rotation and save it on the stack before all transformations in the scene, after you load the identity matrix. In opengl will be:
glRotatef(90.0, 1.0, 0, 0); //a rotation around the X axis, that brings up the Y axis)
glPushMatrix();
....
//al the transform code goes here
....
glPopMatrix();

hope it helps.

##### Share on other sites
Quote:
Original post by sveinm
Quote:
 Original post by RaeldorThank you. This seems to work for the geometry, but the rotation animations are still wrong somewhere. If I take my rotation information as euler angles, should I just be able to swap the axis in the same way, or is it more complicated than that?

My guess would be that you should be able to just swap the axis in the same way for your angles and it should work. However, if the animation used to work when the model was on its side (pre y/z swap), you will probably have to change the order you apply the rotations in, and possibly the sign of the angles as well. Sorry about this sounding pretty vague, but these things tend to be a bit confusing. Another thing I would recommend would be to make some simple animations, rotating around each of the axis to see which components you need to swap, and wether the signs are right etc. Also, don't forget to swap the y and z on your translations as well.

good luck,
svein

I finally got it to work, but it's not ideal. Instead of swapping the Y and Z, I instead negated the Z axis for all vertex and translation output. However to get the rotations to work I had to negate the X and Y portion or the euler angles. What is the logic behind this?

As I say it is not ideal, as now I have to rotate all my models when I import them. If I can figure out why I have to negate the XY of the rotations, maybe it will help fix the problems I am having when swapping YZ on the vertices.

##### Share on other sites
Quote:
 Original post by RaeldorI finally got it to work, but it's not ideal. Instead of swapping the Y and Z, I instead negated the Z axis for all vertex and translation output. However to get the rotations to work I had to negate the X and Y portion or the euler angles. What is the logic behind this?As I say it is not ideal, as now I have to rotate all my models when I import them. If I can figure out why I have to negate the XY of the rotations, maybe it will help fix the problems I am having when swapping YZ on the vertices.

Not quite sure what the logic is behind negating the x and y portion of the euler angles are, but I can only assume that when you change the coordinate system around like that you need to change the sign of your rotations.

Anyways, if you're calculating your euler angles from the world transform of the node, you will need to swap the rows and columns of your matrix around before you calculate the euler angles as well, that is if you would like ot swap the y and z of your vertices around. Just swap row 1 and 2 and column 1 and 2 around before you calculate the euler angles, that way the transform should be in the same coordinate space as your vertices.

svein

##### Share on other sites
Hi,

I'm not a math wizzard, so I can't explain how I came up with the following code (it was pure hack : try something, see if it works, etc. ^^) But I've been using it for more than half a year now, and it works.

Here's a piece of code I use in my exporter :

// transform each vertexfor (unsigned int v = 0; v < m_VertexList.GetNum(); v++){   m_VertexList[v].position.x  = -m_VertexList[v].position.x;   m_VertexList[v].normal.x    = -m_VertexList[v].normal.x;}// ...// extract the transformations from the transformtransform.getRotation(eulerRotation);transform.getScale(scale);translation  = transform.translation(MSpace::kWorld);// convert it to left handed :// - negate translation along X// - negate rotations around Y and Ztranslation.x	= -translation.x;eulerRotation.y	= -eulerRotation.y;eulerRotation.z	= -eulerRotation.z;// rebuild a transformtion matrix from the modified transformationsMTransformationMatrix transformationMatrix;transformationMatrix = transformationMatrix.identity;transformationMatrix.rotateBy(eulerRotation, MSpace::kWorld);transformationMatrix.setScale(scale, MSpace::kObject);transformationMatrix.setTranslation(translation, MSpace::kWorld);

It's the same as you do. I think that when we switch from right to left handed systems, the rotation orders change. So we should invert all rotations. BUT we also have to invert 1 axis. So, inverting this axis and inverting the rotation around it would give the same rotation. That's why, if we invert X, we only need to invert rotations around Y and Z.
I'm pretty sur that if we add to invert the Y axis (for example), we would have to invert rotations around X and Z.

That's the only explanation I can find with the pieces of math I still remember from my studies ^^

##### Share on other sites
Euler angle rotation is not commutative. Also, they rotate clockwise (left handed) or anti-clockwise (right handed) depending on the handedness of the coordinate system.

Also, to my understanding, Euler angles work by a rotation first around the x then the y then the z axes. Currently doing this with a right handed model on a left handed system, you're actually doing rotations around x, then z, then y.

So theoretically, in order for this to work, first you should swap your y and z axes to convert the coordinate system (i.e. swap your y and z components of the Euler angle set).

Thereby rotations will be applied in x, y and z in correct order.

Now, only slightly more difficult, negate the angle of each subset in the Euler angle set you're using.

-X, -Y, -Z

reason being that you have to convert from rotating anti-clockwise to clockwise.

I hope this works, I'm a little rusty with Euler angles and I've never actually used them in a game or programmed them or converted them from right handed to left handed. This is more or less a guess and my doing some working in the past 5 minutes off the top of my head.

##### Share on other sites
Quote:
 It's the same as you do. I think that when we switch from right to left handed systems, the rotation orders change. So we should invert all rotations. BUT we also have to invert 1 axis. So, inverting this axis and inverting the rotation around it would give the same rotation. That's why, if we invert X, we only need to invert rotations around Y and Z.I'm pretty sur that if we add to invert the Y axis (for example), we would have to invert rotations around X and Z.

Thanks. This makes a lot of sense and I think that's what is going on here. However, I still can't get my head around what is going on when I instead swap the Y and Z axis.

Quote:
 So theoretically, in order for this to work, first you should swap your y and z axes to convert the coordinate system (i.e. swap your y and z components of the Euler angle set).Thereby rotations will be applied in x, y and z in correct order.Now, only slightly more difficult, negate the angle of each subset in the Euler angle set you're using.-X, -Y, -Zreason being that you have to convert from rotating anti-clockwise to clockwise.

I tried this, but still no luck and the animations are still mangled. I tried a few combinations of negating different axis, but still no joy.

##### Share on other sites
Question, are you negating the angles or their sines and cosines? There's a BIG difference between the two.

##### Share on other sites
Quote:
 Original post by Leo_E_49Question, are you negating the angles or their sines and cosines? There's a BIG difference between the two.

I am negating the angles, ie the euler values.

##### Share on other sites
Is there any chance you could change the animation system to use quaternions? There are a bunch of other advantages to this representation as well. In my Max exporter I just convert the quaternions by converting to axis angle, then applying the same axis swap (y <-> z) then converting back to a quaternion. This probably isn't the best way but it works and makes sense.

##### Share on other sites
Quote:
 Original post by d00fusIs there any chance you could change the animation system to use quaternions? There are a bunch of other advantages to this representation as well. In my Max exporter I just convert the quaternions by converting to axis angle, then applying the same axis swap (y <-> z) then converting back to a quaternion. This probably isn't the best way but it works and makes sense.

I am currently exporting as euler angles and then converting the eulers into quaternions in my engine. The reason I went with eulers is because it makes the export file more readable and easier to find errors.

I could go with quaternions (I originally was using quaternions but changed to eulers), but I am thinking I will still have the same problem and it will just make it worse because the quaternions are pretty unreadable and I will end up with less of a clue than I have now (pretty much why I changed to eulers in the first place! :P).

##### Share on other sites
Would you mind showing us your actual code? It might make things a little easier.

##### Share on other sites
Quote:
 Original post by Leo_E_49Now, only slightly more difficult, negate the angle of each subset in the Euler angle set you're using.-X, -Y, -Z

Actully come to think of it... Why do you need to swap the Y and Z axes for rotations? Translations yes, but rotations, this is confusing me. :S

This concept supports your results from negating X and Y components. All you should have to do is negate the Z component too. Why it popped into my head that you have to swap the Y and Z axes for rotations I don't know. :(

##### Share on other sites
Quote:
 Actully come to think of it... Why do you need to swap the Y and Z axes for rotations? Translations yes, but rotations, this is confusing me. :S

Yeah, it's confusing me too. I know that it doesn't work if I just leave them as is, so swapping the Y and Z for vertices definitely affects the rotations somehow.

##### Share on other sites
Quote:
 Original post by Leo_E_49Would you mind showing us your actual code? It might make things a little easier.

Ok, this is the code that works...
---- my first export script---- export all selected objects and scene materials-- written by ray price 8/30/05---- check we have a selected objectif selection.count < 1 then	messagebox "You must have at least one object selected."else(	-- check validity of objects	allvalid=true	for s=1 to selection.count do	(		-- must be an editable mesh		mytri = snapshotasmesh selection[s]		mymesh = selection[s]		if classof mytri != trimesh then		(			msg="Mesh "+mymesh.name+" is not an editable mesh.  Cannot export."			messagebox msg			allvalid=false			exit		)		else		(			-- mesh must have a standard material			if classof mymesh.material != standardmaterial then			(				msg="Mesh " + mymesh.name + " must have a standard material.  Cannot export."				messagebox msg				allvalid=false				exit			)		)	)		-- if all objects are valid for export	if allvalid then	(		-- open binary file		myfilename = getsavefilename caption:"Export to..." types:"Data(*.dat)|*.dat"		outfile = fopen myfilename "wbS"					-- get used material count		usedmaterialcount=0		for m=1 to scenematerials.count do		(			-- make sure item is used			used=false			for s=1 to selection.count do			(				matindex = finditem scenematerials selection[s].material				if matindex == m then				(					used=true					exit				)			)						-- if used, add to count			if used then				usedmaterialcount = usedmaterialcount + 1		)						-- write out scene materials		writeshort outfile usedmaterialcount #unsigned		for m=1 to scenematerials.count do		(			-- make sure item is used			used=false			for s=1 to selection.count do			(				matindex = finditem scenematerials selection[s].material				if matindex == m then				(					used=true					exit				)			)						-- if used, continue			if used then			(				-- get next material				thismat=scenematerials[m]						-- write out the material properties				writefloat outfile (thismat.ambient.a/255)				writefloat outfile (thismat.ambient.r/255)				writefloat outfile (thismat.ambient.g/255)				writefloat outfile (thismat.ambient.b/255)				writefloat outfile (thismat.diffuse.a/255)				writefloat outfile (thismat.diffuse.r/255)				writefloat outfile (thismat.diffuse.g/255)				writefloat outfile (thismat.diffuse.b/255)				writefloat outfile (thismat.specular.a/255)				writefloat outfile (thismat.specular.r/255)				writefloat outfile (thismat.specular.g/255)				writefloat outfile (thismat.specular.b/255)								-- write out the texture filename				if classof thismat.diffusemap == undefinedclass then	 				writestring outfile ""				else					writestring outfile thismat.diffusemap.filename			)		)				-- write as a hierarchy so only process root objects		rootcount=0		for i=1 to selection.count do		(			if selection[i].parent == selection[1].parent then				rootcount=rootcount+1		)				-- for each selected object		writeshort outfile rootcount #unsigned		for s=1 to selection.count do		(			-- process root objects resursively			if selection[s].parent == selection[1].parent then			(				writemesh selection[s] outfile			)		)				-- close file		fclose outfile				-- success		messagebox "Export complete"	))-- write out vertex details now we have the index!!fn writevertex mytri mymesh vindex outfile =(	-- now we have the real vertex details, output to file	-- reverse z and y like direct3d	-- multiply world vertex by inverse mesh objecttransform to get true local	--	-- mytri tri is fixed vertices at time of snapshot, so make sure snapshot	-- is not taken in pose position!	--	meshvert = in coordsys world getvert mytri vindex	meshvert = meshvert * (inverse mymesh.transform)	writefloat outfile meshvert.x	writefloat outfile meshvert.y	writefloat outfile -meshvert.z		-- now we need to calculate the vertex normal	-- using all the attached polys faces	vertfaces = meshop.getpolysusingvert mytri vindex	vertnorm = point3 0 0 0	for vf=1 to vertfaces.count do	(		if vertfaces[vf] then		(			-- get the normal for this face			-- use mesh to get local normal, not tri			thisnorm = in coordsys local getfacenormal mymesh vf						-- add to running normal			vertnorm = vertnorm + thisnorm		)	)		-- normalize our normal	vertnorm = normalize vertnorm	-- output the vertex normal	writefloat outfile vertnorm.x	writefloat outfile vertnorm.y	writefloat outfile -vertnorm.z)fn writemesh mymesh outfile =(	-- set to first animation frame	at time 1	(		-- get mesh version of object--		mytri = snapshotasmesh mymesh		mytri=mymesh			-- write out name		writestring outfile mymesh.name			-- get local position and rotation info from controller helper		-- use it to build a local transform matrix		conthelper=exposetm pos:[0,0,0]		conthelper.exposenode=mymesh		conthelper.localreferencenode=mymesh.parent				-- write out initial rotation		-- this is currently in left handed form, need to convert to right handed		-- also, y and z are reversed		myquat=eulertoquat (eulerangles conthelper.localeulerx conthelper.localeulery conthelper.localeulerz)		myquat=inverse myquat		writefloat outfile myquat.x		writefloat outfile myquat.y		writefloat outfile myquat.z		writefloat outfile myquat.w				-- write out initial position		writefloat outfile conthelper.localposition.x		writefloat outfile conthelper.localposition.y		writefloat outfile -conthelper.localposition.z				-- see if we have uv mapping		mapsupport=meshop.getmapsupport mytri 1				-- get vertex count		if mapsupport then			numverts = meshop.getnummapverts mytri 1		else			numverts = meshop.getnumverts mytri				-- find true vertex count (those used by texture faces)		if mapsupport then		(			trueverts = 0			for v=1 to numverts do			(				-- find texture faces that uses this vert				tvertfaces = meshop.getmapfacesusingmapvert mytri 1 v				for f=1 to tvertfaces.count do				(					-- if this face uses the texture vertex					if tvertfaces[f] then					(						trueverts = trueverts + 1						exit					)				)			)		)		else			trueverts = numverts				-- write out vertex count		writelong outfile trueverts #unsigned		-- we have to build a mapping array because some of the texture vertices can be un-used		-- by any of the faces					-- really we must output same number of vertices		-- as that of tverts, not verts! this will mean		-- outputing the texture vertices instead of the		-- regular vertices and the texture faces instead		-- of the regular faces		ourvertindex=1		ourvertmap=#()		for v=1 to numverts do		(			-- default index map to zero			ourvertmap[v]=0						if not mapsupport then			(				-- write out this vertex				writevertex mytri mymesh v outfile								-- output dummy uv for now!				writefloat outfile 0				writefloat outfile 0								-- build our vertex index array				ourvertmap[v]=ourvertindex				ourvertindex=ourvertindex+1			)			else			(				-- find texture faces that uses this vert				tvertfaces = meshop.getmapfacesusingmapvert mytri 1 v				for f=1 to tvertfaces.count do				(					-- if this face uses the texture vertex					if tvertfaces[f] then					(						-- find which index in texture face						tvertindexes = meshop.getmapface mytri 1 f						tvindex = 0						if tvertindexes[1] == v then tvindex=1						if tvertindexes[2] == v then tvindex=2						if tvertindexes[3] == v then tvindex=3												-- find same index in mesh face						vertindexes = getface mytri  f						vindex = vertindexes[tvindex]												-- write vertex out using function						writevertex mytri mymesh vindex outfile												-- now get texture vertex and output uv						texvert = meshop.getmapvert mytri 1 v						writefloat outfile texvert.x						writefloat outfile texvert.y												-- build our vertex index array						ourvertmap[v]=ourvertindex						ourvertindex=ourvertindex+1										-- we only need to find the first one						exit					)				)			)		)			-- write out number of faces		if mapsupport then			numfaces = meshop.getnummapfaces mytri 1		else			numfaces = meshop.getnumfaces mytri		writelong outfile numfaces #unsigned			-- now write out mesh faces using texture faces so we get		-- correct corresponding uv's		for f=1 to numfaces do		(			-- use texure vertex index			-- use zero based though, so -1!			if mapsupport then				face=meshop.getmapface mytri 1 f			else				face=getface mytri f			-- reverse winding order of faces for left handed			writeshort outfile (ourvertmap[face.x]-1) #unsigned			writeshort outfile (ourvertmap[face.z]-1) #unsigned			writeshort outfile (ourvertmap[face.y]-1) #unsigned		)	)		-- write out material index	matindex = finditem scenematerials mymesh.material	writeshort outfile matindex #unsigned		-- animationrange.start	-- animationrange.end	-- currenttime	-- framerate	-- trackbar.getnextkeytime	-- write out number of rotation keyframes	writelong outfile (animationrange.end-animationrange.start+1) #unsigned		-- loop through animation frames	for fr=animationrange.start to animationrange.end do	(		-- write out rotation keyframe		at time fr		(			writefloat outfile (fr/framerate)			if mymesh.parent == selection[1].parent then				mymat=in coordsys world mymesh.transform			else				mymat=in coordsys world (mymesh.transform*(inverse mymesh.parent.transform))			myeuler=(inverse mymat.rotationpart) as eulerangles			writefloat outfile -myeuler.x			writefloat outfile -myeuler.y			writefloat outfile myeuler.z		)	)		-- write out number of translation keyframes	writelong outfile (animationrange.end-animationrange.start+1) #unsigned		-- loop through animation frames	for fr=animationrange.start to animationrange.end do	(		-- write out translation keyframe		at time fr		(			writefloat outfile (fr/framerate)			if mymesh.parent == selection[1].parent then				mypos=in coordsys world mymesh.transform.position			else				mypos=in coordsys world (mymesh.transform*(inverse mymesh.parent.transform)).position			writefloat outfile mypos.x			writefloat outfile mypos.y			writefloat outfile -mypos.z		)	)			-- delete cont helper	delete conthelper		-- only count children that are selected	childcount=0	for c=1 to mymesh.children.count do	(		if mymesh.children[c].isselected then			childcount=childcount+1	)			-- write out number of children	writeshort outfile childcount #unsigned		-- process children	for c=1 to mymesh.children.count do		if mymesh.children[c].isselected then			writemesh mymesh.children[c] outfile)

However, when I swap the Y and Z axis instead of using the negating of Z then it all goes pear-shaped when it's bought into my engine. The fact that it works using the negating leads me to believe my engine is ok, and that the euler to quaternions and quaternions to matrix functions are all good. I think the issue lies somewhere in how to handle exporting the rotations when you swap Y and Z.

##### Share on other sites
Hi,
I had the same problem once, and I realized that I had to talk to the artists on their own terms... so I switched the hand of the engine.

This is pretty easy to do with DX and just in 3 easy steps.

a. Instead of using D3DXCreateLeftHandedViewMatrix (or something like that... I dont recall the exact name) just use the D3DXCreateRightHandedViewMatrix in order to create your view. This puts you in the same system than Max.

b. Change your up vector. In a D3D app this is usually Y for up and Z for depth, noy you use Z for up and Y for depth.

c. Change your cull mode from CCW to CW.

Thats all. Its really easy and your artists will thank you a lot.

Luck!
Guimo

##### Share on other sites
Then you'd have to change your entire game to a left handed coordinate system, wouldn't you?

Try this, for translations and vertex positions only swap the Y and Z coordinates but for rotations only negate all x, y and z components without swapping the Y and Z axes. This should work and is logical and can be explained.

When you rotate around the z axis in the left handed model, converting that you don't want to rotate around the y axis!, you want to rotate the other direction about the z axis! The right handedness changes rotations from clockwise to anti-clockwise but it doesn't affect the axes at all!

[eureka moment]When you translate, sweeping the y to z axis in the left handed coordinate system occurs clockwise, in the right handed system it occurs anti-clockwise. Therefore we reverse the direction which one is swept to another by swapping their positions. This is why we swap y and z axes for translations, we're negating the rotation of one axis to the other. It all makes sense now! :)[/eureka moment]

Ignore the eureka moment, things just fell in place in my mind and I felt like writing it down. If you can actually understand it, congratulations, you must be one of the best translators on the planet.

##### Share on other sites
Quote:
 Try this, for translations and vertex positions only swap the Y and Z coordinates but for rotations only negate all x, y and z components without swapping the Y and Z axes. This should work and is logical and can be explained.

I tried this and it VERY close, but still not quite right. My characters legs appear crossed. Interestingly enough I am not sure if this applies, but the the model is a four legged animal. The front legs look wrong, but the back legs look right. Is it possible that swapping the Y and Z could produce an effect where the rotations have to be reversed on only one side of the axis?

##### Share on other sites
Quote:
 Original post by RaeldorI tried this and it VERY close, but still not quite right. My characters legs appear crossed. Interestingly enough I am not sure if this applies, but the the model is a four legged animal. The front legs look wrong, but the back legs look right. Is it possible that swapping the Y and Z could produce an effect where the rotations have to be reversed on only one side of the axis?

I still think you will need to rearrange the rows and columns in the matrix before you convert to euler angles, pretty much the same way as you do with the y and z components in the vertices and normals, the following code snippet should do it ....

-- your code			if mymesh.parent == selection[1].parent then				mymat=in coordsys world mymesh.transform			else				mymat=in coordsys world (mymesh.transform*(inverse mymesh.parent.transform))	--insert this bit			m = matrix3 [1,0,0] [0,0,1] [0,1,0] [0,0,0]			mymat = m * mymat * m-- your code continues here...			myeuler=(inverse mymat.rotationpart) as eulerangles

hopefully this will do the trick, I do something similar in my animation exporter and it works fine, however I use quaternions not euler angles.

svein

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628396
• Total Posts
2982438

• 10
• 9
• 19
• 24
• 10