Do boning and animation properly
authorLuke Lau <luke_lau@icloud.com>
Tue, 11 Feb 2020 12:25:29 +0000 (12:25 +0000)
committerLuke Lau <luke_lau@icloud.com>
Tue, 11 Feb 2020 12:25:29 +0000 (12:25 +0000)
14 files changed:
Makefile
main.cpp
material.cpp
model.cpp
model.hpp
models/cowedboy.blend
models/ik.blend
models/ik.glb
pbrvert.glsl
program.cpp
shapes.hpp
skybox.cpp
util.cpp [new file with mode: 0644]
util.hpp [new file with mode: 0644]

index 27cdf319928646882668dfb9e83ef65393ddac7f..5d9c00cec357e965db26d68d324078120b135f3b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ all: bin/main
 
 CXX_FLAGS := -g --std=c++17 -Wall
 
 
 CXX_FLAGS := -g --std=c++17 -Wall
 
-bin/main: model.o material.o image.o skybox.o program.o main.o
+bin/main: model.o material.o image.o skybox.o program.o main.o util.o
        clang++ $(CXX_FLAGS) $^ \
                -I/usr/local/include -L/usr/local/lib \
                -lassimp \
        clang++ $(CXX_FLAGS) $^ \
                -I/usr/local/include -L/usr/local/lib \
                -lassimp \
index aa78a224281b54efff84c3012daaa587b6add1fb..15599b078cd64aa72465777a7dbf71659fb84005 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -20,6 +20,7 @@
 #include "program.hpp"
 #include "skybox.hpp"
 #include "image.hpp"
 #include "program.hpp"
 #include "skybox.hpp"
 #include "image.hpp"
+#include "util.hpp"
 
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
 
 
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
 
@@ -115,6 +116,9 @@ void display() {
 
        float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f;
 
 
        float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f;
 
+       glUseProgram(getUtilProg()->progId);
+       setProjectionAndViewUniforms(getUtilProg()->progId);
+
        glUseProgram(pbrProg->progId);
        setProjectionAndViewUniforms(pbrProg->progId);
 
        glUseProgram(pbrProg->progId);
        setProjectionAndViewUniforms(pbrProg->progId);
 
@@ -144,7 +148,8 @@ void display() {
        glUniform3fv(glGetUniformLocation(pbrProg->progId, "lightPositions"), 6, glm::value_ptr(lightPositions[0]));
        glUniform3fv(glGetUniformLocation(pbrProg->progId, "lightColors"), 6, glm::value_ptr(lightColors[0]));
 
        glUniform3fv(glGetUniformLocation(pbrProg->progId, "lightPositions"), 6, glm::value_ptr(lightPositions[0]));
        glUniform3fv(glGetUniformLocation(pbrProg->progId, "lightColors"), 6, glm::value_ptr(lightColors[0]));
 
-       /* pbr->getRoot()->model = glm::rotate(glm::mat4(1.f), glm::radians(d * 10), glm::vec3(0, 1, 0)); */
+       /* sceneModel->find("Top Bone")->transform = glm::rotate(glm::mat4(1), d / 5.f, { 1, 0, 0}); */
+       /* sceneModel->find("Bottom Bone")->transform = glm::rotate(glm::mat4(1), d / 3.f, { 1, 0, 0}); */
        sceneModel->draw(skyboxes[activeSkybox], d * 1000);
 
        for (Light &light: lights) drawLight(light);
        sceneModel->draw(skyboxes[activeSkybox], d * 1000);
 
        for (Light &light: lights) drawLight(light);
@@ -193,6 +198,8 @@ int findNodeTrans(struct aiNode *n, const struct aiString name, glm::mat4 *dest)
 }
 
 void init() {
 }
 
 void init() {
+       initUtilProg();
+
        plainProg = new Program("plainvertex.glsl", "plainfrag.glsl");
        glUseProgram(plainProg->progId);
        setupLightBuffers(plainProg->progId);
        plainProg = new Program("plainvertex.glsl", "plainfrag.glsl");
        glUseProgram(plainProg->progId);
        setupLightBuffers(plainProg->progId);
@@ -257,7 +264,10 @@ void keyboardUp(unsigned char key, int x, int y) {
        keyStates[key] = false;
 }
 
        keyStates[key] = false;
 }
 
+#define ENABLE_MOVEMENT
+
 void timer(int _) {
 void timer(int _) {
+#ifdef ENABLE_MOVEMENT
        float xSpeed = 0.f, ySpeed = 0.f, zSpeed = 0.f;
        if (keyStates['w'])
                zSpeed = 0.1f;
        float xSpeed = 0.f, ySpeed = 0.f, zSpeed = 0.f;
        if (keyStates['w'])
                zSpeed = 0.1f;
@@ -282,6 +292,7 @@ void timer(int _) {
        camPos.x += xSpeed * sin(yaw) + zSpeed * cos(yaw);
        camPos.y += ySpeed;
        camPos.z += zSpeed * sin(yaw) - xSpeed * cos(yaw);
        camPos.x += xSpeed * sin(yaw) + zSpeed * cos(yaw);
        camPos.y += ySpeed;
        camPos.z += zSpeed * sin(yaw) - xSpeed * cos(yaw);
+#endif
        glutPostRedisplay();
        glutTimerFunc(16, timer, 0);
 }
        glutPostRedisplay();
        glutTimerFunc(16, timer, 0);
 }
@@ -290,6 +301,7 @@ int prevMouseX, prevMouseY;
 bool firstMouse = true;
 
 void motion(int x, int y) {
 bool firstMouse = true;
 
 void motion(int x, int y) {
+#ifdef ENABLE_MOVEMENT
        if (firstMouse) {
                prevMouseX = x;
                prevMouseY = y;
        if (firstMouse) {
                prevMouseX = x;
                prevMouseY = y;
@@ -315,6 +327,7 @@ void motion(int x, int y) {
        } else {
                camUp = glm::vec3(0, 1, 0);
        }
        } else {
                camUp = glm::vec3(0, 1, 0);
        }
+#endif
 }
 
 void mouse(int button, int state, int x, int y) {
 }
 
 void mouse(int button, int state, int x, int y) {
index e1fb5c3a391605fe4c118db74b594cb39358b0d3..838f6736d637e2a8792959932afcfceab32acd9c 100644 (file)
@@ -54,38 +54,38 @@ Material::Texture::Texture(const aiString fileName, const aiScene &scene) {
 
 void Material::bind() const {
        if (ambientOcclusion != nullptr) {
 
 void Material::bind() const {
        if (ambientOcclusion != nullptr) {
-               glUniform1i(glGetUniformLocation(progId, "material.albedoMap"), 0);
+               glUniform1i(glGetUniformLocation(progId, "mat.albedoMap"), 0);
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, albedo->texId);
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, albedo->texId);
-               glUniform1i(glGetUniformLocation(progId, "material.hasAlbedo"), 1);
+               glUniform1i(glGetUniformLocation(progId, "mat.hasAlbedo"), 1);
        } else {
        } else {
-               glUniform1i(glGetUniformLocation(progId, "material.hasAlbedo"), 0);
+               glUniform1i(glGetUniformLocation(progId, "mat.hasAlbedo"), 0);
        }
 
        if (normal != nullptr) {
        }
 
        if (normal != nullptr) {
-               glUniform1i(glGetUniformLocation(progId, "material.normalMap"), 1);
+               glUniform1i(glGetUniformLocation(progId, "mat.normalMap"), 1);
                glActiveTexture(GL_TEXTURE1);
                glBindTexture(GL_TEXTURE_2D, normal->texId);
                glActiveTexture(GL_TEXTURE1);
                glBindTexture(GL_TEXTURE_2D, normal->texId);
-               glUniform1i(glGetUniformLocation(progId, "material.hasNormal"), 1);
+               glUniform1i(glGetUniformLocation(progId, "mat.hasNormal"), 1);
        } else {
        } else {
-               glUniform1i(glGetUniformLocation(progId, "material.hasNormal"), 0);
+               glUniform1i(glGetUniformLocation(progId, "mat.hasNormal"), 0);
        }
 
        if (metallicRoughness != nullptr) {
                glUniform1i(glGetUniformLocation(progId, "metallicRoughnessMap"), 2);
                glActiveTexture(GL_TEXTURE2);
                glBindTexture(GL_TEXTURE_2D, metallicRoughness->texId);
        }
 
        if (metallicRoughness != nullptr) {
                glUniform1i(glGetUniformLocation(progId, "metallicRoughnessMap"), 2);
                glActiveTexture(GL_TEXTURE2);
                glBindTexture(GL_TEXTURE_2D, metallicRoughness->texId);
-               glUniform1i(glGetUniformLocation(progId, "material.hasMetallicRoughness"), 1);
+               glUniform1i(glGetUniformLocation(progId, "mat.hasMetallicRoughness"), 1);
        } else {
        } else {
-               glUniform1i(glGetUniformLocation(progId, "material.hasMetallicRoughness"), 0);
+               glUniform1i(glGetUniformLocation(progId, "mat.hasMetallicRoughness"), 0);
        }
 
        if (ambientOcclusion != nullptr) {
                glUniform1i(glGetUniformLocation(progId, "aoMap"), 3);
                glActiveTexture(GL_TEXTURE3);
                glBindTexture(GL_TEXTURE_2D, ambientOcclusion->texId);
        }
 
        if (ambientOcclusion != nullptr) {
                glUniform1i(glGetUniformLocation(progId, "aoMap"), 3);
                glActiveTexture(GL_TEXTURE3);
                glBindTexture(GL_TEXTURE_2D, ambientOcclusion->texId);
-               glUniform1i(glGetUniformLocation(progId, "material.hasAo"), 1);
+               glUniform1i(glGetUniformLocation(progId, "mat.hasAo"), 1);
        } else {
        } else {
-               glUniform1i(glGetUniformLocation(progId, "material.hasAo"), 0);
+               glUniform1i(glGetUniformLocation(progId, "mat.hasAo"), 0);
        }
 }
        }
 }
index 3c1ecf4830c2ce95989a09bfb4935cfb7d21d767..5302df06238038d32a686e8bffb2c62881f19a91 100644 (file)
--- a/model.cpp
+++ b/model.cpp
@@ -2,6 +2,7 @@
 #include <iostream>
 #include <assimp/quaternion.h>
 #include <glm/gtc/type_ptr.hpp>
 #include <iostream>
 #include <assimp/quaternion.h>
 #include <glm/gtc/type_ptr.hpp>
+#include "util.hpp"
 
 
 Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) {
 
 
 Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) {
@@ -19,7 +20,7 @@ Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) {
                        normals.push_back(glm::vec3(v.x, v.y, v.z));
                } else {
                        std::cerr << "Missing normals" << std::endl;
                        normals.push_back(glm::vec3(v.x, v.y, v.z));
                } else {
                        std::cerr << "Missing normals" << std::endl;
-                       exit(1);
+                       abort();
                }
                // check for texture coord set 0
                if (aiMesh->HasTextureCoords(0)) {
                }
                // check for texture coord set 0
                if (aiMesh->HasTextureCoords(0)) {
@@ -81,12 +82,13 @@ Model::Mesh::Mesh(const aiMesh *aiMesh, GLuint progId) {
        for (unsigned int i = 0; i < aiMesh->mNumBones; i++) {
                aiBone *aiBone = aiMesh->mBones[i];
 
        for (unsigned int i = 0; i < aiMesh->mNumBones; i++) {
                aiBone *aiBone = aiMesh->mBones[i];
 
-               boneMap[std::string(aiBone->mName.C_Str())] = std::pair(i + 1, aiMatrixToMat4(aiBone->mOffsetMatrix));
+               boneMap[std::string(aiBone->mName.C_Str())] = std::pair(i + 1, aiBone);
 
                for (int j = 0; j < aiBone->mNumWeights; j++) {
                        aiVertexWeight vw = aiBone->mWeights[j];
 
 
                for (int j = 0; j < aiBone->mNumWeights; j++) {
                        aiVertexWeight vw = aiBone->mWeights[j];
 
-                       if (!boneWeightMap.count(vw.mVertexId)) boneWeightMap[vw.mVertexId] = std::vector<std::pair<unsigned int, float>>();
+                       if (!boneWeightMap.count(vw.mVertexId))
+                               boneWeightMap[vw.mVertexId] = std::vector<std::pair<unsigned int, float>>();
                        boneWeightMap[vw.mVertexId].push_back(std::pair(i + 1, vw.mWeight));
                }
        }
                        boneWeightMap[vw.mVertexId].push_back(std::pair(i + 1, vw.mWeight));
                }
        }
@@ -202,33 +204,39 @@ glm::mat4 lerpScaling(const aiNodeAnim *anim, const float tick) {
        return aiMatrixToMat4(result);
 }
 
        return aiMatrixToMat4(result);
 }
 
-void Model::Node::draw(        const std::vector<Mesh> &meshes,
-                                               const std::vector<Material> &materials,
-                                               const Skybox skybox,
-                                               const float tick,
-                                               glm::mat4 parentTrans = glm::mat4(1),
-                                               BoneTransforms boneTransforms = BoneTransforms()) const {
-
-       GLuint modelLoc = glGetUniformLocation(progId, "model");
-
-       glm::mat4 animTrans(1.f);
+glm::mat4 Model::Node::totalTrans(const glm::mat4 parentTrans, const float tick) const {
+       glm::mat4 aiTrans = aiMatrixToMat4(ai.mTransformation);
        if (animMap->count(std::string(ai.mName.C_Str()))) {
                for (const Animation anim: animMap->at(std::string(ai.mName.C_Str()))) {
        if (animMap->count(std::string(ai.mName.C_Str()))) {
                for (const Animation anim: animMap->at(std::string(ai.mName.C_Str()))) {
+                       // animations are *absolute*
+                       // they replace aiNode.mTransformation!!
+                       aiTrans = glm::mat4(1);
                        float t = fmod(tick, anim.duration);
                        for (const aiNodeAnim *nodeAnim: anim.nodeAnims) {
                        float t = fmod(tick, anim.duration);
                        for (const aiNodeAnim *nodeAnim: anim.nodeAnims) {
-                               animTrans *= lerpPosition(nodeAnim, t);
-                               animTrans *= lerpRotation(nodeAnim, t);
-                               animTrans *= lerpScaling(nodeAnim, t);
+                               aiTrans *= lerpPosition(nodeAnim, t);
+                               aiTrans *= lerpRotation(nodeAnim, t);
+                               aiTrans *= lerpScaling(nodeAnim, t);
+                       }
                }
        }
                }
        }
+
+       glm::mat4 m = parentTrans * aiTrans * transform;
+       return m;
 }
 
 }
 
+void Model::Node::draw(        const std::vector<Mesh> &meshes,
+                                               const std::vector<Material> &materials,
+                                               const Skybox skybox,
+                                               const float tick,
+                                               const BoneTransforms &boneTransforms,
+                                               glm::mat4 parentTrans = glm::mat4(1)) const {
 
 
-       glm::mat4 m = parentTrans * animTrans * aiMatrixToMat4(ai.mTransformation);
+       GLuint modelLoc = glGetUniformLocation(progId, "model");
+       glm::mat4 m = totalTrans(parentTrans, tick);
 
 
-       /* for (auto child: children) { */
-       /*      boneTransforms[std::string(ai.mName.C_Str())] = m; */
-       /* } */
+#ifdef DEBUG_NODES
+       drawDebugNode(m);
+#endif
 
        for (unsigned int i: meshIndices) {
                const Mesh &mesh = meshes[i];
 
        for (unsigned int i: meshIndices) {
                const Mesh &mesh = meshes[i];
@@ -238,35 +246,23 @@ void Model::Node::draw(   const std::vector<Mesh> &meshes,
                std::vector<glm::mat4> idBones(17, glm::mat4(1.f));
                glUniformMatrix4fv(glGetUniformLocation(progId, "bones"), 17, GL_FALSE, glm::value_ptr(idBones[0]));
 
                std::vector<glm::mat4> idBones(17, glm::mat4(1.f));
                glUniformMatrix4fv(glGetUniformLocation(progId, "bones"), 17, GL_FALSE, glm::value_ptr(idBones[0]));
 
-               for (std::pair<std::string, std::pair<unsigned int, glm::mat4>> pair: mesh.boneMap) {
-
-                       std::string nodeName = pair.first;
+               // bonemap: map from bone nodes to bone ids and aiBones
+               for (auto pair: mesh.boneMap) {
 
 
-                       if (animMap->count(nodeName) <= 0) break;
+                       std::string boneName = pair.first;
 
                        unsigned int boneId = pair.second.first;
 
                        unsigned int boneId = pair.second.first;
+                       aiBone *bone = pair.second.second;
                        // This is actually an inverse-bind matrix
                        // This is actually an inverse-bind matrix
-                       // i.e. position of the mesh in bone space
+                       // i.e. transforms bone space -> mesh space
                        // so no need to inverse again!
                        // https://github.com/assimp/assimp/pull/1803/files
                        // so no need to inverse again!
                        // https://github.com/assimp/assimp/pull/1803/files
-                       glm::mat4 boneOffset = pair.second.second;
-
-                       glm::mat4 boneTrans(1.f);
-                       /* if (boneTransforms.count(nodeName)) { */
-                       /*      std::cerr << "got bone transform from map" << std::endl; */
-                       /*      boneTrans = boneTransforms[nodeName]; */
-                       /* } */
-                       for (const Animation anim: animMap->at(nodeName)) {
-                               float t = fmod(tick, anim.duration);
-                               for (const aiNodeAnim *nodeAnim: anim.nodeAnims) {
-                                       boneTrans = boneTrans * lerpPosition(nodeAnim, t);
-                                       boneTrans = boneTrans * lerpRotation(nodeAnim, t);
-                                       boneTrans = boneTrans * lerpScaling(nodeAnim, t);
-                               }
-                       }
+                       glm::mat4 boneOffset = aiMatrixToMat4(bone->mOffsetMatrix);
 
 
-                       boneTrans = boneTrans * boneOffset;
+                       if (!boneTransforms.count(boneName)) abort();
+                       glm::mat4 boneTrans = boneTransforms.at(boneName);
 
 
+                       boneTrans = boneTrans * boneOffset;
 
                        std::string boneLocStr = "bones[" + std::to_string(boneId) + "]";
                        GLuint boneLoc = glGetUniformLocation(progId, boneLocStr.c_str());
 
                        std::string boneLocStr = "bones[" + std::to_string(boneId) + "]";
                        GLuint boneLoc = glGetUniformLocation(progId, boneLocStr.c_str());
@@ -292,7 +288,23 @@ void Model::Node::draw(    const std::vector<Mesh> &meshes,
 
                glDrawElements(GL_TRIANGLES, mesh.numIndices, GL_UNSIGNED_INT, 0);
        }
 
                glDrawElements(GL_TRIANGLES, mesh.numIndices, GL_UNSIGNED_INT, 0);
        }
-       for (Node *child: children) child->draw(meshes, materials, skybox, tick, m, boneTransforms);
+       for (Node *child: children) child->draw(meshes, materials, skybox, tick, boneTransforms, m);
+}
+
+void printMatrix4x4(aiMatrix4x4 m) {
+       fprintf(stderr, "%f, %f, %f, %f\n", m.a1, m.a2, m.a3, m.a4);
+       fprintf(stderr, "%f, %f, %f, %f\n", m.b1, m.b2, m.b3, m.b4);
+       fprintf(stderr, "%f, %f, %f, %f\n", m.c1, m.c2, m.c3, m.c4);
+       fprintf(stderr, "%f, %f, %f, %f\n", m.d1, m.d2, m.d3, m.d4);
+}
+
+void printHierarchy(aiNode *n, int indent = 0) {
+       for (int i = 0; i < indent; i++)
+               fprintf(stderr, "\t");
+       fprintf(stderr,"%s\n", n->mName.C_Str());
+       printMatrix4x4(n->mTransformation);
+       for (int i = 0; i < n->mNumChildren; i++)
+               printHierarchy(n->mChildren[i], indent + 1);
 }
 
 Model::Model(const aiScene *scene, Program p): program(p) {
 }
 
 Model::Model(const aiScene *scene, Program p): program(p) {
@@ -303,13 +315,11 @@ Model::Model(const aiScene *scene, Program p): program(p) {
                meshes.push_back(Mesh(mesh, p.progId));
        }
 
                meshes.push_back(Mesh(mesh, p.progId));
        }
 
-       // TODO: handle default material inserted at the end by assimp
        for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
                const aiMaterial &material = *scene->mMaterials[i];
                materials.push_back(Material(material, *scene, p.progId));
        }
 
        for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
                const aiMaterial &material = *scene->mMaterials[i];
                materials.push_back(Material(material, *scene, p.progId));
        }
 
-       AnimMap *animMap = new AnimMap();
        for (int i = 0; i < scene->mNumAnimations; i++) {
                const aiAnimation *aiAnim = scene->mAnimations[i];
 
        for (int i = 0; i < scene->mNumAnimations; i++) {
                const aiAnimation *aiAnim = scene->mAnimations[i];
 
@@ -327,44 +337,49 @@ Model::Model(const aiScene *scene, Program p): program(p) {
                for (std::pair<std::string, std::vector<const aiNodeAnim*>> pair: nodeAnims) {
                        std::string nodeName = pair.first;
 
                for (std::pair<std::string, std::vector<const aiNodeAnim*>> pair: nodeAnims) {
                        std::string nodeName = pair.first;
 
-                       if (!animMap->count(nodeName)) (*animMap)[nodeName] = std::vector<const Animation>();
-                       (*animMap)[nodeName].push_back({ aiAnim->mDuration, pair.second });
+                       if (!animMap.count(nodeName)) animMap[nodeName] = std::vector<const Animation>();
+                       animMap[nodeName].push_back({ aiAnim->mDuration, pair.second });
                }
        }
 
                }
        }
 
-       root = new Node(*(scene->mRootNode), p.progId, animMap);
+       root = new Node(*(scene->mRootNode), p.progId, &animMap);
 }
 
 }
 
-/* void Model::calcBoneTransforms(aiNode &node, glm::mat4 parentTrans = glm::mat4(1), BoneTransforms boneTrans = BoneTransforms()) { */
-/*     glm::mat4 animTrans(1.f); */
-/*     if (animMap->count(std::string(ai.mName.C_Str()))) { */
-/*             for (const Animation anim: animMap->at(std::string(ai.mName.C_Str()))) { */
-/*                     float t = fmod(tick, anim.duration); */
-/*                     for (const aiNodeAnim *nodeAnim: anim.nodeAnims) { */
-/*                             animTrans *= lerpPosition(nodeAnim, t); */
-/*                             animTrans *= lerpRotation(nodeAnim, t); */
-/*                             animTrans *= lerpScaling(nodeAnim, t); */
-/*                     } */
-/*             } */
-/*     } */
 
 
+std::map<std::string, glm::mat4> Model::calcBoneTransforms(const Node &n, const float tick, const std::set<std::string> bones, const glm::mat4 parentTrans = glm::mat4(1)) const {
+       std::string name = std::string(n.ai.mName.C_Str());
 
 
-/*     glm::mat4 m = parentTrans * animTrans * aiMatrixToMat4(ai.mTransformation) * model; */
-/* } */
+       glm::mat4 m = n.totalTrans(parentTrans, tick);
+
+       BoneTransforms res;
+       if (bones.count(name) > 0)
+               res[std::string(n.ai.mName.C_Str())] = m; // take part in hierarchy
+       else
+               m = glm::mat4(1); // ignore this node transformation
+       for (const auto child: n.getChildren())
+               res.merge(calcBoneTransforms(*child, tick, bones, m));
+       return res;
+}
 
 void Model::draw(Skybox skybox, const float tick) const {
        glUseProgram(program.progId);
 
 
 void Model::draw(Skybox skybox, const float tick) const {
        glUseProgram(program.progId);
 
+       std::set<std::string> bones;
+       for (auto m: this->meshes) {
+               for (auto b: m.boneMap) {
+                       bones.insert(b.first);
+               }
+       }
+       auto boneTransforms = calcBoneTransforms(*root, tick, bones);
 
 
-
-       root->draw(meshes, materials, skybox, tick);
+       root->draw(meshes, materials, skybox, tick, boneTransforms);
 }
 
 }
 
-Model::Node* Model::find(const std::string &name) {
+Model::Node* Model::find(const std::string &name) const {
        return find(aiString(name));
 }
 
        return find(aiString(name));
 }
 
-Model::Node* Model::find(const aiString name) {
+Model::Node* Model::find(const aiString name) const {
        const aiNode *node = root->ai.FindNode(name);
        Model::Node* res = root->findNode(*node);
        return res;
        const aiNode *node = root->ai.FindNode(name);
        Model::Node* res = root->findNode(*node);
        return res;
index 92aab0dd21cb80cb95791f475819522ee0b58056..bf6f08f346133920d792870d6a0f42249fe5e0cd 100644 (file)
--- a/model.hpp
+++ b/model.hpp
@@ -1,5 +1,6 @@
 #include <vector>
 #include <map>
 #include <vector>
 #include <map>
+#include <set>
 #ifdef __APPLE__
 #include <GL/glew.h>
 #else
 #ifdef __APPLE__
 #include <GL/glew.h>
 #else
@@ -26,7 +27,7 @@ class Model {
                std::vector<const aiNodeAnim*> nodeAnims;
        };
 
                std::vector<const aiNodeAnim*> nodeAnims;
        };
 
-       typedef std::map<std::string, std::pair<unsigned int, glm::mat4>> BoneMap;
+       typedef std::map<std::string, std::pair<unsigned int, aiBone*>> BoneMap;
        typedef std::map<std::string, std::vector<const Animation>> AnimMap;
        typedef std::map<std::string, glm::mat4> BoneTransforms;
 
        typedef std::map<std::string, std::vector<const Animation>> AnimMap;
        typedef std::map<std::string, glm::mat4> BoneTransforms;
 
@@ -49,11 +50,16 @@ class Model {
                class Node {
                        public:
                                Node(const aiNode &aiNode, GLuint progId, AnimMap *animMap);
                class Node {
                        public:
                                Node(const aiNode &aiNode, GLuint progId, AnimMap *animMap);
-                               void draw(const std::vector<Mesh> &meshes, const std::vector<Material> &materials, const Skybox s, const float tick, glm::mat4 parentModel, BoneTransforms boneTransforms) const;
+                               void draw(const std::vector<Mesh> &meshes, const std::vector<Material> &materials, const Skybox s, const float tick, const BoneTransforms &boneTransforms, glm::mat4 parentModel) const;
                                const std::vector<Node*> &getChildren() const { return children; }
                                Node* findNode(const aiNode &aiNode);
                                const aiNode &ai;
 
                                const std::vector<Node*> &getChildren() const { return children; }
                                Node* findNode(const aiNode &aiNode);
                                const aiNode &ai;
 
+                               // an extra transform
+                               glm::mat4 transform = glm::mat4(1);
+                               
+                               glm::mat4 totalTrans(const glm::mat4 parentTrans, const float tick) const;
+
                        private:
                                const GLuint progId;
 
                        private:
                                const GLuint progId;
 
@@ -63,8 +69,8 @@ class Model {
                };
                
                Node* getRoot() { return root; }
                };
                
                Node* getRoot() { return root; }
-               Node* find(const aiString name);
-               Node* find(const std::string &name);
+               Node* find(const aiString name) const;
+               Node* find(const std::string &name) const;
        
        private:
                const Program program;
        
        private:
                const Program program;
@@ -74,5 +80,8 @@ class Model {
 
                std::vector<Material> materials;
 
 
                std::vector<Material> materials;
 
+               AnimMap animMap;
+
+               BoneTransforms calcBoneTransforms(const Node &n, const float tick, const std::set<std::string> bones, const glm::mat4 parentTrans) const;
                void loadModel(const std::string &path);
 };
                void loadModel(const std::string &path);
 };
index 1d916c0c6cb1788fb23bc5219b216b00432c20e5..5fe3aa3ffeeb3ec073e91486cd1f7dfbee185225 100644 (file)
Binary files a/models/cowedboy.blend and b/models/cowedboy.blend differ
index 03af46d7cbcf149863da7a73a1e56884b8c0503d..9aad7693b19481bd1003774d4e655c95839bc939 100644 (file)
Binary files a/models/ik.blend and b/models/ik.blend differ
index b992585d31be32c0e111f841db5376c384b08aa9..33539b76e0a376f055a6fb48e02263ca95c94c38 100644 (file)
Binary files a/models/ik.glb and b/models/ik.glb differ
index 775cebfb0f411c04aa80c10f195e1e31cad1308b..57633800ad4402dd2f4a5c6c55377f51a4c9a82c 100644 (file)
@@ -25,7 +25,7 @@ void main() {
        boneTrans += bones[boneIds.z] * boneWeights.z;
        boneTrans += bones[boneIds.w] * boneWeights.w;
 
        boneTrans += bones[boneIds.z] * boneWeights.z;
        boneTrans += bones[boneIds.w] * boneWeights.w;
 
-       mat4 bonedModel = boneTrans * model;
+       mat4 bonedModel = model * boneTrans;
 
        worldPos = vec3(bonedModel * vec4(pos, 1.f));
 
 
        worldPos = vec3(bonedModel * vec4(pos, 1.f));
 
index 74744fd0c5b76c1e8142318e3705a80188f0aa9c..2275dcb416bed7740725f0a170a7a16610f795a1 100644 (file)
@@ -26,7 +26,7 @@ void attachShader(GLuint progId, string filePath, GLenum type) {
        if (!success) {
                GLchar log[1024];
                glGetShaderInfoLog(shader, 1024, NULL, log);
        if (!success) {
                GLchar log[1024];
                glGetShaderInfoLog(shader, 1024, NULL, log);
-               fprintf(stderr, "error: %s\n%s\n", filePath.c_str(), log);
+               fprintf(stderr, "Error compiling %s\n%s\n", filePath.c_str(), log);
                exit(1);
        }
        glAttachShader(progId, shader);
                exit(1);
        }
        glAttachShader(progId, shader);
@@ -57,7 +57,7 @@ void Program::validate() const {
        if (!success) {
                GLchar log[1024];
                glGetProgramInfoLog(progId, sizeof(log), NULL, log);
        if (!success) {
                GLchar log[1024];
                glGetProgramInfoLog(progId, sizeof(log), NULL, log);
-               fprintf(stderr, "error: %s\n", log);
+               fprintf(stderr, "Error validating: %s\n", log);
                exit(1);
        }
 }
                exit(1);
        }
 }
index 63263b52c40f7470fbacd8d536d2832d57760098..a1a42ebc43800efb299310b88e5fd3bf258b726e 100644 (file)
@@ -86,3 +86,28 @@ constexpr array<glm::vec3, 36> cube() {
 
        return vertices;
 }
 
        return vertices;
 }
+
+constexpr glm::vec3 pyramid[18] = {
+       glm::vec3(0.0f, 1.0f, 0.0f),
+       glm::vec3(1.0f, -1.0f, -1.0f),
+       glm::vec3(-1.0f, -1.0f, -1.0f),
+
+       glm::vec3(0.0f, 1.0f, 0.0f),
+       glm::vec3(-1.0f, -1.0f, 1.0f),
+       glm::vec3(1.0f, -1.0f, 1.0f),
+
+       glm::vec3(0.0f, 1.0f, 0.0f),
+       glm::vec3(-1.0f, -1.0f, -1.0f),
+       glm::vec3(-1.0f, -1.0f, 1.0f),
+
+       glm::vec3(0.0f, 1.0f, 0.0f),
+       glm::vec3(1.0f, -1.0f, 1.0f),
+       glm::vec3(1.0f, -1.0f, -1.0f),
+
+       glm::vec3(1, -1, 1),
+       glm::vec3(-1, -1, 1),
+       glm::vec3(-1, -1, -1),
+       glm::vec3(-1, -1, -1),
+       glm::vec3(1, -1, -1),
+       glm::vec3(1, -1, 1)
+};
index c0a9ff63e75c539ef3eb62108c3325beeeff6c13..83f130855fa668919ea9ca938230a117bb839e5f 100644 (file)
@@ -207,8 +207,6 @@ void Skybox::draw(glm::mat4 proj, glm::mat4 view) const {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexId);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexId);
        glDrawArrays(GL_TRIANGLES, 0, 36);
-
-       if (glGetError()) exit(1);
 }
 
 template <std::size_t N>
 }
 
 template <std::size_t N>
diff --git a/util.cpp b/util.cpp
new file mode 100644 (file)
index 0000000..796017d
--- /dev/null
+++ b/util.cpp
@@ -0,0 +1,47 @@
+#include <GL/glew.h>
+#include <glm/ext.hpp>
+#include "shapes.hpp"
+#include "util.hpp"
+
+GLuint utilVao;
+Program *utilProg;
+
+Program *getUtilProg() { return utilProg; }
+
+void initUtilProg() {
+       utilProg = new Program("plainvertex.glsl", "plainfrag.glsl");
+
+       glGenVertexArrays(1, &utilVao);
+       GLuint vbo;
+       glBindVertexArray(utilVao);
+       glGenBuffers(1, &vbo);
+       glBindBuffer(GL_ARRAY_BUFFER, vbo);
+       glBufferData(GL_ARRAY_BUFFER, sizeof(pyramid), pyramid, GL_STATIC_DRAW);
+       GLuint posLoc = glGetAttribLocation(utilProg->progId, "vPosition");
+       glEnableVertexAttribArray(posLoc);
+       glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+       if (glGetError()) abort();
+}
+
+void drawDebugNode(glm::mat4 model, glm::vec4 color) {
+       GLint prevProg; glGetIntegerv(GL_CURRENT_PROGRAM, &prevProg);
+
+       glUseProgram(utilProg->progId);
+
+       glDepthRange(0, 0.01);
+
+       glBindVertexArray(utilVao);
+       model = glm::scale(model, {0.1, 0.3, 0.1});
+       GLuint modelLoc = glGetUniformLocation(utilProg->progId, "model");
+       glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
+
+       GLuint colorLoc = glGetUniformLocation(utilProg->progId, "color");
+       glUniform4fv(colorLoc, 1, glm::value_ptr(color));
+               
+       glDrawArrays(GL_TRIANGLES, 0, 36);
+
+       glDepthRange(0, 1.f);
+
+       glUseProgram(prevProg);
+}
diff --git a/util.hpp b/util.hpp
new file mode 100644 (file)
index 0000000..89236e2
--- /dev/null
+++ b/util.hpp
@@ -0,0 +1,6 @@
+#include "program.hpp"
+#include <glm/ext.hpp>
+
+void initUtilProg();
+Program *getUtilProg();
+void drawDebugNode(glm::mat4 transform, glm::vec4 color = {1, 0.5, 1, 1});