diff options
author | dec05eba <dec05eba@protonmail.com> | 2020-02-28 23:45:47 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2020-02-28 23:45:47 +0100 |
commit | 8b8a84334f234b21945e8433ba3bd7d117ca69d9 (patch) | |
tree | c1178f5b06b084f62a8733adc4d17d364a459f7a /src |
Initial commit, it works
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..a679828 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,114 @@ +#include <assert.h> +#include <stdio.h> + +#include <assimp/Importer.hpp> +#include <assimp/postprocess.h> +#include <assimp/scene.h> +#include <assimp/DefaultLogger.hpp> +#include <assimp/LogStream.hpp> + +static void usage(); +static void file_write_error_check(FILE *file, const void *data, size_t size); +static void file_write_uint_error_check(FILE *file, unsigned int value); +static void process_node(const aiScene *scene, const aiNode *node, FILE *output_file); + +int main(int argc, char **argv) { + if(argc != 3) + usage(); + + const char *source_filepath = argv[1]; + const char *destination_filepath = argv[2]; + + Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE; + Assimp::DefaultLogger::create("", severity, aiDefaultLogStream_STDERR); + + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(source_filepath, aiProcessPreset_TargetRealtime_Quality | aiProcess_Triangulate | aiProcess_FlipUVs); + if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { + fprintf(stderr, "Failed to load file: %s, reason: %s\n", source_filepath, importer.GetErrorString()); + exit(2); + } + + FILE *destination_file = fopen(destination_filepath, "wb"); + if(!destination_file) { + perror(destination_filepath); + exit(3); + } + file_write_uint_error_check(destination_file, 0x036144AF); // magic number + file_write_uint_error_check(destination_file, 0x00000001); // version + + process_node(scene, scene->mRootNode, destination_file); + fclose(destination_file); + Assimp::DefaultLogger::kill(); + return 0; +} + +void usage() { + fprintf(stderr, "usage: amalgine-model-converter <source> <destination>\n"); + exit(1); +} + +void file_write_error_check(FILE *file, const void *data, size_t size) { + if(fwrite(data, 1, size, file) != size) { + fprintf(stderr, "Error: failed to write %ld bytes to output file, error: %s\n", size, strerror(errno)); + exit(4); + } +} + +void file_write_uint_error_check(FILE *file, unsigned int value) { + const size_t size = sizeof(value); + if(fwrite(&value, 1, size, file) != size) { + fprintf(stderr, "Error: failed to write %ld bytes to output file, error: %s\n", size, strerror(errno)); + exit(4); + } +} + +static void process_mesh(const aiScene *scene, const aiMesh *mesh, FILE *output_file) { + file_write_uint_error_check(output_file, mesh->mNumVertices); + file_write_error_check(output_file, &mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D)); + file_write_error_check(output_file, &mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D)); + + file_write_uint_error_check(output_file, mesh->mNumFaces); + for(unsigned int i = 0; i < mesh->mNumFaces; ++i) { + // Should always be 3 since the file was loaded with aiProcess_Triangulate + file_write_error_check(output_file, mesh->mFaces[i].mIndices, 3 * sizeof(unsigned int)); + } + + file_write_uint_error_check(output_file, mesh->mTextureCoords[0] ? 1 : 0); + if(mesh->mTextureCoords[0]) + file_write_error_check(output_file, &mesh->mTextureCoords[0], mesh->mNumVertices * sizeof(aiVector3D)); + + file_write_uint_error_check(output_file, mesh->mMaterialIndex < scene->mNumMaterials); + if(mesh->mMaterialIndex < scene->mNumMaterials) { + const unsigned int num_texture_types = 3; + const aiTextureType texture_types[num_texture_types] = { + aiTextureType_DIFFUSE, + aiTextureType_SPECULAR, + aiTextureType_AMBIENT + }; + + const aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; + for(unsigned int i = 0; i < num_texture_types; ++i) { + unsigned int num_textures_for_type = material->GetTextureCount(texture_types[i]); + file_write_uint_error_check(output_file, num_textures_for_type); + for(unsigned int j = 0; j < num_textures_for_type; ++j) { + aiString str; + if(material->GetTexture(texture_types[i], j, &str) == aiReturn_SUCCESS) + file_write_error_check(output_file, str.data, str.length + 1); // +1 to include null-terminate character + else + file_write_error_check(output_file, "\0", 1); + } + } + } +} + +void process_node(const aiScene *scene, const aiNode *node, FILE *output_file) { + for(unsigned int i = 0; i < node->mNumMeshes; ++i) { + const aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; + process_mesh(scene, mesh, output_file); + } + + for(unsigned int i = 0; i < node->mNumChildren; ++i) { + process_node(scene, node->mChildren[i], output_file); + } +}
\ No newline at end of file |