我可以在另一堂课中画出模特吗?

时间:2013-03-15 07:43:49

标签: c# visual-studio xna drawablegamecomponent

我正在尝试在另一个班级中绘制模型。 我试图在另一个类中绘制模型。但是,我的模型根本无法使用我所做的代码进行渲染。

此处 Game1的代码:注意:这些代码适用于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);
}

这里是另一个类的代码:注意:这些代码效果不佳,或者模型无法在Game1图片上呈现)

         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);
    }
}

好的,我的观点只是想在另一个类中绘制3D模型,

好吧,我该怎么做才能解决这个问题?

我希望你不介意帮助我,你可以理解我的意思..

1 个答案:

答案 0 :(得分:2)

很难看出代码有什么问题,因为它包含两个版本。清理一下。以下是一些提示:

根据我的经验,您不希望将DrawableGameComponent用于单个对象。坚持编写自己的类并将它们放入集合或类似的东西。通过这种方式,您无需处理XNA的巫术,即可启动更新并为您绘制。更好地控制自己。

您不希望您的CAR处理View和Projection-Matrices。把它们留在你的Game-class中(现在应该有一个相机类)并将它们传递给你的Car.Draw方法。我看到你在构造函数中传递它,但Matrixes是值类型,据我所知,所以代码的其他部分对视图的更改不会传播到你的汽车。

所以将Car.Draw更改为:

public void Draw(Matrix view, Matrix projection)
{
    DrawModel(view, projection);
}

正如您可能从我的绘制更改中获得的,您还应该使DrawModel成为常规方法(删除静态),这样它就不必接收模型和世界。

你的车应该有一个四元数或类似的轮换。因此可以写出Car.World:

Matrix World = Matrix.Identity;

//In update:
World = Matrix.FromQuaternion(Rotation) * Matrix.CreateTranslation(Position);

让Car的构造函数将Model作为参数。这样你也可以抛弃“GameParent”和LoadContent-Method。

在你的游戏课程中:

抛弃静态DrawModel方法。 抛弃田野世界和汽车。他们现在属于汽车级。

为您的汽车创建一个字段(非属性的类级别变量):

Car MyCar = null;

在Game1.LoadContent中:

MyCar = new Car(Content.Load<Model>("car//car"));

在Game1.Update中:

MyCar.Update(gameTime);

在Game1.Draw中:

GraphicsDevice.Clear(Color.CornFlowerBlue);
MyCar.Draw(View, Projection);

编辑;

对于游戏引擎,您通常会有一些目前缺少的“部分”:

  • 游戏状态系统(菜单是一种状态,NormalLevel和BossLeve是其他类型的例子)
  • 相机服务(这样您就可以从任何地方获取当前视图/投影矩阵) - 定时服务(所以你可以从任何地方获得(浮动)gameTime.ElapsedGametime.TotalSeconds)
  • 输入服务(因此您可以从任何地方获取每次更新的输入值)

相机系统可以简单如下:

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
    }
}
相关问题