2014-04-25 2 views
0

나는 애니메이션 렌더링에 필요한 모든 정보를 기본적으로 포함하고있는 컨테이너 클래스를 만들었습니다. Assimp 라이브러리를 사용하여 애니메이션을로드합니다. 그런 다음 scene->mVertices 등의 데이터를 배열 버퍼에 할당하면 다른 프레임의 데이터를 버퍼에 저장하는 방법이 달라집니다.Assimp로 애니메이션로드 이해하기

나는 또한 HasAnimations() 호출 된 함수 및 aiAnimation **mAnimations 있다는 것을 알고있다. 하지만 그곳에 다음 버텍스 데이터 세트를 가져 오는 것과 관련이있는 데이터를 찾을 수 없습니다.

나는 그것과 OBJ-일련의 파일을로드하고 내 수업이 제대로 작동하는지 comfirm하기 위해 그들을 끌어 냈다. 그러나 분명히 내가 진짜 거래로 확장하고 싶을 때 나는 뭔가를 선호하거나 적극적으로 사용할 필요가있다. 250 프레임을 개별적으로로드하는 데 2 ​​~ 3 분이 소요됩니다. (간단한 애니메이션을로드하는 것은 바로, 약 5 초 꼭대기에서 수행해야 하는가?) 내가 파일 형식의 어떤 종류를 사용하여 열려있어

. 하지만 블렌더에서 어떻게 설정하여 애니메이션을 내보낼 지 알아야합니다. 블렌더에 대한 경험이 거의 없기 때문에 나는 현재 끔찍하게 실패하는 것처럼 보입니다.

지금 2 일 동안 수출이 라이브러리 및 믹서기에 자습서를 검색하고 유용한 거의 아무 것도 발견했습니다. 나는 Assimp에 대한 문서도 확인해 봤는데, 지금까지 나를 데려 갔지만 aiAnimation이 정점에 어떻게 영향을 미치는지에 대해서는 설명하지 못했습니다. 또는 내가 필요한 다른 데이터 프레임을 얻는 방법.

답변

0

글쎄, 나는 끝없는 시간 후에 작동하게 만들었다. 일종의 ... 루프에서 변형 된 모델을 만들었습니다. x+5, y+5, x-5, y-5 ... 내가 결국 무엇을했는지, 어쨌든 생각할 수있는 유일한 것이 었습니다. 장면 -> mAnimations []에서 데이터를 읽는 것은 기본적으로 키 프레임의 배열로만 구성됩니다. 그래서 모든 꼭지점을 직접 보간해야했습니다. (항상 접근하는 재미있는 일입니다!).

Effectivly :

  1. 당신은 키 프레임이 완전히 보간해야하는 시간을 얻는다.
  2. 그런 다음 오브젝트가 현재 이동해야하는 양을 계산하는 위치를 뺍니다.
  3. 이제는 각 단계를 얼마나 이동해야하는지 파악해야하므로 가장 쉬운 해결책을 취하고 운동을 몇 개의 프레임으로 나눠야 하는지를 나누었습니다.
  4. 이제 모든 정점을 VBO로 보내기 전에 업데이트하는 것이 중요합니다.

    헤더 :

    class AssimpMesh { 
    private: 
        struct ShaderProgram { 
         //Shader data 
         GLuint program; 
         string programName; 
         vector <GLuint> shaders, uniforms; 
        }; 
    
        struct MeshData { 
         //Mesh data 
         GLuint meshArray; 
         vector <GLuint> buffers; 
         vector <string> bufferNames; 
    
         //Shader data 
         ShaderProgram *shader; 
    
         vector <aiVector3D> transedVertices; 
         int totalIndices; 
        }; 
    
        struct Frame { 
         vector <MeshData*> meshes; 
        }; 
    
        struct Animation { 
         string name; 
         vector <Frame*> frames; 
        }; 
    
        //Global shader data 
        ShaderProgram *globalShader; 
    
        //Model data 
        Assimp::Importer importer; 
        const aiScene *scene; 
    
        //Mesh data 
        bool initialized, perMeshShading; 
        vector <Animation*> animations; 
        int currentFrame, currentAnimation; 
        Uint32 lastFrameTicks; 
        Transform *transform; 
        glm::mat4 projectionView; 
        aiVector3D lightPosition; 
    
        void loadScene(string filePath); 
        void loadAnimation(Animation *animation, int numFrames); 
        void initMesh(aiMesh *mesh, MeshData *data); 
        ... 
    
    public: 
        AssimpMesh(string filePath); 
        ~AssimpMesh(); 
    
        void draw(); 
        ... 
    }; 
    

    출처 :

    나는이처럼 보이는 뭔가있어, 그 단계 후

(이 단계는 아마 당신의 데이터 설정에 따라 약간 변하는) 물론

void AssimpMesh::loadScene(string filePath) { 
    //Load animation file 
    scene = importer.ReadFile(filePath.c_str(), aiProcessPreset_TargetRealtime_MaxQuality); 

    if (scene) { 
     if (scene->HasAnimations()) { 
      for (int i = 0; i < scene->mNumAnimations; i++) { 
       aiAnimation *anime = scene->mAnimations[i]; 
       int framesInAnimation = ceil(anime->mDuration * ANIMATION_IMPORT_FPS); 

       Animation *animation = new Animation(); 
       animation->name = anime->mName.C_Str(); 
       loadAnimation(animation, framesInAnimation); 
       animations.push_back(animation); 
      } 
     } 
     else { 
      Animation *animation = new Animation(); 
      animation->name = "Default"; 
      loadAnimation(animation, 1); 
      animations.push_back(animation); 
     } 
     printf("Done loading '%s'\n", filePath.c_str()); 
    } 
    else { 
     //Report error 
     printf("Assimp error: %s\n", importer.GetErrorString()); 
    } 
} 

void AssimpMesh::loadAnimation(Animation *animation, int numFrames) { 
    int nextKeyframe = -1; 
    int nextKeyframeId = -1; 
    int transedFrames = 0; 
    aiVector3D transPos = aiVector3D(); 
    aiVector3D transVec = aiVector3D(); 

    for (int f = 0; f < numFrames; f++) { 
     Frame *frame = new Frame(); 

     if (f > nextKeyframe && nextKeyframe < numFrames) { 
      //Get the new keyframe 
      aiAnimation *anime = scene->mAnimations[animations.size()]; 
      aiNodeAnim *aniNode = anime->mChannels[0]; 
      aiVectorKey key = aniNode->mPositionKeys[++nextKeyframeId]; 
      nextKeyframe = ceil(key.mTime * ANIMATION_IMPORT_FPS); 

      if (!nextKeyframeId) { 
       transVec = key.mValue; 
       transPos = key.mValue; 
      } 
      else { 
       int transFrames = nextKeyframe - (f - 1); 
       aiVector3D transDir = key.mValue - transPos; 
       transPos = key.mValue; 
       transVec = transDir; 
       transVec /= transFrames; 
       transedFrames = 0; 
      } 
     } 

     if (scene->HasLights()) { 
      aiLight *light = scene->mLights[0]; 
      //lightPosition = light->mPosition; 
     } 

     //Put data into vertex arrays 
     transedFrames++; 
     aiMesh *mesh; 
     MeshData *data; 
     for (int i = 0; i < scene->mNumMeshes; i++) { 
      mesh = scene->mMeshes[i]; 
      data = new MeshData(); 

      if (!i) { 
       for (int j = 0; j < mesh->mNumVertices; j++) { 
        if (!f) { 
         data->transedVertices.push_back(mesh->mVertices[j] + transVec); 
        } 
        else { 
         data->transedVertices.push_back(animation->frames[f-1]->meshes[i]->transedVertices[j] + transVec); 
        } 
       } 
      } 

      //Assign VBO 
      initMesh(mesh, data); 

      //Assign shader 
      if (perMeshShading) { 
       initShader(mesh, data); 
       setUniforms(mesh, data); 
      } 

      frame->meshes.push_back(data); 
     } 

     animation->frames.push_back(frame); 
    } 
} 

void AssimpMesh::initMesh(aiMesh *mesh, MeshData *data) { 
    //Buffer for temporary storage of new ids 
    GLuint id; 

    //Make vertex array 
    if (!initialized) { 
     glGenVertexArrays(1, &id); 
    } 
    data->meshArray = id; 

    //Tell OpenGL to use this array 
    glBindVertexArray(id); 

    //Assign vertices 
    if (mesh->HasPositions()) { 
     //Make buffer 
     if (!initialized) { 
      glGenBuffers(1, &id); 
     } 
     data->buffers.push_back(id); 
     data->bufferNames.push_back("Positions"); 

     //Set buffer data 
     glBindBuffer(GL_ARRAY_BUFFER, id); 
     if (data->transedVertices.size()) { 
      glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D) * data->transedVertices.size(), &data->transedVertices[0], GL_STATIC_DRAW); 
     } 
     else { 
      glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D) * mesh->mNumVertices, &mesh->mVertices[0], GL_STATIC_DRAW); 
     } 
     //Set shader attribute data 
     glEnableVertexAttribArray(VBO_VERTEX); 
     glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL); 
    } 

    unsigned int matId = mesh->mMaterialIndex; 
    aiMaterial *material = scene->mMaterials[matId]; 
    vector <aiColor3D> colors; 
    aiColor3D diffuse(0, 0, 0); 
    material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); 

    for (int i = 0; i < mesh->mNumVertices; i++) { 
     colors.push_back(diffuse); 
    } 

    //Make buffer 
    if (!initialized) { 
     glGenBuffers(1, &id); 
    } 
    data->buffers.push_back(id); 
    data->bufferNames.push_back("Colors"); 

    //Set buffer data 
    glBindBuffer(GL_ARRAY_BUFFER, id); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(aiColor3D) * mesh->mNumVertices, &colors.front(), GL_STATIC_DRAW); 

    //Set shader attribute data 
    glEnableVertexAttribArray(VBO_COLOR); 
    glVertexAttribPointer(VBO_COLOR, 3, GL_FLOAT, GL_FALSE, NULL, NULL); 

    //Assign texture coords 
    if (mesh->HasTextureCoords(0)) { 
     //Make buffer 
     if (!initialized) { 
      glGenBuffers(1, &id); 
     } 
     data->buffers.push_back(id); 
     data->bufferNames.push_back("TextureCoords"); 

     //Set buffer data 
     glBindBuffer(GL_ARRAY_BUFFER, id); 
     glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D) * mesh->mNumVertices, &mesh->mTextureCoords[0], GL_STATIC_DRAW); 

     //Set shader attribute data 
     glEnableVertexAttribArray(VBO_TEXCORD); 
     glVertexAttribPointer(VBO_TEXCORD, 3, GL_FLOAT, GL_FALSE, NULL, NULL); 
    } 

    //Assign colors 
    if (mesh->HasNormals()) { 
     //Make buffer 
     if (!initialized) { 
      glGenBuffers(1, &id); 
     } 
     data->buffers.push_back(id); 
     data->bufferNames.push_back("Normals"); 

     //Set buffer data 
     glBindBuffer(GL_ARRAY_BUFFER, id); 
     glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D) * mesh->mNumVertices, &mesh->mNormals[0], GL_STATIC_DRAW); 

     //Set shader attribute data 
     glEnableVertexAttribArray(VBO_NORMAL); 
     glVertexAttribPointer(VBO_NORMAL, 3, GL_FLOAT, GL_FALSE, NULL, NULL); 
    } 

    if (mesh->HasFaces()) { 
     vector <unsigned int> indices; 
     aiFace face; 
     for (int i = 0; i < mesh->mNumFaces; i++) { 
      face = mesh->mFaces[i]; 
      for (int j = 0; j < face.mNumIndices; j++) { 
       indices.push_back(face.mIndices[j]); 
      } 
     } 
     data->totalIndices = indices.size(); 

     //Make buffer 
     if (!initialized) { 
      glGenBuffers(1, &id); 
     } 
     data->buffers.push_back(id); 
     data->bufferNames.push_back("Faces"); 

     //Set buffer data 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id); 
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indices.size(), &indices.front(), GL_STATIC_DRAW); 
    } 
} 

는, 아직 모든 작동하지 않습니다. 사실 번역 및 전체 모델. 분명히 그것은 이름 값을 올바르게 읽지 않아서 애니메이션이 의미하는 메시가 될 수 없습니다. 그러나 그것은 나에게 달렸어, 어쩌면 누군가 도움이 될지도 모른다. =)