Compare commits

...

36 commits
v1.1 ... master

Author SHA1 Message Date
Richard Knight
9884aa86b0
Merge pull request #51 from corporateshark/master
Update CMake file to CMake version `3.5...3.31`
2024-12-10 08:53:05 +00:00
Sergey Kosarevsky
fce8123891 Update CMake file to CMake version 3.5...3.31
This approach allows us to maintain compatibility with the minimum supported CMake version 3.5,
while suppressing all policy warnings up to the latest version 3.31.
2024-12-06 16:46:51 -08:00
Richard Knight
8145eb0a94
Merge pull request #50 from corporateshark/master
Update CMake file to CMake version 3.5
2024-11-19 20:38:52 +00:00
Sergey Kosarevsky
ddfe2e7f86 Update CMake file to CMake version 3.5
Fixed this deprecation warning:
``
CMake Deprecation Warning at CMakeLists.txt:1 (CMAKE_MINIMUM_REQUIRED):
Compatibility with CMake < 3.5 will be removed from a future version of CMake.
``
2024-11-03 22:40:54 -08:00
Richard Knight
42629f7442
Small note about API change in 1.3 2024-06-04 20:31:38 +01:00
Richard Knight
9e2c3677b6 Bump version number to 1.3 2024-06-04 20:27:55 +01:00
Richard Knight
0ba37c7ff9
Merge pull request #36 from laurelkeys/patch-1
Proposal: move material texture maps into fastObjMesh
2024-06-04 20:21:10 +01:00
Tiago Chaves
12b04fc1ab
Merge branch 'master' into patch-1 2023-12-30 14:05:57 -05:00
Richard Knight
724e09ff1e Fix fuzzer test when vertex index is garbage 2023-12-21 17:17:30 +00:00
Richard Knight
c8707104b8
Merge pull request #46 from DavidKorczynski/clusterfuzzlite-intergation
Add ClusterFuzzLite integration
2023-12-21 16:38:36 +00:00
Richard Knight
e24d2c5533
Merge pull request #45 from zeux/master
Mark materials that weren't loaded from mtllib as fallback
2023-12-21 16:33:03 +00:00
David Korczynski
bcc68cca4c Add ClusterFuzzLite integration
Signed-off-by: David Korczynski <david@adalogics.com>
2023-12-21 04:19:45 -08:00
Arseny Kapoulkine
b827219dbf Mark materials that weren't loaded from mtllib as fallback
This can happen when mtllib is absent, points to a non-existing file, or
material names are incorrect. In either case it helps the reader
differentiate between materials that are actually specified in the file,
even if their definition happens to match the default, from materials
that were never loaded in the first place.
2023-12-15 11:29:56 -08:00
Richard Knight
36cb5a8d89
Merge pull request #43 from zeux/skip_name
Trim trailing whitespace for names
2023-08-14 20:14:40 +01:00
Arseny Kapoulkine
33e0ee7162 Trim trailing whitespace for names
Some .obj files have extra whitespace after usemtl and other statements;
this may interfere with parsing, for example by adding a space to the
material name which can result in inability to find it in .mtl file.

For consistency, we replace all uses of is_end_of_name with skip_name
that handles this by leaving trailing whitespace alone. It will be
skipped in the parsing flow when we skip the newline, which is similar
to the behavior of trailing whitespace after numeric data (which
parse_float/int leave alone).
2023-08-13 10:08:29 -07:00
Richard Knight
2bb0b1f650
Merge pull request #41 from maxrigout/master
added support for colored vertices (issue #28)
2023-08-08 10:52:23 +01:00
Max Rigout
491efbbb59 removed extra white spaces 2023-08-03 10:17:31 -04:00
Max Rigout
cd5be148c3 re-added mesh normal initialization that was accidently removed) 2023-08-03 08:40:58 -04:00
Max Rigout
27803406d7 reverted color parsing to original approach 2023-08-03 08:31:16 -04:00
Max Rigout
20a9db53a0
Merge pull request #1 from maxrigout/colors
Colors
2023-08-02 22:34:25 -04:00
Max Rigout
2c91cb2993 added lazy fill for vertex_color_index 2023-08-02 22:18:31 -04:00
Max Rigout
9037820f30 improved color parsing 2023-08-02 22:17:37 -04:00
Max Rigout
a511f60249 added support for colored vertices (issue #28) 2023-07-31 21:23:40 -04:00
Richard Knight
1a8060257a
Merge pull request #40 from zeux/master
Fix 32-bit integer overflow issues
2023-06-10 12:57:54 +01:00
Arseny Kapoulkine
66f467de8f Fix 32-bit integer overflow issues
When an array reached a size that would require >4GB allocation, the
argument to realloc would overflow during multiplication, resulting in a
very small allocation and a subsequent out of bounds access.

This change fixes that and also adjusts capacity calculation so that it
doesn't overflow 32-bit range until it's basically impossible not to.

This is not perfect - in particular, on 32-bit systems there's a risk of
size_t overflow that remains, however because we grow in 1.5x
increments, realistically an attempt to grow a 2GB allocation to the
next increment would fail before that. We can also technically overflow
capacity even after the adjustment, but that requires 3+B elements which
effectively means an .obj file on the scale of hundreds of gigabytes, at
which point maybe a streaming parser would be more practical.
2023-06-08 20:35:25 -07:00
Tiago Chaves
6f4e843882
Move material texture maps into fastObjMesh 2022-08-29 11:24:49 -03:00
Richard Knight
85778da5fc
Merge pull request #31 from cadenji/add-index_count
Add index_count member to fastObjMesh struct
2022-01-29 16:42:41 +00:00
cadenji
3a1efbcc79 Add index_count member to fastObjMesh struct
In some cases we need to know the length of `indices`.
Currently need to calculate the sum of the `face_vertices`
elements to get this value.

It would be convenient if we could get the value directly.
2022-01-29 23:15:20 +08:00
Richard Knight
d2c273248a Use the same struct definition for Object and Group. 2021-10-19 08:54:00 +01:00
Richard Knight
ed03b86e7f Fix stupid face counting bug in objects 2021-10-19 08:44:07 +01:00
Richard Knight
9f4b38eb1b Add support for object names 2021-10-18 15:56:38 +01:00
Richard Knight
49c810ae1c Bump version number 2021-08-01 14:07:18 +01:00
Richard Knight
86d7dc6e43 Update CMake file so it can be used with FetchContent in other projects 2021-08-01 14:06:21 +01:00
Richard Knight
92551724cf Avoid signed overflow with crazy exponents. Fixes #27. 2021-06-01 18:23:53 +01:00
Richard Knight
d97389aa2d
Merge pull request #26 from zeux/patch-1
Fix version number in the comment
2021-04-01 18:09:38 +01:00
Arseny Kapoulkine
fed0e5760f
Fix version number in the comment
Also fix copyright year while I'm at this.
2021-03-31 22:55:39 -07:00
9 changed files with 318 additions and 84 deletions

View file

@ -0,0 +1,6 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake libtool
COPY . $SRC/fast_obj
COPY .clusterfuzzlite/build.sh $SRC/build.sh
WORKDIR $SRC/fast_obj

View file

@ -0,0 +1,3 @@
# ClusterFuzzLite set up
This folder contains a fuzzing set for [ClusterFuzzLite](https://google.github.io/clusterfuzzlite).

View file

@ -0,0 +1,5 @@
#!/bin/bash -eu
$CXX $CFLAGS $LIB_FUZZING_ENGINE \
$SRC/fast_obj/.clusterfuzzlite/fast_obj_fuzzer.cpp \
-o $OUT/fast_obj_fuzzer \
-I$SRC/fast_obj

View file

@ -0,0 +1,27 @@
#define FAST_OBJ_IMPLEMENTATION
#include "fast_obj.h"
#include <string>
#include <sys/types.h>
#include <unistd.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
char filename[256];
sprintf(filename, "/tmp/libfuzzer.%d", getpid());
FILE *fp = fopen(filename, "wb");
if (!fp)
return 0;
fwrite(data, size, 1, fp);
fclose(fp);
fastObjMesh *m = fast_obj_read(filename);
if (!m) {
unlink(filename);
return 0;
}
fast_obj_destroy(m);
unlink(filename);
return 0;
}

View file

@ -0,0 +1 @@
language: c++

30
.github/workflows/cflite_pr.yml vendored Normal file
View file

@ -0,0 +1,30 @@
name: ClusterFuzzLite PR fuzzing
on:
workflow_dispatch:
pull_request:
branches: [ main ]
permissions: read-all
jobs:
PR:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sanitizer: [address]
steps:
- name: Build Fuzzers (${{ matrix.sanitizer }})
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
with:
sanitizer: ${{ matrix.sanitizer }}
language: c++
bad-build-check: false
- name: Run Fuzzers (${{ matrix.sanitizer }})
id: run
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 100
mode: 'code-change'
report-unreproducible-crashes: false
sanitizer: ${{ matrix.sanitizer }}

View file

@ -1,10 +1,18 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
CMAKE_MINIMUM_REQUIRED(VERSION 3.5...3.31)
PROJECT(fast_obj)
SET(CMAKE_CXX_STANDARD 11)
OPTION(FAST_OBJ_BUILD_TEST "Build test application" OFF)
ADD_EXECUTABLE(test test/test.cpp)
TARGET_INCLUDE_DIRECTORIES(test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
ADD_LIBRARY(fast_obj INTERFACE)
TARGET_INCLUDE_DIRECTORIES(fast_obj INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
ADD_LIBRARY(fast_obj_lib STATIC fast_obj.c)
TARGET_INCLUDE_DIRECTORIES(fast_obj_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
IF(${FAST_OBJ_BUILD_TEST})
ADD_EXECUTABLE(fast_obj_test test/test.cpp)
TARGET_COMPILE_FEATURES(fast_obj_test PRIVATE cxx_std_11)
TARGET_LINK_LIBRARIES(fast_obj_test PRIVATE fast_obj_lib)
ENDIF()

View file

@ -21,4 +21,9 @@ the mesh arrays.
A simple test app is provided to compare speed against [tinyobjloader](https://github.com/syoyo/tinyobjloader) and
check output matches.
### Version 1.3
Version 1.3 makes a small change to the API. Textures are now stored in a separate array on the
`fastObjMesh` structure, and are referenced by index from materials, instead of being referenced
by the material directly.

View file

@ -1,11 +1,11 @@
/*
* fast_obj
*
* Version 1.0
* Version 1.3
*
* MIT License
*
* Copyright (c) 2018-2020 Richard Knight
* Copyright (c) 2018-2021 Richard Knight
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -31,7 +31,7 @@
#define FAST_OBJ_HDR
#define FAST_OBJ_VERSION_MAJOR 1
#define FAST_OBJ_VERSION_MINOR 1
#define FAST_OBJ_VERSION_MINOR 3
#define FAST_OBJ_VERSION ((FAST_OBJ_VERSION_MAJOR << 8) | FAST_OBJ_VERSION_MINOR)
#include <stdlib.h>
@ -65,16 +65,19 @@ typedef struct
float d; /* Disolve (alpha) */
int illum; /* Illumination model */
/* Texture maps */
fastObjTexture map_Ka;
fastObjTexture map_Kd;
fastObjTexture map_Ks;
fastObjTexture map_Ke;
fastObjTexture map_Kt;
fastObjTexture map_Ns;
fastObjTexture map_Ni;
fastObjTexture map_d;
fastObjTexture map_bump;
/* Set for materials that don't come from the associated mtllib */
int fallback;
/* Texture map indices in fastObjMesh textures array */
unsigned int map_Ka;
unsigned int map_Kd;
unsigned int map_Ks;
unsigned int map_Ke;
unsigned int map_Kt;
unsigned int map_Ns;
unsigned int map_Ni;
unsigned int map_d;
unsigned int map_bump;
} fastObjMaterial;
@ -111,6 +114,10 @@ typedef struct
} fastObjGroup;
/* Note: a dummy zero-initialized value is added to the first index
of the positions, texcoords, normals and textures arrays. Hence,
valid indices into these arrays start from 1, with an index of 0
indicating that the attribute is not present. */
typedef struct
{
/* Vertex data */
@ -123,19 +130,31 @@ typedef struct
unsigned int normal_count;
float* normals;
unsigned int color_count;
float* colors;
/* Face data: one element for each face */
unsigned int face_count;
unsigned int* face_vertices;
unsigned int* face_materials;
/* Index data: one element for each face vertex */
unsigned int index_count;
fastObjIndex* indices;
/* Materials */
unsigned int material_count;
fastObjMaterial* materials;
/* Mesh groups */
/* Texture maps */
unsigned int texture_count;
fastObjTexture* textures;
/* Mesh objects ('o' tag in .obj file) */
unsigned int object_count;
fastObjGroup* objects;
/* Mesh groups ('g' tag in .obj file) */
unsigned int group_count;
fastObjGroup* groups;
@ -197,7 +216,8 @@ typedef struct
/* Final mesh */
fastObjMesh* mesh;
/* Current group */
/* Current object/group */
fastObjGroup object;
fastObjGroup group;
/* Current material index */
@ -259,15 +279,14 @@ static void* array_realloc(void* ptr, fastObjUInt n, fastObjUInt b)
fastObjUInt sz = array_size(ptr);
fastObjUInt nsz = sz + n;
fastObjUInt cap = array_capacity(ptr);
fastObjUInt ncap = 3 * cap / 2;
fastObjUInt ncap = cap + cap / 2;
fastObjUInt* r;
if (ncap < nsz)
ncap = nsz;
ncap = (ncap + 15) & ~15u;
r = (fastObjUInt*)(memory_realloc(ptr ? _array_header(ptr) : 0, b * ncap + 2 * sizeof(fastObjUInt)));
r = (fastObjUInt*)(memory_realloc(ptr ? _array_header(ptr) : 0, (size_t)b * ncap + 2 * sizeof(fastObjUInt)));
if (!r)
return 0;
@ -289,7 +308,7 @@ void* file_open(const char* path, void* user_data)
static
void file_close(void* file, void* user_data)
{
FILE* f;
FILE* f;
(void)(user_data);
f = (FILE*)(file);
@ -300,7 +319,7 @@ void file_close(void* file, void* user_data)
static
size_t file_read(void* file, void* dst, size_t bytes, void* user_data)
{
FILE* f;
FILE* f;
(void)(user_data);
f = (FILE*)(file);
@ -315,7 +334,7 @@ unsigned long file_size(void* file, void* user_data)
long p;
long n;
(void)(user_data);
f = (FILE*)(file);
p = ftell(f);
@ -405,12 +424,6 @@ int is_whitespace(char c)
return (c == ' ' || c == '\t' || c == '\r');
}
static
int is_end_of_name(char c)
{
return (c == '\t' || c == '\r' || c == '\n');
}
static
int is_newline(char c)
{
@ -432,6 +445,21 @@ int is_exponent(char c)
}
static
const char* skip_name(const char* ptr)
{
const char* s = ptr;
while (!is_newline(*ptr))
ptr++;
while (ptr > s && is_whitespace(*(ptr - 1)))
ptr--;
return ptr;
}
static
const char* skip_whitespace(const char* ptr)
{
@ -452,6 +480,44 @@ const char* skip_line(const char* ptr)
}
static
fastObjGroup object_default(void)
{
fastObjGroup object;
object.name = 0;
object.face_count = 0;
object.face_offset = 0;
object.index_offset = 0;
return object;
}
static
void object_clean(fastObjGroup* object)
{
memory_dealloc(object->name);
}
static
void flush_object(fastObjData* data)
{
/* Add object if not empty */
if (data->object.face_count > 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);
}
static
fastObjGroup group_default(void)
{
@ -474,7 +540,7 @@ void group_clean(fastObjGroup* group)
static
void flush_output(fastObjData* data)
void flush_group(fastObjData* data)
{
/* Add group if not empty */
if (data->group.face_count > 0)
@ -484,7 +550,7 @@ void flush_output(fastObjData* data)
/* Reset for more data */
data->group = group_default();
data->group.face_offset = array_size(data->mesh->face_vertices);
data->group.face_offset = array_size(data->mesh->face_vertices);
data->group.index_offset = array_size(data->mesh->indices);
}
@ -523,7 +589,7 @@ const char* parse_float(const char* ptr, float* val)
double num;
double fra;
double div;
int eval;
unsigned int eval;
const double* powers;
@ -612,6 +678,23 @@ const char* parse_vertex(fastObjData* data, const char* ptr)
array_push(data->mesh->positions, v);
}
ptr = skip_whitespace(ptr);
if (!is_newline(*ptr))
{
/* Fill the colors array until it matches the size of the positions array */
for (ii = array_size(data->mesh->colors); ii < array_size(data->mesh->positions) - 3; ++ii)
{
array_push(data->mesh->colors, 1.0f);
}
for (ii = 0; ii < 3; ++ii)
{
ptr = parse_float(ptr, &v);
array_push(data->mesh->colors, v);
}
}
return ptr;
}
@ -685,8 +768,10 @@ const char* parse_face(fastObjData* data, const char* ptr)
if (v < 0)
vn.p = (array_size(data->mesh->positions) / 3) - (fastObjUInt)(-v);
else
else if (v > 0)
vn.p = (fastObjUInt)(v);
else
return ptr; /* Skip lines with no valid vertex index */
if (t < 0)
vn.t = (array_size(data->mesh->texcoords) / 2) - (fastObjUInt)(-t);
@ -712,6 +797,27 @@ const char* parse_face(fastObjData* data, const char* ptr)
array_push(data->mesh->face_materials, data->material);
data->group.face_count++;
data->object.face_count++;
return ptr;
}
static
const char* parse_object(fastObjData* data, const char* ptr)
{
const char* s;
const char* e;
ptr = skip_whitespace(ptr);
s = ptr;
ptr = skip_name(ptr);
e = ptr;
flush_object(data);
data->object.name = string_copy(s, e);
return ptr;
}
@ -727,12 +833,10 @@ const char* parse_group(fastObjData* data, const char* ptr)
ptr = skip_whitespace(ptr);
s = ptr;
while (!is_end_of_name(*ptr))
ptr++;
ptr = skip_name(ptr);
e = ptr;
flush_output(data);
flush_group(data);
data->group.name = string_copy(s, e);
return ptr;
@ -781,15 +885,17 @@ fastObjMaterial mtl_default(void)
mtl.d = 1.0;
mtl.illum = 1;
mtl.map_Ka = map_default();
mtl.map_Kd = map_default();
mtl.map_Ks = map_default();
mtl.map_Ke = map_default();
mtl.map_Kt = map_default();
mtl.map_Ns = map_default();
mtl.map_Ni = map_default();
mtl.map_d = map_default();
mtl.map_bump = map_default();
mtl.fallback = 0;
mtl.map_Ka = 0;
mtl.map_Kd = 0;
mtl.map_Ks = 0;
mtl.map_Ke = 0;
mtl.map_Kt = 0;
mtl.map_Ns = 0;
mtl.map_Ni = 0;
mtl.map_d = 0;
mtl.map_bump = 0;
return mtl;
}
@ -808,9 +914,7 @@ const char* parse_usemtl(fastObjData* data, const char* ptr)
/* Parse the material name */
s = ptr;
while (!is_end_of_name(*ptr))
ptr++;
ptr = skip_name(ptr);
e = ptr;
/* Find an existing material with the same name */
@ -824,12 +928,13 @@ const char* parse_usemtl(fastObjData* data, const char* ptr)
idx++;
}
/* If doesn't exists, create a default one with this name
Note: this case happens when OBJ doesn't have its MTL */
/* If doesn't exist, create a default one with this name
Note: this case happens when OBJ doesn't have its MTL */
if (idx == array_size(data->mesh->materials))
{
fastObjMaterial new_mtl = mtl_default();
new_mtl.name = string_copy(s, e);
new_mtl.fallback = 1;
array_push(data->mesh->materials, new_mtl);
}
@ -850,16 +955,6 @@ void map_clean(fastObjTexture* map)
static
void mtl_clean(fastObjMaterial* mtl)
{
map_clean(&mtl->map_Ka);
map_clean(&mtl->map_Kd);
map_clean(&mtl->map_Ks);
map_clean(&mtl->map_Ke);
map_clean(&mtl->map_Kt);
map_clean(&mtl->map_Ns);
map_clean(&mtl->map_Ni);
map_clean(&mtl->map_d);
map_clean(&mtl->map_bump);
memory_dealloc(mtl->name);
}
@ -890,12 +985,12 @@ const char* read_mtl_triple(const char* p, float v[3])
static
const char* read_map(fastObjData* data, const char* ptr, fastObjTexture* map)
const char* read_map(fastObjData* data, const char* ptr, unsigned int* idx)
{
const char* s;
const char* e;
char* name;
char* path;
const char* s;
const char* e;
fastObjTexture* map;
ptr = skip_whitespace(ptr);
@ -906,18 +1001,29 @@ const char* read_map(fastObjData* data, const char* ptr, fastObjTexture* map)
/* Read name */
s = ptr;
while (!is_end_of_name(*ptr))
ptr++;
ptr = skip_name(ptr);
e = ptr;
name = string_copy(s, e);
/* Try to find an existing texture map with the same name */
*idx = 1; /* skip dummy at index 0 */
while (*idx < array_size(data->mesh->textures))
{
map = &data->mesh->textures[*idx];
if (map->name && string_equal(map->name, s, e))
break;
path = string_concat(data->base, s, e);
string_fix_separators(path);
(*idx)++;
}
map->name = name;
map->path = path;
/* Add it to the texture array if it didn't already exist */
if (*idx == array_size(data->mesh->textures))
{
fastObjTexture new_map = map_default();
new_map.name = string_copy(s, e);
new_map.path = string_concat(data->base, s, e);
string_fix_separators(new_map.path);
array_push(data->mesh->textures, new_map);
}
return e;
}
@ -982,8 +1088,7 @@ int read_mtllib(fastObjData* data, void* file, const fastObjCallbacks* callbacks
p++;
s = p;
while (!is_end_of_name(*p))
p++;
p = skip_name(p);
mtl.name = string_copy(s, p);
}
@ -1125,9 +1230,7 @@ const char* parse_mtllib(fastObjData* data, const char* ptr, const fastObjCallba
ptr = skip_whitespace(ptr);
s = ptr;
while (!is_end_of_name(*ptr))
ptr++;
ptr = skip_name(ptr);
e = ptr;
lib = string_concat(data->base, s, e);
@ -1200,6 +1303,21 @@ void parse_buffer(fastObjData* data, const char* ptr, const char* end, const fas
}
break;
case 'o':
p++;
switch (*p++)
{
case ' ':
case '\t':
p = parse_object(data, p);
break;
default:
p--; /* roll p++ back in case *p was a newline */
}
break;
case 'g':
p++;
@ -1245,6 +1363,15 @@ void parse_buffer(fastObjData* data, const char* ptr, const char* end, const fas
data->line++;
}
if (array_size(data->mesh->colors) > 0)
{
/* Fill the remaining slots in the colors array */
unsigned int ii;
for (ii = array_size(data->mesh->colors); ii < array_size(data->mesh->positions); ++ii)
{
array_push(data->mesh->colors, 1.0f);
}
}
}
@ -1253,20 +1380,29 @@ void fast_obj_destroy(fastObjMesh* m)
unsigned int ii;
for (ii = 0; ii < array_size(m->objects); ii++)
object_clean(&m->objects[ii]);
for (ii = 0; ii < array_size(m->groups); ii++)
group_clean(&m->groups[ii]);
for (ii = 0; ii < array_size(m->materials); ii++)
mtl_clean(&m->materials[ii]);
for (ii = 0; ii < array_size(m->textures); ii++)
map_clean(&m->textures[ii]);
array_clean(m->positions);
array_clean(m->texcoords);
array_clean(m->normals);
array_clean(m->colors);
array_clean(m->face_vertices);
array_clean(m->face_materials);
array_clean(m->indices);
array_clean(m->objects);
array_clean(m->groups);
array_clean(m->materials);
array_clean(m->textures);
memory_dealloc(m);
}
@ -1315,14 +1451,17 @@ fastObjMesh* fast_obj_read_with_callbacks(const char* path, const fastObjCallbac
m->positions = 0;
m->texcoords = 0;
m->normals = 0;
m->colors = 0;
m->face_vertices = 0;
m->face_materials = 0;
m->indices = 0;
m->materials = 0;
m->textures = 0;
m->objects = 0;
m->groups = 0;
/* Add dummy position/texcoord/normal */
/* Add dummy position/texcoord/normal/texture */
array_push(m->positions, 0.0f);
array_push(m->positions, 0.0f);
array_push(m->positions, 0.0f);
@ -1334,9 +1473,12 @@ fastObjMesh* fast_obj_read_with_callbacks(const char* path, const fastObjCallbac
array_push(m->normals, 0.0f);
array_push(m->normals, 1.0f);
array_push(m->textures, map_default());
/* Data needed during parsing */
data.mesh = m;
data.object = object_default();
data.group = group_default();
data.material = 0;
data.line = 1;
@ -1410,15 +1552,22 @@ fastObjMesh* fast_obj_read_with_callbacks(const char* path, const fastObjCallbac
}
/* Flush final group */
flush_output(&data);
/* Flush final object/group */
flush_object(&data);
object_clean(&data.object);
flush_group(&data);
group_clean(&data.group);
m->position_count = array_size(m->positions) / 3;
m->texcoord_count = array_size(m->texcoords) / 2;
m->normal_count = array_size(m->normals) / 3;
m->color_count = array_size(m->colors) / 3;
m->face_count = array_size(m->face_vertices);
m->index_count = array_size(m->indices);
m->material_count = array_size(m->materials);
m->texture_count = array_size(m->textures);
m->object_count = array_size(m->objects);
m->group_count = array_size(m->groups);