X-Git-Url: https://git.lukelau.me/?p=opengl.git;a=blobdiff_plain;f=main.cpp;h=7054e7a04905a2a636da53ce115233687661c3c1;hp=d1a35534b5ae67b3a25c78fba5d1025b3cb3cbe6;hb=b91a0d30ae6484b6c4d981aeafa8d4996c98effe;hpb=9886c33eb8cd31f28234585718410cd51aef2a4c diff --git a/main.cpp b/main.cpp index d1a3553..7054e7a 100644 --- a/main.cpp +++ b/main.cpp @@ -30,9 +30,10 @@ using namespace std; -GLuint lightVao; +GLuint lightVao, cursorVao; +GLuint cursorNumIndices; -Program *textureProg, *plainProg, *reflectProg, *pbrProg; +Program *textureProg, *plainProg, *reflectProg, *pbrProg, *cursorProg; ControlWindow controlWindow; @@ -48,6 +49,8 @@ float yaw = 1.57, pitch = 0; Model *targetModel; // The model that the selection is happening on Model::VertexLookup closestVertex; +// How close a vertex needs to be to the cursor before it is "over" +const float closestVertexThreshold = 0.5; std::map manipulators; VertIdx curManipulator = {-1,-1}; @@ -108,22 +111,22 @@ void setLightColorAndPos(GLuint progId, glm::vec3 lightPos, glm::vec4 lightColor glUniform3fv(viewPosLoc, 1, glm::value_ptr(camPos)); } -void drawBox(glm::mat4 trans, glm::vec3 color) { - glUseProgram(plainProg->progId); - glBindVertexArray(lightVao); - setProjectionAndViewUniforms(plainProg->progId); +void drawPlainProg(Program *p, GLuint vao, glm::mat4 trans, glm::vec3 color) { + glUseProgram(p->progId); + glBindVertexArray(vao); + setProjectionAndViewUniforms(p->progId); glm::mat4 model = glm::scale(trans, glm::vec3(0.3)); - GLuint modelLoc = glGetUniformLocation(plainProg->progId, "model"); + GLuint modelLoc = glGetUniformLocation(p->progId, "model"); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); - GLuint colorLoc = glGetUniformLocation(plainProg->progId, "color"); + GLuint colorLoc = glGetUniformLocation(p->progId, "color"); glUniform4fv(colorLoc, 1, glm::value_ptr(color)); glDrawArrays(GL_TRIANGLES, 0, 36); } void drawLight(Light &light) { - drawBox(light.trans, light.color); + drawPlainProg(plainProg, lightVao, light.trans, light.color); } int findNodeTrans(const struct aiNode *n, const struct aiString name, glm::mat4 *dest) { @@ -154,8 +157,18 @@ glm::mat4 worldSpaceToModelSpace(aiNode *node, glm::mat4 m) { return res; } -void highlightVertex() { - drawBox(glm::translate(glm::mat4(1), closestVertex.pos), {1, 1, 0.5}); +void drawCursor(glm::vec3 pos, glm::vec3 color, float scale = 1) { + glUseProgram(cursorProg->progId); + glBindVertexArray(cursorVao); + setProjectionAndViewUniforms(cursorProg->progId); + glm::mat4 model = glm::scale(glm::translate(glm::mat4(1), pos), glm::vec3(scale * 0.4)); + GLuint modelLoc = glGetUniformLocation(cursorProg->progId, "model"); + glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); + + GLuint colorLoc = glGetUniformLocation(cursorProg->progId, "color"); + glUniform4fv(colorLoc, 1, glm::value_ptr(color)); + + glDrawElements(GL_TRIANGLES, cursorNumIndices, GL_UNSIGNED_INT, 0); } void display() { @@ -214,17 +227,18 @@ void display() { sceneModel->draw(skyboxes[activeSkybox], d * 1000); if (curMode == Blendshapes) { - highlightVertex(); + if (closestVertex.distance < closestVertexThreshold) + drawCursor(closestVertex.pos, {0.5,0,1}, 0.9); for (auto v: manipulators) { glm::vec3 color = { 0.4, 1, 0 }; if (closestVertex.meshIdx == v.first.first && closestVertex.vertIdx == v.first.second) color = {1, 0, 0}; - drawBox(glm::translate(glm::mat4(1), v.second), color); + drawCursor(v.second, color); glm::vec3 origVertex = aiVector3DToVec3(bsModel.model->meshes[v.first.first].ai.mVertices[v.first.second]); - drawBox(glm::translate(glm::mat4(1), origVertex), {0,0,1}); + drawCursor(origVertex, {0,0,1}, 0.7); } bsModel.model->draw(skyboxes[activeSkybox], d * 1000); @@ -245,9 +259,8 @@ void display() { glutSwapBuffers(); } -void setupLightBuffers(GLuint progId) { - auto vertices = cube(); - GLuint verticesSize = 36 * 3 * sizeof(GLfloat); +void setupPlainBuffers(GLuint progId, std::vector vertices) { + GLuint verticesSize = vertices.size() * sizeof(glm::vec3); glGenVertexArrays(1, &lightVao); GLuint vbo; @@ -261,6 +274,31 @@ void setupLightBuffers(GLuint progId) { glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); } +GLuint setupBuffersWithIndices(GLuint progId, GLuint vao, + std::vector vertices, + std::vector indices) { + GLuint vbos[2]; + glBindVertexArray(vao); + glGenBuffers(2, vbos); + + int verticesSize = vertices.size() * sizeof(glm::vec3); + // positions + glBindBuffer(GL_ARRAY_BUFFER, vbos[0]); + glBufferData(GL_ARRAY_BUFFER, verticesSize, NULL, GL_STATIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, verticesSize, + glm::value_ptr(vertices[0])); + + GLuint posLoc = glGetAttribLocation(progId, "vPosition"); + glEnableVertexAttribArray(posLoc); + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); + + // indices + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW); + + return indices.size(); +} + bool needToCalculateClosestVertex = false; bool needToInterpolateBlendshapes = false; @@ -297,9 +335,15 @@ void init() { plainProg = new Program("plainvertex.glsl", "plainfrag.glsl"); glUseProgram(plainProg->progId); - setupLightBuffers(plainProg->progId); + setupPlainBuffers(plainProg->progId, cube()); plainProg->validate(); + cursorProg = new Program("plainvertex.glsl", "plainfrag.glsl"); + glUseProgram(cursorProg->progId); + glGenVertexArrays(1, &cursorVao); + cursorNumIndices = setupBuffersWithIndices(cursorProg->progId, cursorVao, sphere(), sphereIndices()); + cursorProg->validate(); + skyboxes.push_back(Skybox(Image("skyboxes/loft/Newport_Loft_Ref.hdr"))); skyboxes.push_back(Skybox(Image("skyboxes/wooden_lounge_8k.hdr"))); skyboxes.push_back(Skybox(Image("skyboxes/machine_shop_02_8k.hdr"))); @@ -360,7 +404,7 @@ void init() { for (int i = 0; i < numBlends; i++) names[i] = bsModel.blendshapes[i].name; controlWindow = createControlWindow(names, &cwDelegate); - camPos = { 0, 22, 81 }; + camPos = { 0, 18, 81 }; camFront = { 0, 0, -1 }; camUp = { 0, 1, 0 }; zfar = 10000; @@ -476,12 +520,40 @@ int prevMouseX, prevMouseY; bool firstMouse = true; void motion(int x, int y) { -#ifdef ENABLE_MOVEMENT if (firstMouse) { prevMouseX = x; prevMouseY = y; firstMouse = false; } + float dx = x - prevMouseX, dy = y - prevMouseY; + prevMouseX = x; prevMouseY = y; + if (curMode == Blendshapes) { + if (closestVertex.distance > closestVertexThreshold) { + const glm::vec3 origin(0,18,0); + const float sensitivity = 0.003f; + auto camMat = glm::translate(glm::mat4(1), origin + camPos); + auto rotation = glm::rotate(glm::rotate(glm::mat4(1), -dx * sensitivity, {0, 1, 0}), + -dy * sensitivity, {1, 0, 0}); + auto rotAroundOrig = camMat * rotation * glm::translate(glm::mat4(1), origin - camPos); + camPos = rotAroundOrig * glm::vec4(camPos, 0); + camFront = origin - camPos; // face center + } + needToCalculateClosestVertex = true; + } +} + +void passiveMotion(int x, int y) { + if (firstMouse) { + prevMouseX = x; + prevMouseY = y; + firstMouse = false; + } + mouseX = x; mouseY = y; + prevMouseX = x; + prevMouseY = y; +#ifdef ENABLE_MOVEMENT + + int dx = x - prevMouseX, dy = y - prevMouseY; prevMouseX = x; @@ -503,21 +575,22 @@ void motion(int x, int y) { camUp = glm::vec3(0, 1, 0); } #endif - - mouseX = x; mouseY = y; + if (curMode == Blendshapes) needToCalculateClosestVertex = true; - } void mouse(int button, int state, int x, int y) { if (isPanelFocused(controlWindow)) return; + if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { + if (closestVertex.distance < closestVertexThreshold) { VertIdx idx = { closestVertex.meshIdx, closestVertex.vertIdx }; if (manipulators.count(idx) <= 0) manipulators[idx] = closestVertex.pos; curManipulator = idx; } + } #ifdef ENABLE_MOVEMENT if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) @@ -547,7 +620,7 @@ int main(int argc, char** argv) { glutKeyboardUpFunc(keyboardUp); glutTimerFunc(16, timer, 0); glutMotionFunc(motion); - glutPassiveMotionFunc(motion); + glutPassiveMotionFunc(passiveMotion); glutMouseFunc(mouse); glutMainLoop();