R3DEngine
R3DEngine stands for (imaginatively) Rob's 3D Engine. It's all
part of my work towards my final year university project. By
putting what I've done so far here, I hope to give others some
ideas, and maybe receive some constructive criticism! The
documentation so far consists only of this page, but I plan to do
more complete documentation before too long.
The source *.h and *.cpp files are in zipped into a 25K file.
You must first agree to the terms and
conditions.
Using the Source
First put all the files into some directory. To access all the
R3D classes, just include the file "R3DEngine.h". This
contains #includes for all the other files. Also, you will need
to add all the files to your project so that they are compiled.
To get an idea of how the engine works, have a look at this example. The example renders a
cylinder and some other shapes, and then rotates them all over
the place before reporting the number of frames per second. A
more complete example is the Traffic3D
workspace.
The R3DEngine Classes
The R3DEngine provides a number of classes that work together
to generate a 3D scene.
R3DfxHardware
This class encapsulates some of the functionality of the 3Dfx
card. It is used mainly to initialise and shutdown the card. It's
member functions include:
- InitHardware() - This activates the
card, returning 0 on failure. It also sets up a small set
of global pointers. R3DHW can be used to access the
R3DfxHardware object used in the InitHardware() call
(obviously there is no point having more than one
R3DfxHardware object). R3DCALC provides nice and fast Sin
and Cosine functions. R3DCAM points to the current
camera. A default camera is provided, but more can be
created. Point R3DCAM to the one which you want to use to
render the next frame.
- ActivateTextures() - Always call this
after InitHardware to start up the textures. The original
idea was to have a choice of using textures or not, but
so far I have not tested without textures.
- BufferClear() - Clears the back buffer,
ready to draw the next frame.
- BufferSwap() - Draws the next frame by
swapping the back buffer with the front.
- CloseHardware() - Switches off the card.
Do this last.
Other functions are present, but most shouldn't really be in
the public interface of the class. In particular, the texture
manipulation functions should be avoided as the R3DTexture class
handles all this. At some point I will make these functions
private and have friend functions in R3DTexture.
R3DVector
This class is used everywhere. It's my implementation of a
vector, and includes various operators like += and -=. Not all of
the operators are fully functional yet, particularly ^ which was
supposed to return the angle between two vectors but doesn't
work. The data members m_vx, m_vy, and m_vz can all be accessed
publicly. Member functions include:
- R3DVector(float x, float y, float z) -
This constructor allows you to set the starting position
of the vector. You can also use something like
R3DVector(1.f, 2.f, 3.f) as a parameter to a function
that requires a vector. The default constructor
initialises the vector to (0, 0, 0).
- RotateX(R3DVector origin, float theta) -
Rotates the vector about the X axis. Origin is the centre
point about which to rotate, and theta is the angle in
degrees. RotateY and RotateZ are also provided, and are
used in all other rotate-able objects too.
R3DVertex
This class encapsulates Glide's GrVertex structure. You
shouldn't have to use it directly as the R3DShape derived classes
all handle their own vertexes.
R3DShape
All drawable, transformable shapes are derived from this. It
is a pure virtual class that defines an interface to provide
RotateX/Y/Z functions, a Move(R3DVector &v)
function, and a SetTexture(R3DTexture &t)
function.
R3DTexture
Encapsulates the notion of a texture. So far only the texture
information is present, I plan to add a choice of shading methods
(Phong for shiny objects and Gouraud for dull objects). The
member functions of note are:
- Load(char *filename) - This loads a
*.3df format file from disk. Call this, or the
constructor which accepts a filename before assigning the
texture to an object. Thanks to Andrew Hodgson
whose excellent 3dfx tutorial page I got this code from.
R3DTriangle
Finally a real drawable object! This is a simple texture
mapped triangle that can be rotated and moved. Triangles have the
following member functions:
- Draw() - Draws the triangle to the back
buffer. At the moment all shapes must be drawn this way.
I plan to make the R3DCamera class contain a list of
shapes to draw so that shapes are added to the camera,
then the camera is drawn.
- R3DTriangle(R3DVector v1, R3DVector v2, R3DVector
v3) - A constructor that initialises the
triangle's position. Note that so far it is best to
position the triangle on the X-Y axis, otherwise the
texture may come out funny due to the way the texture is
initialised.
- SetPosition(...) - Takes the same
arguments as the constructor (above) and has much the
same effect.
- SetTexture(R3DTexture &t) - Sets the
texture of the triangle (unsurprisingly...)
- SetupTexture(float offset_s, float offset_t,
float scale) - By default, one unit of distance
= 1 texel, so use this function to scale and line up
textures. Note that the world co-ordinates are used to
set up the textures by default, so that two triangles
with the same texture next to each other will have lined
up textures automatically.
R3DRectangle
Made up from two triangles, but a little quicker to transform
than two triangles would be. Used in almost the same way as a
R3DTriangle.
R3DCuboid
A real 3D shape. This draws all the triangles necessary to
make up a 6 sided shape.
- SetPosition(R3DVector &v1, R3DVector &v2)
- Initialises the cuboid. The shape is constructed in
line with the axes. "v1" is the
top/left/nearest co-ordinate, and "v2" is
bottom/right/farthest. Note that the Z-axis is positive
into the screen, so nearest<farthest.
R3DCylinder
This is a 10 sided cylinder shape.
- SetPosition(float centre, float depth, float
radius) - Initialises the cylinder. The cylider
is starts off lined up on the X-Y plane.
- SetTexture(R3DTexture face, R3DTexture edge)
- Edge and face textures can be specified seperately.
- Spin(float distance) - Spins the
cylinder around its imaginary axle. The distance is used
to calculate the angle based on the circumference of the
cylinder. In this way it can be used as the wheel of a
car that turns just the right amount as the car moves
along.
R3DGroup
Use this to group R3DShapes together for translation and
rotation.
R3DModel
This class is used to build models out of Triangles,
Rectangles, Cuboids and Cylinders. The Triangles and Rectangles
are aligned on a mesh of Vectors so that when a model is
transformed only the vectors have to be actually transformed -
the shapes are simply glued onto the mesh. This approach reduces
the number of calculations. Models can be saved to disk and
reloaded. Note that all the textures used currently have to be
loaded in the same order for the correct textures to appear on
the model when it is reloaded. In the future I plan to save the
filenames of the textures with the models, instead of just the
texture id number.
- AddCuboid(R3DCuboid &c) - Adds a
cuboid to the model. Set up the position and texture
before adding it. At the moment the cuboid (or any other
shape in the model) cannot be referenced after it has
been added. This is obviously a flaw, and is caused
because a copy of the shape is made when it is
added, and no pointer to the new shape is returned. Don't
draw the shapes you add to the model, draw the model, ie:
R3DCuboid mycube(v1, v2); //
create a cuboid
mymodel.AddCuboid(mycube);
mycube.Move(R3DVector(10.f,
20.f, 0.f); // move to a new position
mymodel.AddCuboid(mycube); //
adds a second cube in the new position
mymodel.Draw(); // draws the
model (both cubes)
- AddCylinder(R3DCylinder &c) - Works
in the same way as AddCuboid().
- SetupVectors(R3DVector *v, int number) -
"v" is a pointer to an array of vectors. The
idea here is to specify a mesh of positions onto which
the triangles and rectangles in the model are mapped.
- AddTriangle(R3DTriangle &t, int v1, int v2,
int v3) - Adds a triangle to the model. You
create the triangle and set up its texture first, then
you add it, specifying the indexes of the vertexes in the
mesh onto which the triangle is glued.
- AddRectangle(R3DRectangle &r, int v1, int v2,
int v3, int v4) - Works in the same way as
AddTriangle().
- SetTexture(R3DTexture &t) - Does
nothing. Only here because R3DModel is derived from
R3DShape.
R3DCamera
This class encapsulates the notion of a camera that is
positioned somewhere in the world co-ordinate system. When an
object is Draw()n, it uses the global pointer R3DCAM to transform
from world to screen co-ordinates. When
R3DfxHardware::InitHardware() is called, a default camera is
created. This camera is positioned at (320, 240, -640). In this
way, objects at (0, 0, 0) appear in the top left of the screen,
and (640, 480, 0) appear at the bottom right. The camera can be
Moved just like an R3DShape. Other transformations are available:
- Pan(float angle) - Where angle is the
number of degrees to pan the camera.
- Tilt(float angle) - Tilts the camera up
or down.
- Walk(float distance) - Moves the camera
forward or back, taking into account the direction it is
facing in. It does not move up or down in the Y axis.
R3DCalc
A calculator object that provides quick Sin and Cos functions.
When R3DfxHardware::InitHardware() is called, an R3DCalc object
is created which is pointed to by R3DCALC. The Cos() and Sin()
functions take a floating point angle in degrees which is rounded
down to the nearest degree.
I can be reached by email on [email protected]
[Home][3Dfx
Programming]