for (auto sun : sim.Suns()) {
// TODO: source sun's light color and strength
glm::vec3 pos(cam.View() * cam.Model(*sun)[3]);
- glm::vec3 col(1.0f, 1.0f, 1.0f);
- float str = 1.0e6f;
assets.shaders.planet_surface.Activate();
- assets.shaders.planet_surface.SetLight(num_lights, pos, col, str);
+ assets.shaders.planet_surface.SetLight(num_lights, pos, sun->Color(), sun->Luminosity());
assets.shaders.creature_skin.Activate();
- assets.shaders.creature_skin.SetLight(num_lights, pos, col, str);
+ assets.shaders.creature_skin.SetLight(num_lights, pos, sun->Color(), sun->Luminosity());
++num_lights;
if (num_lights >= graphics::PlanetSurface::MAX_LIGHTS || num_lights >= graphics::CreatureSkin::MAX_LIGHTS) {
break;
double sun_radius = sun->Radius();
assets.shaders.sun_surface.SetM(
cam.Model(*sun) * glm::scale(glm::vec3(sun_radius, sun_radius, sun_radius)));
- assets.shaders.sun_surface.SetLight(glm::vec3(1.0f, 1.0f, 1.0f), 1.0e6f);
+ assets.shaders.sun_surface.SetLight(sun->Color(), sun->Luminosity());
assets.shaders.sun_surface.Draw();
}
world::Sun sun;
sun.Name("Sun");
- sun.Mass(1.0e14);
- sun.Radius(20.0);
+ sun.Mass(1.0e17);
+ sun.Radius(200.0);
+ sun.Color(glm::dvec3(1.0));
+ sun.Luminosity(1.0e8);
sun.SurfaceTilt(glm::dvec2(PI * 0.25, PI * 0.25));
- sun.AngularMomentum(1.0e13);
+ sun.AngularMomentum(1.0e18);
world::Planet planet(25);
planet.Name("Planet");
planet.SetParent(sun);
- planet.Mass(1.0e10);
- planet.GetOrbit().SemiMajorAxis(941.7);
+ planet.Mass(1.0e13);
+ planet.GetOrbit().SemiMajorAxis(8184.0);
planet.SurfaceTilt(glm::dvec2(PI * 0.25, PI * 0.25));
planet.AxialTilt(glm::dvec2(PI * 0.127, 0.0));
- planet.AngularMomentum(6.0e10);
+ planet.AngularMomentum(6.5e13);
- world::Planet moon(3);
+ world::Planet moon(5);
moon.Name("Moon");
moon.SetParent(planet);
- moon.Mass(1.0e6);
- moon.GetOrbit().SemiMajorAxis(37.0);
+ moon.Mass(1.0e7);
+ moon.GetOrbit().SemiMajorAxis(72.5);
moon.Rotation(PI * 0.25);
- moon.AngularMomentum(1.0e4);
+ moon.AngularMomentum(5.22e5);
- world::Planet second_planet(9);
+ world::Planet second_planet(14);
second_planet.Name("Second planet");
second_planet.SetParent(sun);
- second_planet.Mass(1.0e9);
- second_planet.GetOrbit().SemiMajorAxis(350.0);
+ second_planet.Mass(1.0e12);
+ second_planet.GetOrbit().SemiMajorAxis(4350.0);
second_planet.SurfaceTilt(glm::dvec2(PI * 0.125, PI * 0.25));
second_planet.AxialTilt(glm::dvec2(PI * 0.95, 0.0));
- second_planet.AngularMomentum(1.0e8);
+ second_planet.AngularMomentum(1.0e12);
world::Simulation sim(sun, assets);
sim.AddSun(sun);
bool Moving() const noexcept { return glm::length2(state.vel) > 0.00001; }
void Move(const glm::dvec3 &dp) noexcept;
void Accelerate(const glm::dvec3 &dv) noexcept;
- void EnforceConstraints(State &) noexcept;
+ void EnforceConstraints(State &) const noexcept;
void Heading(const glm::dvec3 &h) noexcept { state.dir = h; }
const glm::dvec3 &Heading() const noexcept { return state.dir; }
}
situation.SetState(state);
// work is force times distance
- DoWork(glm::length(f.acc) * Mass() * glm::length(f.vel) * dt);
+ // exclude gravity for no apparent reason
+ // actually, this should solely be based on steering force
+ DoWork(glm::length(f.acc - situation.GetPlanet().GravityAt(state.pos)) * Mass() * glm::length(f.vel) * dt);
}
Situation::Derivative Creature::Step(const Situation::Derivative &ds, double dt) const noexcept {
Situation::State s = situation.GetState();
s.pos += ds.vel * dt;
s.vel += ds.acc * dt;
+ situation.EnforceConstraints(s);
glm::dvec3 force(steering.Force(s));
// gravity = antinormal * mass * Gm / r²
glm::dvec3 normal(situation.GetPlanet().NormalAt(s.pos));
force += glm::dvec3(
-normal
- * Mass() * situation.GetPlanet().GravitationalParameter()
- / glm::length2(s.pos));
+ * (Mass() * situation.GetPlanet().GravitationalParameter()
+ / glm::length2(s.pos)));
// if net force is applied and in contact with surface
- if (!allzero(force) && glm::length2(s.pos) < (situation.GetPlanet().Radius() + 0.01) * (situation.GetPlanet().Radius() + 0.01)) {
- // apply friction = -|normal force| * tangential force * coefficient
+ if (!allzero(force) && !allzero(s.vel) && glm::length2(s.pos) < (situation.GetPlanet().Radius() + 0.01) * (situation.GetPlanet().Radius() + 0.01)) {
+ // apply friction
glm::dvec3 fn(normal * glm::dot(force, normal));
+ // TODO: friction somehow bigger than force?
glm::dvec3 ft(force - fn);
double u = 0.4;
- glm::dvec3 friction(-glm::length(fn) * ft * u);
+ glm::dvec3 friction(-glm::clamp(glm::length(ft), 0.0, glm::length(fn) * u) * glm::normalize(s.vel));
force += friction;
}
return {
c.GetSimulation().Assets().random.SNorm(),
c.GetSimulation().Assets().random.SNorm(),
c.GetSimulation().Assets().random.SNorm());
- pos += error * (2.0 * (1.0 - c.IntelligenceFactor()));
+ pos += error * (4.0 * (1.0 - c.IntelligenceFactor()));
pos = glm::normalize(pos) * c.GetSituation().GetPlanet().Radius();
return true;
} else {
EnforceConstraints(state);
}
-void Situation::EnforceConstraints(State &s) noexcept {
+void Situation::EnforceConstraints(State &s) const noexcept {
if (OnSurface()) {
double r = GetPlanet().Radius();
if (glm::length2(s.pos) < r * r) {
- s.pos = glm::normalize(s.pos) * r;
+ const glm::dvec3 normal(GetPlanet().NormalAt(s.pos));
+ s.pos = normal * r;
+ s.vel -= normal * glm::dot(normal, s.vel);
}
}
}
}
// remove vertical component, if any
const glm::dvec3 normal(c.GetSituation().GetPlanet().NormalAt(s.pos));
- result += normal * glm::dot(normal, result);
+ result -= normal * glm::dot(normal, result);
// clamp to max
if (glm::length2(result) > max_force * max_force) {
result = glm::normalize(result) * max_force;
double ElevationAt(const glm::dvec3 &p) const noexcept { return glm::length(p) - Radius(); }
/// distance to planet center
double DistanceAt(const glm::dvec3 &p) const noexcept { return glm::length(p); }
+ /// acceleration due to gravity at given point
+ glm::dvec3 GravityAt(const glm::dvec3 &p) const noexcept { return NormalAt(p) * (-GravitationalParameter() / glm::length2(p)); }
/// get ground tile
Tile &TileAt(const glm::dvec3 &) noexcept;
Sun(Sun &&) = delete;
Sun &operator =(Sun &&) = delete;
+public:
+ void Color(const glm::dvec3 &c) noexcept { color = c; }
+ const glm::dvec3 &Color() const noexcept { return color; }
+
+ void Luminosity(double l) noexcept { luminosity = l; }
+ double Luminosity() const noexcept { return luminosity; }
+
+private:
+ glm::dvec3 color;
+ double luminosity;
+
};
}
Sun::Sun()
-: Body() {
+: Body()
+, color(1.0)
+, luminosity(1.0) {
}
Sun::~Sun() {