Back to index

extremetuxracer  0.5beta
Classes | Functions | Variables
snow.h File Reference
#include "ppgltk/ppgltk.h"
#include "player.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  SnowType
struct  WindType

Functions

static double xrand (double min, double max)
void UpdateArea (pp::Vec3d pos)
static void MakeSnowParticle (int i)
static void MakeNearParticle (int i)
void init_snow (pp::Vec3d playerPos)
void update_snow (double time_step, bool windy, pp::Vec3d playerPos)
void draw_snow (pp::Vec3d eyepoint)
void update_wind ()
void draw_sprite (pp::Vec3d eyepoint, pp::Vec3d spriteLoc, double spriteSize, pp::Vec2d tex_min, pp::Vec2d tex_max)
void draw_cuboid_areas ()
void reset_snow ()
void RegisterSnowType (int index, SnowType type)
void SetSnowType (int index)
void RegisterWindType (int index, WindType type)
void SetWindType (int index)

Variables

static const int SnowTypeArgCount = 5
static const int WindTypeArgCount = 3
pp::Vec3d wind_vel
double wind_scale

Class Documentation

struct SnowType

Definition at line 42 of file snow.h.

Class Members
int MAXNEAR
int MAXPART
double maxSize
double minSize
double speed
struct WindType

Definition at line 50 of file snow.h.

Collaboration diagram for WindType:
Class Members
Vec3d wind_vel

Function Documentation

Definition at line 531 of file snow.cpp.

                         {
    glLineWidth(3.0);
    
    glPushMatrix();
    
    glColor4f(1.0,0.0,0.0,1.0);
    
    glBegin(GL_LINES);
    glVertex3f(neararea.left,neararea.bottom,neararea.front);
    glVertex3f(neararea.left,neararea.top,neararea.front);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(neararea.left,neararea.top,neararea.front);
    glVertex3f(neararea.right,neararea.top,neararea.front);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(neararea.right,neararea.top,neararea.front);
    glVertex3f(neararea.right,neararea.bottom,neararea.front);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(neararea.right,neararea.bottom,neararea.front);
    glVertex3f(neararea.left,neararea.bottom,neararea.front);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(neararea.left,neararea.bottom,neararea.back);
    glVertex3f(neararea.left,neararea.top,neararea.back);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(neararea.left,neararea.top,neararea.back);
    glVertex3f(neararea.right,neararea.top,neararea.back);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(neararea.right,neararea.top,neararea.back);
    glVertex3f(neararea.right,neararea.bottom,neararea.back);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(neararea.right,neararea.bottom,neararea.back);
    glVertex3f(neararea.left,neararea.bottom,neararea.back);
    glEnd();
    
    glPopMatrix();
    
    glPushMatrix();
    
    glColor4f(0.0,1.0,0.0,1.0);
    
    glBegin(GL_LINES);
    glVertex3f(area.left,area.bottom,area.front);
    glVertex3f(area.left,area.top,area.front);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(area.left,area.top,area.front);
    glVertex3f(area.right,area.top,area.front);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(area.right,area.top,area.front);
    glVertex3f(area.right,area.bottom,area.front);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(area.right,area.bottom,area.front);
    glVertex3f(area.left,area.bottom,area.front);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(area.left,area.bottom,area.back);
    glVertex3f(area.left,area.top,area.back);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(area.left,area.top,area.back);
    glVertex3f(area.right,area.top,area.back);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(area.right,area.top,area.back);
    glVertex3f(area.right,area.bottom,area.back);
    glEnd();
    
    glBegin(GL_LINES);
    glVertex3f(area.right,area.bottom,area.back);
    glVertex3f(area.left,area.bottom,area.back);
    glEnd();
    
    glPopMatrix();
}
void draw_snow ( pp::Vec3d  eyepoint)

Definition at line 413 of file snow.cpp.

{
    int i;
    double size;

    set_gl_options (PARTICLES);
    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    
    glColor4f( particleColor[0], particleColor[1], particleColor[2],particleColor[3] );
    
    //color unspecified : shows snow
    //glColor4f( 1.0, 1.0, 1.0,1.0); shows snow
    //glColor4f( 0.0, 0.0, 0.0,0.0); doesnt show any snow
    
    //its the alpha vaolue in the color... if the alpha is null (total transparence), the textured color is also totally transparent => invisible
    
    //the snow only shows up near the start flag... why ?
    //because the y axis grows upwards. And in udateArea(), you had top = pos.y - YRANGE...and bottom = pos.y Also, in make*Particle(), you have part.y = -xrand(bottom,top)
    //  so it doesnt show too much on the strt line, for some reason...
    
    //a totally grey snowflake :-)
    //glColor4f(0.0,0.0,0.0,0.5);
    
    //glColor4f(0.0,1.0,0.0,0.5);
    
    //hardly visible with this color ! too... white :-)
    //glColor4f(1.0,1.0,1.0,0.5);
    
    
    
    for(i=0;i<MAXPART;i++) {
    
        /*
        if(i==0) {
            glColor4f(0.0,1.0,0.0,1.0);
        }*/
    
        size = PartArr[i].size;
        glBindTexture(GL_TEXTURE_2D, snow_tex[PartArr[i].index_tex]);
        draw_sprite( eyepoint, PartArr[i].pt, size, PartArr[i].tex_min, PartArr[i].tex_max );
        /*
        glPushMatrix();
        glTranslatef(PartArr[i].pt.x,PartArr[i].pt.y,PartArr[i].pt.z);
        glBegin( GL_QUADS );
        glTexCoord2f(PartArr[i].tex_min.x,PartArr[i].tex_min.y);
        glVertex3f(0,0,0);
        glTexCoord2f(PartArr[i].tex_min.x,PartArr[i].tex_max.y);
        glVertex3f(0,size,0);
        glTexCoord2f(PartArr[i].tex_max.x,PartArr[i].tex_max.y);
        glVertex3f(size,size,0);
        glTexCoord2f(PartArr[i].tex_max.x,PartArr[i].tex_min.y);
        glVertex3f(size,0,0);
        glEnd();
        glPopMatrix();
        */
        
        /*if(i==0) {
            glColor4f(0.0,0.0,0.0,0.5);
        }*/
    }
    
    for(i=0;i<MAXNEAR;i++) {
        size = NearArr[i].size;
        glBindTexture(GL_TEXTURE_2D, snow_tex[NearArr[i].index_tex]);
        /*
        glPushMatrix();
        glTranslatef(NearArr[i].pt.x,NearArr[i].pt.y,NearArr[i].pt.z);
        
        glBegin( GL_QUADS );
        glTexCoord2f(NearArr[i].tex_min.x,NearArr[i].tex_min.y);
        glVertex3f(0,0,0);
        glTexCoord2f(NearArr[i].tex_min.x,NearArr[i].tex_max.y);
        glVertex3f(0,size,0);
        glTexCoord2f(NearArr[i].tex_max.x,NearArr[i].tex_max.y);
        glVertex3f(size,size,0);
        glTexCoord2f(NearArr[i].tex_max.x,NearArr[i].tex_min.y);
        glVertex3f(size,0,0);
        glEnd();
        
        glPopMatrix();
        */
        draw_sprite( eyepoint, NearArr[i].pt, size, NearArr[i].tex_min, NearArr[i].tex_max );
    }
    
    

}

Here is the call graph for this function:

Here is the caller graph for this function:

void draw_sprite ( pp::Vec3d  eyepoint,
pp::Vec3d  spriteLoc,
double  spriteSize,
pp::Vec2d  tex_min,
pp::Vec2d  tex_max 
)

Definition at line 502 of file snow.cpp.

                                                                                                             {
    pp::Vec3d normal = eyepoint - spriteLoc;
    normal.normalize();
    if(normal.y == 1) return; // ||normal||==1 so if normal.y == 1 then normal == (0,1,0) and then we dont want to draw a "flat" sprite (contained in the (x,z) plane)
    glPushMatrix();
        glTranslatef( spriteLoc.x, spriteLoc.y, spriteLoc.z );
        glNormal3f(normal.x,normal.y,normal.z);//for lightning purposes... dont know if this is relevant here, so i put it just in case
        normal.y = 0; //the sprite has to be drawn using a normal vector contained in the (x,z) plane in order to appear as a billboard
        normal.normalize();
        glBegin( GL_QUADS );
           {
            double spriteRadius = spriteSize/2; //we assume the sprite to occupy the space of a cube in 3d; so the radius is equal to size/2 here
            double spriteHeight = spriteSize;//we assume the sprite to occupy the space of a cube in 3d; so the height is equal to the size here
              glTexCoord2f( tex_min.x, tex_min.y );
              glVertex3f( -spriteRadius*normal.z, 0.0, spriteRadius*normal.x );
              glTexCoord2f( tex_max.x, tex_min.y );
              glVertex3f( spriteRadius*normal.z, 0.0, -spriteRadius*normal.x );
              glTexCoord2f( tex_max.x, tex_max.y );
              glVertex3f( spriteRadius*normal.z, spriteHeight, -spriteRadius*normal.x );
              glTexCoord2f( tex_min.x, tex_max.y );
              glVertex3f( -spriteRadius*normal.z, spriteHeight, spriteRadius*normal.x );
           }
           glEnd();
    glPopMatrix();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void init_snow ( pp::Vec3d  playerPos)

Definition at line 258 of file snow.cpp.

{
    //tried to call this function in course_load::course_load()
    //init_snow(players[0].pos);
    //init_snow(players[0].view.pos);
    //but both pos and view.pos werent initialized
    //now this function is called in racing::racing()
    if ( !get_texture_binding("c_snow_flake0", &(snow_tex[0]) ) ) {
        std::cerr << "Can't load snow texture : c_snow_flake0 ! Ay Ay Ay !\n";
    }
    if ( !get_texture_binding("c_snow_flake1", &(snow_tex[1]) ) ) {
        std::cerr << "Can't load snow texture : c_snow_flake1 ! Ay Ay Ay !\n";
    }
    if ( !get_texture_binding("c_snow_flake2", &(snow_tex[2]) ) ) {
        std::cerr << "Can't load snow texture : c_snow_flake2 ! Ay Ay Ay !\n";
    }
    if ( !get_texture_binding("c_snow_flake3", &(snow_tex[3]) ) ) {
        std::cerr << "Can't load snow texture : c_snow_flake3 ! Ay Ay Ay !\n";
    }
    
    UpdateArea(playerPos);
    NearArr = (TParticle*)malloc(sizeof(TParticle)*MAXNEAR);
    PartArr = (TParticle*)malloc(sizeof(TParticle)*MAXPART);
    int i;
    for(i = 0; i<MAXPART;i++) MakeSnowParticle(i);
    for(i = 0; i<MAXNEAR;i++) MakeNearParticle(i);
    
    lastPos = playerPos;
    
    /*
    UpdateArea(eyepoint);
    
    int i;
    for(i=0;i<MAXPART;i++) {
        MakeSnowParticle(i);
    }
    for(i=0;i<MAXNEAR;i++) {
        MakeNearParticle(i);
    }
    */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void MakeNearParticle ( int  i) [static]
static void MakeSnowParticle ( int  i) [static]
void RegisterSnowType ( int  index,
SnowType  type 
)

Definition at line 128 of file snow.cpp.

                                                 {
    if((index < MAXTYPES) && (index > -1)) {
//        if(istyperegistered[index] == false) {
            snowtypes[index] = type;
            istyperegistered[index] = true;
//       } else {
//            std::cerr << "RegisterSnowType, index : " << index << " [ERROR] Type is already registered !\n";
//        }
    } else {
        std::cerr << "RegisterSnowType, index : " << index << " [ERROR] Index must be in range [0 .. " << MAXTYPES << "]\n";
    }
}

Here is the caller graph for this function:

void RegisterWindType ( int  index,
WindType  type 
)

Definition at line 141 of file snow.cpp.

                                                 {
    if((index < MAXTYPES) && (index > -1)) {
//     if(iswindtyperegistered[index] == false) {
            windtypes[index] = type;
            iswindtyperegistered[index] = true;
//        } else {
//            std::cerr << "RegisterWindType, index : " << index << " [ERROR] Type is already registered !\n";
//        }
    } else {
        std::cerr << "RegisterWindType, index : " << index << " [ERROR] Index must be in range [0 .. " << MAXTYPES << "]\n";
    }
}

Here is the caller graph for this function:

void reset_snow ( )

Definition at line 300 of file snow.cpp.

                  {
    free(NearArr);
    free(PartArr);
}

Here is the caller graph for this function:

void SetSnowType ( int  index)

Definition at line 154 of file snow.cpp.

                             {
    if((index < MAXTYPES) && (index > -1)) {
        if(istyperegistered[index]){
            speed = snowtypes[index].speed;
            minSize = snowtypes[index].minSize;
            maxSize = snowtypes[index].maxSize;
            MAXPART = snowtypes[index].MAXPART;
            MAXNEAR = snowtypes[index].MAXNEAR;
        } else {
            std::cerr << "SetSnowType, index : " << index << " [ERROR] No type has been registered with this index !\n";
        }
    } else {
        std::cerr << "RegisterSnowType, index : " << index << " [ERROR] Index must be in range [0 .. " << MAXTYPES << "]\n";
    }
}

Here is the caller graph for this function:

void SetWindType ( int  index)

Definition at line 170 of file snow.cpp.

                             {
    if((index < MAXTYPES) && (index > -1)) {
        if(iswindtyperegistered[index]){
            wind_vel = windtypes[index].wind_vel;
        } else {
            std::cerr << "SetWindType, index : " << index << " [ERROR] No type has been registered with this index !\n";
        }
    } else {
        std::cerr << "RegisterWindType, index : " << index << " [ERROR] Index must be in range [0 .. " << MAXTYPES << "]\n";
    }
}

Here is the caller graph for this function:

void update_snow ( double  time_step,
bool  windy,
pp::Vec3d  playerPos 
)

Definition at line 305 of file snow.cpp.

{
    UpdateArea(playerPos);
 
    if ( gameMgr->getCurrentRace().windy ) {
        XWindFactor = wind_vel.x * wind_scale * 0.03;
        ZWindFactor = wind_vel.z * wind_scale * 0.045;
    }
  
    double xdiff = playerPos.x - lastPos.x;
    double ydiff = playerPos.y - lastPos.y;
       double zdiff = playerPos.z - lastPos.z;
    double xNearCoeff = XWindFactor * time_step + 0.5*(xdiff * xdrift);//We slow down the xdrift for near particles because otherwise the correction would be too obvious when the player turns (having snow flakes "following" him along the x axis)
    double xcoeff = XWindFactor * time_step + (xdiff * xdrift);
       double ycoeff = (ydiff * ydrift) + (ZWindFactor * 0.025);      
       double zcoeff = (ZWindFactor * time_step) + (zdiff * zdrift);
    
    int i;
    
    for(i = 0; i<MAXPART;i++) {
        //PartArr[i].pt.x += (eyepoint.x - PartArr[0].pt.x);  
       //PartArr[i].pt.y += (eyepoint.y - PartArr[0].pt.y) + 1;
       //PartArr[i].pt.z += (eyepoint.z - PartArr[0].pt.z);
        
        //PartArr[i].pt.x += (eyepoint.x - PartArr[0].pt.x);  
       //PartArr[i].pt.y += (eyepoint.y - PartArr[0].pt.y) + 1;
       //PartArr[i].pt.y += (eyepoint.y - PartArr[0].pt.y);
        //PartArr[i].pt.z += PartArr[i].vel.z;
        //PartArr[i].pt.z += (eyepoint.z - PartArr[0].pt.z) - 1;
        
        
        if (PartArr[i].pt.x < area.left) {
                     PartArr[i].pt.x += XRANGE;
              } else if (PartArr[i].pt.x > area.right) {
                     PartArr[i].pt.x -= XRANGE;
              } else if (PartArr[i].pt.y < area.bottom) {
                     PartArr[i].pt.y += YRANGE;  
              } else if (PartArr[i].pt.y > area.top) {
                     PartArr[i].pt.y -= YRANGE;                
              } else if (PartArr[i].pt.z < area.front) {
                     PartArr[i].pt.z += ZRANGE;         
              } else if (PartArr[i].pt.z > area.back) {
                     PartArr[i].pt.z -= ZRANGE;         
              }
        
        PartArr[i].pt.x += xcoeff;
              PartArr[i].pt.y += PartArr[i].vel.y * time_step + ycoeff;
              PartArr[i].pt.z += zcoeff;
    }
    for(i = 0; i<MAXNEAR;i++) {
        //NearArr[i].pt.x += (eyepoint.x - PartArr[0].pt.x);  
        //NearArr[i].pt.y += (eyepoint.y - PartArr[0].pt.y) + 1;
        //NearArr[i].pt.z += (eyepoint.z - PartArr[0].pt.z);
        //NearArr[i].pt.x += (eyepoint.x - PartArr[0].pt.x);
        //NearArr[i].pt.x += NearArr[i].vel.x;
        //NearArr[i].pt.y += (eyepoint.y - PartArr[0].pt.y) + 1;
        //NearArr[i].pt.y += (eyepoint.y - PartArr[0].pt.y);
        //NearArr[i].pt.z += (eyepoint.z - PartArr[0].pt.z) - 1;
        
        
        if (NearArr[i].pt.x < neararea.left) {
            NearArr[i].pt.x += NEAR_XRANGE;
              } else if (NearArr[i].pt.x > neararea.right) {
                     NearArr[i].pt.x -= NEAR_XRANGE;
              } else if (NearArr[i].pt.y < neararea.bottom) {
                     NearArr[i].pt.y += NEAR_YRANGE;    
              } else if (NearArr[i].pt.y > neararea.top) {
                     NearArr[i].pt.y -= NEAR_YRANGE;
              } else if (NearArr[i].pt.z < neararea.front) {
                     NearArr[i].pt.z += NEAR_ZRANGE;           
              } else if (NearArr[i].pt.z > neararea.back) {
                     NearArr[i].pt.z -= NEAR_ZRANGE;           
              }
        
        NearArr[i].pt.x += xNearCoeff;//We disable the xdrift for near particles because it is too obvious when the player turns
              NearArr[i].pt.y += NearArr[i].vel.y * time_step + ycoeff;
              NearArr[i].pt.z += zcoeff;
    }
    
    lastPos = playerPos;
    
    
    /*
    UpdateArea(eyepoint);
    
    int i;
    for(i=0;i<MAXPART;i++) {
        MakeSnowParticle(i);
    }
    for(i=0;i<MAXNEAR;i++) {
        MakeNearParticle(i);
    }
    */
} 

Here is the call graph for this function:

Here is the caller graph for this function:

void update_wind ( )

Definition at line 400 of file snow.cpp.

                   {
    static float last_time_called = -1;
    if ( gameMgr->getCurrentRace().windy ) {
        /* adjust wind_scale with a random walk */
       if ( last_time_called != gameMgr->time ) {
           wind_scale = wind_scale + 
              (rand()/(double)RAND_MAX-0.50) * 0.15;
           wind_scale = MIN( 1.0, MAX( 0.0, wind_scale ) );
       }
        last_time_called = gameMgr->time;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void UpdateArea ( pp::Vec3d  pos)

Definition at line 96 of file snow.cpp.

                             {
    area.left = pos.x - XRANGE / 2;
       area.right = area.left + XRANGE;
       area.back = pos.z + ZRANGE/3;
       area.front = area.back - ZRANGE;
       area.top = pos.y + 0.5*YRANGE;
       area.bottom = area.top - YRANGE;

// some remarks about the neararea:
//============================

// If the size of the flakes is very low they won't appear dense enough
// If the flakes are sized very large they seem to be snowballs in the near area
// This problem can be solved by using two areas, one for the far and ond for the 
// near with smaller flakes

//if the Yarea doesnt go below the player's Z, then the player can see the snow ahead of him just stopping in midair
//if the Zarea doesnt go behind the player, the player can see that there is no snow behind, when he turns around

       neararea.left = pos.x - NEAR_XRANGE / 2;
       neararea.right = neararea.left + NEAR_XRANGE;
       neararea.back = pos.z + NEAR_ZRANGE/3;
       neararea.front = neararea.back - NEAR_ZRANGE;
       neararea.top = pos.y + 0.5*NEAR_YRANGE;
       neararea.bottom = neararea.top - NEAR_YRANGE;
    
    //std::cout << "[snow.cpp] Player position as passed to UpdateArea() : " << pos.x << " " << pos.y << " " << pos.z << "\n";
    //std::cout << "[snow.cpp] Updated snow area : " << neararea.left << " " << neararea.back << " " <<neararea.top  << "\n";
}

Here is the caller graph for this function:

static double xrand ( double  min,
double  max 
) [static]

Variable Documentation

const int SnowTypeArgCount = 5 [static]

Definition at line 54 of file snow.h.

double wind_scale

Definition at line 51 of file snow.cpp.

const int WindTypeArgCount = 3 [static]

Definition at line 55 of file snow.h.