Where to implement a camera controller? (an scripts 'n stuff)

Feb 11, 2010 at 8:05 AM

I'm having a go at modifying bubzy's camera code into a a component that I can easily snap into any project.  Code is below.  I've implemented this as an UpdateableComponent and then startr it up with a call like...

FreeLookCameraController freeLookCamera = new FreeLookCameraController(engine, LevelDomainName, true) { Parent = engine.Root, Position = new Vector3(0, -3, 20f) };

So is this the right way to add this sort of functionality to the camera?  The camera doesn't seem to be a component so I can't use a script, and inheriting from FovCamera also seems like the wrong way to go because my camera controller should be able to be attached to any camera.  My next step from this will be another camera type that focuses on a specific model and rotates around it.  The idea is so I can easily switch them back and forth to assist with dev.

...and while I was looking for how to do that I also noticed that other components don't seem to have the ScriptClassName property that's available in the scene editor.  So how would I attach a script via code when I need to?  I noticed the Script property has a comment in the source saying it shouldn't be set directly and the documentation seems to suggest it just can't be done that way, but I tend to build things dynamically so I think my use of the scene editor will be minimal.

...and I'm completely lost as to where subcomponents fit in to the whole picture too.

Sorry to lump all this together but I'm still trying to get my head around the structure I should be using and I think past game engines I've used are also clouding my judgement a bit.  Just need some clarification about where the correct points are to extend the engine from I think.

 

Finally, my current camera controller...

using Microsoft.Xna.Framework;
using Ox.Engine;
using Ox.Engine.Component;

namespace Wheely.Component
{
    class FreeLookCameraController : UpdateableComponent
    {
        private OxEngine _engine;

        private float _xLook;
        private float _yLook;
        private float _moveSpeed = 5f;
        private float _turnSpeed = 5f;
        private bool _invertX;
        private bool _invertY;

        public FreeLookCameraController(OxEngine engine, string domainName, bool ownedByDomain)
            : base(engine, domainName, ownedByDomain)
        {
            _engine = engine;
        }

        public Vector3 Position
        {
            get { return _engine.Camera.Position; }
            set { _engine.Camera.Position = value; }
        }

        /// <summary>
        /// The orientation matrix.
        /// </summary>
        public Matrix Orientation
        {
            get { return _engine.Camera.Orientation; }
            set
            {
                Matrix orientation = value;
                _engine.Camera.SetOrientation(ref orientation);
            }
        }

        public float MoveSpeed
        {
            get { return _moveSpeed; }
            set { _moveSpeed = value; }
        }

        public float TurnSpeed
        {
            get { return _turnSpeed; }
            set { _turnSpeed = value; }
        }

        public bool InvertX
        {
            get { return _invertX; }
            set { _invertX = value; }
        }

        public bool InvertY
        {
            get { return _invertY; }
            set { _invertY = value; }
        }

        protected override void UpdateHook(GameTime gameTime)
        {
            RotateCamera(gameTime.ElapsedGameTime.Milliseconds);
            MoveCamera(gameTime.ElapsedGameTime.Milliseconds);
        }

        private void RotateCamera(double elapsedGameTime)
        {
            // Get the current position of the gamepad's right thumbstick
            // and add it to xLook and yLook
            _xLook += _engine.GamePadState.ThumbSticks.Right.X * _turnSpeed * (float)elapsedGameTime * 0.001f;
            _yLook += _engine.GamePadState.ThumbSticks.Right.Y * _turnSpeed * (float)elapsedGameTime * 0.001f;

            // Create a rotation matrix based on xLook and yLook
            // and apply it to the camera orientation
            Orientation = Matrix.CreateRotationX(_invertY ? -_yLook : _yLook) * Matrix.CreateRotationY(_invertX ? _xLook : -_xLook);
        }

        private void MoveCamera(double elapsedGameTime)
        {
            // Determine how much to move based on the gamepad's left thumbstick
            float moveForwardBack = _engine.GamePadState.ThumbSticks.Left.Y;
            float moveLeftRight = _engine.GamePadState.ThumbSticks.Left.X;
            Vector3 moveVector = new Vector3(moveLeftRight, 0, -moveForwardBack);

            // Translate the camera based on the current orientation
            Position += _moveSpeed * Vector3.Transform(moveVector, Orientation);
        }
    }
}

Coordinator
Feb 11, 2010 at 6:42 PM

That's right except for one caveat.

Recently, there's been a shader bug that has made me realized Ox's camera object is implemented incorrectly. Soon in SVN, there will be a different implementation rendering your code moot.

Sorry.

 

Coordinator
Feb 11, 2010 at 7:19 PM

Alright, I've refactored the camera and the changes are pretty easy to handle.

I'll be back in a moment with a concrete suggestion.

 

Coordinator
Feb 12, 2010 at 7:09 PM

For the new camera system, what you've got there is mostly fine. If you've pulled down the head, you'll notice that there's no longer a mutable Position property and the Orientation property is completely gone. This is because you must now either set the View matrix directly or indirectly via a SetViewByLookTarget or SetViewByLookNormal. Now, this may seem restricting, but it actually opens up a lot more control over the camera's behavior (not to mention finally allows me to fix a bug that I simply could fix before).

Let me know if you have any questions. I'll be putting out a new download as soon as I receive the new video card and squash the remaining rendering bugs.

Cheers!

Feb 17, 2010 at 7:31 AM

For now I'm running the 2.2.2.0 beta installer version.  I've collected the source via TortoiseSVN but I'm not actually referencing that one from my project yet.  Don't think I've grabbed those camera changes yet either.  This camera things is a bit of a sideline anyway and I'm tied up with some heavy trig atm.  (Trying to put corners into my tube :)  Still progressing really well btw).  So I'll probably wait till you release another installer before I get back to this.  What you've said makes sense (in theory).  I'll let you know if I have trouble with the implementation.

Mar 9, 2010 at 7:42 AM
Edited Mar 11, 2010 at 1:07 PM

I've successfully updated my FreeLookCameraController to work with rev 404.  Done quite a bit of reading up on matrices and I understand what you mean about it opening up more control now.  To compliment what you've done I made the effort to apply all my translations and rotations to the world matrix rather than using vectors and converting all the time.  The only real issue I had was that initially I was applying the changes directly to the view matrix which gave some odd results.  Today I clicked that I should modify the world matrix and then set the inverse of that to the view matrix and it started working perfectly.  My code is based on this matrix tutorial which I highly recommend to anyone trying to get their head around this stuff.  I especially like how it clearly separates out each of the transformations.  Code for the freelook cam is below.  I welcome any comments or suggestions.  Going to move on to a simple follow cam now and I'm happy to post that code also if anyone is interested.

 

using Microsoft.Xna.Framework;
using Ox.Engine;
using Ox.Engine.Component;

namespace Wheely.Component
{
    class FreeLookCameraController : UpdateableComponent
    {
        private OxEngine _engine;

        private float _moveSpeed = 1f;
        private float _turnSpeed = 1f;

        private bool _invertX;
        private bool _invertY;

        private Matrix _worldMatrix = Matrix.Identity;

        public FreeLookCameraController(OxEngine engine, string domainName, bool ownedByDomain)
            : base(engine, domainName, ownedByDomain)
        {
            _engine = engine;
        }

        public float MoveSpeed
        {
            get { return _moveSpeed; }
            set { _moveSpeed = value; }
        }

        public float TurnSpeed
        {
            get { return _turnSpeed; }
            set { _turnSpeed = value; }
        }

        public bool InvertX
        {
            get { return _invertX; }
            set { _invertX = value; }
        }

        public bool InvertY
        {
            get { return _invertY; }
            set { _invertY = value; }
        }

        protected override void UpdateHook(GameTime gameTime)
        {
            // Apply rotation and movement based on joystick controls
            RotateCamera(gameTime.ElapsedGameTime.Milliseconds);
            MoveCamera(gameTime.ElapsedGameTime.Milliseconds);

            // Set the view matrix to be the inverse of the world matrix
            Matrix viewMatrix = Matrix.Invert(_worldMatrix);
            _engine.Camera.SetViewByMatrix(ref viewMatrix);
        }

        private void RotateCamera(double elapsedGameTime)
        {
            // Store the translation component of the world matrix
            // (If we don't store and restore this the camera will always rotate around the origin)
            Vector3 position = _worldMatrix.Translation;

            // Turn speed is measured in 10th's of a degree
            // i.e. a turnSpeed of 1 will turn a tenth of a degree every millisecond
            float oneTenthDegree = MathHelper.Pi * 0.0018f;
            
            // Turn left/right
            float xAngleAdjust = _engine.GamePadState.ThumbSticks.Right.X * (_turnSpeed * oneTenthDegree) * (float)elapsedGameTime;
            _worldMatrix *= Matrix.CreateFromAxisAngle(Vector3.Up, _invertX ? xAngleAdjust : -xAngleAdjust);

            // Turn up/down
            float yAngleAdjust = _engine.GamePadState.ThumbSticks.Right.Y * (_turnSpeed * oneTenthDegree) * (float)elapsedGameTime;
            _worldMatrix *= Matrix.CreateFromAxisAngle(_worldMatrix.Right, _invertY ? -yAngleAdjust : yAngleAdjust);

            // Restore the translation component of the world matrix
            _worldMatrix.Translation = position;
        }

        private void MoveCamera(double elapsedGameTime)
        {
            // Move forward/backward
            float forwardBackwardAdjust = _engine.GamePadState.ThumbSticks.Left.Y * (_moveSpeed * 0.1f) * (float)elapsedGameTime;
            _worldMatrix *= Matrix.CreateTranslation(_worldMatrix.Forward * forwardBackwardAdjust);

            // Move left/right
            float leftRightAdjust = _engine.GamePadState.ThumbSticks.Left.X * (_moveSpeed * 0.1f) * (float)elapsedGameTime;
            _worldMatrix *= Matrix.CreateTranslation(_worldMatrix.Right * leftRightAdjust);

            // Move up/down
            float upDownAdjust = (_engine.GamePadState.Triggers.Right - _engine.GamePadState.Triggers.Left) * (_moveSpeed * 0.1f) * (float)elapsedGameTime;
            _worldMatrix *= Matrix.CreateTranslation(_worldMatrix.Up * upDownAdjust);
        }
    }
}

 

Mar 10, 2010 at 3:01 AM

I'm not there yet (still learning the system), but I will need a follow cam for my project so I would appriciate the follow cam code!

From what I have been reading about the Ox Engine I wonder if you could just link a model to the camera object and have them do the same movements.

Mar 10, 2010 at 8:15 AM
Edited Mar 11, 2010 at 1:21 PM

The camera is not an OxComponent so AFAIK you can't add children to it, or add it as a child to other components.  The PhysicsDemo constantly updates the camera position to be the position of the last ball, so I expect Bryan would have just linked them together if there was a way.

Already done the basics for my follow cam so the code is below.  This is pretty basic, and could use some extra features like making the camera smoothly auto center and such, but it should be a pretty good start.  Where you go from here will depend what you need for your specific case.  A coupla points to note about this one...

  • I'm not storing/restoring the translation in RotateCamera in this case.  This is because I'm setting the translation to an absolute value in MoveCamera rather than making incremental adjustments like the free look cam.
  • I've made the camera focus to a fixed point above the target object.  You can easily adjust this or remove it if needed.  Near the end of MoveCamera.
  • I've also made the camera sit a fixed distance behind the target object (i.e. rotate around the target at a fixed radius).  That's right at the end of MoveCamera.  You can also uncomment that other block of code there to make up/down on the left stick adjust the radius.
  • The right stick will make the camera rotate around the target, but the camera will always point at the target (or to be more exact, the focus point).

Initialize the camera controller with something like this (where target is an object in the scene which derives from SceneComponent.)

 

FollowCameraController followCamera = new FollowCameraController(engine, LevelDomainName, true)
{
     Parent = engine.Root,
     Target = target
}

 

using Microsoft.Xna.Framework;
using Ox.Engine;
using Ox.Engine.Component;
using Ox.Scene.Component;

namespace Wheely.Component
{
    class FollowCameraController : UpdateableComponent
    {
        private OxEngine _engine;
        private SceneComponent _target;

        private float _moveSpeed = 1f;
        private float _turnSpeed = 1f;

        private bool _invertX;
        private bool _invertY;

        private Matrix _worldMatrix = Matrix.Identity;
        private float _radius = -15f;
        private float _height = 3f;

        public FollowCameraController(OxEngine engine, string domainName, bool ownedByDomain)
            : base(engine, domainName, ownedByDomain)
        {
            _engine = engine;

            // Angle the camera down a bit at the start
            _worldMatrix *= Matrix.CreateFromAxisAngle(_worldMatrix.Right, MathHelper.Pi * -0.05f);
        }

        public SceneComponent Target
        {
            get { return _target; }
            set { _target = value; }
        }

        public float MoveSpeed
        {
            get { return _moveSpeed; }
            set { _moveSpeed = value; }
        }

        public float TurnSpeed
        {
            get { return _turnSpeed; }
            set { _turnSpeed = value; }
        }

        public bool InvertX
        {
            get { return _invertX; }
            set { _invertX = value; }
        }

        public bool InvertY
        {
            get { return _invertY; }
            set { _invertY = value; }
        }

        protected override void UpdateHook(GameTime gameTime)
        {
            // Apply rotation and movement based on joystick controls
            RotateCamera(gameTime.ElapsedGameTime.Milliseconds);
            MoveCamera(gameTime.ElapsedGameTime.Milliseconds);

            // Set the view matrix to be the inverse of the world matrix
            Matrix viewMatrix = Matrix.Invert(_worldMatrix);
            _engine.Camera.SetViewByMatrix(ref viewMatrix);
        }

        private void RotateCamera(double elapsedGameTime)
        {
            // Turn speed is measured in 10th's of a degree
            // i.e. a turnSpeed of 1 will turn a tenth of a degree every millisecond
            float oneTenthDegree = MathHelper.Pi * 0.0018f;
            
            // Turn left/right
            float xAngleAdjust = _engine.GamePadState.ThumbSticks.Right.X * (_turnSpeed * oneTenthDegree) * (float)elapsedGameTime;
            _worldMatrix *= Matrix.CreateFromAxisAngle(Vector3.Up, _invertX ? xAngleAdjust : -xAngleAdjust);

            // Turn up/down
            float yAngleAdjust = _engine.GamePadState.ThumbSticks.Right.Y * (_turnSpeed * oneTenthDegree) * (float)elapsedGameTime;
            _worldMatrix *= Matrix.CreateFromAxisAngle(_worldMatrix.Right, _invertY ? yAngleAdjust : -yAngleAdjust);
        }

        private void MoveCamera(double elapsedGameTime)
        {
            // Update the camera position based on the target position
            if (_target != null)
                _worldMatrix.Translation = _target.PositionWorld;

            //// Move in/out
            //float inOutAdjust = _engine.GamePadState.ThumbSticks.Left.Y * (_moveSpeed * 0.1f) * (float)elapsedGameTime;
            //_radius += inOutAdjust;
            //_worldMatrix *= Matrix.CreateTranslation(_worldMatrix.Forward * _radius);

            // Move the focus point up from the target
 _worldMatrix *= Matrix.CreateTranslation(Vector3.Up * _height); // Move the camera back from the target _worldMatrix *= Matrix.CreateTranslation(_worldMatrix.Forward * _radius); } } }

 

 

Mar 10, 2010 at 9:29 AM

I've just discovered a bug in both of these controllers.  If you rotate the right stick in either direction it becomes apparent that the camera is twisting sideways, but it should be staying upright.  At this point I have no idea what's causing it.

Mar 10, 2010 at 4:23 PM
Edited Mar 10, 2010 at 10:41 PM

After reading this now that I am more awake, I realized it has nothing to do with your issue... I need to not post help when I am 1/2 asleep.  I will try and find the tutorial bit and place it here, but what Bubzy said below it really what I was shooting for anyway.

Editor
Mar 10, 2010 at 9:50 PM

dont know if this helps but when i had problems with the camera "twisting" as it were. it was because I had applied the matrix.createrotationX and createrotationY in the wrong order. swapping them around solved this. hope this helps :D

Mar 11, 2010 at 8:12 AM

Didn't help in this case unfortunately.  I suspect the difference is that with your method you're creating a new matrix each time, but mine is constantly modifying the same matrix.  I'm really struggling to find anything on the net that would explain it, but I'm beginning to think that its just a side effect of this approach.  Probably why most people store vectors and create the matrix each time with something like CreateLookAt.  So I may have to abandon this method, which is a bummer cause I really do like how it lays out in code and the fact that I only need to store one matrix.  It's not critical to what I'm doing atm anyway so I think I'll just sit on it for now and see if I have a brainwave or come across something that explains it.  I may apply these controls to a model at some point to make it easier to visualize what's going on.

Before I sign off, I should explain the problem a bit more clearly because "twisting" is really not the best way to say it.  I was a bit asleep when I posted that one too :)  So a more correct way to say it would be...

Left/right rotates the camera around the Up axis (Yaw).  Up/Down rotates the camera around the Right axis (Pitch).  The final axis is Forward (Roll) which should remain at an angle of zero, but it doesn't.  So I think the problem is different amounts of yaw and pitch are in fact generating a certain amount of roll.  If you return to the starting point with a different combination of yaw and pitch, some roll could be left over.  Maybe there's a way to just reset the roll to zero to compensate, but I can't find anyway to do that directly to a matrix.

 

Mar 11, 2010 at 8:44 AM
Edited Mar 11, 2010 at 9:03 AM

I saw something on this awhile back, and I really wish I could remember where it was, but it has to do with apply Yaw to a different axis or something.  It only happens when you want roll to remain at Zero.  I'll keep looking and see what I can come up with.

If you want to test my theory turn off the part that adjusts Pitch and just shake the mouse back and forth -- I think you will see it still turning rolling you models.  It's been a few years since I last worked with anything 3D so I may be way off.

 

Mar 11, 2010 at 1:18 PM

Kudos to Steve!  The owner of the blog that this code was born from.  I posted a comment on his site and he responded with a solution in no time.  The key is in how the left/right rotation is applied.  Instead of rotating around the camera up vector, it should be rotated around the world up vector.  That effectively stops the rotations from mixing together and producing the unwanted roll.  This works in both the freelook and follow cams.  I've edited the code above and applied the fix.  Simply replace _worldMatrix.Up with Vector3.Up.

On a side note, when I was looking for info about this earlier I also saw some comments about floating point errors that can creep in and cause the matrix to skew (become non-orthogonal) when constantly modifying a matrix like this.  Apparently the solution is to normalize the matrix on each update (or just every once in a while) to remove the inaccuracies.  I haven't seen this effect yet but it may appear after running the game for some time.  May need to look into that more later.  Couldn't find any clear explanation on how to actually perform the normalization with a quick search.

Mar 13, 2010 at 12:55 AM

I think the normalize command you are looking for is Vector3.Normalize(yourVector3) --  it basicly sets everything to a total (sum) of 1.  This should probably be called each time before you call all of you camera changes or after you call all the camera changes.

Mar 15, 2010 at 8:13 AM

Need to normalize a matrix, not a vector.  I'll refer back to Steve's matrix tutorial again to help explain.  Have a look at the first image on that page and the text in the couple of paragraphs below it.  Particularly this comment...

"When we use a matrix to represent an orientation or rotation, we always want these three vectors to be 90 degrees to each other. They will not always be aligned with the world axis like they are in this graphic, but they must always be 90 degrees to each other."

When we constantly adjust pieces of the matrix over and over again, floating point errors could build up (in theory) that cause those 90 degree angles to not be 90 degrees anymore.  So to normalize a matrix we aren't just trying to adjust one part of the rotation matrix.  We would have to probably adjust two of the axis to force them to be 90 degrees with the other again.  If you wanna see a good example of what can happen when those angles aren't square in relation to each other (i.e. they are not orthogonal) try putting something like _worldMatrix.Forward = Vector3.Forward; at the bottom of the RotateCamera function in one of my classes above and move the camera around a bit.  Probably not wanted in most cases, but can also produce some very interesting effects.

Mar 18, 2010 at 4:46 AM

Hello everyone. Sorry if I am posting in the wrong thread, but the following line of code:

_engine.Camera.SetViewByMatrix(ref viewMatrix);

Gives me the following error:

'Ox.Engine.Camera.BaseCamera' does not contain a definition for 'SetViewByMatrix' and no extension method 'SetViewByMatrix' accepting a first argument of type 'Ox.Engine.Camera.BaseCamera' could be found (are you missing a using directive or an assembly reference?)

I am sorry if it's a stupid question, but could someone tell me what I am doing wrong? Thank you.

Mar 18, 2010 at 7:41 AM

Bryan made a few changes to the camera functions in rev 403 of Ox.  If you are using the 2.2.2.0 installer only the first section of code in this thread will work.  To use the 2nd or 3rd chunks of code you will need to get the source for rev 403 or later and reference that from your project.  I was linking to rev 404 when I wrote those (and still am).

Mar 18, 2010 at 7:59 AM

Thank you for your fast reply.

I am indeed using the version of the installer and understand the error now.

Apr 12, 2010 at 2:44 AM

Hello all. I got a (simple) question.

If I am correctly, the camera will follow an object (SceneComponent), but how can I move an object?

I got the following code working:

SceneComponent comp = Engine.GetComponent<SceneComponent>("Self");

Vector3 pos = comp.Position;
pos.Z += 0.5f;

comp.Position = pos;

Which moves the object and the camera will follow.

But how can I rotate an object? For example, looking to the left while staying on the same position?

Editor
Apr 13, 2010 at 6:46 AM

you need to set the cameras orientation.

Matrix rotC = Matrix.CreateRotationY(90);

Engine.Camera.Orientation = rotC;

 

or something similar

Apr 13, 2010 at 7:12 AM

Thank you for your answer.

I'm still a bit confused on how to set the camera rotation. I compiled the references in latest SVN revision (406) but if I am correctly there's no such property "Orientation".

Am I missing something or doing something wrong? Sorry for all the questions, i'm new to XNA and the Ox Game Engine.

Editor
Apr 14, 2010 at 6:48 AM

thats because it no longer exists as a property in the camera code......

not quite sure what bryan is doing with the project at the moment but ive had a month off coding and find that all my old projects are now unusable with the latest SVN,

you can download the EXE from this site for some stable functionality until its fixed.  sorry for my previous post but i promise you, it works with the .exe download.

bubzy

Apr 14, 2010 at 7:12 AM
Edited Apr 14, 2010 at 7:12 AM

Thank you for your reply.

It was confusing me but I understand the problem now. I have one last question tho.

If i'm correct the class will not work with any previous version. So when I download the stable release (the exe you we're talking about?) and us that I will get the error:

'Ox.Engine.Camera.BaseCamera' does not contain a definition for 'SetViewByMatrix' and no extension method 'SetViewByMatrix' accepting a first argument of type 'Ox.Engine.Camera.BaseCamera' could be found (are you missing a using directive or an assembly reference?)

And i'm back where I started?

Editor
Apr 14, 2010 at 7:36 AM

WAIIIIIT :D

found out how to rotate. seems a little digging was in order.

try this.

im using game pad for controls so i use this code (its only a value input so you can change it to whatever)

// in definitions
float yRot;
matrix yRotMatrix;


// in update
yRot += engine.GamePadState.ThumbSticks.Right.X;
yRotMatrix = Matrix.CreateRotationY(yRot);;

engine.Camera.SetViewByMatrix(ref yRotMatrix);

Try that and let me know what happens :) 
Apr 14, 2010 at 8:22 AM

This explanation of this change you guys are stuck on is spread throughout this thread, but to clarify...

In rev 402 and earlier (this includes the exe installer) you use the Orientation property.  This property is a world matrix so you can take a result from CreateRotationY etc and assign it directly (as you were doing in your original example that I started all this camera code from, bubzy).

In rev 403 and later the Orientation property is gone.  Now you should use SetViewByLookTarget or SetViewByLookNormal or SetViewByMatrix.  If you use SetViewByMatrix be aware that functions like CreateRotationY create a world matrix, not a view matrix.  A view matrix is the inverse of the world matrix so in the code in the last post you really should invert the matrix like this before you apply it to the view...

yRotMatrix = Matrix.CreateRotationY(yRot);
viewMatrix = Matrix.Invert(yRotMatrix)
engine.Camera.SetViewByMatrix(ref viewMatrix);

On the other hand you could also use Matrix.CreateLookAt and assign that directly with SetViewByMatrix, because CreateLookAt does create a view matrix.  The main point to take away here is that when you're building matrices check the help and confirm what type of matrix is actually returned from the function you're using.  Keep in mind that a matrix is just somewhere to store a bunch of numbers in a specific structure.  The effect that matrix actually has depends on what you apply it to.

Of course I'm still a bit of a newbie with this stuff too so I can't guarantee all this is correct, but I'm pretty confident it is.

Apr 15, 2010 at 6:25 AM
Works like a charm. Thank you!
Apr 22, 2010 at 4:25 AM

How can I make it so that the camera stays always behind the target? I'm not that good when it comes to math in 3D space but I think that both the camera and target should have the same orientation (correct me if i'm wrong).

The RotateCamera method has the follow code:

// Turn up/down
float yAngleAdjust = _engine.GamePadState.ThumbSticks.Right.Y * (_turnSpeed * oneTenthDegree) * (float)elapsedGameTime;
_worldMatrix *= Matrix.CreateFromAxisAngle(_worldMatrix.Right, _invertY ? yAngleAdjust : -yAngleAdjust);

The adjustment is based on the input of the gamepad. How can I rotate the camera based on the rotation of the target?

I'm sorry if I am hijacking this thread with my question but I thought this might be the right please.

Thanks in advance.

Apr 24, 2010 at 12:47 PM

WARNING! ANNOYING RANT FOLLOWS!

<Annoying rant Type="tired" Mood="Grumpy" Event="FrustratedTrigger">
I too am blatantly hi-jacking this thread. I'm going to say it: GoshDarn it's hard to mess with the camera.

I've only just got back into playing with the engine but I really really really think the learning curve for messing with the camera is steep.

I just end up with "Meh, I can't do that, gah!" all the time.
Yes, I understand that is my lack of understanding of the architechture of the engine (again :( ), but I would dearly love to be able to just instance a new chase-cam (sprung maybe?) and to "Magically activate" it as the current cam.

Heck, I will revist this thread and laugh in a few weeks. But after much messing around, re-reading of docs, and following of threads, I still find attaching a (useful) camera to my Player1 a mega-chore.

</Annoying rant>

Hmm, When I do eventually cobble something useful together again (remember, I already did all this once before), I'm going to post it somewhere. Meh, etc. :)

An, NO, I'm not doing the oft-heard moaning about docs, I just want a selection of handy cameras to attach.

<sarcasm>
I don't want much? right?

</sarcarsm>
Oh my! did I type that out loud? ah well.

Editor
Apr 24, 2010 at 9:38 PM
Edited Apr 24, 2010 at 9:42 PM
Maybe this will help a little. if it doesn't please let me know what the problem is :)
 
Matrix RotMatrix;
float xLook, yLook;
 private void rotateCamera()
        {
            Vector3 camPos = RotMatrix.Translation;
            xLook = engine.GamePadState.ThumbSticks.Right.Y * 0.1f;
            yLook = engine.GamePadState.ThumbSticks.Right.X * 0.1f;
            MathHelper.Clamp(xLook, 0, 2);
            RotMatrix *= Matrix.CreateFromAxisAngle(Vector3.Up, -yLook);
            RotMatrix *= Matrix.CreateFromAxisAngle(RotMatrix.Right, -xLook);
            RotMatrix.Translation = camPos;
        }
        
        private void moveCamera()
        {
            float sideSpeed = engine.GamePadState.ThumbSticks.Left.X * moveSpeed;
            float forwardSpeed = engine.GamePadState.ThumbSticks.Left.Y * moveSpeed;
            RotMatrix *= Matrix.CreateTranslation(RotMatrix.Right * sideSpeed);
            RotMatrix *= Matrix.CreateTranslation(RotMatrix.Forward * forwardSpeed);
                     }
   protected override void Update(GameTime gameTime)
        {
            rotateCamera();
            moveCamera();
             Matrix viewMatrix = Matrix.Invert(RotMatrix);
            engine.Camera.SetTransformByLookForward(RotMatrix.Translation,RotMatrix.Up,RotMatrix.Forward);
            base.Update(gameTime);
        }
Some code taken from kermitt's hard work.
Thanks
Bubzy.
Apr 24, 2010 at 11:26 PM
Wow, I'm such a misery when I just wake up.

Many thanks for this buzby. It will undoubtedly be a great help.

[Note to self] Stop being such a misery.

:)

Thanks Si.
Apr 25, 2010 at 4:21 AM

Don't sweat it Simon, I think we've all been where you are.  I know I definitely have been.  What made the difference for me was just reading a lot of theory about how translations, rotations and curves could be applied and finding ways to deal with things one step at a time instead of trying to jump right to the answer.  When you understand how to combine matrices and Vector3's together, it doesn't matter so much what engine you're using.  Here's a bunch of random links I've used along the way that may help you.  (Note the links down the right hand side on the first page listed below.  There's all sorts of handy stuff on that site.)

http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/Rotation_-_translation.php

http://www.xnawiki.com/index.php?title=Vector_Math

http://blogs.msdn.com/shawnhar/archive/2007/05/03/transitions-part-one-the-importance-of-curves.aspx

http://stevehazen.wordpress.com/2010/02/15/matrix-basics-how-to-step-away-from-storing-an-orientation-as-3-angles/

 

As for creating springy movement in the camera, I was looking for the answer to that myself recently too.  Here's a link to my post on the XNA forums and the sample that had the answer in it.

http://forums.xna.com/forums/p/50151/302568.aspx#302568

http://creators.xna.com/en-US/sample/chasecamera

 

BTW... I've also used engines that try to give you pre-canned functions like you suggested, and in the end I really don't think that works too well.  I think the prob is that if you try to supply someone with a component that handles many situations it ends up not handling any of them very well, and also can become too bloated to be of any real use to anyone, (jack of all trades, master of none) so I understand why Brian has kept this engine at the low level it is.  Quite often you just end up fighting the thing trying to get it to work the way you want.  In most cases things really need to be built for the specific purpose u need.  You could still argue that it would be good to have some simple pre-built cameras available that work with Ox, but they would have to be thought of as a starting point, rather than something that could be just used as is (e.g. my 2 camera controllers that appear earlier in this thread).

Another suggestion I have is to try and visualize what is happening.  First visualize it in your mind, but if things don't seem to be reacting the way you expect then take the next step and visualize it on screen.  I've made numerous 'visualizer' classes that are based on the BoundingBoxVisualizerSurface to display lines and boxes on screen when I wasn't getting the result I wanted, and although it takes a little longer to write that extra code it can really help to actually see a point on screen rather than just looking at numbers in debug.

Well anyway, I'm beginning to ramble a bit now.  Just take it one step at a time, don't give up, and one day a light will turn on and you'll wonder why you once struggled with it so much.  Like that bit at the end of the Matrix when Neo can suddenly see what the Matrix is on the inside, rather than just how it's presented on the outside. :)  Nothing is what it really appears to be in 3d graphics.  It's all just smoke and mirrors.

Coordinator
Apr 25, 2010 at 10:14 AM
Edited Apr 25, 2010 at 10:15 AM
Kermitt wrote:

BTW... I've also used engines that try to give you pre-canned functions like you suggested, and in the end I really don't think that works too well.  I think the prob is that if you try to supply someone with a component that handles many situations it ends up not handling any of them very well, and also can become too bloated to be of any real use to anyone, (jack of all trades, master of none) so I understand why Brian has kept this engine at the low level it is.  Quite often you just end up fighting the thing trying to get it to work the way you want.  In most cases things really need to be built for the specific purpose u need.  You could still argue that it would be good to have some simple pre-built cameras available that work with Ox, but they would have to be thought of as a starting point, rather than something that could be just used as is (e.g. my 2 camera controllers that appear earlier in this thread).

ya, that's the reason why I tried to expose the view matrix directly is to give you guys full flexibility to do it your way. unfortunately, it was only long after when I realized that the laws of mathematics prevented it from getting along with other parts of the engine. my experience with other engines reflects Kermitts completely - the engines that do everything for you are never flexible enough to do what you want without severe and incredibly hairy modifications on your part.

so now I'm trying to come up with a way for you to define your own camera system without a lot of hassle. this is actually a really hard problem, so it may take a bit of time.

Apr 25, 2010 at 12:00 PM
Totally agree.

I was having a bit of a moan yesterday. I really must apologise.

Many thanks for all your sage, and kind, words.

Meh! who needs facebook!

:)