Lephisto/trunk/src/WaveEmitter.cpp

225 lines
4.7 KiB
C++

/* This software is the propery of 'SaraCraft' - developed by Allanis.
* Only members directly assosiated with the SaraCraft project may view/change
* this code.
*/
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <iostream>
#include <GL/gl.h>
#include <vector>
#include <list>
#include <time.h>
#include <stdlib.h>
#include "Log.h"
#include "image.h"
#include "Point.h"
#include "Terrain.h"
#include "BoundBox.h"
#include "Wave.h"
#include "WaveEmitter.h"
using namespace std;
#define WAVE_RATE .002
#define EMIT_RATE 3300
#define EMIT_DIFF_PERCENT .2
#define EMIT_RATIO .2
class WaveLoc {
public:
float x;
float z;
float angle;
};
GLuint WaveEmitter::waveList = 0;
list <Wave*> WaveEmitter::activeWaves;
WaveEmitter::WaveEmitter(Terrain *terrain, BoundBox *box) {
// List of points on shore
list< Point* > shorePoints;
Point *temp;
float tAngle = 0.0;
WaveLoc *tLoc;
ticksToNextEmit = (int) (EMIT_RATE*(rand()/(RAND_MAX+1.0)));
//counter = 0.0;
isVisible = false;
// Populate the shore line list
terrain->locateShoreLine(box, &shorePoints);
while(!shorePoints.empty()) {
// First, we need to read the front element of the list
temp = shorePoints.front();
// Next, remove the shore element
shorePoints.pop_front();
// Find shore angle and move point to propper distance
if(terrain->findNearestShoreAngle(temp, &tAngle)) {
// Set tLoc angle and move point to propper distance
tLoc = new WaveLoc();
tLoc->x = temp->x;
tLoc->z = temp->z;
tLoc->angle = tAngle;
waveLocations.push_back(tLoc);
}
// Finaly delete the Point the list element pointed to
delete temp;
}
}
WaveEmitter::~WaveEmitter() {
// Delete the wave locations in vector
WaveLoc *temp;
while(!waveLocations.empty()) {
temp = waveLocations.back();
waveLocations.pop_back();
delete temp;
}
}
void WaveEmitter::update(unsigned int ticks) {
int numToGenerate;
ticksToNextEmit -= ticks;
if(ticksToNextEmit <= 0) {
// Update ticksToNextEmit
// I add EMIT_RATE and ticksToNextEmit so that it keeps the emit rate exact (I hope)
ticksToNextEmit = getNextEmit() + ticksToNextEmit;
// Add a new wave (only if it is visible???)
if(isVisible) {
numToGenerate = 1+(int) (waveLocations.size() * EMIT_RATIO * (rand()/(RAND_MAX+1.0)));
for(int i = 0; i < numToGenerate; i++) {
generateWave();
}
}
}
isVisible = false;
}
void WaveEmitter::setVisible() {
isVisible = true;
}
int WaveEmitter::getNextEmit() {
int diff = (int) (EMIT_DIFF_PERCENT * EMIT_RATE);
float randNum = (2.0 * (rand() / (RAND_MAX + 1.0))) - 1;
return EMIT_RATE + (int) (diff * randNum);
}
void WaveEmitter::generateWaveList() {
// Generate the surf list
waveList = glGenLists(1);
if(waveList == 0) {
// Should throw an exception
return;
}
glNewList(waveList, GL_COMPILE);
// Draw the actual surf
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex3f(1, 0, -.3);
glTexCoord2f(1, 1);
glVertex3f(-1, 0, -.3);
glTexCoord2f(1, 0);
glVertex3f(-1, 0, .3);
glTexCoord2f(0, 0);
glVertex3f(1, 0, .3);
glEnd();
glEndList();
}
void WaveEmitter::deleteWaveList() {
glDeleteLists(waveList, 1);
}
void WaveEmitter::generateWave() {
WaveLoc *temp;
int index;
index = (int) (waveLocations.size() * (rand() / (RAND_MAX + 1.0)));
temp = waveLocations[index];
activeWaves.push_back(new Wave(temp->x, temp->z, temp->angle));
}
int WaveEmitter::numWaveLocations() {
return waveLocations.size();
}
void WaveEmitter::drawActiveWaves() {
Wave *temp;
list< Wave* >::iterator iter;
list< Wave* >::iterator listEnd;
if(activeWaves.size() <= 0) return;
glEnable(GL_COLOR_MATERIAL);
// Disable depth writes
glDepthMask(GL_FALSE);
iter = activeWaves.begin();
listEnd = activeWaves.end();
while(iter != listEnd) {
temp = *iter;
glPushMatrix();
temp->prepDraw();
glCallList(waveList);
glPopMatrix();
++iter;
}
// Reenable depth testing
glDepthMask(GL_TRUE);
glDisable(GL_COLOR_MATERIAL);
}
void WaveEmitter::updateActiveWaves(unsigned int ticks) {
Wave *temp;
list< Wave* >::iterator iter;
list< Wave* >::iterator listEnd;
if(activeWaves.size() <= 0) return;
temp = activeWaves.front();
while(!activeWaves.empty() && !temp->isActive()) {
activeWaves.pop_front();
}
iter = activeWaves.begin();
listEnd = activeWaves.end();
while(iter != listEnd) {
temp = *iter;
temp->update(ticks);
++iter;
}
}
void WaveEmitter::deleteActiveWaves() {
Wave *temp;
while(!activeWaves.empty()) {
temp = activeWaves.front();
activeWaves.pop_front();
delete temp;
}
}