Hello fellow Blender users, I have started learning C++ and OpenGL.
Now I try to learn more about vertex skinning. I want to make a simple application that does vertex skinning.
(If you wonder why it worth the trouble then the answer is for educational purposes mostly, then everything else.)
Check down there on Vertex Skinning section.
#include <iostream>
#include <array>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace std;
int main()
{
// Bone positions
array<glm::vec3, 3> positions
{
glm::vec3(0, -2, 0),
glm::vec3(0, 2, 0), // Move 2 units up from root (local space)
glm::vec3(0, 2, 0) // Move 2 units up from 1 (local space)
};
// Bone matrices
array<glm::mat4, 3> bones;
// Vertex positions
array<glm::vec3, 6> vertices
{
glm::vec3(-0.5f, -2, 0),
glm::vec3( 0.5f, -2, 0),
glm::vec3(-0.5f, 0, 0),
glm::vec3( 0.5f, 0, 0),
glm::vec3(-0.5f, 2, 0),
glm::vec3( 0.5f, 2, 0)
};
// Vertex bone ids
array<int, 6> vertBoneIDs = { 0, 0, 1, 1, 2, 2 };
// Vertex bone weights
array<float, 6> vertBoneWeights = { 1, 1, 1, 1, 1, 1 };
// Edges
array<int, 16> indices =
{
0, 1, 1, 3, 3, 2, 2, 0,
2, 3, 3, 5, 5, 4, 4, 2
};
//{ Setup window
int width = 800;
int height = 600;
glfwInit();
GLFWwindow* window;
window = glfwCreateWindow(width, height, "GLFW", NULL, NULL);
glfwMakeContextCurrent(window);
// Camera
glm::mat4 matrixProj = glm::perspective(45.0f, (float)width/height, 0.1f, 100.0f);
glm::mat4 matrixView = glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
//}
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadMatrixf(glm::value_ptr(matrixProj * matrixView));
//{ Bone transformations
// Prepare some values
float sinValue = glm::sin(glfwGetTime());
float cosValue = glm::cos(glfwGetTime());
float rotValue = sinValue * 100;
glm::vec3 rotVec = glm::vec3(0, 0, 1);
// Base bone
bones[0] = glm::translate(positions[0]);
bones[0] *= glm::rotate(rotValue*0.25f, rotVec);
// Secondary bone
bones[1] = bones[0];
bones[1] *= glm::translate(positions[1]);
bones[1] *= glm::rotate(rotValue*0.5f, rotVec);
// Third bone
bones[2] = bones[1];
bones[2] *= glm::translate(positions[2]);
//}
//{ Vertex skinning
for (int i = 0; i < vertices.size(); i++)
{
// Something wrong goes here...
// glm::mat4 v =
// glm::translate(vertices[i])
// * bones[vertBoneIDs[i]];
// vertices[i] = glm::vec3(v[3].x, v[3].y, v[3].z);
}
//}
//{ Drawing
// Bones
glPointSize(1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < bones.size(); i++)
glVertex2f((bones[i])[3].x, (bones[i])[3].y);
glEnd();
// Bone joints
glPointSize(10.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_POINTS);
for (int i = 0; i < bones.size(); i++)
glVertex2f((bones[i])[3].x, (bones[i])[3].y);
glEnd();
// Edges
glPointSize(1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_LINES);
for (int i = 0; i < indices.size(); i+=2)
{
glm::vec3 a = vertices[indices[i]];
glm::vec3 b = vertices[indices[i+1]];
glVertex3f(a.x, a.y, a.z);
glVertex3f(b.x, b.y, b.z);
}
glEnd();
//}
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Currently keeping things as simple as possible everything is done in immediate mode and is very hard coded, but later it will be improved and many more features will be added. I have looked at many sources on Github but I don’t understand how they work, I want only a simple solution.