0

Im trying to apply the model's transforms by walking the node heirarchy, but the poses are wrong (im not trying to animate it, just load it in a pose by using the transforms given in the gtlf file)

heres the code for loading the model

int mesh_idx = 0;
void ProcessAssimpMesh(struct aiMesh *mesh, const struct aiScene *scene, 
 Assimp_mesh **mesh_list, mat4 transform)
{
 Assimp_mesh *a_mesh = &(*mesh_list)[mesh_idx];
 int ptr = 0; 
 // 1. ALLOCATE MEMORY for vertices
 int vertex_size = 8; // 3 pos + 2 tex + 3 normal
 int total_vertices = mesh->mNumVertices * vertex_size;
 
 a_mesh->vertices = (GLfloat*)malloc(sizeof(GLfloat) * total_vertices);
 
 if (!a_mesh->vertices) {
 printf("ERROR: Failed to allocate memory for vertices\n");
 return;
 }
 // 2. PROCESS VERTICES
 for (size_t i = 0; i < mesh->mNumVertices; i++)
 {
 // Position
 a_mesh->vertices[ptr++] = mesh->mVertices[i].x;
 a_mesh->vertices[ptr++] = mesh->mVertices[i].y;
 a_mesh->vertices[ptr++] = mesh->mVertices[i].z;
 // Texture coordinates
 if (mesh->mTextureCoords[0]) {
 a_mesh->vertices[ptr++] = mesh->mTextureCoords[0][i].x;
 a_mesh->vertices[ptr++] = mesh->mTextureCoords[0][i].y;
 } else {
 a_mesh->vertices[ptr++] = 0.0f;
 a_mesh->vertices[ptr++] = 0.0f;
 }
 // Normals
 if (mesh->mNormals) {
 a_mesh->vertices[ptr++] = mesh->mNormals[i].x;
 a_mesh->vertices[ptr++] = mesh->mNormals[i].y;
 a_mesh->vertices[ptr++] = mesh->mNormals[i].z;
 } else {
 a_mesh->vertices[ptr++] = 0.0f;
 a_mesh->vertices[ptr++] = 0.0f;
 a_mesh->vertices[ptr++] = 0.0f;
 }
 }
 a_mesh->vertex_count = ptr;
 glm_mat4_identity(a_mesh->transformation);
 glm_mat4_copy(transform, a_mesh->transformation);
 
 // 3. PROCESS INDICES
 a_mesh->index_count = mesh->mNumFaces * 3;
 a_mesh->indices = (unsigned int*)malloc(sizeof(unsigned int) * a_mesh->index_count);
 
 if (a_mesh->indices) {
 unsigned int index_ptr = 0;
 for (size_t i = 0; i < mesh->mNumFaces; i++) {
 a_mesh->indices[index_ptr++] = mesh->mFaces[i].mIndices[0];
 a_mesh->indices[index_ptr++] = mesh->mFaces[i].mIndices[1];
 a_mesh->indices[index_ptr++] = mesh->mFaces[i].mIndices[2];
 }
 }
 a_mesh->mesh_name = strdup(mesh->mName.data);
 a_mesh->identifier = mesh_idx;
 mesh_idx++;
}
void convert_backslash_to_frontslash(char *str, int len)
{
 for (size_t i = 0; i < len; i++)
 {
 if (str[i] == '\\')
 {
 str[i] = '/';
 }
 }
}
void ProcessMaterialTextures(struct aiMaterial **materials, struct aiMesh *mesh, Assimp_mesh *created_mesh, char *model_path, const struct aiScene *scene)
{
 const struct aiMaterial *mat = materials[mesh->mMaterialIndex];
 struct aiString path;
 aiReturn ok;
 ok = aiGetMaterialTexture(
 mat, aiTextureType_DIFFUSE, 0, &path, NULL, NULL, NULL, NULL, NULL, NULL
 );
 if (ok == AI_SUCCESS)
 {
 if (path.data[0] == '*')
 {
 printf("Embedded texture\n");
 created_mesh->texture.embedded = 1;
 int idx = atoi(path.data+1);
 if (idx >= 0 && idx < scene->mNumTextures)
 {
 struct aiTexture *tex = scene->mTextures[idx];
 created_mesh->texture.embedded_data = (unsigned char *)tex->pcData;
 created_mesh->texture.embedded_len = tex->mWidth;
 printf("Created embedded texture %d, data length %d\n", idx, created_mesh->texture.embedded_len);
 } else
 {
 printf("Embedded texture idx out of range\n");
 }
 } else
 {
 printf("External texture\n");
 created_mesh->texture.texture_id = mesh->mMaterialIndex;
 created_mesh->texture.embedded = 0;
 char actual_path[4096];
 strcpy(actual_path, model_path);
 strcat(actual_path, "\\");
 strcat(actual_path, path.data);
 convert_backslash_to_frontslash(actual_path, 4096);
 created_mesh->texture.texture_path = strdup(actual_path);
 created_mesh->texture.has_texture = 1;
 }
 } else
 {
 printf("mesh %d has no diffuse texture\n", created_mesh->identifier);
 created_mesh->texture.has_texture = 0;
 }
}
static inline void aimat4x4_to_cglm(const struct aiMatrix4x4 *m, mat4 out)
{
 out[0][0] = m->a1; out[0][1] = m->b1; out[0][2] = m->c1; out[0][3] = m->d1;
 out[1][0] = m->a2; out[1][1] = m->b2; out[1][2] = m->c2; out[1][3] = m->d2;
 out[2][0] = m->a3; out[2][1] = m->b3; out[2][2] = m->c3; out[2][3] = m->d3;
 out[3][0] = m->a4; out[3][1] = m->b4; out[3][2] = m->c4; out[3][3] = m->d4;
}
void ProcessAssimpNode(const struct aiScene *scene, const struct aiNode *node, mat4 parentMat, Assimp_mesh **meshes)
{
 mat4 local, world; glm_mat4_identity(local); glm_mat4_identity(world);
 aimat4x4_to_cglm(&node->mTransformation, local);
 glm_mat4_transpose(local);
 glm_mat4_mul(local, parentMat, world);
 for (size_t i = 0; i < node->mNumMeshes; i++)
 {
 ProcessAssimpMesh(scene->mMeshes[node->mMeshes[i]], scene, meshes, world);
 }
 
 for (size_t i = 0; i < node->mNumChildren; i++)
 {
 ProcessAssimpNode(scene, node->mChildren[i], world, meshes);
 }
}
Assimp_object LoadAssimp(const char *fname)
{
 const struct aiScene *scene = aiImportFile(fname,
 aiProcess_Triangulate |
 aiProcess_CalcTangentSpace |
 aiProcess_GenSmoothNormals |
 aiProcess_JoinIdenticalVertices |
 aiProcess_FlipUVs 
 );
 Assimp_object ass;
 Assimp_mesh *meshes = malloc( sizeof(Assimp_mesh) * scene->mNumMeshes );
 char model_path[PATH_MAX];
 strcpy(model_path, fname);
 PathRemoveFileSpecA(model_path);
 mat4 test_matrice;
 glm_mat4_identity(test_matrice);
 //glm_rotate_y(test_matrice, glm_rad(90), test_matrice);
 ProcessAssimpNode(scene, scene->mRootNode, test_matrice, &meshes);
 for (size_t i = 0; i < scene->mNumMeshes; i++)
 {
 ProcessMaterialTextures(scene->mMaterials, scene->mMeshes[i], &meshes[i], model_path, scene);
 }
 ass.meshes = meshes;
 ass.n_meshes = scene->mNumMeshes;
 
 aiReleaseImport(scene);
 return ass;
}

heres how i create the model to render it

Model_blueprint RendererCreateModelAOS(
 GLfloat *vertices, GLsizeiptr vertices_size,
 GLint *indices, GLsizeiptr indices_size,
 VAOAttribute *vao_attributes, int n_vao_attrs,
 char *vertex_shader_path, char *fragment_shader_path
)
{
 Model_blueprint model;
 
 model.vertices_size = vertices_size;
 model.indices_size = indices_size;
 model.vertices = (GLfloat *)malloc(model.vertices_size);
 model.indices = (GLint *)malloc(model.indices_size);
 if (model.vertices != NULL && model.indices != NULL)
 {
 memcpy(model.vertices, vertices, model.vertices_size);
 memcpy(model.indices, indices, model.indices_size);
 } else {printf("Error\n");}
 if (model.indices == NULL || model.vertices == NULL)
 {
 printf("Error\n");
 }
 char *vertex_shader = LoadShaderFromFile(vertex_shader_path);
 char *fragment_shader = LoadShaderFromFile(fragment_shader_path);
 GLuint vertex_shader_addr = CreateCompileShader(GL_VERTEX_SHADER, vertex_shader);
 GLuint frag_shader_addr = CreateCompileShader(GL_FRAGMENT_SHADER, fragment_shader);
 GLuint shaders[2] = {vertex_shader_addr, frag_shader_addr};
 GLuint shader_program = ShaderProgramCreateAttachLink(shaders, 2);
 DeleteShaders(shaders, 2);
 model.shader_program = shader_program;
 GLuint VAO, VBO, EBO;
 glGenVertexArrays(1, &VAO);
 glGenBuffers(1, &VBO);
 glGenBuffers(1, &EBO);
 VAOBindVertexArray(VAO);
 VBOBindWithData(VBO, model.vertices_size, model.vertices, GL_STATIC_DRAW);
 EBOBindWithData(EBO, model.indices_size, model.indices, GL_STATIC_DRAW);
 for (size_t i = 0; i < n_vao_attrs; i++)
 {
 VAOAttribSetAndEnable(vao_attributes[i], VBO);
 }
 model.VAO = VAO; model.VBO = VBO; model.EBO = EBO;
 VBOBindWithData(0, 0, (void *)0, 0);
 VAOBindVertexArray(0);
 EBOBindWithData(0, 0, (void *)0, 0);
 return model;
}
// creates the data for the vbo and ebo
Model_blueprint *RendererCreateModel(Assimp_object ass, char *vertex_shader_path, char *fragment_shader_path)
{
 Model_blueprint *models;
 models = malloc(sizeof(Model_blueprint) * ass.n_meshes);
 VAOAttribute *attribs = VAOCreateVAOAttributeArrays(3);
 attribs[0] = (VAOAttribute){0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(0 * sizeof(float))};
 attribs[1] = (VAOAttribute){1, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3 * sizeof(float))};
 attribs[2] = (VAOAttribute){2, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(5 * sizeof(float))};
 printf("Starting to create model\n");
 
 for (size_t i = 0; i < ass.n_meshes; i++)
 {
 models[i] = RendererCreateModelAOS(
 ass.meshes[i].vertices,
 ass.meshes[i].vertex_count * sizeof(GLfloat),
 ass.meshes[i].indices,
 ass.meshes[i].index_count * sizeof(GLuint),
 attribs, 3, vertex_shader_path, fragment_shader_path
 );
 
 models[i].indices_count = ass.meshes[i].index_count;
 models[i].model_name = ass.meshes[i].mesh_name;
 glm_mat4_identity(models[i].model);
 glm_mat4_copy(ass.meshes[i].transformation, models[i].model);
 models[i].texture = 0;
 if (ass.meshes[i].texture.has_texture)
 {
 TextureCreateTexture(&models[i].texture, models[i].shader_program, "tex0", 0, ass.meshes[i].texture.texture_path, ass.meshes[i].texture.embedded, ass.meshes[i].texture);
 }
 }
 return models;
}

heres the rendering loop

while (!glfwWindowShouldClose(window))
{
 int w, h;
 glfwGetFramebufferSize(window, &w, &h);
 glClearColor(0.176, 0.176, 0.188, 1);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
 // Process input
 camera_process_keyboard(&cam, window);
 camera_process_mouse(&cam, window, WIDTH, HEIGHT);
 
 // Update camera matrices
 camera_update_view(&cam);
 float aspect = (float)WIDTH/(float)HEIGHT;
 camera_update_projection(&cam, 45, aspect, 0.1, 100.0);
 glm_mat4_mul(cam.projection, cam.view, camMat);
 /*
 DRAWING THE MODELS
 */
 
 if (WIREFRAME_MODE)
 {
 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 }
 for (size_t i = 0; i < n_models; i++)
 {
 UniformSend4x4Matrix(models[i].shader_program, "camMat", camMat);
 UniformSend4x4Matrix(models[i].shader_program, "model", models[i].model);
 if (i == selected_model) {
 UniformSendVec4(models[i].shader_program, "lightC", selected_color);
 } else {
 UniformSendVec4(models[i].shader_program, "lightC", c.color);
 }
 UniformSendVec3(models[i].shader_program, "lightPos", c.position);
 if (models[i].texture != 0)
 {
 TextureBindTexture(models[i], GL_TEXTURE_2D);
 }
 
 EBODraw(models[i].indices_count, GL_UNSIGNED_INT, models[i].VAO);
 }
 UniformSend4x4Matrix(c.shader_program, "camMat", camMat);
 UniformSend4x4Matrix(c.shader_program, "model", c.model);
 UniformSendVec4(c.shader_program, "lightC", c.color);
 EBODraw(ARRAY_LEN(lightIndices), GL_UNSIGNED_INT, c.VAO);
 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 /*
 DRAWING THE GUI
 */

i transform the model in the vertex shader as so

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTex;
layout (location = 2) in vec3 aNormal;
out vec2 texCoord;
out vec3 Normal;
out vec3 currentPos;
uniform mat4 camMat;
uniform mat4 model;
void main()
{
 vec4 v4Pos = model * vec4(aPos, 1.0f);
 currentPos = v4Pos.xyz; 
 gl_Position = camMat * v4Pos;
 texCoord = aTex;
 Normal = mat3(transpose(inverse(model))) * aNormal;
}

any help?

NOTE: i know that i am multiplying the parent and node matrices correctly as if i set a test matrix (glm_rotate_y example) the entire model is rotated correctly, and i know the model cant be broken since other loaders (assimp's viewer, window's model viewer and blender) all load it correctly in the correct pose

but i cant figure out why mine isnt proper, either assimp loads the transforms incorrectly or some other problem in my code

genpfault
52.3k12 gold badges93 silver badges153 bronze badges
asked Nov 12 at 6:17
New contributor
Muaaz Khan is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
0

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.