0
\$\begingroup\$

I successfully draw the model, and made it move forward and backward, but when I try to make it rotates (yaw) its not working correctly, like its moving too instead of only rotate. Here is my camera code:

public class NewCamera
{
    float aspectRatio;
    public NewPlayer player;
    Matrix viewMatrix;
    Matrix projectionMatrix;
    Matrix terrainMatrix;

    public NewCamera(float aspectRatio, NewPlayer player)
    {
        this.player = player;
        this.aspectRatio = aspectRatio;
    }

    public void Update()
    {
        Vector3 campos = new Vector3(0, 0.2f, -0.6f);
        campos = Vector3.Transform(campos, Matrix.CreateFromQuaternion(player.rotation));
        campos += player.position;

        Vector3 camup = new Vector3(0, 1, 0);
        camup = Vector3.Transform(camup, Matrix.CreateFromQuaternion(player.rotation));

        viewMatrix = Matrix.CreateLookAt(campos, player.position, camup);
        projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, 0.2f, 500.0f);
    }

    public void SetEffects(BasicEffect basicEffect)
    {
        basicEffect.View = viewMatrix;
        basicEffect.Projection = projectionMatrix;
        basicEffect.World = terrainMatrix;
    }

    public void Draw(Terrain terrain)
    {
        terrainMatrix = Matrix.CreateTranslation(terrain.position);
        SetEffects(terrain.basicEffect);
        foreach (EffectPass pass in terrain.basicEffect.CurrentTechnique.Passes)
        {
            pass.Apply();
            terrain.Draw();
        }
        player.Draw(viewMatrix, projectionMatrix);
    }
}

And here is my player (character) code:

public class NewPlayer
{
    Model model;
    public Vector3 position = new Vector3(8, 1, -3);
    public Quaternion rotation = Quaternion.Identity;
    public Matrix worldMatrix = Matrix.Identity;

    public NewPlayer(Model _model)
    {
        model = _model;
        foreach (ModelBone bone in model.Bones)
        {
            bone.Transform *= Matrix.CreateScale(0.01f);
        }            
    }


    public void RecreateWorld()
    {
        worldMatrix = Matrix.CreateRotationY(MathHelper.Pi)
            * Matrix.CreateFromQuaternion(rotation)
            * Matrix.CreateTranslation(position);
    }

    public void Draw(Matrix viewMatrix, Matrix projectionMatrix)
    {
        RecreateWorld();
        Matrix[] transforms = new Matrix[model.Bones.Count];
        model.CopyAbsoluteBoneTransformsTo(transforms);

        foreach (ModelMesh mesh in model.Meshes)
        {
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.EnableDefaultLighting();
                effect.World = transforms[mesh.ParentBone.Index]
                    * worldMatrix;
                effect.View = viewMatrix;
                effect.Projection = projectionMatrix;
            }
            mesh.Draw();
        }
    }

    public void MoveForward(float speed)
    {
        Vector3 addVector = Vector3.Transform(new Vector3(0, 0, 1), this.rotation);
        this.position += addVector * speed;
    }

    public void MoveBackward(float speed)
    {
        Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), this.rotation);
        this.position += addVector * speed;
    }

    public void Yaw(float amount)
    {
        this.rotation *= Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(amount), 0, 0);
    }
}

So, whats wrong at the Yaw function??

EDIT: Adding some SS to show what I mean, it appears that it yaws around camera and not player

No Yaw Yaw 1 Yaw 2

\$\endgroup\$
1
\$\begingroup\$

Since I misunderstood your question and your camera seems not to be working correctly here is a minimal solution for what you want to achive. (Note this is a bare bones example which uses only what you need)

class FollowCamera
{
    public Vector3 offset;
    public MeshTransform target;

    public Matrix view;
    public Matrix projection;

    public FollowCamera(Game game)
    {
        projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, game.GraphicsDevice.Viewport.AspectRatio, 0.01f, 1000.0f);
    }

    public void Update(GameTime gameTime)
    {
        Vector3 cameraPosition = Vector3.Transform(offset, target.rotation);
        cameraPosition += target.position;
        view = Matrix.CreateLookAt(cameraPosition, target.position, Vector3.Up);
    }
}

class MeshTransform
{
    public Model mesh;
    public Vector3 position;
    public Quaternion rotation;

    public MeshTransform(Game game) {
        // From http://msdn.microsoft.com/en-us/library/bb197293%28v=xnagamestudio.31%29.aspx
        mesh = game.Content.Load<Model>("Models\\p1_wedge");
        position = Vector3.Zero;
        rotation = Quaternion.Identity;
    }

    public Matrix GetTransform() {
        return Matrix.CreateScale(Vector3.One * 0.005f) * Matrix.CreateFromQuaternion(rotation) * Matrix.CreateTranslation(position);
    }

    public void Draw(FollowCamera camera) {
        mesh.Draw(GetTransform(), camera.view, camera.projection);
    }
}

class Game1 : Microsoft.Xna.Framework.Game {
    GraphicsDeviceManager graphics;
    MeshTransform cameraTarget;
    MeshTransform referencePoint;
    FollowCamera camera;

    public Game1() {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void LoadContent() {
        cameraTarget = new MeshTransform(this);
        cameraTarget.position = Vector3.Backward * 5;
        referencePoint = new MeshTransform(this);
        referencePoint.position = Vector3.Forward * 150 + Vector3.Right * 50;
        camera = new FollowCamera(this);
        camera.offset = Vector3.Backward * 20;
        camera.target = cameraTarget;
    }

    protected override void Update(GameTime gameTime) {
        float dTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
        float turnSpeed = 10 * dTime;
        Quaternion rotation = cameraTarget.rotation;

        if (Keyboard.GetState().IsKeyDown(Keys.A))
        {
            rotation = Quaternion.CreateFromYawPitchRoll(turnSpeed , 0, 0) * rotation;
        }
        else if (Keyboard.GetState().IsKeyDown(Keys.D))
        {
            rotation = Quaternion.CreateFromYawPitchRoll(-turnSpeed, 0, 0) * rotation;
        }
        cameraTarget.rotation = rotation;

        camera.Update(gameTime);

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime) {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        cameraTarget.Draw(camera);
        referencePoint.Draw(camera);

        base.Draw(gameTime);
    }
}

The camera is glued to the offset from the cameraTarget mesh, the important part is in FollowCamera::Update() to get a view matrix where the camera is behind your model you have to rotate the offset you want with the current offset from the model, you will get your offset in "transformed model space" then you just have to add the current position of your model to get the desired effect.

A small tipp I have for you is, use the Vector3.Up/Down/Left/Right... propertys. They are much less code to write and you can see by the name Up/Down... already what it is used for instead of looking at the constructor arguments you pass in.

\$\endgroup\$
  • \$\begingroup\$ Didnt work, seems like its rotating around the camera position instead of player position \$\endgroup\$ – Caio Keto Jan 15 '15 at 10:18
  • \$\begingroup\$ Reading your question I thought you wanted to rotate the yaw around your current camera position. Do you want to just rotate the model and keep the camera "behind" the model? Thats how it looks like on the screenshots. \$\endgroup\$ – prydain Jan 16 '15 at 2:40
  • \$\begingroup\$ I want to rotate the model and keep the camera at the same relative position to the model ("behind" it) \$\endgroup\$ – Caio Keto Jan 16 '15 at 23:19
0
\$\begingroup\$

I'm want to clarify about this line in your camera Update method

campos = Vector3.Transform(campos, Matrix.CreateFromQuaternion(player.rotation));

As I can understand you rotate camera with your model. If so you cannot not see rotation. Did you have any other objects in scene to determine that model realy rotated or not? Please add some screenshots with no rotation and with applying some yaw.

\$\endgroup\$
  • \$\begingroup\$ I added the screenshots to show what I mean, it appears that it yaws around the camera position, and not the player. \$\endgroup\$ – Caio Keto Jan 15 '15 at 12:50
  • \$\begingroup\$ I'm still not sure what could be a mistake. However, I was a little confused by how you are using the camera. This is purely my opinion, but I think the model is stored in the camera is very impractical. I think that the camera should know HOW to draw but not WHAT to draw and I'm use camera as a parameter in the Draw method. So I avoid inconsistencies in the displaing models. Heare an example: goo.gl/x4oJTc. Search by pCamera word on page to see what i'm talking about. \$\endgroup\$ – user52551 Jan 15 '15 at 13:44
  • \$\begingroup\$ Its like that based on one tutorial I saw about terrains, it pass it to the camera, but I dont think changing it would make much diference. I'll try that out, put the camera as parameter and drawing terrain and player in each class. \$\endgroup\$ – Caio Keto Jan 15 '15 at 13:51
  • \$\begingroup\$ Sorry, but the last thing I can suggest is to carefully review all the places where you use a variable rotation. It looks like you're already primenyaeete her after moving model. Also try rotate camera (not model) at additional 180 degrees to see did model realy rotates around camera or around some point behind camera. \$\endgroup\$ – user52551 Jan 15 '15 at 14:04
  • \$\begingroup\$ It rotates, the only place I use the rotation is at the Yaw function. the problem is that appears that it considers the origin point the position of the camera, if you look carefull, it Yaws around the camera position, I dont know why is that. \$\endgroup\$ – Caio Keto Jan 15 '15 at 14:07
0
\$\begingroup\$

I guess I found out the problem. Its not the model or camera that is not rotating, the problem is with the terrain. As the only thing I draw is model and terrain, I was basing my vision on the terrain, but when I log the position, its rotating the model and keeping it in the same position, wich is the correct thing to do, so its yaw is correct, the problem is with the terrain that is changing position. Ill try to find out the problem in the terrain, if I correct it I'll post here so others wont get the same error.

\$\endgroup\$
-1
\$\begingroup\$

Not a pro at these things but try changing

effect.World = transforms[mesh.ParentBone.Index]
                * worldMatrix;

to...

effect.World =  worldMatrix 
                * transforms[mesh.ParentBone.Index];
\$\endgroup\$
  • \$\begingroup\$ If I change it like you said, it doesnt show the player anymore, and its rotating around the camera. \$\endgroup\$ – Caio Keto Jan 15 '15 at 10:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.