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"
#include "vectors.h"
#define MIN_X 0.0
#define MIN_Y 3.0
#define MIN_Z 0.0
#define MAX_X 100.0
#define MAX_Y 30.0
#define MAX_Z 100.0
#define TEX_COUNT 4
// calculate a random float between
// 0.0 and ran.
inline GLfloat randf(GLfloat min, GLfloat max) {
// calculate between 0 and 1
int ir = rand() % 1000;
GLfloat v = ((float)(ir) / 1000.0f);
// change to range
return (v * (max - min)) + min;
}
// init textures
Texture** FishObject::textures;
void FishObject::initTextures()
{
FishObject::textures = new Texture*[TEX_COUNT];
for (int i = 0; i < TEX_COUNT; i++) {
char txt[] = "fish0.jpg";
sprintf(txt, "fish%i.jpg", i);
FishObject::textures[i] = new Texture(txt);
}
}
// constructor
FishObject::FishObject()
{
// random location on map
loc.x = randf(MIN_X, MAX_X);
loc.y = randf(MIN_Y, MAX_Y);
loc.z = randf(MIN_Z, MAX_Z);
pos.x = loc.x;
pos.y = loc.y;
pos.z = loc.z;
// random bearing
bearing = randf(0, 360);
// random texture
tex = rand() % TEX_COUNT;
if (tex == 4 && rand()%4 != 0) tex = rand() % TEX_COUNT;
// random size
if (tex == 4) {
// shark
w = randf(3.5,4);
h = randf(1,1.5);
s = randf(1, 3);
moving = true;
v = randf(0.2, 10);
} else {
// other fish
w = randf(2, 3);
h = randf(0.5, 1);
s = randf(0.1, 0.8);
// moving?
if (randf(0, 1) < 0.5) moving = true;
else moving = false;
v = randf(0.05, 10);
}
}
// draw
void FishObject::drawMesh()
{
glColor3f(1, 1, 1);
glDisable(GL_LIGHTING);
Texture* t = FishObject::textures[tex];
t->Begin();
//GLfloat cl[] = {1.0, 0, 0, 0, 0};
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
//glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cl);
//glColor3f(0.2, 0.2, 1);
glPushMatrix();
glRotatef(bearing, 0, 1, 0);
glScalef(1, h, w);
glScalef(s, s, s);
//Primitives::drawSphere();
glBegin(GL_QUADS);
glTexCoord2f(t->minX(), t->maxY());
glVertex3f(0, 0, 0);
glTexCoord2f(t->maxX(), t->maxY());
glVertex3f(0, 0, 1);
glTexCoord2f(t->maxX(), t->minY());
glVertex3f(0, 1, 1);
glTexCoord2f(t->minX(), t->minY());
glVertex3f(0, 1, 0);
glEnd();
glPopMatrix();
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
t->End();
glEnable(GL_LIGHTING);
}
// simulate
void FishObject::simulate(GLfloat dT)
{
time += dT;
// wave in the current
pos.x = loc.x + sin(time);
// move along vector
if (moving) {
Vec3 dir;
dir.z += v * dT;
Mat4 m;
m.rotate(bearing + 90, 0, 1, 0);
m.transform(&dir);
pos.add(&dir);
}
// check if out of bounds
if (pos.x > MAX_X) pos.x = MIN_X;
else if (pos.x < MIN_X) pos.x = MAX_X;
if (pos.y > MAX_Y) pos.y = MIN_Y;
else if (pos.y < MIN_Y) pos.y = MAX_Y;
if (pos.z > MAX_Z) pos.z = MIN_Z;
else if (pos.z < MIN_Z) pos.z = MAX_Z;
}