void CMoonImage::Repaint (double angle, float age) { // x_10 = moon_angle^10 double x_2 = angle * angle; double x_10 = x_2 * x_2 * x_2 * x_2 * x_2; // Calculate ambient light caused by moon; clamped between 0.3 and 1.0 /// \todo This does not account for lunar phase? float ambient = (float)(0.4 * pow (1.1, -x_10 / 30.0)); if (ambient < 0.3f) ambient = 0.3f; if (ambient > 1.0f) ambient = 1.0f; // Compute moon colouring sgSetVec4 (colour, (ambient * 6.0f) - 1.0f, (ambient * 11.0f) - 3.0f, (ambient * 12.0f) - 3.6f, 0.5f); // For testing, force colour to pure white sgSetVec4 (colour, 1.0f, 1.0f, 1.0f, 1.0f); // Clamp colour components to maximum 1.0 if (colour[0] > 1.0f) colour[0] = 1.0f; if (colour[1] > 1.0f) colour[1] = 1.0f; if (colour[2] > 1.0f) colour[2] = 1.0f; }
TransIcelandicExpress::TransIcelandicExpress() { // constructor music = NULL; angle = 0.0; dot_init = false; sgSetVec3( cameraPos, 0.0f, 0.013f, -0.2f ); sgSetVec4( light_pos, -1.0f, -1.0f, -1.0f, 0.0f ); sgSetVec4( light_amb, 0.2f, 0.2f, 0.3f, 1.0f ); sgSetVec4( light_diff, 1.0f, 1.0f, 0.8f, 1.0f ); sgSetVec4( light_spec, 1.0f, 1.0f, 1.0f, 1.0f ); sgSetVec4( ocean_diff, 0.4f, 0.5f, 0.7f, 1.0f ); player = new Player(); showHelp = true; roadX = 0; roadY = 0; loadLevel( "./gamedata/levels/tess2.txt" ); //loadLevel( "./gamedata/levels/SimpleRoad.txt" ); //loadLevel( "./gamedata/levels/Challenge2.txt" ); }
// build the moon object ssgBranch * cGrMoon::build( double moon_size ) { ssgDeRefDelete( moon_transform ); moon_transform = new ssgTransform; moon_transform->ref(); moon_cl = new ssgColourArray( 1 ); sgVec4 color; sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); moon_cl->add( color ); moon_state = new ssgSimpleState(); moon_state->setTexture( "data/textures/moon.rgba" ); moon_state->setShadeModel( GL_SMOOTH ); moon_state->enable( GL_LIGHTING ); moon_state->enable( GL_CULL_FACE ); moon_state->enable( GL_TEXTURE_2D ); moon_state->enable( GL_COLOR_MATERIAL ); moon_state->setColourMaterial( GL_DIFFUSE ); moon_state->setMaterial( GL_AMBIENT, 0, 0, 0, 1 ); moon_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); moon_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); moon_state->enable( GL_BLEND ); moon_state->enable( GL_ALPHA_TEST ); moon_state->setAlphaClamp( 0.01f ); ssgBranch *moon = grMakeSphere( moon_state, moon_cl, moon_size, 15, 15, grMoonOrbPreDraw, grMoonOrbPostDraw ); moon_transform->addKid( moon ); repaint( 0.0 ); return moon_transform; }
/** \brief Perform the basic scenegraph initialization * * Initializes the PLIB SSG library, creates the scenegraph * root, a rendering context and the sun. */ void initialize_scenegraph() { // Initialize SSG ssgInit(); // add to SSG function for read JPEG Textures ::ssgAddTextureFormat ( ".jpg", ssgLoadJPG); // font puSetDefaultFonts ( FONT_HELVETICA_14, FONT_HELVETICA_14 ); // Some basic OpenGL setup sgVec4 skycol; sgSetVec4 ( skycol, 0.0f, 0.0f, 0.0f, 1.0f ) ; glClearColor ( skycol[0], skycol[1], skycol[2], skycol[3] ) ; glEnable ( GL_DEPTH_TEST ) ; // Set up the viewing parameters context = new ssgContext(); context->setFOV ( 35.0f, 0 ) ; context->setNearFar ( 1.0f, 10000.0f ) ; context->makeCurrent(); ssgModelPath(""); ssgTexturePath("textures"); // Create a root node scene = new ssgRoot(); // Set up a light source sgVec4 lightamb; sgSetVec4(lightamb , 0.2f, 0.2f, 0.2f, 1.0f); ssgGetLight(0)->setPosition(lightposn); ssgGetLight(0)->setColour(GL_AMBIENT, lightamb); ssgGetLight(0)->setPosition(lightposn); }
ssgBranch * cGrStars::build( int num, sgdVec3 *star_data, double star_dist ) { sgVec4 color; // clean-up previous ssgDeRefDelete( stars_transform ); // create new stars_transform = new ssgTransform; stars_transform->ref(); if ( star_data == NULL ) { if (num > 0) ulSetError(UL_WARNING, "null star data passed to cGrStars::build()"); else return stars_transform; } // set up the orb state state = new ssgSimpleState(); state->disable( GL_LIGHTING ); state->disable( GL_CULL_FACE ); state->disable( GL_TEXTURE_2D ); state->enable( GL_COLOR_MATERIAL ); state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); state->enable( GL_BLEND ); state->disable( GL_ALPHA_TEST ); vl = new ssgVertexArray( num ); cl = new ssgColourArray( num ); // cl = new ssgColourArray( 1 ); // sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); // cl->add( color ); // Build ssg structure sgVec3 p; for ( int i = 0; i < num; ++i ) { // position seeded to arbitrary values sgSetVec3( p, (float)( star_dist * cos( star_data[i][0] ) * cos( star_data[i][1] )), (float)( star_dist * sin( star_data[i][0] ) * cos( star_data[i][1] )), (float)( star_dist * sin( star_data[i][1] ))); vl->add( p ); // color (magnitude) sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); cl->add( color ); } ssgLeaf *stars_obj = new ssgVtxTable ( GL_POINTS, vl, NULL, NULL, cl ); stars_obj->setState( state ); stars_obj->setCallback( SSG_CALLBACK_PREDRAW, grStarPreDraw ); stars_obj->setCallback( SSG_CALLBACK_POSTDRAW, grStarPostDraw ); stars_transform->addKid( stars_obj ); return stars_transform; }
bool cGrStars::repaint( double sol_angle, int num, sgdVec3 *star_data ) { double mag, nmag, alpha, factor, cutoff; float *color; int phase; // determine which star structure to draw if ( sol_angle > ( SD_PI_2 + 10.0 * SGD_DEGREES_TO_RADIANS )) { // deep night factor = 1.0; cutoff = 4.5; phase = 0; } else if ( sol_angle > ( SD_PI_2 + 8.8 * SGD_DEGREES_TO_RADIANS )) { factor = 1.0; cutoff = 3.8; phase = 1; } else if ( sol_angle > ( SD_PI_2 + 7.5 * SGD_DEGREES_TO_RADIANS )) { factor = 0.95; cutoff = 3.1; phase = 2; } else if ( sol_angle > ( SD_PI_2 + 7.0 * SGD_DEGREES_TO_RADIANS )) { factor = 0.9; cutoff = 2.4; phase = 3; } else if ( sol_angle > ( SD_PI_2 + 6.5 * SGD_DEGREES_TO_RADIANS )) { factor = 0.85; cutoff = 1.8; phase = 4; } else if ( sol_angle > ( SD_PI_2 + 6.0 * SGD_DEGREES_TO_RADIANS )) { factor = 0.8; cutoff = 1.2; phase = 5; } else if ( sol_angle > ( SD_PI_2 + 5.5 * SGD_DEGREES_TO_RADIANS )) { factor = 0.75; cutoff = 0.6; phase = 6; } else { // early dusk or late dawn factor = 0.7; cutoff = 0.0; phase = 7; } if( phase != old_phase ) { old_phase = phase; for ( int i = 0; i < num; ++i ) { // if ( star_data[i][2] < min ) { min = star_data[i][2]; } // if ( star_data[i][2] > max ) { max = star_data[i][2]; } // magnitude ranges from -1 (bright) to 4 (dim). The // range of star and planet magnitudes can actually go // outside of this, but for our purpose, if it is brighter // that -1, we'll color it full white/alpha anyway and 4 // is a convenient cutoff point which keeps the number of // stars drawn at about 500. // color (magnitude) mag = star_data[i][2]; if ( mag < cutoff ) { nmag = ( 4.5 - mag ) / 5.5; // translate to 0 ... 1.0 scale // alpha = nmag * 0.7 + 0.3; // translate to a 0.3 ... 1.0 scale alpha = nmag * 0.85 + 0.15; // translate to a 0.15 ... 1.0 scale alpha *= factor; // dim when the sun is brighter } else { alpha = 0.0; } if (alpha > 1.0) { alpha = 1.0; } if (alpha < 0.0) { alpha = 0.0; } color = cl->get( i ); sgSetVec4( color, 1.0, 1.0, 1.0, (float)alpha ); } } return true; }
static ssgTransform *initWheel(tCarElt *car, int wheel_index) { int i, j, k; float alpha; sgVec3 vtx; sgVec4 clr; sgVec3 nrm; sgVec2 tex; tdble b_offset = 0.0f; tdble curAngle = 0.0f; #define BRK_BRANCH 16 #define BRK_ANGLE (2.0 * M_PI / (tdble)BRK_BRANCH) #define BRK_OFFSET 0.2 switch(wheel_index) { case FRNT_RGT: curAngle = -(M_PI / 2.0 + BRK_ANGLE); b_offset = BRK_OFFSET - car->_tireWidth(wheel_index) / 2.0; break; case FRNT_LFT: curAngle = -(M_PI / 2.0 + BRK_ANGLE); b_offset = car->_tireWidth(wheel_index) / 2.0 - BRK_OFFSET; break; case REAR_RGT: curAngle = (M_PI / 2.0 - BRK_ANGLE); b_offset = BRK_OFFSET - car->_tireWidth(wheel_index) / 2.0; break; case REAR_LFT: curAngle = (M_PI / 2.0 - BRK_ANGLE); b_offset = car->_tireWidth(wheel_index) / 2.0 - BRK_OFFSET; break; } /* hub */ ssgVertexArray *brk_vtx = new ssgVertexArray(BRK_BRANCH + 1); ssgColourArray *brk_clr = new ssgColourArray(1); ssgNormalArray *brk_nrm = new ssgNormalArray(1); tdble hubRadius; /* center */ vtx[0] = vtx[2] = 0.0; vtx[1] = b_offset; brk_vtx->add(vtx); hubRadius = car->_brakeDiskRadius(wheel_index) * 0.6; for (i = 0; i < BRK_BRANCH; i++) { alpha = (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1); vtx[0] = hubRadius * cos(alpha); vtx[1] = b_offset; vtx[2] = hubRadius * sin(alpha); brk_vtx->add(vtx); } clr[0] = clr[1] = clr[2] = 0.0; clr[3] = 1.0; brk_clr->add(clr); nrm[0] = nrm[2] = 0.0; // Make normal point outside to have proper lighting. switch(wheel_index) { case FRNT_RGT: case REAR_RGT: nrm[1] = -1.0; break; case FRNT_LFT: case REAR_LFT: nrm[1] = 1.0; break; } brk_nrm->add(nrm); ssgVtxTable *brk = new ssgVtxTable(GL_TRIANGLE_FAN, brk_vtx, brk_nrm, NULL, brk_clr); brk->setCullFace(0); brk->setState(commonState); ssgTransform *wheel = new ssgTransform; wheel->addKid(brk); /* Brake disk */ brk_vtx = new ssgVertexArray(BRK_BRANCH + 4); brk_clr = new ssgColourArray(1); brk_nrm = new ssgNormalArray(1); for (i = 0; i < (BRK_BRANCH / 2 + 2); i++) { alpha = curAngle + (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1); vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha); vtx[1] = b_offset; vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha); brk_vtx->add(vtx); vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha) * 0.6; vtx[1] = b_offset; vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha) * 0.6; brk_vtx->add(vtx); } clr[0] = clr[1] = clr[2] = 0.1; clr[3] = 1.0; brk_clr->add(clr); //nrm[0] = nrm[2] = 0.0; //nrm[1] = 1.0; brk_nrm->add(nrm); brk = new ssgVtxTable(GL_TRIANGLE_STRIP, brk_vtx, brk_nrm, NULL, brk_clr); brk->setCullFace(0); brk->setState(brakeState); grCarInfo[grCarIndex].brkColor[wheel_index] = brk_clr; wheel->addKid(brk); /* Brake caliper */ brk_vtx = new ssgVertexArray(BRK_BRANCH - 4); brk_clr = new ssgColourArray(1); brk_nrm = new ssgNormalArray(1); for (i = 0; i < (BRK_BRANCH / 2 - 2); i++) { alpha = - curAngle + (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1); vtx[0] = (car->_brakeDiskRadius(wheel_index) + 0.02) * cos(alpha); vtx[1] = b_offset; vtx[2] = (car->_brakeDiskRadius(wheel_index) + 0.02) * sin(alpha); brk_vtx->add(vtx); vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha) * 0.6; vtx[1] = b_offset; vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha) * 0.6; brk_vtx->add(vtx); } clr[0] = 0.2; clr[1] = 0.2; clr[2] = 0.2; clr[3] = 1.0; brk_clr->add(clr); //nrm[0] = nrm[2] = 0.0; //nrm[1] = 1.0; brk_nrm->add(nrm); brk = new ssgVtxTable(GL_TRIANGLE_STRIP, brk_vtx, brk_nrm, NULL, brk_clr); brk->setCullFace(0); brk->setState(commonState); wheel->addKid(brk); DBG_SET_NAME(wheel, "Wheel", grCarIndex, wheel_index); grCarInfo[grCarIndex].wheelPos[wheel_index] = wheel; /* wheels */ ssgTransform *whrotation = new ssgTransform; grCarInfo[grCarIndex].wheelRot[wheel_index] = whrotation; wheel->addKid(whrotation); ssgSelector *whselector = new ssgSelector; whrotation->addKid(whselector); grCarInfo[grCarIndex].wheelselector[wheel_index] = whselector; float wheelRadius = car->_rimRadius(wheel_index) + car->_tireHeight(wheel_index); // Create wheels for 4 speeds (stillstanding - fast --> motion blur, look at the texture). for (j = 0; j < 4; j++) { ssgBranch *whl_branch = new ssgBranch; ssgEntity *whl3d = 0; // load speed-dependant 3D wheels if available and if detailed wheels are desired. // wheel data files are located in the wheels directory. first set directory. if (grUseDetailedWheels == DETAILED) { const int bufsize = 1024; char buf[bufsize]; const char* wheel_dir = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_WHEEL_3D_DIR, 0); if (wheel_dir != 0) { snprintf(buf, bufsize, "wheels/%s", wheel_dir); ssgModelPath(buf); ssgTexturePath(buf); } // set basename for wheel file 0..3 gets appended const char* wheel_obj = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_WHEEL_3D, 0); if (wheel_obj != 0 && wheel_dir != 0) { snprintf(buf, bufsize, "%s%d.acc", wheel_obj, j); whl3d = grssgCarLoadAC3D(buf, NULL, car->index); } } // if we have a 3D wheel, use it. otherwise use normal generated wheel... if (whl3d) { // Adapt size of the wheel ssgTransform *whl_size = new ssgTransform; sgMat4 wheelsz; sgSetVec4(wheelsz[0], wheelRadius * 2, SG_ZERO, SG_ZERO, SG_ZERO) ; sgSetVec4(wheelsz[1], SG_ZERO, car->_tireWidth(wheel_index), SG_ZERO, SG_ZERO) ; sgSetVec4(wheelsz[2], SG_ZERO, SG_ZERO, wheelRadius * 2, SG_ZERO) ; sgSetVec4(wheelsz[3], SG_ZERO, SG_ZERO, SG_ZERO, SG_ONE) ; whl_size->setTransform(wheelsz); whl_size->addKid(whl3d); whl3d = whl_size; if (wheel_index == FRNT_RGT || wheel_index == REAR_RGT) { // flip wheel around so it faces the right way ssgTransform *whl_mesh_transform = new ssgTransform; sgCoord wheelpos; sgSetCoord(&wheelpos, 0, 0, 0, 180, 0, 0); whl_mesh_transform->setTransform( &wheelpos); whl_mesh_transform->addKid(whl3d); whl_branch->addKid(whl_mesh_transform); } else { whl_branch->addKid(whl3d); } } else { static sgVec2 toffset[4] = { {0.0, 0.5}, {0.5, 0.5}, {0.0, 0.0}, {0.5, 0.0} }; // TORCS's standard generated wheel const int WHL_BRANCH = 16; /* Tread */ { ssgVertexArray *whl_vtx = new ssgVertexArray(2 * WHL_BRANCH); ssgColourArray *whl_clr = new ssgColourArray(2 * WHL_BRANCH); ssgNormalArray *whl_nrm = new ssgNormalArray(1); whl_nrm->add(nrm); clr[3] = 1.0; for (i = 0; i < WHL_BRANCH; i++) { alpha = (float)i * 2.0 * M_PI / (float)(WHL_BRANCH - 1); vtx[0] = wheelRadius * cos(alpha); vtx[2] = wheelRadius * sin(alpha); vtx[1] = - car->_tireWidth(wheel_index) / 2.0; whl_vtx->add(vtx); vtx[1] = car->_tireWidth(wheel_index) / 2.0; whl_vtx->add(vtx); if (i % 2) { clr[0] = clr[1] = clr[2] = 0.15; } else { clr[0] = clr[1] = clr[2] = 0.0; } whl_clr->add(clr); whl_clr->add(clr); } ssgVtxTable *whl = new ssgVtxTable(GL_TRIANGLE_STRIP, whl_vtx, whl_nrm, NULL, whl_clr); whl->setState(commonState); whl->setCullFace(0); // stripify wheel, should improve performance ssgStripify(whl); whl_branch->addKid(whl); } /* Rim */ switch(wheel_index) { case FRNT_RGT: case REAR_RGT: b_offset = -0.05; break; case FRNT_LFT: case REAR_LFT: b_offset = 0.05; break; } // Make inside rim very dark and take care of normals. float colorfactor[2]; float norm_orig = nrm[1]; if (nrm[1] > 0.0f) { colorfactor[0] = 0.3f; colorfactor[1] = 1.0f; nrm[1] *= -1.0f; } else { colorfactor[0] = 1.0f; colorfactor[1] = 0.3f; } for (k = 0; k < 2; k++) { ssgVertexArray *whl_vtx = new ssgVertexArray(WHL_BRANCH + 1); ssgTexCoordArray *whl_tex = new ssgTexCoordArray(WHL_BRANCH + 1); ssgColourArray *whl_clr = new ssgColourArray(1); ssgNormalArray *whl_nrm = new ssgNormalArray(1); clr[0] = 0.8f*colorfactor[k]; clr[1] = 0.8f*colorfactor[k]; clr[2] = 0.8f*colorfactor[k]; clr[3] = 1.0f; whl_clr->add(clr); whl_nrm->add(nrm); vtx[0] = vtx[2] = 0.0; vtx[1] = (float)(2 * k - 1) * car->_tireWidth(wheel_index) / 2.0 - b_offset; whl_vtx->add(vtx); tex[0] = 0.25 + toffset[j][0]; tex[1] = 0.25 + toffset[j][1]; whl_tex->add(tex); vtx[1] = (float)(2 * k - 1) * car->_tireWidth(wheel_index) / 2.0; for (i = 0; i < WHL_BRANCH; i++) { alpha = (float)i * 2.0 * M_PI / (float)(WHL_BRANCH - 1); vtx[0] = wheelRadius * cos(alpha); vtx[2] = wheelRadius * sin(alpha); whl_vtx->add(vtx); tex[0] = 0.25 + 0.25 * cos(alpha) + toffset[j][0]; tex[1] = 0.25 + 0.25 * sin(alpha) + toffset[j][1]; whl_tex->add(tex); } ssgVtxTable *whl = new ssgVtxTable(GL_TRIANGLE_FAN, whl_vtx, whl_nrm, whl_tex, whl_clr); whl->setState(grCarInfo[grCarIndex].wheelTexture); whl->setCullFace(0); // stripify rim, should improve performance ssgStripify(whl); whl_branch->addKid(whl); // Swap normal for "inside" rim face. nrm[1] *= -1.0; } nrm[1] = norm_orig; } whselector->addKid(whl_branch); } return wheel; }
void cGrCloudLayer::build( ssgSimpleState *cloud_state, float span, float elevation, float thickness, float transition ) { layer_span = span; layer_asl = elevation; layer_thickness = thickness; layer_transition = transition; scale = 4000.0; last_lon = last_lat = -999.0f; last_x = last_y = 0.0f; sgVec2 base; sgSetVec2( base, (float)grRandom(), (float)grRandom() ); // build the cloud layer sgVec4 color; sgVec3 vertex; sgVec2 tc; const float layer_scale = layer_span / scale; const float mpi = SG_PI/4; const float alt_diff = layer_asl * 1.5f; for (int i = 0; i < 4; i++) { if ( layer[i] != NULL ) { layer_transform->removeKid(layer[i]); // automatic delete } vl[i] = new ssgVertexArray( 10 ); cl[i] = new ssgColourArray( 10 ); tl[i] = new ssgTexCoordArray( 10 ); sgSetVec3( vertex, layer_span*(i-2)/2, -layer_span, (float)(alt_diff * (sin(i*mpi) - 2)) ); sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] ); sgSetVec4( color, 1.0f, 1.0f, 1.0f, (i == 0) ? 0.0f : 0.15f ); cl[i]->add( color ); vl[i]->add( vertex ); tl[i]->add( tc ); for (int j = 0; j < 4; j++) { sgSetVec3( vertex, layer_span*(i-1)/2, layer_span*(j-2)/2, (float)(alt_diff * (sin((i+1)*mpi) + sin(j*mpi) - 2)) ); sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, base[1] + layer_scale * j/4 ); sgSetVec4( color, 1.0f, 1.0f, 1.0f, ( (j == 0) || (i == 3)) ? ( (j == 0) && (i == 3)) ? 0.0f : 0.15f : 1.0f ); cl[i]->add( color ); vl[i]->add( vertex ); tl[i]->add( tc ); sgSetVec3( vertex, layer_span*(i-2)/2, layer_span*(j-1)/2, (float)(alt_diff * (sin(i*mpi) + sin((j+1)*mpi) - 2)) ); sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] + layer_scale * (j+1)/4 ); sgSetVec4( color, 1.0f, 1.0f, 1.0f, ((j == 3) || (i == 0)) ? ((j == 3) && (i == 0)) ? 0.0f : 0.15f : 1.0f ); cl[i]->add( color ); vl[i]->add( vertex ); tl[i]->add( tc ); } sgSetVec3( vertex, layer_span*(i-1)/2, layer_span, (float)(alt_diff * (sin((i+1)*mpi) - 2)) ); sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, base[1] + layer_scale ); sgSetVec4( color, 1.0f, 1.0f, 1.0f, (i == 3) ? 0.0f : 0.15f ); cl[i]->add( color ); vl[i]->add( vertex ); tl[i]->add( tc ); layer[i] = new ssgVtxTable(GL_TRIANGLE_STRIP, vl[i], NULL, tl[i], cl[i]); layer_transform->addKid( layer[i] ); layer[i]->setState( cloud_state ); } // force a repaint of the sky colors with arbitrary defaults repaint( color ); }
/** \brief The per-frame OpenGL display routine * * This function does the complete OpenGL drawing. First * the 3D scene is drawn, then some 2D overlays * (wind and battery indicator, GUI). */ void display() { CRRCMath::Vector3 plane_pos = FDM2Graphics(Global::aircraft->getPos()); // Prepare the current frame buffer and reset // the modelview matrix (for non-SSG drawing) GLbitfield clearmask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; if (vidbits.stencil) { clearmask |= GL_STENCIL_BUFFER_BIT; } glClear(clearmask); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); //~ glBlendFunc(GL_ONE, GL_ZERO); //~ glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); // Set up the viewing transformation (for SSG drawing) sgVec3 viewpos, planepos, up; sgSetVec3(viewpos, player_pos.r[0], player_pos.r[1], player_pos.r[2]); sgSetVec3(planepos, looking_pos.r[0], looking_pos.r[1], looking_pos.r[2]); sgSetVec3(up, 0.0, 1.0, 0.0); context->setCameraLookAt(viewpos, planepos, up); // 3D scene if( Global::scenery != NULL) { // 3D scene: sky sphere draw_sky(&viewpos, Global::Simulation->getTotalTime()); // 3D scene: airplane if (Global::aircraft->getModel() != NULL) { // For SSG rendering, this call does not draw anything, // but calculates the airplane's transformation matrix glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); Global::aircraft->getModel()->draw(Global::aircraft->getFDM()); } // 3D scene: scenery Global::scenery->draw(Global::Simulation->getTotalTime()); } // Lighting setup. Only needed as long as there are // non-SSG parts that modify the light sources. sgVec4 lightamb; sgSetVec4(lightamb , 0.2f, 0.2f, 0.2f, 1.0f); ssgGetLight(0)->setPosition(lightposn); ssgGetLight(0)->setColour(GL_AMBIENT, lightamb); // Draw the scenegraph (airplane model, shadow) ssgCullAndDraw(scene); context->forceBasicState(); // ssgCullAndDraw() ends up with an identity modelview matrix, // so we have to set up our own viewing transformation for // the thermals glLoadIdentity(); gluLookAt(player_pos.r[0], player_pos.r[1], player_pos.r[2], looking_pos.r[0], looking_pos.r[1], looking_pos.r[2], 0.0, 1.0, 0.0); if (Global::training_mode==TRUE) { draw_thermals(Global::aircraft->getPos()); } // 3D scene: game-mode-specific stuff (pylons etc.) Global::gameHandler->draw(); glPopMatrix(); // Overlay: game handler Global::gameHandler->display_infos(window_xsize, window_ysize); // Overlay: scope for audio interface if ( Global::testmode.test_mode && (Global::TXInterface->inputMethod() == T_TX_Interface::eIM_audio) ) { GlOverlay::setupRenderingState(window_xsize, window_ysize); oscillo(); GlOverlay::restoreRenderingState(); } // Overlay: wind direction indicator { double dx = (plane_pos.r[2] - player_pos.r[2]); double dy = (player_pos.r[0] - plane_pos.r[0]); double dir = atan2(dy, dx); GlOverlay::setupRenderingState(window_xsize, window_ysize); draw_wind(dir); GlOverlay::restoreRenderingState(); } // Overlay: battery capacity/fuel left { int r = window_ysize >> 5; int w = r >> 1; int h = window_ysize >> 3; int ht = (int)(Global::aircraft->getFDM()->getBatCapLeft() * h); #if 0 glDisable(GL_LIGHTING); glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity (); gluOrtho2D (0, window_xsize-1, 0, window_ysize); #endif GlOverlay::setupRenderingState(window_xsize, window_ysize); // Background glColor3f (0, 0, 0); glRectf(window_xsize-w, r+ht, window_xsize-1, r+h); glTranslatef(0,0,0.1); // Indicator glColor3f (0, 1, 0.); glRectf(window_xsize-w, r, window_xsize-1, r+ht); #if 0 glPopMatrix(); glEnable(GL_LIGHTING); glMatrixMode(GL_MODELVIEW); #endif GlOverlay::restoreRenderingState(); } // Overlay: console console->render(window_xsize, window_ysize); // Overlay: gui Global::gui->draw(); // check for any OpenGL errors evaluateOpenGLErrors(); // Force pipeline flushing and flip front and back buffer glFlush(); SDL_GL_SwapBuffers(); }
ssgBranch * cGrCelestialBody::build( ssgSimpleState *orb_state, ssgSimpleState *halo_state, double body_size ) { ssgVertexArray *halo_vl; ssgTexCoordArray *halo_tl; // clean-up previous ssgDeRefDelete( transform ); // build the ssg scene graph sub tree for the sky and connected // into the provide scene graph branch transform = new ssgTransform; transform->ref(); cl = new ssgColourArray( 1 ); sgVec4 color; sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); cl->add( color ); ssgBranch *orb = grMakeSphere( orb_state, cl, (float)body_size, 15, 15, grCelestialBodyOrbPreDraw, grCelestialBodyOrbPostDraw ); transform->addKid( orb ); // force a repaint of the colors with arbitrary defaults repaint( 0.0 ); if (halo_state) { // Build ssg structure float size = float(body_size * 10.0); sgVec3 v3; halo_vl = new ssgVertexArray; sgSetVec3( v3, -size, 0.0, -size ); halo_vl->add( v3 ); sgSetVec3( v3, size, 0.0, -size ); halo_vl->add( v3 ); sgSetVec3( v3, -size, 0.0, size ); halo_vl->add( v3 ); sgSetVec3( v3, size, 0.0, size ); halo_vl->add( v3 ); sgVec2 v2; halo_tl = new ssgTexCoordArray; sgSetVec2( v2, 0.0f, 0.0f ); halo_tl->add( v2 ); sgSetVec2( v2, 1.0, 0.0 ); halo_tl->add( v2 ); sgSetVec2( v2, 0.0, 1.0 ); halo_tl->add( v2 ); sgSetVec2( v2, 1.0, 1.0 ); halo_tl->add( v2 ); ssgLeaf *halo = new ssgVtxTable ( GL_TRIANGLE_STRIP, halo_vl, NULL, halo_tl, cl ); halo->setState( halo_state ); halo->setCallback( SSG_CALLBACK_PREDRAW, grCelestialBodyHaloPreDraw ); halo->setCallback( SSG_CALLBACK_POSTDRAW, grCelestialBodyHaloPostDraw ); transform->addKid( halo ); //transform->addKid(new ssgaLensFlare); } return transform; }
SceneObject::SceneObject() { sgSetVec3( pos, 0.0, 0.0, 0.0 ); sgSetVec3( hpr, 0.0, 0.0, 0.0 ); sgSetVec4( dbgDiffColor, 1.0, 0.5, 0.5, 1.0 ); }
void TransIcelandicExpress::loadLevel( const char *filename ) { FILE *fp = fopen( filename, "r" ); char line[1000], cmd[100], type[100]; IceFloe *floe; sgVec2 *pnt; float x, y; int num, npnt, i, j; // clear any floes for (std::vector<IceFloe*>::iterator floei=floes.begin(); floei != floes.end(); floei++ ) { delete *floei; } floes.erase( floes.begin(), floes.end() ); while (fgets( line, 1000, fp )) { if (line[0]=='#') continue; sscanf( line, "%s", cmd ); if (!strcmp(cmd, "location")) { sscanf( line, "%*s %f %f %s\n", &x, &y, type ); if (!strcmp( type, "StartPos" )) { sgSetVec3( player->pos, x, 0.05f, y ); player->pos[1] = getHeight( player->pos ); } else if (!strcmp( type, "Sheep" )) { SceneObject *shp; shp = new SceneObject(); sgSetVec3( shp->pos, x, 0.05f, y ); shp->pos[1] = getHeight( shp->pos ); sgSetVec4( shp->dbgDiffColor, 0.8f, 0.8f, 0.8f, 1.0f ); sheep.push_back( shp ); } else if (!strcmp( type, "Crate" )) { SceneObject *crt; crt = new SceneObject(); sgSetVec3( crt->pos, x, 0.05f, y ); crt->pos[1] = getHeight( crt->pos ); sgSetVec4( crt->dbgDiffColor, 1.0f, 0.9f, 0.4f, 1.0f ); crates.push_back( crt ); } } else if (!strcmp(cmd, "mapsize")) { // delete the old map if present for (j = 0; j < roadY; j++) { for (i = 0; i < roadX; i++) { delete road[i][j]; road[i][j] = NULL; } } sscanf( line, "%*s %d %d", &roadX, &roadY ); // make a new map for (j = 0; j < roadY; j++) { for (i = 0; i < roadX; i++) { road[i][j] = new Road(); } } } else if (!strcmp(cmd, "road_tiles")) { int pylon, roadway; sscanf( line, "%*s %d", &num ); for (int n = 0; n < num; n++ ) { fgets( line, 1000, fp ); sscanf( line, "%s %d %d %d %d", cmd, &i, &j, &roadway, &pylon ); if (strcmp(cmd, "road")) { printf( "Error: Expecting 'road' got %s\n", line ); } else { road[i][j]->pylon = pylon; road[i][j]->road = roadway; road[i][j]->base_height = c_RoadLevel * 0.5; sgSetVec3( road[i][j]->pos, float(i) + 0.5f, 0.0f, float(j) + 0.5f); } } } else if (!strcmp(cmd, "num_floes")) { sscanf( line, "%*s %d", &num ); for (i = 0; i < num; i++) { fgets( line, 1000, fp ); floe = new IceFloe(); sscanf( line, "%s %f %f %d %d %s %d", cmd, &(floe->health), &(floe->height), &(floe->breakable), &(floe->anchored), type, &npnt ); pnt = new sgVec2[ npnt ]; for ( j = 0; j < npnt; j++ ) { fgets( line, 1000, fp ); sscanf( line, "%f %f", &x, &y ); pnt[j][0] = x; pnt[j][1] = y; } floe->build( npnt, pnt ); delete [] pnt; floes.push_back( floe ); } } else { printf ("Skipping command %s \n", cmd ); } } }
//-------------------------------------------------------------------- IceFloe::IceFloe() : SceneObject() { sgSetVec4( dbgDiffColor, 0.4f, 0.8f, 1.0f, 1.0f ); }
// initialize the sky object and connect it into our scene graph ssgBranch * cGrSkyDome::build( double hscale, double vscale ) { sgVec4 color; double theta; int i; // clean-up previous ssgDeRefDelete( dome_transform ); // create new dome_transform = new ssgTransform; dome_transform->ref(); // set up the state dome_state = new ssgSimpleState(); dome_state->setShadeModel( GL_SMOOTH ); dome_state->disable( GL_LIGHTING ); dome_state->disable( GL_CULL_FACE ); dome_state->disable( GL_TEXTURE_2D ); dome_state->enable( GL_COLOR_MATERIAL ); dome_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); dome_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); dome_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); dome_state->disable( GL_BLEND ); dome_state->disable( GL_ALPHA_TEST ); // initialize arrays center_disk_vl = new ssgVertexArray( 14 ); center_disk_cl = new ssgColourArray( 14 ); upper_ring_vl = new ssgVertexArray( 26 ); upper_ring_cl = new ssgColourArray( 26 ); middle_ring_vl = new ssgVertexArray( 26 ); middle_ring_cl = new ssgColourArray( 26 ); lower_ring_vl = new ssgVertexArray( 26 ); lower_ring_cl = new ssgColourArray( 26 ); // initially seed to all blue sgSetVec4( color, 0.0, 0.0, 1.0, 1.0 ); // generate the raw vertex data sgVec3 center_vertex; sgVec3 upper_vertex[12]; sgVec3 middle_vertex[12]; sgVec3 lower_vertex[12]; sgVec3 bottom_vertex[12]; sgSetVec3( center_vertex, 0.0, 0.0, (float)(center_elev * vscale)); for ( i = 0; i < 12; i++ ) { theta = (i * 30.0) * SGD_DEGREES_TO_RADIANS; sgSetVec3( upper_vertex[i], (float)(cos(theta) * upper_radius * hscale), (float)(sin(theta) * upper_radius * hscale), (float)(upper_elev * vscale)); sgSetVec3( middle_vertex[i], (float)(cos(theta) * middle_radius * hscale), (float)(sin(theta) * middle_radius * hscale), (float)(middle_elev * vscale)); sgSetVec3( lower_vertex[i], (float)(cos(theta) * lower_radius * hscale), (float)(sin(theta) * lower_radius * hscale), (float)(lower_elev * vscale)); sgSetVec3( bottom_vertex[i], (float)(cos(theta) * bottom_radius * hscale), (float)(sin(theta) * bottom_radius * hscale), (float)(bottom_elev * vscale)); } // generate the center disk vertex/color arrays center_disk_vl->add( center_vertex ); center_disk_cl->add( color ); for ( i = 11; i >= 0; i-- ) { center_disk_vl->add( upper_vertex[i] ); center_disk_cl->add( color ); } center_disk_vl->add( upper_vertex[11] ); center_disk_cl->add( color ); // generate the upper ring for ( i = 0; i < 12; i++ ) { upper_ring_vl->add( middle_vertex[i] ); upper_ring_cl->add( color ); upper_ring_vl->add( upper_vertex[i] ); upper_ring_cl->add( color ); } upper_ring_vl->add( middle_vertex[0] ); upper_ring_cl->add( color ); upper_ring_vl->add( upper_vertex[0] ); upper_ring_cl->add( color ); // generate middle ring for ( i = 0; i < 12; i++ ) { middle_ring_vl->add( lower_vertex[i] ); middle_ring_cl->add( color ); middle_ring_vl->add( middle_vertex[i] ); middle_ring_cl->add( color ); } middle_ring_vl->add( lower_vertex[0] ); middle_ring_cl->add( color ); middle_ring_vl->add( middle_vertex[0] ); middle_ring_cl->add( color ); // generate lower ring for ( i = 0; i < 12; i++ ) { lower_ring_vl->add( bottom_vertex[i] ); lower_ring_cl->add( color ); lower_ring_vl->add( lower_vertex[i] ); lower_ring_cl->add( color ); } lower_ring_vl->add( bottom_vertex[0] ); lower_ring_cl->add( color ); lower_ring_vl->add( lower_vertex[0] ); lower_ring_cl->add( color ); // force a repaint of the sky colors with ugly defaults sgVec3 fog_color; sgSetVec3( fog_color, 1.0, 1.0, 1.0 ); repaint( color, fog_color, 0.0, 5000.0 ); // build the ssg scene graph sub tree for the sky and connected // into the provide scene graph branch ssgVtxTable *center_disk, *upper_ring, *middle_ring, *lower_ring; center_disk = new ssgVtxTable( GL_TRIANGLE_FAN, center_disk_vl, NULL, NULL, center_disk_cl ); upper_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, upper_ring_vl, NULL, NULL, upper_ring_cl ); middle_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, middle_ring_vl, NULL, NULL, middle_ring_cl ); lower_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, lower_ring_vl, NULL, NULL, lower_ring_cl ); center_disk->setState( dome_state ); upper_ring->setState( dome_state ); middle_ring->setState( dome_state ); lower_ring->setState( dome_state ); dome_transform->addKid( center_disk ); dome_transform->addKid( upper_ring ); dome_transform->addKid( middle_ring ); dome_transform->addKid( lower_ring ); // not entirely satisfying. We are depending here that the first // thing we add to a parent is the first drawn center_disk->setCallback( SSG_CALLBACK_PREDRAW, grSkyDomePreDraw ); center_disk->setCallback( SSG_CALLBACK_POSTDRAW, grSkyDomePostDraw ); upper_ring->setCallback( SSG_CALLBACK_PREDRAW, grSkyDomePreDraw ); upper_ring->setCallback( SSG_CALLBACK_POSTDRAW, grSkyDomePostDraw ); middle_ring->setCallback( SSG_CALLBACK_PREDRAW, grSkyDomePreDraw ); middle_ring->setCallback( SSG_CALLBACK_POSTDRAW, grSkyDomePostDraw ); lower_ring->setCallback( SSG_CALLBACK_PREDRAW, grSkyDomePreDraw ); lower_ring->setCallback( SSG_CALLBACK_POSTDRAW, grSkyDomePostDraw ); return dome_transform; }