diff --git a/gltf/gltfpack.h b/gltf/gltfpack.h index 4b4c71ed7..b186f66fd 100644 --- a/gltf/gltfpack.h +++ b/gltf/gltfpack.h @@ -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 diff --git a/gltf/parseobj.cpp b/gltf/parseobj.cpp index 9768e8e2a..90fdc069d 100644 --- a/gltf/parseobj.cpp +++ b/gltf/parseobj.cpp @@ -21,11 +21,16 @@ static int textureIndex(const std::vector& 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 textures; for (unsigned int mi = 0; mi < obj->material_count; ++mi) @@ -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)); @@ -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; @@ -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) @@ -179,11 +230,12 @@ 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& meshes) +static void parseMeshGroupObj(fastObjMesh* obj, const fastObjGroup& og, cgltf_data* data, cgltf_node* node, std::vector& 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]; @@ -191,7 +243,7 @@ static void parseMeshesObj(fastObjMesh* obj, cgltf_data* data, std::vector 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]; @@ -210,6 +262,9 @@ static void parseMeshesObj(fastObjMesh* obj, cgltf_data* data, std::vector 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; @@ -227,9 +282,16 @@ cgltf_data* parseObj(const char* path, std::vector& 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);