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:
#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