#### Archived

This topic is now archived and is closed to further replies.

# Skeletanal animation (ms3d files)

This topic is 5562 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I''m trying to get skeletanal animation working using Milkshape''s .ms3d file format, yet i''m not sure i understand how to go about things. Currently I''ve loaded all the info from file, so i''m left with a whole bunch of vertices (+materials, textures etc.) and a bunch of bones/joints with keyframe info. For the time being i''m just trying to get a wireframe skeleton drawing right - each bone has a position (x,y,z) associated with it, and a rotational (pretty certain this is a set of x,y,z rotations). So how would i go about drawing these? I''d guess at starting from the root bone and recursivly going though all those attached to it, somehow applying all the transformations as i go. But this seems very vauge, I''d appreciate any pointers on how to go about this. Thanks in advance.

##### Share on other sites

I''m guessing that milkshape stores angles in radians, since the angles i''m reading in are pretty small. But i don''t understand how i''m supposed to chain the rotations together to create the basic bone structure - are they relative or global rotations?

At the moment i''m calling transformBone() (below) for every bone at the start to calc the transform matrix, then using this as a relative transformation between bones and recursivly drawing them.

  	public void transformBone(Bone currentBone)	{		// Create the transform matrix from the rotational and translational info.		Matrix4f tempMatrix = new Matrix4f();		Matrix4f currentTrans = new Matrix4f();				// Rotation x,y,z		float rotX = currentBone.joint.rotation[X_ROT];		float rotY = currentBone.joint.rotation[Y_ROT];		float rotZ = currentBone.joint.rotation[Z_ROT];				// Radians -> Degrees		float toDeg = (float)(180 / java.lang.Math.PI);		rotX *= toDeg;		rotY *= toDeg;		rotZ *= toDeg;						currentTrans.rotateX( rotX );		currentBone.transform.multiply(tempMatrix, currentTrans);		tempMatrix.set(currentBone.transform);				currentTrans.rotateY( rotY );		currentBone.transform.multiply(tempMatrix, currentTrans);		tempMatrix.set(currentBone.transform);				currentTrans.rotateY( rotZ );		currentBone.transform.multiply(tempMatrix, currentTrans);		tempMatrix.set(currentBone.transform);						// Translation x,y,z		currentTrans.translate( currentBone.joint.translation[X_COORD],								currentBone.joint.translation[Y_COORD],								currentBone.joint.translation[Z_COORD] );				currentBone.transform.multiply(tempMatrix, currentTrans);	}

##### Share on other sites
As far as I remember ms3d stores relative rotations. Think it stores both rotation and translation keyframes in the same way (3 axis values) Not sure from what you said, but could be the problem.

Have you read Brett Porter''s tutorial?

If you''d like to see a similar but slightly different approach you can get my old ms3d loader from cvs of the unifighter project at sourceforge (or view it thru the webcvs interface).

##### Share on other sites
Yes, i''ve seen the RealSoonNow tuturial, but its prety cryptic At the moment i seem to have built the relative transformation matrices from a parent bone to itself, but it only works for the bones directly off the root - anything else is screwed up. Perhaps my drawing function is wrong?:

  // Initially called with the root bone and a pos of 0,0,0	public void drawBone(GL gl, Bone currentBone, Vector3f currentPos)	{		// Prev point		gl.vertex3f(currentPos.x, currentPos.y, currentPos.z);				// transform		currentPos.transformPoint(currentBone.relativeTransform, currentPos.x, currentPos.y, currentPos.z);				gl.color3f(1f, 1f, 1f);				// Updated point		gl.vertex3f(currentPos.x, currentPos.y, currentPos.z);				gl.color3f((float)java.lang.Math.random(), (float)java.lang.Math.random(), (float)java.lang.Math.random() );				// Recurse		Vector3f tempVector = new Vector3f();		for (int i=0; i<currentBone.childBones.length; i++)		{		//	tempVector.set(0f, 0f, 0f);			tempVector.set(currentPos);						drawBone(gl, currentBone.childBones[i], tempVector);		}	}

##### Share on other sites
Your drawing code looks OK, but then I don''t know java

Looking thru your code and comparing to mine (that I haven''t looked at for over a year... so I''m a little rusty on this) the things I noticed that could be issues were:

You''re using eulers for rotation - convert these to quaternions maybe to avoid gimbal lock? I know milkshape stores them as eulers, but converting them isn''t too much hassle.

Also look at the initial positioning of the joints - you have to use that as well as the keyframed relative transformations.

Next (and this could just be me misunderstanding your math funcs) it looks like you are applying the x rotation to the joint, then the x and y, then the x y and z. Shouldn''t you be doing something like

CurrentTrans.RotateX(xrot);
CurrentTrans.RotateY(yrot);
CurrentTrans.RotateZ(zrot);
CurrentBone.PostMultiply(CurrentTrans);

?

Assuming those Rotate funcs are cumulative. But most math libs tend to call the non cumulative transformation function LoadRotate or something like that.

Dan

##### Share on other sites
Milkshape''s bones use an odd rotation system. basically what you do is after loading all of the bone data, you transform like this.

RotateZ
RotateY
RotateX
Translate

The key part here is the fact that the rotations are meant to be applied in ZYX order, not XYZ order. I hope that helps!

1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 15
• 13
• 9
• 12
• 10
• ### Forum Statistics

• Total Topics
631442
• Total Posts
3000087
×