Compare commits

..

181 Commits

Author SHA1 Message Date
Syoyo Fujita
c6817d206b Remove some assert() 2023-06-07 19:10:44 +09:00
Syoyo Fujita
c201efb998 Merge pull request #422 from agnat/fix/add_missing_extras_and_extensions
Add missing extras and extensions fields
2023-06-07 02:47:59 +09:00
Syoyo Fujita
b88e9cc52a Merge pull request #423 from agnat/finish_KHR_lights_puncutal
KHR_lights_punctual: parse light source references from scene nodes
2023-06-06 23:12:50 +09:00
Syoyo Fujita
9417144f48 Merge pull request #424 from agnat/rewrite_ForEachInArray
get rid of std::function
2023-06-06 23:11:12 +09:00
David Siegel
07616e8190 refactor extension and extra serialization
Add missing serialization:

accessor.extensions
accessor.sparse.extensions
accessor.sparse.extras
accessor.sparse.indices.extensions
accessor.sparse.indices.extras
accessor.sparse.values.extensions
accessor.sparse.values.extras
animation.channel.target.extras
animation.sampler.extensions
buffer.extensions
bufferView.extensions
sampler.extensions
camera.orthographic.extensions
camera.perspective.extensions
skin.extras
skin.extensions
2023-06-06 15:40:29 +02:00
David Siegel
bec8a6d54f rewrite ForEachInArray as a simple C++11 function
no need for std::function here. A free function with an unspecified callback will do nicely.
2023-06-06 15:36:07 +02:00
David Siegel
157063fa1b fix: add missing nullptr check 2023-06-06 15:31:58 +02:00
David Siegel
c164878d0f parse light source references 2023-06-06 06:18:14 +02:00
David Siegel
d852f50d49 Add missing extras and extensions fields
Handle extras and extensions in nested “sub-objects”:

animation.channel.target.extras
accessor.sparse.extras
accessor.sparse.extensions
accessor.sparse.indices.extras
accessor.sparse.indices.extensions
accessor.sparse.values.extras
accessor.sparse.values.extensions
2023-06-06 00:07:37 +02:00
David Siegel
22cafa1032 remove duplicate code
use a function to parse extras and extensions
2023-06-06 00:07:37 +02:00
David Siegel
47208b234d fix warnings: unused variable 2023-06-06 00:07:37 +02:00
Syoyo Fujita
5a6df34d99 Simplify version comment in tiny_gltf.h
Remove wuffs code(which was accidently adde to `release` branch)
2023-06-04 19:07:00 +09:00
Syoyo Fujita
147a00a601 Prevent duplicated key generation when serializing lights + RapidJSON backend. Fixes #420 2023-06-04 05:45:24 +09:00
Syoyo Fujita
350c296802 Merge pull request #418 from agnat/fix_get_file_size_bug
[Bugfix] Actually invoke the user-supplied function instead of subtracting from a pointer...
2023-04-26 19:28:58 +09:00
David Siegel
cc93e1fd25 Fix: Actually invoke the user-supplied function 2023-04-26 12:13:41 +02:00
Syoyo Fujita
59cc44ad4f Merge pull request #417 from syoyo/filesize-check
Fix to #416
2023-04-23 23:15:07 +09:00
Syoyo Fujita
1a5046e06b Fix MSVC compile failure on AppVeyor CI. 2023-04-23 23:08:41 +09:00
Syoyo Fujita
877d856e71 Format error message.
Add regression test of issue-416.
2023-04-23 21:47:31 +09:00
Syoyo Fujita
b534b6b0d8 Fix syntax. 2023-04-23 21:40:23 +09:00
Syoyo Fujita
ecfd37dee2 - Add GetFileSizeInBytes Filesystem Callback
- Add feature to limit file size for external resources(images, buffers)
- Use strlen to correctly retrieve a string from a string which contains multiple null-characters.
- Return fail when opening a directory(Posix only). Fixes #416
2023-04-23 21:31:30 +09:00
Syoyo Fujita
5c06b7d03b Merge pull request #415 from louwaque/release
Fix serialization of AnimationChannel::target_node when it is zero
2023-04-19 05:17:06 +09:00
Loïc Escales
a75355b018 Fix serialization of AnimationChannel::target_node when it is zero 2023-04-18 21:03:39 +02:00
Syoyo Fujita
a977f7a16f Merge pull request #412 from agnat/add_char_pointer_ctor
Fix #411 by adding a Value(const char *) constructor.
2023-04-10 19:11:35 +09:00
Syoyo Fujita
5a6c55870e Deprecate ubuntu-18.04 image and update CI build configuration. 2023-04-10 18:51:29 +09:00
David Siegel
49caa65177 Fix #411 by adding a Value(const char *) constructor.
Avoid implicit conversion of pointers to bool. Closes #411.
2023-04-08 23:44:53 +02:00
Syoyo Fujita
d71c6f61f3 Merge pull request #409 from NeilBickford-NV/nbickford/update-stb-image
Updates stb_image and stb_image_write
2023-03-30 18:13:12 +09:00
Neil Bickford
b5d27fd151 stb_image: Apply https://github.com/nothings/stb/pull/1443 2023-03-29 12:00:24 -07:00
Neil Bickford
af4456ba68 stb_image: Apply https://github.com/nothings/stb/pull/1454 2023-03-29 11:57:27 -07:00
Neil Bickford
344669ddf6 Update stb_image and stb_image_write to latest nothings/stb dev branch: 9f1776a36d 2023-03-29 11:56:13 -07:00
Syoyo Fujita
967c98dd90 Merge pull request #408 from marco-langer/feature/ostream_error_handling
Added error checking to ostream writing
2023-03-13 21:18:02 +09:00
Marco Langer
7658624bb4 Added error handling to ostream writing 2023-03-12 19:26:05 +01:00
Syoyo Fujita
84a83d39f5 Merge pull request #407 from DavidSM64/release
Added detail namespace to prevent json namespace conflicts
2023-02-19 02:08:19 +09:00
David
03ad33cc8d Fixed global namespace issue 2023-02-15 23:35:51 -06:00
David
3831802717 Fix RapidJSON implementation (hopefully) 2023-02-15 23:21:09 -06:00
David
1f9a4b97a3 Added detail namespace to prevent namespace conflicts 2023-02-15 22:56:18 -06:00
Syoyo Fujita
6dba104c54 Merge pull request #405 from tioez326/patch-2
Fix typo
2023-02-10 21:00:27 +09:00
tioez326
b5e1b35ef1 Fix typo 2023-02-10 12:09:12 +01:00
Syoyo Fujita
52b73c7f0b Update README.md 2023-01-16 05:46:11 +09:00
Syoyo Fujita
98adbb3fb3 Merge pull request #401 from jmousseau/animation-channel-node-optionality
Fix animation channel target node optionality
2023-01-16 05:33:40 +09:00
Jack Mousseau
283b552a4e Fix animation channel target node optionality 2023-01-15 11:45:45 -08:00
Syoyo Fujita
c2ca97b38b v2.8.1 2023-01-13 18:15:21 +09:00
Syoyo Fujita
f051892c55 Merge pull request #399 from e2e4e6/texture_sampler_name_fix
Missed serialization texture sampler name fixed.
2023-01-13 18:13:12 +09:00
s00665032
137a7ca999 Missed serialization texture sampler name fixed.
According to the glTF 2.0 specification it exists, the internal tinygltf structure contains 'name' field as well.
2023-01-13 12:52:08 +07:00
Syoyo Fujita
477d977fea Merge pull request #398 from nicolas-raoul/patch-1
Fixed typo
2023-01-12 16:21:35 +09:00
Nicolas Raoul
8cd5e759d0 Fixed typo 2023-01-12 15:29:32 +09:00
Syoyo Fujita
a6c3945ed3 Bump version 2.8.0. 2023-01-10 20:42:24 +09:00
Syoyo Fujita
6614bddef3 Merge pull request #397 from pknowlesnv/encode_image_uri
urlencode image urls
2023-01-10 20:31:39 +09:00
Pyarelal Knowles
385946dfd8 add URI encode/decode API
Tinygltf is able to write files defined by a URI, so it needs to be able
to decode it. Since it may also modify the path where the image is saved
it may need to re-encode the URI too. This patch provides an API to set
URI encoding and decoding callbacks and exposes the default decode
method.

Uses the existing dlib::urldecode as a decode default. The encode
callback is left null, matching existing behaviour.

Updates the WriteImageDataFunction signature to include
tinygltf::URICallbacks.

Decodes the image and buffer uris before using them as a filename.

If the encode callback is set, encodes the written image location in the
default WriteImageDataFunction and encodes generated buffer locations
when writing .bin files.

Adds a save+load step to the test image-uri-spaces to verify uri
encoding.
2023-01-09 20:54:29 -08:00
Syoyo Fujita
03bbe0921c Merge pull request #396 from pknowlesnv/image_write_failure
propagate image writing failures
2022-12-30 17:59:41 +09:00
Pyarelal Knowles
a9121550b9 SerializeGltfImage: add missing & std::string ref
Hopefully the compiler would optimize this away but better to avoid the
copy in the first place.
2022-12-29 14:12:29 -08:00
Pyarelal Knowles
d2b0af6915 propagate image writing failures
Modifies UpdateImageObject() so that Returning false from the
WriteImageDataFunction callback results in the WriteGltfScene*() call
returning false.

Does not call WriteImageDataFunction if there is no image data.

Adds test case serialize-image-failure to verify the callback return
code is able to cause an overall failure to save the gltf.
2022-12-29 13:50:17 -08:00
Syoyo Fujita
695608dd11 Update readme. 2022-12-29 21:50:47 +09:00
Syoyo Fujita
584f1dfbe4 Merge branch 'release' of github.com:syoyo/tinygltf into release 2022-12-29 21:13:48 +09:00
Syoyo Fujita
a40ca4c5ab Merge pull request #393 from pknowlesnv/serialize_const
allow serializing a const Model
2022-12-29 21:00:24 +09:00
Pyarelal Knowles
de75d87cfd allow serializing a const Model
Adds 'const' to all Serialize*() methods.

Updates WriteImageData callback to take a URI out pointer that was
previously being written to the Image::uri, which is now const.

This breaks the WriteImageData API and as a side effect, Image::uri will
no longer contain the written image URI after saving.

Adds test serialize-const-image, which verifies the model's image is not
changed (because it's const), but the uri written to the gltf json is
still correct.

Adds test serialize-image-callback that defines a WriteImageDataFunction
and also verifies the uri can be overwritten.
2022-12-28 17:20:09 -08:00
Syoyo Fujita
cf11842e64 Merge pull request #395 from ethanpepro/cmake-export
Add CMake export configuration
2022-12-28 18:33:36 +09:00
James Luke
38003032e3 Add CMake export configuration 2022-12-27 21:12:54 -05:00
Syoyo Fujita
186016bf11 Merge branch 'release' of github.com:syoyo/tinygltf into release 2022-12-03 19:42:27 +09:00
Syoyo Fujita
5ee08f9274 Remove Python 2 description. 2022-12-03 19:40:50 +09:00
Syoyo Fujita
aa613a1f57 Update README.md
Remove Python 2.x description
2022-12-03 19:40:45 +09:00
Syoyo Fujita
222454cc6d Create FUNDING.yml 2022-12-03 18:33:05 +09:00
Syoyo Fujita
16c2d3a8bf Merge pull request #390 from eduardodoria/patch-1
Added Supernova Engine to Projects using TinyGLTF
2022-11-07 21:18:50 +09:00
Eduardo Doria
186093657a Added Supernova Engine to Projects using TinyGLTF 2022-11-07 08:53:47 -03:00
Syoyo Fujita
9bdd256625 Merge pull request #388 from stromaster/patch-1
Avoid multiple asset_manager definitions on Android
2022-10-31 17:40:40 +09:00
Serdar Kocdemir
264ae4c131 Avoid multiple asset_manager definition on Android
Using TINYGLTF_IMPLEMENTATION to make the actual definition of the 'asset_manager' global variable.
2022-10-30 22:32:59 +00:00
Syoyo Fujita
091a1fcc1a Merge pull request #386 from geometrian/master
Fix Clang Compile Warnings/Errors (and Typos)
2022-10-08 19:08:22 +09:00
imallett
3a295887d6 Patch to fix previous commit for MinGW. 2022-10-07 11:20:39 -07:00
imallett
d9ce9eb9d2 Fix a gazillion typos. 2022-10-07 10:37:09 -07:00
imallett
56e1098993 Fix various type mismatches and header include case (fixes compile warnings on Clang). 2022-10-07 10:35:16 -07:00
Syoyo Fujita
9bb5806df4 Merge pull request #385 from operatios/master
Fix UTF-8 filepath on LLVM MinGW
2022-09-25 05:35:36 +09:00
operatios
1668d1ecc5 Fix UTF-8 filepath on LLVM MinGW 2022-09-24 22:37:14 +03:00
Syoyo Fujita
6e8a858c45 Add WASI build procedure. 2022-09-22 04:36:58 +09:00
Syoyo Fujita
e0b625561c v2.6.3 2022-09-19 03:36:58 +09:00
Syoyo Fujita
18450eafe7 Merge pull request #382 from syoyo/glb-zero-chunk
Fix parsing GLB file with empty Chunk1(BIN data).
2022-09-19 03:34:09 +09:00
Syoyo Fujita
e9fbc03e2d Clear error/warn message. 2022-09-19 03:29:57 +09:00
Syoyo Fujita
612e57816f Fix handling <4 byte BIN data.
Fix handling GLB file with empty CHUNK1(BIN).
2022-09-18 21:01:39 +09:00
Kh4n
a778c089d1 readd toplevel makefile 2022-09-17 15:39:28 -05:00
Kh4n
387fd61b83 update test to match gltf-validator 2022-09-17 13:02:39 -05:00
Kh4n
6514490090 update gitignore to remove test file
readd accidental removals in gitignore

undo autoformat

more undo autoformatting
2022-09-17 12:52:59 -05:00
Kh4n
6b7ec9f494 added tests to cover empty, empty buffer, and single byte buffer cases 2022-09-17 12:28:39 -05:00
Syoyo Fujita
c670f08a3b Fix parsing GLB file with empty Chunk1(BIN data). 2022-09-17 19:52:25 +09:00
Syoyo Fujita
eec4c98862 Add note on v2.6.2(Fix out-of-bounds access of accessors. PR#379) 2022-09-16 17:27:20 +09:00
Syoyo Fujita
c7e911cf11 Merge pull request #380 from AlvaroBarua/master
Fixes compiler warning on VS (Unreachable code detected)
2022-09-11 17:56:55 +09:00
AlvaroBarua
43172238f7 Fixes compiler warning on VS (Unreachable code detected) 2022-09-11 00:41:43 +01:00
Syoyo Fujita
0cc23356dc Merge pull request #379 from nirmal/patch-1
Fix possible out of bounds index in LoadFromString
2022-09-07 01:52:55 +09:00
Nirmal Patel
e413216722 Fix possible out of bounds index in LoadFromString 2022-09-06 09:16:31 -07:00
Syoyo Fujita
4581d37bec v2.6.1 2022-09-06 22:02:31 +09:00
Syoyo Fujita
966a9d0df7 Merge pull request #374 from syoyo/glb_chunk_check
Better GLB data size check when reading.
2022-09-06 21:35:47 +09:00
Syoyo Fujita
64452bb5fa Merge pull request #377 from zbendefy/master
Auto detect C++14 standard version
2022-09-06 14:01:26 +09:00
zbendefy
69eeea145b Auto detect C++14 standard version 2022-09-05 23:54:57 +02:00
Syoyo Fujita
24e539621d Merge pull request #376 from kacprzak/master
Read from moved object
2022-09-03 01:16:41 +09:00
Marcin Kacprzak
f4f5c3cf3a Fix read from moved object. 2022-09-02 16:15:54 +02:00
Marcin Kacprzak
b12a54ed15 Silence MS code analysis tool. 2022-09-02 16:13:11 +02:00
Syoyo Fujita
240d993f94 Create codeql-analysis.yml 2022-09-02 05:09:09 +09:00
Syoyo Fujita
46ee8b4276 GLB: Fix interger-overflow when calculating JSON Chunk size.
GLB: Check BIN Chunk size.
GLB: Chenk byte alignment of each chunk.
2022-08-26 22:06:53 +09:00
Syoyo Fujita
3bddc09af4 Update README. 2022-08-19 18:21:24 +09:00
Syoyo Fujita
9117abb45d Merge branch 'master' of github.com:syoyo/tinygltf 2022-08-16 20:11:52 +09:00
Syoyo Fujita
52ff00a384 Do not expand file path since its not necessary for glTF asset path(URI) and for security reason(wordexp). 2022-08-16 20:08:45 +09:00
Syoyo Fujita
0fa56e239c Merge pull request #367 from fynv/master
Sparse accessor: typo fix
2022-08-14 20:54:01 +09:00
Fei Yang
5c2dd83964 Merge branch 'syoyo:master' into master 2022-08-14 19:50:14 +08:00
feiy
1a8814d687 Sparse accessor serialization: typo fix. 2022-08-14 19:49:07 +08:00
Syoyo Fujita
666ab8661c Merge pull request #366 from fynv/master
Adding serialization code for sparse accessors.
2022-08-13 18:34:24 +09:00
feiy
0b31543098 Adding serialization code for sparse accessors. 2022-08-13 10:08:17 +08:00
Syoyo Fujita
81f7dbe53a Partial fix of issue 365 2022-08-02 01:05:34 +09:00
Syoyo Fujita
544969b732 Check the failure of RapidJson Accept(). Fixes #332
TODO: Better error reporting when Accept() failed.
2022-07-13 19:03:33 +09:00
Syoyo Fujita
3d4150419e Merge pull request #362 from hschwane/master
fix images not beeing embeded into stream
2022-06-29 20:16:35 +09:00
Hendrik Schwanekamp
41e1102e57 fix images not beeing embeded into stream 2022-06-29 12:22:40 +02:00
Syoyo Fujita
b901dd62d8 Merge pull request #357 from eariassoto/fix-basic-example
Fix basic example
2022-05-15 20:06:17 +09:00
Syoyo Fujita
bc03ceaac1 Merge pull request #358 from brlcad/patch-2
treat powerpc as big endian too
2022-05-15 20:02:28 +09:00
Christopher Sean Morrison
2c9b25642b treat powerpc as big endian too
added powerpc to the list of big endian types
2022-05-14 19:00:19 -04:00
Emmanuel Arias Soto
a894904f11 Fix basic example
Context: When parsing a mesh with primitives that have indices pointing to different buffer views, the VAO will use the last GL_ELEMENT_ARRAY_BUFFER that was bound to it. In this scenario, the mesh will not be rendered properly.

When binding a mesh, return VAO and EBOs so that primitives can bind to the proper element array buffer.
2022-05-14 19:54:03 +02:00
Syoyo Fujita
912856823d Add Open3D to "projects using TinyGLTF". 2022-05-07 01:35:14 +09:00
Syoyo Fujita
1a7c7d2001 Merge pull request #353 from mgerhardy/master
Fixed find_last_of call in GetBaseFilename
2022-03-14 14:50:32 +09:00
Martin Gerhardy
fae6543b7a Fixed find_last_of call in GetBaseFilename
this leads to a stack overflow on linux - it looks like this magically works on msvc though...
2022-03-13 18:42:39 +01:00
Syoyo Fujita
6ed7c39d71 Add note on componentType double type. 2022-03-03 16:40:54 +09:00
Syoyo Fujita
5a90ab76ee Merge pull request #350 from tsmaster/master
Examples/glview - apply translation, rotation, scale in that order
2022-03-03 03:16:29 +09:00
Dave LeCompte
0ffdc4334a Examples/glview - apply translation, rotation, scale in that order
Tested on the Kenney.nl CarKit models: https://www.kenney.nl/assets/car-kit
2022-03-02 07:01:34 -08:00
Syoyo Fujita
53338352f2 Merge pull request #349 from tsmaster/master
Fix examples/glview rotations
2022-03-02 02:55:15 +09:00
Dave LeCompte
d642c80a86 Fix examples/glview rotations
GLtf defines rotations as quaternions, glRotated expects angle/axis, with angle in degrees.
2022-03-01 08:11:22 -08:00
Syoyo Fujita
a1952053ee Merge pull request #347 from syoyo/jmousseau-sparse-accessor-optionality
Jmousseau sparse accessor optionality
2022-02-26 21:27:35 +09:00
Syoyo Fujita
cbd3885049 Check required attribute exists for SparseAccessor. 2022-02-26 21:19:15 +09:00
Jack Mousseau
9471517c1e Fix byte offset optionality for sparse accessor indices and values 2022-02-24 14:25:37 -08:00
Syoyo Fujita
e59028d68f Merge pull request #345 from syoyo/github-actions-ci-fix
GitHub actions ci fix
2022-02-25 02:07:46 +09:00
Syoyo Fujita
cfab524125 VS2019 seems gone. Use VS2022. 2022-02-25 01:39:02 +09:00
Syoyo Fujita
9229971bcb Print cmake help 2022-02-25 01:25:15 +09:00
Syoyo Fujita
051149311c Specify x64 for MSVC build. 2022-02-25 01:11:51 +09:00
Syoyo Fujita
0c7789b1e5 Merge pull request #344 from epajarre/fix-wrapS
Added missing comparison for wrapS
2022-02-24 21:52:43 +09:00
Eero Pajarre
51b12d2546 Added missing comparison for wrapS 2022-02-24 14:38:20 +02:00
Syoyo Fujita
4749b0989d Merge pull request #342 from brlcad/patch-1
add missing switch case for binary
2022-02-24 03:34:58 +09:00
Christopher Sean Morrison
0bfcb4f49e add missing switch case for binary
with warnings cranked up and warnings-as-errors enabled, the compiler throws an error due to this switch missing a case for binary.  this makes the ignore explicit in order for compilation to proceed.
2022-02-23 10:02:49 -05:00
Syoyo Fujita
17e6e310ce Merge pull request #341 from mushrom/loopfix
Fixing loop index
2022-02-14 17:10:31 +09:00
My Name
07ceb4c313 Fixing loop index 2022-02-13 16:31:27 -05:00
Syoyo Fujita
e7f1ff5c59 Merge pull request #339 from yslking/yslking-update-json-hpp-3-10-4
update json.hpp to v3.10.4 to compile with c++20 compilers
2021-11-28 22:25:34 +09:00
yslking
fd904063c9 update json.hpp to v3.10.4 2021-11-28 15:08:05 +08:00
Syoyo Fujita
38398cc2da Fix typo from PR #320 2021-11-21 18:59:10 +09:00
Syoyo Fujita
ed1a294bc4 Merge branch 'master' of github.com:syoyo/tinygltf 2021-11-21 18:58:39 +09:00
Syoyo Fujita
b86eb6c079 Merge pull request #331 from abwood/so-updates
Remove stackoverflow references from tinygltf.
2021-10-19 21:45:19 +09:00
Alexander Wood
e4bc6c7bd4 - Remove clang warning suppression. I assume this stackoverflow reference can just be removed as it isn't a code snippet but a repost of clang documentation of ignoring warning levels.
- Remove stackoverflow reference that recommends the use of dlib. There's no source that was pulled from this s.o. post, only a recommendation on a library, I wouldn't think a link to s.o. is necessary here. Per the Boost License, I've included a copy of the license along with the snippet
2021-10-14 08:54:59 -04:00
Alexander Wood
13803659f8 Build fix. 2021-10-08 20:13:07 -04:00
Alexander Wood
a3d5d5d1c9 Build fix. 2021-10-08 20:09:08 -04:00
Alexander Wood
9e3d1f6db5 Build fix. 2021-10-08 16:57:56 -04:00
Alexander Wood
190382aecd GetBaseFilename contained a logic error in that a filename that does not contain a path separator would result in a crash.
Removed the roundUp lambda, as this generalization is not necessary; the caller always attempts 4 byte alignment.
2021-10-08 12:19:13 -04:00
Syoyo Fujita
c6501530e3 Merge branch 'master' of github.com:syoyo/tinygltf 2021-09-24 17:11:07 +09:00
Syoyo Fujita
ed48224f4b Describe current status(its stable) 2021-09-24 17:10:29 +09:00
Syoyo Fujita
19a41d20ec Merge pull request #330 from cgdae/master
Fix for OpenBSD - wordexp.h not available.
2021-08-25 20:25:03 +09:00
Julian Smith
0598a20cce Fix for OpenBSD - wordexp.h not available. 2021-08-25 12:06:08 +01:00
Syoyo Fujita
514167b475 Merge pull request #329 from syoyo/cmake-add-subdirectory
Cmake add subdirectory
2021-07-03 22:09:26 +09:00
Syoyo Fujita
0f76561ebf Add readme to use tinygtf through cmake + add_subdirectory. 2021-07-03 22:06:29 +09:00
Syoyo Fujita
f3dc4acaa4 Merge branch 'master' into cmake-add-subdirectory 2021-07-03 22:01:46 +09:00
Syoyo Fujita
1588e75e26 Merge branch 'master' of github.com:syoyo/tinygltf 2021-06-09 21:23:57 +09:00
Syoyo Fujita
d1453b5e5e GLEW_LIBRARY -> GLEW_LIBRARIES 2021-06-09 21:23:37 +09:00
Syoyo Fujita
7e83ef9fb4 Merge pull request #327 from CppProgrammer23/master
update enum Type
2021-05-20 20:44:16 +09:00
Idriss Chaouch
425195bf9c update enum Type
the first element in an enum is 0, so it's not necessarily to affect values from 0 to 7.
2021-05-20 12:11:00 +01:00
Syoyo Fujita
ce3a30e612 Merge pull request #326 from xzrunner/master
Fix comment on minFilter
2021-05-14 15:06:07 +09:00
zz
8a35b8f6fe Fix comment on minFilter 2021-05-14 13:49:33 +08:00
Syoyo Fujita
f66f3bfeb3 Merge pull request #325 from iceydee/scene-extras
Store scene extras and extensions on the scene
2021-05-11 19:01:25 +09:00
Mio Nilsson
e29ba7c49a 🐛 Store scene extras and exteions on the scene
This was being stored in the wrong place
2021-05-11 11:50:35 +02:00
Syoyo Fujita
bc753d4ac5 Merge pull request #322 from syoyo/fix-negative-skeleton-id
Do not serialize skeleton id -1
2021-04-29 16:20:42 +09:00
Syoyo Fujita
688ba8a60e Add regression test for issue 321 2021-04-29 16:04:52 +09:00
Syoyo Fujita
d07b976d59 Do not write negative skeleton id(skeleton is not assigned).
Also ensure `inverseBindMatrices` should not be -2 or other negative values.
2021-04-28 19:15:16 +09:00
Syoyo Fujita
08a7dd8dad Merge pull request #317 from Snowapril/master
Delete unused variable initialization code
2021-03-30 03:15:26 +09:00
snowapril
87da1e775f Delete unused variable initialization code
Line 4536 in tinygltf.h file, there is unused variable initialization code like below.
```c++
    const auto pBuffer = pAttribute->buffer();
```

gcc compiler complain about that unused variable. 

I found there is no side-effect in  `pAttribute->buffer()` call and also pBuffer variable is never used. Therefore I delete that line entirely.
2021-03-30 00:16:04 +09:00
Syoyo Fujita
151495558e Merge pull request #314 from Snowapril/master
Add (void)err for handling unused variable warning
2021-03-20 19:59:44 +09:00
snowapril
84e15260ba add (void)err for handling unused variable warning
I saw in the `ParseExtensionsProperty`(3667) function,
unused variable err argument is wrapped with (void) keword.

I think err argument in the `ParseDracoExtension`(4472) is exactly
same situation with the above one.

For consistency, I think it need to be added (void)err in the
`ParseDracoExtension` function.
2021-03-20 19:25:58 +09:00
Syoyo Fujita
03cdef430d Merge pull request #312 from AlvaroBarua/no_include_rapidjson
Added TINYGLTF_NO_INCLUDE_RAPIDJSON
2021-03-19 14:32:35 +09:00
AlvaroBarua
fb4bd82e2c Updated Readme.md 2021-03-18 18:40:09 +00:00
Alvaro Barua
3ddf8301f6 Added TINYGLTF_NO_INCLUDE_RAPIDJSON for consistency and because my project already used rapidjson/ 2021-03-18 00:21:23 +00:00
Syoyo Fujita
298c37a954 Merge pull request #310 from syoyo/write-assert-version
`asset.version` is a required field
2021-03-03 00:35:55 +09:00
Syoyo Fujita
b702de755f asset.version is a required field so write "2.0" when asset.version is empty. Fixes #308 2021-03-02 19:08:29 +09:00
Syoyo Fujita
58ceed1d89 Add CMake file and Makefile for examples/build-gltf 2021-02-26 18:34:00 +09:00
Dov Grobgeld
d1b6b3a5aa Add example for creating a triangle gltf file from scratch 2021-02-26 09:30:05 +02:00
Syoyo Fujita
c56d069726 Merge pull request #306 from mahiuchun/const
Drop an unnecessary 'const'.
2021-02-21 16:07:51 +09:00
Hill Ma
d1e32865f1 Drop an unnecessary 'const'. 2021-02-20 22:30:44 -08:00
Syoyo Fujita
869a9d273c Merge pull request #305 from Selmar/patch-2
check correct `extensionsUsed` for serialization
2021-02-02 14:17:34 +09:00
Selmar
1208f057d6 check correct extensionsUsed for serialization 2021-02-01 19:24:41 +01:00
Syoyo Fujita
f684dde9f1 Merge pull request #303 from syoyo/int-minmax-serialize
Issue #301. Serialize accessor min/vax value as int
2021-01-22 03:40:52 +09:00
Syoyo Fujita
7905a5b4dc Issue #301. Serialize accessor min/vax value as int if its component type is an integer. 2021-01-21 20:33:11 +09:00
Syoyo Fujita
f161782001 Merge pull request #299 from DethRaid/patch-1
Add my project to the README
2020-12-23 15:46:32 +09:00
David Dubois
654bcf733c Add my project to the README
My personal project uses tinygltf so i want to add it to the "Projects using TinyGLTF" section of the README
2020-12-22 22:32:59 -08:00
syoyo
001c870051 Make cmake script add_subdirectory friendly. 2020-12-18 01:10:21 +09:00
Syoyo Fujita
2c521b3432 Remove sampler.wrapR parameter(unused tinygltf extension). Fixes #287
Suppress clang `-Wdocumentation-unknown-command` warning.
2020-12-04 00:50:46 +09:00
26 changed files with 15961 additions and 7976 deletions

13
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: syoyo
#patreon: # Replace with a single Patreon username
#open_collective: # Replace with a single Open Collective username
#ko_fi: # Replace with a single Ko-fi username
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
#liberapay: # Replace with a single Liberapay username
#issuehunt: # Replace with a single IssueHunt username
#otechie: # Replace with a single Otechie username
#lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -4,41 +4,43 @@ on: [push, pull_request]
jobs: jobs:
# compile with older gcc4.8 # gcc4.8 is too old and ubuntu-18.04 image is not supported in GitHub Actions anymore,
build-gcc48: # so disable this build.
## compile with older gcc4.8
#build-gcc48:
runs-on: ubuntu-18.04 # runs-on: ubuntu-18.04
name: Build with gcc 4.8 # name: Build with gcc 4.8
steps: # steps:
- name: Checkout # - name: Checkout
uses: actions/checkout@v1 # uses: actions/checkout@v1
- name: Build # - name: Build
run: | # run: |
sudo apt-get update # sudo apt-get update
sudo apt-get install -y build-essential # sudo apt-get install -y build-essential
sudo apt-get install -y gcc-4.8 g++-4.8 # sudo apt-get install -y gcc-4.8 g++-4.8
g++-4.8 -std=c++11 -o loader_example loader_example.cc # g++-4.8 -std=c++11 -o loader_example loader_example.cc
- name: NoexceptBuild # - name: NoexceptBuild
run: | # run: |
g++-4.8 -DTINYGLTF_NOEXCEPTION -std=c++11 -o loader_example loader_example.cc # g++-4.8 -DTINYGLTF_NOEXCEPTION -std=c++11 -o loader_example loader_example.cc
- name: RapidjsonBuild # - name: RapidjsonBuild
run: | # run: |
git clone https://github.com/Tencent/rapidjson # git clone https://github.com/Tencent/rapidjson
g++-4.8 -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -o loader_example loader_example.cc # g++-4.8 -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -o loader_example loader_example.cc
# compile with mingw gcc cross # compile with mingw gcc cross
build-mingw-cross: build-mingw-cross:
runs-on: ubuntu-18.04 runs-on: ubuntu-latest
name: Build with MinGW gcc cross name: Build with MinGW gcc cross
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v1 uses: actions/checkout@v2
- name: Build - name: Build
run: | run: |
@@ -47,7 +49,8 @@ jobs:
sudo apt-get install -y mingw-w64 sudo apt-get install -y mingw-w64
x86_64-w64-mingw32-g++ -std=c++11 -o loader_example loader_example.cc x86_64-w64-mingw32-g++ -std=c++11 -o loader_example loader_example.cc
# Windows(x64) + Visual Studio 2019 build # Windows(x64) + Visual Studio 2022 build
# Assume windows-latest have VS2022 installed
build-windows-msvc: build-windows-msvc:
runs-on: windows-latest runs-on: windows-latest
@@ -62,7 +65,8 @@ jobs:
run: | run: |
mkdir build mkdir build
cd build cd build
cmake -G "Visual Studio 16 2019" -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On .. cmake --help
cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On ..
cd .. cd ..
- name: Build - name: Build
run: cmake --build build --config Release run: cmake --build build --config Release
@@ -131,20 +135,20 @@ jobs:
# Cross-compile for aarch64 linux target # Cross-compile for aarch64 linux target
build-cross-aarch64: build-cross-aarch64:
runs-on: ubuntu-18.04 runs-on: ubuntu-latest
name: Build on cross aarch64 name: Build on cross aarch64
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v1 uses: actions/checkout@v2
- name: Build - name: Build
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y build-essential sudo apt-get install -y build-essential
sudo apt-get install -y gcc-8-aarch64-linux-gnu g++-8-aarch64-linux-gnu sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
git clone https://github.com/Tencent/rapidjson git clone https://github.com/Tencent/rapidjson
aarch64-linux-gnu-g++-8 -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -g -O0 -o loader_example loader_example.cc aarch64-linux-gnu-g++ -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -g -O0 -o loader_example loader_example.cc
# macOS clang # macOS clang
build-macos: build-macos:

72
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
schedule:
- cron: '21 20 * * 5'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

7
.gitignore vendored
View File

@@ -68,4 +68,11 @@ loader_example
tests/tester tests/tester
tests/tester_noexcept tests/tester_noexcept
tests/issue-97.gltf tests/issue-97.gltf
tests/issue-261.gltf
# unignore
!Makefile
!examples/build-gltf/Makefile
!examples/raytrace/cornellbox_suzanne.obj
!tests/Makefile
!tools/windows/premake5.exe

View File

@@ -2,11 +2,17 @@ cmake_minimum_required(VERSION 3.6)
PROJECT (tinygltf) PROJECT (tinygltf)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD 11)
option(TINYGLTF_BUILD_LOADER_EXAMPLE "Build loader_example" ON) option(TINYGLTF_BUILD_LOADER_EXAMPLE "Build loader_example(load glTF and dump infos)" ON)
option(TINYGLTF_BUILD_GL_EXAMPLES "Build GL exampels(requires glfw, OpenGL, etc)" OFF) option(TINYGLTF_BUILD_GL_EXAMPLES "Build GL exampels(requires glfw, OpenGL, etc)" OFF)
option(TINYGLTF_BUILD_VALIDATOR_EXAMPLE "Build validator exampe" OFF) option(TINYGLTF_BUILD_VALIDATOR_EXAMPLE "Build validator exampe" OFF)
option(TINYGLTF_BUILD_BUILDER_EXAMPLE "Build glTF builder example" OFF)
option(TINYGLTF_HEADER_ONLY "On: header-only mode. Off: create tinygltf library(No TINYGLTF_IMPLEMENTATION required in your project)" OFF)
option(TINYGLTF_INSTALL "Install tinygltf files during install step. Usually set to OFF if you include tinygltf through add_subdirectory()" ON)
if (TINYGLTF_BUILD_LOADER_EXAMPLE) if (TINYGLTF_BUILD_LOADER_EXAMPLE)
ADD_EXECUTABLE ( loader_example ADD_EXECUTABLE ( loader_example
@@ -22,20 +28,49 @@ endif (TINYGLTF_BUILD_GL_EXAMPLES)
if (TINYGLTF_BUILD_VALIDATOR_EXAMPLE) if (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
ADD_SUBDIRECTORY ( examples/validator ) ADD_SUBDIRECTORY ( examples/validator )
endif (TINYGLTF_BUILD_VALIDATOR_EXAMPLE) endif (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
if (TINYGLTF_BUILD_BUILDER_EXAMPLE)
ADD_SUBDIRECTORY ( examples/build-gltf )
endif (TINYGLTF_BUILD_BUILDER_EXAMPLE)
# #
# TinuGLTF is a header-only library, so no library build. just install header files. # for add_subdirectory and standalone build
# #
INSTALL ( FILES if (TINYGLTF_HEADER_ONLY)
json.hpp add_library(tinygltf INTERFACE)
stb_image.h
stb_image_write.h target_include_directories(tinygltf
tiny_gltf.h INTERFACE
DESTINATION $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
include $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
INSTALL ( FILES else (TINYGLTF_HEADER_ONLY)
cmake/TinyGLTFConfig.cmake add_library(tinygltf)
DESTINATION target_sources(tinygltf PRIVATE
cmake ${CMAKE_CURRENT_SOURCE_DIR}/tiny_gltf.cc)
) target_include_directories(tinygltf
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
endif (TINYGLTF_HEADER_ONLY)
if (TINYGLTF_INSTALL)
install(TARGETS tinygltf EXPORT tinygltfTargets)
install(EXPORT tinygltfTargets NAMESPACE tinygltf:: FILE TinyGLTFTargets.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/TinyGLTFConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/TinyGLTFConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/TinyGLTFConfig.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
# Do not install .lib even if !TINYGLTF_HEADER_ONLY
INSTALL ( FILES
json.hpp
stb_image.h
stb_image_write.h
tiny_gltf.h
${TINYGLTF_EXTRA_SOUECES}
DESTINATION
include
)
endif(TINYGLTF_INSTALL)

View File

@@ -2,20 +2,27 @@
`TinyGLTF` is a header only C++11 glTF 2.0 https://github.com/KhronosGroup/glTF library. `TinyGLTF` is a header only C++11 glTF 2.0 https://github.com/KhronosGroup/glTF library.
`TinyGLTF` uses Niels Lohmann's json library(https://github.com/nlohmann/json), so now it requires C++11 compiler. `TinyGLTF` uses Niels Lohmann's json library (https://github.com/nlohmann/json), so now it requires C++11 compiler.
If you are looking for old, C++03 version, please use `devel-picojson` branch(but not maintained anymore). (Also, you can use RadpidJSON as an JSON backend)
If you are looking for old, C++03 version, please use `devel-picojson` branch (but not maintained anymore).
## Status ## Status
Currently TinyGLTF is stable and maintenance mode. No drastic changes and feature additions planned.
- v2.8.0 Add URICallbacks for custom URI handling in Buffer and Image. PR#397
- v2.7.0 Change WriteImageDataFunction user callback function signature. PR#393
- v2.6.0 Support serializing sparse accessor(Thanks to @fynv).
- v2.5.0 Add SetPreserveImageChannels() option to load image data as is.
- v2.4.0 Experimental RapidJSON support. Experimental C++14 support(C++14 may give better performance) - v2.4.0 Experimental RapidJSON support. Experimental C++14 support(C++14 may give better performance)
- v2.3.0 Modified Material representation according to glTF 2.0 schema(and introduced TextureInfo class) - v2.3.0 Modified Material representation according to glTF 2.0 schema(and introduced TextureInfo class)
- v2.2.0 release(Support loading 16bit PNG. Sparse accessor support) - v2.2.0 release(Support loading 16bit PNG. Sparse accessor support)
- v2.1.0 release(Draco support) - v2.1.0 release(Draco decoding support)
- v2.0.0 release(22 Aug, 2018)! - v2.0.0 release(22 Aug, 2018)!
### Branches ### Branches
* `sajson` : Use sajson to parse JSON. Parsing only but faster compile time(2x reduction compared to json.hpp and RapidJson) * `sajson` : Use sajson to parse JSON. Parsing only but faster compile time(2x reduction compared to json.hpp and RapidJson), but not well maintained.
## Builds ## Builds
@@ -27,6 +34,8 @@ If you are looking for old, C++03 version, please use `devel-picojson` branch(bu
## Features ## Features
Probably mostly feature-complete. Last missing feature is Draco encoding: https://github.com/syoyo/tinygltf/issues/207
* Written in portable C++. C++-11 with STL dependency only. * Written in portable C++. C++-11 with STL dependency only.
* [x] macOS + clang(LLVM) * [x] macOS + clang(LLVM)
* [x] iOS + clang * [x] iOS + clang
@@ -77,6 +86,13 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
* [glview](examples/glview) : Simple glTF geometry viewer. * [glview](examples/glview) : Simple glTF geometry viewer.
* [validator](examples/validator) : Simple glTF validator with JSON schema. * [validator](examples/validator) : Simple glTF validator with JSON schema.
* [basic](examples/basic) : Basic glTF viewer with texturing support. * [basic](examples/basic) : Basic glTF viewer with texturing support.
* [build-gltf](examples/build-gltf) : Build simple glTF scene from a scratch.
### WASI/WASM build
Users who want to run TinyGLTF securely and safely(e.g. need to handle malcious glTF file to serve online glTF conver),
I recommend to build TinyGLTF for WASM target.
WASI build example is located in [wasm](wasm) .
## Projects using TinyGLTF ## Projects using TinyGLTF
@@ -90,11 +106,14 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
* [GlslViewer](https://github.com/patriciogonzalezvivo/glslViewer) - live GLSL coding for MacOS and Linux * [GlslViewer](https://github.com/patriciogonzalezvivo/glslViewer) - live GLSL coding for MacOS and Linux
* [Vulkan-Samples](https://github.com/KhronosGroup/Vulkan-Samples) - The Vulkan Samples is collection of resources to help you develop optimized Vulkan applications. * [Vulkan-Samples](https://github.com/KhronosGroup/Vulkan-Samples) - The Vulkan Samples is collection of resources to help you develop optimized Vulkan applications.
* [TDME2](https://github.com/andreasdr/tdme2) - TDME2 - ThreeDeeMiniEngine2 is a lightweight 3D engine including tools suited for 3D game development using C++11 * [TDME2](https://github.com/andreasdr/tdme2) - TDME2 - ThreeDeeMiniEngine2 is a lightweight 3D engine including tools suited for 3D game development using C++11
* [SanityEngine](https://github.com/DethRaid/SanityEngine) - A C++/D3D12 renderer focused on the personal and professional development of its developer
* [Open3D](http://www.open3d.org/) - A Modern Library for 3D Data Processing
* [Supernova Engine](https://github.com/supernovaengine/supernova) - Game engine for 2D and 3D projects with Lua or C++ in data oriented design.
* Your projects here! (Please send PR) * Your projects here! (Please send PR)
## TODOs ## TODOs
* [ ] Write C++ code generator which emits C++ code from JSON schema for robust parsing. * [ ] Robust URI decoding/encoding. https://github.com/syoyo/tinygltf/issues/369
* [ ] Mesh Compression/decompression(Open3DGC, etc) * [ ] Mesh Compression/decompression(Open3DGC, etc)
* [x] Load Draco compressed mesh * [x] Load Draco compressed mesh
* [ ] Save Draco compressed mesh * [ ] Save Draco compressed mesh
@@ -105,6 +124,10 @@ In extension(`ExtensionMap`), JSON number value is parsed as int or float(number
* [ ] 16bit PNG support in Serialization * [ ] 16bit PNG support in Serialization
* [ ] Write example and tests for `animation` and `skin` * [ ] Write example and tests for `animation` and `skin`
### Optional
* [ ] Write C++ code generator which emits C++ code from JSON schema for robust parsing?
## Licenses ## Licenses
TinyGLTF is licensed under MIT license. TinyGLTF is licensed under MIT license.
@@ -168,12 +191,28 @@ if (!ret) {
* `TINYGLTF_ANDROID_LOAD_FROM_ASSETS`: Load all files from packaged app assets instead of the regular file system. **Note:** You must pass a valid asset manager from your android app to `tinygltf::asset_manager` beforehand. * `TINYGLTF_ANDROID_LOAD_FROM_ASSETS`: Load all files from packaged app assets instead of the regular file system. **Note:** You must pass a valid asset manager from your android app to `tinygltf::asset_manager` beforehand.
* `TINYGLTF_ENABLE_DRACO`: Enable Draco compression. User must provide include path and link correspnding libraries in your project file. * `TINYGLTF_ENABLE_DRACO`: Enable Draco compression. User must provide include path and link correspnding libraries in your project file.
* `TINYGLTF_NO_INCLUDE_JSON `: Disable including `json.hpp` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`. * `TINYGLTF_NO_INCLUDE_JSON `: Disable including `json.hpp` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
* `TINYGLTF_NO_INCLUDE_RAPIDJSON `: Disable including RapidJson's header files from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
* `TINYGLTF_NO_INCLUDE_STB_IMAGE `: Disable including `stb_image.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`. * `TINYGLTF_NO_INCLUDE_STB_IMAGE `: Disable including `stb_image.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
* `TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE `: Disable including `stb_image_write.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`. * `TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE `: Disable including `stb_image_write.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
* `TINYGLTF_USE_RAPIDJSON` : Use RapidJSON as a JSON parser/serializer. RapidJSON files are not included in TinyGLTF repo. Please set an include path to RapidJSON if you enable this featrure. * `TINYGLTF_USE_RAPIDJSON` : Use RapidJSON as a JSON parser/serializer. RapidJSON files are not included in TinyGLTF repo. Please set an include path to RapidJSON if you enable this feature.
* `TINYGLTF_USE_CPP14` : Use C++14 feature(requires C++14 compiler). This may give better performance than C++11. * `TINYGLTF_USE_CPP14` : Use C++14 feature(requires C++14 compiler). This may give better performance than C++11.
## CMake options
You can add tinygltf using `add_subdirectory` feature.
If you add tinygltf to your project using `add_subdirectory`, it would be better to set `TINYGLTF_HEADER_ONLY` on(just add an include path to tinygltf) and `TINYGLTF_INSTALL` off(Which does not install tinygltf files).
```
// Your project's CMakeLists.txt
...
set(TINYGLTF_HEADER_ONLY ON CACHE INTERNAL "" FORCE)
set(TINYGLTF_INSTALL OFF CACHE INTERNAL "" FORCE)
add_subdirectory(/path/to/tinygltf)
```
### Saving gltTF 2.0 model ### Saving gltTF 2.0 model
* Buffers. * Buffers.
@@ -193,7 +232,7 @@ if (!ret) {
#### Setup #### Setup
Python 2.6 or 2.7 required. Python required.
Git clone https://github.com/KhronosGroup/glTF-Sample-Models to your local dir. Git clone https://github.com/KhronosGroup/glTF-Sample-Models to your local dir.
#### Run parsing test #### Run parsing test

View File

@@ -1,15 +0,0 @@
# -*- cmake -*-
# - Find TinyGLTF
# TinyGLTF_INCLUDE_DIR TinyGLTF's include directory
FIND_PACKAGE ( PackageHandleStandardArgs )
SET ( TinyGLTF_INCLUDE_DIR "${TinyGLTF_DIR}/../include" CACHE STRING "TinyGLTF include directory")
FIND_FILE ( TinyGLTF_HEADER tiny_gltf.h PATHS ${TinyGLTF_INCLUDE_DIR} )
IF (NOT TinyGLTF_HEADER)
MESSAGE ( FATAL_ERROR "Unable to find tiny_gltf.h, TinyGLTF_INCLUDE_DIR = ${TinyGLTF_INCLUDE_DIR}")
ENDIF ()

View File

@@ -0,0 +1,3 @@
@PACKAGE_INIT@
include(${CMAKE_CURRENT_LIST_DIR}/TinyGLTFTargets.cmake)

View File

@@ -39,8 +39,8 @@ bool loadModel(tinygltf::Model &model, const char *filename) {
return res; return res;
} }
std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos, void bindMesh(std::map<int, GLuint>& vbos,
tinygltf::Model &model, tinygltf::Mesh &mesh) { tinygltf::Model &model, tinygltf::Mesh &mesh) {
for (size_t i = 0; i < model.bufferViews.size(); ++i) { for (size_t i = 0; i < model.bufferViews.size(); ++i) {
const tinygltf::BufferView &bufferView = model.bufferViews[i]; const tinygltf::BufferView &bufferView = model.bufferViews[i];
if (bufferView.target == 0) { // TODO impl drawarrays if (bufferView.target == 0) { // TODO impl drawarrays
@@ -144,12 +144,10 @@ std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
} }
} }
} }
return vbos;
} }
// bind models // bind models
void bindModelNodes(std::map<int, GLuint> vbos, tinygltf::Model &model, void bindModelNodes(std::map<int, GLuint>& vbos, tinygltf::Model &model,
tinygltf::Node &node) { tinygltf::Node &node) {
if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) { if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) {
bindMesh(vbos, model, model.meshes[node.mesh]); bindMesh(vbos, model, model.meshes[node.mesh]);
@@ -160,7 +158,8 @@ void bindModelNodes(std::map<int, GLuint> vbos, tinygltf::Model &model,
bindModelNodes(vbos, model, model.nodes[node.children[i]]); bindModelNodes(vbos, model, model.nodes[node.children[i]]);
} }
} }
GLuint bindModel(tinygltf::Model &model) {
std::pair<GLuint, std::map<int, GLuint>> bindModel(tinygltf::Model &model) {
std::map<int, GLuint> vbos; std::map<int, GLuint> vbos;
GLuint vao; GLuint vao;
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
@@ -173,19 +172,29 @@ GLuint bindModel(tinygltf::Model &model) {
} }
glBindVertexArray(0); glBindVertexArray(0);
// cleanup vbos // cleanup vbos but do not delete index buffers yet
for (size_t i = 0; i < vbos.size(); ++i) { for (auto it = vbos.cbegin(); it != vbos.cend();) {
glDeleteBuffers(1, &vbos[i]); tinygltf::BufferView bufferView = model.bufferViews[it->first];
if (bufferView.target != GL_ELEMENT_ARRAY_BUFFER) {
glDeleteBuffers(1, &vbos[it->first]);
vbos.erase(it++);
}
else {
++it;
}
} }
return vao; return {vao, vbos};
} }
void drawMesh(tinygltf::Model &model, tinygltf::Mesh &mesh) { void drawMesh(const std::map<int, GLuint>& vbos,
tinygltf::Model &model, tinygltf::Mesh &mesh) {
for (size_t i = 0; i < mesh.primitives.size(); ++i) { for (size_t i = 0; i < mesh.primitives.size(); ++i) {
tinygltf::Primitive primitive = mesh.primitives[i]; tinygltf::Primitive primitive = mesh.primitives[i];
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices]; tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos.at(indexAccessor.bufferView));
glDrawElements(primitive.mode, indexAccessor.count, glDrawElements(primitive.mode, indexAccessor.count,
indexAccessor.componentType, indexAccessor.componentType,
BUFFER_OFFSET(indexAccessor.byteOffset)); BUFFER_OFFSET(indexAccessor.byteOffset));
@@ -193,20 +202,22 @@ void drawMesh(tinygltf::Model &model, tinygltf::Mesh &mesh) {
} }
// recursively draw node and children nodes of model // recursively draw node and children nodes of model
void drawModelNodes(tinygltf::Model &model, tinygltf::Node &node) { void drawModelNodes(const std::pair<GLuint, std::map<int, GLuint>>& vaoAndEbos,
tinygltf::Model &model, tinygltf::Node &node) {
if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) { if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) {
drawMesh(model, model.meshes[node.mesh]); drawMesh(vaoAndEbos.second, model, model.meshes[node.mesh]);
} }
for (size_t i = 0; i < node.children.size(); i++) { for (size_t i = 0; i < node.children.size(); i++) {
drawModelNodes(model, model.nodes[node.children[i]]); drawModelNodes(vaoAndEbos, model, model.nodes[node.children[i]]);
} }
} }
void drawModel(GLuint vao, tinygltf::Model &model) { void drawModel(const std::pair<GLuint, std::map<int, GLuint>>& vaoAndEbos,
glBindVertexArray(vao); tinygltf::Model &model) {
glBindVertexArray(vaoAndEbos.first);
const tinygltf::Scene &scene = model.scenes[model.defaultScene]; const tinygltf::Scene &scene = model.scenes[model.defaultScene];
for (size_t i = 0; i < scene.nodes.size(); ++i) { for (size_t i = 0; i < scene.nodes.size(); ++i) {
drawModelNodes(model, model.nodes[scene.nodes[i]]); drawModelNodes(vaoAndEbos, model, model.nodes[scene.nodes[i]]);
} }
glBindVertexArray(0); glBindVertexArray(0);
@@ -282,7 +293,7 @@ void displayLoop(Window &window, const std::string &filename) {
tinygltf::Model model; tinygltf::Model model;
if (!loadModel(model, filename.c_str())) return; if (!loadModel(model, filename.c_str())) return;
GLuint vao = bindModel(model); std::pair<GLuint, std::map<int, GLuint>> vaoAndEbos = bindModel(model);
// dbgModel(model); return; // dbgModel(model); return;
// Model matrix : an identity matrix (model will be at the origin) // Model matrix : an identity matrix (model will be at the origin)
@@ -317,10 +328,12 @@ void displayLoop(Window &window, const std::string &filename) {
glUniform3fv(sun_position_u, 1, &sun_position[0]); glUniform3fv(sun_position_u, 1, &sun_position[0]);
glUniform3fv(sun_color_u, 1, &sun_color[0]); glUniform3fv(sun_color_u, 1, &sun_color[0]);
drawModel(vao, model); drawModel(vaoAndEbos, model);
glfwSwapBuffers(window.window); glfwSwapBuffers(window.window);
glfwPollEvents(); glfwPollEvents();
} }
glDeleteVertexArrays(1, &vaoAndEbos.first);
} }
static void error_callback(int error, const char *description) { static void error_callback(int error, const char *description) {

View File

@@ -0,0 +1,2 @@
all:
$(CXX) -o create_triangle_gltf -I../../ create_triangle_gltf.cpp

View File

@@ -0,0 +1,121 @@
// An example of how to generate a gltf file from scratch. This example
// was translated from the pygltlib documentation in the pypi project page,
// which in turn is based on the Khronos Sample Models at:
//
// https://github.com/KhronosGroup/glTF-Sample-Models
//
// This example is released under the MIT license.
//
// 2021-02-25 Thu
// Dov Grobgeld <dov.grobgeld@gmail.com>
// Define these only in *one* .cc file.
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
// #define TINYGLTF_NOEXCEPTION // optional. disable exception handling.
#include "tiny_gltf.h"
int main(int argc, char **argv)
{
// Create a model with a single mesh and save it as a gltf file
tinygltf::Model m;
tinygltf::Scene scene;
tinygltf::Mesh mesh;
tinygltf::Primitive primitive;
tinygltf::Node node;
tinygltf::Buffer buffer;
tinygltf::BufferView bufferView1;
tinygltf::BufferView bufferView2;
tinygltf::Accessor accessor1;
tinygltf::Accessor accessor2;
tinygltf::Asset asset;
// This is the raw data buffer.
buffer.data = {
// 6 bytes of indices and two bytes of padding
0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,
// 36 bytes of floating point numbers
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,
0x00,0x00,0x00,0x00};
// "The indices of the vertices (ELEMENT_ARRAY_BUFFER) take up 6 bytes in the
// start of the buffer.
bufferView1.buffer = 0;
bufferView1.byteOffset=0;
bufferView1.byteLength=6;
bufferView1.target = TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
// The vertices take up 36 bytes (3 vertices * 3 floating points * 4 bytes)
// at position 8 in the buffer and are of type ARRAY_BUFFER
bufferView2.buffer = 0;
bufferView2.byteOffset=8;
bufferView2.byteLength=36;
bufferView2.target = TINYGLTF_TARGET_ARRAY_BUFFER;
// Describe the layout of bufferView1, the indices of the vertices
accessor1.bufferView = 0;
accessor1.byteOffset = 0;
accessor1.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT;
accessor1.count = 3;
accessor1.type = TINYGLTF_TYPE_SCALAR;
accessor1.maxValues.push_back(2);
accessor1.minValues.push_back(0);
// Describe the layout of bufferView2, the vertices themself
accessor2.bufferView = 1;
accessor2.byteOffset = 0;
accessor2.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
accessor2.count = 3;
accessor2.type = TINYGLTF_TYPE_VEC3;
accessor2.maxValues = {1.0, 1.0, 0.0};
accessor2.minValues = {0.0, 0.0, 0.0};
// Build the mesh primitive and add it to the mesh
primitive.indices = 0; // The index of the accessor for the vertex indices
primitive.attributes["POSITION"] = 1; // The index of the accessor for positions
primitive.material = 0;
primitive.mode = TINYGLTF_MODE_TRIANGLES;
mesh.primitives.push_back(primitive);
// Other tie ups
node.mesh = 0;
scene.nodes.push_back(0); // Default scene
// Define the asset. The version is required
asset.version = "2.0";
asset.generator = "tinygltf";
// Now all that remains is to tie back all the loose objects into the
// our single model.
m.scenes.push_back(scene);
m.meshes.push_back(mesh);
m.nodes.push_back(node);
m.buffers.push_back(buffer);
m.bufferViews.push_back(bufferView1);
m.bufferViews.push_back(bufferView2);
m.accessors.push_back(accessor1);
m.accessors.push_back(accessor2);
m.asset = asset;
// Create a simple material
tinygltf::Material mat;
mat.pbrMetallicRoughness.baseColorFactor = {1.0f, 0.9f, 0.9f, 1.0f};
mat.doubleSided = true;
m.materials.push_back(mat);
// Save it to a file
tinygltf::TinyGLTF gltf;
gltf.WriteGltfSceneToFile(&m, "triangle.gltf",
true, // embedImages
true, // embedBuffers
true, // pretty print
false); // write binary
exit(0);
}

View File

@@ -610,7 +610,7 @@ void Viewer::buildSamplerDescs() {
samplerDesc.AddressU = toTextureAddressMode(glTFSampler.wrapS); samplerDesc.AddressU = toTextureAddressMode(glTFSampler.wrapS);
samplerDesc.AddressV = toTextureAddressMode(glTFSampler.wrapT); samplerDesc.AddressV = toTextureAddressMode(glTFSampler.wrapT);
samplerDesc.AddressW = toTextureAddressMode(glTFSampler.wrapR); samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
samplerDesc.MaxLOD = 256; samplerDesc.MaxLOD = 256;
samplerDescs_.push_back(samplerDesc); samplerDescs_.push_back(samplerDesc);

View File

@@ -51,7 +51,7 @@ add_executable(glview
target_link_libraries ( glview target_link_libraries ( glview
${DRACO_LIBRARY} ${DRACO_LIBRARY}
${GLFW3_UNIX_LINK_LIBRARIES} ${GLFW3_UNIX_LINK_LIBRARIES}
${GLEW_LIBRARY} ${GLEW_LIBRARIES}
${GLFW3_glfw_LIBRARY} ${GLFW3_glfw_LIBRARY}
${OPENGL_gl_LIBRARY} ${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY} ${OPENGL_glu_LIBRARY}

View File

@@ -771,6 +771,30 @@ static void DrawCurves(tinygltf::Scene &scene, const tinygltf::Mesh &mesh) {
} }
#endif #endif
static void QuatToAngleAxis(const std::vector<double> quaternion,
double &outAngleDegrees,
double *axis) {
double qx = quaternion[0];
double qy = quaternion[1];
double qz = quaternion[2];
double qw = quaternion[3];
double angleRadians = 2 * acos(qw);
if (angleRadians == 0.0) {
outAngleDegrees = 0.0;
axis[0] = 0.0;
axis[1] = 0.0;
axis[2] = 1.0;
return;
}
double denom = sqrt(1-qw*qw);
outAngleDegrees = angleRadians * 180.0 / M_PI;
axis[0] = qx / denom;
axis[1] = qy / denom;
axis[2] = qz / denom;
}
// Hierarchically draw nodes // Hierarchically draw nodes
static void DrawNode(tinygltf::Model &model, const tinygltf::Node &node) { static void DrawNode(tinygltf::Model &model, const tinygltf::Node &node) {
// Apply xform // Apply xform
@@ -781,19 +805,23 @@ static void DrawNode(tinygltf::Model &model, const tinygltf::Node &node) {
glMultMatrixd(node.matrix.data()); glMultMatrixd(node.matrix.data());
} else { } else {
// Assume Trans x Rotate x Scale order // Assume Trans x Rotate x Scale order
if (node.scale.size() == 3) {
glScaled(node.scale[0], node.scale[1], node.scale[2]);
}
if (node.rotation.size() == 4) {
glRotated(node.rotation[0], node.rotation[1], node.rotation[2],
node.rotation[3]);
}
if (node.translation.size() == 3) { if (node.translation.size() == 3) {
glTranslated(node.translation[0], node.translation[1], glTranslated(node.translation[0], node.translation[1],
node.translation[2]); node.translation[2]);
} }
if (node.rotation.size() == 4) {
double angleDegrees;
double axis[3];
QuatToAngleAxis(node.rotation, angleDegrees, axis);
glRotated(angleDegrees, axis[0], axis[1], axis[2]);
}
if (node.scale.size() == 3) {
glScaled(node.scale[0], node.scale[1], node.scale[2]);
}
} }
// std::cout << "node " << node.name << ", Meshes " << node.meshes.size() << // std::cout << "node " << node.name << ", Meshes " << node.meshes.size() <<

18613
json.hpp

File diff suppressed because it is too large Load Diff

View File

@@ -524,7 +524,7 @@ static void Dump(const tinygltf::Model &model) {
<< std::endl; << std::endl;
std::cout << Indent(1) << "channels : [ " << std::endl; std::cout << Indent(1) << "channels : [ " << std::endl;
for (size_t j = 0; i < animation.channels.size(); i++) { for (size_t j = 0; j < animation.channels.size(); j++) {
std::cout << Indent(2) std::cout << Indent(2)
<< "sampler : " << animation.channels[j].sampler << "sampler : " << animation.channels[j].sampler
<< std::endl; << std::endl;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* stb_image_write - v1.11 - public domain - http://nothings.org/stb/stb_image_write.h /* stb_image_write - v1.16 - public domain - http://nothings.org/stb
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
no warranty implied; use at your own risk no warranty implied; use at your own risk
@@ -10,11 +10,6 @@
Will probably not work correctly with strict-aliasing optimizations. Will probably not work correctly with strict-aliasing optimizations.
If using a modern Microsoft Compiler, non-safe versions of CRT calls may cause
compilation warnings or even errors. To avoid this, also before #including,
#define STBI_MSC_SECURE_CRT
ABOUT: ABOUT:
This header file is a library for writing images to C stdio or a callback. This header file is a library for writing images to C stdio or a callback.
@@ -145,6 +140,7 @@ CREDITS:
Ivan Tikhonov Ivan Tikhonov
github:ignotion github:ignotion
Adam Schackart Adam Schackart
Andrew Kensler
LICENSE LICENSE
@@ -171,9 +167,9 @@ LICENSE
#endif #endif
#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations #ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations
extern int stbi_write_tga_with_rle; STBIWDEF int stbi_write_tga_with_rle;
extern int stbi_write_png_compression_level; STBIWDEF int stbi_write_png_compression_level;
extern int stbi_write_force_png_filter; STBIWDEF int stbi_write_force_png_filter;
#endif #endif
#ifndef STBI_WRITE_NO_STDIO #ifndef STBI_WRITE_NO_STDIO
@@ -183,7 +179,7 @@ STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
#ifdef STBI_WINDOWS_UTF8 #ifdef STBIW_WINDOWS_UTF8
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
#endif #endif
#endif #endif
@@ -252,17 +248,17 @@ STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
#ifdef STB_IMAGE_WRITE_STATIC #ifdef STB_IMAGE_WRITE_STATIC
static int stbi__flip_vertically_on_write=0;
static int stbi_write_png_compression_level = 8; static int stbi_write_png_compression_level = 8;
static int stbi_write_tga_with_rle = 1; static int stbi_write_tga_with_rle = 1;
static int stbi_write_force_png_filter = -1; static int stbi_write_force_png_filter = -1;
#else #else
int stbi_write_png_compression_level = 8; int stbi_write_png_compression_level = 8;
int stbi__flip_vertically_on_write=0;
int stbi_write_tga_with_rle = 1; int stbi_write_tga_with_rle = 1;
int stbi_write_force_png_filter = -1; int stbi_write_force_png_filter = -1;
#endif #endif
static int stbi__flip_vertically_on_write = 0;
STBIWDEF void stbi_flip_vertically_on_write(int flag) STBIWDEF void stbi_flip_vertically_on_write(int flag)
{ {
stbi__flip_vertically_on_write = flag; stbi__flip_vertically_on_write = flag;
@@ -272,6 +268,8 @@ typedef struct
{ {
stbi_write_func *func; stbi_write_func *func;
void *context; void *context;
unsigned char buffer[64];
int buf_used;
} stbi__write_context; } stbi__write_context;
// initialize a callback-based context // initialize a callback-based context
@@ -288,7 +286,7 @@ static void stbi__stdio_write(void *context, void *data, int size)
fwrite(data,1,size,(FILE*) context); fwrite(data,1,size,(FILE*) context);
} }
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) #if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
#ifdef __cplusplus #ifdef __cplusplus
#define STBIW_EXTERN extern "C" #define STBIW_EXTERN extern "C"
#else #else
@@ -299,25 +297,25 @@ STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned in
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
{ {
return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, bufferlen, NULL, NULL); return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
} }
#endif #endif
static FILE *stbiw__fopen(char const *filename, char const *mode) static FILE *stbiw__fopen(char const *filename, char const *mode)
{ {
FILE *f; FILE *f;
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) #if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
wchar_t wMode[64]; wchar_t wMode[64];
wchar_t wFilename[1024]; wchar_t wFilename[1024];
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
return 0; return 0;
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
return 0; return 0;
#if _MSC_VER >= 1400 #if defined(_MSC_VER) && _MSC_VER >= 1400
if (0 != _wfopen_s(&f, wFilename, wMode)) if (0 != _wfopen_s(&f, wFilename, wMode))
f = 0; f = 0;
#else #else
f = _wfopen(wFilename, wMode); f = _wfopen(wFilename, wMode);
#endif #endif
@@ -385,16 +383,36 @@ static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
va_end(v); va_end(v);
} }
static void stbiw__write_flush(stbi__write_context *s)
{
if (s->buf_used) {
s->func(s->context, &s->buffer, s->buf_used);
s->buf_used = 0;
}
}
static void stbiw__putc(stbi__write_context *s, unsigned char c) static void stbiw__putc(stbi__write_context *s, unsigned char c)
{ {
s->func(s->context, &c, 1); s->func(s->context, &c, 1);
} }
static void stbiw__write1(stbi__write_context *s, unsigned char a)
{
if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
stbiw__write_flush(s);
s->buffer[s->buf_used++] = a;
}
static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
{ {
unsigned char arr[3]; int n;
arr[0] = a, arr[1] = b, arr[2] = c; if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
s->func(s->context, arr, 3); stbiw__write_flush(s);
n = s->buf_used;
s->buf_used = n+3;
s->buffer[n+0] = a;
s->buffer[n+1] = b;
s->buffer[n+2] = c;
} }
static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
@@ -403,7 +421,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
int k; int k;
if (write_alpha < 0) if (write_alpha < 0)
s->func(s->context, &d[comp - 1], 1); stbiw__write1(s, d[comp - 1]);
switch (comp) { switch (comp) {
case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
@@ -411,7 +429,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
if (expand_mono) if (expand_mono)
stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
else else
s->func(s->context, d, 1); // monochrome TGA stbiw__write1(s, d[0]); // monochrome TGA
break; break;
case 4: case 4:
if (!write_alpha) { if (!write_alpha) {
@@ -427,7 +445,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
break; break;
} }
if (write_alpha > 0) if (write_alpha > 0)
s->func(s->context, &d[comp - 1], 1); stbiw__write1(s, d[comp - 1]);
} }
static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
@@ -441,16 +459,18 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i
if (stbi__flip_vertically_on_write) if (stbi__flip_vertically_on_write)
vdir *= -1; vdir *= -1;
if (vdir < 0) if (vdir < 0) {
j_end = -1, j = y-1; j_end = -1; j = y-1;
else } else {
j_end = y, j = 0; j_end = y; j = 0;
}
for (; j != j_end; j += vdir) { for (; j != j_end; j += vdir) {
for (i=0; i < x; ++i) { for (i=0; i < x; ++i) {
unsigned char *d = (unsigned char *) data + (j*x+i)*comp; unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
} }
stbiw__write_flush(s);
s->func(s->context, &zero, scanline_pad); s->func(s->context, &zero, scanline_pad);
} }
} }
@@ -471,16 +491,27 @@ static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x,
static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
{ {
int pad = (-x*3) & 3; if (comp != 4) {
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, // write RGB bitmap
"11 4 22 4" "4 44 22 444444", int pad = (-x*3) & 3;
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header "11 4 22 4" "4 44 22 444444",
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
} else {
// RGBA bitmaps need a v4 header
// use BI_BITFIELDS mode with 32bpp and alpha mask
// (straight BI_RGB with alpha mask doesn't work in most readers)
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
"11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header
108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header
}
} }
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
{ {
stbi__write_context s; stbi__write_context s = { 0 };
stbi__start_write_callbacks(&s, func, context); stbi__start_write_callbacks(&s, func, context);
return stbi_write_bmp_core(&s, x, y, comp, data); return stbi_write_bmp_core(&s, x, y, comp, data);
} }
@@ -488,7 +519,7 @@ STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x,
#ifndef STBI_WRITE_NO_STDIO #ifndef STBI_WRITE_NO_STDIO
STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
{ {
stbi__write_context s; stbi__write_context s = { 0 };
if (stbi__start_write_file(&s,filename)) { if (stbi__start_write_file(&s,filename)) {
int r = stbi_write_bmp_core(&s, x, y, comp, data); int r = stbi_write_bmp_core(&s, x, y, comp, data);
stbi__end_write_file(&s); stbi__end_write_file(&s);
@@ -561,24 +592,25 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v
if (diff) { if (diff) {
unsigned char header = STBIW_UCHAR(len - 1); unsigned char header = STBIW_UCHAR(len - 1);
s->func(s->context, &header, 1); stbiw__write1(s, header);
for (k = 0; k < len; ++k) { for (k = 0; k < len; ++k) {
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
} }
} else { } else {
unsigned char header = STBIW_UCHAR(len - 129); unsigned char header = STBIW_UCHAR(len - 129);
s->func(s->context, &header, 1); stbiw__write1(s, header);
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
} }
} }
} }
stbiw__write_flush(s);
} }
return 1; return 1;
} }
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
{ {
stbi__write_context s; stbi__write_context s = { 0 };
stbi__start_write_callbacks(&s, func, context); stbi__start_write_callbacks(&s, func, context);
return stbi_write_tga_core(&s, x, y, comp, (void *) data); return stbi_write_tga_core(&s, x, y, comp, (void *) data);
} }
@@ -586,7 +618,7 @@ STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x,
#ifndef STBI_WRITE_NO_STDIO #ifndef STBI_WRITE_NO_STDIO
STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
{ {
stbi__write_context s; stbi__write_context s = { 0 };
if (stbi__start_write_file(&s,filename)) { if (stbi__start_write_file(&s,filename)) {
int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
stbi__end_write_file(&s); stbi__end_write_file(&s);
@@ -602,6 +634,8 @@ STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
#ifndef STBI_WRITE_NO_STDIO
static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
{ {
int exponent; int exponent;
@@ -736,8 +770,8 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
s->func(s->context, header, sizeof(header)-1); s->func(s->context, header, sizeof(header)-1);
#ifdef STBI_MSC_SECURE_CRT #ifdef __STDC_LIB_EXT1__
len = sprintf_s(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
#else #else
len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
#endif #endif
@@ -752,15 +786,14 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
{ {
stbi__write_context s; stbi__write_context s = { 0 };
stbi__start_write_callbacks(&s, func, context); stbi__start_write_callbacks(&s, func, context);
return stbi_write_hdr_core(&s, x, y, comp, (float *) data); return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
} }
#ifndef STBI_WRITE_NO_STDIO
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
{ {
stbi__write_context s; stbi__write_context s = { 0 };
if (stbi__start_write_file(&s,filename)) { if (stbi__start_write_file(&s,filename)) {
int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
stbi__end_write_file(&s); stbi__end_write_file(&s);
@@ -778,7 +811,7 @@ STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const
#ifndef STBIW_ZLIB_COMPRESS #ifndef STBIW_ZLIB_COMPRESS
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
#define stbiw__sbraw(a) ((int *) (a) - 2) #define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
#define stbiw__sbm(a) stbiw__sbraw(a)[0] #define stbiw__sbm(a) stbiw__sbraw(a)[0]
#define stbiw__sbn(a) stbiw__sbraw(a)[1] #define stbiw__sbn(a) stbiw__sbraw(a)[1]
@@ -872,7 +905,7 @@ STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, i
unsigned int bitbuf=0; unsigned int bitbuf=0;
int i,j, bitcount=0; int i,j, bitcount=0;
unsigned char *out = NULL; unsigned char *out = NULL;
unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**));
if (hash_table == NULL) if (hash_table == NULL)
return NULL; return NULL;
if (quality < 5) quality = 5; if (quality < 5) quality = 5;
@@ -895,7 +928,7 @@ STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, i
for (j=0; j < n; ++j) { for (j=0; j < n; ++j) {
if (hlist[j]-data > i-32768) { // if entry lies within window if (hlist[j]-data > i-32768) { // if entry lies within window
int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
if (d >= best) best=d,bestloc=hlist[j]; if (d >= best) { best=d; bestloc=hlist[j]; }
} }
} }
// when hash table entry is too long, delete half the entries // when hash table entry is too long, delete half the entries
@@ -948,14 +981,31 @@ STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, i
(void) stbiw__sbfree(hash_table[i]); (void) stbiw__sbfree(hash_table[i]);
STBIW_FREE(hash_table); STBIW_FREE(hash_table);
// store uncompressed instead if compression was worse
if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1
for (j = 0; j < data_len;) {
int blocklen = data_len - j;
if (blocklen > 32767) blocklen = 32767;
stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression
stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN
stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN
stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
memcpy(out+stbiw__sbn(out), data+j, blocklen);
stbiw__sbn(out) += blocklen;
j += blocklen;
}
}
{ {
// compute adler32 on input // compute adler32 on input
unsigned int s1=1, s2=0; unsigned int s1=1, s2=0;
int blocklen = (int) (data_len % 5552); int blocklen = (int) (data_len % 5552);
j=0; j=0;
while (j < data_len) { while (j < data_len) {
for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
s1 %= 65521, s2 %= 65521; s1 %= 65521; s2 %= 65521;
j += blocklen; j += blocklen;
blocklen = 5552; blocklen = 5552;
} }
@@ -1275,26 +1325,31 @@ static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
bits[0] = val & ((1<<bits[1])-1); bits[0] = val & ((1<<bits[1])-1);
} }
static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) { static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, int du_stride, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] }; const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] }; const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
int dataOff, i, diff, end0pos; int dataOff, i, j, n, diff, end0pos, x, y;
int DU[64]; int DU[64];
// DCT rows // DCT rows
for(dataOff=0; dataOff<64; dataOff+=8) { for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]); stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
} }
// DCT columns // DCT columns
for(dataOff=0; dataOff<8; ++dataOff) { for(dataOff=0; dataOff<8; ++dataOff) {
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]); stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
&CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
} }
// Quantize/descale/zigzag the coefficients // Quantize/descale/zigzag the coefficients
for(i=0; i<64; ++i) { for(y = 0, j=0; y < 8; ++y) {
float v = CDU[i]*fdtbl[i]; for(x = 0; x < 8; ++x,++j) {
// DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f)); float v;
// ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway? i = y*du_stride+x;
DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f); v = CDU[i]*fdtbl[j];
// DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
// ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
}
} }
// Encode DC // Encode DC
@@ -1412,7 +1467,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
int row, col, i, k; int row, col, i, k, subsample;
float fdtbl_Y[64], fdtbl_UV[64]; float fdtbl_Y[64], fdtbl_UV[64];
unsigned char YTable[64], UVTable[64]; unsigned char YTable[64], UVTable[64];
@@ -1421,6 +1476,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
} }
quality = quality ? quality : 90; quality = quality ? quality : 90;
subsample = quality <= 90 ? 1 : 0;
quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
quality = quality < 50 ? 5000 / quality : 200 - quality * 2; quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
@@ -1443,7 +1499,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
s->func(s->context, (void*)head0, sizeof(head0)); s->func(s->context, (void*)head0, sizeof(head0));
s->func(s->context, (void*)YTable, sizeof(YTable)); s->func(s->context, (void*)YTable, sizeof(YTable));
stbiw__putc(s, 1); stbiw__putc(s, 1);
@@ -1466,36 +1522,74 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
// Encode 8x8 macroblocks // Encode 8x8 macroblocks
{ {
static const unsigned short fillBits[] = {0x7F, 7}; static const unsigned short fillBits[] = {0x7F, 7};
const unsigned char *imageData = (const unsigned char *)data;
int DCY=0, DCU=0, DCV=0; int DCY=0, DCU=0, DCV=0;
int bitBuf=0, bitCnt=0; int bitBuf=0, bitCnt=0;
// comp == 2 is grey+alpha (alpha is ignored) // comp == 2 is grey+alpha (alpha is ignored)
int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
const unsigned char *dataR = (const unsigned char *)data;
const unsigned char *dataG = dataR + ofsG;
const unsigned char *dataB = dataR + ofsB;
int x, y, pos; int x, y, pos;
for(y = 0; y < height; y += 8) { if(subsample) {
for(x = 0; x < width; x += 8) { for(y = 0; y < height; y += 16) {
float YDU[64], UDU[64], VDU[64]; for(x = 0; x < width; x += 16) {
for(row = y, pos = 0; row < y+8; ++row) { float Y[256], U[256], V[256];
// row >= height => use last input row for(row = y, pos = 0; row < y+16; ++row) {
int clamped_row = (row < height) ? row : height - 1; // row >= height => use last input row
int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; int clamped_row = (row < height) ? row : height - 1;
for(col = x; col < x+8; ++col, ++pos) { int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
float r, g, b; for(col = x; col < x+16; ++col, ++pos) {
// if col >= width => use pixel from last input column // if col >= width => use pixel from last input column
int p = base_p + ((col < width) ? col : (width-1))*comp; int p = base_p + ((col < width) ? col : (width-1))*comp;
float r = dataR[p], g = dataG[p], b = dataB[p];
Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
}
}
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
r = imageData[p+0]; // subsample U,V
g = imageData[p+ofsG]; {
b = imageData[p+ofsB]; float subU[64], subV[64];
YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128; int yy, xx;
UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b; for(yy = 0, pos = 0; yy < 8; ++yy) {
VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b; for(xx = 0; xx < 8; ++xx, ++pos) {
int j = yy*32+xx*2;
subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
}
}
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
} }
} }
}
} else {
for(y = 0; y < height; y += 8) {
for(x = 0; x < width; x += 8) {
float Y[64], U[64], V[64];
for(row = y, pos = 0; row < y+8; ++row) {
// row >= height => use last input row
int clamped_row = (row < height) ? row : height - 1;
int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
for(col = x; col < x+8; ++col, ++pos) {
// if col >= width => use pixel from last input column
int p = base_p + ((col < width) ? col : (width-1))*comp;
float r = dataR[p], g = dataG[p], b = dataB[p];
Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
}
}
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
}
} }
} }
@@ -1512,7 +1606,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
{ {
stbi__write_context s; stbi__write_context s = { 0 };
stbi__start_write_callbacks(&s, func, context); stbi__start_write_callbacks(&s, func, context);
return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
} }
@@ -1521,7 +1615,7 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x,
#ifndef STBI_WRITE_NO_STDIO #ifndef STBI_WRITE_NO_STDIO
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
{ {
stbi__write_context s; stbi__write_context s = { 0 };
if (stbi__start_write_file(&s,filename)) { if (stbi__start_write_file(&s,filename)) {
int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
stbi__end_write_file(&s); stbi__end_write_file(&s);
@@ -1534,6 +1628,15 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
#endif // STB_IMAGE_WRITE_IMPLEMENTATION #endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history /* Revision history
1.16 (2021-07-11)
make Deflate code emit uncompressed blocks when it would otherwise expand
support writing BMPs with alpha channel
1.15 (2020-07-13) unknown
1.14 (2020-02-02) updated JPEG writer to downsample chroma channels
1.13
1.12
1.11 (2019-08-11)
1.10 (2019-02-07) 1.10 (2019-02-07)
support utf8 filenames in Windows; fix warnings and platform ifdefs support utf8 filenames in Windows; fix warnings and platform ifdefs
1.09 (2018-02-11) 1.09 (2018-02-11)
@@ -1566,7 +1669,7 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
add HDR output add HDR output
fix monochrome BMP fix monochrome BMP
0.95 (2014-08-17) 0.95 (2014-08-17)
add monochrome TGA output add monochrome TGA output
0.94 (2014-05-31) 0.94 (2014-05-31)
rename private functions to avoid conflicts with stb_image.h rename private functions to avoid conflicts with stb_image.h
0.93 (2014-05-27) 0.93 (2014-05-27)

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# Assume python 2.6 or 2.7
import glob import glob
import os import os
import subprocess import subprocess

1
tests/issue-416.gltf Normal file
View File

@@ -0,0 +1 @@
{"images":[{"uri":"%!QAAAQAAA5"}],"asset":{"version":""}}

View File

@@ -16,10 +16,10 @@
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
static JsonDocument JsonConstruct(const char* str) static tinygltf::detail::JsonDocument JsonConstruct(const char* str)
{ {
JsonDocument doc; tinygltf::detail::JsonDocument doc;
JsonParse(doc, str, strlen(str)); tinygltf::detail::JsonParse(doc, str, strlen(str));
return doc; return doc;
} }
@@ -275,9 +275,9 @@ TEST_CASE("parse-integer", "[bounds-checking]") {
err.clear(); err.clear();
{ {
JsonDocument o; tinygltf::detail::JsonDocument o;
double nan = std::numeric_limits<double>::quiet_NaN(); double nan = std::numeric_limits<double>::quiet_NaN();
tinygltf::JsonAddMember(o, "int", json(nan)); tinygltf::detail::JsonAddMember(o, "int", tinygltf::detail::json(nan));
CHECK_FALSE(tinygltf::ParseIntegerProperty( CHECK_FALSE(tinygltf::ParseIntegerProperty(
&result, &err, o, &result, &err, o,
"int", true)); "int", true));
@@ -321,9 +321,9 @@ TEST_CASE("parse-unsigned", "[bounds-checking]") {
err.clear(); err.clear();
{ {
JsonDocument o; tinygltf::detail::JsonDocument o;
double nan = std::numeric_limits<double>::quiet_NaN(); double nan = std::numeric_limits<double>::quiet_NaN();
tinygltf::JsonAddMember(o, "int", json(nan)); tinygltf::detail::JsonAddMember(o, "int", tinygltf::detail::json(nan));
CHECK_FALSE(tinygltf::ParseUnsignedProperty( CHECK_FALSE(tinygltf::ParseUnsignedProperty(
&result, &err, o, &result, &err, o,
"int", true)); "int", true));
@@ -392,27 +392,105 @@ TEST_CASE("pbr-khr-texture-transform", "[material]") {
TEST_CASE("image-uri-spaces", "[issue-236]") { TEST_CASE("image-uri-spaces", "[issue-236]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx; tinygltf::TinyGLTF ctx;
std::string err; std::string err;
std::string warn; std::string warn;
// Test image file with single spaces. // Test image file with single spaces.
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/CubeImageUriSpaces/CubeImageUriSpaces.gltf"); {
if (!err.empty()) { tinygltf::Model model;
std::cerr << err << std::endl; bool ret = ctx.LoadASCIIFromFile(
} &model, &err, &warn,
"../models/CubeImageUriSpaces/CubeImageUriSpaces.gltf");
if (!warn.empty()) {
std::cerr << warn << std::endl;
}
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret); REQUIRE(true == ret);
REQUIRE(warn.empty());
REQUIRE(err.empty());
REQUIRE(model.images.size() == 1);
REQUIRE(model.images[0].uri.find(' ') != std::string::npos);
}
// Test image file with a beginning space, trailing space, and greater than // Test image file with a beginning space, trailing space, and greater than
// one consecutive spaces. // one consecutive spaces.
ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/CubeImageUriSpaces/CubeImageUriMultipleSpaces.gltf"); tinygltf::Model model;
bool ret = ctx.LoadASCIIFromFile(
&model, &err, &warn,
"../models/CubeImageUriSpaces/CubeImageUriMultipleSpaces.gltf");
if (!warn.empty()) {
std::cerr << warn << std::endl;
}
if (!err.empty()) { if (!err.empty()) {
std::cerr << err << std::endl; std::cerr << err << std::endl;
} }
REQUIRE(true == ret); REQUIRE(true == ret);
REQUIRE(warn.empty());
REQUIRE(err.empty());
REQUIRE(model.images.size() == 1);
REQUIRE(model.images[0].uri.size() > 1);
REQUIRE(model.images[0].uri[0] == ' ');
// Test the URI encoding API by saving and re-load the file, without embedding
// the image.
// TODO(syoyo): create temp directory.
{
// Encoder that only replaces spaces with "%20".
auto uriencode = [](const std::string &in_uri,
const std::string &object_type, std::string *out_uri,
void *user_data) -> bool {
(void)user_data;
bool imageOrBuffer = object_type == "image" || object_type == "buffer";
REQUIRE(true == imageOrBuffer);
*out_uri = {};
for (char c : in_uri) {
if (c == ' ')
*out_uri += "%20";
else
*out_uri += c;
}
return true;
};
// Remove the buffer URI, so a new one is generated based on the gltf
// filename and then encoded with the above callback.
model.buffers[0].uri.clear();
tinygltf::URICallbacks uri_cb{uriencode, tinygltf::URIDecode, nullptr};
ctx.SetURICallbacks(uri_cb);
ret = ctx.WriteGltfSceneToFile(&model, " issue-236.gltf", false, false);
REQUIRE(true == ret);
// read back serialized glTF
tinygltf::Model saved;
bool ret = ctx.LoadASCIIFromFile(&saved, &err, &warn, " issue-236.gltf");
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(err.empty());
REQUIRE(!warn.empty()); // relative image path won't exist in tests/
REQUIRE(saved.images.size() == model.images.size());
// The image uri in CubeImageUriMultipleSpaces.gltf is not encoded and
// should be different after encoding spaces with %20.
REQUIRE(model.images[0].uri != saved.images[0].uri);
// Verify the image path remains the same after uri decoding
std::string image_uri, image_uri_saved;
(void)tinygltf::URIDecode(model.images[0].uri, &image_uri, nullptr);
(void)tinygltf::URIDecode(saved.images[0].uri, &image_uri_saved, nullptr);
REQUIRE(image_uri == image_uri_saved);
// Verify the buffer's generated and encoded URI
REQUIRE(saved.buffers.size() == model.buffers.size());
REQUIRE(saved.buffers[0].uri == "%20issue-236.bin");
}
} }
TEST_CASE("serialize-empty-material", "[issue-294]") { TEST_CASE("serialize-empty-material", "[issue-294]") {
@@ -426,17 +504,48 @@ TEST_CASE("serialize-empty-material", "[issue-294]") {
std::stringstream os; std::stringstream os;
tinygltf::TinyGLTF ctx; tinygltf::TinyGLTF ctx;
ctx.WriteGltfSceneToStream(&m, os, false, false); bool ret = ctx.WriteGltfSceneToStream(&m, os, false, false);
REQUIRE(true == ret);
// use nlohmann json // use nlohmann json
nlohmann::json j = nlohmann::json::parse(os.str()); nlohmann::json j = nlohmann::json::parse(os.str());
REQUIRE(1 == j["materials"].size()); REQUIRE(1 == j["materials"].size());
REQUIRE(j["asset"].is_null());
REQUIRE(j["materials"][0].is_object()); REQUIRE(j["materials"][0].is_object());
} }
TEST_CASE("empty-skeleton-id", "[issue-321]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/regression/unassigned-skeleton.gltf");
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(model.skins.size() == 1);
REQUIRE(model.skins[0].skeleton == -1); // unassigned
std::stringstream os;
ret = ctx.WriteGltfSceneToStream(&model, os, false, false);
REQUIRE(true == ret);
// use nlohmann json
nlohmann::json j = nlohmann::json::parse(os.str());
// Ensure `skeleton` property is not written to .gltf(was serialized as -1)
REQUIRE(1 == j["skins"].size());
REQUIRE(j["skins"][0].is_object());
REQUIRE(j["skins"][0].count("skeleton") == 0);
}
#ifndef TINYGLTF_NO_FS #ifndef TINYGLTF_NO_FS
TEST_CASE("expandpath-utf-8", "[pr-226]") { TEST_CASE("expandpath-utf-8", "[pr-226]") {
@@ -453,3 +562,198 @@ TEST_CASE("expandpath-utf-8", "[pr-226]") {
} }
#endif #endif
TEST_CASE("empty-bin-buffer", "[issue-382]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
tinygltf::Model model_empty;
std::stringstream stream;
bool ret = ctx.WriteGltfSceneToStream(&model_empty, stream, false, true);
REQUIRE(ret == true);
std::string str = stream.str();
const unsigned char* bytes = (unsigned char*)str.data();
ret = ctx.LoadBinaryFromMemory(&model, &err, &warn, bytes, str.size());
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
err.clear();
warn.clear();
tinygltf::Model model_empty_buffer;
model_empty_buffer.buffers.push_back(tinygltf::Buffer());
stream = std::stringstream();
ret = ctx.WriteGltfSceneToStream(&model_empty_buffer, stream, false, true);
REQUIRE(ret == true);
str = stream.str();
bytes = (unsigned char*)str.data();
ret = ctx.LoadBinaryFromMemory(&model, &err, &warn, bytes, str.size());
if (err.empty()) {
std::cerr << "there should have been an error reported" << std::endl;
}
REQUIRE(false == ret);
err.clear();
warn.clear();
tinygltf::Model model_single_byte_buffer;
tinygltf::Buffer buffer;
buffer.data.push_back(0);
model_single_byte_buffer.buffers.push_back(buffer);
stream = std::stringstream();
ret = ctx.WriteGltfSceneToStream(&model_single_byte_buffer, stream, false, true);
REQUIRE(ret == true);
str = stream.str();
{
std::ofstream ofs("tmp.glb");
ofs.write(str.data(), str.size());
}
bytes = (unsigned char*)str.data();
ret = ctx.LoadBinaryFromMemory(&model_single_byte_buffer, &err, &warn, bytes, str.size());
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
}
TEST_CASE("serialize-const-image", "[issue-394]") {
tinygltf::Model m;
tinygltf::Image i;
i.width = 1;
i.height = 1;
i.component = 4;
i.bits = 8;
i.pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
i.image = {255, 255, 255, 255};
i.uri = "image.png";
m.images.push_back(i);
std::stringstream os;
tinygltf::TinyGLTF ctx;
bool ret = ctx.WriteGltfSceneToStream(const_cast<const tinygltf::Model *>(&m), os, false,
false);
REQUIRE(true == ret);
REQUIRE(m.images[0].uri == i.uri);
// use nlohmann json
nlohmann::json j = nlohmann::json::parse(os.str());
REQUIRE(1 == j["images"].size());
REQUIRE(j["images"][0].is_object());
REQUIRE(j["images"][0]["uri"].get<std::string>() != i.uri);
REQUIRE(j["images"][0]["uri"].get<std::string>().rfind("data:", 0) == 0);
}
TEST_CASE("serialize-image-callback", "[issue-394]") {
tinygltf::Model m;
tinygltf::Image i;
i.width = 1;
i.height = 1;
i.bits = 32;
i.image = {255, 255, 255, 255};
i.uri = "foo";
m.images.push_back(i);
std::stringstream os;
auto writer = [](const std::string *basepath, const std::string *filename,
const tinygltf::Image *image, bool embedImages,
const tinygltf::URICallbacks *uri_cb, std::string *out_uri,
void *user_pointer) -> bool {
(void)basepath;
(void)image;
(void)uri_cb;
REQUIRE(*filename == "foo");
REQUIRE(embedImages == true);
REQUIRE(user_pointer == (void *)0xba5e1e55);
*out_uri = "bar";
return true;
};
tinygltf::TinyGLTF ctx;
ctx.SetImageWriter(writer, (void *)0xba5e1e55);
bool result = ctx.WriteGltfSceneToStream(const_cast<const tinygltf::Model *>(&m), os, false,
false);
// use nlohmann json
nlohmann::json j = nlohmann::json::parse(os.str());
REQUIRE(true == result);
REQUIRE(1 == j["images"].size());
REQUIRE(j["images"][0].is_object());
REQUIRE(j["images"][0]["uri"].get<std::string>() == "bar");
}
TEST_CASE("serialize-image-failure", "[issue-394]") {
tinygltf::Model m;
tinygltf::Image i;
// Set some data so the ImageWriter callback will be called
i.image = {255, 255, 255, 255};
m.images.push_back(i);
std::stringstream os;
auto writer = [](const std::string *basepath, const std::string *filename,
const tinygltf::Image *image, bool embedImages,
const tinygltf::URICallbacks *uri_cb, std::string *out_uri,
void *user_pointer) -> bool {
(void)basepath;
(void)filename;
(void)image;
(void)embedImages;
(void)uri_cb;
(void)out_uri;
(void)user_pointer;
return false;
};
tinygltf::TinyGLTF ctx;
ctx.SetImageWriter(writer, (void *)0xba5e1e55);
bool result = ctx.WriteGltfSceneToStream(const_cast<const tinygltf::Model *>(&m), os, false,
false);
REQUIRE(false == result);
REQUIRE(os.str().size() == 0);
}
TEST_CASE("filesize-check", "[issue-416]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
ctx.SetMaxExternalFileSize(10); // 10 bytes. will fail to load texture image.
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/Cube/Cube.gltf");
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(false == ret);
}
TEST_CASE("load-issue-416-model", "[issue-416]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "issue-416.gltf");
if (!warn.empty()) {
std::cout << "WARN:" << warn << std::endl;
}
if (!err.empty()) {
std::cerr << "ERR:" << err << std::endl;
}
// external file load fails, but reading glTF itself is ok.
REQUIRE(true == ret);
}

4
tiny_gltf.cc Normal file
View File

@@ -0,0 +1,4 @@
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "tiny_gltf.h"

File diff suppressed because it is too large Load Diff

11
wasm/Makefile Normal file
View File

@@ -0,0 +1,11 @@
WASI_VERSION=16
WASI_VERSION_FULL=${WASI_VERSION}.0
WASI_SDK_PATH=$(HOME)/local/wasi-sdk-${WASI_VERSION_FULL}
CC=${WASI_SDK_PATH}/bin/clang
CXX=${WASI_SDK_PATH}/bin/clang++
CXXFLAGS=-fno-rtti -fno-exceptions -g -Os
all:
$(CXX) ../loader_example.cc $(CXXFLAGS) -I../

31
wasm/README.md Normal file
View File

@@ -0,0 +1,31 @@
Experimental WASI/WASM build
## Build
Download wasi-sdk https://github.com/WebAssembly/wasi-sdk
Compile tinygltf without C++ exceptions and threads. See `Makefile` for details
(NOTE: TinyGLTF itself does not use RTTI and threading feature(C++ threads, posix, win32 thread))
## Build examples and Run
Build `loader_example.cc`
```
$ /path/to/wasi-sdk-16.0/bin/clang++ ../loader_example.cc -fno-rtti -fno-exceptions -g -Os -I../ -o loader_example.wasi
```
Tested with wasmtime. https://github.com/bytecodealliance/wasmtime
Set a folder containing .gltf file to `--dir`
```
$ wasmtime --dir=../models loader_example.wasi ../models/Cube/Cube.gltf
```
## Emscripen
T.B.W. ...
EoL.