/** ******************************************************************************* @file /gui/engine/Effects.cpp @brief Zaklad pro visualni efekty(casticove systemy, sprite,..) @author Vajicek @version 0.1 ******************************************************************************/ // #include "gui/engine/Effects.h" #include "gui/engine/TextureManager.h" #include "gui/model/DrawModel.h" #include "gui/model/guimap.h" #include "gui/common/mymath_ext.h" #include "gui/common/Sounds.h" // #include #include #include using namespace std; namespace gui{ /*****************************************************************************/ void GenerateRandomDirectionInSector(float r, float z, P3F *dir, float size) { float ang = RAND(0,2*M_PI); float dist = RAND(0,r); // float x = sin(ang)*dist; float y = cos(ang)*dist; // SETV3(dir->p, x, y, z); NormalizeV3(dir->p); MulV3(dir->p, size); } void GenerateRandomPositionInSector(float r, float z, P3F *pos) { float x; float y; do{ x = RAND(-r, r); y = RAND(-r, r); }while( (x*x+y*y) > (r*r) ); SETV3(pos->p, x, y, z); } /// polynom f0(asi fergusonuv) #define F0(x) (3*x*x+2*x*x*x) /// polynom f1 #define F1(x) (1-3*x*x+2*x*x*x) float FadeInOut(float t, float t1 , float t2) { if(tt2) return F1((t-t2)/(1-t2)); return 1; } /////////////////////////////////////////////////////////////////////////////// // TEffectEngine // /////////////////////////////////////////////////////////////////////////////// TEffectEngine::TEffectEngine(TScene* sc, TControllerManager* cm){ scene = sc; ctrlmng = cm; // SETV3(p3fSceneWind.p, 0,0,0); //vitr vzhledem ke scene v jednotkovem case SETV3(p3fSceneGravity.p, 0,0,-5); //gravitace vzhledem ke scene v jednotkovem case //poz: scena bezi v jednotkovem case asi polovicni "normalni" rychlosti // vyska nebe fSkyHeight = 600.0f; // rychlost obnovovani casticovejch systemu v ms, zmena hodnoty muze urychlit a znepresnit system iPRP = 50; // inicializace stinu TSimpleShadow::initShadowTextures(); // inicializuje kour TSmoke::initSmokeTexture(); // strelba TProjectileAttack::initProjectiles(); // vybuch TDestruction::initParticleTextures(); // jiskreni TSparkle::initParticleTextures(); } void TEffectEngine::initEffectEngine(TScene* sc, TControllerManager* cm){ TEffectEngine::ee = new TEffectEngine(sc, cm); } void TEffectEngine::destroyEffectEngine(){ delete TEffectEngine::ee; TEffectEngine::ee = NULL; } TEffectEngine* TEffectEngine::ee = NULL; /////////////////////////////////////////////////////////////////////////////// // TAdvController // /////////////////////////////////////////////////////////////////////////////// void TAdvController::update(int absoluteTime){ int step = ROUND( (absoluteTime-iLastTime)*fTimeRatio ); int rtime = iLastRelativeTime + step; if(step < iGranularity)return; update(absoluteTime, rtime, step); iLastRelativeTime = rtime; iLastTime = absoluteTime; } void TAdvController::update(int absoluteTime, int rtime, int step){ } void TAdvController::activate(int absoluteTime, int recursive){ TController::activate(absoluteTime, recursive); iLastRelativeTime = 0; } TAdvController::TAdvController(int granularity) :TController() { iGranularity = granularity; iLastRelativeTime = 0; RTTID("advcntrl"); } /////////////////////////////////////////////////////////////////////////////// // TParticles // /////////////////////////////////////////////////////////////////////////////// void TParticles::drawObject(){ if (getRealFade() != FADE_0) return; glPushMatrix(); glMultMatrixf(mx4Pos); glDisable(GL_LIGHTING); glBegin(GL_POINTS); for(int i = 0; i < iCount; i++){ glVertex3f(p3fPositions[i].x,p3fPositions[i].y,p3fPositions[i].z); } glEnd(); glEnable(GL_LIGHTING); glPopMatrix(); TSceneObject::drawObject(); } void TParticles::calculateAABB(){ float minx = FLT_MAX; float maxx = -FLT_MAX; float miny = FLT_MAX; float maxy = -FLT_MAX; float minz = FLT_MAX; float maxz = -FLT_MAX; for(int i = 0; i < iCount; i++){ if( p3fPositions[i].x > maxx )maxx=p3fPositions[i].x; if( p3fPositions[i].x < minx )minx=p3fPositions[i].x; if( p3fPositions[i].y > maxy )maxy=p3fPositions[i].y; if( p3fPositions[i].y < miny )miny=p3fPositions[i].y; if( p3fPositions[i].z > maxz )maxz=p3fPositions[i].z; if( p3fPositions[i].z < minz )minz=p3fPositions[i].z; } P4F p1, p2; SETV4( p1.p, 0,0,0, 1); // ApplyVectorMX4 (p1.p, mx4Pos, p2.p); CopyV4toV3(aabbCenter.p, p2.p); // SETV3(aabbDim.p, maxx-minx, maxy-miny, maxz-minz); } TParticles::TParticles() :TAdvController(TEffectEngine::ee->iPRP) { iCount = 0; p3fDirections = NULL; p3fPositions = NULL; RTTID("particles"); } TParticles::~TParticles(){ if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); } /////////////////////////////////////////////////////////////////////////////// // TSimpleSpray // /////////////////////////////////////////////////////////////////////////////// void TSimpleSpray::update(int absoluteTime, int rtime, int step) { float dist = step*fSpeed; P3F v; // for(int i = 0; i < iCount; i++){ if( RAND(0,1) < fDeathProb ){ GenerateRandomDirectionInSector(fBaseDiam, 0, p3fPositions + i, 1); } else{ CopyV3(v.p, p3fDirections[i].p); MulV3(v.p, dist); AddV3(p3fPositions[i].p, v.p); } } } int TSimpleSpray::setUp(){ if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); // p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); // for(int i = 0; i < iCount; i++){ GenerateRandomDirectionInSector(fBaseDiam, fBaseDiam, p3fDirections + i, 1); GenerateRandomPositionInSector(fBaseDiam, 0, p3fPositions + i); } return 1; } TSimpleSpray::TSimpleSpray(float speed, int pcount, float bdiam, float deathp){ fSpeed = speed;; fBaseDiam = bdiam; iCount = pcount; fDeathProb = deathp; setUp(); RTTID("sim_spray"); } /////////////////////////////////////////////////////////////////////////////// // TAtmosphericEffect // /////////////////////////////////////////////////////////////////////////////// void TAtmosphericEffect::cellOrderChange(){ //vymena bunek int px = (int)(cam->aabbCenter.x / AE_CELL_SIZE); int py = (int)(cam->aabbCenter.y / AE_CELL_SIZE); TCell* new_cellorder[9]; //kopiruj if(px > posx) { for(int cy = 0; cy < 3; cy++) for(int cx = 0; cx < 3; cx++) new_cellorder[cy*3+cx] = cellorder[cy*3+(cx+1)%3]; for(int i = 0; i < 9; i++) cellorder[i] = new_cellorder[i]; } else if(px < posx) { for(int cy = 0; cy < 3; cy++) for(int cx = 0; cx < 3; cx++) new_cellorder[cy*3+cx] = cellorder[cy*3+(cx+2)%3]; for(int i = 0; i < 9; i++) cellorder[i] = new_cellorder[i]; } if(py > posy) { for(int cy = 0; cy < 3; cy++) for(int cx = 0; cx < 3; cx++) new_cellorder[cy*3+cx] = cellorder[((cy+1)%3)*3+cx]; for(int i = 0; i < 9; i++) cellorder[i] = new_cellorder[i]; } else if(py < posy) { for(int cy = 0; cy < 3; cy++) for(int cx = 0; cx < 3; cx++) new_cellorder[cy*3+cx] = cellorder[((cy+2)%3)*3+cx]; for(int i = 0; i < 9; i++) cellorder[i] = new_cellorder[i]; } //aktualizace posx = px; posy = py; } void TAtmosphericEffect::setUpCells(){ //inicializuj bunky for(int cx = 0; cx < 3; cx++) for(int cy = 0; cy < 3; cy++){ cellorder[cy*3+cx] = cells + (cy*3+cx); cells[cy*3+cx].c1 = (int)( (cy*3+cx)*iCount/9.0f ); cells[cy*3+cx].c2 = (int)( (cy*3+cx+1)*iCount/9.0f-1 ); cells[cy*3+cx].i = cy*3+cx; } } void TAtmosphericEffect::calculateAABB(){ } void TAtmosphericEffect::setTimeRatio(float tr, int recursive){ TParticles::setTimeRatio(tr, recursive); fTimeRatio = AE_BASIC_TIMERATIO; } void TAtmosphericEffect::stopGradually(){ iStopped = 1; } TAtmosphericEffect::TAtmosphericEffect(P3F* center, P3F* dim, TCamera* c){ fSkyTop = (center->z + dim->z/2) + TEffectEngine::ee->fSkyHeight; fGround = (center->z - dim->z/2); CopyV3(aabbDim.p, dim->p); CopyV3(aabbCenter.p, center->p); cam = c; iStopped = 0; transparent = true; // TEffectEngine::ee->scene->addObject(this); TEffectEngine::ee->ctrlmng->addController(this); // setTimeRatio(AE_BASIC_TIMERATIO, 0); } void TAtmosphericEffect::uninstallAtmosphericEffect(TAtmosphericEffect* ae){ TEffectEngine::ee->scene->remFromScene(ae); TEffectEngine::ee->ctrlmng->removeController(ae); } /////////////////////////////////////////////////////////////////////////////// // TSnow // /////////////////////////////////////////////////////////////////////////////// int TSnow::setUp(){ //pamet if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); //inicializace vlocek for(int i = 0; i < iCount; i++){ // GenerateRandomDirectionInSector(fBaseDiam/2, -fBaseDiam, p3fDirections + i, RAND(1, fSpeedVariation)); // p3fPositions[i].x = RAND(0, AE_CELL_SIZE); p3fPositions[i].y = RAND(0, AE_CELL_SIZE); p3fPositions[i].z = fSkyTop + RAND(fGround, fSkyTop); } // setUpCells(); return 1; } void TSnow::update(int absoluteTime, int rtime, int step) { float dist = step*fSpeed; P3F v; iAlive = 0; // int snowinterval = (int)(fSkyTop - fGround); for(int i = 0; i < iCount; i++){ if( !iStopped && (p3fPositions[i].z < fGround) ){ p3fPositions[i].z = fSkyTop - ( ((int)(fGround - p3fPositions[i].z))%snowinterval ); } else if(p3fPositions[i].z >= fGround){ iAlive++; CopyV3(v.p, p3fDirections[i].p); MulV3(v.p, dist); AddV3(p3fPositions[i].p, v.p); } //zmen smer, mihotani if((step%4)==0) GenerateRandomDirectionInSector(fBaseDiam/2, -fBaseDiam, p3fDirections + i, RAND(1, fSpeedVariation)); } // cellOrderChange(); if(!iAlive && iStopped){ TAtmosphericEffect::uninstallAtmosphericEffect(this); } } void TSnow::drawObject(){ //pruhlednost vlocek float flakes_alfa = float(iAlive)/iCount; flakes_alfa *= flakes_alfa; //nastaveni vsech vlocek glPointSize(SNOWFLAKE_SIZ); glEnable(GL_POINT_SMOOTH); glColor4f(SNOWFLAKE_COL, flakes_alfa); glDisable(GL_LIGHTING); //stred centralni bunky float x = posx*AE_CELL_SIZE; float y = posy*AE_CELL_SIZE; //vykresli bunky for(int cx = 0; cx < 3; cx++) for(int cy = 0; cy < 3; cy++) { //nastav souradnice glPushMatrix(); glTranslatef(x+(cx-1)*AE_CELL_SIZE, y+(cy-1)*AE_CELL_SIZE, 0); //index bunky a krajni indexy vlocek int cellindex = cy * 3 + cx; int c1 = cellorder[cellindex]->c1; int c2 = cellorder[cellindex]->c2; glVertexPointer(3, GL_FLOAT, sizeof(P3F), p3fPositions); glEnableClientState(GL_VERTEX_ARRAY); glDrawArrays(GL_POINTS,c1, c2-c1); glDisableClientState(GL_VERTEX_ARRAY); //zpet glPopMatrix(); } glEnable(GL_LIGHTING); glPointSize(1); TSceneObject::drawObject(); } TSnow::TSnow(P3F* center, P3F* dim, TCamera* c, int density) :TAtmosphericEffect(center, dim, c) { RTTID("snow"); iPriorityOfSelection = -1; selected = false; iCount = density; fBaseDiam = 10; fSpeed = 0.004f; fSpeedVariation = 6; // moveTo(aabbCenter.x, aabbCenter.y, aabbCenter.z); // setUp(); // activate(0); TEffectEngine::ee->scene->reinstalObject(this); } TSnow* TSnow::installSnow(int density){ return new TSnow( &(TEffectEngine::ee->scene->aabbCenter), &(TEffectEngine::ee->scene->aabbDim), ((gui::TguiMap*)(TEffectEngine::ee->scene))->getCam(), density); } /////////////////////////////////////////////////////////////////////////////// // TRain // /////////////////////////////////////////////////////////////////////////////// int TRain::setUp(){ //pamet if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); //inicializace kapek for(int i = 0; i < iCount; i++){ // p3fDirections[i] = fRainDir; MulV3(p3fDirections[i].p, RAND(0.9f, 1.1f)); // p3fPositions[i].x = RAND(0, AE_CELL_SIZE); p3fPositions[i].y = RAND(0, AE_CELL_SIZE); p3fPositions[i].z = fSkyTop + RAND(fGround, fSkyTop); } // setUpCells(); return 1; } void TRain::update(int absoluteTime, int rtime, int step) { float dist = step*fSpeed; P3F v; int alive = 0; // int interval = (int)(fSkyTop - fGround); for(int i = 0; i < iCount; i++){ if( !iStopped && (p3fPositions[i].z < fGround) ) { p3fPositions[i].x = RAND(0, AE_CELL_SIZE); p3fPositions[i].y = RAND(0, AE_CELL_SIZE); p3fPositions[i].z = fSkyTop - ( ((int)(fGround - p3fPositions[i].z))%interval ); } else if(p3fPositions[i].z >= fGround) { alive++; CopyV3(v.p, p3fDirections[i].p); MulV3(v.p, dist); AddV3(p3fPositions[i].p, v.p); } } //hrom if( thunderTime < absoluteTime && thunderTime && !iStopped ){ if(TSoundInterface::si) TSoundInterface::si->playSample(SAMPLE_THUNDER); thunderTime = 0; } //blesk if(iStopped) { flash(false); } else if((lightingTime+LIGHTING_INTERVAL_LEN) < absoluteTime ) { lightingTime = absoluteTime + (int)RAND(LIGHTING_INTERVAL_MIN, LIGHTING_INTERVAL_MAX); thunderTime = lightingTime - THUNDER_TIMING; flash(false); } else if( lightingTime < absoluteTime ) { flash( (absoluteTime - lightingTime)%80 < 50 ); } //update cellOrderChange(); if(!alive && iStopped){ TAtmosphericEffect::uninstallAtmosphericEffect(this); } } void TRain::flash(int on){ if(on){ float f4Fog[4] = {1, 1, 1, 1}; glFogfv(GL_FOG_COLOR, f4Fog); glClearColor(1, 1, 1, 1); lsLighting->iEnabled= true; } else { float f4Fog[4] = {DEFAULT_BACKGROUND_RGB, 1}; glFogfv(GL_FOG_COLOR, f4Fog); glClearColor(DEFAULT_BACKGROUND_RGB, 1); lsLighting->iEnabled=false; } } void TRain::drawObject() { glLineWidth(RAINDROPS_SIZ); glDisable(GL_LIGHTING); //stred centralni bunky float x = posx*AE_CELL_SIZE; float y = posy*AE_CELL_SIZE; //vykresli bunky for(int cx = 0; cx < 3; cx++) for(int cy = 0; cy < 3; cy++) { //nastav souradnice glPushMatrix(); glTranslatef(x+(cx-1)*AE_CELL_SIZE, y+(cy-1)*AE_CELL_SIZE, 0); //index bunky a krajni indexy vlocek int cellindex = cy * 3 + cx; int c1 = cellorder[cellindex]->c1; int c2 = cellorder[cellindex]->c2; glBegin(GL_LINES); //vykresli jen bunky okolo kamery for(int i = c1; i < c2; i++){ glColor4f(RAINDROPS_COL,0); glVertex3f(p3fPositions[i].x,p3fPositions[i].y,p3fPositions[i].z); glColor4f(RAINDROPS_COL,1); glVertex3f(p3fPositions[i].x+fRainDir.x, p3fPositions[i].y+fRainDir.y, p3fPositions[i].z+fRainDir.z); } glEnd(); //zpet glPopMatrix(); } glEnable(GL_LIGHTING); glLineWidth(1); TSceneObject::drawObject(); } TRain::TRain(P3F* center, P3F* dim, TCamera* c, int density) :TAtmosphericEffect(center, dim, c) { RTTID("rain"); iPriorityOfSelection = -1; thunderTime = 0; lightingTime = INT_MAX; selected = false; iCount = density; GenerateRandomDirectionInSector(RAINDROPS_LEN/2, -RAINDROPS_LEN, &fRainDir, RAINDROPS_LEN); fSpeed = 0.008f; //blesk lsLighting = (TLightSource *) new TLightSource((KHANDLE)LIGHTSOURCE_LIGHTING,(HWID)1); TEffectEngine::ee->scene->addLightSource(lsLighting); SETP4(lsLighting->p4fAmbient,1,1,1,1); SETP4(lsLighting->p4fPosition,0.5f,0.5f,1,0); SETP4(lsLighting->p4fDiffuse,1,1,1,1); SETP4(lsLighting->p4fSpecular,1,1,1,1); // moveTo(aabbCenter.x, aabbCenter.y, aabbCenter.z); // setUp(); // activate(0); TEffectEngine::ee->scene->reinstalObject(this); } TRain* TRain::installRain(int density){ return new TRain( &(TEffectEngine::ee->scene->aabbCenter), &(TEffectEngine::ee->scene->aabbDim), ((gui::TguiMap*)(TEffectEngine::ee->scene))->getCam(), density); } TRain::~TRain(){ if(lsLighting && TEffectEngine::ee){ if( TEffectEngine::ee->scene->remLightSource((KHANDLE)LIGHTSOURCE_LIGHTING) ){ flash(false); delete lsLighting; } } } /////////////////////////////////////////////////////////////////////////////// // TWeatherController // /////////////////////////////////////////////////////////////////////////////// void TWeatherController::update(int absoluteTime){ //prubeh zmeny int rtime = (int)((absoluteTime - iActivationTime)*fTimeRatio); float t = MIN(1, MAX(0 ,((float)rtime)/WEATHER_CHANGE_DELAY )); TVector prev, next; switch(previous_state){ case wsWinter: prev = TVector(WEATHER_WINTER_SKYCOLOR); break; case wsSummer: prev = TVector(WEATHER_SUMMER_SKYCOLOR); break; case wsAutumn: prev = TVector(WEATHER_AUTUMN_SKYCOLOR); break; } switch(state){ case wsWinter: next = TVector(WEATHER_WINTER_SKYCOLOR); break; case wsSummer: next = TVector(WEATHER_SUMMER_SKYCOLOR); break; case wsAutumn: next = TVector(WEATHER_AUTUMN_SKYCOLOR); break; } TVector val = TVector( TVector(prev)*(1-t) + TVector(next)*t ); if(scenefog)scenefog->setColor(val.x, val.y, val.z, 1); if(t>=1){ switch(state){ case wsWinter: atmosphericeffect = TSnow::installSnow(); break; case wsSummer: atmosphericeffect = NULL; break; case wsAutumn: atmosphericeffect = TRain::installRain(); break; } deactivate(0); } } void TWeatherController::change(TWeatherState new_state){ if(new_state == state)return; previous_state = state; state = new_state; //ukonci atmosferickej efekt if(atmosphericeffect) atmosphericeffect->stopGradually(); activate(KTime()); } TWeatherController::TWeatherController(TSceneFog* scfog, TWeatherState initial_state){ scenefog = scfog; previous_state = initial_state; state = initial_state; switch(initial_state){ case wsWinter: atmosphericeffect = TSnow::installSnow(); if(scenefog)scenefog->setColor(WEATHER_WINTER_SKYCOLOR, 1); break; case wsSummer: atmosphericeffect = NULL; if(scenefog)scenefog->setColor(WEATHER_SUMMER_SKYCOLOR, 1); break; case wsAutumn: atmosphericeffect = TRain::installRain(); if(scenefog)scenefog->setColor(WEATHER_AUTUMN_SKYCOLOR, 1); break; } } TWeatherController::~TWeatherController(){ } TWeatherController* TWeatherController::installWeatherController(TWeatherState initial_state){ // TWeatherController* wc = new TWeatherController( TEffectEngine::ee->scene->fog, initial_state ); // TEffectEngine::ee->ctrlmng->addController(wc); return wc; } /////////////////////////////////////////////////////////////////////////////// // TBloodSplash // /////////////////////////////////////////////////////////////////////////////// int TBloodSplash::setUp(){ if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); if(pfAlpha) KMemFree(pfAlpha); // p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); pfAlpha = (float*)KMemAlloc( sizeof(float)*iCount ); // P3F ax = {0,0,1}; float ang; // for(int i = 0; i < iCount; i++){ //nahodny smer ang = RAND(-fAngle, fAngle); ROT(&(p3fStartDirection), &ax, ang, p3fDirections + i); //nahodna pocatecni rychlost MulV3( p3fDirections[i].p, RAND(fStartSpeedMin, fStartSpeedMax) ); //pozice CopyV3( p3fPositions[i].p, p3fStartPosition.p); //pocatecni pruhlednost; pfAlpha[i] = 1; } return 1; } void TBloodSplash::drawObject(){ if (getRealFade() != FADE_0) return; glPushMatrix(); glMultMatrixf(mx4Pos); glPointSize(4); glEnable(GL_POINT_SMOOTH); glDisable(GL_LIGHTING); glBegin(GL_POINTS); for(int i = 0; i < iCount; i++){ glColor4f(BLOODSPLASH_COLOR, pfAlpha[i]); glVertex3f(p3fPositions[i].x,p3fPositions[i].y,p3fPositions[i].z); } glEnd(); glEnable(GL_LIGHTING); glPopMatrix(); TSceneObject::drawObject(); } void TBloodSplash::update(int absoluteTime, int rtime, int step) { float dist = step/1000.0f; int alive = 0; // for(int i = 0; i < iCount; i++) { if(p3fPositions[i].z != 0) { p3fPositions[i] = (TVector(p3fPositions[i]) + TVector(p3fDirections[i])*dist ).toP3F(); p3fDirections[i] = (TVector(p3fDirections[i]) + TVector(TEffectEngine::ee->p3fSceneGravity)*dist ).toP3F(); //konec if(p3fPositions[i].z < 0){ p3fPositions[i].z = 0; SETV3(p3fDirections[i].p,0,0,0); } alive++; } else{ pfAlpha[i]*=0.98f; if(pfAlpha[i]> 0.5) alive++; }//if z != 0 }//for // if(!alive){ TEffectEngine::ee->scene->remFromScene(this); if(parent_controller)parent_controller->removeChildControler(this); } } TBloodSplash::TBloodSplash(P3F* dir, P3F* pos, int pc, float ang, int startAt, float ssmin = 3, float ssmax = 10) :TParticles() { RTTID("bloodsplash"); // pfAlpha = NULL; iCount = pc; CopyV3(p3fStartDirection.p, dir->p); CopyV3(p3fStartPosition.p, pos->p); // fAngle = ang; fStartSpeedMin = ssmin; fStartSpeedMax = ssmax; // setUp(); // TEffectEngine::ee->scene->addObject(this); // TEffectEngine::ee->ctrlmng->addController(this); // if( startAt >= 0 ) activate(startAt); } TBloodSplash::~TBloodSplash(){ if(pfAlpha) KMemFree(pfAlpha); } TBloodSplash* TBloodSplash::installSmallBloodSplash(P3F* dir, P3F* scpos, P3F* pos, int startAt) { TBloodSplash* bs = new TBloodSplash(dir, pos, SMALL_BLOODSPLASH_PARTICLES, SMALL_BLOODSPLASH_ANGLE, startAt); // bs->moveTo(scpos->x, scpos->y, scpos->z); TEffectEngine::ee->scene->reinstalObject(bs); // return bs; } /////////////////////////////////////////////////////////////////////////////// // TExplosion // /////////////////////////////////////////////////////////////////////////////// int TExplosion::setUp(){ if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); if(pfAlpha) KMemFree(pfAlpha); // p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); pfAlpha = (float*)KMemAlloc( sizeof(float)*iCount ); // P3F ax = {0,0,1}; float ang; // float limit1 = RAND(0, (2*M_PI)); float limit2 = limit1+RAND(0, (2*M_PI)); // for(int i = 0; i < iCount; i++){ //nahodny smer ang = RAND(limit1, limit2); ROT(&(p3fStartDirection), &ax, ang, p3fDirections + i); //nahodna pocatecni rychlost MulV3( p3fDirections[i].p, RAND(fStartSpeedMin, fStartSpeedMax) ); //pozice CopyV3( p3fPositions[i].p, p3fStartPosition.p); //pocatecni pruhlednost; pfAlpha[i] = 1; } return 1; } void TExplosion::drawObject(){ if (getRealFade() != FADE_0) return; if(!draw_on)return; glPushMatrix(); glMultMatrixf(mx4Pos); glEnable(GL_POINT_SMOOTH); glDisable(GL_LIGHTING); glBegin(GL_POINTS); for(int i = 0; i < iCount; i++){ glColor4f(EXPLOSION_COLOR, pfAlpha[i]); glVertex3f(p3fPositions[i].x,p3fPositions[i].y,p3fPositions[i].z); if(i%(iCount/8) == 0){ glEnd(); glPointSize((8.0f*i)/iCount+1); glBegin(GL_POINTS); } } glEnd(); glEnable(GL_LIGHTING); glPopMatrix(); TSceneObject::drawObject(); } void TExplosion::update(int absoluteTime, int rtime, int step) { float dist = step/1000.0f; draw_on = 1; //vykeslovani zapnuto int alive = 0; // for(int i = 0; i < iCount; i++) { if(p3fPositions[i].z != 0) { p3fPositions[i] = (TVector(p3fPositions[i]) + TVector(p3fDirections[i])*dist ).toP3F(); p3fDirections[i] = (TVector(p3fDirections[i]) + TVector(TEffectEngine::ee->p3fSceneGravity)*dist ).toP3F(); //konec if(p3fPositions[i].z < 0){ p3fPositions[i].z = 0; SETV3(p3fDirections[i].p,0,0,0); } alive++; } else{ pfAlpha[i] *= fadeout_factor; if(pfAlpha[i] > disapper_limit) alive++; }//if z != 0 }//for // lets play if(iSoundFlag){ if(TSoundInterface::si) TSoundInterface::si->playSampleSpatialConrolled(SAMPLE_EXPLOSION, &aabbCenter); iSoundFlag = 0; } if(!alive){ TEffectEngine::ee->scene->remFromScene(this); if(parent_controller)parent_controller->removeChildControler(this); } } TExplosion::TExplosion(P3F* dir, P3F* pos, int pc, int startAt, float ssmin = 20, float ssmax = 45) :TParticles() { RTTID("explosion"); // pfAlpha = NULL; iCount = pc; CopyV3(p3fStartDirection.p, dir->p); CopyV3(p3fStartPosition.p, pos->p); // fStartSpeedMin = ssmin; fStartSpeedMax = ssmax; // fadeout_factor = 0.98f; disapper_limit = 0.5f; draw_on = 0; iSoundFlag = 1; // setUp(); // TEffectEngine::ee->scene->addObject(this); // TEffectEngine::ee->ctrlmng->addController(this); // if( startAt >= 0 ) activate(startAt); } TExplosion::~TExplosion(){ if(pfAlpha) KMemFree(pfAlpha); } TExplosion* TExplosion::installExplosion(P3F* dir, P3F* scpos, P3F* pos, int startAt, int particles = 30, float speed = 10) { TExplosion* ex = new TExplosion(dir, pos, particles, startAt, speed*0.8f, speed*1.2f); // ex->moveTo(scpos->x, scpos->y, scpos->z); TEffectEngine::ee->scene->reinstalObject(ex); // return ex; } /////////////////////////////////////////////////////////////////////////////// // TBillBoard // /////////////////////////////////////////////////////////////////////////////// TBillBoard::TBillBoard(TCamera *cam){ camera = cam; } void TBillBoard::screenBase(P3F* x, P3F* y){ P3F z; CopyV4toV3(z.p, camera->p4fDir.p); CopyV4toV3(y->p, camera->p4fUp.p); VectMulV3(x->p, z.p, y->p); NormalizeV3(x->p); NormalizeV3(y->p); } /////////////////////////////////////////////////////////////////////////////// // TSmoke // /////////////////////////////////////////////////////////////////////////////// int TSmoke::setUp() { if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); if(piOn) KMemFree(piOn); // p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); piOn = (int*)KMemAlloc( sizeof(int)*(iCount/4) ); // for(int i = 0; i < iCount/4; i++){ //rozptyl stoupani koure float xdir = RAND(0, 0.2f); float ydir = RAND(0, 0.2f); //smer oblacku SETV3(p3fDirections[4*i].p, xdir, ydir, 1 ); SETV3(p3fDirections[4*i+1].p, xdir, ydir, 1 ); SETV3(p3fDirections[4*i+2].p, xdir, ydir, 1 ); SETV3(p3fDirections[4*i+3].p, xdir, ydir, 1 ); // NormalizeV3( p3fDirections[4*i].p ); NormalizeV3( p3fDirections[4*i+1].p ); NormalizeV3( p3fDirections[4*i+2].p ); NormalizeV3( p3fDirections[4*i+3].p ); // float rand1 = RAND(fSpeedMin, fSpeedMax); float rand2 = RAND(fSpeedMin, fSpeedMax); // MulV3( p3fDirections[4*i].p, rand1 ); MulV3( p3fDirections[4*i+1].p, rand2 ); MulV3( p3fDirections[4*i+2].p, rand1*1.1f ); MulV3( p3fDirections[4*i+3].p, rand2*1.1f ); //poloha SETV3(p3fPositions[4*i].p, -fBaseDiam, 0, 0 ); SETV3(p3fPositions[4*i+1].p, fBaseDiam, 0, 0 ); SETV3(p3fPositions[4*i+2].p, fBaseDiam, 0, 2*fBaseDiam ); SETV3(p3fPositions[4*i+3].p, -fBaseDiam, 0, 2*fBaseDiam ); //zpozdeni piOn[i/4] = (int)RAND(0,fMaxHeight/(20*2)*1000); } return 1; } void TSmoke::update(int absoluteTime, int rtime, int step) { float dist = step/(float)TEffectEngine::ee->iPRP; P3F v; int nth = 0; int hi = iCount; // for(int i = 0; i < iCount; i++){ //start oblacku if( (absoluteTime-iActivationTime) < piOn[i/4] ) continue; else piOn[i/4] = 0; // CopyV3(v.p, p3fDirections[i].p); MulV3(v.p, dist); AddV3(p3fPositions[i].p, v.p); // if( !(i % 4) ) nth = 0; if(p3fPositions[i].z > fMaxHeight ){ hi--; nth++; } //restartuj oblacek if((nth == 4) && (iPermanent || iDur>0) ) { int t = i / 4; SETV3(p3fPositions[4*t].p, -fBaseDiam, 0, 0 ); SETV3(p3fPositions[4*t+1].p, fBaseDiam, 0, 0 ); SETV3(p3fPositions[4*t+2].p, fBaseDiam, 0, 2*fBaseDiam ); SETV3(p3fPositions[4*t+3].p, -fBaseDiam, 0, 2*fBaseDiam ); } } //prepocitej AABB // calculateAABB(); //vyprsel cas a vsechny body jsou vysoko if( (iDur<0) && !hi && !iPermanent ){ TEffectEngine::ee->scene->remFromScene(this); if(parent_controller)parent_controller->removeChildControler(this); } else iDur -= (int)(step*fTimeRatio); } void TSmoke::setTimeRatio(float tr, int recursive){ TParticles::setTimeRatio(tr, recursive); fTimeRatio = SMOKE_BASIC_TIMERATIO; } void TSmoke::drawObject() { if (getRealFade() != FADE_0) return; glPushMatrix(); glMultMatrixf(mx4Pos); //natoceni ke kamere P3F smokedir = {0,1,0};//mormala k oblacku P3F camdir; P3F rotang; //smer ke kamere getPosition(&camdir); SubV3(camdir.p, camera->p4fPos.p); camdir.z = 0; float ang = Angle3Db(&camdir, &smokedir); //natoc ke kamere VectMulV3(rotang.p, smokedir.p, camdir.p); glRotatef((float)Rad2Deg(ang), rotang.x, rotang.y, rotang.z); //nastaveni textury glBindTexture(GL_TEXTURE_2D, hTextureID); // glDisable(GL_LIGHTING); glDisable(GL_STENCIL_TEST); glDepthMask(false); glBegin(GL_QUADS); for(int i = 0; i < iCount; i++){ if( piOn[i/4] ) continue; // glColor4f(1,1,1, 1 - p3fPositions[i].z/MAX(fMaxHeight, p3fPositions[i].z)); if(i%4 == 0)glTexCoord2f(0,0); if(i%4 == 1)glTexCoord2f(1,0); if(i%4 == 2)glTexCoord2f(1,1); if(i%4 == 3)glTexCoord2f(0,1); glVertex3f(p3fPositions[i].x,p3fPositions[i].y,p3fPositions[i].z); } glEnd(); glDepthMask(true); glEnable(GL_LIGHTING); glEnable(GL_STENCIL_TEST); glBindTexture(GL_TEXTURE_2D, 0); glPopMatrix(); TSceneObject::drawObject(); } void TSmoke::smokeOut(int time){ if(time<0) iPermanent = 1; else{ iPermanent = 0; iDur = time; } } TSmoke::TSmoke(int bid, TCamera* cam, int clcount, float maxheight, int dur, float basediam, float speedmin, float speedmax) :TBillBoard(cam) { RTTID("smoke"); // TTextureManager::tm->loadTextureQuery(bid, &hTextureID); // piOn = NULL; // transparent = true; // iDur = dur; iPermanent = (dur<0); fSpeedMin = speedmin; fSpeedMax = speedmax; fBaseDiam = basediam; fMaxHeight = maxheight; iCount = 4*clcount; setUp(); } TSmoke::~TSmoke(){ } TSmoke* TSmoke::installSmoke(P3F* scpos, int startAt, int dur){ // gui::TCamera* cam = ((gui::TguiMap*)(TEffectEngine::ee->scene))->getCam(); // TSmoke* smoke = new TSmoke(RASTER_SMOKE, cam, 30, scpos->z + SMOKE_BASIC_HEIGHT, dur, 20); // TEffectEngine::ee->scene->addObject(smoke); smoke->setPosition(scpos->x, scpos->y, scpos->z); TEffectEngine::ee->scene->reinstalObject(smoke); // TEffectEngine::ee->ctrlmng->addController(smoke); // if( startAt >= 0 ) smoke->activate(startAt, 0); return smoke; } HWTID TSmoke::hSmokeTextureID = 0; void TSmoke::initSmokeTexture(){ TTextureManager::tm->loadTextureQuery(RASTER_SMOKE, &(TSmoke::hSmokeTextureID)); } /////////////////////////////////////////////////////////////////////////////// // TSimpleShadow // /////////////////////////////////////////////////////////////////////////////// #define SIMPLESHADOW_MAGIC_CONSTANT 0.5f void TSimpleShadow::drawRealShadow() { if(!hShadowTextureID)return; // glBindTexture(GL_TEXTURE_2D, hShadowTextureID); float mat[]={0,0,0,1}; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, mat); // glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex3f(points[0].x, points[0].y, points[0].z); glTexCoord2f(0,1); glVertex3f(points[1].x, points[1].y, points[1].z); glTexCoord2f(1,1); glVertex3f(points[2].x, points[2].y, points[2].z); glTexCoord2f(1,0); glVertex3f(points[3].x, points[3].y, points[3].z); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); } void TSimpleShadow::drawShadow() { drawShadowRequest(); } TSimpleShadow::TSimpleShadow(TAABB* obj, int bid) { object = obj; TTextureManager::tm->loadTextureQuery(bid, &(hShadowTextureID)); } void TSimpleShadow::drawShadowRequest(){ float radius = SizeV3(object->aabbDim.p)/2; gui::TguiMap* map = ((gui::TguiMap*)(TEffectEngine::ee->scene)); SETV3(points[0].p, object->aabbCenter.x-radius, object->aabbCenter.y-radius, 0); SETV3(points[1].p, object->aabbCenter.x+radius, object->aabbCenter.y-radius, 0); SETV3(points[2].p, object->aabbCenter.x+radius, object->aabbCenter.y+radius, 0); SETV3(points[3].p, object->aabbCenter.x-radius, object->aabbCenter.y+radius, 0); map->altitude(points[0].x, points[0].y, &(points[0].z)); map->altitude(points[1].x, points[1].y, &(points[1].z)); map->altitude(points[2].x, points[2].y, &(points[2].z)); map->altitude(points[3].x, points[3].y, &(points[3].z)); TSimpleShadow::shadows.push_back(this); } void TSimpleShadow::initShadowTextures() { TTextureManager::tm->loadTextureQuery(RASTER_SHADOW, &(TSimpleShadow::hSmallShadowTextureID)); } void TSimpleShadow::drawSecondPassShadows() { //nastaveni vykreslovani jen na mista prijimajici stiny glStencilFunc(GL_EQUAL,1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); //nastaveni projekcni matice na zvetseni hodnoty v zbufferu glMatrixMode(GL_PROJECTION); float matrix[16]; glGetFloatv(GL_PROJECTION_MATRIX, matrix); matrix[14]-=SIMPLESHADOW_MAGIC_CONSTANT; glLoadMatrixf(matrix); // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); //vykresli vsechny stiny for(vector::iterator it = TSimpleShadow::shadows.begin(); it != TSimpleShadow::shadows.end(); it++) { (*it)->drawRealShadow(); } // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // matrix[14]+= SIMPLESHADOW_MAGIC_CONSTANT; glLoadMatrixf(matrix); } void TSimpleShadow::drawThirdPassShadows(){ //nastaveni vykreslovani jen na mista prijimajici stiny glStencilFunc(GL_LESS, 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // glDisable(GL_DEPTH_TEST); //vykresli vsechny stiny for(vector::iterator it = TSimpleShadow::shadows.begin(); it != TSimpleShadow::shadows.end(); it++) { (*it)->drawRealShadow(); } glEnable(GL_DEPTH_TEST); } HWTID TSimpleShadow::hSmallShadowTextureID = 0; vector TSimpleShadow::shadows; /////////////////////////////////////////////////////////////////////////////// // TDistantAttack // /////////////////////////////////////////////////////////////////////////////// int TDistantAttack::setUp(){ if( datType == datMagicMissile ){ //vytvor castice okoli zdroje nahodne zdroji // iCount = 50; // if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); if(fvVisibility) KMemFree(fvVisibility); p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); fvVisibility = (float*)KMemAlloc( sizeof(float)*iCount ); // for(int i = 0; i < iCount; i++){ SETV3(p3fPositions[i].p, 0, 0, 0); CopyV3(p3fDirections[i].p, TEffectEngine::ee->p3fSceneGravity.p); MulV3(p3fDirections[i].p, 0.01f); fvVisibility[i] = -1; } } return 1; } void TDistantAttack::update(int absoluteTime, int rtime, int step) { float dist = step/(float)TEffectEngine::ee->iPRP; //modifikace pozice if( iRemaining > 0 ){ //kineticka slozka P3F dir; CopyV3(dir.p, p3fDir.p); MulV3(dir.p, dist); AddV3(p3fPos.p, dir.p); //modifikace smeru gravitaci P3F grav; CopyV3(grav.p, p3fGrav.p); MulV3(grav.p, dist); AddV3(p3fDir.p, grav.p); //nastavit orientaci soustavy MX4 m; P3F T,N, B; VectMulV3(N.p, p3fGrav.p, p3fDir.p); VectMulV3(B.p, N.p, p3fDir.p); CopyV3(T.p, p3fDir.p); NormalizeV3(T.p); NormalizeV3(N.p); NormalizeV3(B.p); SetMX4(m, T.x, T.y, T.z, 0, N.x, N.y, N.z, 0, B.x, B.y, B.z, 0, p3fPos.x, p3fPos.y, p3fPos.z, 1); setPositionMX4(m); TEffectEngine::ee->scene->reinstalObject(this); msoProjectile->setPositionMX4(m); TEffectEngine::ee->scene->reinstalObject(msoProjectile); } //castice if( datType == datMagicMissile && iRemaining > 0 ){ //v jaky casti cesty jsem float f = 1-iRemaining/(float)iDur; int p = (int)(f*iCount); //uz byla uvolnena x-ta castice if(fvVisibility[p] < 0){ //nastav pozici a zviditelni p3fPositions[p] = p3fPos; p3fPositions[p].x += RAND(-15,15); p3fPositions[p].y += RAND(-15,15); p3fPositions[p].z += RAND(-15,15); fvVisibility[p] = 1; } } //updatuj pozice int visible = 0; for(int i = 0; i < iCount; i++){ // AddV3(p3fPositions[i].p, p3fDirections[i].p); fvVisibility[i] -= step/5000.0f; // if( fvVisibility[i] > 0 ) visible++; } //prehrej zvuk if(iSoundFlag){ if(TSoundInterface::si){ switch(datType){ case datArrow: TSoundInterface::si->playSampleSpatialConrolled(SAMPLE_ARROW_ATTACK, &p3fPos); break; case datCatapultProjectile: TSoundInterface::si->playSampleSpatialConrolled(SAMPLE_CATAPULT_ATTACK, &p3fPos); break; } }//if iSoundFlag = 0; }//if // iStarted = 1; // if( (iRemaining < 0) && !visible ){ TEffectEngine::ee->scene->remFromScene(this); if(parent_controller)parent_controller->removeChildControler(this); } else{ iRemaining -= (int)(step*fTimeRatio); } } void TDistantAttack::drawObject(){ if (getRealFade() != FADE_0) return; if(!iStarted)return; // if(!msoProjectile) { glPushMatrix(); glMultMatrixf(mx4Pos); switch(datType){ case datArrow:{ glLineWidth(4); glBegin(GL_LINES); glVertex3f(0, 0, 0); glVertex3f(10,0,0); glEnd(); glLineWidth(1); }break; case datMagicMissile: case datCatapultProjectile:{ glPointSize(16); glBegin(GL_POINTS); glVertex3f(0, 0, 0); glEnd(); glPointSize(1); }break; }//switch glPopMatrix(); }//if if(datType == datMagicMissile) { glPointSize(10); glDisable(GL_LIGHTING); glBegin(GL_POINTS); for(int i = 0; i < iCount; i++){ if(fvVisibility[i]>0){ glColor4f(0, 0, 0, fvVisibility[i]); glVertex3f(p3fPositions[i].x,p3fPositions[i].y,p3fPositions[i].z); } } glEnd(); glEnable(GL_LIGHTING); glPointSize(1); } TSceneObject::drawObject(); } void TDistantAttack::setTimeRatio(float tr, int recursive){ TParticles::setTimeRatio(tr, recursive); fTimeRatio = DA_BASIC_TIMERATIO; } /* aproximace */ void TDistantAttack::calculateAABB(){ // CopyV3(aabbCenter.p, p3fPos.p); // SETV3(aabbDim.p, 10, 10, 10); } TDistantAttack::TDistantAttack(P3F* attacker, P3F* target, TDistantAttackType dat, int startAt) { RTTID("distatt"); datType = dat; fvVisibility = NULL; msoProjectile = NULL; iStarted = 0; iSoundFlag = 1; selectable = false; //vzdalenosti float dist3d = DISTV3(attacker->p, target->p); float dist2d = DISTV2(attacker->p, target->p); float projectilespeed, dur, envres; rm::TRM_model_i* rmm = (rm::TRM_model_i*) KSendGlobalMessage(MSG_GET_RM_MODEL_I,MOD_GUI,MOD_RM,NULL); if(!rmm) THROW(E_8K_GUI, "TDistantAttack::TDistantAttack(): failed to query rmmodel interface\n"); TModel* rm_projmodel = NULL; //vlastnosti podle typu switch(datType){ case datArrow:{ //rychlost strely v jednotkach za milisekundu projectilespeed = RAND(0.2f, 0.50f); //odpor prostredi, zavis na tvaru strely, zjisteno experimentalne envres = RAND(3.6f, 4.4f); //vyber model rm_projmodel = rmm->get(MODEL_ARROW); } break; case datCatapultProjectile:{ //rychlost strely v jednotkach za milisekundu projectilespeed = RAND(0.25f, 0.35f); //odpor prostredi, zavis na tvaru strely envres = RAND(4.0f, 6.4f); //vyber model rm_projmodel = rmm->get(MODEL_CATAPULT_PROJECTILE); } break; case datMagicMissile:{ //rychlost strely v jednotkach za milisekundu projectilespeed = RAND(0.5f, 0.8f); //odpor prostredi, zavis na tvaru strely envres = RAND(10, 15); //vyber model rm_projmodel = rmm->get(MODEL_CATAPULT_PROJECTILE); } break; } //doba trvani v milisekundach dur = (float)(dist3d/projectilespeed)*envres; iDur = ROUND(dur); iRemaining = iDur; //sceneobject msoProjectile = new TModelSceneObject(rm_projmodel); TEffectEngine::ee->scene->addObject(msoProjectile); //gravitacni slozka v jednotkach za iPRP CopyV3(p3fGrav.p, TEffectEngine::ee->p3fSceneGravity.p); MulV3(p3fGrav.p, (fTimeRatio)/(TEffectEngine::ee->iPRP*envres)); //pohybova slozka ve smeru cile za iPRP CopyV2(p3fDir.p, target->p); SubV2(p3fDir.p, attacker->p); NormalizeV2(p3fDir.p); MulV2(p3fDir.p, TEffectEngine::ee->iPRP*(dist2d/dur)); //vypocet stoupani int slices = (int)ceil( dur/TEffectEngine::ee->iPRP ); p3fDir.z = (float)(target->z - attacker->z - 0.5f*SQR(slices)*p3fGrav.z) / slices; //pozice modelu & nastaveni castic CopyV3(p3fPos.p, attacker->p); setUp(); //pocatek moveTo(p3fPos.x, p3fPos.y, p3fPos.z); TEffectEngine::ee->scene->addObject(this); TEffectEngine::ee->ctrlmng->addController(this); // if( startAt >= 0 ) activate(startAt); // delete rmm; } /////////////////////////////////////////////////////////////////////////////// // TDistant_Attack // /////////////////////////////////////////////////////////////////////////////// TDistant_Attack::TDistant_Attack(P3F* source, P3F* target, P3F* homing, int startAt) :TController() { RTTID("distatt"); // p3fSource = *source; p3fTarget = *target; pp3fHoming = homing; iStarted = 0; iSoundSample = 0; iDur = ROUND( DISTV3(source->p, target->p) ); iRemaining = iDur; //pocatek TEffectEngine::ee->ctrlmng->addController(this); // if( startAt >= 0 ) activate(startAt); } void TDistant_Attack::update(int absoluteTime) { if(iActivationTime>absoluteTime) return; //prehrej zvuk if(iSoundSample){ if(TSoundInterface::si){ TSoundInterface::si->playSampleSpatialConrolled(iSoundSample, &p3fSource); }//if iSoundSample = 0; }//if // iStarted = 1; } void TDistant_Attack::setTimeRatio(float tr, int recursive) { TController::setTimeRatio(tr, recursive); fTimeRatio = DA_BASIC_TIMERATIO; } /////////////////////////////////////////////////////////////////////////////// // TProjectileAttack // /////////////////////////////////////////////////////////////////////////////// void TProjectileAttack::update(int absoluteTime) { if(iActivationTime>absoluteTime)return; TDistant_Attack::update(absoluteTime); //cas int step = absoluteTime - iLastTime; if(step < TEffectEngine::ee->iPRP)return; iLastTime = absoluteTime; float dist = step*fTimeRatio/TEffectEngine::ee->iPRP; //modifikace pozice if( iRemaining > 0 ){ //kineticka slozka P3F dir; CopyV3(dir.p, p3fDir.p); MulV3(dir.p, dist); AddV3(p3fPos.p, dir.p); //modifikace smeru gravitaci P3F grav; CopyV3(grav.p, p3fGrav.p); MulV3(grav.p, dist); AddV3(p3fDir.p, grav.p); //nastavit orientaci soustavy setPosition(&p3fPos, &p3fDir, &p3fGrav); TEffectEngine::ee->scene->reinstalObject(this); } // if( (iRemaining < 0) ){ TEffectEngine::ee->scene->remFromScene(this); if(parent_controller)parent_controller->removeChildControler(this); } else{ iRemaining -= (int)(step*fTimeRatio); } } void TProjectileAttack::drawObject(){ if(iStarted) { float mat[] = {PROJECTILE_ATTACK_COLOR}; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, mat); TModelSceneObject::drawObject(); } } TProjectileAttack::TProjectileAttack(P3F* source, P3F* target, P3F* homing, int startAt, float speed, float envres, TModel* mod) :TModelSceneObject(mod), TDistant_Attack(source, target, homing, startAt) { selectable = false; //vzdalenosti float dist3d = DISTV3(source->p, target->p); float dist2d = DISTV2(source->p, target->p); //doba trvani v milisekundach float dur = (float)(dist3d/speed)*envres; iDur = ROUND(dur); iRemaining = iDur; //gravitacni slozka v jednotkach za iPRP CopyV3(p3fGrav.p, TEffectEngine::ee->p3fSceneGravity.p); MulV3(p3fGrav.p, (fTimeRatio)/(TEffectEngine::ee->iPRP*envres)); //pohybova slozka ve smeru cile za iPRP CopyV2(p3fDir.p, target->p); SubV2(p3fDir.p, source->p); NormalizeV2(p3fDir.p); MulV2(p3fDir.p, TEffectEngine::ee->iPRP*(dist2d/dur)); //vypocet stoupani int slices = (int)ceil( dur/TEffectEngine::ee->iPRP ); p3fDir.z = (float)(target->z - source->z - 0.5f*SQR(slices)*p3fGrav.z) / slices; //pozice modelu & nastaveni castic CopyV3(p3fPos.p, source->p); //pocatek setPosition(&p3fPos, &p3fDir, &p3fGrav); TEffectEngine::ee->scene->addObject(this); } TModel* TProjectileAttack::getProjectileModel(int id) { // rm::TRM_model_i* rmm = (rm::TRM_model_i*) KSendGlobalMessage(MSG_GET_RM_MODEL_I,MOD_GUI,MOD_RM,NULL); if(!rmm) THROW(E_8K_GUI, "TCatapultAttack::TCatapultAttack(): failed to query rmmodel interface\n"); TModel* rm_projmodel = rm_projmodel = rmm->get(id); delete rmm; // return rm_projmodel; } TProjectileAttack* TProjectileAttack::installSimpleProjectile(P3F* attacker, P3F* target, TDistantAttackType dat, int startAt) { // TModel* rm_projmodel = NULL; float projectilespeed, envres; // switch(dat){ case datArrow:{ //rychlost strely v jednotkach za milisekundu projectilespeed = RAND(0.2f, 0.50f); //odpor prostredi, zavis na tvaru strely, zjisteno experimentalne envres = RAND(3.6f, 4.4f); //vyber model rm_projmodel = TProjectileAttack::getProjectileModel(MODEL_ARROW); } break; case datCatapultProjectile:{ //rychlost strely v jednotkach za milisekundu projectilespeed = RAND(0.25f, 0.35f); //odpor prostredi, zavis na tvaru strely envres = RAND(4.0f, 6.4f); //vyber model rm_projmodel = TProjectileAttack::getProjectileModel(MODEL_CATAPULT_PROJECTILE); } break; case datMagicMissile:{ //rychlost strely v jednotkach za milisekundu projectilespeed = RAND(1, 2); //odpor prostredi, zavis na tvaru strely envres = RAND(4.0f, 6.4f); //vyber model rm_projmodel = TProjectileAttack::getProjectileModel(MODEL_MAGIC_MISSILE); } break; } // TProjectileAttack* pa = new TProjectileAttack(attacker, target, NULL, startAt, projectilespeed, envres, rm_projmodel); // return pa; } HWTID TProjectileAttack::hParticleTexture = 0; HWTID TProjectileAttack::hWaveTexture = 0; void TProjectileAttack::initProjectiles(){ TTextureManager::tm->loadTextureQuery(RASTER_PARTICLE, &(TProjectileAttack::hParticleTexture)); TTextureManager::tm->loadTextureQuery(RASTER_WAVE, &(TProjectileAttack::hWaveTexture)); } /////////////////////////////////////////////////////////////////////////////// // TArrowAttack // /////////////////////////////////////////////////////////////////////////////// void TArrowAttack::update(int absoluteTime){ TProjectileAttack::update(absoluteTime); //update stopy P3F prev; getPosition(&prev); for(int i = 0; i < TRACE_SIZE; i++){ float dist = DISTV2(prev.p, trace[i].p); if(dist>TRACE_STEP_SIZE){ trace[i] = (TVector(prev) + (TVector(trace[i])-TVector(prev)).norm()*TRACE_STEP_SIZE).toP3F(); } prev = trace[i]; } } void TArrowAttack::drawObject(){ TProjectileAttack::drawObject(); // glDisable(GL_LIGHTING); glLineWidth(2); glBegin(GL_LINE_STRIP); for(int i = 0; i < TRACE_SIZE; i++){ float c = (TRACE_SIZE-i)/(float)TRACE_SIZE; glColor4f(1,1,1,c); glVertex3f(trace[i].x, trace[i].y, trace[i].z); } glEnd(); glLineWidth(1); glEnable(GL_LIGHTING); } TArrowAttack::TArrowAttack(P3F* source, P3F* target, P3F* homing, int startAt, float speed, float envres, TModel* mod) :TProjectileAttack(source, target, homing, startAt, speed, envres, mod) { // iSoundSample = SAMPLE_ARROW_ATTACK; // for(int i = 0; i < TRACE_SIZE; i++) trace[i] = *source; } TArrowAttack* TArrowAttack::installArrowAttack(P3F* attacker, P3F* target, int startAt){ //vyber model TModel* rm_projmodel = TProjectileAttack::getProjectileModel(MODEL_ARROW); //rychlost strely v jednotkach za milisekundu float projectilespeed = RAND(0.2f, 0.50f); //odpor prostredi, zavis na tvaru strely float envres = RAND(3.6f, 4.4f); // TArrowAttack* aa = new TArrowAttack(attacker, target, NULL, startAt, projectilespeed, envres, rm_projmodel); aa->setTimeRatio(DA_BASIC_TIMERATIO, true); // return aa; } /////////////////////////////////////////////////////////////////////////////// // TCatapultAttack // /////////////////////////////////////////////////////////////////////////////// TCatapultAttack::TCatapultAttack(TCamera* cam, P3F* source, P3F* target, P3F* homing, int startAt, float speed, float envres, TModel* mod) :TParticles(), TBillBoard(cam), TProjectileAttack(source, target, homing, startAt, speed, envres, mod) { // fvVisibility = NULL; TProjectileAttack::transparent = true; fWaveRadius = 0; fWaveTransparency = 1; iSoundSample = SAMPLE_CATAPULT_ATTACK; // iCount = (int)(DISTV3(source->p, target->p) * CATAPULT_TRACE_DENSITY); // setUp(); // disk = gluNewQuadric(); } TCatapultAttack::~TCatapultAttack(){ if(fvVisibility) KMemFree(fvVisibility); if(disk) gluDeleteQuadric(disk); } void TCatapultAttack::update(int absoluteTime, int rtime, int step) { //castice if( iRemaining > 0 ){ //v jaky casti cesty jsem float f = 1-iRemaining/(float)iDur; int p = (int)(f*iCount); //uz byla uvolnena x-ta castice if(fvVisibility[p] < 0){ //nastav pozici a zviditelni p3fPositions[p] = p3fPos; p3fPositions[p].x += -p3fDir.x*RAND(-2,12); p3fPositions[p].y += -p3fDir.y*RAND(-2,12); p3fPositions[p].z += -p3fDir.z*RAND(-2,12); fvVisibility[p] = 1; } } //updatuj pozice int visible = 0; for(int i = 0; i < iCount; i++){ // AddV3(p3fPositions[i].p, p3fDirections[i].p); fvVisibility[i] -= step/5000.0f; // if( fvVisibility[i] > 0 ) visible++; } if(iRemaining<0 && visible!=0) iRemaining=0; //odstartuj animaci tlakove vlny if(iRemaining<=0 && fWaveRadius<=0){ fWaveRadius = 20; P3F pos = {0,0,1}; P3F dir = (TVector(p3fDir).norm()*0.1f).toP3F(); dir.z*=-5; TExplosion* ex = TExplosion::installExplosion(&dir, &p3fPos, &pos, absoluteTime, 150, 100.0); ex->setTimeRatio( TProjectileAttack::fTimeRatio*3, 0 ); } //animuj tlakovou vlnu if(fWaveRadius>0){ fWaveRadius+=step*0.15f; fWaveTransparency*=0.85f; } } void TCatapultAttack::update(int absoluteTime) { TProjectileAttack::update(absoluteTime); TAdvController::update(absoluteTime);//>TCatapultAttack::update(int,int,int) } int TCatapultAttack::setUp(){ //vytvor castice okoli zdroje nahodne zdroji // if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); if(fvVisibility) KMemFree(fvVisibility); p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); fvVisibility = (float*)KMemAlloc( sizeof(float)*iCount ); // for(int i = 0; i < iCount; i++){ SETV3(p3fPositions[i].p, 0, 0, 0); CopyV3(p3fDirections[i].p, TEffectEngine::ee->p3fSceneGravity.p); MulV3(p3fDirections[i].p, -0.05f); p3fDirections[i].x *= RAND(1,1.2f); p3fDirections[i].y *= RAND(1,1.2f); p3fDirections[i].z *= RAND(1,1.2f); fvVisibility[i] = -1; } return 1; } void TCatapultAttack::drawObject(){ if(!iStarted)return; P3F camup, cambi; glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDepthMask(false); glDisable(GL_STENCIL_TEST); //vlna if(fWaveRadius>0){ glPushMatrix(); glTranslatef(p3fTarget.x,p3fTarget.y,p3fTarget.z); // glColor4f(CATAPULT_WAVE_COLOR, fWaveTransparency); glBindTexture(GL_TEXTURE_2D, TProjectileAttack::hWaveTexture); gluQuadricTexture(disk,GL_TRUE); gluDisk(disk, 0, fWaveRadius, 32,1); // glPopMatrix(); } //jiskry screenBase(&cambi, &camup); MulV3(cambi.p,CATAPULT_TRACE_PARTICLE_SIZE); MulV3(camup.p,CATAPULT_TRACE_PARTICLE_SIZE); // glBindTexture(GL_TEXTURE_2D, TProjectileAttack::hParticleTexture); glBegin(GL_QUADS); for(int i = 0; i < iCount; i++){ glColor4f(CATAPULT_TRACE_PARTICLE_COLOR, fvVisibility[i]); glTexCoord2f(0,0); glVertex3f(p3fPositions[i].x + cambi.x - camup.x, p3fPositions[i].y + cambi.y - camup.y, p3fPositions[i].z + cambi.z - camup.z); glTexCoord2f(0,1); glVertex3f(p3fPositions[i].x + cambi.x + camup.x, p3fPositions[i].y + cambi.y + camup.y, p3fPositions[i].z + cambi.z + camup.z); glTexCoord2f(1,1); glVertex3f(p3fPositions[i].x - cambi.x + camup.x, p3fPositions[i].y - cambi.y + camup.y, p3fPositions[i].z - cambi.z + camup.z); glTexCoord2f(1,0); glVertex3f(p3fPositions[i].x - cambi.x - camup.x, p3fPositions[i].y - cambi.y - camup.y, p3fPositions[i].z - cambi.z - camup.z); } glEnd(); glEnable(GL_STENCIL_TEST); glDepthMask(true); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glBindTexture(GL_TEXTURE_2D, 0); TProjectileAttack::drawObject(); } void TCatapultAttack::calculateAABB() { TParticles::calculateAABB(); TAABB part; part.copyAABB((TProjectileAttack*)this); TProjectileAttack::calculateAABB(); TProjectileAttack::addAABB(&part); } TCatapultAttack* TCatapultAttack::installCatapultProjectile(P3F* attacker, P3F* target, int startAt) { //vyber model TModel* rm_projmodel = TProjectileAttack::getProjectileModel(MODEL_CATAPULT_PROJECTILE); //rychlost strely v jednotkach za milisekundu float projectilespeed = RAND(0.25f, 0.35f); //odpor prostredi, zavis na tvaru strely float envres = RAND(4.0f, 6.4f); // gui::TCamera* cam = ((gui::TguiMap*)(TEffectEngine::ee->scene))->getCam(); // TCatapultAttack* ca = new TCatapultAttack(cam, attacker, target, NULL, startAt, projectilespeed, envres, rm_projmodel); ca->TProjectileAttack::setTimeRatio(DA_BASIC_TIMERATIO, true); // return ca; } /////////////////////////////////////////////////////////////////////////////// // TMagicMissileAttack // /////////////////////////////////////////////////////////////////////////////// TMagicMissileAttack::TMagicMissileAttack(TCamera* cam, P3F* source, P3F* target, P3F* homing, int startAt, float speed, float envres, TModel* mod) :TParticles(), TBillBoard(cam), TProjectileAttack(source, target, homing, startAt, speed, envres, mod) { // fvVisibility = NULL; fWaveRadius = 0; fWaveTransparency = 1; TProjectileAttack::transparent = true; iSoundSample = SAMPLE_FIREBALL; // iCount = (int)(DISTV3(source->p, target->p) * MAGIC_TRACE_DENSITY); // setUp(); // disk = gluNewQuadric(); } TMagicMissileAttack::~TMagicMissileAttack(){ if(fvVisibility) KMemFree(fvVisibility); if(disk) gluDeleteQuadric(disk); } void TMagicMissileAttack::update(int absoluteTime, int rtime, int step) { //castice if( iRemaining > 0 ){ //v jaky casti cesty jsem float f = 1-iRemaining/(float)iDur; int p = (int)(f*iCount); //uz byla uvolnena x-ta castice while( fvVisibility[p]<0 && p>=0 ) { //nastav pozici a zviditelni p3fPositions[p] = p3fPos; p3fPositions[p].x += -p3fDir.x*RAND(-1,3); p3fPositions[p].y += -p3fDir.y*RAND(-1,3); p3fPositions[p].z += -p3fDir.z*RAND(-1,3); fvVisibility[p] = 1; p--; } } //updatuj pozice int visible = 0; for(int i = 0; i < iCount; i++){ // AddV3(p3fPositions[i].p, p3fDirections[i].p); fvVisibility[i] -= step/2000.0f; // if( fvVisibility[i] > 0 ) visible++; } //drz na nule, aby se nesplasil if(iRemaining<0 && visible!=0) iRemaining=0; //odstartuj animaci tlakove vlny if(iRemaining<=0 && fWaveRadius<=0){ fWaveRadius = 30; } //animuj tlakovou vlnu if(fWaveRadius>0){ fWaveRadius+=step*0.1f; fWaveTransparency*=0.85f; } } void TMagicMissileAttack::update(int absoluteTime){ TProjectileAttack::update(absoluteTime); TAdvController::update(absoluteTime); } int TMagicMissileAttack::setUp(){ //vytvor castice okoli zdroje nahodne zdroji // if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); if(fvVisibility) KMemFree(fvVisibility); p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); fvVisibility = (float*)KMemAlloc( sizeof(float)*iCount ); // for(int i = 0; i < iCount; i++){ SETV3(p3fPositions[i].p, 0, 0, 0); CopyV3(p3fDirections[i].p, TEffectEngine::ee->p3fSceneGravity.p); MulV3(p3fDirections[i].p, 0.05f); p3fDirections[i].x *= RAND(1,1.2f); p3fDirections[i].y *= RAND(1,1.2f); p3fDirections[i].z *= RAND(1,1.2f); fvVisibility[i] = -1; } return 1; } void TMagicMissileAttack::drawObject(){ if(!iStarted)return; glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDepthMask(false); glDisable(GL_STENCIL_TEST); //vlna if(fWaveRadius>0){ glPushMatrix(); glTranslatef(p3fTarget.x,p3fTarget.y,p3fTarget.z); // glColor4f(MAGIC_MISSILE_WAVE_COLOR, fWaveTransparency); glBindTexture(GL_TEXTURE_2D, TProjectileAttack::hWaveTexture); gluQuadricTexture(disk,GL_TRUE); gluDisk(disk, 0, fWaveRadius, 32,1); // glPopMatrix(); } //jiskry P3F camup, cambi; screenBase(&cambi, &camup); MulV3(cambi.p,MAGIC_TRACE_PARTICLE_SIZE); MulV3(camup.p,MAGIC_TRACE_PARTICLE_SIZE); // glBindTexture(GL_TEXTURE_2D, TProjectileAttack::hParticleTexture); glBegin(GL_QUADS); for(int i = 0; i < iCount; i++){ glColor4f(MAGIC_TRACE_PARTICLE_COLOR, fvVisibility[i]); glTexCoord2f(0,0); glVertex3f(p3fPositions[i].x + cambi.x - camup.x, p3fPositions[i].y + cambi.y - camup.y, p3fPositions[i].z + cambi.z - camup.z); glTexCoord2f(0,1); glVertex3f(p3fPositions[i].x + cambi.x + camup.x, p3fPositions[i].y + cambi.y + camup.y, p3fPositions[i].z + cambi.z + camup.z); glTexCoord2f(1,1); glVertex3f(p3fPositions[i].x - cambi.x + camup.x, p3fPositions[i].y - cambi.y + camup.y, p3fPositions[i].z - cambi.z + camup.z); glTexCoord2f(1,0); glVertex3f(p3fPositions[i].x - cambi.x - camup.x, p3fPositions[i].y - cambi.y - camup.y, p3fPositions[i].z - cambi.z - camup.z); } glEnd(); // glEnable(GL_STENCIL_TEST); glDepthMask(true); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); //projektyl if(iRemaining>0){ float mat[] = {MAGIC_MISSILE_COLOR,1}; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, mat); glBindTexture(GL_TEXTURE_2D, 0); if(iStarted) TModelSceneObject::drawObject(); } } TMagicMissileAttack* TMagicMissileAttack::installMagicMissileAttack(P3F* attacker, P3F* target, int startAt) { //vyber model TModel* rm_projmodel = TProjectileAttack::getProjectileModel(MODEL_MAGIC_MISSILE); //rychlost strely v jednotkach za milisekundu float projectilespeed = RAND(1,2); //odpor prostredi, zavis na tvaru strely float envres = RAND(4.0f, 6.4f); // gui::TCamera* cam = ((gui::TguiMap*)(TEffectEngine::ee->scene))->getCam(); // TMagicMissileAttack* mma = new TMagicMissileAttack(cam, attacker, target, NULL, startAt, projectilespeed, envres, rm_projmodel); mma->TProjectileAttack::setTimeRatio(DA_BASIC_TIMERATIO, true); // return mma; } /////////////////////////////////////////////////////////////////////////////// // TDestruction // /////////////////////////////////////////////////////////////////////////////// int TDestruction::setUp(){ if(p3fDirections) KMemFree(p3fDirections); if(p3fPositions) KMemFree(p3fPositions); if(pfAlpha) KMemFree(pfAlpha); // p3fDirections = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); p3fPositions = (P3F*)KMemAlloc( sizeof(P3F)*iCount ); pfAlpha = (float*)KMemAlloc( sizeof(float)*iCount ); // int updates = (int)(iDur/TEffectEngine::ee->iPRP); float vectsize = (fRadMax/updates); // for(int i = 0; i < iCount; i++){ p3fPositions[i].x = 0; p3fPositions[i].y = 0; p3fPositions[i].z = 0; // p3fDirections[i].x = RAND(-1,1); p3fDirections[i].y = RAND(-1,1); p3fDirections[i].z = RAND(-1,1); // NormalizeV3(p3fDirections[i].p); MulV3(p3fDirections[i].p, vectsize*RAND(1,10)); // pfAlpha[i] = 1; } return 0; } void TDestruction::update(int absoluteTime, int rtime, int step) { //normalizace float dist = (step/(float)TEffectEngine::ee->iPRP); //velikost exploze float fact = ((float)rtime)/iDur; fRad = fRadMin + (fRadMax - fRadMin) * (float)(log(20*fact+1)/log(20.0)); fDiskRad = (float)pow((double)fRad, 1.1); //pruhlednost expoloze const float hold = 0.2f; if(fact>hold){ float tfact = fact/(1-hold)-hold/(1-hold); fTransparency = 1-(float)(log(10*tfact+1)/log(10.0)); }else fTransparency = 1; //update castic for(int i = 0; i < iCount; i++){ AddV3(p3fPositions[i].p, p3fDirections[i].p); pfAlpha[i] = fTransparency; } //camerashake P3F epicentrum; P3F campos; float shakestrength = 0; getPosition(&epicentrum); camera->getPosition(&campos); // shakestrength = TVector( TVector(epicentrum) - TVector(campos) ).len(); shakestrength = MAX_SHAKERSTRENGTH*(MAX_SHAKERDISTANCE/(shakestrength+MAX_SHAKERDISTANCE)); if(shakestrength<1) shakestrength=0; shakestrength *= (1-fact); // campos.x += RAND(-shakestrength, shakestrength); campos.y += RAND(-shakestrength, shakestrength); campos.z += RAND(-shakestrength, shakestrength); camera->setPosition(&campos); if(iSoundFlag){ if(TSoundInterface::si) TSoundInterface::si->playSampleSpatialConrolled(SAMPLE_DESTRUCTION, &aabbCenter); iSoundFlag = 0; } //odstraneni if( rtime > iDur){ TEffectEngine::ee->scene->remFromScene(this); if(parent_controller)parent_controller->removeChildControler(this); } } void TDestruction::setTimeRatio(float tr, int recursive){ TParticles::setTimeRatio(tr, recursive); fTimeRatio /= 2; } void TDestruction::drawObject() { if (getRealFade() != FADE_0) return; P3F camdir, camup, cambi; // glPushMatrix(); glMultMatrixf(mx4Pos); glDisable(GL_LIGHTING); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); //sfera glColor4f(DESTRUCTION_SPHERE_COLOR, fTransparency); glBindTexture(GL_TEXTURE_2D, TDestruction::hSimpleSphereTextureID); gluQuadricTexture(sphere,GL_TRUE); gluSphere(sphere, fRad, 16, 16); //disk glColor4f(DESTRUCTION_DISK_COLOR, fTransparency); glBindTexture(GL_TEXTURE_2D, TDestruction::hSimpleWaveTextureID); gluQuadricTexture(disk,GL_TRUE); gluDisk(disk, 0, fDiskRad, 32,1); //jiskry CopyV4toV3(camdir.p, camera->p4fDir.p); CopyV4toV3(camup.p, camera->p4fUp.p); VectMulV3(cambi.p, camdir.p, camup.p); NormalizeV3(cambi.p); NormalizeV3(camup.p); MulV3(cambi.p,FLARESIZE); MulV3(camup.p,FLARESIZE); // glBindTexture(GL_TEXTURE_2D, TDestruction::hSimpleParticleTextureID); glBegin(GL_QUADS); for(int i = 0; i < iCount; i++){ glColor4f(DESTRUCTION_SPARKLE_COLOR, pfAlpha[i]); glTexCoord2f(0,0); glVertex3f(p3fPositions[i].x + cambi.x - camup.x, p3fPositions[i].y + cambi.y - camup.y, p3fPositions[i].z + cambi.z - camup.z); glTexCoord2f(0,1); glVertex3f(p3fPositions[i].x + cambi.x + camup.x, p3fPositions[i].y + cambi.y + camup.y, p3fPositions[i].z + cambi.z + camup.z); glTexCoord2f(1,1); glVertex3f(p3fPositions[i].x - cambi.x + camup.x, p3fPositions[i].y - cambi.y + camup.y, p3fPositions[i].z - cambi.z + camup.z); glTexCoord2f(1,0); glVertex3f(p3fPositions[i].x - cambi.x - camup.x, p3fPositions[i].y - cambi.y - camup.y, p3fPositions[i].z - cambi.z - camup.z); } glEnd(); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glEnable(GL_LIGHTING); glPopMatrix(); TSceneObject::drawObject(); } TDestruction::TDestruction(P3F* scpos, TCamera* cam, int startAt, int dur, float rmin, float rmax, int flares) :TBillBoard(cam) { RTTID("destr"); //data sphere = gluNewQuadric(); disk = gluNewQuadric(); //mod vykreslovani transparent = true; if( startAt >= 0 ) activate(startAt); //natav cas iDur = dur; fRadMax = rmax; fRadMin = rmin; fRad = fRadMin; fDiskRad = fRadMin; iCount = flares; pfAlpha = NULL; iSoundFlag = 1; setUp(); //umisti na scenu TEffectEngine::ee->scene->addObject(this); moveTo(scpos->x, scpos->y, scpos->z); TEffectEngine::ee->scene->reinstalObject(this); //umisteni do managera TEffectEngine::ee->ctrlmng->addController(this); } TDestruction::~TDestruction(){ if(sphere) gluDeleteQuadric(sphere); if(disk) gluDeleteQuadric(disk); if(pfAlpha) KMemFree(pfAlpha); } HWTID TDestruction::hSimpleParticleTextureID = 0; HWTID TDestruction::hSimpleSphereTextureID = 0; HWTID TDestruction::hSimpleWaveTextureID = 0; void TDestruction::initParticleTextures(){ TTextureManager::tm->loadTextureQuery(RASTER_WAVE, &(TDestruction::hSimpleWaveTextureID)); TTextureManager::tm->loadTextureQuery(RASTER_EXNOISE, &(TDestruction::hSimpleSphereTextureID)); TTextureManager::tm->loadTextureQuery(RASTER_PARTICLE, &(TDestruction::hSimpleParticleTextureID)); } TDestruction* TDestruction::installDestruction(P3F* scpos, int len, float size, int startAt){ // gui::TCamera* cam = ((gui::TguiMap*)(TEffectEngine::ee->scene))->getCam(); // TDestruction* des = new TDestruction(scpos, cam, startAt, len, 10, size, 80); return des; } /////////////////////////////////////////////////////////////////////////////// // TFlyAway // /////////////////////////////////////////////////////////////////////////////// void TFlyAway::update(int absoluteTime){ // TSceneObject* so = (TSceneObject*)data; if( (absoluteTime - iActivationTime) > iDur ){ delete so; TEffectEngine::ee->ctrlmng->removeChildControler(this); } else{ //cas na obnoveni int step = absoluteTime - iLastTime; if(step < TEffectEngine::ee->iPRP)return; iLastTime = absoluteTime; TVector a = TVector(dir)*(float)step; P3F pos; so->getPosition(&pos); pos = (TVector(pos) + a).toP3F(); so->setPosition(&pos); TVector b = TVector(rot)*(float)step; so->rotateBy(b.x, b.y, b.z); // TEffectEngine::ee->scene->reinstalObject(so); } } TFlyAway::TFlyAway(TSceneObject* so, float speed, float rspeed, int dur, int startAt){ data = (void*)so; iDur = dur; //nahodnej smer letu TVector a(RAND(-1, 1), RAND(-1, 1), RAND(0.5f, 1)); dir = (a.norm()*speed).toP3F(); //nahodna rotace TVector b(RAND(-0.0001f, 0.0001f), RAND(-0.0001f, 0.0001f), RAND(-0.0001f, 0.0001f)); rot = (b*rspeed).toP3F(); //umisteni do managera TEffectEngine::ee->ctrlmng->addController(this); //odstartuj activate(startAt); } TFlyAway* TFlyAway::installFlyAway(TSceneObject* so, float speed, float rspeed, int dur, int startAt){ return new TFlyAway(so, speed, rspeed, dur, startAt); } /////////////////////////////////////////////////////////////////////////////// // TSparkle // /////////////////////////////////////////////////////////////////////////////// int TSparkle::setUp() { if(p3fDirections)KMemFree(p3fDirections); if(p3fPositions)KMemFree(p3fPositions); if(pfSize)KMemFree(pfSize); // p3fDirections = (P3F*)KMemAlloc(sizeof(P3F)*iCount); p3fPositions = (P3F*)KMemAlloc(sizeof(P3F)*iCount); pfSize = (float*)KMemAlloc(sizeof(float)*iCount); for(int i=0; i < iCount; i++){ //poloha float h = RAND(0, 0.1f*fHeight); GenerateRandomPositionInSector(fBaseDiam/2, h, p3fPositions + i); //rychlost float s = RAND(fSpeed*0.1f, fSpeed); GenerateRandomDirectionInSector(5, 10, p3fDirections+i, s); //velikost pfSize[i] = RAND(SPARKLE_PARTICLE_SIZE-SPARKLE_PARTICLE_SIZE_VAR, SPARKLE_PARTICLE_SIZE); } return 0; } void TSparkle::update(int absoluteTime, int rtime, int step) { //ukonceni if( (absoluteTime - iActivationTime) > iDur ){ TEffectEngine::ee->scene->remFromScene(this); TEffectEngine::ee->ctrlmng->removeChildControler(this); } //prubeh else{ //pruhlednost fTransparency = FadeInOut(float(absoluteTime - iActivationTime)/iDur, 0.2f , 0.8f); //updatni pozice for(int i=0; i < iCount; i++){ P3F a = p3fDirections[i]; MulV3(a.p, step); AddV3(p3fPositions[i].p, p3fDirections[i].p); float x=p3fPositions[i].x; float y=p3fPositions[i].y; float cosr = cos(fRotSpeed); float sinr = sin(fRotSpeed); p3fPositions[i].x = cosr*x + sinr*y; p3fPositions[i].y = -sinr*x + cosr*y; } //zvuk if(iSoundFlag){ if(TSoundInterface::si) TSoundInterface::si->playSampleSpatialConrolled(SAMPLE_SPARKLE, &aabbCenter); iSoundFlag = 0; } } } void TSparkle::drawObject(){ if (getRealFade() != FADE_0) return; P3F camdir, camup, cambi; glPushMatrix(); glMultMatrixf(mx4Pos); glDisable(GL_LIGHTING); glDepthMask(false); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); //jiskry CopyV4toV3(camdir.p, camera->p4fDir.p); CopyV4toV3(camup.p, camera->p4fUp.p); VectMulV3(cambi.p, camdir.p, camup.p); NormalizeV3(cambi.p); NormalizeV3(camup.p); // glBindTexture(GL_TEXTURE_2D, hParticleTextureID); glColor4f(pfColor[0],pfColor[1],pfColor[2],fTransparency); for(int i = 0; i < iCount; i++){ glBegin(GL_QUADS); glTexCoord2f(1,1); glVertex3f(p3fPositions[i].x + (cambi.x - camup.x)*pfSize[i], p3fPositions[i].y + (cambi.y - camup.y)*pfSize[i], p3fPositions[i].z + (cambi.z - camup.z)*pfSize[i]); glTexCoord2f(1,0); glVertex3f(p3fPositions[i].x + (cambi.x + camup.x)*pfSize[i], p3fPositions[i].y + (cambi.y + camup.y)*pfSize[i], p3fPositions[i].z + (cambi.z + camup.z)*pfSize[i]); glTexCoord2f(0,0); glVertex3f(p3fPositions[i].x - (cambi.x - camup.x)*pfSize[i], p3fPositions[i].y - (cambi.y - camup.y)*pfSize[i], p3fPositions[i].z - (cambi.z - camup.z)*pfSize[i]); glTexCoord2f(0,1); glVertex3f(p3fPositions[i].x - (cambi.x + camup.x)*pfSize[i], p3fPositions[i].y - (cambi.y + camup.y)*pfSize[i], p3fPositions[i].z - (cambi.z + camup.z)*pfSize[i]); glEnd(); } glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glDepthMask(true); glEnable(GL_LIGHTING); glPopMatrix(); TSceneObject::drawObject(); } TSparkle::TSparkle(TCamera* cam, P3F* scpos, int dur, float speed, float rotspeed, int pcount, float bdiam, float height, int startAt) :TBillBoard(cam) { //pruhledne transparent=1; float c[] = {SPARKLE_DEFAULT_COLOR}; CopyV3(pfColor, c); //castice p3fDirections = NULL; p3fPositions = NULL; pfSize = NULL; iCount = pcount; hParticleTextureID = TSparkle::hSimpleParticleTextureID; //velikost fBaseDiam = bdiam; fHeight = height; //rychlost, cas fSpeed = speed; fRotSpeed = rotspeed; iDur = dur; fTransparency = 0; iSoundFlag = 1; //inicializuj castice setUp(); if( startAt >= 0 ) activate(startAt); //umisti na scenu TEffectEngine::ee->scene->addObject(this); moveTo(scpos->x, scpos->y, scpos->z); TEffectEngine::ee->scene->reinstalObject(this); //umisteni do managera TEffectEngine::ee->ctrlmng->addController(this); } HWTID TSparkle::hSimpleParticleTextureID = 0; HWTID TSparkle::hHeartParticleTextureID = 0; HWTID TSparkle::hCrossTextureID = 0; HWTID TSparkle::hHeadParticleTextureID = 0; void TSparkle::initParticleTextures(){ TTextureManager::tm->loadTextureQuery(RASTER_PARTICLE, &(TSparkle::hSimpleParticleTextureID)); TTextureManager::tm->loadTextureQuery(RASTER_HEART_PARTICLE, &(TSparkle::hHeartParticleTextureID)); TTextureManager::tm->loadTextureQuery(RASTER_CROSS_PARTICLE, &(TSparkle::hCrossTextureID)); TTextureManager::tm->loadTextureQuery(RASTER_HEAD_PARTICLE, &(TSparkle::hHeadParticleTextureID)); } TSparkle* TSparkle::installSparkle(P3F* scpos, float bdiam, float height, float* c, HWTID hT) { int count = ROUND( (height*M_PI*bdiam/2)*SPARKLE_PARTICLE_DENSITY ); // gui::TCamera* cam = ((gui::TguiMap*)(TEffectEngine::ee->scene))->getCam(); // TSparkle* h = new TSparkle(cam, scpos, SPARKLE_DEFAULT_DUR, SPARKLE_DEFAULT_SPEED, SPARKLE_DEFAULT_ROT_SPEED, count, bdiam, height, KTime()); h->hParticleTextureID = hT; SETV3(h->pfColor, c[0], c[1], c[2]); return h; } TSparkle* TSparkle::installSparkle(P3F* scpos, float bdiam, float height) { float c[]={SPARKLE_DEFAULT_COLOR}; return TSparkle::installSparkle(scpos, bdiam, height, c, TSparkle::hSimpleParticleTextureID); } TSparkle* TSparkle::installHearts(P3F* scpos, float bdiam, float height) { float c[]={1,0,0}; return TSparkle::installSparkle(scpos, bdiam, height, c, TSparkle::hHeartParticleTextureID); } TSparkle* TSparkle::installCross(P3F* scpos, float bdiam, float height) { float c[]={0,1,0}; return TSparkle::installSparkle(scpos, bdiam, height, c, TSparkle::hCrossTextureID); } TSparkle* TSparkle::installHeads(P3F* scpos, float bdiam, float height) { float c[]={0,0,1}; return TSparkle::installSparkle(scpos, bdiam, height, c, TSparkle::hHeadParticleTextureID); } }//namespace /*****************************************************************************/