Reputation: 287
I'm trying to draw model in another class. i have tried to draw the model in another class. however, my model won't get rendering at all with the codes of what i have made.
here the code for Game1: (Note: these codes work well for Game1)
private Vector3 position = new Vector3(0, 0, 0);
private Matrix world;
private Matrix view;
private Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 600f, 0.1f, 100f);
private Model car;
SpriteBatch spriteBatch;
GraphicsDeviceManager graphics;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
Vector3 transformedReference = Vector3.Transform(new Vector3(0, 5, 15), Matrix.CreateRotationY(0f));
view = Matrix.CreateLookAt(position + transformedReference, position, Vector3.Up);
}
protected override void Initialize()
{
Components.Add(new Car(this, view, projection));
world = Matrix.CreateTranslation(position);
Vector3 transformedReference = Vector3.Transform(new Vector3(0, 5, 15), Matrix.CreateRotationY(0f));
view = Matrix.CreateLookAt(position + transformedReference, position, Vector3.Up);
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
car = Content.Load < Model > ("car\\car");
}
public 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.PreferPerPixelLighting = true;
effect.World = mesh.ParentBone.Transform * world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
world = Matrix.CreateTranslation(position);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
DrawModel(car, world, view, projection);
base.Draw(gameTime);
}
and here the codes of my another class: (Note: these codes doesn't work well or the model can't be rendered on Game1 graphic)
public class Car: DrawableGameComponent
{
public Model CarModel
{
get;
set;
}
private Vector3 position = new Vector3(0, 0, 0);
private Matrix World = Matrix.CreateTranslation(new Vector3(0, 0, 0));
public Matrix Camera
{
get;
set;
}
public Matrix Projection
{
get;
set;
}
public Game1 GameParent
{
get;
set;
}
public Car(Game1 game, Matrix view, Matrix projection): base(game)
{
view = Camera;
Projection = projection;
Camera = view;
GameParent = game;
World = Matrix.CreateTranslation(position);
base.Initialize();
}
public static 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.PreferPerPixelLighting = true;
effect.World = mesh.ParentBone.Transform * world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
protected override void LoadContent()
{
CarModel = GameParent.Content.Load < Model > ("car\\car");
base.LoadContent();
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
DrawModel(CarModel, World, Camera, Projection); //DOESN'T WORK WELL!!
base.Draw(gameTime);
}
}
OK, my point just want to drawing 3D model in another class,,
well, What should i do to solve this?
i hope you don't mind to help me and you can understand what i mean..
Upvotes: 0
Views: 237
Reputation: 868
It is hard to see what is wrong with your code, because it contains two versions in one. Clean it up a bit. Here are some tips:
You don't want to use DrawableGameComponent for individual objects, in my experience. Stick to writing your own classes and putting them in collections or something like that. This way, you don't have to deal with the voodoo of XNA firing off your update and draw for you. Better to control that yourself.
You don't want your CAR to handle View- and Projection-Matrices. Leave those in your Game-class (for now. there should be a camera-class instead) and pass them to your Car.Draw-method. I see you pass it in the constructor, but Matrixes are value-types, as far as I can remember, and so changes to your view in other parts of the code would not propagate to your car.
so change Car.Draw to:
public void Draw(Matrix view, Matrix projection)
{
DrawModel(view, projection);
}
As you might get from my changes to draw, you should also make DrawModel a normal method (remove static), so that it don't have to receive model and world.
Your Car should have a Quaternion or similar for rotation. The Car.World can thus be written:
Matrix World = Matrix.Identity;
//In update:
World = Matrix.FromQuaternion(Rotation) * Matrix.CreateTranslation(Position);
Let Car's constructor take a Model as a parameter. That way you can also ditch "GameParent" and the LoadContent-Method.
In you game-class:
Ditch the static DrawModel-method. Ditch the fields world and car. they belong to the Car-class now.
Make a field (class-level variable that is not a property) for your car:
Car MyCar = null;
In Game1.LoadContent:
MyCar = new Car(Content.Load<Model>("car//car"));
In Game1.Update:
MyCar.Update(gameTime);
In Game1.Draw:
GraphicsDevice.Clear(Color.CornFlowerBlue);
MyCar.Draw(View, Projection);
Edit;
For a game engine, you will normally have some "parts" that you currently are missing:
A Camera-system can be as simple as:
public interface ICamera
{
Vector3 Position { get; }
Matrix View { get; }
Matrix Projection { get; }
void Update(float deltaTime);
void Target(Vector3 targetPosition);
}
public class CameraService
{
public static ICamera ActiveCamera { get; private set; }
public static void ActivateCamera(ICamera camera)
{
if (ActiveCamera != null)
camera.Target(ActiveCamera.Target);
ActiveCamera = camera;
}
public static Update(float deltaTime)
{
if (ActiveCamera != null)
ActiveCamera.Update(deltaTime);
}
}
public class BasicCamera: ICamera
{
public Vector3 Position { get; protected set; }
public Matrix View { get; protected set; }
public Matrix Projection { get; protected set; }
public void Target(Vector3 targetPosition)
{
View = Matrix.CreateLookAt(Position, targetPosition, something something);
}
public BasicCamera(Vector3 position, Vector3 target)
{
//Set shit up
}
}
Upvotes: 2