void IceFloe::build( int nsrcpnt, sgVec2 *srcpnt ) { sgVec2 c; sgSetVec2( c, 0.0, 0.0 ); int n=0,i; // find the centeroid for ( i = 0; i < nsrcpnt; i++) { c[0] += srcpnt[i][0]; c[1] += srcpnt[i][1]; n++; } if (n>0.00001) { c[0] /= n; c[1] /= n; } // make the points local pnts = new sgVec3[ nsrcpnt ]; npnts = nsrcpnt; for ( i=0; i < nsrcpnt; i++) { sgSetVec3( pnts[i], srcpnt[i][0] - c[0], 0.0, srcpnt[i][1] - c[1] ); } // set location sgSetVec3( pos, c[0], 0.0, c[1] ); }
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 ); }
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; }
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 * 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; }
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; }