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:

splines.cpp

home Home   up Up   ( Download )


#include "splines.h" /** * MotionPath * */ // constructor MotionPath::MotionPath(int numPoints): vertices(new Vec3[numPoints]), n(numPoints), p(0.0) { } // set a point on the path void MotionPath::set(int u, float x, float y, float z) { vertices[u].set(x, y, z); } // get point void MotionPath::get(float u, Vec3* pos, Vec3* dest) { // find the two points its between int v0 = (int)floor(u * n) % n; int v1 = (v0 + 1) % n; // return the point interpolated on that line float d = u*n - v0; Vec3 dir(&vertices[v1]); dir.subtract(&vertices[v0]); dir.multiply(d); dir.add(&vertices[v0]); // return pos->set(&dir); //dest->set(&vertices[v1]); if (dest != NULL) get(u+(0.8*(1.0/n)), dest); } void MotionPath::get(float u, Vec3* pos) { get(u, pos, NULL); } // reset void MotionPath::reset() { p = 0.0; } // move void MotionPath::move(float d) { p += d; if (p > 1.0) p -= 1.0; } // get now void MotionPath::getNow(Vec3* pos, Vec3* dest) { get(p, pos, dest); } // draw for testing purposes void MotionPath::draw() { glDisable(GL_LIGHTING); glBegin(GL_LINE_STRIP); for (float u = 0; u < 1.0; u += 0.01) { Vec3 p, d; get(u, &p, &d); glVertex3f(p.x, p.y, p.z); } glEnd(); glEnable(GL_LIGHTING); } /* * SplineCurve class * represents a parametric cubic b-spline * curve. */ SplineCurve::SplineCurve(int numPoints): numPoints(numPoints), controlPoints(new Vec3[numPoints]) { // init matrix Ms.set(0, 0, 1.0f); Ms.set(0, 1, 4.0f); Ms.set(0, 2, 1.0f); Ms.set(0, 3, 0.0f); Ms.set(1, 0, -3.0f); Ms.set(1, 1, 0.0f); Ms.set(1, 2, 3.0f); Ms.set(1, 3, 0.0f); Ms.set(2, 0, 3.0f); Ms.set(2, 1, -6.0f); Ms.set(2, 2, 3.0f); Ms.set(2, 3, 0.0f); Ms.set(3, 0, -1.0f); Ms.set(3, 1, 3.0f); Ms.set(3, 2, -3.0f); Ms.set(3, 3, 1.0f); Ms.multiply(1.0/6.0); } // allows assigning at fixed control points // u - integer index in [0,numPoints-1] // x,y,z coordinate of control point void SplineCurve::set(int u, float x, float y, float z) { if (u > 0 && u < numPoints) controlPoints[u].set(x, y, z); else fprintf(stderr, "comp3004/cwk3/spline/error: u outside spline curve bounds %i\n", u); } void SplineCurve::set(int u, const Vec3* v) { if (u > 0 && u < numPoints) controlPoints[u].set(v); else fprintf(stderr, "comp3004/cwk3/spline/error: u outside spline curve bounds %i\n", u); } // accessor interpolating along spline curve // treats the curve as a loop, joinging the ends // u - the parameter to interpolate the position of // in [0, numPoints-1] // r - pointer to vector to store the result in void SplineCurve::get(float u, Vec3* r) { // get nearest control points int u0 = (int)floor(u); r->set(&controlPoints[u0]); /*int u1 = (u0 + 1) % numPoints; int u_2 = (u0 - 2); if (u_2 < 0) u_2 = numPoints - u_2; int u_1 = u_2 - 1; // init terms in uT * M * p Mat4 P; P.set(0, &controlPoints[u_2]); P.set(1, &controlPoints[u_1]); P.set(2, &controlPoints[u0]); P.set(3, &controlPoints[u1]); u = u - u0; float U[] = {1, u, u*u, u*u*u}; // calculate matrix P.multiply(&Ms); P.multiply(U); // calculate point r->x = 1; r->y = 1; r->z = 1; P.transform(r);*/ } // draw for testing purposes void SplineCurve::draw() { glBegin(GL_LINE_STRIP); for (float u = 0; u < numPoints; u += 0.1) { Vec3 p; get(u, &p); glVertex3f(p.x, p.y, p.z); } glEnd(); }