From c80f817e984fbabbadef14fc11bf0fa7385bc89b Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Thu, 9 Apr 2020 20:56:53 +0100 Subject: [PATCH] Start simulation --- Makefile | 4 +- billboardfrag.glsl | 2 +- clouds.cpp | 63 +++++++++++++++++++++------ clouds.h | 0 simulation.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++++ simulation.h | 15 +++++++ 6 files changed, 173 insertions(+), 15 deletions(-) create mode 100644 clouds.h create mode 100644 simulation.cpp create mode 100644 simulation.h diff --git a/Makefile b/Makefile index 7cd3b96..fcdd422 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -clouds: clouds.cpp program.cpp - clang++ -std=c++17 $^ -o $@ \ +clouds: clouds.cpp program.cpp simulation.cpp + clang++ -std=c++17 $^ -Ofast -o $@ \ -Wall -g \ -I/usr/local/include -L/usr/local/lib \ -framework OpenGL -framework glut -lglew diff --git a/billboardfrag.glsl b/billboardfrag.glsl index 2349e4d..94d15dc 100644 --- a/billboardfrag.glsl +++ b/billboardfrag.glsl @@ -6,7 +6,7 @@ out vec4 FragColor; uniform bool modulate; void main() { // Cf = color from fragment, Ct = color from texture - // Cc = color from texture environment(?) assume to be 0? + // Cc = color from texture environment -- not set, defaults to (0,0,0,0) // Af = alpha from fragment, At = alpha from texture // C = output color, A = output alpha float f = texture(tex, texCoord).r; diff --git a/clouds.cpp b/clouds.cpp index 96612e8..e406f5c 100644 --- a/clouds.cpp +++ b/clouds.cpp @@ -1,4 +1,5 @@ #include "debug.hpp" +#include "simulation.h" #include "program.hpp" #include #include @@ -14,12 +15,6 @@ using namespace std; using namespace glm; -static const int CLOUD_DIM = 16; -struct Clouds { - char cld[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; - float contDist[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; -}; - // calculate continuous distribution void calcContDist(Clouds *clds); @@ -75,8 +70,6 @@ vector bbColors; GLuint bbProg; GLuint bbVao; -void calculateMetaballs() {} - // Here we need to generate n_q textures for different densities of metaballs // These textures then go on the billboards // The texture stores attenuation ratio? @@ -91,7 +84,7 @@ void precalculateBillboardTextures() { // TODO: properly calculate this instead of whatever this is for (int j = 0; j < 32; j++) for (int i = 0; i < 32; i++) - data[i + j * 32] = fmin(1.f, 0.3f + 2.f * (distance(vec2(i, j), vec2(16, 16)) / 16)); + data[i + j * 32] = fmin(1.f, 0.5f + 1.f * (distance(vec2(i, j), vec2(16, 16)) / 16)); glGenTextures(NQ, bbTexIds); @@ -116,6 +109,32 @@ struct Metaball { vector metaballs = {{{0, 0, 0.5}, 1.f}, {{0, 0.3, 0.3}, 0.7f}}; +Clouds cs; + +void calculateMetaballs() { + stepClouds(&cs); + metaballs.clear(); + for (int i = 0; i < CLOUD_DIM; i++) { + for (int j = 0; j < CLOUD_DIM; j++) { + for (int k = 0; k < CLOUD_DIM; k++) { + if (cs.cld[i][j][k]) { + /* float x = (float)rand()/(float)(RAND_MAX); */ + /* float y = (float)rand()/(float)(RAND_MAX); */ + /* float z = (float)rand()/(float)(RAND_MAX); */ + /* float r = (float)rand()/(float)(RAND_MAX); */ + /* Metaball m = {{x,y, 0.3 + z * 0.5}, r}; */ + /* metaballs.push_back(m); */ + Metaball m = {{i / (float)CLOUD_DIM, j / (float)CLOUD_DIM, k / (float)CLOUD_DIM}, + 1.f / (float)CLOUD_DIM }; + m.pos = (m.pos * vec3(2)) - vec3(1); + metaballs.push_back(m); + } + } + } + } + fprintf(stderr, "num metaballs: %lu\n", metaballs.size()); +} + vec3 sunPos = {0, 2, 2}, viewPos = {0, 0, 0}, lookPos = {0, 0, 1}; mat4 proj; // projection matrix mat4 view; // view matrix @@ -198,6 +217,8 @@ void shadeClouds() { * vec2(width, height); vec4 pixel; glReadPixels(screenPos.x, screenPos.y, 1, 1, GL_RGBA, GL_FLOAT, value_ptr(pixel)); + /* fprintf(stderr, "pixel:"); */ + /* dump(pixel); */ // Multiply the pixel value by the sunlight color. vec4 sunColor = {1, 1, 0.9, 1}; @@ -236,8 +257,11 @@ void renderClouds() { glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); // Set the billboard color as C[n]. - fprintf(stderr, "bbColors[i]: "); - dump(bbColors[i]); + /* fprintf(stderr, "bbColors[i]: "); */ + /* dump(bbColors[i]); */ + /* bbColors[i].x = 1 - bbColors[i].x; */ + /* bbColors[i].y = 1 - bbColors[i].y; */ + /* bbColors[i].z = 1 - bbColors[i].z; */ bbColors[i].w = 1; glUniform4fv(glGetUniformLocation(bbProg, "color"), 1, glm::value_ptr(bbColors[i])); @@ -276,6 +300,19 @@ void display() { glutSwapBuffers(); } +void timer(int _) { + /* calculateMetaballs(); */ + /* glutPostRedisplay(); */ + /* glutTimerFunc(16, timer, 0); */ +} + +void keyboard(unsigned char key, int x, int y) { + if (key == ' ') { + calculateMetaballs(); + glutPostRedisplay(); + } +} + int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB | @@ -314,11 +351,13 @@ int main(int argc, char **argv) { precalculateBillboardTextures(); + initClouds(&cs); calculateMetaballs(); glGenTextures(1, &attenuationTex); - /* glutTimerFunc(16, timer, 0); */ + glutKeyboardFunc(keyboard); + glutTimerFunc(16, timer, 0); // set up billboard prog diff --git a/clouds.h b/clouds.h new file mode 100644 index 0000000..e69de29 diff --git a/simulation.cpp b/simulation.cpp new file mode 100644 index 0000000..0471f4a --- /dev/null +++ b/simulation.cpp @@ -0,0 +1,104 @@ +#include "simulation.h" +#include +#include + +inline float randf() { + return (float)rand()/(float)(RAND_MAX); +} + +// Helper to account for bounds +inline void set(float x[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM], int i, int j, int k, float y) { + if (i < 0 || i >= CLOUD_DIM || + j < 0 || j >= CLOUD_DIM || + k < 0 || k >= CLOUD_DIM) + return; + x[i][j][k] = y; +} + +#define P_EXT 0.1 +#define P_HUM 0.1 +#define P_ACT 0.001 + +void initClouds(Clouds *cs) { + for (int i = 0; i < CLOUD_DIM; i++) { + for (int j = 0; j < CLOUD_DIM; j++) { + for (int k = 0; k < CLOUD_DIM; k++) { + cs->act[i][j][k] = rand() % 8 == 0; + cs->cld[i][j][k] = false; + cs->hum[i][j][k] = rand() % 9 == 0; + cs->p_ext[i][j][k] = 0.f; + cs->p_hum[i][j][k] = 0.f; + cs->p_act[i][j][k] = 0.f; + } + } + } + + // generate ellipsoids of probability + for (int n = 0; n < 6; n++) { + const float maxSize = 5; + int width = randf() * maxSize, height = randf() * maxSize, depth = randf() * maxSize; + int x = randf() * CLOUD_DIM, y = randf() * CLOUD_DIM, z = randf() * CLOUD_DIM; + glm::vec3 center(x + width / 2, y + height / 2, z + depth / 2); + + for (int i = x; i < x + width; i++) { + for (int j = y; j < y + height; j++) { + for (int k = z; k < z + depth; k++) { + set(cs->p_ext, x, y, z, P_EXT * glm::distance(glm::vec3(x,y,z), center) / maxSize); + set(cs->p_hum, x, y, z, P_HUM * (1.f - glm::distance(glm::vec3(x,y,z), center) / maxSize)); + set(cs->p_act, x, y, z, P_ACT * (1.f - glm::distance(glm::vec3(x,y,z), center) / maxSize)); + } + } + } + } +} + +// Helper to account for bounds +inline bool get(bool x[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM], int i, int j, int k) { + if (i < 0 || i >= CLOUD_DIM || + j < 0 || j >= CLOUD_DIM || + k < 0 || k >= CLOUD_DIM) + return false; + return x[i][j][k]; +} + +inline bool f_act(Clouds *cs, int i, int j, int k) { + return get(cs->act, i + 1, j, k) || get(cs->act, i, j + 1, k) + || get(cs->act, i, j, k + 1) || get(cs->act, i - 1, j, k) || get(cs->act, i, j - 1, k) + || get(cs->act, i , j, k - 1) || get(cs->act, i - 2, j, k) || get(cs->act, i + 2, j , k) + || get(cs->act, i, j - 2, k) || get(cs->act, i , j + 2, k) || get(cs->act, i, j, k - 2); +} + +void growth(Clouds *cs) { + Clouds ncs; + + for (int i = 0; i < CLOUD_DIM; i++) { + for (int j = 0; j < CLOUD_DIM; j++) { + for (int k = 0; k < CLOUD_DIM; k++) { + ncs.hum[i][j][k] = cs->hum[i][j][k] && !cs->act[i][j][k]; + ncs.cld[i][j][k] = cs->cld[i][j][k] || cs->act[i][j][k]; + ncs.act[i][j][k] = !cs->act[i][j][k] && cs->hum[i][j][k] && f_act(cs, i, j, k); + } + } + } + + *cs = ncs; +} + +void extinction(Clouds *cs) { + Clouds ncs; + for (int i = 0; i < CLOUD_DIM; i++) { + for (int j = 0; j < CLOUD_DIM; j++) { + for (int k = 0; k < CLOUD_DIM; k++) { + ncs.cld[i][j][k] = cs->cld[i][j][k] && (randf() > cs->p_ext[i][j][k]); + ncs.hum[i][j][k] = cs->hum[i][j][k] || (randf() < cs->p_hum[i][j][k]); + ncs.act[i][j][k] = cs->act[i][j][k] || (randf() < cs->p_act[i][j][k]); + } + } + } + *cs = ncs; +} + +void stepClouds(Clouds *cs) { + growth(cs); + extinction(cs); +} diff --git a/simulation.h b/simulation.h new file mode 100644 index 0000000..f021ce4 --- /dev/null +++ b/simulation.h @@ -0,0 +1,15 @@ +#define CLOUD_DIM 16 +struct Clouds { + // TODO: make more efficient + bool hum[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; + bool cld[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; + bool act[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; + float p_ext[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; + float p_hum[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; + float p_act[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; + float contDist[CLOUD_DIM][CLOUD_DIM][CLOUD_DIM]; +}; + +void initClouds(Clouds *cs); + +void stepClouds(Clouds *cs); -- 2.30.2