Reputation: 105
i created a model in 3d max, and i centered it in the world.. nevertheless when i put it in XNA and apply a rotation through XNA it seems like its center of rotation is NOT in the actual object but slightly away from it so it lookslike the object is moving in circles rather tahn rotationg... which is annoying any1 know how to fix this?
Upvotes: 0
Views: 1699
Reputation: 11
The problem is that the pivot point in 3D Studio Max is not passed to XNA. You can change the pivot point all day and the bone transforms and vertices will stay the same. It's just not exported right.
I have a MAXScript at http://metlab.cse.msu.edu/xna.html that fixes this problem.
Charles
Upvotes: 1
Reputation: 29041
Just to expand a bit on @Steve H's answer, here are a couple of possibilities:
In your XNA code, you're not applying the bone transforms to your model. Like most modeling tools, Max tends to modify the world transformation matrix for a model rather than the vertices themselves. Transforming vertices tends to introduce small floating-point errors ie, a vertex at 1,0,0 rotated Pi/2 radians about the z axis may be come 0,0.99999,0 instead of 0,1,0 - that's just the nature of floating-point math, and is also the reason that, in your game, you always transform from the source geometry.
Here's a link to a bone transforms example on MSDN (from v3.1, but there are plenty of v4 examples out there): Pay attention to the myModel.CopyAbsoluteBoneTransformsTo(transforms)
and the effect.World
assignment. This example is for BasicEffect
, but even with your own effect you'll need to extract the bone transforms and apply them. You could do that when the model is loaded if, for example, you're using a custom shader. (Note that the bone transforms are necessary even if you haven't really defined any bones in your model in Max.)
(Borrowed from the linked MSDN article)
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
// Copy any parent transforms.
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in myModel.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = transforms[mesh.ParentBone.Index] *
Matrix.CreateRotationY(modelRotation)
* Matrix.CreateTranslation(modelPosition);
effect.View = Matrix.CreateLookAt(cameraPosition,
Vector3.Zero, Vector3.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f), aspectRatio,
1.0f, 10000.0f);
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}
base.Draw(gameTime);
}
The other possibility is that, in Max, the object's pivot (the center about which all rotate/scale/translate transforms are based) isn't centered to the mesh. This is easy to change.
Upvotes: 0
Reputation: 5519
When you centered the object in the 3ds world, it did not alter the vertex positions. It only created a matrix that can transform the vertices from where they were to where you put them.
Possibly, because often you don't have a visual reference to the world origin & don't realize your model is offset in XNA, it may not be obvious that you haven't taken this matrix into account.
This is done through the Model.CopyAbsoluteBoneTransformsTo() to place that matrix (which has become a "Bone" transform by way of the content processor) into an array that you can use while setting the effect.World.
If this sounds like it may be the issue and you want a quick example of the code, let us know.
Upvotes: 1