Tuesday, May 15, 2007

Quaternion Camera in XNA

XNA unfortunately does not provide a QuaternionCamera class in it's Framework. Nowhere on the Internet could I find a camera class that provides six degrees of freedom without requiring additional coding from the reader. (It may be out there somewhere and my google-fu was weak). I even have a couple books that outline quaternion cameras but stop short of implementing them fully. In the process of attacking this problem in my book, I've made a few camera classes. I'm posting the simplest class here - good for beginners. The final camera class in the book will be more complicated. This class should provide a good jumping-off point for anybody interested, or a simple helper class for those who just want a camera without hassles. In the camera, GetViewMatrix and CreateYawPitchRoll are where the money is. One reason they are statics is to make it easy to test these functions - they don't have to be. Another reason is that I hope it makes them stand out to people familiarizing themselves with the class.

        public static Matrix GetViewMatrix(ref Vector3 position, ref Vector3 target,
            ref Vector3 up, float yaw, float pitch, float roll)
        {
            // The right vector can be inferred
            Vector3 forward = target - position;
            Vector3 right = Vector3.Cross(forward, up);

            // This quaternion is the total of all the
            // specified rotations
            Quaternion yawpitch = CreateFromYawPitchRoll(up, yaw,
                right, pitch, forward, roll);

            // Calculate the new target position, and the
            // new up vector by transforming the quaternion
            target = position + Vector3.Transform(forward, yawpitch);
            up = Vector3.Transform(up, yawpitch);

            return Matrix.CreateLookAt(position, target, up);
        }
        public static Quaternion CreateFromYawPitchRoll(Vector3 up, float yaw, Vector3 right,
float pitch, Vector3 forward, float roll)
        {
            // Create a quaternion for each rotation, and multiply them
            // together.  We normalize them to avoid using the conjugate
            Quaternion qyaw = Quaternion.CreateFromAxisAngle(up, (float)yaw);
            qyaw.Normalize();
            Quaternion qtilt = Quaternion.CreateFromAxisAngle(right, (float)pitch);
            qtilt.Normalize();
            Quaternion qroll = Quaternion.CreateFromAxisAngle(forward, (float)roll);
            qroll.Normalize();
            Quaternion yawpitch = qyaw * qtilt * qroll;
            yawpitch.Normalize();

            return yawpitch;
        }

GetViewMatrix shows you how to transform the target and up vectors using a quaternion. CreateFromYawPitchRoll combines three quaternions into a single quaternion defining all the camera rotations. (NOTE: The XNA version of this function uses the world axes as the axes of rotation. This version uses the camera axes supplied by the caller).

Enjoy! Update: Apparently blogger or my web server doesn't like .cs files. I've changed the link to a zip file that appears to work. SimpleQuaternionCamera.zip

6 Comments:

Anonymous Anonymous said...

Hi Scott, nice work however the download link above fails returning a server error. Hope this helps.

1:59 PM  
Anonymous Anonymous said...

mamma mia quanto sei brutto!

9:15 PM  
Anonymous Anonymous said...

Couldn't find a camera class that provides six degrees of freedom without requiring additional coding from the reader? Did you try this?

12:16 AM  
Anonymous <a href="http://search2.site.io/index.html">Viagra</a> said...

Glad to read articles like this. Thanks to author!

6:51 AM  
Anonymous <a href="http://courses.cvcc.vccs.edu/ENG112_GROSS/_Chat_Room/000008fd.htm">Anonimous</a> said...

Excellent website. Good work. Very useful. I will bookmark!

11:58 AM  
Blogger Sebastian said...

Yes! That's it! Mama I can Flyyy!!! :D.
Great job. I spend long hours to write correct camera moving/rotation by you resolve my problem in several minutes. Big Thx man :)

10:21 AM  

Post a Comment

<< Home