Skip to content

Commit

Permalink
Merge pull request #596 from zeux/gltf-objext
Browse files Browse the repository at this point in the history
gltfpack: Enhance .obj parsing by preserving more information
  • Loading branch information
zeux authored Aug 23, 2023
2 parents fd0b723 + 5dccdc3 commit 9c6759b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 13 deletions.
4 changes: 4 additions & 0 deletions gltf/gltfpack.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#define _CRT_SECURE_NO_WARNINGS
#endif

#ifndef _CRT_NONSTDC_NO_WARNINGS
#define _CRT_NONSTDC_NO_WARNINGS
#endif

#include "../extern/cgltf.h"

#include <assert.h>
Expand Down
88 changes: 75 additions & 13 deletions gltf/parseobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ static int textureIndex(const std::vector<std::string>& textures, const char* na
return -1;
}

static cgltf_data* parseSceneObj(fastObjMesh* obj)
static void fixupUri(char* uri)
{
cgltf_data* data = (cgltf_data*)calloc(1, sizeof(cgltf_data));
data->memory.free_func = defaultFree;
// Some .obj paths come with back slashes, that are invalid as URI separators and won't open on macOS/Linux when embedding textures
for (char* s = uri; *s; ++s)
if (*s == '\\')
*s = '/';
}

static void parseMaterialsObj(fastObjMesh* obj, cgltf_data* data)
{
std::vector<std::string> textures;

for (unsigned int mi = 0; mi < obj->material_count; ++mi)
Expand All @@ -41,8 +46,8 @@ static cgltf_data* parseSceneObj(fastObjMesh* obj)

for (size_t i = 0; i < textures.size(); ++i)
{
data->images[i].uri = (char*)malloc(textures[i].size() + 1);
strcpy(data->images[i].uri, textures[i].c_str());
data->images[i].uri = strdup(textures[i].c_str());
fixupUri(data->images[i].uri);
}

data->textures = (cgltf_texture*)calloc(textures.size(), sizeof(cgltf_texture));
Expand All @@ -58,14 +63,19 @@ static cgltf_data* parseSceneObj(fastObjMesh* obj)

for (unsigned int mi = 0; mi < obj->material_count; ++mi)
{
const fastObjMaterial& om = obj->materials[mi];
cgltf_material& gm = data->materials[mi];
fastObjMaterial& om = obj->materials[mi];

if (om.name)
gm.name = strdup(om.name);

gm.has_pbr_metallic_roughness = true;

gm.pbr_metallic_roughness.base_color_factor[0] = 1.0f;
gm.pbr_metallic_roughness.base_color_factor[1] = 1.0f;
gm.pbr_metallic_roughness.base_color_factor[2] = 1.0f;
gm.pbr_metallic_roughness.base_color_factor[3] = 1.0f;

gm.pbr_metallic_roughness.metallic_factor = 0.0f;
gm.pbr_metallic_roughness.roughness_factor = 1.0f;

Expand All @@ -78,17 +88,58 @@ static cgltf_data* parseSceneObj(fastObjMesh* obj)

gm.alpha_mode = (om.illum == 4 || om.illum == 6 || om.illum == 7 || om.illum == 9) ? cgltf_alpha_mode_mask : cgltf_alpha_mode_opaque;
}
else
{
gm.pbr_metallic_roughness.base_color_factor[0] = om.Kd[0];
gm.pbr_metallic_roughness.base_color_factor[1] = om.Kd[1];
gm.pbr_metallic_roughness.base_color_factor[2] = om.Kd[2];
}

if (om.map_d.name)
{
if (om.map_Kd.name && strcmp(om.map_Kd.name, om.map_d.name) != 0)
fprintf(stderr, "Warning: material has different diffuse and alpha textures (Kd: %s, d: %s) and might not render correctly\n", om.map_Kd.name, om.map_d.name);

gm.alpha_mode = cgltf_alpha_mode_blend;
}
else if (om.d < 1.0f)
{
gm.pbr_metallic_roughness.base_color_factor[3] = om.d;

gm.alpha_mode = cgltf_alpha_mode_blend;
}
}
}

static void parseNodesObj(fastObjMesh* obj, cgltf_data* data)
{
data->nodes = (cgltf_node*)calloc(obj->object_count, sizeof(cgltf_node));
data->nodes_count = obj->object_count;

for (unsigned int oi = 0; oi < obj->object_count; ++oi)
{
const fastObjGroup& og = obj->objects[oi];
cgltf_node* node = &data->nodes[oi];

if (og.name)
node->name = strdup(og.name);

node->rotation[3] = 1.0f;
node->scale[0] = 1.0f;
node->scale[1] = 1.0f;
node->scale[2] = 1.0f;
}

data->scenes = (cgltf_scene*)calloc(1, sizeof(cgltf_scene));
data->scenes_count = 1;

return data;
data->scene = data->scenes;

data->scenes->nodes = (cgltf_node**)calloc(obj->object_count, sizeof(cgltf_node*));
data->scenes->nodes_count = obj->object_count;

for (unsigned int oi = 0; oi < obj->object_count; ++oi)
data->scenes->nodes[oi] = &data->nodes[oi];
}

static void parseMeshObj(fastObjMesh* obj, unsigned int face_offset, unsigned int face_vertex_offset, unsigned int face_count, unsigned int face_vertex_count, unsigned int index_count, Mesh& mesh)
Expand Down Expand Up @@ -179,19 +230,20 @@ static void parseMeshObj(fastObjMesh* obj, unsigned int face_offset, unsigned in
assert(index_offset == index_count);
}

static void parseMeshesObj(fastObjMesh* obj, cgltf_data* data, std::vector<Mesh>& meshes)
static void parseMeshGroupObj(fastObjMesh* obj, const fastObjGroup& og, cgltf_data* data, cgltf_node* node, std::vector<Mesh>& meshes)
{
unsigned int face_vertex_offset = 0;
unsigned int face_vertex_offset = og.index_offset;
unsigned int face_end_offset = og.face_offset + og.face_count;

for (unsigned int face_offset = 0; face_offset < obj->face_count; )
for (unsigned int face_offset = og.face_offset; face_offset < face_end_offset; )
{
unsigned int mi = obj->face_materials[face_offset];

unsigned int face_count = 0;
unsigned int face_vertex_count = 0;
unsigned int index_count = 0;

for (unsigned int fj = face_offset; fj < obj->face_count && obj->face_materials[fj] == mi; ++fj)
for (unsigned int fj = face_offset; fj < face_end_offset && obj->face_materials[fj] == mi; ++fj)
{
face_count += 1;
face_vertex_count += obj->face_vertices[fj];
Expand All @@ -210,6 +262,9 @@ static void parseMeshesObj(fastObjMesh* obj, cgltf_data* data, std::vector<Mesh>
mesh.type = cgltf_primitive_type_triangles;
mesh.targets = 0;

if (node)
mesh.nodes.push_back(node);

parseMeshObj(obj, face_offset, face_vertex_offset, face_count, face_vertex_count, index_count, mesh);

face_offset += face_count;
Expand All @@ -227,9 +282,16 @@ cgltf_data* parseObj(const char* path, std::vector<Mesh>& meshes, const char** e
return 0;
}

cgltf_data* data = parseSceneObj(obj);
cgltf_data* data = (cgltf_data*)calloc(1, sizeof(cgltf_data));
data->memory.free_func = defaultFree;

parseMaterialsObj(obj, data);

parseNodesObj(obj, data);
assert(data->nodes_count == obj->object_count);

parseMeshesObj(obj, data, meshes);
for (unsigned int oi = 0; oi < obj->object_count; ++oi)
parseMeshGroupObj(obj, obj->objects[oi], data, &data->nodes[oi], meshes);

fast_obj_destroy(obj);

Expand Down

0 comments on commit 9c6759b

Please sign in to comment.