Compare commits

...
447 Commits
Author SHA1 Message Date
Syoyo Fujita a34aa8ea77 Suppress variable-is-shadowed warnings.
Apply clang-format.
Add note on RapidJSON and C++14 compilation flags.
2019-09-05 14:40:32 +09:00
Syoyo Fujita 59b2966f81 Merge branch 'master' of https://github.com/jrkoonce/tinygltf into jrkoonce-master 2019-09-05 14:22:51 +09:00
jrkoonce 7481011fd9 Removing RapidJSON toggle 2019-09-04 13:46:59 -05:00
jrkoonce 0d2b6efa6f Removing warnings 2019-09-04 13:46:45 -05:00
jrkoonce ce7fa7419b Support simultaneous gltf load/saves
Added support for RapidJSON's CrtAllocator which is stateless and allows multiple documents to be in use at once, removing that restriction on default documents.  Enable with TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
2019-09-04 13:31:44 -05:00
jrkoonce 906f98fa74 Revert "Support simultaneous gltf load/saves"
This reverts commit d2a2703ec5.
2019-09-04 13:30:02 -05:00
jrkoonce d2a2703ec5 Support simultaneous gltf load/saves
Added support for RapidJSON's CrtAllocator which is stateless and allows multiple documents to be in use at once, removing that restriction on default documents.  Enable with TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
2019-09-04 12:19:27 -05:00
jrkoonce 95f05757d6 Revert "Support simultaneous gltf load/saves (TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR)"
This reverts commit ab63db6318.
2019-09-04 12:15:51 -05:00
jrkoonce ab63db6318 Support simultaneous gltf load/saves (TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR)
This allows multiple gltf's to be loaded/saved in parallel.  It removes the restriction of a single JsonDocument active at once which is default behavior.  Enable with TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
2019-09-04 12:01:39 -05:00
jrkoonce 6ff95392b0 Fix Compiler Warnings 2019-09-04 10:50:55 -05:00
Syoyo Fujita c29bd3d9ce Use const reference for Buffer to fix compilation.
Removed UTF BOM?
2019-09-04 14:26:58 +09:00
jrkoonce 63419a11e1 Revert accidental committed change
Put "JsonX" helpers back in anonymous namespace to keep them inside local translation unit.
2019-09-03 17:06:41 -05:00
jrkoonce 06c30c4d04 Fixed Bugs/Unit Tests Pass
Fixed bugs found by unit tests and got unit tests running with RapidJSON as well as nlohmann.
2019-09-03 15:56:48 -05:00
jrkoonce 67e6160a9a Fixed move bugs 2019-09-03 10:42:39 -05:00
jrkoonce a3b8b355ae Merge branch 'pr/1' 2019-09-03 10:30:19 -05:00
jrkoonce 5145394239 Made C++14 optional, default off. 2019-09-03 09:48:30 -05:00
Syoyo Fujita 67aa2ca75e Merge pull request #200 from ux3d/feature/allow-scenes-without-nodes
allow scenes without nodes
2019-09-02 22:12:15 +09:00
Benjamin Schmithüsen ce25385eab remove extra parenthesis 2019-09-02 13:43:24 +02:00
Benjamin Schmithüsen 6143c6662b don't fail if a scene has no nodes property (which is not required) 2019-09-02 13:41:59 +02:00
Syoyo Fujita 81d75df48a Rename typeSizeInBytes to numComponents. 2019-08-30 19:19:52 +09:00
DingboDingboDingbo 83ccb9f28d GetTypeSizeInBytes not returning Type Size In Bytes
Changed name to be less misleading.
2019-08-29 18:49:15 -04:00
jrkoonce 9b6f52e98a Fix bug in ParseNumberArrayProperty()
Only doubles were being accepted instead of any number (including ordinals)
2019-08-29 13:56:58 -05:00
jrkoonce 5cecc41db9 More cleanup
1. Reserve array memory when converting JSON to Value for heap efficiency.
2. Grouped more JSON abstraction functions together and put in anonymous namespace instead of making each static.
2019-08-29 11:45:04 -05:00
jrkoonce 208c3058bf Remove test code accidentally commited 2019-08-29 11:28:07 -05:00
jrkoonce cba5d6caae RapidJson 1.1 support + More move semantics
*Support for RapidJson 1.1, use TINYGLTF_USE_RAPIDJSON to toggle between RapidJson and nlohmann

*Lot more move semantics enabled.  All parsing and serialization now move all json objects with far fewer copies
2019-08-29 11:26:22 -05:00
jrkoonce d1e1472992 Update tiny_gltf.h
Add/Enable move semantics to most all structs/classes
2019-08-27 11:51:02 -05:00
Syoyo Fujita ff51570c26 Apply clang format.
Remove `const static std::string` global variable.
2019-08-24 16:29:14 +09:00
Syoyo Fujita a472a3fa0f Add Set/Get SerializeDefaultValues method(W.I.P.) 2019-08-21 14:23:00 +09:00
Syoyo Fujita 1f160d5b8f Merge pull request #195 from ux3d/fix/parse-int-as-double
(also) parse int as double
2019-08-20 19:33:20 +09:00
Syoyo Fujita 5150a46072 Merge branch 'master' of github.com:syoyo/tinygltf 2019-08-20 17:11:29 +09:00
Syoyo Fujita cea69e37a5 Suppress clang warnings. 2019-08-20 17:10:30 +09:00
Syoyo Fujita 8b56c016ab Merge pull request #193 from Selmar/emissiveFactor_defaults
Emissive factor defaults
2019-08-20 13:13:12 +09:00
Benjamin Schmithüsen c7e205be87 when parsing a number from an int, also set the 'real value' to the value 2019-08-19 16:16:43 +02:00
Selmar Kok 6dba6c6aac [emissiveFactor] correct default values 2019-08-19 11:23:31 +02:00
Selmar Kok 6df800d2b6 [emissiveFactor] fix inconsistency with baseColorFactor where default values were set only for baseColorFactor and not emissiveFactor 2019-08-19 11:05:28 +02:00
Syoyo Fujita 2f044e77f1 Merge pull request #191 from Selmar/animation_extension_properties
Animation extension properties
2019-08-17 01:09:34 +09:00
Selmar Kok af5a5ef026 Merge branch 'master' of github.com:syoyo/tinygltf into animation_extension_properties 2019-08-16 17:54:14 +02:00
Syoyo Fujita 6591ba4461 Merge pull request #190 from ux3d/feature/parse-node-weights
parse/serialize node weights
2019-08-16 22:21:48 +09:00
Benjamin Schmithüsen 74c3c10121 serialize node weights 2019-08-16 14:24:26 +02:00
Benjamin Schmithüsen ad63bf748b parse node weights 2019-08-16 14:19:27 +02:00
Selmar Kok 5d43cf8e64 Merge branch 'master' of github.com:syoyo/tinygltf 2019-08-16 14:08:31 +02:00
Selmar Kok 4e2988eebd add extension property for Animation and AnimationChannel 2019-08-16 14:08:08 +02:00
Syoyo Fujita ee179b2cb6 Set default value of minFilter and magFilter in Sampler to -1(unset), since glTF 2.0 spec does not declare default values for it.
Fixes #186
2019-08-16 13:11:30 +09:00
Syoyo Fujita 4ebd6368fb Fix inequality of texture index check when serializing texture of material.
Texture info was written even if it have invalid index(-1). Fixes #189
2019-08-15 12:25:50 +09:00
Syoyo Fujita 67d3d2504d Merge pull request #188 from ux3d/fix/alphaMode
Fixed saving of alphaMode if not OPAQUE
2019-08-14 21:40:07 +09:00
Patrick Härtl d9a468bbb4 Fixed saving of alphaMode if not OPAQUE
Removed duplicated code for alphaCutoff
2019-08-14 14:14:07 +02:00
Syoyo Fujita c7bae71f7f Merge pull request #185 from DerouineauNicolas/endif
remove extra #endif in examples/basic app
2019-08-14 03:09:53 +09:00
nicolasDEROUINEAU f93642c196 remove extra #endif in examples/basic app 2019-08-13 15:08:01 +02:00
Syoyo Fujita f68d5e1f2a Merge pull request #182 from ux3d/textureinfo
[TextureInfo] fix default value checks for serialization
2019-07-26 01:29:23 +09:00
Benjamin Schmithüsen 1c84fc22a5 fix default value checks for serialization 2019-07-25 16:07:27 +02:00
Syoyo Fujita 150f243b1b Change the behavior of NUMBER value in Value class. NUMBER now reprents the value is either int or real(floating point). 2019-07-25 19:22:44 +09:00
Syoyo Fujita 0ee273fdfa Update README. Add note on tinygltf::Value for extensions. 2019-07-24 19:55:04 +09:00
Syoyo Fujita 046400b17f Now material is parsed as a struct with explicit parameter definitions.
Implement Material struct serialization.
2019-07-24 19:26:48 +09:00
Syoyo Fujita 89fd93f815 Introduce TextureInfo class(W.I.P.) 2019-07-23 22:37:06 +09:00
Syoyo Fujita e940337796 Merge pull request #180 from ux3d/master
Explicitly use the correct constructor for empty object
2019-07-23 18:55:34 +09:00
Syoyo Fujita 1b5f476d95 Merge pull request #178 from rapidimages/feature/write-to-streams
Serialize to stream
2019-07-17 18:53:35 +09:00
Johan Bowald 52936a00e0 clang format 2019-07-17 09:06:45 +02:00
Benjamin Schmithüsen f3ef880029 call json constructor explicitly 2019-07-16 17:07:45 +02:00
Johan Bowald 1af7c1d784 can write to streams 2019-07-16 15:56:18 +02:00
Benjamin Schmithüsen c0b79afecc Merge pull request #2 from syoyo/master
update from original repository
2019-07-15 15:13:50 +02:00
Syoyo Fujita c49461b7c2 Merge pull request #176 from ux3d/feature/update-lights
Feature: update lights
2019-07-10 21:20:12 +09:00
Benjamin Schmithüsen 051f4be2f1 serialize lights 2019-07-09 17:59:20 +02:00
Benjamin Schmithüsen 4557b6aa22 fix spot light parsingg 2019-07-09 16:55:55 +02:00
Benjamin Schmithüsen b2d7d88dbc parse additional light properties and fix defaults 2019-07-09 16:32:42 +02:00
Benjamin Schmithüsen b7ca7c9381 update lights to follow the KHR_lights_punctual extension 2019-07-08 18:04:24 +02:00
Benjamin Schmithüsen 0ffedcbe79 Merge pull request #1 from syoyo/master
update fork
2019-07-08 17:40:20 +02:00
Syoyo Fujita 80faac5238 Merge pull request #174 from Ybalrid/pr_material_param_tex_info
Add Parameter::TextureStrength(). Precise default values.
2019-07-05 14:11:15 +09:00
Arthur Brianville (Ybalrid) 2a9d9deb67 Applied clang-format 2019-07-05 00:30:47 +02:00
Arthur Brainville 8a98d98cd9 Add Paramter::TextureStrength(). Precise default values.
The default values on these methods as been set to what is described [here](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0?ts=4#normaltextureinfo) and [here](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0?ts=4#occlusiontextureinfo).

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

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

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

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

1. Validate that the primitive indices value is within the
   model->accessors bounds before dereferencing.
2. Validate that the accessors bufferView index if valid.
3. Validate that the buffer's index is valid when parsing images.
4. For glb files, validate that the overall length is within the
   provided input buffer.
2019-04-25 16:51:09 -07:00
Jeff McGlynn 9446f65667 Set up tests to run in travis-ci and ignore test outputs in .gitignore 2019-04-25 16:26:26 -07:00
Syoyo Fujita fb9f709166 Merge pull request #157 from Selmar/patch-1
correct Value::Equals mistake
2019-04-17 03:19:00 +09:00
Selmar a63cc6373d correct Value::Equals mistake
a missing exclamation mark... ^^
2019-04-16 16:57:43 +02:00
Syoyo Fujita b3c1471317 Merge pull request #155 from ffreling/accessor-normalized
Serialize accessor 'normalized' attribute.
2019-03-22 01:32:34 +09:00
Fabien Freling 9056aee823 Serialize accessor 'normalized' attribute. 2019-03-21 17:06:22 +01:00
Syoyo Fujita 29c431b2f2 Add build option with draco in Makefile. 2019-03-08 14:01:06 +09:00
Syoyo Fujita d06b2c2022 Merge pull request #154 from Ybalrid/patch-3
Fix the display of the version history
2019-03-08 13:32:31 +09:00
Arthur Brainville 339c9d578a Fix the display of the version history
Markdown is like HTML: simple line-breaks don't work.

Besides, making a list with dots here looks nicer :)
2019-03-07 19:40:57 +01:00
Syoyo Fujita 7c315fa8a8 Merge pull request #153 from Ybalrid/patch-2
fix a few typos in README.md
2019-03-07 21:30:20 +09:00
Arthur Brainville 0f04ed018a fix a few typos in README.md 2019-03-07 13:23:59 +01:00
Syoyo Fujita ca56f726d6 Merge branch '16bit-lodepng' 2019-03-07 21:04:25 +09:00
Syoyo Fujita e8a46c4e1d Update README.
Check bit depth when saving image as PNG.
2019-03-07 20:50:58 +09:00
Syoyo Fujita 9cd14a461b Update README. 2019-03-07 01:05:02 +09:00
Syoyo Fujita 1ef603ea2a Merge pull request #150 from Ybalrid/sparse_accessor
Sparse accessor
2019-03-07 00:49:29 +09:00
Arthur Brainville (Ybalrid) 14d259f361 glview can now load static geometry modified by sparse accessor 2019-03-06 14:48:44 +00:00
Arthur Brainville (Ybalrid) 9223d3133a Ran clang-format on tiny_gltf.h 2019-03-06 14:00:56 +00:00
Arthur Brainville (Ybalrid) 9b321a8515 clang-format + added sparse accessor in loader_example 2019-03-06 12:39:39 +00:00
Arthur Brainville (Ybalrid) 7e9f734d73 Parse sparse accessors 2019-03-06 12:27:23 +00:00
Arthur Brainville (Ybalrid) 9d86405d3d Fix accessor ctor 2019-03-06 11:33:30 +00:00
Arthur Brainville (Ybalrid) 1ccb4ff580 added sparse structure to accessors 2019-03-06 11:30:00 +01:00
Syoyo Fujita 8fd91aea04 Update TinyEXR. 2019-03-04 02:15:03 +09:00
Syoyo Fujita 8f76d790b8 Merge pull request #148 from Ybalrid/16bit-lodepng-good-byteswap
When writing out a 16bit image with lodepng, simplify the byteswap to big-endian
2019-03-04 01:15:20 +09:00
Arthur Brainville (Ybalrid) 853f6df7b5 Simplify byteswap code to convert to big endian 16bit 2019-03-03 16:26:20 +01:00
Syoyo Fujita 758a1240c9 Reorder 16 bit pixel data to big endian when saving it as 16 png, since lodepng::encode expects image data is in big endian manner.
Add OpenEXR saver for 16bit image as a bonus.
2019-03-03 21:21:18 +09:00
Syoyo Fujita 7bdfed3bec Add lodepng to save 16bit PNG.
Suppress clang/gcc warnings.
2019-03-03 17:04:49 +09:00
Syoyo Fujita bf9c2f4abd Merge pull request #146 from WARP-LAB/master
Fix for when json and stb is aready used in project
2019-03-03 15:31:09 +09:00
kroko fc0116b323 rename TINYGLTF_BYPASS_INCLUDE_x to TINYGLTF_NO_INCLUDE_x 2019-03-03 08:28:49 +02:00
Syoyo Fujita 962552c5c8 Merge pull request #145 from Ybalrid/upgrade_stb_libs
Upgrade the STB libraries, and fix #132
2019-03-03 13:39:10 +09:00
kroko 606e5dde31 be more precise in readme about include bypassing flags 2019-03-03 01:56:34 +02:00
kroko 6a0d4c57b1 Fix for when json and stb is aready used in project v2 2019-03-03 01:28:45 +02:00
kroko f4b6d11abc Fix for when json and stb is aready used in project 2019-03-03 01:11:31 +02:00
Arthur Brainville (Ybalrid) 5a4c898912 Fixed wrong metadata in case 16bit image wasn't actually loaded
The fallback to 8 bit would have been broken.
2019-03-02 22:03:34 +01:00
Arthur Brainville (Ybalrid) f2addc0e44 16bit images are 16bit images: added Image::bits and Image::pixel_type 2019-03-02 22:00:48 +01:00
Arthur Brainville (Ybalrid) 70d16a7b92 Upgrade the STB libraries, and fix #132 2019-03-02 16:10:54 +01:00
Syoyo Fujita 326d7ea310 Merge pull request #144 from SaschaWillems/master
Add direct access to texture coordinate set on texture parameter
2019-02-24 14:42:51 +09:00
Sascha Willems eb011068c0 Added function to easily access texture coordinate set index on a texture parameter 2019-02-23 21:15:45 +01:00
Syoyo Fujita 87be0ce34b Define WIN32_LEAN_AND_MEAN to save the number of including files. 2019-02-19 21:36:32 +09:00
Syoyo Fujita 7d9a0bda3a Define NOMINMAX to avoid defining MIN/MAX macros on Windows. Without defining NOMINMAX, MIN/MAX macro would affect other header/c++ files. Fixes #143 2019-02-19 16:03:23 +09:00
Syoyo Fujita 7ece5c8275 Merge pull request #142 from ebirenbaum/animation-sampler-interpolation
Change AnimationSampler::interpolation to a non-required field.
2019-02-15 14:04:06 +09:00
Evan Birenbaum 6bdffedcbe Change AnimationSampler::interpolation to a non-required field. The spec states to default to LINEAR when not present. 2019-02-14 13:30:57 -08:00
Syoyo Fujita d2fb7dc2af Merge pull request #140 from timmmeh/master
Adding default values for min and mag filter.
2019-02-10 00:01:11 +09:00
Syoyo Fujita c0d0251e2c Update json.hpp to fix compilation with clang with C++17(-std=c++1z) support. 2019-02-04 16:19:13 +09:00
timmmeh 62a72c4845 fix compile 2019-01-31 11:46:19 -08:00
timmmeh 73584ba7b7 Adding default values for min and mag filter. 2019-01-30 18:38:46 -08:00
Syoyo Fujita ead876fce9 Merge pull request #138 from dolphineye/dolphineye/add_mode_line_strip
Add line strip primitive mode define
2019-01-30 23:19:30 +09:00
Thomas Tissot 6c4a006496 Add line strip primitive mode define
This small commit adds the `TINYGLTF_MODE_LINE_STRIP` primitive mode
define whose value is set to `3` as per the GLTF 2.0 specification.
2019-01-30 13:10:51 +01:00
Syoyo Fujita 281af41b6c Merge pull request #137 from Ybalrid/pr_fix_glview_no_scene_no_nodes
Fix glView in case there is no default scene
2019-01-28 13:00:26 +09:00
Arthur Brainville (Ybalrid) 215e1fae61 handle not having default scene 2019-01-27 20:52:04 +00:00
Arthur Brainville (Ybalrid) cba75b9927 fix glview in case gltf asset doesn't have a default scene 2019-01-27 20:52:04 +00:00
Syoyo Fujita 4de57db325 Add TINYGLTF_ENABLE_DRACO flag to README. 2019-01-27 00:43:02 +09:00
Syoyo Fujita a32fa80102 Add support for building glview with draco.
Fix out-of-bounds access when calling DrawMesh().
Fix potential out-of-bounds access when filling window title string.
2019-01-27 00:38:34 +09:00
Syoyo Fujita 5f34dab548 Merge pull request #136 from abwood/draco
Fixed decoding bugs in draco
2019-01-26 23:22:55 +09:00
Alexander Wood 0d77a291f7 Updates to draco decoding:
- When injecting draco decoded meshes into accessor data, update count to match the optimized and decoded draco mesh
 - accessor.componentType is now used for extraction of decoded draco meshes.

Fixes #135
2019-01-26 08:58:45 -05:00
Syoyo Fujita b926195ef8 Merge pull request #134 from abwood/draco
Initial support for draco mesh compression
2019-01-25 16:45:33 +09:00
Alex Wood c8ba17fcab Looks like I'm colliding with work by syoyo. Only difference so far appears to be our macro name. 2019-01-24 15:45:16 -05:00
Alex Wood df39e04e7b Merge branch 'draco' of https://github.com/abwood/tinygltf into draco 2019-01-24 15:40:28 -05:00
Alex Wood 7319db7a50 Initial support for draco mesh compression. In this PR, we establish that draco is a dependency built external to tinygltf, which breaks from the current tradition of header only dependencies. For that reason, this feature is hidden behind a #define TINYGLTF_ENABLE_DRACO and requires developers to explicitly opt-in for draco support.
In this change, tinygltf any primitive using draco compression will:
If indices are specified
1) Decode the index buffer using draco, creating a new buffer and bufferview, adding to Model::bufferViews and Model::buffer collections
2) Update the primitive's accessor id to reference this new decoded bufferview.
For each attribute semantic specified by the draco extension
1) Decode the vertex buffer using draco, creating a new buffer and bufferview, adding to Model::bufferViews and Model::buffer collections
2) Update the primitive's accessor id to reference this new decoded bufferview.
2019-01-24 15:38:16 -05:00
Syoyo Fujita 7ae7110800 Begin supporting draco. 2019-01-19 03:03:22 +09:00
Syoyo Fujita b864ea7349 Support macOS + OpenGL 3.3+ GPU 2019-01-14 22:11:11 +09:00
Syoyo Fujita d6b0b0b990 Convert UTF16 file to UTF8.
Add premake project to build on Linux.
2019-01-14 21:30:53 +09:00
Syoyo Fujita af3ebb2e76 Show more expressive messages when parsing image. 2019-01-06 18:55:57 +09:00
Syoyo Fujita 105694b468 Merge pull request #129 from SaschaWillems/master
Added new compiler option for loading all gltf related files from android app asset package
2018-12-29 12:33:34 +09:00
Sascha Willems 5f9cb24245 Added new feature for loading all gltf related files (including textures, binaries, etc.) from assets packaged with an Android app 2018-12-28 20:53:41 +01:00
Syoyo Fujita 9fcd3f998e Merge pull request #127 from nyue/master
Renamed glTFConfig to TinyGLTFConfig
2018-12-28 14:31:33 +09:00
Tan Meng Yue d96b45df06 Renamed glTFConfig to TinyGLTFConfig
This renaming is done so that the config file matches
the project name which is TinyGLTF. This is done to prevent
future name collision should the Khronos glTF project decides
to provide their own CMake configuration file.
2018-12-27 10:24:13 +11:00
Syoyo Fujita dd7c9efbea Merge pull request #125 from nyue/master
Fix bug in handling OS X build via CMake
2018-12-25 15:06:37 +09:00
Tan Meng Yue 80a85af661 Fix bug in handling OS X build via CMake
The OS macros needs to be upper case for the
if statement to work as expected
2018-12-25 17:03:58 +11:00
Syoyo Fujita 7cf2c44ad7 Merge pull request #124 from nyue/master
Fix GLFW3 handling on CentOS
2018-12-25 11:27:33 +09:00
Nicholas Yue f1b5bb12fd Add support for static GLFW3 library linking 2018-12-25 09:48:26 +11:00
Nicholas Yue 174334eaf4 Fix GLFW3 handling on CentOS 2018-12-25 09:15:13 +11:00
Syoyo Fujita 1212a6ee51 Update README. 2018-12-24 01:50:17 +09:00
Syoyo Fujita 8674c60781 Add document on TINYGLTF_NO_EXTERNAL_IMAGE. Fixes #123 2018-12-18 21:59:23 +09:00
Syoyo Fujita 9d89f02cf0 Merge pull request #122 from lebek/master
Fix incorrect index into bufferViews array
2018-12-09 12:23:39 +09:00
Peter Le Bek 463408c4a0 Fix incorrect index into bufferViews array 2018-12-08 16:04:42 -08:00
Syoyo Fujita a9d862aeee Merge pull request #119 from nyue/master
Add CMake package for developer
2018-12-07 18:48:14 +09:00
Tan Meng Yue 2123da775b Add CMake package for developer
Added the glTFConfig.cmake file so that once
installed, it is easy for developers to find
all the path location for include purposes.
2018-12-07 20:45:13 +11:00
Syoyo Fujita 20806b27d7 Merge pull request #118 from nyue/master
Added more CMake support
2018-12-07 16:07:16 +09:00
Tan Meng Yue 94fcfdeb9d Added installation of headers and target binaries 2018-12-07 18:01:08 +11:00
Syoyo Fujita d44b6e7bcc Merge pull request #117 from viperscape/master
Fill in missing bufferView targets
2018-12-06 11:20:18 +09:00
viperscape 9df05806ad find missing bufferView target types and fill them in 2018-12-05 14:11:01 -05:00
Chris Gill 93db9e20c0 Merge pull request #1 from syoyo/master
update to latest
2018-12-05 13:03:44 -05:00
Syoyo Fujita 2c5597f591 Merge pull request #115 from Selmar/serialization_fixes
some serialization fixes
2018-12-06 02:05:26 +09:00
Tan Meng Yue 2dcf79566f Add CMake configuration for glview
So that we can build more of the examples consistently
with CMake
2018-12-05 23:56:23 +11:00
Tan Meng Yue f20888ae8b Added top level CMake configuration file 2018-12-05 23:55:53 +11:00
Selmar Kok 5892d3e3ea Set a default for sampler.wrapR, because it was serializing an uninitialized value 2018-12-04 19:55:56 +01:00
Selmar Kok 27aab61d62 Fix prettyprint to really not print pretty 2018-11-30 18:01:31 +01:00
Syoyo Fujita d80f0f9a6c Merge pull request #111 from viperscape/master
This is a basic example I added after figuring out how to use the tinygltf library
2018-11-16 14:01:13 +09:00
Syoyo Fujita 5110820ebb Merge pull request #110 from AlvaroBarua/warnings_cleanup
Removed unreachable code and fixed ambiguity warning.
2018-11-16 14:00:33 +09:00
viperscape c3e34c2ff7 add screenshot 2018-11-15 17:03:38 -05:00
viperscape 0ddfaead8f add basic example 2018-11-15 17:02:20 -05:00
Unknown ae2cf8e26f Removed unreachable code and fixed ambiguity warning. 2018-11-15 18:36:59 +00:00
Syoyo Fujita 8b7cdde30c Merge pull request #109 from viperscape/master
Windows build with provided VS solution
2018-11-15 00:28:06 +09:00
viperscape 764bcb5a8a add win32 includes 2018-11-14 10:19:39 -05:00
viperscape 50ada7ff11 rework to include VS 2017 project, fully configured and tested 2018-11-14 10:15:58 -05:00
Syoyo Fujita 16fae080f9 Merge branch 'master' of github.com:syoyo/tinygltf 2018-11-10 20:08:02 +09:00
Syoyo Fujita 90c0008b0e Merge branch 'loomai-master' 2018-11-10 20:07:47 +09:00
Syoyo Fujita b572650d26 Merge branch 'master' of https://github.com/loomai/tinygltf into loomai-master 2018-11-10 20:07:15 +09:00
Syoyo Fujita 6af9e886cd Merge pull request #107 from Selmar/serialization_fixes
Add missing serialization of `sampler.wrapR`
2018-11-10 02:32:56 +09:00
Selmar Kok 60f97325b1 Merge remote-tracking branch 'origin/master' into serialization_fixes 2018-11-09 10:34:55 +01:00
Selmar Kok a3595488e3 Fix missing serialization: sampler.wrapR 2018-11-09 10:34:39 +01:00
Syoyo Fujita cf60322e73 Merge pull request #105 from rapidimages/bugfix/write_image_to_disk
Fixed a reference error which cause an error when writing images to disk
2018-11-07 00:56:34 +09:00
Johan Bowald 77decfaff8 fixed a reference error which cause an error when writing images to disk 2018-11-06 14:28:20 +01:00
Syoyo Fujita e26117e026 Merge branch 'master' of github.com:syoyo/tinygltf 2018-11-05 13:33:27 +09:00
Syoyo Fujita 33514af61a Fix logic error. Fixes #104 2018-11-05 13:32:43 +09:00
Syoyo Fujita ba3c3c99ef Merge pull request #102 from 1div0/master
Building glview failed
2018-10-28 15:30:21 +09:00
Syoyo Fujita 8d96b4a14e Merge pull request #103 from Selmar/serialization_fixes
[serialization] handle failing buffer file writes
2018-10-26 02:12:24 +09:00
Selmar Kok 1cef6dcf33 Merge remote-tracking branch 'origin/master' into serialization_fixes 2018-10-25 16:48:14 +02:00
Selmar Kok e46774940c fail serialization if a buffer file fails to be written (e.g. due to access rights) 2018-10-25 16:45:49 +02:00
Peter Kovář dddaee695d Merge branch 'master' of https://github.com/1div0/tinygltf 2018-10-17 15:30:33 +02:00
Peter Kovář a645cfc840 Added include directory ../common/ for trackball.h 2018-10-17 15:29:56 +02:00
Peter Kovář 040310e0d3 Added include direectory ../common/ for trackball.h 2018-10-17 15:24:59 +02:00
Syoyo Fujita d9eddbfeb9 Merge pull request #101 from 1div0/master
make lint
2018-10-16 19:11:17 +09:00
Peter Kovář 10365a53ff Fixed make lint 2018-10-16 12:03:45 +02:00
Peter Kovář d0e293fd7d Fixed typos 2018-10-16 12:00:24 +02:00
Syoyo Fujita 3b25d9130a Merge pull request #100 from Selmar/serialization_fixes
yet another serialization fix
2018-10-11 01:25:12 +09:00
Selmar Kok db7f4e4d04 fix an issue when serializing an empty extension object would serialize as type null (and thus deserialize as type null, causing it to be ignored) 2018-10-10 18:10:58 +02:00
Syoyo Fujita 30bbe0fe3c Merge pull request #99 from Selmar/serialization_fixes
Pretty print & some (de)serialization fixes
2018-10-09 02:12:38 +09:00
Selmar Kok ee3d06646d // pretty print as optional parameter, default true
// serialize name instead of type for camera.name
// create empy Value::Object if extension value parsing failed
2018-10-08 16:20:43 +02:00
Syoyo Fujita 924d86e362 Serialize extension with empty object. Fixes #97
Use pretty printing JSON when serializing for the readability.
2018-10-08 21:18:33 +09:00
Syoyo Fujita 68353f1b34 Merge branch 'master' of github.com:syoyo/tinygltf 2018-10-07 20:35:14 +09:00
Syoyo Fujita 05a8d0bc52 Fix premake script. 2018-10-07 20:34:45 +09:00
Syoyo Fujita 39a263c2a8 Merge branch 'master' of github.com:syoyo/tinygltf 2018-10-06 03:20:31 +09:00
Syoyo Fujita 61673a62ef Update README. 2018-10-06 03:20:11 +09:00
Syoyo Fujita fdf105645b Merge pull request #96 from Selmar/serialization_fixes
Serialization & comparison fixes
2018-10-06 01:36:27 +09:00
Selmar Kok 440cb1e66b tabs to spaces 2018-10-05 16:30:50 +02:00
Selmar Kok c884e5827e better implementation for bin file name checking 2018-10-05 16:25:54 +02:00
Selmar Kok 7cb31e4e23 - support writing multiple bin files
- use existing buffer.uri as filename if not empty and not a data uri
2018-10-05 16:02:29 +02:00
Selmar Kok 2bda71c8fb - always check Parameter::number_value to catch user errors, e.g. setting number_value without setting has_number_value, which will cause it to serialize as a bool but read back in as a float anyway 2018-10-05 14:36:05 +02:00
Selmar Kok 13b6402388 Merge branch 'master' of github.com:syoyo/tinygltf into serialization_fixes 2018-10-05 14:30:16 +02:00
Selmar Kok 8eb3904de2 - Parse image extras property
- Optionally serialize texture.source (it is not required in the current spec)
2018-10-05 14:29:35 +02:00
Syoyo Fujita b5a72a1ba2 Remove duplicated files. 2018-10-04 15:48:17 +09:00
Syoyo Fujita 0820d83a9d Update to v2.0.1 2018-10-04 15:45:13 +09:00
Syoyo Fujita 641b3ccf8c Suppress clang warnings.
Apply clang-format.
2018-10-04 15:43:33 +09:00
Syoyo Fujita 7518334044 Merge pull request #95 from Selmar/equality_operator_and_some_additions
Equality operator and some additions
2018-10-04 13:56:35 +09:00
Syoyo Fujita efc919c022 Merge branch 'master' into devel 2018-10-04 13:55:21 +09:00
Selmar Kok fa0a998a8b Merge branch 'master' of github.com:syoyo/tinygltf into equality_operator_and_some_additions
# Conflicts:
#	tiny_gltf.h
2018-10-03 15:46:23 +02:00
Selmar Kok 31cb7f92d8 // equality operator for tinygltf::Model and types contained by it
// double comparison (although perhaps not necessary, as json reads/writes bytes directly? unsure..)
// initialize some variables for operator==() reliabiltiy
// change some floats to doubles
// intellisense define
// serialize accessor.name
// dont serialize some names if they're empty
// return false if writing gltf file fails
2018-10-03 15:39:05 +02:00
Syoyo Fujita e59dd6a5c0 Update TODOs. 2018-09-25 03:03:49 +09:00
Syoyo Fujita e66d8c992f Add as-is flag to Image. Tentative solution for issue #82 2018-09-02 16:58:43 +09:00
Syoyo Fujita 3e53feb046 Parse extensions property of Image. 2018-09-02 15:36:17 +09:00
Syoyo Fujita 9ec7109089 Bump clang version from 3.7 to 3.9 since clang-3.7 apt source is untrusted. 2018-08-30 21:27:11 +09:00
David Harmon da9eac2fbe Enable support for writing binary glTF. 2018-08-30 08:06:05 -04:00
Syoyo Fujita 5cf22e3abc Merge branch 'master' of github.com:syoyo/tinygltf 2018-08-28 21:34:06 +09:00
Syoyo Fujita a8f0b1c383 Suppress unknown pragma warning on clang 3.7 2018-08-28 21:33:40 +09:00
Syoyo Fujita 098dfee982 Merge pull request #92 from walf443/respect_stb_image_write_error
handling stbi_write_xxx_to_func return code
2018-08-28 21:33:07 +09:00
Keiji Yoshimi c0cfc1ed95 handling stbi_write_xxx_to_func return code 2018-08-28 21:13:03 +09:00
Syoyo Fujita be718436c1 Merge pull request #90 from victorbush/force_32bit_tex
Force default image loader to use 32-bit images
2018-08-23 12:51:43 +09:00
Victor Bushong 18ef338ff5 Force default image loader to use 32-bit images for Vulkan compatibility. 2018-08-22 22:03:30 -05:00
Syoyo Fujita 1d0bd6c64f Merge pull request #89 from Selmar/missing_bin_to_error_message
missing bin files are reported as warning instead of error
2018-08-23 02:16:10 +09:00
Selmar Kok e3b3fa9eb6 add required parameter to LoadExternalFile 2018-08-22 19:04:21 +02:00
Selmar Kok cda38e03ed change from warning to error for missing bin files 2018-08-22 18:26:10 +02:00
Syoyo Fujita fcdfc71ba6 Merge pull request #88 from Selmar/forward_declare_dataUri_utils
forward declare DataURI helpers
2018-08-22 21:36:16 +09:00
Selmar Kok 0d0e97e8cd forward declare DataURI helper functions to allow usage outside of implementation file (in case of custom image handling) 2018-08-22 14:01:57 +02:00
Syoyo Fujita dfc3545d79 Fix unit test.
Update README.
2018-08-22 20:35:04 +09:00
Syoyo Fujita 1898f10836 Merge branch 'devel' 2018-08-22 20:30:52 +09:00
Syoyo Fujita 96d2f314cd Merge pull request #86 from mosra/fail-when-bin-missing-from-glb
Properly fail also when external *.bin are missing from *.glb.
2018-08-17 19:52:09 +09:00
Vladimír Vondruš fd84ceb791 Properly fail also when external *.bin are missing from *.glb.
Consistency with behavior for external *.bin files referenced from
*.gltf.
2018-08-16 21:07:56 +02:00
Syoyo Fujita 6d38ca3894 Merge branch 'devel' of github.com:syoyo/tinygltf into devel 2018-08-16 15:57:28 +09:00
Syoyo Fujita a6802d10fb Fix typo(n2.z -> n1.z) 2018-08-16 15:56:13 +09:00
Syoyo Fujita 28dc902368 Add link to px_render. 2018-08-09 01:58:40 +09:00
Syoyo Fujita 7c8d4ed748 Added 'warning' message parameter to glTF loader API.
Asset loading failure messages(e.g. image file is missing) are now stored in `warning` message, not `error` message.
2018-07-27 16:49:10 +09:00
Syoyo Fujita a71be9cc98 Merge pull request #80 from mosra/texture-name
Import texture names as well
2018-07-25 13:51:41 +09:00
Syoyo Fujita 8c29e35b42 Merge pull request #81 from mosra/emscripten-file-paths
Don't try to expand file paths on Emscripten.
2018-07-25 13:51:00 +09:00
Vladimír Vondruš 9f04583280 Don't try to expand file paths on Emscripten.
Since the same is done on all mobile platforms already, I think it
should not do any harm. Without this I was getting compilation/linker
errors.
2018-07-24 23:32:17 +02:00
Vladimír Vondruš 239be2c09f Import texture names as well.
Every other structure has it already.
2018-07-24 23:23:56 +02:00
Syoyo Fujita 39abfb5f91 Consider Data URI buffers in binary. Fixes #79. 2018-07-11 02:46:52 +09:00
Syoyo Fujita 81bbf86e2a Merge pull request #78 from UberLambda/devel
Added filesystem callback support (#77)
2018-07-08 15:17:13 +09:00
Paolo Jovon b2a587af96 Fixed C++11 compliance of previous commit 2018-07-07 21:50:01 +02:00
Paolo Jovon e6601bfb4b Added filesystem callback support
Now a library like PhysFS can be used to load files by defining custom
callbacks and disabling the builtin ones by #define TINYGLTF_NO_FS
2018-07-07 20:43:33 +02:00
Syoyo Fujita 90e2c9cc74 Merge pull request #76 from mynz/devel
parse extras on the root object
2018-06-28 20:25:23 +02:00
mynz c0d4d1c50c parse extras on the root object 2018-06-28 23:06:00 +09:00
Syoyo Fujita 0f282f7e26 Merge pull request #75 from holzon/fix/allextras
Adding missing extras field serializaton
2018-06-04 19:07:49 +09:00
Jens Olsson b3af2f1cf6 adding missing extras field serializaton 2018-06-04 11:56:00 +02:00
Syoyo Fujita 4769b1ca37 Apply clang-format. 2018-06-04 18:40:16 +09:00
Syoyo Fujita 0067a9e43a Support gltf-buffer mime.
Make `min` and `max` parameters in `Accessor` optional.
2018-06-04 18:26:05 +09:00
Syoyo Fujita 57f8e7ca3b Correctly handle filename containing spaces for external resources. Fixes #74. 2018-06-04 17:52:08 +09:00
Syoyo Fujita a48f12d2fc Merge pull request #73 from holzon/fix/extras
Added missing extras serialization for nodes
2018-05-24 23:59:56 +09:00
Jens Olsson a9718668b4 fixing typo 2018-05-24 15:48:49 +02:00
Jens Olsson b96f6966ab added missing extras serialization for nodes 2018-05-24 15:29:54 +02:00
Syoyo Fujita 7c56f8eb9e Merge pull request #69 from benbuzbee/serialization-fixes
Serialization fixes for single-number values and integers
2018-04-26 14:06:18 +09:00
Ben Buzbee f6af224135 Remove use of optional 2018-04-25 15:13:05 -07:00
Ben Buzbee 3b735bb878 Serialization fixes 2018-04-24 11:39:30 -07:00
Syoyo Fujita 2d17a31d3b typedef struct -> struct for enabling forward declarations of struct. 2018-04-17 15:45:42 +09:00
Syoyo Fujita 48f6db0994 Suppress clang warnings. 2018-04-15 18:40:55 +09:00
Syoyo Fujita c89fc5f06b Describe supported VS 2015 update revision. 2018-04-12 11:52:14 +09:00
Syoyo Fujita 1e629c8efe Fix printing accessor.min and accessor.max in loader_example.
Initial support for printing extensions(no pretty printing at the moment).
Merge branch 'generic_extension_support' of https://github.com/Selmar/tinygltf into Selmar-generic_extension_support
2018-04-05 15:37:57 +09:00
Selmar Kok 341fc31aee Merge remote-tracking branch 'origin/devel' into generic_extension_support
# Conflicts:
#	tiny_gltf.h
2018-04-04 18:34:30 +02:00
Syoyo Fujita 7b0bbc6570 Merge branch 'devel' into Selmar-generic_extension_support 2018-04-05 01:27:03 +09:00
Selmar Kok 9eae110946 serialize texture extensions 2018-04-04 18:10:37 +02:00
Selmar Kok fa7022f364 Changed ExtensionMap to use Value instead of ParameterMap 2018-04-04 18:10:20 +02:00
Syoyo Fujita 6c67da478f Merge pull request #62 from bowald/feature/serializer-handle-image-output
small bugfix, serializer skipped texture samplers refering to first index.
2018-04-02 15:24:04 +09:00
johan bowald b97d34cfee bugfix, serializer skipped texture samplers refering to first index. 2018-04-02 07:29:29 +02:00
Syoyo Fujita 142aed7499 Merge pull request #61 from bowald/fix/readme-update
Updated readme
2018-04-02 12:42:49 +09:00
johan bowald ca80a591e0 updated readme: fixed example, fixed dead links to stb_image/stb_image_write 2018-04-01 22:57:07 +02:00
Syoyo Fujita dc4bb86bf1 Suppress clang warnings. 2018-04-02 02:04:24 +09:00
johan bowald ef151a4fed update examples with new defines 2018-04-01 14:08:45 +02:00
johan bowald 0894de77f9 added stb_image_write.h 2018-04-01 13:31:09 +02:00
johan bowald 642a343684 output both embedded and image files, small fix to serializer. 2018-04-01 12:37:18 +02:00
Syoyo Fujita 719d7e4a74 Suppress clang warnings.
Apply clang-format.
2018-03-30 19:26:35 +09:00
Syoyo Fujita 13fd7152ee Merge pull request #59 from bowald/feature/serializer-embed-buffer
Added embed buffers as an option in serializer
2018-03-30 19:17:18 +09:00
johan bowald 30c5347afe added embed buffers as an option in serializer 2018-03-30 11:52:56 +02:00
Syoyo Fujita 841c858bfd Merge pull request #58 from bowald/Bowald-serializer-fixes
Serializer skips null values
2018-03-28 22:09:08 +09:00
Johan Bowald faa2722f45 Serializer skips null values 2018-03-28 14:54:22 +02:00
Syoyo Fujita ae751c4882 Merge pull request #57 from Squareys/patch-1
Add Magnum's TinyGltfImporter plugin to projects
2018-03-28 19:23:39 +09:00
Jonathan Hale 6a04c87807 Add Magnum's TinyGltfImporter plugin to projects 2018-03-28 12:19:42 +02:00
Selmar Kok 5210f1539e Merge remote-tracking branch 'origin/devel' into generic_extension_support 2018-03-26 16:22:18 +02:00
Selmar Kok 35c798ed28 Merge remote-tracking branch 'origin/Selmar-generic_extension_support' into generic_extension_support 2018-03-26 16:20:44 +02:00
Syoyo Fujita 5e379693cb Merge pull request #55 from Ybalrid/pr_add_ogre_gltf_to_readme
Add Ogre_glTF to the list of projects using the lib
2018-03-22 02:09:49 +09:00
Arthur Brainville (Ybalrid) a403cd8736 Add Ogre_glTF to the list of projects using the lib
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-21 18:02:36 +01:00
Syoyo Fujita 246654a15a Code clean-up. Reviewed by @Squareeyes. 2018-03-21 20:32:22 +09:00
Syoyo Fujita ba28ddcc9e Modify error message. 2018-03-21 20:05:11 +09:00
Syoyo Fujita 8e2c24fb92 Refactor ParseImage function.
Returns error when both `bufferView` and `uri` are defined in Image.
2018-03-21 19:54:38 +09:00
Syoyo Fujita ba809ff52f Merge branch 'devel' of github.com:syoyo/tinygltf into devel 2018-03-21 18:52:53 +09:00
Syoyo Fujita d1f8bae89c Print extensions. 2018-03-21 18:48:03 +09:00
Syoyo Fujita 70d8b7a42b Merge pull request #53 from Ybalrid/gltfutil
Gltf utility
2018-03-20 11:01:22 +09:00
Syoyo Fujita 3f1c5a90d3 Merge pull request #54 from Ybalrid/fix_msvc_build_usage
Fix MSVC build: removing static keyowrd befor tinygltf::LoadImageData
2018-03-20 10:36:26 +09:00
Arthur Brainville 2960379eba Can select image file format with -f argument in gltf util
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-19 20:24:00 +01:00
Arthur Brainville 4ba01f5968 Add a "not specified" option to the enum class for image formats
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-19 20:06:59 +01:00
Arthur Brainville cd366ddd1d Fix MSVC build: removing static keyowrd befor tinygltf::LoadImageData
This is peculiar:
It looks like MSVC doesn't want to build when multiple compilation units
(e.g. multiple .cc files) uses tiny_gltf and this funciton is static.

The only one file that will build without error is the one that defined
the `TINYGLTF_IMPLEMENTATION` macro.

Removing `static` here solves the issue...

Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-19 19:54:05 +01:00
Arthur Brainville 68174a3fb3 Fix MSVC build: removing static keyowrd befor tinygltf::LoadImageData
This is peculiar:
It looks like MSVC doesn't want to build when multiple compilation units
(e.g. multiple .cc files) uses tiny_gltf and this funciton is static.

The only one file that will build without error is the one that defined
the `TINYGLTF_IMPLEMENTATION` macro.

Removing `static` here solves the issue...

Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-19 19:40:04 +01:00
Arthur Brainville (Ybalrid) 34c8b60325 Can specify output directory for dumped texture with -o
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-19 17:21:18 +01:00
Arthur Brainville (Ybalrid) 8d8840f809 Added basic texture dumper
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-19 17:11:53 +01:00
Selmar Kok 85b3cbc44d Merge branch 'devel' into generic_extension_support 2018-03-19 16:15:22 +01:00
Arthur Brainville ea2b1c5e5d Start working on a gltf utility program
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-19 15:49:14 +01:00
Syoyo Fujita d5b0244e2c Serialize lights under as KHR_lights_cmn extension. 2018-03-17 16:12:42 -05:00
Syoyo Fujita f1cdd1c4cb Merge pull request #52 from Selmar/opt_out_external_image_loading
Allow opting out of external image loading
2018-03-16 17:26:49 -05:00
Selmar Kok 2a15f387bc Merge branch 'devel' into generic_extension_support
# Conflicts:
#	tiny_gltf.h
2018-03-16 12:32:52 +01:00
Selmar Kok 5b8eb9b429 Merge branch 'devel' into opt_out_external_image_loading 2018-03-16 12:15:13 +01:00
Selmar 67af3c98aa Allow opting out of external image loading
We do not require image loading for external files, we have separate texture directories at the moment.

I've also added saving the image->uri when loading a binary gltf.
2018-03-16 11:48:19 +01:00
Syoyo Fujita 580d7c8b9f Parse defaultScene value correcrly. Fixes #47. 2018-03-15 22:09:01 -05:00
Syoyo Fujita e69069d53c Loading a GLB file without BIN data fails. Fixes #49. 2018-03-15 22:01:18 -05:00
Syoyo Fujita d42767e63f Store relative URI in Buffer serializer. Fixes #48.
Apply clang-format.
Add simple saver sample.
2018-03-15 21:52:00 -05:00
Selmar 7d8cbba8e4 removed code from another issue 2018-03-15 17:32:27 +01:00
Selmar 09d2ff12d8 generic extension support
Two issues remaining:
- The lights data exists twice on export; once outside of the gltf specification and once in the extensions.
- A lot of objects are still missing the extensions property.
2018-03-15 17:30:42 +01:00
Syoyo Fujita 20244e1e4e Fix storing uri to Buffer.uri. Fixes #50.
Fix decoding DataURI with 'data:application/gltf-buffer;base64' mime.
2018-03-15 11:01:05 -05:00
Syoyo Fujita 4f0b893d73 Merge pull request #45 from Squareys/custom-image-loaders
Allow custom image loaders
2018-03-14 10:07:49 +09:00
Squareys 2d3594de22 Allow opting out of STB_IMAGE dependency
Signed-off-by: Squareys <squareys@googlemail.com>
2018-03-13 23:08:03 +01:00
Squareys ff644d82c9 Allow specifying custom image loader callback
Signed-off-by: Squareys <squareys@googlemail.com>
2018-03-13 23:08:03 +01:00
Squareys f99f760b07 Clean up obsolete debug output
Signed-off-by: Squareys <squareys@googlemail.com>
2018-03-13 22:29:31 +01:00
Squareys 4337463c79 Remove trailing whitespaces
Signed-off-by: Squareys <squareys@googlemail.com>
2018-03-13 22:20:48 +01:00
Squareys 188965b11e Fix minor typo
Signed-off-by: Squareys <squareys@googlemail.com>
2018-03-13 22:20:01 +01:00
Syoyo Fujita 179edbf054 Fix empty serialization. Fixes #44. 2018-03-06 12:04:51 +09:00
Syoyo Fujita 1e94d05012 Merge pull request #43 from Ybalrid/devel
raytrace: remove code that ouput the 1st loaded texture as PPM
2018-03-03 02:15:44 +09:00
Arthur Brainville 92000ddeed raytrace: remove code that ouput the 1st loaded texture as PPM
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-02 16:58:30 +01:00
Syoyo Fujita abf4bd1800 Merge pull request #42 from Ybalrid/pr_raytrace_texture_loading
raytrace: add simple code that load texture data
2018-03-03 00:55:58 +09:00
Syoyo Fujita c14616d21c Merge pull request #41 from Ybalrid/pr_upgrade_imgui_imguizmo_raytrace
Upgraded dear imgui and ImGuizmo to the latest version
2018-03-03 00:43:18 +09:00
Arthur Brainville e832baf229 Restored previous behavior when moving node in scene
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-02 16:21:28 +01:00
Arthur Brainville df9003ea08 Update scene when moving gizmo
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-02 16:10:20 +01:00
Arthur Brainville ab156c7d18 Upgraded dear imgui and ImGuizmo to the latest version
The Gizmo feels a little bit nicer to use in the latest version

Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-02 15:49:01 +01:00
Arthur Brainville dd45c56927 raytrace: add simple code that load texture data
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-03-02 13:57:37 +01:00
Syoyo Fujita 0b01361d15 Fix return location. 2018-02-28 19:59:32 +09:00
Syoyo Fujita 493cad4e64 Merge pull request #40 from Ybalrid/pr_raytrace_example
Pr raytrace example
2018-02-28 00:04:07 +09:00
Arthur Brainville c227c5bddb Fixed triangle fan indices
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-27 12:47:06 +01:00
Arthur Brainville (Ybalrid) de8e3a6e6b Enforece some const correctness. Add comments.
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-25 01:23:04 +01:00
Arthur Brainville (Ybalrid) a5a03a2d44 Reorder UVs in vacevaying order
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-25 01:14:57 +01:00
Arthur Brainville (Ybalrid) 6cf0228fa7 Handle all types of triangle-based vertex buffer.
Some small codepath changes too.

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-25 00:52:50 +01:00
Arthur Brainville (Ybalrid) 1cd3b0f756 Fix pesudo -> pseudo typo
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-25 00:42:35 +01:00
Arthur Brainville (Ybalrid) 0e0a884378 Check the type of vectors before checking the type of their component
This order makes more sense.

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-24 22:09:17 +01:00
Arthur Brainville (Ybalrid) 8eb0fbb3d4 Fix the loading of normals by putting them into facevarying order
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-24 21:52:53 +01:00
Arthur Brainville (Ybalrid) 0da2b35085 Fixes problem when mesh in glTF file doesn't have a name
a "unnamed_X" name will be genrated.

This fixes the loading of Trinagle.gltf from khronos

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-23 15:15:33 +01:00
Arthur Brainville (Ybalrid) 55bff342c2 Merge branch 'pr_raytrace_example' of github.com:Ybalrid/tinygltf into pr_raytrace_example 2018-02-23 14:26:55 +01:00
Arthur Brainville (Ybalrid) 37ba0ae481 Log the types of data used by the currently loaded GLTF file
This will help test and improve compatibilitiy.

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-23 14:23:30 +01:00
Arthur Brainville (Ybalrid) 27ae4ba9c1 load texture coordinates
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:24 +01:00
Arthur Brainville 07e6c5c109 Small code cleanup
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:23 +01:00
Arthur Brainville 0b4f54162b Switch to unsigned int for the int arrays. Fix compatibility issue
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:23 +01:00
Arthur Brainville db1e8b3e8b added loading of doubles for position
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:23 +01:00
Arthur Brainville 2b211221c8 Add double type vector. Remove by default byte_stride value
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:22 +01:00
Arthur Brainville (Ybalrid) 72f535e198 Move defined types (array adapter templates) to the header
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:22 +01:00
Arthur Brainville (Ybalrid) 02fce26c6c Use default material as the 1st material on the array
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:22 +01:00
Arthur Brainville (Ybalrid) 7218e40bfd Fix pivot. Hack material to prevent crash
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:22 +01:00
Arthur Brainville (Ybalrid) 2b10d88e42 Load inside the scene graph the gltf mesh (like the obj)
pivot is still invalid

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:21 +01:00
Arthur Brainville aad6f06208 Fix linux build in C++11 strict
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:21 +01:00
Arthur Brainville b62e95f414 Load the normal vectors of the primitive
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:21 +01:00
Arthur Brainville ffc79a719b Also access the position attribute of the primitive
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:20 +01:00
Arthur Brainville (Ybalrid) ce75870894 Now load index buffer
Added some template infrastructure to read arrays where type is defined by a value.

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:20 +01:00
Arthur Brainville (Ybalrid) 49721f0fd4 Add the entry point for loading gltf files.
Also switch on the primitive mode of each mesh. Will only attempt to
load lists of triangles for now...

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:20 +01:00
Arthur Brainville (Ybalrid) 62da4688af Only attempt to load the obj file if the obj_filename is defined in json
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:20 +01:00
Arthur Brainville (Ybalrid) 365e56b779 Small adjustment to the NanoSG readme
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:19 +01:00
Arthur Brainville (Ybalrid) 1baa211450 Add files to .gitignore
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:19 +01:00
Arthur Brainville 01bf27443e Fix where stb image is actually implemented
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:18 +01:00
Arthur Brainville (Ybalrid) 7e91e9bb9f Setup CI for raytrace example
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:18 +01:00
Arthur Brainville (Ybalrid) 67f5fbd79e Add a gltf_filename feild to the renderconfig struct
This is to get the filename that will be given to the gltf-loader

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:18 +01:00
Arthur Brainville (Ybalrid) a6cbf3d35b Applyind clang-format on main.cc. Included gltf-loader
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:17 +01:00
Arthur Brainville (Ybalrid) 3903446bfc Move the implementation of stbi to it's own .cc file
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:17 +01:00
Arthur Brainville (Ybalrid) 8066a54415 Build the tinygltf loader code
Also remove the implementation of STB-Image from obj-loader.cc

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:17 +01:00
Arthur Brainville (Ybalrid) 3d63a08ce2 Make this code buildable as is
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:16 +01:00
Arthur Brainville (Ybalrid) d868aff1d1 Add the current code of nanort + nanosg
This implementation will be based on commit
b31dc0bd92eb7ac896079849a2205fac4abbd087 from the nanort project

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:16 +01:00
Arthur Brainville (Ybalrid) 6233b2e6bb Remove old nanort/nanosg code. Keep the gltf-loader class on hand
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-22 21:50:15 +01:00
Syoyo Fujita b09d660c38 Update premake script for glview example. Fixes #39. 2018-02-23 01:14:13 +09:00
Arthur Brainville (Ybalrid) 0dca478817 load texture coordinates
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-21 10:02:04 +01:00
Arthur Brainville b7bf01c679 Switch to unsigned int for the int arrays. Fix compatibility issue
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 21:47:22 +01:00
Arthur Brainville dc07a50ab7 added loading of doubles for position
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 21:43:07 +01:00
Arthur Brainville 6edd3a7f60 Add double type vector. Remove by default byte_stride value
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 21:40:55 +01:00
Arthur Brainville (Ybalrid) fac0ad9243 Move defined types (array adapter templates) to the header
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 15:55:23 +01:00
Arthur Brainville (Ybalrid) 58baa51463 Use default material as the 1st material on the array
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:57 +01:00
Arthur Brainville (Ybalrid) d095ef53c4 Fix pivot. Hack material to prevent crash
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:57 +01:00
Arthur Brainville (Ybalrid) 9993a71410 Load inside the scene graph the gltf mesh (like the obj)
pivot is still invalid

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:57 +01:00
Arthur Brainville e64e6d2d2a Fix linux build in C++11 strict
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:56 +01:00
Arthur Brainville db5b272a1b Load the normal vectors of the primitive
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:56 +01:00
Arthur Brainville 5682cb4542 Also access the position attribute of the primitive
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:56 +01:00
Arthur Brainville (Ybalrid) 7c54677acd Now load index buffer
Added some template infrastructure to read arrays where type is defined by a value.

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:56 +01:00
Arthur Brainville (Ybalrid) b8040e2a19 Add the entry point for loading gltf files.
Also switch on the primitive mode of each mesh. Will only attempt to
load lists of triangles for now...

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:56 +01:00
Arthur Brainville (Ybalrid) e42ba4e404 Only attempt to load the obj file if the obj_filename is defined in json
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:56 +01:00
Arthur Brainville (Ybalrid) cc4fd4be8e Small adjustment to the NanoSG readme
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:37 +01:00
Arthur Brainville (Ybalrid) f4fbee1cdf Add files to .gitignore
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:42:11 +01:00
Arthur Brainville 088aa0210f Fix where stb image is actually implemented
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:40:50 +01:00
Arthur Brainville (Ybalrid) 1340e62848 Setup CI for raytrace example
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-20 14:40:33 +01:00
Syoyo Fujita d800c88d09 Merge branch 'devel' of github.com:syoyo/tinygltf into devel 2018-02-19 19:28:17 +09:00
Syoyo Fujita ca8cfee824 Add link to Vulkan-glTF-PBR. 2018-02-19 18:05:47 +09:00
Arthur Brainville (Ybalrid) c9ec1ea7b6 Add a gltf_filename feild to the renderconfig struct
This is to get the filename that will be given to the gltf-loader

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-18 21:01:59 +01:00
Arthur Brainville (Ybalrid) adfe936dd3 Applyind clang-format on main.cc. Included gltf-loader
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-18 20:24:57 +01:00
Arthur Brainville (Ybalrid) e1e868a704 Move the implementation of stbi to it's own .cc file
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-18 20:09:24 +01:00
Arthur Brainville (Ybalrid) 75af411fda Build the tinygltf loader code
Also remove the implementation of STB-Image from obj-loader.cc

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-18 19:55:02 +01:00
Arthur Brainville (Ybalrid) 90ff6f7ce9 Make this code buildable as is
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-18 19:21:38 +01:00
Arthur Brainville (Ybalrid) c81be8f87d Add the current code of nanort + nanosg
This implementation will be based on commit
b31dc0bd92eb7ac896079849a2205fac4abbd087 from the nanort project

Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-18 19:16:16 +01:00
Arthur Brainville (Ybalrid) fb7ebb955e Remove old nanort/nanosg code. Keep the gltf-loader class on hand
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-18 19:13:57 +01:00
Syoyo Fujita c7ae1a3e76 Merge pull request #38 from o-micron/patch-2
Fix LoadImageData return value when error occurs
2018-02-10 16:53:00 +09:00
Omar C. F d492efc38a Fix return value when error occurs 2018-02-10 09:50:35 +02:00
Syoyo Fujita 568f05fec9 Merge pull request #37 from o-micron/patch-1
Add missing bmp and gif mimetypes
2018-02-10 16:11:35 +09:00
Omar C. F f8a8d9caa0 Add missing bmp and gif mimetypes 2018-02-10 09:09:41 +02:00
Syoyo Fujita 0d9a495fd1 Merge pull request #36 from Ybalrid/devel_add_gitignore
Add gitignore file
2018-02-02 00:57:32 +09:00
Arthur Brainville (Ybalrid) a62e955a52 Add gitignore file
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-02-01 15:38:34 +01:00
Syoyo Fujita 89cd83e22f Merge branch 'devel' of github.com:syoyo/tinygltf into devel 2018-01-21 12:20:00 +09:00
Syoyo Fujita 476a8b21b0 Set GL_DOUBLE value from OpenGL spec. Fixes #35. 2018-01-21 12:19:01 +09:00
Syoyo Fujita 05e0bf1cdc Suppress clang warnigns.
Refactor code to use C++11 features.
2018-01-16 18:55:13 +09:00
Syoyo Fujita f2aba36638 Add more note on Visual Studio version. 2018-01-11 14:06:10 +09:00
Syoyo Fujita 688236a3a8 Merge pull request #34 from Ybalrid/patch-1
Add language tags on code snippets in README
2018-01-10 20:52:24 +09:00
Arthur Brainville d93364e63f Add language tag on code snippets in README 2018-01-10 12:04:51 +01:00
Syoyo Fujita e3a7aef197 Describe note on Visual Studio version. 2018-01-10 18:32:51 +09:00
Syoyo Fujita 85ed1ac824 Merge pull request #33 from Ybalrid/CI_fix
Attempt to fix continuous integration (fix #31)
2018-01-10 18:30:45 +09:00
Arthur Brainville (Ybalrid) 760c1a5065 Change VS version to one that is better compatible with C++11
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-01-10 09:09:21 +01:00
Syoyo Fujita f0606e83d3 Merge pull request #32 from Ybalrid/narrowingConversionWarning
Silence a MSVC warning about narrowing conversion
2018-01-10 12:20:28 +09:00
Arthur Brainville 8ce4e54394 Silence a MSVC warning about narrowing conversion
We actually want to convert a size_t value into an int value in this
return statement.

Fix the annoying MSVC warning by actually casting the bytestride to an
int

Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-01-10 01:27:12 +01:00
Syoyo Fujita 45c29dc54d Update README of gltf-validator. 2018-01-09 14:28:16 +09:00
Syoyo Fujita 1b482fe0be Merge pull request #30 from Ybalrid/simplerMaterial
Simpler material data retreival
2018-01-09 12:19:03 +09:00
Arthur Brainville 9585391311 rename Color to ColorFactor
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-01-08 18:37:44 +01:00
Arthur Brainville 41fe772058 Const qualify const methods
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-01-08 18:32:48 +01:00
Arthur Brainville 5845319b1a Add little utility methods to access the content of a Parameter object
Signed-off-by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
2018-01-08 18:25:52 +01:00
Syoyo Fujita 1ebd29d84e Remove unnecessary text. 2018-01-05 20:21:27 +09:00
Syoyo Fujita f5318cc759 Describe more about C++ exception. 2018-01-05 20:17:37 +09:00
Syoyo Fujita 17cfbcc976 Fix argument to catch claus was wrong.
Add support to compile TinyGLTF with no C++ exception(TINYGLTF_NOEXCEPTION). Fixes #18.
Add initial unit tests.
2018-01-05 20:14:46 +09:00
Syoyo Fujita 584f8c0ddf Add method for computing byteStride to Accessor struct.
This would fix issue #29.
2018-01-03 17:47:08 +09:00
Syoyo Fujita 3ab8ee1f87 Add name of Adrien and many contributrors. 2017-12-31 18:36:02 +09:00
Syoyo Fujita daa726ec7c Merge pull request #28 from Ybalrid/devel
Create LICENSE file according to the terms of the MIT License agreement
2017-12-31 15:02:01 +09:00
Arthur Brainville 5194b47a16 Create LICENSE
This library is an awesome project, and I can imagine a lot of 3D application written in C++ would happily use it to load glTF assets ;-)

However, the license wasn't properly stated on the project. To actually put work under the term of the MIT license agreement, a copyright notice **needs** to be distributed alongside the source code.

It is also standard practice to add a warranty disclaimer. This prevent people to hold you liable if (at least they think) something doesn't work because of this library.

I took the liberty to put the file in place, with your full name as stated on your GitHub profile as the copyright holder. This is the text that states that you, the author, grants the to other people to use this as a free/open-source software, with all the thing that comes with it (access to source code, right to modify, redistribute, redistribute modified version, and use for any purpose they like) 

Sorry for the annoyance ^^"
2017-12-31 04:07:06 +00:00
Syoyo Fujita b66d68f3fb Report error message. 2017-12-19 18:45:22 +09:00
Syoyo Fujita 85591954ab Update README. 2017-12-19 18:29:34 +09:00
Syoyo Fujita dac2a89b63 Fix wrong return value(Fixes #26) 2017-12-19 17:58:32 +09:00
Syoyo Fujita 660256062b Update premake5.exe binary(5.0.0 alpha12). 2017-12-10 00:44:29 +09:00
Syoyo Fujita 87a76e1679 Merge branch 'patch-1' of https://github.com/cemdervis/tinygltf into cemdervis-patch-1 2017-12-10 00:39:52 +09:00
Syoyo Fujita 6bdd54f709 Rename premake config script. 2017-12-08 19:45:33 +09:00
Cemalettin Dervis f889d2b0dc Fixed typo ("RPEAT") 2017-12-07 21:58:15 +01:00
Cemalettin Dervis 246d866961 Fixed typo ("RPEAT") 2017-12-07 20:29:51 +01:00
Syoyo Fujita 06096520b8 Update README. 2017-12-03 17:26:25 +09:00
Syoyo Fujita 5307850555 Update README. 2017-06-21 19:27:18 +09:00
105 changed files with 55599 additions and 11746 deletions
+71
View File
@@ -0,0 +1,71 @@
# CMake
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
#Files created by the CI scripts (downloading and installing premake)
premake5
premake5.tar.gz
#built examples
/examples/raytrace/bin/
#visual studio files
*.sln
*.vcxproj*
.vs
#binary directories
bin/
obj/
#runtime gui config
imgui.ini
#visual stuido code
.vscode
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
loader_example
tests/tester
tests/tester_noexcept
tests/issue-97.gltf
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
if [[ "$TRAVIS_OS_NAME" == "osx" ]]
then
brew upgrade
curl -o premake5.tar.gz https://github.com/premake/premake-core/releases/download/v5.0.0-alpha12/premake-5.0.0-alpha12-macosx.tar.gz
else
wget https://github.com/premake/premake-core/releases/download/v5.0.0-alpha12/premake-5.0.0-alpha12-linux.tar.gz -O premake5.tar.gz
fi
tar xzf premake5.tar.gz
+13 -6
View File
@@ -7,15 +7,15 @@ matrix:
sources:
- george-edison55-precise-backports
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
- llvm-toolchain-trusty-3.9
packages:
- g++-4.9
- clang-3.7
- clang-3.9
compiler: clang
env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug
env: COMPILER_VERSION=3.9 BUILD_TYPE=Debug
- addons: *1
compiler: clang
env: COMPILER_VERSION=3.7 BUILD_TYPE=Release
env: COMPILER_VERSION=3.9 BUILD_TYPE=Release
- addons: &2
apt:
sources:
@@ -30,10 +30,10 @@ matrix:
env: COMPILER_VERSION=4.9 BUILD_TYPE=Release EXTRA_CXXFLAGS="-fsanitize=address"
- addons: *1
compiler: clang
env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug CFLAGS="-O0" CXXFLAGS="-O0"
env: COMPILER_VERSION=3.9 BUILD_TYPE=Debug CFLAGS="-O0" CXXFLAGS="-O0"
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi
- ./.travis-before-install.sh
script:
@@ -42,3 +42,10 @@ script:
- ${CC} -v
- ${CXX} ${EXTRA_CXXFLAGS} -std=c++11 -Wall -g -o loader_example loader_example.cc
- ./loader_example ./models/Cube/Cube.gltf
- cd tests
- make
- ./tester
- ./tester_noexcept
- cd ../examples/raytrace
- ../../premake5 gmake
- make
+28
View File
@@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.6)
PROJECT (tinygltf)
SET(CMAKE_CXX_STANDARD 11)
ADD_EXECUTABLE ( loader_example
loader_example.cc
)
ADD_SUBDIRECTORY ( examples/gltfutil )
ADD_SUBDIRECTORY ( examples/glview )
ADD_SUBDIRECTORY ( examples/validator )
INSTALL ( FILES
json.hpp
stb_image.h
stb_image_write.h
tiny_gltf.h
DESTINATION
include
)
INSTALL ( FILES
cmake/TinyGLTFConfig.cmake
DESTINATION
cmake
)
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+7 -3
View File
@@ -1,9 +1,13 @@
# Use this for strict compilation check(will work on clang 3.8+)
#EXTRA_CXXFLAGS := -fsanitize=address -Wall -Werror -Weverything -Wno-c++11-long-long -DTINYGLTF_APPLY_CLANG_WEVERYTHING
#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:
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:
./cpplint.py tiny_gltf_loader.h
deps/cpplint.py tiny_gltf.h
+113 -24
View File
@@ -2,9 +2,16 @@
`TinyGLTF` is a header only C++11 glTF 2.0 https://github.com/KhronosGroup/glTF library.
`TinyGLTF` uses Niels Lohmann's json library(https://github.com/nlohmann/json), so now it requires C++11 compiler.
If you are looking for old, C++03 version, please use `devel-picojson` branch.
## Status
Work in process(`devel` branch). Very near to release, but need more tests and examples.
- 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)!
## Builds
@@ -19,6 +26,9 @@ Work in process(`devel` branch). Very near to release, but need more tests and e
* [x] iOS + clang
* [x] Linux + gcc/clang
* [x] Windows + MinGW
* [x] Windows + Visual Studio 2015 Update 3 or later.
* Visual Studio 2013 is not supported since they have limited C++11 support and failed to compile `json.hpp`.
* [x] Android NDK
* [x] Android + CrystaX(NDK drop-in replacement) GCC
* [x] Web using Emscripten(LLVM)
* Moderate parsing time and memory consumption.
@@ -27,29 +37,58 @@ Work in process(`devel` branch). Very near to release, but need more tests and e
* [x] Binary glTF(GLB)
* [x] PBR material description
* Buffers
* [x] Parse BASE64 encoded embedded buffer fata(DataURI).
* [x] Parse BASE64 encoded embedded buffer data(DataURI).
* [x] Load `.bin` file.
* Image(Using stb_image)
* [x] Parse BASE64 encoded embedded image fata(DataURI).
* [x] Parse BASE64 encoded embedded image data(DataURI).
* [x] Load external image file.
* [x] PNG(8bit only)
* [x] JPEG(8bit only)
* [x] BMP
* [x] GIF
* [x] Load PNG(8bit and 16bit)
* [x] Load JPEG(8bit only)
* [x] Load BMP
* [x] Load GIF
* [x] Custom Image decoder callback(e.g. for decoding OpenEXR image)
* Morph traget
* [x] Sparse accessor
* Load glTF from memory
* Custom callback handler
* [x] Image load
* [x] Image save
* Extensions
* [x] Draco mesh decoding
## Note on extension property
In extension(`ExtensionMap`), JSON number value is parsed as int or float(number) and stored as `tinygltf::Value` object. If you want a floating point value from `tinygltf::Value`, use `GetNumberAsDouble()` method.
`IsNumber()` returns true if the underlying value is an int value or a floating point value.
## Examples
* [glview](examples/glview) : Simple glTF geometry viewer.
* [validator](examples/validator) : Simple glTF validator with JSON schema.
* [basic](examples/basic) : Basic glTF viewer with texturing support.
## Projects using TinyGLTF
* px_render Single header C++ Libraries for Thread Scheduling, Rendering, and so on... https://github.com/pplux/px
* Physical based rendering with Vulkan using glTF 2.0 models https://github.com/SaschaWillems/Vulkan-glTF-PBR
* GLTF loader plugin for OGRE 2.1. Support for PBR materials via HLMS/PBS https://github.com/Ybalrid/Ogre_glTF
* [TinyGltfImporter](http://doc.magnum.graphics/magnum/classMagnum_1_1Trade_1_1TinyGltfImporter.html) plugin for [Magnum](https://github.com/mosra/magnum), a lightweight and modular C++11/C++14 graphics middleware for games and data visualization.
* [Diligent Engine](https://github.com/DiligentGraphics/DiligentEngine) - A modern cross-platform low-level graphics library and rendering framework
* Your projects here! (Please send PR)
## TODOs
* [ ] Write C++ code generator from json schema for robust parsing.
* [x] Serialization
* [ ] Compression/decompression(Open3DGC, etc)
* [ ] Support `extensions` and `extras` property
* [ ] Write C++ code generator which emits C++ code from JSON schema for robust parsing.
* [ ] Mesh Compression/decompression(Open3DGC, etc)
* [x] Load Draco compressed mesh
* [ ] Save Draco compressed mesh
* [ ] Open3DGC?
* [x] Support `extensions` and `extras` property
* [ ] HDR image?
* [ ] Write tests for `animation` and `skin`
* [ ] OpenEXR extension through TinyEXR.
* [ ] 16bit PNG support in Serialization
* [ ] Write example and tests for `animation` and `skin`
## Licenses
@@ -59,29 +98,38 @@ TinyGLTF uses the following third party libraries.
* json.hpp : Copyright (c) 2013-2017 Niels Lohmann. MIT license.
* base64 : Copyright (C) 2004-2008 René Nyffenegger
* stb_image.h : v2.08 - public domain image loader - http://nothings.org/stb_image.h
* stb_image.h : v2.08 - public domain image loader - [Github link](https://github.com/nothings/stb/blob/master/stb_image.h)
* stb_image_write.h : v1.09 - public domain image writer - [Github link](https://github.com/nothings/stb/blob/master/stb_image_write.h)
## Build and example
Copy `stb_image.h`, `json.hpp` and `tiny_gltf.h` to your project.
Copy `stb_image.h`, `stb_image_write.h`, `json.hpp` and `tiny_gltf.h` to your project.
### Loading glTF 2.0 model
```
```c++
// Define these only in *one* .cc file.
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
// #define TINYGLTF_NOEXCEPTION // optional. disable exception handling.
#include "tiny_gltf.h"
using namespace tinygltf;
Model model;
Model model;
TinyGLTF loader;
std::string err;
bool ret = loader.LoadASCIIFromFile(&model, &err, argv[1]);
//bool ret = loader.LoadBinaryFromFile(&model, &err, argv[1]); // for binary glTF(.glb)
std::string warn;
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, argv[1]);
//bool ret = loader.LoadBinaryFromFile(&model, &err, &warn, argv[1]); // for binary glTF(.glb)
if (!warn.empty()) {
printf("Warn: %s\n", warn.c_str());
}
if (!err.empty()) {
printf("Err: %s\n", err.c_str());
}
@@ -92,19 +140,60 @@ if (!ret) {
}
```
### Saving gltTF 2.0 model
## Compile options
T.B.W.
* `TINYGLTF_NOEXCEPTION` : Disable C++ exception in JSON parsing. You can use `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION` and `TINYGLTF_NOEXCEPTION` to fully remove C++ exception codes when compiling TinyGLTF.
* `TINYGLTF_NO_STB_IMAGE` : Do not load images with stb_image. Instead use `TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)` to set a callback for loading images.
* `TINYGLTF_NO_STB_IMAGE_WRITE` : Do not write images with stb_image_write. Instead use `TinyGLTF::SetImageWriter(WriteimageDataFunction WriteImageData, void *user_data)` to set a callback for writing images.
* `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_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
* [ ] Buffers.
* [x] To file
* [x] Embedded
* [ ] Draco compressed?
* [x] Images
* [x] To file
* [x] Embedded
* [ ] Binary(.glb)
## Running tests.
### Setup
### glTF parsing test
#### Setup
Python 2.6 or 2.7 required.
Git clone https://github.com/KhronosGroup/glTF-Sample-Models to your local dir.
### Run test
#### Run parsing test
After building `loader_example`, edit `test_runner.py`, then,
$ python test_runner.py
```bash
$ python test_runner.py
```
### Unit tests
```bash
$ cd tests
$ make
$ ./tester
$ ./tester_noexcept
```
## Third party licenses
* 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.
* 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/
+6
View File
@@ -1,5 +1,8 @@
version: 0.9.{build}
image:
- Visual Studio 2015
# scripts that runs after repo cloning.
install:
- vcsetup.bat
@@ -10,3 +13,6 @@ configuration: Release
build:
parallel: true
project: TinyGLTFSolution.sln
after_build:
- examples.bat
+15
View File
@@ -0,0 +1,15 @@
# -*- cmake -*-
# - Find TinyGLTF
# TinyGLTF_INCLUDE_DIR TinyGLTF's include directory
FIND_PACKAGE ( PackageHandleStandardArgs )
SET ( TinyGLTF_INCLUDE_DIR "${TinyGLTF_DIR}/../include" CACHE STRING "TinyGLTF include directory")
FIND_FILE ( TinyGLTF_HEADER tiny_gltf.h PATHS ${TinyGLTF_INCLUDE_DIR} )
IF (NOT TinyGLTF_HEADER)
MESSAGE ( FATAL_ERROR "Unable to find tiny_gltf.h, TinyGLTF_INCLUDE_DIR = ${TinyGLTF_INCLUDE_DIR}")
ENDIF ()
+3
View File
@@ -0,0 +1,3 @@
cd examples\raytrace
..\..\tools\windows\premake5.exe vs2015
msbuild NanoSGSolution.sln /property:Configuration=Release
+7
View File
@@ -0,0 +1,7 @@
.vs
Debug
x64
packages
!*.sln
!*.vcxproj*
+21
View File
@@ -0,0 +1,21 @@
# Basic glTF viewer
## Requirements
* glew
* glfw3
* premake5(linux)
* OpenGL 3.3+ GPU
## Build on Linux and macOS
```
$ premake5 gmake
$ make
```
## Build on Visual Studio
Plese use solution file located at `basic` folder.
+31
View File
@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2050
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic", "basic.vcxproj", "{0589AC44-0CF3-40D8-8D89-68393CFD40F3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0589AC44-0CF3-40D8-8D89-68393CFD40F3}.Debug|x64.ActiveCfg = Debug|x64
{0589AC44-0CF3-40D8-8D89-68393CFD40F3}.Debug|x64.Build.0 = Debug|x64
{0589AC44-0CF3-40D8-8D89-68393CFD40F3}.Debug|x86.ActiveCfg = Debug|Win32
{0589AC44-0CF3-40D8-8D89-68393CFD40F3}.Debug|x86.Build.0 = Debug|Win32
{0589AC44-0CF3-40D8-8D89-68393CFD40F3}.Release|x64.ActiveCfg = Release|x64
{0589AC44-0CF3-40D8-8D89-68393CFD40F3}.Release|x64.Build.0 = Release|x64
{0589AC44-0CF3-40D8-8D89-68393CFD40F3}.Release|x86.ActiveCfg = Release|Win32
{0589AC44-0CF3-40D8-8D89-68393CFD40F3}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {055E97C4-43DC-41B4-8D61-4FDDBC7B1EF7}
EndGlobalSection
EndGlobal
+159
View File
@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{0589AC44-0CF3-40D8-8D89-68393CFD40F3}</ProjectGuid>
<RootNamespace>basic</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);opengl32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);opengl32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);opengl32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);opengl32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\main.cpp" />
<ClCompile Include="..\shaders.cpp" />
<ClCompile Include="..\window.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\shaders.h" />
<ClInclude Include="..\window.h" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="packages\nupengl.core.redist.0.1.0.1\build\native\nupengl.core.redist.targets" Condition="Exists('packages\nupengl.core.redist.0.1.0.1\build\native\nupengl.core.redist.targets')" />
<Import Project="packages\nupengl.core.0.1.0.1\build\native\nupengl.core.targets" Condition="Exists('packages\nupengl.core.0.1.0.1\build\native\nupengl.core.targets')" />
<Import Project="packages\glm.0.9.9.200\build\native\glm.targets" Condition="Exists('packages\glm.0.9.9.200\build\native\glm.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\nupengl.core.redist.0.1.0.1\build\native\nupengl.core.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\nupengl.core.redist.0.1.0.1\build\native\nupengl.core.redist.targets'))" />
<Error Condition="!Exists('packages\nupengl.core.0.1.0.1\build\native\nupengl.core.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\nupengl.core.0.1.0.1\build\native\nupengl.core.targets'))" />
<Error Condition="!Exists('packages\glm.0.9.9.200\build\native\glm.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\glm.0.9.9.200\build\native\glm.targets'))" />
</Target>
</Project>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\window.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\shaders.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\window.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\shaders.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="glm" version="0.9.9.200" targetFramework="native" />
<package id="nupengl.core" version="0.1.0.1" targetFramework="native" />
<package id="nupengl.core.redist" version="0.1.0.1" targetFramework="native" />
</packages>
+364
View File
@@ -0,0 +1,364 @@
#include <fstream>
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/gtc/matrix_transform.hpp>
#include "shaders.h"
#include "window.h"
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define TINYGLTF_NOEXCEPTION
#define JSON_NOEXCEPTION
#include "../../tiny_gltf.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
bool loadModel(tinygltf::Model &model, const char *filename) {
tinygltf::TinyGLTF loader;
std::string err;
std::string warn;
bool res = loader.LoadASCIIFromFile(&model, &err, &warn, filename);
if (!warn.empty()) {
std::cout << "WARN: " << warn << std::endl;
}
if (!err.empty()) {
std::cout << "ERR: " << err << std::endl;
}
if (!res)
std::cout << "Failed to load glTF: " << filename << std::endl;
else
std::cout << "Loaded glTF: " << filename << std::endl;
return res;
}
std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
tinygltf::Model &model, tinygltf::Mesh &mesh) {
for (size_t i = 0; i < model.bufferViews.size(); ++i) {
const tinygltf::BufferView &bufferView = model.bufferViews[i];
if (bufferView.target == 0) { // TODO impl drawarrays
std::cout << "WARN: bufferView.target is zero" << std::endl;
continue; // Unsupported bufferView.
/*
From spec2.0 readme:
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
... drawArrays function should be used with a count equal to
the count property of any of the accessors referenced by the
attributes property (they are all equal for a given
primitive).
*/
}
const tinygltf::Buffer &buffer = model.buffers[bufferView.buffer];
std::cout << "bufferview.target " << bufferView.target << std::endl;
GLuint vbo;
glGenBuffers(1, &vbo);
vbos[i] = vbo;
glBindBuffer(bufferView.target, vbo);
std::cout << "buffer.data.size = " << buffer.data.size()
<< ", bufferview.byteOffset = " << bufferView.byteOffset
<< std::endl;
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];
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
for (auto &attrib : primitive.attributes) {
tinygltf::Accessor accessor = model.accessors[attrib.second];
int byteStride =
accessor.ByteStride(model.bufferViews[accessor.bufferView]);
glBindBuffer(GL_ARRAY_BUFFER, vbos[accessor.bufferView]);
int size = 1;
if (accessor.type != TINYGLTF_TYPE_SCALAR) {
size = accessor.type;
}
int vaa = -1;
if (attrib.first.compare("POSITION") == 0) vaa = 0;
if (attrib.first.compare("NORMAL") == 0) vaa = 1;
if (attrib.first.compare("TEXCOORD_0") == 0) vaa = 2;
if (vaa > -1) {
glEnableVertexAttribArray(vaa);
glVertexAttribPointer(vaa, size, accessor.componentType,
accessor.normalized ? GL_TRUE : GL_FALSE,
byteStride, BUFFER_OFFSET(accessor.byteOffset));
} else
std::cout << "vaa missing: " << attrib.first << std::endl;
}
GLuint texid;
glGenTextures(1, &texid);
tinygltf::Texture &tex = model.textures[0];
tinygltf::Image &image = model.images[tex.source];
glBindTexture(GL_TEXTURE_2D, texid);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GLenum format = GL_RGBA;
if (image.component == 1) {
format = GL_RED;
} else if (image.component == 2) {
format = GL_RG;
} else if (image.component == 3) {
format = GL_RGB;
} else {
// ???
}
GLenum type = GL_UNSIGNED_BYTE;
if (image.bits == 8) {
// ok
} else if (image.bits == 16) {
type = GL_UNSIGNED_SHORT;
} else {
// ???
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0,
format, type, &image.image.at(0));
}
return vbos;
}
// bind models
void bindModelNodes(std::map<int, GLuint> vbos, tinygltf::Model &model,
tinygltf::Node &node) {
bindMesh(vbos, model, model.meshes[node.mesh]);
for (size_t i = 0; i < node.children.size(); i++) {
bindModelNodes(vbos, model, model.nodes[node.children[i]]);
}
}
GLuint bindModel(tinygltf::Model &model) {
std::map<int, GLuint> vbos;
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
const tinygltf::Scene &scene = model.scenes[model.defaultScene];
for (size_t i = 0; i < scene.nodes.size(); ++i) {
bindModelNodes(vbos, model, model.nodes[scene.nodes[i]]);
}
glBindVertexArray(0);
// cleanup vbos
for (size_t i = 0; i < vbos.size(); ++i) {
glDeleteBuffers(1, &vbos[i]);
}
return vao;
}
void drawMesh(tinygltf::Model &model, tinygltf::Mesh &mesh) {
for (size_t i = 0; i < mesh.primitives.size(); ++i) {
tinygltf::Primitive primitive = mesh.primitives[i];
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
glDrawElements(primitive.mode, indexAccessor.count,
indexAccessor.componentType,
BUFFER_OFFSET(indexAccessor.byteOffset));
}
}
// recursively draw node and children nodes of model
void drawModelNodes(tinygltf::Model &model, tinygltf::Node &node) {
drawMesh(model, model.meshes[node.mesh]);
for (size_t i = 0; i < node.children.size(); i++) {
drawModelNodes(model, model.nodes[node.children[i]]);
}
}
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) {
drawModelNodes(model, model.nodes[scene.nodes[i]]);
}
glBindVertexArray(0);
}
void dbgModel(tinygltf::Model &model) {
for (auto &mesh : model.meshes) {
std::cout << "mesh : " << mesh.name << std::endl;
for (auto &primitive : mesh.primitives) {
const tinygltf::Accessor &indexAccessor =
model.accessors[primitive.indices];
std::cout << "indexaccessor: count " << indexAccessor.count << ", type "
<< indexAccessor.componentType << std::endl;
tinygltf::Material &mat = model.materials[primitive.material];
for (auto &mats : mat.values) {
std::cout << "mat : " << mats.first.c_str() << std::endl;
}
for (auto &image : model.images) {
std::cout << "image name : " << image.uri << std::endl;
std::cout << " size : " << image.image.size() << std::endl;
std::cout << " w/h : " << image.width << "/" << image.height
<< std::endl;
}
std::cout << "indices : " << primitive.indices << std::endl;
std::cout << "mode : "
<< "(" << primitive.mode << ")" << std::endl;
for (auto &attrib : primitive.attributes) {
std::cout << "attribute : " << attrib.first.c_str() << std::endl;
}
}
}
}
glm::mat4 genView(glm::vec3 pos, glm::vec3 lookat) {
// Camera matrix
glm::mat4 view = glm::lookAt(
pos, // Camera in World Space
lookat, // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
return view;
}
glm::mat4 genMVP(glm::mat4 view_mat, glm::mat4 model_mat, float fov, int w,
int h) {
glm::mat4 Projection =
glm::perspective(glm::radians(fov), (float)w / (float)h, 0.01f, 1000.0f);
// 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
glm::mat4 mvp = Projection * view_mat * model_mat;
return mvp;
}
void displayLoop(Window &window, const std::string &filename) {
Shaders shader = Shaders();
glUseProgram(shader.pid);
// grab uniforms to modify
GLuint MVP_u = glGetUniformLocation(shader.pid, "MVP");
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;
GLuint vao = bindModel(model);
// dbgModel(model); return;
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 model_mat = glm::mat4(1.0f);
glm::mat4 model_rot = glm::mat4(1.0f);
glm::vec3 model_pos = glm::vec3(-3, 0, -3);
// generate a camera view, based on eye-position and lookAt world-position
glm::mat4 view_mat = genView(glm::vec3(2, 2, 20), model_pos);
glm::vec3 sun_position = glm::vec3(3.0, 10.0, -5.0);
glm::vec3 sun_color = glm::vec3(1.0);
while (!window.Close()) {
window.Resize();
glClearColor(0.2, 0.2, 0.2, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 trans =
glm::translate(glm::mat4(1.0f), model_pos); // reposition model
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;
// build a model-view-projection
GLint w, h;
glfwGetWindowSize(window.window, &w, &h);
glm::mat4 mvp = genMVP(view_mat, model_mat, 45.0f, w, h);
glUniformMatrix4fv(MVP_u, 1, GL_FALSE, &mvp[0][0]);
glUniform3fv(sun_position_u, 1, &sun_position[0]);
glUniform3fv(sun_color_u, 1, &sun_color[0]);
drawModel(vao, model);
glfwSwapBuffers(window.window);
glfwPollEvents();
}
}
static void error_callback(int error, const char *description) {
(void)error;
fprintf(stderr, "Error: %s\n", description);
}
int main(int argc, char **argv) {
std::string filename = "../../models/Cube/Cube.gltf";
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.
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#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;
}
+44
View File
@@ -0,0 +1,44 @@
solution "basic_viewer"
-- location ( "build" )
configurations { "Debug", "Release" }
platforms {"native", "x64", "x32"}
project "basic_viewer"
kind "ConsoleApp"
language "C++"
cppdialect "C++11"
files { "main.cpp", "shaders.cpp", "window.cpp" }
includedirs { "./" }
includedirs { "../../" }
includedirs { "../common/glm" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW", "X11", "Xrandr", "Xinerama", "Xi", "Xxf86vm", "Xcursor", "dl" }
configuration { "windows" }
-- Edit path to glew and GLFW3 fit to your environment.
includedirs { "../../../../local/glew-1.13.0/include/" }
includedirs { "../../../../local/glfw-3.2.bin.WIN32/include/" }
libdirs { "../../../../local/glew-1.13.0/lib/Release/Win32/" }
libdirs { "../../../../local/glfw-3.2.bin.WIN32/lib-vc2013/" }
links { "glfw3", "gdi32", "winmm", "user32", "glew32", "glu32","opengl32", "kernel32" }
defines { "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
includedirs { "/usr/local/include" }
buildoptions { "-Wno-deprecated-declarations" }
libdirs { "/usr/local/lib" }
links { "glfw", "GLEW" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" }
configuration "Debug"
defines { "DEBUG" }
symbols "On"
warnings "Extra"
configuration "Release"
defines { "NDEBUG" }
optimize "On"
warnings "Extra"
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

+114
View File
@@ -0,0 +1,114 @@
#include "shaders.h"
#include <iostream>
#include <vector>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
std::string FragmentShaderCode =
"#version 330 core\n\
in vec3 normal;\n\
in vec3 position;\n\
in vec2 texcoord;\n\
\n\
uniform sampler2D tex;\n\
uniform vec3 sun_position; \n\
uniform vec3 sun_color; \n\
\n\
out vec4 color;\n\
void main() {\n\
float lum = max(dot(normal, normalize(sun_position)), 0.0);\n\
color = texture(tex, texcoord) * vec4((0.3 + 0.7 * lum) * sun_color, 1.0);\n\
}\n\
";
std::string VertexShaderCode =
"#version 330 core\n\
layout(location = 0) in vec3 in_vertex;\n\
layout(location = 1) in vec3 in_normal;\n\
layout(location = 2) in vec2 in_texcoord;\n\
\n\
uniform mat4 MVP;\n\
\n\
out vec3 normal;\n\
out vec3 position;\n\
out vec2 texcoord;\n\
\n\
void main(){\n\
gl_Position = MVP * vec4(in_vertex, 1);\n\
position = gl_Position.xyz;\n\
normal = normalize(mat3(MVP) * in_normal);\n\
position = in_vertex;\n\
texcoord = in_texcoord;\n\
}";
Shaders::Shaders()
{
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
this->pid = ProgramID;
}
Shaders::~Shaders()
{
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
class Shaders
{
public:
GLuint pid;
Shaders();
~Shaders();
};
+27
View File
@@ -0,0 +1,27 @@
#include "window.h"
Window::Window(int x, int y, const char* title)
{
GLFWwindow* window = glfwCreateWindow(x, y, title, NULL, NULL);
this->window = window;
}
Window::~Window()
{
glfwDestroyWindow(this->window);
}
void Window::Resize()
{
GLint w, h;
glfwGetWindowSize(this->window, &w, &h);
glViewport(0, 0, w, h);
}
int Window::Close()
{
return glfwWindowShouldClose(this->window);
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <GLFW/glfw3.h>
class Window
{
public:
GLFWwindow* window;
Window(int x, int y, const char* title);
~Window();
void Resize();
int Close();
};
+21
View 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.
+358 -253
View File
@@ -21,7 +21,9 @@
// SOFTWARE.
#include "imgui.h"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "imgui_internal.h"
#include "ImGuizmo.h"
@@ -65,6 +67,8 @@ namespace ImGuizmo
//template <typename T> T LERP(T x, T y, float z) { return (x + (y - x)*z); }
template <typename T> T Clamp(T x, T y, T z) { return ((x<y) ? y : ((x>z) ? z : x)); }
template <typename T> T max(T x, T y) { return (x > y) ? x : y; }
template <typename T> T min(T x, T y) { return (x < y) ? x : y; }
template <typename T> bool IsWithin(T x, T y, T z) { return (x>=y) && (x<=z); }
struct matrix_t;
struct vec_t
@@ -86,7 +90,7 @@ namespace ImGuizmo
vec_t& operator -= (const vec_t& v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
vec_t& operator += (const vec_t& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
vec_t& operator *= (const vec_t& v) { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; }
vec_t& operator *= (float v) { x *= v; y *= v; z *= v; w *= v; return *this; }
vec_t& operator *= (float v) { x *= v; y *= v; z *= v; w *= v; return *this; }
vec_t operator * (float f) const;
vec_t operator - () const;
@@ -99,7 +103,7 @@ namespace ImGuizmo
float LengthSq() const { return (x*x + y*y + z*z); };
vec_t Normalize() { (*this) *= (1.f / Length()); return (*this); }
vec_t Normalize(const vec_t& v) { this->Set(v.x, v.y, v.z, v.w); this->Normalize(); return (*this); }
vec_t Abs() const;
vec_t Abs() const;
void Cross(const vec_t& v)
{
vec_t res;
@@ -147,7 +151,6 @@ namespace ImGuizmo
vec_t vec_t::operator + (const vec_t& v) const { return makeVect(x + v.x, y + v.y, z + v.z, w + v.w); }
vec_t vec_t::operator * (const vec_t& v) const { return makeVect(x * v.x, y * v.y, z * v.z, w * v.w); }
vec_t vec_t::Abs() const { return makeVect(fabsf(x), fabsf(y), fabsf(z)); }
ImVec2 operator+ (const ImVec2& a, const ImVec2& b) { return ImVec2(a.x + b.x, a.y + b.y); }
vec_t Normalized(const vec_t& v) { vec_t res; res = v; res.Normalize(); return res; }
vec_t Cross(const vec_t& v1, const vec_t& v2)
@@ -188,7 +191,7 @@ namespace ImGuizmo
{
vec_t right, up, dir, position;
} v;
vec_t component[4];
vec_t component[4];
};
matrix_t(const matrix_t& other) { memcpy(&m16[0], &other.m16[0], sizeof(float) * 16); }
@@ -491,7 +494,7 @@ namespace ImGuizmo
SCALE_Y,
SCALE_Z,
SCALE_XYZ,
BOUNDS
BOUNDS
};
struct Context
@@ -520,6 +523,7 @@ namespace ImGuizmo
vec_t mRayOrigin;
vec_t mRayVector;
float mRadiusSquareCenter;
ImVec2 mScreenSquareCenter;
ImVec2 mScreenSquareMin;
ImVec2 mScreenSquareMax;
@@ -551,23 +555,25 @@ namespace ImGuizmo
bool mBelowPlaneLimit[3];
float mAxisFactor[3];
// bounds stretching
vec_t mBoundsPivot;
vec_t mBoundsAnchor;
vec_t mBoundsPlan;
vec_t mBoundsLocalPivot;
int mBoundsBestAxis;
int mBoundsAxis[2];
bool mbUsingBounds;
matrix_t mBoundsMatrix;
// bounds stretching
vec_t mBoundsPivot;
vec_t mBoundsAnchor;
vec_t mBoundsPlan;
vec_t mBoundsLocalPivot;
int mBoundsBestAxis;
int mBoundsAxis[2];
bool mbUsingBounds;
matrix_t mBoundsMatrix;
//
int mCurrentOperation;
float mX = 0.f;
float mY = 0.f;
float mWidth = 0.f;
float mHeight = 0.f;
float mX = 0.f;
float mY = 0.f;
float mWidth = 0.f;
float mHeight = 0.f;
float mXMax = 0.f;
float mYMax = 0.f;
};
static Context gContext;
@@ -577,7 +583,11 @@ namespace ImGuizmo
static const vec_t directionUnary[3] = { makeVect(1.f, 0.f, 0.f), makeVect(0.f, 1.f, 0.f), makeVect(0.f, 0.f, 1.f) };
static const ImU32 directionColor[3] = { 0xFF0000AA, 0xFF00AA00, 0xFFAA0000 };
static const ImU32 selectionColor = 0xFF1080FF;
// Alpha: 100%: FF, 87%: DE, 70%: B3, 54%: 8A, 50%: 80, 38%: 61, 12%: 1F
static const ImU32 planeBorderColor[3] = { 0xFFAA0000, 0xFF0000AA, 0xFF00AA00 };
static const ImU32 planeColor[3] = { 0x610000AA, 0x6100AA00, 0x61AA0000 };
static const ImU32 selectionColor = 0x8A1080FF;
static const ImU32 inactiveColor = 0x99999999;
static const ImU32 translationLineColor = 0xAAAAAAAA;
static const char *translationInfoMask[] = { "X : %5.3f", "Y : %5.3f", "Z : %5.3f", "X : %5.3f Y : %5.3f", "Y : %5.3f Z : %5.3f", "X : %5.3f Z : %5.3f", "X : %5.3f Y : %5.3f Z : %5.3f" };
@@ -598,18 +608,16 @@ namespace ImGuizmo
static ImVec2 worldToPos(const vec_t& worldPos, const matrix_t& mat)
{
//ImGuiIO& io = ImGui::GetIO();
vec_t trans;
trans.TransformPoint(worldPos, mat);
trans *= 0.5f / trans.w;
trans += makeVect(0.5f, 0.5f);
trans.y = 1.f - trans.y;
trans.x *= gContext.mWidth;
trans.y *= gContext.mHeight;
trans.x += gContext.mX;
trans.y += gContext.mY;
return ImVec2(trans.x, trans.y);
trans.x *= gContext.mWidth;
trans.y *= gContext.mHeight;
trans.x += gContext.mX;
trans.y += gContext.mY;
return ImVec2(trans.x, trans.y);
}
static void ComputeCameraRay(vec_t &rayOrigin, vec_t &rayDir)
@@ -619,9 +627,9 @@ namespace ImGuizmo
matrix_t mViewProjInverse;
mViewProjInverse.Inverse(gContext.mViewMat * gContext.mProjectionMat);
float mox = ((io.MousePos.x - gContext.mX) / gContext.mWidth) * 2.f - 1.f;
float moy = (1.f - ((io.MousePos.y - gContext.mY) / gContext.mHeight)) * 2.f - 1.f;
float mox = ((io.MousePos.x - gContext.mX) / gContext.mWidth) * 2.f - 1.f;
float moy = (1.f - ((io.MousePos.y - gContext.mY) / gContext.mHeight)) * 2.f - 1.f;
rayOrigin.Transform(makeVect(mox, moy, 0.f, 1.f), mViewProjInverse);
rayOrigin *= 1.f / rayOrigin.w;
vec_t rayEnd;
@@ -641,23 +649,38 @@ namespace ImGuizmo
return -(numer / denom);
}
static bool IsInContextRect( ImVec2 p )
{
return IsWithin( p.x, gContext.mX, gContext.mXMax ) && IsWithin(p.y, gContext.mY, gContext.mYMax );
}
void SetRect(float x, float y, float width, float height)
{
gContext.mX = x;
gContext.mY = y;
gContext.mWidth = width;
gContext.mHeight = height;
gContext.mX = x;
gContext.mY = y;
gContext.mWidth = width;
gContext.mHeight = height;
gContext.mXMax = gContext.mX + gContext.mWidth;
gContext.mYMax = gContext.mY + gContext.mXMax;
}
void SetDrawlist()
{
gContext.mDrawList = ImGui::GetWindowDrawList();
}
void BeginFrame()
{
ImGuiIO& io = ImGui::GetIO();
ImGui::Begin("gizmo", NULL, io.DisplaySize, 0, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus);
gContext.mDrawList = ImGui::GetWindowDrawList();
const ImU32 flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus;
ImGui::SetNextWindowSize(io.DisplaySize);
ImGui::PushStyleColor(ImGuiCol_WindowBg, 0);
ImGui::Begin("gizmo", NULL, flags);
gContext.mDrawList = ImGui::GetWindowDrawList();
ImGui::End();
ImGui::PopStyleColor();
}
bool IsUsing()
@@ -673,11 +696,11 @@ namespace ImGuizmo
void Enable(bool enable)
{
gContext.mbEnable = enable;
if (!enable)
{
gContext.mbUsing = false;
gContext.mbUsingBounds = false;
}
if (!enable)
{
gContext.mbUsing = false;
gContext.mbUsingBounds = false;
}
}
static float GetUniform(const vec_t& position, const matrix_t& mat)
@@ -738,7 +761,8 @@ namespace ImGuizmo
{
int colorPlaneIndex = (i + 2) % 3;
colors[i + 1] = (type == (int)(MOVE_X + i)) ? selectionColor : directionColor[i];
colors[i + 4] = (type == (int)(MOVE_XY + i)) ? selectionColor : directionColor[colorPlaneIndex];
colors[i + 4] = (type == (int)(MOVE_XY + i)) ? selectionColor : planeColor[colorPlaneIndex];
colors[i + 4] = (type == MOVE_SCREEN) ? selectionColor : colors[i + 4];
}
break;
case ROTATE:
@@ -751,8 +775,6 @@ namespace ImGuizmo
for (int i = 0; i < 3; i++)
colors[i + 1] = (type == (int)(SCALE_X + i)) ? selectionColor : directionColor[i];
break;
default:
break;
}
}
else
@@ -848,7 +870,6 @@ namespace ImGuizmo
static void DrawRotationGizmo(int type)
{
ImDrawList* drawList = gContext.mDrawList;
//ImGuiIO& io = ImGui::GetIO();
// colors
ImU32 colors[7];
@@ -857,6 +878,7 @@ namespace ImGuizmo
vec_t cameraToModelNormalized = Normalized(gContext.mModel.v.position - gContext.mCameraEye);
cameraToModelNormalized.TransformVector(gContext.mModelInverse);
gContext.mRadiusSquareCenter = screenRotateSize * gContext.mHeight;
for (int axis = 0; axis < 3; axis++)
{
ImVec2 circlePos[halfCircleSegmentCount];
@@ -870,9 +892,14 @@ namespace ImGuizmo
vec_t pos = makeVect(axisPos[axis], axisPos[(axis+1)%3], axisPos[(axis+2)%3]) * gContext.mScreenFactor;
circlePos[i] = worldToPos(pos, gContext.mMVP);
}
drawList->AddPolyline(circlePos, halfCircleSegmentCount, colors[3 - axis], false, 2, true);
float radiusAxis = sqrtf( (ImLengthSqr(worldToPos(gContext.mModel.v.position, gContext.mViewProjection) - circlePos[0]) ));
if(radiusAxis > gContext.mRadiusSquareCenter)
gContext.mRadiusSquareCenter = radiusAxis;
drawList->AddPolyline(circlePos, halfCircleSegmentCount, colors[3 - axis], false, 2);
}
drawList->AddCircle(worldToPos(gContext.mModel.v.position, gContext.mViewProjection), screenRotateSize * gContext.mHeight, colors[0], 64);
drawList->AddCircle(worldToPos(gContext.mModel.v.position, gContext.mViewProjection), gContext.mRadiusSquareCenter, colors[0], 64, 3.f);
if (gContext.mbUsing)
{
@@ -889,8 +916,8 @@ namespace ImGuizmo
pos *= gContext.mScreenFactor;
circlePos[i] = worldToPos(pos + gContext.mModel.v.position, gContext.mViewProjection);
}
drawList->AddConvexPolyFilled(circlePos, halfCircleSegmentCount, 0x801080FF, true);
drawList->AddPolyline(circlePos, halfCircleSegmentCount, 0xFF1080FF, true, 2, true);
drawList->AddConvexPolyFilled(circlePos, halfCircleSegmentCount, 0x801080FF);
drawList->AddPolyline(circlePos, halfCircleSegmentCount, 0xFF1080FF, true, 2);
ImVec2 destinationPosOnScreen = circlePos[1];
char tmps[512];
@@ -918,9 +945,6 @@ namespace ImGuizmo
ImU32 colors[7];
ComputeColors(colors, type, SCALE);
// draw screen cirle
drawList->AddCircleFilled(gContext.mScreenSquareCenter, 12.f, colors[0], 32);
// draw
vec_t scaleDisplay = { 1.f, 1.f, 1.f, 1.f };
@@ -942,17 +966,20 @@ namespace ImGuizmo
if (gContext.mbUsing)
{
drawList->AddLine(baseSSpace, worldDirSSpaceNoScale, 0xFF404040, 6.f);
drawList->AddCircleFilled(worldDirSSpaceNoScale, 10.f, 0xFF404040);
drawList->AddLine(baseSSpace, worldDirSSpaceNoScale, 0xFF404040, 3.f);
drawList->AddCircleFilled(worldDirSSpaceNoScale, 6.f, 0xFF404040);
}
drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 6.f);
drawList->AddCircleFilled(worldDirSSpace, 10.f, colors[i + 1]);
drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 3.f);
drawList->AddCircleFilled(worldDirSSpace, 6.f, colors[i + 1]);
if (gContext.mAxisFactor[i] < 0.f)
DrawHatchedAxis(dirPlaneX * scaleDisplay[i]);
}
}
// draw screen cirle
drawList->AddCircleFilled(gContext.mScreenSquareCenter, 6.f, colors[0], 32);
if (gContext.mbUsing)
{
@@ -978,21 +1005,21 @@ namespace ImGuizmo
static void DrawTranslationGizmo(int type)
{
ImDrawList* drawList = gContext.mDrawList;
if (!drawList)
return;
if (!drawList)
return;
// colors
ImU32 colors[7];
ComputeColors(colors, type, TRANSLATE);
// draw screen quad
drawList->AddRectFilled(gContext.mScreenSquareMin, gContext.mScreenSquareMax, colors[0], 2.f);
const ImVec2 origin = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);
// draw
for (unsigned int i = 0; i < 3; i++)
bool belowAxisLimit = false;
bool belowPlaneLimit = false;
for (unsigned int i = 0; i < 3; ++i)
{
vec_t dirPlaneX, dirPlaneY;
bool belowAxisLimit, belowPlaneLimit;
ComputeTripodAxisAndVisibility(i, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
// draw axis
@@ -1001,8 +1028,20 @@ namespace ImGuizmo
ImVec2 baseSSpace = worldToPos(dirPlaneX * 0.1f * gContext.mScreenFactor, gContext.mMVP);
ImVec2 worldDirSSpace = worldToPos(dirPlaneX * gContext.mScreenFactor, gContext.mMVP);
drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 6.f);
drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 3.f);
// Arrow head begin
ImVec2 dir(origin - worldDirSSpace);
float d = sqrtf(ImLengthSqr(dir));
dir /= d; // Normalize
dir *= 6.0f;
ImVec2 ortogonalDir(dir.y, -dir.x); // Perpendicular vector
ImVec2 a(worldDirSSpace + dir);
drawList->AddTriangleFilled(worldDirSSpace - dir, a + ortogonalDir, a - ortogonalDir, colors[i + 1]);
// Arrow head end
if (gContext.mAxisFactor[i] < 0.f)
DrawHatchedAxis(dirPlaneX);
}
@@ -1011,15 +1050,18 @@ namespace ImGuizmo
if (belowPlaneLimit)
{
ImVec2 screenQuadPts[4];
for (int j = 0; j < 4; j++)
for (int j = 0; j < 4; ++j)
{
vec_t cornerWorldPos = (dirPlaneX * quadUV[j * 2] + dirPlaneY * quadUV[j * 2 + 1]) * gContext.mScreenFactor;
screenQuadPts[j] = worldToPos(cornerWorldPos, gContext.mMVP);
}
drawList->AddConvexPolyFilled(screenQuadPts, 4, colors[i + 4], true);
drawList->AddPolyline(screenQuadPts, 4, planeBorderColor[i], true, 1.0f);
drawList->AddConvexPolyFilled(screenQuadPts, 4, colors[i + 4]);
}
}
drawList->AddCircleFilled(gContext.mScreenSquareCenter, 6.f, colors[0], 32);
if (gContext.mbUsing)
{
ImVec2 sourcePosOnScreen = worldToPos(gContext.mMatrixOrigin, gContext.mViewProjection);
@@ -1040,176 +1082,233 @@ namespace ImGuizmo
}
}
static bool CanActivate()
{
if (ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered() && !ImGui::IsAnyItemActive())
return true;
return false;
}
static void HandleAndDrawLocalBounds(float *bounds, matrix_t *matrix, float *snapValues)
{
ImGuiIO& io = ImGui::GetIO();
ImDrawList* drawList = gContext.mDrawList;
ImGuiIO& io = ImGui::GetIO();
ImDrawList* drawList = gContext.mDrawList;
// compute best projection axis
vec_t bestAxisWorldDirection;
int bestAxis = gContext.mBoundsBestAxis;
if (!gContext.mbUsingBounds)
{
float bestDot = 0.f;
for (unsigned int i = 0; i < 3; i++)
{
vec_t dirPlaneNormalWorld;
dirPlaneNormalWorld.TransformVector(directionUnary[i], gContext.mModelSource);
dirPlaneNormalWorld.Normalize();
// compute best projection axis
vec_t axesWorldDirections[3];
vec_t bestAxisWorldDirection = { 0.0f, 0.0f, 0.0f, 0.0f };
int axes[3];
unsigned int numAxes = 1;
axes[0] = gContext.mBoundsBestAxis;
int bestAxis = axes[0];
if (!gContext.mbUsingBounds)
{
numAxes = 0;
float bestDot = 0.f;
for (unsigned int i = 0; i < 3; i++)
{
vec_t dirPlaneNormalWorld;
dirPlaneNormalWorld.TransformVector(directionUnary[i], gContext.mModelSource);
dirPlaneNormalWorld.Normalize();
float dt = Dot(Normalized(gContext.mCameraEye - gContext.mModelSource.v.position), dirPlaneNormalWorld);
if (fabsf(dt) >= bestDot)
{
bestDot = fabsf(dt);
bestAxis = i;
bestAxisWorldDirection = dirPlaneNormalWorld;
}
}
}
float dt = fabsf( Dot(Normalized(gContext.mCameraEye - gContext.mModelSource.v.position), dirPlaneNormalWorld) );
if ( dt >= bestDot )
{
bestDot = dt;
bestAxis = i;
bestAxisWorldDirection = dirPlaneNormalWorld;
}
// corners
vec_t aabb[4];
if( dt >= 0.1f )
{
axes[numAxes] = i;
axesWorldDirections[numAxes] = dirPlaneNormalWorld;
++numAxes;
}
}
}
int secondAxis = (bestAxis + 1) % 3;
int thirdAxis = (bestAxis + 2) % 3;
if( numAxes == 0 )
{
axes[0] = bestAxis;
axesWorldDirections[0] = bestAxisWorldDirection;
numAxes = 1;
}
else if( bestAxis != axes[0] )
{
unsigned int bestIndex = 0;
for (unsigned int i = 0; i < numAxes; i++)
{
if( axes[i] == bestAxis )
{
bestIndex = i;
break;
}
}
int tempAxis = axes[0];
axes[0] = axes[bestIndex];
axes[bestIndex] = tempAxis;
vec_t tempDirection = axesWorldDirections[0];
axesWorldDirections[0] = axesWorldDirections[bestIndex];
axesWorldDirections[bestIndex] = tempDirection;
}
for (int i = 0; i < 4; i++)
{
aabb[i][3] = aabb[i][bestAxis] = 0.f;
aabb[i][secondAxis] = bounds[secondAxis + 3 * (i >> 1)];
aabb[i][thirdAxis] = bounds[thirdAxis + 3 * ((i >> 1) ^ (i & 1))];
}
for (unsigned int axisIndex = 0; axisIndex < numAxes; ++axisIndex)
{
bestAxis = axes[axisIndex];
bestAxisWorldDirection = axesWorldDirections[axisIndex];
// draw bounds
unsigned int anchorAlpha = gContext.mbEnable ? 0xFF000000 : 0x80000000;
// corners
vec_t aabb[4];
matrix_t boundsMVP = gContext.mModelSource * gContext.mViewProjection;
for (int i = 0; i < 4;i++)
{
ImVec2 worldBound1 = worldToPos(aabb[i], boundsMVP);
ImVec2 worldBound2 = worldToPos(aabb[(i+1)%4], boundsMVP);
float boundDistance = sqrtf(ImLengthSqr(worldBound1 - worldBound2));
int stepCount = (int)(boundDistance / 10.f);
float stepLength = 1.f / (float)stepCount;
for (int j = 0; j < stepCount; j++)
{
float t1 = (float)j * stepLength;
float t2 = (float)j * stepLength + stepLength * 0.5f;
ImVec2 worldBoundSS1 = ImLerp(worldBound1, worldBound2, ImVec2(t1, t1));
ImVec2 worldBoundSS2 = ImLerp(worldBound1, worldBound2, ImVec2(t2, t2));
drawList->AddLine(worldBoundSS1, worldBoundSS2, 0xAAAAAA + anchorAlpha, 3.f);
}
vec_t midPoint = (aabb[i] + aabb[(i + 1) % 4] ) * 0.5f;
ImVec2 midBound = worldToPos(midPoint, boundsMVP);
static const float AnchorBigRadius = 8.f;
static const float AnchorSmallRadius = 6.f;
bool overBigAnchor = ImLengthSqr(worldBound1 - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
bool overSmallAnchor = ImLengthSqr(midBound - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
int secondAxis = (bestAxis + 1) % 3;
int thirdAxis = (bestAxis + 2) % 3;
unsigned int bigAnchorColor = overBigAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
unsigned int smallAnchorColor = overSmallAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
drawList->AddCircleFilled(worldBound1, AnchorBigRadius, bigAnchorColor);
drawList->AddCircleFilled(midBound, AnchorSmallRadius, smallAnchorColor);
int oppositeIndex = (i + 2) % 4;
// big anchor on corners
if (!gContext.mbUsingBounds && gContext.mbEnable && overBigAnchor && io.MouseDown[0])
{
gContext.mBoundsPivot.TransformPoint(aabb[(i + 2) % 4], gContext.mModelSource);
gContext.mBoundsAnchor.TransformPoint(aabb[i], gContext.mModelSource);
gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
gContext.mBoundsBestAxis = bestAxis;
gContext.mBoundsAxis[0] = secondAxis;
gContext.mBoundsAxis[1] = thirdAxis;
for (int i = 0; i < 4; i++)
{
aabb[i][3] = aabb[i][bestAxis] = 0.f;
aabb[i][secondAxis] = bounds[secondAxis + 3 * (i >> 1)];
aabb[i][thirdAxis] = bounds[thirdAxis + 3 * ((i >> 1) ^ (i & 1))];
}
gContext.mBoundsLocalPivot.Set(0.f);
gContext.mBoundsLocalPivot[secondAxis] = aabb[oppositeIndex][secondAxis];
gContext.mBoundsLocalPivot[thirdAxis] = aabb[oppositeIndex][thirdAxis];
// draw bounds
unsigned int anchorAlpha = gContext.mbEnable ? 0xFF000000 : 0x80000000;
gContext.mbUsingBounds = true;
gContext.mBoundsMatrix = gContext.mModelSource;
}
// small anchor on middle of segment
if (!gContext.mbUsingBounds && gContext.mbEnable && overSmallAnchor && io.MouseDown[0])
{
vec_t midPointOpposite = (aabb[(i + 2) % 4] + aabb[(i + 3) % 4]) * 0.5f;
gContext.mBoundsPivot.TransformPoint(midPointOpposite, gContext.mModelSource);
gContext.mBoundsAnchor.TransformPoint(midPoint, gContext.mModelSource);
gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
gContext.mBoundsBestAxis = bestAxis;
int indices[] = { secondAxis , thirdAxis };
gContext.mBoundsAxis[0] = indices[i%2];
gContext.mBoundsAxis[1] = -1;
matrix_t boundsMVP = gContext.mModelSource * gContext.mViewProjection;
for (int i = 0; i < 4;i++)
{
ImVec2 worldBound1 = worldToPos(aabb[i], boundsMVP);
ImVec2 worldBound2 = worldToPos(aabb[(i+1)%4], boundsMVP);
if( !IsInContextRect( worldBound1 ) || !IsInContextRect( worldBound2 ) )
{
continue;
}
float boundDistance = sqrtf(ImLengthSqr(worldBound1 - worldBound2));
int stepCount = (int)(boundDistance / 10.f);
stepCount = min( stepCount, 1000 );
float stepLength = 1.f / (float)stepCount;
for (int j = 0; j < stepCount; j++)
{
float t1 = (float)j * stepLength;
float t2 = (float)j * stepLength + stepLength * 0.5f;
ImVec2 worldBoundSS1 = ImLerp(worldBound1, worldBound2, ImVec2(t1, t1));
ImVec2 worldBoundSS2 = ImLerp(worldBound1, worldBound2, ImVec2(t2, t2));
drawList->AddLine(worldBoundSS1, worldBoundSS2, 0xAAAAAA + anchorAlpha, 3.f);
}
vec_t midPoint = (aabb[i] + aabb[(i + 1) % 4] ) * 0.5f;
ImVec2 midBound = worldToPos(midPoint, boundsMVP);
static const float AnchorBigRadius = 8.f;
static const float AnchorSmallRadius = 6.f;
bool overBigAnchor = ImLengthSqr(worldBound1 - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
bool overSmallAnchor = ImLengthSqr(midBound - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
gContext.mBoundsLocalPivot.Set(0.f);
gContext.mBoundsLocalPivot[gContext.mBoundsAxis[0]] = aabb[oppositeIndex][indices[i % 2]];// bounds[gContext.mBoundsAxis[0]] * (((i + 1) & 2) ? 1.f : -1.f);
unsigned int bigAnchorColor = overBigAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
unsigned int smallAnchorColor = overSmallAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
drawList->AddCircleFilled(worldBound1, AnchorBigRadius, bigAnchorColor);
drawList->AddCircleFilled(midBound, AnchorSmallRadius, smallAnchorColor);
int oppositeIndex = (i + 2) % 4;
// big anchor on corners
if (!gContext.mbUsingBounds && gContext.mbEnable && overBigAnchor && CanActivate())
{
gContext.mBoundsPivot.TransformPoint(aabb[(i + 2) % 4], gContext.mModelSource);
gContext.mBoundsAnchor.TransformPoint(aabb[i], gContext.mModelSource);
gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
gContext.mBoundsBestAxis = bestAxis;
gContext.mBoundsAxis[0] = secondAxis;
gContext.mBoundsAxis[1] = thirdAxis;
gContext.mbUsingBounds = true;
gContext.mBoundsMatrix = gContext.mModelSource;
}
}
if (gContext.mbUsingBounds)
{
matrix_t scale;
scale.SetToIdentity();
gContext.mBoundsLocalPivot.Set(0.f);
gContext.mBoundsLocalPivot[secondAxis] = aabb[oppositeIndex][secondAxis];
gContext.mBoundsLocalPivot[thirdAxis] = aabb[oppositeIndex][thirdAxis];
// compute projected mouse position on plan
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mBoundsPlan);
vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
gContext.mbUsingBounds = true;
gContext.mBoundsMatrix = gContext.mModelSource;
}
// small anchor on middle of segment
if (!gContext.mbUsingBounds && gContext.mbEnable && overSmallAnchor && CanActivate())
{
vec_t midPointOpposite = (aabb[(i + 2) % 4] + aabb[(i + 3) % 4]) * 0.5f;
gContext.mBoundsPivot.TransformPoint(midPointOpposite, gContext.mModelSource);
gContext.mBoundsAnchor.TransformPoint(midPoint, gContext.mModelSource);
gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
gContext.mBoundsBestAxis = bestAxis;
int indices[] = { secondAxis , thirdAxis };
gContext.mBoundsAxis[0] = indices[i%2];
gContext.mBoundsAxis[1] = -1;
// compute a reference and delta vectors base on mouse move
vec_t deltaVector = (newPos - gContext.mBoundsPivot).Abs();
vec_t referenceVector = (gContext.mBoundsAnchor - gContext.mBoundsPivot).Abs();
gContext.mBoundsLocalPivot.Set(0.f);
gContext.mBoundsLocalPivot[gContext.mBoundsAxis[0]] = aabb[oppositeIndex][indices[i % 2]];// bounds[gContext.mBoundsAxis[0]] * (((i + 1) & 2) ? 1.f : -1.f);
// for 1 or 2 axes, compute a ratio that's used for scale and snap it based on resulting length
for (int i = 0; i < 2; i++)
{
int axisIndex = gContext.mBoundsAxis[i];
if (axisIndex == -1)
continue;
gContext.mbUsingBounds = true;
gContext.mBoundsMatrix = gContext.mModelSource;
}
}
if (gContext.mbUsingBounds)
{
matrix_t scale;
scale.SetToIdentity();
float ratioAxis = 1.f;
vec_t axisDir = gContext.mBoundsMatrix.component[axisIndex].Abs();
// compute projected mouse position on plan
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mBoundsPlan);
vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
float dtAxis = axisDir.Dot(referenceVector);
float boundSize = bounds[axisIndex + 3] - bounds[axisIndex];
if (dtAxis > FLT_EPSILON)
ratioAxis = axisDir.Dot(deltaVector) / dtAxis;
// compute a reference and delta vectors base on mouse move
vec_t deltaVector = (newPos - gContext.mBoundsPivot).Abs();
vec_t referenceVector = (gContext.mBoundsAnchor - gContext.mBoundsPivot).Abs();
if (snapValues)
{
float length = boundSize * ratioAxis;
ComputeSnap(&length, snapValues[axisIndex]);
if (boundSize > FLT_EPSILON)
ratioAxis = length / boundSize;
}
scale.component[axisIndex] *= ratioAxis;
}
// for 1 or 2 axes, compute a ratio that's used for scale and snap it based on resulting length
for (int i = 0; i < 2; i++)
{
int axisIndex1 = gContext.mBoundsAxis[i];
if (axisIndex1 == -1)
continue;
// transform matrix
matrix_t preScale, postScale;
preScale.Translation(-gContext.mBoundsLocalPivot);
postScale.Translation(gContext.mBoundsLocalPivot);
matrix_t res = preScale * scale * postScale * gContext.mBoundsMatrix;
*matrix = res;
float ratioAxis = 1.f;
vec_t axisDir = gContext.mBoundsMatrix.component[axisIndex1].Abs();
// info text
char tmps[512];
ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);
ImFormatString(tmps, sizeof(tmps), "X: %.2f Y: %.2f Z:%.2f"
, (bounds[3] - bounds[0]) * gContext.mBoundsMatrix.component[0].Length() * scale.component[0].Length()
, (bounds[4] - bounds[1]) * gContext.mBoundsMatrix.component[1].Length() * scale.component[1].Length()
, (bounds[5] - bounds[2]) * gContext.mBoundsMatrix.component[2].Length() * scale.component[2].Length()
);
drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), 0xFF000000, tmps);
drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), 0xFFFFFFFF, tmps);
}
float dtAxis = axisDir.Dot(referenceVector);
float boundSize = bounds[axisIndex1 + 3] - bounds[axisIndex1];
if (dtAxis > FLT_EPSILON)
ratioAxis = axisDir.Dot(deltaVector) / dtAxis;
if (!io.MouseDown[0])
gContext.mbUsingBounds = false;
if (snapValues)
{
float length = boundSize * ratioAxis;
ComputeSnap(&length, snapValues[axisIndex1]);
if (boundSize > FLT_EPSILON)
ratioAxis = length / boundSize;
}
scale.component[axisIndex1] *= ratioAxis;
}
// transform matrix
matrix_t preScale, postScale;
preScale.Translation(-gContext.mBoundsLocalPivot);
postScale.Translation(gContext.mBoundsLocalPivot);
matrix_t res = preScale * scale * postScale * gContext.mBoundsMatrix;
*matrix = res;
// info text
char tmps[512];
ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);
ImFormatString(tmps, sizeof(tmps), "X: %.2f Y: %.2f Z:%.2f"
, (bounds[3] - bounds[0]) * gContext.mBoundsMatrix.component[0].Length() * scale.component[0].Length()
, (bounds[4] - bounds[1]) * gContext.mBoundsMatrix.component[1].Length() * scale.component[1].Length()
, (bounds[5] - bounds[2]) * gContext.mBoundsMatrix.component[2].Length() * scale.component[2].Length()
);
drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), 0xFF000000, tmps);
drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), 0xFFFFFFFF, tmps);
}
if (!io.MouseDown[0])
gContext.mbUsingBounds = false;
if( gContext.mbUsingBounds )
break;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1255,7 +1354,7 @@ namespace ImGuizmo
vec_t deltaScreen = { io.MousePos.x - gContext.mScreenSquareCenter.x, io.MousePos.y - gContext.mScreenSquareCenter.y, 0.f, 0.f };
float dist = deltaScreen.Length();
if (dist >= (screenRotateSize - 0.002f) * gContext.mHeight && dist < (screenRotateSize + 0.002f) * gContext.mHeight)
if (dist >= (gContext.mRadiusSquareCenter - 1.0f) && dist < (gContext.mRadiusSquareCenter + 1.0f))
type = ROTATE_SCREEN;
const vec_t planNormals[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir};
@@ -1327,6 +1426,7 @@ namespace ImGuizmo
// move
if (gContext.mbUsing)
{
ImGui::CaptureMouseFromApp();
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
@@ -1385,8 +1485,9 @@ namespace ImGuizmo
// find new possible way to move
vec_t gizmoHitProportion;
type = GetMoveType(&gizmoHitProportion);
if (io.MouseDown[0] && type != NONE)
if (CanActivate() && type != NONE)
{
ImGui::CaptureMouseFromApp();
gContext.mbUsing = true;
gContext.mCurrentOperation = type;
const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.up, -gContext.mCameraDir };
@@ -1409,8 +1510,9 @@ namespace ImGuizmo
{
// find new possible way to scale
type = GetScaleType();
if (io.MouseDown[0] && type != NONE)
if (CanActivate() && type != NONE)
{
ImGui::CaptureMouseFromApp();
gContext.mbUsing = true;
gContext.mCurrentOperation = type;
const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.up, gContext.mModel.v.right, -gContext.mCameraDir };
@@ -1429,6 +1531,7 @@ namespace ImGuizmo
// scale
if (gContext.mbUsing)
{
ImGui::CaptureMouseFromApp();
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
vec_t newOrigin = newPos - gContext.mRelativeOrigin * gContext.mScreenFactor;
@@ -1448,7 +1551,7 @@ namespace ImGuizmo
gContext.mScale[axisIndex] = max(ratio, 0.001f);
}
else
{
{
float scaleDelta = (io.MousePos.x - gContext.mSaveMousePosx) * 0.01f;
gContext.mScale.Set(max(1.f + scaleDelta, 0.001f));
}
@@ -1492,14 +1595,15 @@ namespace ImGuizmo
if (!gContext.mbUsing)
{
type = GetRotateType();
if (type == ROTATE_SCREEN)
{
applyRotationLocaly = true;
}
if (io.MouseDown[0] && type != NONE)
if (CanActivate() && type != NONE)
{
ImGui::CaptureMouseFromApp();
gContext.mbUsing = true;
gContext.mCurrentOperation = type;
const vec_t rotatePlanNormal[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir, -gContext.mCameraDir };
@@ -1523,6 +1627,7 @@ namespace ImGuizmo
// rotation
if (gContext.mbUsing)
{
ImGui::CaptureMouseFromApp();
gContext.mRotationAngle = ComputeAngleOnPlan();
if (snap)
{
@@ -1627,41 +1732,41 @@ namespace ImGuizmo
int type = NONE;
if (gContext.mbEnable)
{
if (!gContext.mbUsingBounds)
{
switch (operation)
{
case ROTATE:
HandleRotation(matrix, deltaMatrix, type, snap);
break;
case TRANSLATE:
HandleTranslation(matrix, deltaMatrix, type, snap);
break;
case SCALE:
HandleScale(matrix, deltaMatrix, type, snap);
break;
}
}
if (!gContext.mbUsingBounds)
{
switch (operation)
{
case ROTATE:
HandleRotation(matrix, deltaMatrix, type, snap);
break;
case TRANSLATE:
HandleTranslation(matrix, deltaMatrix, type, snap);
break;
case SCALE:
HandleScale(matrix, deltaMatrix, type, snap);
break;
}
}
}
if (localBounds && !gContext.mbUsing)
HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap);
if (localBounds && !gContext.mbUsing)
HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap);
if (!gContext.mbUsingBounds)
{
switch (operation)
{
case ROTATE:
DrawRotationGizmo(type);
break;
case TRANSLATE:
DrawTranslationGizmo(type);
break;
case SCALE:
DrawScaleGizmo(type);
break;
}
}
if (!gContext.mbUsingBounds)
{
switch (operation)
{
case ROTATE:
DrawRotationGizmo(type);
break;
case TRANSLATE:
DrawTranslationGizmo(type);
break;
case SCALE:
DrawScaleGizmo(type);
break;
}
}
}
void DrawCube(const float *view, const float *projection, float *matrix)
@@ -1713,7 +1818,7 @@ namespace ImGuizmo
continue;
// draw face with lighter color
gContext.mDrawList->AddConvexPolyFilled(faceCoordsScreen, 4, directionColor[normalIndex] | 0x808080, true);
gContext.mDrawList->AddConvexPolyFilled(faceCoordsScreen, 4, directionColor[normalIndex] | 0x808080);
}
}
};
+3
View File
@@ -112,6 +112,9 @@ void EditTransform(const Camera& camera, matrix_t& matrix)
namespace ImGuizmo
{
// call inside your own window and before Manipulate() in order to draw gizmo to that window.
IMGUI_API void SetDrawlist();
// call BeginFrame right after ImGui_XXXX_NewFrame();
IMGUI_API void BeginFrame();
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -17,6 +17,7 @@
#include "OpenGLWindow/X11OpenGLWindow.h"
#endif
#include <imgui_internal.h>
#include <cstdio>
#define IMGUI_B3G_CONTROL (300)
@@ -122,12 +123,12 @@ void ImGui_ImplBtGui_RenderDrawLists(ImDrawData* draw_data) {
(GLsizei)last_viewport[3]);
}
static const char* ImGui_ImplBtGui_GetClipboardText() {
static const char* ImGui_ImplBtGui_GetClipboardText(void* user_ctx) {
// @todo
return NULL; // glfwGetClipboardString(g_Window);
}
static void ImGui_ImplBtGui_SetClipboardText(const char* text) {
static void ImGui_ImplBtGui_SetClipboardText(void* user_ctx, const char* text) {
// @todo
return;
// glfwSetClipboardString(g_Window, text);
@@ -259,7 +260,7 @@ bool ImGui_ImplBtGui_Init(b3gDefaultOpenGLWindow* window) {
io.SetClipboardTextFn = ImGui_ImplBtGui_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplBtGui_GetClipboardText;
#ifdef _WIN32
//io.ImeWindowHandle = glfwGetWin32Window(g_Window);
// io.ImeWindowHandle = glfwGetWin32Window(g_Window);
#endif
#if 0
@@ -277,7 +278,7 @@ bool ImGui_ImplBtGui_Init(b3gDefaultOpenGLWindow* window) {
void ImGui_ImplBtGui_Shutdown() {
ImGui_ImplBtGui_InvalidateDeviceObjects();
ImGui::Shutdown();
ImGui::Shutdown(ImGui::GetCurrentContext());
}
void ImGui_ImplBtGui_NewFrame(int mouse_x, int mouse_y) {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1502 -602
View File
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.6)
project(gltfutil)
set(CMAKE_CXX_STANDARD 11)
include_directories(../../)
include_directories(../common/)
file(GLOB gltfutil_sources *.cc *.h)
add_executable(gltfutil ${gltfutil_sources} ../common/lodepng.cpp)
install ( TARGETS
gltfutil
DESTINATION
bin
)
+61
View File
@@ -0,0 +1,61 @@
#include <algorithm>
#include <array>
#include <fstream>
#include <iostream>
#include <string>
#include "texture_dumper.h"
namespace gltfutil {
enum class ui_mode { cli, interactive };
enum class cli_action { not_set, help, dump };
enum class FileType { Ascii, Binary, Unknown };
/// Probe inside the file, or check the extension to determine if we have to
/// load a text file, or a binary file
FileType detectType(const std::string& path) {
// Quickly open the file as binary and chekc if there's the gltf binary magic
// number
{
auto probe = std::ifstream(path, std::ios_base::binary);
if (!probe) throw std::runtime_error("Could not open " + path);
std::array<char, 5> buffer;
for (size_t i{0}; i < 4; ++i) probe >> buffer[i];
buffer[4] = 0;
if (std::string("glTF") == std::string(buffer.data())) {
std::cout
<< "Detected binary file thanks to the magic number at the start!\n";
return FileType::Binary;
}
}
// If we don't have any better, check the file extension.
auto extension = path.substr(path.find_last_of('.') + 1);
std::transform(std::begin(extension), std::end(extension),
std::begin(extension),
[](char c) { return char(::tolower(int(c))); });
if (extension == "gltf") return FileType::Ascii;
if (extension == "glb") return FileType::Binary;
return FileType::Unknown;
}
struct configuration {
std::string input_path, output_dir;
ui_mode mode;
cli_action action = cli_action::not_set;
texture_dumper::texture_output_format requested_format =
texture_dumper::texture_output_format::not_specified;
bool use_exr = false;
bool has_output_dir;
bool is_valid() {
// TODO impl check
return true;
}
};
} // namespace gltfutil
+136
View File
@@ -0,0 +1,136 @@
#include <iostream>
#include <string>
#include "gltfuilconfig.h"
#include "texture_dumper.h"
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#include <tiny_gltf.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define TINYEXR_IMPLEMENTATION
#include "tinyexr.h"
namespace gltfutil {
int usage(int ret = 0) {
using std::cout;
cout << "gltfutil: tool for manipulating gltf files\n"
<< " usage information:\n\n"
<< "\t gltfutil (-d|-h|) (-f [png|bmp|tga]) [path to .gltf/glb] (-o "
"[path to output directory])\n\n"
//<< "\t\t -i: start in interactive mode\n"
<< "\t\t -d: dump enclosed content (image assets)\n"
<< "\t\t -f: file format for image output\n"
<< "\t\t -o: ouptput directory path\n"
<< "\t\t -e: Use OpenEXR format for 16bit image\n"
<< "\t\t -h: print this help\n";
return ret;
}
int arg_error() {
(void)usage();
return -1;
}
int parse_args(int argc, char** argv) {
gltfutil::configuration config;
for (size_t i = 1; i < size_t(argc); ++i) {
char* arg = argv[i];
if (arg[0] == '-') switch (arg[1]) {
case 'h':
return usage(0);
break;
case 'd':
config.mode = ui_mode::cli;
config.action = cli_action::dump;
break;
case 'e':
config.use_exr = true;
break;
case 'i':
config.mode = ui_mode::interactive;
break;
case 'o':
i++;
config.output_dir = argv[i];
break;
case 'f':
i++;
config.requested_format =
texture_dumper::get_fromat_from_string(argv[i]);
break;
default:
return arg_error();
}
else {
// set the input path
config.input_path = argv[i];
}
}
if (config.is_valid()) {
tinygltf::TinyGLTF loader;
tinygltf::Model model;
std::string error;
std::string warning;
bool state;
switch (detectType(config.input_path)) {
case FileType::Ascii:
state = loader.LoadASCIIFromFile(&model, &error, &warning, config.input_path);
break;
case FileType::Binary:
state = loader.LoadBinaryFromFile(&model, &error, &warning, config.input_path);
break;
case FileType::Unknown:
default:
return arg_error();
break;
}
std::cerr << "state is " << state << '\n';
if (config.mode == ui_mode::interactive) {
// interactive usage now;
// TODO impl
} else {
switch (config.action) {
case cli_action::help:
return usage();
break;
case cli_action::dump: {
texture_dumper dumper(model);
if (config.use_exr) {
dumper.set_use_exr(true);
}
if (config.requested_format !=
texture_dumper::texture_output_format::not_specified)
dumper.set_output_format(config.requested_format);
if (config.output_dir.empty())
dumper.dump_to_folder();
else
dumper.dump_to_folder(config.output_dir);
} break;
default:
return arg_error();
}
}
} else {
return arg_error();
}
return 0;
}
} // namespace gltfutil
int main(int argc, char* argv[]) {
if (argc == 1) return gltfutil::usage();
if (argc > 1) return gltfutil::parse_args(argc, argv);
}
File diff suppressed because it is too large Load Diff
+169
View File
@@ -0,0 +1,169 @@
#include <algorithm>
#include <iostream>
#include "stb_image_write.h"
#include "texture_dumper.h"
#include "lodepng.h" // ../common
#include "tinyexr.h"
#include <tiny_gltf.h>
using namespace gltfutil;
using namespace tinygltf;
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)
: model(input), configured_format(texture_output_format::png) {
cout << "Texture dumper\n";
}
void texture_dumper::dump_to_folder(const std::string& path) {
cout << "dumping to folder " << path << '\n';
cout << "model file has " << model.textures.size() << " textures.\n";
size_t index = 0;
for (const auto& texture : model.textures) {
index++;
const auto& image = model.images[texture.source];
cout << "image name is: \"" << image.name << "\"\n";
cout << "image size is: " << image.width << 'x' << image.height << '\n';
cout << "pixel channel count :" << image.component << '\n';
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) {
case texture_output_format::png:
filename = path + "/" + basename + ".png";
if (this->use_exr) {
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;
case texture_output_format::bmp:
filename = path + "/" + basename + ".bmp";
std::cout << "Image will be written to " << filename << '\n';
stbi_write_bmp(filename.c_str(), image.width, image.height,
image.component, bytes_to_write);
break;
case texture_output_format::tga:
filename = path + "/" + basename + ".tga";
std::cout << "Image will be written to " << filename << '\n';
stbi_write_tga(filename.c_str(), image.width, image.height,
image.component, bytes_to_write);
break;
}
}
}
void texture_dumper::set_output_format(texture_output_format format) {
configured_format = format;
}
texture_dumper::texture_output_format texture_dumper::get_fromat_from_string(
const std::string& str) {
std::string type = str;
std::transform(str.begin(), str.end(), type.begin(), ::tolower);
if (type == "png") return texture_output_format::png;
if (type == "bmp") return texture_output_format::bmp;
if (type == "tga") return texture_output_format::tga;
return texture_output_format::not_specified;
}
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <string>
#include <tiny_gltf.h>
namespace gltfutil {
class texture_dumper {
public:
enum class texture_output_format { png, bmp, tga, not_specified };
private:
const tinygltf::Model& model;
texture_output_format configured_format;
bool use_exr = false; // Use EXR for 16bit image?
public:
texture_dumper(const tinygltf::Model& inputModel);
void dump_to_folder(const std::string& path = "./");
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);
};
} // namespace gltfutil
+7
View File
@@ -0,0 +1,7 @@
.vs
Debug
x64
packages
!*.sln
!*.vcxproj*
+69
View File
@@ -0,0 +1,69 @@
cmake_minimum_required(VERSION 3.5)
project(glview)
set ( CMAKE_PREFIX_PATH cmake )
set ( DRACO_DIR "" CACHE STRING "Path to draco" )
find_package ( GLEW REQUIRED )
find_package ( GLFW3 REQUIRED )
find_package ( OpenGL REQUIRED )
if (APPLE)
find_library(COCOA_LIBRARY Cocoa)
find_library(COREVIDEO_LIBRARY CoreVideo)
find_library(IOKIT_LIBRARY IOKit)
else ()
if (NOT WIN32)
# This means it is Unices
set ( GLFW3_UNIX_LINK_LIBRARIES X11 Xxf86vm Xrandr Xi Xinerama Xcursor )
find_package (Threads)
endif()
endif (APPLE)
set(CMAKE_CXX_STANDARD 11)
if (DEFINED DRACO_DIR)
if (DRACO_DIR STREQUAL "")
else ()
# TODO(syoyo): better CMake script for draco
add_definitions(-DTINYGLTF_ENABLE_DRACO)
include_directories(${DRACO_DIR}/include)
link_directories(${DRACO_DIR}/lib)
set(DRACO_LIBRARY draco)
endif ()
endif()
include_directories(
../../
../common
# ${OPENGL_INCLUDE_DIR}
${GLEW_INCLUDE_DIR}
${GLFW3_INCLUDE_DIR}
)
add_executable(glview
glview.cc
../common/trackball.cc
)
target_link_libraries ( glview
${DRACO_LIBRARY}
${GLFW3_UNIX_LINK_LIBRARIES}
${GLEW_LIBRARY}
${GLFW3_glfw_LIBRARY}
${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY}
${COCOA_LIBRARY}
${COREVIDEO_LIBRARY}
${IOKIT_LIBRARY}
${CMAKE_DL_LIBS}
${CMAKE_THREAD_LIBS_INIT}
)
install ( TARGETS
glview
DESTINATION
bin
)
+15 -2
View File
@@ -2,9 +2,11 @@ Simple OpenGL viewer for glTF geometry.
## Requirements
* premake4 : Requires recent `premake4` for macosx and linux, `premake5` for windows.
* premake5 : Requires recent `premake5`(alpha12 or later) for macosx and linux. `premake5` for windows is included in `$tinygltf/tools/window` directory.
* GLEW
* Ubuntu 16.04: sudo apt install libglew-dev
* glfw3
* Ubuntu 16.04: sudo apt install libglfw3-dev
### MacOSX and Linux
@@ -17,7 +19,7 @@ Simple OpenGL viewer for glTF geometry.
### Windows(not tested well)
Edit glew and glfw path in `premake4.lua`, then
Edit glew and glfw path in `premake5.lua`, then
> premake5.exe vs2013
@@ -25,6 +27,17 @@ Open .sln in Visual Studio 2013
When running .exe, glew and glfw dll must exist in the working directory.
#### Build with Draco(optional)
Assume CMake build.
```
$ mkdir build
$ cd build
$ cmake -DDRACO_DIR=/path/to/draco ../
$ make
```
## TODO
* [ ] PBR Material
+71
View File
@@ -0,0 +1,71 @@
#-*-cmake-*-
#
# yue.nicholas@gmail.com
#
# This auxiliary CMake file helps in find the glfw3 headers and libraries
#
# GLFW3_FOUND set if glfw3 is found.
# GLFW3_INCLUDE_DIR glfw3's include directory
# GLFW3_LIBRARY_DIR glfw3's library directory
# GLFW3_LIBRARIES all glfw3 libraries
FIND_PACKAGE (Threads)
FIND_PACKAGE ( PackageHandleStandardArgs )
FIND_PATH( GLFW3_LOCATION include/GLFW/glfw3.h
"$ENV{GLFW3_HOME}"
)
FIND_PACKAGE_HANDLE_STANDARD_ARGS ( GLFW3
REQUIRED_VARS GLFW3_LOCATION
)
IF (GLFW3_FOUND)
SET( GLFW3_INCLUDE_DIR "${GLFW3_LOCATION}/include" CACHE STRING "GLFW3 include path")
IF (GLFW3_USE_STATIC_LIBS)
FIND_LIBRARY ( GLFW3_glfw_LIBRARY libglfw3.a ${GLFW3_LOCATION}/lib
)
ELSE (GLFW3_USE_STATIC_LIBS)
# On windows build, we need to look for glfw3
IF (WIN32)
SET ( GLFW3_LIBRARY_NAME glfw3 )
ELSE ()
SET ( GLFW3_LIBRARY_NAME glfw )
ENDIF()
FIND_LIBRARY ( GLFW3_glfw_LIBRARY ${GLFW3_LIBRARY_NAME} ${GLFW3_LOCATION}/lib
)
ENDIF (GLFW3_USE_STATIC_LIBS)
IF (APPLE)
FIND_LIBRARY ( COCOA_LIBRARY Cocoa )
FIND_LIBRARY ( IOKIT_LIBRARY IOKit )
FIND_LIBRARY ( COREVIDEO_LIBRARY CoreVideo )
ELSEIF (UNIX AND NOT APPLE)
SET ( GLFW3_REQUIRED_X11_LIBRARIES
X11
Xi
Xrandr
Xinerama
Xcursor
Xxf86vm
m
${CMAKE_DL_LIBS}
${CMAKE_THREAD_LIBS_INIT}
)
ENDIF ()
SET ( GLFW3_LIBRARIES
${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY}
${GLFW3_glfw_LIBRARY}
# UNIX
${GLFW3_REQUIRED_X11_LIBRARIES}
# APPLE
${COCOA_LIBRARY}
${IOKIT_LIBRARY}
${COREVIDEO_LIBRARY}
CACHE STRING "GLFW3 required libraries"
)
ENDIF ()
+395 -223
View File
@@ -12,11 +12,21 @@
#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
#ifdef _WIN32
#include "../common/trackball.h"
#else
#include "trackball.h"
#endif
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#ifdef _WIN32
#include "../../tiny_gltf.h"
#else
#include "tiny_gltf.h"
#endif
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
@@ -44,7 +54,9 @@ float eye[3], lookat[3], up[3];
GLFWwindow *window;
typedef struct { GLuint vb; } GLBufferState;
typedef struct {
GLuint vb;
} GLBufferState;
typedef struct {
std::vector<GLuint> diffuseTex; // for each primitive in mesh
@@ -243,6 +255,26 @@ void motionFunc(GLFWwindow *window, double mouse_x, double 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) {
// Buffer
{
@@ -253,14 +285,117 @@ static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
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];
GLBufferState state;
glGenBuffers(1, &state.vb);
glBindBuffer(bufferView.target, state.vb);
std::cout << "buffer.size= " << buffer.data.size()
<< ", 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);
gBufferState[i] = state;
@@ -268,55 +403,55 @@ static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
}
#if 0 // TODO(syoyo): Implement
// Texture
{
for (size_t i = 0; i < model.meshes.size(); i++) {
const tinygltf::Mesh &mesh = model.meshes[i];
// Texture
{
for (size_t i = 0; i < model.meshes.size(); i++) {
const tinygltf::Mesh &mesh = model.meshes[i];
gMeshState[mesh.name].diffuseTex.resize(mesh.primitives.size());
for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
const tinygltf::Primitive &primitive = mesh.primitives[primId];
gMeshState[mesh.name].diffuseTex.resize(mesh.primitives.size());
for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
const tinygltf::Primitive &primitive = mesh.primitives[primId];
gMeshState[mesh.name].diffuseTex[primId] = 0;
gMeshState[mesh.name].diffuseTex[primId] = 0;
if (primitive.material < 0) {
continue;
}
tinygltf::Material &mat = model.materials[primitive.material];
// printf("material.name = %s\n", mat.name.c_str());
if (mat.values.find("diffuse") != mat.values.end()) {
std::string diffuseTexName = mat.values["diffuse"].string_value;
if (model.textures.find(diffuseTexName) != model.textures.end()) {
tinygltf::Texture &tex = model.textures[diffuseTexName];
if (scene.images.find(tex.source) != model.images.end()) {
tinygltf::Image &image = model.images[tex.source];
GLuint texId;
glGenTextures(1, &texId);
glBindTexture(tex.target, texId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (primitive.material < 0) {
continue;
}
tinygltf::Material &mat = model.materials[primitive.material];
// printf("material.name = %s\n", mat.name.c_str());
if (mat.values.find("diffuse") != mat.values.end()) {
std::string diffuseTexName = mat.values["diffuse"].string_value;
if (model.textures.find(diffuseTexName) != model.textures.end()) {
tinygltf::Texture &tex = model.textures[diffuseTexName];
if (scene.images.find(tex.source) != model.images.end()) {
tinygltf::Image &image = model.images[tex.source];
GLuint texId;
glGenTextures(1, &texId);
glBindTexture(tex.target, texId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Ignore Texture.fomat.
GLenum format = GL_RGBA;
if (image.component == 3) {
format = GL_RGB;
}
glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
image.height, 0, format, tex.type,
&image.image.at(0));
// Ignore Texture.fomat.
GLenum format = GL_RGBA;
if (image.component == 3) {
format = GL_RGB;
}
glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
image.height, 0, format, tex.type,
&image.image.at(0));
CheckErrors("texImage2D");
glBindTexture(tex.target, 0);
CheckErrors("texImage2D");
glBindTexture(tex.target, 0);
printf("TexId = %d\n", texId);
gMeshState[mesh.name].diffuseTex[primId] = texId;
}
}
}
}
}
}
printf("TexId = %d\n", texId);
gMeshState[mesh.name].diffuseTex[primId] = texId;
}
}
}
}
}
}
#endif
glUseProgram(progId);
@@ -337,164 +472,164 @@ static void SetupMeshState(tinygltf::Model &model, GLuint progId) {
#if 0 // TODO(syoyo): Implement
// Setup curves geometry extension
static void SetupCurvesState(tinygltf::Scene &scene, GLuint progId) {
// Find curves primitive.
{
std::map<std::string, tinygltf::Mesh>::const_iterator it(
scene.meshes.begin());
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(
scene.meshes.end());
// Find curves primitive.
{
std::map<std::string, tinygltf::Mesh>::const_iterator it(
scene.meshes.begin());
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(
scene.meshes.end());
for (; it != itEnd; it++) {
const tinygltf::Mesh &mesh = it->second;
for (; it != itEnd; it++) {
const tinygltf::Mesh &mesh = it->second;
// Currently we only support one primitive per mesh.
if (mesh.primitives.size() > 1) {
continue;
}
// Currently we only support one primitive per mesh.
if (mesh.primitives.size() > 1) {
continue;
}
for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
const tinygltf::Primitive &primitive = mesh.primitives[primId];
for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
const tinygltf::Primitive &primitive = mesh.primitives[primId];
gMeshState[mesh.name].diffuseTex[primId] = 0;
gMeshState[mesh.name].diffuseTex[primId] = 0;
if (primitive.material.empty()) {
continue;
}
if (primitive.material.empty()) {
continue;
}
bool has_curves = false;
if (primitive.extras.IsObject()) {
if (primitive.extras.Has("ext_mode")) {
const tinygltf::Value::Object &o =
primitive.extras.Get<tinygltf::Value::Object>();
const tinygltf::Value &ext_mode = o.find("ext_mode")->second;
bool has_curves = false;
if (primitive.extras.IsObject()) {
if (primitive.extras.Has("ext_mode")) {
const tinygltf::Value::Object &o =
primitive.extras.Get<tinygltf::Value::Object>();
const tinygltf::Value &ext_mode = o.find("ext_mode")->second;
if (ext_mode.IsString()) {
const std::string &str = ext_mode.Get<std::string>();
if (str.compare("curves") == 0) {
has_curves = true;
}
}
}
}
if (ext_mode.IsString()) {
const std::string &str = ext_mode.Get<std::string>();
if (str.compare("curves") == 0) {
has_curves = true;
}
}
}
}
if (!has_curves) {
continue;
}
if (!has_curves) {
continue;
}
// Construct curves buffer
const tinygltf::Accessor &vtx_accessor =
scene.accessors[primitive.attributes.find("POSITION")->second];
const tinygltf::Accessor &nverts_accessor =
scene.accessors[primitive.attributes.find("NVERTS")->second];
const tinygltf::BufferView &vtx_bufferView =
scene.bufferViews[vtx_accessor.bufferView];
const tinygltf::BufferView &nverts_bufferView =
scene.bufferViews[nverts_accessor.bufferView];
const tinygltf::Buffer &vtx_buffer =
scene.buffers[vtx_bufferView.buffer];
const tinygltf::Buffer &nverts_buffer =
scene.buffers[nverts_bufferView.buffer];
// Construct curves buffer
const tinygltf::Accessor &vtx_accessor =
scene.accessors[primitive.attributes.find("POSITION")->second];
const tinygltf::Accessor &nverts_accessor =
scene.accessors[primitive.attributes.find("NVERTS")->second];
const tinygltf::BufferView &vtx_bufferView =
scene.bufferViews[vtx_accessor.bufferView];
const tinygltf::BufferView &nverts_bufferView =
scene.bufferViews[nverts_accessor.bufferView];
const tinygltf::Buffer &vtx_buffer =
scene.buffers[vtx_bufferView.buffer];
const tinygltf::Buffer &nverts_buffer =
scene.buffers[nverts_bufferView.buffer];
// std::cout << "vtx_bufferView = " << vtx_accessor.bufferView <<
// std::endl;
// std::cout << "nverts_bufferView = " << nverts_accessor.bufferView <<
// std::endl;
// std::cout << "vtx_buffer.size = " << vtx_buffer.data.size() <<
// std::endl;
// std::cout << "nverts_buffer.size = " << nverts_buffer.data.size() <<
// std::endl;
// std::cout << "vtx_bufferView = " << vtx_accessor.bufferView <<
// std::endl;
// std::cout << "nverts_bufferView = " << nverts_accessor.bufferView <<
// std::endl;
// std::cout << "vtx_buffer.size = " << vtx_buffer.data.size() <<
// std::endl;
// std::cout << "nverts_buffer.size = " << nverts_buffer.data.size() <<
// std::endl;
const int *nverts =
reinterpret_cast<const int *>(nverts_buffer.data.data());
const float *vtx =
reinterpret_cast<const float *>(vtx_buffer.data.data());
const int *nverts =
reinterpret_cast<const int *>(nverts_buffer.data.data());
const float *vtx =
reinterpret_cast<const float *>(vtx_buffer.data.data());
// Convert to GL_LINES data.
std::vector<float> line_pts;
size_t vtx_offset = 0;
for (int k = 0; k < static_cast<int>(nverts_accessor.count); k++) {
for (int n = 0; n < nverts[k] - 1; n++) {
// Convert to GL_LINES data.
std::vector<float> line_pts;
size_t vtx_offset = 0;
for (int k = 0; k < static_cast<int>(nverts_accessor.count); k++) {
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) + 1]);
line_pts.push_back(vtx[3 * (vtx_offset + n) + 2]);
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) + 2]);
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) + 2]);
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) + 2]);
// std::cout << "p0 " << vtx[3 * (vtx_offset + n) + 0] << ", "
// << vtx[3 * (vtx_offset + n) + 1] << ", "
// << vtx[3 * (vtx_offset + n) + 2] << std::endl;
// std::cout << "p0 " << vtx[3 * (vtx_offset + n) + 0] << ", "
// << vtx[3 * (vtx_offset + n) + 1] << ", "
// << vtx[3 * (vtx_offset + n) + 2] << std::endl;
// std::cout << "p1 " << vtx[3 * (vtx_offset + n+1) + 0] << ", "
// << vtx[3 * (vtx_offset + n+1) + 1] << ", "
// << vtx[3 * (vtx_offset + n+1) + 2] << std::endl;
}
// std::cout << "p1 " << vtx[3 * (vtx_offset + n+1) + 0] << ", "
// << vtx[3 * (vtx_offset + n+1) + 1] << ", "
// << vtx[3 * (vtx_offset + n+1) + 2] << std::endl;
}
vtx_offset += nverts[k];
}
vtx_offset += nverts[k];
}
GLCurvesState state;
glGenBuffers(1, &state.vb);
glBindBuffer(GL_ARRAY_BUFFER, state.vb);
glBufferData(GL_ARRAY_BUFFER, line_pts.size() * sizeof(float),
line_pts.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLCurvesState state;
glGenBuffers(1, &state.vb);
glBindBuffer(GL_ARRAY_BUFFER, state.vb);
glBufferData(GL_ARRAY_BUFFER, line_pts.size() * sizeof(float),
line_pts.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
state.count = line_pts.size() / 3;
gCurvesMesh[mesh.name] = state;
state.count = line_pts.size() / 3;
gCurvesMesh[mesh.name] = state;
// Material
tinygltf::Material &mat = scene.materials[primitive.material];
// printf("material.name = %s\n", mat.name.c_str());
if (mat.values.find("diffuse") != mat.values.end()) {
std::string diffuseTexName = mat.values["diffuse"].string_value;
if (scene.textures.find(diffuseTexName) != scene.textures.end()) {
tinygltf::Texture &tex = scene.textures[diffuseTexName];
if (scene.images.find(tex.source) != scene.images.end()) {
tinygltf::Image &image = scene.images[tex.source];
GLuint texId;
glGenTextures(1, &texId);
glBindTexture(tex.target, texId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Material
tinygltf::Material &mat = scene.materials[primitive.material];
// printf("material.name = %s\n", mat.name.c_str());
if (mat.values.find("diffuse") != mat.values.end()) {
std::string diffuseTexName = mat.values["diffuse"].string_value;
if (scene.textures.find(diffuseTexName) != scene.textures.end()) {
tinygltf::Texture &tex = scene.textures[diffuseTexName];
if (scene.images.find(tex.source) != scene.images.end()) {
tinygltf::Image &image = scene.images[tex.source];
GLuint texId;
glGenTextures(1, &texId);
glBindTexture(tex.target, texId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Ignore Texture.fomat.
GLenum format = GL_RGBA;
if (image.component == 3) {
format = GL_RGB;
}
glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
image.height, 0, format, tex.type,
&image.image.at(0));
// Ignore Texture.fomat.
GLenum format = GL_RGBA;
if (image.component == 3) {
format = GL_RGB;
}
glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
image.height, 0, format, tex.type,
&image.image.at(0));
CheckErrors("texImage2D");
glBindTexture(tex.target, 0);
CheckErrors("texImage2D");
glBindTexture(tex.target, 0);
printf("TexId = %d\n", texId);
gMeshState[mesh.name].diffuseTex[primId] = texId;
}
}
}
}
}
}
printf("TexId = %d\n", texId);
gMeshState[mesh.name].diffuseTex[primId] = texId;
}
}
}
}
}
}
glUseProgram(progId);
GLint vtloc = glGetAttribLocation(progId, "in_vertex");
GLint nrmloc = glGetAttribLocation(progId, "in_normal");
GLint uvloc = glGetAttribLocation(progId, "in_texcoord");
glUseProgram(progId);
GLint vtloc = glGetAttribLocation(progId, "in_vertex");
GLint nrmloc = glGetAttribLocation(progId, "in_normal");
GLint uvloc = glGetAttribLocation(progId, "in_texcoord");
GLint diffuseTexLoc = glGetUniformLocation(progId, "diffuseTex");
GLint isCurvesLoc = glGetUniformLocation(progId, "uIsCurves");
GLint diffuseTexLoc = glGetUniformLocation(progId, "diffuseTex");
GLint isCurvesLoc = glGetUniformLocation(progId, "uIsCurves");
gGLProgramState.attribs["POSITION"] = vtloc;
gGLProgramState.attribs["NORMAL"] = nrmloc;
gGLProgramState.attribs["TEXCOORD_0"] = uvloc;
gGLProgramState.uniforms["diffuseTex"] = diffuseTexLoc;
gGLProgramState.uniforms["uIsCurves"] = isCurvesLoc;
gGLProgramState.attribs["POSITION"] = vtloc;
gGLProgramState.attribs["NORMAL"] = nrmloc;
gGLProgramState.attribs["TEXCOORD_0"] = uvloc;
gGLProgramState.uniforms["diffuseTex"] = diffuseTexLoc;
gGLProgramState.uniforms["uIsCurves"] = isCurvesLoc;
};
#endif
@@ -546,10 +681,14 @@ static void DrawMesh(tinygltf::Model &model, const tinygltf::Mesh &mesh) {
(it->first.compare("NORMAL") == 0) ||
(it->first.compare("TEXCOORD_0") == 0)) {
if (gGLProgramState.attribs[it->first] >= 0) {
// Compute byteStride from Accessor + BufferView combination.
int byteStride =
accessor.ByteStride(model.bufferViews[accessor.bufferView]);
assert(byteStride != -1);
glVertexAttribPointer(gGLProgramState.attribs[it->first], size,
accessor.componentType, accessor.normalized ? GL_TRUE : GL_FALSE,
model.bufferViews[accessor.bufferView].byteStride,
BUFFER_OFFSET(accessor.byteOffset));
accessor.componentType,
accessor.normalized ? GL_TRUE : GL_FALSE,
byteStride, BUFFER_OFFSET(accessor.byteOffset));
CheckErrors("vertex attrib pointer");
glEnableVertexAttribArray(gGLProgramState.attribs[it->first]);
CheckErrors("enable vertex attrib array");
@@ -603,32 +742,32 @@ static void DrawMesh(tinygltf::Model &model, const tinygltf::Mesh &mesh) {
#if 0 // TODO(syoyo): Implement
static void DrawCurves(tinygltf::Scene &scene, const tinygltf::Mesh &mesh) {
(void)scene;
(void)scene;
if (gCurvesMesh.find(mesh.name) == gCurvesMesh.end()) {
return;
}
if (gCurvesMesh.find(mesh.name) == gCurvesMesh.end()) {
return;
}
if (gGLProgramState.uniforms["isCurvesLoc"] >= 0) {
glUniform1i(gGLProgramState.uniforms["isCurvesLoc"], 1);
}
if (gGLProgramState.uniforms["isCurvesLoc"] >= 0) {
glUniform1i(gGLProgramState.uniforms["isCurvesLoc"], 1);
}
GLCurvesState &state = gCurvesMesh[mesh.name];
GLCurvesState &state = gCurvesMesh[mesh.name];
if (gGLProgramState.attribs["POSITION"] >= 0) {
glBindBuffer(GL_ARRAY_BUFFER, state.vb);
glVertexAttribPointer(gGLProgramState.attribs["POSITION"], 3, GL_FLOAT,
GL_FALSE, /* stride */ 0, BUFFER_OFFSET(0));
CheckErrors("curve: vertex attrib pointer");
glEnableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
CheckErrors("curve: enable vertex attrib array");
}
if (gGLProgramState.attribs["POSITION"] >= 0) {
glBindBuffer(GL_ARRAY_BUFFER, state.vb);
glVertexAttribPointer(gGLProgramState.attribs["POSITION"], 3, GL_FLOAT,
GL_FALSE, /* stride */ 0, BUFFER_OFFSET(0));
CheckErrors("curve: vertex attrib pointer");
glEnableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
CheckErrors("curve: enable vertex attrib array");
}
glDrawArrays(GL_LINES, 0, state.count);
glDrawArrays(GL_LINES, 0, state.count);
if (gGLProgramState.attribs["POSITION"] >= 0) {
glDisableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
}
if (gGLProgramState.attribs["POSITION"] >= 0) {
glDisableVertexAttribArray(gGLProgramState.attribs["POSITION"]);
}
}
#endif
@@ -663,10 +802,14 @@ static void DrawNode(tinygltf::Model &model, const tinygltf::Node &node) {
// std::cout << it->first << std::endl;
// FIXME(syoyo): Refactor.
// DrawCurves(scene, it->second);
DrawMesh(model, model.meshes[node.mesh]);
if (node.mesh > -1) {
assert(node.mesh < model.meshes.size());
DrawMesh(model, model.meshes[node.mesh]);
}
// Draw child nodes.
for (size_t i = 0; i < node.children.size(); i++) {
assert(node.children[i] < model.nodes.size());
DrawNode(model, model.nodes[node.children[i]]);
}
@@ -675,18 +818,19 @@ static void DrawNode(tinygltf::Model &model, const tinygltf::Node &node) {
static void DrawModel(tinygltf::Model &model) {
#if 0
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 it(scene.meshes.begin());
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(scene.meshes.end());
for (; it != itEnd; it++) {
DrawMesh(scene, it->second);
DrawCurves(scene, it->second);
}
for (; it != itEnd; it++) {
DrawMesh(scene, it->second);
DrawCurves(scene, it->second);
}
#else
// TODO(syoyo): Support non-default scenes.
assert(model.defaultScene >= 0);
const tinygltf::Scene &scene = model.scenes[model.defaultScene];
// If the glTF asset has at least one scene, and doesn't define a default one
// just show the first one we can find
assert(model.scenes.size() > 0);
int scene_to_display = model.defaultScene > -1 ? model.defaultScene : 0;
const tinygltf::Scene &scene = model.scenes[scene_to_display];
for (size_t i = 0; i < scene.nodes.size(); i++) {
DrawNode(model, model.nodes[scene.nodes[i]]);
}
@@ -717,8 +861,8 @@ static void PrintNodes(const tinygltf::Scene &scene) {
int main(int argc, char **argv) {
if (argc < 2) {
std::cout << "glview input.gltf <scale>\n" << std::endl;
return 0;
std::cout << "glview input.gltf <scale>" << std::endl;
std::cout << "defaulting to example cube model" << std::endl;
}
float scale = 1.0f;
@@ -729,16 +873,31 @@ int main(int argc, char **argv) {
tinygltf::Model model;
tinygltf::TinyGLTF loader;
std::string err;
std::string input_filename(argv[1]);
std::string warn;
#ifdef _WIN32
#ifdef _DEBUG
std::string input_filename(argv[1] ? argv[1]
: "../../../models/Cube/Cube.gltf");
#endif
#else
std::string input_filename(argv[1] ? argv[1] : "../../models/Cube/Cube.gltf");
#endif
std::string ext = GetFilePathExtension(input_filename);
bool ret = false;
if (ext.compare("glb") == 0) {
// assume binary glTF.
ret = loader.LoadBinaryFromFile(&model, &err, input_filename.c_str());
ret =
loader.LoadBinaryFromFile(&model, &err, &warn, input_filename.c_str());
} else {
// assume ascii glTF.
ret = loader.LoadASCIIFromFile(&model, &err, input_filename.c_str());
ret = loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
}
if (!warn.empty()) {
printf("Warn: %s\n", warn.c_str());
}
if (!err.empty()) {
@@ -752,17 +911,19 @@ int main(int argc, char **argv) {
Init();
// DBG
PrintNodes(model.scenes[model.defaultScene]);
PrintNodes(model.scenes[model.defaultScene > -1 ? model.defaultScene : 0]);
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW." << std::endl;
return -1;
}
char title[1024];
sprintf(title, "Simple glTF viewer: %s", input_filename.c_str());
std::stringstream ss;
ss << "Simple glTF viewer: " << input_filename;
window = glfwCreateWindow(width, height, title, NULL, NULL);
std::string title = ss.str();
window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
if (window == NULL) {
std::cerr << "Failed to open GLFW window. " << std::endl;
glfwTerminate();
@@ -788,12 +949,23 @@ int main(int argc, char **argv) {
reshapeFunc(window, width, height);
GLuint vertId = 0, fragId = 0, progId = 0;
if (false == LoadShader(GL_VERTEX_SHADER, vertId, "shader.vert")) {
#ifdef _WIN32
#ifdef _DEBUG
const char *shader_frag_filename = "../shader.frag";
const char *shader_vert_filename = "../shader.vert";
#endif
#else
const char *shader_frag_filename = "shader.frag";
const char *shader_vert_filename = "shader.vert";
#endif
if (false == LoadShader(GL_VERTEX_SHADER, vertId, shader_vert_filename)) {
return -1;
}
CheckErrors("load vert shader");
if (false == LoadShader(GL_FRAGMENT_SHADER, fragId, "shader.frag")) {
if (false == LoadShader(GL_FRAGMENT_SHADER, fragId, shader_frag_filename)) {
return -1;
}
CheckErrors("load frag shader");
+31
View File
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2050
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glview", "glview\glview.vcxproj", "{D078BB24-377E-497B-8045-03AF2A0547ED}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D078BB24-377E-497B-8045-03AF2A0547ED}.Debug|x64.ActiveCfg = Debug|x64
{D078BB24-377E-497B-8045-03AF2A0547ED}.Debug|x64.Build.0 = Debug|x64
{D078BB24-377E-497B-8045-03AF2A0547ED}.Debug|x86.ActiveCfg = Debug|Win32
{D078BB24-377E-497B-8045-03AF2A0547ED}.Debug|x86.Build.0 = Debug|Win32
{D078BB24-377E-497B-8045-03AF2A0547ED}.Release|x64.ActiveCfg = Release|x64
{D078BB24-377E-497B-8045-03AF2A0547ED}.Release|x64.Build.0 = Release|x64
{D078BB24-377E-497B-8045-03AF2A0547ED}.Release|x86.ActiveCfg = Release|Win32
{D078BB24-377E-497B-8045-03AF2A0547ED}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DB7C2F91-06C9-4BD8-95BF-04814E0C62DA}
EndGlobalSection
EndGlobal
+152
View File
@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{D078BB24-377E-497B-8045-03AF2A0547ED}</ProjectGuid>
<RootNamespace>glview</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);opengl32.lib;glu32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);opengl32.lib;glu32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);opengl32.lib;glu32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);opengl32.lib;glu32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\common\trackball.cc" />
<ClCompile Include="..\glview.cc" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\nupengl.core.redist.0.1.0.1\build\native\nupengl.core.redist.targets" Condition="Exists('..\packages\nupengl.core.redist.0.1.0.1\build\native\nupengl.core.redist.targets')" />
<Import Project="..\packages\nupengl.core.0.1.0.1\build\native\nupengl.core.targets" Condition="Exists('..\packages\nupengl.core.0.1.0.1\build\native\nupengl.core.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\nupengl.core.redist.0.1.0.1\build\native\nupengl.core.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\nupengl.core.redist.0.1.0.1\build\native\nupengl.core.redist.targets'))" />
<Error Condition="!Exists('..\packages\nupengl.core.0.1.0.1\build\native\nupengl.core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\nupengl.core.0.1.0.1\build\native\nupengl.core.targets'))" />
</Target>
</Project>
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\glview.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\common\trackball.cc">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nupengl.core" version="0.1.0.1" targetFramework="native" />
<package id="nupengl.core.redist" version="0.1.0.1" targetFramework="native" />
</packages>
@@ -7,10 +7,11 @@ solution "glview"
kind "ConsoleApp"
language "C++"
files { "glview.cc", "trackball.cc" }
cppdialect "C++11"
files { "glview.cc", "../common/trackball.cc" }
includedirs { "./" }
includedirs { "../../" }
flags "c++11"
includedirs { "../common/" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
@@ -34,9 +35,10 @@ solution "glview"
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
symbols "On"
warnings "Extra"
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
optimize "On"
warnings "Extra"
-292
View File
@@ -1,292 +0,0 @@
/*
* (c) Copyright 1993, 1994, Silicon Graphics, Inc.
* ALL RIGHTS RESERVED
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the above
* copyright notice appear in all copies and that both the copyright notice
* and this permission notice appear in supporting documentation, and that
* the name of Silicon Graphics, Inc. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
* clause at DFARS 252.227-7013 and/or in similar or successor
* clauses in the FAR or the DOD or NASA FAR Supplement.
* Unpublished-- rights reserved under the copyright laws of the
* United States. Contractor/manufacturer is Silicon Graphics,
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
*
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
/*
* Trackball code:
*
* Implementation of a virtual trackball.
* Implemented by Gavin Bell, lots of ideas from Thant Tessman and
* the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129.
*
* Vector manip code:
*
* Original code from:
* David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli
*
* Much mucking with by:
* Gavin Bell
*/
#include <math.h>
#include "trackball.h"
/*
* This size should really be based on the distance from the center of
* rotation to the point on the object underneath the mouse. That
* point would then track the mouse as closely as possible. This is a
* simple example, though, so that is left as an Exercise for the
* Programmer.
*/
#define TRACKBALLSIZE (0.8)
/*
* Local function prototypes (not defined in trackball.h)
*/
static float tb_project_to_sphere(float, float, float);
static void normalize_quat(float[4]);
static void vzero(float *v) {
v[0] = 0.0;
v[1] = 0.0;
v[2] = 0.0;
}
static void vset(float *v, float x, float y, float z) {
v[0] = x;
v[1] = y;
v[2] = z;
}
static void vsub(const float *src1, const float *src2, float *dst) {
dst[0] = src1[0] - src2[0];
dst[1] = src1[1] - src2[1];
dst[2] = src1[2] - src2[2];
}
static void vcopy(const float *v1, float *v2) {
register int i;
for (i = 0; i < 3; i++)
v2[i] = v1[i];
}
static void vcross(const float *v1, const float *v2, float *cross) {
float temp[3];
temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
vcopy(temp, cross);
}
static float vlength(const float *v) {
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
static void vscale(float *v, float div) {
v[0] *= div;
v[1] *= div;
v[2] *= div;
}
static void vnormal(float *v) { vscale(v, 1.0 / vlength(v)); }
static float vdot(const float *v1, const float *v2) {
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
static void vadd(const float *src1, const float *src2, float *dst) {
dst[0] = src1[0] + src2[0];
dst[1] = src1[1] + src2[1];
dst[2] = src1[2] + src2[2];
}
/*
* Ok, simulate a track-ball. Project the points onto the virtual
* trackball, then figure out the axis of rotation, which is the cross
* product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
* Note: This is a deformed trackball-- is a trackball in the center,
* but is deformed into a hyperbolic sheet of rotation away from the
* center. This particular function was chosen after trying out
* several variations.
*
* It is assumed that the arguments to this routine are in the range
* (-1.0 ... 1.0)
*/
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) {
float a[3]; /* Axis of rotation */
float phi; /* how much to rotate about axis */
float p1[3], p2[3], d[3];
float t;
if (p1x == p2x && p1y == p2y) {
/* Zero rotation */
vzero(q);
q[3] = 1.0;
return;
}
/*
* First, figure out z-coordinates for projection of P1 and P2 to
* deformed sphere
*/
vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y));
vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y));
/*
* Now, we want the cross product of P1 and P2
*/
vcross(p2, p1, a);
/*
* Figure out how much to rotate around that axis.
*/
vsub(p1, p2, d);
t = vlength(d) / (2.0 * TRACKBALLSIZE);
/*
* Avoid problems with out-of-control values...
*/
if (t > 1.0)
t = 1.0;
if (t < -1.0)
t = -1.0;
phi = 2.0 * asin(t);
axis_to_quat(a, phi, q);
}
/*
* Given an axis and angle, compute quaternion.
*/
void axis_to_quat(float a[3], float phi, float q[4]) {
vnormal(a);
vcopy(a, q);
vscale(q, sin(phi / 2.0));
q[3] = cos(phi / 2.0);
}
/*
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
* if we are away from the center of the sphere.
*/
static float tb_project_to_sphere(float r, float x, float y) {
float d, t, z;
d = sqrt(x * x + y * y);
if (d < r * 0.70710678118654752440) { /* Inside sphere */
z = sqrt(r * r - d * d);
} else { /* On hyperbola */
t = r / 1.41421356237309504880;
z = t * t / d;
}
return z;
}
/*
* Given two rotations, e1 and e2, expressed as quaternion rotations,
* figure out the equivalent single rotation and stuff it into dest.
*
* This routine also normalizes the result every RENORMCOUNT times it is
* called, to keep error from creeping in.
*
* NOTE: This routine is written so that q1 or q2 may be the same
* as dest (or each other).
*/
#define RENORMCOUNT 97
void add_quats(float q1[4], float q2[4], float dest[4]) {
static int count = 0;
float t1[4], t2[4], t3[4];
float tf[4];
vcopy(q1, t1);
vscale(t1, q2[3]);
vcopy(q2, t2);
vscale(t2, q1[3]);
vcross(q2, q1, t3);
vadd(t1, t2, tf);
vadd(t3, tf, tf);
tf[3] = q1[3] * q2[3] - vdot(q1, q2);
dest[0] = tf[0];
dest[1] = tf[1];
dest[2] = tf[2];
dest[3] = tf[3];
if (++count > RENORMCOUNT) {
count = 0;
normalize_quat(dest);
}
}
/*
* Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0
* If they don't add up to 1.0, dividing by their magnitued will
* renormalize them.
*
* Note: See the following for more information on quaternions:
*
* - Shoemake, K., Animating rotation with quaternion curves, Computer
* Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985.
* - Pletinckx, D., Quaternion calculus as a basic tool in computer
* graphics, The Visual Computer 5, 2-13, 1989.
*/
static void normalize_quat(float q[4]) {
int i;
float mag;
mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
for (i = 0; i < 4; i++)
q[i] /= mag;
}
/*
* Build a rotation matrix, given a quaternion rotation.
*
*/
void build_rotmatrix(float m[4][4], const float q[4]) {
m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]);
m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);
m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]);
m[0][3] = 0.0;
m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]);
m[1][1] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]);
m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
m[1][3] = 0.0;
m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]);
m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]);
m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]);
m[2][3] = 0.0;
m[3][0] = 0.0;
m[3][1] = 0.0;
m[3][2] = 0.0;
m[3][3] = 1.0;
}
-75
View File
@@ -1,75 +0,0 @@
/*
* (c) Copyright 1993, 1994, Silicon Graphics, Inc.
* ALL RIGHTS RESERVED
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the above
* copyright notice appear in all copies and that both the copyright notice
* and this permission notice appear in supporting documentation, and that
* the name of Silicon Graphics, Inc. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
* clause at DFARS 252.227-7013 and/or in similar or successor
* clauses in the FAR or the DOD or NASA FAR Supplement.
* Unpublished-- rights reserved under the copyright laws of the
* United States. Contractor/manufacturer is Silicon Graphics,
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
*
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
/*
* trackball.h
* A virtual trackball implementation
* Written by Gavin Bell for Silicon Graphics, November 1988.
*/
/*
* Pass the x and y coordinates of the last and current positions of
* the mouse, scaled so they are from (-1.0 ... 1.0).
*
* The resulting rotation is returned as a quaternion rotation in the
* first paramater.
*/
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y);
void negate_quat(float *q, float *qn);
/*
* Given two quaternions, add them together to get a third quaternion.
* Adding quaternions to get a compound rotation is analagous to adding
* translations to get a compound translation. When incrementally
* adding rotations, the first argument here should be the new
* rotation, the second and third the total rotation (which will be
* over-written with the resulting new total rotation).
*/
void add_quats(float *q1, float *q2, float *dest);
/*
* A useful function, builds a rotation matrix in Matrix based on
* given quaternion.
*/
void build_rotmatrix(float m[4][4], const float q[4]);
/*
* This function computes a quaternion based on an axis (defined by
* the given vector) and an angle about which to rotate. The angle is
* expressed in radians. The result is put into the third argument.
*/
void axis_to_quat(float a[3], float phi, float q[4]);
+109 -9
View File
@@ -1,28 +1,128 @@
# Raytrace example
# NanoSG
Simple raytracing example with OpenGL preview
Simple, minimal and header-only scene graph library for NanoRT.
NanoSG itself shoud be compiled with C++-03 compiler, but demo code uses C++11 features.
![screenshot of the demo program](images/nanosg-demo.png)
![Animation showing node manipulation](https://media.giphy.com/media/l3JDO29fMFndyObHW/giphy.gif)
## Build
### Linux or macOS
```
$ premake5 gmake
$ make
```bash
premake5 gmake
make
```
### Windows
```
$ premake5 vs2015
```bash
premake5 vs2015
```
## Data structure
## Third party libraries and its icenses.
### Node
Node represents scene graph node. Tansformation node or Mesh(shape) node.
Node is interpreted as transformation node when passing `nullptr` to Node class constructure.
Node can contain multiple children.
### Scene
Scene contains root nodes and provides the method to find an intersection of nodes.
## User defined data structure
Following are required in user application.
### Mesh class
Current example code assumes mesh is all composed of triangle meshes.
Following method must be implemented for `Scene::Traversal`.
```cpp
///
/// Get the geometric normal and the shading normal at `face_idx' th face.
///
template<typename T>
void GetNormal(T Ng[3], T Ns[3], const unsigned int face_idx, const T u, const T v) const;
```
### Intersection class
Represents intersection(hit) information.
### Transform
Transformation is done in the following procedure.
`M' = parent_xform x local_xform x local_pivot`
## Memory management
`Scene` and `Node` does not create a copy of asset data(e.g. vertices, indices). Thus user must care about memory management of scene assets in user side.
## API
API is still subject to change.
### Node
```cpp
void Node::SetName(const std::string &name);
```
Set (unique) name for the node.
```cpp
void Node::AddChild(const type &child);
```
Add node as child node.
```cpp
void Node::SetLocalXform(const T xform[4][4]) {
```
Set local transformation matrix. Default is identity matrix.
### Scene
```cpp
bool Scene::AddNode(const Node<T, M> &node);
```
Add a node to the scene.
```cpp
bool Scene::Commit() {
```
Commit the scene. After adding nodes to the scene or changed transformation matrix, call this `Commit` before tracing rays.
`Commit` triggers BVH build in each nodes and updates node's transformation matrix.
```cpp
template<class H>
bool Scene::Traverse(nanort::Ray<T> &ray, H *isect, const bool cull_back_face = false) const;
```
Trace ray into the scene and find an intersection.
Returns `true` when there is an intersection and hit information is stored in `isect`.
## TODO
* [ ] Compute pivot point of each node(mesh).
## Third party libraries and its icenses
* picojson : BSD license.
* bt3gui : zlib license.
* bt3gui : zlib license.
* glew : BSD/MIT license.
* tinyobjloader : MIT license.
* glm : The Happy Bunny License (Modified MIT License). Copyright (c) 2005 - 2017 G-Truc Creation
+22 -8
View File
@@ -1,9 +1,23 @@
{ "gltf_filename" : "../../models/Cube/Cube.gltf",
"scene_scale" : 1.0,
"width" : 512,
"height" : 512,
"eye" : [0, 2.5, 15],
"up" : [0, 1, 0],
"look_at" : [0, 0, 0],
"dummy" : 0
{
"commented_out_obj_filename": "cornellbox_suzanne.obj",
"gltf_filename": "../../models/Cube/Cube.gltf",
"scene_scale": 1.0,
"width": 512,
"height": 512,
"eye": [
0,
2.5,
15
],
"up": [
0,
1,
0
],
"look_at": [
0,
0,
0
],
"dummy": 0
}
File diff suppressed because it is too large Load Diff
+459 -13
View File
@@ -1,13 +1,12 @@
#include "gltf-loader.h"
#include <iostream>
#include <memory> // c++11
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#include "tiny_gltf.h"
#define TINYGLTF_NO_STB_IMAGE_WRITE
#include <tiny_gltf.h>
namespace example {
static std::string GetFilePathExtension(const std::string &FileName) {
if (FileName.find_last_of(".") != std::string::npos)
return FileName.substr(FileName.find_last_of(".") + 1);
@@ -17,24 +16,30 @@ static std::string GetFilePathExtension(const std::string &FileName) {
///
/// Loads glTF 2.0 mesh
///
bool LoadGLTF(const std::string &filename, float scale, std::vector<Mesh<float> > *meshes, std::vector<Material> *materials, std::vector<Texture> *textures)
{
bool LoadGLTF(const std::string &filename, float scale,
std::vector<Mesh<float> > *meshes,
std::vector<Material> *materials,
std::vector<Texture> *textures) {
// TODO(syoyo): Texture
// TODO(syoyo): Material
tinygltf::Model model;
tinygltf::TinyGLTF loader;
std::string err;
std::string ext = GetFilePathExtension(filename);
std::string warn;
const std::string ext = GetFilePathExtension(filename);
bool ret = false;
if (ext.compare("glb") == 0) {
// assume binary glTF.
ret = loader.LoadBinaryFromFile(&model, &err, filename.c_str());
ret = loader.LoadBinaryFromFile(&model, &err, &warn, filename.c_str());
} else {
// assume ascii glTF.
ret = loader.LoadASCIIFromFile(&model, &err, filename.c_str());
ret = loader.LoadASCIIFromFile(&model, &err, &warn, filename.c_str());
}
if (!warn.empty()) {
std::cout << "glTF parse warning: " << warn << std::endl;
}
if (!err.empty()) {
@@ -45,7 +50,448 @@ bool LoadGLTF(const std::string &filename, float scale, std::vector<Mesh<float>
return false;
}
return false;
}
std::cout << "loaded glTF file has:\n"
<< model.accessors.size() << " accessors\n"
<< model.animations.size() << " animations\n"
<< model.buffers.size() << " buffers\n"
<< model.bufferViews.size() << " bufferViews\n"
<< model.materials.size() << " materials\n"
<< model.meshes.size() << " meshes\n"
<< model.nodes.size() << " nodes\n"
<< model.textures.size() << " textures\n"
<< model.images.size() << " images\n"
<< model.skins.size() << " skins\n"
<< model.samplers.size() << " samplers\n"
<< model.cameras.size() << " cameras\n"
<< model.scenes.size() << " scenes\n"
<< model.lights.size() << " lights\n";
} // namespace example
// Iterate through all the meshes in the glTF file
for (const auto &gltfMesh : model.meshes) {
std::cout << "Current mesh has " << gltfMesh.primitives.size()
<< " primitives:\n";
// Create a mesh object
Mesh<float> loadedMesh(sizeof(float) * 3);
// To store the min and max of the buffer (as 3D vector of floats)
v3f pMin = {}, pMax = {};
// Store the name of the glTF mesh (if defined)
loadedMesh.name = gltfMesh.name;
// For each primitive
for (const auto &meshPrimitive : gltfMesh.primitives) {
// Boolean used to check if we have converted the vertex buffer format
bool convertedToTriangleList = false;
// This permit to get a type agnostic way of reading the index buffer
std::unique_ptr<intArrayBase> indicesArrayPtr = nullptr;
{
const auto &indicesAccessor = model.accessors[meshPrimitive.indices];
const auto &bufferView = model.bufferViews[indicesAccessor.bufferView];
const auto &buffer = model.buffers[bufferView.buffer];
const auto dataAddress = buffer.data.data() + bufferView.byteOffset +
indicesAccessor.byteOffset;
const auto byteStride = indicesAccessor.ByteStride(bufferView);
const auto count = indicesAccessor.count;
// Allocate the index array in the pointer-to-base declared in the
// parent scope
switch (indicesAccessor.componentType) {
case TINYGLTF_COMPONENT_TYPE_BYTE:
indicesArrayPtr =
std::unique_ptr<intArray<char> >(new intArray<char>(
arrayAdapter<char>(dataAddress, count, byteStride)));
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
indicesArrayPtr = std::unique_ptr<intArray<unsigned char> >(
new intArray<unsigned char>(arrayAdapter<unsigned char>(
dataAddress, count, byteStride)));
break;
case TINYGLTF_COMPONENT_TYPE_SHORT:
indicesArrayPtr =
std::unique_ptr<intArray<short> >(new intArray<short>(
arrayAdapter<short>(dataAddress, count, byteStride)));
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
indicesArrayPtr = std::unique_ptr<intArray<unsigned short> >(
new intArray<unsigned short>(arrayAdapter<unsigned short>(
dataAddress, count, byteStride)));
break;
case TINYGLTF_COMPONENT_TYPE_INT:
indicesArrayPtr = std::unique_ptr<intArray<int> >(new intArray<int>(
arrayAdapter<int>(dataAddress, count, byteStride)));
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
indicesArrayPtr = std::unique_ptr<intArray<unsigned int> >(
new intArray<unsigned int>(arrayAdapter<unsigned int>(
dataAddress, count, byteStride)));
break;
default:
break;
}
}
const auto &indices = *indicesArrayPtr;
if (indicesArrayPtr) {
std::cout << "indices: ";
for (size_t i(0); i < indicesArrayPtr->size(); ++i) {
std::cout << indices[i] << " ";
loadedMesh.faces.push_back(indices[i]);
}
std::cout << '\n';
}
switch (meshPrimitive.mode) {
// We re-arrange the indices so that it describe a simple list of
// triangles
case TINYGLTF_MODE_TRIANGLE_FAN:
if (!convertedToTriangleList) {
std::cout << "TRIANGLE_FAN\n";
// This only has to be done once per primitive
convertedToTriangleList = true;
// We steal the guts of the vector
auto triangleFan = std::move(loadedMesh.faces);
loadedMesh.faces.clear();
// Push back the indices that describe just one triangle one by one
for (size_t i{2}; i < triangleFan.size(); ++i) {
loadedMesh.faces.push_back(triangleFan[0]);
loadedMesh.faces.push_back(triangleFan[i - 1]);
loadedMesh.faces.push_back(triangleFan[i]);
}
}
case TINYGLTF_MODE_TRIANGLE_STRIP:
if (!convertedToTriangleList) {
std::cout << "TRIANGLE_STRIP\n";
// This only has to be done once per primitive
convertedToTriangleList = true;
auto triangleStrip = std::move(loadedMesh.faces);
loadedMesh.faces.clear();
for (size_t i{2}; i < triangleStrip.size(); ++i) {
loadedMesh.faces.push_back(triangleStrip[i - 2]);
loadedMesh.faces.push_back(triangleStrip[i - 1]);
loadedMesh.faces.push_back(triangleStrip[i]);
}
}
case TINYGLTF_MODE_TRIANGLES: // this is the simpliest case to handle
{
std::cout << "TRIANGLES\n";
for (const auto &attribute : meshPrimitive.attributes) {
const auto attribAccessor = model.accessors[attribute.second];
const auto &bufferView =
model.bufferViews[attribAccessor.bufferView];
const auto &buffer = model.buffers[bufferView.buffer];
const auto dataPtr = buffer.data.data() + bufferView.byteOffset +
attribAccessor.byteOffset;
const auto byte_stride = attribAccessor.ByteStride(bufferView);
const auto count = attribAccessor.count;
std::cout << "current attribute has count " << count
<< " and stride " << byte_stride << " bytes\n";
std::cout << "attribute string is : " << attribute.first << '\n';
if (attribute.first == "POSITION") {
std::cout << "found position attribute\n";
// get the position min/max for computing the boundingbox
pMin.x = attribAccessor.minValues[0];
pMin.y = attribAccessor.minValues[1];
pMin.z = attribAccessor.minValues[2];
pMax.x = attribAccessor.maxValues[0];
pMax.y = attribAccessor.maxValues[1];
pMax.z = attribAccessor.maxValues[2];
switch (attribAccessor.type) {
case TINYGLTF_TYPE_VEC3: {
switch (attribAccessor.componentType) {
case TINYGLTF_COMPONENT_TYPE_FLOAT:
std::cout << "Type is FLOAT\n";
// 3D vector of float
v3fArray positions(
arrayAdapter<v3f>(dataPtr, count, byte_stride));
std::cout << "positions's size : " << positions.size()
<< '\n';
for (size_t i{0}; i < positions.size(); ++i) {
const auto v = positions[i];
std::cout << "positions[" << i << "]: (" << v.x << ", "
<< v.y << ", " << v.z << ")\n";
loadedMesh.vertices.push_back(v.x * scale);
loadedMesh.vertices.push_back(v.y * scale);
loadedMesh.vertices.push_back(v.z * scale);
}
}
break;
case TINYGLTF_COMPONENT_TYPE_DOUBLE: {
std::cout << "Type is DOUBLE\n";
switch (attribAccessor.type) {
case TINYGLTF_TYPE_VEC3: {
v3dArray positions(
arrayAdapter<v3d>(dataPtr, count, byte_stride));
for (size_t i{0}; i < positions.size(); ++i) {
const auto v = positions[i];
std::cout << "positions[" << i << "]: (" << v.x
<< ", " << v.y << ", " << v.z << ")\n";
loadedMesh.vertices.push_back(v.x * scale);
loadedMesh.vertices.push_back(v.y * scale);
loadedMesh.vertices.push_back(v.z * scale);
}
} break;
default:
// TODO Handle error
break;
}
break;
default:
break;
}
} break;
}
}
if (attribute.first == "NORMAL") {
std::cout << "found normal attribute\n";
switch (attribAccessor.type) {
case TINYGLTF_TYPE_VEC3: {
std::cout << "Normal is VEC3\n";
switch (attribAccessor.componentType) {
case TINYGLTF_COMPONENT_TYPE_FLOAT: {
std::cout << "Normal is FLOAT\n";
v3fArray normals(
arrayAdapter<v3f>(dataPtr, count, byte_stride));
// IMPORTANT: We need to reorder normals (and texture
// coordinates into "facevarying" order) for each face
// For each triangle :
for (size_t i{0}; i < indices.size() / 3; ++i) {
// get the i'th triange's indexes
auto f0 = indices[3 * i + 0];
auto f1 = indices[3 * i + 1];
auto f2 = indices[3 * i + 2];
// get the 3 normal vectors for that face
v3f n0, n1, n2;
n0 = normals[f0];
n1 = normals[f1];
n2 = normals[f2];
// Put them in the array in the correct order
loadedMesh.facevarying_normals.push_back(n0.x);
loadedMesh.facevarying_normals.push_back(n0.y);
loadedMesh.facevarying_normals.push_back(n0.z);
loadedMesh.facevarying_normals.push_back(n1.x);
loadedMesh.facevarying_normals.push_back(n1.y);
loadedMesh.facevarying_normals.push_back(n1.z);
loadedMesh.facevarying_normals.push_back(n2.x);
loadedMesh.facevarying_normals.push_back(n2.y);
loadedMesh.facevarying_normals.push_back(n2.z);
}
} break;
case TINYGLTF_COMPONENT_TYPE_DOUBLE: {
std::cout << "Normal is DOUBLE\n";
v3dArray normals(
arrayAdapter<v3d>(dataPtr, count, byte_stride));
// IMPORTANT: We need to reorder normals (and texture
// coordinates into "facevarying" order) for each face
// For each triangle :
for (size_t i{0}; i < indices.size() / 3; ++i) {
// get the i'th triange's indexes
auto f0 = indices[3 * i + 0];
auto f1 = indices[3 * i + 1];
auto f2 = indices[3 * i + 2];
// get the 3 normal vectors for that face
v3d n0, n1, n2;
n0 = normals[f0];
n1 = normals[f1];
n2 = normals[f2];
// Put them in the array in the correct order
loadedMesh.facevarying_normals.push_back(n0.x);
loadedMesh.facevarying_normals.push_back(n0.y);
loadedMesh.facevarying_normals.push_back(n0.z);
loadedMesh.facevarying_normals.push_back(n1.x);
loadedMesh.facevarying_normals.push_back(n1.y);
loadedMesh.facevarying_normals.push_back(n1.z);
loadedMesh.facevarying_normals.push_back(n2.x);
loadedMesh.facevarying_normals.push_back(n2.y);
loadedMesh.facevarying_normals.push_back(n2.z);
}
} break;
default:
std::cerr << "Unhandeled componant type for normal\n";
}
} break;
default:
std::cerr << "Unhandeled vector type for normal\n";
}
// Face varying comment on the normals is also true for the UVs
if (attribute.first == "TEXCOORD_0") {
std::cout << "Found texture coordinates\n";
switch (attribAccessor.type) {
case TINYGLTF_TYPE_VEC2: {
std::cout << "TEXTCOORD is VEC2\n";
switch (attribAccessor.componentType) {
case TINYGLTF_COMPONENT_TYPE_FLOAT: {
std::cout << "TEXTCOORD is FLOAT\n";
v2fArray uvs(
arrayAdapter<v2f>(dataPtr, count, byte_stride));
for (size_t i{0}; i < indices.size() / 3; ++i) {
// get the i'th triange's indexes
auto f0 = indices[3 * i + 0];
auto f1 = indices[3 * i + 1];
auto f2 = indices[3 * i + 2];
// get the texture coordinates for each triangle's
// vertices
v2f uv0, uv1, uv2;
uv0 = uvs[f0];
uv1 = uvs[f1];
uv2 = uvs[f2];
// push them in order into the mesh data
loadedMesh.facevarying_uvs.push_back(uv0.x);
loadedMesh.facevarying_uvs.push_back(uv0.y);
loadedMesh.facevarying_uvs.push_back(uv1.x);
loadedMesh.facevarying_uvs.push_back(uv1.y);
loadedMesh.facevarying_uvs.push_back(uv2.x);
loadedMesh.facevarying_uvs.push_back(uv2.y);
}
} break;
case TINYGLTF_COMPONENT_TYPE_DOUBLE: {
std::cout << "TEXTCOORD is DOUBLE\n";
v2dArray uvs(
arrayAdapter<v2d>(dataPtr, count, byte_stride));
for (size_t i{0}; i < indices.size() / 3; ++i) {
// get the i'th triange's indexes
auto f0 = indices[3 * i + 0];
auto f1 = indices[3 * i + 1];
auto f2 = indices[3 * i + 2];
v2d uv0, uv1, uv2;
uv0 = uvs[f0];
uv1 = uvs[f1];
uv2 = uvs[f2];
loadedMesh.facevarying_uvs.push_back(uv0.x);
loadedMesh.facevarying_uvs.push_back(uv0.y);
loadedMesh.facevarying_uvs.push_back(uv1.x);
loadedMesh.facevarying_uvs.push_back(uv1.y);
loadedMesh.facevarying_uvs.push_back(uv2.x);
loadedMesh.facevarying_uvs.push_back(uv2.y);
}
} break;
default:
std::cerr << "unrecognized vector type for UV";
}
} break;
default:
std::cerr << "unreconized componant type for UV";
}
}
}
}
break;
default:
std::cerr << "primitive mode not implemented";
break;
// These aren't triangles:
case TINYGLTF_MODE_POINTS:
case TINYGLTF_MODE_LINE:
case TINYGLTF_MODE_LINE_LOOP:
std::cerr << "primitive is not triangle based, ignoring";
}
}
// bbox :
v3f bCenter;
bCenter.x = 0.5f * (pMax.x - pMin.x) + pMin.x;
bCenter.y = 0.5f * (pMax.y - pMin.y) + pMin.y;
bCenter.z = 0.5f * (pMax.z - pMin.z) + pMin.z;
for (size_t v = 0; v < loadedMesh.vertices.size() / 3; v++) {
loadedMesh.vertices[3 * v + 0] -= bCenter.x;
loadedMesh.vertices[3 * v + 1] -= bCenter.y;
loadedMesh.vertices[3 * v + 2] -= bCenter.z;
}
loadedMesh.pivot_xform[0][0] = 1.0f;
loadedMesh.pivot_xform[0][1] = 0.0f;
loadedMesh.pivot_xform[0][2] = 0.0f;
loadedMesh.pivot_xform[0][3] = 0.0f;
loadedMesh.pivot_xform[1][0] = 0.0f;
loadedMesh.pivot_xform[1][1] = 1.0f;
loadedMesh.pivot_xform[1][2] = 0.0f;
loadedMesh.pivot_xform[1][3] = 0.0f;
loadedMesh.pivot_xform[2][0] = 0.0f;
loadedMesh.pivot_xform[2][1] = 0.0f;
loadedMesh.pivot_xform[2][2] = 1.0f;
loadedMesh.pivot_xform[2][3] = 0.0f;
loadedMesh.pivot_xform[3][0] = bCenter.x;
loadedMesh.pivot_xform[3][1] = bCenter.y;
loadedMesh.pivot_xform[3][2] = bCenter.z;
loadedMesh.pivot_xform[3][3] = 1.0f;
// TODO handle materials
for (size_t i{0}; i < loadedMesh.faces.size(); ++i)
loadedMesh.material_ids.push_back(materials->at(0).id);
meshes->push_back(loadedMesh);
ret = true;
}
}
// Iterate through all texture declaration in glTF file
for (const auto &gltfTexture : model.textures) {
std::cout << "Found texture!";
Texture loadedTexture;
const auto &image = model.images[gltfTexture.source];
loadedTexture.components = image.component;
loadedTexture.width = image.width;
loadedTexture.height = image.height;
const auto size =
image.component * image.width * image.height * sizeof(unsigned char);
loadedTexture.image = new unsigned char[size];
memcpy(loadedTexture.image, image.image.data(), size);
textures->push_back(loadedTexture);
}
return ret;
}
} // namespace example
+152 -5
View File
@@ -1,19 +1,166 @@
#ifndef EXAMPLE_GLTF_LOADER_H_
#define EXAMPLE_GLTF_LOADER_H_
#include <vector>
#include <stdexcept>
#include <string>
#include <vector>
#include "mesh.h"
#include "material.h"
#include "mesh.h"
namespace example {
/// Adapts an array of bytes to an array of T. Will advace of byte_stride each
/// elements.
template <typename T>
struct arrayAdapter {
/// Pointer to the bytes
const unsigned char *dataPtr;
/// Number of elements in the array
const size_t elemCount;
/// Stride in bytes between two elements
const size_t stride;
/// Construct an array adapter.
/// \param ptr Pointer to the start of the data, with offset applied
/// \param count Number of elements in the array
/// \param byte_stride Stride betweens elements in the array
arrayAdapter(const unsigned char *ptr, size_t count, size_t byte_stride)
: dataPtr(ptr), elemCount(count), stride(byte_stride) {}
/// Returns a *copy* of a single element. Can't be used to modify it.
T operator[](size_t pos) const {
if (pos >= elemCount)
throw std::out_of_range(
"Tried to access beyond the last element of an array adapter with "
"count " +
std::to_string(elemCount) + " while getting elemnet number " +
std::to_string(pos));
return *(reinterpret_cast<const T *>(dataPtr + pos * stride));
}
};
/// Interface of any adapted array that returns ingeger data
struct intArrayBase {
virtual ~intArrayBase() = default;
virtual unsigned int operator[](size_t) const = 0;
virtual size_t size() const = 0;
};
/// Interface of any adapted array that returns float data
struct floatArrayBase {
virtual ~floatArrayBase() = default;
virtual float operator[](size_t) const = 0;
virtual size_t size() const = 0;
};
/// An array that loads interger types, returns them as int
template <class T>
struct intArray : public intArrayBase {
arrayAdapter<T> adapter;
intArray(const arrayAdapter<T> &a) : adapter(a) {}
unsigned int operator[](size_t position) const override {
return static_cast<unsigned int>(adapter[position]);
}
size_t size() const override { return adapter.elemCount; }
};
template <class T>
struct floatArray : public floatArrayBase {
arrayAdapter<T> adapter;
floatArray(const arrayAdapter<T> &a) : adapter(a) {}
float operator[](size_t position) const override {
return static_cast<float>(adapter[position]);
}
size_t size() const override { return adapter.elemCount; }
};
#pragma pack(push, 1)
template <typename T>
struct v2 {
T x, y;
};
/// 3D vector of floats without padding
template <typename T>
struct v3 {
T x, y, z;
};
/// 4D vector of floats without padding
template <typename T>
struct v4 {
T x, y, z, w;
};
#pragma pack(pop)
using v2f = v2<float>;
using v3f = v3<float>;
using v4f = v4<float>;
using v2d = v2<double>;
using v3d = v3<double>;
using v4d = v4<double>;
struct v2fArray {
arrayAdapter<v2f> adapter;
v2fArray(const arrayAdapter<v2f> &a) : adapter(a) {}
v2f operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};
struct v3fArray {
arrayAdapter<v3f> adapter;
v3fArray(const arrayAdapter<v3f> &a) : adapter(a) {}
v3f operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};
struct v4fArray {
arrayAdapter<v4f> adapter;
v4fArray(const arrayAdapter<v4f> &a) : adapter(a) {}
v4f operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};
struct v2dArray {
arrayAdapter<v2d> adapter;
v2dArray(const arrayAdapter<v2d> &a) : adapter(a) {}
v2d operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};
struct v3dArray {
arrayAdapter<v3d> adapter;
v3dArray(const arrayAdapter<v3d> &a) : adapter(a) {}
v3d operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};
struct v4dArray {
arrayAdapter<v4d> adapter;
v4dArray(const arrayAdapter<v4d> &a) : adapter(a) {}
v4d operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};
///
/// Loads glTF 2.0 mesh
///
bool LoadGLTF(const std::string &filename, float scale, std::vector<Mesh<float> > *meshes, std::vector<Material> *materials, std::vector<Texture> *textures);
bool LoadGLTF(const std::string &filename, float scale,
std::vector<Mesh<float> > *meshes,
std::vector<Material> *materials, std::vector<Texture> *textures);
}
} // namespace example
#endif // EXAMPLE_GLTF_LOADER_H_
#endif // EXAMPLE_GLTF_LOADER_H_
Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

+226 -165
View File
@@ -53,12 +53,13 @@ THE SOFTWARE.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <limits>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <sstream>
#include <map>
#include <atomic> // C++11
#include <chrono> // C++11
@@ -72,22 +73,23 @@ THE SOFTWARE.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4201)
#pragma warning(disable : 4201)
#endif
#include "glm/mat4x4.hpp"
#include "glm/gtc/quaternion.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/quaternion.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "glm/mat4x4.hpp"
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#include "gltf-loader.h"
#include "nanosg.h"
#include "obj-loader.h"
#include "render-config.h"
#include "render.h"
#include "gltf-loader.h"
#include "trackball.h"
#ifdef WIN32
@@ -96,19 +98,17 @@ THE SOFTWARE.
#endif
#endif
#define SHOW_BUFFER_COLOR (0)
#define SHOW_BUFFER_NORMAL (1)
#define SHOW_BUFFER_POSITION (2)
#define SHOW_BUFFER_DEPTH (3)
#define SHOW_BUFFER_TEXCOORD (4)
#define SHOW_BUFFER_VARYCOORD (5)
b3gDefaultOpenGLWindow* window = 0;
b3gDefaultOpenGLWindow *window = 0;
int gWidth = 512;
int gHeight = 512;
int gMousePosX = -1, gMousePosY = -1;
bool gMouseLeftDown = false;
// FIX issue when max passes is done - no modes is switched. pass must be set to
// 0 when mode is changed
int gShowBufferMode_prv = SHOW_BUFFER_COLOR;
int gShowBufferMode = SHOW_BUFFER_COLOR;
bool gTabPressed = false;
bool gShiftPressed = false;
float gShowPositionScale = 1.0f;
@@ -128,8 +128,7 @@ std::atomic<bool> gSceneDirty;
example::RenderConfig gRenderConfig;
std::mutex gMutex;
struct RenderLayer
{
struct RenderLayer {
std::vector<float> displayRGBA; // Accumurated image.
std::vector<float> rgba;
std::vector<float> auxRGBA; // Auxiliary buffer
@@ -143,14 +142,12 @@ struct RenderLayer
RenderLayer gRenderLayer;
struct Camera
{
struct Camera {
glm::mat4 view;
glm::mat4 projection;
};
struct ManipConfig
{
struct ManipConfig {
glm::vec3 snapTranslation;
glm::vec3 snapRotation;
glm::vec3 snapScale;
@@ -201,9 +198,12 @@ void RenderThread() {
// gRenderCancel may be set to true in main loop.
// Render() will repeatedly check this flag inside the rendering loop.
bool ret =
example::Renderer::Render(&gRenderLayer.rgba.at(0), &gRenderLayer.auxRGBA.at(0), &gRenderLayer.sampleCounts.at(0),
gCurrQuat, gScene, gAsset, gRenderConfig, gRenderCancel);
bool ret = example::Renderer::Render(
&gRenderLayer.rgba.at(0), &gRenderLayer.auxRGBA.at(0),
&gRenderLayer.sampleCounts.at(0), gCurrQuat, gScene, gAsset,
gRenderConfig, gRenderCancel,
gShowBufferMode // added mode passing
);
if (ret) {
std::lock_guard<std::mutex> guard(gMutex);
@@ -219,16 +219,18 @@ void RenderThread() {
}
}
void InitRender(example::RenderConfig* rc) {
void InitRender(example::RenderConfig *rc) {
rc->pass = 0;
rc->max_passes = 128;
gRenderLayer.sampleCounts.resize(rc->width * rc->height);
std::fill(gRenderLayer.sampleCounts.begin(), gRenderLayer.sampleCounts.end(), 0.0);
std::fill(gRenderLayer.sampleCounts.begin(), gRenderLayer.sampleCounts.end(),
0.0);
gRenderLayer.displayRGBA.resize(rc->width * rc->height * 4);
std::fill(gRenderLayer.displayRGBA.begin(), gRenderLayer.displayRGBA.end(), 0.0);
std::fill(gRenderLayer.displayRGBA.begin(), gRenderLayer.displayRGBA.end(),
0.0);
gRenderLayer.rgba.resize(rc->width * rc->height * 4);
std::fill(gRenderLayer.rgba.begin(), gRenderLayer.rgba.end(), 0.0);
@@ -237,19 +239,23 @@ void InitRender(example::RenderConfig* rc) {
std::fill(gRenderLayer.auxRGBA.begin(), gRenderLayer.auxRGBA.end(), 0.0);
gRenderLayer.normalRGBA.resize(rc->width * rc->height * 4);
std::fill(gRenderLayer.normalRGBA.begin(), gRenderLayer.normalRGBA.end(), 0.0);
std::fill(gRenderLayer.normalRGBA.begin(), gRenderLayer.normalRGBA.end(),
0.0);
gRenderLayer.positionRGBA.resize(rc->width * rc->height * 4);
std::fill(gRenderLayer.positionRGBA.begin(), gRenderLayer.positionRGBA.end(), 0.0);
std::fill(gRenderLayer.positionRGBA.begin(), gRenderLayer.positionRGBA.end(),
0.0);
gRenderLayer.depthRGBA.resize(rc->width * rc->height * 4);
std::fill(gRenderLayer.depthRGBA.begin(), gRenderLayer.depthRGBA.end(), 0.0);
gRenderLayer.texCoordRGBA.resize(rc->width * rc->height * 4);
std::fill(gRenderLayer.texCoordRGBA.begin(), gRenderLayer.texCoordRGBA.end(), 0.0);
std::fill(gRenderLayer.texCoordRGBA.begin(), gRenderLayer.texCoordRGBA.end(),
0.0);
gRenderLayer.varyCoordRGBA.resize(rc->width * rc->height * 4);
std::fill(gRenderLayer.varyCoordRGBA.begin(), gRenderLayer.varyCoordRGBA.end(), 0.0);
std::fill(gRenderLayer.varyCoordRGBA.begin(),
gRenderLayer.varyCoordRGBA.end(), 0.0);
rc->normalImage = &gRenderLayer.normalRGBA.at(0);
rc->positionImage = &gRenderLayer.positionRGBA.at(0);
@@ -268,19 +274,18 @@ void checkErrors(std::string desc) {
}
}
static int CreateDisplayTextureGL(const float *data, int width, int height,
int components) {
GLuint id;
glGenTextures(1, &id);
static int CreateDisplayTextureGL(const float *data, int width,
int height, int components) {
GLuint id;
glGenTextures(1, &id);
GLint last_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLenum format = GL_RGBA;
if (components == 1) {
format = GL_LUMINANCE;
@@ -290,15 +295,15 @@ static int CreateDisplayTextureGL(const float *data, int width,
format = GL_RGB;
} else if (components == 4) {
format = GL_RGBA;
} else {
assert(0); // "Invalid components"
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format,
GL_FLOAT, data);
} else {
assert(0); // "Invalid components"
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_FLOAT,
data);
glBindTexture(GL_TEXTURE_2D, last_texture);
return static_cast<int>(id);
}
@@ -312,8 +317,10 @@ void keyboardCallback(int keycode, int state) {
// reset.
trackball(gCurrQuat, 0.0f, 0.0f, 0.0f, 0.0f);
// clear buffer.
memset(gRenderLayer.rgba.data(), 0, sizeof(float) * gRenderConfig.width * gRenderConfig.height * 4);
memset(gRenderLayer.sampleCounts.data(), 0, sizeof(int) * gRenderConfig.width * gRenderConfig.height);
memset(gRenderLayer.rgba.data(), 0,
sizeof(float) * gRenderConfig.width * gRenderConfig.height * 4);
memset(gRenderLayer.sampleCounts.data(), 0,
sizeof(int) * gRenderConfig.width * gRenderConfig.height);
} else if (keycode == 9) {
gTabPressed = (state == 1);
} else if (keycode == B3G_SHIFT) {
@@ -330,9 +337,10 @@ void keyboardCallback(int keycode, int state) {
}
void mouseMoveCallback(float x, float y) {
if (gMouseLeftDown) {
if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) {
gSceneDirty = true;
// RequestRender();
} else {
float w = static_cast<float>(gRenderConfig.width);
float h = static_cast<float>(gRenderConfig.height);
@@ -371,31 +379,34 @@ void mouseButtonCallback(int button, int state, float x, float y) {
(void)y;
ImGui_ImplBtGui_SetMouseButtonState(button, (state == 1));
ImGuiIO& io = ImGui::GetIO();
if (io.WantCaptureMouse || io.WantCaptureKeyboard) {
return;
}
if (button == 0 && !state)
gMouseLeftDown = false; // prevent sticky trackball after using gizmo
// left button
if (button == 0) {
if (state) {
gMouseLeftDown = true;
if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) {
} else {
trackball(gPrevQuat, 0.0f, 0.0f, 0.0f, 0.0f);
}
} else {
gMouseLeftDown = false;
if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) {
ImGuiIO &io = ImGui::GetIO();
if (io.WantCaptureMouse || io.WantCaptureKeyboard) {
if (button == 0 && !state) {
if (ImGuizmo::IsUsing()) {
gSceneDirty = true;
RequestRender();
}
}
} else {
// left button
if (button == 0) {
if (state) {
gMouseLeftDown = true;
if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) {
} else {
trackball(gPrevQuat, 0.0f, 0.0f, 0.0f, 0.0f);
}
} else {
}
}
}
}
void resizeCallback(float width, float height) {
//GLfloat h = (GLfloat)height / (GLfloat)width;
// GLfloat h = (GLfloat)height / (GLfloat)width;
GLfloat xmax, znear, zfar;
znear = 1.0f;
@@ -406,7 +417,7 @@ void resizeCallback(float width, float height) {
gHeight = static_cast<int>(height);
}
inline float pesudoColor(float v, int ch) {
inline float pseudoColor(float v, int ch) {
if (ch == 0) { // red
if (v <= 0.5f)
return 0.f;
@@ -471,7 +482,7 @@ void UpdateDisplayTextureGL(GLint tex_id, int width, int height) {
for (size_t i = 0; i < buf.size(); i++) {
float v = (gRenderLayer.depthRGBA[i] - d_min) / d_diff;
if (gShowDepthPeseudoColor) {
buf[i] = pesudoColor(v, i % 4);
buf[i] = pseudoColor(v, i % 4);
} else {
buf[i] = v;
}
@@ -491,31 +502,31 @@ void UpdateDisplayTextureGL(GLint tex_id, int width, int height) {
disp.resize(width * height * 4);
{
for (size_t y = 0; y < height; y++) {
memcpy(&disp[4 * (y * width)], &buf[4 * ((height - y - 1) * width)], sizeof(float) * 4 * width);
memcpy(&disp[4 * (y * width)], &buf[4 * ((height - y - 1) * width)],
sizeof(float) * 4 * width);
}
}
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, disp.data());
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT,
disp.data());
glBindTexture(GL_TEXTURE_2D, 0);
//glRasterPos2i(-1, -1);
//glDrawPixels(width, height, GL_RGBA, GL_FLOAT,
// glRasterPos2i(-1, -1);
// glDrawPixels(width, height, GL_RGBA, GL_FLOAT,
// static_cast<const GLvoid*>(&buf.at(0)));
}
void EditTransform(const ManipConfig &config, const Camera& camera, glm::mat4& matrix)
{
void EditTransform(const ManipConfig &config, const Camera &camera,
glm::mat4 &matrix) {
static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE);
static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD);
if (ImGui::IsKeyPressed(90))
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
if (ImGui::IsKeyPressed(69))
mCurrentGizmoOperation = ImGuizmo::ROTATE;
if (ImGui::IsKeyPressed(82)) // r Key
if (ImGui::IsKeyPressed(90)) mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
if (ImGui::IsKeyPressed(69)) mCurrentGizmoOperation = ImGuizmo::ROTATE;
if (ImGui::IsKeyPressed(82)) // r Key
mCurrentGizmoOperation = ImGuizmo::SCALE;
if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
if (ImGui::RadioButton("Translate",
mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
ImGui::SameLine();
if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE))
@@ -524,14 +535,15 @@ void EditTransform(const ManipConfig &config, const Camera& camera, glm::mat4& m
if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE))
mCurrentGizmoOperation = ImGuizmo::SCALE;
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
ImGuizmo::DecomposeMatrixToComponents(&matrix[0][0], matrixTranslation, matrixRotation, matrixScale);
ImGuizmo::DecomposeMatrixToComponents(&matrix[0][0], matrixTranslation,
matrixRotation, matrixScale);
ImGui::InputFloat3("Tr", matrixTranslation, 3);
ImGui::InputFloat3("Rt", matrixRotation, 3);
ImGui::InputFloat3("Sc", matrixScale, 3);
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, &matrix[0][0]);
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation,
matrixScale, &matrix[0][0]);
if (mCurrentGizmoOperation != ImGuizmo::SCALE)
{
if (mCurrentGizmoOperation != ImGuizmo::SCALE) {
if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
mCurrentGizmoMode = ImGuizmo::LOCAL;
ImGui::SameLine();
@@ -539,33 +551,32 @@ void EditTransform(const ManipConfig &config, const Camera& camera, glm::mat4& m
mCurrentGizmoMode = ImGuizmo::WORLD;
}
static bool useSnap(false);
if (ImGui::IsKeyPressed(83))
useSnap = !useSnap;
if (ImGui::IsKeyPressed(83)) useSnap = !useSnap;
ImGui::Checkbox("", &useSnap);
ImGui::SameLine();
glm::vec3 snap;
switch (mCurrentGizmoOperation)
{
case ImGuizmo::TRANSLATE:
snap = config.snapTranslation;
ImGui::InputFloat3("Snap", &snap.x);
break;
case ImGuizmo::ROTATE:
snap = config.snapRotation;
ImGui::InputFloat("Angle Snap", &snap.x);
break;
case ImGuizmo::SCALE:
snap = config.snapScale;
ImGui::InputFloat("Scale Snap", &snap.x);
break;
switch (mCurrentGizmoOperation) {
case ImGuizmo::TRANSLATE:
snap = config.snapTranslation;
ImGui::InputFloat3("Snap", &snap.x);
break;
case ImGuizmo::ROTATE:
snap = config.snapRotation;
ImGui::InputFloat("Angle Snap", &snap.x);
break;
case ImGuizmo::SCALE:
snap = config.snapScale;
ImGui::InputFloat("Scale Snap", &snap.x);
break;
}
ImGuiIO& io = ImGui::GetIO();
ImGuiIO &io = ImGui::GetIO();
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
ImGuizmo::Manipulate(&camera.view[0][0], &camera.projection[0][0], mCurrentGizmoOperation, mCurrentGizmoMode, &matrix[0][0], NULL, useSnap ? &snap.x : NULL);
ImGuizmo::Manipulate(&camera.view[0][0], &camera.projection[0][0],
mCurrentGizmoOperation, mCurrentGizmoMode, &matrix[0][0],
NULL, useSnap ? &snap.x : NULL);
}
void DrawMesh(const example::Mesh<float> *mesh)
{
void DrawMesh(const example::Mesh<float> *mesh) {
// TODO(LTE): Use vertex array or use display list.
glBegin(GL_TRIANGLES);
@@ -579,20 +590,17 @@ void DrawMesh(const example::Mesh<float> *mesh)
glNormal3f(mesh->facevarying_normals[9 * i + 0],
mesh->facevarying_normals[9 * i + 1],
mesh->facevarying_normals[9 * i + 2]);
glVertex3f(mesh->vertices[3 * f0 + 0],
mesh->vertices[3 * f0 + 1],
glVertex3f(mesh->vertices[3 * f0 + 0], mesh->vertices[3 * f0 + 1],
mesh->vertices[3 * f0 + 2]);
glNormal3f(mesh->facevarying_normals[9 * i + 3],
mesh->facevarying_normals[9 * i + 4],
mesh->facevarying_normals[9 * i + 5]);
glVertex3f(mesh->vertices[3 * f1 + 0],
mesh->vertices[3 * f1 + 1],
glVertex3f(mesh->vertices[3 * f1 + 0], mesh->vertices[3 * f1 + 1],
mesh->vertices[3 * f1 + 2]);
glNormal3f(mesh->facevarying_normals[9 * i + 6],
mesh->facevarying_normals[9 * i + 7],
mesh->facevarying_normals[9 * i + 8]);
glVertex3f(mesh->vertices[3 * f2 + 0],
mesh->vertices[3 * f2 + 1],
glVertex3f(mesh->vertices[3 * f2 + 0], mesh->vertices[3 * f2 + 1],
mesh->vertices[3 * f2 + 2]);
}
@@ -602,23 +610,19 @@ void DrawMesh(const example::Mesh<float> *mesh)
unsigned int f1 = mesh->faces[3 * i + 1];
unsigned int f2 = mesh->faces[3 * i + 2];
glVertex3f(mesh->vertices[3 * f0 + 0],
mesh->vertices[3 * f0 + 1],
glVertex3f(mesh->vertices[3 * f0 + 0], mesh->vertices[3 * f0 + 1],
mesh->vertices[3 * f0 + 2]);
glVertex3f(mesh->vertices[3 * f1 + 0],
mesh->vertices[3 * f1 + 1],
glVertex3f(mesh->vertices[3 * f1 + 0], mesh->vertices[3 * f1 + 1],
mesh->vertices[3 * f1 + 2]);
glVertex3f(mesh->vertices[3 * f2 + 0],
mesh->vertices[3 * f2 + 1],
glVertex3f(mesh->vertices[3 * f2 + 0], mesh->vertices[3 * f2 + 1],
mesh->vertices[3 * f2 + 2]);
}
}
glEnd();
glEnd();
}
void DrawNode(const nanosg::Node<float, example::Mesh<float> > &node)
{
void DrawNode(const nanosg::Node<float, example::Mesh<float> > &node) {
glPushMatrix();
glMultMatrixf(node.GetLocalXformPtr());
@@ -634,8 +638,8 @@ void DrawNode(const nanosg::Node<float, example::Mesh<float> > &node)
}
// Draw scene with OpenGL
void DrawScene(const nanosg::Scene<float, example::Mesh<float> > &scene, const Camera &camera)
{
void DrawScene(const nanosg::Scene<float, example::Mesh<float> > &scene,
const Camera &camera) {
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
@@ -649,11 +653,12 @@ void DrawScene(const nanosg::Scene<float, example::Mesh<float> > &scene, const C
const float light_diffuse[4] = {0.5f, 0.5f, 0.5f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, &light0_pos[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, &light_diffuse[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, &light_diffuse[0]);
glLightfv(GL_LIGHT1, GL_POSITION, &light1_pos[0]);
glLightfv(GL_LIGHT1, GL_DIFFUSE, &light_diffuse[0]);
glLightfv(GL_LIGHT1, GL_DIFFUSE, &light_diffuse[0]);
const std::vector<nanosg::Node<float, example::Mesh<float> > > &root_nodes = scene.GetNodes();
const std::vector<nanosg::Node<float, example::Mesh<float> > > &root_nodes =
scene.GetNodes();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
@@ -675,15 +680,12 @@ void DrawScene(const nanosg::Scene<float, example::Mesh<float> > &scene, const C
glDisable(GL_LIGHT1);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
}
void BuildSceneItems(
std::vector<std::string> *display_names,
std::vector<std::string> *names,
const nanosg::Node<float, example::Mesh<float> > &node,
int indent)
{
void BuildSceneItems(std::vector<std::string> *display_names,
std::vector<std::string> *names,
const nanosg::Node<float, example::Mesh<float> > &node,
int indent) {
if (node.GetName().empty()) {
// Skip a node with empty name.
return;
@@ -699,14 +701,16 @@ void BuildSceneItems(
display_names->push_back(display_name);
names->push_back(node.GetName());
for (size_t i = 0; i < node.GetChildren().size(); i++) {
BuildSceneItems(display_names, names, node.GetChildren()[i], indent + 1);
}
}
int main(int argc, char** argv) {
// tigra: add default material
example::Material default_material;
int main(int argc, char **argv) {
std::string config_filename = "config.json";
if (argc > 1) {
@@ -729,13 +733,47 @@ int main(int argc, char** argv) {
std::vector<example::Material> materials;
std::vector<example::Texture> textures;
bool ret = LoadGLTF(gRenderConfig.gltf_filename, gRenderConfig.scene_scale, &meshes, &materials, &textures);
if (!ret) {
std::cerr << "Failed to load glTF [ " << gRenderConfig.gltf_filename << " ]" << std::endl;
return -1;
// tigra: set default material to 95% white diffuse
default_material.diffuse[0] = 0.95f;
default_material.diffuse[1] = 0.95f;
default_material.diffuse[2] = 0.95f;
default_material.specular[0] = 0;
default_material.specular[1] = 0;
default_material.specular[2] = 0;
// Material pushed as first material on the list
materials.push_back(default_material);
if (!gRenderConfig.obj_filename.empty()) {
bool ret = LoadObj(gRenderConfig.obj_filename, gRenderConfig.scene_scale,
&meshes, &materials, &textures);
if (!ret) {
std::cerr << "Failed to load .obj [ " << gRenderConfig.obj_filename
<< " ]" << std::endl;
return -1;
}
}
if (!gRenderConfig.gltf_filename.empty()) {
std::cout << "Found gltf file : " << gRenderConfig.gltf_filename << "\n";
bool ret =
LoadGLTF(gRenderConfig.gltf_filename, gRenderConfig.scene_scale,
&meshes, &materials, &textures);
if (!ret) {
std::cerr << "Failed to load glTF file [ "
<< gRenderConfig.gltf_filename << " ]" << std::endl;
return -1;
}
}
if (textures.size() > 0) {
materials[0].diffuse_texid = 0;
}
gAsset.materials = materials;
gAsset.default_material = default_material;
gAsset.textures = textures;
for (size_t n = 0; n < meshes.size(); n++) {
@@ -744,12 +782,20 @@ int main(int argc, char** argv) {
}
for (size_t n = 0; n < gAsset.meshes.size(); n++) {
nanosg::Node<float, example::Mesh<float> > node(&gAsset.meshes[n]);
// case where the name of a mesh isn't defined in the loaded file
if (gAsset.meshes[n].name.empty()) {
std::string generatedName = "unnamed_" + std::to_string(n);
gAsset.meshes[n].name = generatedName;
meshes[n].name = generatedName;
}
node.SetName(meshes[n].name);
node.SetLocalXform(meshes[n].pivot_xform); // Use mesh's pivot transform as node's local transform.
node.SetLocalXform(meshes[n].pivot_xform); // Use mesh's pivot transform
// as node's local transform.
gNodes.push_back(node);
gScene.AddNode(node);
}
@@ -761,11 +807,12 @@ int main(int argc, char** argv) {
float bmin[3], bmax[3];
gScene.GetBoundingBox(bmin, bmax);
printf(" # of nodes : %d\n", int(gNodes.size()));
printf(" Scene Bmin : %f, %f, %f\n", bmin[0], bmin[1], bmin[2]);
printf(" Scene Bmax : %f, %f, %f\n", bmax[0], bmax[1], bmax[2]);
printf(" Scene Bmin : %f, %f, %f\n", bmin[0], bmin[1],
bmin[2]);
printf(" Scene Bmax : %f, %f, %f\n", bmax[0], bmax[1],
bmax[2]);
}
std::vector<const char *> imgui_node_names;
std::vector<std::string> display_node_names;
std::vector<std::string> node_names;
@@ -773,13 +820,14 @@ int main(int argc, char** argv) {
{
for (size_t i = 0; i < gScene.GetNodes().size(); i++) {
BuildSceneItems(&display_node_names, &node_names, gScene.GetNodes()[i], /* indent */0);
BuildSceneItems(&display_node_names, &node_names, gScene.GetNodes()[i],
/* indent */ 0);
}
// List of strings for imgui.
// Assume nodes in the scene does not change.
for (size_t i = 0; i < display_node_names.size(); i++) {
//std::cout << "name : " << display_node_names[i] << std::endl;
// std::cout << "name : " << display_node_names[i] << std::endl;
imgui_node_names.push_back(display_node_names[i].c_str());
}
@@ -788,13 +836,13 @@ int main(int argc, char** argv) {
nanosg::Node<float, example::Mesh<float> > *node;
if (gScene.FindNode(node_names[i], &node)) {
//std::cout << "id : " << i << ", name : " << node_names[i] << std::endl;
// std::cout << "id : " << i << ", name : " << node_names[i] <<
// std::endl;
node_map[i] = node;
}
}
}
window = new b3gDefaultOpenGLWindow;
b3gWindowConstructionInfo ci;
#ifdef USE_OPENGL2
@@ -834,11 +882,12 @@ int main(int argc, char** argv) {
window->setResizeCallback(resizeCallback);
checkErrors("resize");
ImGui::CreateContext();
ImGui_ImplBtGui_Init(window);
ImGuiIO& io = ImGui::GetIO();
ImGuiIO &io = ImGui::GetIO();
io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("./DroidSans.ttf", 15.0f);
// io.Fonts->AddFontFromFileTTF("./DroidSans.ttf", 15.0f);
glm::mat4 projection(1.0f);
glm::mat4 view(1.0f);
@@ -861,7 +910,7 @@ int main(int argc, char** argv) {
ImGuizmo::BeginFrame();
ImGuizmo::Enable(true);
//ImGuiIO &io = ImGui::GetIO();
// ImGuiIO &io = ImGui::GetIO();
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
ImGui::Begin("UI");
@@ -897,7 +946,7 @@ int main(int argc, char** argv) {
ImGui::InputFloat("show pos scale", &gShowPositionScale);
ImGui::InputFloat2("show depth range", gShowDepthRange);
ImGui::Checkbox("show depth pesudo color", &gShowDepthPeseudoColor);
ImGui::Checkbox("show depth pseudo color", &gShowDepthPeseudoColor);
}
ImGui::End();
@@ -908,38 +957,47 @@ int main(int argc, char** argv) {
checkErrors("clear");
// fix max passes issue
if (gShowBufferMode_prv != gShowBufferMode) {
gRenderConfig.pass = 0;
gShowBufferMode_prv = gShowBufferMode;
}
// Render display window
{
static GLint gl_texid = -1;
if (gl_texid < 0) {
gl_texid = CreateDisplayTextureGL(NULL, gRenderConfig.width, gRenderConfig.height, 4);
gl_texid = CreateDisplayTextureGL(NULL, gRenderConfig.width,
gRenderConfig.height, 4);
}
// Refresh texture until rendering finishes.
if (gRenderConfig.pass < gRenderConfig.max_passes) {
// FIXME(LTE): Do not update GL texture frequently.
UpdateDisplayTextureGL(gl_texid, gRenderConfig.width, gRenderConfig.height);
UpdateDisplayTextureGL(gl_texid, gRenderConfig.width,
gRenderConfig.height);
}
ImGui::Begin("Render");
ImTextureID tex_id = reinterpret_cast<void *>(
static_cast<intptr_t>(gl_texid));
ImTextureID tex_id =
reinterpret_cast<void *>(static_cast<intptr_t>(gl_texid));
ImGui::Image(tex_id, ImVec2(256, 256), ImVec2(0, 0),
ImVec2(1, 1));// Setup camera and draw imguizomo
ImVec2(1, 1)); // Setup camera and draw imguizomo
ImGui::End();
}
// scene graph tree
glm::mat4 node_matrix;
static int node_selected = 0;
static int node_selected_index = 0;
{
ImGui::Begin("Scene");
ImGui::ListBox("Node list", &node_selected, imgui_node_names.data(), imgui_node_names.size(), 16);
node_matrix = glm::make_mat4(node_map[node_selected]->GetLocalXformPtr());
ImGui::ListBox("Node list", &node_selected_index, imgui_node_names.data(),
imgui_node_names.size(), 16);
auto node_selected = node_map.at(node_selected_index);
node_matrix = glm::make_mat4(node_selected->GetLocalXformPtr());
ImGui::End();
}
@@ -964,11 +1022,14 @@ int main(int argc, char** argv) {
up[2] = gRenderConfig.up[2];
// NOTE(LTE): w, then (x,y,z) for glm::quat.
glm::quat rot = glm::quat(gCurrQuat[3], gCurrQuat[0], gCurrQuat[1], gCurrQuat[2]);
glm::quat rot =
glm::quat(gCurrQuat[3], gCurrQuat[0], gCurrQuat[1], gCurrQuat[2]);
glm::mat4 rm = glm::mat4_cast(rot);
view = glm::lookAt(eye, lookat, up) * glm::inverse(glm::mat4_cast(rot));
projection = glm::perspective (45.0f, float(window->getWidth()) / float(window->getHeight()), 0.01f, 1000.0f);
projection = glm::perspective(
45.0f, float(window->getWidth()) / float(window->getHeight()), 0.01f,
1000.0f);
camera.view = view;
camera.projection = projection;
@@ -978,10 +1039,10 @@ int main(int argc, char** argv) {
float mat[4][4];
memcpy(mat, &node_matrix[0][0], sizeof(float) * 16);
node_map[node_selected]->SetLocalXform(mat);
node_map[node_selected_index]->SetLocalXform(mat);
checkErrors("edit_transform");
ImGui::End();
}
+8 -2
View File
@@ -3,9 +3,14 @@
#include <cstdlib>
namespace example {
#ifdef __clang__
#pragma clang diagnostic push
#if __has_warning("-Wzero-as-null-pointer-constant")
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
#endif
// TODO(syoyo): Support PBR material.
namespace example {
struct Material {
// float ambient[3];
@@ -53,6 +58,7 @@ struct Texture {
int width;
int height;
int components;
int _pad_;
unsigned char* image;
Texture() {
+7 -1
View File
@@ -4,6 +4,7 @@
#include <vector>
#include <algorithm>
#include <cmath>
#include <limits>
namespace example {
@@ -69,9 +70,13 @@ inline void calculate_normal(T Nn[3], const T v0[3], const T v1[3], const T v2[3
template<typename T>
class Mesh {
public:
explicit Mesh(const size_t vertex_stride) :
stride(vertex_stride) {
}
std::string name;
std::vector<T> vertices; /// [xyz] * num_vertices
std::vector<T> vertices; /// stride * num_vertices
std::vector<T> facevarying_normals; /// [xyz] * 3(triangle) * num_faces
std::vector<T> facevarying_tangents; /// [xyz] * 3(triangle) * num_faces
std::vector<T> facevarying_binormals; /// [xyz] * 3(triangle) * num_faces
@@ -82,6 +87,7 @@ class Mesh {
std::vector<unsigned int> material_ids; /// index x num_faces
T pivot_xform[4][4];
size_t stride; /// stride for vertex data.
// --- Required methods in Scene::Traversal. ---
+1
View File
@@ -0,0 +1 @@
#include "nanort.h"
+208 -125
View File
@@ -44,6 +44,13 @@ THE SOFTWARE.
namespace nanort {
#ifdef __clang__
#pragma clang diagnostic push
#if __has_warning("-Wzero-as-null-pointer-constant")
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
#endif
// Parallelized BVH build is not yet fully tested,
// thus turn off if you face a problem when building BVH.
#define NANORT_ENABLE_PARALLEL_BUILD (1)
@@ -301,9 +308,7 @@ class real3 {
real3 operator/(const real3 &f2) const {
return real3(x() / f2.x(), y() / f2.y(), z() / f2.z());
}
real3 operator-() const {
return real3(-x(), -y(), -z());
}
real3 operator-() const { return real3(-x(), -y(), -z()); }
T operator[](int i) const { return v[i]; }
T &operator[](int i) { return v[i]; }
@@ -330,8 +335,8 @@ template <typename T>
inline real3<T> vnormalize(const real3<T> &rhs) {
real3<T> v = rhs;
T len = vlength(rhs);
if (fabs(len) > 1.0e-6f) {
float inv_len = 1.0f / len;
if (std::fabs(len) > static_cast<T>(1.0e-6)) {
T inv_len = static_cast<T>(1.0) / len;
v.v[0] *= inv_len;
v.v[1] *= inv_len;
v.v[2] *= inv_len;
@@ -363,9 +368,7 @@ inline const real *get_vertex_addr(const real *p, const size_t idx,
template <typename T = float>
class Ray {
public:
Ray()
: min_t(static_cast<T>(0.0))
, max_t(std::numeric_limits<T>::max()) {
Ray() : min_t(static_cast<T>(0.0)), max_t(std::numeric_limits<T>::max()) {
org[0] = static_cast<T>(0.0);
org[1] = static_cast<T>(0.0);
org[2] = static_cast<T>(0.0);
@@ -374,11 +377,11 @@ class Ray {
dir[2] = static_cast<T>(-1.0);
}
T org[3]; // must set
T dir[3]; // must set
T min_t; // minium ray hit distance.
T max_t; // maximum ray hit distance.
T inv_dir[3]; // filled internally
T org[3]; // must set
T dir[3]; // must set
T min_t; // minimum ray hit distance.
T max_t; // maximum ray hit distance.
T inv_dir[3]; // filled internally
int dir_sign[3]; // filled internally
};
@@ -386,6 +389,38 @@ template <typename T = float>
class BVHNode {
public:
BVHNode() {}
BVHNode(const BVHNode &rhs) {
bmin[0] = rhs.bmin[0];
bmin[1] = rhs.bmin[1];
bmin[2] = rhs.bmin[2];
flag = rhs.flag;
bmax[0] = rhs.bmax[0];
bmax[1] = rhs.bmax[1];
bmax[2] = rhs.bmax[2];
axis = rhs.axis;
data[0] = rhs.data[0];
data[1] = rhs.data[1];
}
BVHNode &operator=(const BVHNode &rhs) {
bmin[0] = rhs.bmin[0];
bmin[1] = rhs.bmin[1];
bmin[2] = rhs.bmin[2];
flag = rhs.flag;
bmax[0] = rhs.bmax[0];
bmax[1] = rhs.bmax[1];
bmax[2] = rhs.bmax[2];
axis = rhs.axis;
data[0] = rhs.data[0];
data[1] = rhs.data[1];
return (*this);
}
~BVHNode() {}
T bmin[3];
@@ -480,14 +515,26 @@ class BBox {
}
};
template<typename T>
class NodeHit
{
template <typename T>
class NodeHit {
public:
NodeHit()
: t_min(std::numeric_limits<T>::max())
, t_max(-std::numeric_limits<T>::max())
, node_id(static_cast<unsigned int>(-1)) {
: t_min(std::numeric_limits<T>::max()),
t_max(-std::numeric_limits<T>::max()),
node_id(static_cast<unsigned int>(-1)) {}
NodeHit(const NodeHit<T> &rhs) {
t_min = rhs.t_min;
t_max = rhs.t_max;
node_id = rhs.node_id;
}
NodeHit &operator=(const NodeHit<T> &rhs) {
t_min = rhs.t_min;
t_max = rhs.t_max;
node_id = rhs.node_id;
return (*this);
}
~NodeHit() {}
@@ -497,9 +544,8 @@ class NodeHit
unsigned int node_id;
};
template<typename T>
class NodeHitComparator
{
template <typename T>
class NodeHitComparator {
public:
inline bool operator()(const NodeHit<T> &a, const NodeHit<T> &b) {
return a.t_min < b.t_min;
@@ -512,29 +558,37 @@ class BVHAccel {
BVHAccel() : pad0_(0) { (void)pad0_; }
~BVHAccel() {}
///
/// Build BVH for input primitives.
template<class P, class Pred>
bool Build(const unsigned int num_primitives,
const P &p, const Pred &pred, const BVHBuildOptions<T> &options = BVHBuildOptions<T>());
///
template <class P, class Pred>
bool Build(const unsigned int num_primitives, const P &p, const Pred &pred,
const BVHBuildOptions<T> &options = BVHBuildOptions<T>());
///
/// Get statistics of built BVH tree. Valid after Build()
///
BVHBuildStatistics GetStatistics() const { return stats_; }
///
/// Dump built BVH to the file.
///
bool Dump(const char *filename);
///
/// Load BVH binary
///
bool Load(const char *filename);
void Debug();
///
/// Traverse into BVH along ray and find closest hit point & primitive if
/// found
template<class I, class H>
bool Traverse(const Ray<T> &ray,
const I &intersector,
H *isect,
const BVHTraceOptions& options = BVHTraceOptions()) const;
///
template <class I, class H>
bool Traverse(const Ray<T> &ray, const I &intersector, H *isect,
const BVHTraceOptions &options = BVHTraceOptions()) const;
#if 0
/// Multi-hit ray traversal
@@ -551,16 +605,17 @@ class BVHAccel {
/// List up nodes which intersects along the ray.
/// This function is useful for two-level BVH traversal.
///
template<class I>
bool ListNodeIntersections(const Ray<T> &ray,
int max_intersections,
template <class I>
bool ListNodeIntersections(const Ray<T> &ray, int max_intersections,
const I &intersector,
StackVector<NodeHit<T>, 128> *hits) const;
const std::vector<BVHNode<T> > &GetNodes() const { return nodes_; }
const std::vector<unsigned int> &GetIndices() const { return indices_; }
///
/// Returns bounding box of built BVH.
///
void BoundingBox(T bmin[3], T bmax[3]) const {
if (nodes_.empty()) {
bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<T>::max();
@@ -589,7 +644,7 @@ class BVHAccel {
std::vector<ShallowNodeInfo> shallow_node_infos_;
/// Builds shallow BVH tree recursively.
template<class P, class Pred>
template <class P, class Pred>
unsigned int BuildShallowTree(std::vector<BVHNode<T> > *out_nodes,
unsigned int left_idx, unsigned int right_idx,
unsigned int depth,
@@ -598,22 +653,22 @@ class BVHAccel {
#endif
/// Builds BVH tree recursively.
template<class P, class Pred>
template <class P, class Pred>
unsigned int BuildTree(BVHBuildStatistics *out_stat,
std::vector<BVHNode<T> > *out_nodes,
unsigned int left_idx, unsigned int right_idx,
unsigned int depth, const P &p, const Pred &pred);
template<class I>
template <class I>
bool TestLeafNode(const BVHNode<T> &node, const Ray<T> &ray,
const I &intersector) const;
template<class I>
bool TestLeafNodeIntersections(const BVHNode<T> &node,
const Ray<T> &ray,
const int max_intersections,
const I &intersector,
std::priority_queue<NodeHit<T>, std::vector<NodeHit<T> >, NodeHitComparator<T> > *isect_pq) const;
template <class I>
bool TestLeafNodeIntersections(
const BVHNode<T> &node, const Ray<T> &ray, const int max_intersections,
const I &intersector,
std::priority_queue<NodeHit<T>, std::vector<NodeHit<T> >,
NodeHitComparator<T> > *isect_pq) const;
#if 0
template<class I, class H, class Comp>
@@ -663,7 +718,7 @@ class TriangleSAHPred {
T center = p0[axis] + p1[axis] + p2[axis];
return (center < pos * 3.0);
return (center < pos * static_cast<T>(3.0));
}
private:
@@ -762,7 +817,7 @@ class TriangleIntersector {
/// distance `t`,
/// varycentric coordinate `u` and `v`.
/// Returns true if there's intersection.
bool Intersect(T *t_inout, unsigned int prim_index) const {
bool Intersect(T *t_inout, const unsigned int prim_index) const {
if ((prim_index < trace_options_.prim_ids_range[0]) ||
(prim_index >= trace_options_.prim_ids_range[1])) {
return false;
@@ -791,8 +846,13 @@ class TriangleIntersector {
T V = Ax * Cy - Ay * Cx;
T W = Bx * Ay - By * Ax;
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
#endif
// Fall back to test against edges using double precision.
if (U == 0.0 || V == 0.0 || W == 0.0) {
if (U == static_cast<T>(0.0) || V == static_cast<T>(0.0) || W == static_cast<T>(0.0)) {
double CxBy = static_cast<double>(Cx) * static_cast<double>(By);
double CyBx = static_cast<double>(Cy) * static_cast<double>(Bx);
U = static_cast<T>(CxBy - CyBx);
@@ -807,15 +867,19 @@ class TriangleIntersector {
}
if (trace_options_.cull_back_face) {
if (U < 0.0 || V < 0.0 || W < 0.0) return false;
if (U < static_cast<T>(0.0) || V < static_cast<T>(0.0) || W < static_cast<T>(0.0)) return false;
} else {
if ((U < 0.0 || V < 0.0 || W < 0.0) && (U > 0.0 || V > 0.0 || W > 0.0)) {
if ((U < static_cast<T>(0.0) || V < static_cast<T>(0.0) || W < static_cast<T>(0.0)) && (U > static_cast<T>(0.0) || V > static_cast<T>(0.0) || W > static_cast<T>(0.0))) {
return false;
}
}
T det = U + V + W;
if (det == 0.0) return false;
if (det == static_cast<T>(0.0)) return false;
#ifdef __clang__
#pragma clang diagnostic pop
#endif
const T Az = ray_coeff_.Sz * A[ray_coeff_.kz];
const T Bz = ray_coeff_.Sz * B[ray_coeff_.kz];
@@ -829,6 +893,10 @@ class TriangleIntersector {
return false;
}
if (tt < t_min_) {
return false;
}
(*t_inout) = tt;
// Use Thomas-Mueller style barycentric coord.
// U + V + W = 1.0 and interp(p) = U * p0 + V * p1 + W * p2
@@ -884,6 +952,8 @@ class TriangleIntersector {
trace_options_ = trace_options;
t_min_ = ray.min_t;
u_ = 0.0f;
v_ = 0.0f;
}
@@ -901,19 +971,20 @@ class TriangleIntersector {
}
private:
const T *vertices_;
const unsigned int *faces_;
const size_t vertex_stride_bytes_;
mutable real3<T> ray_org_;
mutable RayCoeff ray_coeff_;
mutable BVHTraceOptions trace_options_;
mutable T t_min_;
mutable T t_;
mutable T u_;
mutable T v_;
mutable T t_;
mutable T u_;
mutable T v_;
mutable unsigned int prim_id_;
int _pad_;
};
//
@@ -950,7 +1021,8 @@ struct BinBuffer {
template <typename T>
inline T CalculateSurfaceArea(const real3<T> &min, const real3<T> &max) {
real3<T> box = max - min;
return static_cast<T>(2.0) * (box[0] * box[1] + box[1] * box[2] + box[2] * box[0]);
return static_cast<T>(2.0) *
(box[0] * box[1] + box[1] * box[2] + box[2] * box[0]);
}
template <typename T>
@@ -994,12 +1066,12 @@ inline void ContributeBinBuffer(BinBuffer *bins, // [out]
real3<T> scene_size, scene_inv_size;
scene_size = scene_max - scene_min;
for (int i = 0; i < 3; ++i) {
assert(scene_size[i] >= 0.0);
assert(scene_size[i] >= static_cast<T>(0.0));
if (scene_size[i] > 0.0) {
if (scene_size[i] > static_cast<T>(0.0)) {
scene_inv_size[i] = bin_size / scene_size[i];
} else {
scene_inv_size[i] = 0.0;
scene_inv_size[i] = static_cast<T>(0.0);
}
}
@@ -1057,7 +1129,8 @@ inline T SAH(size_t ns1, T leftArea, size_t ns2, T rightArea, T invS, T Taabb,
T Ttri) {
T sah;
sah = static_cast<T>(2.0) * Taabb + (leftArea * invS) * static_cast<T>(ns1) * Ttri +
sah = static_cast<T>(2.0) * Taabb +
(leftArea * invS) * static_cast<T>(ns1) * Ttri +
(rightArea * invS) * static_cast<T>(ns2) * Ttri;
return sah;
@@ -1079,22 +1152,22 @@ inline bool FindCutFromBinBuffer(T *cut_pos, // [out] xyz
T pos;
T minCost[3];
T costTtri = 1.0f - costTaabb;
T costTtri = static_cast<T>(1.0) - costTaabb;
(*minCostAxis) = 0;
bsize = bmax - bmin;
bstep = bsize * (1.0f / bins->bin_size);
bstep = bsize * (static_cast<T>(1.0) / bins->bin_size);
saTotal = CalculateSurfaceArea(bmin, bmax);
T invSaTotal = 0.0f;
T invSaTotal = static_cast<T>(0.0);
if (saTotal > kEPS) {
invSaTotal = 1.0f / saTotal;
invSaTotal = static_cast<T>(1.0) / saTotal;
}
for (int j = 0; j < 3; ++j) {
//
// Compute SAH cost for right side of each cell of the bbox.
// Compute SAH cost for the right side of each cell of the bbox.
// Exclude both extreme side of the bbox.
//
// i: 0 1 2 3
@@ -1103,7 +1176,7 @@ inline bool FindCutFromBinBuffer(T *cut_pos, // [out] xyz
// +----+----+----+----+----+
//
T minCostPos = bmin[j] + 0.5f * bstep[j];
T minCostPos = bmin[j] + static_cast<T>(1.0) * bstep[j];
minCost[j] = std::numeric_limits<T>::max();
left = 0;
@@ -1127,7 +1200,7 @@ inline bool FindCutFromBinBuffer(T *cut_pos, // [out] xyz
// +1 for i since we want a position on right side of the cell.
//
pos = bmin[j] + (i + 0.5f) * bstep[j];
pos = bmin[j] + (i + static_cast<T>(1.0)) * bstep[j];
bmaxLeft[j] = pos;
bminRight[j] = pos;
@@ -1280,11 +1353,14 @@ inline void GetBoundingBox(real3<T> *bmin, real3<T> *bmax,
//
#if NANORT_ENABLE_PARALLEL_BUILD
template <typename T> template<class P, class Pred>
unsigned int BVHAccel<T>::BuildShallowTree(
std::vector<BVHNode<T> > *out_nodes, unsigned int left_idx,
unsigned int right_idx, unsigned int depth, unsigned int max_shallow_depth,
const P &p, const Pred &pred) {
template <typename T>
template <class P, class Pred>
unsigned int BVHAccel<T>::BuildShallowTree(std::vector<BVHNode<T> > *out_nodes,
unsigned int left_idx,
unsigned int right_idx,
unsigned int depth,
unsigned int max_shallow_depth,
const P &p, const Pred &pred) {
assert(left_idx <= right_idx);
unsigned int offset = static_cast<unsigned int>(out_nodes->size());
@@ -1424,11 +1500,13 @@ unsigned int BVHAccel<T>::BuildShallowTree(
}
#endif
template <typename T> template<class P, class Pred>
unsigned int BVHAccel<T>::BuildTree(
BVHBuildStatistics *out_stat, std::vector<BVHNode<T> > *out_nodes,
unsigned int left_idx, unsigned int right_idx, unsigned int depth,
const P &p, const Pred &pred) {
template <typename T>
template <class P, class Pred>
unsigned int BVHAccel<T>::BuildTree(BVHBuildStatistics *out_stat,
std::vector<BVHNode<T> > *out_nodes,
unsigned int left_idx,
unsigned int right_idx, unsigned int depth,
const P &p, const Pred &pred) {
assert(left_idx <= right_idx);
unsigned int offset = static_cast<unsigned int>(out_nodes->size());
@@ -1554,10 +1632,10 @@ unsigned int BVHAccel<T>::BuildTree(
return offset;
}
template <typename T> template<class P, class Pred>
bool BVHAccel<T>::Build(unsigned int num_primitives,
const P &p, const Pred &pred,
const BVHBuildOptions<T> &options) {
template <typename T>
template <class P, class Pred>
bool BVHAccel<T>::Build(unsigned int num_primitives, const P &p,
const Pred &pred, const BVHBuildOptions<T> &options) {
options_ = options;
stats_ = BVHBuildStatistics();
@@ -1566,6 +1644,10 @@ bool BVHAccel<T>::Build(unsigned int num_primitives,
assert(options_.bin_size > 1);
if (num_primitives == 0) {
return false;
}
unsigned int n = num_primitives;
//
@@ -1697,15 +1779,9 @@ void BVHAccel<T>::Debug() {
}
for (size_t i = 0; i < nodes_.size(); i++) {
printf("node[%d] : bmin %f, %f, %f, bmax %f, %f, %f\n",
int(i),
nodes_[i].bmin[0],
nodes_[i].bmin[1],
nodes_[i].bmin[1],
nodes_[i].bmax[0],
nodes_[i].bmax[1],
nodes_[i].bmax[1]);
printf("node[%d] : bmin %f, %f, %f, bmax %f, %f, %f\n", int(i),
nodes_[i].bmin[0], nodes_[i].bmin[1], nodes_[i].bmin[1],
nodes_[i].bmax[0], nodes_[i].bmax[1], nodes_[i].bmax[1]);
}
}
@@ -1713,7 +1789,7 @@ template <typename T>
bool BVHAccel<T>::Dump(const char *filename) {
FILE *fp = fopen(filename, "wb");
if (!fp) {
//fprintf(stderr, "[BVHAccel] Cannot write a file: %s\n", filename);
// fprintf(stderr, "[BVHAccel] Cannot write a file: %s\n", filename);
return false;
}
@@ -1744,7 +1820,7 @@ template <typename T>
bool BVHAccel<T>::Load(const char *filename) {
FILE *fp = fopen(filename, "rb");
if (!fp) {
//fprintf(stderr, "Cannot open file: %s\n", filename);
// fprintf(stderr, "Cannot open file: %s\n", filename);
return false;
}
@@ -1815,10 +1891,10 @@ inline bool IntersectRayAABB(T *tminOut, // [out]
return false; // no hit
}
template <typename T> template<class I>
inline bool BVHAccel<T>::TestLeafNode(const BVHNode<T> &node,
const Ray<T> &ray,
const I &intersector) const {
template <typename T>
template <class I>
inline bool BVHAccel<T>::TestLeafNode(const BVHNode<T> &node, const Ray<T> &ray,
const I &intersector) const {
bool hit = false;
unsigned int num_primitives = node.data[0];
@@ -1841,20 +1917,18 @@ inline bool BVHAccel<T>::TestLeafNode(const BVHNode<T> &node,
T local_t = t;
if (intersector.Intersect(&local_t, prim_idx)) {
if (local_t > ray.min_t) {
// Update isect state
t = local_t;
// Update isect state
t = local_t;
intersector.Update(t, prim_idx);
hit = true;
}
intersector.Update(t, prim_idx);
hit = true;
}
}
return hit;
}
#if 0 // TODO(LTE): Implement
#if 0 // TODO(LTE): Implement
template <typename T> template<class I, class H, class Comp>
bool BVHAccel<T>::MultiHitTestLeafNode(
std::priority_queue<H, std::vector<H>, Comp> *isect_pq,
@@ -1928,11 +2002,10 @@ bool BVHAccel<T>::MultiHitTestLeafNode(
}
#endif
template <typename T> template<class I, class H>
bool BVHAccel<T>::Traverse(const Ray<T> &ray,
const I &intersector,
H *isect,
const BVHTraceOptions &options) const {
template <typename T>
template <class I, class H>
bool BVHAccel<T>::Traverse(const Ray<T> &ray, const I &intersector, H *isect,
const BVHTraceOptions &options) const {
const int kMaxStackDepth = 512;
T hit_t = ray.max_t;
@@ -1999,13 +2072,14 @@ bool BVHAccel<T>::Traverse(const Ray<T> &ray,
return hit;
}
template <typename T> template<class I>
inline bool BVHAccel<T>::TestLeafNodeIntersections(const BVHNode<T> &node,
const Ray<T> &ray,
const int max_intersections,
const I &intersector,
std::priority_queue<NodeHit<T>, std::vector<NodeHit<T> >, NodeHitComparator<T> > *isect_pq) const {
template <typename T>
template <class I>
inline bool BVHAccel<T>::TestLeafNodeIntersections(
const BVHNode<T> &node, const Ray<T> &ray, const int max_intersections,
const I &intersector,
std::priority_queue<NodeHit<T>, std::vector<NodeHit<T> >,
NodeHitComparator<T> > *isect_pq) const {
bool hit = false;
unsigned int num_primitives = node.data[0];
@@ -2043,7 +2117,6 @@ inline bool BVHAccel<T>::TestLeafNodeIntersections(const BVHNode<T> &node,
isect_pq->pop();
isect_pq->push(isect);
}
}
}
@@ -2052,11 +2125,11 @@ inline bool BVHAccel<T>::TestLeafNodeIntersections(const BVHNode<T> &node,
return hit;
}
template <typename T> template<class I>
bool BVHAccel<T>::ListNodeIntersections(const Ray<T> &ray,
int max_intersections,
const I &intersector,
StackVector<NodeHit<T>, 128> *hits) const {
template <typename T>
template <class I>
bool BVHAccel<T>::ListNodeIntersections(
const Ray<T> &ray, int max_intersections, const I &intersector,
StackVector<NodeHit<T>, 128> *hits) const {
const int kMaxStackDepth = 512;
T hit_t = ray.max_t;
@@ -2066,14 +2139,19 @@ bool BVHAccel<T>::ListNodeIntersections(const Ray<T> &ray,
node_stack[0] = 0;
// Stores furthest intersection at top
std::priority_queue<NodeHit<T>, std::vector<NodeHit<T> >, NodeHitComparator<T> > isect_pq;
std::priority_queue<NodeHit<T>, std::vector<NodeHit<T> >,
NodeHitComparator<T> >
isect_pq;
(*hits)->clear();
int dir_sign[3];
dir_sign[0] = ray.dir[0] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
dir_sign[1] = ray.dir[1] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
dir_sign[2] = ray.dir[2] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
dir_sign[0] =
ray.dir[0] < static_cast<T>(0.0) ? 1 : 0;
dir_sign[1] =
ray.dir[1] < static_cast<T>(0.0) ? 1 : 0;
dir_sign[2] =
ray.dir[2] < static_cast<T>(0.0) ? 1 : 0;
// @fixme { Check edge case; i.e., 1/0 }
real3<T> ray_inv_dir;
@@ -2108,7 +2186,8 @@ bool BVHAccel<T>::ListNodeIntersections(const Ray<T> &ray,
} else { // leaf node
if (hit) {
TestLeafNodeIntersections(node, ray, max_intersections, intersector, &isect_pq);
TestLeafNodeIntersections(node, ray, max_intersections, intersector,
&isect_pq);
}
}
}
@@ -2132,7 +2211,7 @@ bool BVHAccel<T>::ListNodeIntersections(const Ray<T> &ray,
return false;
}
#if 0 // TODO(LTE): Implement
#if 0 // TODO(LTE): Implement
template <typename T> template<class I, class H, class Comp>
bool BVHAccel<T>::MultiHitTraverse(const Ray<T> &ray,
int max_intersections,
@@ -2225,6 +2304,10 @@ bool BVHAccel<T>::MultiHitTraverse(const Ray<T> &ray,
}
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
} // namespace nanort
#endif // NANORT_H_
+185 -203
View File
@@ -31,35 +31,36 @@ THE SOFTWARE.
#endif
#endif
#include <iostream>
#include <limits>
#include <vector>
#include <iostream>
#include "nanort.h"
namespace nanosg {
template<class T>
template <class T>
class PrimitiveInterface;
template<class T>
class PrimitiveInterface{
public:
void print(){ static_cast<T &>(this)->print(); }
template <class T>
class PrimitiveInterface {
public:
void print() { static_cast<T &>(this)->print(); }
};
class SpherePrimitive : PrimitiveInterface<SpherePrimitive> {
public:
void print(){ std::cout << "Sphere" << std::endl; }
public:
void print() { std::cout << "Sphere" << std::endl; }
};
// 4x4 matrix
template <typename T> class Matrix {
public:
template <typename T>
class Matrix {
public:
Matrix();
~Matrix();
static void Print(T m[4][4]) {
static void Print(const T m[4][4]) {
for (int i = 0; i < 4; i++) {
printf("m[%d] = %f, %f, %f, %f\n", i, m[i][0], m[i][1], m[i][2], m[i][3]);
}
@@ -232,18 +233,15 @@ public:
dst[1] = tmp[1];
dst[2] = tmp[2];
}
};
//typedef Matrix<float> Matrixf;
//typedef Matrix<double> Matrixd;
template<typename T>
static void XformBoundingBox(T xbmin[3], // out
T xbmax[3], // out
T bmin[3], T bmax[3],
T m[4][4]) {
// typedef Matrix<float> Matrixf;
// typedef Matrix<double> Matrixd;
template <typename T>
static void XformBoundingBox(T xbmin[3], // out
T xbmax[3], // out
T bmin[3], T bmax[3], T m[4][4]) {
// create bounding vertex from (bmin, bmax)
T b[8][3];
@@ -286,7 +284,6 @@ static void XformBoundingBox(T xbmin[3], // out
xbmax[2] = xb[0][2];
for (int i = 1; i < 8; i++) {
xbmin[0] = std::min(xb[i][0], xbmin[0]);
xbmin[1] = std::min(xb[i][1], xbmin[1]);
xbmin[2] = std::min(xb[i][2], xbmin[2]);
@@ -297,48 +294,45 @@ static void XformBoundingBox(T xbmin[3], // out
}
}
template<typename T>
struct Intersection
{
template <typename T>
struct Intersection {
// required fields.
T t; // hit distance
unsigned int prim_id; // primitive ID of the hit
float u;
float v;
T t; // hit distance
unsigned int prim_id; // primitive ID of the hit
float u;
float v;
unsigned int node_id; // node ID of the hit.
nanort::real3<T> P; // intersection point
nanort::real3<T> Ns; // shading normal
nanort::real3<T> Ng; // geometric normal
unsigned int node_id; // node ID of the hit.
nanort::real3<T> P; // intersection point
nanort::real3<T> Ns; // shading normal
nanort::real3<T> Ng; // geometric normal
};
///
/// Renderable node
///
template<typename T, class M>
class Node
{
template <typename T, class M>
class Node {
public:
typedef Node<T, M> type;
explicit Node(const M *mesh)
: mesh_(mesh)
{
xbmin_[0] = xbmin_[1] = xbmin_[2] = std::numeric_limits<T>::max();
xbmax_[0] = xbmax_[1] = xbmax_[2] = -std::numeric_limits<T>::max();
explicit Node(const M *mesh) : mesh_(mesh) {
xbmin_[0] = xbmin_[1] = xbmin_[2] = std::numeric_limits<T>::max();
xbmax_[0] = xbmax_[1] = xbmax_[2] = -std::numeric_limits<T>::max();
lbmin_[0] = lbmin_[1] = lbmin_[2] = std::numeric_limits<T>::max();
lbmax_[0] = lbmax_[1] = lbmax_[2] = -std::numeric_limits<T>::max();
lbmin_[0] = lbmin_[1] = lbmin_[2] = std::numeric_limits<T>::max();
lbmax_[0] = lbmax_[1] = lbmax_[2] = -std::numeric_limits<T>::max();
Matrix<T>::Identity(local_xform_);
Matrix<T>::Identity(xform_);
Matrix<T>::Identity(inv_xform_);
Matrix<T>::Identity(inv_xform33_); inv_xform33_[3][3] = static_cast<T>(0.0);
Matrix<T>::Identity(inv_transpose_xform33_); inv_transpose_xform33_[3][3] = static_cast<T>(0.0);
Matrix<T>::Identity(inv_xform33_);
inv_xform33_[3][3] = static_cast<T>(0.0);
Matrix<T>::Identity(inv_transpose_xform33_);
inv_transpose_xform33_[3][3] = static_cast<T>(0.0);
}
}
~Node() {}
~Node() {}
void Copy(const type &rhs) {
Matrix<T>::Copy(local_xform_, rhs.local_xform_);
@@ -369,53 +363,44 @@ class Node
children_ = rhs.children_;
}
Node(const type &rhs) {
Copy(rhs);
}
Node(const type &rhs) { Copy(rhs); }
const type &operator=(const type &rhs) {
Copy(rhs);
return (*this);
}
void SetName(const std::string &name) {
name_ = name;
}
void SetName(const std::string &name) { name_ = name; }
const std::string &GetName() const {
return name_;
}
const std::string &GetName() const { return name_; }
///
/// Add child node.
///
void AddChild(const type &child) {
children_.push_back(child);
}
void AddChild(const type &child) { children_.push_back(child); }
///
/// Get chidren
///
const std::vector<type> &GetChildren() const {
return children_;
}
const std::vector<type> &GetChildren() const { return children_; }
std::vector<type> &GetChildren() {
return children_;
}
///
/// Update internal state.
///
void Update(const T parent_xform[4][4]) {
if (!accel_.IsValid() && mesh_ && (mesh_->vertices.size() > 3) && (mesh_->faces.size() >= 3)) {
std::vector<type> &GetChildren() { return children_; }
///
/// Update internal state.
///
void Update(const T parent_xform[4][4]) {
if (!accel_.IsValid() && mesh_ && (mesh_->vertices.size() > 3) &&
(mesh_->faces.size() >= 3)) {
// Assume mesh is composed of triangle faces only.
nanort::TriangleMesh<float> triangle_mesh(mesh_->vertices.data(), mesh_->faces.data(), sizeof(float) * 3);
nanort::TriangleSAHPred<float> triangle_pred(mesh_->vertices.data(), mesh_->faces.data(), sizeof(float) * 3);
nanort::TriangleMesh<float> triangle_mesh(
mesh_->vertices.data(), mesh_->faces.data(), mesh_->stride);
nanort::TriangleSAHPred<float> triangle_pred(
mesh_->vertices.data(), mesh_->faces.data(), mesh_->stride);
bool ret = accel_.Build(int(mesh_->faces.size()) / 3, triangle_mesh, triangle_pred);
bool ret =
accel_.Build(static_cast<unsigned int>(mesh_->faces.size()) / 3,
triangle_mesh, triangle_pred);
// Update local bbox.
if (ret) {
@@ -433,7 +418,7 @@ class Node
Matrix<T>::Copy(inv_xform_, xform_);
Matrix<T>::Inverse(inv_xform_);
// Clear translation, then inverse(xform)
// Clear translation, then inverse(xform)
Matrix<T>::Copy(inv_xform33_, xform_);
inv_xform33_[3][0] = static_cast<T>(0.0);
inv_xform33_[3][1] = static_cast<T>(0.0);
@@ -448,67 +433,61 @@ class Node
for (size_t i = 0; i < children_.size(); i++) {
children_[i].Update(xform_);
}
}
}
///
/// Set local transformation.
///
///
/// Set local transformation.
///
void SetLocalXform(const T xform[4][4]) {
memcpy(local_xform_, xform, sizeof(float) * 16);
}
const T *GetLocalXformPtr() const {
return &local_xform_[0][0];
const T *GetLocalXformPtr() const { return &local_xform_[0][0]; }
const T *GetXformPtr() const { return &xform_[0][0]; }
const M *GetMesh() const { return mesh_; }
const nanort::BVHAccel<T> &GetAccel() const { return accel_; }
inline void GetWorldBoundingBox(T bmin[3], T bmax[3]) const {
bmin[0] = xbmin_[0];
bmin[1] = xbmin_[1];
bmin[2] = xbmin_[2];
bmax[0] = xbmax_[0];
bmax[1] = xbmax_[1];
bmax[2] = xbmax_[2];
}
const T *GetXformPtr() const {
return &xform_[0][0];
inline void GetLocalBoundingBox(T bmin[3], T bmax[3]) const {
bmin[0] = lbmin_[0];
bmin[1] = lbmin_[1];
bmin[2] = lbmin_[2];
bmax[0] = lbmax_[0];
bmax[1] = lbmax_[1];
bmax[2] = lbmax_[2];
}
const M *GetMesh() const {
return mesh_;
}
const nanort::BVHAccel<T> &GetAccel() const {
return accel_;
}
inline void GetWorldBoundingBox(T bmin[3], T bmax[3]) const {
bmin[0] = xbmin_[0];
bmin[1] = xbmin_[1];
bmin[2] = xbmin_[2];
bmax[0] = xbmax_[0];
bmax[1] = xbmax_[1];
bmax[2] = xbmax_[2];
}
inline void GetLocalBoundingBox(T bmin[3], T bmax[3]) const {
bmin[0] = lbmin_[0];
bmin[1] = lbmin_[1];
bmin[2] = lbmin_[2];
bmax[0] = lbmax_[0];
bmax[1] = lbmax_[1];
bmax[2] = lbmax_[2];
}
T local_xform_[4][4]; // Node's local transformation matrix.
T xform_[4][4]; // Parent xform x local_xform.
T inv_xform_[4][4]; // inverse(xform). world -> local
T inv_xform33_[4][4]; // inverse(xform0 with upper-left 3x3 elemets only(for transforming direction vector)
T inv_transpose_xform33_[4][4]; // inverse(transpose(xform)) with upper-left 3x3 elements only(for transforming normal vector)
T local_xform_[4][4]; // Node's local transformation matrix.
T xform_[4][4]; // Parent xform x local_xform.
T inv_xform_[4][4]; // inverse(xform). world -> local
T inv_xform33_[4][4]; // inverse(xform0 with upper-left 3x3 elemets only(for
// transforming direction vector)
T inv_transpose_xform33_[4][4]; // inverse(transpose(xform)) with upper-left
// 3x3 elements only(for transforming normal
// vector)
private:
// bounding box(local space)
T lbmin_[3];
T lbmax_[3];
// bounding box(local space)
T lbmin_[3];
T lbmax_[3];
// bounding box after xform(world space)
T xbmin_[3];
T xbmax_[3];
// bounding box after xform(world space)
T xbmin_[3];
T xbmax_[3];
nanort::BVHAccel<T> accel_;
std::string name_;
@@ -516,16 +495,16 @@ class Node
const M *mesh_;
std::vector<type> children_;
};
// -------------------------------------------------
// Predefined SAH predicator for cube.
template<typename T, class M>
template <typename T, class M>
class NodeBBoxPred {
public:
NodeBBoxPred(const std::vector<Node<T, M> >* nodes) : axis_(0), pos_(0.0f), nodes_(nodes) {}
NodeBBoxPred(const std::vector<Node<T, M> > *nodes)
: axis_(0), pos_(0.0f), nodes_(nodes) {}
void Set(int axis, float pos) const {
axis_ = axis;
@@ -538,8 +517,8 @@ class NodeBBoxPred {
T bmin[3], bmax[3];
(*nodes_)[i].GetWorldBoundingBox(bmin, bmax);
(*nodes_)[i].GetWorldBoundingBox(bmin, bmax);
T center = bmax[axis] - bmin[axis];
return (center < pos);
@@ -551,15 +530,15 @@ class NodeBBoxPred {
const std::vector<Node<T, M> > *nodes_;
};
template<typename T, class M>
template <typename T, class M>
class NodeBBoxGeometry {
public:
NodeBBoxGeometry(const std::vector<Node<T, M> >* nodes)
: nodes_(nodes) {}
NodeBBoxGeometry(const std::vector<Node<T, M> > *nodes) : nodes_(nodes) {}
/// Compute bounding box for `prim_index`th cube.
/// This function is called for each primitive in BVH build.
void BoundingBox(nanort::real3<T>* bmin, nanort::real3<T>* bmax, unsigned int prim_index) const {
void BoundingBox(nanort::real3<T> *bmin, nanort::real3<T> *bmax,
unsigned int prim_index) const {
T a[3], b[3];
(*nodes_)[prim_index].GetWorldBoundingBox(a, b);
(*bmin)[0] = a[0];
@@ -570,10 +549,11 @@ class NodeBBoxGeometry {
(*bmax)[2] = b[2];
}
const std::vector<Node<T, M> >* nodes_;
const std::vector<Node<T, M> > *nodes_;
mutable nanort::real3<T> ray_org_;
mutable nanort::real3<T> ray_dir_;
mutable nanort::BVHTraceOptions trace_options_;
int _pad_;
};
class NodeBBoxIntersection {
@@ -587,14 +567,13 @@ class NodeBBoxIntersection {
unsigned int prim_id;
};
template<typename T, class M>
template <typename T, class M>
class NodeBBoxIntersector {
public:
NodeBBoxIntersector(const std::vector<Node<T, M> >* nodes)
: nodes_(nodes) {}
bool Intersect(float* out_t_min, float *out_t_max, unsigned int prim_index) const {
NodeBBoxIntersector(const std::vector<Node<T, M> > *nodes) : nodes_(nodes) {}
bool Intersect(float *out_t_min, float *out_t_max,
unsigned int prim_index) const {
T bmin[3], bmax[3];
(*nodes_)[prim_index].GetWorldBoundingBox(bmin, bmax);
@@ -634,7 +613,7 @@ class NodeBBoxIntersector {
/// Prepare BVH traversal(e.g. compute inverse ray direction)
/// This function is called only once in BVH traversal.
void PrepareTraversal(const nanort::Ray<float>& ray) const {
void PrepareTraversal(const nanort::Ray<float> &ray) const {
ray_org_[0] = ray.org[0];
ray_org_[1] = ray.org[1];
ray_org_[2] = ray.org[2];
@@ -648,40 +627,37 @@ class NodeBBoxIntersector {
ray_inv_dir_[1] = static_cast<T>(1.0) / ray.dir[1];
ray_inv_dir_[2] = static_cast<T>(1.0) / ray.dir[2];
ray_dir_sign_[0] = ray.dir[0] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
ray_dir_sign_[1] = ray.dir[1] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
ray_dir_sign_[2] = ray.dir[2] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
ray_dir_sign_[0] = ray.dir[0] < static_cast<T>(0.0) ? 1 : 0;
ray_dir_sign_[1] = ray.dir[1] < static_cast<T>(0.0) ? 1 : 0;
ray_dir_sign_[2] = ray.dir[2] < static_cast<T>(0.0) ? 1 : 0;
}
const std::vector<Node<T, M> >* nodes_;
const std::vector<Node<T, M> > *nodes_;
mutable nanort::real3<T> ray_org_;
mutable nanort::real3<T> ray_dir_;
mutable nanort::real3<T> ray_inv_dir_;
mutable int ray_dir_sign_[3];
};
template<typename T, class M>
class Scene
{
template <typename T, class M>
class Scene {
public:
Scene() {
Scene() {
bmin_[0] = bmin_[1] = bmin_[2] = std::numeric_limits<T>::max();
bmax_[0] = bmax_[1] = bmax_[2] = -std::numeric_limits<T>::max();
}
~Scene() {};
~Scene() {}
///
/// Add intersectable node to the scene.
///
bool AddNode(const Node<T, M> &node) {
bool AddNode(const Node<T, M> &node) {
nodes_.push_back(node);
return true;
}
const std::vector<Node<T, M> > &GetNodes() const {
return nodes_;
}
const std::vector<Node<T, M> > &GetNodes() const { return nodes_; }
bool FindNode(const std::string &name, Node<T, M> **found_node) {
if (!found_node) {
@@ -702,11 +678,15 @@ class Scene
return false;
}
///
/// Commit the scene. Must be called before tracing rays into the scene.
///
bool Commit() {
// the scene should contains something
if (nodes_.size() == 0) {
std::cerr << "You are attempting to commit an empty scene!\n";
return false;
}
// Update nodes.
for (size_t i = 0; i < nodes_.size(); i++) {
@@ -719,21 +699,26 @@ class Scene
// Build toplevel BVH.
NodeBBoxGeometry<T, M> geom(&nodes_);
NodeBBoxPred<T, M> pred(&nodes_);
// FIXME(LTE): Limit one leaf contains one node bbox primitive. This would work, but would be inefficient.
// e.g. will miss some node when constructed BVH depth is larger than the value of BVHBuildOptions.
// Implement more better and efficient BVH build and traverse for Toplevel BVH.
// FIXME(LTE): Limit one leaf contains one node bbox primitive. This would
// work, but would be inefficient.
// e.g. will miss some node when constructed BVH depth is larger than the
// value of BVHBuildOptions.
// Implement more better and efficient BVH build and traverse for Toplevel
// BVH.
nanort::BVHBuildOptions<T> build_options;
build_options.min_leaf_primitives = 1;
bool ret = toplevel_accel_.Build(static_cast<unsigned int>(nodes_.size()), geom, pred, build_options);
bool ret = toplevel_accel_.Build(static_cast<unsigned int>(nodes_.size()),
geom, pred, build_options);
nanort::BVHBuildStatistics stats = toplevel_accel_.GetStatistics();
(void)stats;
//toplevel_accel_.Debug();
// toplevel_accel_.Debug();
if (ret) {
toplevel_accel_.BoundingBox(bmin_, bmax_);
toplevel_accel_.BoundingBox(bmin_, bmax_);
} else {
// Set invalid bbox value.
bmin_[0] = std::numeric_limits<T>::max();
@@ -766,51 +751,54 @@ class Scene
/// First find the intersection of nodes' bounding box using toplevel BVH.
/// Then, trace into the hit node to find the intersection of the primitive.
///
template<class H>
bool Traverse(nanort::Ray<T> &ray, H *isect, const bool cull_back_face = false) const {
template <class H>
bool Traverse(nanort::Ray<T> &ray, H *isect,
const bool cull_back_face = false) const {
if (!toplevel_accel_.IsValid()) {
return false;
}
const int kMaxIntersections = 64;
const int kMaxIntersections = 64;
bool has_hit = false;
NodeBBoxIntersector<T, M> isector(&nodes_);
nanort::StackVector<nanort::NodeHit<T>, 128> node_hits;
bool may_hit = toplevel_accel_.ListNodeIntersections(ray, kMaxIntersections, isector, &node_hits);
bool may_hit = toplevel_accel_.ListNodeIntersections(ray, kMaxIntersections,
isector, &node_hits);
if (may_hit) {
T t_max = std::numeric_limits<T>::max();
T t_nearest = t_max;
if (may_hit) {
T t_max = std::numeric_limits<T>::max();
T t_nearest = t_max;
nanort::BVHTraceOptions trace_options;
trace_options.cull_back_face = cull_back_face;
// Find actual intersection point.
for (size_t i = 0; i < node_hits->size(); i++) {
// Early cull test.
// Find actual intersection point.
for (size_t i = 0; i < node_hits->size(); i++) {
// Early cull test.
if (t_nearest < node_hits[i].t_min) {
//printf("near: %f, t_min: %f, t_max: %f\n", t_nearest, node_hits[i].t_min, node_hits[i].t_max);
// printf("near: %f, t_min: %f, t_max: %f\n", t_nearest,
// node_hits[i].t_min, node_hits[i].t_max);
continue;
}
assert(node_hits[i].node_id < nodes_.size());
const Node<T, M> &node = nodes_[node_hits[i].node_id];
// Transform ray into node's local space
// Transform ray into node's local space
// TODO(LTE): Set ray tmin and tmax
nanort::Ray<T> local_ray;
Matrix<T>::MultV(local_ray.org, node.inv_xform_, ray.org);
Matrix<T>::MultV(local_ray.dir, node.inv_xform33_, ray.dir);
nanort::TriangleIntersector<T, H> triangle_intersector(node.GetMesh()->vertices.data(), node.GetMesh()->faces.data(), sizeof(T) * 3);
nanort::TriangleIntersector<T, H> triangle_intersector(
node.GetMesh()->vertices.data(), node.GetMesh()->faces.data(),
node.GetMesh()->stride);
H local_isect;
bool hit = node.GetAccel().Traverse(local_ray, triangle_intersector, &local_isect);
bool hit = node.GetAccel().Traverse(local_ray, triangle_intersector,
&local_isect);
if (hit) {
// Calulcate hit distance in world coordiante.
@@ -828,6 +816,7 @@ class Scene
po[2] = world_P[2] - ray.org[2];
float t_world = vlength(po);
// printf("tworld %f, tnear %f\n", t_world, t_nearest);
if (t_world < t_nearest) {
t_nearest = t_world;
@@ -839,36 +828,30 @@ class Scene
isect->v = local_isect.v;
// TODO(LTE): Implement
T Ng[3], Ns[3]; // geometric normal, shading normal.
T Ng[3], Ns[3]; // geometric normal, shading normal.
node.GetMesh()->GetNormal(Ng, Ns, isect->prim_id, isect->u,
isect->v);
node.GetMesh()->GetNormal(Ng, Ns, isect->prim_id, isect->u, isect->v);
// Convert position and normal into world coordinate.
isect->t = t_world;
Matrix<T>::MultV(isect->P, node.xform_, local_P);
Matrix<T>::MultV(isect->Ng, node.inv_transpose_xform33_,
Ng);
Matrix<T>::MultV(isect->Ns, node.inv_transpose_xform33_,
Ns);
}
Matrix<T>::MultV(isect->Ng, node.inv_transpose_xform33_, Ng);
Matrix<T>::MultV(isect->Ns, node.inv_transpose_xform33_, Ns);
}
}
}
}
}
}
return has_hit;
}
private:
///
/// Find a node by name.
///
bool FindNodeRecursive(const std::string &name, Node<T, M> *root, Node<T, M> **found_node) {
///
bool FindNodeRecursive(const std::string &name, Node<T, M> *root,
Node<T, M> **found_node) {
if (root->GetName().compare(name) == 0) {
(*found_node) = root;
return true;
@@ -882,19 +865,18 @@ class Scene
}
return false;
}
// Scene bounding box.
// Valid after calling `Commit()`.
T bmin_[3];
T bmax_[3];
// Toplevel BVH accel.
nanort::BVHAccel<T> toplevel_accel_;
std::vector<Node<T, M> > nodes_;
std::vector<Node<T, M> > nodes_;
};
} // namespace nanosg
} // namespace nanosg
#endif // NANOSG_H_
#endif // NANOSG_H_
+458
View File
@@ -0,0 +1,458 @@
#include "obj-loader.h"
#include "nanort.h" // for float3
#define TINYOBJLOADER_IMPLEMENTATION
#include "tiny_obj_loader.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wreserved-id-macro"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#pragma clang diagnostic ignored "-Wcast-align"
#pragma clang diagnostic ignored "-Wpadded"
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wvariadic-macros"
#pragma clang diagnostic ignored "-Wc++11-extensions"
#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#if __has_warning("-Wdouble-promotion")
#pragma clang diagnostic ignored "-Wdouble-promotion"
#endif
#if __has_warning("-Wcomma")
#pragma clang diagnostic ignored "-Wcomma"
#endif
#if __has_warning("-Wcast-qual")
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
#endif
#include "stb_image.h"
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#include <iostream>
#ifdef NANOSG_USE_CXX11
#include <unordered_map>
#else
#include <map>
#endif
#define USE_TEX_CACHE 1
namespace example {
typedef nanort::real3<float> float3;
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wglobal-constructors"
#endif
// TODO(LTE): Remove global static definition.
#ifdef NANOSG_USE_CXX11
static std::unordered_map<std::string, int> hashed_tex;
#else
static std::map<std::string, int> hashed_tex;
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
inline void CalcNormal(float3 &N, float3 v0, float3 v1, float3 v2) {
float3 v10 = v1 - v0;
float3 v20 = v2 - v0;
N = vcross(v20, v10);
N = vnormalize(N);
}
static std::string GetBaseDir(const std::string &filepath) {
if (filepath.find_last_of("/\\") != std::string::npos)
return filepath.substr(0, filepath.find_last_of("/\\"));
return "";
}
static int LoadTexture(const std::string &filename,
std::vector<Texture> *textures) {
int idx;
if (filename.empty()) return -1;
std::cout << " Loading texture : " << filename << std::endl;
Texture texture;
// tigra: find in cache. get index
if (USE_TEX_CACHE) {
if (hashed_tex.find(filename) != hashed_tex.end()) {
puts("from cache");
return hashed_tex[filename];
}
}
int w, h, n;
unsigned char *data = stbi_load(filename.c_str(), &w, &h, &n, 0);
if (data) {
texture.width = w;
texture.height = h;
texture.components = n;
size_t n_elem = size_t(w * h * n);
texture.image = new unsigned char[n_elem];
for (size_t i = 0; i < n_elem; i++) {
texture.image[i] = data[i];
}
free(data);
textures->push_back(texture);
idx = int(textures->size()) - 1;
// tigra: store index to cache
if (USE_TEX_CACHE) {
hashed_tex[filename] = idx;
}
return idx;
}
std::cout << " Failed to load : " << filename << std::endl;
return -1;
}
static void ComputeBoundingBoxOfMesh(float bmin[3], float bmax[3],
const example::Mesh<float> &mesh) {
bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<float>::max();
bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits<float>::max();
for (size_t i = 0; i < mesh.vertices.size() / 3; i++) {
bmin[0] = std::min(bmin[0], mesh.vertices[3 * i + 0]);
bmin[1] = std::min(bmin[1], mesh.vertices[3 * i + 1]);
bmin[2] = std::min(bmin[1], mesh.vertices[3 * i + 2]);
bmax[0] = std::max(bmax[0], mesh.vertices[3 * i + 0]);
bmax[1] = std::max(bmax[1], mesh.vertices[3 * i + 1]);
bmax[2] = std::max(bmax[2], mesh.vertices[3 * i + 2]);
}
}
bool LoadObj(const std::string &filename, float scale,
std::vector<Mesh<float> > *meshes,
std::vector<Material> *out_materials,
std::vector<Texture> *out_textures) {
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
std::string err;
std::string basedir = GetBaseDir(filename) + "/";
const char *basepath = (basedir.compare("/") == 0) ? NULL : basedir.c_str();
// auto t_start = std::chrono::system_clock::now();
bool ret =
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename.c_str(),
basepath, /* triangulate */ true);
// auto t_end = std::chrono::system_clock::now();
// std::chrono::duration<double, std::milli> ms = t_end - t_start;
if (!err.empty()) {
std::cerr << err << std::endl;
}
if (!ret) {
return false;
}
// std::cout << "[LoadOBJ] Parse time : " << ms.count() << " [msecs]"
// << std::endl;
std::cout << "[LoadOBJ] # of shapes in .obj : " << shapes.size() << std::endl;
std::cout << "[LoadOBJ] # of materials in .obj : " << materials.size()
<< std::endl;
{
size_t total_num_vertices = 0;
size_t total_num_faces = 0;
total_num_vertices = attrib.vertices.size() / 3;
std::cout << " vertices : " << attrib.vertices.size() / 3 << std::endl;
for (size_t i = 0; i < shapes.size(); i++) {
std::cout << " shape[" << i << "].name : " << shapes[i].name
<< std::endl;
std::cout << " shape[" << i
<< "].indices : " << shapes[i].mesh.indices.size() << std::endl;
assert((shapes[i].mesh.indices.size() % 3) == 0);
total_num_faces += shapes[i].mesh.indices.size() / 3;
// tigra: empty name convert to _id
if (shapes[i].name.length() == 0) {
#ifdef NANOSG_USE_CXX11
shapes[i].name = "_" + std::to_string(i);
#else
std::stringstream ss;
ss << i;
shapes[i].name = "_" + ss.str();
#endif
std::cout << " EMPTY shape[" << i << "].name, new : " << shapes[i].name
<< std::endl;
}
}
std::cout << "[LoadOBJ] # of faces: " << total_num_faces << std::endl;
std::cout << "[LoadOBJ] # of vertices: " << total_num_vertices << std::endl;
}
// TODO(LTE): Implement tangents and binormals
for (size_t i = 0; i < shapes.size(); i++) {
Mesh<float> mesh(/* stride */ sizeof(float) * 3);
mesh.name = shapes[i].name;
const size_t num_faces = shapes[i].mesh.indices.size() / 3;
mesh.faces.resize(num_faces * 3);
mesh.material_ids.resize(num_faces);
mesh.facevarying_normals.resize(num_faces * 3 * 3);
mesh.facevarying_uvs.resize(num_faces * 3 * 2);
mesh.vertices.resize(num_faces * 3 * 3);
for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
// reorder vertices. may create duplicated vertices.
size_t f0 = size_t(shapes[i].mesh.indices[3 * f + 0].vertex_index);
size_t f1 = size_t(shapes[i].mesh.indices[3 * f + 1].vertex_index);
size_t f2 = size_t(shapes[i].mesh.indices[3 * f + 2].vertex_index);
mesh.vertices[9 * f + 0] = scale * attrib.vertices[3 * f0 + 0];
mesh.vertices[9 * f + 1] = scale * attrib.vertices[3 * f0 + 1];
mesh.vertices[9 * f + 2] = scale * attrib.vertices[3 * f0 + 2];
mesh.vertices[9 * f + 3] = scale * attrib.vertices[3 * f1 + 0];
mesh.vertices[9 * f + 4] = scale * attrib.vertices[3 * f1 + 1];
mesh.vertices[9 * f + 5] = scale * attrib.vertices[3 * f1 + 2];
mesh.vertices[9 * f + 6] = scale * attrib.vertices[3 * f2 + 0];
mesh.vertices[9 * f + 7] = scale * attrib.vertices[3 * f2 + 1];
mesh.vertices[9 * f + 8] = scale * attrib.vertices[3 * f2 + 2];
mesh.faces[3 * f + 0] = static_cast<unsigned int>(3 * f + 0);
mesh.faces[3 * f + 1] = static_cast<unsigned int>(3 * f + 1);
mesh.faces[3 * f + 2] = static_cast<unsigned int>(3 * f + 2);
mesh.material_ids[f] =
static_cast<unsigned int>(shapes[i].mesh.material_ids[f]);
}
if (attrib.normals.size() > 0) {
for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
size_t f0, f1, f2;
f0 = size_t(shapes[i].mesh.indices[3 * f + 0].normal_index);
f1 = size_t(shapes[i].mesh.indices[3 * f + 1].normal_index);
f2 = size_t(shapes[i].mesh.indices[3 * f + 2].normal_index);
if (f0 > 0 && f1 > 0 && f2 > 0) {
float n0[3], n1[3], n2[3];
n0[0] = attrib.normals[3 * f0 + 0];
n0[1] = attrib.normals[3 * f0 + 1];
n0[2] = attrib.normals[3 * f0 + 2];
n1[0] = attrib.normals[3 * f1 + 0];
n1[1] = attrib.normals[3 * f1 + 1];
n1[2] = attrib.normals[3 * f1 + 2];
n2[0] = attrib.normals[3 * f2 + 0];
n2[1] = attrib.normals[3 * f2 + 1];
n2[2] = attrib.normals[3 * f2 + 2];
mesh.facevarying_normals[3 * (3 * f + 0) + 0] = n0[0];
mesh.facevarying_normals[3 * (3 * f + 0) + 1] = n0[1];
mesh.facevarying_normals[3 * (3 * f + 0) + 2] = n0[2];
mesh.facevarying_normals[3 * (3 * f + 1) + 0] = n1[0];
mesh.facevarying_normals[3 * (3 * f + 1) + 1] = n1[1];
mesh.facevarying_normals[3 * (3 * f + 1) + 2] = n1[2];
mesh.facevarying_normals[3 * (3 * f + 2) + 0] = n2[0];
mesh.facevarying_normals[3 * (3 * f + 2) + 1] = n2[1];
mesh.facevarying_normals[3 * (3 * f + 2) + 2] = n2[2];
} else { // face contains invalid normal index. calc geometric normal.
f0 = size_t(shapes[i].mesh.indices[3 * f + 0].vertex_index);
f1 = size_t(shapes[i].mesh.indices[3 * f + 1].vertex_index);
f2 = size_t(shapes[i].mesh.indices[3 * f + 2].vertex_index);
float3 v0, v1, v2;
v0[0] = attrib.vertices[3 * f0 + 0];
v0[1] = attrib.vertices[3 * f0 + 1];
v0[2] = attrib.vertices[3 * f0 + 2];
v1[0] = attrib.vertices[3 * f1 + 0];
v1[1] = attrib.vertices[3 * f1 + 1];
v1[2] = attrib.vertices[3 * f1 + 2];
v2[0] = attrib.vertices[3 * f2 + 0];
v2[1] = attrib.vertices[3 * f2 + 1];
v2[2] = attrib.vertices[3 * f2 + 2];
float3 N;
CalcNormal(N, v0, v1, v2);
mesh.facevarying_normals[3 * (3 * f + 0) + 0] = N[0];
mesh.facevarying_normals[3 * (3 * f + 0) + 1] = N[1];
mesh.facevarying_normals[3 * (3 * f + 0) + 2] = N[2];
mesh.facevarying_normals[3 * (3 * f + 1) + 0] = N[0];
mesh.facevarying_normals[3 * (3 * f + 1) + 1] = N[1];
mesh.facevarying_normals[3 * (3 * f + 1) + 2] = N[2];
mesh.facevarying_normals[3 * (3 * f + 2) + 0] = N[0];
mesh.facevarying_normals[3 * (3 * f + 2) + 1] = N[1];
mesh.facevarying_normals[3 * (3 * f + 2) + 2] = N[2];
}
}
} else {
// calc geometric normal
for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
size_t f0, f1, f2;
f0 = size_t(shapes[i].mesh.indices[3 * f + 0].vertex_index);
f1 = size_t(shapes[i].mesh.indices[3 * f + 1].vertex_index);
f2 = size_t(shapes[i].mesh.indices[3 * f + 2].vertex_index);
float3 v0, v1, v2;
v0[0] = attrib.vertices[3 * f0 + 0];
v0[1] = attrib.vertices[3 * f0 + 1];
v0[2] = attrib.vertices[3 * f0 + 2];
v1[0] = attrib.vertices[3 * f1 + 0];
v1[1] = attrib.vertices[3 * f1 + 1];
v1[2] = attrib.vertices[3 * f1 + 2];
v2[0] = attrib.vertices[3 * f2 + 0];
v2[1] = attrib.vertices[3 * f2 + 1];
v2[2] = attrib.vertices[3 * f2 + 2];
float3 N;
CalcNormal(N, v0, v1, v2);
mesh.facevarying_normals[3 * (3 * f + 0) + 0] = N[0];
mesh.facevarying_normals[3 * (3 * f + 0) + 1] = N[1];
mesh.facevarying_normals[3 * (3 * f + 0) + 2] = N[2];
mesh.facevarying_normals[3 * (3 * f + 1) + 0] = N[0];
mesh.facevarying_normals[3 * (3 * f + 1) + 1] = N[1];
mesh.facevarying_normals[3 * (3 * f + 1) + 2] = N[2];
mesh.facevarying_normals[3 * (3 * f + 2) + 0] = N[0];
mesh.facevarying_normals[3 * (3 * f + 2) + 1] = N[1];
mesh.facevarying_normals[3 * (3 * f + 2) + 2] = N[2];
}
}
if (attrib.texcoords.size() > 0) {
for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
size_t f0, f1, f2;
f0 = size_t(shapes[i].mesh.indices[3 * f + 0].texcoord_index);
f1 = size_t(shapes[i].mesh.indices[3 * f + 1].texcoord_index);
f2 = size_t(shapes[i].mesh.indices[3 * f + 2].texcoord_index);
if (f0 > 0 && f1 > 0 && f2 > 0) {
float3 n0, n1, n2;
n0[0] = attrib.texcoords[2 * f0 + 0];
n0[1] = attrib.texcoords[2 * f0 + 1];
n1[0] = attrib.texcoords[2 * f1 + 0];
n1[1] = attrib.texcoords[2 * f1 + 1];
n2[0] = attrib.texcoords[2 * f2 + 0];
n2[1] = attrib.texcoords[2 * f2 + 1];
mesh.facevarying_uvs[2 * (3 * f + 0) + 0] = n0[0];
mesh.facevarying_uvs[2 * (3 * f + 0) + 1] = n0[1];
mesh.facevarying_uvs[2 * (3 * f + 1) + 0] = n1[0];
mesh.facevarying_uvs[2 * (3 * f + 1) + 1] = n1[1];
mesh.facevarying_uvs[2 * (3 * f + 2) + 0] = n2[0];
mesh.facevarying_uvs[2 * (3 * f + 2) + 1] = n2[1];
}
}
}
// Compute pivot translation and add offset to the vertices.
float bmin[3], bmax[3];
ComputeBoundingBoxOfMesh(bmin, bmax, mesh);
float bcenter[3];
bcenter[0] = 0.5f * (bmax[0] - bmin[0]) + bmin[0];
bcenter[1] = 0.5f * (bmax[1] - bmin[1]) + bmin[1];
bcenter[2] = 0.5f * (bmax[2] - bmin[2]) + bmin[2];
for (size_t v = 0; v < mesh.vertices.size() / 3; v++) {
mesh.vertices[3 * v + 0] -= bcenter[0];
mesh.vertices[3 * v + 1] -= bcenter[1];
mesh.vertices[3 * v + 2] -= bcenter[2];
}
mesh.pivot_xform[0][0] = 1.0f;
mesh.pivot_xform[0][1] = 0.0f;
mesh.pivot_xform[0][2] = 0.0f;
mesh.pivot_xform[0][3] = 0.0f;
mesh.pivot_xform[1][0] = 0.0f;
mesh.pivot_xform[1][1] = 1.0f;
mesh.pivot_xform[1][2] = 0.0f;
mesh.pivot_xform[1][3] = 0.0f;
mesh.pivot_xform[2][0] = 0.0f;
mesh.pivot_xform[2][1] = 0.0f;
mesh.pivot_xform[2][2] = 1.0f;
mesh.pivot_xform[2][3] = 0.0f;
mesh.pivot_xform[3][0] = bcenter[0];
mesh.pivot_xform[3][1] = bcenter[1];
mesh.pivot_xform[3][2] = bcenter[2];
mesh.pivot_xform[3][3] = 1.0f;
meshes->push_back(mesh);
}
// material_t -> Material and Texture
out_materials->resize(materials.size());
out_textures->resize(0);
for (size_t i = 0; i < materials.size(); i++) {
(*out_materials)[i].diffuse[0] = materials[i].diffuse[0];
(*out_materials)[i].diffuse[1] = materials[i].diffuse[1];
(*out_materials)[i].diffuse[2] = materials[i].diffuse[2];
(*out_materials)[i].specular[0] = materials[i].specular[0];
(*out_materials)[i].specular[1] = materials[i].specular[1];
(*out_materials)[i].specular[2] = materials[i].specular[2];
(*out_materials)[i].id = int(i);
// map_Kd
(*out_materials)[i].diffuse_texid =
LoadTexture(materials[i].diffuse_texname, out_textures);
// map_Ks
(*out_materials)[i].specular_texid =
LoadTexture(materials[i].specular_texname, out_textures);
}
return true;
}
} // namespace example
+19
View File
@@ -0,0 +1,19 @@
#ifndef EXAMPLE_OBJ_LOADER_H_
#define EXAMPLE_OBJ_LOADER_H_
#include <vector>
#include <string>
#include "mesh.h"
#include "material.h"
namespace example {
///
/// Loads wavefront .obj mesh
///
bool LoadObj(const std::string &filename, float scale, std::vector<Mesh<float> > *meshes, std::vector<Material> *materials, std::vector<Texture> *textures);
}
#endif // EXAMPLE_OBJ_LOADER_H_
+8 -2
View File
@@ -1,12 +1,19 @@
newoption {
trigger = "with-gtk3nfd",
description = "Build with native file dialog support(GTK3 required. Linux only)"
}
newoption {
trigger = "asan",
description = "Enable Address Sanitizer(gcc5+ ang clang only)"
}
sources = {
"stbi-impl.cc",
"main.cc",
"render.cc",
"render-config.cc",
"obj-loader.cc",
"gltf-loader.cc",
"matrix.cc",
"../common/trackball.cc",
@@ -16,7 +23,7 @@ sources = {
"../common/imgui/ImGuizmo.cpp",
}
solution "RaytraceSolution"
solution "NanoSGSolution"
configurations { "Release", "Debug" }
if os.is("Windows") then
@@ -53,7 +60,6 @@ solution "RaytraceSolution"
end
if os.is("Windows") then
flags { "FatalCompileWarnings" }
warnings "Extra" -- /W4
defines { "NOMINMAX" }
+13 -1
View File
@@ -29,12 +29,24 @@ bool LoadRenderConfig(example::RenderConfig* config, const char* filename) {
picojson::object o = v.get<picojson::object>();
if (o.find("obj_filename") != o.end()) {
if (o["obj_filename"].is<std::string>()) {
config->obj_filename = o["obj_filename"].get<std::string>();
}
}
if (o.find("gltf_filename") != o.end()) {
if (o["gltf_filename"].is<std::string>()) {
config->gltf_filename = o["gltf_filename"].get<std::string>();
}
}
if (o.find("eson_filename") != o.end()) {
if (o["eson_filename"].is<std::string>()) {
config->eson_filename = o["eson_filename"].get<std::string>();
}
}
config->scene_scale = 1.0f;
if (o.find("scene_scale") != o.end()) {
if (o["scene_scale"].is<double>()) {
@@ -107,4 +119,4 @@ bool LoadRenderConfig(example::RenderConfig* config, const char* filename) {
return true;
}
}
} // namespace example
+2
View File
@@ -28,7 +28,9 @@ typedef struct {
float *varycoordImage;
// Scene input info
std::string obj_filename;
std::string gltf_filename;
std::string eson_filename;
float scene_scale;
} RenderConfig;
+65 -17
View File
@@ -200,6 +200,7 @@ void BuildCameraFrame(float3* origin, float3* corner, float3* u, float3* v,
}
}
#if 0 // TODO(LTE): Not used method. Delete.
nanort::Ray<float> GenerateRay(const float3& origin, const float3& corner,
const float3& du, const float3& dv, float u,
float v) {
@@ -217,9 +218,12 @@ nanort::Ray<float> GenerateRay(const float3& origin, const float3& corner,
ray.org[1] = origin[1];
ray.org[2] = origin[2];
ray.dir[0] = dir[0];
ray.dir[1] = dir[1];
ray.dir[2] = dir[2];
return ray;
}
#endif
void FetchTexture(const Texture &texture, float u, float v, float* col) {
int tx = u * texture.width;
@@ -235,10 +239,15 @@ bool Renderer::Render(float* rgba, float* aux_rgba, int* sample_counts,
const nanosg::Scene<float, example::Mesh<float>> &scene,
const example::Asset &asset,
const RenderConfig& config,
std::atomic<bool>& cancelFlag) {
std::atomic<bool>& cancelFlag,
int &_showBufferMode
) {
//if (!gAccel.IsValid()) {
// return false;
//}
int width = config.width;
int height = config.height;
@@ -300,6 +309,19 @@ bool Renderer::Render(float* rgba, float* aux_rgba, int* sample_counts,
float u1 = pcg32_random(&rng);
float3 dir;
//for modes not a "color"
if(_showBufferMode != SHOW_BUFFER_COLOR)
{
//only one pass
if(config.pass > 0)
continue;
//to the center of pixel
u0 = 0.5f;
u1 = 0.5f;
}
dir = corner + (float(x) + u0) * u +
(float(config.height - y - 1) + u1) * v;
dir = vnormalize(dir);
@@ -320,6 +342,9 @@ bool Renderer::Render(float* rgba, float* aux_rgba, int* sample_counts,
const std::vector<Material> &materials = asset.materials;
const std::vector<Texture> &textures = asset.textures;
const Mesh<float> &mesh = asset.meshes[isect.node_id];
//tigra: add default material
const Material &default_material = asset.default_material;
float3 p;
p[0] =
@@ -410,26 +435,49 @@ bool Renderer::Render(float* rgba, float* aux_rgba, int* sample_counts,
// Fetch texture
unsigned int material_id =
mesh.material_ids[isect.prim_id];
//printf("material_id=%d materials=%lld\n", material_id, materials.size());
float diffuse_col[3];
int diffuse_texid = materials[material_id].diffuse_texid;
if (diffuse_texid >= 0) {
FetchTexture(textures[diffuse_texid], UV[0], UV[1], diffuse_col);
} else {
diffuse_col[0] = materials[material_id].diffuse[0];
diffuse_col[1] = materials[material_id].diffuse[1];
diffuse_col[2] = materials[material_id].diffuse[2];
}
float specular_col[3];
int specular_texid = materials[material_id].specular_texid;
if (specular_texid >= 0) {
FetchTexture(textures[specular_texid], UV[0], UV[1], specular_col);
} else {
specular_col[0] = materials[material_id].specular[0];
specular_col[1] = materials[material_id].specular[1];
specular_col[2] = materials[material_id].specular[2];
}
//tigra: material_id is ok
if(material_id<materials.size())
{
//printf("ok mat\n");
int diffuse_texid = materials[material_id].diffuse_texid;
if (diffuse_texid >= 0) {
FetchTexture(textures[diffuse_texid], UV[0], UV[1], diffuse_col);
} else {
diffuse_col[0] = materials[material_id].diffuse[0];
diffuse_col[1] = materials[material_id].diffuse[1];
diffuse_col[2] = materials[material_id].diffuse[2];
}
int specular_texid = materials[material_id].specular_texid;
if (specular_texid >= 0) {
FetchTexture(textures[specular_texid], UV[0], UV[1], specular_col);
} else {
specular_col[0] = materials[material_id].specular[0];
specular_col[1] = materials[material_id].specular[1];
specular_col[2] = materials[material_id].specular[2];
}
}
else
//tigra: wrong material_id, use default_material
{
//printf("default_material\n");
diffuse_col[0] = default_material.diffuse[0];
diffuse_col[1] = default_material.diffuse[1];
diffuse_col[2] = default_material.diffuse[2];
specular_col[0] = default_material.specular[0];
specular_col[1] = default_material.specular[1];
specular_col[2] = default_material.specular[2];
}
// Simple shading
float NdotV = fabsf(vdot(N, dir));
+16 -1
View File
@@ -3,6 +3,15 @@
#include <atomic> // C++11
//mode definitions now here
#define SHOW_BUFFER_COLOR (0)
#define SHOW_BUFFER_NORMAL (1)
#define SHOW_BUFFER_POSITION (2)
#define SHOW_BUFFER_DEPTH (3)
#define SHOW_BUFFER_TEXCOORD (4)
#define SHOW_BUFFER_VARYCOORD (5)
#include "render-config.h"
#include "nanosg.h"
#include "mesh.h"
@@ -13,6 +22,9 @@ namespace example {
struct Asset {
std::vector<Mesh<float> > meshes;
std::vector<Material> materials;
//tigra: add default material
Material default_material;
std::vector<Texture> textures;
};
@@ -23,7 +35,10 @@ class Renderer {
/// Returns false when the rendering was canceled.
static bool Render(float* rgba, float* aux_rgba, int *sample_counts, float quat[4],
const nanosg::Scene<float, Mesh<float>> &scene, const Asset &asset, const RenderConfig& config, std::atomic<bool>& cancel_flag);
const nanosg::Scene<float, Mesh<float>> &scene, const Asset &asset, const RenderConfig& config,
std::atomic<bool>& cancel_flag,
int& _showBufferMode
);
};
};
+3
View File
@@ -0,0 +1,3 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
+357
View File
@@ -0,0 +1,357 @@
# GNU Make project makefile autogenerated by Premake
ifndef config
config=release_native
endif
ifndef verbose
SILENT = @
endif
.PHONY: clean prebuild prelink
ifeq ($(config),release_native)
RESCOMP = windres
TARGETDIR = bin/native/Release
TARGET = $(TARGETDIR)/view
OBJDIR = obj/native/Release
DEFINES += -DGLEW_INIT_OPENGL11_FUNCTIONS=1 -DGLEW_STATIC -DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1
INCLUDES += -I../common/ThirdPartyLibs/Glew -I. -I../.. -I../common -I../common/imgui -I../common/glm
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -O2 -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -O2 -g -std=c++11
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS += -lX11 -lpthread -ldl
LDDEPS +=
ALL_LDFLAGS += $(LDFLAGS)
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
ifeq ($(config),release_x64)
RESCOMP = windres
TARGETDIR = bin/x64/Release
TARGET = $(TARGETDIR)/view
OBJDIR = obj/x64/Release
DEFINES += -DGLEW_INIT_OPENGL11_FUNCTIONS=1 -DGLEW_STATIC -DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1
INCLUDES += -I../common/ThirdPartyLibs/Glew -I. -I../.. -I../common -I../common/imgui -I../common/glm
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -O2 -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -O2 -g -std=c++11
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS += -lX11 -lpthread -ldl
LDDEPS +=
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
ifeq ($(config),release_x32)
RESCOMP = windres
TARGETDIR = bin/x32/Release
TARGET = $(TARGETDIR)/view
OBJDIR = obj/x32/Release
DEFINES += -DGLEW_INIT_OPENGL11_FUNCTIONS=1 -DGLEW_STATIC -DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1
INCLUDES += -I../common/ThirdPartyLibs/Glew -I. -I../.. -I../common -I../common/imgui -I../common/glm
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m32 -O2 -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m32 -O2 -g -std=c++11
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS += -lX11 -lpthread -ldl
LDDEPS +=
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib32 -m32
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
ifeq ($(config),debug_native)
RESCOMP = windres
TARGETDIR = bin/native/Debug
TARGET = $(TARGETDIR)/view_debug
OBJDIR = obj/native/Debug
DEFINES += -DGLEW_INIT_OPENGL11_FUNCTIONS=1 -DGLEW_STATIC -DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1 -DDEBUG
INCLUDES += -I../common/ThirdPartyLibs/Glew -I. -I../.. -I../common -I../common/imgui -I../common/glm
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -g -std=c++11
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS += -lX11 -lpthread -ldl
LDDEPS +=
ALL_LDFLAGS += $(LDFLAGS)
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
ifeq ($(config),debug_x64)
RESCOMP = windres
TARGETDIR = bin/x64/Debug
TARGET = $(TARGETDIR)/view_debug
OBJDIR = obj/x64/Debug
DEFINES += -DGLEW_INIT_OPENGL11_FUNCTIONS=1 -DGLEW_STATIC -DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1 -DDEBUG
INCLUDES += -I../common/ThirdPartyLibs/Glew -I. -I../.. -I../common -I../common/imgui -I../common/glm
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -g -std=c++11
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS += -lX11 -lpthread -ldl
LDDEPS +=
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
ifeq ($(config),debug_x32)
RESCOMP = windres
TARGETDIR = bin/x32/Debug
TARGET = $(TARGETDIR)/view_debug
OBJDIR = obj/x32/Debug
DEFINES += -DGLEW_INIT_OPENGL11_FUNCTIONS=1 -DGLEW_STATIC -DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1 -DDEBUG
INCLUDES += -I../common/ThirdPartyLibs/Glew -I. -I../.. -I../common -I../common/imgui -I../common/glm
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m32 -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m32 -g -std=c++11
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS += -lX11 -lpthread -ldl
LDDEPS +=
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib32 -m32
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
OBJECTS := \
$(OBJDIR)/X11OpenGLWindow.o \
$(OBJDIR)/glew.o \
$(OBJDIR)/ImGuizmo.o \
$(OBJDIR)/imgui.o \
$(OBJDIR)/imgui_draw.o \
$(OBJDIR)/imgui_impl_btgui.o \
$(OBJDIR)/trackball.o \
$(OBJDIR)/gltf-loader.o \
$(OBJDIR)/main.o \
$(OBJDIR)/matrix.o \
$(OBJDIR)/obj-loader.o \
$(OBJDIR)/render-config.o \
$(OBJDIR)/render.o \
$(OBJDIR)/stbi-impl.o \
RESOURCES := \
CUSTOMFILES := \
SHELLTYPE := msdos
ifeq (,$(ComSpec)$(COMSPEC))
SHELLTYPE := posix
endif
ifeq (/bin,$(findstring /bin,$(SHELL)))
SHELLTYPE := posix
endif
$(TARGET): $(GCH) ${CUSTOMFILES} $(OBJECTS) $(LDDEPS) $(RESOURCES)
@echo Linking viwewer
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(TARGETDIR)
else
$(SILENT) mkdir $(subst /,\\,$(TARGETDIR))
endif
$(SILENT) $(LINKCMD)
$(POSTBUILDCMDS)
clean:
@echo Cleaning viwewer
ifeq (posix,$(SHELLTYPE))
$(SILENT) rm -f $(TARGET)
$(SILENT) rm -rf $(OBJDIR)
else
$(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET))
$(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR))
endif
prebuild:
$(PREBUILDCMDS)
prelink:
$(PRELINKCMDS)
ifneq (,$(PCH))
$(OBJECTS): $(GCH) $(PCH)
$(GCH): $(PCH)
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) -x c++-header $(ALL_CXXFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<"
endif
$(OBJDIR)/X11OpenGLWindow.o: ../common/OpenGLWindow/X11OpenGLWindow.cpp
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/glew.o: ../common/ThirdPartyLibs/Glew/glew.c
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/ImGuizmo.o: ../common/imgui/ImGuizmo.cpp
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/imgui.o: ../common/imgui/imgui.cpp
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/imgui_draw.o: ../common/imgui/imgui_draw.cpp
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/imgui_impl_btgui.o: ../common/imgui/imgui_impl_btgui.cpp
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/trackball.o: ../common/trackball.cc
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/gltf-loader.o: gltf-loader.cc
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/main.o: main.cc
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/matrix.o: matrix.cc
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/obj-loader.o: obj-loader.cc
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/render-config.o: render-config.cc
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/render.o: render.cc
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/stbi-impl.o: stbi-impl.cc
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-include $(OBJECTS:%.o=%.d)
ifneq (,$(PCH))
-include $(OBJDIR)/$(notdir $(PCH)).d
endif
+2
View File
@@ -0,0 +1,2 @@
all:
clang++ -std=c++11 -I../../ -g -O1 -o saver main.cc
+1
View File
@@ -0,0 +1 @@
# Simple serialization API sample.
+53
View File
@@ -0,0 +1,53 @@
#include <fstream>
#include <iostream>
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
//#define TINYGLTF_NO_STB_IMAGE_WRITE
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
#define STB_IMAGE_WRITE_IMPLEMENTATION
#endif
// If using a modern Microsoft Compiler, this define supress compilation
// warnings in stb_image_write
//#define STBI_MSC_SECURE_CRT
#include "tiny_gltf.h"
int main(int argc, char *argv[]) {
if (argc != 3) {
std::cout << "Needs input.gltf output.gltf" << std::endl;
return EXIT_FAILURE;
}
tinygltf::Model model;
tinygltf::TinyGLTF loader;
std::string err;
std::string warn;
std::string input_filename(argv[1]);
std::string output_filename(argv[2]);
std::string embedded_filename =
output_filename.substr(0, output_filename.size() - 5) + "-Embedded.gltf";
// assume ascii glTF.
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
if (!warn.empty()) {
std::cout << "warn : " << warn << std::endl;
}
if (!ret) {
if (!err.empty()) {
std::cerr << err << std::endl;
}
return EXIT_FAILURE;
}
loader.WriteGltfSceneToFile(&model, output_filename);
// Embedd buffers and images
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
loader.WriteGltfSceneToFile(&model, embedded_filename, true, true);
#endif
return EXIT_SUCCESS;
}
+6
View File
@@ -45,3 +45,9 @@ endif()
# test-zone
# enable_testing()
install ( TARGETS
tinygltf-validator
DESTINATION
bin
)
+16
View File
@@ -9,6 +9,22 @@ Experimental. W.I.P.
## Requirements
* C++11 compiler
* CMake
## How to build
```
$ mkdir build
$ cd build
$ cmake ..
$ make
```
## How to use
```
$ gltf-validator /path/to/file.gltf /path/to/gltf-schema
```
## Third party licenses
+15
View File
@@ -0,0 +1,15 @@
# Python script which generates C++11 code from JSON schema.
## Requirements
* python3
* jsonref
## Generate
Run `gen.py` by specifing the path to glTF schema directory(from https://github.com/KhronosGroup/glTF.git)
```
$ python gen.py /path/to/glTF/specification/2.0/schema
```
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os
import subprocess
import json
from pprint import pprint
import jsonref
# glTF 2.0
schema_files = [
"glTF.schema.json"
]
def main():
if len(sys.argv) < 2:
print("Requires path to glTF scheme directory.")
sys.exit(-1)
gltf_schema_dir = sys.argv[1]
gltf_schema_filepath = os.path.join(gltf_schema_dir, schema_files[0])
if not os.path.exists(gltf_schema_filepath):
print("File not found: {}".format(gltf_schema_filepath))
sys.exit(-1)
gltf_schema_uri = 'file://{}/'.format(gltf_schema_dir)
with open(gltf_schema_filepath) as schema_file:
j = jsonref.loads(schema_file.read(), base_uri=gltf_schema_uri, jsonschema=True)
pprint(j)
main()
+9082 -3398
View File
File diff suppressed because it is too large Load Diff
+193 -17
View File
@@ -1,5 +1,9 @@
//
// TODO(syoyo): Print extensions and extras for each glTF object.
//
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "tiny_gltf.h"
#include <cstdio>
@@ -135,7 +139,7 @@ static std::string PrintParameterType(int ty) {
#endif
static std::string PrintWrapMode(int mode) {
if (mode == TINYGLTF_TEXTURE_WRAP_RPEAT) {
if (mode == TINYGLTF_TEXTURE_WRAP_REPEAT) {
return "REPEAT";
} else if (mode == TINYGLTF_TEXTURE_WRAP_CLAMP_TO_EDGE) {
return "CLAMP_TO_EDGE";
@@ -171,7 +175,10 @@ static std::string PrintIntArray(const std::vector<int> &arr) {
std::stringstream ss;
ss << "[ ";
for (size_t i = 0; i < arr.size(); i++) {
ss << arr[i] << ((i != arr.size() - 1) ? ", " : "");
ss << arr[i];
if (i != arr.size() - 1) {
ss << ", ";
}
}
ss << " ]";
@@ -186,7 +193,10 @@ static std::string PrintFloatArray(const std::vector<double> &arr) {
std::stringstream ss;
ss << "[ ";
for (size_t i = 0; i < arr.size(); i++) {
ss << arr[i] << ((i != arr.size() - 1) ? ", " : "");
ss << arr[i];
if (i != arr.size() - 1) {
ss << ", ";
}
}
ss << " ]";
@@ -210,8 +220,22 @@ static std::string PrintParameterValue(const tinygltf::Parameter &param) {
}
}
#if 0
static std::string PrintParameterMap(const tinygltf::ParameterMap &pmap) {
std::stringstream ss;
ss << pmap.size() << std::endl;
for (auto &kv : pmap) {
ss << kv.first << " : " << PrintParameterValue(kv.second) << std::endl;
}
return ss.str();
}
#endif
static std::string PrintValue(const std::string &name,
const tinygltf::Value &value, const int indent) {
const tinygltf::Value &value, const int indent,
const bool tag = true) {
std::stringstream ss;
if (value.IsObject()) {
@@ -219,19 +243,45 @@ static std::string PrintValue(const std::string &name,
tinygltf::Value::Object::const_iterator it(o.begin());
tinygltf::Value::Object::const_iterator itEnd(o.end());
for (; it != itEnd; it++) {
ss << PrintValue(name, it->second, indent + 1);
ss << PrintValue(it->first, it->second, indent + 1) << std::endl;
}
} else if (value.IsString()) {
ss << Indent(indent) << name << " : " << value.Get<std::string>()
<< std::endl;
if (tag) {
ss << Indent(indent) << name << " : " << value.Get<std::string>();
} else {
ss << Indent(indent) << value.Get<std::string>() << " ";
}
} else if (value.IsBool()) {
ss << Indent(indent) << name << " : " << value.Get<bool>() << std::endl;
if (tag) {
ss << Indent(indent) << name << " : " << value.Get<bool>();
} else {
ss << Indent(indent) << value.Get<bool>() << " ";
}
} else if (value.IsNumber()) {
ss << Indent(indent) << name << " : " << value.Get<double>() << std::endl;
if (tag) {
ss << Indent(indent) << name << " : " << value.Get<double>();
} else {
ss << Indent(indent) << value.Get<double>() << " ";
}
} else if (value.IsInt()) {
ss << Indent(indent) << name << " : " << value.Get<int>() << std::endl;
if (tag) {
ss << Indent(indent) << name << " : " << value.Get<int>();
} else {
ss << Indent(indent) << value.Get<int>() << " ";
}
} else if (value.IsArray()) {
// TODO(syoyo): Better pretty printing of array item
ss << Indent(indent) << name << " [ \n";
for (size_t i = 0; i < value.Size(); i++) {
ss << PrintValue("", value.Get(int(i)), indent + 1, /* tag */ false);
if (i != (value.ArrayLen() - 1)) {
ss << ", \n";
}
}
ss << "\n" << Indent(indent) << "] ";
}
// @todo { binary, array }
// @todo { binary }
return ss.str();
}
@@ -287,6 +337,63 @@ static void DumpPrimitive(const tinygltf::Primitive &primitive, int indent) {
<< PrintValue("extras", primitive.extras, indent + 1) << std::endl;
}
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 DumpTextureInfo(const tinygltf::TextureInfo &texinfo,
const int indent) {
std::cout << Indent(indent) << "index : " << texinfo.index << "\n";
std::cout << Indent(indent) << "texCoord : TEXCOORD_" << texinfo.texCoord
<< "\n";
DumpExtensions(texinfo.extensions, indent + 1);
std::cout << PrintValue("extras", texinfo.extras, indent + 1) << "\n";
}
static void DumpNormalTextureInfo(const tinygltf::NormalTextureInfo &texinfo,
const int indent) {
std::cout << Indent(indent) << "index : " << texinfo.index << "\n";
std::cout << Indent(indent) << "texCoord : TEXCOORD_" << texinfo.texCoord
<< "\n";
std::cout << Indent(indent) << "scale : " << texinfo.scale << "\n";
DumpExtensions(texinfo.extensions, indent + 1);
std::cout << PrintValue("extras", texinfo.extras, indent + 1) << "\n";
}
static void DumpOcclusionTextureInfo(
const tinygltf::OcclusionTextureInfo &texinfo, const int indent) {
std::cout << Indent(indent) << "index : " << texinfo.index << "\n";
std::cout << Indent(indent) << "texCoord : TEXCOORD_" << texinfo.texCoord
<< "\n";
std::cout << Indent(indent) << "strength : " << texinfo.strength << "\n";
DumpExtensions(texinfo.extensions, indent + 1);
std::cout << PrintValue("extras", texinfo.extras, indent + 1) << "\n";
}
static void DumpPbrMetallicRoughness(const tinygltf::PbrMetallicRoughness &pbr,
const int indent) {
std::cout << Indent(indent)
<< "baseColorFactor : " << PrintFloatArray(pbr.baseColorFactor)
<< "\n";
std::cout << Indent(indent) << "baseColorTexture :\n";
DumpTextureInfo(pbr.baseColorTexture, indent + 1);
std::cout << Indent(indent) << "metallicFactor : " << pbr.metallicFactor
<< "\n";
std::cout << Indent(indent) << "roughnessFactor : " << pbr.roughnessFactor
<< "\n";
std::cout << Indent(indent) << "metallicRoughnessTexture :\n";
DumpTextureInfo(pbr.metallicRoughnessTexture, indent + 1);
DumpExtensions(pbr.extensions, indent + 1);
std::cout << PrintValue("extras", pbr.extras, indent + 1) << "\n";
}
static void Dump(const tinygltf::Model &model) {
std::cout << "=== Dump glTF ===" << std::endl;
std::cout << "asset.copyright : " << model.asset.copyright
@@ -307,6 +414,7 @@ static void Dump(const tinygltf::Model &model) {
for (size_t i = 0; i < model.scenes.size(); i++) {
std::cout << Indent(1) << "scene[" << i
<< "] name : " << model.scenes[i].name << std::endl;
DumpExtensions(model.scenes[i].extensions, 1);
}
}
@@ -344,7 +452,7 @@ static void Dump(const tinygltf::Model &model) {
std::cout << Indent(2) << "min : [";
for (size_t k = 0; k < accessor.minValues.size(); k++) {
std::cout << accessor.minValues[k]
<< ((i != accessor.minValues.size() - 1) ? ", " : "");
<< ((k != accessor.minValues.size() - 1) ? ", " : "");
}
std::cout << "]" << std::endl;
}
@@ -352,10 +460,34 @@ static void Dump(const tinygltf::Model &model) {
std::cout << Indent(2) << "max : [";
for (size_t k = 0; k < accessor.maxValues.size(); k++) {
std::cout << accessor.maxValues[k]
<< ((i != accessor.maxValues.size() - 1) ? ", " : "");
<< ((k != accessor.maxValues.size() - 1) ? ", " : "");
}
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;
}
}
}
@@ -432,16 +564,44 @@ static void Dump(const tinygltf::Model &model) {
<< std::endl;
for (size_t i = 0; i < model.materials.size(); i++) {
const tinygltf::Material &material = model.materials[i];
std::cout << Indent(1) << "name : " << material.name << std::endl;
std::cout << Indent(1) << "values(items=" << material.values.size() << ")"
std::cout << Indent(1) << "name : " << material.name
<< std::endl;
std::cout << Indent(1) << "alphaMode : " << material.alphaMode
<< std::endl;
std::cout << Indent(1)
<< "alphaCutoff : " << material.alphaCutoff
<< std::endl;
std::cout << Indent(1) << "doubleSided : "
<< (material.doubleSided ? "true" : "false") << std::endl;
std::cout << Indent(1) << "emissiveFactor : "
<< PrintFloatArray(material.emissiveFactor) << std::endl;
std::cout << Indent(1) << "pbrMetallicRoughness :\n";
DumpPbrMetallicRoughness(material.pbrMetallicRoughness, 2);
std::cout << Indent(1) << "normalTexture :\n";
DumpNormalTextureInfo(material.normalTexture, 2);
std::cout << Indent(1) << "occlusionTexture :\n";
DumpOcclusionTextureInfo(material.occlusionTexture, 2);
std::cout << Indent(1) << "emissiveTexture :\n";
DumpTextureInfo(material.emissiveTexture, 2);
std::cout << Indent(1) << "---- legacy material parameter ----\n";
std::cout << Indent(1) << "values(items=" << material.values.size() << ")"
<< std::endl;
tinygltf::ParameterMap::const_iterator p(material.values.begin());
tinygltf::ParameterMap::const_iterator pEnd(material.values.end());
for (; p != pEnd; p++) {
std::cout << Indent(2) << p->first << ": "
<< PrintParameterValue(p->second) << std::endl;
}
std::cout << Indent(1) << "-------------------------------------\n";
DumpExtensions(material.extensions, 1);
std::cout << PrintValue("extras", material.extras, 2) << std::endl;
}
}
@@ -464,6 +624,7 @@ static void Dump(const tinygltf::Model &model) {
std::cout << Indent(2) << "width : " << image.width << std::endl;
std::cout << Indent(2) << "height : " << image.height << std::endl;
std::cout << Indent(2) << "component : " << image.component << std::endl;
DumpExtensions(image.extensions, 1);
}
}
@@ -475,6 +636,7 @@ static void Dump(const tinygltf::Model &model) {
<< std::endl;
std::cout << Indent(1) << "source : " << texture.source
<< std::endl;
DumpExtensions(texture.extensions, 1);
}
}
@@ -530,6 +692,13 @@ static void Dump(const tinygltf::Model &model) {
}
}
}
// toplevel extensions
{
std::cout << "extensions(items=" << model.extensions.size() << ")"
<< std::endl;
DumpExtensions(model.extensions, 1);
}
}
int main(int argc, char **argv) {
@@ -541,6 +710,7 @@ int main(int argc, char **argv) {
tinygltf::Model model;
tinygltf::TinyGLTF gltf_ctx;
std::string err;
std::string warn;
std::string input_filename(argv[1]);
std::string ext = GetFilePathExtension(input_filename);
@@ -548,11 +718,17 @@ int main(int argc, char **argv) {
if (ext.compare("glb") == 0) {
std::cout << "Reading binary glTF" << std::endl;
// assume binary glTF.
ret = gltf_ctx.LoadBinaryFromFile(&model, &err, input_filename.c_str());
ret = gltf_ctx.LoadBinaryFromFile(&model, &err, &warn,
input_filename.c_str());
} else {
std::cout << "Reading ASCII glTF" << std::endl;
// assume ascii glTF.
ret = gltf_ctx.LoadASCIIFromFile(&model, &err, input_filename.c_str());
ret =
gltf_ctx.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
}
if (!warn.empty()) {
printf("Warn: %s\n", warn.c_str());
}
if (!err.empty()) {
@@ -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"
}
}
@@ -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"
}
}
@@ -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"
}
}
@@ -0,0 +1,36 @@
{
"scenes": [],
"nodes": [],
"buffers": [],
"meshes": [
{
"primitives": [
{
"attributes": {},
"indices": 1
}
]
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 6,
"target": 34963
}
],
"accessors": [
{
"bufferView": 1,
"componentType": 5123,
"count": 3,
"type": "SCALAR",
"max": [2],
"min": [0]
}
],
"asset": {
"version": "2.0"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 44 B

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

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

+6
View File
@@ -0,0 +1,6 @@
Added KHR_texture_transform property to Cube scene.
License: Donated by Norbert Nopper for glTF testing.
https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Cube
+66
View File
@@ -0,0 +1,66 @@
{
"scenes" : [
{
"nodes" : [ 0 ]
}
],
"nodes" : [
{
"mesh" : 0
}
],
"meshes" : [
{
"primitives" : [ {
"attributes" : {
"POSITION" : 0
}
} ]
}
],
"buffers" : [
{
"uri" : "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA",
"byteLength" : 36
}
],
"bufferViews" : [
{
"buffer" : 0,
"byteOffset" : 0,
"byteLength" : 36,
"target" : 34962
}
],
"accessors" : [
{
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 3,
"type" : "VEC3",
"max" : [ 1.0, 1.0, 0.0 ],
"min" : [ 0.0, 0.0, 0.0 ]
}
],
"asset" : {
"version" : "2.0"
},
"materials" : [
{ "name" : "WHITE",
"extensions": {
"VENDOR_material_some_ext" : { }
}
}
],
"extensionsUsed" : [
"VENDOR_material_some_ext"
]
}
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -17,7 +17,7 @@ solution "TinyGLTFSolution"
kind "ConsoleApp"
language "C++"
files { sources }
flags { "c++11" }
flags { "C++11" }
configuration "Debug"
defines { "DEBUG" } -- -DDEBUG
+1887 -866
View File
File diff suppressed because it is too large Load Diff
+1621
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -14,6 +14,7 @@ import subprocess
sample_model_dir = "/home/syoyo/work/glTF-Sample-Models"
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"]
# ---------------------------------
@@ -28,7 +29,7 @@ def run(filename):
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = p.communicate()
except:
print "Failed to execute: ", cmd
print("Failed to execute: ", cmd)
raise
if p.returncode != 0:
+6
View File
@@ -0,0 +1,6 @@
# Use this for strict compilation check(will work on clang 3.8+)
#EXTRA_CXXFLAGS := -fsanitize=address -Wall -Werror -Weverything -Wno-c++11-long-long -DTINYGLTF_APPLY_CLANG_WEVERYTHING
all: ../tiny_gltf.h
clang++ -I../ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o tester tester.cc
clang++ -DTINYGLTF_NOEXCEPTION -I../ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o tester_noexcept tester.cc

Some files were not shown because too many files have changed in this diff Show More