Giter VIP home page Giter VIP logo

tinyobjloader-c's Introduction

tinyobjloader in C

Tiny but powerful header only wavefront obj loader written in C99.

If you are looking for C++ version, please see https://github.com/syoyo/tinyobjloader

Current status

Experimental. Loading geometry data would be OK, More testing required for materials and shapes.

Features

  • Single file, header only
  • Dependency-free pure C99 implementation(except for libc)
  • Provides mostly similar functionality as in C++ version. https://github.com/syoyo/tinyobjloader
  • Moderate speed and moderate memory consumption
    • Rungholt 7M triangle scene(260 MB) can be loaded in 4.7 secs and consumes 3.6 GB memory at the maximum on MacBook12 Core m5 1.2 GHz(single core use)
  • Unit tests using acutest thanks to @andystanton

Usage

Copy tinyobj_loader_c.h to your project.

/* define TINYOBJ_LOADER_C_IMPLEMENTATION for only *one* .c */
#define TINYOBJ_LOADER_C_IMPLEMENTATION
#include "tinyobj_loader_c.h"

...

See examples/viewer/ for more details.

tinyobjloader allocates memory. To replace the functions used for allocation, define TINYOBJ_MALLOC, TINYOBJ_REALLOC, TINYOBJ_CALLOC and TINYOBJ_FREE in the .c file you defined TINYOBJ_LOADER_C_IMPLEMENTATION in, before including tinyobj_loader_c.h. Define either all or none of them. They replace malloc, realloc, calloc and free respectively.

Example:

#define TINYOBJ_LOADER_C_IMPLEMENTATION
#define TINYOBJ_MALLOC my_malloc
#define TINYOBJ_REALLOC my_realloc
#define TINYOBJ_CALLOC my_calloc
#define TINYOBJ_FREE my_free
#include "tinyobj_loader_c.h"

Tests

The single header test library acutest is used to provide a test runner and assertion macros. There are two test suites: one for the API and one for the internal functions. Ultimately the internal tests should be removed, but are useful while the project is volatile.

The tests can be run from the project root using:

$ make test

This builds and executes a binary called tinyobj_tests in the test folder. There are some options to run specific tests that can be passed to the executable directly that are described on the acutest readme.

By default acutest forks for each test. To disable this for debugging purposes, you can pass the switch --no-exec to tinyobj_tests.

License

MIT license.

Third party licenses

TODO

  • Windows build?

tinyobjloader-c's People

Contributors

abnercoimbre avatar agentoak avatar andystanton avatar arkenidar avatar benfradella avatar geckor14 avatar koga25 avatar latencyhiding avatar mandyedi avatar nashidau avatar neurotok avatar nmdnm avatar peterogb avatar randompigyt avatar syoyo avatar the-swank avatar unn4m3d avatar vkoskiv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tinyobjloader-c's Issues

Windows version of map file

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;
}

Presumably broken hashmap for material listing

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:
issue.png

I hope this can be fixed, and I would to thank you very much for all what have been already done :)

obj to gltf?

Hi this is an amazing repo.
Is there any obj-to-gltf example? Thanks.

Maybe use sscanf?

static int my_atoi(const char *c) {

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.

Material name corruption in tinyobj_parse_obj

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;

Clearify num_face and num_face_num_verts variable

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.

Last face ignored if it's the last line in the file

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

Renders in the viewer like this:
screenshot 2018-11-16 at 20 33 48

Loading materials

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?

Swapped values in returned attribs ?

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.

fpermissing warning

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.

No need for the trig when creating quaternions

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]

tinyobj_parse_obj fails to read .mtl file

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.

Failed to initialize GLEW. (linux)

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.

Infinite loop in hash table inserting when reading mtl file

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.

Documenting the main data structures

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?

`obj` parsing doesn't know the file name, but `mtllib` is relative to that file

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.