Search code examples
c#3dxnaxna-4.0

Weapon on first person


My team and I have been trying to display our weapon on the screen for a week now, without success: we really need help with this. What we would like to get is, as in every FPS, the weapon display with a little horizontal offset on the screen as if the player was holding it.

We've already tried to use matrix, but without success: the weapon isn't even visible, it seems to be behind us, and even if we try to play with the values a bit we can't get it working properly.

We know that we need to use the rotation of the camera, as well as its position, but we can't figure out the formula to get the weapon's world matrix.

What we have is, the position of the camera as a Vector3, the rotation of the camera as a Vector3 too, with the y coord being the horizontal rotation, between pi and -pi, and x being the vertical rotation. The weapon is scaled at 0.1f. What should we do?

Thank you very much for your help.

EDIT: Here is some code relative to my problem:

public void Update()
{
    weapon.Rotation = ThisPlayer.Rotation;

    weapon.WorldMatrix = WeaponWorldMatrix(
        ThisPlayer.Position, 
        ThisPlayer.Rotation.Y, 
        ThisPlayer.Rotation.X
    );

}

private Matrix WeaponWorldMatrix(Vector3 Position, float updown, float leftright)
{
    Vector3 xAxis;
    Vector3 yAxis;

    xAxis.X = SceneManager.Game.Camera.View.M11;
    xAxis.Y = SceneManager.Game.Camera.View.M21;
    xAxis.Z = SceneManager.Game.Camera.View.M31;

    yAxis.X = SceneManager.Game.Camera.View.M12;
    yAxis.Y = SceneManager.Game.Camera.View.M22;
    yAxis.Z = SceneManager.Game.Camera.View.M32;

    Position += new Vector3(1, 0, 0) / 5;  //How far infront of the camera The gun will be
    Position += xAxis * 1f;      //X axis offset
    Position += -yAxis * 0.5f;     //Y axis offset
    SceneManager.Game.DebugScreen.Debug(Position.ToString());
    return Matrix.CreateScale(0.1f)                        //Size of the Gun
        * Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(5), 0, 0)      //Rotation offset
        * Matrix.CreateRotationX(updown)
        * Matrix.CreateRotationY(leftright)
        * Matrix.CreateTranslation(Position);
}

Solution

  • The simplest way to do this is to invert the camera's view matrix which can then be used to represent the world space position and rotation of the camera. This result can be borrowed and altered slightly to become the weapon's world matrix.

    Matrix cameraWorld = Matrix.Invert(view);
    
    Matrix weaponWorld = cameraWorld; //gives your weapon a matrix that is co-located and co-rotated with camera
    
    
    //then simply reposition the weapon matrix as necessary   
        weaponWorld.Translation += (cameraWorld.Forward * distInFrontOfCam) +                       //set to taste. moves the weapon slightly in front of cam
                                   (cameraWorld.Down * amountWeaponIsLoweredFromCenterOfScreen) +   //set to taste. moves the weapon from the center of the screen to the lower part
                                   (cameraWorld.Right * leftOrRightOffset);                         //set to taste. moves the weapon left or right of center if desired.
    

    Edit. I noticed you are also trying to apply scale to your weapon. My suggestion is to not do that in code. Rather right click the weapon model in the solution explorer and select properties. On the properties window, click the little arrowhead next to 'content processor' to expand the list. Find the scale property and set the scale there (to your 0.1f or whatever). Now you never need to waste cpu cycles to scale that model in code. This causes the scale to be set in the build phase when it converts the fbx to an xnb.