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; }
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 ); }