mirror of
https://github.com/syoyo/tinygltf.git
synced 2026-07-13 01:29:10 +00:00
Compare commits
280 Commits
json11
...
empty-mate
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1923067982 | ||
|
|
68adc4ba5e | ||
|
|
42a8cd50ff | ||
|
|
0543640a83 | ||
|
|
9c59a0b64c | ||
|
|
452541a231 | ||
|
|
78fe8d9b89 | ||
|
|
51e5508fa0 | ||
|
|
91da299729 | ||
|
|
50ae8a31a8 | ||
|
|
0af0435ef1 | ||
|
|
7c342533e9 | ||
|
|
7842c1276f | ||
|
|
125e4a2033 | ||
|
|
c9d6c5b9b4 | ||
|
|
96a8b2c69b | ||
|
|
01d54380ac | ||
|
|
6cd8fdb2c8 | ||
|
|
fe01af2f01 | ||
|
|
efdd2b04dc | ||
|
|
2e642b3322 | ||
|
|
1739d025a9 | ||
|
|
39418e5728 | ||
|
|
5622d2762d | ||
|
|
3d939fd3ee | ||
|
|
fbbeb4d6a9 | ||
|
|
cef1787ef8 | ||
|
|
2f5aa9f13b | ||
|
|
28bafe4b11 | ||
|
|
34894a6325 | ||
|
|
2e7006797b | ||
|
|
d9c03d041a | ||
|
|
50a3061ddf | ||
|
|
014dce27f4 | ||
|
|
c046769054 | ||
|
|
c43266fdc9 | ||
|
|
aca196e8d3 | ||
|
|
b48c027c9a | ||
|
|
db5c3bea45 | ||
|
|
ddfa1f2f0b | ||
|
|
7b69c778fe | ||
|
|
73e73bf3c1 | ||
|
|
35d664e417 | ||
|
|
272a9dfa5f | ||
|
|
f3bf6ee78e | ||
|
|
aba57bb907 | ||
|
|
6fad7adb9c | ||
|
|
3dad303bea | ||
|
|
ff0a2e9fb4 | ||
|
|
fe77cc5cdd | ||
|
|
18f0e20a11 | ||
|
|
978adee547 | ||
|
|
73c4cce303 | ||
|
|
925b83627a | ||
|
|
92c23725ae | ||
|
|
af750a5104 | ||
|
|
ff48fa0ff4 | ||
|
|
ec45334d3d | ||
|
|
5f603c56dc | ||
|
|
063b8586f1 | ||
|
|
db855c6794 | ||
|
|
e391f6b03e | ||
|
|
5ecede71f0 | ||
|
|
40982716f9 | ||
|
|
4bdc96fb9b | ||
|
|
96ecea080a | ||
|
|
22bfc843ee | ||
|
|
eaa25a307a | ||
|
|
ab600b8e72 | ||
|
|
eb9d29c06e | ||
|
|
57356933c5 | ||
|
|
c3d6716c56 | ||
|
|
ac5e09f8c3 | ||
|
|
e2c3fe1c0b | ||
|
|
973d9b3394 | ||
|
|
28ad4ab7b8 | ||
|
|
0227ae5d9b | ||
|
|
a0a62bde1c | ||
|
|
23d1ff2880 | ||
|
|
bcf2ce586e | ||
|
|
aa3c5a1cad | ||
|
|
db2fbeec9d | ||
|
|
c4166e4c60 | ||
|
|
1cf179d377 | ||
|
|
ddc14f8ba6 | ||
|
|
72f4a55edd | ||
|
|
379bb612f1 | ||
|
|
1da4e5d633 | ||
|
|
4e47bc7799 | ||
|
|
9cc3e91968 | ||
|
|
d09788d10f | ||
|
|
a11f6e1939 | ||
|
|
8ced108571 | ||
|
|
3eb65e269a | ||
|
|
1322c7bf09 | ||
|
|
49651fe3d9 | ||
|
|
db93a87c4a | ||
|
|
7b0d81bf12 | ||
|
|
2e8a115d7e | ||
|
|
ae9364902a | ||
|
|
06d2fbdae6 | ||
|
|
d5ff5cbfb1 | ||
|
|
1d20520680 | ||
|
|
4ab0386d09 | ||
|
|
a471770f38 | ||
|
|
125d8e50a9 | ||
|
|
45cac78709 | ||
|
|
a9d86c1af4 | ||
|
|
2f26eddac4 | ||
|
|
a0939550ca | ||
|
|
58ab95be2f | ||
|
|
bf0e4f8e45 | ||
|
|
30f333c607 | ||
|
|
419162716e | ||
|
|
9533c352a1 | ||
|
|
9ff3d93084 | ||
|
|
aea514a975 | ||
|
|
05a4456948 | ||
|
|
6e08b17ce3 | ||
|
|
fb256609f2 | ||
|
|
5cecef2b92 | ||
|
|
1100f0f1eb | ||
|
|
2b66c81f67 | ||
|
|
f29375f59b | ||
|
|
79e3df26a8 | ||
|
|
e3cf5edb94 | ||
|
|
b74fadef8e | ||
|
|
a11709a9ff | ||
|
|
cf668683f9 | ||
|
|
817bbcfb58 | ||
|
|
23467959ca | ||
|
|
6f08785e9f | ||
|
|
ff2b1f92dd | ||
|
|
e886247329 | ||
|
|
83bb1a48d7 | ||
|
|
c3353e1acd | ||
|
|
81b672bcc2 | ||
|
|
cece6ee6d2 | ||
|
|
31f875ddbc | ||
|
|
8dccf9bf4e | ||
|
|
508dcfa2e6 | ||
|
|
7e009041e3 | ||
|
|
14977937c2 | ||
|
|
8bb18fbd9c | ||
|
|
9eeaf20133 | ||
|
|
a34aa8ea77 | ||
|
|
59b2966f81 | ||
|
|
7481011fd9 | ||
|
|
0d2b6efa6f | ||
|
|
ce7fa7419b | ||
|
|
906f98fa74 | ||
|
|
d2a2703ec5 | ||
|
|
95f05757d6 | ||
|
|
ab63db6318 | ||
|
|
6ff95392b0 | ||
|
|
c29bd3d9ce | ||
|
|
63419a11e1 | ||
|
|
06c30c4d04 | ||
|
|
67e6160a9a | ||
|
|
a3b8b355ae | ||
|
|
5145394239 | ||
|
|
67aa2ca75e | ||
|
|
ce25385eab | ||
|
|
6143c6662b | ||
|
|
81d75df48a | ||
|
|
83ccb9f28d | ||
|
|
9b6f52e98a | ||
|
|
5cecc41db9 | ||
|
|
208c3058bf | ||
|
|
cba5d6caae | ||
|
|
d1e1472992 | ||
|
|
ff51570c26 | ||
|
|
a472a3fa0f | ||
|
|
1f160d5b8f | ||
|
|
5150a46072 | ||
|
|
cea69e37a5 | ||
|
|
8b56c016ab | ||
|
|
c7e205be87 | ||
|
|
6dba6c6aac | ||
|
|
6df800d2b6 | ||
|
|
2f044e77f1 | ||
|
|
af5a5ef026 | ||
|
|
6591ba4461 | ||
|
|
74c3c10121 | ||
|
|
ad63bf748b | ||
|
|
5d43cf8e64 | ||
|
|
4e2988eebd | ||
|
|
ee179b2cb6 | ||
|
|
4ebd6368fb | ||
|
|
67d3d2504d | ||
|
|
d9a468bbb4 | ||
|
|
c7bae71f7f | ||
|
|
f93642c196 | ||
|
|
f68d5e1f2a | ||
|
|
1c84fc22a5 | ||
|
|
150f243b1b | ||
|
|
0ee273fdfa | ||
|
|
046400b17f | ||
|
|
89fd93f815 | ||
|
|
e940337796 | ||
|
|
1b5f476d95 | ||
|
|
52936a00e0 | ||
|
|
f3ef880029 | ||
|
|
1af7c1d784 | ||
|
|
c0b79afecc | ||
|
|
c49461b7c2 | ||
|
|
051f4be2f1 | ||
|
|
4557b6aa22 | ||
|
|
b2d7d88dbc | ||
|
|
b7ca7c9381 | ||
|
|
0ffedcbe79 | ||
|
|
80faac5238 | ||
|
|
2a9d9deb67 | ||
|
|
8a98d98cd9 | ||
|
|
689edcbef6 | ||
|
|
820ede87db | ||
|
|
d6b0d0a61f | ||
|
|
5f180aaf74 | ||
|
|
dab0daaedf | ||
|
|
0ccc8dc262 | ||
|
|
811e1d3899 | ||
|
|
f65e06c5ca | ||
|
|
f29ae1a653 | ||
|
|
3bf16e4be5 | ||
|
|
fbc4295770 | ||
|
|
edf8d5cae1 | ||
|
|
b7f2473225 | ||
|
|
ed7bf66255 | ||
|
|
caa36dd050 | ||
|
|
389d5016ad | ||
|
|
d02ad0dede | ||
|
|
8f67121deb | ||
|
|
62be8d04cf | ||
|
|
d11a4c4d71 | ||
|
|
19b806e052 | ||
|
|
e0ab69cb31 | ||
|
|
8915252407 | ||
|
|
9446f65667 | ||
|
|
fb9f709166 | ||
|
|
a63cc6373d | ||
|
|
b3c1471317 | ||
|
|
9056aee823 | ||
|
|
29c431b2f2 | ||
|
|
d06b2c2022 | ||
|
|
339c9d578a | ||
|
|
7c315fa8a8 | ||
|
|
0f04ed018a | ||
|
|
ca56f726d6 | ||
|
|
e8a46c4e1d | ||
|
|
9cd14a461b | ||
|
|
1ef603ea2a | ||
|
|
14d259f361 | ||
|
|
9223d3133a | ||
|
|
9b321a8515 | ||
|
|
7e9f734d73 | ||
|
|
9d86405d3d | ||
|
|
1ccb4ff580 | ||
|
|
8fd91aea04 | ||
|
|
8f76d790b8 | ||
|
|
853f6df7b5 | ||
|
|
758a1240c9 | ||
|
|
7bdfed3bec | ||
|
|
bf9c2f4abd | ||
|
|
fc0116b323 | ||
|
|
962552c5c8 | ||
|
|
606e5dde31 | ||
|
|
6a0d4c57b1 | ||
|
|
f4b6d11abc | ||
|
|
5a4c898912 | ||
|
|
f2addc0e44 | ||
|
|
70d16a7b92 | ||
|
|
326d7ea310 | ||
|
|
eb011068c0 | ||
|
|
87be0ce34b | ||
|
|
7d9a0bda3a | ||
|
|
7ece5c8275 | ||
|
|
6bdffedcbe | ||
|
|
d2fb7dc2af | ||
|
|
62a72c4845 | ||
|
|
73584ba7b7 |
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
30
.github/ISSUE_TEMPLATE/issue-report.md
vendored
Normal file
30
.github/ISSUE_TEMPLATE/issue-report.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
name: Issue report
|
||||||
|
about: Create a report
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the issue**
|
||||||
|
|
||||||
|
A clear and concise description of what the issue is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
|
||||||
|
- OS
|
||||||
|
- Compiler, compiler version, compile options
|
||||||
|
- Please attach minimal and reproducible .glTF file if you got an issue related to .glTF data
|
||||||
|
|
||||||
|
**Expected behaviour**
|
||||||
|
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
165
.github/workflows/c-cpp.yml
vendored
Normal file
165
.github/workflows/c-cpp.yml
vendored
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
name: C/C++ CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# compile with older gcc4.8
|
||||||
|
build-gcc48:
|
||||||
|
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
name: Build with gcc 4.8
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y build-essential
|
||||||
|
sudo apt-get install -y gcc-4.8 g++-4.8
|
||||||
|
g++-4.8 -std=c++11 -o loader_example loader_example.cc
|
||||||
|
|
||||||
|
- name: NoexceptBuild
|
||||||
|
run: |
|
||||||
|
g++-4.8 -DTINYGLTF_NOEXCEPTION -std=c++11 -o loader_example loader_example.cc
|
||||||
|
|
||||||
|
- name: RapidjsonBuild
|
||||||
|
run: |
|
||||||
|
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
|
||||||
|
|
||||||
|
# compile with mingw gcc cross
|
||||||
|
build-mingw-cross:
|
||||||
|
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
name: Build with MinGW gcc cross
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y build-essential
|
||||||
|
sudo apt-get install -y mingw-w64
|
||||||
|
x86_64-w64-mingw32-g++ -std=c++11 -o loader_example loader_example.cc
|
||||||
|
|
||||||
|
# Windows(x64) + Visual Studio 2019 build
|
||||||
|
build-windows-msvc:
|
||||||
|
|
||||||
|
runs-on: windows-latest
|
||||||
|
name: Build for Windows(x64, MSVC)
|
||||||
|
|
||||||
|
# Use system installed cmake
|
||||||
|
# https://help.github.com/en/actions/reference/software-installed-on-github-hosted-runners
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
- name: Configure
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -G "Visual Studio 16 2019" -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On ..
|
||||||
|
cd ..
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build --config Release
|
||||||
|
|
||||||
|
|
||||||
|
build-linux:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Buld with gcc
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: build
|
||||||
|
run: |
|
||||||
|
g++ -std=c++11 -o loader_example loader_example.cc
|
||||||
|
- name: test
|
||||||
|
run: |
|
||||||
|
./loader_example models/Cube/Cube.gltf
|
||||||
|
|
||||||
|
- name: tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
g++ -I../ -std=c++11 -g -O0 -o tester tester.cc
|
||||||
|
./tester
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
- name: noexcept_tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
g++ -DTINYGLTF_NOEXCEPTION -I../ -std=c++11 -g -O0 -o tester_noexcept tester.cc
|
||||||
|
./tester_noexcept
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
|
||||||
|
build-rapidjson-linux:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Buld with gcc + rapidjson
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: build
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/Tencent/rapidjson
|
||||||
|
g++ -v
|
||||||
|
g++ -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -o loader_example loader_example.cc
|
||||||
|
|
||||||
|
- name: loader_example_test
|
||||||
|
run: |
|
||||||
|
./loader_example models/Cube/Cube.gltf
|
||||||
|
|
||||||
|
- name: tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
g++ -DTINYGLTF_USE_RAPIDJSON -I../rapidjson/include/rapidjson -I../ -std=c++11 -g -O0 -o tester tester.cc
|
||||||
|
./tester
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
- name: noexcept_tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
g++ -DTINYGLTF_USE_RAPIDJSON -I../rapidjson/include/rapidjson -DTINYGLTF_NOEXCEPTION -I../ -std=c++11 -g -O0 -o tester_noexcept tester.cc
|
||||||
|
./tester_noexcept
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Cross-compile for aarch64 linux target
|
||||||
|
build-cross-aarch64:
|
||||||
|
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
name: Build on cross aarch64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y build-essential
|
||||||
|
sudo apt-get install -y gcc-8-aarch64-linux-gnu g++-8-aarch64-linux-gnu
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# macOS clang
|
||||||
|
build-macos:
|
||||||
|
|
||||||
|
runs-on: macos-latest
|
||||||
|
name: Build on macOS
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
clang++ -std=c++11 -g -O0 -o loader_example loader_example.cc
|
||||||
|
./loader_example models/Cube/Cube.gltf
|
||||||
|
|
||||||
|
git clone https://github.com/Tencent/rapidjson
|
||||||
|
clang++ -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -g -O0 -o loader_example loader_example.cc
|
||||||
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -67,4 +67,5 @@ imgui.ini
|
|||||||
loader_example
|
loader_example
|
||||||
tests/tester
|
tests/tester
|
||||||
tests/tester_noexcept
|
tests/tester_noexcept
|
||||||
|
tests/issue-97.gltf
|
||||||
|
|
||||||
|
|||||||
18
.travis.yml
18
.travis.yml
@@ -31,6 +31,17 @@ matrix:
|
|||||||
- addons: *1
|
- addons: *1
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER_VERSION=3.9 BUILD_TYPE=Debug CFLAGS="-O0" CXXFLAGS="-O0"
|
env: COMPILER_VERSION=3.9 BUILD_TYPE=Debug CFLAGS="-O0" CXXFLAGS="-O0"
|
||||||
|
- addons: &3
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.8
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER_VERSION=4.8 BUILD_TYPE=Debug
|
||||||
|
- addons: *3
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER_VERSION=4.8 BUILD_TYPE=Release
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- ./.travis-before-install.sh
|
- ./.travis-before-install.sh
|
||||||
@@ -42,6 +53,11 @@ script:
|
|||||||
- ${CC} -v
|
- ${CC} -v
|
||||||
- ${CXX} ${EXTRA_CXXFLAGS} -std=c++11 -Wall -g -o loader_example loader_example.cc
|
- ${CXX} ${EXTRA_CXXFLAGS} -std=c++11 -Wall -g -o loader_example loader_example.cc
|
||||||
- ./loader_example ./models/Cube/Cube.gltf
|
- ./loader_example ./models/Cube/Cube.gltf
|
||||||
- cd examples/raytrace
|
- cd tests
|
||||||
|
- clang++ -v
|
||||||
|
- make
|
||||||
|
- ./tester
|
||||||
|
- ./tester_noexcept
|
||||||
|
- cd ../examples/raytrace
|
||||||
- ../../premake5 gmake
|
- ../../premake5 gmake
|
||||||
- make
|
- make
|
||||||
|
|||||||
@@ -4,14 +4,27 @@ PROJECT (tinygltf)
|
|||||||
|
|
||||||
SET(CMAKE_CXX_STANDARD 11)
|
SET(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
ADD_EXECUTABLE ( loader_example
|
option(TINYGLTF_BUILD_LOADER_EXAMPLE "Build loader_example" ON)
|
||||||
loader_example.cc
|
option(TINYGLTF_BUILD_GL_EXAMPLES "Build GL exampels(requires glfw, OpenGL, etc)" OFF)
|
||||||
)
|
option(TINYGLTF_BUILD_VALIDATOR_EXAMPLE "Build validator exampe" OFF)
|
||||||
|
|
||||||
ADD_SUBDIRECTORY ( examples/gltfutil )
|
if (TINYGLTF_BUILD_LOADER_EXAMPLE)
|
||||||
ADD_SUBDIRECTORY ( examples/glview )
|
ADD_EXECUTABLE ( loader_example
|
||||||
ADD_SUBDIRECTORY ( examples/validator )
|
loader_example.cc
|
||||||
|
)
|
||||||
|
endif (TINYGLTF_BUILD_LOADER_EXAMPLE)
|
||||||
|
|
||||||
|
if (TINYGLTF_BUILD_GL_EXAMPLES)
|
||||||
|
ADD_SUBDIRECTORY ( examples/gltfutil )
|
||||||
|
ADD_SUBDIRECTORY ( examples/glview )
|
||||||
|
endif (TINYGLTF_BUILD_GL_EXAMPLES)
|
||||||
|
|
||||||
|
if (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
|
||||||
|
ADD_SUBDIRECTORY ( examples/validator )
|
||||||
|
endif (TINYGLTF_BUILD_VALIDATOR_EXAMPLE)
|
||||||
|
#
|
||||||
|
# TinuGLTF is a header-only library, so no library build. just install header files.
|
||||||
|
#
|
||||||
INSTALL ( FILES
|
INSTALL ( FILES
|
||||||
json.hpp
|
json.hpp
|
||||||
stb_image.h
|
stb_image.h
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -2,8 +2,12 @@
|
|||||||
# Use this for strict compilation check(will work on clang 3.8+)
|
# Use this for strict compilation check(will work on clang 3.8+)
|
||||||
#EXTRA_CXXFLAGS := -fsanitize=address -Wall -Werror -Weverything -Wno-c++11-long-long -Wno-c++98-compat
|
#EXTRA_CXXFLAGS := -fsanitize=address -Wall -Werror -Weverything -Wno-c++11-long-long -Wno-c++98-compat
|
||||||
|
|
||||||
|
# With draco
|
||||||
|
# EXTRA_CXXFLAGS := -I../draco/src/ -I../draco/build -DTINYGLTF_ENABLE_DRACO -L../draco/build
|
||||||
|
# EXTRA_LINKFLAGS := -L../draco/build/ -ldracodec -ldraco
|
||||||
|
|
||||||
all:
|
all:
|
||||||
clang++ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o loader_example loader_example.cc
|
clang++ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o loader_example loader_example.cc $(EXTRA_LINKFLAGS)
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
deps/cpplint.py tiny_gltf.h
|
deps/cpplint.py tiny_gltf.h
|
||||||
|
|||||||
85
README.md
85
README.md
@@ -3,11 +3,19 @@
|
|||||||
`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.
|
If you are looking for old, C++03 version, please use `devel-picojson` branch(but not maintained anymore).
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
v2.0.0 release(22 Aug, 2018)!
|
- 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.2.0 release(Support loading 16bit PNG. Sparse accessor support)
|
||||||
|
- v2.1.0 release(Draco support)
|
||||||
|
- v2.0.0 release(22 Aug, 2018)!
|
||||||
|
|
||||||
|
### Branches
|
||||||
|
|
||||||
|
* `sajson` : Use sajson to parse JSON. Parsing only but faster compile time(2x reduction compared to json.hpp and RapidJson)
|
||||||
|
|
||||||
## Builds
|
## Builds
|
||||||
|
|
||||||
@@ -15,6 +23,8 @@ v2.0.0 release(22 Aug, 2018)!
|
|||||||
|
|
||||||
[](https://ci.appveyor.com/project/syoyo/tinygltf)
|
[](https://ci.appveyor.com/project/syoyo/tinygltf)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Written in portable C++. C++-11 with STL dependency only.
|
* Written in portable C++. C++-11 with STL dependency only.
|
||||||
@@ -30,24 +40,37 @@ v2.0.0 release(22 Aug, 2018)!
|
|||||||
* Moderate parsing time and memory consumption.
|
* Moderate parsing time and memory consumption.
|
||||||
* glTF specification v2.0.0
|
* glTF specification v2.0.0
|
||||||
* [x] ASCII glTF
|
* [x] ASCII glTF
|
||||||
|
* [x] Load
|
||||||
|
* [x] Save
|
||||||
* [x] Binary glTF(GLB)
|
* [x] Binary glTF(GLB)
|
||||||
* [x] PBR material description
|
* [x] Load
|
||||||
|
* [x] Save(.bin embedded .glb)
|
||||||
* Buffers
|
* Buffers
|
||||||
* [x] Parse BASE64 encoded embedded buffer data(DataURI).
|
* [x] Parse BASE64 encoded embedded buffer data(DataURI).
|
||||||
* [x] Load `.bin` file.
|
* [x] Load `.bin` file.
|
||||||
* Image(Using stb_image)
|
* Image(Using stb_image)
|
||||||
* [x] Parse BASE64 encoded embedded image data(DataURI).
|
* [x] Parse BASE64 encoded embedded image data(DataURI).
|
||||||
* [x] Load external image file.
|
* [x] Load external image file.
|
||||||
* [x] PNG(8bit only)
|
* [x] Load PNG(8bit and 16bit)
|
||||||
* [x] JPEG(8bit only)
|
* [x] Load JPEG(8bit only)
|
||||||
* [x] BMP
|
* [x] Load BMP
|
||||||
* [x] GIF
|
* [x] Load GIF
|
||||||
* [x] Custom Image decoder callback(e.g. for decoding OpenEXR image)
|
* [x] Custom Image decoder callback(e.g. for decoding OpenEXR image)
|
||||||
* Load from memory
|
* Morph traget
|
||||||
|
* [x] Sparse accessor
|
||||||
|
* Load glTF from memory
|
||||||
* Custom callback handler
|
* Custom callback handler
|
||||||
* [x] Image load
|
* [x] Image load
|
||||||
|
* [x] Image save
|
||||||
* Extensions
|
* Extensions
|
||||||
* [x] Draco mesh decoding
|
* [x] Draco mesh decoding
|
||||||
|
* [ ] Draco mesh encoding
|
||||||
|
|
||||||
|
## 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
|
## Examples
|
||||||
|
|
||||||
@@ -61,6 +84,12 @@ v2.0.0 release(22 Aug, 2018)!
|
|||||||
* Physical based rendering with Vulkan using glTF 2.0 models https://github.com/SaschaWillems/Vulkan-glTF-PBR
|
* 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
|
* 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.
|
* [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
|
||||||
|
* Lighthouse 2: a rendering framework for real-time ray tracing / path tracing experiments. https://github.com/jbikker/lighthouse2
|
||||||
|
* [QuickLook GLTF](https://github.com/toshiks/glTF-quicklook) - quicklook plugin for macos. Also SceneKit wrapper for tinygltf.
|
||||||
|
* [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.
|
||||||
|
* [TDME2](https://github.com/andreasdr/tdme2) - TDME2 - ThreeDeeMiniEngine2 is a lightweight 3D engine including tools suited for 3D game development using C++11
|
||||||
* Your projects here! (Please send PR)
|
* Your projects here! (Please send PR)
|
||||||
|
|
||||||
## TODOs
|
## TODOs
|
||||||
@@ -68,13 +97,13 @@ v2.0.0 release(22 Aug, 2018)!
|
|||||||
* [ ] Write C++ code generator which emits C++ code from JSON schema for robust parsing.
|
* [ ] Write C++ code generator which emits C++ code from JSON schema for robust parsing.
|
||||||
* [ ] Mesh Compression/decompression(Open3DGC, etc)
|
* [ ] Mesh Compression/decompression(Open3DGC, etc)
|
||||||
* [x] Load Draco compressed mesh
|
* [x] Load Draco compressed mesh
|
||||||
* [x] Save Draco compressed mesh
|
* [ ] Save Draco compressed mesh
|
||||||
* [ ] Support `extensions` and `extras` property
|
* [ ] Open3DGC?
|
||||||
|
* [x] Support `extensions` and `extras` property
|
||||||
* [ ] HDR image?
|
* [ ] HDR image?
|
||||||
* [ ] OpenEXR extension through TinyEXR.
|
* [ ] OpenEXR extension through TinyEXR.
|
||||||
* [ ] Write example and tests for `animation` and `skin`
|
* [ ] 16bit PNG support in Serialization
|
||||||
* [ ] Skinning
|
* [ ] Write example and tests for `animation` and `skin`
|
||||||
* [ ] Morph targets
|
|
||||||
|
|
||||||
## Licenses
|
## Licenses
|
||||||
|
|
||||||
@@ -104,13 +133,13 @@ Copy `stb_image.h`, `stb_image_write.h`, `json.hpp` and `tiny_gltf.h` to your pr
|
|||||||
|
|
||||||
using namespace tinygltf;
|
using namespace tinygltf;
|
||||||
|
|
||||||
Model model;
|
Model model;
|
||||||
TinyGLTF loader;
|
TinyGLTF loader;
|
||||||
std::string err;
|
std::string err;
|
||||||
std::string warn;
|
std::string warn;
|
||||||
|
|
||||||
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, argv[1]);
|
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, argv[1]);
|
||||||
//bool ret = loader.LoadBinaryFromFile(&model, &err, &warn, argv[1]); // for binary glTF(.glb)
|
//bool ret = loader.LoadBinaryFromFile(&model, &err, &warn, argv[1]); // for binary glTF(.glb)
|
||||||
|
|
||||||
if (!warn.empty()) {
|
if (!warn.empty()) {
|
||||||
printf("Warn: %s\n", warn.c_str());
|
printf("Warn: %s\n", warn.c_str());
|
||||||
@@ -131,19 +160,28 @@ if (!ret) {
|
|||||||
* `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_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` : 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.
|
* `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.
|
||||||
* `TINYGLTF_NO_EXTERNAL_IMAGE` : Do not try to load external image file. This option woulde be helpful if you do not want load image file during glTF parsing.
|
* `TINYGLTF_NO_EXTERNAL_IMAGE` : Do not try to load external image file. This option would be helpful if you do not want to load image files during glTF parsing.
|
||||||
* `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_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_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_CPP14` : Use C++14 feature(requires C++14 compiler). This may give better performance than C++11.
|
||||||
|
|
||||||
|
|
||||||
### Saving gltTF 2.0 model
|
### Saving gltTF 2.0 model
|
||||||
* [ ] Buffers.
|
|
||||||
|
* Buffers.
|
||||||
* [x] To file
|
* [x] To file
|
||||||
* [x] Embedded
|
* [x] Embedded
|
||||||
* [ ] Draco compressed?
|
* [ ] Draco compressed?
|
||||||
* [x] Images
|
* [x] Images
|
||||||
* [x] To file
|
* [x] To file
|
||||||
* [x] Embedded
|
* [x] Embedded
|
||||||
* [ ] Binary(.glb)
|
* Binary(.glb)
|
||||||
|
* [x] .bin embedded single .glb
|
||||||
|
* [ ] External .bin
|
||||||
|
|
||||||
## Running tests.
|
## Running tests.
|
||||||
|
|
||||||
@@ -171,8 +209,17 @@ $ ./tester
|
|||||||
$ ./tester_noexcept
|
$ ./tester_noexcept
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Fuzzing tests
|
||||||
|
|
||||||
|
See `tests/fuzzer` for details.
|
||||||
|
|
||||||
|
After running fuzzer on Ryzen9 3950X a week, at least `LoadASCIIFromString` looks safe except for out-of-memory error in Fuzzer.
|
||||||
|
We may be better to introduce bounded memory size checking when parsing glTF data.
|
||||||
|
|
||||||
## Third party licenses
|
## Third party licenses
|
||||||
|
|
||||||
* json.hpp : Licensed under the MIT License <http://opensource.org/licenses/MIT>. Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
|
* json.hpp : Licensed under the MIT License <http://opensource.org/licenses/MIT>. Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
|
||||||
* stb_image : Public domain.
|
* stb_image : Public domain.
|
||||||
* catch : Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. Distributed under the Boost Software License, Version 1.0.
|
* catch : Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* RapidJSON : Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. http://rapidjson.org/
|
||||||
|
* dlib(uridecode, uriencode) : Copyright (C) 2003 Davis E. King Boost Software License 1.0. http://dlib.net/dlib/server/server_http.cpp.html
|
||||||
|
|||||||
1
examples/basic/.gitignore
vendored
1
examples/basic/.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
.vs
|
.vs
|
||||||
Debug
|
Debug
|
||||||
|
Release
|
||||||
x64
|
x64
|
||||||
packages
|
packages
|
||||||
|
|
||||||
|
|||||||
@@ -19,3 +19,7 @@ $ make
|
|||||||
Plese use solution file located at `basic` folder.
|
Plese use solution file located at `basic` folder.
|
||||||
|
|
||||||
|
|
||||||
|
## Limitation
|
||||||
|
|
||||||
|
There are so many limitations in this example(e.g. no PBR shader. the shader only shows texture of textures[0] if available).
|
||||||
|
|
||||||
|
|||||||
@@ -22,32 +22,32 @@
|
|||||||
<VCProjectVersion>15.0</VCProjectVersion>
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
<ProjectGuid>{0589AC44-0CF3-40D8-8D89-68393CFD40F3}</ProjectGuid>
|
<ProjectGuid>{0589AC44-0CF3-40D8-8D89-68393CFD40F3}</ProjectGuid>
|
||||||
<RootNamespace>basic</RootNamespace>
|
<RootNamespace>basic</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,334 +1,381 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include "shaders.h"
|
#include "shaders.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
#define TINYGLTF_IMPLEMENTATION
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#define TINYGLTF_NOEXCEPTION
|
#define TINYGLTF_NOEXCEPTION
|
||||||
#define JSON_NOEXCEPTION
|
#define JSON_NOEXCEPTION
|
||||||
#include "../../tiny_gltf.h"
|
#include "../../tiny_gltf.h"
|
||||||
|
|
||||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||||
|
|
||||||
bool loadModel(tinygltf::Model &model, const char *filename) {
|
bool loadModel(tinygltf::Model &model, const char *filename) {
|
||||||
tinygltf::TinyGLTF loader;
|
tinygltf::TinyGLTF loader;
|
||||||
std::string err;
|
std::string err;
|
||||||
std::string warn;
|
std::string warn;
|
||||||
|
|
||||||
bool res = loader.LoadASCIIFromFile(&model, &err, &warn, filename);
|
bool res = loader.LoadASCIIFromFile(&model, &err, &warn, filename);
|
||||||
if (!warn.empty()) {
|
if (!warn.empty()) {
|
||||||
std::cout << "WARN: " << warn << std::endl;
|
std::cout << "WARN: " << warn << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!err.empty()) {
|
if (!err.empty()) {
|
||||||
std::cout << "ERR: " << err << std::endl;
|
std::cout << "ERR: " << err << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
std::cout << "Failed to load glTF: " << filename << std::endl;
|
std::cout << "Failed to load glTF: " << filename << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << "Loaded glTF: " << filename << std::endl;
|
std::cout << "Loaded glTF: " << filename << std::endl;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
|
std::map<int, GLuint> 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
|
||||||
std::cout << "WARN: bufferView.target is zero" << std::endl;
|
std::cout << "WARN: bufferView.target is zero" << std::endl;
|
||||||
continue; // Unsupported bufferView.
|
continue; // Unsupported bufferView.
|
||||||
/*
|
/*
|
||||||
From spec2.0 readme:
|
From spec2.0 readme:
|
||||||
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
|
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
|
||||||
... drawArrays function should be used with a count equal to
|
... drawArrays function should be used with a count equal to
|
||||||
the count property of any of the accessors referenced by the attributes
|
the count property of any of the accessors referenced by the
|
||||||
property (they are all equal for a given primitive).
|
attributes property (they are all equal for a given
|
||||||
*/
|
primitive).
|
||||||
}
|
*/
|
||||||
|
}
|
||||||
tinygltf::Buffer buffer = model.buffers[bufferView.buffer];
|
|
||||||
std::cout << "bufferview.target " << bufferView.target << std::endl;
|
const tinygltf::Buffer &buffer = model.buffers[bufferView.buffer];
|
||||||
|
std::cout << "bufferview.target " << bufferView.target << std::endl;
|
||||||
GLuint vbo;
|
|
||||||
glGenBuffers(1, &vbo);
|
GLuint vbo;
|
||||||
vbos[i] = vbo;
|
glGenBuffers(1, &vbo);
|
||||||
glBindBuffer(bufferView.target, vbo);
|
vbos[i] = vbo;
|
||||||
|
glBindBuffer(bufferView.target, vbo);
|
||||||
std::cout << "buffer.data.size = " << buffer.data.size()
|
|
||||||
<< ", bufferview.byteOffset = " << bufferView.byteOffset
|
std::cout << "buffer.data.size = " << buffer.data.size()
|
||||||
<< std::endl;
|
<< ", bufferview.byteOffset = " << bufferView.byteOffset
|
||||||
|
<< std::endl;
|
||||||
glBufferData(bufferView.target, bufferView.byteLength,
|
|
||||||
&buffer.data.at(0) + bufferView.byteOffset, GL_STATIC_DRAW);
|
glBufferData(bufferView.target, bufferView.byteLength,
|
||||||
}
|
&buffer.data.at(0) + bufferView.byteOffset, GL_STATIC_DRAW);
|
||||||
|
}
|
||||||
for (size_t i = 0; i < mesh.primitives.size(); ++i) {
|
|
||||||
tinygltf::Primitive primitive = mesh.primitives[i];
|
for (size_t i = 0; i < mesh.primitives.size(); ++i) {
|
||||||
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
|
tinygltf::Primitive primitive = mesh.primitives[i];
|
||||||
|
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
|
||||||
for (auto &attrib : primitive.attributes) {
|
|
||||||
tinygltf::Accessor accessor = model.accessors[attrib.second];
|
for (auto &attrib : primitive.attributes) {
|
||||||
int byteStride =
|
tinygltf::Accessor accessor = model.accessors[attrib.second];
|
||||||
accessor.ByteStride(model.bufferViews[accessor.bufferView]);
|
int byteStride =
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbos[accessor.bufferView]);
|
accessor.ByteStride(model.bufferViews[accessor.bufferView]);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbos[accessor.bufferView]);
|
||||||
int size = 1;
|
|
||||||
if (accessor.type != TINYGLTF_TYPE_SCALAR) {
|
int size = 1;
|
||||||
size = accessor.type;
|
if (accessor.type != TINYGLTF_TYPE_SCALAR) {
|
||||||
}
|
size = accessor.type;
|
||||||
|
}
|
||||||
int vaa = -1;
|
|
||||||
if (attrib.first.compare("POSITION") == 0) vaa = 0;
|
int vaa = -1;
|
||||||
if (attrib.first.compare("NORMAL") == 0) vaa = 1;
|
if (attrib.first.compare("POSITION") == 0) vaa = 0;
|
||||||
if (attrib.first.compare("TEXCOORD_0") == 0) vaa = 2;
|
if (attrib.first.compare("NORMAL") == 0) vaa = 1;
|
||||||
if (vaa > -1) {
|
if (attrib.first.compare("TEXCOORD_0") == 0) vaa = 2;
|
||||||
glEnableVertexAttribArray(vaa);
|
if (vaa > -1) {
|
||||||
glVertexAttribPointer(vaa, size, accessor.componentType,
|
glEnableVertexAttribArray(vaa);
|
||||||
accessor.normalized ? GL_TRUE : GL_FALSE,
|
glVertexAttribPointer(vaa, size, accessor.componentType,
|
||||||
byteStride, BUFFER_OFFSET(accessor.byteOffset));
|
accessor.normalized ? GL_TRUE : GL_FALSE,
|
||||||
} else
|
byteStride, BUFFER_OFFSET(accessor.byteOffset));
|
||||||
std::cout << "vaa missing: " << attrib.first << std::endl;
|
} else
|
||||||
}
|
std::cout << "vaa missing: " << attrib.first << std::endl;
|
||||||
|
}
|
||||||
GLuint texid;
|
|
||||||
glGenTextures(1, &texid);
|
if (model.textures.size() > 0) {
|
||||||
|
// fixme: Use material's baseColor
|
||||||
tinygltf::Texture &tex = model.textures[0];
|
tinygltf::Texture &tex = model.textures[0];
|
||||||
tinygltf::Image &image = model.images[tex.source];
|
|
||||||
|
if (tex.source > -1) {
|
||||||
glBindTexture(GL_TEXTURE_2D, texid);
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
GLuint texid;
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glGenTextures(1, &texid);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
tinygltf::Image &image = model.images[tex.source];
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texid);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0,
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
GL_RGBA, GL_UNSIGNED_BYTE, &image.image.at(0));
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
}
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
return vbos;
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
}
|
|
||||||
|
GLenum format = GL_RGBA;
|
||||||
// bind models
|
|
||||||
void bindModelNodes(std::map<int, GLuint> vbos, tinygltf::Model &model,
|
if (image.component == 1) {
|
||||||
tinygltf::Node &node) {
|
format = GL_RED;
|
||||||
bindMesh(vbos, model, model.meshes[node.mesh]);
|
} else if (image.component == 2) {
|
||||||
for (size_t i = 0; i < node.children.size(); i++) {
|
format = GL_RG;
|
||||||
bindModelNodes(vbos, model, model.nodes[node.children[i]]);
|
} else if (image.component == 3) {
|
||||||
}
|
format = GL_RGB;
|
||||||
}
|
} else {
|
||||||
GLuint bindModel(tinygltf::Model &model) {
|
// ???
|
||||||
std::map<int, GLuint> vbos;
|
}
|
||||||
GLuint vao;
|
|
||||||
glGenVertexArrays(1, &vao);
|
GLenum type = GL_UNSIGNED_BYTE;
|
||||||
glBindVertexArray(vao);
|
if (image.bits == 8) {
|
||||||
|
// ok
|
||||||
const tinygltf::Scene &scene = model.scenes[model.defaultScene];
|
} else if (image.bits == 16) {
|
||||||
for (size_t i = 0; i < scene.nodes.size(); ++i) {
|
type = GL_UNSIGNED_SHORT;
|
||||||
bindModelNodes(vbos, model, model.nodes[scene.nodes[i]]);
|
} else {
|
||||||
}
|
// ???
|
||||||
|
}
|
||||||
glBindVertexArray(0);
|
|
||||||
// cleanup vbos
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0,
|
||||||
for (size_t i = 0; i < vbos.size(); ++i) {
|
format, type, &image.image.at(0));
|
||||||
glDeleteBuffers(1, &vbos[i]);
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return vao;
|
|
||||||
}
|
return vbos;
|
||||||
|
}
|
||||||
void drawMesh(tinygltf::Model &model, tinygltf::Mesh &mesh) {
|
|
||||||
for (size_t i = 0; i < mesh.primitives.size(); ++i) {
|
// bind models
|
||||||
tinygltf::Primitive primitive = mesh.primitives[i];
|
void bindModelNodes(std::map<int, GLuint> vbos, tinygltf::Model &model,
|
||||||
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
|
tinygltf::Node &node) {
|
||||||
|
if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) {
|
||||||
glDrawElements(primitive.mode, indexAccessor.count,
|
bindMesh(vbos, model, model.meshes[node.mesh]);
|
||||||
indexAccessor.componentType,
|
}
|
||||||
BUFFER_OFFSET(indexAccessor.byteOffset));
|
|
||||||
}
|
for (size_t i = 0; i < node.children.size(); i++) {
|
||||||
}
|
assert((node.children[i] >= 0) && (node.children[i] < model.nodes.size()));
|
||||||
|
bindModelNodes(vbos, model, model.nodes[node.children[i]]);
|
||||||
// recursively draw node and children nodes of model
|
}
|
||||||
void drawModelNodes(tinygltf::Model &model, tinygltf::Node &node) {
|
}
|
||||||
drawMesh(model, model.meshes[node.mesh]);
|
GLuint bindModel(tinygltf::Model &model) {
|
||||||
for (size_t i = 0; i < node.children.size(); i++) {
|
std::map<int, GLuint> vbos;
|
||||||
drawModelNodes(model, model.nodes[node.children[i]]);
|
GLuint vao;
|
||||||
}
|
glGenVertexArrays(1, &vao);
|
||||||
}
|
glBindVertexArray(vao);
|
||||||
void drawModel(GLuint vao, tinygltf::Model &model) {
|
|
||||||
glBindVertexArray(vao);
|
const tinygltf::Scene &scene = model.scenes[model.defaultScene];
|
||||||
|
for (size_t i = 0; i < scene.nodes.size(); ++i) {
|
||||||
const tinygltf::Scene &scene = model.scenes[model.defaultScene];
|
assert((scene.nodes[i] >= 0) && (scene.nodes[i] < model.nodes.size()));
|
||||||
for (size_t i = 0; i < scene.nodes.size(); ++i) {
|
bindModelNodes(vbos, model, model.nodes[scene.nodes[i]]);
|
||||||
drawModelNodes(model, model.nodes[scene.nodes[i]]);
|
}
|
||||||
}
|
|
||||||
|
glBindVertexArray(0);
|
||||||
glBindVertexArray(0);
|
// cleanup vbos
|
||||||
}
|
for (size_t i = 0; i < vbos.size(); ++i) {
|
||||||
|
glDeleteBuffers(1, &vbos[i]);
|
||||||
void dbgModel(tinygltf::Model &model) {
|
}
|
||||||
for (auto &mesh : model.meshes) {
|
|
||||||
std::cout << "mesh : " << mesh.name << std::endl;
|
return vao;
|
||||||
for (auto &primitive : mesh.primitives) {
|
}
|
||||||
const tinygltf::Accessor &indexAccessor =
|
|
||||||
model.accessors[primitive.indices];
|
void drawMesh(tinygltf::Model &model, tinygltf::Mesh &mesh) {
|
||||||
|
for (size_t i = 0; i < mesh.primitives.size(); ++i) {
|
||||||
std::cout << "indexaccessor: count " << indexAccessor.count << ", type "
|
tinygltf::Primitive primitive = mesh.primitives[i];
|
||||||
<< indexAccessor.componentType << std::endl;
|
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
|
||||||
|
|
||||||
tinygltf::Material &mat = model.materials[primitive.material];
|
glDrawElements(primitive.mode, indexAccessor.count,
|
||||||
for (auto &mats : mat.values) {
|
indexAccessor.componentType,
|
||||||
std::cout << "mat : " << mats.first.c_str() << std::endl;
|
BUFFER_OFFSET(indexAccessor.byteOffset));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (auto &image : model.images) {
|
|
||||||
std::cout << "image name : " << image.uri << std::endl;
|
// recursively draw node and children nodes of model
|
||||||
std::cout << " size : " << image.image.size() << std::endl;
|
void drawModelNodes(tinygltf::Model &model, tinygltf::Node &node) {
|
||||||
std::cout << " w/h : " << image.width << "/" << image.height
|
if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) {
|
||||||
<< std::endl;
|
drawMesh(model, model.meshes[node.mesh]);
|
||||||
}
|
}
|
||||||
|
for (size_t i = 0; i < node.children.size(); i++) {
|
||||||
std::cout << "indices : " << primitive.indices << std::endl;
|
drawModelNodes(model, model.nodes[node.children[i]]);
|
||||||
std::cout << "mode : "
|
}
|
||||||
<< "(" << primitive.mode << ")" << std::endl;
|
}
|
||||||
|
void drawModel(GLuint vao, tinygltf::Model &model) {
|
||||||
for (auto &attrib : primitive.attributes) {
|
glBindVertexArray(vao);
|
||||||
std::cout << "attribute : " << attrib.first.c_str() << std::endl;
|
|
||||||
}
|
const tinygltf::Scene &scene = model.scenes[model.defaultScene];
|
||||||
}
|
for (size_t i = 0; i < scene.nodes.size(); ++i) {
|
||||||
}
|
drawModelNodes(model, model.nodes[scene.nodes[i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 genView(glm::vec3 pos, glm::vec3 lookat) {
|
glBindVertexArray(0);
|
||||||
// Camera matrix
|
}
|
||||||
glm::mat4 view = glm::lookAt(
|
|
||||||
pos, // Camera in World Space
|
void dbgModel(tinygltf::Model &model) {
|
||||||
lookat, // and looks at the origin
|
for (auto &mesh : model.meshes) {
|
||||||
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
|
std::cout << "mesh : " << mesh.name << std::endl;
|
||||||
);
|
for (auto &primitive : mesh.primitives) {
|
||||||
|
const tinygltf::Accessor &indexAccessor =
|
||||||
return view;
|
model.accessors[primitive.indices];
|
||||||
}
|
|
||||||
|
std::cout << "indexaccessor: count " << indexAccessor.count << ", type "
|
||||||
glm::mat4 genMVP(glm::mat4 view_mat, glm::mat4 model_mat, float fov, int w,
|
<< indexAccessor.componentType << std::endl;
|
||||||
int h) {
|
|
||||||
glm::mat4 Projection =
|
tinygltf::Material &mat = model.materials[primitive.material];
|
||||||
glm::perspective(glm::radians(fov), (float)w / (float)h, 0.01f, 1000.0f);
|
for (auto &mats : mat.values) {
|
||||||
|
std::cout << "mat : " << mats.first.c_str() << std::endl;
|
||||||
// Or, for an ortho camera :
|
}
|
||||||
// glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f);
|
|
||||||
// // In world coordinates
|
for (auto &image : model.images) {
|
||||||
|
std::cout << "image name : " << image.uri << std::endl;
|
||||||
glm::mat4 mvp = Projection * view_mat * model_mat;
|
std::cout << " size : " << image.image.size() << std::endl;
|
||||||
|
std::cout << " w/h : " << image.width << "/" << image.height
|
||||||
return mvp;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayLoop(Window &window, const std::string &filename) {
|
std::cout << "indices : " << primitive.indices << std::endl;
|
||||||
Shaders shader = Shaders();
|
std::cout << "mode : "
|
||||||
glUseProgram(shader.pid);
|
<< "(" << primitive.mode << ")" << std::endl;
|
||||||
|
|
||||||
// grab uniforms to modify
|
for (auto &attrib : primitive.attributes) {
|
||||||
GLuint MVP_u = glGetUniformLocation(shader.pid, "MVP");
|
std::cout << "attribute : " << attrib.first.c_str() << std::endl;
|
||||||
GLuint sun_position_u = glGetUniformLocation(shader.pid, "sun_position");
|
}
|
||||||
GLuint sun_color_u = glGetUniformLocation(shader.pid, "sun_color");
|
}
|
||||||
|
}
|
||||||
tinygltf::Model model;
|
}
|
||||||
if (!loadModel(model, filename.c_str())) return;
|
|
||||||
|
glm::mat4 genView(glm::vec3 pos, glm::vec3 lookat) {
|
||||||
GLuint vao = bindModel(model);
|
// Camera matrix
|
||||||
// dbgModel(model); return;
|
glm::mat4 view = glm::lookAt(
|
||||||
|
pos, // Camera in World Space
|
||||||
// Model matrix : an identity matrix (model will be at the origin)
|
lookat, // and looks at the origin
|
||||||
glm::mat4 model_mat = glm::mat4(1.0f);
|
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
|
||||||
glm::mat4 model_rot = glm::mat4(1.0f);
|
);
|
||||||
glm::vec3 model_pos = glm::vec3(-3, 0, -3);
|
|
||||||
|
return view;
|
||||||
// generate a camera view, based on eye-position and lookAt world-position
|
}
|
||||||
glm::mat4 view_mat = genView(glm::vec3(2, 2, 2), model_pos);
|
|
||||||
|
glm::mat4 genMVP(glm::mat4 view_mat, glm::mat4 model_mat, float fov, int w,
|
||||||
glm::vec3 sun_position = glm::vec3(3.0, 10.0, -5.0);
|
int h) {
|
||||||
glm::vec3 sun_color = glm::vec3(1.0);
|
glm::mat4 Projection =
|
||||||
|
glm::perspective(glm::radians(fov), (float)w / (float)h, 0.01f, 1000.0f);
|
||||||
while (!window.Close()) {
|
|
||||||
window.Resize();
|
// Or, for an ortho camera :
|
||||||
|
// glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f);
|
||||||
glClearColor(0.2, 0.2, 0.2, 1.0);
|
// // In world coordinates
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
glm::mat4 mvp = Projection * view_mat * model_mat;
|
||||||
glm::mat4 trans =
|
|
||||||
glm::translate(glm::mat4(1.0f), model_pos); // reposition model
|
return mvp;
|
||||||
model_rot = glm::rotate(model_rot, glm::radians(0.8f),
|
}
|
||||||
glm::vec3(0, 1, 0)); // rotate model on y axis
|
|
||||||
model_mat = trans * model_rot;
|
void displayLoop(Window &window, const std::string &filename) {
|
||||||
|
Shaders shader = Shaders();
|
||||||
// build a model-view-projection
|
glUseProgram(shader.pid);
|
||||||
GLint w, h;
|
|
||||||
glfwGetWindowSize(window.window, &w, &h);
|
// grab uniforms to modify
|
||||||
glm::mat4 mvp = genMVP(view_mat, model_mat, 45.0f, w, h);
|
GLuint MVP_u = glGetUniformLocation(shader.pid, "MVP");
|
||||||
glUniformMatrix4fv(MVP_u, 1, GL_FALSE, &mvp[0][0]);
|
GLuint sun_position_u = glGetUniformLocation(shader.pid, "sun_position");
|
||||||
|
GLuint sun_color_u = glGetUniformLocation(shader.pid, "sun_color");
|
||||||
glUniform3fv(sun_position_u, 1, &sun_position[0]);
|
|
||||||
glUniform3fv(sun_color_u, 1, &sun_color[0]);
|
tinygltf::Model model;
|
||||||
|
if (!loadModel(model, filename.c_str())) return;
|
||||||
drawModel(vao, model);
|
|
||||||
glfwSwapBuffers(window.window);
|
GLuint vao = bindModel(model);
|
||||||
glfwPollEvents();
|
// dbgModel(model); return;
|
||||||
}
|
|
||||||
}
|
// Model matrix : an identity matrix (model will be at the origin)
|
||||||
|
glm::mat4 model_mat = glm::mat4(1.0f);
|
||||||
int main(int argc, char **argv) {
|
glm::mat4 model_rot = glm::mat4(1.0f);
|
||||||
std::string filename = "../../models/Cube/Cube.gltf";
|
glm::vec3 model_pos = glm::vec3(-3, 0, -3);
|
||||||
|
|
||||||
if (argc > 1) {
|
// generate a camera view, based on eye-position and lookAt world-position
|
||||||
filename = argv[1];
|
glm::mat4 view_mat = genView(glm::vec3(2, 2, 20), model_pos);
|
||||||
}
|
|
||||||
|
glm::vec3 sun_position = glm::vec3(3.0, 10.0, -5.0);
|
||||||
if (!glfwInit()) return -1;
|
glm::vec3 sun_color = glm::vec3(1.0);
|
||||||
|
|
||||||
// Force create 3.3 profile.
|
while (!window.Close()) {
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
window.Resize();
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glClearColor(0.2, 0.2, 0.2, 1.0);
|
||||||
#ifdef __APPLE__
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
|
||||||
#endif
|
glm::mat4 trans =
|
||||||
|
glm::translate(glm::mat4(1.0f), model_pos); // reposition model
|
||||||
Window window = Window(800, 600, "TinyGLTF basic example");
|
model_rot = glm::rotate(model_rot, glm::radians(0.8f),
|
||||||
glfwMakeContextCurrent(window.window);
|
glm::vec3(0, 1, 0)); // rotate model on y axis
|
||||||
|
model_mat = trans * model_rot;
|
||||||
#ifdef __APPLE__
|
|
||||||
// https://stackoverflow.com/questions/50192625/openggl-segmentation-fault
|
// build a model-view-projection
|
||||||
glewExperimental = GL_TRUE;
|
GLint w, h;
|
||||||
#endif
|
glfwGetWindowSize(window.window, &w, &h);
|
||||||
|
glm::mat4 mvp = genMVP(view_mat, model_mat, 45.0f, w, h);
|
||||||
glewInit();
|
glUniformMatrix4fv(MVP_u, 1, GL_FALSE, &mvp[0][0]);
|
||||||
std::cout << glGetString(GL_RENDERER) << ", " << glGetString(GL_VERSION)
|
|
||||||
<< std::endl;
|
glUniform3fv(sun_position_u, 1, &sun_position[0]);
|
||||||
|
glUniform3fv(sun_color_u, 1, &sun_color[0]);
|
||||||
if (!GLEW_VERSION_3_3) {
|
|
||||||
std::cerr << "OpenGL 3.3 is required to execute this app." << std::endl;
|
drawModel(vao, model);
|
||||||
return EXIT_FAILURE;
|
glfwSwapBuffers(window.window);
|
||||||
}
|
glfwPollEvents();
|
||||||
|
}
|
||||||
glEnable(GL_DEPTH_TEST);
|
}
|
||||||
glDepthFunc(GL_LESS);
|
|
||||||
|
static void error_callback(int error, const char *description) {
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
(void)error;
|
||||||
glEnable(GL_BLEND);
|
fprintf(stderr, "Error: %s\n", description);
|
||||||
|
}
|
||||||
displayLoop(window, filename);
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
glfwTerminate();
|
std::string filename = "../../../models/Cube/Cube.gltf";
|
||||||
return 0;
|
|
||||||
}
|
if (argc > 1) {
|
||||||
|
filename = argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
|
if (!glfwInit()) return -1;
|
||||||
|
|
||||||
|
// Force create OpenGL 3.3
|
||||||
|
// NOTE(syoyo): Linux + NVIDIA driver segfaults for some reason? commenting out glfwWindowHint will work.
|
||||||
|
// Note (PE): On laptops with intel hd graphics card you can overcome the segfault by enabling experimental, see below (tested on lenovo thinkpad)
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
glewExperimental = GL_TRUE;
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Window window = Window(800, 600, "TinyGLTF basic example");
|
||||||
|
glfwMakeContextCurrent(window.window);
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// https://stackoverflow.com/questions/50192625/openggl-segmentation-fault
|
||||||
|
glewExperimental = GL_TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
glewInit();
|
||||||
|
std::cout << glGetString(GL_RENDERER) << ", " << glGetString(GL_VERSION)
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
if (!GLEW_VERSION_3_3) {
|
||||||
|
std::cerr << "OpenGL 3.3 is required to execute this app." << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
|
displayLoop(window, filename);
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
21
examples/common/LICENSE.lodepng
Normal file
21
examples/common/LICENSE.lodepng
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
Copyright (c) 2005-2018 Lode Vandevenne
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
|
||||||
5992
examples/common/lodepng.cpp
Normal file
5992
examples/common/lodepng.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1919
examples/common/lodepng.h
Normal file
1919
examples/common/lodepng.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
36
examples/dxview/CMakeLists.txt
Normal file
36
examples/dxview/CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
project(dxview)
|
||||||
|
|
||||||
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
|
find_package(spdlog CONFIG REQUIRED)
|
||||||
|
|
||||||
|
add_executable(dxview
|
||||||
|
src/Viewer.h
|
||||||
|
src/Viewer.cc
|
||||||
|
src/dxview.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(dxview
|
||||||
|
PRIVATE
|
||||||
|
../../
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(dxview
|
||||||
|
PRIVATE
|
||||||
|
DXVIEW_SWAP_CHAIN_BUFFER_COUNT=3
|
||||||
|
DXVIEW_RES_DIR=L"${PROJECT_SOURCE_DIR}/res"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(dxview
|
||||||
|
PRIVATE
|
||||||
|
dxgi
|
||||||
|
d3dcompiler
|
||||||
|
d3d12
|
||||||
|
glfw
|
||||||
|
spdlog::spdlog
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(dxview
|
||||||
|
PROPERTIES
|
||||||
|
CXX_STANDARD 17
|
||||||
|
)
|
||||||
37
examples/dxview/README.md
Normal file
37
examples/dxview/README.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# DirectX glTF Viewer
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This project was motivated by a lack of sample code demonstrating the graphics API agnostic nature of the glTF specification. The sample code is written using modern C++ and DirectX 12 for the client application.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* [x] DirectX 12
|
||||||
|
* [ ] Loader
|
||||||
|
* [ ] Animation
|
||||||
|
* [ ] Morph Target
|
||||||
|
* [ ] Physical Base Rendering
|
||||||
|
* [ ] Environment Map
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
* [CMake](https://github.com/Kitware/CMake)
|
||||||
|
* [Vcpkg](https://github.com/Microsoft/vcpkg)
|
||||||
|
* [GLFW](https://github.com/glfw/glfw)
|
||||||
|
* [spdlog](https://github.com/gabime/spdlog)
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
### Install dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
vcpkg install glfw3:x64-windows
|
||||||
|
vcpkg install spdlog:x64-windows
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generate Project Files
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build
|
||||||
|
cmake . -B build -DCMAKE_TOOLCHAIN_FILE=${VCPKG_DIR}/script/buildsystem/vcpkg.cmake
|
||||||
|
```
|
||||||
3
examples/dxview/res/gray.hlsl
Normal file
3
examples/dxview/res/gray.hlsl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
float4 main() : SV_Target {
|
||||||
|
return float4(0.5, 0.5, 0.5, 1.0);
|
||||||
|
}
|
||||||
52
examples/dxview/res/lighting.hlsl
Normal file
52
examples/dxview/res/lighting.hlsl
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
struct RS2PS {
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
|
||||||
|
#ifdef HAS_TEXCOORD_0
|
||||||
|
float2 texcoord_0: TEXCOORD_0;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TextureInfo {
|
||||||
|
uint textureIndex;
|
||||||
|
uint samplerIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PBRMetallicRoughness {
|
||||||
|
float4 baseColorFactor;
|
||||||
|
TextureInfo baseColorTexture;
|
||||||
|
float metallicFactor;
|
||||||
|
float roughnessFactor;
|
||||||
|
TextureInfo metallicRoughnessTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer Material : register(b2) {
|
||||||
|
PBRMetallicRoughness pbrMetallicRoughness;
|
||||||
|
};
|
||||||
|
|
||||||
|
Texture2D textures[5] : register(t0);
|
||||||
|
SamplerState samplerState[5] : register(s0);
|
||||||
|
|
||||||
|
float4 getBaseColor(float2 uv) {
|
||||||
|
float4 baseColor = pbrMetallicRoughness.baseColorFactor;
|
||||||
|
|
||||||
|
#ifdef HAS_TEXCOORD_0
|
||||||
|
TextureInfo baseColorTexture = pbrMetallicRoughness.baseColorTexture;
|
||||||
|
if (baseColorTexture.textureIndex >= 0) {
|
||||||
|
baseColor *= textures[baseColorTexture.textureIndex].Sample(samplerState[baseColorTexture.samplerIndex], uv);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return baseColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 main(RS2PS input) : SV_Target {
|
||||||
|
float2 uv = float2(0.0, 0.0);
|
||||||
|
|
||||||
|
#ifdef HAS_TEXCOORD_0
|
||||||
|
uv = input.texcoord_0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float4 color = getBaseColor(uv);
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
46
examples/dxview/res/primitive.hlsl
Normal file
46
examples/dxview/res/primitive.hlsl
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
struct IA2VS {
|
||||||
|
float3 position : POSITION;
|
||||||
|
|
||||||
|
#ifdef HAS_NORMAL
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_TANGENT
|
||||||
|
float4 tangent : TANGENT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_TEXCOORD_0
|
||||||
|
float2 texcoord_0: TEXCOORD_0;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VS2RS {
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
|
||||||
|
#ifdef HAS_TEXCOORD_0
|
||||||
|
float2 texcoord_0: TEXCOORD_0;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer Camera : register(b0) {
|
||||||
|
float4x4 V;
|
||||||
|
float4x4 P;
|
||||||
|
float4x4 VP;
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer Node : register(b1) {
|
||||||
|
float4x4 M;
|
||||||
|
};
|
||||||
|
|
||||||
|
VS2RS main(IA2VS input) {
|
||||||
|
VS2RS output;
|
||||||
|
output.position = mul(float4(input.position, 1.0), M);
|
||||||
|
output.position = mul(output.position, V);
|
||||||
|
output.position = mul(output.position, P);
|
||||||
|
|
||||||
|
#ifdef HAS_TEXCOORD_0
|
||||||
|
output.texcoord_0 = input.texcoord_0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
1292
examples/dxview/src/Viewer.cc
Normal file
1292
examples/dxview/src/Viewer.cc
Normal file
File diff suppressed because it is too large
Load Diff
130
examples/dxview/src/Viewer.h
Normal file
130
examples/dxview/src/Viewer.h
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
#ifndef DXVIEW_VIEWER_GUARD
|
||||||
|
#define DXVIEW_VIEWER_GUARD
|
||||||
|
|
||||||
|
#include <DirectXMath.h>
|
||||||
|
#include <d3d12.h>
|
||||||
|
#include <dxgi1_6.h>
|
||||||
|
#include <tiny_gltf.h>
|
||||||
|
#include <wrl.h>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
|
enum RenderPassType { RENDER_PASS_TYPE_PRESENT = 0, RENDER_PASS_TYPE_COUNT };
|
||||||
|
|
||||||
|
struct RenderTarget {
|
||||||
|
ComPtr<ID3D12Resource> pTexture;
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE viewDescriptor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TextureInfo {
|
||||||
|
int32_t textureIndex;
|
||||||
|
int32_t samplerIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PBRMetallicRoughness {
|
||||||
|
DirectX::XMFLOAT4 baseColorFactor;
|
||||||
|
TextureInfo baseColorTexture;
|
||||||
|
float metallicFactor;
|
||||||
|
float roughnessFactor;
|
||||||
|
TextureInfo metallicRoughnessTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Material {
|
||||||
|
std::string name;
|
||||||
|
D3D12_BLEND_DESC blendDesc;
|
||||||
|
D3D12_RASTERIZER_DESC rasterizerDesc;
|
||||||
|
ComPtr<ID3D12Resource> pBuffer;
|
||||||
|
void* pBufferData;
|
||||||
|
ComPtr<ID3D12DescriptorHeap> pSRVDescriptorHeap;
|
||||||
|
ComPtr<ID3D12DescriptorHeap> pSamplerDescriptorHeap;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Attribute {
|
||||||
|
std::string name;
|
||||||
|
DXGI_FORMAT format;
|
||||||
|
D3D12_VERTEX_BUFFER_VIEW vertexBufferView;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Primitive {
|
||||||
|
std::vector<Attribute> attributes;
|
||||||
|
uint32_t vertexCount;
|
||||||
|
D3D12_PRIMITIVE_TOPOLOGY primitiveTopology;
|
||||||
|
D3D12_INDEX_BUFFER_VIEW indexBufferView;
|
||||||
|
uint32_t indexCount;
|
||||||
|
Material* pMaterial;
|
||||||
|
ComPtr<ID3D12RootSignature> pRootSignature;
|
||||||
|
ComPtr<ID3D12PipelineState> pPipelineState;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Mesh {
|
||||||
|
std::string name;
|
||||||
|
std::vector<Primitive> primitives;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
DirectX::XMFLOAT4X4 M;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Camera {
|
||||||
|
DirectX::XMFLOAT4X4 V;
|
||||||
|
DirectX::XMFLOAT4X4 P;
|
||||||
|
DirectX::XMFLOAT4X4 VP;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Viewer {
|
||||||
|
public:
|
||||||
|
Viewer(HWND window, tinygltf::Model* pModel);
|
||||||
|
|
||||||
|
void update(double deltaTime);
|
||||||
|
void render(double deltaTime);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initDirectX(HWND window);
|
||||||
|
void buildRenderTargets();
|
||||||
|
void buildResources();
|
||||||
|
void buildBuffers(std::vector<ComPtr<ID3D12Resource> >* pStagingResources);
|
||||||
|
void buildImages(std::vector<ComPtr<ID3D12Resource> >* pStagingResources);
|
||||||
|
void buildSamplerDescs();
|
||||||
|
void buildMaterials();
|
||||||
|
void buildMeshes();
|
||||||
|
void buildNodes();
|
||||||
|
|
||||||
|
void drawNode(uint64_t nodeIndex);
|
||||||
|
|
||||||
|
private:
|
||||||
|
tinygltf::Model* pModel_;
|
||||||
|
ComPtr<IDXGIFactory1> pFactory_;
|
||||||
|
ComPtr<IDXGIAdapter1> pAdapter_;
|
||||||
|
ComPtr<ID3D12Device> pDevice_;
|
||||||
|
ComPtr<ID3D12CommandQueue> pDirectCommandQueue_;
|
||||||
|
UINT64 directFenceValue_;
|
||||||
|
ComPtr<ID3D12Fence> pDirectFence_;
|
||||||
|
ComPtr<ID3D12CommandQueue> pCopyCommandQueue_;
|
||||||
|
UINT64 copyFenceValue_;
|
||||||
|
ComPtr<ID3D12Fence> pCopyFence_;
|
||||||
|
ComPtr<IDXGISwapChain3> pSwapChain_;
|
||||||
|
ComPtr<ID3D12Resource> pSwapChainBuffers_[DXVIEW_SWAP_CHAIN_BUFFER_COUNT];
|
||||||
|
ComPtr<ID3D12CommandAllocator>
|
||||||
|
pDirectCommandAllocators_[DXVIEW_SWAP_CHAIN_BUFFER_COUNT];
|
||||||
|
ComPtr<ID3D12GraphicsCommandList> pDirectCommandList_;
|
||||||
|
ComPtr<ID3D12CommandAllocator> pCopyCommandAllocator_;
|
||||||
|
ComPtr<ID3D12GraphicsCommandList> pCopyCommandList_;
|
||||||
|
UINT descriptorIncrementSize_[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
|
||||||
|
ComPtr<ID3D12DescriptorHeap>
|
||||||
|
pRTVDescriptorHeaps_[DXVIEW_SWAP_CHAIN_BUFFER_COUNT];
|
||||||
|
std::vector<RenderTarget> renderTargets_[DXVIEW_SWAP_CHAIN_BUFFER_COUNT];
|
||||||
|
std::vector<ComPtr<ID3D12Resource> > pBuffers_;
|
||||||
|
std::vector<ComPtr<ID3D12Resource> > pTextures_;
|
||||||
|
std::vector<D3D12_SAMPLER_DESC> samplerDescs_;
|
||||||
|
std::vector<Material> materials_;
|
||||||
|
std::vector<Mesh> meshes_;
|
||||||
|
std::vector<ComPtr<ID3D12Resource> > pNodeBuffers_;
|
||||||
|
ComPtr<ID3D12Resource> pCameraBuffer_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
90
examples/dxview/src/dxview.cc
Normal file
90
examples/dxview/src/dxview.cc
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
|
#define STBI_MSC_SECURE_CRT
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <tiny_gltf.h>
|
||||||
|
|
||||||
|
#undef GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
#undef TINYGLTF_IMPLEMENTATION
|
||||||
|
#undef STBI_MSC_SECURE_CRT
|
||||||
|
#undef STB_IMAGE_IMPLEMENTATION
|
||||||
|
#undef STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Viewer.h"
|
||||||
|
|
||||||
|
static void onError(int error, const char* message) {
|
||||||
|
spdlog::error("[{}] {}", error, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onRender(Viewer* pViewer, double deltaTime) {
|
||||||
|
pViewer->update(deltaTime);
|
||||||
|
pViewer->render(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
tinygltf::TinyGLTF context;
|
||||||
|
|
||||||
|
tinygltf::Model model;
|
||||||
|
std::string error;
|
||||||
|
std::string warning;
|
||||||
|
if (!context.LoadASCIIFromFile(&model, &error, &warning, argv[1])) {
|
||||||
|
if (!error.empty()) {
|
||||||
|
spdlog::error("{}", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!warning.empty()) {
|
||||||
|
spdlog::warn("{}", warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWwindow* pWindow;
|
||||||
|
|
||||||
|
glfwSetErrorCallback(onError);
|
||||||
|
|
||||||
|
if (!glfwInit()) {
|
||||||
|
spdlog::error("Fail to initialize GLFW!!!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
|
|
||||||
|
pWindow = glfwCreateWindow(512, 512, "dxview", nullptr, nullptr);
|
||||||
|
if (!pWindow) {
|
||||||
|
spdlog::error("Fail to create GLFWwindow!!!");
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pViewer = std::make_unique<Viewer>(glfwGetWin32Window(pWindow), &model);
|
||||||
|
if (!pViewer) {
|
||||||
|
spdlog::error("Fail to create Viewer");
|
||||||
|
glfwDestroyWindow(pWindow);
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prevTimeStamp = glfwGetTime();
|
||||||
|
while (!glfwWindowShouldClose(pWindow)) {
|
||||||
|
auto currTimeStamp = glfwGetTime();
|
||||||
|
|
||||||
|
onRender(pViewer.get(), currTimeStamp - prevTimeStamp);
|
||||||
|
prevTimeStamp = currTimeStamp;
|
||||||
|
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwDestroyWindow(pWindow);
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
@@ -4,9 +4,10 @@ project(gltfutil)
|
|||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
include_directories(../../)
|
include_directories(../../)
|
||||||
|
include_directories(../common/)
|
||||||
|
|
||||||
file(GLOB gltfutil_sources *.cc *.h)
|
file(GLOB gltfutil_sources *.cc *.h)
|
||||||
add_executable(gltfutil ${gltfutil_sources})
|
add_executable(gltfutil ${gltfutil_sources} ../common/lodepng.cpp)
|
||||||
|
|
||||||
install ( TARGETS
|
install ( TARGETS
|
||||||
gltfutil
|
gltfutil
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ struct configuration {
|
|||||||
cli_action action = cli_action::not_set;
|
cli_action action = cli_action::not_set;
|
||||||
texture_dumper::texture_output_format requested_format =
|
texture_dumper::texture_output_format requested_format =
|
||||||
texture_dumper::texture_output_format::not_specified;
|
texture_dumper::texture_output_format::not_specified;
|
||||||
|
bool use_exr = false;
|
||||||
|
|
||||||
bool has_output_dir;
|
bool has_output_dir;
|
||||||
bool is_valid() {
|
bool is_valid() {
|
||||||
|
|||||||
@@ -11,6 +11,9 @@
|
|||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#include "stb_image_write.h"
|
#include "stb_image_write.h"
|
||||||
|
|
||||||
|
#define TINYEXR_IMPLEMENTATION
|
||||||
|
#include "tinyexr.h"
|
||||||
|
|
||||||
namespace gltfutil {
|
namespace gltfutil {
|
||||||
int usage(int ret = 0) {
|
int usage(int ret = 0) {
|
||||||
using std::cout;
|
using std::cout;
|
||||||
@@ -20,8 +23,9 @@ int usage(int ret = 0) {
|
|||||||
"[path to output directory])\n\n"
|
"[path to output directory])\n\n"
|
||||||
//<< "\t\t -i: start in interactive mode\n"
|
//<< "\t\t -i: start in interactive mode\n"
|
||||||
<< "\t\t -d: dump enclosed content (image assets)\n"
|
<< "\t\t -d: dump enclosed content (image assets)\n"
|
||||||
<< "\t\t -f: file format for image output"
|
<< "\t\t -f: file format for image output\n"
|
||||||
<< "\t\t -o: ouptput directory path"
|
<< "\t\t -o: ouptput directory path\n"
|
||||||
|
<< "\t\t -e: Use OpenEXR format for 16bit image\n"
|
||||||
<< "\t\t -h: print this help\n";
|
<< "\t\t -h: print this help\n";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -44,6 +48,9 @@ int parse_args(int argc, char** argv) {
|
|||||||
config.mode = ui_mode::cli;
|
config.mode = ui_mode::cli;
|
||||||
config.action = cli_action::dump;
|
config.action = cli_action::dump;
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
config.use_exr = true;
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
config.mode = ui_mode::interactive;
|
config.mode = ui_mode::interactive;
|
||||||
break;
|
break;
|
||||||
@@ -97,6 +104,11 @@ int parse_args(int argc, char** argv) {
|
|||||||
|
|
||||||
case cli_action::dump: {
|
case cli_action::dump: {
|
||||||
texture_dumper dumper(model);
|
texture_dumper dumper(model);
|
||||||
|
|
||||||
|
if (config.use_exr) {
|
||||||
|
dumper.set_use_exr(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (config.requested_format !=
|
if (config.requested_format !=
|
||||||
texture_dumper::texture_output_format::not_specified)
|
texture_dumper::texture_output_format::not_specified)
|
||||||
dumper.set_output_format(config.requested_format);
|
dumper.set_output_format(config.requested_format);
|
||||||
|
|||||||
@@ -1,15 +1,84 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "stb_image_write.h"
|
#include "stb_image_write.h"
|
||||||
#include "texture_dumper.h"
|
#include "texture_dumper.h"
|
||||||
|
|
||||||
|
#include "lodepng.h" // ../common
|
||||||
|
|
||||||
|
#include "tinyexr.h"
|
||||||
|
|
||||||
#include <tiny_gltf.h>
|
#include <tiny_gltf.h>
|
||||||
|
|
||||||
using namespace gltfutil;
|
using namespace gltfutil;
|
||||||
using namespace tinygltf;
|
using namespace tinygltf;
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
|
||||||
|
static LodePNGColorType GetLodePNGColorType(int channels) {
|
||||||
|
if (channels == 1) {
|
||||||
|
return LodePNGColorType::LCT_GREY;
|
||||||
|
} else if (channels == 2) {
|
||||||
|
return LodePNGColorType::LCT_GREY_ALPHA;
|
||||||
|
} else if (channels == 3) {
|
||||||
|
return LodePNGColorType::LCT_RGB;
|
||||||
|
} else if (channels == 4) {
|
||||||
|
return LodePNGColorType::LCT_RGBA;
|
||||||
|
} else {
|
||||||
|
std::cerr << "??? unsupported channels " << channels << "\n";
|
||||||
|
return LodePNGColorType::LCT_RGB; // FIXME(syoyo): Raise error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ToBigEndian(std::vector<uint8_t>* image) {
|
||||||
|
|
||||||
|
assert(image->size() % 2 == 0);
|
||||||
|
|
||||||
|
union {
|
||||||
|
unsigned int i;
|
||||||
|
char c[4];
|
||||||
|
} bint = {0x01020304};
|
||||||
|
|
||||||
|
bool is_big_endian = (bint.c[0] == 1);
|
||||||
|
|
||||||
|
if (is_big_endian) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t *ptr = reinterpret_cast<uint16_t *>(image->data());
|
||||||
|
size_t n = image->size() / 2;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
ptr[i] = ((0xFF00 & ptr[i]) >> 8) | ((0x00FF & ptr[i]) << 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Save16bitImageAsEXR(const std::string& filename,
|
||||||
|
const tinygltf::Image& image) {
|
||||||
|
assert(image.bits == 16);
|
||||||
|
|
||||||
|
std::vector<float> buf(image.width * image.height * image.component);
|
||||||
|
|
||||||
|
// widen to float image.
|
||||||
|
// Store as is(i.e, pixel value range is [0.0, 65535.0])
|
||||||
|
const unsigned short* ptr =
|
||||||
|
reinterpret_cast<const unsigned short*>(image.image.data());
|
||||||
|
for (size_t i = 0; i < image.width * image.height * image.component; i++) {
|
||||||
|
buf[i] = float(ptr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* err = nullptr;
|
||||||
|
int ret = SaveEXR(buf.data(), image.width, image.height, image.component,
|
||||||
|
/* save_as_fp16 */ 0, filename.c_str(), &err);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
std::cerr << "EXR err: " << err << std::endl;
|
||||||
|
FreeEXRErrorMessage(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret == TINYEXR_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
texture_dumper::texture_dumper(const Model& input)
|
texture_dumper::texture_dumper(const Model& input)
|
||||||
: model(input), configured_format(texture_output_format::png) {
|
: model(input), configured_format(texture_output_format::png) {
|
||||||
cout << "Texture dumper\n";
|
cout << "Texture dumper\n";
|
||||||
@@ -26,26 +95,58 @@ void texture_dumper::dump_to_folder(const std::string& path) {
|
|||||||
cout << "image name is: \"" << image.name << "\"\n";
|
cout << "image name is: \"" << image.name << "\"\n";
|
||||||
cout << "image size is: " << image.width << 'x' << image.height << '\n';
|
cout << "image size is: " << image.width << 'x' << image.height << '\n';
|
||||||
cout << "pixel channel count :" << image.component << '\n';
|
cout << "pixel channel count :" << image.component << '\n';
|
||||||
std::string name = image.name.empty() ? std::to_string(index) : image.name;
|
cout << "pixel bit depth :" << image.bits << '\n';
|
||||||
|
std::string basename =
|
||||||
|
image.name.empty() ? std::to_string(index) : image.name;
|
||||||
|
|
||||||
|
unsigned char* bytes_to_write =
|
||||||
|
const_cast<unsigned char*>(image.image.data());
|
||||||
|
|
||||||
|
std::string filename;
|
||||||
switch (configured_format) {
|
switch (configured_format) {
|
||||||
case texture_output_format::png:
|
case texture_output_format::png:
|
||||||
name = path + "/" + name + ".png";
|
filename = path + "/" + basename + ".png";
|
||||||
std::cout << "Image will be written to " << name << '\n';
|
|
||||||
stbi_write_png(name.c_str(), image.width, image.height, image.component,
|
if (this->use_exr) {
|
||||||
image.image.data(), 0);
|
if (image.pixel_type == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
|
||||||
|
filename = path + "/" + basename + ".exr";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Image will be written to " << filename << '\n';
|
||||||
|
|
||||||
|
if (image.pixel_type == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
|
||||||
|
if (this->use_exr) {
|
||||||
|
bool ret = Save16bitImageAsEXR(filename, image);
|
||||||
|
assert(ret);
|
||||||
|
} else {
|
||||||
|
// Use lodepng to save 16bit PNG.
|
||||||
|
// NOTE(syoyo): `loadpng::encode` requires image data must be stored in big endian.
|
||||||
|
std::vector<uint8_t> tmp = image.image; // copy
|
||||||
|
ToBigEndian(&tmp);
|
||||||
|
|
||||||
|
unsigned ret = lodepng::encode(
|
||||||
|
filename, tmp.data(), image.width, image.height,
|
||||||
|
GetLodePNGColorType(image.component), /* bits */ 16);
|
||||||
|
assert(ret == 0); // 0 = no err.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO(syoyo): check status
|
||||||
|
stbi_write_png(filename.c_str(), image.width, image.height,
|
||||||
|
image.component, bytes_to_write, 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case texture_output_format::bmp:
|
case texture_output_format::bmp:
|
||||||
std::cout << "Image will be written to " << name << '\n';
|
filename = path + "/" + basename + ".bmp";
|
||||||
name = path + "/" + name + ".bmp";
|
std::cout << "Image will be written to " << filename << '\n';
|
||||||
stbi_write_bmp(name.c_str(), image.width, image.height, image.component,
|
stbi_write_bmp(filename.c_str(), image.width, image.height,
|
||||||
image.image.data());
|
image.component, bytes_to_write);
|
||||||
break;
|
break;
|
||||||
case texture_output_format::tga:
|
case texture_output_format::tga:
|
||||||
std::cout << "Image will be written to " << name << '\n';
|
filename = path + "/" + basename + ".tga";
|
||||||
name = path + "/" + name + ".tga";
|
std::cout << "Image will be written to " << filename << '\n';
|
||||||
stbi_write_tga(name.c_str(), image.width, image.height, image.component,
|
stbi_write_tga(filename.c_str(), image.width, image.height,
|
||||||
image.image.data());
|
image.component, bytes_to_write);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,15 @@ class texture_dumper {
|
|||||||
private:
|
private:
|
||||||
const tinygltf::Model& model;
|
const tinygltf::Model& model;
|
||||||
texture_output_format configured_format;
|
texture_output_format configured_format;
|
||||||
|
bool use_exr = false; // Use EXR for 16bit image?
|
||||||
|
|
||||||
public:
|
public:
|
||||||
texture_dumper(const tinygltf::Model& inputModel);
|
texture_dumper(const tinygltf::Model& inputModel);
|
||||||
void dump_to_folder(const std::string& path = "./");
|
void dump_to_folder(const std::string& path = "./");
|
||||||
void set_output_format(texture_output_format format);
|
void set_output_format(texture_output_format format);
|
||||||
|
void set_use_exr(const bool value) {
|
||||||
|
use_exr = value;
|
||||||
|
}
|
||||||
|
|
||||||
static texture_output_format get_fromat_from_string(const std::string& str);
|
static texture_output_format get_fromat_from_string(const std::string& str);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
#include "tiny_gltf.h"
|
#include "tiny_gltf.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||||
|
|
||||||
#define CheckGLErrors(desc) \
|
#define CheckGLErrors(desc) \
|
||||||
@@ -55,7 +54,9 @@ float eye[3], lookat[3], up[3];
|
|||||||
|
|
||||||
GLFWwindow *window;
|
GLFWwindow *window;
|
||||||
|
|
||||||
typedef struct { GLuint vb; } GLBufferState;
|
typedef struct {
|
||||||
|
GLuint vb;
|
||||||
|
} GLBufferState;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
std::vector<GLuint> diffuseTex; // for each primitive in mesh
|
std::vector<GLuint> diffuseTex; // for each primitive in mesh
|
||||||
@@ -254,6 +255,26 @@ void motionFunc(GLFWwindow *window, double mouse_x, double mouse_y) {
|
|||||||
prevMouseY = mouse_y;
|
prevMouseY = mouse_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t ComponentTypeByteSize(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_BYTE:
|
||||||
|
return sizeof(char);
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_SHORT:
|
||||||
|
return sizeof(short);
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_INT:
|
||||||
|
return sizeof(int);
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_FLOAT:
|
||||||
|
return sizeof(float);
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_DOUBLE:
|
||||||
|
return sizeof(double);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
|
static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
|
||||||
// Buffer
|
// Buffer
|
||||||
{
|
{
|
||||||
@@ -264,14 +285,117 @@ static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
|
|||||||
continue; // Unsupported bufferView.
|
continue; // Unsupported bufferView.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sparse_accessor = -1;
|
||||||
|
for (size_t a_i = 0; a_i < model.accessors.size(); ++a_i) {
|
||||||
|
const auto &accessor = model.accessors[a_i];
|
||||||
|
if (accessor.bufferView == i) {
|
||||||
|
std::cout << i << " is used by accessor " << a_i << std::endl;
|
||||||
|
if (accessor.sparse.isSparse) {
|
||||||
|
std::cout
|
||||||
|
<< "WARN: this bufferView has at least one sparse accessor to "
|
||||||
|
"it. We are going to load the data as patched by this "
|
||||||
|
"sparse accessor, not the original data"
|
||||||
|
<< std::endl;
|
||||||
|
sparse_accessor = a_i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const tinygltf::Buffer &buffer = model.buffers[bufferView.buffer];
|
const tinygltf::Buffer &buffer = model.buffers[bufferView.buffer];
|
||||||
GLBufferState state;
|
GLBufferState state;
|
||||||
glGenBuffers(1, &state.vb);
|
glGenBuffers(1, &state.vb);
|
||||||
glBindBuffer(bufferView.target, state.vb);
|
glBindBuffer(bufferView.target, state.vb);
|
||||||
std::cout << "buffer.size= " << buffer.data.size()
|
std::cout << "buffer.size= " << buffer.data.size()
|
||||||
<< ", byteOffset = " << bufferView.byteOffset << std::endl;
|
<< ", byteOffset = " << bufferView.byteOffset << std::endl;
|
||||||
glBufferData(bufferView.target, bufferView.byteLength,
|
|
||||||
&buffer.data.at(0) + bufferView.byteOffset, GL_STATIC_DRAW);
|
if (sparse_accessor < 0)
|
||||||
|
glBufferData(bufferView.target, bufferView.byteLength,
|
||||||
|
&buffer.data.at(0) + bufferView.byteOffset,
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
else {
|
||||||
|
const auto accessor = model.accessors[sparse_accessor];
|
||||||
|
// copy the buffer to a temporary one for sparse patching
|
||||||
|
unsigned char *tmp_buffer = new unsigned char[bufferView.byteLength];
|
||||||
|
memcpy(tmp_buffer, buffer.data.data() + bufferView.byteOffset,
|
||||||
|
bufferView.byteLength);
|
||||||
|
|
||||||
|
const size_t size_of_object_in_buffer =
|
||||||
|
ComponentTypeByteSize(accessor.componentType);
|
||||||
|
const size_t size_of_sparse_indices =
|
||||||
|
ComponentTypeByteSize(accessor.sparse.indices.componentType);
|
||||||
|
|
||||||
|
const auto &indices_buffer_view =
|
||||||
|
model.bufferViews[accessor.sparse.indices.bufferView];
|
||||||
|
const auto &indices_buffer = model.buffers[indices_buffer_view.buffer];
|
||||||
|
|
||||||
|
const auto &values_buffer_view =
|
||||||
|
model.bufferViews[accessor.sparse.values.bufferView];
|
||||||
|
const auto &values_buffer = model.buffers[values_buffer_view.buffer];
|
||||||
|
|
||||||
|
for (size_t sparse_index = 0; sparse_index < accessor.sparse.count;
|
||||||
|
++sparse_index) {
|
||||||
|
int index = 0;
|
||||||
|
// std::cout << "accessor.sparse.indices.componentType = " <<
|
||||||
|
// accessor.sparse.indices.componentType << std::endl;
|
||||||
|
switch (accessor.sparse.indices.componentType) {
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_BYTE:
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
|
||||||
|
index = (int)*(
|
||||||
|
unsigned char *)(indices_buffer.data.data() +
|
||||||
|
indices_buffer_view.byteOffset +
|
||||||
|
accessor.sparse.indices.byteOffset +
|
||||||
|
(sparse_index * size_of_sparse_indices));
|
||||||
|
break;
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_SHORT:
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
|
||||||
|
index = (int)*(
|
||||||
|
unsigned short *)(indices_buffer.data.data() +
|
||||||
|
indices_buffer_view.byteOffset +
|
||||||
|
accessor.sparse.indices.byteOffset +
|
||||||
|
(sparse_index * size_of_sparse_indices));
|
||||||
|
break;
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_INT:
|
||||||
|
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
|
||||||
|
index = (int)*(
|
||||||
|
unsigned int *)(indices_buffer.data.data() +
|
||||||
|
indices_buffer_view.byteOffset +
|
||||||
|
accessor.sparse.indices.byteOffset +
|
||||||
|
(sparse_index * size_of_sparse_indices));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::cout << "updating sparse data at index : " << index
|
||||||
|
<< std::endl;
|
||||||
|
// index is now the target of the sparse index to patch in
|
||||||
|
const unsigned char *read_from =
|
||||||
|
values_buffer.data.data() +
|
||||||
|
(values_buffer_view.byteOffset +
|
||||||
|
accessor.sparse.values.byteOffset) +
|
||||||
|
(sparse_index * (size_of_object_in_buffer * accessor.type));
|
||||||
|
|
||||||
|
/*
|
||||||
|
std::cout << ((float*)read_from)[0] << "\n";
|
||||||
|
std::cout << ((float*)read_from)[1] << "\n";
|
||||||
|
std::cout << ((float*)read_from)[2] << "\n";
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char *write_to =
|
||||||
|
tmp_buffer + index * (size_of_object_in_buffer * accessor.type);
|
||||||
|
|
||||||
|
memcpy(write_to, read_from, size_of_object_in_buffer * accessor.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug:
|
||||||
|
/*for(size_t p = 0; p < bufferView.byteLength/sizeof(float); p++)
|
||||||
|
{
|
||||||
|
float* b = (float*)tmp_buffer;
|
||||||
|
std::cout << "modified_buffer [" << p << "] = " << b[p] << '\n';
|
||||||
|
}*/
|
||||||
|
|
||||||
|
glBufferData(bufferView.target, bufferView.byteLength, tmp_buffer,
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
delete[] tmp_buffer;
|
||||||
|
}
|
||||||
glBindBuffer(bufferView.target, 0);
|
glBindBuffer(bufferView.target, 0);
|
||||||
|
|
||||||
gBufferState[i] = state;
|
gBufferState[i] = state;
|
||||||
@@ -279,55 +403,55 @@ static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // TODO(syoyo): Implement
|
#if 0 // TODO(syoyo): Implement
|
||||||
// Texture
|
// Texture
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < model.meshes.size(); i++) {
|
for (size_t i = 0; i < model.meshes.size(); i++) {
|
||||||
const tinygltf::Mesh &mesh = model.meshes[i];
|
const tinygltf::Mesh &mesh = model.meshes[i];
|
||||||
|
|
||||||
gMeshState[mesh.name].diffuseTex.resize(mesh.primitives.size());
|
gMeshState[mesh.name].diffuseTex.resize(mesh.primitives.size());
|
||||||
for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
|
for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
|
||||||
const tinygltf::Primitive &primitive = mesh.primitives[primId];
|
const tinygltf::Primitive &primitive = mesh.primitives[primId];
|
||||||
|
|
||||||
gMeshState[mesh.name].diffuseTex[primId] = 0;
|
gMeshState[mesh.name].diffuseTex[primId] = 0;
|
||||||
|
|
||||||
if (primitive.material < 0) {
|
if (primitive.material < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tinygltf::Material &mat = model.materials[primitive.material];
|
tinygltf::Material &mat = model.materials[primitive.material];
|
||||||
// printf("material.name = %s\n", mat.name.c_str());
|
// printf("material.name = %s\n", mat.name.c_str());
|
||||||
if (mat.values.find("diffuse") != mat.values.end()) {
|
if (mat.values.find("diffuse") != mat.values.end()) {
|
||||||
std::string diffuseTexName = mat.values["diffuse"].string_value;
|
std::string diffuseTexName = mat.values["diffuse"].string_value;
|
||||||
if (model.textures.find(diffuseTexName) != model.textures.end()) {
|
if (model.textures.find(diffuseTexName) != model.textures.end()) {
|
||||||
tinygltf::Texture &tex = model.textures[diffuseTexName];
|
tinygltf::Texture &tex = model.textures[diffuseTexName];
|
||||||
if (scene.images.find(tex.source) != model.images.end()) {
|
if (scene.images.find(tex.source) != model.images.end()) {
|
||||||
tinygltf::Image &image = model.images[tex.source];
|
tinygltf::Image &image = model.images[tex.source];
|
||||||
GLuint texId;
|
GLuint texId;
|
||||||
glGenTextures(1, &texId);
|
glGenTextures(1, &texId);
|
||||||
glBindTexture(tex.target, texId);
|
glBindTexture(tex.target, texId);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
// Ignore Texture.fomat.
|
// Ignore Texture.fomat.
|
||||||
GLenum format = GL_RGBA;
|
GLenum format = GL_RGBA;
|
||||||
if (image.component == 3) {
|
if (image.component == 3) {
|
||||||
format = GL_RGB;
|
format = GL_RGB;
|
||||||
}
|
}
|
||||||
glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
|
glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
|
||||||
image.height, 0, format, tex.type,
|
image.height, 0, format, tex.type,
|
||||||
&image.image.at(0));
|
&image.image.at(0));
|
||||||
|
|
||||||
CheckErrors("texImage2D");
|
CheckErrors("texImage2D");
|
||||||
glBindTexture(tex.target, 0);
|
glBindTexture(tex.target, 0);
|
||||||
|
|
||||||
printf("TexId = %d\n", texId);
|
printf("TexId = %d\n", texId);
|
||||||
gMeshState[mesh.name].diffuseTex[primId] = texId;
|
gMeshState[mesh.name].diffuseTex[primId] = texId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glUseProgram(progId);
|
glUseProgram(progId);
|
||||||
@@ -348,164 +472,164 @@ static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
|
|||||||
#if 0 // TODO(syoyo): Implement
|
#if 0 // TODO(syoyo): Implement
|
||||||
// Setup curves geometry extension
|
// Setup curves geometry extension
|
||||||
static void SetupCurvesState(tinygltf::Scene &scene, GLuint progId) {
|
static void SetupCurvesState(tinygltf::Scene &scene, GLuint progId) {
|
||||||
// Find curves primitive.
|
// Find curves primitive.
|
||||||
{
|
{
|
||||||
std::map<std::string, tinygltf::Mesh>::const_iterator it(
|
std::map<std::string, tinygltf::Mesh>::const_iterator it(
|
||||||
scene.meshes.begin());
|
scene.meshes.begin());
|
||||||
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(
|
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(
|
||||||
scene.meshes.end());
|
scene.meshes.end());
|
||||||
|
|
||||||
for (; it != itEnd; it++) {
|
for (; it != itEnd; it++) {
|
||||||
const tinygltf::Mesh &mesh = it->second;
|
const tinygltf::Mesh &mesh = it->second;
|
||||||
|
|
||||||
// Currently we only support one primitive per mesh.
|
// Currently we only support one primitive per mesh.
|
||||||
if (mesh.primitives.size() > 1) {
|
if (mesh.primitives.size() > 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
|
for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
|
||||||
const tinygltf::Primitive &primitive = mesh.primitives[primId];
|
const tinygltf::Primitive &primitive = mesh.primitives[primId];
|
||||||
|
|
||||||
gMeshState[mesh.name].diffuseTex[primId] = 0;
|
gMeshState[mesh.name].diffuseTex[primId] = 0;
|
||||||
|
|
||||||
if (primitive.material.empty()) {
|
if (primitive.material.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_curves = false;
|
bool has_curves = false;
|
||||||
if (primitive.extras.IsObject()) {
|
if (primitive.extras.IsObject()) {
|
||||||
if (primitive.extras.Has("ext_mode")) {
|
if (primitive.extras.Has("ext_mode")) {
|
||||||
const tinygltf::Value::Object &o =
|
const tinygltf::Value::Object &o =
|
||||||
primitive.extras.Get<tinygltf::Value::Object>();
|
primitive.extras.Get<tinygltf::Value::Object>();
|
||||||
const tinygltf::Value &ext_mode = o.find("ext_mode")->second;
|
const tinygltf::Value &ext_mode = o.find("ext_mode")->second;
|
||||||
|
|
||||||
if (ext_mode.IsString()) {
|
if (ext_mode.IsString()) {
|
||||||
const std::string &str = ext_mode.Get<std::string>();
|
const std::string &str = ext_mode.Get<std::string>();
|
||||||
if (str.compare("curves") == 0) {
|
if (str.compare("curves") == 0) {
|
||||||
has_curves = true;
|
has_curves = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_curves) {
|
if (!has_curves) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct curves buffer
|
// Construct curves buffer
|
||||||
const tinygltf::Accessor &vtx_accessor =
|
const tinygltf::Accessor &vtx_accessor =
|
||||||
scene.accessors[primitive.attributes.find("POSITION")->second];
|
scene.accessors[primitive.attributes.find("POSITION")->second];
|
||||||
const tinygltf::Accessor &nverts_accessor =
|
const tinygltf::Accessor &nverts_accessor =
|
||||||
scene.accessors[primitive.attributes.find("NVERTS")->second];
|
scene.accessors[primitive.attributes.find("NVERTS")->second];
|
||||||
const tinygltf::BufferView &vtx_bufferView =
|
const tinygltf::BufferView &vtx_bufferView =
|
||||||
scene.bufferViews[vtx_accessor.bufferView];
|
scene.bufferViews[vtx_accessor.bufferView];
|
||||||
const tinygltf::BufferView &nverts_bufferView =
|
const tinygltf::BufferView &nverts_bufferView =
|
||||||
scene.bufferViews[nverts_accessor.bufferView];
|
scene.bufferViews[nverts_accessor.bufferView];
|
||||||
const tinygltf::Buffer &vtx_buffer =
|
const tinygltf::Buffer &vtx_buffer =
|
||||||
scene.buffers[vtx_bufferView.buffer];
|
scene.buffers[vtx_bufferView.buffer];
|
||||||
const tinygltf::Buffer &nverts_buffer =
|
const tinygltf::Buffer &nverts_buffer =
|
||||||
scene.buffers[nverts_bufferView.buffer];
|
scene.buffers[nverts_bufferView.buffer];
|
||||||
|
|
||||||
// std::cout << "vtx_bufferView = " << vtx_accessor.bufferView <<
|
// std::cout << "vtx_bufferView = " << vtx_accessor.bufferView <<
|
||||||
// std::endl;
|
// std::endl;
|
||||||
// std::cout << "nverts_bufferView = " << nverts_accessor.bufferView <<
|
// std::cout << "nverts_bufferView = " << nverts_accessor.bufferView <<
|
||||||
// std::endl;
|
// std::endl;
|
||||||
// std::cout << "vtx_buffer.size = " << vtx_buffer.data.size() <<
|
// std::cout << "vtx_buffer.size = " << vtx_buffer.data.size() <<
|
||||||
// std::endl;
|
// std::endl;
|
||||||
// std::cout << "nverts_buffer.size = " << nverts_buffer.data.size() <<
|
// std::cout << "nverts_buffer.size = " << nverts_buffer.data.size() <<
|
||||||
// std::endl;
|
// std::endl;
|
||||||
|
|
||||||
const int *nverts =
|
const int *nverts =
|
||||||
reinterpret_cast<const int *>(nverts_buffer.data.data());
|
reinterpret_cast<const int *>(nverts_buffer.data.data());
|
||||||
const float *vtx =
|
const float *vtx =
|
||||||
reinterpret_cast<const float *>(vtx_buffer.data.data());
|
reinterpret_cast<const float *>(vtx_buffer.data.data());
|
||||||
|
|
||||||
// Convert to GL_LINES data.
|
// Convert to GL_LINES data.
|
||||||
std::vector<float> line_pts;
|
std::vector<float> line_pts;
|
||||||
size_t vtx_offset = 0;
|
size_t vtx_offset = 0;
|
||||||
for (int k = 0; k < static_cast<int>(nverts_accessor.count); k++) {
|
for (int k = 0; k < static_cast<int>(nverts_accessor.count); k++) {
|
||||||
for (int n = 0; n < nverts[k] - 1; n++) {
|
for (int n = 0; n < nverts[k] - 1; n++) {
|
||||||
|
|
||||||
line_pts.push_back(vtx[3 * (vtx_offset + n) + 0]);
|
line_pts.push_back(vtx[3 * (vtx_offset + n) + 0]);
|
||||||
line_pts.push_back(vtx[3 * (vtx_offset + n) + 1]);
|
line_pts.push_back(vtx[3 * (vtx_offset + n) + 1]);
|
||||||
line_pts.push_back(vtx[3 * (vtx_offset + n) + 2]);
|
line_pts.push_back(vtx[3 * (vtx_offset + n) + 2]);
|
||||||
|
|
||||||
line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 0]);
|
line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 0]);
|
||||||
line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 1]);
|
line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 1]);
|
||||||
line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 2]);
|
line_pts.push_back(vtx[3 * (vtx_offset + n + 1) + 2]);
|
||||||
|
|
||||||
// std::cout << "p0 " << vtx[3 * (vtx_offset + n) + 0] << ", "
|
// std::cout << "p0 " << vtx[3 * (vtx_offset + n) + 0] << ", "
|
||||||
// << vtx[3 * (vtx_offset + n) + 1] << ", "
|
// << vtx[3 * (vtx_offset + n) + 1] << ", "
|
||||||
// << vtx[3 * (vtx_offset + n) + 2] << std::endl;
|
// << vtx[3 * (vtx_offset + n) + 2] << std::endl;
|
||||||
|
|
||||||
// std::cout << "p1 " << vtx[3 * (vtx_offset + n+1) + 0] << ", "
|
// std::cout << "p1 " << vtx[3 * (vtx_offset + n+1) + 0] << ", "
|
||||||
// << vtx[3 * (vtx_offset + n+1) + 1] << ", "
|
// << vtx[3 * (vtx_offset + n+1) + 1] << ", "
|
||||||
// << vtx[3 * (vtx_offset + n+1) + 2] << std::endl;
|
// << vtx[3 * (vtx_offset + n+1) + 2] << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
vtx_offset += nverts[k];
|
vtx_offset += nverts[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
GLCurvesState state;
|
GLCurvesState state;
|
||||||
glGenBuffers(1, &state.vb);
|
glGenBuffers(1, &state.vb);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, state.vb);
|
glBindBuffer(GL_ARRAY_BUFFER, state.vb);
|
||||||
glBufferData(GL_ARRAY_BUFFER, line_pts.size() * sizeof(float),
|
glBufferData(GL_ARRAY_BUFFER, line_pts.size() * sizeof(float),
|
||||||
line_pts.data(), GL_STATIC_DRAW);
|
line_pts.data(), GL_STATIC_DRAW);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
state.count = line_pts.size() / 3;
|
state.count = line_pts.size() / 3;
|
||||||
gCurvesMesh[mesh.name] = state;
|
gCurvesMesh[mesh.name] = state;
|
||||||
|
|
||||||
// Material
|
// Material
|
||||||
tinygltf::Material &mat = scene.materials[primitive.material];
|
tinygltf::Material &mat = scene.materials[primitive.material];
|
||||||
// printf("material.name = %s\n", mat.name.c_str());
|
// printf("material.name = %s\n", mat.name.c_str());
|
||||||
if (mat.values.find("diffuse") != mat.values.end()) {
|
if (mat.values.find("diffuse") != mat.values.end()) {
|
||||||
std::string diffuseTexName = mat.values["diffuse"].string_value;
|
std::string diffuseTexName = mat.values["diffuse"].string_value;
|
||||||
if (scene.textures.find(diffuseTexName) != scene.textures.end()) {
|
if (scene.textures.find(diffuseTexName) != scene.textures.end()) {
|
||||||
tinygltf::Texture &tex = scene.textures[diffuseTexName];
|
tinygltf::Texture &tex = scene.textures[diffuseTexName];
|
||||||
if (scene.images.find(tex.source) != scene.images.end()) {
|
if (scene.images.find(tex.source) != scene.images.end()) {
|
||||||
tinygltf::Image &image = scene.images[tex.source];
|
tinygltf::Image &image = scene.images[tex.source];
|
||||||
GLuint texId;
|
GLuint texId;
|
||||||
glGenTextures(1, &texId);
|
glGenTextures(1, &texId);
|
||||||
glBindTexture(tex.target, texId);
|
glBindTexture(tex.target, texId);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
// Ignore Texture.fomat.
|
// Ignore Texture.fomat.
|
||||||
GLenum format = GL_RGBA;
|
GLenum format = GL_RGBA;
|
||||||
if (image.component == 3) {
|
if (image.component == 3) {
|
||||||
format = GL_RGB;
|
format = GL_RGB;
|
||||||
}
|
}
|
||||||
glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
|
glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
|
||||||
image.height, 0, format, tex.type,
|
image.height, 0, format, tex.type,
|
||||||
&image.image.at(0));
|
&image.image.at(0));
|
||||||
|
|
||||||
CheckErrors("texImage2D");
|
CheckErrors("texImage2D");
|
||||||
glBindTexture(tex.target, 0);
|
glBindTexture(tex.target, 0);
|
||||||
|
|
||||||
printf("TexId = %d\n", texId);
|
printf("TexId = %d\n", texId);
|
||||||
gMeshState[mesh.name].diffuseTex[primId] = texId;
|
gMeshState[mesh.name].diffuseTex[primId] = texId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glUseProgram(progId);
|
glUseProgram(progId);
|
||||||
GLint vtloc = glGetAttribLocation(progId, "in_vertex");
|
GLint vtloc = glGetAttribLocation(progId, "in_vertex");
|
||||||
GLint nrmloc = glGetAttribLocation(progId, "in_normal");
|
GLint nrmloc = glGetAttribLocation(progId, "in_normal");
|
||||||
GLint uvloc = glGetAttribLocation(progId, "in_texcoord");
|
GLint uvloc = glGetAttribLocation(progId, "in_texcoord");
|
||||||
|
|
||||||
GLint diffuseTexLoc = glGetUniformLocation(progId, "diffuseTex");
|
GLint diffuseTexLoc = glGetUniformLocation(progId, "diffuseTex");
|
||||||
GLint isCurvesLoc = glGetUniformLocation(progId, "uIsCurves");
|
GLint isCurvesLoc = glGetUniformLocation(progId, "uIsCurves");
|
||||||
|
|
||||||
gGLProgramState.attribs["POSITION"] = vtloc;
|
gGLProgramState.attribs["POSITION"] = vtloc;
|
||||||
gGLProgramState.attribs["NORMAL"] = nrmloc;
|
gGLProgramState.attribs["NORMAL"] = nrmloc;
|
||||||
gGLProgramState.attribs["TEXCOORD_0"] = uvloc;
|
gGLProgramState.attribs["TEXCOORD_0"] = uvloc;
|
||||||
gGLProgramState.uniforms["diffuseTex"] = diffuseTexLoc;
|
gGLProgramState.uniforms["diffuseTex"] = diffuseTexLoc;
|
||||||
gGLProgramState.uniforms["uIsCurves"] = isCurvesLoc;
|
gGLProgramState.uniforms["uIsCurves"] = isCurvesLoc;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -558,12 +682,13 @@ static void DrawMesh(tinygltf::Model &model, const tinygltf::Mesh &mesh) {
|
|||||||
(it->first.compare("TEXCOORD_0") == 0)) {
|
(it->first.compare("TEXCOORD_0") == 0)) {
|
||||||
if (gGLProgramState.attribs[it->first] >= 0) {
|
if (gGLProgramState.attribs[it->first] >= 0) {
|
||||||
// Compute byteStride from Accessor + BufferView combination.
|
// Compute byteStride from Accessor + BufferView combination.
|
||||||
int byteStride = accessor.ByteStride(model.bufferViews[accessor.bufferView]);
|
int byteStride =
|
||||||
|
accessor.ByteStride(model.bufferViews[accessor.bufferView]);
|
||||||
assert(byteStride != -1);
|
assert(byteStride != -1);
|
||||||
glVertexAttribPointer(gGLProgramState.attribs[it->first], size,
|
glVertexAttribPointer(gGLProgramState.attribs[it->first], size,
|
||||||
accessor.componentType, accessor.normalized ? GL_TRUE : GL_FALSE,
|
accessor.componentType,
|
||||||
byteStride,
|
accessor.normalized ? GL_TRUE : GL_FALSE,
|
||||||
BUFFER_OFFSET(accessor.byteOffset));
|
byteStride, BUFFER_OFFSET(accessor.byteOffset));
|
||||||
CheckErrors("vertex attrib pointer");
|
CheckErrors("vertex attrib pointer");
|
||||||
glEnableVertexAttribArray(gGLProgramState.attribs[it->first]);
|
glEnableVertexAttribArray(gGLProgramState.attribs[it->first]);
|
||||||
CheckErrors("enable vertex attrib array");
|
CheckErrors("enable vertex attrib array");
|
||||||
@@ -617,32 +742,32 @@ static void DrawMesh(tinygltf::Model &model, const tinygltf::Mesh &mesh) {
|
|||||||
|
|
||||||
#if 0 // TODO(syoyo): Implement
|
#if 0 // TODO(syoyo): Implement
|
||||||
static void DrawCurves(tinygltf::Scene &scene, const tinygltf::Mesh &mesh) {
|
static void DrawCurves(tinygltf::Scene &scene, const tinygltf::Mesh &mesh) {
|
||||||
(void)scene;
|
(void)scene;
|
||||||
|
|
||||||
if (gCurvesMesh.find(mesh.name) == gCurvesMesh.end()) {
|
if (gCurvesMesh.find(mesh.name) == gCurvesMesh.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gGLProgramState.uniforms["isCurvesLoc"] >= 0) {
|
if (gGLProgramState.uniforms["isCurvesLoc"] >= 0) {
|
||||||
glUniform1i(gGLProgramState.uniforms["isCurvesLoc"], 1);
|
glUniform1i(gGLProgramState.uniforms["isCurvesLoc"], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLCurvesState &state = gCurvesMesh[mesh.name];
|
GLCurvesState &state = gCurvesMesh[mesh.name];
|
||||||
|
|
||||||
if (gGLProgramState.attribs["POSITION"] >= 0) {
|
if (gGLProgramState.attribs["POSITION"] >= 0) {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, state.vb);
|
glBindBuffer(GL_ARRAY_BUFFER, state.vb);
|
||||||
glVertexAttribPointer(gGLProgramState.attribs["POSITION"], 3, GL_FLOAT,
|
glVertexAttribPointer(gGLProgramState.attribs["POSITION"], 3, GL_FLOAT,
|
||||||
GL_FALSE, /* stride */ 0, BUFFER_OFFSET(0));
|
GL_FALSE, /* stride */ 0, BUFFER_OFFSET(0));
|
||||||
CheckErrors("curve: vertex attrib pointer");
|
CheckErrors("curve: vertex attrib pointer");
|
||||||
glEnableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
|
glEnableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
|
||||||
CheckErrors("curve: enable vertex attrib array");
|
CheckErrors("curve: enable vertex attrib array");
|
||||||
}
|
}
|
||||||
|
|
||||||
glDrawArrays(GL_LINES, 0, state.count);
|
glDrawArrays(GL_LINES, 0, state.count);
|
||||||
|
|
||||||
if (gGLProgramState.attribs["POSITION"] >= 0) {
|
if (gGLProgramState.attribs["POSITION"] >= 0) {
|
||||||
glDisableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
|
glDisableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -693,16 +818,16 @@ static void DrawNode(tinygltf::Model &model, const tinygltf::Node &node) {
|
|||||||
|
|
||||||
static void DrawModel(tinygltf::Model &model) {
|
static void DrawModel(tinygltf::Model &model) {
|
||||||
#if 0
|
#if 0
|
||||||
std::map<std::string, tinygltf::Mesh>::const_iterator it(scene.meshes.begin());
|
std::map<std::string, tinygltf::Mesh>::const_iterator it(scene.meshes.begin());
|
||||||
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(scene.meshes.end());
|
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(scene.meshes.end());
|
||||||
|
|
||||||
for (; it != itEnd; it++) {
|
for (; it != itEnd; it++) {
|
||||||
DrawMesh(scene, it->second);
|
DrawMesh(scene, it->second);
|
||||||
DrawCurves(scene, it->second);
|
DrawCurves(scene, it->second);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//If the glTF asset has at least one scene, and doesn't define a default one
|
// If the glTF asset has at least one scene, and doesn't define a default one
|
||||||
//just show the first one we can find
|
// just show the first one we can find
|
||||||
assert(model.scenes.size() > 0);
|
assert(model.scenes.size() > 0);
|
||||||
int scene_to_display = model.defaultScene > -1 ? model.defaultScene : 0;
|
int scene_to_display = model.defaultScene > -1 ? model.defaultScene : 0;
|
||||||
const tinygltf::Scene &scene = model.scenes[scene_to_display];
|
const tinygltf::Scene &scene = model.scenes[scene_to_display];
|
||||||
@@ -752,7 +877,8 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
std::string input_filename(argv[1] ? argv[1] : "../../../models/Cube/Cube.gltf");
|
std::string input_filename(argv[1] ? argv[1]
|
||||||
|
: "../../../models/Cube/Cube.gltf");
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
std::string input_filename(argv[1] ? argv[1] : "../../models/Cube/Cube.gltf");
|
std::string input_filename(argv[1] ? argv[1] : "../../models/Cube/Cube.gltf");
|
||||||
@@ -763,7 +889,8 @@ int main(int argc, char **argv) {
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (ext.compare("glb") == 0) {
|
if (ext.compare("glb") == 0) {
|
||||||
// assume binary glTF.
|
// assume binary glTF.
|
||||||
ret = loader.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
|
ret =
|
||||||
|
loader.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
|
||||||
} else {
|
} else {
|
||||||
// assume ascii glTF.
|
// assume ascii glTF.
|
||||||
ret = loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
|
ret = loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
|
||||||
@@ -825,15 +952,14 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
const char *shader_frag_filename = "../shader.frag";
|
const char *shader_frag_filename = "../shader.frag";
|
||||||
const char *shader_vert_filename = "../shader.vert";
|
const char *shader_vert_filename = "../shader.vert";
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
const char *shader_frag_filename = "shader.frag";
|
const char *shader_frag_filename = "shader.frag";
|
||||||
const char *shader_vert_filename = "shader.vert";
|
const char *shader_vert_filename = "shader.vert";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (false == LoadShader(GL_VERTEX_SHADER, vertId, shader_vert_filename)) {
|
if (false == LoadShader(GL_VERTEX_SHADER, vertId, shader_vert_filename)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,7 +175,10 @@ static std::string PrintIntArray(const std::vector<int> &arr) {
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "[ ";
|
ss << "[ ";
|
||||||
for (size_t i = 0; i < arr.size(); i++) {
|
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 << " ]";
|
ss << " ]";
|
||||||
|
|
||||||
@@ -190,7 +193,10 @@ static std::string PrintFloatArray(const std::vector<double> &arr) {
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "[ ";
|
ss << "[ ";
|
||||||
for (size_t i = 0; i < arr.size(); i++) {
|
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 << " ]";
|
ss << " ]";
|
||||||
|
|
||||||
@@ -228,7 +234,8 @@ static std::string PrintParameterMap(const tinygltf::ParameterMap &pmap) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string PrintValue(const std::string &name,
|
static std::string PrintValue(const std::string &name,
|
||||||
const tinygltf::Value &value, const int indent, const bool tag = true) {
|
const tinygltf::Value &value, const int indent,
|
||||||
|
const bool tag = true) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
if (value.IsObject()) {
|
if (value.IsObject()) {
|
||||||
@@ -242,36 +249,36 @@ static std::string PrintValue(const std::string &name,
|
|||||||
if (tag) {
|
if (tag) {
|
||||||
ss << Indent(indent) << name << " : " << value.Get<std::string>();
|
ss << Indent(indent) << name << " : " << value.Get<std::string>();
|
||||||
} else {
|
} else {
|
||||||
ss << " " << value.Get<std::string>() << " ";
|
ss << Indent(indent) << value.Get<std::string>() << " ";
|
||||||
}
|
}
|
||||||
} else if (value.IsBool()) {
|
} else if (value.IsBool()) {
|
||||||
if (tag) {
|
if (tag) {
|
||||||
ss << Indent(indent) << name << " : " << value.Get<bool>();
|
ss << Indent(indent) << name << " : " << value.Get<bool>();
|
||||||
} else {
|
} else {
|
||||||
ss << " " << value.Get<bool>() << " ";
|
ss << Indent(indent) << value.Get<bool>() << " ";
|
||||||
}
|
}
|
||||||
} else if (value.IsNumber()) {
|
} else if (value.IsNumber()) {
|
||||||
if (tag) {
|
if (tag) {
|
||||||
ss << Indent(indent) << name << " : " << value.Get<double>();
|
ss << Indent(indent) << name << " : " << value.Get<double>();
|
||||||
} else {
|
} else {
|
||||||
ss << " " << value.Get<double>() << " ";
|
ss << Indent(indent) << value.Get<double>() << " ";
|
||||||
}
|
}
|
||||||
} else if (value.IsInt()) {
|
} else if (value.IsInt()) {
|
||||||
if (tag) {
|
if (tag) {
|
||||||
ss << Indent(indent) << name << " : " << value.Get<int>();
|
ss << Indent(indent) << name << " : " << value.Get<int>();
|
||||||
} else {
|
} else {
|
||||||
ss << " " << value.Get<int>() << " ";
|
ss << Indent(indent) << value.Get<int>() << " ";
|
||||||
}
|
}
|
||||||
} else if (value.IsArray()) {
|
} 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++) {
|
for (size_t i = 0; i < value.Size(); i++) {
|
||||||
ss << PrintValue("", value.Get(int(i)), indent + 1, /* tag */false);
|
ss << PrintValue("", value.Get(int(i)), indent + 1, /* tag */ false);
|
||||||
if (i != (value.ArrayLen()-1)) {
|
if (i != (value.ArrayLen() - 1)) {
|
||||||
ss << ", ";
|
ss << ", \n";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ss << Indent(indent) << "] ";
|
ss << "\n" << Indent(indent) << "] ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo { binary }
|
// @todo { binary }
|
||||||
@@ -315,6 +322,15 @@ static void DumpStringIntMap(const std::map<std::string, int> &m, int indent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DumpExtensions(const tinygltf::ExtensionMap &extension,
|
||||||
|
const int indent) {
|
||||||
|
// TODO(syoyo): pritty print Value
|
||||||
|
for (auto &e : extension) {
|
||||||
|
std::cout << Indent(indent) << e.first << std::endl;
|
||||||
|
std::cout << PrintValue("extensions", e.second, indent + 1) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void DumpPrimitive(const tinygltf::Primitive &primitive, int indent) {
|
static void DumpPrimitive(const tinygltf::Primitive &primitive, int indent) {
|
||||||
std::cout << Indent(indent) << "material : " << primitive.material
|
std::cout << Indent(indent) << "material : " << primitive.material
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
@@ -326,17 +342,80 @@ static void DumpPrimitive(const tinygltf::Primitive &primitive, int indent) {
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
DumpStringIntMap(primitive.attributes, indent + 1);
|
DumpStringIntMap(primitive.attributes, indent + 1);
|
||||||
|
|
||||||
|
DumpExtensions(primitive.extensions, indent);
|
||||||
std::cout << Indent(indent) << "extras :" << std::endl
|
std::cout << Indent(indent) << "extras :" << std::endl
|
||||||
<< PrintValue("extras", primitive.extras, indent + 1) << std::endl;
|
<< PrintValue("extras", primitive.extras, indent + 1) << std::endl;
|
||||||
|
|
||||||
|
if (!primitive.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(indent + 1) << "extensions(JSON string) = "
|
||||||
|
<< primitive.extensions_json_string << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!primitive.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(indent + 1)
|
||||||
|
<< "extras(JSON string) = " << primitive.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DumpExtensions(const tinygltf::ExtensionMap &extension, const int indent)
|
|
||||||
{
|
static void DumpTextureInfo(const tinygltf::TextureInfo &texinfo,
|
||||||
// TODO(syoyo): pritty print Value
|
const int indent) {
|
||||||
for (auto &e : extension) {
|
std::cout << Indent(indent) << "index : " << texinfo.index << "\n";
|
||||||
std::cout << Indent(indent) << e.first << std::endl;
|
std::cout << Indent(indent) << "texCoord : TEXCOORD_" << texinfo.texCoord
|
||||||
std::cout << PrintValue("extensions", e.second, indent+1) << std::endl;
|
<< "\n";
|
||||||
}
|
DumpExtensions(texinfo.extensions, indent + 1);
|
||||||
|
std::cout << PrintValue("extras", texinfo.extras, indent + 1) << "\n";
|
||||||
|
|
||||||
|
if (!texinfo.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(indent)
|
||||||
|
<< "extensions(JSON string) = " << texinfo.extensions_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!texinfo.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(indent)
|
||||||
|
<< "extras(JSON string) = " << texinfo.extras_json_string << "\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) {
|
static void Dump(const tinygltf::Model &model) {
|
||||||
@@ -409,6 +488,30 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
}
|
}
|
||||||
std::cout << "]" << std::endl;
|
std::cout << "]" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (accessor.sparse.isSparse) {
|
||||||
|
std::cout << Indent(2) << "sparse:" << std::endl;
|
||||||
|
std::cout << Indent(3) << "count : " << accessor.sparse.count
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << Indent(3) << "indices: " << std::endl;
|
||||||
|
std::cout << Indent(4)
|
||||||
|
<< "bufferView : " << accessor.sparse.indices.bufferView
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << Indent(4)
|
||||||
|
<< "byteOffset : " << accessor.sparse.indices.byteOffset
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << Indent(4) << "componentType: "
|
||||||
|
<< PrintComponentType(accessor.sparse.indices.componentType)
|
||||||
|
<< "(" << accessor.sparse.indices.componentType << ")"
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << Indent(3) << "values : " << std::endl;
|
||||||
|
std::cout << Indent(4)
|
||||||
|
<< "bufferView : " << accessor.sparse.values.bufferView
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << Indent(4)
|
||||||
|
<< "byteOffset : " << accessor.sparse.values.byteOffset
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,6 +570,21 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
std::cout << Indent(2)
|
std::cout << Indent(2)
|
||||||
<< "target : " << PrintTarget(bufferView.target)
|
<< "target : " << PrintTarget(bufferView.target)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
std::cout << Indent(1) << "-------------------------------------\n";
|
||||||
|
|
||||||
|
DumpExtensions(bufferView.extensions, 1);
|
||||||
|
std::cout << PrintValue("extras", bufferView.extras, 2) << std::endl;
|
||||||
|
|
||||||
|
if (!bufferView.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(2) << "extensions(JSON string) = "
|
||||||
|
<< bufferView.extensions_json_string << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bufferView.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extras(JSON string) = " << bufferView.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,6 +595,21 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
std::cout << Indent(1) << "name : " << buffer.name << std::endl;
|
std::cout << Indent(1) << "name : " << buffer.name << std::endl;
|
||||||
std::cout << Indent(2) << "byteLength : " << buffer.data.size()
|
std::cout << Indent(2) << "byteLength : " << buffer.data.size()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
std::cout << Indent(1) << "-------------------------------------\n";
|
||||||
|
|
||||||
|
DumpExtensions(buffer.extensions, 1);
|
||||||
|
std::cout << PrintValue("extras", buffer.extras, 2) << std::endl;
|
||||||
|
|
||||||
|
if (!buffer.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(2) << "extensions(JSON string) = "
|
||||||
|
<< buffer.extensions_json_string << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buffer.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extras(JSON string) = " << buffer.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,16 +618,55 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
for (size_t i = 0; i < model.materials.size(); i++) {
|
for (size_t i = 0; i < model.materials.size(); i++) {
|
||||||
const tinygltf::Material &material = model.materials[i];
|
const tinygltf::Material &material = model.materials[i];
|
||||||
std::cout << Indent(1) << "name : " << material.name << std::endl;
|
std::cout << Indent(1) << "name : " << material.name
|
||||||
std::cout << Indent(1) << "values(items=" << material.values.size() << ")"
|
|
||||||
<< std::endl;
|
<< 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 p(material.values.begin());
|
||||||
tinygltf::ParameterMap::const_iterator pEnd(material.values.end());
|
tinygltf::ParameterMap::const_iterator pEnd(material.values.end());
|
||||||
for (; p != pEnd; p++) {
|
for (; p != pEnd; p++) {
|
||||||
std::cout << Indent(2) << p->first << ": "
|
std::cout << Indent(2) << p->first << ": "
|
||||||
<< PrintParameterValue(p->second) << std::endl;
|
<< PrintParameterValue(p->second) << std::endl;
|
||||||
}
|
}
|
||||||
|
std::cout << Indent(1) << "-------------------------------------\n";
|
||||||
|
|
||||||
|
DumpExtensions(material.extensions, 1);
|
||||||
|
std::cout << PrintValue("extras", material.extras, 2) << std::endl;
|
||||||
|
|
||||||
|
if (!material.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(2) << "extensions(JSON string) = "
|
||||||
|
<< material.extensions_json_string << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!material.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extras(JSON string) = " << material.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,6 +690,18 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
std::cout << Indent(2) << "height : " << image.height << std::endl;
|
std::cout << Indent(2) << "height : " << image.height << std::endl;
|
||||||
std::cout << Indent(2) << "component : " << image.component << std::endl;
|
std::cout << Indent(2) << "component : " << image.component << std::endl;
|
||||||
DumpExtensions(image.extensions, 1);
|
DumpExtensions(image.extensions, 1);
|
||||||
|
std::cout << PrintValue("extras", image.extras, 2) << std::endl;
|
||||||
|
|
||||||
|
if (!image.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(2) << "extensions(JSON string) = "
|
||||||
|
<< image.extensions_json_string << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!image.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extras(JSON string) = " << image.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,6 +714,18 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
std::cout << Indent(1) << "source : " << texture.source
|
std::cout << Indent(1) << "source : " << texture.source
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
DumpExtensions(texture.extensions, 1);
|
DumpExtensions(texture.extensions, 1);
|
||||||
|
std::cout << PrintValue("extras", texture.extras, 2) << std::endl;
|
||||||
|
|
||||||
|
if (!texture.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(2) << "extensions(JSON string) = "
|
||||||
|
<< texture.extensions_json_string << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!texture.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extras(JSON string) = " << texture.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,6 +747,20 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
std::cout << Indent(2)
|
std::cout << Indent(2)
|
||||||
<< "wrapT : " << PrintWrapMode(sampler.wrapT)
|
<< "wrapT : " << PrintWrapMode(sampler.wrapT)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
|
DumpExtensions(sampler.extensions, 1);
|
||||||
|
std::cout << PrintValue("extras", sampler.extras, 2) << std::endl;
|
||||||
|
|
||||||
|
if (!sampler.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(2) << "extensions(JSON string) = "
|
||||||
|
<< sampler.extensions_json_string << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sampler.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extras(JSON string) = " << sampler.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,12 +793,61 @@ static void Dump(const tinygltf::Model &model) {
|
|||||||
<< "znear : " << camera.orthographic.znear
|
<< "znear : " << camera.orthographic.znear
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << Indent(1) << "-------------------------------------\n";
|
||||||
|
|
||||||
|
DumpExtensions(camera.extensions, 1);
|
||||||
|
std::cout << PrintValue("extras", camera.extras, 2) << std::endl;
|
||||||
|
|
||||||
|
if (!camera.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(2) << "extensions(JSON string) = "
|
||||||
|
<< camera.extensions_json_string << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!camera.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extras(JSON string) = " << camera.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::cout << "skins(items=" << model.skins.size() << ")" << std::endl;
|
||||||
|
for (size_t i = 0; i < model.skins.size(); i++) {
|
||||||
|
const tinygltf::Skin &skin = model.skins[i];
|
||||||
|
std::cout << Indent(1) << "name : " << skin.name << std::endl;
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "inverseBindMatrices : " << skin.inverseBindMatrices
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << Indent(2) << "skeleton : " << skin.skeleton
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "joints : " << PrintIntArray(skin.joints)
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << Indent(1) << "-------------------------------------\n";
|
||||||
|
|
||||||
|
DumpExtensions(skin.extensions, 1);
|
||||||
|
std::cout << PrintValue("extras", skin.extras, 2) << std::endl;
|
||||||
|
|
||||||
|
if (!skin.extensions_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extensions(JSON string) = " << skin.extensions_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skin.extras_json_string.empty()) {
|
||||||
|
std::cout << Indent(2)
|
||||||
|
<< "extras(JSON string) = " << skin.extras_json_string
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// toplevel extensions
|
// toplevel extensions
|
||||||
{
|
{
|
||||||
std::cout << "extensions(items=" << model.extensions.size() << ")" << std::endl;
|
std::cout << "extensions(items=" << model.extensions.size() << ")"
|
||||||
|
<< std::endl;
|
||||||
DumpExtensions(model.extensions, 1);
|
DumpExtensions(model.extensions, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -599,29 +858,39 @@ int main(int argc, char **argv) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store original JSON string for `extras` and `extensions`
|
||||||
|
bool store_original_json_for_extras_and_extensions = false;
|
||||||
|
if (argc > 2) {
|
||||||
|
store_original_json_for_extras_and_extensions = true;
|
||||||
|
}
|
||||||
|
|
||||||
tinygltf::Model model;
|
tinygltf::Model model;
|
||||||
tinygltf::TinyGLTF gltf_ctx;
|
tinygltf::TinyGLTF gltf_ctx;
|
||||||
std::string err;
|
std::string err;
|
||||||
std::string warn;
|
std::string warn;
|
||||||
std::string input_filename(argv[1]);
|
std::string input_filename(argv[1]);
|
||||||
std::string ext = GetFilePathExtension(input_filename);
|
std::string ext = GetFilePathExtension(input_filename);
|
||||||
|
|
||||||
|
gltf_ctx.SetStoreOriginalJSONForExtrasAndExtensions(
|
||||||
|
store_original_json_for_extras_and_extensions);
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (ext.compare("glb") == 0) {
|
if (ext.compare("glb") == 0) {
|
||||||
std::cout << "Reading binary glTF" << std::endl;
|
std::cout << "Reading binary glTF" << std::endl;
|
||||||
// assume binary glTF.
|
// assume binary glTF.
|
||||||
ret = gltf_ctx.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
|
ret = gltf_ctx.LoadBinaryFromFile(&model, &err, &warn,
|
||||||
|
input_filename.c_str());
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Reading ASCII glTF" << std::endl;
|
std::cout << "Reading ASCII glTF" << std::endl;
|
||||||
// assume ascii glTF.
|
// assume ascii glTF.
|
||||||
ret = gltf_ctx.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
|
ret =
|
||||||
|
gltf_ctx.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!warn.empty()) {
|
if (!warn.empty()) {
|
||||||
printf("Warn: %s\n", warn.c_str());
|
printf("Warn: %s\n", warn.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!err.empty()) {
|
if (!err.empty()) {
|
||||||
printf("Err: %s\n", err.c_str());
|
printf("Err: %s\n", err.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
67
models/BoundsChecking/integer-out-of-bounds.gltf
Normal file
67
models/BoundsChecking/integer-out-of-bounds.gltf
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
53
models/BoundsChecking/invalid-buffer-index.gltf
Normal file
53
models/BoundsChecking/invalid-buffer-index.gltf
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
36
models/BoundsChecking/invalid-buffer-view-index.gltf
Normal file
36
models/BoundsChecking/invalid-buffer-view-index.gltf
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
36
models/BoundsChecking/invalid-primitive-indices.gltf
Normal file
36
models/BoundsChecking/invalid-primitive-indices.gltf
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
models/BoundsChecking/simpleTriangle.bin
Normal file
BIN
models/BoundsChecking/simpleTriangle.bin
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 B |
224
models/Cube-texture-ext/Cube-textransform.gltf
Normal file
224
models/Cube-texture-ext/Cube-textransform.gltf
Normal 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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
models/Cube-texture-ext/Cube.bin
Normal file
BIN
models/Cube-texture-ext/Cube.bin
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
models/Cube-texture-ext/Cube_MetallicRoughness.png
Normal file
BIN
models/Cube-texture-ext/Cube_MetallicRoughness.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 319 B |
6
models/Cube-texture-ext/README.md
Normal file
6
models/Cube-texture-ext/README.md
Normal 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
|
||||||
|
|
||||||
BIN
models/CubeImageUriSpaces/ 2x2 image has multiple spaces.png
Normal file
BIN
models/CubeImageUriSpaces/ 2x2 image has multiple spaces.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 79 B |
BIN
models/CubeImageUriSpaces/2x2 image has spaces.png
Normal file
BIN
models/CubeImageUriSpaces/2x2 image has spaces.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 79 B |
171
models/CubeImageUriSpaces/CubeImageUriMultipleSpaces.gltf
Normal file
171
models/CubeImageUriSpaces/CubeImageUriMultipleSpaces.gltf
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
{
|
||||||
|
"asset": {
|
||||||
|
"version": "2.0"
|
||||||
|
},
|
||||||
|
"scenes": [
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scene": 0,
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"mesh": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes": [
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"NORMAL": 2,
|
||||||
|
"POSITION": 1,
|
||||||
|
"TEXCOORD_0": 3
|
||||||
|
},
|
||||||
|
"indices": 0,
|
||||||
|
"mode": 4,
|
||||||
|
"material": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials": [
|
||||||
|
{
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorTexture": {
|
||||||
|
"index": 0,
|
||||||
|
"texCoord": 0
|
||||||
|
},
|
||||||
|
"baseColorFactor": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"metallicFactor": 1,
|
||||||
|
"roughnessFactor": 1
|
||||||
|
},
|
||||||
|
"emissiveFactor": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"alphaMode": "OPAQUE"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"source": 0,
|
||||||
|
"sampler": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers": [
|
||||||
|
{
|
||||||
|
"wrapS": 33071,
|
||||||
|
"wrapT": 33071
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images": [
|
||||||
|
{
|
||||||
|
"uri": " 2x2 image has multiple spaces.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors": [
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5121,
|
||||||
|
"count": 36,
|
||||||
|
"normalized": false,
|
||||||
|
"max": [
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"type": "SCALAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 24,
|
||||||
|
"normalized": false,
|
||||||
|
"max": [
|
||||||
|
0.5,
|
||||||
|
0.5,
|
||||||
|
0.5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.5,
|
||||||
|
-0.5,
|
||||||
|
-0.5
|
||||||
|
],
|
||||||
|
"type": "VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 2,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 24,
|
||||||
|
"normalized": false,
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
-1
|
||||||
|
],
|
||||||
|
"type": "VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 3,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 24,
|
||||||
|
"normalized": false,
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"type": "VEC2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews": [
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"byteLength": 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 36,
|
||||||
|
"byteLength": 288
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 324,
|
||||||
|
"byteLength": 288
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 612,
|
||||||
|
"byteLength": 192
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers": [
|
||||||
|
{
|
||||||
|
"byteLength": 804,
|
||||||
|
"uri": "CubeImageUriSpaces.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
models/CubeImageUriSpaces/CubeImageUriSpaces.bin
Normal file
BIN
models/CubeImageUriSpaces/CubeImageUriSpaces.bin
Normal file
Binary file not shown.
171
models/CubeImageUriSpaces/CubeImageUriSpaces.gltf
Normal file
171
models/CubeImageUriSpaces/CubeImageUriSpaces.gltf
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
{
|
||||||
|
"asset": {
|
||||||
|
"version": "2.0"
|
||||||
|
},
|
||||||
|
"scenes": [
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scene": 0,
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"mesh": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes": [
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"NORMAL": 2,
|
||||||
|
"POSITION": 1,
|
||||||
|
"TEXCOORD_0": 3
|
||||||
|
},
|
||||||
|
"indices": 0,
|
||||||
|
"mode": 4,
|
||||||
|
"material": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials": [
|
||||||
|
{
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorTexture": {
|
||||||
|
"index": 0,
|
||||||
|
"texCoord": 0
|
||||||
|
},
|
||||||
|
"baseColorFactor": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"metallicFactor": 1,
|
||||||
|
"roughnessFactor": 1
|
||||||
|
},
|
||||||
|
"emissiveFactor": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"alphaMode": "OPAQUE"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"source": 0,
|
||||||
|
"sampler": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers": [
|
||||||
|
{
|
||||||
|
"wrapS": 33071,
|
||||||
|
"wrapT": 33071
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images": [
|
||||||
|
{
|
||||||
|
"uri": "2x2 image has spaces.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors": [
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5121,
|
||||||
|
"count": 36,
|
||||||
|
"normalized": false,
|
||||||
|
"max": [
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"type": "SCALAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 24,
|
||||||
|
"normalized": false,
|
||||||
|
"max": [
|
||||||
|
0.5,
|
||||||
|
0.5,
|
||||||
|
0.5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.5,
|
||||||
|
-0.5,
|
||||||
|
-0.5
|
||||||
|
],
|
||||||
|
"type": "VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 2,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 24,
|
||||||
|
"normalized": false,
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
-1
|
||||||
|
],
|
||||||
|
"type": "VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 3,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 24,
|
||||||
|
"normalized": false,
|
||||||
|
"max": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"type": "VEC2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews": [
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 0,
|
||||||
|
"byteLength": 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 36,
|
||||||
|
"byteLength": 288
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 324,
|
||||||
|
"byteLength": 288
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 612,
|
||||||
|
"byteLength": 192
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers": [
|
||||||
|
{
|
||||||
|
"byteLength": 804,
|
||||||
|
"uri": "CubeImageUriSpaces.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
models/Extensions-overwrite-issue261/issue-261.bin
Normal file
BIN
models/Extensions-overwrite-issue261/issue-261.bin
Normal file
Binary file not shown.
376
models/Extensions-overwrite-issue261/issue-261.gltf
Normal file
376
models/Extensions-overwrite-issue261/issue-261.gltf
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
{
|
||||||
|
"accessors": [
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 8,
|
||||||
|
"max": [
|
||||||
|
0.5,
|
||||||
|
0.5,
|
||||||
|
0.5
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.5,
|
||||||
|
-0.5,
|
||||||
|
-0.5
|
||||||
|
],
|
||||||
|
"type": "VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"componentType": 5125,
|
||||||
|
"count": 36,
|
||||||
|
"type": "SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"asset": {
|
||||||
|
"copyright": "NVIDIA Corporation",
|
||||||
|
"generator": "Iray glTF plugin",
|
||||||
|
"version": "2.0"
|
||||||
|
},
|
||||||
|
"bufferViews": [
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteLength": 96,
|
||||||
|
"byteStride": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteLength": 144,
|
||||||
|
"byteOffset": 96
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers": [
|
||||||
|
{
|
||||||
|
"byteLength": 240,
|
||||||
|
"uri": "issue-261.bin"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cameras": [
|
||||||
|
{
|
||||||
|
"extensions": {
|
||||||
|
"NV_Iray": {
|
||||||
|
"mip_burn_highlights": 0.699999988079071,
|
||||||
|
"mip_burn_highlights_per_component": false,
|
||||||
|
"mip_camera_shutter": 4.0,
|
||||||
|
"mip_cm2_factor": 1.0,
|
||||||
|
"mip_crush_blacks": 0.5,
|
||||||
|
"mip_f_number": 1.0,
|
||||||
|
"mip_film_iso": 100.0,
|
||||||
|
"mip_gamma": 2.200000047683716,
|
||||||
|
"mip_saturation": 1.0,
|
||||||
|
"mip_vignetting": 0.00019999999494757503,
|
||||||
|
"mip_whitepoint": [
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"tm_enable_tonemapper": true,
|
||||||
|
"tm_tonemapper": "mia_exposure_photographic"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extras": {
|
||||||
|
"resolution": [
|
||||||
|
640,
|
||||||
|
480
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "default",
|
||||||
|
"perspective": {
|
||||||
|
"aspectRatio": 1.3333333730697632,
|
||||||
|
"yfov": 0.9272952079772949,
|
||||||
|
"zfar": 1000.0,
|
||||||
|
"znear": 0.1
|
||||||
|
},
|
||||||
|
"type": "perspective"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extensions": {
|
||||||
|
"KHR_lights_punctual": {
|
||||||
|
"lights": [
|
||||||
|
{
|
||||||
|
"color": [
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"intensity": 1000.0,
|
||||||
|
"name": "light",
|
||||||
|
"type": "point"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"NV_MDL": {
|
||||||
|
"modules": [
|
||||||
|
"mdl::base",
|
||||||
|
"mdl::nvidia::core_definitions",
|
||||||
|
"mdl::state"
|
||||||
|
],
|
||||||
|
"shaders": [
|
||||||
|
{
|
||||||
|
"definition": "mdl::base::environment_spherical(texture_2d)",
|
||||||
|
"name": "env_shd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": {
|
||||||
|
"base_color": [
|
||||||
|
0.0055217444896698,
|
||||||
|
0.36859095096588135,
|
||||||
|
0.0041161770932376385
|
||||||
|
],
|
||||||
|
"normal=": 2
|
||||||
|
},
|
||||||
|
"definition": "mdl::nvidia::core_definitions::flex_material",
|
||||||
|
"name": "cube_instance_material"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"definition": "mdl::state::normal()",
|
||||||
|
"name": "mdl::state::normal_341"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arguments": {
|
||||||
|
"base_color": [
|
||||||
|
0.0055217444896698,
|
||||||
|
0.36859095096588135,
|
||||||
|
0.0041161770932376385
|
||||||
|
],
|
||||||
|
"normal=": 4
|
||||||
|
},
|
||||||
|
"definition": "mdl::nvidia::core_definitions::flex_material",
|
||||||
|
"name": "cube_instance_material"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"definition": "mdl::state::normal()",
|
||||||
|
"name": "mdl::state::normal_341"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extensionsUsed": [
|
||||||
|
"NV_MDL",
|
||||||
|
"NV_Iray",
|
||||||
|
"KHR_lights_punctual"
|
||||||
|
],
|
||||||
|
"materials": [
|
||||||
|
{
|
||||||
|
"doubleSided": true,
|
||||||
|
"extras": {
|
||||||
|
"mdl_shader": 1
|
||||||
|
},
|
||||||
|
"name": "cube_instance_material",
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorFactor": [
|
||||||
|
0.0055217444896698,
|
||||||
|
0.36859095096588135,
|
||||||
|
0.0041161770932376385,
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes": [
|
||||||
|
{
|
||||||
|
"name": "cube",
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"POSITION": 0
|
||||||
|
},
|
||||||
|
"indices": 1,
|
||||||
|
"material": 0,
|
||||||
|
"mode": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"camera": 0,
|
||||||
|
"extensions": {
|
||||||
|
"NV_Iray": {
|
||||||
|
"iview:fkey": -1,
|
||||||
|
"iview:fov": 53.130104064941406,
|
||||||
|
"iview:interest": [
|
||||||
|
0.1342654824256897,
|
||||||
|
-0.14356137812137604,
|
||||||
|
0.037264324724674225
|
||||||
|
],
|
||||||
|
"iview:position": [
|
||||||
|
0.9729073643684387,
|
||||||
|
1.2592438459396362,
|
||||||
|
2.4199187755584717
|
||||||
|
],
|
||||||
|
"iview:roll": 0.0,
|
||||||
|
"iview:up": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"matrix": [
|
||||||
|
0.9432751389105357,
|
||||||
|
-1.1769874756875739e-16,
|
||||||
|
-0.3320120665176343,
|
||||||
|
0.0,
|
||||||
|
-0.16119596696756341,
|
||||||
|
0.8742297945345237,
|
||||||
|
-0.45797175303889276,
|
||||||
|
0.0,
|
||||||
|
0.290254840694694,
|
||||||
|
0.48551237507207207,
|
||||||
|
0.8246392308792816,
|
||||||
|
0.0,
|
||||||
|
0.9729073377709113,
|
||||||
|
1.2592438262175363,
|
||||||
|
2.419918748461627,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"name": "CamInst"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"extensions": {
|
||||||
|
"NV_Iray": {
|
||||||
|
"caustic": true,
|
||||||
|
"caustic_cast": true,
|
||||||
|
"caustic_recv": true,
|
||||||
|
"face_back": true,
|
||||||
|
"face_front": true,
|
||||||
|
"finalgather": true,
|
||||||
|
"finalgather_cast": true,
|
||||||
|
"finalgather_recv": true,
|
||||||
|
"globillum": true,
|
||||||
|
"globillum_cast": true,
|
||||||
|
"globillum_recv": true,
|
||||||
|
"material=": 3,
|
||||||
|
"pickable": true,
|
||||||
|
"reflection_cast": true,
|
||||||
|
"reflection_recv": true,
|
||||||
|
"refraction_cast": true,
|
||||||
|
"refraction_recv": true,
|
||||||
|
"shadow_cast": true,
|
||||||
|
"shadow_recv": true,
|
||||||
|
"transparency_cast": true,
|
||||||
|
"transparency_recv": true,
|
||||||
|
"visible": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mesh": 0,
|
||||||
|
"name": "cube_instance"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"extensions": {
|
||||||
|
"KHR_lights_punctual": {
|
||||||
|
"light": 0
|
||||||
|
},
|
||||||
|
"NV_Iray": {
|
||||||
|
"shadow_cast": true,
|
||||||
|
"visible": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"matrix": [
|
||||||
|
0.6988062355563571,
|
||||||
|
-7.76042172309776e-17,
|
||||||
|
-0.7153110128800992,
|
||||||
|
-0.0,
|
||||||
|
-0.4276881690736487,
|
||||||
|
0.8015668284138362,
|
||||||
|
-0.41781987700564616,
|
||||||
|
-0.0,
|
||||||
|
0.57336957992379,
|
||||||
|
0.5979051928078428,
|
||||||
|
0.5601398979107212,
|
||||||
|
0.0,
|
||||||
|
2.3640632834071384,
|
||||||
|
2.465226204472449,
|
||||||
|
2.309515908392224,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"name": "light_inst"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scene": 0,
|
||||||
|
"scenes": [
|
||||||
|
{
|
||||||
|
"extensions": {
|
||||||
|
"NV_Iray": {
|
||||||
|
"CP_canny_threshold1": 40,
|
||||||
|
"CP_canny_threshold2": 120,
|
||||||
|
"CP_color_quantization": 8,
|
||||||
|
"IVP_color": [
|
||||||
|
1.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"TM_drago_bias": 0.8500000238418579,
|
||||||
|
"TM_drago_gamma2": 2.200000047683716,
|
||||||
|
"TM_drago_saturation": 1.0,
|
||||||
|
"TM_durand_contrast": 4.0,
|
||||||
|
"TM_durand_gamma": 2.200000047683716,
|
||||||
|
"TM_durand_saturation": 1.0,
|
||||||
|
"TM_durand_sigma_color": 2.0,
|
||||||
|
"TM_durand_sigma_space": 2.0,
|
||||||
|
"TM_linear_gamma": 2.200000047683716,
|
||||||
|
"TM_reinhard_color_adapt": 0.8999999761581421,
|
||||||
|
"TM_reinhard_gamma": 1.0,
|
||||||
|
"TM_reinhard_intensity": 0.0,
|
||||||
|
"TM_reinhard_light_adapt": 1.0,
|
||||||
|
"TM_reye_Ywhite": 1000000.0,
|
||||||
|
"TM_reye_bsize": 2,
|
||||||
|
"TM_reye_bthres": 3.0,
|
||||||
|
"TM_reye_gamma": 2.200000047683716,
|
||||||
|
"TM_reye_key": 0.5,
|
||||||
|
"TM_reye_saturation": 1.0,
|
||||||
|
"TM_reye_whitebalance": [
|
||||||
|
1.0,
|
||||||
|
0.9965101480484009,
|
||||||
|
0.9805564880371094,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"environment_dome_depth": 200.0,
|
||||||
|
"environment_dome_height": 200.0,
|
||||||
|
"environment_dome_mode": "infinite",
|
||||||
|
"environment_dome_position": [
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"environment_dome_radius": 100.0,
|
||||||
|
"environment_dome_rotation_angle": 0.0,
|
||||||
|
"environment_dome_width": 200.0,
|
||||||
|
"environment_function=": 0,
|
||||||
|
"environment_function_intensity": 1.9900000095367432,
|
||||||
|
"iray_instancing": "off",
|
||||||
|
"iview::inline_color": [
|
||||||
|
1.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"iview::inline_width": 1.0,
|
||||||
|
"iview::magnifier_size": 300,
|
||||||
|
"iview::offset": 10.0,
|
||||||
|
"iview::outline_color": [
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"iview::outline_width": 2.0,
|
||||||
|
"iview::overview": true,
|
||||||
|
"iview::zoom_factor": 1.0,
|
||||||
|
"samples": 4.0,
|
||||||
|
"shadow_cast": true,
|
||||||
|
"shadow_recv": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
2753
stb_image.h
2753
stb_image.h
File diff suppressed because it is too large
Load Diff
2632
stb_image_write.h
2632
stb_image_write.h
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ import subprocess
|
|||||||
sample_model_dir = "/home/syoyo/work/glTF-Sample-Models"
|
sample_model_dir = "/home/syoyo/work/glTF-Sample-Models"
|
||||||
base_model_dir = os.path.join(sample_model_dir, "2.0")
|
base_model_dir = os.path.join(sample_model_dir, "2.0")
|
||||||
|
|
||||||
|
# Include `glTF-Draco` when you build `loader_example` with draco support.
|
||||||
kinds = [ "glTF", "glTF-Binary", "glTF-Embedded", "glTF-MaterialsCommon"]
|
kinds = [ "glTF", "glTF-Binary", "glTF-Embedded", "glTF-MaterialsCommon"]
|
||||||
# ---------------------------------
|
# ---------------------------------
|
||||||
|
|
||||||
|
|||||||
46
tests/fuzzer/README.md
Normal file
46
tests/fuzzer/README.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Fuzzing test
|
||||||
|
|
||||||
|
Do fuzzing test for TinyGLTF API.
|
||||||
|
|
||||||
|
## Supported API
|
||||||
|
|
||||||
|
* [x] LoadASCIIFromMemory
|
||||||
|
* [ ] LoadBinaryFromMemory
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* meson
|
||||||
|
* clang with fuzzer support(`-fsanitize=fuzzer`. at least clang 8.0 should work)
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### Ubuntu 18.04
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo apt install clang++-8
|
||||||
|
$ sudo apt install libfuzzer-8-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally, if you didn't set `update-alternatives` you can set `clang++` to point to `clang++8`
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-8 10
|
||||||
|
$ sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 10
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to compile
|
||||||
|
|
||||||
|
```
|
||||||
|
$ CXX=clang++ CC=clang meson build
|
||||||
|
$ cd build
|
||||||
|
$ ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to run
|
||||||
|
|
||||||
|
Increase memory limit. e.g. `-rss_limit_mb=50000`
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./fuzz_gltf -rss_limit_mb=20000 -jobs 4
|
||||||
|
```
|
||||||
|
|
||||||
33
tests/fuzzer/fuzz_gltf.cc
Normal file
33
tests/fuzzer/fuzz_gltf.cc
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
|
#include "tiny_gltf.h"
|
||||||
|
|
||||||
|
static void parse_intCoding4(const uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
|
||||||
|
tinygltf::Model model;
|
||||||
|
tinygltf::TinyGLTF ctx;
|
||||||
|
std::string err;
|
||||||
|
std::string warn;
|
||||||
|
|
||||||
|
const char *str = reinterpret_cast<const char *>(data);
|
||||||
|
|
||||||
|
bool ret = ctx.LoadASCIIFromString(&model, &err, &warn, str, size, /* base_dir */"" );
|
||||||
|
(void)ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size)
|
||||||
|
{
|
||||||
|
parse_intCoding4(data, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
9
tests/fuzzer/meson.build
Normal file
9
tests/fuzzer/meson.build
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
project('fuzz_tinygltf', 'cpp', default_options : ['cpp_std=c++11'])
|
||||||
|
|
||||||
|
incdirs = include_directories('../../')
|
||||||
|
executable('fuzz_gltf',
|
||||||
|
'fuzz_gltf.cc',
|
||||||
|
include_directories : incdirs,
|
||||||
|
cpp_args : '-fsanitize=address,fuzzer',
|
||||||
|
link_args : '-fsanitize=address,fuzzer' )
|
||||||
|
|
||||||
373
tests/tester.cc
373
tests/tester.cc
@@ -3,6 +3,9 @@
|
|||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#include "tiny_gltf.h"
|
#include "tiny_gltf.h"
|
||||||
|
|
||||||
|
// Nlohmann json(include ../json.hpp)
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
@@ -13,6 +16,14 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
static JsonDocument JsonConstruct(const char* str)
|
||||||
|
{
|
||||||
|
JsonDocument doc;
|
||||||
|
JsonParse(doc, str, strlen(str));
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("parse-error", "[parse]") {
|
TEST_CASE("parse-error", "[parse]") {
|
||||||
|
|
||||||
tinygltf::Model model;
|
tinygltf::Model model;
|
||||||
@@ -20,7 +31,7 @@ TEST_CASE("parse-error", "[parse]") {
|
|||||||
std::string err;
|
std::string err;
|
||||||
std::string warn;
|
std::string warn;
|
||||||
|
|
||||||
bool ret = ctx.LoadASCIIFromString(&model, &err, &warn, "bora", strlen("bora"), /* basedir*/ "");
|
bool ret = ctx.LoadASCIIFromString(&model, &err, &warn, "bora", static_cast<int>(strlen("bora")), /* basedir*/ "");
|
||||||
|
|
||||||
REQUIRE(false == ret);
|
REQUIRE(false == ret);
|
||||||
|
|
||||||
@@ -37,7 +48,7 @@ TEST_CASE("datauri-in-glb", "[issue-79]") {
|
|||||||
if (!err.empty()) {
|
if (!err.empty()) {
|
||||||
std::cerr << err << std::endl;
|
std::cerr << err << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(true == ret);
|
REQUIRE(true == ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +93,363 @@ TEST_CASE("extension-with-empty-object", "[issue-97]") {
|
|||||||
REQUIRE(m.materials[0].extensions.size() == 1);
|
REQUIRE(m.materials[0].extensions.size() == 1);
|
||||||
REQUIRE(m.materials[0].extensions.count("VENDOR_material_some_ext") == 1);
|
REQUIRE(m.materials[0].extensions.count("VENDOR_material_some_ext") == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("extension-overwrite", "[issue-261]") {
|
||||||
|
|
||||||
|
tinygltf::Model model;
|
||||||
|
tinygltf::TinyGLTF ctx;
|
||||||
|
std::string err;
|
||||||
|
std::string warn;
|
||||||
|
|
||||||
|
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/Extensions-overwrite-issue261/issue-261.gltf");
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
|
||||||
|
REQUIRE(model.extensionsUsed.size() == 3);
|
||||||
|
{
|
||||||
|
bool has_ext_lights = false;
|
||||||
|
has_ext_lights |= (model.extensionsUsed[0].compare("KHR_lights_punctual") == 0);
|
||||||
|
has_ext_lights |= (model.extensionsUsed[1].compare("KHR_lights_punctual") == 0);
|
||||||
|
has_ext_lights |= (model.extensionsUsed[2].compare("KHR_lights_punctual") == 0);
|
||||||
|
|
||||||
|
REQUIRE(true == has_ext_lights);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
REQUIRE(model.extensions.size() == 2);
|
||||||
|
REQUIRE(model.extensions.count("NV_MDL"));
|
||||||
|
REQUIRE(model.extensions.count("KHR_lights_punctual"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(syoyo): create temp directory.
|
||||||
|
{
|
||||||
|
ret = ctx.WriteGltfSceneToFile(&model, "issue-261.gltf", true, true);
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
|
||||||
|
tinygltf::Model m;
|
||||||
|
|
||||||
|
// read back serialized glTF
|
||||||
|
bool ret = ctx.LoadASCIIFromFile(&m, &err, &warn, "issue-261.gltf");
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
|
||||||
|
REQUIRE(m.extensionsUsed.size() == 3);
|
||||||
|
|
||||||
|
REQUIRE(m.extensions.size() == 2);
|
||||||
|
REQUIRE(m.extensions.count("NV_MDL"));
|
||||||
|
REQUIRE(m.extensions.count("KHR_lights_punctual"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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, JsonConstruct("{\"zero\" : 0}"), "zero",
|
||||||
|
true));
|
||||||
|
REQUIRE(err == "");
|
||||||
|
REQUIRE(result == 0);
|
||||||
|
|
||||||
|
CHECK(tinygltf::ParseIntegerProperty(&result, &err, JsonConstruct("{\"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, JsonConstruct(""), "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, JsonConstruct(""), "int", false));
|
||||||
|
REQUIRE(err == "");
|
||||||
|
REQUIRE(result == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("invalid integers") {
|
||||||
|
std::string err;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
CHECK_FALSE(tinygltf::ParseIntegerProperty(&result, &err, JsonConstruct("{\"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, JsonConstruct("{\"int\": 1e300}"),
|
||||||
|
"int", true));
|
||||||
|
REQUIRE_THAT(err, Catch::Contains("not an integer type"));
|
||||||
|
|
||||||
|
err.clear();
|
||||||
|
{
|
||||||
|
JsonDocument o;
|
||||||
|
double nan = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
tinygltf::JsonAddMember(o, "int", json(nan));
|
||||||
|
CHECK_FALSE(tinygltf::ParseIntegerProperty(
|
||||||
|
&result, &err, o,
|
||||||
|
"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.
|
||||||
|
auto zero_obj = JsonConstruct("{\"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, JsonConstruct("{\"int\": -1234}"),
|
||||||
|
"int", true));
|
||||||
|
REQUIRE_THAT(err, Catch::Contains("not a positive integer"));
|
||||||
|
|
||||||
|
err.clear();
|
||||||
|
CHECK_FALSE(tinygltf::ParseUnsignedProperty(&result, &err, JsonConstruct("{\"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, JsonConstruct("{\"int\": 1e300}"),
|
||||||
|
"int", true));
|
||||||
|
REQUIRE_THAT(err, Catch::Contains("not a positive integer"));
|
||||||
|
|
||||||
|
err.clear();
|
||||||
|
{
|
||||||
|
JsonDocument o;
|
||||||
|
double nan = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
tinygltf::JsonAddMember(o, "int", json(nan));
|
||||||
|
CHECK_FALSE(tinygltf::ParseUnsignedProperty(
|
||||||
|
&result, &err, o,
|
||||||
|
"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,
|
||||||
|
JsonConstruct("{\"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, JsonConstruct("{\"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));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("image-uri-spaces", "[issue-236]") {
|
||||||
|
|
||||||
|
tinygltf::Model model;
|
||||||
|
tinygltf::TinyGLTF ctx;
|
||||||
|
std::string err;
|
||||||
|
std::string warn;
|
||||||
|
|
||||||
|
// Test image file with single spaces.
|
||||||
|
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/CubeImageUriSpaces/CubeImageUriSpaces.gltf");
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
|
||||||
|
// Test image file with a beginning space, trailing space, and greater than
|
||||||
|
// one consecutive spaces.
|
||||||
|
ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/CubeImageUriSpaces/CubeImageUriMultipleSpaces.gltf");
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("serialize-empty-material", "[issue-294]") {
|
||||||
|
|
||||||
|
tinygltf::Model m;
|
||||||
|
|
||||||
|
tinygltf::Material mat;
|
||||||
|
mat.pbrMetallicRoughness.baseColorFactor = {1.0f, 1.0f, 1.0f, 1.0f}; // default baseColorFactor
|
||||||
|
m.materials.push_back(mat);
|
||||||
|
|
||||||
|
std::stringstream os;
|
||||||
|
|
||||||
|
tinygltf::TinyGLTF ctx;
|
||||||
|
ctx.WriteGltfSceneToStream(&m, os, false, false);
|
||||||
|
|
||||||
|
// use nlohmann json
|
||||||
|
nlohmann::json j = nlohmann::json::parse(os.str());
|
||||||
|
|
||||||
|
REQUIRE(1 == j["materials"].size());
|
||||||
|
REQUIRE(j["asset"].is_null());
|
||||||
|
REQUIRE(j["materials"][0].is_object());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef TINYGLTF_NO_FS
|
||||||
|
TEST_CASE("expandpath-utf-8", "[pr-226]") {
|
||||||
|
|
||||||
|
std::string s1 = "\xe5\xaf\xb9"; // utf-8 string
|
||||||
|
|
||||||
|
std::string ret = tinygltf::ExpandFilePath(s1, /* userdata */nullptr);
|
||||||
|
|
||||||
|
// expected: E5 AF B9
|
||||||
|
REQUIRE(3 == ret.size());
|
||||||
|
|
||||||
|
REQUIRE(0xe5 == static_cast<uint8_t>(ret[0]));
|
||||||
|
REQUIRE(0xaf == static_cast<uint8_t>(ret[1]));
|
||||||
|
REQUIRE(0xb9 == static_cast<uint8_t>(ret[2]));
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
5133
tiny_gltf.h
5133
tiny_gltf.h
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user