XNA Game Development Forums
2012/05/21 19:31:32 *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Search Calendar Login Register  
Pages: [1]
  Print  
Author Topic: Camera Tracking  (Read 2007 times)
muchrejoicing
Newbie
*
Offline Offline

Posts: 46


View Profile
« on: 2007/05/26 15:56:47 »

I just realized that I'd accidentally posted this in the 3D engine board; behold -- delete and repost.

I'm trying to come up with a good way to make a TrackingCamera class, which would take in an HMObject equivalent when constructed, and continue to follow its position. Left to my own devices, I would try to store a reference to the target HMObject's position, eliminating the need to poll it actively, but I don't know if that's even possible in C#. Either way, it wouldn't help -- the HMCamera/HMCameraManager setup only calls Update when the camera itself has been moved.

So, the existing Camera class would have to change a lot to do this modularly. I could always make a boring hack, and refresh the camera manually in my game's Update function, but I'd like something that fit better with an HMCameraManager.

Things it would need:
A call to ActiveCamera.Update() in HMGame.Update(). The view matrix will change frequently, and I don't feel like that would fit well in the HMObject.
Some new properties, like UseObjectRotation; that option alone gives you three viable styles of cameras: independently rotating, locked rotation (indirectly controlled by when you rotate the target) and combined. A more elaborate SlerpObjectRotation could be fun -- I imagine that as slerping the camera's rotation to 0 as the target moves; however it works, I'm clearly getting sidetracked.
Some of these tricks would work best if the camera remembered the target's last position -- it could skip a bunch of updates, and use the distance moved to throttle its SLERPing.

If you have any suggestions, let me know. I'll be back with some actual code/questions once I've done my homework.
Logged
muchrejoicing
Newbie
*
Offline Offline

Posts: 46


View Profile
« Reply #1 on: 2007/05/26 16:56:33 »

Adding Custom Cameras:
I was trying to add cameras to the manager in my SetupScene method (i.e. from outside the game library code), and noticed a problem with the structure: the Camera class takes a Viewport in its constructor. Apparently, the GraphicsDevice's Viewport isn't initialized until after you call game.Run(). But, once you do that, there's no way to call code from outside the library. (Don't say 'threading.' *shudder*) My solution was to add an OnInit delegate to the HMGame, and change the Initialize function like so:

Code:
// inside namespace HMEngine:
public delegate void InitMethod();

// with the rest of HMGame's fields:
public InitMethod OnInit;

// in HMGame:
protected override void Initialize() {
    this.IsMouseVisible = true;
    HMShaderManager.Initialize();

    // 1st CHANGE:
    if (OnInit != null) OnInit();

    // 2nd CHANGE:
    if (HMCameraManager.ActiveCamera == null) { // Only add a default camera if there are none after OnInit
        HMCamera defaultCamera = new HMCamera(myGraphics.GraphicsDevice.Viewport);
        HMCameraManager.AddCamera(defaultCamera, "default");
        HMCameraManager.SetActiveCamera("default");
    }
    base.Initialize();
}

The call to OnInit should come before the default camera, for reasons that should be clear. This way, you can take complete control of your camera management or ignore the question entirely, without penalty either way. I'm taking a similar approach to my HMCamera work -- if you paste it in to your engine and don't change the way you call the HMCamera itself, you won't be able to tell the difference.

Using it is simple enough:
Code:
public static void Main() {
    // [other code]
    game.OnInit += new InitMethod(LoadCamera);

    game.Run();
}

public static void LoadCamera() {
    HMCamera cam = new HMCamera(game.Graphics.GraphicsDevice.Viewport);
    cam.Target = myModel;
    HMCameraManager.AddCamera(cam, "default");
    HMCameraManager.SetActiveCamera("default");
}
Logged
muchrejoicing
Newbie
*
Offline Offline

Posts: 46


View Profile
« Reply #2 on: 2007/05/27 09:01:16 »

The basic idea is working by now; for now, I just have a little request for comments regarding style.

I've changed some things about how the camera works -- a plain (non-tracking) camera now has an origin (myPosition) and an offset from that origin. ((myPosition, myOffset) is roughly equivalent to (myRevolveTarget, myPosition) from the original HMCamera, but slightly more general.) Calls to Translate modify the offset value; to re-center the camera, a property CameraPosition has been added.

When you're in "normal" mode, you will be updating CameraPosition a lot. But, when it's in tracking mode, assigning to CameraPosition doesn't really make sense: by setting a Target, you asked the game to manage CameraPosition. How should I respond?

My impulse is to throw an exception. So:

Code:
/// <summary>
/// The camera's origin. Cannot be set while tracking
/// </summary>
public Vector3 CameraPosition {
    get { return (myTarget == null) ? myPosition : myTarget.Position; }
    set {
        if (myTarget == null) myPosition = value;
        else // You must set Target = null to set the camera's position manually
            throw new ArgumentException("Position is not assignable in Tracking mode", "Position");
    }
}

I was disappointed to discover there's no IllegalOperationException.

I want to throw an exception here because, if someone tries to set the CameraPosition in tracking mode, they don't understand what it's for. I could just disable tracking and set the position, but I would rather crash the program than gracefully ignore the input. I feel like that would be send the unsuspecting programmer on a wild bug chase. Instead, I leave a hint in the comments, and make them look at it. Thoughts?
Logged
muchrejoicing
Newbie
*
Offline Offline

Posts: 46


View Profile
« Reply #3 on: 2007/05/27 20:02:35 »

I just noticed the Chase Camera sample (http://creators.xna.com/Headlines/developmentaspx/archive/2007/01/01/Chase-Camera-Sample.aspx); it looks like I've been one-upped in a big way. Here are my changes:

Code:
private HMObject myTarget;
private Vector3 myOffset = new Vector3(0, 0, 0);

public HMObject Target {
    get { return myTarget; }
    set {
        // Reset default camera behavior and update myPosition
        if (value != null) myPosition = value.Position;
        useTargetRotation = false;
        myTarget = value;
    }
}

public bool UseTargetRotation {
    get { return useTargetRotation; }
    set {
        if (value == true && myTarget == null) { // Illegal operation
            throw new ArgumentException("Target must be set before enabling tracking", "UseTargetPosition");
        }
        useTargetRotation = true;
    }
}

/// <summary>
/// The camera's eye position
/// </summary>
public Vector3 Position {
    get {
        return myPosition + myOffset;
    }
}

/// <summary>
/// The camera's origin. Cannot be set while tracking.
/// </summary>
public Vector3 CameraPosition {
    get { return (myTarget == null) ? myPosition : myTarget.Position; }
    set {
        if (myTarget == null) myPosition = value;
        else // You must set Target = null to set the camera's position manually
            throw new ArgumentException("Position cannot be set in Tracking mode", "Position");
    }
}

/// <summary>
/// The camera's rotation.
/// </summary>
public Quaternion Rotation { get { return (useTargetRotation) ? myRotation + myTarget.Rotation : myRotation; } }

public void Translate(Vector3 distance) {
    myOffset += distance;
}

public void Update() {
    if (Slerping) slerpType = SlerpType.None;

    myWorld = Matrix.Identity;

    // First, translate the camera out by its offset position. Uses myView as an accumulator.
    Matrix temp;
    Matrix.CreateTranslation(ref myOffset, out myView);

    // Now, rotate around the camera's origin
    if (useTargetRotation) { // Combine the object and camera rotations
        Quaternion tRotation = myTarget.Rotation;
        Quaternion.Multiply(ref tRotation, ref myRotation, out tRotation);
        Quaternion.Normalize(ref tRotation, out tRotation);
        Matrix.CreateFromQuaternion(ref tRotation, out temp);
    } else {
        Matrix.CreateFromQuaternion(ref myRotation, out temp);
    } // starting here, temp is the final rotation matrix
    Matrix.Multiply(ref myView, ref temp, out myView);

    // Finally, translate the camera out to its final position
    if (myTarget != null) {
        myPosition = myTarget.Position;
    }
    Matrix.CreateTranslation(ref myPosition, out temp);
    Matrix.Multiply(ref myView, ref temp, out myView);
    Matrix.Invert(ref myView, out myView);

    Matrix.CreatePerspectiveFieldOfView(
        MathHelper.Pi / 3.0f, (float)myViewport.Width / (float)myViewport.Height,
        myViewport.MinDepth, myViewport.MaxDepth,
        out myProjection
    );

    Matrix.Multiply(ref myView, ref myProjection, out temp);
    myFrustum = new BoundingFrustum(temp);
}

Rotate is basically what Revolve was, as this version of the camera is built to face towards myPosition.
« Last Edit: 2007/05/28 09:22:54 by muchrejoicing » Logged
daenris
Newbie
*
Offline Offline

Posts: 7


View Profile
« Reply #4 on: 2007/05/29 19:50:23 »

That sample chase camera was a great find.  I've begun to roughly integrate it into my Camera class in my version of the HM Engine.  Right now the code looks horrible, but it does work and tracks nicely behind a model as I fly around the scene.
Logged
Pages: [1]
  Print  
 
Jump to:  

Related Topics
Subject Started by Replies Views Last post
Tutorial 12 :: Adding in Advanced Camera Functionality Tutorial Discussion « 1 2 3 » mikeschuld 30 11116 Last post 2007/08/01 07:00:20
by Suzume
Parenting Camera to an Object Hazy Mind XNA Engine Requests rstackhouse 4 3098 Last post 2007/03/14 06:13:57
by 5parrowhawk
Camera Issues Hazy Mind XNA Engine minich21 6 3047 Last post 2007/08/14 21:27:30
by mikeschuld
Camera Issues Hazy Mind XNA Engine Trano 3 2811 Last post 2008/09/17 08:27:25
by mikeschuld
Camera problem Hazy Mind XNA Engine Montynis 2 1685 Last post 2007/08/02 09:54:14
by Montynis
Back tracking a few months General Discussion mikeschuld 3 3031 Last post 2008/04/14 03:25:14
by precious roy
Camera rotation issues (z-axis drift solved!) Hazy Mind XNA Engine ppardee 10 4271 Last post 2008/11/19 11:22:49
by inbreed
extending the camera classes/cameramanager Hazy Mind XNA Engine Mikeske 7 2079 Last post 2009/12/16 01:46:28
by Mikeske
Powered by MySQL Powered by PHP Powered by SMF 1.1.12 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Page created in 0.132 seconds with 18 queries.