/* 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; } }