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 cGrCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double dt ) { sgMat4 T1, LON, LAT; sgVec3 axis; // combine p and asl (meters) to get translation offset sgVec3 asl_offset; sgCopyVec3( asl_offset, up ); sgNormalizeVec3( asl_offset ); if ( alt <= layer_asl ) { sgScaleVec3( asl_offset, layer_asl ); } else { sgScaleVec3( asl_offset, layer_asl + layer_thickness ); } sgAddVec3( asl_offset, p ); // Translate to zero elevation sgMakeTransMat4( T1, asl_offset ); // Rotate to proper orientation sgSetVec3( axis, 0.0, 0.0, 1.0 ); sgMakeRotMat4( LON, (float)(lon * SGD_RADIANS_TO_DEGREES), axis ); sgSetVec3( axis, 0.0, 1.0, 0.0 ); sgMakeRotMat4( LAT, (float)(90.0 - lat * SGD_RADIANS_TO_DEGREES), axis ); sgMat4 TRANSFORM; sgCopyMat4( TRANSFORM, T1 ); sgPreMultMat4( TRANSFORM, LON ); sgPreMultMat4( TRANSFORM, LAT ); sgCoord layerpos; sgSetCoord( &layerpos, TRANSFORM ); layer_transform->setTransform( &layerpos ); // now calculate update texture coordinates if ( last_lon < -900 ) { last_lon = lon; last_lat = lat; } double sp_dist = speed*dt; if ( lon != last_lon || lat != last_lat || sp_dist != 0 ) { double course = 0.0, dist = 0.0; if ( lon != last_lon || lat != last_lat ) { sgVec2 start, dest; sgSetVec2(start, (float)last_lon, (float)last_lat); sgSetVec2(dest, (float)lon, (float)lat); calc_gc_course_dist( dest, start, &course, &dist ); } // calculate cloud movement double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0; if (dist > 0.0) { ax = cos(course) * dist; ay = sin(course) * dist; } if (sp_dist > 0) { bx = cos(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist; by = sin(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist; } float xoff = (float)((ax + bx) / (2 * scale)); float yoff = (float)((ay + by) / (2 * scale)); const float layer_scale = layer_span / scale; float *base, *tc; base = tl[0]->get( 0 ); base[0] += xoff; if ( base[0] > -10.0 && base[0] < 10.0 ) { base[0] -= (int)base[0]; } else { base[0] = 0.0; ulSetError(UL_WARNING, "Warning: base1\n"); } base[1] += yoff; if ( base[1] > -10.0 && base[1] < 10.0 ) { base[1] -= (int)base[1]; } else { base[1] = 0.0; ulSetError(UL_WARNING, "Warning: base2\n"); } for (int i = 0; i < 4; i++) { tc = tl[i]->get( 0 ); sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] ); for (int j = 0; j < 4; j++) { tc = tl[i]->get( j*2+1 ); sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, base[1] + layer_scale * j/4 ); tc = tl[i]->get( (j+1)*2 ); sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] + layer_scale * (j+1)/4 ); } tc = tl[i]->get( 9 ); sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, base[1] + layer_scale ); } last_lon = lon; last_lat = lat; } return true; }
static void initBackground(void) { int i; float x, y, z1, z2; double alpha; float texLen; tTrackGraphicInfo *graphic; ssgSimpleState *envst; sgVec3 vtx; sgVec4 clr; sgVec3 nrm; sgVec2 tex; static char buf[1024]; ssgVtxTable *bg; ssgVertexArray *bg_vtx; ssgTexCoordArray *bg_tex; ssgColourArray *bg_clr; ssgNormalArray *bg_nrm; ssgSimpleState *bg_st; sprintf(buf, "tracks/%s/%s;data/img;data/textures;.", grTrack->category, grTrack->internalname); grFilePath = buf; grGammaValue = 1.8; grMipMap = 0; graphic = &grTrack->graphic; glClearColor(graphic->bgColor[0], graphic->bgColor[1], graphic->bgColor[2], 1.0); BackgroundTex = BackgroundTex2 = 0; TheBackground = new ssgRoot(); clr[0] = clr[1] = clr[2] = 1.0; clr[3] = 1.0; nrm[0] = nrm[2] = 0.0; nrm[1] = 1.0; z1 = -0.5; z2 = 1.0; BackgroundType = graphic->bgtype; switch (BackgroundType) { case 0: bg_vtx = new ssgVertexArray(NB_BG_FACES + 1); bg_tex = new ssgTexCoordArray(NB_BG_FACES + 1); bg_clr = new ssgColourArray(1); bg_nrm = new ssgNormalArray(1); bg_clr->add(clr); bg_nrm->add(nrm); for (i = 0; i < NB_BG_FACES + 1; i++) { alpha = (float)i * 2 * PI / (float)NB_BG_FACES; texLen = (float)i / (float)NB_BG_FACES; x = BG_DIST * cos(alpha); y = BG_DIST * sin(alpha); vtx[0] = x; vtx[1] = y; vtx[2] = z1; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 0; bg_tex->add(tex); vtx[0] = x; vtx[1] = y; vtx[2] = z2; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 1.0; bg_tex->add(tex); } bg = new ssgVtxTable(GL_TRIANGLE_STRIP, bg_vtx, bg_nrm, bg_tex, bg_clr); bg_st = (ssgSimpleState*)grSsgLoadTexState(graphic->background); bg_st->disable(GL_LIGHTING); bg->setState(bg_st); bg->setCullFace(0); TheBackground->addKid(bg); break; case 2: bg_vtx = new ssgVertexArray(NB_BG_FACES + 1); bg_tex = new ssgTexCoordArray(NB_BG_FACES + 1); bg_clr = new ssgColourArray(1); bg_nrm = new ssgNormalArray(1); bg_clr->add(clr); bg_nrm->add(nrm); for (i = 0; i < NB_BG_FACES / 4 + 1; i++) { alpha = (float)i * 2 * PI / (float)NB_BG_FACES; texLen = (float)i / (float)NB_BG_FACES; x = BG_DIST * cos(alpha); y = BG_DIST * sin(alpha); vtx[0] = x; vtx[1] = y; vtx[2] = z1; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 0; bg_tex->add(tex); vtx[0] = x; vtx[1] = y; vtx[2] = z2; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 0.5; bg_tex->add(tex); } bg = new ssgVtxTable(GL_TRIANGLE_STRIP, bg_vtx, bg_nrm, bg_tex, bg_clr); bg_st = (ssgSimpleState*)grSsgLoadTexState(graphic->background); bg_st->disable(GL_LIGHTING); bg->setState(bg_st); bg->setCullFace(0); TheBackground->addKid(bg); bg_vtx = new ssgVertexArray(NB_BG_FACES + 1); bg_tex = new ssgTexCoordArray(NB_BG_FACES + 1); bg_clr = new ssgColourArray(1); bg_nrm = new ssgNormalArray(1); bg_clr->add(clr); bg_nrm->add(nrm); for (i = NB_BG_FACES/4; i < NB_BG_FACES / 2 + 1; i++) { alpha = (float)i * 2 * PI / (float)NB_BG_FACES; texLen = (float)i / (float)NB_BG_FACES; x = BG_DIST * cos(alpha); y = BG_DIST * sin(alpha); vtx[0] = x; vtx[1] = y; vtx[2] = z1; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 0.5; bg_tex->add(tex); vtx[0] = x; vtx[1] = y; vtx[2] = z2; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 1.0; bg_tex->add(tex); } bg = new ssgVtxTable(GL_TRIANGLE_STRIP, bg_vtx, bg_nrm, bg_tex, bg_clr); bg_st = (ssgSimpleState*)grSsgLoadTexState(graphic->background); bg_st->disable(GL_LIGHTING); bg->setState(bg_st); bg->setCullFace(0); TheBackground->addKid(bg); bg_vtx = new ssgVertexArray(NB_BG_FACES + 1); bg_tex = new ssgTexCoordArray(NB_BG_FACES + 1); bg_clr = new ssgColourArray(1); bg_nrm = new ssgNormalArray(1); bg_clr->add(clr); bg_nrm->add(nrm); for (i = NB_BG_FACES / 2; i < 3 * NB_BG_FACES / 4 + 1; i++) { alpha = (float)i * 2 * PI / (float)NB_BG_FACES; texLen = (float)i / (float)NB_BG_FACES; x = BG_DIST * cos(alpha); y = BG_DIST * sin(alpha); vtx[0] = x; vtx[1] = y; vtx[2] = z1; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 0.0; bg_tex->add(tex); vtx[0] = x; vtx[1] = y; vtx[2] = z2; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 0.5; bg_tex->add(tex); } bg = new ssgVtxTable(GL_TRIANGLE_STRIP, bg_vtx, bg_nrm, bg_tex, bg_clr); bg_st = (ssgSimpleState*)grSsgLoadTexState(graphic->background); bg_st->disable(GL_LIGHTING); bg->setState(bg_st); bg->setCullFace(0); TheBackground->addKid(bg); bg_vtx = new ssgVertexArray(NB_BG_FACES + 1); bg_tex = new ssgTexCoordArray(NB_BG_FACES + 1); bg_clr = new ssgColourArray(1); bg_nrm = new ssgNormalArray(1); bg_clr->add(clr); bg_nrm->add(nrm); for (i = 3 * NB_BG_FACES / 4; i < NB_BG_FACES + 1; i++) { alpha = (float)i * 2 * PI / (float)NB_BG_FACES; texLen = (float)i / (float)NB_BG_FACES; x = BG_DIST * cos(alpha); y = BG_DIST * sin(alpha); vtx[0] = x; vtx[1] = y; vtx[2] = z1; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 0.5; bg_tex->add(tex); vtx[0] = x; vtx[1] = y; vtx[2] = z2; bg_vtx->add(vtx); tex[0] = texLen*4.0; tex[1] = 1.0; bg_tex->add(tex); } bg = new ssgVtxTable(GL_TRIANGLE_STRIP, bg_vtx, bg_nrm, bg_tex, bg_clr); bg_st = (ssgSimpleState*)grSsgLoadTexState(graphic->background); bg_st->disable(GL_LIGHTING); bg->setState(bg_st); bg->setCullFace(0); TheBackground->addKid(bg); break; case 4: z1 = -1.0; z2 = 1.0; bg_vtx = new ssgVertexArray(NB_BG_FACES + 1); bg_tex = new ssgTexCoordArray(NB_BG_FACES + 1); bg_clr = new ssgColourArray(1); bg_nrm = new ssgNormalArray(1); bg_clr->add(clr); bg_nrm->add(nrm); for (i = 0; i < NB_BG_FACES + 1; i++) { alpha = (double)i * 2 * PI / (double)NB_BG_FACES; texLen = 1.0 - (float)i / (float)NB_BG_FACES; x = BG_DIST * cos(alpha); y = BG_DIST * sin(alpha); vtx[0] = x; vtx[1] = y; vtx[2] = z1; bg_vtx->add(vtx); tex[0] = texLen; tex[1] = 0; bg_tex->add(tex); vtx[0] = x; vtx[1] = y; vtx[2] = z2; bg_vtx->add(vtx); tex[0] = texLen; tex[1] = 1.0; bg_tex->add(tex); } bg = new ssgVtxTable(GL_TRIANGLE_STRIP, bg_vtx, bg_nrm, bg_tex, bg_clr); bg_st = (ssgSimpleState*)grSsgLoadTexState(graphic->background); bg_st->disable(GL_LIGHTING); bg->setState(bg_st); bg->setCullFace(0); TheBackground->addKid(bg); break; default: break; } /* Environment Mapping Settings */ grEnvSelector = new ssgStateSelector(graphic->envnb); for (i = 0; i < graphic->envnb; i++) { GfOut("Loading Environment Mapping Image %s\n", graphic->env[i]); envst = (ssgSimpleState*)grSsgLoadTexState(graphic->env[i]); envst->enable(GL_BLEND); grEnvSelector->setStep(i, envst); envst->deRef(); } grEnvSelector->selectStep(0); /* mandatory !!! */ grEnvState=(grMultiTexState*)grSsgEnvTexState(graphic->env[0]); grEnvShadowState=(grMultiTexState*)grSsgEnvTexState("envshadow.png"); grEnvShadowStateOnCars=(grMultiTexState*)grSsgEnvTexState("shadow2.rgb"); if (grEnvShadowState==NULL) { ulSetError ( UL_WARNING, "grscene:initBackground Failed to open envshadow.png for reading") ; ulSetError ( UL_WARNING, " mandatory for top env mapping ") ; ulSetError ( UL_WARNING, " should be in the .xml !! ") ; ulSetError ( UL_WARNING, " copy the envshadow.png from g-track-2 to the track you selected ") ; ulSetError ( UL_WARNING, " c'est pas classe comme sortie, mais ca evite un crash ") ; GfScrShutdown(); exit(-1); } if (grEnvShadowStateOnCars==NULL) { ulSetError ( UL_WARNING, "grscene:initBackground Failed to open shadow2.rgb for reading") ; ulSetError ( UL_WARNING, " no shadow mapping on cars for this track ") ; } }
bool cGrCloudLayer::repositionFlat( sgVec3 p, double dt ) { sgMat4 T1; // combine p and asl (meters) to get translation offset sgVec3 asl_offset; if ( p[SG_Z] <= layer_asl ) { sgSetVec3( asl_offset, p[SG_X], p[SG_Y], layer_asl ); } else { sgSetVec3( asl_offset, p[SG_X], p[SG_Y], layer_asl + layer_thickness ); } // Translate to elevation sgMakeTransMat4( T1, asl_offset ); sgMat4 TRANSFORM; sgCopyMat4( TRANSFORM, T1 ); sgCoord layerpos; sgSetCoord( &layerpos, TRANSFORM ); layer_transform->setTransform( &layerpos ); // now calculate update texture coordinates double sp_dist = speed*dt; if ( p[SG_X] != last_x || p[SG_Y] != last_y || sp_dist != 0 ) { // calculate cloud movement double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0; ax = p[SG_X] - last_x; ay = p[SG_Y] - last_y; if (sp_dist > 0) { bx = cos(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist; by = sin(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist; } float xoff = (float)((ax + bx) / (2 * scale)); float yoff = (float)((ay + by) / (2 * scale)); const float layer_scale = layer_span / scale; float *base, *tc; base = tl[0]->get( 0 ); base[0] += xoff; // the while loops can lead to *long* pauses if base[0] comes // with a bogus value. // while ( base[0] > 1.0 ) { base[0] -= 1.0; } // while ( base[0] < 0.0 ) { base[0] += 1.0; } if ( base[0] > -10.0 && base[0] < 10.0 ) { base[0] -= (int)base[0]; } else { base[0] = 0.0; ulSetError(UL_WARNING, "Warning: base1\n"); } base[1] += yoff; // the while loops can lead to *long* pauses if base[0] comes // with a bogus value. // while ( base[1] > 1.0 ) { base[1] -= 1.0; } // while ( base[1] < 0.0 ) { base[1] += 1.0; } if ( base[1] > -10.0 && base[1] < 10.0 ) { base[1] -= (int)base[1]; } else { base[1] = 0.0; ulSetError(UL_WARNING, "Warning: base2\n"); } for (int i = 0; i < 4; i++) { tc = tl[i]->get( 0 ); sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] ); for (int j = 0; j < 4; j++) { tc = tl[i]->get( j*2+1 ); sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, base[1] + layer_scale * j/4 ); tc = tl[i]->get( (j+1)*2 ); sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] + layer_scale * (j+1)/4 ); } tc = tl[i]->get( 9 ); sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, base[1] + layer_scale ); } last_x = p[SG_X]; last_y = p[SG_Y]; } return true; }
ssgBranch *grMakeSphere( ssgSimpleState *state, ssgColourArray *cl, float radius, int slices, int stacks, ssgCallback predraw, ssgCallback postdraw ) { double rho, drho, theta, dtheta; float x, y, z; float s, t, ds, dt; int i, j, imin, imax; float nsign = 1.0; ssgBranch *sphere = new ssgBranch; sgVec2 vec2; sgVec3 vec3; drho = SGD_PI / (float)stacks; dtheta = (2.0 * SGD_PI) / (float)slices; /* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */ ds = 1.0f / slices; dt = 1.0f / stacks; t = 1.0; /* because loop now runs from 0 */ imin = 0; imax = stacks; /* build slices as quad strips */ for ( i = imin; i < imax; i++ ) { ssgVertexArray *vl = new ssgVertexArray(); ssgNormalArray *nl = new ssgNormalArray(); ssgTexCoordArray *tl = new ssgTexCoordArray(); rho = i * drho; s = 0.0; for ( j = 0; j <= slices; j++ ) { theta = (j == slices) ? 0.0 : j * dtheta; x = (float)(-sin(theta) * sin(rho)); y = (float)(cos(theta) * sin(rho)); z = (float)(nsign * cos(rho)); sgSetVec3( vec3, x*nsign, y*nsign, z*nsign ); sgNormalizeVec3( vec3 ); nl->add( vec3 ); sgSetVec2( vec2, s, t ); tl->add( vec2 ); sgSetVec3( vec3, x*radius, y*radius, z*radius ); vl->add( vec3 ); x = (float)(-sin(theta) * sin(rho+drho)); y = (float)(cos(theta) * sin(rho+drho)); z = (float)(nsign * cos(rho+drho)); sgSetVec3( vec3, x*nsign, y*nsign, z*nsign ); sgNormalizeVec3( vec3 ); nl->add( vec3 ); sgSetVec2( vec2, s, t-dt ); tl->add( vec2 ); s += ds; sgSetVec3( vec3, x*radius, y*radius, z*radius ); vl->add( vec3 ); } ssgLeaf *slice = new ssgVtxTable ( GL_TRIANGLE_STRIP, vl, nl, tl, cl ); if ( vl->getNum() != nl->getNum() ) { ulSetError(UL_FATAL, "bad sphere1\n"); exit(-1); } if ( vl->getNum() != tl->getNum() ) { ulSetError(UL_FATAL, "bad sphere2\n"); exit(-1); } slice->setState( state ); slice->setCallback( SSG_CALLBACK_PREDRAW, predraw ); slice->setCallback( SSG_CALLBACK_POSTDRAW, postdraw ); sphere->addKid( slice ); t -= dt; } return sphere; }