-Subproject commit 51cf5cf9b1bda806e44dd77fb31041f90d06ce2b
+Subproject commit 3c715b39e3aece21fc1f0fd6042611e79bfbeb44
textures.skins.Bind();
textures.skins.Reserve(256, 256, 9, format);
- LoadSkinTexture("1", textures.skins, 0);
- LoadSkinTexture("2", textures.skins, 1);
- LoadSkinTexture("3", textures.skins, 2);
- LoadSkinTexture("4", textures.skins, 3);
- LoadSkinTexture("5", textures.skins, 4);
- LoadSkinTexture("6", textures.skins, 5);
- LoadSkinTexture("7", textures.skins, 6);
- LoadSkinTexture("8", textures.skins, 7);
- LoadSkinTexture("9", textures.skins, 8);
+ LoadSkinTexture("plain", textures.skins, 0);
+ LoadSkinTexture("stripes", textures.skins, 1);
+ LoadSkinTexture("dots", textures.skins, 2);
+ LoadSkinTexture("lines", textures.skins, 3);
+ LoadSkinTexture("spots", textures.skins, 4);
+ LoadSkinTexture("circles", textures.skins, 5);
textures.skins.FilterTrilinear();
}
// TODO: extend to nearby bodies as well
for (auto c : cam.Reference().Creatures()) {
assets.shaders.creature_skin.SetM(cam.Model(cam.Reference()) * glm::mat4(c->LocalTransform()));
+ assets.shaders.creature_skin.SetBaseColor(c->BaseColor());
+ assets.shaders.creature_skin.SetHighlightColor(c->HighlightColor());
c->Draw(viewport);
}
Genome::Properties<double> &GetProperties() noexcept { return properties; }
const Genome::Properties<double> &GetProperties() const noexcept { return properties; }
+ const Genome::PropertySet<double> &CurProps() const noexcept { return properties.props[cur_prop]; }
+ const Genome::PropertySet<double> &NextProps() const noexcept { return properties.props[cur_prop + 1]; }
+
+ void BaseColor(const glm::dvec3 &c) noexcept { base_color = c; }
+ const glm::dvec3 &BaseColor() const noexcept { return base_color; }
+
+ void HighlightColor(const glm::dvec3 &c) noexcept { highlight_color = c; }
+ glm::dvec4 HighlightColor() const noexcept;
+
void Mass(double m) noexcept { mass = m; size = std::cbrt(mass / density); }
double Mass() const noexcept { return mass; }
void Grow(double amount) noexcept;
double Size() const noexcept;
double Age() const noexcept;
+ double AgeLerp(double from, double to) const noexcept;
// change of giving birth per tick
double Fertility() const noexcept;
Genome::Properties<double> properties;
int cur_prop;
+ glm::dvec3 base_color;
+ glm::dvec3 highlight_color;
+
double mass;
double density;
double size;
#include "../math/Distribution.hpp"
#include "../math/GaloisLFSR.hpp"
+#include "../math/glm.hpp"
#include <vector>
T age;
T mass;
T fertility;
+ T highlight;
};
template<class T>
struct Properties {
return {
p.age.FakeNormal(rand.SNorm()),
p.mass.FakeNormal(rand.SNorm()),
- p.fertility.FakeNormal(rand.SNorm())
+ p.fertility.FakeNormal(rand.SNorm()),
+ glm::clamp(p.highlight.FakeNormal(rand.SNorm()), 0.0, 1.0)
};
}
, genome()
, properties()
, cur_prop(0)
+, base_color(1.0)
+, highlight_color(0.0)
, mass(1.0)
, density(1.0)
, size(1.0)
Creature::~Creature() {
}
+glm::dvec4 Creature::HighlightColor() const noexcept {
+ return glm::dvec4(highlight_color, AgeLerp(CurProps().highlight, NextProps().highlight));
+}
+
void Creature::Grow(double amount) noexcept {
- Mass(std::min(properties.props[cur_prop].mass, mass + amount));
+ const double max_mass = AgeLerp(CurProps().mass, NextProps().mass);
+ Mass(std::min(max_mass, mass + amount));
}
void Creature::Hurt(double dt) noexcept {
return sim.Time() - birth;
}
+double Creature::AgeLerp(double from, double to) const noexcept {
+ return glm::mix(from, to, glm::smoothstep(CurProps().age, NextProps().age, Age()));
+}
+
double Creature::Fertility() const noexcept {
- // TODO: lerp based on age?
- return properties.props[cur_prop].fertility / 3600.0;
+ return AgeLerp(CurProps().fertility, NextProps().fertility) / 3600.0;
}
void Creature::AddGoal(std::unique_ptr<Goal> &&g) {
void Creature::Tick(double dt) {
if (cur_prop < 5 && Age() > properties.props[cur_prop + 1].age) {
- ++cur_prop;
- if (cur_prop == 5) {
+ if (cur_prop == 4) {
std::cout << "[" << int(sim.Time()) << "s] "
<< name << " died of old age" << std::endl;
Die();
+ } else {
+ ++cur_prop;
}
}
genome.properties.Birth().age = { 0.0, 0.0 };
genome.properties.Birth().mass = { 0.5, 0.05 };
genome.properties.Birth().fertility = { 0.0, 0.0 };
+ genome.properties.Birth().highlight = { 0.0, 0.0 };
genome.properties.Child().age = { 30.0, 1.0 };
genome.properties.Child().mass = { 0.7, 0.05 };
genome.properties.Child().fertility = { 0.0, 0.0 };
+ genome.properties.Child().highlight = { 0.2, 0.05 };
genome.properties.Youth().age = { 60.0, 5.0 };
genome.properties.Youth().mass = { 0.9, 0.1 };
genome.properties.Youth().fertility = { 0.5, 0.03 };
+ genome.properties.Youth().highlight = { 0.9, 0.1 };
genome.properties.Adult().age = { 120.0, 10.0 };
genome.properties.Adult().mass = { 1.2, 0.1 };
genome.properties.Adult().fertility = { 0.4, 0.01 };
+ genome.properties.Adult().highlight = { 0.7, 0.1 };
genome.properties.Elder().age = { 360.0, 30.0 };
genome.properties.Elder().mass = { 1.0, 0.05 };
genome.properties.Elder().fertility = { 0.1, 0.01 };
+ genome.properties.Elder().highlight = { 0.6, 0.1 };
genome.properties.Death().age = { 480.0, 60.0 };
genome.properties.Death().mass = { 0.9, 0.05 };
genome.properties.Death().fertility = { 0.0, 0.0 };
+ genome.properties.Death().highlight = { 0.5, 0.1 };
glm::dvec3 color_avg(0.0);
double color_divisor = 0.0;
{ 0.1, 0.0005 }, // penalty
{ 0.0, 0.0 }, // growth
});
- color_avg += c.GetSimulation().Resources()[p.Atmosphere()].base_color;
+ color_avg += c.GetSimulation().Resources()[p.Atmosphere()].base_color * 0.1;
color_divisor += 0.1;
}
if (liquid > -1) {
{ 0.01, 0.002 }, // penalty
{ 0.1, 0.0 }, // growth
});
- color_avg += c.GetSimulation().Resources()[liquid].base_color;
+ color_avg += c.GetSimulation().Resources()[liquid].base_color * 0.5;
color_divisor += 0.5;
}
if (solid > -1) {
c.AddNeed(std::move(need));
}
+ glm::dvec3 base_color(
+ std::fmod(base_hue.FakeNormal(random.SNorm()) + 1.0, 1.0),
+ glm::clamp(base_saturation.FakeNormal(random.SNorm()), 0.0, 1.0),
+ glm::clamp(base_lightness.FakeNormal(random.SNorm()), 0.0, 1.0)
+ );
+ glm::dvec3 highlight_color(
+ std::fmod(base_color.x + 0.5, 1.0),
+ 1.0 - base_color.y,
+ 1.0 - base_color.z
+ );
+ c.BaseColor(hsl2rgb(base_color));
+ c.HighlightColor(hsl2rgb(highlight_color));
+
c.Mass(c.GetProperties().props[0].mass);
c.Density(mass / volume);
c.GetSteering().MaxAcceleration(1.4);
void Split(Creature &c) {
Creature *a = new Creature(c.GetSimulation());
const Situation &s = c.GetSituation();
- // TODO: generate names
a->Name(c.GetSimulation().Assets().name.Sequential());
// TODO: mutate
c.GetGenome().Configure(*a);
void SetV(const glm::mat4 &v) noexcept;
void SetVP(const glm::mat4 &v, const glm::mat4 &p) noexcept;
void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept;
+ void SetBaseColor(const glm::vec3 &) noexcept;
+ void SetHighlightColor(const glm::vec4 &) noexcept;
void SetTexture(ArrayTexture &) noexcept;
void SetLight(int n, const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept;
void SetNumLights(int n) noexcept;
GLuint m_handle;
GLuint mv_handle;
GLuint mvp_handle;
- GLuint sampler_handle;
+ GLuint base_color_handle;
+ GLuint highlight_color_handle;
+ GLuint sampler_handle;
GLuint num_lights_handle;
GLuint light_handle[MAX_LIGHTS * 3];
"in vec3 frag_tex_uv;\n"
"in vec3 normal;\n"
+ "uniform vec3 base_color;\n"
+ "uniform vec4 highlight_color;\n"
"uniform sampler2DArray tex_sampler;\n"
"uniform int num_lights;\n"
"uniform LightSource light[8];\n"
"out vec3 color;\n"
"void main() {\n"
- "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n"
- "vec3 total_light = tex_color * vec3(0.1, 0.1, 0.1);\n"
+ "vec4 tex_color = texture(tex_sampler, frag_tex_uv);\n"
+ "vec3 mat_color = mix(base_color, highlight_color.rgb, tex_color.r * tex_color.a * highlight_color.a);\n"
+ "vec3 total_light = mat_color * vec3(0.1, 0.1, 0.1);\n"
"for (int i = 0; i < num_lights; ++i) {\n"
"vec3 to_light = light[i].position - vtx_viewspace;\n"
"float distance = length(to_light) + length(vtx_viewspace);\n"
"vec3 light_dir = normalize(to_light);\n"
"float attenuation = light[i].strength / (distance * distance);\n"
- "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light[i].color * tex_color;\n"
+ "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light[i].color * mat_color;\n"
"vec3 view_dir = vec3(0.0, 0.0, 1.0);\n"
"vec3 specular = vec3(0.0, 0.0, 0.0);\n"
"if (dot(normal, light_dir) >= 0.0) {\n"
m_handle = prog.UniformLocation("M");
mv_handle = prog.UniformLocation("MV");
mvp_handle = prog.UniformLocation("MVP");
+ base_color_handle = prog.UniformLocation("base_color");
+ highlight_color_handle = prog.UniformLocation("highlight_color");
sampler_handle = prog.UniformLocation("tex_sampler");
num_lights_handle = prog.UniformLocation("num_lights");
for (int i = 0; i < MAX_LIGHTS; ++i) {
prog.Uniform(mvp_handle, mvp);
}
+void CreatureSkin::SetBaseColor(const glm::vec3 &c) noexcept {
+ prog.Uniform(base_color_handle, c);
+}
+
+void CreatureSkin::SetHighlightColor(const glm::vec4 &c) noexcept {
+ prog.Uniform(highlight_color_handle, c);
+}
+
void CreatureSkin::SetTexture(ArrayTexture &tex) noexcept {
glActiveTexture(GL_TEXTURE0);
tex.Bind();
inline T hsl2rgb(const T &hsl) {
using Vec3 = glm::tvec3<typename T::value_type>;
using Vec4 = glm::tvec4<typename T::value_type>;
- const Vec4 K(0.0, -1.0/3.0, 2.0/3.0, -1.0);
- const Vec3 p(glm::abs(glm::fract(Vec3(hsl.h) + Vec3(K)) * 6.0 - Vec3(K.w)));
+ const Vec4 K(1.0, 2.0/3.0, 1.0/3.0, 3.0);
+ const Vec3 p(glm::abs(glm::fract(Vec3(hsl.x) + Vec3(K)) * 6.0 - Vec3(K.w)));
T rgb = hsl.z * glm::mix(Vec3(K.x), glm::clamp(p - Vec3(K.x), 0.0, 1.0), hsl.y);
return rgb;
}
for (int y = 0; y < sidelength; ++y) {
for (int x = 0; x < sidelength; ++x, ++index) {
float tex = ts[TileAt(surface, x, y).type].texture;
- const float tex_u_begin = surface < 3 ? 1.0f : 0.0f;
- const float tex_u_end = surface < 3 ? 0.0f : 1.0f;
+ const float tex_v_begin = surface < 3 ? 1.0f : 0.0f;
+ const float tex_v_end = surface < 3 ? 0.0f : 1.0f;
attrib[4 * index + 0].position[(surface + 0) % 3] = x + 0 - offset;
attrib[4 * index + 0].position[(surface + 1) % 3] = y + 0 - offset;
attrib[4 * index + 0].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
- attrib[4 * index + 0].tex_coord[0] = tex_u_begin;
- attrib[4 * index + 0].tex_coord[1] = 1.0f;
+ attrib[4 * index + 0].tex_coord[0] = 0.0f;
+ attrib[4 * index + 0].tex_coord[1] = tex_v_begin;
attrib[4 * index + 0].tex_coord[2] = tex;
attrib[4 * index + 1].position[(surface + 0) % 3] = x + 0 - offset;
attrib[4 * index + 1].position[(surface + 1) % 3] = y + 1 - offset;
attrib[4 * index + 1].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
- attrib[4 * index + 1].tex_coord[0] = tex_u_end;
- attrib[4 * index + 1].tex_coord[1] = 1.0f;
+ attrib[4 * index + 1].tex_coord[0] = 0.0f;
+ attrib[4 * index + 1].tex_coord[1] = tex_v_end;
attrib[4 * index + 1].tex_coord[2] = tex;
attrib[4 * index + 2].position[(surface + 0) % 3] = x + 1 - offset;
attrib[4 * index + 2].position[(surface + 1) % 3] = y + 0 - offset;
attrib[4 * index + 2].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
- attrib[4 * index + 2].tex_coord[0] = tex_u_begin;
- attrib[4 * index + 2].tex_coord[1] = 0.0f;
+ attrib[4 * index + 2].tex_coord[0] = 1.0f;
+ attrib[4 * index + 2].tex_coord[1] = tex_v_begin;
attrib[4 * index + 2].tex_coord[2] = tex;
attrib[4 * index + 3].position[(surface + 0) % 3] = x + 1 - offset;
attrib[4 * index + 3].position[(surface + 1) % 3] = y + 1 - offset;
attrib[4 * index + 3].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
- attrib[4 * index + 3].tex_coord[0] = tex_u_end;
- attrib[4 * index + 3].tex_coord[1] = 0.0f;
+ attrib[4 * index + 3].tex_coord[0] = 1.0f;
+ attrib[4 * index + 3].tex_coord[1] = tex_v_end;
attrib[4 * index + 3].tex_coord[2] = tex;
}
}