From 9059716493de4ffe224dea7477d2503ebcd0f01b Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Thu, 9 Apr 2020 21:33:41 +0100 Subject: [PATCH] Fix billboard orientation --- Makefile | 2 +- clouds.cpp | 93 ++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index fcdd422..67b688d 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ clouds: clouds.cpp program.cpp simulation.cpp - clang++ -std=c++17 $^ -Ofast -o $@ \ + clang++ -std=c++17 $^ -o $@ \ -Wall -g \ -I/usr/local/include -L/usr/local/lib \ -framework OpenGL -framework glut -lglew diff --git a/clouds.cpp b/clouds.cpp index e406f5c..d5c8f6a 100644 --- a/clouds.cpp +++ b/clouds.cpp @@ -84,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.5f + 1.f * (distance(vec2(i, j), vec2(16, 16)) / 16)); + data[i + j * 32] = fmin(1.f, 0.5f + 2.f * (distance(vec2(i, j), vec2(16, 16)) / 16)); glGenTextures(NQ, bbTexIds); @@ -112,30 +112,33 @@ vector metaballs = {{{0, 0, 0.5}, 1.f}, Clouds cs; void calculateMetaballs() { - stepClouds(&cs); + /* 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); + for (int i = 0; i < 256; i++) { + float x = ((float)rand()/(float)(RAND_MAX) - 0.5) * 2; + float y = ((float)rand()/(float)(RAND_MAX) - 0.5) * 2; + float z = ((float)rand()/(float)(RAND_MAX) - 0.5) * 2; + float r = (float)rand()/(float)(RAND_MAX) * 1; + Metaball m = {{x,y,z}, r}; metaballs.push_back(m); } - } - } - } + /* 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]) { */ + /* 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}; +vec3 sunPos = {0, 2, 2}, sunDir = {0, -1, -1}; +vec3 camPos = {0, 0, -5}, viewPos = {0, 0, 0}; mat4 proj; // projection matrix mat4 view; // view matrix float znear = 0.001, zfar = 1000; @@ -152,7 +155,7 @@ void setProjectionAndViewUniforms(GLuint progId) { /** Orientates the transformation matrix to face the camera in the view matrix */ -void faceView(mat4 m) { +mat4 faceView(mat4 m) { m[0][0] = view[0][0]; m[0][1] = view[1][0]; m[0][2] = view[2][0]; @@ -162,6 +165,7 @@ void faceView(mat4 m) { m[2][0] = view[0][2]; m[2][1] = view[1][2]; m[2][2] = view[2][2]; + return m; } GLuint attenuationTex; @@ -191,7 +195,7 @@ void shadeClouds() { mat4 model = scale(translate(mat4(1), k.pos), vec3(k.r) * 2.f); // rotate the billboard so that its normal is oriented to the sun - faceView(model); + model = faceView(model); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); @@ -217,6 +221,7 @@ void shadeClouds() { * vec2(width, height); vec4 pixel; glReadPixels(screenPos.x, screenPos.y, 1, 1, GL_RGBA, GL_FLOAT, value_ptr(pixel)); + /* if (pixel.g == 0 && pixel.b == 0) abort(); */ /* fprintf(stderr, "pixel:"); */ /* dump(pixel); */ @@ -237,7 +242,7 @@ void renderObject() {} void renderClouds() { // Sort metaballs in descending order from the viewpoint sort(metaballs.begin(), metaballs.end(), [](Metaball &a, Metaball &b) { - return distance(viewPos, a.pos) > distance(viewPos, b.pos); + return distance(camPos, a.pos) > distance(camPos, b.pos); }); glDisable(GL_DEPTH_TEST); @@ -252,13 +257,13 @@ void renderClouds() { // Place the billboard at the center of the corresponding metaball n. mat4 model = scale(translate(mat4(1), k.pos), vec3(k.r) * 2.f); // Rotate the billboard so that its normal is oriented to the viewpoint. - faceView(model); + model = faceView(model); 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; */ @@ -280,7 +285,8 @@ void renderClouds() { } void display() { - view = glm::lookAt(sunPos, viewPos, {0, 1, 0}); + // TODO: find a way to make sure there's no clipping + view = glm::lookAt(sunPos + sunDir * vec3(20), sunPos, {0, 1, 0}); proj = glm::ortho(1.f * aspect, -1.f * aspect, -1.f, 1.f, znear, zfar); setProjectionAndViewUniforms(bbProg); @@ -288,11 +294,11 @@ void display() { glClear(GL_COLOR_BUFFER_BIT); shadeClouds(); - view = glm::lookAt(viewPos, lookPos, {0, 1, 0}); - proj = glm::perspective(60.f, aspect, znear, zfar); + view = glm::lookAt(camPos, viewPos, {0, 1, 0}); + proj = glm::perspective(45.f, aspect, znear, zfar); setProjectionAndViewUniforms(bbProg); - glClearColor(0.73,1,1,1); // background color + glClearColor(0.83,1,1,1); // background color glClear(GL_COLOR_BUFFER_BIT); renderObject(); // render things that aren't clouds renderClouds(); @@ -300,10 +306,14 @@ void display() { glutSwapBuffers(); } +bool needsRedisplay = false; void timer(int _) { /* calculateMetaballs(); */ - /* glutPostRedisplay(); */ - /* glutTimerFunc(16, timer, 0); */ + if (needsRedisplay) { + glutPostRedisplay(); + needsRedisplay = false; + } + glutTimerFunc(16, timer, 0); } void keyboard(unsigned char key, int x, int y) { @@ -313,6 +323,26 @@ void keyboard(unsigned char key, int x, int y) { } } +int prevMouseX, prevMouseY; +bool firstMouse = true; +void motion(int x, int y) { + if (firstMouse) { + prevMouseX = x; + prevMouseY = y; + firstMouse = false; + } + float dx = x - prevMouseX, dy = y - prevMouseY; + prevMouseX = x; prevMouseY = y; + const vec3 origin(0,18,0); + const float sensitivity = 0.003f; + auto camMat = translate(mat4(1), origin + camPos); + auto rotation = rotate(rotate(mat4(1), -dx * sensitivity, {0, 1, 0}), + -dy * sensitivity, {1, 0, 0}); + auto rotAroundOrig = camMat * rotation * translate(mat4(1), origin - camPos); + camPos = rotAroundOrig * glm::vec4(camPos, 0); + needsRedisplay = true; +} + int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB | @@ -357,6 +387,7 @@ int main(int argc, char **argv) { glGenTextures(1, &attenuationTex); glutKeyboardFunc(keyboard); + glutMotionFunc(motion); glutTimerFunc(16, timer, 0); // set up billboard prog -- 2.30.2