Moving Cameras and Objects


Moving Cameras and Objects

Two basic types of objects need to be defined as we enter the realm of 3D rendering: cameras and 3D objects. A camera should be thought of as the point of view to which rendering is oriented. Although we will always have at least one camera defined, we may also have several. Depending on the style of game, we could switch between a first person view where the camera is the viewpoint of an animated character or the unseen driver of a vehicle to that of a chase camera. We could also have several styles of third-person cameras that follow or orbit the player-controlled object. No matter how the camera is moved through the scene, it is the position, orientation, and definition of the camera that determines what gets rendered. The camera system for the game engine will be discussed in depth in Chapter 6.

Looking at Objects

The general term object encapsulates anything that is rendered as part of the 3D environment. This might be a single point that is part of a particle system, a two-dimensional billboard, or a multifaceted animated mesh. Regardless of the details about an object, it will always have certain basic characteristics. First and most important is that it has a name. We want to be able to reference objects by a name specified when the object is created. This makes it easier for the game software using the engine to specify the object by its assigned name .

The next characteristic is the object s position. This position could be relative to the world at large (world coordinated) or relative to another object. Our generic object will therefore have a three-dimensional position as well as a reference to a parent object. If the parent object reference is null , we will know that the position is in world coordinates.

The next characteristic will be the orientation of the object. The orientation is the rotation around each of the three axes. Although the single-point objects mentioned earlier will not require orientation, that is a special case. Again, the orientation is relative to the orientation of a parent object and will be against the world axis system if the parent is null . It is important to establish this hierarchy of position and orientation between objects. This allows a complicated object to be constructed whose component parts have some freedom of movement relative to a base object. A good example of this is an animated human figure. If the body is one unified object, it would be quite difficult to manipulate. If each section of a body that is separated from another part by a joint is a different object, it becomes simple to move portions of the body and have attached sections move properly. This is the basis for animated models.

The generic object class will also have a pair of flags that determine whether or not the object should be rendered. The first flag is for visibility. This flag does not determine if the object is in sight. It states whether we want the object to be seen. By setting this flag to false , we can make the object invisible. Often we will wish to create an object and hold it in reserve for later rendering. By setting the object state to invisible, we not only prevent it from being rendered, we also disable the movement, culling, and collision checks that are associated with objects. The other flag is the culled state of the object. This is the flag that determines that the object is within the camera s view and needs to be rendered. During the rendering phase, this flag is checked and, if set, the object is rendered. The flag is then cleared. During the culling phase the flag is set if the culling process finds that the object is in sight. I will get to the details of the culling process shortly.

Several methods are common to all objects, described in the following list. This is set up by inheriting from the interfaces that we saw earlier in the book.

  • All objects will have a Render method to draw themselves in the scene.

  • All objects will have a Cull method in order to determine if they should be rendered.

  • All objects will have a CollisionCheck method to determine if they have collided with another object.

Chapter 10 will deal with the reaction to collisions when we get into physics modeling.

Implementing Objects

With this basic concept of a generic object type, let s look at Listing 3 “1, which shows what this would look like in C#.

Listing 3.1: Object3D Declaration
start example
 using System;  using System.Collections;  using System.Diagnostics;  using System.Drawing;  using Microsoft.DirectX;  using Microsoft.DirectX.Direct3D;  namespace GameEngine  {     /// <summary>     /// Delegate used for specifying the update method for the object.     /// </summary>     public delegate void ObjectUpdate( Object3D Obj, float DeltaT );     /// <summary>     /// Summary description for Object 3D.     /// </summary>     abstract public class Object3D : IDisposable, IRenderable, ICullable,        ICollidable, IDynamic     {     #region Attributes        protected string     m_sName;        protected Vector3    m_vPosition;        protected Vector3    m_vVelocity;        protected Attitude   m_vOrientation;        protected bool        m_bVisible;        protected bool        m_bCulled;        protected bool        m_bHasMoved = false;        protected Object3D   m_Parent;        protected SortedList m_Children = new SortedList();        protected float      m_fRadius; // Bounding circle        protected float      m_fRange; // Distance from viewpoint        protected Matrix     m_Matrix;        protected ObjectUpdate m_UpdateMethod = null;        public Array List  m_Quads = new Array List ();        public string Name       { get { return m_sName; } }        public Vector3 Position { get { return m_vPosition; }           set { m_vPosition = value; m_bHasMoved = true;} }        public Vector3 Velocity { get { return m_vVelocity; } }           set { m_vVelocity = value; } }        public float VelocityX { get { return m_vVelocity.X; } }           set { m_vVelocity.X = value; m_bHasMoved = true;} }        public float VelocityY { get { return m_vVelocity.Y; } }           set { m_vVelocity.Y = value; m_bHasMoved = true;} }        public float VelocityZ { get { return m_vVelocity.Z; } }           set { m_vVelocity.Z = value; m_bHasMoved = true;} }        public Attitude Attitude { get { return m_vOrientation; } }           set { m_vOrientation = value; } }        public virtual float North      { get { return m_vPosition.Z; } }           set { m_vPosition.Z = value; m_bHasMoved = true;} }        public virtual float East       { get { return m_vPosition.X; } }           set { m_vPosition.X = value; m_bHasMoved = true;} }        public virtual float Height     { get { return m_vPosition.Y; } }           set { m_vPosition.Y = value; m_bHasMoved = true;} }        public virtual float Roll       { get { return m_vOrientation.Roll; }}           set { m_vOrientation.Roll =  value; } }        public virtual float Pitch      { get { return m_vOrientation.Pitch; } }           set { m_vOrientation. Pitch =  value; } }        public virtual float Heading { get { return m_vOrientation.Heading; } }           set { m_vOrientation. Heading = value; } }        public float Range { get { return m_fRange; } }           set { m_fRange = value; } }        public float Radius     { get { return m_fRadius; } }           set { m_fRadius = value; } }        public Matrix WorldMatrix    { get { return m_Matrix; } }     #endregion               public Object3D( string sName )        {           m_sName = sName;           m_bCulled = false;           m_bVisible = true;           m_Matrix = Matrix.Identity;        }                    public void SetUpdateMethod( ObjectUpdate method )        {           m_UpdateMethod = method;        }        public virtual bool InRect( Rectangle rect )        {           // Check to see if the object is within this rectangle,           return false;        }               public virtual bool Collide( Object3D Other ) { return false; }               public virtual void Render() { }               public virtual void Dispose()        {           Debug.WriteLine("Disposing of " + Name + " in Object3D");        }        public virtual void Render( Camera cam ){}        public virtual void Update( float DeltaT ){}        public virtual bool Culled { set { m_bCulled = value; } }        public virtual bool IsCulled { get { return m_bCulled; } }        public Vector3 CenterOfMass { get { return m_vPosition; } }        public float BoundingRadius { get { return m_fRadius; } }        public virtual bool CollideSphere ( Object3D other ){ return false; }        public virtual bool CollidePolygon ( Vector3 Point1, Vector3 Point2, }           Vector3 Point3 ){ return false; }               public void AddChild( Object3D child )        {           m_Children.Add(child.Name, child);           child.m_Parent = this;        }               public void RemoveChild( string name )        {           Object3D obj =               (Object3D)m_Children.GetByIndex(m_Children.IndexOfKey(name));           obj.m_Parent = null;           m_Children.Remove(name);        }               public Object3D GetChild( string name )        {           try           {              return (Object3D)m_Children.GetByIndex(m_Children.IndexOfKey(name));           }           catch           {              return null;           }        }     }  } 
end example
 

The use of the m_Parent and m_Children members allow for the creation of a hierarchy called a scene graph. Every object is positioned relative to its parent object and is visible only if the parent object is visible. Remember that objects without specified parents are world objects, and other methods will determine if they and their children are visible.

Now that we have established what objects and cameras are at a generic level, we are ready to talk about moving them. Some objects may never move. They are in the scene as part of the scenery to set the stage for the game. Even if we do not expect an object to move during the game, we should not eliminate the possibility from this aspect of the game engine. If the logic for the application tells the engine to move an object, we move the object. To support the movement of the object, we would also inherit from the IDynamic interface and add another method to the definition outlined previously, Update . This method is prototyped as follows :

 Public void Update( float dt ) { }; 

The argument to the method is the amount of time that has passed in seconds since the last update of the object s position. Given this time value, it is simple to convert a linear or rotational velocity into a change in position and orientation. It is important to complete all of the object movement prior to starting the rendering so that the scene appears fluid and realistic.




Introduction to 3D Game Engine Design Using DirectX 9 and C#
Introduction to 3D Game Engine Design Using DirectX 9 and C#
ISBN: 1590590813
EAN: 2147483647
Year: 2005
Pages: 98

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net