syoyo / tinyobjloader-c Goto Github PK
View Code? Open in Web Editor NEWHeader only tiny wavefront .obj loader in pure C99
Header only tiny wavefront .obj loader in pure C99
The STB style is good, but it's incomplete. There should be an option to provide file data without <stdio.h>
and memory allocation without malloc()
/realloc()
/free()
. See the STB libraries for examples.
I have no idea why GLEW does not initialize properly (Debian 10), I'm using glew for my other projects and everything is working just fine. In the meantime i replaced GLEW with glad
https://glad.dav1d.de/ (Opengl 2.0 compatibility mode)
and that solve the issue. Can I contribute my modyfication of the vewer example ? it's one dependency less.
Hi!!!
I was using the lib, on a windows platform
I made a Map File version for windows, if you want to use it, feel free to use it.
The only problem that you need to allocate space for the file and if this file is very large, read it in chunks
The code has been tested
char *g_pData=NULL;//Global data free It later
static const char* mmap_fileWIN(size_t* len, const char* filename)
{
HANDLE hfile =
CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hfile == INVALID_HANDLE_VALUE)
{
printf("Erro:mmap_file CreateFileA=INVALID_HANDLE_VALUE of %s \n",filename);
printf("Could not open %s file, error %d\n", filename, GetLastError());
return NULL;
}
DWORD dwsize = GetFileSize( hfile, NULL);
if (dwsize == 0xFFFFFFFF)
{
printf("Error:map_file Getfilesize 0xff\n");
return NULL;
}
g_pData = (char*)malloc(dwsize);
if(g_pData ==NULL)
return NULL;
HANDLE hFileMapping = CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
if(hFileMapping == INVALID_HANDLE_VALUE)
{
printf("Erro:mmap_file CreateFileMapping=INVALID_HANDLE_of %s \n",filename);
return NULL;
}
int iPos = 0;
const unsigned int BlockSize = 128 * 1024;
while(iPos < dwsize)//Read chunk of data
{
int iLeft = dwsize - iPos;
int iBytesToRead = iLeft > BlockSize ? BlockSize: iLeft;
void *rawBuffer = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, iPos, iBytesToRead);
if(rawBuffer!=NULL)
{
memcpy(&g_pData[iPos], rawBuffer, iBytesToRead);
UnmapViewOfFile(rawBuffer);
}
else
{
UnmapViewOfFile(rawBuffer);
break;
}
iPos += iBytesToRead;
}
*len = dwsize;
if(iPos!=0)
return &g_pData[0];
return NULL;
}
The code correctly computes a negative exponent, but in the final 'assemble' section negative exponents are not handled.
See issue raysan5/raylib#1374 for more detailed information.
When compiling with gcc with -Wall -Werror, I got:
In file included from src/shared/util/tinyobj.cpp:3:0:
lib/tinyobjloader-c/tinyobj_loader_c.h: In function 'int tinyobj_parse_obj(tinyobj_attrib_t*, tinyobj_shape_t**, size_t*, tinyobj_material_t**, size_t*, const char*, size_t, unsigned int)':
lib/tinyobjloader-c/tinyobj_loader_c.h:1393:23: error: invalid conversion from 'void*' to 'tinyobj_shape_t*' [-fpermissive]
(*shapes) = malloc(sizeof(tinyobj_shape_t) * (n + 1));
~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make: *** [Makefile:187: build/client/util/tinyobj.o] Error 1
Will send PR in a moment.
https://github.com/syoyo/tinyobjloader-c/blob/master/examples/viewer/trackball.c#L177
here you end up doing a asin and then a sin and cos on the result.
However to get a quaternion that rotates from one direction v1
to another v2
you only need to do
float q[4];
vnorm(v1);
vnorm(v2);
q[3] = vdot(v1, v2) +1;
vcross(v1, v2, q);
normalize_quat(q);
The plus 1 on the dot product is to get the quaternion representing the half rotation than when you would take just the dot and cross.
On the note of normalize: the magnitude you are dividing with should be the sqrt of the dot product with itself.
You can also opt to not do the normalize of the quaternion (and spare the sqrt) and adjust the matrix generation by dividing each q[...] * q[...]
with q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]
I attempted to load an OBJ file with tinyobj_parse_obj
from gordon/gordon.obj
. It contains an MTL file, gordon/gordon.mtl
. The reading failed and I got the following output:
open: No such file or directory
TINYOBJ: Failed to parse material file 'gordon.mtl^M': -2
Not sure what the first line is. Maybe an error on my side.
I believe the ^M is a carriage return as it displays in Vim. I don't know why that's there as it's in the file name. I believe it also misses that gordon.mtl
is in gordon/
. I know there is a branch that fixes this.
When constructing a null terminated version of the material name, the last character is being overwritten due to wrong character index being used .
Line 1379:
material_name_null_term[commands[i].material_name_len-1] = 0;
should be
material_name_null_term[commands[i].material_name_len] = 0;
Currently max bytes per line are limited to 8192.
Support arbitrary bytes per line.
The hash_table_insert_value
hits an infinite loop if the capacity
is 10 and the start_index
is 9, the (i*i)
addition doesn't produce every possible index and in my case unfortunately it so happens that every index it produces were filled, here is a simple log:
|| ===============
|| start index 9 index 9
|| i : 1) new index 0
|| i : 2) new index 3
|| i : 3) new index 8
|| i : 4) new index 5
|| i : 5) new index 4
|| i : 6) new index 5
|| i : 7) new index 8
|| i : 8) new index 3
|| i : 9) new index 0
|| ===============
here are the files to reproduce this:
car.zip
changing i*i
to a simple i
fixes this.
No clue if it has been reported before.
We need to choose more better name for these variables.
Currently,
num_face = the number of f
lines
num_face_num_verts = length of face_num_verts.
Each face_num_verts contains the number of vertices of a primitive(face). (e.g. 3(triangle), 4(quads))
If we dont triangulate face(primitive), num_face == num_face_num_verts.
Hi,
Well firstly I am very grateful to the developers of the C version of Tinyobjloader, and Tinyobjloader itself being a real lifesaver.
So I've been experimenting the library for my own usage, and recently started to add materials support to my program. However, it looks like the Hashmap implementation that handles the material IDs is broken, as it firstly work well with like 1500 triangles, but then returns a large random number that doesn't seem correct.
It happened on 2 different models, with relatively low numbers of materials (2 and 6), and so by printing printf("Texture mat ID = %d\n", attrib.material_ids[face_offset + 1]);
on every triangle, and at some (random) point in a middle of a shape, the material_id starts to behave strangely:
I hope this can be fixed, and I would to thank you very much for all what have been already done :)
Are the returned values for attrib.num_face_num_verts and attrib.num_faces swapped ?
Loading a simple object that has only a cube and a plane I get
attrib.num_face_num_verts = 14
attrib.num_faces = 42
There are 7 square faces, so 14 triangles, each with 3 vertices, so
attrib.num_face_num_verts = 42
attrib.num_faces = 14
would seem more sensible values.
Memory is allocates for line_infos
by get_line_infos
, but the memory is never free'd.
Adding TINYOBJ_FREE(line_infos);
at the end if the function solves this.
If the face is the last line in the file, it doesn't get added.
v 0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
vn 0.0000 -0.5000 0.0000
vn 0.0000 0.5000 0.0000
vn 0.5000 0.0000 0.0000
vn -0.0000 -0.0000 0.5000
vn -0.5000 -0.0000 -0.0000
vn 0.0000 0.0000 -0.5000
s off
f 1//1 2//1 3//1 4//1
f 5//2 8//2 7//2 6//2
f 1//3 5//3 6//3 2//3
f 2//4 6//4 7//4 3//4
f 3//5 7//5 8//5 4//5
f 5//6 1//6 4//6 8//6
strlen()
on non null terminated string:
tinyobjloader-c/tinyobj_loader_c.h
Line 482 in a56a006
The code uses in-loop initializers (i.e. for int x...) and C++ comments,
so it is not pure C89 code. It is C99-style code.
tinyobjloader-c/tinyobj_loader_c.h
Line 196 in 1ee072e
for atoi function really hard to check errors, because it returns integer for input params, so you can't check it for bad input. You can use sscanf(buf, "%d", &n) to get integer from string and return value will be != 1 if there is problems.
buf hold the readed file content, but no place to free it.
Hi this is an amazing repo.
Is there any obj-to-gltf example? Thanks.
Hello!
This is a nice library, but I had a bit of trouble using it because I didn't quite understand what was contained in the main data structures.
In my opinion, that is the most important thing to document.
For instance: the members in 'tinyobj_attrib_t' struct could use some comments.
In particular, the members: 'num_faces', 'num_face_num_verts', 'faces' and 'face_num_verts'.
What are their relationships, and how they are affected by the TINYOBJ_FLAG_TRIANGULATE flag?
Not an issue per se, but I just wanted to get an update on some of the contributors' plans for completing this.
Scanning through the code, it seems like the thing that needs to be done to wrap up the material loading is mapping material IDs for each face. Is it worth implementing a hashmap right in the file, or should it suffice to just keep a list of hashed material names that you search through linearly?
I have an obj
and mtl
file exported from blender in a directory, and I'd like to read them both.
I'm using tinyobj_parse_obj
for this, which takes the .obj
file as a char *
as input. However, one of the commands in the file is mtllib <filename>.mtl
, which it tries to read, and fails, since the files aren't in the same directory as the executable. Since tinyobj_parse_obj
doesn't know anything about the location of the obj
file it would be unable to locate the .mtl
file, since I assume mtllib
is supposed to give a relative path.
Is this a bug, or is there some way of handing this?
On windows and with VS, reading the texture name return a carriage return, texture cannot be properly loaded in some cases.
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.