4
\$\begingroup\$

I have an arcball set up to follow my model in XNA. It rotates around the target correctly when holding in the left mouse button and moving the mouse. It zooms in and our correctly with the mouse wheel. It turns so it's orientation is always the same as the character turns left and right. The one part that's missing: I want the player direction to snap to the camera direction if I press the right mouse button, so I can then steer the player with the mouse. This refuses to work, I just can't seem to get the player facing in the correct direction.

The camera update class:

      public Matrix UpdateCamera(GameTime gameTime, HeightMapInfo heightMapInfo, float playerFacingDirection, Vector3 playerPosition)
    {
        float time = (float)gameTime.ElapsedGameTime.TotalMilliseconds;

        Matrix cameraFacingMatrix = Matrix.CreateRotationY(playerFacingDirection);

        Vector3 targetOffset = Vector3.Transform(cameraTargetOffset,
            cameraFacingMatrix);

        Vector3 cameraTarget = playerPosition + targetOffset;

        Matrix orientation = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(cameraRotation),
                MathHelper.ToRadians(cameraArc), MathHelper.ToRadians(cameraDistance));

        view = Matrix.CreateLookAt(cameraTarget + (orientation.Backward * cameraPositionOffset.Z), cameraTarget, Vector3.Up);

        return view;
    }

And a snippet of the player class (based upon the XNA heightmap collision demo off MSDN):

        Matrix playerFacingMatrix = Matrix.CreateRotationY(playerFacingDirection);
            Vector3 velocity = Vector3.Transform(movement, playerFacingMatrix);
        velocity *= playerVelocity;

        Vector3 newplayerPosition = GetPlayerPosition() + velocity;
        if (heightMapInfo.IsOnHeightmap(newplayerPosition))
        {
            newplayerPosition.Y = heightMapInfo.GetHeight(newplayerPosition) +
                SphereRadius;
        }
        else
        {
            newplayerPosition = playerPosition;
        }
        float distanceMoved = Vector3.Distance(playerPosition, newplayerPosition);           

        int rollDirection = movement.Z > 0 ? 1 : -1;

        sphereRollingMatrix *= Matrix.CreateFromAxisAngle(playerFacingMatrix.Right,
            theta * rollDirection);

        playerPosition = newplayerPosition;

and then the Draw for the player model

            DrawModel(sphere, camera.ReturnSphereRollingMatrix() *
            Matrix.CreateTranslation(camera.GetPlayerPosition()));

Basically, from what's above, what do I need to set as what to make the player direction point in the same direction as the camera direction? (not vice versa)

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

You might be able to determine the angle between the player's forward direction and the camera's forward direction and add that amount to playerFacingDirection.

float angleToAddToPlayerFacingDirection(Matrix view, Matrix playerFacingMatrix)
{
  Matrix camWorld = Matrix.Invert(view);
  Vector3 camForward = camWorld.Forward;
  camForward.Y = 0;
  camForward.Normalize();

  Vector3 playerForward = playerFacingMatrix.Forward;
  playerForward.Y = 0;
  playerForward.Normalize();

  float yAngleBetweenCamAndPlayer = (float)Math.Acos(Vector3.Dot(camForward, playerForward));

  if(Vector3.Dot(camForward, playerFacingMatrix.Right) > 0)//if it goes the wrong way, change the > to a <.
  {
    yAngleBetweenCamAndPlayer *= -1f;
  }

  return yAngleBetweenCamAndPlayer;//this value is in radians, add a line to change it to degrees if necessasary

}

It is possible (based on your current code) that you don't need to set the Y values to 0 and normalize but would be necessary if you eventually have your player or camera looking upwards or downwards.

\$\endgroup\$

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.