#include "util.hpp"
#include "ik.hpp"
#include "blendshapes.hpp"
-#include "ui.h"
+#include "ui.hpp"
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Program *textureProg, *plainProg, *reflectProg, *pbrProg;
+ControlWindow controlWindow;
+
std::vector<Skybox> skyboxes;
int activeSkybox = 0;
float yaw = 1.57, pitch = 0;
Model *targetModel; // The model that the selection is happening on
-glm::vec3 closestVertex;
-std::vector<glm::vec3> manipulators;
-Blendshapes blendshapes;
-float *blendshapeWeights;
+Model::VertexLookup closestVertex;
+
+std::map<VertIdx, glm::vec3> manipulators;
+VertIdx curManipulator = {-1,-1};
+
+BlendshapeModel bsModel;
+bool playBlendshapeAnim = false;
struct Light {
glm::mat4 trans;
}
void highlightVertex() {
- drawBox(glm::translate(glm::mat4(1), closestVertex), {1, 1, 0.5});
+ drawBox(glm::translate(glm::mat4(1), closestVertex.pos), {1, 1, 0.5});
}
void display() {
if (curMode == Blendshapes) {
highlightVertex();
- for (auto v: manipulators)
- drawBox(glm::translate(glm::mat4(1), v), {0.2, 1, 0});
+ 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);
- blendshapes.model->draw(skyboxes[activeSkybox], d * 1000);
+ 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});
+ }
+
+ bsModel.model->draw(skyboxes[activeSkybox], d * 1000);
}
for (Light &light: lights) drawLight(light);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
}
-void weightsChanged(int blendshape, float weight) {
- blendshapeWeights[blendshape] = weight;
- std::vector<float> weights;
- weights.assign(blendshapeWeights, blendshapeWeights + blendshapes.deltas.size());
- interpolateBlendshapes(&blendshapes, weights);
-}
+bool needToCalculateClosestVertex = false;
+bool needToInterpolateBlendshapes = false;
-void loadBlendshapes() {
+class Delegate : public ControlWindowDelegate {
+ public:
- // get all the obj files
- std::vector<std::string> blends;
- const std::string modelDir = "models/high-res-blendshapes/";
- DIR *blendDir = opendir(modelDir.c_str());
- while (dirent *e = readdir(blendDir)) {
- if (e->d_type & DT_DIR) continue;
- const std::string name(e->d_name);
- if (name == "neutral.obj") continue;
- blends.push_back(name);
+ virtual void weightChanged(int blendshape, float weight) {
+ bsModel.blendshapes[blendshape].weight = weight;
+ needToInterpolateBlendshapes = true;
}
- closedir(blendDir);
- std::vector<std::string> blendFps;
- for (auto blend: blends) blendFps.push_back(modelDir + blend);
- createBlendshapes(blendFps, modelDir + "neutral.obj", *pbrProg, &blendshapes);
- targetModel = blendshapes.model;
+ virtual void solveWeights(std::vector<float> &newWeights) {
+ ::solveWeights(&bsModel, manipulators);
+ for (int i = 0; i < newWeights.size(); i++)
+ newWeights[i] = bsModel.blendshapes[i].weight;
+ needToInterpolateBlendshapes = true;
+ }
- size_t numBlends = blends.size();
- blendshapeWeights = new float[numBlends];
- for (int i = 0; i < numBlends; i++) blendshapeWeights[i] = 0;
- const char *names[numBlends];
- for (int i = 0; i < numBlends; i++) names[i] = blends[i].c_str();
- createControlWindow(numBlends, names, weightsChanged);
+ virtual void resetManipulators() {
+ manipulators.clear();
+ curManipulator = { -1, -1 };
+ }
- camPos = { 0, 22, 81 };
- camFront = { 0, 0, -1 };
- camUp = { 0, 1, 0 };
- zfar = 10000;
- znear = 0.1f;
+ virtual void playbackChanged(bool playing) {
+ playBlendshapeAnim = playing;
}
+};
+
+Delegate cwDelegate;
+
void init() {
initUtilProg();
}
if (curMode == Blendshapes) {
- loadBlendshapes();
+ loadBlendshapes("models/high-res-blendshapes/", *pbrProg, &bsModel);
+ targetModel = bsModel.model;
+
+ size_t numBlends = bsModel.blendshapes.size();
+ std::vector<std::string> names(numBlends);
+ for (int i = 0; i < numBlends; i++) names[i] = bsModel.blendshapes[i].name;
+ controlWindow = createControlWindow(names, &cwDelegate);
+
+ camPos = { 0, 22, 81 };
+ camFront = { 0, 0, -1 };
+ camUp = { 0, 1, 0 };
+ zfar = 10000;
+ znear = 0.1f;
}
glEnable(GL_DEPTH_TEST);
}
int mouseX, mouseY;
-bool needToCalculateClosestVertex = false;
/* #define ENABLE_MOVEMENT */
void timer(int _) {
camPos.z += zSpeed * sin(yaw) - xSpeed * cos(yaw);
#endif
+ if (curMode == Blendshapes) {
+ float xSpeed = 0, ySpeed = 0, zSpeed = 0;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wchar-subscripts"
+ if (keyStates['w'])
+ zSpeed = 0.1f;
+ if (keyStates['s'])
+ zSpeed = -0.1f;
+ if (keyStates['a'])
+ xSpeed = 0.1f;
+ if (keyStates['d'])
+ xSpeed = -0.1f;
+ if (keyStates['q'])
+ ySpeed = 0.1f;
+ if (keyStates['e'])
+ ySpeed = -0.1f;
+#pragma clang diagnostic pop
+
+ if (playBlendshapeAnim) {
+ stepBlendshapeAnim(&bsModel);
+ needToInterpolateBlendshapes = true;
+ std::vector<float> newWeights(bsModel.blendshapes.size());
+ for (int i = 0; i < bsModel.blendshapes.size(); i++)
+ newWeights[i] = bsModel.blendshapes[i].weight;
+ updateWeights(&controlWindow, newWeights);
+ }
+
+ if (curManipulator.first != -1 && curManipulator.second != -1) {
+ manipulators[curManipulator].x += xSpeed;
+ manipulators[curManipulator].y += ySpeed;
+ manipulators[curManipulator].z += zSpeed;
+ }
+
+ if (needToInterpolateBlendshapes) {
+ interpolateBlendshapes(&bsModel);
+ needToInterpolateBlendshapes = false;
+ }
+
if (needToCalculateClosestVertex) {
GLint vpArr[4]; glGetIntegerv(GL_VIEWPORT, vpArr);
glm::vec4 viewport(vpArr[0], vpArr[1], vpArr[2], vpArr[3]);
projMat(),
viewport);
- closestVertex = targetModel->closestVertex(targetModel->getRoot(), camPos, selectedPos).first;
+ closestVertex = targetModel->closestVertex(targetModel->getRoot(), camPos, selectedPos);
needToCalculateClosestVertex = false;
}
+ }
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
}
void mouse(int button, int state, int x, int y) {
- if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
- manipulators.push_back(closestVertex);
+ if (isPanelFocused(controlWindow))
+ return;
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
+ 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)