bool cGrCelestialBody::reposition( sgVec3 p, double angle, double rightAscension, double declination, double sol_dist ) { sgMat4 T1, T2, GST, RA, DEC; sgVec3 axis; sgVec3 v; sgMakeTransMat4( T1, p ); sgSetVec3( axis, 0.0, 0.0, -1.0 ); sgMakeRotMat4( GST, (float)angle, axis ); sgSetVec3( axis, 0.0, 0.0, 1.0 ); sgMakeRotMat4( RA, (float)((rightAscension * SGD_RADIANS_TO_DEGREES) - 90.0), axis ); sgSetVec3( axis, 1.0, 0.0, 0.0 ); sgMakeRotMat4( DEC, (float)(declination * SGD_RADIANS_TO_DEGREES), axis ); sgSetVec3( v, 0.0, (float)sol_dist, 0.0 ); sgMakeTransMat4( T2, v ); sgMat4 TRANSFORM; sgCopyMat4( TRANSFORM, T1 ); sgPreMultMat4( TRANSFORM, GST ); sgPreMultMat4( TRANSFORM, RA ); sgPreMultMat4( TRANSFORM, DEC ); sgPreMultMat4( TRANSFORM, T2 ); sgCoord skypos; sgSetCoord( &skypos, TRANSFORM ); transform->setTransform( &skypos ); return true; }
bool cGrSkyDome::reposition( sgVec3 p, double lon, double lat, double spin ) { sgMat4 T, LON, LAT, SPIN; sgVec3 axis; // Translate to view position sgMakeTransMat4( T, p ); // 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 ); sgSetVec3( axis, 0.0, 0.0, 1.0 ); sgMakeRotMat4( SPIN, (float)(spin * SGD_RADIANS_TO_DEGREES), axis ); sgMat4 TRANSFORM; sgCopyMat4( TRANSFORM, T ); sgPreMultMat4( TRANSFORM, LON ); sgPreMultMat4( TRANSFORM, LAT ); sgPreMultMat4( TRANSFORM, SPIN ); sgCoord skypos; sgSetCoord( &skypos, TRANSFORM ); dome_transform->setTransform( &skypos ); asl = - skypos.xyz[2]; return true; }
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] ); }
bool cGrMoon::reposition(sgVec3 p, double angle, double moonrightAscension, double moondeclination, double moon_dist) { sgMat4 T1, T2, GST, RA, DEC; sgVec3 axis; sgVec3 v; sgMakeTransMat4( T1, p ); sgSetVec3( axis, 0.0, 0.0, -1.0 ); sgMakeRotMat4( GST, angle, axis ); sgSetVec3( axis, 0.0, 0.0, 1.0 ); sgMakeRotMat4( RA, (moonrightAscension * SGD_RADIANS_TO_DEGREES) - 90.0, axis ); sgSetVec3( axis, 1.0, 0.0, 0.0 ); sgMakeRotMat4( DEC, moondeclination * SGD_RADIANS_TO_DEGREES, axis ); sgSetVec3( v, 0.0, moon_dist, 0.0 ); sgMakeTransMat4( T2, v ); sgMat4 TRANSFORM; sgCopyMat4( TRANSFORM, T1 ); sgPreMultMat4( TRANSFORM, GST ); sgPreMultMat4( TRANSFORM, RA ); sgPreMultMat4( TRANSFORM, DEC ); sgPreMultMat4( TRANSFORM, T2 ); sgCoord skypos; sgSetCoord( &skypos, TRANSFORM ); moon_transform->setTransform( &skypos ); return true; }
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" ); }
// // Update the position of the moon image in the sky // void CMoonImage::Reposition (sgVec3 p, double theta, double lst, double lat, double ra, double dec, double spin) { sgMat4 LST, LAT, RA, DEC, D, SCALE, ECLIPTIC, SPIN; sgVec3 axis; sgVec3 v; // Create scaling matrix for moon illusion (appears larger near horizon) float scale = 1.0f; sgMakeIdentMat4 (SCALE); float maxMagnification = 0.5f; float minThreshold = DegToRad (80.0f); float maxThreshold = DegToRad (95.0f); float span = maxThreshold - minThreshold; if ((theta >= minThreshold) && (theta <= maxThreshold)) { sgMat4 I; sgMakeIdentMat4 (I); scale = 1.0f + (maxMagnification * (theta - minThreshold) / span); sgScaleMat4 (SCALE, I, scale); } // Rotation matrix for latitude sgSetVec3 (axis, -1.0f, 0, 0); sgMakeRotMat4 (LAT, 90.0f-(float)lat, axis); // Rotation matrix for local sidereal time, converted from h to deg sgSetVec3 (axis, 0, 0, -1.0f); sgMakeRotMat4 (LST, ((float)lst * 15), axis); // Rotation matrix for right ascension sgSetVec3 (axis, 0, 0, 1); sgMakeRotMat4 (RA, RadToDeg ((float)ra), axis); // Rotation matrix for declination sgSetVec3 (axis, 1, 0, 0); sgMakeRotMat4 (DEC, 90.0f - RadToDeg ((float)dec), axis); // Translate moon distance sgSetVec3 (v, 0, 0, distance); sgMakeTransMat4 (D, v); // Rotate to align moon equator with ecliptic sgSetVec3 (axis, 1.0f, 0, 0); sgMakeRotMat4 (ECLIPTIC, 90.0f, axis); /// Rotate the moon image accurately towards the sun position sgSetVec3 (axis, 0, 0, 1); sgMakeRotMat4 (SPIN, spin, axis); // Combine all transforms sgMakeIdentMat4 (T); sgPreMultMat4 (T, LAT); sgPreMultMat4 (T, LST); sgPreMultMat4 (T, RA); sgPreMultMat4 (T, DEC); sgPreMultMat4 (T, D); sgPreMultMat4 (T, ECLIPTIC); sgPreMultMat4 (T, SPIN); }
void CRRCControlSurfaceAnimation::transformPoint(CRRCMath::Vector3& point) { sgVec3 pnt_sg; sgSetVec3(pnt_sg, (float)point.r[0], (float)point.r[1], (float)point.r[2]); sgXformVec3(pnt_sg, current_transformation); point.r[0] = pnt_sg[SG_X]; point.r[1] = pnt_sg[SG_Y]; point.r[2] = pnt_sg[SG_Z]; }
/** \brief Create a rotation matrix * * This function creates a rotation matrix from the original * OpenGL glRotatef commands in CRRCAirplaneLaRCSim::draw(). * * \param m The matrix to be rotated * \param phi Euler angle phi * \param theta Euler angle theta * \param psi Euler angle psi */ inline void makeOGLRotMat4(sgMat4 m, double phi, double theta, double psi) { sgMat4 temp; sgVec3 rvec; //~ sgSetVec3(rvec, 0.0, 1.0, 0.0); //~ sgMakeRotMat4(temp, 90.0, rvec); //~ sgPreMultMat4(m, temp); sgSetVec3(rvec, 0.0, 1.0, 0.0); sgMakeRotMat4(temp, 180.0f - (float)psi * SG_RADIANS_TO_DEGREES, rvec); sgPreMultMat4(m, temp); sgSetVec3(rvec, -1.0, 0.0, 0.0); sgMakeRotMat4(temp, (float)theta * SG_RADIANS_TO_DEGREES, rvec); sgPreMultMat4(m, temp); sgSetVec3(rvec, 0.0, 0.0, 1.0); sgMakeRotMat4(temp, (float)phi * SG_RADIANS_TO_DEGREES, rvec); sgPreMultMat4(m, temp); }
void TransIcelandicExpress::mouseMotion( int xrel, int yrel ) { // rotate the camera sgVec3 axis, oldCamPos; sgMat4 m; float rot_factor = 0.5; // change heading sgSetVec3( axis, 0.0, 1.0, 0.0 ); sgMakeRotMat4( m, (float)xrel * rot_factor, axis ) ; sgXformVec3( cameraPos, m ) ; // change pitch sgSetVec3( axis, 1.0, 0.0, 0.0 ); sgMakeRotMat4( m, (float)yrel * rot_factor, axis ) ; sgCopyVec3( oldCamPos, cameraPos ); sgXformVec3( cameraPos, m ) ; // don't let the camera go below player if (cameraPos[1] < 0.0 ) { sgCopyVec3( cameraPos, oldCamPos ); } }
bool cGrStars::reposition( sgVec3 p, double angle ) { sgMat4 T1, GST; sgVec3 axis; sgMakeTransMat4( T1, p ); sgSetVec3( axis, 0.0, 0.0, -1.0 ); sgMakeRotMat4( GST, (float)angle, axis ); sgMat4 TRANSFORM; sgCopyMat4( TRANSFORM, T1 ); sgPreMultMat4( TRANSFORM, GST ); sgCoord skypos; sgSetCoord( &skypos, TRANSFORM ); stars_transform->setTransform( &skypos ); return true; }
/** * Create a CRRCControlSurfaceAnimation object * * Initialize the animation from an * <animation type="ControlSurface"> tag */ CRRCControlSurfaceAnimation::CRRCControlSurfaceAnimation(SimpleXMLTransfer *xml) : CRRCAnimation(new ssgTransform()), fallback_data(0.0f), eventAdapter(this, &CRRCControlSurfaceAnimation::axisValueCallback, Event::Input), aileron(0.0f), elevator(0.0f), rudder(0.0f), throttle(0.0f), spoiler(0.0f), flap(0.0f), retract(0.0f), pitch(0.0f) { bool failed = false; // evaluate <object> tag SimpleXMLTransfer *map = xml->getChild("object", true); symbolic_name = map->getString("name", "no_name_set"); max_angle = (float)(map->getDouble("max_angle", 0.0) * SG_RADIANS_TO_DEGREES); abs_max_angle = (float)fabs((double)max_angle); // find hinges and evaluate all <control> tags int num_controls = 0; int num_hinges = 0; for (int i = 0; i < xml->getChildCount(); i++) { SimpleXMLTransfer *child = xml->getChildAt(i); if (child->getName() == "hinge") { // found a <hinge> child sgVec3 pos; pos[SG_X] = (float)(-1 * child->getDouble("y", 0.0)); pos[SG_Y] = (float)(-1 * child->getDouble("x", 0.0)); pos[SG_Z] = (float)(-1 * child->getDouble("z", 0.0)); if (num_hinges == 0) { sgCopyVec3(hinge_1, pos); } else if (num_hinges == 1) { sgCopyVec3(hinge_2, pos); } num_hinges++; } else if (child->getName() == "control") { // found a <control> child // The "*2" factor for each gain value scales the control input // values from -0.5...+0.5 to -1.0...+1.0. This saves one // float multiplication per mapping in the runtime update() routine. std::string mapping = child->getString("mapping", "NOTHING"); float gain = (float)child->getDouble("gain", 1.0); if (mapping == "ELEVATOR") { datasource.push_back(&elevator); source_gain.push_back(gain * 2); num_controls++; } else if (mapping == "AILERON") { datasource.push_back(&aileron); source_gain.push_back(gain * 2); num_controls++; } else if (mapping == "THROTTLE") { datasource.push_back(&throttle); source_gain.push_back(gain * 2); num_controls++; } else if (mapping == "RUDDER") { datasource.push_back(&rudder); source_gain.push_back(gain * 2); num_controls++; } else if (mapping == "FLAP") { datasource.push_back(&flap); source_gain.push_back(gain * 2); num_controls++; } else if (mapping == "SPOILER") { datasource.push_back(&spoiler); source_gain.push_back(gain * 2); num_controls++; } else if (mapping == "RETRACT") { datasource.push_back(&retract); source_gain.push_back(gain * 2); num_controls++; } else if (mapping == "PITCH") { datasource.push_back(&pitch); source_gain.push_back(gain * 2); num_controls++; } else { std::cerr << "ControlSurfaceAnimation: ignoring <control> tag without mapping." << std::endl; } } } if (num_controls < 1) { std::cerr << "ControlSurfaceAnimation: found animation without proper <control> tag. Animation disabled." << std::endl; failed = true; } if (num_hinges < 2) { std::cerr << "ControlSurfaceAnimation: Must specify exactly two hinges!" << std::endl; failed = true; } else { if (num_hinges > 2) { std::cerr << "ControlSurfaceAnimation: Must specify exactly two hinges!" << std::endl; std::cerr << "ControlSurfaceAnimation: Ignoring excessive hinge tag(s)." << std::endl; } sgSubVec3(axis, hinge_2, hinge_1); if (sgLengthVec3(axis) < 0.001) { std::cerr << "ControlSurfaceAnimation: Insufficient spacing between hinges!" << std::endl; failed = true; } } if (failed) { std::cerr << "ControlSurfaceAnimation: Animation setup failed." << std::endl; // set to some non-critical defaults datasource.resize(1); datasource[0] = &fallback_data; source_gain.resize(1); source_gain[0] = 1.0; sgSetVec3(hinge_1, 0.0f, 0.0f, 0.0f); sgSetVec3(hinge_2, 1.0f, 0.0f, 0.0f); sgSubVec3(axis, hinge_2, hinge_1); } sgMakeIdentMat4(move_to_origin); move_to_origin[3][0] = -hinge_1[0]; move_to_origin[3][1] = -hinge_1[1]; move_to_origin[3][2] = -hinge_1[2]; sgMakeTransMat4(move_back, hinge_1); realInit(); }
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; }
/** \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(); }
// 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; }
//-------------------------------------------------------------------- Player::Player() : SceneObject() { sgSetVec3( vel, 0.0, 0.0, 0.0 ); }
/*void CSkyManager::GetSkyDomeColour (float theta, float phi, float &r, float &g, float &b) { // Set default fog colour // r = g = b = 0.0f; if (domeimage != NULL) domeimage->GetDomeColour (theta, phi, r, g, b); } */ void CSkyManager::PreDraw (void) { SPosition eyePos = globals->geop; double mjd = globals->tim->GetModifiedJulianDate (); double lst = globals->tim->GetLocalSiderealTime(eyePos.lon); // Convert camera eye position to cartesian coordinates SVector v; v = GeodToCartesian (eyePos); sgVec3 p; sgSetVec3 (p, (float)v.x, (float)v.y, (float)v.z); // Convert latitude and longitude to degrees for sky object repositioning double lat = eyePos.lat / 3600; double lon = eyePos.lon / 3600; /// \todo Sun/moon positions only need to be recalculated infrequently, not /// on every update cycle // Update ephemeris calculations for sun. This needs to be done first since // the sun elevation is needed to update the other celestial objects sol->UpdatePosition (mjd); // Update ephemeris calculations for other celestial objects moon->UpdatePosition (mjd, lst, lat, sol); /// \todo Planet positions only need to be calculated once at situation start mercury->UpdatePosition (mjd, sol); venus->UpdatePosition (mjd, sol); mars->UpdatePosition (mjd, sol); jupiter->UpdatePosition (mjd, sol); saturn->UpdatePosition (mjd, sol); // Get solar zenith and azimuth angles calc_zenith_azimuth_angles (sol->GetRightAscension(), sol->GetDeclination(), lat, lon, &solTheta, &solPhi); double moonTheta, moonPhi; calc_zenith_azimuth_angles (moon->GetRightAscension(), moon->GetDeclination(), lat, lon, &moonTheta, &moonPhi); // Update sky lighting model skylight->Update (solTheta, solPhi, moonTheta, moonPhi); // DEBUG // char debug[80]; // sprintf (debug, "solTheta=%7.3f deg, solPhi=%7.3f deg", // RadToDeg (solTheta), RadToDeg (solPhi)); // DrawNoticeToUser (debug, 1); // Update appearance and position of sky dome domeimage->Repaint (solTheta, solPhi); // Update appearance and position of Sol // solimage->Repaint (solTheta); // solimage->Reposition (p, lst, lat, // sol->GetRightAscension(), sol->GetDeclination(), // skyDistance); // Update appearance and position of the Moon /// \todo Orient moon towards sun using the 'spin' parameter moonimage->Repaint (moonTheta, moon->GetAge ()); moonimage->Reposition (p, moonTheta, lst, lat, moon->GetRightAscension(), moon->GetDeclination(), 0); // Determine limiting magnitude and ambient light factor for night sky objects float limit, factor; float limitLastUpdate = 10.0; // EDarkPhase phase = limitingMagnitude (solTheta, &limit, &factor); limitingMagnitude (solTheta, &limit, &factor); // If the limiting magnitude has changed by more than the preset value, repaint // the stars and planets // if (phase != old_phase) { if (fabs (limitLastUpdate - limit) > 0.1) { limitLastUpdate = limit; // Update appearance for all planets and stars mercuryimage->Repaint ((float)mercury->GetMagnitude (), limit, factor); venusimage->Repaint ((float)venus->GetMagnitude(), limit, factor); marsimage->Repaint ((float)mars->GetMagnitude(), limit, factor); jupiterimage->Repaint ((float)jupiter->GetMagnitude(), limit, factor); saturnimage->Repaint ((float)saturn->GetMagnitude(), limit, factor); starimage->Repaint (limit, factor); } // Update positions of all planets mercuryimage->Reposition (p, lst, lat, mercury->GetRightAscension(), mercury->GetDeclination(), skyDistance); venusimage->Reposition (p, lst, lat, venus->GetRightAscension(), venus->GetDeclination(), skyDistance); marsimage->Reposition (p, lst, lat, mars->GetRightAscension(), mars->GetDeclination(), skyDistance); jupiterimage->Reposition (p, lst, lat, jupiter->GetRightAscension(), jupiter->GetDeclination(), skyDistance); saturnimage->Reposition (p, lst, lat, saturn->GetRightAscension(), saturn->GetDeclination(), skyDistance); // Update positions of stars starimage->Reposition (p, lon, lat, lst); // Depth testing is disabled for all sky elements, therefore they must be drawn // from "farthest" to "nearest" glPushAttrib (GL_DEPTH_BUFFER_BIT); glDisable (GL_DEPTH_TEST); // Draw sky sub-components domeimage->Draw (); starimage->Draw (); saturnimage->Draw (); jupiterimage->Draw (); marsimage->Draw (); venusimage->Draw (); mercuryimage->Draw (); // Sun and moon images temporarily left undrawn //solimage->Draw (); moonimage->Draw (); glPopAttrib (); }
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::simulate() { sgVec3 fwd, right, up, frict, v; sgVec3 playerForce; float cf_accel = 1.0, // m/s^2 maxVel = 0.5, // m/2 cf_friction_land = 8.0, cf_friction_ice = 5.0; float pv, ff; // friction fudge... more friction for slow objects float timestep = 0.01f; static float timeleft = 0.0f; timeleft += deltaT; sgSetVec3( up, 0.0, 1.0, 0.0 ); sgSetVec3( playerForce, 0.0, 0.0, 0.0 ); while (timeleft > timestep) { sgCopyVec3( fwd, cameraPos ); sgNegateVec3( fwd ); fwd[1] = 0.0; sgNormalizeVec3( fwd ); sgVectorProductVec3( right, fwd, up ); // todo: if on the ground sgScaleVec3( fwd, cf_moveForward ); sgAddVec3( playerForce, fwd ); sgScaleVec3( right, cf_moveSideways ); sgAddVec3( playerForce, right ); sgScaleVec3( playerForce, cf_accel * timestep ); sgAddVec3( player->vel, playerForce ); pv = sgLengthVec3( player->vel ) ; ff = (1.0 - ((pv / maxVel)* 0.8)); ff = ff*ff; sgCopyVec3( frict, player->vel ); sgNegateVec3( frict ); sgScaleVec3( frict, ff * cf_friction_ice * timestep ); sgAddVec3( player->vel, frict ); dbgVel.push_back( pv ); if (dbgVel.size() > 100 ) { dbgVel.pop_front(); } if ( pv > maxVel ) { //printf("maxvel!\n" ); sgNormalizeVec3( player->vel ); sgScaleVec3( player->vel, maxVel ); } sgCopyVec3( v, player->vel ); sgScaleVec3( v, timestep ); sgAddVec3( player->pos, v ); // advance timeleft -= timestep; } player->pos[1] = getHeight( player->pos ); }
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 ); } } }
bool cGrSkyDome::repaint( sgVec4 sky_color, sgVec4 fog_color, double sol_angle, double vis ) { double diff, prev_sun_angle = 999.0; sgVec3 outer_param, outer_amt, outer_diff; sgVec3 middle_param, middle_amt, middle_diff; int i, j; if (prev_sun_angle == sol_angle) return true; prev_sun_angle = sol_angle; //sol_angle *= SGD_RADIANS_TO_DEGREES; // Check for sunrise/sunset condition if ((sol_angle > 80.0)) { sgSetVec3( outer_param, (float)((10.0 - fabs(90.0 - sol_angle)) / 20.0), (float)((10.0 - fabs(90.0 - sol_angle)) / 40.0), (float)(-(10.0 - fabs(90.0 - sol_angle)) / 30.0)); sgSetVec3( middle_param, (float)((10.0 - fabs(90.0 - sol_angle)) / 40.0), (float)((10.0 - fabs(90.0 - sol_angle)) / 80.0), 0.0 ); sgScaleVec3( outer_diff, outer_param, 1.0f / 6.0f ); sgScaleVec3( middle_diff, middle_param, 1.0f / 6.0f ); } else { sgSetVec3( outer_param, 0.0, 0.0, 0.0 ); sgSetVec3( middle_param, 0.0, 0.0, 0.0 ); sgSetVec3( outer_diff, 0.0, 0.0, 0.0 ); sgSetVec3( middle_diff, 0.0, 0.0, 0.0 ); } // calculate transition colors between sky and fog sgCopyVec3( outer_amt, outer_param ); sgCopyVec3( middle_amt, middle_param ); // // First, recalulate the basic colors // sgVec4 center_color; sgVec4 upper_color[12]; sgVec4 middle_color[12]; sgVec4 lower_color[12]; sgVec4 bottom_color[12]; double vis_factor, cvf = vis; if (cvf > 45000) cvf = 45000; vis_factor = (vis - 1000.0) / 2000.0; if ( vis_factor < 0.0 ) { vis_factor = 0.0; } else if ( vis_factor > 1.0) { vis_factor = 1.0; } for ( j = 0; j < 3; j++ ) { diff = sky_color[j] - fog_color[j]; center_color[j] = sky_color[j]; // - (float)(diff * ( 1.0 - vis_factor )); } for ( i = 0; i < 6; i++ ) { for ( j = 0; j < 3; j++ ) { double saif = sol_angle/SG_PI; diff = sky_color[j] - fog_color[j] * (0.8 + j * 0.2) * (0.8 + saif - ((6-i)/10)); upper_color[i][j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor * (0.7 + 0.3 * cvf/45000))); middle_color[i][j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor * (0.1 + 0.85 * cvf/45000))) + middle_amt[j]; lower_color[i][j] = fog_color[j] + outer_amt[j]; if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; } if ( upper_color[i][j] < 0.0 ) { upper_color[i][j] = 0.0; } if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; } if ( middle_color[i][j] < 0.0 ) { middle_color[i][j] = 0.0; } if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; } if ( lower_color[i][j] < 0.0 ) { lower_color[i][j] = 0.0; } } upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0; for ( j = 0; j < 3; j++ ) { outer_amt[j] -= outer_diff[j]; middle_amt[j] -= middle_diff[j]; } } sgSetVec3( outer_amt, 0.0, 0.0, 0.0 ); sgSetVec3( middle_amt, 0.0, 0.0, 0.0 ); for ( i = 6; i < 12; i++ ) { for ( j = 0; j < 3; j++ ) { double saif = sol_angle/SG_PI; diff = (sky_color[j] - fog_color[j]) * (0.8 + j * 0.2) * (0.8 + saif - ((-i+12)/10)); upper_color[i][j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor * (0.7 + 0.3 * cvf/45000))); middle_color[i][j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor * (0.1 + 0.85 * cvf/45000))) + middle_amt[j]; lower_color[i][j] = fog_color[j] + outer_amt[j]; if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; } if ( upper_color[i][j] < 0.0 ) { upper_color[i][j] = 0.0; } if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; } if ( middle_color[i][j] < 0.0 ) { middle_color[i][j] = 0.0; } if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; } if ( lower_color[i][j] < 0.0 ) { lower_color[i][j] = 0.0; } } upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0; for ( j = 0; j < 3; j++ ) { outer_amt[j] += outer_diff[j]; middle_amt[j] += middle_diff[j]; } } fade_to_black( (sgVec4 *) center_color, asl * center_elev, 1); fade_to_black( upper_color, (asl+0.05f) * upper_elev, 12); fade_to_black( middle_color, (asl+0.05f) * middle_elev, 12); fade_to_black( lower_color, (asl+0.05f) * lower_elev, 12); for ( i = 0; i < 12; i++ ) { sgCopyVec4( bottom_color[i], fog_color ); } // // Second, assign the basic colors to the object color arrays // float *slot; int counter; // update the center disk color arrays counter = 0; slot = center_disk_cl->get( counter++ ); // sgVec4 red; // sgSetVec4( red, 1.0, 0.0, 0.0, 1.0 ); sgCopyVec4( slot, center_color ); for ( i = 11; i >= 0; i-- ) { slot = center_disk_cl->get( counter++ ); sgCopyVec4( slot, upper_color[i] ); } slot = center_disk_cl->get( counter++ ); sgCopyVec4( slot, upper_color[11] ); // generate the upper ring counter = 0; for ( i = 0; i < 12; i++ ) { slot = upper_ring_cl->get( counter++ ); sgCopyVec4( slot, middle_color[i] ); slot = upper_ring_cl->get( counter++ ); sgCopyVec4( slot, upper_color[i] ); } slot = upper_ring_cl->get( counter++ ); sgCopyVec4( slot, middle_color[0] ); slot = upper_ring_cl->get( counter++ ); sgCopyVec4( slot, upper_color[0] ); // generate middle ring counter = 0; for ( i = 0; i < 12; i++ ) { slot = middle_ring_cl->get( counter++ ); sgCopyVec4( slot, lower_color[i] ); slot = middle_ring_cl->get( counter++ ); sgCopyVec4( slot, middle_color[i] ); } slot = middle_ring_cl->get( counter++ ); sgCopyVec4( slot, lower_color[0] ); slot = middle_ring_cl->get( counter++ ); sgCopyVec4( slot, middle_color[0] ); // generate lower ring counter = 0; for ( i = 0; i < 12; i++ ) { slot = lower_ring_cl->get( counter++ ); sgCopyVec4( slot, bottom_color[i] ); slot = lower_ring_cl->get( counter++ ); sgCopyVec4( slot, lower_color[i] ); } slot = lower_ring_cl->get( counter++ ); sgCopyVec4( slot, bottom_color[0] ); slot = lower_ring_cl->get( counter++ ); sgCopyVec4( slot, lower_color[0] ); 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; }
// // Update the position of the moon image in the sky // void CMoonImage::Reposition (sgVec3 p, double theta, double lst, double lat, double ra, double dec, double spin) { sgMat4 LST, LAT, RA, DEC, D, SCALE, ECLIPTIC, SPIN; sgVec3 axis; sgVec3 v; // Create scaling matrix for moon illusion (appears larger near horizon) float scale = 1.0f; sgMakeIdentMat4 (SCALE); float maxMagnification = 0.5f; float minThreshold = DegToRad (80.0f); float maxThreshold = DegToRad (95.0f); float span = maxThreshold - minThreshold; if ((theta >= minThreshold) && (theta <= maxThreshold)) { sgMat4 I; sgMakeIdentMat4 (I); scale = 1.0f + (maxMagnification * (theta - minThreshold) / span); sgScaleMat4 (SCALE, I, scale); } // Rotation matrix for latitude sgSetVec3 (axis, -1.0f, 0, 0); sgMakeRotMat4 (LAT, 90.0f-(float)lat, axis); // Rotation matrix for local sidereal time, converted from h to deg sgSetVec3 (axis, 0, 0, -1.0f); sgMakeRotMat4 (LST, ((float)lst * 15), axis); // Rotation matrix for right ascension sgSetVec3 (axis, 0, 0, 1); sgMakeRotMat4 (RA, RadToDeg ((float)ra), axis); // Rotation matrix for declination sgSetVec3 (axis, 1, 0, 0); sgMakeRotMat4 (DEC, 90.0f - RadToDeg ((float)dec), axis); // Translate moon distance sgSetVec3 (v, 0, 0, distance); sgMakeTransMat4 (D, v); // Rotate to align moon equator with ecliptic sgSetVec3 (axis, 1.0f, 0, 0); sgMakeRotMat4 (ECLIPTIC, 90.0f, axis); /// Rotate the moon image accurately towards the sun position sgSetVec3 (axis, 0, 0, 1); sgMakeRotMat4 (SPIN, spin, axis); // Combine all transforms sgMakeIdentMat4 (T); sgPreMultMat4 (T, LAT); sgPreMultMat4 (T, LST); sgPreMultMat4 (T, RA); sgPreMultMat4 (T, DEC); sgPreMultMat4 (T, D); sgPreMultMat4 (T, ECLIPTIC); sgPreMultMat4 (T, SPIN); /* char debug[256]; double jd = CTimeManager::Instance().GetJulianDate(); SDateTime dt = CTimeManager::Instance().GetLocalDateTime (); sprintf (debug, "JD=%f D=%d/%d/%d T=%d:%d RA=%f Dec=%f", jd, dt.date.year, dt.date.month, dt.date.day, dt.time.hour, dt.time.minute, RadToDeg(ra), RadToDeg(dec)); DrawNoticeToUser (debug, 1); */ }
void IceFloe::drawGeom() { int i, j; float h; h = height * TransIcelandicExpress::c_RoadLevel; // draw the sides sgVec3 edge, n, up; sgSetVec3( up, 0.0, 1.0, 0.0 ); glBegin( GL_QUADS ); for (j = npnts-1, i = 0; i < npnts; j=i++) { sgSetVec3( edge, pnts[j][0] - pnts[i][0], 0.0, pnts[j][2] - pnts[i][2] ); sgNormalizeVec3( edge ); sgVectorProductVec3( n, edge, up ); glNormal3f( n[0], n[1], n[2] ); glVertex3f( pnts[i][0], h, pnts[i][2] ); glVertex3f( pnts[j][0], h, pnts[j][2] ); glVertex3f( pnts[j][0], 0.0, pnts[j][2] ); glVertex3f( pnts[i][0], 0.0, pnts[i][2] ); } glEnd(); // tesselate the top if (!tess.size()) { if (!gluTess) { gluTess = gluNewTess(); gluTessCallback( gluTess, GLU_BEGIN, (void(__stdcall *)(void))tessBegin ); gluTessCallback( gluTess, GLU_END, (void(__stdcall *)(void))tessEnd ); gluTessCallback( gluTess, GLU_VERTEX, (void(__stdcall *)(void))tessVertex ); gluTessCallback( gluTess, GLU_ERROR, (void(__stdcall *)(void))tessError ); } printf("Tesselating polygon....\n"); floeToTess = this; gluBeginPolygon( gluTess ); GLdouble *v; for (i = 0; i < npnts; i++) { pnts[i][1] = h; v = new GLdouble[4]; v[0] = pnts[i][0]; v[1] = pnts[i][1]; v[2] = pnts[i][2]; printf("gluTessVertex %3.4f %3.4f %3.4f\n", v[0], v[1], v[2] ); gluTessVertex( gluTess, v, pnts[i] ); } printf("About to call end....\n"); gluEndPolygon( gluTess ); printf("Done.\n"); floeToTess = NULL; } // draw the top glNormal3f( 0.0, 1.0, 0.0 ); glBegin( GL_TRIANGLES ); for (std::vector<TessTri*>::iterator ti = tess.begin(); ti != tess.end(); ti++ ) { glVertex3f( (*ti)->a[0], (*ti)->a[1], (*ti)->a[2] ); glVertex3f( (*ti)->b[0], (*ti)->b[1], (*ti)->b[2] ); glVertex3f( (*ti)->c[0], (*ti)->c[1], (*ti)->c[2] ); } glEnd(); }
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; }
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; }