- list_spriteDef.clear();
- list_spriteContainer.clear();
- cldCache->free( bbId, cloudId );
-}
-
-
-// load all textures used to draw cloud sprites
-void SGNewCloud::loadTextures(const string &tex_path) {
- if( texturesLoaded )
- return;
- texturesLoaded = true;
-
- SGPath cloud_path;
-
- cloud_path.set(tex_path);
- cloud_path.append("cl_cumulus.rgb");
- cloudTextures[ CLTexture_cumulus ] = new ssgTexture( cloud_path.str().c_str(), false, false, false );
- cloudTextures[ CLTexture_cumulus ]->ref();
-
- cloud_path.set(tex_path);
- cloud_path.append("cl_stratus.rgb");
- cloudTextures[ CLTexture_stratus ] = new ssgTexture( cloud_path.str().c_str(), false, false, false );
- cloudTextures[ CLTexture_stratus ]->ref();
-
-}
-
-void SGNewCloud::startFade(bool direction, float duration, float pauseLength) {
- if(duration <= 0.0) {
- fadeActive = false;
- return;
- }
- this->direction = direction;
- fadetimer = 0.0;
- this->duration = duration;
- this->pauseLength = pauseLength;
- last_step = -1.0;
- fadeActive = true;
-}
-void SGNewCloud::setFade(float howMuch) {
- duration = 100.0;
- fadetimer = howMuch;
- fadeActive = false;
- last_step = -1.0;
-}
-
-
-static inline float rayleighCoeffAngular(float cosAngle) {
- return 3.0f / 4.0f * (1.0f + cosAngle * cosAngle);
-}
-
-// cp is normalized (len==1)
-static void CartToPolar3d(sgVec3 cp, sgVec3 polar) {
- polar[0] = atan2(cp[1], cp[0]);
- polar[1] = SG_PI / 2.0f - atan2(sqrt (cp[0] * cp[0] + cp[1] * cp[1]), cp[2]);
- polar[2] = 1.0f;
-}
-
-static void PolarToCart3d(sgVec3 p, sgVec3 cart) {
- float tmp = cos(p[1]);
- cart[0] = cos(p[0]) * tmp;
- cart[1] = sin(p[0]) * tmp;
- cart[2] = sin(p[1]);
-}
-
-
-// compute the light for a cloud sprite corner
-// from the normal and the sun, scaled by the Rayleigh factor
-// and finaly added to the ambient light
-static inline void lightFunction(sgVec3 normal, sgVec4 light, float pf) {
- float cosAngle = sgScalarProductVec3( normal, SGNewCloud::modelSunDir);
- float vl = (1.0f - 0.5f + cosAngle * 0.5f) * pf;
- sgScaleVec3( light, SGNewCloud::sunlight, 0.25f + 0.75f * vl );
- sgAddVec3( light, SGNewCloud::ambLight );
- // we need to clamp or else the light will bug when adding transparency
- if( light[0] > 1.0 ) light[0] = 1.0;
- if( light[1] > 1.0 ) light[1] = 1.0;
- if( light[2] > 1.0 ) light[2] = 1.0;
- light[3] = 1.0;
-}
-
-// compute the light for a cloud sprite
-// we use ambient light and orientation versus sun position
-void SGNewCloud::computeSimpleLight(sgVec3 FakeEyePos) {
- // constant Rayleigh factor if we are not doing Anisotropic lighting
- float pf = 1.0f;
-
- list_of_spriteDef::iterator iSprite;
- for( iSprite = list_spriteDef.begin() ; iSprite != list_spriteDef.end() ; iSprite++ ) {
- if( useAnisotropic ) {
- sgVec3 eyeDir;
- sgSubVec3(eyeDir, iSprite->pos, FakeEyePos);
- sgNormaliseVec3(eyeDir);
- float cosAngle = sgScalarProductVec3(eyeDir, modelSunDir);
- pf = rayleighCoeffAngular(cosAngle);
- }
- lightFunction(iSprite->n0, iSprite->l0, pf);
- lightFunction(iSprite->n1, iSprite->l1, pf);
- lightFunction(iSprite->n2, iSprite->l2, pf);
- lightFunction(iSprite->n3, iSprite->l3, pf);
-
- }
-}
-
-
-// add a new box to the cloud
-void SGNewCloud::addContainer (float x, float y, float z, float r, CLbox_type type) {
- spriteContainer cont;
- sgSetVec3( cont.pos, x, y, z );
- cont.r = r;
- cont.cont_type = type;
- sgSetVec3( cont.center, 0.0f, 0.0f, 0.0f);
- list_spriteContainer.push_back( cont );
- // don't place cloud below his base
- if( y - r*0.50 < delta_base )
- delta_base = y - r*0.50;
-}
-
-// add a sprite inside a box
-void SGNewCloud::addSprite(float x, float y, float z, float r, CLbox_type type, int box) {
- spriteDef newSpriteDef;
- int rank = list_spriteDef.size();
- sgSetVec3( newSpriteDef.pos, x, y - delta_base, z);
- newSpriteDef.box = box;
- newSpriteDef.sprite_type = type;
- newSpriteDef.rank = rank;
- newSpriteDef.r = r;
- list_spriteDef.push_back( newSpriteDef );
- spriteContainer *thisBox = &list_spriteContainer[box];
- sgVec3 deltaPos;
- sgSubVec3( deltaPos, newSpriteDef.pos, thisBox->pos );
- sgAddVec3( thisBox->center, deltaPos );
-
- r = r * 0.65f; // 0.5 * 1.xxx
- if( x - r < minx )
- minx = x - r;
- if( y - r < miny )
- miny = y - r;
- if( z - r < minz )
- minz = z - r;
- if( x + r > maxx )
- maxx = x + r;
- if( y + r > maxy )
- maxy = y + r;
- if( z + r > maxz )
- maxz = z + r;
-
-}
-
-// return a random number between -n/2 and n/2
-static float Rnd(float n) {
- return n * (-0.5f + sg_random());
-}
-
-// generate all sprite with defined boxes
-void SGNewCloud::genSprites( void ) {
- float x, y, z, r;
- int N, sc;
- minx = miny = minz = 99999.0;
- maxx = maxy = maxz = -99999.0;
-
- N = list_spriteContainer.size();
- for(int i = 0 ; i < N ; i++ ) {
- spriteContainer *thisBox = & list_spriteContainer[i];
- // the type defines how the sprites can be positioned inside the box, their size, etc
- switch(thisBox->cont_type) {
- case CLbox_sc:
- sc = 1;
- r = thisBox->r + Rnd(0.2f);
- x = thisBox->pos[SG_X] + Rnd(thisBox->r * 0.75f);
- y = thisBox->pos[SG_Y] + Rnd(thisBox->r * 0.75f);
- z = thisBox->pos[SG_Z] + Rnd(thisBox->r * 0.75f);
- addSprite(x, y, z, r, thisBox->cont_type, i);
- break;
- case CLbox_stratus:
- sc = 1;
- r = thisBox->r;
- x = thisBox->pos[SG_X];
- y = thisBox->pos[SG_Y];
- z = thisBox->pos[SG_Z];
- addSprite(x, y, z, r, thisBox->cont_type, i);
- break;
- case CLbox_cumulus:
- for( sc = 0 ; sc <= 4 ; sc ++ ) {
- r = thisBox->r + Rnd(0.2f);
- x = thisBox->pos[SG_X] + Rnd(thisBox->r * 0.75f);
- y = thisBox->pos[SG_Y] + Rnd(thisBox->r * 0.5f);
- z = thisBox->pos[SG_Z] + Rnd(thisBox->r * 0.75f);
- if ( y < thisBox->pos[SG_Y] - thisBox->r / 10.0f )
- y = thisBox->pos[SG_Y] - thisBox->r / 10.0f;
- addSprite(x, y, z, r, thisBox->cont_type, i);
- }
- break;
- default:
- for( sc = 0 ; sc <= 4 ; sc ++ ) {
- r = thisBox->r + Rnd(0.2f);
- x = thisBox->pos[SG_X] + Rnd(thisBox->r);
- y = thisBox->pos[SG_Y] + Rnd(thisBox->r);
- z = thisBox->pos[SG_Z] + Rnd(thisBox->r);
- addSprite(x, y, z, r, thisBox->cont_type, i);
- }
- break;
- }
- sgScaleVec3(thisBox->center, 1.0f / sc);
- }
-
- radius = maxx - minx;
- if ( (maxy - miny) > radius )
- radius = (maxy - miny);
- if ( (maxz - minz) > radius )
- radius = (maxz - minz);
- radius /= 2.0f;
- sgSetVec3( center, (maxx + minx) / 2.0f, (maxy + miny) / 2.0f, (maxz + minz) / 2.0f );
-
- const float ang = 45.0f * SG_PI / 180.0f;
-
- // compute normals
- list_of_spriteDef::iterator iSprite;
- for( iSprite = list_spriteDef.begin() ; iSprite != list_spriteDef.end() ; iSprite++ ) {
- sgVec3 normal;
- spriteContainer *thisSpriteContainer = &list_spriteContainer[iSprite->box];
- if( familly == CLFamilly_sc || familly == CLFamilly_cu || familly == CLFamilly_cb) {
- sgSubVec3(normal, iSprite->pos, center);
- } else {
- sgSubVec3(normal, iSprite->pos, thisSpriteContainer->pos);
- sgSubVec3(normal, thisSpriteContainer->center);
- sgSubVec3(normal, cloudpos);
- }
- if( normal[0] == 0.0f && normal[1] == 0.0f && normal[2] == 0.0f )
- sgSetVec3( normal, 0.0f, 1.0f, 0.0f );
- sgNormaliseVec3(normal);
- // use exotic lightning function, this will give more 'relief' to the clouds
- // compute a normal for each vextex this will simulate a smooth shading for a round shape
- sgVec3 polar, pt;
- // I suspect this code to be bugged...
- CartToPolar3d(normal, polar);
- sgCopyVec3(iSprite->normal, normal);
-
- // offset the normal vector by some angle for each vertex
- sgSetVec3(pt, polar[0] - ang, polar[1] - ang, polar[2]);
- PolarToCart3d(pt, iSprite->n0);
- sgSetVec3(pt, polar[0] + ang, polar[1] - ang, polar[2]);
- PolarToCart3d(pt, iSprite->n1);
- sgSetVec3(pt, polar[0] + ang, polar[1] + ang, polar[2]);
- PolarToCart3d(pt, iSprite->n2);
- sgSetVec3(pt, polar[0] - ang, polar[1] + ang, polar[2]);
- PolarToCart3d(pt, iSprite->n3);
- }
-
- // experimental : clouds are dissipating with time
- if( familly == CLFamilly_cu ) {
- startFade(true, 300.0f, 30.0f);
- fadetimer = sg_random() * 300.0f;
- }
-}
-
-
-// definition of a cu cloud, only for testing
-void SGNewCloud::new_cu(void) {
- float s = 250.0f;
- float r = Rnd(1.0) + 0.5;
- if( r < 0.5f ) {
- addContainer(0.0f, 0.0f, 0.0f, s, CLbox_cumulus);
- addContainer(s, 0, 0, s, CLbox_cumulus);
- addContainer(0, 0, 2 * s, s, CLbox_cumulus);
- addContainer(s, 0, 2 * s, s, CLbox_cumulus);
-
- addContainer(-1.2f * s, 0.2f * s, s, s * 1.4f, CLbox_cumulus);
- addContainer(0.2f * s, 0.2f * s, s, s * 1.4f, CLbox_cumulus);
- addContainer(1.6f * s, 0.2f * s, s, s * 1.4f, CLbox_cumulus);
- } else if ( r < 0.90f ) {
- addContainer(0, 0, 0, s * 1.2, CLbox_cumulus);
- addContainer(s, 0, 0, s, CLbox_cumulus);
- addContainer(0, 0, s, s, CLbox_cumulus);
- addContainer(s * 1.1, 0, s, s * 1.2, CLbox_cumulus);
-
- addContainer(-1.2 * s, 1 + 0.2 * s, s * 0.5, s * 1.4, CLbox_standard);
- addContainer(0.2 * s, 1 + 0.25 * s, s * 0.5, s * 1.5, CLbox_standard);
- addContainer(1.6 * s, 1 + 0.2 * s, s * 0.5, s * 1.4, CLbox_standard);
-
- } else {
- // cb
- s = 675.0f;
- addContainer(0, 0, 0, s, CLbox_cumulus);
- addContainer(0, 0, s, s, CLbox_cumulus);
- addContainer(s, 0, s, s, CLbox_cumulus);
- addContainer(s, 0, 0, s, CLbox_cumulus);
-
- addContainer(s / 2, s, s / 2, s * 1.5, CLbox_standard);
-
- addContainer(0, 2 * s, 0, s, CLbox_standard);
- addContainer(0, 2 * s, s, s, CLbox_standard);
- addContainer(s, 2 * s, s, s, CLbox_standard);
- addContainer(s, 2 * s, 0, s, CLbox_standard);
-
- }
- genSprites();