#include #include #include #include #include #include std::map bindStringToNum { {"null", BIND_NULL}, {"head", BIND_HEAD}, {"face", BIND_FACE}, {"offset-eyes", OFFSET_EYES}, }; std::map triggerStringToNum { {"null", TRIGGER_NULL}, {"mouth-open", TRIGGER_MOUTH_OPEN}, }; ModelPart::ModelPart() { //create vbo, ebo, vao initBuffers(&vao); empty = false; } void ModelPart::bindAndDraw() { glBindVertexArray(vao); glBindTexture(GL_TEXTURE_2D, tex[texSelection]); glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(transMatrix)); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } void ModelPart::setBind(std::string bindName) { bind = bindStringToNum[bindName]; } void ModelPart::setFollowTarget(std::string followTarget) { follow = bindStringToNum[followTarget]; } void ModelPart::setOffsetBind(std::string bindName) { offsetBind = bindStringToNum[bindName]; } void ModelPart::smoothTransform(glm::vec2 position, float rotation, float scale) { histPositions[histI] = position; histRotations[histI] = rotation; histScales[histI] = scale; histI++; histI = histI % SMOOTHING_FRAMES; glm::vec2 smoothedPosition(0,0); float smoothedRotation = 0; float smoothedScale = 0; for(size_t i = 0; i < SMOOTHING_FRAMES; i++) { smoothedPosition += histPositions[i]; smoothedRotation += histRotations[i]; smoothedScale += histScales[i]; } smoothedPosition /= SMOOTHING_FRAMES; smoothedRotation /= SMOOTHING_FRAMES; smoothedScale /= SMOOTHING_FRAMES; setTransform(smoothedPosition, smoothedRotation, smoothedScale); } void ModelPart::setTransform(glm::vec2 position, float rotation, float scale) { transMatrix = glm::ortho(-windowAspectRatio, windowAspectRatio, -1.0f, 1.0f); transMatrix = glm::translate(transMatrix, glm::vec3(position.x, -position.y, 0.0f) + glm::vec3(posOffset, 0.0f)); transMatrix = glm::rotate(transMatrix, rotation * rotFactor, glm::vec3(0.0f, 0.0f, 1.0f)); transMatrix = glm::scale(transMatrix, glm::vec3(1,1,1) + (scale - 1 + glm::vec3(scaleOffset, 0.0f)) * scaleFactor); transMatrix = glm::translate(transMatrix, glm::vec3(-origin, 0.0f)); } void ModelPart::processFaceData(struct FaceData faceData) { // calculate position glm::vec2 bindPosition = faceData.positions[bind]; glm::vec2 followPosition = faceData.positions[follow]; glm::vec2 followDirection = followPosition - bindPosition; glm::vec2 offset = faceData.positions[offsetBind] * offsetFactor * faceData.scale; glm::vec2 newPosition = bindPosition + offset + (followDirection * factor); smoothTransform(newPosition, faceData.headRotation, faceData.scale); // change textures selectTexture(0); // if none are triggered, use the first one for (size_t i = 0; i < texCount; i++) { if (faceData.triggers[texTriggers[i]]) { selectTexture(i); break; // if several textures are triggered, the first one defined in model.toml will get priority } } } void ModelPart::addTexture(unsigned char* texBuffer, size_t texLength, size_t slot, std::string triggerName) { initTexture(&tex[slot], texBuffer, texLength); texTriggers[slot] = triggerStringToNum[triggerName]; texCount++; } void ModelPart::selectTexture(size_t slot) { texSelection = slot; }