Copyright Tristan Aubrey-Jones January 2008.
This is an example OpenGL SDL application which creates an animated 3D underwater world (screenshot), with "Thunderbird 4" with headlights moving on a spline path, a randomly generated sand terrain, sunken ship/submarine/treasure chest models, and swaying fish and seaweed. It is designed to demonstrate basic OpenGL features, and the structure is as follows:
#include "worldobjects.h"
/* WorldObject class
Base class for all objects in the 3D enviroment.
*/
WorldObject::WorldObject():
bearing(0.0),
height(1.0),
width(1.0),
depth(1.0)
{
}
void WorldObject::draw(CameraView* view)
{
// if visible then draw
glPushMatrix();
// translate to correct position
glTranslatef(pos.x, pos.y, pos.z);
// rotate to correct bearing
glRotatef(bearing, 0, 1, 0);
// draw
drawInternal();
glPopMatrix();
// draw end
#ifdef DEBUG
Mat4 m;
m.setI();
m.rotate(bearing, 0, 1, 0);
m.translate(pos.x, pos.y, pos.z);
Vec3 s(org.x, org.y, org.z);
m.transform(&s);
Vec3 f(org.x + width, org.y + height, org.z + depth);
m.transform(&f);
glPushMatrix();
glColor3f(0, 1.0, 0);
glTranslatef(s.x, s.y, s.z);
glScalef(0.5, 0.5, 0.5);
Primitives::drawSphere();
glPopMatrix();
glPushMatrix();
glColor3f(1.0, 0.0, 0);
glTranslatef(f.x, f.y, f.z);
glScalef(0.5, 0.5, 0.5);
Primitives::drawSphere();
glPopMatrix();
#endif
}
// check for collision, and if
// one occurs provides the point of
// collision
// position - vertex to check
// direction - direction of vertex as it approached
// result - when returns true contains the point of collision
bool WorldObject::collisionDetect(Vec3* position, Vec3* direction, Vec3* result)
{
// copy position
Vec3 loc(position);
// convert direction to point just infront
Vec3 obj(position);
obj.add(direction);
// transform point the local space of this world object
Mat4 m;
m.translate(-pos.x, -pos.y, -pos.z);
m.rotate(-bearing, 0, 1, 0);
m.transform(&loc);
m.transform(&obj);
// see if is inside the collision box
if (isInside(&loc))
{
// transformed direction
Vec3 dir(&obj);
dir.subtract(&loc);
dir.norm(); dir.multiply(0.1);
// reverse position, until not infringing
int i = 0; // limit incase of infinate loop
while (i < 1000 && isInside(&loc)) {
loc.subtract(&dir); i++;
}
result->set(&loc);
// transform back into normal space
m.setI();
m.rotate(bearing, 0, 1, 0);
m.translate(pos.x, pos.y, pos.z);
m.transform(result);
// does collide
return true;
}
// no infringment
return false;
}
// checks if a point in this world object's
// space is inside the collision box.
bool WorldObject::isInside(Vec3* loc)
{
return (loc->x >= org.x && loc->x <= org.x + width &&
loc->y >= org.y && loc->y <= org.y + height &&
loc->z >= org.z && loc->z <= org.z + depth);
}
// single function call to position and setup
// the static object in the scene
void StaticObject::init(float x, float y, float z, float b)
{
pos.x = x;
pos.y = y;
pos.z = z;
bearing = b;
}