Compare commits

...

11 Commits

Author SHA1 Message Date
Syoyo Fujita
3c0bcb7d72 Add document on schema validation feature. 2019-06-24 15:30:32 +09:00
Syoyo Fujita
d5694dc15d Some pointer variables are not initialized. 2019-06-15 16:22:40 +09:00
Syoyo Fujita
ddf0a0e83c Update rapidjson-amalgamation to include error/en.h and cursorstreamwrapper.h.
Now schema validation is getting to work.
2019-06-14 22:03:11 +09:00
Syoyo Fujita
f3ee08c595 Merge branch 'rapidjson' of github.com:syoyo/tinygltf into rapidjson 2019-06-14 19:29:26 +09:00
Syoyo Fujita
f75327bc5b Fix compilation on MSVC. 2019-06-14 19:29:13 +09:00
Syoyo Fujita
7acc95a2ae Write an array of string to avoid the limit of the character length in MSVC compiler. 2019-06-14 19:28:37 +09:00
Syoyo Fujita
2a6f2cc356 Serializer now started to work. 2019-06-13 20:36:37 +09:00
Syoyo Fujita
0cf2812775 Use rapidjson for serialization(W.I.P. currently segfaults when serialize a scene) 2019-06-12 22:35:28 +09:00
Syoyo Fujita
2673d1d3ef Add C++ string of glTF Schema. 2019-06-11 14:38:01 +09:00
Syoyo Fujita
cf8b7cc0a4 Add JSON schema ref resolver. 2019-06-11 14:25:16 +09:00
Syoyo Fujita
93d0e365bb RapidJson version of TinyGLTF.
TODO: Serializer.
2019-06-10 02:39:13 +09:00
11 changed files with 20870 additions and 662 deletions

13
LICENSE.rapidjson.txt Normal file
View File

@@ -0,0 +1,13 @@
// 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,11 @@
`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.
If you are looking for old, C++03 version, please use `devel-picojson` branch.
`TinyGLTF` uses single-header version of RapidJson(https://github.com/Tencent/rapidjson) as a JSON parser.
## Status
- v2.3.0 release(Support built-in schema validation)
- 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,6 +34,7 @@ If you are looking for old, C++03 version, please use `devel-picojson` branch.
* [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.
@@ -68,6 +69,11 @@ If you are looking for old, C++03 version, please use `devel-picojson` branch.
* [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.
* 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.
@@ -95,7 +101,7 @@ TinyGLTF uses the following third party libraries.
## Build and example
Copy `stb_image.h`, `stb_image_write.h`, `json.hpp` and `tiny_gltf.h` to your project.
Copy `stb_image.h`, `stb_image_write.h`, `rapidjson-amalgamation.h` and `tiny_gltf.h` to your project.
### Loading glTF 2.0 model
@@ -104,6 +110,7 @@ Copy `stb_image.h`, `stb_image_write.h`, `json.hpp` and `tiny_gltf.h` to your pr
#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"
@@ -116,6 +123,10 @@ 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());
@@ -133,6 +144,7 @@ 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.

16
gltf.schema.resolved.inc Normal file

File diff suppressed because one or more lines are too long

View File

@@ -2,6 +2,7 @@
// 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"
@@ -640,8 +641,13 @@ 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()) {

16906
rapidjson-amalgamation.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
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

@@ -0,0 +1,37 @@
# 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

@@ -0,0 +1,82 @@
# 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