XNA Game Development Forums
2012/05/18 05:48:58 *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Search Calendar Login Register  
Pages: [1] 2 3
  Print  
Author Topic: Tutorial 12 :: Adding in Advanced Camera Functionality  (Read 11100 times)
mikeschuld
Administrator
Sr. Member
*****
Offline Offline

Posts: 389


View Profile WWW
« on: 2007/02/10 15:30:19 »

Smiley
Logged
Nemo Krad
Global Moderator
Hero Member
*****
Offline Offline

Posts: 512


I have seen the fnords


View Profile WWW
« Reply #1 on: 2007/02/10 16:04:18 »

AAAHHGGGH!

It's past my bed time, I will have to do this one tomorrow night. Mike, you really need to start working on GMT  Grin

Thanks for this, can't wait to have a play with it.  Cheesy
Logged
Droxx
Newbie
*
Offline Offline

Posts: 6


View Profile
« Reply #2 on: 2007/02/10 17:49:02 »

Woot...thanks Mike!
Logged
Chr0n1x
Global Moderator
Sr. Member
*****
Offline Offline

Posts: 307


View Profile WWW
« Reply #3 on: 2007/02/11 03:10:25 »

Smiley
SLERP... I now have a sudden urge to purchase a certain forzen drink. Wink
Nice one Mike, thanks for the Maths. Smiley
Logged

mikeschuld
Administrator
Sr. Member
*****
Offline Offline

Posts: 389


View Profile WWW
« Reply #4 on: 2007/02/11 11:47:04 »

Luckily, that actual SLERP math is built in. I have gone over it in my grad course on graphics, but I didn't want to have to fit an explanation in the tut as there are actually 6 ways of doing it (some of which are better for computer stuff as they are much faster).
Logged
stuntpope
Newbie
*
Offline Offline

Posts: 4


View Profile
« Reply #5 on: 2007/02/12 05:06:56 »

Mike,

I just had a look at your SLERP code and I think you need to add some code to update the target position when you do a rotate SLERP in the same way that you are updating the position when doing a revolve SLERP. That's assuming that the desired behaviour is to always revolve around the centre of view.

One way is to remove the if statements before calling SlerpPosition then change the SlerpPosition code to.

private void SlerpPosition()
        {
            Vector3 normal = -1 * Vector3.Transform(Vector3.Forward, Matrix.CreateFromQuaternion(myRotation));
            normal.Normalize();

            if (slerpType == SlerpType.Revolve)
            {
                myPosition = normal * slerpDistance + myTarget;
            }
            else if (slerpType == SlerpType.Rotate)
            {
                myTarget = - normal * slerpDistance + myPosition;
            }
        }

Also in UpdateSlerp you should move the line "slerpType = SlerpType.None;" to after calling SlerpPosition, otherwise SlerpPosition will not do anything (or not get called the way you had it).

By the way, thanks for the great site.
Logged
mikeschuld
Administrator
Sr. Member
*****
Offline Offline

Posts: 389


View Profile WWW
« Reply #6 on: 2007/02/12 15:50:33 »

Rotate SLERP is supposed to involve no movement at all. It is simply a rotation of the camera. I defined it that way for a reason Wink That is why the lookat function uses Rotate SLERP, because the camera will simply TURN towards the position in question and not move around to it.
Logged
stuntpope
Newbie
*
Offline Offline

Posts: 4


View Profile
« Reply #7 on: 2007/02/13 00:10:16 »

Yes, I understand that. But surely you want your target location to move. Think about what will happen if you do a rotate slerp followed by a revolve of any sort. Where are you now revolving around?

I just noticed that in the above code "myTarget" should read "myRevolveTarget". Perhaps that will be clearer.

I also just noticed that you aren't moving the target position in your normal rotate function either. Perhaps this is your intended functionality but it's a little unusual. I have modified my camera code a bit from yours and have holding left and right mouse buttons while moving mapped to rotate and revolve respectively. This means I often do rotates followed by revolves and is probably why I noticed this behaviour. I had fixed the original rotate function some time ago to allow this behaviour.

You certainly seem to have implemented the right behaviour in your lookat function.

My personal feeling is that if you rotate and then revolve you should be rotating around your centre of view, not the origin. I hope I have made myself a little clearer.

Of course if you had intended that revolves are always around some fixed point regardless of where the camera is looking then you can disregard what I've said.
Logged
Nemo Krad
Global Moderator
Hero Member
*****
Offline Offline

Posts: 512


I have seen the fnords


View Profile WWW
« Reply #8 on: 2007/02/13 01:43:12 »

Mike,

It's probably me not implementing the call correctly but, when I call the lookat function, my camera just constantly zooms away. I think this is because the myRevolveTarget- myPosition results in a new myPosition once myRevolveTarget is set.

I have set my camera functionality like this in my Demo code:
(CameraViewType.ThirdPerson is how I think you are implementign the camera movement, naturally the LookAt method does nothing with the other camera modes I have)
Code:
            switch (RCCameraManager.ActiveCamera.ViewType)
            {
                case CameraViewType.ThirdPerson:
                    RCCameraManager.ActiveCamera.GlobalRevolve(new Vector3(1, 0, 0), mouseMove.Y * 0.01f);
                    RCCameraManager.ActiveCamera.Revolve(new Vector3(0, 1, 0), mouseMove.X * 0.01f);
                    break;
                case CameraViewType.POV:
                    RCCameraManager.ActiveCamera.Rotate(new Vector3(1, 0, 0), mouseMove.Y * 0.01f);
                    RCCameraManager.ActiveCamera.Rotate(new Vector3(0, 1, 0), mouseMove.X * 0.01f);
                    break;
                default:
                    RCCameraManager.ActiveCamera.Revolve( new Vector3(1, 0, 0), mouseMove.Y * 0.01f);
                    RCCameraManager.ActiveCamera.Revolve( new Vector3(0, 1, 0), mouseMove.X * 0.01f);
                    break;
            }

            if (game.Input.Keys.Contains(Keys.D0))
                RCCameraManager.ActiveCamera.ViewType = CameraViewType.Floating;
            if (game.Input.Keys.Contains(Keys.D9))
                RCCameraManager.ActiveCamera.ViewType = CameraViewType.ThirdPerson;
            if (game.Input.Keys.Contains(Keys.D8))
                RCCameraManager.ActiveCamera.ViewType = CameraViewType.POV;

The LookAt cal is this:
Code:
        if (game.Input.Keys.Contains(Keys.L))           
                RCCameraManager.ActiveCamera.LookAt(new Vector3(0, 0, -10), 0.25f);


Should I be setting myRevolveTarget to Vector3.Zero once the call is made?

What am I missing; I don't mean in the code, but my understanding of what should happen when LookAt is called. I am assuming that I give my target position in the first parameter and the function should move the camera to the position for me.

Thanks.
Logged
mikeschuld
Administrator
Sr. Member
*****
Offline Offline

Posts: 389


View Profile WWW
« Reply #9 on: 2007/02/13 11:14:41 »

stuntpope: the rotate doesnt go about the origin, it rotate the camera relative to its own current orientation. This is a concept that a lot of people have been having a hard time grapsing but with Quaternions, it is the correct behavior as that is what they are made to do. When I have had more time to play with it all and do a lot of rotating and revolving in succession, if there is a problem, I will address it. However, as this is simply a teaching tool, I am not going to spend undue stress worrying about it.

Nemo: First of all you should be global rotating around X in the third person more (for the type of camera you are used to Wink ) Having this type of mix might mess up the slerp calls as stuntpope has mentioned. I'll take a look at it later in the week.
« Last Edit: 2007/02/13 17:27:26 by mikeschuld » Logged
Nemo Krad
Global Moderator
Hero Member
*****
Offline Offline

Posts: 512


I have seen the fnords


View Profile WWW
« Reply #10 on: 2007/02/13 14:10:11 »

Mike,

Thanks, I will play with that.
Logged
Nemo Krad
Global Moderator
Hero Member
*****
Offline Offline

Posts: 512


I have seen the fnords


View Profile WWW
« Reply #11 on: 2007/02/13 15:46:05 »

Awesome, thanks Mike, I thought it was me being daft Smiley


Looking forward the next tut, what ever it is Smiley
Logged
rstackhouse
Newbie
*
Offline Offline

Posts: 3


View Profile
« Reply #12 on: 2007/02/25 20:24:55 »

I am having one heck of a time trying to figure out how to set up a third person camera that is always a set distance away from a moving object relative to the object.  The object I'm playing around with now is the skull mesh.  Imagine I am trying to look over its left shoulder no matter which way it rotates.  I believe what I need to do is find the offeset position of the camera relative to the skull and assign that value as the position of the camera.  Then I should make the camera "look" in the direction of the object.  Problem is, I haven't found a way to do that anywhere that uses a separate camera class with its own rotation.

I added a set method to the Camera.Position property, because I couldn't make Translate work the way I wanted it to.

I am in a real bind here.  Any help on this would be greatly appreciated.

Here's my code

Code:
//Program.cs

using HmEngine;
using HmEngine.HmObjects;
using HmEngine.HmShaders;
using HmEngine.HmCameras;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using HmEngine.HmOctrees;
using System;
using System.Collections.Generic;

namespace HmDemo
{
    class Program
    {
        static MyGame game = new MyGame();
        static HmModel target;
        static float speed;
        static float accel = .1f;
        static Vector3 thirdPersonOffset = new Vector3(10, 10, -10);
        static Vector3 delta;
        static Quaternion deltaRot;

        static string[] sky = {
@"Content/Textures/Skybox/top",
@"Content/Textures/Skybox/bottom",
@"Content/Textures/Skybox/left",
@"Content/Textures/Skybox/right",
@"Content/Textures/Skybox/front",
@"Content/Textures/Skybox/back"
};

        static HmSkybox skybox = new HmSkybox(sky);

        public static void Main()
        {
            game.IsMouseVisible = true;
            game.Initialized += new MyGame.InitializeMethod(AssignTarget);
            game.Initialized += new MyGame.InitializeMethod(InitializeCamera);
            game.Input.OnUpdate += new UpdateMethod(Update);

            SetupScene();
            game.Run();
        }

        public static void InitializeCamera()
        {
            Console.Out.WriteLine("In InitializeCamera");
            HmCameraManager.ActiveCamera.Translate(thirdPersonOffset);
            HmCameraManager.ActiveCamera.LookAt(target.Position - HmCameraManager.ActiveCamera.Position,0);
        }

        public static void AssignTarget()
        {
            HmCameraManager.ActiveCamera.RevolveTarget = target.Position;
        }

        private static void SetupScene()
        {   
            MyShader shader = new MyShader(@"Content/Shaders/BasicShader");
            HmShaderManager.AddShader(shader, "BS");

            //MyShader shader1 = new MyShader(@"Content/Shaders/OURHLSLfile");
            //HmShaderManager.AddShader(shader1, "HLSL");

            MyShader shader1 = new MyShader(@"Content/Shaders/TransformTexture");
            HmShaderManager.AddShader(shader1, "TT");

            HmOctreeManager.DrawOctnodes = true;
           
            target = new HmModel(@"Content/Models/skullocc");
            target.SetShader("BS");

            target.Position = new Vector3(0, 0, 0);

            game.Scene.AddObject(target);
            HmOctreeManager.OctRoot.AddObject(target);

            skybox.SetShader("TT");
            game.Scene.AddObject(skybox);
            HmOctreeManager.OctRoot.AddObject(skybox);
        }

        public static void UpdateCamera()
        {
            //Toggle FullScreen
            if (game.Input.Keys.Contains(Keys.F))
            {
                game.Graphics.ToggleFullScreen();
            }

            Vector2 mouseMove = game.Input.MouseMoved;
            ButtonList MouseButtons = game.Input.MouseButtons;

            //Zoom In
            if (MouseButtons[0] == ButtonState.Pressed)
            {
                HmCameraManager.ActiveCamera.Translate(new Vector3(0, 0, -0.3f));
            }

            //Zoom Out
            if (MouseButtons[2] == ButtonState.Pressed)
            {
                HmCameraManager.ActiveCamera.Translate(new Vector3(0, 0, 0.3f));
            }

            if (speed > 0)
            {
               HmCameraManager.ActiveCamera.Position += delta;
            }
        }

        //Borrowed most of this from Riemer's FlightSim tut
        public static void UpdatePosition()
        {
            float yRot = 0;
            KeyboardState keys = Keyboard.GetState();
            if (keys.IsKeyDown(Keys.Right))
            {
                yRot = .1f * speed;
            }
            if (keys.IsKeyDown(Keys.Left))
            {
                yRot = -.1f * speed;
            }

            float xRot = 0;
            if (keys.IsKeyDown(Keys.Down))
            {
                xRot = .1f * speed;
            }
            if (keys.IsKeyDown(Keys.Up))
            {
                xRot = -.1f * speed;
            }
            deltaRot = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), yRot) * Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), xRot);
            target.Rotation *= deltaRot;
   
            if (game.Input.Keys.Contains(Keys.Space))
            {
                if (speed < 10)
                    speed += accel;
            }
            else if (speed > 0) speed -= accel;

            if (speed < 0) speed = 0;

            delta = new Vector3(0, 0, 1);
           
            delta = Vector3.Transform(delta, Matrix.CreateFromQuaternion(target.Rotation));
            delta.Normalize();

            delta *= speed;

            target.Position += delta;
        }

        public static void Update()
        {
            UpdatePosition();
            UpdateCamera();
        }
    }
}

//MyGame.cs

namespace HmDemo
{
    class MyGame : HmGame
    {
        public delegate void InitializeMethod();
        public event InitializeMethod Initialized;

        protected override void Initialize()
        {
            base.Initialize();
            Initialized();
        }

        protected override void Draw(Microsoft.Xna.Framework.GameTime gameTime)
        {
            myScene.SceneRoot.Draw(myGraphics.GraphicsDevice);
            base.Draw(gameTime);
        }
    }
}

Any help on this would be most appreciated

~Robert
Logged
Nemo Krad
Global Moderator
Hero Member
*****
Offline Offline

Posts: 512


I have seen the fnords


View Profile WWW
« Reply #13 on: 2007/02/26 07:42:57 »

Set the cameras position to that of the target object - the distance you want from the required plane and set the rotation of the camera to be the same as the object.....I think...
Logged
rstackhouse
Newbie
*
Offline Offline

Posts: 3


View Profile
« Reply #14 on: 2007/02/26 10:48:58 »

I believe what I need to do in the following order is:

1. Find the Position of the object in World Coordinates
2. Find the Location of the offset from the object relative to the rotation of the object in
world coordinates
3. Update the Camera's position.
4. Aim the camera at the object.
                 
The frustrating thing about it is that I can't seem to figure out how to do that.

I tried something similar to what Nemo suggested, but that didn't work the way I wanted.  It basically puts the camera behind the object (about where it is supposed to go I believe) looking about 180 the wrong direction:

//in HmCamera.cs
public Vector3 Position { get { return myPosition; } }
public Quaternion Rotation { get { return myRotation; } set { myRotation = value; Update(); } }

//in Program.cs
HmCameraManager.ActiveCamera.Position =
                    target.Position - Vector3.Transforim(thirdPersonOffset,
                    Matrix.CreateFromQuaternion(target.Rotation));
                HmCameraManager.ActiveCamera.Rotation = target.Rotation;

Any ideas on how to make the Camera look at the object.  I thought that's what HmCamera.LookAt() was supposed to do, but I can't get it to work for me.

Thanks,

~Robert
Logged
Pages: [1] 2 3
  Print  
 
Jump to:  

Related Topics
Subject Started by Replies Views Last post
Parenting Camera to an Object Hazy Mind XNA Engine Requests rstackhouse 4 3096 Last post 2007/03/14 06:13:57
by 5parrowhawk
Camera Issues Hazy Mind XNA Engine minich21 6 3044 Last post 2007/08/14 21:27:30
by mikeschuld
Tutorial 7...Is this functionality common? Is this only useful onyl in testing? Hazy Mind XNA Engine Robin Sarac 1 1423 Last post 2007/04/03 17:24:41
by Chr0n1x
Camera Issues Hazy Mind XNA Engine Trano 3 2807 Last post 2008/09/17 08:27:25
by mikeschuld
Camera Tracking Hazy Mind XNA Engine muchrejoicing 4 2005 Last post 2007/05/29 19:50:23
by daenris
Camera problem Hazy Mind XNA Engine Montynis 2 1685 Last post 2007/08/02 09:54:14
by Montynis
extending the camera classes/cameramanager Hazy Mind XNA Engine Mikeske 7 2076 Last post 2009/12/16 01:46:28
by Mikeske
Adding in a Screen Manager Hazy Mind XNA Engine mimminito 1 1683 Last post 2010/02/20 23:59:09
by Jeff Lamoureux
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.678 seconds with 20 queries.