├── .gitattributes ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── completion.hxml ├── haxelib.json ├── src └── gltf │ ├── GLTF.hx │ ├── schema │ ├── TAccessor.hx │ ├── TAccessorSparse.hx │ ├── TAccessorSparseIndices.hx │ ├── TAccessorSparseValues.hx │ ├── TAlphaMode.hx │ ├── TAnimation.hx │ ├── TAnimationChannel.hx │ ├── TAnimationChannelTarget.hx │ ├── TAnimationChannelTargetPath.hx │ ├── TAnimationInterpolation.hx │ ├── TAnimationSampler.hx │ ├── TAsset.hx │ ├── TAttributeType.hx │ ├── TBuffer.hx │ ├── TBufferTarget.hx │ ├── TBufferView.hx │ ├── TCamera.hx │ ├── TCameraOrthographic.hx │ ├── TCameraPerspective.hx │ ├── TCameraType.hx │ ├── TComponentType.hx │ ├── TGLTF.hx │ ├── TGLTFChildOfRootProperty.hx │ ├── TGLTFID.hx │ ├── TGLTFProperty.hx │ ├── TGLTFUri.hx │ ├── TImage.hx │ ├── TImageMimeType.hx │ ├── TMagFilter.hx │ ├── TMaterial.hx │ ├── TMaterialNormalTextureInfo.hx │ ├── TMaterialOcclusionTextureInfo.hx │ ├── TMaterialPBRMetallicRoughness.hx │ ├── TMesh.hx │ ├── TMeshPrimitive.hx │ ├── TMeshPrimitiveType.hx │ ├── TMinFilter.hx │ ├── TNode.hx │ ├── TSampler.hx │ ├── TScene.hx │ ├── TSkin.hx │ ├── TTexture.hx │ ├── TTextureInfo.hx │ └── TWrapMode.hx │ └── types │ ├── Accessor.hx │ ├── Animation.hx │ ├── AnimationChannel.hx │ ├── Buffer.hx │ ├── BufferView.hx │ ├── Camera.hx │ ├── CameraType.hx │ ├── Image.hx │ ├── Material.hx │ ├── Mesh.hx │ ├── MeshPrimitive.hx │ ├── Node.hx │ ├── Sampler.hx │ ├── Scene.hx │ ├── Skin.hx │ └── Texture.hx └── test ├── .gitignore ├── TestMain.hx ├── get-samples.sh ├── gltf ├── TestLoading.hx └── TestParsing.hx ├── test.cpp.hxml ├── test.each.hxml ├── test.interp.hxml ├── test.java.hxml └── test.node.hxml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Apply native OS line-endings on checkout of these files... 2 | *.boo text 3 | *.c text 4 | *.cginc text 5 | *.config text 6 | *.contentproj text 7 | *.cpp text 8 | *.cs text 9 | *.css text 10 | *.dae text 11 | *.DAE text 12 | *.dtd text 13 | *.fx text 14 | *.glsl text 15 | *.h text 16 | *.htm text 17 | *.html text 18 | *.inc text 19 | *.ini text 20 | *.js text 21 | *.JSFL text 22 | *.jsfl text 23 | *.json text 24 | *.log text 25 | *.md text 26 | *.mel text 27 | *.php text 28 | *.shader text 29 | *.txt text 30 | *.TXT text 31 | *.xaml text 32 | *.xml text 33 | *.xsd text 34 | .gitattributes text 35 | .gitignore text 36 | COPYING text 37 | INSTALL* text 38 | KEYS* text 39 | LICENSE* text 40 | NEWS* text 41 | NOTICE* text 42 | README* text 43 | TODO* text 44 | WHATSNEW* text 45 | 46 | # Apply Unix-style LF line-endings on checkout of these files... 47 | *.meta text eol=lf 48 | *.sh text eol=lf 49 | *.vspscc text eol=lf 50 | .htaccess text eol=lf 51 | 52 | # Apply Windows/DOS-style CR-LF line-endings on checkout of these files... 53 | *.bat text eol=crlf 54 | *.cmd text eol=crlf 55 | *.csproj text eol=crlf 56 | *.sln text eol=crlf 57 | *.user text eol=crlf 58 | *.vcproj text eol=crlf 59 | 60 | # No end-of-line conversions are applied (i.e., "-text -diff") to these files... 61 | *.7z binary 62 | *.ai binary 63 | *.anim binary 64 | *.apk binary 65 | *.asset binary 66 | *.bin binary 67 | *.bmp binary 68 | *.BMP binary 69 | *.com binary 70 | *.COM binary 71 | *.controller binary 72 | *.cubemap binary 73 | *.dex binary 74 | *.dll binary 75 | *.DLL binary 76 | *.dylib binary 77 | *.eps binary 78 | *.exe binary 79 | *.EXE binary 80 | *.exr binary 81 | *.fbx binary 82 | *.FBX binary 83 | *.fla binary 84 | *.flare binary 85 | *.flv binary 86 | *.gif binary 87 | *.guiskin binary 88 | *.gz binary 89 | *.ht binary 90 | *.ico binary 91 | *.jpeg binary 92 | *.jpg binary 93 | *.keystore binary 94 | *.mask binary 95 | *.mat binary 96 | *.mb binary 97 | *.mp3 binary 98 | *.mp4 binary 99 | *.mpg binary 100 | *.ogg binary 101 | *.PCX binary 102 | *.pcx binary 103 | *.pdb binary 104 | *.pdf binary 105 | *.physicMaterial binary 106 | *.physicmaterial binary 107 | *.png binary 108 | *.prefab binary 109 | *.ps binary 110 | *.psd binary 111 | *.qt binary 112 | *.so binary 113 | *.swf binary 114 | *.tga binary 115 | *.tif binary 116 | *.tiff binary 117 | *.ttf binary 118 | *.TTF binary 119 | *.unity binary 120 | *.unitypackage binary 121 | *.unityPackage binary 122 | *.wav binary 123 | *.wmv binary 124 | *.zip binary 125 | *.ZIP binary -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | 3 | ### Windows ### 4 | # Windows image file caches 5 | Thumbs.db 6 | ehthumbs.db 7 | 8 | # Folder config file 9 | Desktop.ini 10 | 11 | # Recycle Bin used on file shares 12 | $RECYCLE.BIN/ 13 | 14 | # Windows Installer files 15 | *.cab 16 | *.msi 17 | *.msm 18 | *.msp 19 | 20 | # Windows shortcuts 21 | *.lnk 22 | 23 | 24 | ### OSX ### 25 | .DS_Store 26 | .AppleDouble 27 | .LSOverride 28 | 29 | # Icon must end with two \r 30 | Icon 31 | 32 | 33 | # Thumbnails 34 | ._* 35 | 36 | # Files that might appear in the root of a volume 37 | .DocumentRevisions-V100 38 | .fseventsd 39 | .Spotlight-V100 40 | .TemporaryItems 41 | .Trashes 42 | .VolumeIcon.icns 43 | 44 | # Directories potentially created on remote AFP share 45 | .AppleDB 46 | .AppleDesktop 47 | Network Trash Folder 48 | Temporary Items 49 | .apdisk 50 | 51 | 52 | ### Linux ### 53 | *~ 54 | 55 | # KDE directory preferences 56 | .directory 57 | 58 | # Linux trash folder which might appear on any partition or disk 59 | .Trash-* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # adapted from https://github.com/andyli/HaxeCI/blob/master/.travis.yml 2 | language: haxe 3 | 4 | before_script: cd test && sh get-samples.sh 5 | env: 6 | matrix: 7 | - TARGET=interp 8 | - TARGET=cpp 9 | - TARGET=node 10 | - TARGET=java 11 | 12 | # Test with Current Haxe and Haxe development. 13 | haxe: 14 | - stable 15 | - development 16 | 17 | matrix: 18 | # Allow Haxe development to fail. 19 | allow_failures: 20 | - haxe: development 21 | 22 | install: 23 | # install haxelibs 24 | - haxelib install buddy 25 | 26 | # apt packages for each target 27 | - sudo apt-get update 28 | - sh -c "if [ '$TARGET' = 'cpp' ]; then sudo apt-get install gcc-multilib g++-multilib -y; fi" 29 | 30 | # haxelib dependencies for each target 31 | - sh -c "if [ '$TARGET' = 'cpp' ]; then haxelib install hxcpp; fi" 32 | - sh -c "if [ '$TARGET' = 'java' ]; then haxelib install hxjava; fi" 33 | - sh -c "if [ '$TARGET' = 'node' ]; then haxelib install hxnodejs; fi" 34 | 35 | script: 36 | - haxe test.${TARGET}.hxml 37 | 38 | branches: 39 | only: 40 | - master 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017 Kenton Hamaluik 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # haxe-gltf 2 | [![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg?style=flat-square)](https://raw.githubusercontent.com/FuzzyWuzzie/haxe-gltf/master/LICENSE) [![Travis](https://img.shields.io/travis/rust-lang/rust/master.svg?style=flat-square)](https://travis-ci.org/FuzzyWuzzie/haxe-gltf.svg?branch=master) 3 | 4 | A Haxe library for reading (and eventually, writing) [GLTF](https://github.com/KhronosGroup/glTF) files. 5 | -------------------------------------------------------------------------------- /completion.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | 3 | gltf.GLTF 4 | 5 | --interp -------------------------------------------------------------------------------- /haxelib.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gltf", 3 | "classPath": "src", 4 | "url" : "https://github.com/FuzzyWuzzie/haxe-gltf", 5 | "license": "Apache", 6 | "tags": ["cross", "utility"], 7 | "description": "A Haxe library for reading glTF 2.0 files", 8 | "version": "2.1.0", 9 | "releasenote": "Added parsing .glb files, added buffer retrieval callback", 10 | "contributors": ["FuzzyWuzzie"], 11 | "dependencies": {} 12 | } 13 | -------------------------------------------------------------------------------- /src/gltf/GLTF.hx: -------------------------------------------------------------------------------- 1 | package gltf; 2 | 3 | import gltf.schema.TTexture; 4 | import gltf.schema.TSkin; 5 | import gltf.schema.TScene; 6 | import gltf.schema.TWrapMode; 7 | import gltf.schema.TMinFilter; 8 | import gltf.schema.TMagFilter; 9 | import gltf.schema.TSampler; 10 | import gltf.schema.TNode; 11 | import gltf.schema.TMeshPrimitiveType; 12 | import gltf.schema.TMeshPrimitive; 13 | import gltf.schema.TMesh; 14 | import gltf.schema.TMaterial; 15 | import gltf.schema.TImage; 16 | import gltf.schema.TCamera; 17 | import gltf.schema.TBufferView; 18 | import gltf.schema.TBuffer; 19 | import gltf.schema.TAnimationInterpolation; 20 | import gltf.schema.TAnimation; 21 | import gltf.schema.TGLTF; 22 | import gltf.schema.TAccessor; 23 | import haxe.ds.Vector; 24 | import gltf.types.Accessor; 25 | import gltf.types.Animation; 26 | import gltf.types.Buffer; 27 | import gltf.types.BufferView; 28 | import gltf.types.Camera; 29 | import gltf.types.Mesh; 30 | import gltf.types.Material; 31 | import gltf.types.Skin; 32 | import gltf.types.Node; 33 | import gltf.types.Scene; 34 | import gltf.types.Image; 35 | import gltf.types.Texture; 36 | import gltf.types.Sampler; 37 | import haxe.io.Bytes; 38 | 39 | /** 40 | * An object representing a glTF scene 41 | */ 42 | class GLTF { 43 | public var accessors(default, null):Vector = new Vector(0); 44 | public var animations(default, null):Vector = new Vector(0); 45 | public var buffers(default, null):Vector = new Vector(0); 46 | public var bufferViews(default, null):Vector = new Vector(0); 47 | public var cameras(default, null):Vector = new Vector(0); 48 | public var images(default, null):Vector = new Vector(0); 49 | public var material(default, null):Vector = new Vector(0); 50 | public var meshes(default, null):Vector = new Vector(0); 51 | public var samplers(default, null):Vector = new Vector(0); 52 | public var skins(default, null):Vector = new Vector(0); 53 | public var textures(default, null):Vector = new Vector(0); 54 | public var nodes(default, null):Vector = new Vector(0); 55 | public var defaultScene(default, null):Scene = null; 56 | public var scenes(default, null):Vector = new Vector(0); 57 | 58 | function new() {} 59 | 60 | public static function parseAndLoadGLB(data: Bytes): GLTF { 61 | if(data.sub(0, 4).compare(Bytes.ofString('glTF')) != 0) { 62 | throw 'invalid magic: ${data.sub(0, 4).toHex()}'; 63 | } 64 | if(data.sub(4, 4).getInt32(0) != 2) { 65 | throw 'invalid gltf version: ${data.sub(4, 4).getInt32(0)}'; 66 | } 67 | 68 | var jsonChunkLength: Int = data.sub(12, 4).getInt32(0); 69 | if(jsonChunkLength < 1) { 70 | throw 'invalid json chunk length: ${jsonChunkLength}'; 71 | } 72 | var jsonChunkType: String = data.sub(16, 4).toString(); 73 | if(jsonChunkType != 'JSON') { 74 | throw 'invalid json chunk type: ${jsonChunkType}'; 75 | } 76 | 77 | var jsonChunk: String = data.sub(20, jsonChunkLength).toString(); 78 | var raw: TGLTF = parse(jsonChunk); 79 | 80 | var binaryChunkLength: Int = data.sub(20 + jsonChunkLength, 4).getInt32(0); 81 | if(binaryChunkLength < 1) { 82 | throw 'invalid binary chunk length: ${binaryChunkLength}'; 83 | } 84 | if(data.sub(24 + jsonChunkLength, 4).compare(Bytes.ofHex('42494E00')) != 0) { 85 | throw 'invalid binary chunk type: ${data.sub(24 + jsonChunkLength, 4).toHex()}'; 86 | } 87 | 88 | return load(raw, [data.sub(28 + jsonChunkLength, binaryChunkLength)]); 89 | } 90 | 91 | public inline static function parseAndLoad(src:String, buffers:Array):GLTF { 92 | return load(parse(src), buffers); 93 | } 94 | 95 | public inline static function parseAndLoadWithBuffer(src: String, bufferGetter: Int->Bytes): GLTF { 96 | return loadWithBufferGetter(parse(src), bufferGetter); 97 | } 98 | 99 | public static function load(raw:TGLTF, buffers:Array):GLTF { 100 | return loadWithBufferGetter(raw, function(index: Int): Bytes { 101 | return buffers[index]; 102 | }); 103 | } 104 | 105 | public static function loadWithBufferGetter(raw: TGLTF, bufferGetter: Int->Bytes): GLTF { 106 | var gltf:GLTF = new GLTF(); 107 | 108 | gltf.nodes = Node.preloadFromRaw(gltf, raw); 109 | gltf.buffers = Buffer.loadFromRawWithGetter(gltf, raw, bufferGetter); 110 | gltf.bufferViews = BufferView.loadFromRaw(gltf, raw); 111 | gltf.accessors = Accessor.loadFromRaw(gltf, raw); 112 | gltf.animations = Animation.loadFromRaw(gltf, raw); 113 | gltf.cameras = Camera.loadFromRaw(gltf, raw); 114 | gltf.images = Image.loadFromRaw(gltf, raw); 115 | gltf.samplers = Sampler.loadFromRaw(gltf, raw); 116 | gltf.textures = Texture.loadFromRaw(gltf, raw); 117 | gltf.meshes = Mesh.loadFromRaw(gltf, raw); 118 | gltf.material = Material.loadFromRaw(gltf, raw); 119 | gltf.skins = Skin.loadFromRaw(gltf, raw); 120 | gltf.nodes = Node.loadFromRaw(gltf, raw); 121 | gltf.scenes = Scene.loadFromRaw(gltf, raw); 122 | gltf.defaultScene = gltf.scenes[raw.scene]; 123 | 124 | return gltf; 125 | } 126 | 127 | /** 128 | * Parse a glTF json string into typedef'd structs 129 | * @param src The glTF source 130 | * @return TGLTF 131 | */ 132 | public static function parse(src:String):TGLTF { 133 | var gltf:TGLTF = cast(haxe.Json.parse(src)); 134 | 135 | if(gltf.accessors == null) gltf.accessors = new Array(); 136 | for(accessor in gltf.accessors) { 137 | if(accessor.bufferView == null){} // TODO: initialize the accessor with zeros 138 | if(accessor.byteOffset == null) accessor.byteOffset = 0; 139 | if(accessor.normalized == null) accessor.normalized = false; 140 | if(accessor.max == null) accessor.max = new Array(); 141 | if(accessor.min == null) accessor.min = new Array(); 142 | 143 | if(accessor.sparse != null) { 144 | if(accessor.sparse.indices.byteOffset == null) accessor.sparse.indices.byteOffset = 0; 145 | if(accessor.sparse.values.byteOffset == null) accessor.sparse.values.byteOffset = 0; 146 | } 147 | } 148 | 149 | if(gltf.animations == null) gltf.animations = new Array(); 150 | for(animation in gltf.animations) { 151 | for(sampler in animation.samplers) { 152 | if(sampler.interpolation == null) sampler.interpolation = TAnimationInterpolation.LINEAR; 153 | } 154 | } 155 | 156 | if(gltf.buffers == null) gltf.buffers = new Array(); 157 | 158 | if(gltf.bufferViews == null) gltf.bufferViews = new Array(); 159 | for(bufferView in gltf.bufferViews) { 160 | if(bufferView.byteOffset == null) bufferView.byteOffset = 0; 161 | } 162 | 163 | if(gltf.cameras == null) gltf.cameras = new Array(); 164 | 165 | if(gltf.images == null) gltf.images = new Array(); 166 | 167 | if(gltf.materials == null) gltf.materials = new Array(); 168 | for(material in gltf.materials) { 169 | if(material.normalTexture != null) { 170 | if(material.normalTexture.texCoord == null) material.normalTexture.texCoord = 0; 171 | if(material.normalTexture.scale == null) material.normalTexture.scale = 1.0; 172 | } 173 | 174 | if(material.occlusionTexture != null) { 175 | if(material.occlusionTexture.texCoord == null) material.occlusionTexture.texCoord = 0; 176 | if(material.occlusionTexture.strength == null) material.occlusionTexture.strength = 1.0; 177 | } 178 | 179 | if(material.pbrMetallicRoughness != null) { 180 | if(material.pbrMetallicRoughness.baseColorFactor == null) material.pbrMetallicRoughness.baseColorFactor = [1.0, 1.0, 1.0, 1.0]; 181 | if(material.pbrMetallicRoughness.baseColorTexture != null) { 182 | if(material.pbrMetallicRoughness.baseColorTexture.texCoord == null) material.pbrMetallicRoughness.baseColorTexture.texCoord = 0; 183 | } 184 | if(material.pbrMetallicRoughness.metallicFactor == null) material.pbrMetallicRoughness.metallicFactor = 1.0; 185 | if(material.pbrMetallicRoughness.roughnessFactor == null) material.pbrMetallicRoughness.roughnessFactor = 1.0; 186 | if(material.pbrMetallicRoughness.metallicRoughnessTexture != null) { 187 | if(material.pbrMetallicRoughness.metallicRoughnessTexture.texCoord == null) material.pbrMetallicRoughness.metallicRoughnessTexture.texCoord = 0; 188 | } 189 | } 190 | 191 | if(material.emissiveTexture != null) { 192 | if(material.emissiveTexture.texCoord == null) material.emissiveTexture.texCoord = 0; 193 | } 194 | 195 | if(material.emissiveFactor == null) material.emissiveFactor = [0.0, 0.0, 0.0]; 196 | if(material.alphaCutoff == null) material.alphaCutoff = 0.5; 197 | if(material.doubleSided == null) material.doubleSided = false; 198 | } 199 | 200 | if(gltf.meshes == null) gltf.meshes = new Array(); 201 | for(mesh in gltf.meshes) { 202 | if(mesh.primitives == null) mesh.primitives = new Array(); 203 | for(primitive in mesh.primitives) { 204 | if(primitive.mode == null) primitive.mode = TMeshPrimitiveType.TRIANGLES; 205 | } 206 | } 207 | 208 | if(gltf.nodes == null) gltf.nodes = new Array(); 209 | for(node in gltf.nodes) { 210 | // if they all need filling in... 211 | if(node.matrix == null && node.rotation == null && node.scale == null && node.translation == null) { 212 | // use the identity matrix 213 | node.matrix = [ 214 | 1, 0, 0, 0, 215 | 0, 1, 0, 0, 216 | 0, 0, 1, 0, 217 | 0, 0, 0, 1 218 | ]; 219 | } 220 | // if the components need filling in... 221 | if(node.matrix != null) { 222 | var a:Array = node.matrix; 223 | 224 | node.translation = new Array(); 225 | node.translation.push(a[12]); 226 | node.translation.push(a[13]); 227 | node.translation.push(a[14]); 228 | 229 | var sx:Float = Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2] + a[3]*a[3]); 230 | var sy:Float = Math.sqrt(a[4]*a[4] + a[5]*a[5] + a[6]*a[6] + a[7]*a[7]); 231 | var sz:Float = Math.sqrt(a[8]*a[8] + a[9]*a[9] + a[10]*a[10] + a[11]*a[11]); 232 | node.scale = new Array(); 233 | node.scale.push(sx); node.scale.push(sy); node.scale.push(sz); 234 | 235 | var m00 = a[0] / sx; var m11 = a[5] / sy; var m22 = a[10] / sz; 236 | node.rotation = new Array(); 237 | node.rotation.push(Math.sqrt(Math.max(0.0, 1.0 + m00 - m11 - m22)) / 2.0); 238 | node.rotation.push(Math.sqrt(Math.max(0.0, 1.0 - m00 + m11 - m22)) / 2.0); 239 | node.rotation.push(Math.sqrt(Math.max(0.0, 1.0 - m00 - m11 + m22)) / 2.0); 240 | node.rotation.push(Math.sqrt(Math.max(0.0, 1.0 + m00 + m11 + m22)) / 2.0); 241 | } 242 | // if the matrix needs filling in.. 243 | else if(node.matrix == null && (node.rotation != null || node.scale != null || node.translation != null)) { 244 | if(node.rotation == null) node.rotation = [ 0.0, 0.0, 0.0, 1.0 ]; 245 | if(node.scale == null) node.scale = [ 1.0, 1.0, 1.0 ]; 246 | if(node.translation == null) node.translation = [ 0.0, 0.0, 0.0 ]; 247 | 248 | var x2:Float = node.rotation[0] + node.rotation[0]; 249 | var y2:Float = node.rotation[1] + node.rotation[1]; 250 | var z2:Float = node.rotation[2] + node.rotation[2]; 251 | 252 | var xx:Float = node.rotation[0] * x2; 253 | var xy:Float = node.rotation[0] * y2; 254 | var xz:Float = node.rotation[0] * z2; 255 | var yy:Float = node.rotation[1] * y2; 256 | var yz:Float = node.rotation[1] * z2; 257 | var zz:Float = node.rotation[2] * z2; 258 | var wx:Float = node.rotation[3] * x2; 259 | var wy:Float = node.rotation[3] * y2; 260 | var wz:Float = node.rotation[3] * z2; 261 | 262 | node.matrix = [ 263 | (1 - (yy + zz)) * node.scale[0], 264 | (xy + wz) * node.scale[0], 265 | (xz - wy) * node.scale[0], 266 | 0, 267 | 268 | (xy - wz) * node.scale[1], 269 | (1 - (xx + zz)) * node.scale[1], 270 | (yz + wx) * node.scale[1], 271 | 0, 272 | 273 | (xz + wy) * node.scale[2], 274 | (yz - wx) * node.scale[2], 275 | (1 - (xx + yy)) * node.scale[2], 276 | 0, 277 | 278 | node.translation[0], 279 | node.translation[1], 280 | node.translation[2], 281 | 1 282 | ]; 283 | } 284 | else { 285 | throw 'Unhandled transform case: ${node.matrix == null} ${node.translation == null} ${node.rotation == null} ${node.scale == null}'; 286 | } 287 | } 288 | 289 | if(gltf.samplers == null) gltf.samplers = new Array(); 290 | for(sampler in gltf.samplers) { 291 | if(sampler.magFilter == null) sampler.magFilter = TMagFilter.LINEAR; 292 | if(sampler.minFilter == null) sampler.minFilter = TMinFilter.LINEAR; 293 | if(sampler.wrapS == null) sampler.wrapS = TWrapMode.REPEAT; 294 | if(sampler.wrapT == null) sampler.wrapT = TWrapMode.REPEAT; 295 | } 296 | 297 | if(gltf.scene == null) gltf.scene = 0; 298 | 299 | if(gltf.scenes == null) gltf.scenes = new Array(); 300 | 301 | if(gltf.skins == null) gltf.skins = new Array(); 302 | 303 | if(gltf.textures == null) gltf.textures = new Array(); 304 | for(texture in gltf.textures) { 305 | if(texture.sampler == null) texture.sampler = -1; // TODO: better index to default sampler? 306 | } 307 | 308 | return gltf; 309 | } 310 | } 311 | -------------------------------------------------------------------------------- /src/gltf/schema/TAccessor.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A typed view into a bufferView. A bufferView contains raw binary data. An accessor provides a typed view into a bufferView or a subset of a bufferView similar to how WebGL's `vertexAttribPointer()` defines an attribute in a buffer. 5 | */ 6 | typedef TAccessor = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * The index of the bufferView. When not defined, accessor must be initialized with zeros; `sparse` property or extensions could override zeros with actual values. 12 | */ 13 | @:optional var bufferView:TGLTFID; 14 | 15 | /** 16 | * The offset relative to the start of the bufferView in bytes. This must be a multiple of the size of the component datatype. 17 | */ 18 | @:optional var byteOffset:Int; 19 | 20 | /** 21 | * The datatype of components in the attribute. All valid values correspond to WebGL enums. The corresponding typed arrays are `Int8Array`, `Uint8Array`, `Int16Array`, `Uint16Array`, `Uint32Array`, and `Float32Array`, respectively. 5125 (UNSIGNED_INT) is only allowed when the accessor contains indices, i.e., the accessor is only referenced by `primitive.indices`. 22 | */ 23 | var componentType:TComponentType; 24 | 25 | /** 26 | * Specifies whether integer data values should be normalized (`true`) to [0, 1] (for unsigned types) or [-1, 1] (for signed types), or converted directly (`false`) when they are accessed. This property is defined only for accessors that contain vertex attributes or animation output data. 27 | */ 28 | @:optional var normalized:Bool; 29 | 30 | /** 31 | * The number of attributes referenced by this accessor, not to be confused with the number of bytes or number of components. 32 | */ 33 | var count:Int; 34 | 35 | /** 36 | * Specifies if the attribute is a scalar, vector, or matrix. 37 | */ 38 | var type:TAttributeType; 39 | 40 | /** 41 | * Maximum value of each component in this attribute. Array elements must be treated as having the same data type as accessor's `componentType`. Both min and max arrays have the same length. The length is determined by the value of the type property; it can be 1, 2, 3, 4, 9, or 16.\n\n`normalized` property has no effect on array values: they always correspond to the actual values stored in the buffer. When accessor is sparse, this property must contain max values of accessor data with sparse substitution applied. 42 | */ 43 | @:optional var max:Array; 44 | 45 | /** 46 | * Minimum value of each component in this attribute. Array elements must be treated as having the same data type as accessor's `componentType`. Both min and max arrays have the same length. The length is determined by the value of the type property; it can be 1, 2, 3, 4, 9, or 16.\n\n`normalized` property has no effect on array values: they always correspond to the actual values stored in the buffer. When accessor is sparse, this property must contain min values of accessor data with sparse substitution applied. 47 | */ 48 | @:optional var min:Array; 49 | 50 | /** 51 | * Sparse storage of attributes that deviate from their initialization value. 52 | */ 53 | @:optional var sparse:TAccessorSparse; 54 | } 55 | -------------------------------------------------------------------------------- /src/gltf/schema/TAccessorSparse.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Sparse storage of attributes that deviate from their initialization value. 5 | */ 6 | typedef TAccessorSparse = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The number of attributes encoded in this sparse accessor. 11 | */ 12 | var count:Int; 13 | 14 | /** 15 | * Index array of size `count` that points to those accessor attributes that deviate from their initialization value. Indices must strictly increase. 16 | */ 17 | var indices:TAccessorSparseIndices; 18 | 19 | /** 20 | * Array of size `count` times number of components, storing the displaced accessor attributes pointed by `indices`. Substituted values must have the same `componentType` and number of components as the base accessor. 21 | */ 22 | var values:TAccessorSparseValues; 23 | } 24 | -------------------------------------------------------------------------------- /src/gltf/schema/TAccessorSparseIndices.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Indices of those attributes that deviate from their initialization value. 5 | */ 6 | typedef TAccessorSparseIndices = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The index of the bufferView with sparse indices. Referenced bufferView can't have ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER target. 11 | */ 12 | var bufferView:TGLTFID; 13 | 14 | /** 15 | * The offset relative to the start of the bufferView in bytes. Must be aligned. 16 | */ 17 | @:optional var byteOffset:Int; 18 | 19 | /** 20 | * The indices data type. Valid values correspond to WebGL enums: `5121` (UNSIGNED_BYTE), `5123` (UNSIGNED_SHORT), `5125` (UNSIGNED_INT). 21 | */ 22 | var componentType:TComponentType; 23 | } 24 | -------------------------------------------------------------------------------- /src/gltf/schema/TAccessorSparseValues.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Array of size `accessor.sparse.count` times number of components storing the displaced accessor attributes pointed by `accessor.sparse.indices`. 5 | */ 6 | typedef TAccessorSparseValues = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The index of the bufferView with sparse values. Referenced bufferView can't have ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER target. 11 | */ 12 | var bufferView:TGLTFID; 13 | 14 | /** 15 | * The offset relative to the start of the bufferView in bytes. Must be aligned. 16 | */ 17 | @:optional var byteOffset:Int; 18 | } 19 | -------------------------------------------------------------------------------- /src/gltf/schema/TAlphaMode.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The material's alpha rendering mode enumeration specifying the interpretation of the alpha value of the main factor and texture. 5 | */ 6 | @:enum abstract TAlphaMode(String) from String to String { 7 | /** 8 | * The alpha value is ignored and the rendered output is fully opaque. 9 | */ 10 | var OPAQUE = "OPAQUE"; 11 | 12 | /** 13 | * The rendered output is either fully opaque or fully transparent depending on the alpha value and the specified alpha cutoff value. 14 | */ 15 | var MASK = "MASK"; 16 | 17 | /** 18 | * The alpha value is used to composite the source and destination areas. The rendered output is combined with the background using the normal painting operation (i.e. the Porter and Duff over operator). 19 | */ 20 | var BLEND = "BLEND"; 21 | } 22 | -------------------------------------------------------------------------------- /src/gltf/schema/TAnimation.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A keyframe animation. 5 | */ 6 | typedef TAnimation = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * An array of channels, each of which targets an animation's sampler at a node's property. Different channels of the same animation can't have equal targets. 12 | */ 13 | var channels:Array; 14 | 15 | /** 16 | * An array of samplers that combines input and output accessors with an interpolation algorithm to define a keyframe graph (but not its target). 17 | */ 18 | var samplers:Array; 19 | } 20 | -------------------------------------------------------------------------------- /src/gltf/schema/TAnimationChannel.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Targets an animation's sampler at a node's property. 5 | */ 6 | typedef TAnimationChannel = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The index of a sampler in this animation used to compute the value for the target, e.g., a node's translation, rotation, or scale (TRS). 11 | */ 12 | var sampler:TGLTFID; 13 | 14 | /** 15 | * The index of the node and TRS property to target. 16 | */ 17 | var target:TAnimationChannelTarget; 18 | } 19 | -------------------------------------------------------------------------------- /src/gltf/schema/TAnimationChannelTarget.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The index of the node and TRS property that an animation channel targets. 5 | */ 6 | typedef TAnimationChannelTarget = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The index of the node to target. 11 | */ 12 | @:optional var node:TGLTFID; 13 | 14 | /** 15 | * The name of the node's TRS property to modify, or the "weights" of the Morph Targets it instantiates. 16 | */ 17 | var path:TAnimationChannelTargetPath; 18 | } 19 | -------------------------------------------------------------------------------- /src/gltf/schema/TAnimationChannelTargetPath.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The name of the node's TRS property to modify, or the \"weights\" of the Morph Targets it instantiates. 5 | */ 6 | @:enum abstract TAnimationChannelTargetPath(String) from String to String { 7 | var TRANSLATION = "translation"; 8 | var ROTATION = "rotation"; 9 | var SCALE = "scale"; 10 | var WEIGHTS = "weights"; 11 | } 12 | -------------------------------------------------------------------------------- /src/gltf/schema/TAnimationInterpolation.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Interpolation algorithm. 5 | */ 6 | @:enum abstract TAnimationInterpolation(String) from String to String { 7 | /** 8 | * The animated values are linearly interpolated between keyframes. When targeting a rotation, spherical linear interpolation (slerp) should be used to interpolate quaternions. The number output of elements must equal the number of input elements. 9 | */ 10 | var LINEAR = "LINEAR"; 11 | 12 | /** 13 | * The animated values remain constant to the output of the first keyframe, until the next keyframe. The number of output elements must equal the number of input elements. 14 | */ 15 | var STEP = "STEP"; 16 | 17 | /** 18 | * The animation's interpolation is computed using a uniform Catmull-Rom spline. The number of output elements must equal two more than the number of input elements. The first and last output elements represent the start and end tangents of the spline. There must be at least four keyframes when using this interpolation. 19 | */ 20 | var CATMULLROMSPLINE = "CATMULLROMSPLINE"; 21 | 22 | /** 23 | * The animation's interpolation is computed using a cubic spline with specified tangents. The number of output elements must equal three times the number of input elements. For each input element, the output stores three elements, an in-tangent, a spline vertex, and an out-tangent. There must be at least two keyframes when using this interpolation. 24 | */ 25 | var CUBICSPLINE = "CUBICSPLINE"; 26 | } 27 | -------------------------------------------------------------------------------- /src/gltf/schema/TAnimationSampler.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Combines input and output accessors with an interpolation algorithm to define a keyframe graph (but not its target). 5 | */ 6 | typedef TAnimationSampler = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The index of an accessor containing keyframe input values, e.g., time. That accessor must have componentType `FLOAT`. The values represent time in seconds with `time[0] >= 0.0`, and strictly increasing values, i.e., `time[n + 1] > time[n]`. 11 | */ 12 | var input:TGLTFID; 13 | 14 | /** 15 | * Interpolation algorithm. 16 | */ 17 | @:optional var interpolation:TAnimationInterpolation; 18 | 19 | /** 20 | * The index of an accessor containing keyframe output values. When targeting TRS target, the `accessor.componentType` of the output values must be `FLOAT`. When targeting morph weights, the `accessor.componentType` of the output values must be `FLOAT` or normalized integer where each output element stores values with a count equal to the number of morph targets. 21 | */ 22 | var output:TGLTFID; 23 | } 24 | -------------------------------------------------------------------------------- /src/gltf/schema/TAsset.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Metadata about the glTF asset 5 | */ 6 | typedef TAsset = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * A copyright message suitable for display to credit the content creator. 11 | */ 12 | @:optional var copyright:String; 13 | 14 | /** 15 | * Tool that generated this glTF model. Useful for debugging. 16 | */ 17 | @:optional var generator:String; 18 | 19 | /** 20 | * The minimum glTF version that this asset targets. 21 | */ 22 | var version:String; 23 | 24 | /** 25 | * The minimum glTF version that this asset targets. 26 | */ 27 | @:optional var minVersion:String; 28 | } 29 | -------------------------------------------------------------------------------- /src/gltf/schema/TAttributeType.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | @:enum abstract TAttributeType(String) from String to String { 4 | var SCALAR = "SCALAR"; 5 | var VEC2 = "VEC2"; 6 | var VEC3 = "VEC3"; 7 | var VEC4 = "VEC4"; 8 | var MAT2 = "MAT2"; 9 | var MAT3 = "MAT3"; 10 | var MAT4 = "MAT4"; 11 | } 12 | -------------------------------------------------------------------------------- /src/gltf/schema/TBuffer.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A buffer points to binary geometry, animation, or skins. 5 | */ 6 | typedef TBuffer = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | >TGLTFUri, 10 | 11 | /** 12 | * The length of the buffer in bytes. 13 | */ 14 | var byteLength:Int; 15 | } 16 | -------------------------------------------------------------------------------- /src/gltf/schema/TBufferTarget.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The target that the GPU buffer should be bound to. 5 | */ 6 | @:enum abstract TBufferTarget(Int) from Int to Int { 7 | var ARRAY_BUFFER = 34962; 8 | var ELEMENT_ARRAY_BUFFER = 34963; 9 | } 10 | -------------------------------------------------------------------------------- /src/gltf/schema/TBufferView.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A view into a buffer generally representing a subset of the buffer. 5 | */ 6 | typedef TBufferView = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The index of the buffer. 11 | */ 12 | var buffer:TGLTFID; 13 | 14 | /** 15 | * The offset into the buffer in bytes 16 | */ 17 | @:optional var byteOffset:Int; 18 | 19 | /** 20 | * The length of the bufferView in bytes. 21 | */ 22 | var byteLength:Int; 23 | 24 | /** 25 | * The stride, in bytes, between vertex attributes. When this is not defined, data is tightly packed. When two or more accessors use the same bufferView, this field must be defined. 26 | */ 27 | @:optional var byteStride:Int; 28 | 29 | /** 30 | * The target that the GPU buffer should be bound to. 31 | */ 32 | @:optional var target:TBufferTarget; 33 | } 34 | -------------------------------------------------------------------------------- /src/gltf/schema/TCamera.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A camera's projection. A node can reference a camera to apply a transform to place the camera in the scene. 5 | */ 6 | typedef TCamera = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * An orthographic camera containing properties to create an orthographic projection matrix. 12 | */ 13 | @:optional var orthographic:TCameraOrthographic; 14 | 15 | /** 16 | * A perspective camera containing properties to create a perspective projection matrix. 17 | */ 18 | @:optional var perspective:TCameraPerspective; 19 | 20 | /** 21 | * Specifies if the camera uses a perspective or orthographic projection. Based on this, either the camera's `perspective` or `orthographic` property will be defined. 22 | */ 23 | var type:TCameraType; 24 | } 25 | -------------------------------------------------------------------------------- /src/gltf/schema/TCameraOrthographic.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * An orthographic camera containing properties to create an orthographic projection matrix. 5 | */ 6 | typedef TCameraOrthographic = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The floating-point horizontal magnification of the view. Must not be zero. 11 | */ 12 | var xmag:Float; 13 | 14 | /** 15 | * The floating-point vertical magnification of the view. Must not be zero. 16 | */ 17 | var ymag:Float; 18 | 19 | /** 20 | * The floating-point distance to the far clipping plane. `zfar` must be greater than `znear`. 21 | */ 22 | var zfar:Float; 23 | 24 | /** 25 | * The floating-point distance to the near clipping plane. 26 | */ 27 | var znear:Float; 28 | } 29 | -------------------------------------------------------------------------------- /src/gltf/schema/TCameraPerspective.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A perspective camera containing properties to create a perspective projection matrix. 5 | */ 6 | typedef TCameraPerspective = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The floating-point aspect ratio of the field of view. When this is undefined, the aspect ratio of the canvas is used. 11 | */ 12 | @:optional var aspectRatio:Float; 13 | 14 | /** 15 | * The floating-point vertical field of view in radians. 16 | */ 17 | var yfov:Float; 18 | 19 | /** 20 | * The floating-point distance to the far clipping plane. When defined, `zfar` must be greater than `znear`. If `zfar` is undefined, runtime must use infinite projection matrix. 21 | */ 22 | @:optional var zfar:Float; 23 | 24 | /** 25 | * The floating-point distance to the near clipping plane. 26 | */ 27 | var znear:Float; 28 | } 29 | -------------------------------------------------------------------------------- /src/gltf/schema/TCameraType.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Specifies if the camera uses a perspective or orthographic projection. Based on this, either the camera's `perspective` or `orthographic` property will be defined. 5 | */ 6 | @:enum abstract TCameraType(String) from String to String { 7 | var PERSPECTIVE = "perspective"; 8 | var ORTHOGRAPHIC = "orthographic"; 9 | } 10 | -------------------------------------------------------------------------------- /src/gltf/schema/TComponentType.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The datatype of components in the attribute. All valid values correspond to WebGL enums. The corresponding typed arrays are `Int8Array`, `Uint8Array`, `Int16Array`, `Uint16Array`, `Uint32Array`, and `Float32Array`, respectively. 5125 (UNSIGNED_INT) is only allowed when the accessor contains indices, i.e., the accessor is only referenced by `primitive.indices`. 5 | */ 6 | @:enum abstract TComponentType(Int) from Int to Int { 7 | var BYTE = 5120; 8 | var UNSIGNED_BYTE = 5121; 9 | var SHORT = 5122; 10 | var UNSIGNED_SHORT = 5123; 11 | var UNSIGNED_INT = 5125; 12 | var FLOAT = 5126; 13 | } 14 | -------------------------------------------------------------------------------- /src/gltf/schema/TGLTF.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The root object for a glTF asset. 5 | */ 6 | typedef TGLTF = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * Names of glTF extensions used somewhere in this asset 11 | */ 12 | @:optional var extensionsUsed:Array; 13 | 14 | /** 15 | * Names of glTF extensions required to properly load this asset. 16 | */ 17 | @:optional var extensionsRequired:Array; 18 | 19 | /** 20 | * An array of accessors. 21 | */ 22 | @:optional var accessors:Array; 23 | 24 | /** 25 | * An array of keyframe animations. 26 | */ 27 | @:optional var animations:Array; 28 | 29 | /** 30 | * Metadata about the glTF asset. 31 | */ 32 | var asset:TAsset; 33 | 34 | /** 35 | * An array of buffers. 36 | */ 37 | @:optional var buffers:Array; 38 | 39 | /** 40 | * An array of bufferViews. 41 | */ 42 | @:optional var bufferViews:Array; 43 | 44 | /** 45 | * An array of cameras. 46 | */ 47 | @:optional var cameras:Array; 48 | 49 | /** 50 | * An array of images. 51 | */ 52 | @:optional var images:Array; 53 | 54 | /** 55 | * An array of materials. 56 | */ 57 | @:optional var materials:Array; 58 | 59 | /** 60 | * An array of meshes. 61 | */ 62 | @:optional var meshes:Array; 63 | 64 | /** 65 | * An array of nodes. 66 | */ 67 | @:optional var nodes:Array; 68 | 69 | /** 70 | * An array of samplers. 71 | */ 72 | @:optional var samplers:Array; 73 | 74 | /** 75 | * The index of the default scene. 76 | */ 77 | @:optional var scene:TGLTFID; 78 | 79 | /** 80 | * An array of scenes. 81 | */ 82 | @:optional var scenes:Array; 83 | 84 | /** 85 | * An array of skins. 86 | */ 87 | @:optional var skins:Array; 88 | 89 | /** 90 | * An array of textures. 91 | */ 92 | @:optional var textures:Array; 93 | } 94 | -------------------------------------------------------------------------------- /src/gltf/schema/TGLTFChildOfRootProperty.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | typedef TGLTFChildOfRootProperty = { 4 | /** 5 | * The user-defined name of this object. This is not necessarily unique, e.g., an accessor and a buffer could have the same name, or two accessors could even have the same name. 6 | */ 7 | @:optional var name:String; 8 | } 9 | -------------------------------------------------------------------------------- /src/gltf/schema/TGLTFID.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | typedef TGLTFID = Int; 4 | -------------------------------------------------------------------------------- /src/gltf/schema/TGLTFProperty.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | typedef TGLTFProperty = { 4 | @:optional var extensions:Dynamic; 5 | @:optional var extras:Dynamic; 6 | } 7 | -------------------------------------------------------------------------------- /src/gltf/schema/TGLTFUri.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | typedef TGLTFUri = { 4 | /** 5 | * The uri of the buffer. Relative paths are relative to the .gltf file. Instead of referencing an external file, the uri can also be a data-uri. 6 | */ 7 | @:optional var uri:String; 8 | } 9 | -------------------------------------------------------------------------------- /src/gltf/schema/TImage.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Image data used to create a texture. Image can be referenced by URI or `bufferView` index. `mimeType` is required in the latter case. 5 | */ 6 | typedef TImage = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | >TGLTFUri, 10 | 11 | /** 12 | * The image's MIME type. 13 | */ 14 | var mimeType:TImageMimeType; 15 | 16 | /** 17 | * The index of the bufferView that contains the image. Use this instead of the image's uri property. 18 | */ 19 | @:optional var bufferView:TGLTFID; 20 | } 21 | -------------------------------------------------------------------------------- /src/gltf/schema/TImageMimeType.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The image's MIME type. 5 | */ 6 | @:enum abstract TImageMimeType(String) from String to String { 7 | var JPEG = "image/jpeg"; 8 | var PNG = "image/png"; 9 | } 10 | -------------------------------------------------------------------------------- /src/gltf/schema/TMagFilter.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Magnification filter. Valid values correspond to WebGL enums: `9728` (NEAREST) and `9729` (LINEAR). 5 | */ 6 | @:enum abstract TMagFilter(Int) from Int to Int { 7 | var NEAREST = 9728; 8 | var LINEAR = 9729; 9 | } 10 | -------------------------------------------------------------------------------- /src/gltf/schema/TMaterial.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The material appearance of a primitive. 5 | */ 6 | typedef TMaterial = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * A set of parameter values that are used to define the metallic-roughness material model from Physically-Based Rendering (PBR) methodology. When not specified, all the default values of `pbrMetallicRoughness` apply. 12 | */ 13 | @:optional var pbrMetallicRoughness:TMaterialPBRMetallicRoughness; 14 | 15 | /** 16 | * A tangent space normal map. The texture contains RGB components in linear space. Each texel represents the XYZ components of a normal vector in tangent space. Red [0 to 255] maps to X [-1 to 1]. Green [0 to 255] maps to Y [-1 to 1]. Blue [128 to 255] maps to Z [1/255 to 1]. The normal vectors use OpenGL conventions where +X is right and +Y is up. +Z points toward the viewer. In GLSL, this vector would be unpacked like so: `float3 normalVector = tex2D(, texCoord) * 2 - 1`. 17 | */ 18 | @:optional var normalTexture:TMaterialNormalTextureInfo; 19 | 20 | /** 21 | * The occlusion map texture. The occlusion values are sampled from the R channel. Higher values indicate areas that should receive full indirect lighting and lower values indicate no indirect lighting. These values are linear. If other channels are present (GBA), they are ignored for occlusion calculations. 22 | */ 23 | @:optional var occlusionTexture:TMaterialOcclusionTextureInfo; 24 | 25 | /** 26 | * The emissive map controls the color and intensity of the light being emitted by the material. This texture contains RGB components in sRGB color space. If a fourth component (A) is present, it is ignored. 27 | */ 28 | @:optional var emissiveTexture:TTextureInfo; 29 | 30 | /** 31 | * The RGB components of the emissive color of the material. These values are linear. If an emissiveTexture is specified, this value is multiplied with the texel values. 32 | */ 33 | @:optional var emissiveFactor:Array; 34 | 35 | /** 36 | * The material's alpha rendering mode enumeration specifying the interpretation of the alpha value of the main factor and texture. 37 | */ 38 | @:optional var alphaMode:TAlphaMode; 39 | 40 | /** 41 | * Specifies the cutoff threshold when in `MASK` mode. If the alpha value is greater than or equal to this value then it is rendered as fully opaque, otherwise, it is rendered as fully transparent. A value greater than 1.0 will render the entire material as fully transparent. This value is ignored for other modes. 42 | */ 43 | @:optional var alphaCutoff:Float; 44 | 45 | /** 46 | * Specifies whether the material is double sided. When this value is false, back-face culling is enabled. When this value is true, back-face culling is disabled and double sided lighting is enabled. The back-face must have its normals reversed before the lighting equation is evaluated. 47 | */ 48 | @:optional var doubleSided:Bool; 49 | } 50 | -------------------------------------------------------------------------------- /src/gltf/schema/TMaterialNormalTextureInfo.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Material Normal Texture Info 5 | */ 6 | typedef TMaterialNormalTextureInfo = { 7 | >TTextureInfo, 8 | 9 | /** 10 | * The scalar multiplier applied to each normal vector of the texture. This value scales the normal vector using the formula: `scaledNormal = normalize((normalize() * 2.0 - 1.0) * vec3(, , 1.0))`. This value is ignored if normalTexture is not specified. This value is linear. 11 | */ 12 | @:optional var scale:Float; 13 | } 14 | -------------------------------------------------------------------------------- /src/gltf/schema/TMaterialOcclusionTextureInfo.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Material Occlusion Texture Info 5 | */ 6 | typedef TMaterialOcclusionTextureInfo = { 7 | >TTextureInfo, 8 | 9 | /** 10 | * A scalar multiplier controlling the amount of occlusion applied. A value of 0.0 means no occlusion. A value of 1.0 means full occlusion. This value affects the resulting color using the formula: `occludedColor = lerp(color, color * , )`. This value is ignored if the corresponding texture is not specified. This value is linear. 11 | */ 12 | @:optional var strength:Float; 13 | } 14 | -------------------------------------------------------------------------------- /src/gltf/schema/TMaterialPBRMetallicRoughness.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A set of parameter values that are used to define the metallic-roughness material model from Physically-Based Rendering (PBR) methodology. 5 | */ 6 | typedef TMaterialPBRMetallicRoughness = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The RGBA components of the base color of the material. The fourth component (A) is the alpha coverage of the material. The `alphaMode` property specifies how alpha is interpreted. These values are linear. If a baseColorTexture is specified, this value is multiplied with the texel values. 11 | */ 12 | @:optional var baseColorFactor:Array; 13 | 14 | /** 15 | * The base color texture. This texture contains RGB(A) components in sRGB color space. The first three components (RGB) specify the base color of the material. If the fourth component (A) is present, it represents the alpha coverage of the material. Otherwise, an alpha of 1.0 is assumed. The `alphaMode` property specifies how alpha is interpreted. The stored texels must not be premultiplied. 16 | */ 17 | @:optional var baseColorTexture:TTextureInfo; 18 | 19 | /** 20 | * The metalness of the material. A value of 1.0 means the material is a metal. A value of 0.0 means the material is a dielectric. Values in between are for blending between metals and dielectrics such as dirty metallic surfaces. This value is linear. If a metallicRoughnessTexture is specified, this value is multiplied with the metallic texel values. 21 | */ 22 | @:optional var metallicFactor:Float; 23 | 24 | /** 25 | * The roughness of the material. A value of 1.0 means the material is completely rough. A value of 0.0 means the material is completely smooth. This value is linear. If a metallicRoughnessTexture is specified, this value is multiplied with the roughness texel values. 26 | */ 27 | @:optional var roughnessFactor:Float; 28 | 29 | /** 30 | * The metallic-roughness texture. The metalness values are sampled from the B channel. The roughness values are sampled from the G channel. These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations. 31 | */ 32 | @:optional var metallicRoughnessTexture:TTextureInfo; 33 | } 34 | -------------------------------------------------------------------------------- /src/gltf/schema/TMesh.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A set of primitives to be rendered. A node can contain one mesh. A node's transform places the mesh in the scene. 5 | */ 6 | typedef TMesh = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * An array of primitives, each defining geometry to be rendered with a material. 12 | */ 13 | var primitives:Array; 14 | 15 | /** 16 | * Array of weights to be applied to the Morph Targets. 17 | */ 18 | @:optional var weights:Array; 19 | } 20 | -------------------------------------------------------------------------------- /src/gltf/schema/TMeshPrimitive.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Geometry to be rendered with the given material. 5 | */ 6 | typedef TMeshPrimitive = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * A dictionary object, where each key corresponds to mesh attribute semantic and each value is the index of the accessor containing attribute's data. 11 | */ 12 | var attributes:Dynamic; 13 | 14 | /** 15 | * The index of the accessor that contains mesh indices. When this is not defined, the primitives should be rendered without indices using `drawArrays()`. When defined, the accessor must contain indices: the `bufferView` referenced by the accessor should have a `target` equal to 34963 (ELEMENT_ARRAY_BUFFER); `componentType` must be 5121 (UNSIGNED_BYTE), 5123 (UNSIGNED_SHORT) or 5125 (UNSIGNED_INT), the latter may require enabling additional hardware support; `type` must be `\"SCALAR\"`. For triangle primitives, the front face has a counter-clockwise (CCW) winding order. 16 | */ 17 | @:optional var indices:TGLTFID; 18 | 19 | /** 20 | * The index of the material to apply to this primitive when rendering. 21 | */ 22 | @:optional var material:TGLTFID; 23 | 24 | /** 25 | * The type of primitives to render. All valid values correspond to WebGL enums. 26 | */ 27 | @:optional var mode:TMeshPrimitiveType; 28 | 29 | /** 30 | * An array of Morph Targets, each Morph Target is a dictionary mapping attributes (only `POSITION`, `NORMAL`, and `TANGENT` supported) to their deviations in the Morph Target. 31 | * 32 | * Each item is a dictionary object specifying attributes displacements in a Morph Target, where each key corresponds to one of the three supported attribute semantic (`POSITION`, `NORMAL`, or `TANGENT`) and each value is the index of the accessor containing the attribute displacements' data. 33 | */ 34 | @:optional var targets:Array; 35 | } 36 | -------------------------------------------------------------------------------- /src/gltf/schema/TMeshPrimitiveType.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The type of primitives to render. All valid values correspond to WebGL enums. 5 | */ 6 | @:enum abstract TMeshPrimitiveType(Int) from Int to Int { 7 | var POINTS = 0; 8 | var LINES = 1; 9 | var LINE_LOOP = 2; 10 | var LINE_STRIP = 3; 11 | var TRIANGLES = 4; 12 | var TRIANGLE_STRIP = 5; 13 | var TRIANGLE_FAN = 6; 14 | } 15 | -------------------------------------------------------------------------------- /src/gltf/schema/TMinFilter.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Minification filter. All valid values correspond to WebGL enums. 5 | */ 6 | @:enum abstract TMinFilter(Int) from Int to Int { 7 | var NEAREST = 9728; 8 | var LINEAR = 9729; 9 | var NEAREST_MIPMAP_NEAREST = 9984; 10 | var LINEAR_MIPMAP_NEAREST = 9985; 11 | var NEAREST_MIPMAP_LINEAR = 9986; 12 | var LINEAR_MIPMAP_LINEAR = 9987; 13 | } 14 | -------------------------------------------------------------------------------- /src/gltf/schema/TNode.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A node in the node hierarchy. When the node contains `skin`, all `mesh.primitives` must contain `JOINTS_0` and `WEIGHTS_0` attributes. A node can have either a `matrix` or any combination of `translation`/`rotation`/`scale` (TRS) properties. TRS properties are converted to matrices and postmultiplied in the `T * R * S` order to compose the transformation matrix; first the scale is applied to the vertices, then the rotation, and then the translation. If none are provided, the transform is the identity. When a node is targeted for animation (referenced by an animation.channel.target), only TRS properties may be present; `matrix` will not be present. 5 | */ 6 | typedef TNode = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * The index of the camera referenced by this node. 12 | */ 13 | @:optional var camera:TGLTFID; 14 | 15 | /** 16 | * The indices of this node's children. 17 | */ 18 | @:optional var children:Array; 19 | 20 | /** 21 | * The index of the skin referenced by this node. 22 | */ 23 | @:optional var skin:TGLTFID; 24 | 25 | /** 26 | * A floating-point 4x4 transformation matrix stored in column-major order. 27 | */ 28 | @:optional var matrix:Array; 29 | 30 | /** 31 | * The index of the mesh in this node. 32 | */ 33 | @:optional var mesh:TGLTFID; 34 | 35 | /** 36 | * The node's unit quaternion rotation in the order (x, y, z, w), where w is the scalar. 37 | */ 38 | @:optional var rotation:Array; 39 | 40 | /** 41 | * The node's non-uniform scale. 42 | */ 43 | @:optional var scale:Array; 44 | 45 | /** 46 | * The node's translation. 47 | */ 48 | @:optional var translation:Array; 49 | 50 | /** 51 | * The weights of the instantiated Morph Target. Number of elements must match number of Morph Targets of used mesh. 52 | */ 53 | @:optional var weights:Array; 54 | } 55 | -------------------------------------------------------------------------------- /src/gltf/schema/TSampler.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Texture sampler properties for filtering and wrapping modes. 5 | */ 6 | typedef TSampler = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * Magnification filter. Valid values correspond to WebGL enums: `9728` (NEAREST) and `9729` (LINEAR). 12 | */ 13 | @:optional var magFilter:TMagFilter; 14 | 15 | /** 16 | * Minification filter. All valid values correspond to WebGL enums. 17 | */ 18 | @:optional var minFilter:TMinFilter; 19 | 20 | /** 21 | * s wrapping mode. All valid values correspond to WebGL enums. 22 | */ 23 | @:optional var wrapS:TWrapMode; 24 | 25 | /** 26 | * t wrapping mode. All valid values correspond to WebGL enums. 27 | */ 28 | @:optional var wrapT:TWrapMode; 29 | } 30 | -------------------------------------------------------------------------------- /src/gltf/schema/TScene.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * The root nodes of a scene. 5 | */ 6 | typedef TScene = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * The indices of each root node. 12 | */ 13 | var nodes:Array; 14 | } 15 | -------------------------------------------------------------------------------- /src/gltf/schema/TSkin.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Joints and matrices defining a skin. 5 | */ 6 | typedef TSkin = { 7 | >TGLTFChildOfRootProperty, 8 | >TGLTFProperty, 9 | 10 | /** 11 | * The index of the accessor containing the floating-point 4x4 inverse-bind matrices. The default is that each matrix is a 4x4 identity matrix, which implies that inverse-bind matrices were pre-applied. 12 | */ 13 | @:optional var inverseBindMatrices:TGLTFID; 14 | 15 | /** 16 | * The index of the node used as a skeleton root. When undefined, joints transforms resolve to scene root. 17 | */ 18 | @:optional var skeleton:TGLTFID; 19 | 20 | /** 21 | * Indices of skeleton nodes, used as joints in this skin. The array length must be the same as the `count` property of the `inverseBindMatrices` accessor (when defined). 22 | */ 23 | var joints:Array; 24 | } 25 | -------------------------------------------------------------------------------- /src/gltf/schema/TTexture.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * A texture and its sampler. 5 | * 6 | * WebGL functions: `createTexture()`, `deleteTexture()`, `bindTexture()`, `texImage2D()`, and `texParameterf()` 7 | */ 8 | typedef TTexture = { 9 | >TGLTFChildOfRootProperty, 10 | >TGLTFProperty, 11 | 12 | /** 13 | * The index of the sampler used by this texture. When undefined, a sampler with repeat wrapping and auto filtering should be used. 14 | */ 15 | @:optional var sampler:TGLTFID; 16 | 17 | /** 18 | * The index of the image used by this texture. 19 | */ 20 | @:optional var source:TGLTFID; 21 | } 22 | -------------------------------------------------------------------------------- /src/gltf/schema/TTextureInfo.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * Reference to a texture. 5 | */ 6 | typedef TTextureInfo = { 7 | >TGLTFProperty, 8 | 9 | /** 10 | * The index of the texture. 11 | */ 12 | var index:TGLTFID; 13 | 14 | /** 15 | * This integer value is used to construct a string in the format TEXCOORD_ which is a reference to a key in mesh.primitives.attributes (e.g. A value of 0 corresponds to TEXCOORD_0). 16 | */ 17 | @:optional var texCoord:Int; 18 | } 19 | -------------------------------------------------------------------------------- /src/gltf/schema/TWrapMode.hx: -------------------------------------------------------------------------------- 1 | package gltf.schema; 2 | 3 | /** 4 | * s-t wrapping mode. All valid values correspond to WebGL enums. 5 | */ 6 | @:enum abstract TWrapMode(Int) from Int to Int { 7 | var CLAMP_TO_EDGE = 33071; 8 | var MIRROR_REPEAT = 33648; 9 | var REPEAT = 10497; 10 | } 11 | -------------------------------------------------------------------------------- /src/gltf/types/Accessor.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TAccessor; 5 | import gltf.schema.TComponentType; 6 | import gltf.schema.TAttributeType; 7 | import haxe.ds.Vector; 8 | 9 | @:allow(gltf.GLTF) 10 | class Accessor { 11 | public var bufferView(default, null):BufferView = null; 12 | public var byteOffset(default, null):Int = 0; 13 | public var count(default, null):Int = 0; 14 | public var componentType(default, null):TComponentType = TComponentType.BYTE; 15 | public var type(default, null):TAttributeType = TAttributeType.SCALAR; 16 | public var normalized(default, null):Bool = false; 17 | // TODO: min / max 18 | // TODO: sparse accessors 19 | 20 | function new() {} 21 | 22 | function load(gltf:GLTF, accessor:TAccessor):Void { 23 | bufferView = gltf.bufferViews[accessor.bufferView]; 24 | byteOffset = accessor.byteOffset; 25 | count = accessor.count; 26 | componentType = accessor.componentType; 27 | type = accessor.type; 28 | normalized = accessor.normalized == null ? false: accessor.normalized; 29 | } 30 | 31 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 32 | var accessors:Vector = new Vector(raw.accessors.length); 33 | for(i in 0...raw.accessors.length) { 34 | accessors[i] = new Accessor(); 35 | } 36 | for(i in 0...raw.accessors.length) { 37 | accessors[i].load(gltf, raw.accessors[i]); 38 | } 39 | return accessors; 40 | } 41 | 42 | public function getInts():Vector { 43 | if(this.componentType == TComponentType.FLOAT) { 44 | throw 'This accessor points to `float` data, use `getFloats()` instead of `getInts()`!'; 45 | } 46 | 47 | var componentSize:Int = switch(this.type) { 48 | case SCALAR: 1; 49 | case VEC2: 2; 50 | case VEC3: 3; 51 | case VEC4: 4; 52 | case MAT2: 4; 53 | case MAT3: 9; 54 | case MAT4: 16; 55 | }; 56 | 57 | var data:Vector = new Vector(count*componentSize); 58 | 59 | var pos:Int = byteOffset; 60 | // TODO: signed / unsigned versions.. 61 | var accessor:Int->Void = switch(this.componentType) { 62 | case BYTE | UNSIGNED_BYTE: function(i:Int) { data[i] = bufferView.data.get(pos); pos++; } 63 | case SHORT | UNSIGNED_SHORT: function(i:Int) { data[i] = bufferView.data.getUInt16(pos); pos += 2; } 64 | case UNSIGNED_INT: function(i:Int) { data[i] = bufferView.data.getInt32(pos); pos += 4; } 65 | case _: throw 'Floats aren\'t supported with this function!'; 66 | } 67 | for(i in 0...(count*componentSize)) accessor(i); 68 | 69 | return data; 70 | } 71 | 72 | public function getFloats():Vector { 73 | if(this.componentType != TComponentType.FLOAT) { 74 | throw 'This accessor points to `int` data, use `getInts()` instead of `getFloats()`!'; 75 | } 76 | 77 | var size:Int = switch(this.type) { 78 | case SCALAR: 1; 79 | case VEC2: 2; 80 | case VEC3: 3; 81 | case VEC4: 4; 82 | case MAT2: 4; 83 | case MAT3: 9; 84 | case MAT4: 16; 85 | }; 86 | var data:Vector = new Vector(count*size); 87 | 88 | var pos:Int = byteOffset; 89 | for(i in 0...(count*size)) { 90 | data[i] = bufferView.data.getFloat(pos); 91 | pos += 4; 92 | } 93 | 94 | return data; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/gltf/types/Animation.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TAnimation; 5 | import haxe.ds.Vector; 6 | 7 | @:allow(gltf.GLTF) 8 | class Animation { 9 | public var name(default, null):String = null; 10 | public var channels(default, null):Vector = null; 11 | 12 | function new() {} 13 | 14 | function load(gltf:GLTF, animation:TAnimation):Void { 15 | this.name = animation.name; 16 | this.channels = new Vector(animation.channels.length); 17 | 18 | for(i in 0...animation.channels.length) { 19 | channels[i] = new AnimationChannel(); 20 | channels[i].node = gltf.nodes[animation.channels[i].target.node]; 21 | channels[i].loadSampler(gltf, animation.samplers[animation.channels[i].sampler]); 22 | channels[i].path = animation.channels[i].target.path; 23 | } 24 | } 25 | 26 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 27 | var animations:Vector = new Vector(raw.animations.length); 28 | for(i in 0...raw.animations.length) { 29 | animations[i] = new Animation(); 30 | } 31 | for(i in 0...raw.animations.length) { 32 | animations[i].load(gltf, raw.animations[i]); 33 | } 34 | return animations; 35 | } 36 | } -------------------------------------------------------------------------------- /src/gltf/types/AnimationChannel.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import haxe.ds.Vector; 4 | import gltf.schema.TAnimationChannelTargetPath; 5 | import gltf.schema.TAnimationSampler; 6 | 7 | @:allow(gltf.types.AnimationChannel) 8 | class AnimationSample { 9 | public var input(default, null):Float = 0; 10 | public var output(default, null):Vector = null; 11 | 12 | private function new(input:Float, output:Vector) { 13 | this.input = input; 14 | this.output = output; 15 | } 16 | } 17 | 18 | @:allow(gltf.types.Animation) 19 | class AnimationChannel { 20 | public var node(default, null):Node = null; 21 | public var samples(default, null):Vector = null; 22 | public var path(default, null):TAnimationChannelTargetPath = null; 23 | 24 | private function new() {} 25 | 26 | private function loadSampler(gltf:GLTF, sampler:TAnimationSampler):Void { 27 | var inputSampler:Accessor = gltf.accessors[sampler.input]; 28 | var outputSampler:Accessor = gltf.accessors[sampler.output]; 29 | 30 | var inputs:Vector = inputSampler.getFloats(); 31 | var outputs:Vector = outputSampler.getFloats(); 32 | samples = new Vector(inputs.length); 33 | for(i in 0...inputs.length) { 34 | samples[i] = new AnimationSample( 35 | inputs[i], 36 | switch(outputSampler.type) { 37 | case SCALAR: { 38 | var o:Vector = new Vector(1); 39 | o[0] = outputs[i]; 40 | o; 41 | } 42 | 43 | case VEC2: { 44 | var o:Vector = new Vector(2); 45 | o[0] = outputs[(i * 2) + 0]; 46 | o[1] = outputs[(i * 2) + 1]; 47 | o; 48 | } 49 | 50 | case VEC3: { 51 | var o:Vector = new Vector(3); 52 | o[0] = outputs[(i * 3) + 0]; 53 | o[1] = outputs[(i * 3) + 1]; 54 | o[2] = outputs[(i * 3) + 2]; 55 | o; 56 | } 57 | 58 | case VEC4: { 59 | var o:Vector = new Vector(4); 60 | o[0] = outputs[(i * 4) + 0]; 61 | o[1] = outputs[(i * 4) + 1]; 62 | o[2] = outputs[(i * 4) + 2]; 63 | o[3] = outputs[(i * 4) + 3]; 64 | o; 65 | } 66 | 67 | default: { 68 | throw 'Unhandled animation sampler accessor type: \'' + outputSampler.type + '\'!'; 69 | } 70 | } 71 | ); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /src/gltf/types/Buffer.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TBuffer; 5 | import haxe.io.Bytes; 6 | import haxe.ds.Vector; 7 | 8 | @:allow(gltf.GLTF) 9 | class Buffer { 10 | public var uri(default, null):String = ""; 11 | public var name(default, null):String = ""; 12 | public var data(default, null):Bytes = null; 13 | 14 | function new() {} 15 | 16 | function load(gltf:GLTF, buffer:TBuffer, data:Bytes):Void { 17 | this.uri = buffer.uri; 18 | this.name = buffer.name; 19 | this.data = data; 20 | } 21 | 22 | static function loadFromRawWithGetter(gltf: GLTF, raw: TGLTF, getter: Int->Bytes): Vector { 23 | var buffers:Vector = new Vector(raw.buffers.length); 24 | for(i in 0...raw.buffers.length) { 25 | buffers[i] = new Buffer(); 26 | buffers[i].load(gltf, raw.buffers[i], getter(i)); 27 | } 28 | return buffers; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/gltf/types/BufferView.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TBufferView; 5 | import gltf.schema.TBufferTarget; 6 | import haxe.ds.Vector; 7 | import haxe.io.Bytes; 8 | 9 | @:allow(gltf.GLTF) 10 | class BufferView { 11 | public var buffer(default, null):Buffer = null; 12 | public var byteOffset(default, null):Int = 0; 13 | public var byteLength(default, null):Int = 0; 14 | public var byteStride(default, null):Int = 0; 15 | public var target(default, null):TBufferTarget = TBufferTarget.ARRAY_BUFFER; 16 | 17 | private var _data:Bytes = null; 18 | public var data(get, never):Bytes; 19 | private function get_data():Bytes { 20 | // TODO: deal with byteStride (https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment) 21 | if(_data == null) { 22 | _data = buffer.data.sub(byteOffset, byteLength); 23 | } 24 | return _data; 25 | } 26 | 27 | function new() {} 28 | 29 | function load(gltf:GLTF, bufferView:TBufferView):Void { 30 | this.buffer = gltf.buffers[bufferView.buffer]; 31 | this.byteOffset = bufferView.byteOffset; 32 | this.byteLength = bufferView.byteLength; 33 | this.byteStride = bufferView.byteStride; 34 | this.target = bufferView.target; 35 | } 36 | 37 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 38 | var views:Vector = new Vector(raw.bufferViews.length); 39 | for(i in 0...raw.bufferViews.length) { 40 | views[i] = new BufferView(); 41 | } 42 | for(i in 0...raw.bufferViews.length) { 43 | views[i].load(gltf, raw.bufferViews[i]); 44 | } 45 | return views; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/gltf/types/Camera.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TCamera; 5 | import haxe.ds.Vector; 6 | 7 | @:allow(gltf.GLTF) 8 | class Camera { 9 | public var name(default, null):String; 10 | public var type(default, null):CameraType; 11 | public var znear(default, null):Float; 12 | public var zfar(default, null):Float; 13 | public var yfov(default, null):Float; 14 | public var aspectRatio(default, null):Float; 15 | 16 | function new() {} 17 | 18 | function load(gltf:GLTF, camera:TCamera):Void { 19 | name = camera.name; 20 | if(camera.perspective != null) { 21 | type = CameraType.Perspective(camera.perspective.aspectRatio, camera.perspective.yfov); 22 | znear = camera.perspective.znear; 23 | zfar = camera.perspective.zfar; 24 | yfov = camera.perspective.yfov; 25 | aspectRatio = camera.perspective.aspectRatio; 26 | } 27 | else { 28 | type = CameraType.Orthographic(camera.orthographic.xmag, camera.orthographic.ymag); 29 | znear = camera.orthographic.znear; 30 | zfar = camera.orthographic.zfar; 31 | } 32 | } 33 | 34 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 35 | var cameras:Vector = new Vector(raw.cameras.length); 36 | for(i in 0...raw.cameras.length) { 37 | cameras[i] = new Camera(); 38 | } 39 | for(i in 0...raw.cameras.length) { 40 | cameras[i].load(gltf, raw.cameras[i]); 41 | } 42 | return cameras; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/gltf/types/CameraType.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | enum CameraType { 4 | Orthographic(xmag:Float, ymag:Float); 5 | Perspective(aspectRatio:Float, yFov:Float); 6 | } 7 | -------------------------------------------------------------------------------- /src/gltf/types/Image.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.types.BufferView; 4 | import gltf.schema.TGLTF; 5 | import gltf.schema.TImage; 6 | import gltf.schema.TImageMimeType; 7 | import haxe.ds.Vector; 8 | 9 | @:allow(gltf.GLTF) 10 | class Image { 11 | public var name(default, null):String = null; 12 | public var uri(default, null):Null = null; 13 | public var mimeType(default, null):TImageMimeType = TImageMimeType.PNG; 14 | public var bufferView(default, null):Null = null; 15 | 16 | function new() {} 17 | 18 | function load(gltf:GLTF, image:TImage):Void { 19 | this.name = image.name; 20 | this.uri = image.uri; 21 | this.mimeType = image.mimeType; 22 | if(image.bufferView != null) this.bufferView = gltf.bufferViews[image.bufferView]; 23 | } 24 | 25 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 26 | var images:Vector = new Vector(raw.images.length); 27 | for(i in 0...raw.images.length) { 28 | images[i] = new Image(); 29 | } 30 | for(i in 0...raw.images.length) { 31 | images[i].load(gltf, raw.images[i]); 32 | } 33 | return images; 34 | } 35 | } -------------------------------------------------------------------------------- /src/gltf/types/Material.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import haxe.ds.Vector; 4 | import gltf.schema.TGLTF; 5 | import gltf.schema.TMaterialPBRMetallicRoughness; 6 | import gltf.schema.TMaterial; 7 | 8 | @:allow(gltf.GLTF) 9 | class Material { 10 | public var name(default, null):Null = null; 11 | public var pbrMetallicRoughness(default, null):Null = null; 12 | 13 | function new() {} 14 | 15 | function load(gltf:GLTF, material:TMaterial):Void { 16 | name = material.name; 17 | pbrMetallicRoughness = material.pbrMetallicRoughness; 18 | } 19 | 20 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 21 | var materials:Vector = new Vector(raw.materials.length); 22 | for(i in 0...raw.materials.length) { 23 | materials[i] = new Material(); 24 | } 25 | for(i in 0...raw.materials.length) { 26 | materials[i].load(gltf, raw.materials[i]); 27 | } 28 | return materials; 29 | } 30 | } -------------------------------------------------------------------------------- /src/gltf/types/Mesh.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TMesh; 5 | import haxe.ds.Vector; 6 | 7 | @:allow(gltf.GLTF) 8 | class Mesh { 9 | public var name(default, null):Null = null; 10 | public var primitives(default, null):Vector = new Vector(0); 11 | public var weights(default, null):Vector = new Vector(0); 12 | 13 | function new() {} 14 | 15 | function load(gltf:GLTF, mesh:TMesh):Void { 16 | name = mesh.name; 17 | primitives = new Vector(mesh.primitives.length); 18 | for(i in 0...mesh.primitives.length) { 19 | primitives[i] = new MeshPrimitive(); 20 | primitives[i].load(gltf, mesh.primitives[i]); 21 | } 22 | 23 | if(mesh.weights != null) weights = Vector.fromArrayCopy(mesh.weights); 24 | } 25 | 26 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 27 | var meshes:Vector = new Vector(raw.meshes.length); 28 | for(i in 0...raw.meshes.length) { 29 | meshes[i] = new Mesh(); 30 | } 31 | for(i in 0...raw.meshes.length) { 32 | meshes[i].load(gltf, raw.meshes[i]); 33 | } 34 | return meshes; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/gltf/types/MeshPrimitive.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.GLTF; 4 | import gltf.schema.TGLTFID; 5 | import gltf.types.Accessor; 6 | import gltf.schema.TMeshPrimitive; 7 | import haxe.ds.Vector; 8 | import gltf.schema.TComponentType; 9 | 10 | typedef TAttribute = { 11 | var name:String; 12 | var accessor:Accessor; 13 | } 14 | 15 | @:allow(gltf.types.Mesh) 16 | class MeshPrimitive { 17 | public var attributes(default, null):Vector = new Vector(0); 18 | public var indices(default, null):Null = null; 19 | public var material(default, null):Null = null; 20 | // TODO: mode 21 | // TODO: morph targets 22 | 23 | function new() {} 24 | 25 | function load(gltf:GLTF, primitive:TMeshPrimitive):Void { 26 | // load the attributes 27 | var names:Array = Reflect.fields(primitive.attributes); 28 | attributes = new Vector(names.length); 29 | for(i in 0...names.length) { 30 | var aid:Int = Reflect.field(primitive.attributes, names[i]); 31 | attributes[i] = { 32 | name: names[i], 33 | accessor: gltf.accessors[aid] 34 | }; 35 | } 36 | 37 | if(primitive.indices != null) indices = gltf.accessors[primitive.indices]; 38 | if(primitive.material != null) material = primitive.material; 39 | } 40 | 41 | public function getFloatAttributeValues(attribute:String):Vector { 42 | var accessor:Accessor = null; 43 | for(a in attributes) { 44 | if(a.name == attribute) { 45 | accessor = a.accessor; 46 | break; 47 | } 48 | } 49 | if(accessor == null) { 50 | throw 'This mesh primitive doesn\'t contain the \'${attribute}\' attribute!'; 51 | } 52 | 53 | // allow ints to be used as floats 54 | if(accessor.componentType != TComponentType.FLOAT) { 55 | var ints: Vector = accessor.getInts(); 56 | if(accessor.normalized) { 57 | return switch(accessor.componentType) { 58 | case TComponentType.BYTE: ints.map((v: Int) -> ((v / 255.0) - 0.5) * 2.0); 59 | case TComponentType.SHORT: ints.map((v: Int) -> ((v / 65535.0) - 0.5) * 2.0); 60 | case TComponentType.UNSIGNED_BYTE: ints.map((v: Int) -> v / 255.0); 61 | case TComponentType.UNSIGNED_SHORT: ints.map((v: Int) -> v / 65535.0); 62 | case TComponentType.UNSIGNED_INT: ints.map((v: Int) -> v / 4294967295.0); 63 | default: ints.map((v: Int) -> cast(v, Float)); 64 | }; 65 | } 66 | else { 67 | return ints.map((v: Int) -> cast(v, Float)); 68 | } 69 | } 70 | else { 71 | return accessor.getFloats(); 72 | } 73 | } 74 | 75 | public function getIntAttributeValues(attribute:String):Vector { 76 | var accessor:Accessor = null; 77 | for(a in attributes) { 78 | if(a.name == attribute) { 79 | accessor = a.accessor; 80 | break; 81 | } 82 | } 83 | if(accessor == null) { 84 | throw 'This mesh primitive doesn\'t contain the \'${attribute}\' attribute!'; 85 | } 86 | 87 | return accessor.getInts(); 88 | } 89 | 90 | public function getIndexValues():Vector { 91 | if(indices == null) { 92 | throw 'This mesh primitive doesn\'t have indices!'; 93 | } 94 | return indices.getInts(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/gltf/types/Node.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TNode; 5 | import haxe.ds.Vector; 6 | 7 | @:allow(gltf.GLTF) 8 | class Node { 9 | public var id(default, null):Int = -1; 10 | public var name(default, null):Null = null; 11 | public var camera(default, null):Null = null; 12 | public var children(default, null):Vector = new Vector(0); 13 | public var skin(default, null):Null = null; 14 | public var matrix(default, null):Null> = null; 15 | public var mesh(default, null):Null = null; 16 | public var rotation(default, null):Null> = null; 17 | public var scale(default, null):Null> = null; 18 | public var translation(default, null):Null> = null; 19 | public var weights(default, null):Null> = null; 20 | 21 | function new() {} 22 | 23 | function load(gltf:GLTF, node:TNode, existingNodes:Vector):Void { 24 | name = node.name; 25 | if(node.camera != null) camera = gltf.cameras[node.camera]; 26 | if(node.children != null) { 27 | children = new Vector(node.children.length); 28 | for(i in 0...node.children.length) { 29 | children[i] = existingNodes[node.children[i]]; 30 | } 31 | } 32 | if(node.skin != null) skin = gltf.skins[node.skin]; 33 | if(node.matrix != null) matrix = Vector.fromArrayCopy(node.matrix); 34 | if(node.mesh != null) mesh = gltf.meshes[node.mesh]; 35 | if(node.rotation != null) rotation = Vector.fromArrayCopy(node.rotation); 36 | if(node.scale != null) scale = Vector.fromArrayCopy(node.scale); 37 | if(node.translation != null) translation = Vector.fromArrayCopy(node.translation); 38 | if(node.weights != null) weights = Vector.fromArrayCopy(node.weights); 39 | } 40 | 41 | static function preloadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 42 | var existingNodes:Vector = new Vector(raw.nodes.length); 43 | for(i in 0...raw.nodes.length) { 44 | existingNodes[i] = new Node(); 45 | existingNodes[i].id = i; 46 | } 47 | return existingNodes; 48 | } 49 | 50 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 51 | for(i in 0...raw.nodes.length) { 52 | gltf.nodes[i].load(gltf, raw.nodes[i], gltf.nodes); 53 | } 54 | return gltf.nodes; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/gltf/types/Sampler.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TSampler; 5 | import gltf.schema.TMagFilter; 6 | import gltf.schema.TMinFilter; 7 | import gltf.schema.TWrapMode; 8 | import haxe.ds.Vector; 9 | 10 | @:allow(gltf.GLTF) 11 | class Sampler { 12 | public var name(default, null):String; 13 | public var magFilter(default, null):TMagFilter; 14 | public var minFilter(default, null):TMinFilter; 15 | public var wrapS(default, null):TWrapMode; 16 | public var wrapT(default, null):TWrapMode; 17 | 18 | function new() {} 19 | 20 | function load(gltf:GLTF, sampler:TSampler):Void { 21 | this.name = sampler.name; 22 | this.magFilter = sampler.magFilter; 23 | this.minFilter = sampler.minFilter; 24 | this.wrapS = sampler.wrapS; 25 | this.wrapT = sampler.wrapT; 26 | } 27 | 28 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 29 | var samplers:Vector = new Vector(raw.samplers.length); 30 | for(i in 0...raw.samplers.length) { 31 | samplers[i] = new Sampler(); 32 | } 33 | for(i in 0...raw.samplers.length) { 34 | samplers[i].load(gltf, raw.samplers[i]); 35 | } 36 | return samplers; 37 | } 38 | } -------------------------------------------------------------------------------- /src/gltf/types/Scene.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.schema.TGLTF; 4 | import gltf.schema.TScene; 5 | import haxe.ds.Vector; 6 | 7 | @:allow(gltf.GLTF) 8 | class Scene { 9 | public var name(default, null):Null = null; 10 | public var nodes(default, null):Vector = new Vector(0); 11 | 12 | function new() {} 13 | 14 | function load(gltf:GLTF, scene:TScene):Void { 15 | name = scene.name; 16 | nodes = new Vector(scene.nodes.length); 17 | for(i in 0...scene.nodes.length) { 18 | nodes[i] = gltf.nodes[scene.nodes[i]]; 19 | } 20 | } 21 | 22 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 23 | var scenes:Vector = new Vector(raw.scenes.length); 24 | for(i in 0...raw.scenes.length) { 25 | scenes[i] = new Scene(); 26 | } 27 | for(i in 0...raw.scenes.length) { 28 | scenes[i].load(gltf, raw.scenes[i]); 29 | } 30 | return scenes; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/gltf/types/Skin.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import haxe.ds.Vector; 4 | import gltf.types.Accessor; 5 | import gltf.schema.TGLTF; 6 | import gltf.schema.TSkin; 7 | 8 | @:allow(gltf.GLTF) 9 | class Skin { 10 | public var skeleton(default, null):Node; 11 | public var joints(default, null):Vector; 12 | public var inverseBindMatrices(default, null):Vector>; 13 | 14 | function new() {} 15 | 16 | function load(gltf:GLTF, skin:TSkin):Void { 17 | skeleton = gltf.nodes[skin.skeleton]; 18 | 19 | joints = new Vector(skin.joints.length); 20 | for(i in 0...skin.joints.length) { 21 | joints[i] = gltf.nodes[skin.joints[i]]; 22 | } 23 | 24 | inverseBindMatrices = new Vector>(skin.joints.length); 25 | var accessor:Accessor = gltf.accessors[skin.inverseBindMatrices]; 26 | var matrices:Vector = accessor.getFloats(); 27 | for(i in 0...skin.joints.length) { 28 | inverseBindMatrices[i] = new Vector(16); 29 | for(j in 0...16) { 30 | inverseBindMatrices[i][j] = matrices[i * 16 + j]; 31 | } 32 | } 33 | } 34 | 35 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 36 | var skins:Vector = new Vector(raw.skins.length); 37 | for(i in 0...raw.skins.length) { 38 | var skin:Skin = new Skin(); 39 | skin.load(gltf, raw.skins[i]); 40 | skins[i] = skin; 41 | } 42 | return skins; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/gltf/types/Texture.hx: -------------------------------------------------------------------------------- 1 | package gltf.types; 2 | 3 | import gltf.types.Image; 4 | import gltf.types.Sampler; 5 | import gltf.schema.TGLTF; 6 | import gltf.schema.TTexture; 7 | import haxe.ds.Vector; 8 | 9 | @:allow(gltf.GLTF) 10 | class Texture { 11 | public var name(default, null):String = null; 12 | public var image(default, null):Image = null; 13 | public var sampler(default, null):Sampler = null; 14 | 15 | function new() {} 16 | 17 | function load(gltf:GLTF, texture:TTexture):Void { 18 | this.name = texture.name; 19 | if(texture.source != null) this.image = gltf.images[texture.source]; 20 | if(texture.sampler != null) this.sampler = gltf.samplers[texture.sampler]; 21 | } 22 | 23 | static function loadFromRaw(gltf:GLTF, raw:TGLTF):Vector { 24 | var textures:Vector = new Vector(raw.textures.length); 25 | for(i in 0...raw.textures.length) { 26 | textures[i] = new Texture(); 27 | } 28 | for(i in 0...raw.textures.length) { 29 | textures[i].load(gltf, raw.textures[i]); 30 | } 31 | return textures; 32 | } 33 | } -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | samples/ -------------------------------------------------------------------------------- /test/TestMain.hx: -------------------------------------------------------------------------------- 1 | import buddy.*; 2 | 3 | class TestMain implements Buddy<[ 4 | gltf.TestParsing, 5 | gltf.TestLoading 6 | ]> {} -------------------------------------------------------------------------------- /test/get-samples.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -rf samples 3 | mkdir samples 4 | curl -L -o samples/Box.gltf https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Box/glTF/Box.gltf 5 | curl -L -o samples/Box.glb https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Box/glTF-Binary/Box.glb 6 | curl -L -o samples/Box0.bin https://github.com/KhronosGroup/glTF-Sample-Models/raw/master/2.0/Box/glTF/Box0.bin 7 | curl -L -o samples/BoxTextured.gltf https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoxTextured/glTF/BoxTextured.gltf 8 | curl -L -o samples/BoxTextured0.bin https://github.com/KhronosGroup/glTF-Sample-Models/raw/master/2.0/BoxTextured/glTF/BoxTextured0.bin 9 | curl -L -o samples/CesiumLogoFlat.png https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoxTextured/glTF/CesiumLogoFlat.png 10 | curl -L -o samples/RiggedSimple.gltf https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/RiggedSimple/glTF/RiggedSimple.gltf 11 | curl -L -o samples/RiggedSimple0.bin https://github.com/KhronosGroup/glTF-Sample-Models/raw/master/2.0/RiggedSimple/glTF/RiggedSimple0.bin 12 | -------------------------------------------------------------------------------- /test/gltf/TestLoading.hx: -------------------------------------------------------------------------------- 1 | package gltf; 2 | 3 | import gltf.schema.TGLTF; 4 | import buddy.*; 5 | using buddy.Should; 6 | import haxe.io.Bytes; 7 | import haxe.ds.Vector; 8 | 9 | class TestLoading extends BuddySuite { 10 | public function new() { 11 | describe('Loading GLBs', { 12 | var boxData = sys.io.File.getBytes('samples/Box.glb'); 13 | 14 | it('should load a GLB without throwing an exception', { 15 | var box = GLTF.parseAndLoadGLB(boxData); 16 | }); 17 | 18 | it('should load a GLB mesh', { 19 | var box = GLTF.parseAndLoadGLB(boxData); 20 | 21 | box.meshes.length.should.be(1); 22 | box.meshes[0].primitives.length.should.be(1); 23 | box.meshes[0].primitives[0].attributes.length.should.be(2); 24 | box.meshes[0].primitives[0].indices.should.not.be(null); 25 | 26 | var foundPosition:Bool = false; 27 | var foundNormal:Bool = false; 28 | for(a in box.meshes[0].primitives[0].attributes) { 29 | if(a.name == "POSITION") foundPosition = true; 30 | else if(a.name == "NORMAL") foundNormal = true; 31 | } 32 | foundPosition.should.be(true); 33 | foundNormal.should.be(true); 34 | }); 35 | }); 36 | 37 | describe('Loading GLTFs', { 38 | var boxSrc:String = sys.io.File.getContent('samples/Box.gltf'); 39 | var boxBin:Bytes = sys.io.File.getBytes('samples/Box0.bin'); 40 | var boxRaw:TGLTF = GLTF.parse(boxSrc); 41 | var boxObject:GLTF = GLTF.load(boxRaw, [boxBin]); 42 | 43 | var boxTexturedSrc:String = sys.io.File.getContent('samples/BoxTextured.gltf'); 44 | var boxTexturedBin:Bytes = sys.io.File.getBytes('samples/BoxTextured0.bin'); 45 | var boxTexturedRaw:TGLTF = GLTF.parse(boxTexturedSrc); 46 | var boxTexturedObject:GLTF = GLTF.load(boxTexturedRaw, [boxTexturedBin]); 47 | 48 | var riggedSimpleSrc:String = sys.io.File.getContent('samples/RiggedSimple.gltf'); 49 | var riggedSimpleBin:Bytes = sys.io.File.getBytes('samples/RiggedSimple0.bin'); 50 | var riggedSimpleRaw:TGLTF = GLTF.parse(riggedSimpleSrc); 51 | var riggedSimpleObject:GLTF = GLTF.load(riggedSimpleRaw, [riggedSimpleBin]); 52 | 53 | it("should load an array of buffers", { 54 | boxObject.buffers.length.should.be(1); 55 | boxObject.buffers[0].uri.should.be("Box0.bin"); 56 | boxObject.buffers[0].data.should.be(boxBin); 57 | }); 58 | 59 | it("should load an array of buffer views", { 60 | boxObject.bufferViews.length.should.be(2); 61 | boxObject.bufferViews[0].buffer.should.be(boxObject.buffers[0]); 62 | boxObject.bufferViews[0].byteLength.should.be(72); 63 | }); 64 | 65 | it("should load an array of accessors", { 66 | boxObject.accessors.length.should.be(3); 67 | 68 | boxObject.accessors[0].componentType.should.be(gltf.schema.TComponentType.UNSIGNED_SHORT); 69 | boxObject.accessors[0].type.should.be(gltf.schema.TAttributeType.SCALAR); 70 | 71 | boxObject.accessors[1].componentType.should.be(gltf.schema.TComponentType.FLOAT); 72 | boxObject.accessors[1].type.should.be(gltf.schema.TAttributeType.VEC3); 73 | 74 | boxObject.accessors[2].componentType.should.be(gltf.schema.TComponentType.FLOAT); 75 | boxObject.accessors[2].type.should.be(gltf.schema.TAttributeType.VEC3); 76 | }); 77 | 78 | it("should load an array of cameras", { 79 | // TODO: better model test for cameras 80 | boxObject.cameras.length.should.be(0); 81 | }); 82 | 83 | it("should load an array of meshes", { 84 | boxObject.meshes.length.should.be(1); 85 | boxObject.meshes[0].primitives.length.should.be(1); 86 | boxObject.meshes[0].primitives[0].attributes.length.should.be(2); 87 | boxObject.meshes[0].primitives[0].indices.should.not.be(null); 88 | 89 | var foundPosition:Bool = false; 90 | var foundNormal:Bool = false; 91 | for(a in boxObject.meshes[0].primitives[0].attributes) { 92 | if(a.name == "POSITION") foundPosition = true; 93 | else if(a.name == "NORMAL") foundNormal = true; 94 | } 95 | foundPosition.should.be(true); 96 | foundNormal.should.be(true); 97 | 98 | //trace('indices: ' + boxObject.meshes[0].primitives[0].getIndexValues()); 99 | //trace('positions: ' + boxObject.meshes[0].primitives[0].getFloatAttributeValues("POSITION")); 100 | //trace('normals: ' + boxObject.meshes[0].primitives[0].getFloatAttributeValues("NORMAL")); 101 | }); 102 | 103 | it("should load an array of skins", { 104 | riggedSimpleObject.skins.length.should.be(1); 105 | riggedSimpleObject.skins[0].skeleton.should.not.be(null); 106 | riggedSimpleObject.skins[0].joints.length.should.be(2); 107 | riggedSimpleObject.skins[0].inverseBindMatrices.length.should.be(2); 108 | }); 109 | 110 | it("should load an array of nodes", { 111 | boxObject.nodes.length.should.be(2); 112 | boxObject.nodes[0].children.length.should.be(1); 113 | boxObject.nodes[0].matrix.should.not.be(null); 114 | boxObject.nodes[1].mesh.should.not.be(null); 115 | }); 116 | 117 | it("should load an array of scenes and set the default scene", { 118 | boxObject.scenes.length.should.be(1); 119 | boxObject.scenes[0].nodes.length.should.be(1); 120 | boxObject.scenes[0].nodes[0].should.be(boxObject.nodes[0]); 121 | boxObject.defaultScene.should.be(boxObject.scenes[0]); 122 | }); 123 | 124 | it("should load an array of images", { 125 | boxTexturedObject.images.length.should.be(1); 126 | boxTexturedObject.images[0].uri.should.be("CesiumLogoFlat.png"); 127 | }); 128 | 129 | it("should load an array of samplers", { 130 | boxTexturedObject.samplers.length.should.be(1); 131 | boxTexturedObject.samplers[0].magFilter.should.be(gltf.schema.TMagFilter.LINEAR); 132 | }); 133 | 134 | it("should load an array of textures", { 135 | boxTexturedObject.textures.length.should.be(1); 136 | boxTexturedObject.textures[0].image.should.be(boxTexturedObject.images[0]); 137 | boxTexturedObject.textures[0].sampler.should.be(boxTexturedObject.samplers[0]); 138 | }); 139 | 140 | it('should load all nodes', { 141 | riggedSimpleObject.nodes.length.should.be(5); 142 | }); 143 | 144 | it('should load the skins appropriately', { 145 | riggedSimpleObject.nodes[1].skin.should.be(riggedSimpleObject.skins[0]); 146 | }); 147 | 148 | it("should load animations"); 149 | }); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /test/gltf/TestParsing.hx: -------------------------------------------------------------------------------- 1 | package gltf; 2 | 3 | import gltf.schema.TGLTF; 4 | import buddy.*; 5 | using buddy.Should; 6 | 7 | class TestParsing extends BuddySuite { 8 | public function new() { 9 | describe('Parsing GLTF', { 10 | var boxSrc:String = sys.io.File.getContent('samples/Box.gltf'); 11 | var riggedSimpleSrc:String = sys.io.File.getContent('samples/RiggedSimple.gltf'); 12 | var riggedSimpleRaw:TGLTF = GLTF.parse(riggedSimpleSrc); 13 | 14 | it("should parse gltf files", { 15 | var raw:TGLTF = GLTF.parse(boxSrc); 16 | 17 | raw.asset.generator.should.be("COLLADA2GLTF"); 18 | raw.asset.version.should.be("2.0"); 19 | 20 | raw.scene.should.be(0); 21 | raw.scenes.length.should.be(1); 22 | raw.scenes[0].nodes.length.should.be(1); 23 | raw.scenes[0].nodes[0].should.be(0); 24 | 25 | raw.nodes.length.should.be(2); 26 | raw.nodes[0].children.length.should.be(1); 27 | raw.nodes[1].children.should.be(null); 28 | }); 29 | 30 | it('should parse all nodes', { 31 | riggedSimpleRaw.nodes.length.should.be(5); 32 | }); 33 | 34 | it('should parse children arrays', { 35 | riggedSimpleRaw.nodes[0].children.should.not.be(null); 36 | riggedSimpleRaw.nodes[0].children.length.should.be(2); 37 | riggedSimpleRaw.nodes[0].children[0].should.be(4); 38 | riggedSimpleRaw.nodes[0].children[1].should.be(1); 39 | riggedSimpleRaw.nodes[4].children.should.not.be(null); 40 | if(riggedSimpleRaw.nodes[4].children != null) { 41 | riggedSimpleRaw.nodes[4].children.length.should.be(1); 42 | riggedSimpleRaw.nodes[4].children[0].should.be(2); 43 | } 44 | riggedSimpleRaw.nodes[1].children.should.be(null); 45 | }); 46 | 47 | it('should parse matrices', { 48 | riggedSimpleRaw.nodes[0].matrix.length.should.be(16); 49 | riggedSimpleRaw.nodes[0].matrix[6].should.be(-1.0); 50 | }); 51 | 52 | it('should parse mesh and skin', { 53 | if(riggedSimpleRaw.nodes[0].mesh != null) fail('node 0 mesh is not null'); 54 | if(riggedSimpleRaw.nodes[0].skin != null) fail('node 0 skin is not null'); 55 | 56 | riggedSimpleRaw.nodes[1].mesh.should.be(0); 57 | riggedSimpleRaw.nodes[1].skin.should.be(0); 58 | }); 59 | 60 | it('should auto-supply matrix and transform components', { 61 | riggedSimpleRaw.nodes[0].translation.should.not.be(null); 62 | riggedSimpleRaw.nodes[1].matrix.should.not.be(null); 63 | }); 64 | 65 | it('should load the animations', { 66 | riggedSimpleRaw.animations.should.not.be(null); 67 | riggedSimpleRaw.animations.length.should.be(1); 68 | }); 69 | 70 | it('should load the animation channels', { 71 | riggedSimpleRaw.animations[0].channels.should.not.be(null); 72 | riggedSimpleRaw.animations[0].channels.length.should.be(6); 73 | 74 | riggedSimpleRaw.animations[0].channels[0].should.not.be(null); 75 | riggedSimpleRaw.animations[0].channels[1].should.not.be(null); 76 | riggedSimpleRaw.animations[0].channels[2].should.not.be(null); 77 | riggedSimpleRaw.animations[0].channels[3].should.not.be(null); 78 | riggedSimpleRaw.animations[0].channels[4].should.not.be(null); 79 | riggedSimpleRaw.animations[0].channels[5].should.not.be(null); 80 | 81 | riggedSimpleRaw.animations[0].channels[5].sampler.should.be(5); 82 | riggedSimpleRaw.animations[0].channels[5].target.node.should.be(3); 83 | riggedSimpleRaw.animations[0].channels[5].target.path.should.be(gltf.schema.TAnimationChannelTargetPath.SCALE); 84 | }); 85 | 86 | it('should load the animation samplers', { 87 | riggedSimpleRaw.animations[0].samplers.should.not.be(null); 88 | riggedSimpleRaw.animations[0].samplers.length.should.be(6); 89 | 90 | riggedSimpleRaw.animations[0].samplers[0].should.not.be(null); 91 | riggedSimpleRaw.animations[0].samplers[1].should.not.be(null); 92 | riggedSimpleRaw.animations[0].samplers[2].should.not.be(null); 93 | riggedSimpleRaw.animations[0].samplers[3].should.not.be(null); 94 | riggedSimpleRaw.animations[0].samplers[4].should.not.be(null); 95 | riggedSimpleRaw.animations[0].samplers[5].should.not.be(null); 96 | }); 97 | 98 | it("should parse glb files"); 99 | }); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /test/test.cpp.hxml: -------------------------------------------------------------------------------- 1 | test.each.hxml 2 | -cpp bin 3 | -cmd bin/TestMain-debug 4 | -D HXCPP_M64 5 | -------------------------------------------------------------------------------- /test/test.each.hxml: -------------------------------------------------------------------------------- 1 | -lib buddy 2 | -cp ../src 3 | -D testing 4 | -debug 5 | -main TestMain 6 | -------------------------------------------------------------------------------- /test/test.interp.hxml: -------------------------------------------------------------------------------- 1 | test.each.hxml 2 | --interp 3 | -------------------------------------------------------------------------------- /test/test.java.hxml: -------------------------------------------------------------------------------- 1 | test.each.hxml 2 | -java bin 3 | -cmd java -jar bin/TestMain-Debug.jar 4 | -------------------------------------------------------------------------------- /test/test.node.hxml: -------------------------------------------------------------------------------- 1 | test.each.hxml 2 | #-D nodejs 3 | -lib hxnodejs 4 | -js bin/TestMain.node.js 5 | -cmd node bin/TestMain.node.js 6 | --------------------------------------------------------------------------------