I'm new to 3D models so apologises if these seems basic. I've been searching the web and through my books but I'm lost.
I've made a model in 3D Studio Max 9. It consists of a variety of cubes, clyinders etc.
In Xna I've imported the model okay and it shows correctly. However, when I apply rotation, each component in the model rotates around it's own centre rather. I want the model to rotate as a singal unit rather than each component rotating on the spot.
I've linked the components in 3D Max and they rotate as I want in Max.
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
model = Content.Load<Model>("Models/Alien1");
}
protected override void Update(GameTime gameTime)
{
camera.Update(1f, new Vector3(), graphics.GraphicsDevice.Viewport.AspectRatio);
rotation += 0.1f;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
Matrix worldMatrix = Matrix.Identity;
Matrix rotationYMatrix = Matrix.CreateRotationY(rotation);
Matrix translateMatrix = Matrix.CreateTranslation(location);
worldMatrix = rotationYMatrix * translateMatrix;
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = worldMatrix * transforms[mesh.ParentBone.Index];
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
}
mesh.Draw();
}
base.Draw(gameTime);
}
EDIT: Rotating the object via it's properties works fine so I'm guessing there's something up with the code rather than with the object itself.
Translating the object also causes the objects to get moved independently of each other rather than as a single model and each piece becomes spread around the scene.
Related
I have a sphere as FBX and a shader that enables me to have a texture inside of the sphere. Also inside of the sphere I have a camera. The goal is to have a simple panoramic viewer that is being driven by a headtracker.
The texture is being shown but the camera is reacting in a weird way:
When rotating the headtracker, the image is all over the place, jittery and not at all correlated to the actual movements. The headtracker input itself is correct, though.
See this video for further clarification. Each time I keep the tracker steady at first and then I move it. In the second half, the first three numbers are evaluated. The other three values are gyro.
I presume the problem to be in the following code, something about the Vectors(Vector3.whatever) could be off:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.CornflowerBlue);
foreach (ModelMesh mesh in skyDome.Meshes)
{
foreach (BasicEffect ef in mesh.Effects)
{
float aspectRatio = (float)graphics.GraphicsDevice.PresentationParameters.BackBufferWidth / (float)graphics.GraphicsDevice.PresentationParameters.BackBufferHeight;
Vector3 camPosition = Vector3.Transform(Vector3.Up, Quaternion.CreateFromYawPitchRoll(drehung, neigung, rollen));
ef.View = Matrix.CreateLookAt(Vector3.Zero, camPosition,Vector3.Forward);
ef.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, 0.1f, 10000.0f);
ef.TextureEnabled = true; //Textur zulassen
ef.Texture = panoramaTextur; //Textur auf Model darstellen
}
mesh.Draw();
}
base.Draw(gameTime);
}
I have a project due very soon and I'm having lots of issues trying to load a model I made in 3D Studio Max. The model I made is what I want as my terrain in my XNA game. Here is what I've done so far:
Methods:
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Model terrainModel;
Vector3 terrainPosition = Vector3.Zero;
Vector3 cameraPosition = new Vector3(0.0f, 60.0f, 160.0f);
Vector3 cameraLookAt = new Vector3(0.0f, 60.0f, 160.0f);
Matrix cameraProjectionMatrix;
Matrix cameraViewMatrix;
LoadContent()
spriteBatch = new SpriteBatch(GraphicsDevice);
cameraViewMatrix = Matrix.CreateLookAt(
cameraPosition,
Vector3.Zero,
Vector3.Up);
cameraProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(80.0f),
graphics.GraphicsDevice.Viewport.AspectRatio,
1.0f,
1000.0f);
terrainModel = Content.Load<Model>("alphastreet");
Draw(GameTime gameTime)
GraphicsDevice.Clear(Color.CornflowerBlue);
DrawModel(terrainModel, terrainPosition);
// TODO: Add your drawing code here
base.Draw(gameTime);
And then I want to Draw:
void DrawModel(Model model, Vector3 modelPosition)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
effect.World = Matrix.CreateTranslation(modelPosition);
effect.Projection = cameraProjectionMatrix;
effect.View = cameraViewMatrix;
}
mesh.Draw();
}
}
Everything else is just as an XNA file should look. The model it's self looks like a fairly straightforward street. However, upon XNA loading the model, it's just a big block in the window that loads.
I don't know what I'm doing that's making the model load like this, but it's making me pull my hair out. Any help would be appreciated.
Also, would anybody be able to direct me to walk-through/guide or a class that creates a First Person Shooter camera, since that is the game I'm going. I probably shouldn't have picked that, but it's way too late to change now, so if you could help there too you would really be saving my skin!
Thanks, Jake!
Is there more than one mesh in the model, and if so, have you tried rendering each one separately?
Have you tried using identity matrices for world and view to make sure these aren't the issue?
I assume you haven't made any other state changes to xna/directx, if so try disabling these.
For a FPS camera, you can just track the x and y rotation in float variables and update these each frame based upon how far the mouse has moved in x and y. From these you can generate a camera view matrix; something like the following:
var mx = Matrix.CreateRotationX(xangle);
var my = Matrix.CreateRotationY(yangle);
var pos = Matrix.CreateTranslation(position);
var view = mx * my * pos; // These might be in the wrong order, not sure off the top of my head
view.Invert();
The camera is always inverted because moving left moves the world right, turning left turns the world right etc.
The model is a .fbx
I have tried many models also, Nothing seems to be working i was wondering if anyone could help me, The following code is all I have thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace _3D
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Model model;
Matrix[] transforms;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = 800;
graphics.PreferredBackBufferWidth = 1280;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
model = Content.Load<Model>("3d/screwdriver");
transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
base.Update(gameTime);
}
// The draw method is one of the reasons I think nothing is working,
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
Matrix view = Matrix.CreateLookAt(
new Vector3(200, 300, 900),
new Vector3(0, 50, 0),
Vector3.Up);
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 0.1f, 10000.0f);
Matrix baseWorld = Matrix.CreateScale(0.4f) * Matrix.CreateRotationY(MathHelper.ToRadians(180));
foreach (ModelMesh mesh in model.Meshes)
{
Matrix localWorld = transforms[mesh.ParentBone.Index] * baseWorld;
foreach (ModelMeshPart part in mesh.MeshParts)
{
BasicEffect e = (BasicEffect)part.Effect;
e.World = localWorld;
e.View = view;
e.Projection = projection;
e.EnableDefaultLighting();
}
mesh.Draw();
}
base.Draw(gameTime);
}
}
}
I don't see anything really wrong with your code, so the problem may be on the model.
It might be caused by the model file in question. There is a know issue with the stock FBX Exporter on Blender (I don't know which modelling software you used to make the model, but the matter is still relevant) that makes the model be exported with a size 100x bigger than it is on Blender. The result is that the model is so big that it not only encloses the camera inside itself, but also is so big that it's polygons are beyond the viewing frustrum. Result: the model is indeed rendered, but it'll never appear onscreen unless you move the camera around until you realise the scaling problem.
I'm saying this because I dealed with this problem myself. If you are indeed using Blender, you should use the exporter found in this page:
http://blog.diabolicalgame.co.uk/2011/07/exporting-animated-models-from-blender.html
I am new to XNA, and I am creating a simple game. Sorry that this is probably really simple, but I can't find any help on it. There is a ship in the game that I made with Blender, and I want to be able to control the ship by being able to rotate the ship's X, Y and Z axises. Here is the code I have:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
RotationMatrix = Matrix.CreateRotationY(MathHelper.PiOver2) * Matrix.CreateRotationY (rotationY) * Matrix.CreateRotationX(rotationX) * Matrix.CreateRotationZ(rotationZ);
Matrix shipTransformMatrix = RotationMatrix * Matrix.CreateTranslation(ship.Position);
DrawModel(ship.Model, shipTransformMatrix, ship.Transforms);
// TODO: Add your drawing code here
base.Draw(gameTime);
}
public void DrawModel(Model model, Matrix modelTransform, Matrix[] absoluteBoneTransforms)
{
//Draw the model, a model can have multiple meshes, so loop
foreach (ModelMesh mesh in model.Meshes)
{
//This is where the mesh orientation is set
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = absoluteBoneTransforms[mesh.ParentBone.Index] * modelTransform;
effect.Projection = projectionMatrix;
effect.View = viewMatrix;
}
//Draw the mesh, will use the effects set above.
mesh.Draw();
}
}
This will rotate the ship, but not along the ship's axis's. If I rotate the Y axis (by changing the value of rotationY), the ship will rotate along its Y axis. But if I rotate the X or Z axis, the ship rotates according according to the world's X and Z axises, not its own. How do I make it so the ship rotates on its own axises? Do I need to do something different with the matrices?
Thanks
Using CreateRotationX, CreateRotationY, & CreateRotationZ all apply rotations around the world or global axes. Meaning it causes your object to rotate only around the world/global axes, not your object's local axes.
Using CreateFromAxisAngle allows you to input whatever rotation axis you want, including the ship's own local axes.
A shift in your overall rotation paradigm will be needed, however, since a rotation around an arbitrary axis like the ship's Up, for instance, can cause a change to any of the 3 angle values at once. Keeping track of all that is unnecessarily difficult. There is an easier way:
Simply store a rotation in matrix (or quaternion) form instead of the 3 angles.
EDIT: Giving some credit here to Steve below (great answer mate, been a while since I did alot of 3D math).
This tutorial here will show you how to setup what Steve suggested!
http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/Rotation_-_translation.php
Original Post:
I believe you have to create an effect.Rotation in your BasicEffect loop.
All of this is covered in the basic tutorials over at MSDN I believe. Your code even looks like it came from there.
http://msdn.microsoft.com/en-us/library/bb203897(v=xnagamestudio.31)
If not, check out this link, Reimer covers everything in 3D worth knowing to start:
http://www.riemers.net/eng/Tutorials/XNA/Csharp/series1.php
Here is what I ended up doing just in case anyone else gets stuck like I did:
Matrix RotationMatrix;
//every time I wanted to rotate around an axis, I would do something like this:
protected void rotateY()
{
RotationMatrix *= Matrix.CreateFromAxisAngle(RotationMatrix.Up, MathHelper.ToRadians(1.0f));
//For the X axis I used RotationMatrix.Right, and for the Z RotationMatrix.Forward
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
Matrix shipTransformMatrix = RotationMatrix * Matrix.CreateTranslation(ship.Position);
DrawModel(ship.Model, shipTransformMatrix, ship.Transforms);
// TODO: Add your drawing code here
base.Draw(gameTime);
}
public void DrawModel(Model model, Matrix modelTransform, Matrix[] absoluteBoneTransforms)
{
//Draw the model, a model can have multiple meshes, so loop
foreach (ModelMesh mesh in model.Meshes)
{
//This is where the mesh orientation is set
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = absoluteBoneTransforms[mesh.ParentBone.Index] * modelTransform;
effect.Projection = projectionMatrix;
effect.View = viewMatrix;
}
//Draw the mesh, will use the effects set above.
mesh.Draw();
}
}
I have a model that I made in Blender that has individual meshes in it. When I put it in an Xna project and try to move the model via Matrix translation, all the individual meshes go in seperate directions. My code basicly updates each mesh individually. Is there better code i should use to make the model's meshes move together?
If you call this:
private void DrawModel(Model model, Matrix worldMatrix)
{
//Matrix array for number of bones
Matrix[] modelTransformations = new Matrix[model.Bones.Count];
//Put bones into matrix array
model.CopyAbsoluteBoneTransformsTo(modelTransformations);
//for every model
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
//Add default lighting
effect.EnableDefaultLighting();
//Set default postion
effect.World = modelTransformations[mesh.ParentBone.Index] * worldMatrix;
//Set view
effect.View = camera.viewMatrix;
//Set projection
effect.Projection = camera.projectionMatrix;
}
//Draw Model
mesh.Draw();
}
}
And then translate the world matrix that you put in like this:
modelWorld *= Matrix.CreateTranslation(XDir, YDir, ZDir);
You should have no problems. At least, that's how I do it.