Open martinhath opened 4 years ago
It's just an unimplemented feature.
We need to implement a feature to supply search path to .mtl
file or a callback function for mtllib
to tinyobj_parse_obj
API.
PR is welcome!
@martinhath If you would like a solution to link object's materials to mtllib materials, I created a solution to instead to get the object name, get its material name, and use that material name to then look for its corresponding texture. Let me know if you would like me to upload it here :)
@syoyo Glad to hear it!
@iyenal I have a folder full of obj
and corresponding mtl
files, so I think the original route of finding the mtl
from the location of the obj
would be best for me. Thanks anyways!
I ended up hacking something together in which the user can supply the filename of the obj
, extract the directory from that, and append the relative path onto it. Since I'll always supply the filename, I didn't bother (yet) having any error checks, so the code is likely brittle to anyone that doesn't have my exact use-case.
I appreciate the decoupling of file reading and .obj
parsing that the current API has, and so I don't think my current solution is fit for integration in the library. This might be what @syoyo is suggesting, but I think a better solution is to have tinyobj_parrse_obj
take a char *(*cb)(const char *rel, void *param)
and a void *param
, where cb
would take the relative filename and a pointer to some user data (param
, for local state) and return a char *
to the full text, or something like this?
If anyone finds this useful, these are my changes:
457c457
< const char *p = (const char *) memchr(s, 0, n);
---
> const char *p = memchr(s, 0, n);
1208,1212d1207
< int tinyobj_parse_obj_with_filename(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes,
< size_t *num_shapes, tinyobj_material_t **materials_out,
< size_t *num_materials_out, const char *buf, size_t len,
< const char *filename, unsigned int flags);
<
1217,1223d1211
< return tinyobj_parse_obj_with_filename(attrib, shapes, num_shapes, materials_out, num_materials_out, buf, len, NULL, flags);
< }
<
< int tinyobj_parse_obj_with_filename(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes,
< size_t *num_shapes, tinyobj_material_t **materials_out,
< size_t *num_materials_out, const char *buf, size_t len,
< const char *filename, unsigned int flags) {
1329c1317
< char *relative_filename = my_strndup(commands[mtllib_line_index].mtllib_name,
---
> char *filename = my_strndup(commands[mtllib_line_index].mtllib_name,
1331,1341d1318
< char buffer[1024];
< int filename_len = strlen(filename);
< memcpy(buffer, filename, filename_len);
< char *sentinel = buffer + filename_len;
< while (buffer < sentinel && *sentinel != '/')
< sentinel--;
< if (*sentinel == '/')
< sentinel++;
< int rel_len = commands[mtllib_line_index].mtllib_name_len;
< memcpy(sentinel, relative_filename, rel_len);
< sentinel[rel_len] = 0;
1343c1320
< int ret = tinyobj_parse_and_index_mtl_file(&materials, &num_materials, buffer, &material_table);
---
> int ret = tinyobj_parse_and_index_mtl_file(&materials, &num_materials, filename, &material_table);
1347c1324
< fprintf(stderr, "TINYOBJ: Failed to parse material file '%s': %d\n", buffer, ret);
---
> fprintf(stderr, "TINYOBJ: Failed to parse material file '%s': %d\n", filename, ret);
1350c1327
< TINYOBJ_FREE(relative_filename);
---
> TINYOBJ_FREE(filename);
1381a1359,1372
> /* @todo
> if (commands[t][i].material_name &&
> commands[t][i].material_name_len > 0) {
> std::string material_name(commands[t][i].material_name,
> commands[t][i].material_name_len);
>
> if (material_map.find(material_name) != material_map.end()) {
> material_id = material_map[material_name];
> } else {
> // Assign invalid material ID
> material_id = -1;
> }
> }
> */
We can implement both.
One is supply both filename(for the use of .mtl search) and its content, something like what libjsonnet's evaluateSnippet does:
And another is supply callback functions for resource access(.obj, .mtl, etc)
I have an
obj
andmtl
file exported from blender in a directory, and I'd like to read them both. I'm usingtinyobj_parse_obj
for this, which takes the.obj
file as achar *
as input. However, one of the commands in the file ismtllib <filename>.mtl
, which it tries to read, and fails, since the files aren't in the same directory as the executable. Sincetinyobj_parse_obj
doesn't know anything about the location of theobj
file it would be unable to locate the.mtl
file, since I assumemtllib
is supposed to give a relative path.Is this a bug, or is there some way of handing this?