I am trying to import in XNA an .fbx model exported with blender.
Here is my drawing code
public void Draw()
{
Matrix[] modelTransforms = new Matrix[Model.Bones.Count];
Model.CopyAbsoluteBoneTransformsTo(modelTransforms);
foreach (ModelMesh mesh in Model.Meshes)
{
foreach (BasicEffect be in mesh.Effects)
{
be.EnableDefaultLighting();
be.World = GameCamera.World * Translation * modelTransforms[mesh.ParentBone.Index];
be.View = GameCamera.View;
be.Projection = GameCamera.Projection;
}
mesh.Draw();
}
}
The problem is that when I start the game some model parts are overlying others instead of being behind. I've tried to download other models from internet but they have the same problem.
This line:
be.World = GameCamera.World * Translation * modelTransforms[mesh.ParentBone.Index];
is usually arrainged the other way around, and the order that you multiply matrices in will make the results different. Try this:
be.World = modelTransforms[mesh.ParentBone.Index] * GameCamera.World * Translation;
Related
I have a window form with xna included in a control, right now I have two models in one area of the screen. The thing is I need to rotate both models at the same time, I can rotate one object wich is a tank and the other is the skybox(landscape) rendered in a box.
The tank move with data provided by a serial port which is in real time, the tanks move perfectly, but I can't rotate the map.
(the ground should be moving along with the tank).
http://i61.tinypic.com/2efqrvc.jpg
I use this code to render the landscape:
private void SkyBoxRender()
{
RasterizerState originalRasterizerState = GraphicsDevice.RasterizerState;
RasterizerState rasterizerState = new RasterizerState();
rasterizerState.CullMode = CullMode.None;
GraphicsDevice.RasterizerState = rasterizerState;
aspectRatio = GraphicsDevice.Viewport.AspectRatio;
orientacion = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(-85.0f), MathHelper.ToRadians(TiempoReal.rollPitch[1]), MathHelper.ToRadians(TiempoReal.rollPitch[0]));
cameraPositionSkyBox = distance * new Vector3((float)Math.Sin(angle), 0, (float)Math.Cos(angle));
foreach (EffectPass pass in skyBoxEffect.CurrentTechnique.Passes)
{
pass.Apply();
foreach (ModelMesh mesh in skyBox.Meshes)
{
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect = skyBoxEffect;
part.Effect.Parameters["World"].SetValue(Matrix.CreateScale(50.0f) * Matrix.CreateTranslation(cameraPositionSkyBox));
part.Effect.Parameters["View"].SetValue(view);
part.Effect.Parameters["Projection"].SetValue(Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f));
part.Effect.Parameters["SkyBoxTexture"].SetValue(skyBoxTexture);
part.Effect.Parameters["CameraPosition"].SetValue(cameraPositionSkyBox);
}
mesh.Draw();
}
}
GraphicsDevice.RasterizerState = originalRasterizerState;
}
I think the problem is in the line part.Effect.Parameters["World"].SetValue.....
I don't know what to put there to make the map rotate using all the axis.
I rotate the tank using this code:
orientacion = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(-85.0f),
MathHelper.ToRadians(floatAngle1), MathHelper.ToRadians(floatAngle2));
If you look at the second line you can notice that I use angles to rotate the tank (it have to be in that way...), so any idea or suggestion?
Update:
Solved, how?
in the SkyBoxRender Method I added the following:
orientacionCamara = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(0.0f), MathHelper.ToRadians(floatAngle1), MathHelper.ToRadians(floatAngle2));
then I archived to move the camera in the map using this:
part.Effect.Parameters["View"].SetValue(Matrix.CreateLookAt(yourCameraPosition) * orientacionCamara);
Now to move the camera at the same time with the same angles like the model I rotate the model, not the camera in this time.
private void BeginRender3D()
{
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
Matrix[] transforms = new Matrix[modelo.Bones.Count];
modelo.CopyAbsoluteBoneTransformsTo(transforms);
**orientacion** = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(-85.0f), MathHelper.ToRadians(floatAngle1), MathHelper.ToRadians(floatAngle2);
foreach (ModelMesh mesh in modelo.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
effect.World = transforms[mesh.ParentBone.Index] * **orientacion**; //* orientacion
effect.View = Matrix.CreateLookAt(camaraPosicion, Vector3.Zero, Vector3.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);
}
mesh.Draw();
}
fps++;
}
I hope It can help to anyone, thanks for the suggestion guys.
You could rotate the map by the orientation by multiplying the world parameter in the skyboxeffect by "orientacion". Still, you would have to make sure it rotates around the tanks position, by changing the whole line to this:
part.Effect.Parameters["World"].SetValue(Matrix.CreateScale(50.0f) * matrix.createtranslation(TankPosition) * orientacion * Matrix.CreateTranslation(cameraPositionSkyBox - TankPosition));
assuming "TankPosition" would be the position of your tank.
I'm not sure what you're trying to achieve, but if you're trying to simulate rotating a camera round the tank, I would just rotate the camera around the tank, by setting
view = matrix.CreatePerspectiveFieldOfView()
Read up on it here: http://msdn.microsoft.com/en-us/library/bb195667.aspx
I have a 3D FBX model that i want to draw it in XNA 4.0 windows game. Here is the Model in FBX viewer:
But when I run the project, it display like this
this is my drawing method:
private void DrawModel(Model model, Matrix worldMatrix, string name)
{
Matrix[] modelTransforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(modelTransforms);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = Matrix.CreateWorld(position, new Vector3(0, 0, 1), Vector3.Up) * worldMatrix;
effect.View = viewMat;
effect.Projection = projectionMat;
}
mesh.Draw();
}
}
And this is base draw method:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
graphics.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
DrawModel(house, houseWorld, "house");
base.Draw(gameTime);
}
Thanks for your help
Most likely, the problem is with your effect.World property. You are doing something odd by creating a matrix, and then combining it with worldMatrix. What makes it even odder is that you create the set of absolute transforms (modelTransforms), but you don't use them.
Typically, it would look like this:
effect.World = modelTransforms[mesh.ParentBone.Index] * worldMatrix;
Your Matrix.CreateWorld(position, Vector3.Backward, Vector3.Up) looks like a way that you are simply adding some translation (position) to the mix. Usually, you would add position to worldMatrix before bringing it into the draw(). But, the following might work for you:
effect.World = modelTransforms[mesh.ParentBone.Index] * worldMatrix * Matrix.CreateWorld(position, Vector3.Backward, Vector3.Up);
I put the CreateWorld() last because it appears to hold translation info only and with row majore matricies, you translate last.
Recently I have posted the same question that my FBX model was not showing correctly in XNA. I got a answer to the question and the model was displayed slightly better, but it is still not displaying correctly.
What it should look like is this:
https://docs.google.com/open?id=0B54ow8GRluDUYTBubTQ4bjBramM
But it shows as:
https://docs.google.com/open?id=0B54ow8GRluDUNXR5bmJUMVJFTUk
My drawing code is:
public void Draw(Matrix projection, Matrix view)
{
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.View = view;
effect.Projection = projection;
effect.World = Matrix.CreateRotationX(-270) *
transforms[mesh.ParentBone.Index] *
Matrix.CreateTranslation(Position);
}
mesh.Draw();
}
}
Can someone please help!
Thanks.
This is my solution:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
#region ResetGraphic
ResetGraphic();
#endregion
#region render 3D
BeginRender3D();
//Render 3D here
#endregion
#region render 2D
//Render 2D here
#endregion
}
public void ResetGraphic()
{
GraphicsDevice.BlendState = BlendState.AlphaBlend;
GraphicsDevice.DepthStencilState = DepthStencilState.None;
GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
GraphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap;
}
public void BeginRender3D()
{
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
}
Based on your previous question where the Xna rendered image showed that you were rendering 2d and 3d items, it is important to reset some graphics states between 2d & 3d.
Specifically, after rendering the 2d stuff, add these lines:
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
These settings are necessary for 3d but they get changed when calling SpriteBatch.Begin() so it is necessary to change them back before the 3d stuff.
Here is the blog post explaining it:
http://blogs.msdn.com/b/shawnhar/archive/2010/06/18/spritebatch-and-renderstates-in-xna-game-studio-4-0.aspx
I have created a scene in 3DS Max with a stock engine model and some things i added my self, the plane, and the button.
http://i.stack.imgur.com/R2iva.png
Regardless of how i export the scene, whether its as a .X using panda exporter or .fbx using 2012.2 fbx exporter both, when loaded into XNA and rendered, all appear on top of each other.
http://i.stack.imgur.com/6gdMb.png
Since the individual parts of the engine all remain where they should (and are seperate in 3ds max) im pretty sure there is something im not setting correctly in 3ds max with the layout of the rest of my objects.
Update 1 : The code i use to load the models in xna is as follows
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect be in mesh.Effects)
{
be.EnableDefaultLighting();
be.Projection = camera.projection;
be.View = camera.view;
be.World = GetWorld() * mesh.ParentBone.Transform;
// adding the additional * transforms[i]; didnt do anything
}
mesh.Draw();
}
This code works great for other peoples models but not any that i make. Its like 3ds max isnt exporting out the positions of the objects that i create in the scene relative to the scenes origin.
You need to combine all the transform matrices from parent bones and child bones like this:
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in model.Meshes) {
foreach (BasicEffect ef in mesh.Effects) {
ef.World = transforms[mesh.ParentBone.Index];
//Also do other stuff here, set projection and view matrices
}
}
There is probably a better way, but this code should work.
i just try draw a simple 3d model(many model (.fbx) tested) with basicEffect in xna 4.0 , and there is no other object like 2d spritebatchs or text or ...
but it does not shown correctly , i searched it and did some solution but no one work
like set
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
although i did not draw anything else ! and what is funny i already work with 3d model without problem !
here is my draw code and a result screenshot
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
foreach (ModelMesh mesh in m_Model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
BasicEffect effect = (BasicEffect)meshPart.Effect;
effect.View = Matrix.CreateLookAt(new Vector3(0, 100, 1000), Vector3.Zero, Vector3.Up);
effect.World = bones[mesh.ParentBone.Index] * (Matrix.CreateWorld(Vector3.Zero, Vector3.Right, Vector3.Up));
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.0001f, 1000000f);
effect.EnableDefaultLighting();
}
mesh.Draw();
}
base.Draw(gameTime);
}
ty for your time
The near clip value in your projection Matrix is most likely causing this. Try setting it to 1.0f instead of 0.0001f. If that doesn't solve the problem completely, bring the far clip down to something like 10000f.
edit - noticing that your camera is over 1000 units away from your model, you can even set the near clip to 5f or 10f to gain depth read precision if needed.
Its the problem of depth buffer, you are using the spritebrite to draw something which changes your default depth buffer off.
Make it on before drawing 3d model mesh.
After calling SpriteBatch.End(), add this code:
device.DepthStencilState = DepthStencilState.Default;