vector3d TerrainColorFractal<TerrainColorAsteroid>::GetColor(const vector3d &p, double height, const vector3d &norm) const { double n = m_invMaxHeight*height/2; if (n <= 0.02) { const double flatness = pow(p.Dot(norm), 6.0); const vector3d color_cliffs = m_rockColor[1]; double equatorial_desert = (2.0)*(-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(2.0)*(1.0-p.y*p.y); vector3d col; col = interpolate_color(equatorial_desert, m_rockColor[0], m_greyrockColor[3]); col = interpolate_color(n, col, vector3d(1.5,1.35,1.3)); col = interpolate_color(flatness, color_cliffs, col); return col; } else { const double flatness = pow(p.Dot(norm), 6.0); const vector3d color_cliffs = m_greyrockColor[1]; double equatorial_desert = (2.0)*(-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(2.0)*(1.0-p.y*p.y); vector3d col; col = interpolate_color(equatorial_desert, m_greyrockColor[0], m_greyrockColor[2]); col = interpolate_color(n, col, m_rockColor[3]); col = interpolate_color(flatness, color_cliffs, col); return col; } }
vector3d TerrainColorFractal<TerrainColorBandedRock>::GetColor(const vector3d &p, double height, const vector3d &norm) const { const double flatness = pow(p.Dot(norm), 6.0); double n = fabs(noise(vector3d(height*10000.0,0.0,0.0))); vector3d col = interpolate_color(n, m_rockColor[0], m_rockColor[1]); return interpolate_color(flatness, col, m_rockColor[2]); }
double Ship::AIFaceOrient(const vector3d &dir, const vector3d &updir) { double timeStep = Pi::GetTimeStep(); matrix4x4d rot; GetRotMatrix(rot); double maxAccel = GetShipType().angThrust / GetAngularInertia(); // should probably be in stats anyway double frameAccel = maxAccel * timeStep; if (dir.Dot(vector3d(rot[8], rot[9], rot[10])) > -0.999999) { AIFaceDirection(dir); return false; } vector3d uphead = (updir * rot).Normalized(); // create desired object-space updir vector3d dav(0.0, 0.0, 0.0); // desired angular velocity double ang = 0.0; if (uphead.y < 0.999999) { ang = acos(Clamp(uphead.y, -1.0, 1.0)); // scalar angle from head to curhead double iangvel = sqrt(2.0 * maxAccel * ang); // ideal angvel at current time double frameEndAV = iangvel - frameAccel; if (frameEndAV <= 0.0) iangvel = ang / timeStep; // last frame discrete correction else iangvel = (iangvel + frameEndAV) * 0.5; // discrete overshoot correction dav.z = -iangvel; } vector3d cav = (GetAngVelocity() - GetFrame()->GetAngVelocity()) * rot; // current obj-rel angvel // vector3d cav = GetAngVelocity() * rot; // current obj-rel angvel vector3d diff = (dav - cav) / frameAccel; // find diff between current & desired angvel SetAngThrusterState(diff); return ang; // if (diff.x*diff.x > 1.0 || diff.y*diff.y > 1.0 || diff.z*diff.z > 1.0) return false; // else return true; }
vector3d TerrainColorFractal<TerrainColorVolcanic>::GetColor(const vector3d &p, double height, const vector3d &norm) { double n = m_invMaxHeight*height; const double flatness = pow(p.Dot(norm), 6.0); const vector3d color_cliffs = m_rockColor[2]; double equatorial_desert = (-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(1.0-p.y*p.y); vector3d col; if (n > 0.4){ col = interpolate_color(equatorial_desert, vector3d(.3,.2,0), vector3d(.3, .1, .0)); col = interpolate_color(n, col, vector3d(.1, .0, .0)); col = interpolate_color(flatness, color_cliffs, col); } else if (n > 0.2){ col = interpolate_color(equatorial_desert, vector3d(1.2,1,0), vector3d(.9, .3, .0)); col = interpolate_color(n, col, vector3d(-1.1, -1, .0)); col = interpolate_color(flatness, color_cliffs, col); } else if (n > 0.1){ col = interpolate_color(equatorial_desert, vector3d(.2,.1,0), vector3d(.1, .05, .0)); col = interpolate_color(n, col, vector3d(2.5, 2, .0)); col = interpolate_color(flatness, color_cliffs, col); } else { col = interpolate_color(equatorial_desert, vector3d(.75,.6,0), vector3d(.75, .2, .0)); col = interpolate_color(n, col, vector3d(-2, -2.2, .0)); col = interpolate_color(flatness, color_cliffs, col); } return col; }
void CollisionSpace::CollideRaySphere(const vector3d &start, const vector3d &dir, isect_t *isect) { if (sphere.radius > 0.0) { /* Collide with lovely sphere! */ const vector3d v = start - sphere.pos; const double b = -v.Dot(dir); double det = (b * b) - v.LengthSqr() + (sphere.radius*sphere.radius); if (det > 0) { det = sqrt(det); const double i1 = b - det; const double i2 = b + det; if (i2 > 0) { /*if (i1 < 0) { if (i2 < *dist) { *dist = i2; //retval = INPRIM; retval = true; } }*/ if (i1 > 0) { if (i1 < isect->dist) { isect->dist = float(i1); isect->triIdx = 0; } } } } } }
// check whether ship is at risk of colliding with frame body on current path // return values: //0 - no collision //1 - below feature height //2 - unsafe escape from effect radius //3 - unsafe entry to effect radius //4 - probable path intercept static int CheckCollision(Ship *ship, const vector3d &pathdir, double pathdist, const vector3d &tpos, double endvel, double r) { // ship is in obstructor's frame anyway, so is tpos if (pathdist < 100.0) return 0; Body *body = ship->GetFrame()->GetBodyFor(); if (!body) return 0; vector3d spos = ship->GetPosition(); double tlen = tpos.Length(), slen = spos.Length(); double fr = MaxFeatureRad(body); // if target inside, check if direct entry is safe (30 degree) if (tlen < r) { double af = (tlen > fr) ? 0.5 * (1 - (tlen-fr) / (r-fr)) : 0.5; if (pathdir.Dot(tpos) > -af*tlen) if (slen < fr) return 1; else return 3; else return 0; } // if ship inside, check for max feature height and direct escape (30 degree) if (slen < r) { if (slen < fr) return 1; double af = (slen > fr) ? 0.5 * (1 - (slen-fr) / (r-fr)) : 0.5; if (pathdir.Dot(spos) < af*slen) return 2; else return 0; } // now for the intercept calc // find closest point to obstructor double tanlen = -spos.Dot(pathdir); if (tanlen < 0 || tanlen > pathdist) return 0; // closest point outside path vector3d perpdir = (tanlen*pathdir + spos).Normalized(); double perpspeed = ship->GetVelocity().Dot(perpdir); double parspeed = ship->GetVelocity().Dot(pathdir); if (parspeed < 0) parspeed = 0; // shouldn't break any important case if (perpspeed > 0) perpspeed = 0; // prevent attempts to speculatively fly through planets // find time that ship will pass through that point // get velocity as if accelerating from start or end, pick smallest double ivelsqr = endvel*endvel + 2*ship->GetAccelFwd()*(pathdist-tanlen); // could put endvel in here double fvelsqr = parspeed*parspeed + 2*ship->GetAccelFwd()*tanlen; double tanspeed = sqrt(ivelsqr < fvelsqr ? ivelsqr : fvelsqr); double time = tanlen / (0.5 * (parspeed + tanspeed)); // actually correct? double dist = spos.Dot(perpdir) + perpspeed*time; // spos.perpdir should be positive if (dist < r) return 4; return 0; }
static int GetFlipMode(Ship *ship, const vector3d &relpos, const vector3d &relvel) { double dist = relpos.Length(); double vel = relvel.Dot(relpos) / dist; if (vel > 0.0 && vel*vel > 1.7 * ship->GetAccelRev() * dist) return 2; if (dist > 100000000.0) return 1; // arbitrary return 0; }
// check for inability to reach target waypoint without overshooting static bool CheckOvershoot(Ship *ship, const vector3d &reldir, double targdist, const vector3d &relvel, double endvel) { if (targdist < 100.0) return false; // spazzes out occasionally otherwise // only slightly fake minimum time to target // based on s = (sv+ev)*t/2 + a*t*t/4 double fwdacc = ship->GetAccelFwd(); double u = 0.5 * (relvel.Dot(reldir) + endvel); if (u<0) u = 0; double t = (-u + sqrt(u*u + fwdacc*targdist)) / (fwdacc * 0.5); if (t < Pi::game->GetTimeStep()) t = Pi::game->GetTimeStep(); // double t2 = ship->AITravelTime(reldir, targdist, relvel, endvel, true); // check for uncorrectable side velocity vector3d perpvel = relvel - reldir * relvel.Dot(reldir); if (perpvel.Length() > 0.5*ship->GetAccelMin()*t) return true; return false; }
vector3d TerrainColorFractal<TerrainColorIce>::GetColor(const vector3d &p, double height, const vector3d &norm) { double n = m_invMaxHeight*height; if (n <= 0.0) return vector3d(0.96,0.96,0.96); const double flatness = pow(p.Dot(norm), 24.0); double equatorial_desert = (2.0-m_icyness)*(-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(2.0-m_icyness)*(1.0-p.y*p.y); double equatorial_region_1 = billow_octavenoise(GetFracDef(0), 0.5, p) * p.y * p.y; double equatorial_region_2 = ridged_octavenoise(GetFracDef(5), 0.5, p) * p.x * p.x; // cliff colours vector3d color_cliffs; // adds some variation color_cliffs = interpolate_color(equatorial_region_1, m_rockColor[3], m_rockColor[0] ); color_cliffs = interpolate_color(equatorial_region_2, color_cliffs, m_rockColor[2] ); // main colours vector3d col; // start by interpolating between noise values for variation col = interpolate_color(equatorial_region_1, m_darkrockColor[0], vector3d(1, 1, 1) ); col = interpolate_color(equatorial_region_2, m_darkrockColor[1], col ); col = interpolate_color(equatorial_desert, col, vector3d(.96, .95, .94)); // scale by different colours depending on height for more variation if (n > .666) { n -= 0.666; n*= 3.0; col = interpolate_color(n, vector3d(.96, .95, .94), col); col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.333) { n -= 0.333; n*= 3.0; col = interpolate_color(n, col, vector3d(.96, .95, .94)); col = interpolate_color(flatness, color_cliffs, col); return col; } else { n *= 3.0; col = interpolate_color(n, vector3d(.96, .95, .94), col); col = interpolate_color(flatness, color_cliffs, col); return col; } }
// same inputs as matchposvel, returns approximate travel time instead // underestimates if targspeed isn't reachable double Ship::AITravelTime(const vector3d &reldir, double targdist, const vector3d &relvel, double targspeed, bool flip) { double speed = relvel.Dot(reldir); // speed >0 is towards double dist = targdist; double faccel = GetAccelFwd(); double raccel = flip ? faccel : GetAccelRev(); double time1, time2, time3; // time to reduce speed to zero: time1 = -speed / faccel; dist += 0.5 * time1 * -speed; // time to reduce speed to zero after target reached: time3 = -targspeed / raccel; dist += 0.5 * time3 * -targspeed; // now time to cover distance between zero-vel points // midpoint = intercept of two gradients double m = dist*raccel / (faccel+raccel); time2 = sqrt(2*m/faccel) + sqrt(2*(dist-m)/raccel); return time1+time2+time3; }
vector3d TerrainColorFractal<TerrainColorDesert>::GetColor(const vector3d &p, double height, const vector3d &norm) { double n = m_invMaxHeight*height/2; const double flatness = pow(p.Dot(norm), 6.0); const vector3d color_cliffs = m_rockColor[1]; // Ice has been left as is so the occasional desert world will have polar ice-caps like mars if (fabs(m_icyness*p.y) + m_icyness*n > 1) { return interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); } double equatorial_desert = (2.0-m_icyness)*(-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(2.0-m_icyness)*(1.0-p.y*p.y); vector3d col; if (n > .4) { n = n*n; col = interpolate_color(equatorial_desert, vector3d(.8,.75,.5), vector3d(.52, .5, .3)); col = interpolate_color(n, col, vector3d(.1, .0, .0)); col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > .3) { n = n*n; col = interpolate_color(equatorial_desert, vector3d(.81, .68, .3), vector3d(.85, .7, 0)); col = interpolate_color(n, col, vector3d(-1.2,-.84,.35)); col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > .2) { col = interpolate_color(equatorial_desert, vector3d(-0.4, -0.47, -0.6), vector3d(-.6, -.7, -2)); col = interpolate_color(n, col, vector3d(4, 3.95, 3.94)); col = interpolate_color(flatness, color_cliffs, col); return col; } else { col = interpolate_color(equatorial_desert, vector3d(.78, .73, .68), vector3d(.8, .77, .5)); col = interpolate_color(n, col, vector3d(-2.0, -2.3, -2.4)); col = interpolate_color(flatness, color_cliffs, col); return col; } }
// reldir*targdist and relvel are pos and vel of ship relative to target in ship's frame // endspeed is in direction of motion, must be positive // maxdecel is maximum deceleration thrust bool Ship::AIMatchPosVel2(const vector3d &reldir, double targdist, const vector3d &relvel, double endspeed, double maxdecel) { matrix4x4d rot; GetRotMatrix(rot); double parspeed = relvel.Dot(reldir); double ivel = calc_ivel(targdist, endspeed, maxdecel); double diffspeed = ivel - parspeed; vector3d diffvel = diffspeed * reldir * rot; bool rval = false; // crunch diffvel by relative thruster power to get acceleration in right direction if (diffspeed > 0.0) { vector3d maxFA = GetMaxThrust(diffvel) * Pi::game->GetTimeStep() / GetMass(); if (abs(diffvel.x) > maxFA.x) diffvel *= maxFA.x / abs(diffvel.x); if (abs(diffvel.y) > maxFA.y) diffvel *= maxFA.y / abs(diffvel.y); // if (abs(diffvel.z) > maxFA.z) diffvel *= maxFA.z / abs(diffvel.z); if (maxFA.z < diffspeed) rval = true; } // add perpendicular velocity vector3d perpvel = relvel - parspeed*reldir; diffvel -= perpvel * rot; AIChangeVelBy(diffvel); return rval; // true if acceleration was capped }
float ShipCockpit::CalculateSignedForwardVelocity(vector3d normalized_forward, vector3d velocity) { float velz_cos = velocity.Dot(normalized_forward); return (velz_cos * normalized_forward).Length() * (velz_cos < 0.0 ? -1.0 : 1.0); }
void AIParagonCmdSteerAround::CalculateEntryPoint() { // Entry point if (m_data.ship_to_sbody_distance > m_data.sbody_transit_radius + 5000.0 && m_data.ship_to_sbody_distance <= m_data.sbody_transit_radius + 10000.0) { // - Ship is in transit range or nearby // -- Directly above or below to transit range is the entry point (Default) m_entryPoint = -m_data.ship_to_sbody_dir * m_data.sbody_transit_radius; m_stage = ESS_ENTER; } else if (m_data.ship_to_sbody_distance > m_data.sbody_transit_radius + 10000.0) { // - Ship is far from transit range vector3d intersection_point; bool intersection; // -- Calculate entry point if (m_data.target_to_sbody_distance > m_data.sbody_transit_radius) { // -- Target out of planet (WIP) // Ship takes a wide angle turn around the planet const double angle = DEG2RAD(45.0); const double ship_to_entry_distance = sqrt(2.0 * pow(m_data.ship_to_sbody_distance, 2)); vector3d ship_up = m_ship->GetOrientRelTo(m_data.sframe).VectorY(); // Get direction from ship to nearest entry point on planet hemisphere circular edge const vector3d ship_to_entry_dir = m_data.ship_to_sbody_dir * matrix4x4d::RotateMatrix(angle, ship_up.x, ship_up.y, ship_up.z); m_entryPoint = m_data.ship_pos + (ship_to_entry_dir * ship_to_entry_distance); // Planet could intersect path, in which case intersection point is the entry point if (LineSphereIntersection(m_data.sbody_pos, m_data.sbody_transit_radius, m_data.ship_pos, m_entryPoint, intersection_point)) { m_entryPoint = intersection_point; } m_stage = ESS_ENTER; } else { // -- Target in planet // is target in front or back hemisphere relative to ship? if (m_data.target_to_sbody_distance <= DESTINATION_RADIUS || -m_data.ship_to_sbody_dir.Dot(-m_data.target_to_sbody_dir) >= 0.0) { // Front hemisphere // Calculate location at which ship will enter transit-around heading towards target intersection = LineSphereIntersection(m_data.sbody_pos, m_data.sbody_transit_radius, m_data.ship_pos, m_data.target_to_transit, intersection_point); assert(intersection); // There should always be an intersection otherwise this code path would not run // If this exception is hit, it means there is a problem with the code that determines obstacles m_entryPoint = intersection_point; m_stage = ESS_ENTER; } else { // Back hemisphere // Enter point is the point that is exactly at 90 degrees planet-transit-radius from ship // If ship intersects radius before it reaches entry point then intersection point is the entry point const double angle = atan2(m_data.ship_to_sbody_distance, m_data.sbody_transit_radius); const double ship_to_entry_distance = sqrt(pow(m_data.ship_to_sbody_distance, 2) + pow(m_data.sbody_transit_radius, 2)); const vector3d ship_up = m_ship->GetOrientRelTo(m_data.sframe).VectorY(); // Get direction from ship to nearest entry point on planet hemisphere-edge // Note that entry point can be set anywhere around the planet's diameter from the ship's perspective vector3d sbody_to_target = -m_data.target_to_sbody_dir; sbody_to_target = sbody_to_target / ship_up.Dot(sbody_to_target); vector3d ship_to_entry_dir = (sbody_to_target - ship_up).Normalized(); m_entryPoint = m_data.ship_pos + (ship_to_entry_dir * ship_to_entry_distance); // Planet could intersect path, in which case intersection point is the entry point if (LineSphereIntersection(m_data.sbody_pos, m_data.sbody_transit_radius, m_data.ship_pos, m_entryPoint, intersection_point)) { m_entryPoint = intersection_point; } m_stage = ESS_ENTER; } } } else { // -- Ship is already at entry point m_entryPoint = m_data.ship_pos; m_stage = ESS_AROUND; } }
vector3d TerrainColorFractal<TerrainColorTFGood>::GetColor(const vector3d &p, double height, const vector3d &norm) const { double n = m_invMaxHeight*height; const double flatness = pow(p.Dot(norm), 8.0); vector3d color_cliffs = m_rockColor[5]; // ice on mountains and poles if (fabs(m_icyness*p.y) + m_icyness*n > 1) { return interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); } double equatorial_desert = (2.0-m_icyness)*(-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(2.0-m_icyness)*(1.0-p.y*p.y); // This is for fake ocean depth by the coast. double continents = octavenoise(GetFracDef(0), 0.7* ridged_octavenoise(GetFracDef(8), 0.58, p), p) - m_sealevel*0.6; vector3d col; //we don't want water on the poles if there are ice-caps if (fabs(m_icyness*p.y) > 0.75) { col = interpolate_color(equatorial_desert, vector3d(0.42, 0.46, 0), vector3d(0.5, 0.3, 0)); col = interpolate_color(flatness, col, vector3d(1,1,1)); return col; } // water if (n <= 0) { // Oooh, pretty coastal regions with shading based on underwater depth. n += continents - (GetFracDef(0).amplitude*m_sealevel*0.49); n *= 10.0; n = (n>0.3 ? 0.3-(n*n*n-0.027) : n); col = interpolate_color(equatorial_desert, vector3d(0,0,0.15), vector3d(0,0,0.25)); col = interpolate_color(n, col, vector3d(0,0.8,0.6)); return col; } // More sensitive height detection for application of colours if (n > 0.5) { col = interpolate_color(equatorial_desert, m_rockColor[2], m_rockColor[4]); col = interpolate_color(n, col, m_darkrockColor[6]); col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.25) { color_cliffs = m_darkrockColor[1]; col = interpolate_color(equatorial_desert, m_darkrockColor[5], m_darkrockColor[7]); col = interpolate_color(n, col, m_rockColor[1]); col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.05) { col = interpolate_color(equatorial_desert, m_darkrockColor[5], m_darkrockColor[7]); color_cliffs = col; col = interpolate_color(equatorial_desert, vector3d(.45,.43, .2), vector3d(.4, .43, .2)); col = interpolate_color(n, col, vector3d(-1.66,-2.3, -1.75)); col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.01) { color_cliffs = vector3d(0.2,0.28,0.2); col = interpolate_color(equatorial_desert, vector3d(.15,.5, -.1), vector3d(.2, .6, -.1)); col = interpolate_color(n, col, vector3d(5,-5, 5)); col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.005) { color_cliffs = vector3d(0.25,0.28,0.2); col = interpolate_color(equatorial_desert, vector3d(.45,.6,0), vector3d(.5, .6, .0)); col = interpolate_color(n, col, vector3d(-10,-10,0)); col = interpolate_color(flatness, color_cliffs, col); return col; } else { color_cliffs = vector3d(0.3,0.1,0.0); col = interpolate_color(equatorial_desert, vector3d(.35,.3,0), vector3d(.4, .3, .0)); col = interpolate_color(n, col, vector3d(0,20,0)); col = interpolate_color(flatness, color_cliffs, col); return col; } }
vector3d TerrainColorFractal<TerrainColorEarthLikeHeightmapped>::GetColor(const vector3d &p, double height, const vector3d &norm) const { double n = m_invMaxHeight*height; double flatness = pow(p.Dot(norm), 8.0); double equatorial_desert = (2.0-m_icyness)*(-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(2.0-m_icyness)*(1.0-p.y*p.y); vector3d color_cliffs = m_darkrockColor[5]; vector3d col, tex1, tex2; if (n > 0) { // ice on mountains if (flatness > 0.6/Clamp(n*m_icyness+(m_icyness*0.5)+(fabs(p.y*p.y*p.y*0.38)), 0.1, 1.0)) { if (textures) { col = interpolate_color(terrain_colournoise_rock, color_cliffs, m_rockColor[5]); col = interpolate_color(flatness, col, vector3d(1,1,1)); } else col = interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); return col; } //polar ice-caps if ((m_icyness*0.5)+(fabs(p.y*p.y*p.y*0.38)) > 0.6) { //if (flatness > 0.5/Clamp(fabs(p.y*m_icyness), 0.1, 1.0)) { if (textures) { col = interpolate_color(terrain_colournoise_rock, color_cliffs, m_rockColor[5]); col = interpolate_color(flatness, col, vector3d(1,1,1)); } else col = interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); return col; } } // water if (n <= 0) { // waves if (textures) { n += terrain_colournoise_water; n *= 0.1; } col = interpolate_color(equatorial_desert, vector3d(0,0,0.15), vector3d(0,0,0.25)); col = interpolate_color(n, col, vector3d(0,0.8,0.6)); return col; } flatness = pow(p.Dot(norm), 16.0); // More sensitive height detection for application of colours if (n > 0.5) { n -= 0.5; n *= 2.0; color_cliffs = interpolate_color(n, m_darkrockColor[2], m_rockColor[4]); col = interpolate_color(equatorial_desert, m_rockColor[2], m_rockColor[4]); col = interpolate_color(n, col, m_darkrockColor[6]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_sand, col, m_darkdirtColor[3]); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.25) { n -= 0.25; n *= 4.0; color_cliffs = interpolate_color(n, m_rockColor[3], m_darkplantColor[4]); col = interpolate_color(equatorial_desert, m_darkrockColor[3], m_darksandColor[1]); col = interpolate_color(n, col, m_rockColor[2]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_sand, col, m_darkdirtColor[3]); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.05) { n -= 0.05; n *= 5.0; color_cliffs = interpolate_color(equatorial_desert, m_darkrockColor[5], m_darksandColor[7]); col = interpolate_color(equatorial_desert, m_darkplantColor[2], m_sandColor[2]); col = interpolate_color(n, col, m_darkrockColor[3]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_forest, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.01) { n -= 0.01; n *= 25.0; color_cliffs = m_darkdirtColor[7]; col = interpolate_color(equatorial_desert, m_plantColor[1], m_plantColor[0]); col = interpolate_color(n, col, m_darkplantColor[2]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_grass, color_cliffs, col); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.005) { n -= 0.005; n *= 200.0; color_cliffs = m_dirtColor[2]; col = interpolate_color(equatorial_desert, m_darkplantColor[0], m_sandColor[1]); col = interpolate_color(n, col, m_plantColor[0]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_grass, color_cliffs, col); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else { n *= 200.0; color_cliffs = m_darksandColor[0]; col = interpolate_color(equatorial_desert, m_sandColor[0], m_sandColor[1]); col = interpolate_color(n, col, m_darkplantColor[0]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_sand, col, color_cliffs); return col = interpolate_color(flatness, tex1, tex2); } else { return col = interpolate_color(flatness, color_cliffs, col); } } }
// Calculates the ambiently and directly lit portions of the lighting model taking into account the atmosphere and sun positions at a given location // 1. Calculates the amount of direct illumination available taking into account // * multiple suns // * sun positions relative to up direction i.e. light is dimmed as suns set // * Thickness of the atmosphere overhead i.e. as atmospheres get thicker light starts dimming earlier as sun sets, without atmosphere the light switches off at point of sunset // 2. Calculates the split between ambient and directly lit portions taking into account // * Atmosphere density (optical thickness) of the sky dome overhead // as optical thickness increases the fraction of ambient light increases // this takes altitude into account automatically // * As suns set the split is biased towards ambient void SpaceStation::CalcLighting(Planet *planet, double &ambient, double &intensity, const std::vector<Camera::LightSource> &lightSources) { // position relative to the rotating frame of the planet vector3d upDir = GetPosition(); const double dist = upDir.Length(); upDir = upDir.Normalized(); double pressure, density; planet->GetAtmosphericState(dist, &pressure, &density); double surfaceDensity; Color cl; planet->GetSystemBody()->GetAtmosphereFlavor(&cl, &surfaceDensity); // approximate optical thickness fraction as fraction of density remaining relative to earths double opticalThicknessFraction = density/EARTH_ATMOSPHERE_SURFACE_DENSITY; // tweak optical thickness curve - lower exponent ==> higher altitude before ambient level drops opticalThicknessFraction = pow(std::max(0.00001,opticalThicknessFraction),0.15); //max needed to avoid 0^power //step through all the lights and calculate contributions taking into account sun position double light = 0.0; double light_clamped = 0.0; for(std::vector<Camera::LightSource>::const_iterator l = lightSources.begin(); l != lightSources.end(); ++l) { double sunAngle; // calculate the extent the sun is towards zenith if (l->GetBody()){ // relative to the rotating frame of the planet const vector3d lightDir = (l->GetBody()->GetInterpPositionRelTo(planet->GetFrame()).Normalized()); sunAngle = lightDir.Dot(upDir); } else { // light is the default light for systems without lights sunAngle = 1.0; } //0 to 1 as sunangle goes from 0.0 to 1.0 double sunAngle2 = (Clamp(sunAngle, 0.0,1.0))/1.0; //0 to 1 as sunAngle goes from endAngle to startAngle // angle at which light begins to fade on Earth const double startAngle = 0.3; // angle at which sun set completes, which should be after sun has dipped below the horizon on Earth const double endAngle = -0.18; const double start = std::min((startAngle*opticalThicknessFraction),1.0); const double end = std::max((endAngle*opticalThicknessFraction),-0.2); sunAngle = (Clamp(sunAngle, end, start)-end)/(start-end); light += sunAngle; light_clamped += sunAngle2; } // brightness depends on optical depth and intensity of light from all the stars intensity = (Clamp((light),0.0,1.0)); // ambient light fraction // alter ratio between directly and ambiently lit portions towards ambiently lit as sun sets const double fraction = (0.1+0.8*( 1.0-light_clamped*(Clamp((opticalThicknessFraction),0.0,1.0)) )+0.1); //fraction goes from 0.6 to 1.0 // fraction of light left over to be lit directly intensity = (1.0-fraction)*intensity; // scale ambient by amount of light ambient = fraction*(Clamp((light),0.0,1.0))*0.25; }
// Calculates the ambiently and directly lit portions of the lighting model taking into account the atmosphere and sun positions at a given location // 1. Calculates the amount of direct illumination available taking into account // * multiple suns // * sun positions relative to up direction i.e. light is dimmed as suns set // * Thickness of the atmosphere overhead i.e. as atmospheres get thicker light starts dimming earlier as sun sets, without atmosphere the light switches off at point of sunset // 2. Calculates the split between ambient and directly lit portions taking into account // * Atmosphere density (optical thickness) of the sky dome overhead // as optical thickness increases the fraction of ambient light increases // this takes altitude into account automatically // * As suns set the split is biased towards ambient void ModelBody::CalcLighting(double &ambient, double &direct, const Camera *camera) { const double minAmbient = 0.05; ambient = minAmbient; direct = 1.0; Body *astro = GetFrame()->GetBody(); if ( ! (astro && astro->IsType(Object::PLANET)) ) return; Planet *planet = static_cast<Planet*>(astro); // position relative to the rotating frame of the planet vector3d upDir = GetInterpPositionRelTo(planet->GetFrame()); const double planetRadius = planet->GetSystemBody()->GetRadius(); const double dist = std::max(planetRadius, upDir.Length()); upDir = upDir.Normalized(); double pressure, density; planet->GetAtmosphericState(dist, &pressure, &density); double surfaceDensity; Color cl; planet->GetSystemBody()->GetAtmosphereFlavor(&cl, &surfaceDensity); // approximate optical thickness fraction as fraction of density remaining relative to earths double opticalThicknessFraction = density/EARTH_ATMOSPHERE_SURFACE_DENSITY; // tweak optical thickness curve - lower exponent ==> higher altitude before ambient level drops // Commenting this out, since it leads to a sharp transition at // atmosphereRadius, where density is suddenly 0 //opticalThicknessFraction = pow(std::max(0.00001,opticalThicknessFraction),0.15); //max needed to avoid 0^power if (opticalThicknessFraction < 0.0001) return; //step through all the lights and calculate contributions taking into account sun position double light = 0.0; double light_clamped = 0.0; const std::vector<Camera::LightSource> &lightSources = camera->GetLightSources(); for(std::vector<Camera::LightSource>::const_iterator l = lightSources.begin(); l != lightSources.end(); ++l) { double sunAngle; // calculate the extent the sun is towards zenith if (l->GetBody()){ // relative to the rotating frame of the planet const vector3d lightDir = (l->GetBody()->GetInterpPositionRelTo(planet->GetFrame()).Normalized()); sunAngle = lightDir.Dot(upDir); } else { // light is the default light for systems without lights sunAngle = 1.0; } const double critAngle = -sqrt(dist*dist-planetRadius*planetRadius)/dist; //0 to 1 as sunangle goes from critAngle to 1.0 double sunAngle2 = (Clamp(sunAngle, critAngle, 1.0)-critAngle)/(1.0-critAngle); // angle at which light begins to fade on Earth const double surfaceStartAngle = 0.3; // angle at which sun set completes, which should be after sun has dipped below the horizon on Earth const double surfaceEndAngle = -0.18; const double start = std::min((surfaceStartAngle*opticalThicknessFraction),1.0); const double end = std::max((surfaceEndAngle*opticalThicknessFraction),-0.2); sunAngle = (Clamp(sunAngle-critAngle, end, start)-end)/(start-end); light += sunAngle; light_clamped += sunAngle2; } light_clamped /= lightSources.size(); light /= lightSources.size(); // brightness depends on optical depth and intensity of light from all the stars direct = 1.0 - Clamp((1.0 - light),0.0,1.0) * Clamp(opticalThicknessFraction,0.0,1.0); // ambient light fraction // alter ratio between directly and ambiently lit portions towards ambiently lit as sun sets const double fraction = ( 0.2 + 0.8 * (1.0-light_clamped) ) * Clamp(opticalThicknessFraction,0.0,1.0); // fraction of light left over to be lit directly direct = (1.0-fraction)*direct; // scale ambient by amount of light ambient = fraction*(Clamp((light),0.0,1.0))*0.25; ambient = std::max(minAmbient, ambient); }
static void hitCallback(CollisionContact *c) { //printf("OUCH! %x (depth %f)\n", SDL_GetTicks(), c->depth); Object *po1 = static_cast<Object*>(c->userData1); Object *po2 = static_cast<Object*>(c->userData2); const bool po1_isDynBody = po1->IsType(Object::DYNAMICBODY); const bool po2_isDynBody = po2->IsType(Object::DYNAMICBODY); // collision response assert(po1_isDynBody || po2_isDynBody); if (po1_isDynBody && po2_isDynBody) { DynamicBody *b1 = static_cast<DynamicBody*>(po1); DynamicBody *b2 = static_cast<DynamicBody*>(po2); const vector3d linVel1 = b1->GetVelocity(); const vector3d linVel2 = b2->GetVelocity(); const vector3d angVel1 = b1->GetAngVelocity(); const vector3d angVel2 = b2->GetAngVelocity(); const double coeff_rest = 0.5; // step back // mover->UndoTimestep(); const double invMass1 = 1.0 / b1->GetMass(); const double invMass2 = 1.0 / b2->GetMass(); const vector3d hitPos1 = c->pos - b1->GetPosition(); const vector3d hitPos2 = c->pos - b2->GetPosition(); const vector3d hitVel1 = linVel1 + angVel1.Cross(hitPos1); const vector3d hitVel2 = linVel2 + angVel2.Cross(hitPos2); const double relVel = (hitVel1 - hitVel2).Dot(c->normal); // moving away so no collision if (relVel > 0) return; if (!OnCollision(po1, po2, c, -relVel)) return; const double invAngInert1 = 1.0 / b1->GetAngularInertia(); const double invAngInert2 = 1.0 / b2->GetAngularInertia(); const double numerator = -(1.0 + coeff_rest) * relVel; const double term1 = invMass1; const double term2 = invMass2; const double term3 = c->normal.Dot((hitPos1.Cross(c->normal)*invAngInert1).Cross(hitPos1)); const double term4 = c->normal.Dot((hitPos2.Cross(c->normal)*invAngInert2).Cross(hitPos2)); const double j = numerator / (term1 + term2 + term3 + term4); const vector3d force = j * c->normal; b1->SetVelocity(linVel1 + force*invMass1); b1->SetAngVelocity(angVel1 + hitPos1.Cross(force)*invAngInert1); b2->SetVelocity(linVel2 - force*invMass2); b2->SetAngVelocity(angVel2 - hitPos2.Cross(force)*invAngInert2); } else { // one body is static vector3d hitNormal; DynamicBody *mover; if (po1_isDynBody) { mover = static_cast<DynamicBody*>(po1); hitNormal = c->normal; } else { mover = static_cast<DynamicBody*>(po2); hitNormal = -c->normal; } const double coeff_rest = 0.5; const vector3d linVel1 = mover->GetVelocity(); const vector3d angVel1 = mover->GetAngVelocity(); // step back // mover->UndoTimestep(); const double invMass1 = 1.0 / mover->GetMass(); const vector3d hitPos1 = c->pos - mover->GetPosition(); const vector3d hitVel1 = linVel1 + angVel1.Cross(hitPos1); const double relVel = hitVel1.Dot(c->normal); // moving away so no collision if (relVel > 0 && !c->geomFlag) return; if (!OnCollision(po1, po2, c, -relVel)) return; const double invAngInert = 1.0 / mover->GetAngularInertia(); const double numerator = -(1.0 + coeff_rest) * relVel; const double term1 = invMass1; const double term3 = c->normal.Dot((hitPos1.Cross(c->normal)*invAngInert).Cross(hitPos1)); const double j = numerator / (term1 + term3); const vector3d force = j * c->normal; mover->SetVelocity(linVel1 + force*invMass1); mover->SetAngVelocity(angVel1 + hitPos1.Cross(force)*invAngInert); } }
vector3d TerrainColorFractal<TerrainColorTFPoor>::GetColor(const vector3d &p, double height, const vector3d &norm) const { double n = m_invMaxHeight*height; double flatness = pow(p.Dot(norm), 8.0); double continents = 0; double equatorial_desert = (2.0-m_icyness)*(-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(2.0-m_icyness)*(1.0-p.y*p.y); vector3d color_cliffs = m_darkrockColor[5]; vector3d col, tex1, tex2; // ice on mountains and poles if (fabs(m_icyness*p.y) + m_icyness*n > 1) { if (textures) { col = interpolate_color(terrain_colournoise_rock2, color_cliffs, vector3d(.9,.9,.9)); col = interpolate_color(flatness, col, vector3d(1,1,1)); } else col = interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); return col; } //we don't want water on the poles if there are ice-caps if (fabs(m_icyness*p.y) > 0.67) { col = interpolate_color(equatorial_desert, m_sandColor[2], m_darksandColor[5]); col = interpolate_color(flatness, col, vector3d(1,1,1)); return col; } // This is for fake ocean depth by the coast. continents = ridged_octavenoise(GetFracDef(3-m_fracnum), 0.55, p) * (1.0-m_sealevel) - ((m_sealevel*0.1)-0.1); // water if (n <= 0) { // Oooh, pretty coastal regions with shading based on underwater depth. n += continents;// - (GetFracDef(3).amplitude*m_sealevel*0.49); n *= n*10.0; //n = (n>0.3 ? 0.3-(n*n*n-0.027) : n); col = interpolate_color(n, vector3d(0,0.0,0.1), vector3d(0,0.5,0.5)); return col; } // More sensitive height detection for application of colours if (n > 0.5) { n -= 0.5; n *= 2.0; //color_cliffs = m_rockColor[1]; col = interpolate_color(equatorial_desert, m_rockColor[2], m_rockColor[6]); col = interpolate_color(n, col, m_darkrockColor[6]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_rock2, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.25) { n -= 0.25; n *= 4.0; color_cliffs = m_rockColor[3]; col = interpolate_color(equatorial_desert, m_darkrockColor[4], m_darksandColor[6]); col = interpolate_color(n, col, m_rockColor[2]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.05) { n -= 0.05; n *= 5.0; col = interpolate_color(equatorial_desert, m_darkrockColor[5], m_darksandColor[7]); color_cliffs = col; col = interpolate_color(equatorial_desert, m_darksandColor[2], m_sandColor[2]); col = interpolate_color(n, col, m_darkrockColor[3]); if (textures) { tex1 = interpolate_color(terrain_colournoise_mud, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_grass, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.01) { n -= 0.01; n *= 25.0; color_cliffs = m_darkplantColor[0]; col = interpolate_color(equatorial_desert, m_sandColor[1], m_sandColor[0]); col = interpolate_color(n, col, m_darksandColor[2]); if (textures) { tex1 = interpolate_color(terrain_colournoise_grass, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_grass2, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.005) { n -= 0.005; n *= 200.0; color_cliffs = m_plantColor[0]; col = interpolate_color(equatorial_desert, m_darkplantColor[0], m_sandColor[1]); col = interpolate_color(n, col, m_plantColor[0]); if (textures) { tex1 = interpolate_color(terrain_colournoise_sand2, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_grass, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else { n *= 200.0; color_cliffs = m_darksandColor[0]; col = interpolate_color(equatorial_desert, m_sandColor[0], m_sandColor[1]); col = interpolate_color(n, col, m_darkplantColor[0]); if (textures) { tex1 = interpolate_color(terrain_colournoise_sand, col, color_cliffs); //tex2 = interpolate_color(terrain_colournoise_sand2, col, color_cliffs); col = interpolate_color(flatness, tex1, col); } else col = interpolate_color(flatness, color_cliffs, col); return col; } }
vector3d TerrainColorFractal<TerrainColorEarthLike>::GetColor(const vector3d &p, double height, const vector3d &norm) { double n = m_invMaxHeight*height; double flatness = pow(p.Dot(norm), 8.0); //textures: double tex_rock(0), tex_sand(0), tex_grass(0), tex_forest(0); if (textures) { tex_rock = rock; tex_sand = sand; tex_grass = grass; tex_forest = forest; } //textures end double continents = 0; double equatorial_desert = (2.0-m_icyness)*(-1.0+2.0*octavenoise(12, 0.5, 2.0, (n*2.0)*p)) * 1.0*(2.0-m_icyness)*(1.0-p.y*p.y); vector3d color_cliffs = m_darkrockColor[5]; vector3d col, tex1, tex2; if (m_heightMap) { if (n > 0) { // ice on mountains if (flatness > 0.6/Clamp(n*m_icyness+(m_icyness*0.5)+(fabs(p.y*p.y*p.y*0.38)), 0.1, 1.0)) { if (textures) { col = interpolate_color(tex_rock, color_cliffs, m_rockColor[5]); col = interpolate_color(flatness, col, vector3d(1,1,1)); } else col = interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); return col; } //polar ice-caps if ((m_icyness*0.5)+(fabs(p.y*p.y*p.y*0.38)) > 0.6) { //if (flatness > 0.5/Clamp(fabs(p.y*m_icyness), 0.1, 1.0)) { if (textures) { col = interpolate_color(tex_rock, color_cliffs, m_rockColor[5]); col = interpolate_color(flatness, col, vector3d(1,1,1)); } else col = interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); return col; } } } else { // ice on mountains //printf("flatness : %d", flatness); if (flatness > 0.6/Clamp(n*m_icyness+(m_icyness*0.5)+(fabs(p.y*p.y*p.y*0.38)), 0.1, 1.0)) { if (textures) { col = interpolate_color(tex_rock, color_cliffs, m_rockColor[5]); col = interpolate_color(flatness, col, vector3d(1,1,1)); } else col = interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); return col; } //polar ice-caps if ((m_icyness*0.5)+(fabs(p.y*p.y*p.y*0.38)) > 0.6) { //if (flatness > 0.5/Clamp(fabs(p.y*m_icyness), 0.1, 1.0)) { if (textures) { col = interpolate_color(tex_rock, color_cliffs, m_rockColor[5]); col = interpolate_color(flatness, col, vector3d(1,1,1)); } else col = interpolate_color(flatness, color_cliffs, vector3d(1,1,1)); return col; } } // This is for fake ocean depth by the coast. if (m_heightMap) { continents = 0; } else { continents = ridged_octavenoise(GetFracDef(3-m_fracnum), 0.55, p) * (1.0-m_sealevel) - ((m_sealevel*0.1)-0.1); } // water if (n <= 0) { if (m_heightMap) { // waves if (textures) { n += water; n *= 0.1; } } else { // Oooh, pretty coastal regions with shading based on underwater depth. n += continents;// - (GetFracDef(3).amplitude*m_sealevel*0.49); n *= n*10.0; //n = (n>0.3 ? 0.3-(n*n*n-0.027) : n); } col = interpolate_color(equatorial_desert, vector3d(0,0,0.15), vector3d(0,0,0.25)); col = interpolate_color(n, col, vector3d(0,0.8,0.6)); return col; } flatness = pow(p.Dot(norm), 16.0); // More sensitive height detection for application of colours if (n > 0.5) { n -= 0.5; n *= 2.0; color_cliffs = interpolate_color(n, m_darkrockColor[2], m_rockColor[4]); col = interpolate_color(equatorial_desert, m_rockColor[2], m_rockColor[4]); col = interpolate_color(n, col, m_darkrockColor[6]); if (textures) { tex1 = interpolate_color(tex_rock, col, color_cliffs); tex2 = interpolate_color(tex_sand, col, m_darkdirtColor[3]); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.25) { n -= 0.25; n *= 4.0; color_cliffs = interpolate_color(n, m_rockColor[3], m_darkplantColor[4]); col = interpolate_color(equatorial_desert, m_darkrockColor[3], m_darksandColor[1]); col = interpolate_color(n, col, m_rockColor[2]); if (textures) { tex1 = interpolate_color(tex_rock, col, color_cliffs); tex2 = interpolate_color(tex_sand, col, m_darkdirtColor[3]); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.05) { n -= 0.05; n *= 5.0; color_cliffs = interpolate_color(equatorial_desert, m_darkrockColor[5], m_darksandColor[7]); col = interpolate_color(equatorial_desert, m_darkplantColor[2], m_sandColor[2]); col = interpolate_color(n, col, m_darkrockColor[3]); if (textures) { tex1 = interpolate_color(tex_rock, col, color_cliffs); tex2 = interpolate_color(tex_forest, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.01) { n -= 0.01; n *= 25.0; color_cliffs = m_darkdirtColor[7]; col = interpolate_color(equatorial_desert, m_plantColor[1], m_plantColor[0]); col = interpolate_color(n, col, m_darkplantColor[2]); if (textures) { tex1 = interpolate_color(tex_rock, col, color_cliffs); tex2 = interpolate_color(tex_grass, color_cliffs, col); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.005) { n -= 0.005; n *= 200.0; color_cliffs = m_dirtColor[2]; col = interpolate_color(equatorial_desert, m_darkplantColor[0], m_sandColor[1]); col = interpolate_color(n, col, m_plantColor[0]); if (textures) { tex1 = interpolate_color(tex_rock, col, color_cliffs); tex2 = interpolate_color(tex_grass, color_cliffs, col); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else { n *= 200.0; color_cliffs = m_darksandColor[0]; col = interpolate_color(equatorial_desert, m_sandColor[0], m_sandColor[1]); col = interpolate_color(n, col, m_darkplantColor[0]); if (textures) { tex1 = interpolate_color(tex_rock, col, color_cliffs); tex2 = interpolate_color(tex_sand, col, color_cliffs); return col = interpolate_color(flatness, tex1, tex2); } else { return col = interpolate_color(flatness, color_cliffs, col); } } }
vector3d TerrainColorFractal<TerrainColorRock>::GetColor(const vector3d &p, double height, const vector3d &norm) { double n = m_invMaxHeight*height/2; if (n <= 0) return m_darkrockColor[0]; const double flatness = pow(p.Dot(norm), 20.0); const vector3d color_cliffs = m_rockColor[0]; double equatorial_desert = (2.0-m_icyness)*(-1.0+2.0*octavenoise(4, 0.05, 2.0, (n*2.0)*p)) * 1.0*(2.0-m_icyness)*(1.0-p.y*p.y); //double equatorial_region = octavenoise(GetFracDef(0), 0.54, p) * p.y * p.x; //double equatorial_region_2 = ridged_octavenoise(GetFracDef(1), 0.58, p) * p.x * p.x; // Below is to do with variable colours for different heights, it gives a nice effect. // n is height. vector3d col, tex1, tex2; col = interpolate_color(equatorial_desert, m_rockColor[2], m_darkrockColor[4]); //col = interpolate_color(equatorial_region, col, m_darkrockColor[4]); //col = interpolate_color(equatorial_region_2, m_rockColor[1], col); if (n > 0.9) { n -= 0.9; n *= 10.0; col = interpolate_color(n, m_rockColor[5], col ); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.8) { n -= 0.8; n *= 10.0; col = interpolate_color(n, col, m_rockColor[5]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.7) { n -= 0.7; n *= 10.0; col = interpolate_color(n, m_rockColor[4], col); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.6) { n -= 0.6; n *= 10.0; col = interpolate_color(n, m_rockColor[1], m_rockColor[4]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock2, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, m_rockColor[3]); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.5) { n -= 0.5; n *= 10.0; col = interpolate_color(n, col, m_rockColor[1]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock2, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.4) { n -= 0.4; n *= 10.0; col = interpolate_color(n, m_darkrockColor[3], col); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, m_rockColor[3]); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } if (n > 0.3) { n -= 0.3; n *= 10.0; col = interpolate_color(n, col, m_darkrockColor[3]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock2, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, m_darkrockColor[6]); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.2) { n -= 0.2; n *= 10.0; col = interpolate_color(n, m_rockColor[1], col); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_rock2, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else if (n > 0.1) { n -= 0.1; n *= 10.0; col = interpolate_color(n, col, m_rockColor[1]); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock2, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, m_rockColor[3]); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } else { n *= 10.0; col = interpolate_color(n, m_darkrockColor[0], col); if (textures) { tex1 = interpolate_color(terrain_colournoise_rock, col, color_cliffs); tex2 = interpolate_color(terrain_colournoise_mud, col, color_cliffs); col = interpolate_color(flatness, tex1, tex2); } else col = interpolate_color(flatness, color_cliffs, col); return col; } }