thisistherk / fast_obj Goto Github PK
View Code? Open in Web Editor NEWFast C OBJ parser
License: MIT License
Fast C OBJ parser
License: MIT License
I am planning to include fast_obj in another Mesh data translator library (i3s-lib)as an example of mesh-format with LoD packed as a single file via CMake ExternalProject mechanism. Placing the header in the executable source's include path via this mechanism should work.
Has this been done previously for other projects ? Are there samples around ?
Please see : Esri/i3s-lib#6
Would be nice to e.g. ignore texture coordinates if you're not bothered about them. Float parsing takes the majority of execution time, so skipping parsing things that aren't needed would speed things up.
Probably requires a new API - fast_obj_read_with_options
or something - to supply flags indicating which attributes are required.
If the allocation on line fast_obj.h#1450 fails the memory allocated at fast_obj.h#1397 is leaked.
Line 1450 in 85778da
I used this library (thank you for sharing it!) with ttf2mesh and it exports spaces as empty objects. The names still hold data about the characters but your library skips them because they have no geometry. Maybe add an option to not do that :).
Hacked my way out of it like so:
void flush_object(fastObjData* data)
{
/* Add object if not empty */
if (data->object.face_count > 0)
array_push(data->mesh->objects, data->object);
else if(data->object.name != NULL)
{
data->object.face_count=0;
data->object.face_offset=0;
data->object.index_offset=0;
array_push(data->mesh->objects, data->object);
}
else
object_clean(&data->object);
/* Reset for more data */
data->object = object_default();
data->object.face_offset = array_size(data->mesh->face_vertices);
data->object.index_offset = array_size(data->mesh->indices);
}
Could next version have a version number in the header of fast_obj.h ?
like cgltf does here
Otherwise it's hard to know what version of fast_obj is used.
As it's a header only library, more often than not, it's directly added as a file in projects, so using commit date or commit log is not really very practical and guaranteed to succeed.
(would do a PR, but choosing the first version number and what kind of versioning is kind of personal taste thing)
Hey,
would it be possible to add support for
#obj file generated by SculptrVR
#Vertex format: v x y z r g b#Vertex colors are not supported by all programs.
sample is
https://www.shapeways.com/forum/t/vertex-color-obj-format.42061/
Hi,
Wondering if you had tried or have experience around those 2 ideas:
Hey, thanks for making this project available!
When I parse a basic cube mesh with 8 vertices and 12 triangles, the fastObjMesh->position_count reads 9 instead of 8. It looks like this is caused by the dummy data added starting at line 1296 of fast_obj.h.
Here's a link to the cube.obj tested
https://gist.github.com/noonat/1131091/450ad7bbb6e0c8fba1854cc86a9f6b7a224fca56
Hi,
The following obj file causes the parse_face function to get stuck in an infinite loop:
f f
(3 letters only)
In the parse_face function, the pointer never gets advanced, because no valid integers could be read. Also, it will keep pushing new items into the array every iteration, so it will just run for a while, then it'll crash.
The off by one bug is affecting vertex position, texcoords and normals count.
Another bug is fastobj report illum (in mtl file) to be 0 regardless of its value.
here is a sample cube (.obj) from blender, it has 8 vertices, 14 texcoords, and 6 normals:
mtllib untitled.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.875000 0.500000
vt 0.625000 0.750000
vt 0.625000 0.500000
vt 0.375000 1.000000
vt 0.375000 0.750000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.375000 0.500000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.625000 0.250000
vt 0.875000 0.750000
vt 0.625000 1.000000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 5/1/1 3/2/1 1/3/1
f 3/2/2 8/4/2 4/5/2
f 7/6/3 6/7/3 8/8/3
f 2/9/4 8/10/4 6/11/4
f 1/3/5 4/5/5 2/9/5
f 5/12/6 2/9/6 6/7/6
f 5/1/1 7/13/1 3/2/1
f 3/2/2 7/14/2 8/4/2
f 7/6/3 5/12/3 6/7/3
f 2/9/4 4/5/4 8/10/4
f 1/3/5 3/2/5 4/5/5
f 5/12/6 1/3/6 2/9/6
and here is the mtl, notice the illum is 2:
newmtl Material
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
finally the test program and its output:
the test:
#include <stdio.h>
#define FAST_OBJ_IMPLEMENTATION
#include "fast_obj.h"
int main(int argc, char **argv)
{
static fastObjMesh *mesh;
mesh = fast_obj_read("untitled.obj");
if (mesh) {
fprintf(stdout, "vertices count: %i\n", mesh->position_count);
fprintf(stdout, "texture coords count: %i\n", mesh->texcoord_count);
fprintf(stdout, "normals count: %i\n", mesh->normal_count);
fprintf(stdout, "face count: %i\n", mesh->face_count);
fprintf(stdout, "index count: %i\n", mesh->index_count);
for (int i=0;i<mesh->index_count;++i)
fprintf(stdout, "\tindices p:%i t:%i n:%i\n", mesh->indices[i].p, mesh->indices[i].t, mesh->indices[i].n);
fprintf(stdout, "material count: %i\n", mesh->material_count);
for (int i=0;i<mesh->material_count;++i) {
fprintf(stdout, "\tambient: %f, %f, %f\n", mesh->materials[i].Ka[0], mesh->materials[i].Ka[1], mesh->materials[i].Ka[2]);
fprintf(stdout, "\tdiffuse: %f, %f, %f\n", mesh->materials[i].Kd[0], mesh->materials[i].Kd[1], mesh->materials[i].Kd[2]);
fprintf(stdout, "\tspecular: %f, %f, %f\n", mesh->materials[i].Ks[0], mesh->materials[i].Ks[1], mesh->materials[i].Ks[2]);
fprintf(stdout, "\temission: %f, %f, %f\n", mesh->materials[i].Ke[0], mesh->materials[i].Ke[1], mesh->materials[i].Ke[2]);
fprintf(stdout, "\ttransmittance: %f, %f, %f\n", mesh->materials[i].Kt[0], mesh->materials[i].Kt[1], mesh->materials[i].Kt[2]);
fprintf(stdout, "\tshininess: %f\n", mesh->materials[i].Ns);
fprintf(stdout, "\trefraction index: %f\n", mesh->materials[i].Ni);
fprintf(stdout, "\ttransmission filter: %f, %f, %f\n", mesh->materials[i].Tf[0], mesh->materials[i].Tf[1], mesh->materials[i].Tf[2]);
fprintf(stdout, "\tdisolve: %f\n", mesh->materials[i].d);
fprintf(stdout, "\tillum: %i\n", mesh->materials[i].illum);
}
fprintf(stdout, "object count: %i\n", mesh->object_count);
fprintf(stdout, "group count: %i\n", mesh->group_count);
fast_obj_destroy(mesh);
}
return 0;
}
/*`
the output, notice vertex position/texcoords/normals count are off by one, and illum reported as 0:
vertices count: 9
texture coords count: 15
normals count: 7
face count: 12
index count: 36
indices p:5 t:1 n:1
indices p:3 t:2 n:1
indices p:1 t:3 n:1
indices p:3 t:2 n:2
indices p:8 t:4 n:2
indices p:4 t:5 n:2
indices p:7 t:6 n:3
indices p:6 t:7 n:3
indices p:8 t:8 n:3
indices p:2 t:9 n:4
indices p:8 t:10 n:4
indices p:6 t:11 n:4
indices p:1 t:3 n:5
indices p:4 t:5 n:5
indices p:2 t:9 n:5
indices p:5 t:12 n:6
indices p:2 t:9 n:6
indices p:6 t:7 n:6
indices p:5 t:1 n:1
indices p:7 t:13 n:1
indices p:3 t:2 n:1
indices p:3 t:2 n:2
indices p:7 t:14 n:2
indices p:8 t:4 n:2
indices p:7 t:6 n:3
indices p:5 t:12 n:3
indices p:6 t:7 n:3
indices p:2 t:9 n:4
indices p:4 t:5 n:4
indices p:8 t:10 n:4
indices p:1 t:3 n:5
indices p:3 t:2 n:5
indices p:4 t:5 n:5
indices p:5 t:12 n:6
indices p:1 t:3 n:6
indices p:2 t:9 n:6
material count: 1
ambient: 1.000000, 1.000000, 1.000000
diffuse: 0.800000, 0.800000, 0.800000
specular: 0.500000, 0.500000, 0.500000
emission: 0.000000, 0.000000, 0.000000
transmittance: 0.000000, 0.000000, 0.000000
shininess: 324.000000
refraction index: 1.450000
transmission filter: 1.000000, 1.000000, 1.000000
disolve: 1.000000
illum: 0
object count: 1
group count: 1*/
Hello,
We recently received a vulnerability disclosure against your repository. I couldn't find an e-mail to contact or a security process to follow, so created this issue instead.
If you would like me to e-mail over the details or put them on the GitHub Issue, I'm more than happy to facilitate this for you. Otherwise, you can access the advisory here.
It is private to you and the discloser of the report.
If you have any questions, let me know.
-- Jamie from huntr.dev
I'm testing the library with a cube OBJ exported from Blender. It seems to load fine, but loading it into a VBO and EBO using this code doesn't work properly:
glGenVertexArrays(1, &mesh->VAO);
glBindVertexArray(mesh->VAO);
glGenBuffers(1, &mesh->VBO);
glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO);
glBufferData(GL_ARRAY_BUFFER, objmesh->position_count * sizeof(float) * 3, objmesh->positions, GL_STATIC_DRAW);
glGenBuffers(1, &mesh->EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, objmesh->index_count * sizeof(unsigned int), objmesh->indices, GL_STATIC_DRAW);
When drawing with GL_TRIANGLES, nothing is displayed but if I use GL_LINES they go out from the origin to the 8 vertices of the cube. I think it's an issue with the indices, but I've been trying for days and I can't seem to figure out why
Thanks!
cube.obj:
# Blender 4.0.1
# www.blender.org
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
s 0
f 5 3 1
f 3 8 4
f 7 6 8
f 2 8 6
f 1 4 2
f 5 2 6
f 5 7 3
f 3 7 8
f 7 5 6
f 2 4 8
f 1 3 4
f 5 1 2
fast_obj
works quite well as a reader. For application that do rad/write of OBJ, it would be nice to be able to be able to save an in-memory obj to disk as a pair of OBJ/MTL files. An example of this is the cgltf
project.
Any plans to add this in the future?
Line 1088 in e7a99e6
else if (( p[0] == 'b' || p[0] == 'B' )
Cheers !
I noticed that if I'm loading a model on Windows and I use Unix style paths, the library cannot find the .mtl file related to my .obj file, this happens because string_find_last
only searches for one type of slash inside the original path in order to generate the base path.
I suggest the following edit at line 1338:
/* Find base path for materials/textures */
const char *sep, *sep2;
int found_sep;
sep = sep2 = 0;
found_sep = string_find_last(path, FAST_OBJ_SEPARATOR, &sep);
found_sep = found_sep || string_find_last(path, FAST_OBJ_OTHER_SEP, &sep2);
if (sep2 > sep) sep = sep2;
if (found_sep)
data.base = string_substr(path, 0, sep + 1);
For example, in the following code snippet, lines 1398 and 1449 return the function without freeing the allocated memory. These problems all happen when there is not enough memory, so is this intentional?
I think this is a bug, we should make sure the temporary resources are properly released returning the function.
Lines 1389 to 1449 in d2c2732
Just writing here that we used fast_obj in an Unity 3D package for faster Obj loading in Unity in the project I'm working in. If anyone is interested in that you can find it here: https://github.com/equinor/FastObjUnity
It should™ work at runtime in Unity, and is quite fast and nice for most common ".obj" files if you want to quickly preview or use them in a Unity context.
Thanks for a great, fast tool 👍
Hello and thank you for developing fast_obj.
There has been many improvements since the last release and the library is used in Organic Maps among other projects. Could you consider doing a release shortly (or a RC) please?
Thanks!
I'm interested in making a PR that moves fastObjGroup::materials, fastObjGroup::vertices and fastObjGroup::indices to fastObjMesh (probably calling them face_materials, face_vertices and face_indices), and changing fastObjGroup to something along the lines of:
typedef struct
{
/* Group name */
char* name;
/* Number of faces */
unsigned int face_count;
/* Offset of face data in fastObjMesh::face_* arrays */
size_t face_offset;
} fastObjGroup;
Would that make sense / is that PR likely to be merged? The reason I'd like to make this change is that it makes parsing .obj easier for clients that don't care about the group data - since group data is completely extraneous and doesn't always provide meaningful splitting (material definition is per-face, not per-group), it seems like in most cases you'd want to ignore it.
I'm looking at replacing a custom .obj file parser (because the world doesn't need another .obj loader :P) with this one in several places where group data is inessential and this is the last small usability barrier left.
If you could consider it, and now that visual studio also support it since VS2017, it would be really useful to make sure diff/PR/etc are easier ?
OBJ allows line continuations: if you put a backslash at the end of a line, parsing is supposed to continue on the next line as if it were part of the same line (Source: https://www.fileformat.info/format/wavefrontobj/egff.htm). fast_obj doesn't handle this properly and can seg fault when parsing files with line continuations.
It's pretty rare to encounter this in the wild and handling it properly would likely have a performance impact so maybe it's not actually worth supporting, but I thought it was at least worth mentioning.
Either way, thanks for making fast_obj available - it's a really nice little library!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.