3D Underwater World (using OpenGL and SDL)

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:

worldobjects.cpp

home Home   up Up   ( Download )


#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; }