I didnt quite understand whats is the effect.World and effect.View etc. and why we put the matricies in them?
foreach (ModelMesh mesh in model1.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up);
effect.View = Matrix.CreateLookAt(Vector3.Zero, Vector3.Zero, Vector3.Up);
}
}
effect.World is not a matrix representing the world. It is a matrix representing a 3d object's (mesh, model) position and orientation relative to the 3d game world. Each object will have a different effect.World matrix if they are positioned differently &/or pointed differently.
effect.View is a matrix that represents (in an inverted form) the position & orientation of the camera relative to that same 3d game world. Most of the time, there is only one camera, but there can be more (say, a rear view mirror will have it's own view matrix as opposed to the main screen showing the view out the windshield of a car racing game).
a model's vertices are hard valued to model local space.
Then the effect.World transforms them to game world space.
then the effect.View transforms them to camera space.
Then the effect.Projection transforms them to 2d screen space and 'volia', your pixel shader knows where to draw what.
From MSDN;
BasicEffect.World
Gets or sets the world matrix. Use this matrix to change the position
of the model, using world coordinates.
BasicEffect.View
Gets or sets the view matrix. Use this matrix to change the position
and direction of the camera.
I think bold lines explain what is exactly their difference. Also I found some helpful articles;
How to: Use BasicEffect
Does every Entity in an XNA game need it's own BasicEffect instance?
Understanding Half-Pixel and Half-Texel Offsets
http://blogs.msdn.com/b/shawnhar/archive/2010/04/05/spritebatch-and-custom-shaders-in-xna-game-studio-4-0.aspx
http://msdn.microsoft.com/en-us/library/bb219690(VS.85).aspx
Related
I am implementing an Arcball rotation in an existing project I wrote several years ago, using OpenTK & C#, and have got stuck at the final hurdle.
This is 'old-style' non-shader OpenGL. I am confident that the Arcball rotation is working correctly, the problem is just applying the resulting matrix. It should be fairly straightforward but it isn't working out that way.
I get the Arcball rotation as a quaternion (qCurrent) then convert that to a matrix. I have then tried a couple of approaches:
Simply apply that as an additional rotation to the existing scene:
GL.PushMatrix();
Matrix4 arcball_rot = Matrix4.CreateFromQuaternion(qCurrent);
GL.MultMatrix(ref arcball_rot);
... render objects in scene
GL.PopMatrix();
This applies the correct rotation around the correct origin (the camera target), but with respect to the world coordinate system, not the viewer. This makes sense because I am effectively applying the rotations in the wrong sequence.
Apply the rotations in sequence, with the arcball rotation first, which means starting from scratch. Here, rtn_complete is a matrix storing the modelview matrix as initialised, before the Arcball rotation:
Matrix4 modelview = Matrix4.LookAt(camera.camerapos, camera.cameratarget, camera.cameraup);
rtn_complete = modelview;
Then...
Matrix4 mm = Matrix4.CreateFromQuaternion(qCurrent) * rtn_complete;
GL.LoadIdentity();
GL.MultMatrix(ref mm);
This applies the correct rotation wrt the viewer, but around the wrong centre of rotation. It is a point a long way away from the camera target.
Obviously this approach needs a forward/backward translation either side of the rotation, but I have tried pretty much every possible combination of these and none of them work.
Camera and target positions are as follows :-
camera.camerapos = (-51.3, -67.9, 37.7), and
camera.cameratarget = (0.0, 0.6, 7.3)
When I add translations as below (and countless other permutations) I still get the scene rotating around the wrong origin.
GL.LoadIdentity();
GL.Translate(camera.cameratarget);
GL.MultMatrix(ref arcball_rot);
GL.Translate(-camera.cameratarget);
GL.MultMatrix(ref rtn_complete);
My feeling is that the root of the problem is likely to be the translation applied by using LookAt, which I am not taking into account when doing the above transformations.
However, when I check the rtn_complete matrix (which is the modelview matrix following the LookAt) the fourth column does not contain a translation. The matrix looks like this:
0.80, 0.20, -0.56, 0.00
-0.60, 0.27, -0.75, 0.00
0.00, 0.94, 0.34, 0.00
0.38, -7.02, -92.8, 1.00
I would have expected to a see a translation here.
EDIT 1:
Found it eventually. I was on the right track with my suspicion about the translation resulting from using Matrix4.LookAt().
The way I had listed the matrices for debugging resulted in a transpose, so the translation was there for me to see but I was missing it but it was in the fourth row not the fourth column. The translation is (0.38, -0.72, -92.8) Applying this translation on either side of the Arcball rotation results in the expected rotation behaviour, initially.
GL.LoadIdentity();
GL.Translate(0.38, -7.02, -92.8);
GL.MultMatrix(ref mm);
GL.Translate(-0.38, 7.02, 92.8);
GL.MultMatrix(ref rtn_complete);
EDIT 2:
Having worked out the above I am very close, but it's still not quite right when I move somewhere else in the scene. Again I have got a couple of problems, and can solve one or the other but not both simulataneously.
Because of the Matrix4.LookAt I separated out the translation and the rotation components of the rtn_complete matrix (respectively 'rtn_complete_trans' and 'rtn_complete_rot').
If I do this, the rotations are spot on:
GL.LoadIdentity();
GL.Translate(rtn_complete_trans); // modelview translation component
GL.Translate(camera.cameratarget); // translate to rotation centre
GL.MultMatrix(ref arcball_rot); // ongoing Arcball rotation
GL.MultMatrix(ref rtn_complete_rot); // modelview rotation component
GL.Translate(-camera.cameratarget); // translate back from rotation centre
But there is an unwanted translation each time the view is initialised. If I rotate, release and repeat a few times the object gradually moves off screen.
If I change the position of the second camera translation this unwanted shift no longer happens, but the centre of rotation is off:
GL.LoadIdentity();
GL.Translate(rtn_complete_trans); // modelview translation component
GL.Translate(camera.cameratarget); // translate to rotation centre
GL.MultMatrix(ref arcball_rot); // ongoing Arcball rotation
GL.Translate(-camera.cameratarget); // translate back from rotation centre
GL.MultMatrix(ref rtn_complete_rot); // modelview rotation component
Can anyone explain?
i'm drawing several primitives with a camera class that supplies with view, world and projection. With these i can move the camera and see all 3 of my primitives. The problem is that i now wan't to add a 3d model in the project, but the ways i know of to draw a 3d model won't work with the camera class. I have tried using:
Matrix[] transforms = new Matrix[mymodel.Bones.Count];
mymodel.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in mymodel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = transforms[mesh.ParentBone.Index] *
Matrix.CreateRotationY(0.0f)
* Matrix.CreateTranslation(modelposistion);
effect.View = Matrix.CreateLookAt(cameraPosistion, Vector3.Zero, Vector3.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, 1.0f, 10000.0f);
}
mesh.Draw();
}
But this draws the model in the center of the screen, while i want it stationary, so i can view other models in the same project.
Any help to how this can be achieved?
If I understand your problem: "as you move your camera, the model follows".
Most likely, it isn't following, you are just moving the camera without changing where the camera is "looking at". Your view matrix calls for it to look at (camera to be pointed at) Vector3.Zero no matter what position the camera is altered to. This means that if your model position does not change, and your view matrix is always looking at the same world location, then the model will not appear to change position. It may get bigger or smaller or you might see it from different angles, but it will always be in the same spot on your screen. It's because your telling the camera to always look at the same position in your world.
Changing the camera position isn't enough to freely look around your world, you must also change where the camera is looking at ( the 2nd param of the View matrix).
Also, it is best to think of the camera as having just a view and projection matrices. The world matrix should be thought of as part of (or supplied by) the model.
Ok, this is hard to explain without pictures. I made a very limited model of a glock in Blender with an extruded cube making up the base and a scaled cube making up the barrel.
In Blender, It looks fine:
However, after exporting the model to .fbx and loading it into the compiler, it comes out like this:
I don't know exactly what is going on. Everything on the model is properly UV Mapped and the coordinates are correct, It just seems the translation is.. off..
Here is my drawModel code:
private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
Any pointers will be helpful!
EDIT: After Applying rotation, location, and scale, I was able to get them in the right position, but why does it look transparent?
Thank you for all the help!
As Nikola mentioned, in the later versions of Blender, they have proper XNA support.
Here's a screenshot of the settings I chose when exporting a model:
Why this happens:
Your Depth Buffer is not enabled, so when your GPU draws the barrel first, then the stock/handle, the handle is drawn on top of the barrel, even though some parts of it are supposed to be invisible because they would be hidden by the barrel.
How to fix:
Enable Depth Buffer as other answer suggests. And/Or order meshes in your model based on distance from camera, and draw tehm in order from the nearset to the farthest. This may not seem usefull now, but when you start working with transparent objects, you will see why this is a good thing to learn.
Enable depth buffer:
GraphicsDevice.DepthStencilState = DepthStencilStates.Default;
And to Draw a model in Xna you can follow this tutorial, that shows how the bone transforms have to be applied to get the meshes in right position.
I wanted to know if my method used below is the correct way to determine the position of my model before drawing on the screen.
Because when I want to create a floor duplicating my model. I find myself faced with the "Z-fighting" problem ^ ^.
thank you very much
Code sample to st position on my model before drawing :
model_Position.X = (float) 1.0;
model_Position.Z = (float) 3.0;
model_Position.Y = (float) 5.0;
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in model_ground_land1.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(model_Rotation) * Matrix.CreateTranslation(model_Position);
effect.View = View;
effect.Projection = Projection;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}
As far as I can see, your method is correct for positioning the model. What comes to the Z fighting problem, it happens when two 3D faces are drawn in the same plane overlapping each other. As you say that you "duplicate your model" it sounds like this is the problem, not the model positioning itself. To resolve the fighting, you can set some nonzero value to GraphicsDevice.RasterizerState.DepthBias before drawing the second copy of the model. From the documentation:
"Polygons with a high z-bias value appear in front of polygons with a
low value, without requiring sorting for drawing order. For example,
polygons with a value of 1 appear in front of polygons with a value of
0."
I'm a beginner in XNA, trying my luck at a basic 3D game.
I have some very talented 3D modellers backing me, and while I have on issue importing the .fbx files (the models themselves) into my basic 3D universe in XNA, I have no idea how include the normal maps, diffuse, and specular that they've included with their models.
The normal, diffuse and specular are all in .tga image file format, and I don't know how I can add those to the drawing of my model.
Right now my code for drawing the 3D object is as follows:
private void DrawObject(Model spaceStation, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in spaceStation.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}