Game Development Community

GameCamera 2.0 Discussion

by Michael Bacon · in Torque Game Engine · 11/19/2007 (7:23 am) · 8 replies

I'm hard at work expanding the GameCamera.

So far I have gotten good reviews from those that have taken the time to look at my work and this has fueled my drive for further progress on the GameCamera.

I have made some great strides since the initial implementation I released a month or two back. I've only been learning and working with Torque for four and a half months now, in my spare time while working on a project.

This thread is here mostly for me to talk out some ideas and features that I am implementing for the next version of the GameCamera. My hopes is that I might spark some discussion on camera implementation.


GameCamera -- A usable first/third person camera with engine mods that allow proper third person aiming.

GameCamera 2.0

First off, I have refactored much of the code to be cleaner and in some places, even more straight forward. I have cleaned up the network code (again) and the client side interpolation. I have gone from the pitch-only camera method to one that allows both yaw and pitch. This will provide an Orbit style camera. Prior to this I have already added and released a version of the GameCamera that supports Fly Cam mode. This has been better incorporated into the new system. I have then added datablock members for various camera options.

I am currently adding zooming and will at some point before 2.0 add proper collision (with the ability to use either collision scheme).

This doesn't sound like much but included in this are vast changes in the reusability of the basic GameCamera object as well as the added support to more easily extend the GameCamera class.



Let me just give some examples of new features that extend reusability.

- I needed an orbit camera that was attached to an object but didn't collide with any objects that we on top of it. The GameCameraData class now implements a collisionMask field that allows you to easily set the mask that is used for the collision checks by that camera.

- I needed to switch between my previous 'pitch only' camera and the new Orbit mode. The GameCameraData class now provides the default flags, allowCameraYaw, allowCameraPitch as well as others. At the same time the GameCamera class provides a setCameraFlags method for modifying these values on a per-camera basis.



Zooming:

I bought AFX. It looks SOOO kick-ass! I'm terrible at building complex effects but it might be feasible with AFX to help me. Anyhow, what I didn't know when I bought it is that it comes with a pretty decent 3rd person camera! Its just a modified Advanced Camera but hey, SO IS MINE! I just modded mine more, LOL! I did however get some really cool ideas from it.

Zooming in far enough will transition to first person (if your datablock has allowFirstPerson=true and allowCameraZoom=true). I know I've seen this elsewhere but its not something I thought of until I saw it again in the AFX demo.

I will NOT however be altering the Third Person Offset during zoom. Instead the offset will stay unchanged and the Zoom Factor will change.

The datablock provides some useful members for zooming.

cameraZoomMinDist indicates the minimum distance that the camera can be from the target before either stopping (allowFirstPerson=false) or changing to first person mode.

cameraZoomMaxMult indicates the maximum zoom multiplier, how far out we can go. This is based on zoomScale which is a dynamic value represented by the length of the Third Person Offset vector. So if you have your third person offset set to be 10 units back and the cameraZoomMaxMult set to 3.0 you would be able to zoom out to 30 units. You can easily set this 1.0 to ignore zooming past the distance indicated by the Third Person Offset.


Collision:

I'm still not quite sure how this works but I'll either be implementing some kind of BoxConvex or a simple sphere model (like the stock octahedron marker model) for proper collision.





Thats it for now.. I'm off to bed..

#1
11/22/2007 (7:53 am)
I have made some wonderful progress.

First off, I implemented zooming and it works great! At least I think. Its responsive and feels good to me. On top of that I got my auto first/third person switching to work as well but I had to make some minor changes in the engine to get it to work.

I found that when in first person mode the GameConnection will lie about it's camera object! It will return the control object as the camera object. There are a few things that rely on this operation to make first person work right. I'm not quite sure what relies on this stuff but I do know that if I change the default behavior of getCameraObject() that first person mode subtly breaks.

When the GameConnection starts lying about the camera object, GameProcess will no longer send control updates to my GameCamera. So I was able to scroll into first person but couldn't get back out because no input was being processed by the camera.

For now I have implemented a getRealCameraObject() method that allows GameProcess to properly echo the moves information to the camera at all times.

This of course requires a small change to GameConnection.h which is the addition of the following method. I put mine immediately after getCameraObject.
ShapeBase* getRealCameraObject()
      { return (mCameraObject.isNull()) ? mControlObject : mCameraObject; }

Finally, I added another eye position mode. In the previous version of GameCamera I had a block of code IFDEFed that would tell the camera to use the eye position of it's target during it's collision calculations. This would scale the camera in towards the eye. However I found that with the stock Orc player the eye node (as aquired via getEyeTransform or getRenderEyeTransform) jitters ALOT. I believe it has to do with the movement in the stand/root animation.

While working with the zoom I started to wonder why the first person camera didn't jitter. As it turns out, it uses a completely different node! The 'cam' node. I altered ShapeBase to expose this transform and based the calculations on it. It works like a charm and zooming it scrolls straight towards the point used in first person as the eye.

Below are the two functions I added to ShapeBase to expose the cam node.
void ShapeBase::getCamNodeTransform(MatrixF* mat)
{
   // Returns cam to world space transform
   S32 cameraNode = mDataBlock->cameraNode;
   if (cameraNode != -1)
      mat->mul(getTransform(), mShapeInstance->mNodeTransforms[cameraNode]);
   else
      *mat = getTransform();
}

void ShapeBase::getRenderCamNodeTransform(MatrixF* mat)
{
   // Returns cam to world space transform
   S32 cameraNode = mDataBlock->cameraNode;
   if (cameraNode != -1)
      mat->mul(getRenderTransform(), mShapeInstance->mNodeTransforms[cameraNode]);
   else
      *mat = getRenderTransform();
}

I opted for the CamNode naming convention because there is already a getCameraTransform method that the engine uses to get the rendering transform of the control/camera object for display. I didn't want these to be confused.
#2
11/23/2007 (5:08 pm)
I hope nobody minds me using these forums to sound my ideas...


I just hit on another idea, free-look. Okay, so its not a new idea, staring at my default.bind.cs reminded me it was there. Now to just add support to use it.

My plan is to allow the camera to rotate on it's own axis when free-look is enabled. It will still position itself based on it's target but will rotate around.

I need to add more support for look angles and such but it'll be worth it I think. Once support is added to allow the camera to rotate itself alot of other nifty features and come into play.

This is really just a modification of the calcCameraTranform method which uses the getLookAtPos method to orient the camera.
#3
11/24/2007 (2:55 pm)
I don't think anyone minds Brian. I had a good read so far and I hope that you'll end up with something useable since I've been looking for pretty much what you have set out to do.

cheers.
#4
11/25/2007 (6:46 am)
Great strides are yet being made. Free-Look mode is coming along great. I've separated the orbital rotation values from the orientation rotation values. This will allow me to both orbit an object and rotate on my own axis.

However, things are really starting to get complex. I'm not quite sure how to handle the client side.

Currently both the client AND the server calculate the camera transform but the server always overrides the client. This way the client can (hopefully) work without the server in case of lag. However this means keeping everything in sync is that much harder. What if the client knows it just entered free-look mode so it determines a new transform but then a server packet arrives that hasn't received the input event yet. It will transition back out. Its not easy keeping these in sync while maintaining server authority.

For now I have had to make free-look entirely server controlled. The client simply will not enter free-look mode. I was having too much time trying to coordinate the updates and I figure if this becomes an issue I can give it another go later.

A really nice thing to note is that the player will shoot towards the target spot even in free-look. The next task is simply to adjust the player to turn towards the camera target. This should be pretty easy and will open the doors for all kinds of game play.

It doesn't help that I'm not an expert in math, in fact I barely scrape by. A lot of what I do in regards to matrices is copy-and-paste or trial-and-error. Despite that, things are working somehow. One question I have on this front though is how do I add roll into my rotation matrix? Currently my rotation matrix is built like this: rotationMatrix.mul(yawMatrix, pitchMatrix); How do i add in the rollMatrix?

I actually tested the camera without a target for the first time in AGES (in camera code terms). It was buggy but I fixed it up. At this point I don't even know if it worked before but now it works even better. Now, when the camera doesn't have a target it will sit at its position and let you look around as if you were in free-look mode.

I think I can easily write a derivative of GameCamera to provide a fixed-tracking style camera or I could add it into the quickly bloating base. I'd really like to separate all of the update logic into a separate object that can be swapped at run time but that seems like a pretty big task that I'm not sure I really want to take on right now.

Do we really need one be-all end-all camera? Not really, but it would be nice. For now simply creating multiple cameras of different types should do.


I'm getting antsy to release the next version. I don't think proper collision will make it into the next release but it will come eventually. There is still a lot to be done and I really really need to work on the actual game play mechanics of my current project. The camera definitely works for what I need now.

I think I might spend some time tomorrow making another video to show off the new features. I dunno.

For now, thats all.. its bed time again.
#5
12/06/2007 (9:16 am)
I just did most of what you're talking about. Here's a few suggestions:

"LookatObject" mode. This basically is a static positioned camera that tracks another object as it moves keeping it centered on screen.

"WorldLook" mode. This basically orients about another object (relative to its position), but does not orient relative to its orientation.

"RelativeLook" mode. This one basically does the same as world look, but applies the rotation of the object as well as the position.

"Static" mode. Does nothing (its great for cutscenes).

Both of those are useful for cutscene style work. I've used em before in other projects (before I used to hack the shapebase derived class's getCameraTransform code etc, these days I use my own camera class and override GameConnection much as you have.
#6
12/06/2007 (9:40 am)
Cool thread and nice to see such attention being given to one of the most overlooked elements of customization!
#7
12/09/2007 (5:00 am)
I just need to give an ARGH!!!

While fixing bugs related to other things my freelook mode broke.

Again... ARGH!!!!!!!!!!!!


Okay, frustrations aside I've made it so that you can place GameCameras in the level and then select them. I am using this to trigger static cameras for different areas. I have a trigger that activates the desired camera when entered.

Gah, I've tracked down so much bug crud its ridiculous I would really like to impart some wisdom here but I dunno. I'm kinda fried. It took two days to get this working.

Just remember this: unpackData is called BEFORE onAdd on the client side.

Also: In initPersistFields() call the parent method after providing any field overrides.
#8
03/16/2008 (11:45 pm)
Hey Brian I was wondering if this was still available or if you had knocked out all of the bugs in it?