167 lines
5.6 KiB
C
167 lines
5.6 KiB
C
/*
|
|
* obj_exporter.c
|
|
*
|
|
* Created on: 27 juil. 2022
|
|
* Author: JackCarterSmith
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "errors_types.h"
|
|
#include "options.h"
|
|
#include "hob_struct.h"
|
|
#include "rlk/obj.h"
|
|
#include "obj_exporter.h"
|
|
|
|
|
|
static void mtlPathPatch(const char* out_file, const char* obj_name) ;
|
|
|
|
unsigned char exportOBJModel(T_HOB_OBJECT* hob_objects, const char *out_path) {
|
|
char objExport_path[128];
|
|
char mtlExport_path[128];
|
|
obj* objConstruct = NULL;
|
|
unsigned int i,j;
|
|
int surfID = 0, materialID = 0, tmpVertex = 0, tmpIndex = 0;
|
|
int indexOffset = 0; // Used to compensate reset of indices between face group
|
|
float vertexBuff[3] = {0}, textureBuff[2] = {0};
|
|
int indicesBuff[3] = {0};
|
|
|
|
if (hob_objects == NULL || out_path == NULL)
|
|
return ERROR_ARGS_NULL;
|
|
|
|
if (_options & OUTPUT_DIR) {
|
|
strcpy(objExport_path, out_path);
|
|
#ifdef _WIN32
|
|
strcat(objExport_path, "-out\\");
|
|
#else
|
|
strcat(objExport_path, "-out/");
|
|
#endif
|
|
strcat(objExport_path, hob_objects->name);
|
|
} else {
|
|
strcpy(objExport_path, hob_objects->name);
|
|
}
|
|
strcpy(mtlExport_path, objExport_path);
|
|
strcat(objExport_path, ".obj\0");
|
|
strcat(mtlExport_path, ".mtl\0");
|
|
|
|
objConstruct = obj_create(NULL);
|
|
|
|
// Build face/surface material group
|
|
for ( i = 0; i < hob_objects->face_group_count; i++) {
|
|
surfID = obj_add_surf(objConstruct);
|
|
materialID = obj_add_mtrl(objConstruct);
|
|
|
|
// Build vertex container
|
|
for ( j = 0; j < hob_objects->object_parts[i].vertex_count; j++ ) {
|
|
tmpVertex = obj_add_vert(objConstruct);
|
|
|
|
vertexBuff[0] = ((float)1/1024) * -hob_objects->object_parts[i].vertices[j].x; // Invert X to fix mirror display
|
|
vertexBuff[1] = ((float)1/1024) * -hob_objects->object_parts[i].vertices[j].y; // Invert Y to render upside up
|
|
vertexBuff[2] = ((float)1/1024) * hob_objects->object_parts[i].vertices[j].z;
|
|
obj_set_vert_v(objConstruct, tmpVertex, vertexBuff);
|
|
}
|
|
|
|
// Build indices container and UV mapping
|
|
for ( j = 0; j < hob_objects->object_parts[i].face_count; j++ ) {
|
|
tmpIndex = obj_add_poly(objConstruct, surfID);
|
|
|
|
indicesBuff[0] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[0];
|
|
indicesBuff[1] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[1];
|
|
indicesBuff[2] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[2];
|
|
obj_set_poly(objConstruct, surfID, tmpIndex, indicesBuff);
|
|
|
|
if (hob_objects->object_parts[i].faces[j].flags_bits.fHasTexture) {
|
|
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[0].u;
|
|
textureBuff[1] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[0].v;
|
|
obj_set_vert_t(objConstruct, indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[0], textureBuff);
|
|
|
|
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[1].u;
|
|
textureBuff[1] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[1].v;
|
|
obj_set_vert_t(objConstruct, indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[1], textureBuff);
|
|
|
|
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[2].u;
|
|
textureBuff[1] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[2].v;
|
|
obj_set_vert_t(objConstruct, indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[2], textureBuff);
|
|
}
|
|
|
|
// Process 2 triangles if face is Quad
|
|
if (hob_objects->object_parts[i].faces[j].flags_bits.fIsQuad) {
|
|
tmpIndex = obj_add_poly(objConstruct, surfID);
|
|
|
|
indicesBuff[0] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[0];
|
|
indicesBuff[1] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[2];
|
|
indicesBuff[2] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[3];
|
|
obj_set_poly(objConstruct, surfID, tmpIndex, indicesBuff);
|
|
|
|
if (hob_objects->object_parts[i].faces[j].flags_bits.fHasTexture) {
|
|
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[3].u;
|
|
textureBuff[1] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[3].v;
|
|
obj_set_vert_t(objConstruct, indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[3], textureBuff);
|
|
}
|
|
}
|
|
}
|
|
|
|
indexOffset = obj_num_vert(objConstruct);
|
|
}
|
|
|
|
if (_options & EXPORT_MTL) {
|
|
obj_write(objConstruct, objExport_path, mtlExport_path, 8);
|
|
#if defined(__GNUC__) //TODO: review MSVC file management or include and rewrite obj lib?
|
|
if (_options & OUTPUT_DIR) mtlPathPatch(objExport_path, hob_objects->name);
|
|
#endif
|
|
} else obj_write(objConstruct, objExport_path, NULL, 8);
|
|
|
|
obj_delete(objConstruct);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
static void mtlPathPatch(const char* out_file, const char* obj_name) {
|
|
FILE* obj = NULL;
|
|
char* memFile = NULL;
|
|
long fileSize,i,pos = 0,lines;
|
|
char _path[128],b;
|
|
|
|
obj = fopen(out_file, "r");
|
|
if ( obj != NULL ) {
|
|
fseek(obj, 0, SEEK_END);
|
|
fileSize = ftell(obj);
|
|
fseek(obj, 0, SEEK_SET);
|
|
|
|
// Find the end of first line
|
|
for ( i = 0; i < fileSize + 1; i++) {
|
|
b = (char)fgetc(obj);
|
|
if (b == '\n') {
|
|
if (pos == 0) pos = i;
|
|
lines++;
|
|
}
|
|
}
|
|
|
|
// Prepare mtl path for output
|
|
strcpy(_path, obj_name);
|
|
strcat(_path, ".mtl");
|
|
|
|
memFile = malloc(fileSize - (pos + lines));
|
|
if ( memFile != NULL ) {
|
|
// Read the rest of file in memory
|
|
fseek(obj, pos, SEEK_SET);
|
|
fread(memFile, fileSize - (pos + lines), 1, obj);
|
|
fclose(obj);
|
|
|
|
// Begin rewrite file
|
|
obj = fopen(out_file, "w");
|
|
fprintf(obj, "mtllib %s", _path);
|
|
#if defined(_MSC_VER)
|
|
fwrite(memFile, fileSize - pos , 1, obj);
|
|
#elif defined(__GNUC__)
|
|
fwrite(memFile, fileSize - (pos + lines), 1, obj);
|
|
#endif
|
|
|
|
free(memFile);
|
|
}
|
|
|
|
fclose(obj);
|
|
}
|
|
}
|