using namespace std;
-GLuint lightVao;
+GLuint lightVao, cursorVao;
+GLuint cursorNumIndices;
-Program *textureProg, *plainProg, *reflectProg, *pbrProg;
+Program *textureProg, *plainProg, *reflectProg, *pbrProg, *cursorProg;
ControlWindow controlWindow;
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<VertIdx, glm::vec3> manipulators;
VertIdx curManipulator = {-1,-1};
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) {
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() {
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);
glutSwapBuffers();
}
-void setupLightBuffers(GLuint progId) {
- auto vertices = cube();
- GLuint verticesSize = 36 * 3 * sizeof(GLfloat);
+void setupPlainBuffers(GLuint progId, std::vector<glm::vec3> vertices) {
+ GLuint verticesSize = vertices.size() * sizeof(glm::vec3);
glGenVertexArrays(1, &lightVao);
GLuint vbo;
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
}
+GLuint setupBuffersWithIndices(GLuint progId, GLuint vao,
+ std::vector<glm::vec3> vertices,
+ std::vector<GLuint> 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;
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")));
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;
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;
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)
glutKeyboardUpFunc(keyboardUp);
glutTimerFunc(16, timer, 0);
glutMotionFunc(motion);
- glutPassiveMotionFunc(motion);
+ glutPassiveMotionFunc(passiveMotion);
glutMouseFunc(mouse);
glutMainLoop();