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:

vectors.h

home Home   up Up   ( Download )


#ifndef VECTORS_H_INCLUDED #define VECTORS_H_INCLUDED #include "global.h" /** * Vec3 class * Holds a 3D vector. Is not functional, so the * result of an operation is placed in "this" object * so that we dont have allocation and destruction problems. */ struct Vec3 { public: // internal values float x, y, z; // constructors Vec3(): x(0.0), y(0.0), z(0.0) {} Vec3(float x, float y, float z): x(x), y(y), z(z) {} Vec3(const Vec3* v): x(v->x), y(v->y), z(v->z) {} // get inline float get(int i) { if (i == 0) return x; else if (i == 1) return y; else return z; } // set inline void set(int i, float v) { if (i == 0) x = v; else if (i == 1) y = v; else z = v; } inline void set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; } inline void set(const Vec3* v) { x = v->x; y = v->y; z = v->z; } // add inline void add(const Vec3* v) { x += v->x; y += v->y; z += v->z; } inline void add(float v) { x += v; y += v; z += v; } inline void add(float dx, float dy, float dz) { x += dx; y += dy; z += dz; } // subtract inline void subtract(const Vec3* v) { x -= v->x; y -= v->y; z -= v->z; } inline void subtract(float v) { x -= v; y -= v; z -= v; } // multiply inline void multiply(float v) { x *= v; y *= v; z *= v; } // divide inline void divide(float v) { x /= v; y /= v; z /= v; } // dot product of this and v inline float dot(const Vec3* v) { return (x * v->x) + (y * v->y) + (z * v->z); } // cross product, of this and b inline void cross(const Vec3* b) { float ax = x, ay = y, az = z; x = (ay * b->z) - (az * b->y); y = (az * b->x) - (ax * b->z); z = (ax * b->y) - (ay * b->x); } // normailize this vector to a unit vector inline void norm() { float l = sqrt(x*x + y*y + z*z); x /= l; y /= l; z /= l; } inline float length() { return sqrt(x*x + y*y + z*z); } // make always pointing up inline void up() { if (y < 0) { x = -x; y = -y; z = -z; } } // sets the value to the normal vector to the plane // defined by the points a, b, and c void faceNormal(const Vec3* a, const Vec3* b, const Vec3* c); // print on stdout void print() { printf("(%f, %f, %f)", x, y, z); } }; /** * Mat4 class * Holds a 4 dimensional vector. */ struct Mat4 { private: // matrix element float mat[16]; public: // constructor Mat4(); Mat4(const Mat4* v); // accessors // row - 0..3 // col - 0..3 inline float get(int row, int col) { return mat[(row*4)+col]; } inline void set(int row, int col, float v) { mat[(row*4)+col] = v; } void set(int row, float values[]); void set(int row, Vec3* val); // make identity void setI(); // operations void multiply(float a); void multiply(float a[]); void multiply(Mat4* a); void transform(Vec3* v); void transform(Vec3 v[], int n); void transformPlane(Vec3* A, Vec3* N); // transformation matrices void scale(const Vec3* v); void scale(float x, float y, float z); void translate(float x, float y, float z); void translate(const Vec3 *v) { translate(v->x, v->y, v->z); } // rotate by angle about axis void rotate(double angle, double x, double y, double z); void rotate(double angle, const Vec3 *axis) { rotate(angle, axis->x, axis->y, axis->z); } // display void print(); }; /* * HyperPlane class * Represents a 3D plane, against which * lines can be clipped. */ class HyperPlane { public: // normal to plane (pointing to inside) Vec3 N; // point on the plane Vec3 A; // constructor HyperPlane(): N(0.0, 1.0, 0.0), A(0.0, 0.0, 0.0) {} HyperPlane(const HyperPlane* hp): N(hp->N), A(hp->A) {} // normal and point on plane HyperPlane(const Vec3* N, const Vec3* A): N(N), A(A) {} // 3 points on the plane HyperPlane(const Vec3* p1, const Vec3* p2, const Vec3* p3); // set void set(HyperPlane* hp); void set(const Vec3* p1, const Vec3* p2, const Vec3* p3); // tranform using transformation matrix void transform(Mat4* t) { t->transformPlane(&A, &N); } // clipping // which side is the point on? // 0 - lies on plane // < 0 - outside (away from normal) // > 0 - inside (side of normal direction) GLfloat side(const Vec3* p); // same side bool sameSide(const Vec3* p1, const Vec3* p2); }; #endif