0

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

这里是 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 模型,,

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

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

4

1 回答 1

2

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

根据我的经验,您不想将 DrawableGameComponent 用于单个对象。坚持编写自己的类并将它们放入集合或类似的东西中。这样,您就不必处理 XNA 启动更新并为您绘制的巫术。最好自己控制。

您不希望您的 CAR 处理视图矩阵和投影矩阵。将它们留在你的游戏类中(现在应该有一个相机类)并将它们传递给你的 Car.Draw 方法。我看到您在构造函数中传递了它,但据我所知,矩阵是值类型,因此代码其他部分中对视图的更改不会传播到您的汽车。

所以将 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);

编辑;

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

  • 游戏状态系统(Menu 是一种状态,NormalLevel 和 BossLeve 是其他的例子)
  • 相机服务(因此您可以从任何地方获取当前视图/投影矩阵) - 计时服务(因此您可以从任何地方获取 (float)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
    }
}
于 2013-03-15T08:26:54.743 回答