2016-05-10 75 views
0

一直試圖渲染一個MD5網格到我的遊戲引擎,但是當我做網格時,我覺得粘在一起(跟隨它)看起來很平。對於這個問題的一個例子,看看hereASSIMP動畫網格粘在相機上,看起來2D 2D

AnimatedMesh.cpp:

#include "AnimatedMesh.h" 

#define POSITION_LOCATION 0 
#define TEX_COORD_LOCATION 1 
#define NORMAL_LOCATION  2 
#define BONE_ID_LOCATION  3 
#define BONE_WEIGHT_LOCATION 4 

void AnimMesh::VertexBoneData::AddBoneData(unsigned int BoneID, float Weight) 
{ 
    for (unsigned int i = 0; i < ARRAY_SIZE_IN_ELEMENTS(IDs); i++) { 
     if (Weights[i] == 0.0) { 
      IDs[i] = BoneID; 
      Weights[i] = Weight; 
      return; 
     } 
    } 

    assert(0); 
} 

AnimMesh::AnimMesh() 
{ 
    m_VAO = 0; 
    ZERO_MEM(m_Buffers); 
    m_NumBones = 0; 
    m_pScene = NULL; 
} 


AnimMesh::~AnimMesh() 
{ 
    Clear(); 
} 


void AnimMesh::Clear() 
{ 
    for (unsigned int i = 0; i < m_Textures.size(); i++) { 
     SAFE_DELETE(m_Textures[i]); 
    } 

    if (m_Buffers[0] != 0) { 
     glDeleteBuffers(ARRAY_SIZE_IN_ELEMENTS(m_Buffers), m_Buffers); 
    } 

    if (m_VAO != 0) { 
     glDeleteVertexArrays(1, &m_VAO); 
     m_VAO = 0; 
    } 
} 


bool AnimMesh::LoadAnimMesh(const string& Filename) 
{ 
    Clear(); 

    glGenVertexArrays(1, &m_VAO); 
    glBindVertexArray(m_VAO); 

    glGenBuffers(ARRAY_SIZE_IN_ELEMENTS(m_Buffers), m_Buffers); 

    bool Ret = false; 

    m_pScene = m_Importer.ReadFile(Filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs); 

    if (m_pScene) { 
     m_GlobalInverseTransform = m_pScene->mRootNode->mTransformation; 
     m_GlobalInverseTransform.Inverse(); 
     Ret = InitFromScene(m_pScene, Filename); 
    } 
    else { 
     printf("Error parsing '%s': '%s'\n", Filename.c_str(), m_Importer.GetErrorString()); 
    } 

    // Make sure the VAO is not changed from the outside 
    glBindVertexArray(0); 

    return Ret; 
} 


bool AnimMesh::InitFromScene(const aiScene* pScene, const string& Filename) 
{ 
    m_Entries.resize(pScene->mNumMeshes); 
    m_Textures.resize(pScene->mNumMaterials); 

    vector<Vector3f> Positions; 
    vector<Vector3f> Normals; 
    vector<Vector2f> TexCoords; 
    vector<VertexBoneData> Bones; 
    vector<unsigned int> Indices; 

    unsigned int NumVertices = 0; 
    unsigned int NumIndices = 0; 

    // Count the number of vertices and indices 
    for (unsigned int i = 0; i < m_Entries.size(); i++) { 
     m_Entries[i].MaterialIndex = pScene->mMeshes[i]->mMaterialIndex; 
     m_Entries[i].NumIndices = pScene->mMeshes[i]->mNumFaces * 3; 
     m_Entries[i].BaseVertex = NumVertices; 
     m_Entries[i].BaseIndex = NumIndices; 

     NumVertices += pScene->mMeshes[i]->mNumVertices; 
     NumIndices += m_Entries[i].NumIndices; 
    } 

    // Reserve space in the vectors for the vertex attributes and indices 
    Positions.reserve(NumVertices); 
    Normals.reserve(NumVertices); 
    TexCoords.reserve(NumVertices); 
    Bones.resize(NumVertices); 
    Indices.reserve(NumIndices); 

    // Initialize the meshes in the scene one by one 
    for (unsigned int i = 0; i < m_Entries.size(); i++) { 
     const aiMesh* paiMesh = pScene->mMeshes[i]; 
     InitMesh(i, paiMesh, Positions, Normals, TexCoords, Bones, Indices); 
    } 

    if (!InitMaterials(pScene, Filename)) { 
     return false; 
    } 

    // Generate and populate the buffers with vertex attributes and the indices 
    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[POS_VB]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(Positions[0]) * Positions.size(), &Positions[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(POSITION_LOCATION); 
    glVertexAttribPointer(POSITION_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[TEXCOORD_VB]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoords[0]) * TexCoords.size(), &TexCoords[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(TEX_COORD_LOCATION); 
    glVertexAttribPointer(TEX_COORD_LOCATION, 2, GL_FLOAT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[NORMAL_VB]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(Normals[0]) * Normals.size(), &Normals[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(NORMAL_LOCATION); 
    glVertexAttribPointer(NORMAL_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[BONE_VB]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(Bones[0]) * Bones.size(), &Bones[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(BONE_ID_LOCATION); 
    glVertexAttribIPointer(BONE_ID_LOCATION, 4, GL_INT, sizeof(VertexBoneData), (const GLvoid*)0); 
    glEnableVertexAttribArray(BONE_WEIGHT_LOCATION); 
    glVertexAttribPointer(BONE_WEIGHT_LOCATION, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)16); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Buffers[INDEX_BUFFER]); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices[0]) * Indices.size(), &Indices[0], GL_STATIC_DRAW); 

    return GLCheckError(); 
} 


void AnimMesh::InitMesh(unsigned int MeshIndex, 
    const aiMesh* paiMesh, 
    vector<Vector3f>& Positions, 
    vector<Vector3f>& Normals, 
    vector<Vector2f>& TexCoords, 
    vector<VertexBoneData>& Bones, 
    vector<unsigned int>& Indices) 
{ 
    const aiVector3D Zero3D(0.0f, 0.0f, 0.0f); 

    // Populate the vertex attribute vectors 
    for (unsigned int i = 0; i < paiMesh->mNumVertices; i++) { 
     const aiVector3D* pPos = &(paiMesh->mVertices[i]); 
     const aiVector3D* pNormal = &(paiMesh->mNormals[i]); 
     const aiVector3D* pTexCoord = paiMesh->HasTextureCoords(0) ? &(paiMesh->mTextureCoords[0][i]) : &Zero3D; 

     Positions.push_back(Vector3f(pPos->x, pPos->y, pPos->z)); 
     Normals.push_back(Vector3f(pNormal->x, pNormal->y, pNormal->z)); 
     TexCoords.push_back(Vector2f(pTexCoord->x, pTexCoord->y)); 
    } 

    LoadBones(MeshIndex, paiMesh, Bones); 

    // Populate the index buffer 
    for (unsigned int i = 0; i < paiMesh->mNumFaces; i++) { 
     const aiFace& Face = paiMesh->mFaces[i]; 
     assert(Face.mNumIndices == 3); 
     Indices.push_back(Face.mIndices[0]); 
     Indices.push_back(Face.mIndices[1]); 
     Indices.push_back(Face.mIndices[2]); 
    } 
} 


void AnimMesh::LoadBones(unsigned int MeshIndex, const aiMesh* pMesh, vector<VertexBoneData>& Bones) 
{ 
    for (unsigned int i = 0; i < pMesh->mNumBones; i++) { 
     unsigned int BoneIndex = 0; 
     string BoneName(pMesh->mBones[i]->mName.data); 

     if (m_BoneMapping.find(BoneName) == m_BoneMapping.end()) { 
      // Allocate an index for a new bone 
      BoneIndex = m_NumBones; 
      m_NumBones++; 
      BoneInfo bi; 
      m_BoneInfo.push_back(bi); 
      m_BoneInfo[BoneIndex].BoneOffset = pMesh->mBones[i]->mOffsetMatrix; 
      m_BoneMapping[BoneName] = BoneIndex; 
     } 
     else { 
      BoneIndex = m_BoneMapping[BoneName]; 
     } 

     for (unsigned int j = 0; j < pMesh->mBones[i]->mNumWeights; j++) { 
      unsigned int VertexID = m_Entries[MeshIndex].BaseVertex + pMesh->mBones[i]->mWeights[j].mVertexId; 
      float Weight = pMesh->mBones[i]->mWeights[j].mWeight; 
      Bones[VertexID].AddBoneData(BoneIndex, Weight); 
     } 
    } 
} 


bool AnimMesh::InitMaterials(const aiScene* pScene, const string& Filename) 
{ 
    // Extract the directory part from the file name 
    string::size_type SlashIndex = Filename.find_last_of("/"); 
    string Dir; 

    if (SlashIndex == string::npos) { 
     Dir = "."; 
    } 
    else if (SlashIndex == 0) { 
     Dir = "/"; 
    } 
    else { 
     Dir = Filename.substr(0, SlashIndex); 
    } 

    bool Ret = true; 

    // Initialize the materials 
    for (unsigned int i = 0; i < pScene->mNumMaterials; i++) { 
     const aiMaterial* pMaterial = pScene->mMaterials[i]; 

     m_Textures[i] = NULL; 

     if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) { 
      aiString Path; 

      if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) { 
       string p(Path.data); 

       if (p.substr(0, 2) == ".\\") { 
        p = p.substr(2, p.size() - 2); 
       } 

       string FullPath = Dir + "/" + p; 

       m_Textures[i] = new AnimatedTexture(GL_TEXTURE_2D, FullPath.c_str()); 

       if (!m_Textures[i]->Load()) { 
        printf("Error loading texture '%s'\n", FullPath.c_str()); 
        delete m_Textures[i]; 
        m_Textures[i] = NULL; 
        Ret = false; 
       } 
       else { 
        printf("%d - loaded texture '%s'\n", i, FullPath.c_str()); 
       } 
      } 
     } 
    } 

    return Ret; 
} 


void AnimMesh::Renderer(float time, glm::mat4 model, glm::mat4 view, glm::mat4 projection, LightDirectional directionalLight, float baseAmbient, glm::vec3 cameraPos, Shader animationShader) 
{ 
    m_pEffect = new Skinning(animationShader, directionalLight, baseAmbient, 0.0f, 0.0f); 

    vector<Matrix4f> Transforms; 

    BoneTransform(time, Transforms); 

    for (GLuint i = 0; i < Transforms.size(); i++) 
    { 
     m_pEffect->SetBoneTransform(animationShader, i, Transforms[i]); 
    } 

    m_pEffect->SetEyeWorldPos(animationShader, cameraPos); 
    m_pEffect->SetUp(animationShader, model, view, projection); 

    glBindVertexArray(m_VAO); 

    for (unsigned int i = 0; i < m_Entries.size(); i++) { 
     const unsigned int MaterialIndex = m_Entries[i].MaterialIndex; 

     assert(MaterialIndex < m_Textures.size()); 

     if (m_Textures[MaterialIndex]) { 
      m_Textures[MaterialIndex]->Bind(GL_TEXTURE0); 
     } 

     glDrawElementsBaseVertex(GL_TRIANGLES, 
      m_Entries[i].NumIndices, 
      GL_UNSIGNED_INT, 
      (void*)(sizeof(unsigned int)* m_Entries[i].BaseIndex), 
      m_Entries[i].BaseVertex); 
    } 

    // Make sure the VAO is not changed from the outside  
    glBindVertexArray(0); 
} 


unsigned int AnimMesh::FindPosition(float AnimationTime, const aiNodeAnim* pNodeAnim) 
{ 
    for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys - 1; i++) { 
     if (AnimationTime < (float)pNodeAnim->mPositionKeys[i + 1].mTime) { 
      return i; 
     } 
    } 

    assert(0); 

    return 0; 
} 


unsigned int AnimMesh::FindRotation(float AnimationTime, const aiNodeAnim* pNodeAnim) 
{ 
    assert(pNodeAnim->mNumRotationKeys > 0); 

    for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys - 1; i++) { 
     if (AnimationTime < (float)pNodeAnim->mRotationKeys[i + 1].mTime) { 
      return i; 
     } 
    } 

    assert(0); 

    return 0; 
} 


unsigned int AnimMesh::FindScaling(float AnimationTime, const aiNodeAnim* pNodeAnim) 
{ 
    assert(pNodeAnim->mNumScalingKeys > 0); 

    for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys - 1; i++) { 
     if (AnimationTime < (float)pNodeAnim->mScalingKeys[i + 1].mTime) { 
      return i; 
     } 
    } 

    assert(0); 

    return 0; 
} 


void AnimMesh::CalcInterpolatedPosition(aiVector3D& Out, float AnimationTime, const aiNodeAnim* pNodeAnim) 
{ 
    if (pNodeAnim->mNumPositionKeys == 1) { 
     Out = pNodeAnim->mPositionKeys[0].mValue; 
     return; 
    } 

    unsigned int PositionIndex = FindPosition(AnimationTime, pNodeAnim); 
    unsigned int NextPositionIndex = (PositionIndex + 1); 
    assert(NextPositionIndex < pNodeAnim->mNumPositionKeys); 
    float DeltaTime = (float)(pNodeAnim->mPositionKeys[NextPositionIndex].mTime - pNodeAnim->mPositionKeys[PositionIndex].mTime); 
    float Factor = (AnimationTime - (float)pNodeAnim->mPositionKeys[PositionIndex].mTime)/DeltaTime; 
    assert(Factor >= 0.0f && Factor <= 1.0f); 
    const aiVector3D& Start = pNodeAnim->mPositionKeys[PositionIndex].mValue; 
    const aiVector3D& End = pNodeAnim->mPositionKeys[NextPositionIndex].mValue; 
    aiVector3D Delta = End - Start; 
    Out = Start + Factor * Delta; 
} 


void AnimMesh::CalcInterpolatedRotation(aiQuaternion& Out, float AnimationTime, const aiNodeAnim* pNodeAnim) 
{ 
    // we need at least two values to interpolate... 
    if (pNodeAnim->mNumRotationKeys == 1) { 
     Out = pNodeAnim->mRotationKeys[0].mValue; 
     return; 
    } 

    unsigned int RotationIndex = FindRotation(AnimationTime, pNodeAnim); 
    unsigned int NextRotationIndex = (RotationIndex + 1); 
    assert(NextRotationIndex < pNodeAnim->mNumRotationKeys); 
    float DeltaTime = (float)(pNodeAnim->mRotationKeys[NextRotationIndex].mTime - pNodeAnim->mRotationKeys[RotationIndex].mTime); 
    float Factor = (AnimationTime - (float)pNodeAnim->mRotationKeys[RotationIndex].mTime)/DeltaTime; 
    assert(Factor >= 0.0f && Factor <= 1.0f); 
    const aiQuaternion& StartRotationQ = pNodeAnim->mRotationKeys[RotationIndex].mValue; 
    const aiQuaternion& EndRotationQ = pNodeAnim->mRotationKeys[NextRotationIndex].mValue; 
    aiQuaternion::Interpolate(Out, StartRotationQ, EndRotationQ, Factor); 
    Out = Out.Normalize(); 
} 


void AnimMesh::CalcInterpolatedScaling(aiVector3D& Out, float AnimationTime, const aiNodeAnim* pNodeAnim) 
{ 
    if (pNodeAnim->mNumScalingKeys == 1) { 
     Out = pNodeAnim->mScalingKeys[0].mValue; 
     return; 
    } 

    unsigned int ScalingIndex = FindScaling(AnimationTime, pNodeAnim); 
    unsigned int NextScalingIndex = (ScalingIndex + 1); 
    assert(NextScalingIndex < pNodeAnim->mNumScalingKeys); 
    float DeltaTime = (float)(pNodeAnim->mScalingKeys[NextScalingIndex].mTime - pNodeAnim->mScalingKeys[ScalingIndex].mTime); 
    float Factor = (AnimationTime - (float)pNodeAnim->mScalingKeys[ScalingIndex].mTime)/DeltaTime; 
    assert(Factor >= 0.0f && Factor <= 1.0f); 
    const aiVector3D& Start = pNodeAnim->mScalingKeys[ScalingIndex].mValue; 
    const aiVector3D& End = pNodeAnim->mScalingKeys[NextScalingIndex].mValue; 
    aiVector3D Delta = End - Start; 
    Out = Start + Factor * Delta; 
} 


void AnimMesh::ReadNodeHeirarchy(float AnimationTime, const aiNode* pNode, const Matrix4f& ParentTransform) 
{ 
    string NodeName(pNode->mName.data); 

    const aiAnimation* pAnimation = m_pScene->mAnimations[0]; 

    Matrix4f NodeTransformation(pNode->mTransformation); 

    const aiNodeAnim* pNodeAnim = FindNodeAnim(pAnimation, NodeName); 

    if (pNodeAnim) { 
     // Interpolate scaling and generate scaling transformation matrix 
     aiVector3D Scaling; 
     CalcInterpolatedScaling(Scaling, AnimationTime, pNodeAnim); 
     Matrix4f ScalingM; 
     ScalingM.InitScaleTransform(Scaling.x, Scaling.y, Scaling.z); 

     // Interpolate rotation and generate rotation transformation matrix 
     aiQuaternion RotationQ; 
     CalcInterpolatedRotation(RotationQ, AnimationTime, pNodeAnim); 
     Matrix4f RotationM = Matrix4f(RotationQ.GetMatrix()); 

     // Interpolate translation and generate translation transformation matrix 
     aiVector3D Translation; 
     CalcInterpolatedPosition(Translation, AnimationTime, pNodeAnim); 
     Matrix4f TranslationM; 
     TranslationM.InitTranslationTransform(Translation.x, Translation.y, Translation.z); 

     // Combine the above transformations 
     NodeTransformation = TranslationM * RotationM * ScalingM; 
    } 

    Matrix4f GlobalTransformation = ParentTransform * NodeTransformation; 

    if (m_BoneMapping.find(NodeName) != m_BoneMapping.end()) { 
     unsigned int BoneIndex = m_BoneMapping[NodeName]; 
     m_BoneInfo[BoneIndex].FinalTransformation = m_GlobalInverseTransform * GlobalTransformation * m_BoneInfo[BoneIndex].BoneOffset; 
    } 

    for (unsigned int i = 0; i < pNode->mNumChildren; i++) { 
     ReadNodeHeirarchy(AnimationTime, pNode->mChildren[i], GlobalTransformation); 
    } 
} 


void AnimMesh::BoneTransform(float TimeInSeconds, vector<Matrix4f>& Transforms) 
{ 
    Matrix4f Identity; 
    Identity.InitIdentity(); 

    float TicksPerSecond = (float)(m_pScene->mAnimations[0]->mTicksPerSecond != 0 ? m_pScene->mAnimations[0]->mTicksPerSecond : 25.0f); 
    float TimeInTicks = TimeInSeconds * TicksPerSecond; 
    float AnimationTime = fmod(TimeInTicks, (float)m_pScene->mAnimations[0]->mDuration); 

    ReadNodeHeirarchy(AnimationTime, m_pScene->mRootNode, Identity); 

    Transforms.resize(m_NumBones); 

    for (unsigned int i = 0; i < m_NumBones; i++) { 
     Transforms[i] = m_BoneInfo[i].FinalTransformation; 
    } 
} 


const aiNodeAnim* AnimMesh::FindNodeAnim(const aiAnimation* pAnimation, const string NodeName) 
{ 
    for (unsigned int i = 0; i < pAnimation->mNumChannels; i++) { 
     const aiNodeAnim* pNodeAnim = pAnimation->mChannels[i]; 

     if (string(pNodeAnim->mNodeName.data) == NodeName) { 
      return pNodeAnim; 
     } 
    } 

    return NULL; 
} 

Skinning.vert:

#version 330                                  

layout (location = 0) in vec3 Position;           
layout (location = 1) in vec2 TexCoord;            
layout (location = 2) in vec3 Normal;            
layout (location = 3) in ivec4 BoneIDs; 
layout (location = 4) in vec4 Weights; 

out vec2 TexCoord0; 
out vec3 Normal0;                 
out vec3 WorldPos0;                 

const int MAX_BONES = 100; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 
uniform mat4 gBones[MAX_BONES]; 
uniform mat4 modelInverseTranspose; 

void main() 
{  
    mat4 BoneTransform = gBones[BoneIDs[0]] * Weights[0]; 
    BoneTransform += gBones[BoneIDs[1]] * Weights[1]; 
    BoneTransform += gBones[BoneIDs[2]] * Weights[2]; 
    BoneTransform += gBones[BoneIDs[3]] * Weights[3]; 

    vec4 PosL = BoneTransform * vec4(Position, 1.0); 
    gl_Position = model * view * projection * PosL; 
    TexCoord0 = TexCoord; 
    vec4 NormalL = BoneTransform * vec4(Normal, 0.0); 
    Normal0 = (modelInverseTranspose * NormalL).xyz; 
    WorldPos0 = (model * PosL).xyz;         
} 

回答

1

我想你可能已經得到了在着色器錯誤的矩陣乘法順序。從another question引用:

從對象的本地座標空間到世界空間的模型映射,從世界空間到相機空間的視圖,從相機到屏幕的投影。

嘗試改變

gl_Position = model * view * projection * PosL; 

gl_Position = projection * view * model * PosL; 
+0

哈哈以及它現在消失了 –