Repository navigation
Commit 62ff207
Add optimized parser with multithreading, SIMD, and custom allocator support (squashed take-over of tinyobjloader#424) (tinyobjloader#428)
* Add optimized parser with multithreading, SIMD, and custom allocator support
Squashed take-over of tinyobjloader#424 (branch copilot/optimize-parser-for-huge-meshes)
so CI runs on a maintainer-pushed branch.
Highlights:
- New optimized OBJ loader (LoadObjOpt / LoadObjOptTyped) targeting huge meshes,
with fast_float-based ASCII float/double parsing.
- Optional compile-time features: TINYOBJLOADER_USE_MULTITHREADING (threaded
parse + merge), TINYOBJLOADER_USE_SIMD (SSE2/AVX2/NEON newline scanning),
and TINYOBJLOADER_ENABLE_EXCEPTION (opt-in C++ exceptions).
- ArenaAllocator / arena_adapter for bulk allocation and a TypedArray API.
- Experimental stream-based OBJ loader under experimental/stream/.
- Fuzzing harnesses (tests/obj-fuzz, tests/llvm-fuzz, tests/fuzz_common.h)
and extensive parity tests against the legacy loader
(tests/opt/loadobjopt_multithread.inc, tester.cc).
Original work by Copilot coding agent; reviewed and validated locally
(make check passes under clang++ with -std=c++11 -fsanitize=address).
Co-Authored-By: Copilot <198982749+Copilot@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Harden optimized/stream parser per Copilot review
Address the three review comments from Copilot on the take-over PR, plus a
related robustness fix uncovered while doing so.
- experimental/stream: fix `v x y z w r g b` (7-component) vertex parsing.
The stream loader previously treated the weight `w` as red and shifted the
colors. It now mirrors LoadObjOpt, keyed on the component count beyond xyz:
+1 -> weight, +3 -> color (weight = r, legacy compat), +4 -> weight + color.
- tests/tester.cc: include the canonical
experimental/stream/stream_obj_loader.h instead of re-declaring
StreamLoadConfig / LoadObjStreamExperimental, so the test cannot drift from
the real API.
- tests/tester.cc: make test_arena_adapter_overflow_guard conditional on
TINYOBJLOADER_ENABLE_EXCEPTION (allocate() throws std::bad_alloc when
exceptions are enabled, returns nullptr otherwise) so the test no longer
terminates when built with exceptions.
- tiny_obj_loader.h: guard the IMPLEMENTATION block against double inclusion
within a single translation unit (TINYOBJLOADER_IMPLEMENTATION_DEFINED).
Including the stream header after defining TINYOBJLOADER_IMPLEMENTATION now
pulls in tiny_obj_loader.h a second time; without the guard this caused
redefinition errors.
- Add test_stream_loader_weighted_color_vertex_7_components regression test.
Verified: `make check` passes under clang++ and g++, both with and without
-DTINYOBJLOADER_ENABLE_EXCEPTION.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Document 7-component vertex (v x y z w r g b) as a non-standard extension
Web research against the official Wavefront spec, Paul Bourke's vertex-color
reference, and Wikipedia confirms there is no standard 7-component `v` line:
the format defines only xyz / xyzw / xyzrgb, and weight and color are mutually
exclusive.
Per maintainer decision, keep the weight + color interpretation (4th value =
weight, next three = RGB) in LoadObjOpt and the experimental stream loader, but
document clearly that it is a tinyobjloader-specific extension and that the
classic LoadObj / LoadObjWithCallback path instead caps at 6 components, so the
loaders intentionally diverge for 7+ token vertices. Comment-only change; no
behavior change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Make no-SIMD/no-threading/no-exception the tested default; polish dead code
Ensure the library's default configuration (no SIMD, no multithreading, no
exceptions) is the baseline that CI exercises, and clean up warnings/dead code
introduced by the optimized parser.
Default configuration:
- tester.cc no longer force-defines TINYOBJLOADER_USE_MULTITHREADING, so the
default `make check` build now runs with the library defaults (scalar,
single-threaded, exception-free). The header already had no auto-#define of
any feature macro, so consumers were already defaulting to all-off; this just
makes the test build match.
- tests/Makefile builds two binaries: `tester` (defaults) and `tester_features`
(TINYOBJLOADER_USE_MULTITHREADING + _USE_SIMD + ENABLE_EXCEPTION). `make
check` runs both, so CI covers the default and feature-enabled code paths.
New `check_default` / `check_features` targets run a single config.
- Document the opt-in macros (all disabled by default) in the header and
tests/README.
Polish / hardening:
- Remove dead function opt_requires_legacy_fallback (a never-called duplicate
of opt_line_start_is_legacy).
- opt_tryParseDouble: drop the dead inner fast_float branch (unreachable in
every configuration) and guard the whole function with
TINYOBJLOADER_DISABLE_FAST_FLOAT, since it is only called from that fallback
path. Removes two -Wunused-function warnings in the default build.
- Guard the now-unused `cache` parameter in opt_parseLineToThreadData under
TINYOBJLOADER_DISABLE_FAST_FLOAT (-Wunused-parameter).
Verified: default, features, and TINYOBJLOADER_DISABLE_FAST_FLOAT builds all
compile (clang++ and g++, C++11 and C++17) and pass the full suite.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add TINYOBJLOADER_DISABLE_FAST_FLOAT config to the test matrix
`make check` now builds and runs a third configuration, `check_nofastfloat`,
which defines TINYOBJLOADER_DISABLE_FAST_FLOAT to exercise the hand-written
fallback float parser (otherwise library defaults). CI invokes `make check`,
so this fallback path — previously only verified by hand — is now covered
automatically alongside the default and feature-enabled builds.
Verified: all three configs (default, features, nofastfloat) build and pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* README: document the optimized LoadObjOpt loader
Replace the stale "Optimized loader" section (which referenced an old
experimental loader and v0.9/v1.0 benchmark numbers) with a short usage guide
for the in-header LoadObjOpt API: a compilable example, the opt-in
multithreading/SIMD macros (off by default), and a note on the arena-backed
LoadObjOptTyped variant and the experimental stream loader. Also add a
"What's new" entry.
Example verified to compile (-Wall -Wextra) and run against models/cornell_box.obj.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 1fe01b9 commit 62ff207
19 files changed
Lines changed: 11234 additions & 35 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| |||
352 | 353 | | |
353 | 354 | | |
354 | 355 | | |
355 | | - | |
356 | | - | |
357 | | - | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
358 | 360 | | |
359 | | - | |
| 361 | + | |
| 362 | + | |
360 | 363 | | |
361 | | - | |
362 | | - | |
363 | | - | |
364 | | - | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
365 | 395 | | |
366 | 396 | | |
367 | 397 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
0 commit comments