Skip to main content
2 of 3
deleted 56 characters in body

XNA Arcball and moving model - the model is altered instead of the camera

I'm trying to implement an arcball type camera, I've got all controls working very nicely. I can rotate the X/Y axis with my mouse and zoom in and out with the Z/X keys.

The problem is, that the camera doesn't rotate around the model, but instead, the model rotates around its axis and the camera remains on the same position. When I zoom in or out, the model scales bigger or smaller. I've got the feeling my approach is incomplete or isn't correct..

In summary I want to achieve: rotate camera and zoom in/out on my model and still keep control of my model. How should I go about this?

This the code I'm using. Help or advice is much appreciated

Draw character

void DrawCharacter(Matrix view, Matrix projection)
{
    // Render the skinned mesh.
    Matrix[] bones = animationPlayer.GetSkinTransforms();

    foreach (ModelMesh mesh in currentModel.Meshes)
    {
        foreach (SkinnedEffect effect in mesh.Effects)
        {
            effect.SetBoneTransforms(bones);
            effect.View = view;
            effect.Projection = projection;
            effect.EnableDefaultLighting();
            effect.SpecularColor = new Vector3(0.25f);
            effect.SpecularPower = 16;
        }
        mesh.Draw();
    }
}

Update camera

    private void UpdateCamera(GameTime gameTime)
{

    // start arcball
    float time = (float)gameTime.ElapsedGameTime.TotalMilliseconds;

    // mouse movement
    MouseState currentMouseState = Mouse.GetState();
    if (currentMouseState != originalMouseState)
    {

        float xDifference = (currentMouseState.X - originalMouseState.X);
        float yDifference = currentMouseState.Y - originalMouseState.Y;

        Mouse.SetPosition(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
        if (Mouse.GetState().RightButton == ButtonState.Pressed)
        {
            cameraRotation -= xDifference * 1.05f;
            cameraArc += yDifference * 1.025f;

            // Limit the arc movement.
            if (cameraArc > 90.0f)
                cameraArc = 90.0f;
            else if (cameraArc < -90.0f)
                cameraArc = -90.0f;
        }
    }

    // Check for input to zoom camera in and out.
    if (currentKeyboardState.IsKeyDown(Keys.Z))
        cameraDistance += time * 0.25f;

    if (currentKeyboardState.IsKeyDown(Keys.X))
        cameraDistance -= time * 0.25f;

    // Limit the camera distance.
    if (cameraDistance > 500)
        cameraDistance = 500;
    else if (cameraDistance < 0.001f)
        cameraDistance = 0.001f;

    // reset camera
    if (currentKeyboardState.IsKeyDown(Keys.R))
    {
        cameraArc = -5;
        cameraRotation = 180;
        cameraDistance = 100;
    }
    /// end of arcball

    Matrix cameraFacingMatrix = Matrix.CreateRotationY(sphereFacingDirection);
    Vector3 positionOffset = Vector3.Transform(CameraPositionOffset,
        cameraFacingMatrix);
    Vector3 targetOffset = Vector3.Transform(CameraTargetOffset,
        cameraFacingMatrix);

    Vector3 cameraPosition = spherePosition + positionOffset;

    if (heightMapInfo.IsOnHeightmap(cameraPosition))
    {

        float minimumHeight = heightMapInfo.GetHeight(cameraPosition) + CameraPositionOffset.Y;

        if (cameraPosition.Y < minimumHeight)
        {
            cameraPosition.Y = minimumHeight;
        }
    }

    Vector3 cameraTarget = spherePosition + targetOffset;

    // with those values, we'll calculate the viewMatrix.
    viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
}

Draw

    protected override void Draw(GameTime gameTime)
{
    GraphicsDevice device = graphics.GraphicsDevice;

    device.Clear(Color.Gray);

    GraphicsDevice.BlendState = BlendState.Opaque;
    GraphicsDevice.DepthStencilState = DepthStencilState.Default;
    GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

    // draw models
    DrawModel(terrain, Matrix.Identity);

    // Compute camera matrices.
    float aspectRatio = (float)device.Viewport.Width / (float)device.Viewport.Height;

    Matrix view = Matrix.CreateRotationY(MathHelper.ToRadians(cameraRotation)) *
                  Matrix.CreateRotationX(MathHelper.ToRadians(cameraArc)) *
                  Matrix.CreateTranslation(0, -45, 0) *
                  Matrix.CreateLookAt(new Vector3(0, forwardRotation, -cameraDistance),
                                      new Vector3(0, 0, 0), Vector3.Up);

    Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
                                                            aspectRatio,
                                                            1, 10000);

    DrawCharacter(view, projection);

    DrawAxe(view, projection);

    base.Draw(gameTime);
}