So, I'm making a 3rd person game in XNA. I've created a camera that can pitch within constraints and should be able to yaw the full 360.
The class is seen below:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Assignment_3_Redesign
{
/// <summary>
/// This is a game component that implements IUpdateable.
/// </summary>
public class Camera : Microsoft.Xna.Framework.GameComponent
{
//Constrain where our camera can wander in the X and Z plane
public Rectangle XZBoundingBox;
//Angular bounds for camera.
float minPitchIncr = -12;
float maxPitchIncr = 38;
float currentPitchIncr = 12;
float currentYawAngle = 0;
//Matrices to pass to effects.
public Matrix view { get; protected set; }
public Matrix projection { get; protected set; }
//Important directional vars.
public Vector3 pos;
public Vector3 look;
private Vector3 up;
//Mouse Input
//X -- yaw; Y-- pitch
private MouseState prevMouseState;
private MouseState tempMS;
private KeyboardState keyboardState;
//Speed to move camera at for translates.
float Speed = 3;
public Camera(Game game, Vector3 pos, Vector3 target, Vector3 up, Rectangle bounding)
: base(game)
{
this.pos = pos;
this.look = (target - pos);
this.look.Normalize();
this.up = up;
this.view = Matrix.CreateLookAt(pos, target, up);
XZBoundingBox = bounding;
this.projection = Matrix.CreatePerspectiveFieldOfView
(MathHelper.PiOver4,
(float)Game.Window.ClientBounds.Width /
(float)Game.Window.ClientBounds.Height,
1, 500);
}
private void CreateLookAt()
{ view = Matrix.CreateLookAt(pos, pos + look, up); }
//Returns current camera direction as vector.
public Vector3 GetCameraDirection
{ get { return look; } }
///
public override void Initialize()
{
// TODO: Add your initialization code here
Mouse.SetPosition(Game.Window.ClientBounds.Width / 2,
Game.Window.ClientBounds.Height / 2);
prevMouseState = Mouse.GetState();
base.Initialize();
}
/// <summary>
/// Allows the game component to update itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public override void Update(GameTime gameTime)
{
Vector3 tempPos= new Vector3(0.0f,0.0f,0.0f);
//Get keyboard commands
keyboardState = Keyboard.GetState();
/*
//Select object
if (keyboard.IsKeyDown(Keys.D1))
objSelected = 0;
if (keyboard.IsKeyDown(Keys.D2))
objSelected = 1;*/
//Translation
if (keyboardState.IsKeyDown(Keys.A)) //strafe +X (rel)
{
tempPos -= Vector3.Cross(up, look) * Speed;
tempPos.Y = 0.0f;
if (XZBoundingBox.Contains((int)(pos - Vector3.Normalize(tempPos) * Speed).X,
(int)(pos - Vector3.Normalize(tempPos) * Speed).Z))
pos -= Vector3.Normalize(tempPos) * Speed;
}
if (keyboardState.IsKeyDown(Keys.D)) //strafe -X (rel)
{
tempPos -= Vector3.Cross(up, look) * Speed;
tempPos.Y = 0.0f;
if (XZBoundingBox.Contains((int)(pos - Vector3.Normalize(tempPos) * Speed).X,
(int)(pos - Vector3.Normalize(tempPos) * Speed).Z))
pos += Vector3.Normalize(tempPos) * Speed;
}
if (keyboardState.IsKeyDown(Keys.W)) //+Z (rel)
{
tempPos += look * Speed;
tempPos.Y = 0.0f;
if (XZBoundingBox.Contains((int)(pos - Vector3.Normalize(tempPos) * Speed).X,
(int)(pos - Vector3.Normalize(tempPos) * Speed).Z))
pos += Vector3.Normalize(tempPos) * Speed;
}
if (keyboardState.IsKeyDown(Keys.S)) //-Z (rel)
{
tempPos -= look;
tempPos.Y = 0.0f;
if (XZBoundingBox.Contains((int)(pos - Vector3.Normalize(tempPos) * Speed).X,
(int)(pos - Vector3.Normalize(tempPos) * Speed).Z))
pos -= Vector3.Normalize(tempPos) * Speed;
}
//Get mouse commands to control camera direction;
//Yaw rot.
tempMS = Mouse.GetState();
if (tempMS != prevMouseState)
{
currentYawAngle += (tempMS.X - prevMouseState.X) * (-MathHelper.PiOver4 / 150);
currentYawAngle = MathHelper.WrapAngle(currentYawAngle);
if (currentPitchIncr + (tempMS.Y - prevMouseState.Y) < maxPitchIncr &&
currentPitchIncr + (tempMS.Y - prevMouseState.Y) > minPitchIncr)
currentPitchIncr += tempMS.Y - prevMouseState.Y;
if (currentPitchIncr > maxPitchIncr) currentPitchIncr = maxPitchIncr;
else if (currentPitchIncr < minPitchIncr) currentPitchIncr = minPitchIncr;
look = Vector3.Transform(Vector3.Forward,
Matrix.CreateFromYawPitchRoll(currentYawAngle,
currentPitchIncr * (-MathHelper.PiOver4 / 150), 0.0f));
}
//reset prevMouseState
prevMouseState = Mouse.GetState();
base.Update(gameTime);
CreateLookAt();
}
}
}
Now this does what I want ... almost. The problem is that when I'm rotating, it won't go past Pi/-Pi in the yaw. In other words, you can't do a full 360 spin.
Am I making a mistake in some conditional? (I wouldn't doubt it... I've been staring at it for far too long, playing with it and breaking things.)
Here's an example declaration:
camera = new Camera(this, new Vector3(0, 20, 40), Vector3.Zero, Vector3.Up,
new Rectangle(-800,-800,1600,1600));
Also any thoughts on the camera class as a whole?
Thanks for the help!
EDIT 1
This is technically for a #classproject. Wanted to mention that, for clarity's sake. The assignment is open ended and I'm trying to put more time into it because I want to make a solid framework to make WinPhone games...
You can always 'reset' the mouse cursor back to the middle of your screen. This way you can have unlimited motion
When using this technique, make sure you hide the original mousepointer, since it looks very bad. If you still need a mousepointer to be visible, just blit your own mousepointer on the mouse coordinates you track yourself.
Related
I'm currently trying to script a camera that has the player in focus and can move around unlinked to the players own movement.
You can control the camera with the right xBox controller.
The camera should move normally on the X axis in an orbit around the player, but if you move the camera to look up or down (let's say 20° up) it should be on 0° to focus the player again if u let off the joystick and interpolate between those two angles.
In my script the camera is able to look up and down (but the degree isn't locked yet so you could move it on the Y axis 360°+) but it resets to 0°. Additionally the x axis doesn't behave as I want it to since it is able to rotate around the player but only 180° and then it stops and if u let the controller go it also sets it's values back (which I don't want for the x axis).
The camera is a child object of an empty game object. The script is attached to the empty game object.
I'm trying to figure this out since ~3 days and I'd be really grateful for any small advice.
Thanks in advance & here's my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollowPlayer : MonoBehaviour
{
public GameObject target;
public GameObject cameraRig;
public float rotateSpeedX = 90.0f;
public float rotateSpeedY = 5f;
float cameraAngle;
float startCameraAngle;
Vector3 offset;
Vector3 currentOffset;
public float minRotationY;
public float maxRotationY;
bool isCameraMoving;
void Start()
{
offset = transform.position - target.transform.position;
cameraAngle = transform.localEulerAngles.z;
startCameraAngle = cameraAngle;
currentOffset = offset;
}
void Update()
{
transform.position = target.transform.position + currentOffset; // Folgt dem Spieler
float hor = Input.GetAxis("RightJoystickX") * rotateSpeedX; // Input rechter Joystick
float ver = Input.GetAxis("RightJoystickY") * rotateSpeedY;
if (!Mathf.Approximately (hor, 0)) {
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
}
if (!Mathf.Approximately (ver, 0)) {
cameraAngle += 110f * Time.deltaTime;
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
print(ver);
}
else if (ver <= 0.8f) {
//cameraAngle = Mathf.Lerp(cameraAngle, startCameraAngle, 1f - 0.1f * Time.deltaTime);
cameraAngle = startCameraAngle;
}
transform.localEulerAngles = new Vector3(0, hor, cameraAngle);
}
}
If sb else googled this and found my question this worked for me:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollowPlayer : MonoBehaviour
{
public GameObject target;
public GameObject cameraRig;
public float rotateSpeedX = 9.0f;
public float rotateSpeedY = 5f;
float cameraAngle;
float startCameraAngle;
Vector3 offset;
Vector3 currentOffset;
bool isCameraMoving;
void Start()
{
offset = transform.position - target.transform.position;
cameraAngle = transform.localEulerAngles.z;
startCameraAngle = cameraAngle;
currentOffset = offset;
}
void Update()
{
transform.position = target.transform.position + currentOffset; // Folgt dem Spieler
float hor = Input.GetAxisRaw("RightJoystickX") * rotateSpeedX; // Input rechter Joystick GetAxis wenn Bewegung ausschwingen soll
float ver = Input.GetAxisRaw("RightJoystickY") * rotateSpeedY; // GetAxis wenn Bewegung ausschwingen soll
if (!Mathf.Approximately (hor, 0)) {
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
}
if (ver != 0) {
//cameraAngle += 110f * Time.deltaTime;
if (ver > 0)
{
cameraAngle += 110f * Time.deltaTime;
if (cameraAngle >= 420f)
{
cameraAngle = 420f;
}
}
if (ver < 0)
{
cameraAngle -= 110f * Time.deltaTime;
if (cameraAngle <= 290f)
{
cameraAngle = 290f;
}
}
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, cameraAngle);
}
else
{
cameraAngle = Mathf.Lerp(startCameraAngle, cameraAngle, 1f - 0.9f * Time.deltaTime);
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, cameraAngle);
}
So I was working through this tutorial.
https://www.youtube.com/watch?v=OBtaLCmJexk
and I can't find the error in my code anywhere
The problem is just that after working on the vertical ray collisions I run the program and the block just falls through the obstacle.
here is the player code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Controller2D))]
public class Player : MonoBehaviour {
float gravity = -20;
Vector3 velocity;
Controller2D controller;
void Start() {
controller = GetComponent<Controller2D>();
}
void Update() {
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
and here is the Controller2D code:
using UnityEngine;
[RequireComponent(typeof(BoxCollider2D))]
public class Controller2D : MonoBehaviour {
public LayerMask collisionMask;
const float skinWidth = .015f;
public int horizontalRayCount = 4;
public int verticalRayCount = 4;
float horizontalRaySpacing;
float verticalRaySpacing;
BoxCollider2D collider;
RaycastOrigins raycastOrigins;
void Start() {
collider = GetComponent<BoxCollider2D>();
CalculateRaySpacing();
}
public void Move(Vector3 velocity) {
UpdateRaycastOrigins();
VerticalCollisions(ref velocity);
transform.Translate(velocity);
}
void VerticalCollisions(ref Vector3 velocity) {
float directionY = Mathf.Sign(velocity.y);
float rayLength = Mathf.Abs(velocity.y) + skinWidth;
for (int i = 0; i < verticalRayCount; i++) {
Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;
rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);
Debug.DrawRay(raycastOrigins.bottomLeft + Vector2.right * verticalRaySpacing * i, Vector2.up * -2, Color.red);
if (hit) {
velocity.y = (hit.distance - skinWidth) * directionY;
rayLength = hit.distance;
}
}
}
void UpdateRaycastOrigins() {
Bounds bounds = collider.bounds;
bounds.Expand(skinWidth * -2);
raycastOrigins.bottomLeft = new Vector2(bounds.min.x, bounds.min.y);
raycastOrigins.bottomRight = new Vector2(bounds.max.x, bounds.min.y);
raycastOrigins.topLeft = new Vector2(bounds.min.x, bounds.max.y);
raycastOrigins.topRight = new Vector2(bounds.max.x, bounds.max.y);
}
void CalculateRaySpacing() {
Bounds bounds = collider.bounds;
bounds.Expand(skinWidth * -2);
horizontalRayCount = Mathf.Clamp(horizontalRayCount, 2, int.MaxValue);
verticalRayCount = Mathf.Clamp(verticalRayCount, 2, int.MaxValue);
horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);
verticalRaySpacing = bounds.size.y / (verticalRayCount - 1);
}
struct RaycastOrigins {
public Vector2 topLeft, topRight;
public Vector2 bottomLeft, bottomRight;
}
}
Edit: The code is (as I understand from a half an hour tutorial.) just defining attributes to a quad(player) so that it can collide with another quad(obstacle). at the moment the code should only work vertically. so I am testing it by drawing the obstacle under the player and pressing play. the player should come to rest on the obstacle but instead, it sinks straight through it.
My screen after selecting the player block
and asking about debugging, I dont understand the language well enough to not break anything while trying to debug it.
I just got someone on discord to help and it turns out I didn't have the obstacle set with boxcollider2D
Many Thanks all who tried.
This is my Game1.cs code i marked the areas of the camera movement code parts:
Added the camera code in my Game1.cs i used the riemers tutorials camera code here:
http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Mouse_camera.php
I also tried the code in the bottom by user31911 but same results the camera pointer/cursor is dancing/shaking in the middle and not responding.
Im trying to use the Camera class to move the camera around using the mouse.
http://pastebin.com/SF3iiftq
In the constructor i have this line:
viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraFinalTarget, cameraRotatedUpVector);
If i use this line instead assign the viewMatrix variable later in my code then i dont see the terrain at all.
And the big main problem is that the mouse is not responding at all what i get is the mouse pointer dancing/shaking in the middle.
The only thing that responding is my ProcessInput method i did the keys there are working but the method ProcessInputCamera the kkeys and mouse there are not resopnding when im moving the camera the mouse cursor is shaking/dancing in the middle.
I can't figure out why it happen.
But the mouse is not moving the camera.
Pls edit your Question! There are to many unnecessary informations...
here is my camera (1st person) class
class Camera
{ // up in here normal needed vars
public Vector3 cameraPosition;
public float moveSpeed, rotateSpeed;
public bool playing = true;
public GraphicsDevice device;
public Matrix view, projection;
Matrix rotation;
float yaw = 0;
float pitch = 0;
int oldX, oldY;
public Camera(Vector3 cameraPosition, float moveSpeed, float rotateSpeed, float filedOfView, GraphicsDevice device, float PerspectiveFieldOfView)
{
this.cameraPosition = cameraPosition;
this.moveSpeed = moveSpeed;
this.rotateSpeed = rotateSpeed;
this.device = device;
view = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);
projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(PerspectiveFieldOfView), device.Viewport.AspectRatio, 0.1f, filedOfView);
ResetMouseCursor();
}
public void Update()
{
KeyboardState kState = Keyboard.GetState(); // make is able to use your keys
Vector3 v = new Vector3(0, 0, -50) * moveSpeed; // let you permanent walk
move(v); // isnt essential could be deleted if you wont that
}
if (kState.IsKeyDown(Keys.W))
{
Vector3 v = new Vector3(0, 0, -100) * moveSpeed;
move(v);
}
if (kState.IsKeyDown(Keys.S))
{
Vector3 v = new Vector3(0, 0, 50) * moveSpeed;
move(v);
}
if (kState.IsKeyDown(Keys.A))
{
Vector3 v = new Vector3(-50, 0, 0) * moveSpeed;
move(v);
projection = Matrix.
}
if (kState.IsKeyDown(Keys.D))
{
Vector3 v = new Vector3(50, 0, 0) * moveSpeed;
move(v);
}
pitch = MathHelper.Clamp(pitch, -1.5f, 1.5f);
MouseState mState = Mouse.GetState();
int dx = mState.X - oldX; /* is for turning you objekt / camera
yaw -= rotateSpeed * dx; *
*
int dy = mState.Y - oldY; *
pitch -= rotateSpeed * dy; */
ResetMouseCursor(); // this makes your mouse "dancing" in the middle
UpdateMatrices();
}
private void ResetMouseCursor() // mouse settings for the camera
{
int centerX = device.Viewport.Width / 2;
int centerY = device.Viewport.Height / 2;
Mouse.SetPosition(centerX, centerY);
oldX = centerX;
oldY = centerY;
}
private void UpdateMatrices() //standart camera things
{
rotation = Matrix.CreateRotationY(yaw) * Matrix.CreateRotationX(pitch);
Vector3 transformedReference = Vector3.Transform(new Vector3(0, 0, -1), rotation);
Vector3 lookAt = cameraPosition + transformedReference;
view = Matrix.CreateLookAt(cameraPosition, lookAt, Vector3.Up);
}
public void move(Vector3 v) // is the self programmed method to let you move
{
Matrix yRotation = Matrix.CreateRotationY(yaw);
v = Vector3.Transform(v, yRotation);
cameraPosition += v;
}
}
It's pretty standart, but good.
In most cases this class is all you need for the Camera and it's configuration.
Rewrite/Fix it, like however you need it...
Tipp: You could also consider a Arc-Ball-Cam..
What I'm trying to do is increase my viewing distance so that i can see objects beyond 10000f I've included a picture to help you understand what i mean, i want to set my viewing distance to, lets say 50000f so that i can see more objects which are farther away.
below is my camera code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Graphics;
namespace test1
{
public class ArcBallCamera
{
//rotation
public Matrix rotation = Matrix.Identity;
//camera pos.
public Vector3 position = Vector3.Zero;
// Simply feed this camera the position of whatever you want its target to be
public Vector3 targetPosition = Vector3.Zero;
public Matrix viewMatrix = Matrix.Identity;
public Matrix projectionMatrix = Matrix.Identity;
private float zoom = 8000.0f;
public float Zoom
{
get
{
return zoom;
}
set
{ // Keep zoom within range
zoom = MathHelper.Clamp(value, zoomMin, zoomMax);
}
}
private float horizontalAngle = MathHelper.PiOver2;
public float HorizontalAngle
{
get
{
return horizontalAngle;
}
set
{ // Keep horizontalAngle between -pi and pi.
horizontalAngle = value % MathHelper.Pi;
}
}
private float verticalAngle = MathHelper.PiOver2;
public float VerticalAngle
{
get
{
return verticalAngle;
}
set
{ // Keep vertical angle within tolerances
verticalAngle = MathHelper.Clamp(value, verticalAngleMin, verticalAngleMax);
}
}
private const float verticalAngleMin = 0.01f;
private const float verticalAngleMax = MathHelper.Pi - 0.01f;
private const float zoomMin = 0.1f;
private const float zoomMax = 8000.0f;
// FOV is in radians
// screenWidth and screenHeight are pixel values. They're floats because we need to divide them to get an aspect ratio.
public ArcBallCamera(float FOV, float screenWidth, float screenHeight, float nearPlane, float farPlane)
{
if (screenHeight < float.Epsilon)
throw new Exception("screenHeight cannot be zero or a negative value");
if (screenWidth < float.Epsilon)
throw new Exception("screenWidth cannot be zero or a negative value");
if (nearPlane < 0.1f)
throw new Exception("nearPlane must be greater than 0.1");
this.projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(FOV), screenWidth / screenHeight,
nearPlane, farPlane);
}
public void Update(GameTime gameTime)
{
// Start with an initial offset
Vector3 cameraPosition = new Vector3(0.0f, zoom, 0.0f);
// Rotate vertically
cameraPosition = Vector3.Transform(cameraPosition, Matrix.CreateRotationX(verticalAngle));
// Rotate horizontally
cameraPosition = Vector3.Transform(cameraPosition, Matrix.CreateRotationY(horizontalAngle));
position = cameraPosition + targetPosition;
this.LookAt(targetPosition);
// Compute view matrix
this.viewMatrix = Matrix.CreateLookAt(this.position,
this.position + this.rotation.Forward,
this.rotation.Up);
}
/// <summary>
/// Points camera in direction of any position.
/// </summary>
/// <param name="targetPos">Target position for camera to face.</param>
public void LookAt(Vector3 targetPos)
{
Vector3 newForward = targetPos - this.position;
newForward.Normalize();
this.rotation.Forward = newForward;
Vector3 referenceVector = Vector3.UnitY;
// On the slim chance that the camera is pointer perfectly parallel with the Y Axis, we cannot
// use cross product with a parallel axis, so we change the reference vector to the forward axis (Z).
if (this.rotation.Forward.Y == referenceVector.Y || this.rotation.Forward.Y == -referenceVector.Y)
{
referenceVector = Vector3.UnitZ;
}
this.rotation.Right = Vector3.Cross(this.rotation.Forward, referenceVector);
this.rotation.Up = Vector3.Cross(this.rotation.Right, this.rotation.Forward);
}
public Matrix[] SetupEffectDefaults(Model myModel)
{
Matrix[] absoluteTransforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(absoluteTransforms);
foreach (ModelMesh mesh in myModel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.Projection = projectionMatrix;
effect.View = viewMatrix;
}
}
return absoluteTransforms;
}
}
}
We don't see how you create your ArcBallCamera, but simply changing the last parameter of the constructor to 50000 should do the job, see CreatePerspectiveFieldOfView documentation here.
I really don't know whats is going wrong here. The game seams to be drawing funny. The first thing I notice is that when the player moves, the camera move before the avatar does so the camera comes out of the avatars head a bit. Then I noticed that when you look at the avatar from the side you can see though his shoulder and into his cheast cavity (it does not do this in the animation player I build and also in Maya). The next thing I notice is when the player moves forward, the ground starts to flicker. Am I calling the draw method wrong or something?
here is the camera class I am using
public class Camera : Microsoft.Xna.Framework.GameComponent
{
//Cam Matrices
//viw is composed of position, direction, and up vectors
public Matrix view { get; protected set; }
public Matrix projection { get; protected set; }
//to move the camera
//used to recreate view matrix each frame
public Vector3 cameraPosition { get; protected set; }
public Vector3 cameraDirection; //not the target/ point camera is looking at a relative direction camrea is faceing
//to find target add the cameraPosition and cameraDirection togeater
public Vector3 cameraUp;
public Vector3 target;
//camera controls
float speed = 3;
MouseState prevMouseState;
// Pi/180 = 1 degree
// Max yaw/pitch variables
//this is for moving the head only not the body
float totalYaw = MathHelper.PiOver2;
public float currentYaw = 0;
float totalPitch = MathHelper.PiOver2;
public float currentPitch = 0;
public float leftTrigYaw;
public float rightTrigYaw;
//constructor
public Camera(Game game, Vector3 pos, Vector3 target, Vector3 up)
: base(game)
{
//build camera view matrix
cameraPosition = pos;
cameraDirection = target - pos;
cameraDirection.Normalize(); //Convert to magintue 1
//make it easy to apply differt speeds to movement of camera
cameraUp = up;
CreateLookAt();
projection = Matrix.CreatePerspectiveFieldOfView
(
MathHelper.PiOver4,
(float)Game.Window.ClientBounds.Width / (float)Game.Window.ClientBounds.Height,
1, 3000);
}
private void CreateLookAt()
{
//middle variable is the target!
view = Matrix.CreateLookAt(cameraPosition, cameraPosition + cameraDirection, cameraUp);
}
public override void Initialize()
{
Mouse.SetPosition(Game.Window.ClientBounds.Width / 2,
Game.Window.ClientBounds.Height / 2);
prevMouseState = Mouse.GetState();
base.Initialize();
}
public override void Update(GameTime gameTime)
{
GamePadState currentState = GamePad.GetState(PlayerIndex.One);
//move forward
if (currentState.ThumbSticks.Left.Y > 0 || Keyboard.GetState().IsKeyDown(Keys.W))
{
//move just on x and x axis Y is controled other places.
cameraPosition += new Vector3(cameraDirection.X, 0, cameraDirection.Z) * speed;
}
//move backward
if (currentState.ThumbSticks.Left.Y < 0 || Keyboard.GetState().IsKeyDown(Keys.S))
{
//move just on x and x axis Y is controled other places.
cameraPosition -= new Vector3(cameraDirection.X, 0, cameraDirection.Z) * speed;
}
//move left
if (currentState.ThumbSticks.Left.X < 0 || Keyboard.GetState().IsKeyDown(Keys.A))
{
//cross product of the up and direction vectors can give the side direction
cameraPosition += Vector3.Cross(cameraUp, cameraDirection) * speed;
}
//move right
if (currentState.ThumbSticks.Left.X > 0 || Keyboard.GetState().IsKeyDown(Keys.D))
{
cameraPosition -= Vector3.Cross(cameraUp, cameraDirection) * speed;
}
//mouse movements
// Yaw rotation
float yawAngle = (-MathHelper.PiOver4 / 150) *
(Mouse.GetState().X - prevMouseState.X);
float padYaw = (-MathHelper.PiOver2 / 50) *
(currentState.ThumbSticks.Right.X);
if (Math.Abs(currentYaw + yawAngle) < totalYaw)
{
cameraDirection = Vector3.Transform(cameraDirection,
Matrix.CreateFromAxisAngle(cameraUp, yawAngle));
currentYaw += yawAngle;
}
//rotate left and right
if (currentState.ThumbSticks.Right.X < 0 || currentState.ThumbSticks.Right.X > 0)
{
if (Math.Abs(currentYaw + padYaw) < totalYaw)
{
cameraDirection = Vector3.Transform(cameraDirection,
Matrix.CreateFromAxisAngle(cameraUp, padYaw));
currentYaw += padYaw;
}
}
leftTrigYaw = (MathHelper.PiOver2 / 50) *
(currentState.Triggers.Left);
if (currentState.Triggers.Left > 0.0f)
{
cameraDirection = Vector3.Transform(cameraDirection,
Matrix.CreateFromAxisAngle(cameraUp, leftTrigYaw));
}
rightTrigYaw = (-MathHelper.PiOver2 / 50) *
(currentState.Triggers.Right);
if (currentState.Triggers.Right > 0.0f)
{
cameraDirection = Vector3.Transform(cameraDirection,
Matrix.CreateFromAxisAngle(cameraUp, rightTrigYaw));
}
// Pitch rotation
float pitchAngle = (MathHelper.PiOver4 / 150) *
(Mouse.GetState().Y - prevMouseState.Y);
float padPitch = (-MathHelper.PiOver2 / 50) *
(currentState.ThumbSticks.Right.Y);
if (Math.Abs(currentPitch + pitchAngle) < totalPitch)
{
cameraDirection = Vector3.Transform(cameraDirection,
Matrix.CreateFromAxisAngle(
Vector3.Cross(cameraUp, cameraDirection),
pitchAngle));
currentPitch += pitchAngle;
}
if (currentState.ThumbSticks.Right.Y < 0 || currentState.ThumbSticks.Right.Y > 0)
{
if (Math.Abs(currentPitch + padPitch) < totalPitch)
{
cameraDirection = Vector3.Transform(cameraDirection,
Matrix.CreateFromAxisAngle(
Vector3.Cross(cameraUp, cameraDirection),
padPitch));
currentPitch += padPitch;
}
}
//reset mouse state
target = cameraPosition + cameraDirection;
prevMouseState = Mouse.GetState();
//for testing only!! get rid of this when done
if (currentState.Buttons.A == ButtonState.Pressed)
{
//fly upwar
cameraPosition += new Vector3(0, 15, 0);
}
if (currentState.Buttons.B == ButtonState.Pressed)
{
//fly upwar
cameraPosition -= new Vector3(0, 15, 0);
}
//call camera creat look at method to build new view matrix
CreateLookAt();
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
{
Game.Exit();
}
base.Update(gameTime);
}
}
}
I am also using a custom model handler to draw the ground and the avatar
public class CModel
{
public Vector3 Position { get; set; }
public Vector3 Rotation { get; set; }
public Vector3 Scale { get; set; }
public Model Model { get; private set; }
private Matrix[] modelTransforms;
private GraphicsDevice graphicsDevice;
public CModel(Model Model, Vector3 Position, Vector3 Rotation,
Vector3 Scale, GraphicsDevice graphicsDevice)
{
this.Model = Model;
modelTransforms = new Matrix[Model.Bones.Count];
Model.CopyAbsoluteBoneTransformsTo(modelTransforms);
this.Position = Position;
this.Rotation = Rotation;
this.Scale = Scale;
this.graphicsDevice = graphicsDevice;
}
public void Draw(Matrix View, Matrix Projection)
{
// Calculate the base transformation by combining
// translation, rotation, and scaling
Matrix baseWorld = Matrix.CreateScale(Scale)
* Matrix.CreateFromYawPitchRoll(
Rotation.Y, Rotation.X, Rotation.Z)
* Matrix.CreateTranslation(Position);
foreach (ModelMesh mesh in Model.Meshes)
{
Matrix localWorld = modelTransforms[mesh.ParentBone.Index]
* baseWorld;
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
BasicEffect effect = (BasicEffect)meshPart.Effect;
effect.World = localWorld;
effect.View = View;
effect.Projection = Projection;
effect.EnableDefaultLighting();
}
mesh.Draw();
}
}
}
}
I dont know where the problem is originating from but these are the only two things that I can think of that would give the problem.
Thanks for any help with this.
Here is what is going on with the model. I am sure that the normal are right in maya because I used the simple model drawer that Microsoft has up on the tutorials but then you can somewhat see though the guys shoulder and arm. I could not get a picture of the ground flickering because it happens too fast to really screen capture it.But every time i move the camera, the ground jumps up and down a lot. and then stops when I stop moving the camera to look around. am I not calling the the camera.Update() method because its a game component and is linked up with the game1 class.
This is how I am drawing the models
it is a draw method in the custom model class
public void Draw(Matrix View, Matrix Projection)
{
// Calculate the base transformation by combining
// translation, rotation, and scaling
Matrix baseWorld = Matrix.CreateScale(Scale)
* Matrix.CreateFromYawPitchRoll(
Rotation.Y, Rotation.X, Rotation.Z)
* Matrix.CreateTranslation(Position);
foreach (ModelMesh mesh in Model.Meshes)
{
Matrix localWorld = modelTransforms[mesh.ParentBone.Index]
* baseWorld;
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
BasicEffect effect = (BasicEffect)meshPart.Effect;
effect.World = localWorld;
effect.View = View;
effect.Projection = Projection;
effect.EnableDefaultLighting();
}
mesh.Draw();
}
}
For the artifacts on the model: The model doesn't look like it's being rendered properly. Your DrawPrimitives call probably isn't feeding the graphics card the right data (either your vertex/index buffers are filled in wrong or you have the primitive type/count wrong). Try rendering it in wireframe mode, you should be able to see the triangles that are getting distorted, producing these artifacts.
As for the ground - I will look some more through the code and see if I can think of anything.