enablerbr's picture

How do i code a Camera Class that doesn't use GLU?

i've been looking around trying to find how to code a camera class. trouble is there doesn't seem to be a single soloution to this. i really want a camera class that not only doesn't use GLU but also allows me to parent a camera to another object if needed. any ideas where to look or code snippets would be welcomed.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
martinsm's picture

Why do you have need for glu to create camera class?

the Fiddler's picture

It is easy to create a camera that doesn't use GLU. The math API in OpenTK is a little ugly (working on it), but it gets the work done. Here is a quick and dirty implementation I cooked up for a project.

It works like this:

  • In your update function, you set the TargetPosition and TargetOrientation of the camera.
  • In your render function, you call camera.Update(e.Time).
  • Finally, you use GetModelviewMatrix and GetProjectionMatrix to retrieve the relevant matrices and send them to OpenGL - either via GL.UniformMatrix4 if you are using shaders, or via GL.LoadMatrix if you are using the fixed-function pipeline.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using OpenTK.Math;
 
using Graphics;
 
namespace OpenBCI.Maze
{
    public class Camera
    {
        #region Constructors
 
        public Camera()
            : this(new Vector3(), new Quaternion() { X = 0, Y = 1, Z = 0, W = 0 })
        { }
 
        public Camera(Vector3 position)
            : this(position, new Quaternion() { X = 0, Y = 1, Z = 0, W = 0 })
        { }
 
        public Camera(Vector3 position, Quaternion orientation)
        {
            TargetPosition = Position = position;
            TargetOrientation = Orientation = orientation;
 
            AspectRatio = 1.333f;
            FieldOfView = 60;
            ZNear = 1;
            ZFar = 64;
        }
 
        #endregion
 
        #region Public Members
 
        #region Properties
 
        public Vector3 Position { get; set; }
        public Quaternion Orientation { get; set; }
 
        public Vector3 TargetPosition { get; set; }
        public Quaternion TargetOrientation { get; set; }
 
        public Vector3 Forward { get { return Orientation.Apply(Vector3.UnitZ); } }
        public Vector3 Right { get { return Orientation.Apply(Vector3.UnitX); } }
        public Vector3 Up { get { return Orientation.Apply(Vector3.UnitY); } }
 
        public float AspectRatio { get; set; }
        public float FieldOfView { get; set; }
        public float ZNear { get; set; }
        public float ZFar { get; set; }
 
        #endregion
 
        #region Methods
 
        public void Update(double time)
        {
            if (time == 0)
                return;
 
            if (TargetOrientation != Orientation)
            {
                Orientation = Orientation.Lerp(TargetOrientation, (float)time);
            }
 
            if (TargetPosition != Position)
            {
                Position = Vector3.Lerp(Position, TargetPosition, (float)time);
            }
        }
 
        public void GetProjectionMatrix(out Matrix4 matrix)
        {
            matrix = Matrix4.Perspective((float)(FieldOfView * Math.PI / 180.0), AspectRatio, ZNear, ZFar);
        }
 
        public void GetModelviewProjectionMatrix(out Matrix4 result)
        {
            Matrix4 modelview;
            GetProjectionMatrix(out result);
            GetModelviewMatrix(out modelview);
            Matrix4.Mult(ref modelview, ref result, out result);
        }
 
        public void GetModelviewMatrix(out Matrix4 matrix)
        {
            var translation_matrix = Matrix4.Translation(-Position);
            var rotation_matrix = Matrix4.Rotate(Orientation);
            Matrix4.Mult(ref translation_matrix, ref rotation_matrix, out matrix);
        }
 
        #endregion
 
        #endregion
    }
}

Regarding your second question, you will need to create a scene graph: a tree-like structure that indicates the relationships between objects.

enablerbr's picture

thanks the Fiddler. i noticed there is no mention of a WorldMatrix. some of the other types of examples i've seen on the net have a worldmatrix. where would the worldmatrix fit in. sorry for the newbie question.

the Fiddler's picture

The world matrix takes you from model space to world space, i.e. it defines the location and orientation of an object in your world. You must then multiply with the view matrix to move from world space into view space (the view matrix defines the location and orientation of the camera in the world).

You can think of it like this: every object in your world has a "world" matrix. The inverse of the world matrix of your active camera is your "view" matrix. The modelview matrix is what you get by multiplying the world matrix of an object with the view matrix of the camera: it takes you directly from object space to view space.

In the above case, if you wish to render a box at (0, 0, 3) (in world coordinates), you simply need to multiply the result of Matrix4.Translation(0, 0, 3) (i.e. the world matrix) with the result of camera.GetModelviewMatrix() (i.e. the view matrix). The result is the modelview matrix for the box, which you can send to OpenGL via LoadMatrix or UniformMatrix4.

enablerbr's picture

ahh. i think i'll grab a copy of this book "Beginning OpenGL Game Programming, Second Edition " to help me along. it covers opengl 3.0. is there any other book that might be of help? i already have "3D Math Primer for Graphics and Game Developement".

the Fiddler's picture

"Beginning OpenGL Game Programming" is quite good. Between this and google, I think you are covered 100%.

The only OpenGL book I have is the official "red book" for version 1.4. It is quite old, but it is well-written and approachable. I still use it from time to time for legacy stuff, texture parameters and things like that, but the majority of the book covers things deprecated in OpenGL 3.0. (It is quite interesting: OpenGL 3 deprecates only about 200 functions out of 1800, but the resulting API is much, much cleaner.)

enablerbr's picture

i don't think the new red book is out yet. i'll keep an eye out for it. thanks.

rakkarage's picture

thanks for that camera code :) you mention inverse the camera view is the inverse of its individual matrix... i dont see where you do that... is that -Position? thanks

the Fiddler's picture

Yes. The thing to keep in mind is that moving the camera in one direction will cause everything to (apparently) move towards the other direction. This is intuitively correct: if camera.X increases by +1 unit, it is the same as if the camera stayed put and everything moved by -1 unit in the x-direction.

The net effect is that you'll have to watch the signs of your camera acceleration/velocity.

rakkarage's picture

Quaternion.Apply does not exist anymore?