Commit bcc29328 by Kai Westerkamp

BONES

parent 20755150
......@@ -5,6 +5,8 @@ layout(location = 0) out vec3 color;
in vec3 vCamPosition;
in vec3 vCamNormal;
in vec2 vUV;
in vec4 debugout;
uniform sampler2D colorTexture;
uniform vec3 LightPos;
......@@ -40,6 +42,7 @@ vec3 phong(vec3 lightPos){
void main(void)
{
color = phong(LightPos);
//color = debugout.xyz;
//color = texture2D(colorTexture,vUV).xyz;
}
......@@ -2,27 +2,44 @@
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec2 UV;
layout(location = 2) in ivec4 BoneIDs;
layout(location = 2) in vec4 Weights;
layout(location = 3) in ivec4 BoneIDs;
layout(location = 4) in vec4 Weights;
out vec3 vCamPosition;
out vec3 vCamNormal;
out vec2 vUV;
out vec4 debugout;
uniform mat4x4 MV;
uniform mat4x4 MVP;
uniform mat3x3 N;
uniform mat4x4 Bones[100];
void main(void)
{
vCamPosition = vec4(MV*vec4(Position,1.0)).xyz;
debugout = vec4(BoneIDs)/60;
debugout = Weights;
//debugout = vec4(1);
mat4x4 BoneTransform = Bones[BoneIDs[0]] * Weights[0];
BoneTransform += Bones[BoneIDs[1]] * Weights[1];
BoneTransform += Bones[BoneIDs[2]] * Weights[2];
BoneTransform += Bones[BoneIDs[3]] * Weights[3];
vec4 Pos = BoneTransform*vec4(Position,1.0);
//Pos = vec4(Position,1.0);
vCamPosition = vec4(MV*Pos).xyz;
vCamNormal = N*Normal;
vUV = UV;
gl_Position = MVP * vec4(Position,1.0);
gl_Position = MVP * Pos;
}
......
#include "mesh.h"
void Vertex::AddBoneData(uint BoneID, float Weight){
for (int i = 0 ; i < 4 ; i++) {
if (weights[i] == 0.0) {
IDs[i] = BoneID;
weights[i] = Weight;
//qDebug()<<"Add"<<i<<BoneID<<Weight<<pos;
return;
}
}
qCritical()<<"More tahn 4 Bones at Vertex";
qCritical()<<"More tahn 4 Bones at Vertex"<<pos<<BoneID<<Weight<<"added:"
<<IDs[0]<<weights[0]<<IDs[1]<<weights[1]<<IDs[2]<<weights[2]<<IDs[3]<<weights[3];
}
Mesh::MeshEntry::MeshEntry()
......@@ -64,15 +67,17 @@ Mesh::Mesh(QOpenGLFunctions_4_3_Core *f,QString fileName)
{
loaded = false;
this->f =f;
Assimp::Importer importer;
this->scene= importer.ReadFile(fileName.toStdString(),
//aiProcess_CalcTangentSpace |
aiProcess_GenSmoothNormals |
//aiProcess_JoinIdenticalVertices |
//aiProcess_SortByPType |
// ? aiProcess_FlipUVs |
aiProcess_Triangulate
);
numberOfBones = 0;
scene = NULL;
scene= importer.ReadFile(fileName.toStdString(),
//aiProcess_CalcTangentSpace |
aiProcess_GenSmoothNormals |
//aiProcess_JoinIdenticalVertices |
//aiProcess_SortByPType |
// ? aiProcess_FlipUVs |
aiProcess_Triangulate
);
qDebug()<<"File Read";
if( !scene)
{
......@@ -101,6 +106,7 @@ Mesh::Mesh(QOpenGLFunctions_4_3_Core *f,QString fileName)
for (int i = 0 ; i < entries.size() ; i++) {
aiMesh* meshEntry = scene->mMeshes[i];
initMeshEntry(i, meshEntry);
}
} else{
qWarning()<<"No Mesh found";
......@@ -115,7 +121,7 @@ Mesh::Mesh(QOpenGLFunctions_4_3_Core *f,QString fileName)
//TODO init Nodes
if(scene->mRootNode != NULL)
{
initNode(scene, scene->mRootNode, rootNode);
initNode(scene, scene->mRootNode, rootNode, QString());
} else {
rootNode.transformation.setToIdentity();
rootNode.children.resize(0);
......@@ -139,25 +145,30 @@ Mesh::Mesh(QOpenGLFunctions_4_3_Core *f,QString fileName)
}
}
void Mesh::initNode(const aiScene *scene, aiNode *node, Node &newNode){
void Mesh::initNode(const aiScene *scene, aiNode *node, Node &newNode,QString debugoffset){
newNode.name = node->mName.length != 0 ? node->mName.C_Str() : "";
newNode.transformation = QMatrix4x4(node->mTransformation[0]);
newNode.meshes.resize(node->mNumMeshes);
bool debug = false;
if(debug) qDebug()<<debugoffset.toStdString().c_str() << "NodeName" << newNode.name;
if(boneMap.find(newNode.name) != boneMap.end()){
if(debug) qDebug()<<debugoffset.toStdString().c_str() << "hasBone";
}
qDebug() << "NodeName" << newNode.name;
qDebug() << " NumMeshes" << newNode.meshes.size();
if(debug) qDebug()<<debugoffset.toStdString().c_str() << " NumMeshes" << newNode.meshes.size();
for(uint i = 0; i < node->mNumMeshes; ++i)
{
newNode.meshes[i] = node->mMeshes[i];
qDebug() << " MeshName" << entries[newNode.meshes[i]].name;
if(debug) qDebug()<<debugoffset.toStdString().c_str() << " MeshName" << entries[newNode.meshes[i]].name;
}
qDebug() << " NumChildren" << node->mNumChildren;
if(debug) qDebug()<<debugoffset.toStdString().c_str() << " NumChildren" << node->mNumChildren;
QString newDebug = QString(debugoffset).append(" ");
for(uint i = 0; i < node->mNumChildren; ++i)
{
newNode.children.push_back(Node());
initNode(scene, node->mChildren[i], newNode.children[i]);
initNode(scene, node->mChildren[i], newNode.children[i],newDebug);
}
}
......@@ -232,11 +243,126 @@ void Mesh::initMeshEntry(int index, aiMesh * entry){
Indices.push_back(face.mIndices[2]);
}
entries[index].init(f,Vertices, Indices);
entries[index].name = entry->mName.length != 0 ? entry->mName.C_Str() : "";
entries[index].name = entry->mName.length != 0 ? entry->mName.C_Str() : "";
entries[index].materialIndex = entry->mMaterialIndex;
qDebug()<<"Loaded Mesh:"<<entries[index].name;
if(entry->HasBones()){
for(uint i = 0; i< entry->mNumBones; i++){
int index = 0;
QString BoneName = QString(entry->mBones[i]->mName.data);
if (boneMap.find(BoneName) == boneMap.end()) {
// Allocate an index for a new bone
index = numberOfBones;
numberOfBones++;
BoneInfo bi;
bones.push_back(bi);
bones[index].BoneOffset = QMatrix4x4(entry->mBones[i]->mOffsetMatrix[0]);
boneMap[BoneName] = index;
}
else {
index = boneMap[BoneName];
}
for (uint j = 0 ; j < entry->mBones[i]->mNumWeights ; j++) {
uint VertexID = entry->mBones[i]->mWeights[j].mVertexId;
float Weight = entry->mBones[i]->mWeights[j].mWeight;
Vertices[VertexID].AddBoneData(index, Weight);
}
}
}
entries[index].init(f,Vertices, Indices);
}
void Mesh::updateBoneTransform(float TimeInSeconds){
if(!scene)
return;
const aiAnimation* animation = scene->mAnimations[0];
//TODO calc time and get Anaimation;
updateBoneHeirachy(0.0,animation,this->rootNode,QMatrix4x4());
}
void Mesh::updateBoneHeirachy(float AnimTime,const aiAnimation* animation, Node node, QMatrix4x4 parentTransform){
QMatrix4x4 nodeTransformation = node.transformation;
//Find channel
const aiNodeAnim *nodeAnimation = findAnimOfNode(animation,node.name);
//calc Tcurrent Trasnformation;
if (nodeAnimation) {
QVector3D scale = calcInterpolatedScaling(AnimTime,nodeAnimation);
QQuaternion rot = calcInterpolatedRotation(AnimTime,nodeAnimation);
QVector3D trans = calcInterpolatedTranslation(AnimTime,nodeAnimation);
//qDebug()<<"calc"<<scale<<rot<<trans;
nodeTransformation.setToIdentity();
nodeTransformation.translate(trans);
nodeTransformation.rotate(rot);
nodeTransformation.scale(scale);
}
//Update Bone and children
QMatrix4x4 GlobalTransform = parentTransform * nodeTransformation;
if (boneMap.find(node.name) != boneMap.end()) {
int index = boneMap[node.name];
bones[index].FinalTransformation = globalInverseTransform * GlobalTransform * bones[index].BoneOffset;
}
for(int i = 0; i < node.children.size(); ++i)
{
updateBoneHeirachy(AnimTime,animation,node.children[i],GlobalTransform);
}
}
const aiNodeAnim* Mesh::findAnimOfNode(const aiAnimation* animation, QString NodeName){
for (uint i = 0 ; i < animation->mNumChannels ; i++) {
const aiNodeAnim* nodeanim = animation->mChannels[i];
if (QString(nodeanim->mNodeName.data) == NodeName) {
return nodeanim;
}
}
return NULL;
}
QVector3D Mesh::calcInterpolatedScaling(float AnimTime,const aiNodeAnim *nodeAnimation){
int index = nodeAnimation->mNumScalingKeys/2;
//index = 0;
aiVector3D scale = nodeAnimation->mScalingKeys[index].mValue;
return QVector3D(scale.x,scale.y,scale.z);
}
QQuaternion Mesh::calcInterpolatedRotation(float AnimTime,const aiNodeAnim *nodeAnimation){
int index = nodeAnimation->mNumRotationKeys/2;
// index = 0;
aiQuaternion quat = nodeAnimation->mRotationKeys[index].mValue;
return QQuaternion(quat.w,quat.x,quat.y,quat.z);
}
QVector3D Mesh::calcInterpolatedTranslation(float AnimTime, const aiNodeAnim *nodeAnimation){
int index = nodeAnimation->mNumScalingKeys/2;
// index = 0;
aiVector3D pos = nodeAnimation->mPositionKeys[index].mValue;
return QVector3D(pos.x,pos.y,pos.z);
}
......@@ -254,10 +380,15 @@ void Mesh::render(QOpenGLShaderProgram *shader, QMatrix4x4 V,QMatrix4x4 P){
f->glEnableVertexAttribArray(boneIndex);
f->glEnableVertexAttribArray(boneweightIndex);
QMatrix4x4 M;
M.setToIdentity();
renderNode(shader,rootNode,V,P,M);
updateBoneTransform(0.0);
QVector<QMatrix4x4> boneTransforms = QVector<QMatrix4x4>(bones.size());
for(int i = 0; i < bones.size(); i++){
boneTransforms[i] = bones[i].FinalTransformation;
}
shader->setUniformValueArray("Bones",boneTransforms.constData(),bones.size());
renderNode(shader,rootNode,V,P,QMatrix4x4());
f->glDisableVertexAttribArray(positionIndex);
......@@ -282,7 +413,7 @@ void Mesh::renderNode(QOpenGLShaderProgram *shader, Node &node, QMatrix4x4 V,QMa
shader->setUniformValue("N",normalMat);
for (int i = 0 ; i < node.meshes.size() ; i++) {
int index = node.meshes[i];
int index = node.meshes[i];
//load Material
renderMesh(shader, index);
}
......@@ -309,10 +440,10 @@ void Mesh::renderMesh(QOpenGLShaderProgram *shader, int index)
// Draw Vertex Array
f->glBindBuffer(GL_ARRAY_BUFFER, entries[index].VB);
f->glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
f->glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12); //3*4
f->glVertexAttribPointer(uvIndex, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)24); //(3+3)*4
f->glVertexAttribIPointer(boneIndex, 4, GL_INT, sizeof(Vertex), (const GLvoid*)32); //(3+3+2)*4
f->glVertexAttribPointer(boneweightIndex, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)48); //(3+3+2+4)*4
f->glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12); //12
f->glVertexAttribPointer(uvIndex, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)24); // 12+12
f->glVertexAttribIPointer(boneIndex, 4, GL_INT, sizeof(Vertex), (const GLvoid*)32); // 12+12+8
f->glVertexAttribPointer(boneweightIndex, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)48); //12+12+8+16
f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, entries[index].IB);
f->glDrawElements(GL_TRIANGLES, entries[index].numIndex, GL_UNSIGNED_INT, 0);
......
......@@ -23,21 +23,20 @@ struct Vertex
uint IDs[4];
float weights[4];
Vertex() {
Vertex(){}
Vertex(const QVector3D& pos, const QVector3D& normal, const QVector2D& tex)
{
for(int i = 0; i < 4; i++){
IDs[i] = 0;
weights[i] = 0;
}
}
Vertex(const QVector3D& pos, const QVector3D& normal, const QVector2D& tex)
{
this->pos = pos;
this->tex = tex;
this->normal = normal;
}
void AddBoneData(uint BoneID, float Weight);
void AddBoneData(uint BoneID, float Weight);
};
class Mesh
......@@ -86,6 +85,18 @@ private:
QVector3D Intensity;
};
struct BoneInfo
{
QMatrix4x4 BoneOffset;
QMatrix4x4 FinalTransformation;
BoneInfo()
{
BoneOffset.setToIdentity();
FinalTransformation.setToIdentity();
}
};
struct Node
{
Node();
......@@ -96,18 +107,33 @@ private:
};
const aiScene *scene;
Assimp::Importer importer;
QMatrix4x4 globalInverseTransform;
QVector<MeshEntry> entries;
QVector<MaterialInfo> materials;
QVector<BoneInfo> bones;
QMap<QString,int> boneMap;
int numberOfBones;
Node rootNode;
QOpenGLFunctions_4_3_Core *f;
bool loaded;
void initMeshEntry(int i,aiMesh * entry);
void initMaterial(QString dir, unsigned int i, const aiMaterial* material);
void initNode(const aiScene *scene, aiNode *node, Node &newNode);
void initNode(const aiScene *scene, aiNode *node, Node &newNode, QString debugoffset);
void updateBoneTransform(float TimeInSeconds);
void updateBoneHeirachy(float AnimTime,const aiAnimation* animation, Node node, QMatrix4x4 parentTransform);
const aiNodeAnim *findAnimOfNode(const aiAnimation* animation, QString NodeName);
QVector3D calcInterpolatedScaling(float AnimTime,const aiNodeAnim *nodeAnimation);
QQuaternion calcInterpolatedRotation(float AnimTime,const aiNodeAnim *nodeAnimation);
QVector3D calcInterpolatedTranslation(float AnimTime, const aiNodeAnim *nodeAnimation);
void renderNode(QOpenGLShaderProgram *shader, Node &node, QMatrix4x4 V,QMatrix4x4 P,QMatrix4x4 M);
void renderMesh(QOpenGLShaderProgram *shader, int index);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment