Compare commits

..

47 Commits

Author SHA1 Message Date
Syoyo Fujita
f68d5e1f2a Merge pull request #182 from ux3d/textureinfo
[TextureInfo] fix default value checks for serialization
2019-07-26 01:29:23 +09:00
Benjamin Schmithüsen
1c84fc22a5 fix default value checks for serialization 2019-07-25 16:07:27 +02:00
Syoyo Fujita
150f243b1b Change the behavior of NUMBER value in Value class. NUMBER now reprents the value is either int or real(floating point). 2019-07-25 19:22:44 +09:00
Syoyo Fujita
0ee273fdfa Update README. Add note on tinygltf::Value for extensions. 2019-07-24 19:55:04 +09:00
Syoyo Fujita
046400b17f Now material is parsed as a struct with explicit parameter definitions.
Implement Material struct serialization.
2019-07-24 19:26:48 +09:00
Syoyo Fujita
89fd93f815 Introduce TextureInfo class(W.I.P.) 2019-07-23 22:37:06 +09:00
Syoyo Fujita
e940337796 Merge pull request #180 from ux3d/master
Explicitly use the correct constructor for empty object
2019-07-23 18:55:34 +09:00
Syoyo Fujita
1b5f476d95 Merge pull request #178 from rapidimages/feature/write-to-streams
Serialize to stream
2019-07-17 18:53:35 +09:00
Johan Bowald
52936a00e0 clang format 2019-07-17 09:06:45 +02:00
Benjamin Schmithüsen
f3ef880029 call json constructor explicitly 2019-07-16 17:07:45 +02:00
Johan Bowald
1af7c1d784 can write to streams 2019-07-16 15:56:18 +02:00
Benjamin Schmithüsen
c0b79afecc Merge pull request #2 from syoyo/master
update from original repository
2019-07-15 15:13:50 +02:00
Syoyo Fujita
c49461b7c2 Merge pull request #176 from ux3d/feature/update-lights
Feature: update lights
2019-07-10 21:20:12 +09:00
Benjamin Schmithüsen
051f4be2f1 serialize lights 2019-07-09 17:59:20 +02:00
Benjamin Schmithüsen
4557b6aa22 fix spot light parsingg 2019-07-09 16:55:55 +02:00
Benjamin Schmithüsen
b2d7d88dbc parse additional light properties and fix defaults 2019-07-09 16:32:42 +02:00
Benjamin Schmithüsen
b7ca7c9381 update lights to follow the KHR_lights_punctual extension 2019-07-08 18:04:24 +02:00
Benjamin Schmithüsen
0ffedcbe79 Merge pull request #1 from syoyo/master
update fork
2019-07-08 17:40:20 +02:00
Syoyo Fujita
80faac5238 Merge pull request #174 from Ybalrid/pr_material_param_tex_info
Add Parameter::TextureStrength(). Precise default values.
2019-07-05 14:11:15 +09:00
Arthur Brianville (Ybalrid)
2a9d9deb67 Applied clang-format 2019-07-05 00:30:47 +02:00
Arthur Brainville
8a98d98cd9 Add Paramter::TextureStrength(). Precise default values.
The default values on these methods as been set to what is described [here](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0?ts=4#normaltextureinfo) and [here](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0?ts=4#occlusiontextureinfo).

This is to keep consistent with the API behavior from #144
2019-07-05 00:30:20 +02:00
Syoyo Fujita
689edcbef6 Merge pull request #173 from christophe-f8/master
Adding texture scale reading + asset copyright and texture names to the export
2019-07-04 15:39:22 +09:00
Christophe
820ede87db Adding texture scale reading (for normal maps) + asset copyright and texture names to the export 2019-07-04 15:21:21 +09:00
Syoyo Fujita
d6b0d0a61f Explicitly define copy constructor and copy assignment operator for Model an Node. 2019-06-29 17:31:13 +09:00
Syoyo Fujita
5f180aaf74 Merge pull request #171 from Ybalrid/fix_double_parse_material_name
Material names are stored once in material.name, then duplicated in "additionalValues"
2019-06-24 14:06:55 +09:00
Arthur Brainville (Ybalrid)
dab0daaedf Material names are stored once in material.name, then duplicated in "additionalValues"
This patch prevent this duplication
2019-06-23 21:50:10 +02:00
Syoyo Fujita
0ccc8dc262 Merge pull request #170 from Ybalrid/msvc_warn_fix
Fix C4267 warning (size_t -> int) convertion
2019-06-15 15:58:03 +09:00
Arthur Brainville (Ybalrid)
811e1d3899 Fix C4267 warning (size_t -> int) convertion 2019-06-15 07:32:38 +02:00
Syoyo Fujita
f65e06c5ca Merge pull request #169 from Ybalrid/remove_mesh_targets
Remove Mesh::targets, as targets only exists inside `Primitive`
2019-05-26 16:23:46 +09:00
Arthur Brianville (Ybalrid)
f29ae1a653 Remove Mesh::targets, as targets only exists inside Primitive 2019-05-25 22:30:55 +02:00
Syoyo Fujita
3bf16e4be5 Merge branch 'master' of github.com:syoyo/tinygltf 2019-05-16 16:55:09 +09:00
Syoyo Fujita
fbc4295770 Remove CATMULLROMSPLINE, which was removed in the final glTF 2.0 spec. 2019-05-16 16:54:28 +09:00
Syoyo Fujita
edf8d5cae1 Merge pull request #164 from DiligentGraphics/master
Updated readme: added link to Diligent Engine
2019-05-09 12:47:24 +09:00
DiligentGraphics
b7f2473225 Updated readme: added link to Diligent Engine 2019-05-08 18:33:26 -07:00
Syoyo Fujita
ed7bf66255 Merge pull request #162 from ux3d/master
add REQUIRE_VERSION to gltf validation and use it as default instead of REQUIRE_ALL
2019-05-03 15:08:36 +09:00
Syoyo Fujita
caa36dd050 Merge pull request #163 from jwmcglynn/fix-test-gltfs-standalone
Add "asset" section to BoundsChecking test models
2019-05-03 15:06:38 +09:00
Jeff McGlynn
389d5016ad Add "asset" section to BoundsChecking test models
These test assets were trimmed down and erroneously didn't have an
"asset" section or version number, which is required by the glTF spec.

This fixes test failures with pull request #162.
2019-05-02 23:05:13 -07:00
Benjamin Schmithüsen
d02ad0dede add REQUIRE_VERSION to gltf validation and use it as default instead of REQUIRE_ALL 2019-05-02 14:44:20 +02:00
Syoyo Fujita
8f67121deb Merge pull request #161 from rainliang000/patch-1
if image.uri empty, should use image.bufferView
2019-04-29 17:48:47 +09:00
rainliang000
62be8d04cf if image.uri empty, should use bufferview
if uri empty, shoud use mimeType and bufferview
2019-04-29 09:54:27 +08:00
Syoyo Fujita
d11a4c4d71 Merge pull request #160 from jwmcglynn/parse-integer
Parse integers directly instead of casting doubles
2019-04-27 14:57:54 +09:00
Jeff McGlynn
19b806e052 Parse integers directly instead of casting doubles
When parsing numeric values as doubles, its possible for users to
specify values that cannot be converted to integers, such as Inf, NaN,
and extremes such as 1e100.  If this value is received, and then cast to
an int, it is undefined behavior, which trips ubsan when running
tinygltf under a fuzzer.

Instead of parsing integral values as doubles, use nlohmann/json's
built-in support to parse integer and unsigned values directly, with
.is_number_integer() and .is_number_unsigned().

Add ParseIntegerProperty, ParseUnsignedProperty, and
ParseIntegerArrayProperty helpers that allow parsing directly to
int/uint values and update code to use them when appropriate.
2019-04-26 17:20:50 -07:00
Syoyo Fujita
e0ab69cb31 Merge pull request #158 from jwmcglynn/bounds-checking
Add checks for boundary conditions for malformed glTF files
2019-04-26 12:56:21 +09:00
Jeff McGlynn
8915252407 Add checks for boundary conditions for malformed glTF files
When loading untrusted glTF files, ideally an error should be returned
if the file is malformed instead of an exception/crash.  Add additional
validation for crashes found when running tinygltf under a fuzzer, and
add test cases to confirm:

1. Validate that the primitive indices value is within the
   model->accessors bounds before dereferencing.
2. Validate that the accessors bufferView index if valid.
3. Validate that the buffer's index is valid when parsing images.
4. For glb files, validate that the overall length is within the
   provided input buffer.
2019-04-25 16:51:09 -07:00
Jeff McGlynn
9446f65667 Set up tests to run in travis-ci and ignore test outputs in .gitignore 2019-04-25 16:26:26 -07:00
Syoyo Fujita
fb9f709166 Merge pull request #157 from Selmar/patch-1
correct Value::Equals mistake
2019-04-17 03:19:00 +09:00
Selmar
a63cc6373d correct Value::Equals mistake
a missing exclamation mark... ^^
2019-04-16 16:57:43 +02:00
23 changed files with 2487 additions and 21204 deletions

1
.gitignore vendored
View File

@@ -67,4 +67,5 @@ imgui.ini
loader_example
tests/tester
tests/tester_noexcept
tests/issue-97.gltf

View File

@@ -42,6 +42,10 @@ script:
- ${CC} -v
- ${CXX} ${EXTRA_CXXFLAGS} -std=c++11 -Wall -g -o loader_example loader_example.cc
- ./loader_example ./models/Cube/Cube.gltf
- cd examples/raytrace
- cd tests
- make
- ./tester
- ./tester_noexcept
- cd ../examples/raytrace
- ../../premake5 gmake
- make

View File

@@ -1,13 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

View File

@@ -2,11 +2,12 @@
`TinyGLTF` is a header only C++11 glTF 2.0 https://github.com/KhronosGroup/glTF library.
`TinyGLTF` uses single-header version of RapidJson(https://github.com/Tencent/rapidjson) as a JSON parser.
`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.
## Status
- v2.3.0 release(Support built-in schema validation)
- 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.1.0 release(Draco support)
- v2.0.0 release(22 Aug, 2018)!
@@ -34,7 +35,6 @@
* [x] ASCII glTF
* [x] Binary glTF(GLB)
* [x] PBR material description
* [x] Validate inpit glTF JSON with schema
* Buffers
* [x] Parse BASE64 encoded embedded buffer data(DataURI).
* [x] Load `.bin` file.
@@ -55,6 +55,12 @@
* Extensions
* [x] Draco mesh decoding
## Note on extension property
In extension(`ExtensionMap`), JSON number value is parsed as int or float(number) and stored as `tinygltf::Value` object. If you want a floating point value from `tinygltf::Value`, use `GetNumberAsDouble()` method.
`IsNumber()` returns true if the underlying value is an int value or a floating point value.
## Examples
* [glview](examples/glview) : Simple glTF geometry viewer.
@@ -67,13 +73,9 @@
* Physical based rendering with Vulkan using glTF 2.0 models https://github.com/SaschaWillems/Vulkan-glTF-PBR
* GLTF loader plugin for OGRE 2.1. Support for PBR materials via HLMS/PBS https://github.com/Ybalrid/Ogre_glTF
* [TinyGltfImporter](http://doc.magnum.graphics/magnum/classMagnum_1_1Trade_1_1TinyGltfImporter.html) plugin for [Magnum](https://github.com/mosra/magnum), a lightweight and modular C++11/C++14 graphics middleware for games and data visualization.
* [Diligent Engine](https://github.com/DiligentGraphics/DiligentEngine) - A modern cross-platform low-level graphics library and rendering framework
* Your projects here! (Please send PR)
## For developer
Generate single rapidjson file using this node.js script: https://github.com/Tencent/rapidjson/issues/863
Add `cursorstreamwrapper.h` and `error/en.h` inclusion in `rapidjson-all.h` before running merge script.
## TODOs
* [ ] Write C++ code generator which emits C++ code from JSON schema for robust parsing.
@@ -81,7 +83,7 @@ Add `cursorstreamwrapper.h` and `error/en.h` inclusion in `rapidjson-all.h` befo
* [x] Load Draco compressed mesh
* [ ] Save Draco compressed mesh
* [ ] Open3DGC?
* [ ] Support `extensions` and `extras` property
* [x] Support `extensions` and `extras` property
* [ ] HDR image?
* [ ] OpenEXR extension through TinyEXR.
* [ ] 16bit PNG support in Serialization
@@ -101,7 +103,7 @@ TinyGLTF uses the following third party libraries.
## Build and example
Copy `stb_image.h`, `stb_image_write.h`, `rapidjson-amalgamation.h` and `tiny_gltf.h` to your project.
Copy `stb_image.h`, `stb_image_write.h`, `json.hpp` and `tiny_gltf.h` to your project.
### Loading glTF 2.0 model
@@ -110,7 +112,6 @@ Copy `stb_image.h`, `stb_image_write.h`, `rapidjson-amalgamation.h` and `tiny_gl
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
// #define TINYGLTF_ENABLE_SCHEMA_VALIDATOR // optional. enable schema validation API.
// #define TINYGLTF_NOEXCEPTION // optional. disable exception handling.
#include "tiny_gltf.h"
@@ -123,10 +124,6 @@ std::string warn;
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, argv[1]);
//bool ret = loader.LoadBinaryFromFile(&model, &err, &warn, argv[1]); // for binary glTF(.glb)
// Validate with glTF Schema
// #if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
// bool ret = loader.LoadASCIIFromFileWithValidation(&model, &err, &warn, argv[1]);
// #endif
if (!warn.empty()) {
printf("Warn: %s\n", warn.c_str());
@@ -144,7 +141,6 @@ if (!ret) {
## Compile options
* `TINYGLTF_ENABLE_SCHEMA_VALIDATOR` : Enable API with schema validation. glTF Schema JSON(`gltf.schema.resolved.inc`) are embeded into application binary, thus no need to read glTF Schema file at a runtime.
* `TINYGLTF_NOEXCEPTION` : Disable C++ exception in JSON parsing. You can use `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION` and `TINYGLTF_NOEXCEPTION` to fully remove C++ exception codes when compiling TinyGLTF.
* `TINYGLTF_NO_STB_IMAGE` : Do not load images with stb_image. Instead use `TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)` to set a callback for loading images.
* `TINYGLTF_NO_STB_IMAGE_WRITE` : Do not write images with stb_image_write. Instead use `TinyGLTF::SetImageWriter(WriteimageDataFunction WriteImageData, void *user_data)` to set a callback for writing images.

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,6 @@
// TODO(syoyo): Print extensions and extras for each glTF object.
//
#define TINYGLTF_IMPLEMENTATION
#define TINYGLTF_ENABLE_SCHEMA_VALIDATOR
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "tiny_gltf.h"
@@ -176,7 +175,10 @@ static std::string PrintIntArray(const std::vector<int> &arr) {
std::stringstream ss;
ss << "[ ";
for (size_t i = 0; i < arr.size(); i++) {
ss << arr[i] << ((i != arr.size() - 1) ? ", " : "");
ss << arr[i];
if (i != arr.size() - 1) {
ss << ", ";
}
}
ss << " ]";
@@ -191,7 +193,10 @@ static std::string PrintFloatArray(const std::vector<double> &arr) {
std::stringstream ss;
ss << "[ ";
for (size_t i = 0; i < arr.size(); i++) {
ss << arr[i] << ((i != arr.size() - 1) ? ", " : "");
ss << arr[i];
if (i != arr.size() - 1) {
ss << ", ";
}
}
ss << " ]";
@@ -244,35 +249,36 @@ static std::string PrintValue(const std::string &name,
if (tag) {
ss << Indent(indent) << name << " : " << value.Get<std::string>();
} else {
ss << " " << value.Get<std::string>() << " ";
ss << Indent(indent) << value.Get<std::string>() << " ";
}
} else if (value.IsBool()) {
if (tag) {
ss << Indent(indent) << name << " : " << value.Get<bool>();
} else {
ss << " " << value.Get<bool>() << " ";
ss << Indent(indent) << value.Get<bool>() << " ";
}
} else if (value.IsNumber()) {
if (tag) {
ss << Indent(indent) << name << " : " << value.Get<double>();
} else {
ss << " " << value.Get<double>() << " ";
ss << Indent(indent) << value.Get<double>() << " ";
}
} else if (value.IsInt()) {
if (tag) {
ss << Indent(indent) << name << " : " << value.Get<int>();
} else {
ss << " " << value.Get<int>() << " ";
ss << Indent(indent) << value.Get<int>() << " ";
}
} else if (value.IsArray()) {
ss << Indent(indent) << name << " [ ";
// TODO(syoyo): Better pretty printing of array item
ss << Indent(indent) << name << " [ \n";
for (size_t i = 0; i < value.Size(); i++) {
ss << PrintValue("", value.Get(int(i)), indent + 1, /* tag */ false);
if (i != (value.ArrayLen() - 1)) {
ss << ", ";
ss << ", \n";
}
}
ss << Indent(indent) << "] ";
ss << "\n" << Indent(indent) << "] ";
}
// @todo { binary }
@@ -340,6 +346,54 @@ static void DumpExtensions(const tinygltf::ExtensionMap &extension,
}
}
static void DumpTextureInfo(const tinygltf::TextureInfo &texinfo,
const int indent) {
std::cout << Indent(indent) << "index : " << texinfo.index << "\n";
std::cout << Indent(indent) << "texCoord : TEXCOORD_" << texinfo.texCoord
<< "\n";
DumpExtensions(texinfo.extensions, indent + 1);
std::cout << PrintValue("extras", texinfo.extras, indent + 1) << "\n";
}
static void DumpNormalTextureInfo(const tinygltf::NormalTextureInfo &texinfo,
const int indent) {
std::cout << Indent(indent) << "index : " << texinfo.index << "\n";
std::cout << Indent(indent) << "texCoord : TEXCOORD_" << texinfo.texCoord
<< "\n";
std::cout << Indent(indent) << "scale : " << texinfo.scale << "\n";
DumpExtensions(texinfo.extensions, indent + 1);
std::cout << PrintValue("extras", texinfo.extras, indent + 1) << "\n";
}
static void DumpOcclusionTextureInfo(
const tinygltf::OcclusionTextureInfo &texinfo, const int indent) {
std::cout << Indent(indent) << "index : " << texinfo.index << "\n";
std::cout << Indent(indent) << "texCoord : TEXCOORD_" << texinfo.texCoord
<< "\n";
std::cout << Indent(indent) << "strength : " << texinfo.strength << "\n";
DumpExtensions(texinfo.extensions, indent + 1);
std::cout << PrintValue("extras", texinfo.extras, indent + 1) << "\n";
}
static void DumpPbrMetallicRoughness(const tinygltf::PbrMetallicRoughness &pbr,
const int indent) {
std::cout << Indent(indent)
<< "baseColorFactor : " << PrintFloatArray(pbr.baseColorFactor)
<< "\n";
std::cout << Indent(indent) << "baseColorTexture :\n";
DumpTextureInfo(pbr.baseColorTexture, indent + 1);
std::cout << Indent(indent) << "metallicFactor : " << pbr.metallicFactor
<< "\n";
std::cout << Indent(indent) << "roughnessFactor : " << pbr.roughnessFactor
<< "\n";
std::cout << Indent(indent) << "metallicRoughnessTexture :\n";
DumpTextureInfo(pbr.metallicRoughnessTexture, indent + 1);
DumpExtensions(pbr.extensions, indent + 1);
std::cout << PrintValue("extras", pbr.extras, indent + 1) << "\n";
}
static void Dump(const tinygltf::Model &model) {
std::cout << "=== Dump glTF ===" << std::endl;
std::cout << "asset.copyright : " << model.asset.copyright
@@ -510,16 +564,44 @@ static void Dump(const tinygltf::Model &model) {
<< std::endl;
for (size_t i = 0; i < model.materials.size(); i++) {
const tinygltf::Material &material = model.materials[i];
std::cout << Indent(1) << "name : " << material.name << std::endl;
std::cout << Indent(1) << "values(items=" << material.values.size() << ")"
std::cout << Indent(1) << "name : " << material.name
<< std::endl;
std::cout << Indent(1) << "alphaMode : " << material.alphaMode
<< std::endl;
std::cout << Indent(1)
<< "alphaCutoff : " << material.alphaCutoff
<< std::endl;
std::cout << Indent(1) << "doubleSided : "
<< (material.doubleSided ? "true" : "false") << std::endl;
std::cout << Indent(1) << "emissiveFactor : "
<< PrintFloatArray(material.emissiveFactor) << std::endl;
std::cout << Indent(1) << "pbrMetallicRoughness :\n";
DumpPbrMetallicRoughness(material.pbrMetallicRoughness, 2);
std::cout << Indent(1) << "normalTexture :\n";
DumpNormalTextureInfo(material.normalTexture, 2);
std::cout << Indent(1) << "occlusionTexture :\n";
DumpOcclusionTextureInfo(material.occlusionTexture, 2);
std::cout << Indent(1) << "emissiveTexture :\n";
DumpTextureInfo(material.emissiveTexture, 2);
std::cout << Indent(1) << "---- legacy material parameter ----\n";
std::cout << Indent(1) << "values(items=" << material.values.size() << ")"
<< std::endl;
tinygltf::ParameterMap::const_iterator p(material.values.begin());
tinygltf::ParameterMap::const_iterator pEnd(material.values.end());
for (; p != pEnd; p++) {
std::cout << Indent(2) << p->first << ": "
<< PrintParameterValue(p->second) << std::endl;
}
std::cout << Indent(1) << "-------------------------------------\n";
DumpExtensions(material.extensions, 1);
std::cout << PrintValue("extras", material.extras, 2) << std::endl;
}
}
@@ -641,13 +723,8 @@ int main(int argc, char **argv) {
} else {
std::cout << "Reading ASCII glTF" << std::endl;
// assume ascii glTF.
#if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
ret =
gltf_ctx.LoadASCIIFromFileWithValidation(&model, &err, &warn, input_filename.c_str());
#else
ret =
gltf_ctx.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
#endif
}
if (!warn.empty()) {

View File

@@ -0,0 +1,67 @@
{
"scenes": [
{
"nodes": [0]
}
],
"nodes": [
{
"mesh": 0
}
],
"meshes": [
{
"primitives": [
{
"attributes": {
"POSITION": 1
},
"indices": 0
}
]
}
],
"buffers": [
{
"uri": "simpleTriangle.bin",
"byteLength": 44
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 1e300,
"target": 34963
},
{
"buffer": 0,
"byteOffset": 8,
"byteLength": 36,
"target": 34962
}
],
"accessors": [
{
"bufferView": 0,
"byteOffset": 0,
"componentType": 5123,
"count": 3,
"type": "SCALAR",
"max": [2],
"min": [0]
},
{
"bufferView": 1,
"byteOffset": 0,
"componentType": 5126,
"count": 3,
"type": "VEC3",
"max": [1, 1, 0],
"min": [0, 0, 0]
}
],
"asset": {
"version": "2.0"
}
}

View File

@@ -0,0 +1,53 @@
{
"scenes": [],
"nodes": [],
"meshes": [
{
"primitives": [
{
"attributes": {},
"indices": 0
}
]
}
],
"buffers": [
{
"uri": "simpleTriangle.bin",
"byteLength": 44
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 6,
"target": 34963
},
{
"buffer": 1,
"byteOffset": 0,
"byteLength": 6,
"target": 34963
}
],
"images": [
{
"bufferView": 1,
"mimeType": "image/png"
}
],
"accessors": [
{
"bufferView": 0,
"componentType": 5123,
"count": 3,
"type": "SCALAR",
"max": [2],
"min": [0]
}
],
"asset": {
"version": "2.0"
}
}

View File

@@ -0,0 +1,36 @@
{
"scenes": [],
"nodes": [],
"buffers": [],
"meshes": [
{
"primitives": [
{
"attributes": {},
"indices": 0
}
]
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 6,
"target": 34963
}
],
"accessors": [
{
"bufferView": 1,
"componentType": 5123,
"count": 3,
"type": "SCALAR",
"max": [2],
"min": [0]
}
],
"asset": {
"version": "2.0"
}
}

View File

@@ -0,0 +1,36 @@
{
"scenes": [],
"nodes": [],
"buffers": [],
"meshes": [
{
"primitives": [
{
"attributes": {},
"indices": 1
}
]
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 6,
"target": 34963
}
],
"accessors": [
{
"bufferView": 1,
"componentType": 5123,
"count": 3,
"type": "SCALAR",
"max": [2],
"min": [0]
}
],
"asset": {
"version": "2.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 B

View File

@@ -0,0 +1,224 @@
{
"accessors": [
{
"bufferView": 0,
"byteOffset": 0,
"componentType": 5123,
"count": 36,
"max": [
35
],
"min": [
0
],
"type": "SCALAR"
},
{
"bufferView": 1,
"byteOffset": 0,
"componentType": 5126,
"count": 36,
"max": [
1,
1,
1.000001
],
"min": [
-1,
-1,
-1
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 0,
"componentType": 5126,
"count": 36,
"max": [
1,
1,
1
],
"min": [
-1,
-1,
-1
],
"type": "VEC3"
},
{
"bufferView": 3,
"byteOffset": 0,
"componentType": 5126,
"count": 36,
"max": [
1,
-0,
-0,
1
],
"min": [
0,
-0,
-1,
-1
],
"type": "VEC4"
},
{
"bufferView": 4,
"byteOffset": 0,
"componentType": 5126,
"count": 36,
"max": [
1,
1
],
"min": [
-1,
-1
],
"type": "VEC2"
}
],
"asset": {
"generator": "VKTS glTF 2.0 exporter",
"version": "2.0"
},
"bufferViews": [
{
"buffer": 0,
"byteLength": 72,
"byteOffset": 0,
"target": 34963
},
{
"buffer": 0,
"byteLength": 432,
"byteOffset": 72,
"target": 34962
},
{
"buffer": 0,
"byteLength": 432,
"byteOffset": 504,
"target": 34962
},
{
"buffer": 0,
"byteLength": 576,
"byteOffset": 936,
"target": 34962
},
{
"buffer": 0,
"byteLength": 288,
"byteOffset": 1512,
"target": 34962
}
],
"buffers": [
{
"byteLength": 1800,
"uri": "Cube.bin"
}
],
"images": [
{
"0comment": "Use Cube_MetallicRoughness.png to reduce scene filesize",
"uri": "Cube_MetallicRoughness.png"
},
{
"uri": "Cube_MetallicRoughness.png"
}
],
"materials": [
{
"emissiveTexture": {
"index": 0,
"extensions": {
"KHR_texture_transform": {
"offset": [
0,
1
],
"scale": [
1,
-1
]
}
}
}
},
{
"name": "Cube",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicRoughnessTexture": {
"index": 1,
"extensions": {
"KHR_texture_transform": {
"offset": [
0,
1
],
"rotation": 1.57079632679,
"scale": [
0.5,
0.5
]
}
}
}
}
}
],
"meshes": [
{
"name": "Cube",
"primitives": [
{
"attributes": {
"NORMAL": 2,
"POSITION": 1,
"TANGENT": 3,
"TEXCOORD_0": 4
},
"indices": 0,
"material": 0,
"mode": 4
}
]
}
],
"nodes": [
{
"mesh": 0,
"name": "Cube"
}
],
"samplers": [
{}
],
"scene": 0,
"scenes": [
{
"nodes": [
0
]
}
],
"textures": [
{
"sampler": 0,
"source": 0
},
{
"sampler": 0,
"source": 1
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

View File

@@ -0,0 +1,6 @@
Added KHR_texture_transform property to Cube scene.
License: Donated by Norbert Nopper for glTF testing.
https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Cube

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@ TEST_CASE("datauri-in-glb", "[issue-79]") {
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
}
@@ -82,7 +82,236 @@ TEST_CASE("extension-with-empty-object", "[issue-97]") {
REQUIRE(m.materials[0].extensions.size() == 1);
REQUIRE(m.materials[0].extensions.count("VENDOR_material_some_ext") == 1);
}
}
TEST_CASE("invalid-primitive-indices", "[bounds-checking]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
// Loading is expected to fail, but not crash.
bool ret = ctx.LoadASCIIFromFile(
&model, &err, &warn,
"../models/BoundsChecking/invalid-primitive-indices.gltf");
REQUIRE_THAT(err,
Catch::Contains("primitive indices accessor out of bounds"));
REQUIRE_FALSE(ret);
}
TEST_CASE("invalid-buffer-view-index", "[bounds-checking]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
// Loading is expected to fail, but not crash.
bool ret = ctx.LoadASCIIFromFile(
&model, &err, &warn,
"../models/BoundsChecking/invalid-buffer-view-index.gltf");
REQUIRE_THAT(err, Catch::Contains("accessor[0] invalid bufferView"));
REQUIRE_FALSE(ret);
}
TEST_CASE("invalid-buffer-index", "[bounds-checking]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
// Loading is expected to fail, but not crash.
bool ret = ctx.LoadASCIIFromFile(
&model, &err, &warn,
"../models/BoundsChecking/invalid-buffer-index.gltf");
REQUIRE_THAT(
err, Catch::Contains("image[0] buffer \"1\" not found in the scene."));
REQUIRE_FALSE(ret);
}
TEST_CASE("glb-invalid-length", "[bounds-checking]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
// This glb has a much longer length than the provided data and should fail
// initial range checks.
const unsigned char glb_invalid_length[] = "glTF"
"\x20\x00\x00\x00" "\x6c\x66\x00\x00" //
// | version | length |
"\x02\x00\x00\x00" "\x4a\x53\x4f\x4e{}"; //
// | model length | model format |
bool ret = ctx.LoadBinaryFromMemory(&model, &err, &warn, glb_invalid_length,
sizeof(glb_invalid_length));
REQUIRE_THAT(err, Catch::Contains("Invalid glTF binary."));
REQUIRE_FALSE(ret);
}
TEST_CASE("integer-out-of-bounds", "[bounds-checking]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
// Loading is expected to fail, but not crash.
bool ret = ctx.LoadASCIIFromFile(
&model, &err, &warn,
"../models/BoundsChecking/integer-out-of-bounds.gltf");
REQUIRE_THAT(err, Catch::Contains("not a positive integer"));
REQUIRE_FALSE(ret);
}
TEST_CASE("parse-integer", "[bounds-checking]") {
SECTION("parses valid numbers") {
std::string err;
int result = 123;
CHECK(tinygltf::ParseIntegerProperty(&result, &err, {{"zero", 0}}, "zero",
true));
REQUIRE(err == "");
REQUIRE(result == 0);
CHECK(tinygltf::ParseIntegerProperty(&result, &err, {{"int", -1234}}, "int",
true));
REQUIRE(err == "");
REQUIRE(result == -1234);
}
SECTION("detects missing properties") {
std::string err;
int result = -1;
CHECK_FALSE(tinygltf::ParseIntegerProperty(&result, &err, {}, "int", true));
REQUIRE_THAT(err, Catch::Contains("'int' property is missing"));
REQUIRE(result == -1);
}
SECTION("handled missing but not required properties") {
std::string err;
int result = -1;
CHECK_FALSE(
tinygltf::ParseIntegerProperty(&result, &err, {}, "int", false));
REQUIRE(err == "");
REQUIRE(result == -1);
}
SECTION("invalid integers") {
std::string err;
int result = -1;
CHECK_FALSE(tinygltf::ParseIntegerProperty(&result, &err, {{"int", 0.5}},
"int", true));
REQUIRE_THAT(err, Catch::Contains("not an integer type"));
// Excessively large values and NaN aren't allowed either.
err.clear();
CHECK_FALSE(tinygltf::ParseIntegerProperty(&result, &err, {{"int", 1e300}},
"int", true));
REQUIRE_THAT(err, Catch::Contains("not an integer type"));
err.clear();
CHECK_FALSE(tinygltf::ParseIntegerProperty(
&result, &err, {{"int", std::numeric_limits<double>::quiet_NaN()}},
"int", true));
REQUIRE_THAT(err, Catch::Contains("not an integer type"));
}
}
TEST_CASE("parse-unsigned", "[bounds-checking]") {
SECTION("parses valid unsigned integers") {
// Use string-based parsing here, using the initializer list syntax doesn't
// parse 0 as unsigned.
json zero_obj = json::parse("{\"zero\": 0}");
std::string err;
size_t result = 123;
CHECK(
tinygltf::ParseUnsignedProperty(&result, &err, zero_obj, "zero", true));
REQUIRE(err == "");
REQUIRE(result == 0);
}
SECTION("invalid integers") {
std::string err;
size_t result = -1;
CHECK_FALSE(tinygltf::ParseUnsignedProperty(&result, &err, {{"int", -1234}},
"int", true));
REQUIRE_THAT(err, Catch::Contains("not a positive integer"));
err.clear();
CHECK_FALSE(tinygltf::ParseUnsignedProperty(&result, &err, {{"int", 0.5}},
"int", true));
REQUIRE_THAT(err, Catch::Contains("not a positive integer"));
// Excessively large values and NaN aren't allowed either.
err.clear();
CHECK_FALSE(tinygltf::ParseUnsignedProperty(&result, &err, {{"int", 1e300}},
"int", true));
REQUIRE_THAT(err, Catch::Contains("not a positive integer"));
err.clear();
CHECK_FALSE(tinygltf::ParseUnsignedProperty(
&result, &err, {{"int", std::numeric_limits<double>::quiet_NaN()}},
"int", true));
REQUIRE_THAT(err, Catch::Contains("not a positive integer"));
}
}
TEST_CASE("parse-integer-array", "[bounds-checking]") {
SECTION("parses valid integers") {
std::string err;
std::vector<int> result;
CHECK(tinygltf::ParseIntegerArrayProperty(&result, &err,
{{"x", {-1, 2, 3}}}, "x", true));
REQUIRE(err == "");
REQUIRE(result.size() == 3);
REQUIRE(result[0] == -1);
REQUIRE(result[1] == 2);
REQUIRE(result[2] == 3);
}
SECTION("invalid integers") {
std::string err;
std::vector<int> result;
CHECK_FALSE(tinygltf::ParseIntegerArrayProperty(
&result, &err, {{"x", {-1, 1e300, 3}}}, "x", true));
REQUIRE_THAT(err, Catch::Contains("not an integer type"));
}
}
TEST_CASE("pbr-khr-texture-transform", "[material]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
// Loading is expected to fail, but not crash.
bool ret = ctx.LoadASCIIFromFile(
&model, &err, &warn,
"../models/Cube-texture-ext/Cube-textransform.gltf");
REQUIRE(ret == true);
REQUIRE(model.materials.size() == 2);
REQUIRE(model.materials[0].emissiveTexture.extensions.count("KHR_texture_transform") == 1);
REQUIRE(model.materials[0].emissiveTexture.extensions["KHR_texture_transform"].IsObject());
tinygltf::Value::Object &texform = model.materials[0].emissiveTexture.extensions["KHR_texture_transform"].Get<tinygltf::Value::Object>();
REQUIRE(texform.count("scale"));
REQUIRE(texform["scale"].IsArray());
// Note: It looks json.hpp parse integer JSON number as integer, not floating point.
// IsNumber return true either value is int or floating point.
REQUIRE(texform["scale"].Get(0).IsNumber());
REQUIRE(texform["scale"].Get(1).IsNumber());
double scale[2];
scale[0] = texform["scale"].Get(0).GetNumberAsDouble();
scale[1] = texform["scale"].Get(1).GetNumberAsDouble();
REQUIRE(scale[0] == Approx(1.0));
REQUIRE(scale[1] == Approx(-1.0));
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
Create single schema string by deferencing $ref in glTF schema JSON for embedding JSON scheme string in C++.
## Setup
Use python2
```
$ pip2 install jsonpath-rw
$ pip2 install simplejson
```
Put `ref_resolver.py` and `generate_single_schema_doc.py` to glTF schema direcotry(i.e. `$glTF/specification/2.0/schema`)
## Generate
Run `generate_single_schema_doc.py`
## TODO
* [ ] Print date and git commit id?

View File

@@ -1,37 +0,0 @@
# for print with `end` parameter
from __future__ import print_function
import json
from ref_resolver import RefResolver
import base64
f = open("glTF.schema.json")
j = json.loads(f.read())
# call to API resolve method
RefResolver("glTF.schema.json").resolve(j)
j_str = json.dumps(j, indent=2)
# Run json.dumps twice to get escaped string
escaped_str = json.dumps(j_str)
# MSVC does not accept string larger than 16K.
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2026?view=vs-2019
# Also, it has a hard limit of 65,535 bytes even splitting a string with double quotation.
# So, we write string as an array of string(then application must concatenate it)
# https://stackoverflow.com/questions/9475241/split-string-every-nth-character
n = 8000 # Conservative number
splitted_string = [escaped_str[i:i+n] for i in range(0, len(escaped_str), n)]
#print(len(splitted_string))
print("const char *kglTFSchemaStrings[] = {", end='')
for (i, s) in enumerate(splitted_string):
print(s, end='')
if i != (len(splitted_string) - 1):
print('",\n"', end='')
print("};")

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,82 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from urlparse import urlparse, urljoin
import simplejson as json
from os.path import isfile
import jsonpath_rw
import requests
cache = {}
class RefResolver:
def __init__(self):
self.url_fragments = None
def __init__(self, id):
self.id = id
if id is not None:
self.url_fragments = urlparse(id)
else:
self.url_fragments = None
def resolve(self, json_obj):
if isinstance(json_obj, dict):
for key, value in json_obj.items():
if key == "$ref":
ref_frag = urlparse(value)
ref_file = ref_frag.netloc + ref_frag.path
json_dump = {}
if ref_file in cache:
json_dump = cache[ref_file]
else:
if self.url_fragments.scheme in ['http', 'https']:
ref_url = urljoin(self.id, ref_file)
if callable(requests.Response.json):
json_dump = requests.get(ref_url).json()
else:
json_dump = requests.get(ref_url).json
ref_id = None
if 'tilte' in json_dump:
ref_id = json_dump['title']
cache[ref_file] = json_dump
RefResolver(ref_id).resolve(json_dump)
cache[ref_file] = json_dump
#elif self.url_fragments.scheme == 'file':
else:
if isfile(ref_file):
# if the ref is another file -> go there and get it
json_dump = json.load(open(ref_file))
ref_id = None
if 'title' in json_dump:
ref_id = json_dump['title']
cache[ref_file] = json_dump
RefResolver(ref_id).resolve(json_dump)
cache[ref_file] = json_dump
else:
# if the ref is in the same file grab it from the same file
json_dump = json.load(open(self.url_fragments.netloc+self.url_fragments.path))
cache[ref_file] = json_dump
ref_path_expr = "$" + ".".join(ref_frag.fragment.split("/"))
path_expression = jsonpath_rw.parse(ref_path_expr)
list_of_values = [match.value for match in path_expression.find(json_dump)]
if len(list_of_values) > 0:
resolution = list_of_values[0]
return resolution
resolved = self.resolve(value)
if resolved is not None:
json_obj[key] = resolved
elif isinstance(json_obj, list):
for (key, value) in enumerate(json_obj):
resolved = self.resolve(value)
if resolved is not None:
json_obj[key] = resolved
return None