我创建了一个容器类,它基本上包含了渲染动画所需的所有信息。我正在使用Assimp库来加载动画。然后将scene->mVertices
等数据分配给我的数组缓冲区,我找不到的是我应该如何将其他帧的数据存入我的缓冲区!
我知道有一个名为HasAnimations()
的函数,还有一个aiAnimation **mAnimations
。但是,我无法找到与获取下一组顶点数据相关的任何数据。
我已经设法加载了一系列obj文件并绘制它们以确认我的类正常工作。但显然,当我想扩展到真正的交易时,我更愿意或者通常需要使用别的东西。因为单独装载250帧需要几分钟。 (加载一个简单的动画应该在大约5秒内完成,对吗?)
我愿意使用任何类型的文件格式。但我需要知道如何在Blender中设置它以便动画将被导出。因为我现在似乎也失败了,因为我对Blender几乎没有经验。
我一直在寻找关于这个库和搅拌机出口2天的教程,发现几乎没什么用处。我确实查看了Assimp的文档,这对我来说是迄今为止,但没有解释aiAnimation如何影响顶点。或者我如何获得我需要的其他数据帧。
答案 0 :(得分:0)
好吧,我确实设法让它在无数个小时后工作!排序...我创建了一个在循环x+5, y+5, x-5, y-5
中转换的模型...
我最终做了什么,这是我唯一能想到的事情。正在读取场景中的数据 - > mAnimations [],这基本上只包含关键帧数组。所以我不得不自己插入所有顶点(这总是一个有趣的任务!)。
用途不同:
在这些步骤之后,我得到了这样的东西:
部首:
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);
}
}
当然,它对一切都不起作用。实际上只翻译和整个模型。显然它没有正确读取名称值,所以我不能用于动画的网格。但它让我走了,也许有人会觉得这很有帮助。 =)