/src/assimp/code/AssetLib/glTF2/glTF2Asset.inl
Line | Count | Source |
1 | | /* |
2 | | Open Asset Import Library (assimp) |
3 | | ---------------------------------------------------------------------- |
4 | | |
5 | | Copyright (c) 2006-2026, assimp team |
6 | | |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use of this software in source and binary forms, |
10 | | with or without modification, are permitted provided that the |
11 | | following conditions are met: |
12 | | |
13 | | * Redistributions of source code must retain the above |
14 | | copyright notice, this list of conditions and the |
15 | | following disclaimer. |
16 | | |
17 | | * Redistributions in binary form must reproduce the above |
18 | | copyright notice, this list of conditions and the |
19 | | following disclaimer in the documentation and/or other |
20 | | materials provided with the distribution. |
21 | | |
22 | | * Neither the name of the assimp team, nor the names of its |
23 | | contributors may be used to endorse or promote products |
24 | | derived from this software without specific prior |
25 | | written permission of the assimp team. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | | |
39 | | ---------------------------------------------------------------------- |
40 | | */ |
41 | | |
42 | | #include "AssetLib/glTFCommon/glTFCommon.h" |
43 | | |
44 | | #include <assimp/MemoryIOWrapper.h> |
45 | | #include <assimp/StringUtils.h> |
46 | | #include <assimp/DefaultLogger.hpp> |
47 | | #include <assimp/Base64.hpp> |
48 | | #include <rapidjson/document.h> |
49 | | #include <rapidjson/schema.h> |
50 | | #include <rapidjson/stringbuffer.h> |
51 | | |
52 | | // clang-format off |
53 | | #ifdef ASSIMP_ENABLE_DRACO |
54 | | |
55 | | // Google draco library headers spew many warnings. Bad Google, no cookie |
56 | | # if _MSC_VER |
57 | | # pragma warning(push) |
58 | | # pragma warning(disable : 4018) // Signed/unsigned mismatch |
59 | | # pragma warning(disable : 4804) // Unsafe use of type 'bool' |
60 | | # elif defined(__clang__) |
61 | | # pragma clang diagnostic push |
62 | | # pragma clang diagnostic ignored "-Wsign-compare" |
63 | | # elif defined(__GNUC__) |
64 | | # pragma GCC diagnostic push |
65 | | # if (__GNUC__ > 4) |
66 | | # pragma GCC diagnostic ignored "-Wbool-compare" |
67 | | # endif |
68 | | # pragma GCC diagnostic ignored "-Wsign-compare" |
69 | | #endif |
70 | | |
71 | | #include "draco/compression/decode.h" |
72 | | #include "draco/core/decoder_buffer.h" |
73 | | |
74 | | #if _MSC_VER |
75 | | # pragma warning(pop) |
76 | | #elif defined(__clang__) |
77 | | # pragma clang diagnostic pop |
78 | | #elif defined(__GNUC__) |
79 | | # pragma GCC diagnostic pop |
80 | | #endif |
81 | | #ifndef DRACO_MESH_COMPRESSION_SUPPORTED |
82 | | # error glTF: KHR_draco_mesh_compression: draco library must have DRACO_MESH_COMPRESSION_SUPPORTED |
83 | | #endif |
84 | | #endif |
85 | | // clang-format on |
86 | | |
87 | | using namespace Assimp; |
88 | | |
89 | | namespace glTF2 { |
90 | | |
91 | | using glTFCommon::FindStringInContext; |
92 | | using glTFCommon::FindNumberInContext; |
93 | | using glTFCommon::FindUIntInContext; |
94 | | using glTFCommon::FindArrayInContext; |
95 | | using glTFCommon::FindObjectInContext; |
96 | | using glTFCommon::FindExtensionInContext; |
97 | | using glTFCommon::MemberOrDefault; |
98 | | using glTFCommon::ReadMember; |
99 | | using glTFCommon::FindMember; |
100 | | using glTFCommon::FindObject; |
101 | | using glTFCommon::FindUInt; |
102 | | using glTFCommon::FindArray; |
103 | | using glTFCommon::FindArray; |
104 | | |
105 | | namespace { |
106 | | |
107 | | // |
108 | | // JSON Value reading helpers |
109 | | // |
110 | 50.8k | inline CustomExtension ReadExtensions(const char *name, Value &obj) { |
111 | 50.8k | CustomExtension ret; |
112 | 50.8k | ret.name = name; |
113 | 50.8k | if (obj.IsObject()) { |
114 | 26 | ret.mValues.isPresent = true; |
115 | 130 | for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { |
116 | 104 | auto &val = it->value; |
117 | 104 | ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val)); |
118 | 104 | } |
119 | 50.8k | } else if (obj.IsArray()) { |
120 | 37 | ret.mValues.value.reserve(obj.Size()); |
121 | 37 | ret.mValues.isPresent = true; |
122 | 215 | for (unsigned int i = 0; i < obj.Size(); ++i) { |
123 | 178 | ret.mValues.value.push_back(ReadExtensions(name, obj[i])); |
124 | 178 | } |
125 | 50.7k | } else if (obj.IsNumber()) { |
126 | 25.5k | if (obj.IsUint64()) { |
127 | 25.4k | ret.mUint64Value.value = obj.GetUint64(); |
128 | 25.4k | ret.mUint64Value.isPresent = true; |
129 | 25.4k | } else if (obj.IsInt64()) { |
130 | 17 | ret.mInt64Value.value = obj.GetInt64(); |
131 | 17 | ret.mInt64Value.isPresent = true; |
132 | 128 | } else if (obj.IsDouble()) { |
133 | 128 | ret.mDoubleValue.value = obj.GetDouble(); |
134 | 128 | ret.mDoubleValue.isPresent = true; |
135 | 128 | } |
136 | 25.5k | } else if (obj.IsString()) { |
137 | 12.6k | ReadValue(obj, ret.mStringValue); |
138 | 12.6k | ret.mStringValue.isPresent = true; |
139 | 12.6k | } else if (obj.IsBool()) { |
140 | 12.5k | ret.mBoolValue.value = obj.GetBool(); |
141 | 12.5k | ret.mBoolValue.isPresent = true; |
142 | 12.5k | } |
143 | 50.8k | return ret; |
144 | 50.8k | } Unexecuted instantiation: ImporterRegistry.cpp:glTF2::(anonymous namespace)::ReadExtensions(char const*, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&) glTF2Importer.cpp:glTF2::(anonymous namespace)::ReadExtensions(char const*, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&) Line | Count | Source | 110 | 50.8k | inline CustomExtension ReadExtensions(const char *name, Value &obj) { | 111 | 50.8k | CustomExtension ret; | 112 | 50.8k | ret.name = name; | 113 | 50.8k | if (obj.IsObject()) { | 114 | 26 | ret.mValues.isPresent = true; | 115 | 130 | for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { | 116 | 104 | auto &val = it->value; | 117 | 104 | ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val)); | 118 | 104 | } | 119 | 50.8k | } else if (obj.IsArray()) { | 120 | 37 | ret.mValues.value.reserve(obj.Size()); | 121 | 37 | ret.mValues.isPresent = true; | 122 | 215 | for (unsigned int i = 0; i < obj.Size(); ++i) { | 123 | 178 | ret.mValues.value.push_back(ReadExtensions(name, obj[i])); | 124 | 178 | } | 125 | 50.7k | } else if (obj.IsNumber()) { | 126 | 25.5k | if (obj.IsUint64()) { | 127 | 25.4k | ret.mUint64Value.value = obj.GetUint64(); | 128 | 25.4k | ret.mUint64Value.isPresent = true; | 129 | 25.4k | } else if (obj.IsInt64()) { | 130 | 17 | ret.mInt64Value.value = obj.GetInt64(); | 131 | 17 | ret.mInt64Value.isPresent = true; | 132 | 128 | } else if (obj.IsDouble()) { | 133 | 128 | ret.mDoubleValue.value = obj.GetDouble(); | 134 | 128 | ret.mDoubleValue.isPresent = true; | 135 | 128 | } | 136 | 25.5k | } else if (obj.IsString()) { | 137 | 12.6k | ReadValue(obj, ret.mStringValue); | 138 | 12.6k | ret.mStringValue.isPresent = true; | 139 | 12.6k | } else if (obj.IsBool()) { | 140 | 12.5k | ret.mBoolValue.value = obj.GetBool(); | 141 | 12.5k | ret.mBoolValue.isPresent = true; | 142 | 12.5k | } | 143 | 50.8k | return ret; | 144 | 50.8k | } |
Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::ReadExtensions(char const*, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&) |
145 | | |
146 | 12.6k | inline Extras ReadExtras(Value &obj) { |
147 | 12.6k | Extras ret; |
148 | | |
149 | 12.6k | ret.mValues.reserve(obj.MemberCount()); |
150 | 63.2k | for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { |
151 | 50.5k | auto &val = it->value; |
152 | 50.5k | ret.mValues.emplace_back(ReadExtensions(it->name.GetString(), val)); |
153 | 50.5k | } |
154 | | |
155 | 12.6k | return ret; |
156 | 12.6k | } Unexecuted instantiation: ImporterRegistry.cpp:glTF2::(anonymous namespace)::ReadExtras(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&) glTF2Importer.cpp:glTF2::(anonymous namespace)::ReadExtras(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&) Line | Count | Source | 146 | 12.6k | inline Extras ReadExtras(Value &obj) { | 147 | 12.6k | Extras ret; | 148 | | | 149 | 12.6k | ret.mValues.reserve(obj.MemberCount()); | 150 | 63.2k | for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { | 151 | 50.5k | auto &val = it->value; | 152 | 50.5k | ret.mValues.emplace_back(ReadExtensions(it->name.GetString(), val)); | 153 | 50.5k | } | 154 | | | 155 | 12.6k | return ret; | 156 | 12.6k | } |
Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::ReadExtras(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&) |
157 | | |
158 | | inline void CopyData(size_t count, const uint8_t *src, size_t src_stride, |
159 | 0 | uint8_t *dst, size_t dst_stride) { |
160 | 0 | if (src_stride == dst_stride) { |
161 | 0 | memcpy(dst, src, count * src_stride); |
162 | 0 | return; |
163 | 0 | } |
164 | | |
165 | 0 | size_t sz = std::min(src_stride, dst_stride); |
166 | 0 | for (size_t i = 0; i < count; ++i) { |
167 | 0 | memcpy(dst, src, sz); |
168 | 0 | if (sz < dst_stride) { |
169 | 0 | memset(dst + sz, 0, dst_stride - sz); |
170 | 0 | } |
171 | 0 | src += src_stride; |
172 | 0 | dst += dst_stride; |
173 | 0 | } |
174 | 0 | } Unexecuted instantiation: ImporterRegistry.cpp:glTF2::(anonymous namespace)::CopyData(unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long) Unexecuted instantiation: glTF2Importer.cpp:glTF2::(anonymous namespace)::CopyData(unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long) Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::CopyData(unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long) |
175 | | |
176 | 22.8k | void SetVector(vec4 &v, const float (&in)[4]) { |
177 | 22.8k | v[0] = in[0]; |
178 | 22.8k | v[1] = in[1]; |
179 | 22.8k | v[2] = in[2]; |
180 | 22.8k | v[3] = in[3]; |
181 | 22.8k | } Unexecuted instantiation: ImporterRegistry.cpp:glTF2::(anonymous namespace)::SetVector(float (&) [4], float const (&) [4]) glTF2Importer.cpp:glTF2::(anonymous namespace)::SetVector(float (&) [4], float const (&) [4]) Line | Count | Source | 176 | 22.8k | void SetVector(vec4 &v, const float (&in)[4]) { | 177 | 22.8k | v[0] = in[0]; | 178 | 22.8k | v[1] = in[1]; | 179 | 22.8k | v[2] = in[2]; | 180 | 22.8k | v[3] = in[3]; | 181 | 22.8k | } |
glTF2Exporter.cpp:glTF2::(anonymous namespace)::SetVector(float (&) [4], float const (&) [4]) Line | Count | Source | 176 | 12 | void SetVector(vec4 &v, const float (&in)[4]) { | 177 | 12 | v[0] = in[0]; | 178 | 12 | v[1] = in[1]; | 179 | 12 | v[2] = in[2]; | 180 | 12 | v[3] = in[3]; | 181 | 12 | } |
|
182 | | |
183 | 50.0k | void SetVector(vec3 &v, const float (&in)[3]) { |
184 | 50.0k | v[0] = in[0]; |
185 | 50.0k | v[1] = in[1]; |
186 | 50.0k | v[2] = in[2]; |
187 | 50.0k | } Unexecuted instantiation: ImporterRegistry.cpp:glTF2::(anonymous namespace)::SetVector(float (&) [3], float const (&) [3]) glTF2Importer.cpp:glTF2::(anonymous namespace)::SetVector(float (&) [3], float const (&) [3]) Line | Count | Source | 183 | 50.0k | void SetVector(vec3 &v, const float (&in)[3]) { | 184 | 50.0k | v[0] = in[0]; | 185 | 50.0k | v[1] = in[1]; | 186 | 50.0k | v[2] = in[2]; | 187 | 50.0k | } |
glTF2Exporter.cpp:glTF2::(anonymous namespace)::SetVector(float (&) [3], float const (&) [3]) Line | Count | Source | 183 | 30 | void SetVector(vec3 &v, const float (&in)[3]) { | 184 | 30 | v[0] = in[0]; | 185 | 30 | v[1] = in[1]; | 186 | 30 | v[2] = in[2]; | 187 | 30 | } |
|
188 | | |
189 | | template <int N> |
190 | 56.7k | inline int Compare(const char *attr, const char (&str)[N]) { |
191 | 56.7k | return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; |
192 | 56.7k | } Unexecuted instantiation: ImporterRegistry.cpp:int glTF2::(anonymous namespace)::Compare<9>(char const*, char const (&) [9]) Unexecuted instantiation: ImporterRegistry.cpp:int glTF2::(anonymous namespace)::Compare<7>(char const*, char const (&) [7]) Unexecuted instantiation: ImporterRegistry.cpp:int glTF2::(anonymous namespace)::Compare<8>(char const*, char const (&) [8]) Unexecuted instantiation: ImporterRegistry.cpp:int glTF2::(anonymous namespace)::Compare<6>(char const*, char const (&) [6]) Unexecuted instantiation: ImporterRegistry.cpp:int glTF2::(anonymous namespace)::Compare<12>(char const*, char const (&) [12]) glTF2Importer.cpp:int glTF2::(anonymous namespace)::Compare<9>(char const*, char const (&) [9]) Line | Count | Source | 190 | 23.4k | inline int Compare(const char *attr, const char (&str)[N]) { | 191 | 23.4k | return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; | 192 | 23.4k | } |
glTF2Importer.cpp:int glTF2::(anonymous namespace)::Compare<7>(char const*, char const (&) [7]) Line | Count | Source | 190 | 15.9k | inline int Compare(const char *attr, const char (&str)[N]) { | 191 | 15.9k | return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; | 192 | 15.9k | } |
glTF2Importer.cpp:int glTF2::(anonymous namespace)::Compare<8>(char const*, char const (&) [8]) Line | Count | Source | 190 | 9.32k | inline int Compare(const char *attr, const char (&str)[N]) { | 191 | 9.32k | return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; | 192 | 9.32k | } |
glTF2Importer.cpp:int glTF2::(anonymous namespace)::Compare<6>(char const*, char const (&) [6]) Line | Count | Source | 190 | 5.24k | inline int Compare(const char *attr, const char (&str)[N]) { | 191 | 5.24k | return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; | 192 | 5.24k | } |
glTF2Importer.cpp:int glTF2::(anonymous namespace)::Compare<12>(char const*, char const (&) [12]) Line | Count | Source | 190 | 2.75k | inline int Compare(const char *attr, const char (&str)[N]) { | 191 | 2.75k | return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; | 192 | 2.75k | } |
Unexecuted instantiation: glTF2Exporter.cpp:int glTF2::(anonymous namespace)::Compare<9>(char const*, char const (&) [9]) Unexecuted instantiation: glTF2Exporter.cpp:int glTF2::(anonymous namespace)::Compare<7>(char const*, char const (&) [7]) Unexecuted instantiation: glTF2Exporter.cpp:int glTF2::(anonymous namespace)::Compare<8>(char const*, char const (&) [8]) Unexecuted instantiation: glTF2Exporter.cpp:int glTF2::(anonymous namespace)::Compare<6>(char const*, char const (&) [6]) Unexecuted instantiation: glTF2Exporter.cpp:int glTF2::(anonymous namespace)::Compare<12>(char const*, char const (&) [12]) |
193 | | |
194 | | #if _MSC_VER |
195 | | #pragma warning(push) |
196 | | #pragma warning(disable : 4706) |
197 | | #endif // _MSC_VER |
198 | | |
199 | 16.9k | inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) { |
200 | 16.9k | if ((pos = Compare(attr, "POSITION"))) { |
201 | 5.61k | v = &(p.attributes.position); |
202 | 11.3k | } else if ((pos = Compare(attr, "NORMAL"))) { |
203 | 4.78k | v = &(p.attributes.normal); |
204 | 6.53k | } else if ((pos = Compare(attr, "TANGENT"))) { |
205 | 58 | v = &(p.attributes.tangent); |
206 | 6.48k | } else if ((pos = Compare(attr, "TEXCOORD"))) { |
207 | 1.23k | v = &(p.attributes.texcoord); |
208 | 5.24k | } else if ((pos = Compare(attr, "COLOR"))) { |
209 | 606 | v = &(p.attributes.color); |
210 | 4.63k | } else if ((pos = Compare(attr, "JOINTS"))) { |
211 | 1.88k | v = &(p.attributes.joint); |
212 | 2.75k | } else if ((pos = Compare(attr, "JOINTMATRIX"))) { |
213 | 1 | v = &(p.attributes.jointmatrix); |
214 | 2.75k | } else if ((pos = Compare(attr, "WEIGHTS"))) { |
215 | 1.79k | v = &(p.attributes.weight); |
216 | 1.79k | } else |
217 | 954 | return false; |
218 | 15.9k | return true; |
219 | 16.9k | } Unexecuted instantiation: ImporterRegistry.cpp:glTF2::(anonymous namespace)::GetAttribVector(glTF2::Mesh::Primitive&, char const*, std::__1::vector<glTFCommon::Ref<glTF2::Accessor>, std::__1::allocator<glTFCommon::Ref<glTF2::Accessor> > >*&, int&) glTF2Importer.cpp:glTF2::(anonymous namespace)::GetAttribVector(glTF2::Mesh::Primitive&, char const*, std::__1::vector<glTFCommon::Ref<glTF2::Accessor>, std::__1::allocator<glTFCommon::Ref<glTF2::Accessor> > >*&, int&) Line | Count | Source | 199 | 16.9k | inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) { | 200 | 16.9k | if ((pos = Compare(attr, "POSITION"))) { | 201 | 5.61k | v = &(p.attributes.position); | 202 | 11.3k | } else if ((pos = Compare(attr, "NORMAL"))) { | 203 | 4.78k | v = &(p.attributes.normal); | 204 | 6.53k | } else if ((pos = Compare(attr, "TANGENT"))) { | 205 | 58 | v = &(p.attributes.tangent); | 206 | 6.48k | } else if ((pos = Compare(attr, "TEXCOORD"))) { | 207 | 1.23k | v = &(p.attributes.texcoord); | 208 | 5.24k | } else if ((pos = Compare(attr, "COLOR"))) { | 209 | 606 | v = &(p.attributes.color); | 210 | 4.63k | } else if ((pos = Compare(attr, "JOINTS"))) { | 211 | 1.88k | v = &(p.attributes.joint); | 212 | 2.75k | } else if ((pos = Compare(attr, "JOINTMATRIX"))) { | 213 | 1 | v = &(p.attributes.jointmatrix); | 214 | 2.75k | } else if ((pos = Compare(attr, "WEIGHTS"))) { | 215 | 1.79k | v = &(p.attributes.weight); | 216 | 1.79k | } else | 217 | 954 | return false; | 218 | 15.9k | return true; | 219 | 16.9k | } |
Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::GetAttribVector(glTF2::Mesh::Primitive&, char const*, std::__1::vector<glTFCommon::Ref<glTF2::Accessor>, std::__1::allocator<glTFCommon::Ref<glTF2::Accessor> > >*&, int&) |
220 | | |
221 | 44 | inline bool GetAttribTargetVector(Mesh::Primitive &p, const int targetIndex, const char *attr, Mesh::AccessorList *&v, int &pos) { |
222 | 44 | if ((pos = Compare(attr, "POSITION"))) { |
223 | 8 | v = &(p.targets[targetIndex].position); |
224 | 36 | } else if ((pos = Compare(attr, "NORMAL"))) { |
225 | 4 | v = &(p.targets[targetIndex].normal); |
226 | 32 | } else if ((pos = Compare(attr, "TANGENT"))) { |
227 | 8 | v = &(p.targets[targetIndex].tangent); |
228 | 8 | } else |
229 | 24 | return false; |
230 | 20 | return true; |
231 | 44 | } Unexecuted instantiation: ImporterRegistry.cpp:glTF2::(anonymous namespace)::GetAttribTargetVector(glTF2::Mesh::Primitive&, int, char const*, std::__1::vector<glTFCommon::Ref<glTF2::Accessor>, std::__1::allocator<glTFCommon::Ref<glTF2::Accessor> > >*&, int&) glTF2Importer.cpp:glTF2::(anonymous namespace)::GetAttribTargetVector(glTF2::Mesh::Primitive&, int, char const*, std::__1::vector<glTFCommon::Ref<glTF2::Accessor>, std::__1::allocator<glTFCommon::Ref<glTF2::Accessor> > >*&, int&) Line | Count | Source | 221 | 44 | inline bool GetAttribTargetVector(Mesh::Primitive &p, const int targetIndex, const char *attr, Mesh::AccessorList *&v, int &pos) { | 222 | 44 | if ((pos = Compare(attr, "POSITION"))) { | 223 | 8 | v = &(p.targets[targetIndex].position); | 224 | 36 | } else if ((pos = Compare(attr, "NORMAL"))) { | 225 | 4 | v = &(p.targets[targetIndex].normal); | 226 | 32 | } else if ((pos = Compare(attr, "TANGENT"))) { | 227 | 8 | v = &(p.targets[targetIndex].tangent); | 228 | 8 | } else | 229 | 24 | return false; | 230 | 20 | return true; | 231 | 44 | } |
Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::GetAttribTargetVector(glTF2::Mesh::Primitive&, int, char const*, std::__1::vector<glTFCommon::Ref<glTF2::Accessor>, std::__1::allocator<glTFCommon::Ref<glTF2::Accessor> > >*&, int&) |
232 | | |
233 | | } // namespace |
234 | | |
235 | 7.76k | inline Value *Object::FindString(Value &val, const char *memberId) { |
236 | 7.76k | return FindStringInContext(val, memberId, id.c_str(), name.c_str()); |
237 | 7.76k | } |
238 | | |
239 | 0 | inline Value *Object::FindNumber(Value &val, const char *memberId) { |
240 | 0 | return FindNumberInContext(val, memberId, id.c_str(), name.c_str()); |
241 | 0 | } |
242 | | |
243 | 153k | inline Value *Object::FindUInt(Value &val, const char *memberId) { |
244 | 153k | return FindUIntInContext(val, memberId, id.c_str(), name.c_str()); |
245 | 153k | } |
246 | | |
247 | 81.7k | inline Value *Object::FindArray(Value &val, const char *memberId) { |
248 | 81.7k | return FindArrayInContext(val, memberId, id.c_str(), name.c_str()); |
249 | 81.7k | } |
250 | | |
251 | 236k | inline Value *Object::FindObject(Value &val, const char *memberId) { |
252 | 236k | return FindObjectInContext(val, memberId, id.c_str(), name.c_str()); |
253 | 236k | } |
254 | | |
255 | 4 | inline Value *Object::FindExtension(Value &val, const char *extensionId) { |
256 | 4 | return FindExtensionInContext(val, extensionId, id.c_str(), name.c_str()); |
257 | 4 | } |
258 | | |
259 | 81.3k | inline void Object::ReadExtensions(Value &val) { |
260 | 81.3k | if (Value *curExtensions = FindObject(val, "extensions")) { |
261 | 0 | this->customExtensions = glTF2::ReadExtensions("extensions", *curExtensions); |
262 | 0 | } |
263 | 81.3k | } |
264 | | |
265 | 81.3k | inline void Object::ReadExtras(Value &val) { |
266 | 81.3k | if (Value *curExtras = FindObject(val, "extras")) { |
267 | 12.6k | this->extras = glTF2::ReadExtras(*curExtras); |
268 | 12.6k | } |
269 | 81.3k | } |
270 | | |
271 | | #ifdef ASSIMP_ENABLE_DRACO |
272 | | |
273 | | template <typename T> |
274 | | inline void CopyFaceIndex_Draco(Buffer &decodedIndexBuffer, const draco::Mesh &draco_mesh) { |
275 | | const size_t faceStride = sizeof(T) * 3; |
276 | | for (draco::FaceIndex f(0); f < draco_mesh.num_faces(); ++f) { |
277 | | const draco::Mesh::Face &face = draco_mesh.face(f); |
278 | | T indices[3] = { static_cast<T>(face[0].value()), static_cast<T>(face[1].value()), static_cast<T>(face[2].value()) }; |
279 | | memcpy(decodedIndexBuffer.GetPointer() + (f.value() * faceStride), &indices[0], faceStride); |
280 | | } |
281 | | } |
282 | | |
283 | | inline void SetDecodedIndexBuffer_Draco(const draco::Mesh &dracoMesh, Mesh::Primitive &prim) { |
284 | | if (!prim.indices || dracoMesh.num_faces() == 0) |
285 | | return; |
286 | | |
287 | | // Create a decoded Index buffer (if there is one) |
288 | | size_t componentBytes = prim.indices->GetBytesPerComponent(); |
289 | | |
290 | | std::unique_ptr<Buffer> decodedIndexBuffer(new Buffer()); |
291 | | decodedIndexBuffer->Grow(dracoMesh.num_faces() * 3 * componentBytes); |
292 | | |
293 | | // If accessor uses the same size as draco implementation, copy the draco buffer directly |
294 | | |
295 | | // Usually uint32_t but shouldn't assume |
296 | | if (sizeof(dracoMesh.face(draco::FaceIndex(0))[0]) == componentBytes) { |
297 | | memcpy(decodedIndexBuffer->GetPointer(), &dracoMesh.face(draco::FaceIndex(0))[0], decodedIndexBuffer->byteLength); |
298 | | // Assign this alternate data buffer to the accessor |
299 | | prim.indices->decodedBuffer.swap(decodedIndexBuffer); |
300 | | return; |
301 | | } |
302 | | |
303 | | // Not same size, convert |
304 | | switch (componentBytes) { |
305 | | case sizeof(uint32_t): |
306 | | CopyFaceIndex_Draco<uint32_t>(*decodedIndexBuffer, dracoMesh); |
307 | | break; |
308 | | case sizeof(uint16_t): |
309 | | CopyFaceIndex_Draco<uint16_t>(*decodedIndexBuffer, dracoMesh); |
310 | | break; |
311 | | case sizeof(uint8_t): |
312 | | CopyFaceIndex_Draco<uint8_t>(*decodedIndexBuffer, dracoMesh); |
313 | | break; |
314 | | default: |
315 | | ai_assert(false); |
316 | | break; |
317 | | } |
318 | | |
319 | | // Assign this alternate data buffer to the accessor |
320 | | prim.indices->decodedBuffer.swap(decodedIndexBuffer); |
321 | | } |
322 | | |
323 | | template <typename T> |
324 | | static bool GetAttributeForAllPoints_Draco(const draco::Mesh &dracoMesh, |
325 | | const draco::PointAttribute &dracoAttribute, |
326 | | Buffer &outBuffer) { |
327 | | size_t byteOffset = 0; |
328 | | T values[4] = { 0, 0, 0, 0 }; |
329 | | for (draco::PointIndex i(0); i < dracoMesh.num_points(); ++i) { |
330 | | const draco::AttributeValueIndex val_index = dracoAttribute.mapped_index(i); |
331 | | if (!dracoAttribute.ConvertValue<T>(val_index, dracoAttribute.num_components(), values)) { |
332 | | return false; |
333 | | } |
334 | | |
335 | | memcpy(outBuffer.GetPointer() + byteOffset, &values[0], sizeof(T) * dracoAttribute.num_components()); |
336 | | byteOffset += sizeof(T) * dracoAttribute.num_components(); |
337 | | } |
338 | | |
339 | | return true; |
340 | | } |
341 | | |
342 | | inline void SetDecodedAttributeBuffer_Draco(const draco::Mesh &dracoMesh, uint32_t dracoAttribId, Accessor &accessor) { |
343 | | // Create decoded buffer |
344 | | const draco::PointAttribute *pDracoAttribute = dracoMesh.GetAttributeByUniqueId(dracoAttribId); |
345 | | if (pDracoAttribute == nullptr) { |
346 | | throw DeadlyImportError("GLTF: Invalid draco attribute id: ", dracoAttribId); |
347 | | } |
348 | | |
349 | | size_t componentBytes = accessor.GetBytesPerComponent(); |
350 | | |
351 | | std::unique_ptr<Buffer> decodedAttribBuffer(new Buffer()); |
352 | | decodedAttribBuffer->Grow(dracoMesh.num_points() * pDracoAttribute->num_components() * componentBytes); |
353 | | |
354 | | switch (accessor.componentType) { |
355 | | case ComponentType_BYTE: |
356 | | GetAttributeForAllPoints_Draco<int8_t>(dracoMesh, *pDracoAttribute, *decodedAttribBuffer); |
357 | | break; |
358 | | case ComponentType_UNSIGNED_BYTE: |
359 | | GetAttributeForAllPoints_Draco<uint8_t>(dracoMesh, *pDracoAttribute, *decodedAttribBuffer); |
360 | | break; |
361 | | case ComponentType_SHORT: |
362 | | GetAttributeForAllPoints_Draco<int16_t>(dracoMesh, *pDracoAttribute, *decodedAttribBuffer); |
363 | | break; |
364 | | case ComponentType_UNSIGNED_SHORT: |
365 | | GetAttributeForAllPoints_Draco<uint16_t>(dracoMesh, *pDracoAttribute, *decodedAttribBuffer); |
366 | | break; |
367 | | case ComponentType_UNSIGNED_INT: |
368 | | GetAttributeForAllPoints_Draco<uint32_t>(dracoMesh, *pDracoAttribute, *decodedAttribBuffer); |
369 | | break; |
370 | | case ComponentType_FLOAT: |
371 | | GetAttributeForAllPoints_Draco<float>(dracoMesh, *pDracoAttribute, *decodedAttribBuffer); |
372 | | break; |
373 | | default: |
374 | | ai_assert(false); |
375 | | break; |
376 | | } |
377 | | |
378 | | // Assign this alternate data buffer to the accessor |
379 | | accessor.decodedBuffer.swap(decodedAttribBuffer); |
380 | | } |
381 | | |
382 | | #endif // ASSIMP_ENABLE_DRACO |
383 | | |
384 | | // |
385 | | // LazyDict methods |
386 | | // |
387 | | |
388 | | template <class T> |
389 | | inline LazyDict<T>::LazyDict(Asset &asset, const char *dictId, const char *extId) : |
390 | 224k | mDictId(dictId), |
391 | 224k | mExtId(extId), |
392 | 224k | mDict(nullptr), |
393 | 224k | mAsset(asset) { |
394 | 224k | asset.mDicts.push_back(this); // register to the list of dictionaries |
395 | 224k | } glTF2::LazyDict<glTF2::Accessor>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Animation>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Buffer>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::BufferView>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Camera>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Light>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Image>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Material>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Mesh>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Node>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Sampler>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Scene>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Skin>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
glTF2::LazyDict<glTF2::Texture>::LazyDict(glTF2::Asset&, char const*, char const*) Line | Count | Source | 390 | 16.0k | mDictId(dictId), | 391 | 16.0k | mExtId(extId), | 392 | 16.0k | mDict(nullptr), | 393 | 16.0k | mAsset(asset) { | 394 | 16.0k | asset.mDicts.push_back(this); // register to the list of dictionaries | 395 | 16.0k | } |
|
396 | | |
397 | | template <class T> |
398 | 224k | inline LazyDict<T>::~LazyDict() { |
399 | 314k | for (size_t i = 0; i < mObjs.size(); ++i) { |
400 | 89.3k | delete mObjs[i]; |
401 | 89.3k | } |
402 | 224k | } glTF2::LazyDict<glTF2::Texture>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 16.3k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 255 | delete mObjs[i]; | 401 | 255 | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Skin>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 19.9k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 3.87k | delete mObjs[i]; | 401 | 3.87k | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Scene>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 20.2k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 4.16k | delete mObjs[i]; | 401 | 4.16k | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Sampler>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 16.2k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 224 | delete mObjs[i]; | 401 | 224 | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Node>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 41.5k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 25.4k | delete mObjs[i]; | 401 | 25.4k | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Mesh>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 21.7k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 5.63k | delete mObjs[i]; | 401 | 5.63k | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Material>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 20.8k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 4.74k | delete mObjs[i]; | 401 | 4.74k | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Image>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 16.3k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 242 | delete mObjs[i]; | 401 | 242 | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Light>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 16.0k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 0 | delete mObjs[i]; | 401 | 0 | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Camera>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 16.1k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 99 | delete mObjs[i]; | 401 | 99 | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::BufferView>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 30.8k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 14.7k | delete mObjs[i]; | 401 | 14.7k | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Buffer>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 25.1k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 9.12k | delete mObjs[i]; | 401 | 9.12k | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Animation>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 16.3k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 249 | delete mObjs[i]; | 401 | 249 | } | 402 | 16.0k | } |
glTF2::LazyDict<glTF2::Accessor>::~LazyDict() Line | Count | Source | 398 | 16.0k | inline LazyDict<T>::~LazyDict() { | 399 | 36.5k | for (size_t i = 0; i < mObjs.size(); ++i) { | 400 | 20.4k | delete mObjs[i]; | 401 | 20.4k | } | 402 | 16.0k | } |
|
403 | | |
404 | | template <class T> |
405 | 80.3k | inline void LazyDict<T>::AttachToDocument(Document &doc) { |
406 | 80.3k | Value *container = nullptr; |
407 | 80.3k | const char *context = nullptr; |
408 | | |
409 | 80.3k | if (mExtId) { |
410 | 5.74k | if (Value *exts = FindObject(doc, "extensions")) { |
411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); |
412 | 0 | context = mExtId; |
413 | 0 | } |
414 | 74.6k | } else { |
415 | 74.6k | container = &doc; |
416 | 74.6k | context = "the document"; |
417 | 74.6k | } |
418 | | |
419 | 80.3k | if (container) { |
420 | 74.6k | mDict = FindArrayInContext(*container, mDictId, context); |
421 | 74.6k | } |
422 | 80.3k | } glTF2::LazyDict<glTF2::Accessor>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.75k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.75k | Value *container = nullptr; | 407 | 5.75k | const char *context = nullptr; | 408 | | | 409 | 5.75k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.75k | } else { | 415 | 5.75k | container = &doc; | 416 | 5.75k | context = "the document"; | 417 | 5.75k | } | 418 | | | 419 | 5.75k | if (container) { | 420 | 5.75k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.75k | } | 422 | 5.75k | } |
glTF2::LazyDict<glTF2::Animation>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.74k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.74k | Value *container = nullptr; | 407 | 5.74k | const char *context = nullptr; | 408 | | | 409 | 5.74k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.74k | } else { | 415 | 5.74k | container = &doc; | 416 | 5.74k | context = "the document"; | 417 | 5.74k | } | 418 | | | 419 | 5.74k | if (container) { | 420 | 5.74k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.74k | } | 422 | 5.74k | } |
glTF2::LazyDict<glTF2::Buffer>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.74k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.74k | Value *container = nullptr; | 407 | 5.74k | const char *context = nullptr; | 408 | | | 409 | 5.74k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.74k | } else { | 415 | 5.74k | container = &doc; | 416 | 5.74k | context = "the document"; | 417 | 5.74k | } | 418 | | | 419 | 5.74k | if (container) { | 420 | 5.74k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.74k | } | 422 | 5.74k | } |
glTF2::LazyDict<glTF2::BufferView>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.74k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.74k | Value *container = nullptr; | 407 | 5.74k | const char *context = nullptr; | 408 | | | 409 | 5.74k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.74k | } else { | 415 | 5.74k | container = &doc; | 416 | 5.74k | context = "the document"; | 417 | 5.74k | } | 418 | | | 419 | 5.74k | if (container) { | 420 | 5.74k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.74k | } | 422 | 5.74k | } |
glTF2::LazyDict<glTF2::Camera>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.74k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.74k | Value *container = nullptr; | 407 | 5.74k | const char *context = nullptr; | 408 | | | 409 | 5.74k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.74k | } else { | 415 | 5.74k | container = &doc; | 416 | 5.74k | context = "the document"; | 417 | 5.74k | } | 418 | | | 419 | 5.74k | if (container) { | 420 | 5.74k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.74k | } | 422 | 5.74k | } |
glTF2::LazyDict<glTF2::Light>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.74k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.74k | Value *container = nullptr; | 407 | 5.74k | const char *context = nullptr; | 408 | | | 409 | 5.74k | if (mExtId) { | 410 | 5.74k | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.74k | } else { | 415 | 0 | container = &doc; | 416 | 0 | context = "the document"; | 417 | 0 | } | 418 | | | 419 | 5.74k | if (container) { | 420 | 0 | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 0 | } | 422 | 5.74k | } |
glTF2::LazyDict<glTF2::Image>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.74k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.74k | Value *container = nullptr; | 407 | 5.74k | const char *context = nullptr; | 408 | | | 409 | 5.74k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.74k | } else { | 415 | 5.74k | container = &doc; | 416 | 5.74k | context = "the document"; | 417 | 5.74k | } | 418 | | | 419 | 5.74k | if (container) { | 420 | 5.74k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.74k | } | 422 | 5.74k | } |
glTF2::LazyDict<glTF2::Material>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.74k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.74k | Value *container = nullptr; | 407 | 5.74k | const char *context = nullptr; | 408 | | | 409 | 5.74k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.74k | } else { | 415 | 5.74k | container = &doc; | 416 | 5.74k | context = "the document"; | 417 | 5.74k | } | 418 | | | 419 | 5.74k | if (container) { | 420 | 5.74k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.74k | } | 422 | 5.74k | } |
glTF2::LazyDict<glTF2::Mesh>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.73k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.73k | Value *container = nullptr; | 407 | 5.73k | const char *context = nullptr; | 408 | | | 409 | 5.73k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.73k | } else { | 415 | 5.73k | container = &doc; | 416 | 5.73k | context = "the document"; | 417 | 5.73k | } | 418 | | | 419 | 5.73k | if (container) { | 420 | 5.73k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.73k | } | 422 | 5.73k | } |
glTF2::LazyDict<glTF2::Node>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.73k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.73k | Value *container = nullptr; | 407 | 5.73k | const char *context = nullptr; | 408 | | | 409 | 5.73k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.73k | } else { | 415 | 5.73k | container = &doc; | 416 | 5.73k | context = "the document"; | 417 | 5.73k | } | 418 | | | 419 | 5.73k | if (container) { | 420 | 5.73k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.73k | } | 422 | 5.73k | } |
glTF2::LazyDict<glTF2::Sampler>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.73k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.73k | Value *container = nullptr; | 407 | 5.73k | const char *context = nullptr; | 408 | | | 409 | 5.73k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.73k | } else { | 415 | 5.73k | container = &doc; | 416 | 5.73k | context = "the document"; | 417 | 5.73k | } | 418 | | | 419 | 5.73k | if (container) { | 420 | 5.73k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.73k | } | 422 | 5.73k | } |
glTF2::LazyDict<glTF2::Scene>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.73k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.73k | Value *container = nullptr; | 407 | 5.73k | const char *context = nullptr; | 408 | | | 409 | 5.73k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.73k | } else { | 415 | 5.73k | container = &doc; | 416 | 5.73k | context = "the document"; | 417 | 5.73k | } | 418 | | | 419 | 5.73k | if (container) { | 420 | 5.73k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.73k | } | 422 | 5.73k | } |
glTF2::LazyDict<glTF2::Skin>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.72k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.72k | Value *container = nullptr; | 407 | 5.72k | const char *context = nullptr; | 408 | | | 409 | 5.72k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.72k | } else { | 415 | 5.72k | container = &doc; | 416 | 5.72k | context = "the document"; | 417 | 5.72k | } | 418 | | | 419 | 5.72k | if (container) { | 420 | 5.72k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.72k | } | 422 | 5.72k | } |
glTF2::LazyDict<glTF2::Texture>::AttachToDocument(rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) Line | Count | Source | 405 | 5.72k | inline void LazyDict<T>::AttachToDocument(Document &doc) { | 406 | 5.72k | Value *container = nullptr; | 407 | 5.72k | const char *context = nullptr; | 408 | | | 409 | 5.72k | if (mExtId) { | 410 | 0 | if (Value *exts = FindObject(doc, "extensions")) { | 411 | 0 | container = FindObjectInContext(*exts, mExtId, "extensions"); | 412 | 0 | context = mExtId; | 413 | 0 | } | 414 | 5.72k | } else { | 415 | 5.72k | container = &doc; | 416 | 5.72k | context = "the document"; | 417 | 5.72k | } | 418 | | | 419 | 5.72k | if (container) { | 420 | 5.72k | mDict = FindArrayInContext(*container, mDictId, context); | 421 | 5.72k | } | 422 | 5.72k | } |
|
423 | | |
424 | | template <class T> |
425 | 59.4k | inline void LazyDict<T>::DetachFromDocument() { |
426 | 59.4k | mDict = nullptr; |
427 | 59.4k | } glTF2::LazyDict<glTF2::Accessor>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Animation>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Buffer>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::BufferView>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Camera>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Light>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Image>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Material>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Mesh>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Node>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Sampler>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Scene>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Skin>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
glTF2::LazyDict<glTF2::Texture>::DetachFromDocument() Line | Count | Source | 425 | 4.24k | inline void LazyDict<T>::DetachFromDocument() { | 426 | 4.24k | mDict = nullptr; | 427 | 4.24k | } |
|
428 | | |
429 | | template <class T> |
430 | 0 | unsigned int LazyDict<T>::Remove(const char *id) { |
431 | 0 | id = T::TranslateId(mAsset, id); |
432 | |
|
433 | 0 | typename IdDict::iterator objIt = mObjsById.find(id); |
434 | |
|
435 | 0 | if (objIt == mObjsById.end()) { |
436 | 0 | throw DeadlyExportError("GLTF: Object with id \"" + std::string(id) + "\" is not found"); |
437 | 0 | } |
438 | | |
439 | 0 | const unsigned int index = objIt->second; |
440 | |
|
441 | 0 | mObjsById.erase(id); |
442 | 0 | mObjsByOIndex.erase(index); |
443 | 0 | delete mObjs[index]; |
444 | 0 | mObjs.erase(mObjs.begin() + index); |
445 | | |
446 | | //update index of object in mObjs; |
447 | 0 | for (unsigned int i = index; i < mObjs.size(); ++i) { |
448 | 0 | T *obj = mObjs[i]; |
449 | |
|
450 | 0 | obj->index = i; |
451 | 0 | } |
452 | |
|
453 | 0 | for (IdDict::iterator it = mObjsById.begin(); it != mObjsById.end(); ++it) { |
454 | 0 | if (it->second <= index) { |
455 | 0 | continue; |
456 | 0 | } |
457 | | |
458 | 0 | mObjsById[it->first] = it->second - 1; |
459 | 0 | } |
460 | |
|
461 | 0 | for (Dict::iterator it = mObjsByOIndex.begin(); it != mObjsByOIndex.end(); ++it) { |
462 | 0 | if (it->second <= index) { |
463 | 0 | continue; |
464 | 0 | } |
465 | | |
466 | 0 | mObjsByOIndex[it->first] = it->second - 1; |
467 | 0 | } |
468 | |
|
469 | 0 | return index; |
470 | 0 | } |
471 | | |
472 | | template <class T> |
473 | 112k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { |
474 | 112k | typename Dict::iterator it = mObjsByOIndex.find(i); |
475 | 112k | if (it != mObjsByOIndex.end()) { // already created? |
476 | 23.8k | return Ref<T>(mObjs, it->second); |
477 | 23.8k | } |
478 | | |
479 | | // read it from the JSON object |
480 | 88.1k | if (!mDict) { |
481 | 142 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); |
482 | 142 | } |
483 | | |
484 | 88.0k | if (!mDict->IsArray()) { |
485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); |
486 | 0 | } |
487 | | |
488 | 88.0k | if (i >= mDict->Size()) { |
489 | 392 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); |
490 | 392 | } |
491 | | |
492 | 87.6k | Value &obj = (*mDict)[i]; |
493 | | |
494 | 87.6k | if (!obj.IsObject()) { |
495 | 31 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); |
496 | 31 | } |
497 | | |
498 | 87.6k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { |
499 | 35 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); |
500 | 35 | } |
501 | 87.5k | mRecursiveReferenceCheck.insert(i); |
502 | | |
503 | | // Unique ptr prevents memory leak in case of Read throws an exception |
504 | 87.5k | auto inst = std::unique_ptr<T>(new T()); |
505 | | // Try to make this human readable so it can be used in error messages. |
506 | 87.5k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; |
507 | 87.5k | inst->oIndex = i; |
508 | 87.5k | ReadMember(obj, "name", inst->name); |
509 | 87.5k | inst->Read(obj, mAsset); |
510 | 87.5k | inst->ReadExtensions(obj); |
511 | 87.5k | inst->ReadExtras(obj); |
512 | | |
513 | 87.5k | Ref<T> result = Add(inst.release()); |
514 | 87.5k | mRecursiveReferenceCheck.erase(i); |
515 | 87.5k | return result; |
516 | 87.6k | } glTF2::LazyDict<glTF2::Buffer>::Retrieve(unsigned int) Line | Count | Source | 473 | 15.3k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 15.3k | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 15.3k | if (it != mObjsByOIndex.end()) { // already created? | 476 | 13.7k | return Ref<T>(mObjs, it->second); | 477 | 13.7k | } | 478 | | | 479 | | // read it from the JSON object | 480 | 1.59k | if (!mDict) { | 481 | 5 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 5 | } | 483 | | | 484 | 1.59k | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 1.59k | if (i >= mDict->Size()) { | 489 | 28 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 28 | } | 491 | | | 492 | 1.56k | Value &obj = (*mDict)[i]; | 493 | | | 494 | 1.56k | if (!obj.IsObject()) { | 495 | 1 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 1 | } | 497 | | | 498 | 1.56k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 1.56k | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 1.56k | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 1.56k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 1.56k | inst->oIndex = i; | 508 | 1.56k | ReadMember(obj, "name", inst->name); | 509 | 1.56k | inst->Read(obj, mAsset); | 510 | 1.56k | inst->ReadExtensions(obj); | 511 | 1.56k | inst->ReadExtras(obj); | 512 | | | 513 | 1.56k | Ref<T> result = Add(inst.release()); | 514 | 1.56k | mRecursiveReferenceCheck.erase(i); | 515 | 1.56k | return result; | 516 | 1.56k | } |
glTF2::LazyDict<glTF2::BufferView>::Retrieve(unsigned int) Line | Count | Source | 473 | 16.3k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 16.3k | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 16.3k | if (it != mObjsByOIndex.end()) { // already created? | 476 | 998 | return Ref<T>(mObjs, it->second); | 477 | 998 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 15.3k | if (!mDict) { | 481 | 15 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 15 | } | 483 | | | 484 | 15.3k | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 15.3k | if (i >= mDict->Size()) { | 489 | 44 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 44 | } | 491 | | | 492 | 15.3k | Value &obj = (*mDict)[i]; | 493 | | | 494 | 15.3k | if (!obj.IsObject()) { | 495 | 1 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 1 | } | 497 | | | 498 | 15.3k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 15.3k | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 15.3k | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 15.3k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 15.3k | inst->oIndex = i; | 508 | 15.3k | ReadMember(obj, "name", inst->name); | 509 | 15.3k | inst->Read(obj, mAsset); | 510 | 15.3k | inst->ReadExtensions(obj); | 511 | 15.3k | inst->ReadExtras(obj); | 512 | | | 513 | 15.3k | Ref<T> result = Add(inst.release()); | 514 | 15.3k | mRecursiveReferenceCheck.erase(i); | 515 | 15.3k | return result; | 516 | 15.3k | } |
glTF2::LazyDict<glTF2::Image>::Retrieve(unsigned int) Line | Count | Source | 473 | 268 | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 268 | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 268 | if (it != mObjsByOIndex.end()) { // already created? | 476 | 0 | return Ref<T>(mObjs, it->second); | 477 | 0 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 268 | if (!mDict) { | 481 | 3 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 3 | } | 483 | | | 484 | 265 | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 265 | if (i >= mDict->Size()) { | 489 | 6 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 6 | } | 491 | | | 492 | 259 | Value &obj = (*mDict)[i]; | 493 | | | 494 | 259 | if (!obj.IsObject()) { | 495 | 1 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 1 | } | 497 | | | 498 | 258 | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 258 | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 258 | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 258 | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 258 | inst->oIndex = i; | 508 | 258 | ReadMember(obj, "name", inst->name); | 509 | 258 | inst->Read(obj, mAsset); | 510 | 258 | inst->ReadExtensions(obj); | 511 | 258 | inst->ReadExtras(obj); | 512 | | | 513 | 258 | Ref<T> result = Add(inst.release()); | 514 | 258 | mRecursiveReferenceCheck.erase(i); | 515 | 258 | return result; | 516 | 258 | } |
glTF2::LazyDict<glTF2::Sampler>::Retrieve(unsigned int) Line | Count | Source | 473 | 238 | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 238 | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 238 | if (it != mObjsByOIndex.end()) { // already created? | 476 | 0 | return Ref<T>(mObjs, it->second); | 477 | 0 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 238 | if (!mDict) { | 481 | 8 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 8 | } | 483 | | | 484 | 230 | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 230 | if (i >= mDict->Size()) { | 489 | 5 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 5 | } | 491 | | | 492 | 225 | Value &obj = (*mDict)[i]; | 493 | | | 494 | 225 | if (!obj.IsObject()) { | 495 | 1 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 1 | } | 497 | | | 498 | 224 | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 224 | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 224 | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 224 | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 224 | inst->oIndex = i; | 508 | 224 | ReadMember(obj, "name", inst->name); | 509 | 224 | inst->Read(obj, mAsset); | 510 | 224 | inst->ReadExtensions(obj); | 511 | 224 | inst->ReadExtras(obj); | 512 | | | 513 | 224 | Ref<T> result = Add(inst.release()); | 514 | 224 | mRecursiveReferenceCheck.erase(i); | 515 | 224 | return result; | 516 | 224 | } |
glTF2::LazyDict<glTF2::Texture>::Retrieve(unsigned int) Line | Count | Source | 473 | 400 | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 400 | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 400 | if (it != mObjsByOIndex.end()) { // already created? | 476 | 88 | return Ref<T>(mObjs, it->second); | 477 | 88 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 312 | if (!mDict) { | 481 | 4 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 4 | } | 483 | | | 484 | 308 | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 308 | if (i >= mDict->Size()) { | 489 | 8 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 8 | } | 491 | | | 492 | 300 | Value &obj = (*mDict)[i]; | 493 | | | 494 | 300 | if (!obj.IsObject()) { | 495 | 1 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 1 | } | 497 | | | 498 | 299 | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 299 | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 299 | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 299 | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 299 | inst->oIndex = i; | 508 | 299 | ReadMember(obj, "name", inst->name); | 509 | 299 | inst->Read(obj, mAsset); | 510 | 299 | inst->ReadExtensions(obj); | 511 | 299 | inst->ReadExtras(obj); | 512 | | | 513 | 299 | Ref<T> result = Add(inst.release()); | 514 | 299 | mRecursiveReferenceCheck.erase(i); | 515 | 299 | return result; | 516 | 299 | } |
glTF2::LazyDict<glTF2::Accessor>::Retrieve(unsigned int) Line | Count | Source | 473 | 22.2k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 22.2k | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 22.2k | if (it != mObjsByOIndex.end()) { // already created? | 476 | 845 | return Ref<T>(mObjs, it->second); | 477 | 845 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 21.4k | if (!mDict) { | 481 | 26 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 26 | } | 483 | | | 484 | 21.3k | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 21.3k | if (i >= mDict->Size()) { | 489 | 105 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 105 | } | 491 | | | 492 | 21.2k | Value &obj = (*mDict)[i]; | 493 | | | 494 | 21.2k | if (!obj.IsObject()) { | 495 | 1 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 1 | } | 497 | | | 498 | 21.2k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 21.2k | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 21.2k | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 21.2k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 21.2k | inst->oIndex = i; | 508 | 21.2k | ReadMember(obj, "name", inst->name); | 509 | 21.2k | inst->Read(obj, mAsset); | 510 | 21.2k | inst->ReadExtensions(obj); | 511 | 21.2k | inst->ReadExtras(obj); | 512 | | | 513 | 21.2k | Ref<T> result = Add(inst.release()); | 514 | 21.2k | mRecursiveReferenceCheck.erase(i); | 515 | 21.2k | return result; | 516 | 21.2k | } |
glTF2::LazyDict<glTF2::Material>::Retrieve(unsigned int) Line | Count | Source | 473 | 4.88k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 4.88k | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 4.88k | if (it != mObjsByOIndex.end()) { // already created? | 476 | 62 | return Ref<T>(mObjs, it->second); | 477 | 62 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 4.82k | if (!mDict) { | 481 | 5 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 5 | } | 483 | | | 484 | 4.82k | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 4.82k | if (i >= mDict->Size()) { | 489 | 14 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 14 | } | 491 | | | 492 | 4.80k | Value &obj = (*mDict)[i]; | 493 | | | 494 | 4.80k | if (!obj.IsObject()) { | 495 | 2 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 2 | } | 497 | | | 498 | 4.80k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 4.80k | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 4.80k | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 4.80k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 4.80k | inst->oIndex = i; | 508 | 4.80k | ReadMember(obj, "name", inst->name); | 509 | 4.80k | inst->Read(obj, mAsset); | 510 | 4.80k | inst->ReadExtensions(obj); | 511 | 4.80k | inst->ReadExtras(obj); | 512 | | | 513 | 4.80k | Ref<T> result = Add(inst.release()); | 514 | 4.80k | mRecursiveReferenceCheck.erase(i); | 515 | 4.80k | return result; | 516 | 4.80k | } |
glTF2::LazyDict<glTF2::Node>::Retrieve(unsigned int) Line | Count | Source | 473 | 33.8k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 33.8k | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 33.8k | if (it != mObjsByOIndex.end()) { // already created? | 476 | 6.25k | return Ref<T>(mObjs, it->second); | 477 | 6.25k | } | 478 | | | 479 | | // read it from the JSON object | 480 | 27.6k | if (!mDict) { | 481 | 38 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 38 | } | 483 | | | 484 | 27.5k | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 27.5k | if (i >= mDict->Size()) { | 489 | 129 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 129 | } | 491 | | | 492 | 27.4k | Value &obj = (*mDict)[i]; | 493 | | | 494 | 27.4k | if (!obj.IsObject()) { | 495 | 5 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 5 | } | 497 | | | 498 | 27.4k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 35 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 35 | } | 501 | 27.4k | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 27.4k | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 27.4k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 27.4k | inst->oIndex = i; | 508 | 27.4k | ReadMember(obj, "name", inst->name); | 509 | 27.4k | inst->Read(obj, mAsset); | 510 | 27.4k | inst->ReadExtensions(obj); | 511 | 27.4k | inst->ReadExtras(obj); | 512 | | | 513 | 27.4k | Ref<T> result = Add(inst.release()); | 514 | 27.4k | mRecursiveReferenceCheck.erase(i); | 515 | 27.4k | return result; | 516 | 27.4k | } |
glTF2::LazyDict<glTF2::Mesh>::Retrieve(unsigned int) Line | Count | Source | 473 | 8.56k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 8.56k | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 8.56k | if (it != mObjsByOIndex.end()) { // already created? | 476 | 1.87k | return Ref<T>(mObjs, it->second); | 477 | 1.87k | } | 478 | | | 479 | | // read it from the JSON object | 480 | 6.68k | if (!mDict) { | 481 | 35 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 35 | } | 483 | | | 484 | 6.65k | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 6.65k | if (i >= mDict->Size()) { | 489 | 41 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 41 | } | 491 | | | 492 | 6.61k | Value &obj = (*mDict)[i]; | 493 | | | 494 | 6.61k | if (!obj.IsObject()) { | 495 | 6 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 6 | } | 497 | | | 498 | 6.60k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 6.60k | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 6.60k | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 6.60k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 6.60k | inst->oIndex = i; | 508 | 6.60k | ReadMember(obj, "name", inst->name); | 509 | 6.60k | inst->Read(obj, mAsset); | 510 | 6.60k | inst->ReadExtensions(obj); | 511 | 6.60k | inst->ReadExtras(obj); | 512 | | | 513 | 6.60k | Ref<T> result = Add(inst.release()); | 514 | 6.60k | mRecursiveReferenceCheck.erase(i); | 515 | 6.60k | return result; | 516 | 6.60k | } |
glTF2::LazyDict<glTF2::Camera>::Retrieve(unsigned int) Line | Count | Source | 473 | 130 | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 130 | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 130 | if (it != mObjsByOIndex.end()) { // already created? | 476 | 4 | return Ref<T>(mObjs, it->second); | 477 | 4 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 126 | if (!mDict) { | 481 | 3 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 3 | } | 483 | | | 484 | 123 | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 123 | if (i >= mDict->Size()) { | 489 | 12 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 12 | } | 491 | | | 492 | 111 | Value &obj = (*mDict)[i]; | 493 | | | 494 | 111 | if (!obj.IsObject()) { | 495 | 1 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 1 | } | 497 | | | 498 | 110 | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 110 | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 110 | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 110 | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 110 | inst->oIndex = i; | 508 | 110 | ReadMember(obj, "name", inst->name); | 509 | 110 | inst->Read(obj, mAsset); | 510 | 110 | inst->ReadExtensions(obj); | 511 | 110 | inst->ReadExtras(obj); | 512 | | | 513 | 110 | Ref<T> result = Add(inst.release()); | 514 | 110 | mRecursiveReferenceCheck.erase(i); | 515 | 110 | return result; | 516 | 110 | } |
Unexecuted instantiation: glTF2::LazyDict<glTF2::Light>::Retrieve(unsigned int) glTF2::LazyDict<glTF2::Scene>::Retrieve(unsigned int) Line | Count | Source | 473 | 5.45k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 5.45k | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 5.45k | if (it != mObjsByOIndex.end()) { // already created? | 476 | 0 | return Ref<T>(mObjs, it->second); | 477 | 0 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 5.45k | if (!mDict) { | 481 | 0 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 0 | } | 483 | | | 484 | 5.45k | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 5.45k | if (i >= mDict->Size()) { | 489 | 0 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 0 | } | 491 | | | 492 | 5.45k | Value &obj = (*mDict)[i]; | 493 | | | 494 | 5.45k | if (!obj.IsObject()) { | 495 | 8 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 8 | } | 497 | | | 498 | 5.44k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 5.44k | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 5.44k | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 5.44k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 5.44k | inst->oIndex = i; | 508 | 5.44k | ReadMember(obj, "name", inst->name); | 509 | 5.44k | inst->Read(obj, mAsset); | 510 | 5.44k | inst->ReadExtensions(obj); | 511 | 5.44k | inst->ReadExtras(obj); | 512 | | | 513 | 5.44k | Ref<T> result = Add(inst.release()); | 514 | 5.44k | mRecursiveReferenceCheck.erase(i); | 515 | 5.44k | return result; | 516 | 5.44k | } |
glTF2::LazyDict<glTF2::Skin>::Retrieve(unsigned int) Line | Count | Source | 473 | 3.96k | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 3.96k | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 3.96k | if (it != mObjsByOIndex.end()) { // already created? | 476 | 0 | return Ref<T>(mObjs, it->second); | 477 | 0 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 3.96k | if (!mDict) { | 481 | 0 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 0 | } | 483 | | | 484 | 3.96k | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 3.96k | if (i >= mDict->Size()) { | 489 | 0 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 0 | } | 491 | | | 492 | 3.96k | Value &obj = (*mDict)[i]; | 493 | | | 494 | 3.96k | if (!obj.IsObject()) { | 495 | 2 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 2 | } | 497 | | | 498 | 3.96k | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 3.96k | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 3.96k | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 3.96k | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 3.96k | inst->oIndex = i; | 508 | 3.96k | ReadMember(obj, "name", inst->name); | 509 | 3.96k | inst->Read(obj, mAsset); | 510 | 3.96k | inst->ReadExtensions(obj); | 511 | 3.96k | inst->ReadExtras(obj); | 512 | | | 513 | 3.96k | Ref<T> result = Add(inst.release()); | 514 | 3.96k | mRecursiveReferenceCheck.erase(i); | 515 | 3.96k | return result; | 516 | 3.96k | } |
glTF2::LazyDict<glTF2::Animation>::Retrieve(unsigned int) Line | Count | Source | 473 | 326 | Ref<T> LazyDict<T>::Retrieve(unsigned int i) { | 474 | 326 | typename Dict::iterator it = mObjsByOIndex.find(i); | 475 | 326 | if (it != mObjsByOIndex.end()) { // already created? | 476 | 0 | return Ref<T>(mObjs, it->second); | 477 | 0 | } | 478 | | | 479 | | // read it from the JSON object | 480 | 326 | if (!mDict) { | 481 | 0 | throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\""); | 482 | 0 | } | 483 | | | 484 | 326 | if (!mDict->IsArray()) { | 485 | 0 | throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array"); | 486 | 0 | } | 487 | | | 488 | 326 | if (i >= mDict->Size()) { | 489 | 0 | throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\""); | 490 | 0 | } | 491 | | | 492 | 326 | Value &obj = (*mDict)[i]; | 493 | | | 494 | 326 | if (!obj.IsObject()) { | 495 | 1 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" is not a JSON object"); | 496 | 1 | } | 497 | | | 498 | 325 | if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { | 499 | 0 | throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself"); | 500 | 0 | } | 501 | 325 | mRecursiveReferenceCheck.insert(i); | 502 | | | 503 | | // Unique ptr prevents memory leak in case of Read throws an exception | 504 | 325 | auto inst = std::unique_ptr<T>(new T()); | 505 | | // Try to make this human readable so it can be used in error messages. | 506 | 325 | inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]"; | 507 | 325 | inst->oIndex = i; | 508 | 325 | ReadMember(obj, "name", inst->name); | 509 | 325 | inst->Read(obj, mAsset); | 510 | 325 | inst->ReadExtensions(obj); | 511 | 325 | inst->ReadExtras(obj); | 512 | | | 513 | 325 | Ref<T> result = Add(inst.release()); | 514 | 325 | mRecursiveReferenceCheck.erase(i); | 515 | 325 | return result; | 516 | 325 | } |
|
517 | | |
518 | | template <class T> |
519 | 967 | Ref<T> LazyDict<T>::Get(unsigned int i) { |
520 | 967 | return Ref<T>(mObjs, i); |
521 | 967 | } glTF2::LazyDict<glTF2::Skin>::Get(unsigned int) Line | Count | Source | 519 | 967 | Ref<T> LazyDict<T>::Get(unsigned int i) { | 520 | 967 | return Ref<T>(mObjs, i); | 521 | 967 | } |
Unexecuted instantiation: glTF2::LazyDict<glTF2::Buffer>::Get(unsigned int) Unexecuted instantiation: glTF2::LazyDict<glTF2::Texture>::Get(unsigned int) Unexecuted instantiation: glTF2::LazyDict<glTF2::Material>::Get(unsigned int) Unexecuted instantiation: glTF2::LazyDict<glTF2::Node>::Get(unsigned int) Unexecuted instantiation: glTF2::LazyDict<glTF2::Mesh>::Get(unsigned int) |
522 | | |
523 | | template <class T> |
524 | 0 | Ref<T> LazyDict<T>::Get(const char *id) { |
525 | 0 | id = T::TranslateId(mAsset, id); |
526 | |
|
527 | 0 | typename IdDict::iterator it = mObjsById.find(id); |
528 | 0 | if (it != mObjsById.end()) { // already created? |
529 | 0 | return Ref<T>(mObjs, it->second); |
530 | 0 | } |
531 | | |
532 | 0 | return Ref<T>(); |
533 | 0 | } Unexecuted instantiation: glTF2::LazyDict<glTF2::Sampler>::Get(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Node>::Get(char const*) |
534 | | |
535 | | template <class T> |
536 | 89.3k | Ref<T> LazyDict<T>::Add(T *obj) { |
537 | 89.3k | unsigned int idx = unsigned(mObjs.size()); |
538 | 89.3k | mObjs.push_back(obj); |
539 | 89.3k | mObjsByOIndex[obj->oIndex] = idx; |
540 | 89.3k | mObjsById[obj->id] = idx; |
541 | 89.3k | return Ref<T>(mObjs, idx); |
542 | 89.3k | } glTF2::LazyDict<glTF2::Buffer>::Add(glTF2::Buffer*) Line | Count | Source | 536 | 9.12k | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 9.12k | unsigned int idx = unsigned(mObjs.size()); | 538 | 9.12k | mObjs.push_back(obj); | 539 | 9.12k | mObjsByOIndex[obj->oIndex] = idx; | 540 | 9.12k | mObjsById[obj->id] = idx; | 541 | 9.12k | return Ref<T>(mObjs, idx); | 542 | 9.12k | } |
glTF2::LazyDict<glTF2::BufferView>::Add(glTF2::BufferView*) Line | Count | Source | 536 | 14.7k | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 14.7k | unsigned int idx = unsigned(mObjs.size()); | 538 | 14.7k | mObjs.push_back(obj); | 539 | 14.7k | mObjsByOIndex[obj->oIndex] = idx; | 540 | 14.7k | mObjsById[obj->id] = idx; | 541 | 14.7k | return Ref<T>(mObjs, idx); | 542 | 14.7k | } |
glTF2::LazyDict<glTF2::Image>::Add(glTF2::Image*) Line | Count | Source | 536 | 242 | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 242 | unsigned int idx = unsigned(mObjs.size()); | 538 | 242 | mObjs.push_back(obj); | 539 | 242 | mObjsByOIndex[obj->oIndex] = idx; | 540 | 242 | mObjsById[obj->id] = idx; | 541 | 242 | return Ref<T>(mObjs, idx); | 542 | 242 | } |
glTF2::LazyDict<glTF2::Sampler>::Add(glTF2::Sampler*) Line | Count | Source | 536 | 224 | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 224 | unsigned int idx = unsigned(mObjs.size()); | 538 | 224 | mObjs.push_back(obj); | 539 | 224 | mObjsByOIndex[obj->oIndex] = idx; | 540 | 224 | mObjsById[obj->id] = idx; | 541 | 224 | return Ref<T>(mObjs, idx); | 542 | 224 | } |
glTF2::LazyDict<glTF2::Texture>::Add(glTF2::Texture*) Line | Count | Source | 536 | 255 | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 255 | unsigned int idx = unsigned(mObjs.size()); | 538 | 255 | mObjs.push_back(obj); | 539 | 255 | mObjsByOIndex[obj->oIndex] = idx; | 540 | 255 | mObjsById[obj->id] = idx; | 541 | 255 | return Ref<T>(mObjs, idx); | 542 | 255 | } |
glTF2::LazyDict<glTF2::Accessor>::Add(glTF2::Accessor*) Line | Count | Source | 536 | 20.4k | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 20.4k | unsigned int idx = unsigned(mObjs.size()); | 538 | 20.4k | mObjs.push_back(obj); | 539 | 20.4k | mObjsByOIndex[obj->oIndex] = idx; | 540 | 20.4k | mObjsById[obj->id] = idx; | 541 | 20.4k | return Ref<T>(mObjs, idx); | 542 | 20.4k | } |
glTF2::LazyDict<glTF2::Material>::Add(glTF2::Material*) Line | Count | Source | 536 | 4.74k | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 4.74k | unsigned int idx = unsigned(mObjs.size()); | 538 | 4.74k | mObjs.push_back(obj); | 539 | 4.74k | mObjsByOIndex[obj->oIndex] = idx; | 540 | 4.74k | mObjsById[obj->id] = idx; | 541 | 4.74k | return Ref<T>(mObjs, idx); | 542 | 4.74k | } |
glTF2::LazyDict<glTF2::Node>::Add(glTF2::Node*) Line | Count | Source | 536 | 25.4k | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 25.4k | unsigned int idx = unsigned(mObjs.size()); | 538 | 25.4k | mObjs.push_back(obj); | 539 | 25.4k | mObjsByOIndex[obj->oIndex] = idx; | 540 | 25.4k | mObjsById[obj->id] = idx; | 541 | 25.4k | return Ref<T>(mObjs, idx); | 542 | 25.4k | } |
glTF2::LazyDict<glTF2::Mesh>::Add(glTF2::Mesh*) Line | Count | Source | 536 | 5.63k | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 5.63k | unsigned int idx = unsigned(mObjs.size()); | 538 | 5.63k | mObjs.push_back(obj); | 539 | 5.63k | mObjsByOIndex[obj->oIndex] = idx; | 540 | 5.63k | mObjsById[obj->id] = idx; | 541 | 5.63k | return Ref<T>(mObjs, idx); | 542 | 5.63k | } |
glTF2::LazyDict<glTF2::Camera>::Add(glTF2::Camera*) Line | Count | Source | 536 | 99 | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 99 | unsigned int idx = unsigned(mObjs.size()); | 538 | 99 | mObjs.push_back(obj); | 539 | 99 | mObjsByOIndex[obj->oIndex] = idx; | 540 | 99 | mObjsById[obj->id] = idx; | 541 | 99 | return Ref<T>(mObjs, idx); | 542 | 99 | } |
Unexecuted instantiation: glTF2::LazyDict<glTF2::Light>::Add(glTF2::Light*) glTF2::LazyDict<glTF2::Scene>::Add(glTF2::Scene*) Line | Count | Source | 536 | 4.16k | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 4.16k | unsigned int idx = unsigned(mObjs.size()); | 538 | 4.16k | mObjs.push_back(obj); | 539 | 4.16k | mObjsByOIndex[obj->oIndex] = idx; | 540 | 4.16k | mObjsById[obj->id] = idx; | 541 | 4.16k | return Ref<T>(mObjs, idx); | 542 | 4.16k | } |
glTF2::LazyDict<glTF2::Skin>::Add(glTF2::Skin*) Line | Count | Source | 536 | 3.87k | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 3.87k | unsigned int idx = unsigned(mObjs.size()); | 538 | 3.87k | mObjs.push_back(obj); | 539 | 3.87k | mObjsByOIndex[obj->oIndex] = idx; | 540 | 3.87k | mObjsById[obj->id] = idx; | 541 | 3.87k | return Ref<T>(mObjs, idx); | 542 | 3.87k | } |
glTF2::LazyDict<glTF2::Animation>::Add(glTF2::Animation*) Line | Count | Source | 536 | 249 | Ref<T> LazyDict<T>::Add(T *obj) { | 537 | 249 | unsigned int idx = unsigned(mObjs.size()); | 538 | 249 | mObjs.push_back(obj); | 539 | 249 | mObjsByOIndex[obj->oIndex] = idx; | 540 | 249 | mObjsById[obj->id] = idx; | 541 | 249 | return Ref<T>(mObjs, idx); | 542 | 249 | } |
|
543 | | |
544 | | template <class T> |
545 | 7.98k | Ref<T> LazyDict<T>::Create(const char *id) { |
546 | 7.98k | T *inst = new T(); |
547 | 7.98k | unsigned int idx = unsigned(mObjs.size()); |
548 | 7.98k | inst->id = id; |
549 | 7.98k | inst->index = idx; |
550 | 7.98k | inst->oIndex = idx; |
551 | 7.98k | return Add(inst); |
552 | 7.98k | } Unexecuted instantiation: glTF2::LazyDict<glTF2::BufferView>::Create(char const*) glTF2::LazyDict<glTF2::Buffer>::Create(char const*) Line | Count | Source | 545 | 7.98k | Ref<T> LazyDict<T>::Create(const char *id) { | 546 | 7.98k | T *inst = new T(); | 547 | 7.98k | unsigned int idx = unsigned(mObjs.size()); | 548 | 7.98k | inst->id = id; | 549 | 7.98k | inst->index = idx; | 550 | 7.98k | inst->oIndex = idx; | 551 | 7.98k | return Add(inst); | 552 | 7.98k | } |
Unexecuted instantiation: glTF2::LazyDict<glTF2::Accessor>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Sampler>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Texture>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Image>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Material>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Skin>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Mesh>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Node>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Scene>::Create(char const*) Unexecuted instantiation: glTF2::LazyDict<glTF2::Animation>::Create(char const*) |
553 | | |
554 | | // |
555 | | // glTF dictionary objects methods |
556 | | // |
557 | | inline Buffer::Buffer() : |
558 | 9.54k | byteLength(0), |
559 | 9.54k | type(Type_arraybuffer), |
560 | 9.54k | EncodedRegion_Current(nullptr), |
561 | 9.54k | mIsSpecial(false) { |
562 | | // empty |
563 | 9.54k | } |
564 | | |
565 | 9.54k | inline Buffer::~Buffer() { |
566 | 9.54k | for (SEncodedRegion *reg : EncodedRegion_List) delete reg; |
567 | 9.54k | } |
568 | | |
569 | 0 | inline const char *Buffer::TranslateId(Asset & /*r*/, const char *id) { |
570 | 0 | return id; |
571 | 0 | } |
572 | | |
573 | 1.56k | inline void Buffer::Read(Value &obj, Asset &r) { |
574 | 1.56k | size_t statedLength = MemberOrDefault<size_t>(obj, "byteLength", 0); |
575 | 1.56k | byteLength = statedLength; |
576 | | |
577 | 1.56k | Value *it = FindString(obj, "uri"); |
578 | 1.56k | if (!it) { |
579 | 25 | if (statedLength > 0) { |
580 | 18 | throw DeadlyImportError("GLTF: buffer with non-zero length missing the \"uri\" attribute"); |
581 | 18 | } |
582 | 7 | return; |
583 | 25 | } |
584 | | |
585 | 1.53k | const char *uri = it->GetString(); |
586 | | |
587 | 1.53k | glTFCommon::Util::DataURI dataURI; |
588 | 1.53k | if (ParseDataURI(uri, it->GetStringLength(), dataURI)) { |
589 | 1.23k | if (dataURI.base64) { |
590 | 1.18k | uint8_t *data = nullptr; |
591 | 1.18k | this->byteLength = Base64::Decode(dataURI.data, dataURI.dataLength, data); |
592 | 1.18k | this->mData.reset(data, std::default_delete<uint8_t[]>()); |
593 | | |
594 | 1.18k | if (statedLength > 0 && this->byteLength != statedLength) { |
595 | 19 | throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength), |
596 | 19 | " bytes, but found ", ai_to_string(dataURI.dataLength)); |
597 | 19 | } |
598 | 1.18k | } else { // assume raw data |
599 | 49 | if (statedLength != dataURI.dataLength) { |
600 | 47 | throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength), |
601 | 47 | " bytes, but found ", ai_to_string(dataURI.dataLength)); |
602 | 47 | } |
603 | | |
604 | 2 | this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>()); |
605 | 2 | memcpy(this->mData.get(), dataURI.data, dataURI.dataLength); |
606 | 2 | } |
607 | 1.23k | } else { // Local file |
608 | 302 | if (byteLength > 0) { |
609 | 285 | std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir.back() == '/' ? r.mCurrentAssetDir : r.mCurrentAssetDir + '/') : ""; |
610 | | |
611 | 285 | IOStream *file = r.OpenFile(dir + uri, "rb"); |
612 | 285 | if (file) { |
613 | 23 | bool ok = LoadFromStream(*file, byteLength); |
614 | 23 | delete file; |
615 | | |
616 | 23 | if (!ok) |
617 | 0 | throw DeadlyImportError("GLTF: error while reading referenced file \"", uri, "\""); |
618 | 262 | } else { |
619 | 262 | throw DeadlyImportError("GLTF: could not open referenced file \"", uri, "\""); |
620 | 262 | } |
621 | 285 | } |
622 | 302 | } |
623 | 1.53k | } |
624 | | |
625 | 3.57k | inline bool Buffer::LoadFromStream(IOStream &stream, size_t length, size_t baseOffset) { |
626 | 3.57k | byteLength = length ? length : stream.FileSize(); |
627 | | |
628 | 3.57k | if (byteLength > stream.FileSize()) { |
629 | 106 | throw DeadlyImportError("GLTF: Invalid byteLength exceeds size of actual data."); |
630 | 106 | } |
631 | | |
632 | 3.47k | if (baseOffset) { |
633 | 3.45k | stream.Seek(baseOffset, aiOrigin_SET); |
634 | 3.45k | } |
635 | | |
636 | 3.47k | mData.reset(new uint8_t[byteLength], std::default_delete<uint8_t[]>()); |
637 | | |
638 | 3.47k | if (stream.Read(mData.get(), byteLength, 1) != 1) { |
639 | 30 | return false; |
640 | 30 | } |
641 | 3.44k | return true; |
642 | 3.47k | } |
643 | | |
644 | 0 | inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) { |
645 | 0 | // Check pointer to data |
646 | 0 | if (pDecodedData == nullptr) throw DeadlyImportError("GLTF: for marking encoded region pointer to decoded data must be provided."); |
647 | 0 |
|
648 | 0 | // Check offset |
649 | 0 | if (pOffset > byteLength) { |
650 | 0 | const uint8_t val_size = 32; |
651 | 0 |
|
652 | 0 | char val[val_size]; |
653 | 0 |
|
654 | 0 | ai_snprintf(val, val_size, AI_SIZEFMT, pOffset); |
655 | 0 | throw DeadlyImportError("GLTF: incorrect offset value (", val, ") for marking encoded region."); |
656 | 0 | } |
657 | 0 |
|
658 | 0 | // Check length |
659 | 0 | if ((pOffset + pEncodedData_Length) > byteLength) { |
660 | 0 | const uint8_t val_size = 64; |
661 | 0 |
|
662 | 0 | char val[val_size]; |
663 | 0 |
|
664 | 0 | ai_snprintf(val, val_size, AI_SIZEFMT "/" AI_SIZEFMT, pOffset, pEncodedData_Length); |
665 | 0 | throw DeadlyImportError("GLTF: encoded region with offset/length (", val, ") is out of range."); |
666 | 0 | } |
667 | 0 |
|
668 | 0 | // Add new region |
669 | 0 | EncodedRegion_List.push_back(new SEncodedRegion(pOffset, pEncodedData_Length, pDecodedData, pDecodedData_Length, pID)); |
670 | 0 | // And set new value for "byteLength" |
671 | 0 | byteLength += (pDecodedData_Length - pEncodedData_Length); |
672 | 0 | } |
673 | | |
674 | 0 | inline void Buffer::EncodedRegion_SetCurrent(const std::string &pID) { |
675 | 0 | if ((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) { |
676 | 0 | return; |
677 | 0 | } |
678 | 0 |
|
679 | 0 | for (SEncodedRegion *reg : EncodedRegion_List) { |
680 | 0 | if (reg->ID == pID) { |
681 | 0 | EncodedRegion_Current = reg; |
682 | 0 | return; |
683 | 0 | } |
684 | 0 | } |
685 | 0 |
|
686 | 0 | throw DeadlyImportError("GLTF: EncodedRegion with ID: \"", pID, "\" not found."); |
687 | 0 | } |
688 | | |
689 | 0 | inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) { |
690 | 0 | if ((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) { |
691 | 0 | return false; |
692 | 0 | } |
693 | 0 |
|
694 | 0 | const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; |
695 | 0 | uint8_t *new_data = new uint8_t[new_data_size]; |
696 | 0 | // Copy data which place before replacing part. |
697 | 0 | ::memcpy(new_data, mData.get(), pBufferData_Offset); |
698 | 0 | // Copy new data. |
699 | 0 | ::memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count); |
700 | 0 | // Copy data which place after replacing part. |
701 | 0 | ::memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset); |
702 | 0 | // Apply new data |
703 | 0 | mData.reset(new_data, std::default_delete<uint8_t[]>()); |
704 | 0 | byteLength = new_data_size; |
705 | 0 |
|
706 | 0 | return true; |
707 | 0 | } |
708 | | |
709 | 0 | inline bool Buffer::ReplaceData_joint(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) { |
710 | 0 | if ((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) { |
711 | 0 | return false; |
712 | 0 | } |
713 | 0 |
|
714 | 0 | const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; |
715 | 0 | uint8_t *new_data = new uint8_t[new_data_size]; |
716 | 0 | // Copy data which place before replacing part. |
717 | 0 | memcpy(new_data, mData.get(), pBufferData_Offset); |
718 | 0 | // Copy new data. |
719 | 0 | memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count); |
720 | 0 | // Copy data which place after replacing part. |
721 | 0 | memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], new_data_size - (pBufferData_Offset + pReplace_Count)); |
722 | 0 | // Apply new data |
723 | 0 | mData.reset(new_data, std::default_delete<uint8_t[]>()); |
724 | 0 | byteLength = new_data_size; |
725 | 0 |
|
726 | 0 | return true; |
727 | 0 | } |
728 | | |
729 | 0 | inline size_t Buffer::AppendData(uint8_t *data, size_t length) { |
730 | 0 | const size_t offset = this->byteLength; |
731 | 0 |
|
732 | 0 | // Force alignment to 4 bits |
733 | 0 | const size_t paddedLength = (length + 3) & ~3; |
734 | 0 | Grow(paddedLength); |
735 | 0 | memcpy(mData.get() + offset, data, length); |
736 | 0 | memset(mData.get() + offset + length, 0, paddedLength - length); |
737 | 0 | return offset; |
738 | 0 | } |
739 | | |
740 | 0 | inline void Buffer::Grow(size_t amount) { |
741 | 0 | if (amount <= 0) { |
742 | 0 | return; |
743 | 0 | } |
744 | 0 |
|
745 | 0 | // Capacity is big enough |
746 | 0 | if (capacity >= byteLength + amount) { |
747 | 0 | byteLength += amount; |
748 | 0 | return; |
749 | 0 | } |
750 | 0 |
|
751 | 0 | // Just allocate data which we need |
752 | 0 | capacity = byteLength + amount; |
753 | 0 |
|
754 | 0 | uint8_t *b = new uint8_t[capacity]; |
755 | 0 | if (nullptr != mData) { |
756 | 0 | memcpy(b, mData.get(), byteLength); |
757 | 0 | } |
758 | 0 | mData.reset(b, std::default_delete<uint8_t[]>()); |
759 | 0 | byteLength += amount; |
760 | 0 | } |
761 | | |
762 | | // |
763 | | // struct BufferView |
764 | | // |
765 | 15.3k | inline void BufferView::Read(Value &obj, Asset &r) { |
766 | 15.3k | if (Value *bufferVal = FindUInt(obj, "buffer")) { |
767 | 15.3k | buffer = r.buffers.Retrieve(bufferVal->GetUint()); |
768 | 15.3k | } |
769 | | |
770 | 15.3k | if (!buffer) { |
771 | 14 | throw DeadlyImportError("GLTF: Buffer view without valid buffer."); |
772 | 14 | } |
773 | | |
774 | 15.3k | byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); |
775 | 15.3k | byteLength = MemberOrDefault(obj, "byteLength", size_t(0)); |
776 | 15.3k | byteStride = MemberOrDefault(obj, "byteStride", 0u); |
777 | | |
778 | | // Check length |
779 | 15.3k | if ((byteOffset + byteLength) > buffer->byteLength) { |
780 | 57 | throw DeadlyImportError("GLTF: Buffer view with offset/length (", byteOffset, "/", byteLength, ") is out of range."); |
781 | 57 | } |
782 | 15.3k | } |
783 | | |
784 | 0 | inline uint8_t *BufferView::GetPointerAndTailSize(size_t accOffset, size_t& outTailSize) { |
785 | 0 | if (!buffer) { |
786 | 0 | outTailSize = 0; |
787 | 0 | return nullptr; |
788 | 0 | } |
789 | 0 | uint8_t * const basePtr = buffer->GetPointer(); |
790 | 0 | if (!basePtr) { |
791 | 0 | outTailSize = 0; |
792 | 0 | return nullptr; |
793 | 0 | } |
794 | | |
795 | 0 | size_t offset = accOffset + byteOffset; |
796 | 0 | if (buffer->EncodedRegion_Current != nullptr) { |
797 | 0 | const size_t begin = buffer->EncodedRegion_Current->Offset; |
798 | 0 | const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length; |
799 | 0 | if ((offset >= begin) && (offset < end)) { |
800 | 0 | outTailSize = end - offset; |
801 | 0 | return &buffer->EncodedRegion_Current->DecodedData[offset - begin]; |
802 | 0 | } |
803 | 0 | } |
804 | | |
805 | 0 | if (offset >= buffer->byteLength) { |
806 | 0 | outTailSize = 0; |
807 | 0 | return nullptr; |
808 | 0 | } |
809 | | |
810 | 0 | outTailSize = buffer->byteLength - offset; |
811 | 0 | return basePtr + offset; |
812 | 0 | } |
813 | | |
814 | | // |
815 | | // struct Accessor |
816 | | // |
817 | 0 | inline void Accessor::Sparse::PopulateData(size_t numBytes, const uint8_t *bytes) { |
818 | 0 | if (bytes) { |
819 | 0 | data.assign(bytes, bytes + numBytes); |
820 | 0 | } else { |
821 | 0 | data.resize(numBytes, 0x00); |
822 | 0 | } |
823 | 0 | } |
824 | | |
825 | 0 | inline void Accessor::Sparse::PatchData(unsigned int elementSize) { |
826 | 0 | size_t indicesTailDataSize; |
827 | 0 | uint8_t *pIndices = indices->GetPointerAndTailSize(indicesByteOffset, indicesTailDataSize); |
828 | 0 | const unsigned int indexSize = int(ComponentTypeSize(indicesType)); |
829 | 0 | uint8_t *indicesEnd = pIndices + count * indexSize; |
830 | |
|
831 | 0 | if ((uint64_t)indicesEnd > (uint64_t)pIndices + indicesTailDataSize) { |
832 | 0 | throw DeadlyImportError("Invalid sparse accessor. Indices outside allocated memory."); |
833 | 0 | } |
834 | | |
835 | 0 | size_t valuesTailDataSize; |
836 | 0 | uint8_t* pValues = values->GetPointerAndTailSize(valuesByteOffset, valuesTailDataSize); |
837 | |
|
838 | 0 | if (elementSize * count > valuesTailDataSize) { |
839 | 0 | throw DeadlyImportError("Invalid sparse accessor. Indices outside allocated memory."); |
840 | 0 | } |
841 | 0 | while (pIndices != indicesEnd) { |
842 | 0 | size_t offset; |
843 | 0 | switch (indicesType) { |
844 | 0 | case ComponentType_UNSIGNED_BYTE: |
845 | 0 | offset = *pIndices; |
846 | 0 | break; |
847 | 0 | case ComponentType_UNSIGNED_SHORT: |
848 | 0 | offset = *reinterpret_cast<uint16_t *>(pIndices); |
849 | 0 | break; |
850 | 0 | case ComponentType_UNSIGNED_INT: |
851 | 0 | offset = *reinterpret_cast<uint32_t *>(pIndices); |
852 | 0 | break; |
853 | 0 | default: |
854 | | // have fun with float and negative values from signed types as indices. |
855 | 0 | throw DeadlyImportError("Unsupported component type in index."); |
856 | 0 | } |
857 | | |
858 | 0 | offset *= elementSize; |
859 | |
|
860 | 0 | if (offset + elementSize > data.size()) { |
861 | 0 | throw DeadlyImportError("Invalid sparse accessor. Byte offset for patching points outside allocated memory."); |
862 | 0 | } |
863 | | |
864 | 0 | std::memcpy(data.data() + offset, pValues, elementSize); |
865 | |
|
866 | 0 | pValues += elementSize; |
867 | 0 | pIndices += indexSize; |
868 | 0 | } |
869 | 0 | } |
870 | | |
871 | 21.2k | inline void Accessor::Read(Value &obj, Asset &r) { |
872 | 21.2k | if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { |
873 | 16.2k | bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); |
874 | 16.2k | } |
875 | | |
876 | 21.2k | byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); |
877 | 21.2k | componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); |
878 | 21.2k | { |
879 | 21.2k | const Value *countValue = FindUInt(obj, "count"); |
880 | 21.2k | if (!countValue) { |
881 | 22 | throw DeadlyImportError("A count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); |
882 | 22 | } |
883 | 21.2k | count = countValue->GetUint(); |
884 | 21.2k | } |
885 | | |
886 | 0 | const char *typestr; |
887 | 21.2k | type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; |
888 | | |
889 | 21.2k | if (bufferView) { |
890 | | // Check length |
891 | 15.6k | unsigned long long byteLength = count > 0 |
892 | 15.6k | ? (unsigned long long)GetStride() * (unsigned long long)(count - 1) + (unsigned long long)GetElementSize() |
893 | 15.6k | : 0; |
894 | | |
895 | | // handle integer overflow |
896 | 15.6k | if (byteLength < count) { |
897 | 0 | throw DeadlyImportError("GLTF: Accessor with offset/count (", byteOffset, "/", count, ") is out of range."); |
898 | 0 | } |
899 | | |
900 | 15.6k | if ((byteOffset + byteLength) > bufferView->byteLength || (bufferView->byteOffset + byteOffset + byteLength) > bufferView->buffer->byteLength) { |
901 | 138 | throw DeadlyImportError("GLTF: Accessor with offset/length (", byteOffset, "/", byteLength, ") is out of range."); |
902 | 138 | } |
903 | 15.6k | } |
904 | | |
905 | 21.1k | if (Value *sparseValue = FindObject(obj, "sparse")) { |
906 | 0 | sparse.reset(new Sparse); |
907 | | // count |
908 | 0 | ReadMember(*sparseValue, "count", sparse->count); |
909 | | |
910 | | // indices |
911 | 0 | if (Value *indicesValue = FindObject(*sparseValue, "indices")) { |
912 | | //indices bufferView |
913 | 0 | Value *indiceViewID = FindUInt(*indicesValue, "bufferView"); |
914 | 0 | if (!indiceViewID) { |
915 | 0 | throw DeadlyImportError("A bufferView value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); |
916 | 0 | } |
917 | 0 | sparse->indices = r.bufferViews.Retrieve(indiceViewID->GetUint()); |
918 | | //indices byteOffset |
919 | 0 | sparse->indicesByteOffset = MemberOrDefault(*indicesValue, "byteOffset", size_t(0)); |
920 | | //indices componentType |
921 | 0 | sparse->indicesType = MemberOrDefault(*indicesValue, "componentType", ComponentType_BYTE); |
922 | | //sparse->indices->Read(*indicesValue, r); |
923 | 0 | } else { |
924 | | // indicesType |
925 | 0 | sparse->indicesType = MemberOrDefault(*sparseValue, "componentType", ComponentType_UNSIGNED_SHORT); |
926 | 0 | } |
927 | | |
928 | | // value |
929 | 0 | if (Value *valuesValue = FindObject(*sparseValue, "values")) { |
930 | | //value bufferView |
931 | 0 | Value *valueViewID = FindUInt(*valuesValue, "bufferView"); |
932 | 0 | if (!valueViewID) { |
933 | 0 | throw DeadlyImportError("A bufferView value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); |
934 | 0 | } |
935 | 0 | sparse->values = r.bufferViews.Retrieve(valueViewID->GetUint()); |
936 | | //value byteOffset |
937 | 0 | sparse->valuesByteOffset = MemberOrDefault(*valuesValue, "byteOffset", size_t(0)); |
938 | | //sparse->values->Read(*valuesValue, r); |
939 | 0 | } |
940 | | |
941 | | |
942 | 0 | const unsigned int elementSize = GetElementSize(); |
943 | 0 | const size_t dataSize = count * elementSize; |
944 | 0 | if (bufferView) { |
945 | 0 | size_t bufferViewTailSize; |
946 | 0 | const uint8_t* bufferViewPointer = bufferView->GetPointerAndTailSize(byteOffset, bufferViewTailSize); |
947 | 0 | if (dataSize > bufferViewTailSize) { |
948 | 0 | throw DeadlyImportError("Invalid buffer when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); |
949 | 0 | } |
950 | 0 | sparse->PopulateData(dataSize, bufferViewPointer); |
951 | 0 | } |
952 | 0 | else { |
953 | 0 | sparse->PopulateData(dataSize, nullptr); |
954 | 0 | } |
955 | 0 | sparse->PatchData(elementSize); |
956 | 0 | } |
957 | 21.1k | } |
958 | | |
959 | 51.0k | inline unsigned int Accessor::GetNumComponents() { |
960 | 51.0k | return AttribType::GetNumComponents(type); |
961 | 51.0k | } |
962 | | |
963 | 50.0k | inline unsigned int Accessor::GetBytesPerComponent() { |
964 | 50.0k | return int(ComponentTypeSize(componentType)); |
965 | 50.0k | } |
966 | | |
967 | 50.0k | inline unsigned int Accessor::GetElementSize() { |
968 | 50.0k | return GetNumComponents() * GetBytesPerComponent(); |
969 | 50.0k | } |
970 | | |
971 | 13.2k | inline uint8_t *Accessor::GetPointer() { |
972 | 13.2k | if (decodedBuffer) |
973 | 0 | return decodedBuffer->GetPointer(); |
974 | | |
975 | 13.2k | if (sparse) |
976 | 0 | return sparse->data.data(); |
977 | | |
978 | 13.2k | if (!bufferView || !bufferView->buffer) return nullptr; |
979 | 13.0k | uint8_t *basePtr = bufferView->buffer->GetPointer(); |
980 | 13.0k | if (!basePtr) return nullptr; |
981 | | |
982 | 13.0k | size_t offset = byteOffset + bufferView->byteOffset; |
983 | | |
984 | | // Check if region is encoded. |
985 | 13.0k | if (bufferView->buffer->EncodedRegion_Current != nullptr) { |
986 | 0 | const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset; |
987 | 0 | const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length; |
988 | |
|
989 | 0 | if ((offset >= begin) && (offset < end)) |
990 | 0 | return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin]; |
991 | 0 | } |
992 | | |
993 | 13.0k | return basePtr + offset; |
994 | 13.0k | } |
995 | | |
996 | 28.7k | inline size_t Accessor::GetStride() { |
997 | | // Decoded buffer is always packed |
998 | 28.7k | if (decodedBuffer) |
999 | 0 | return GetElementSize(); |
1000 | | |
1001 | | // Sparse and normal bufferView |
1002 | 28.7k | return (bufferView && bufferView->byteStride ? bufferView->byteStride : GetElementSize()); |
1003 | 28.7k | } |
1004 | | |
1005 | 70.9k | inline size_t Accessor::GetMaxByteSize() { |
1006 | 70.9k | if (decodedBuffer) |
1007 | 0 | return decodedBuffer->byteLength; |
1008 | | |
1009 | 70.9k | if (sparse) { |
1010 | 0 | return sparse->data.size(); |
1011 | 0 | } |
1012 | | |
1013 | 70.9k | if (bufferView) { |
1014 | 70.9k | return byteOffset <= bufferView->byteLength ? bufferView->byteLength - byteOffset : 0; |
1015 | 70.9k | } |
1016 | | |
1017 | 0 | return 0; |
1018 | 70.9k | } |
1019 | | |
1020 | | template <class T> |
1021 | 10.7k | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { |
1022 | 10.7k | uint8_t *data = GetPointer(); |
1023 | 10.7k | if (!data) { |
1024 | 106 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); |
1025 | 106 | } |
1026 | | |
1027 | 10.6k | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; |
1028 | 10.6k | const size_t elemSize = GetElementSize(); |
1029 | 10.6k | const size_t totalSize = elemSize * usedCount; |
1030 | | |
1031 | 10.6k | const size_t stride = GetStride(); |
1032 | | |
1033 | 10.6k | const size_t targetElemSize = sizeof(T); |
1034 | | |
1035 | 10.6k | if (elemSize > targetElemSize) { |
1036 | 40 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); |
1037 | 40 | } |
1038 | | |
1039 | 10.6k | const size_t maxSize = GetMaxByteSize(); |
1040 | | |
1041 | 10.6k | outData = new T[usedCount]; |
1042 | | |
1043 | 10.6k | if (remappingIndices != nullptr) { |
1044 | 7.29k | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); |
1045 | 48.9k | for (size_t i = 0; i < usedCount; ++i) { |
1046 | 41.6k | size_t srcIdx = (*remappingIndices)[i]; |
1047 | 41.6k | if (srcIdx >= maxIndexCount) { |
1048 | 2 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); |
1049 | 2 | } |
1050 | 41.6k | memcpy(outData + i, data + srcIdx * stride, elemSize); |
1051 | 41.6k | } |
1052 | 7.29k | } else { // non-indexed cases |
1053 | 3.30k | if (usedCount * stride > maxSize) { |
1054 | 5 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); |
1055 | 5 | } |
1056 | 3.30k | if (stride == elemSize && targetElemSize == elemSize) { |
1057 | 1.59k | memcpy(outData, data, totalSize); |
1058 | 1.71k | } else { |
1059 | 53.3k | for (size_t i = 0; i < usedCount; ++i) { |
1060 | 51.6k | memcpy(outData + i, data + i * stride, elemSize); |
1061 | 51.6k | } |
1062 | 1.71k | } |
1063 | 3.30k | } |
1064 | 10.5k | return usedCount; |
1065 | 10.6k | } glTF2Importer.cpp:unsigned long glTF2::Accessor::ExtractData<BuildVertexWeightMapping(glTF2::Mesh::Primitive&, std::__1::vector<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> >, std::__1::allocator<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> > > >&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*)::Weights>(BuildVertexWeightMapping(glTF2::Mesh::Primitive&, std::__1::vector<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> >, std::__1::allocator<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> > > >&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*)::Weights*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 1.40k | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 1.40k | uint8_t *data = GetPointer(); | 1023 | 1.40k | if (!data) { | 1024 | 15 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 15 | } | 1026 | | | 1027 | 1.39k | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 1.39k | const size_t elemSize = GetElementSize(); | 1029 | 1.39k | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 1.39k | const size_t stride = GetStride(); | 1032 | | | 1033 | 1.39k | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 1.39k | if (elemSize > targetElemSize) { | 1036 | 2 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 2 | } | 1038 | | | 1039 | 1.38k | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 1.38k | outData = new T[usedCount]; | 1042 | | | 1043 | 1.38k | if (remappingIndices != nullptr) { | 1044 | 1.12k | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 5.48k | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 4.36k | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 4.36k | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 4.36k | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 4.36k | } | 1052 | 1.12k | } else { // non-indexed cases | 1053 | 267 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 267 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 217 | memcpy(outData, data, totalSize); | 1058 | 217 | } else { | 1059 | 302 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 252 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 252 | } | 1062 | 50 | } | 1063 | 267 | } | 1064 | 1.38k | return usedCount; | 1065 | 1.38k | } |
glTF2Importer.cpp:unsigned long glTF2::Accessor::ExtractData<BuildVertexWeightMapping(glTF2::Mesh::Primitive&, std::__1::vector<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> >, std::__1::allocator<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> > > >&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*)::Indices8>(BuildVertexWeightMapping(glTF2::Mesh::Primitive&, std::__1::vector<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> >, std::__1::allocator<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> > > >&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*)::Indices8*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 136 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 136 | uint8_t *data = GetPointer(); | 1023 | 136 | if (!data) { | 1024 | 13 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 13 | } | 1026 | | | 1027 | 123 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 123 | const size_t elemSize = GetElementSize(); | 1029 | 123 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 123 | const size_t stride = GetStride(); | 1032 | | | 1033 | 123 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 123 | if (elemSize > targetElemSize) { | 1036 | 21 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 21 | } | 1038 | | | 1039 | 102 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 102 | outData = new T[usedCount]; | 1042 | | | 1043 | 102 | if (remappingIndices != nullptr) { | 1044 | 48 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 306 | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 258 | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 258 | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 258 | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 258 | } | 1052 | 54 | } else { // non-indexed cases | 1053 | 54 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 54 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 35 | memcpy(outData, data, totalSize); | 1058 | 35 | } else { | 1059 | 119 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 100 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 100 | } | 1062 | 19 | } | 1063 | 54 | } | 1064 | 102 | return usedCount; | 1065 | 102 | } |
glTF2Importer.cpp:unsigned long glTF2::Accessor::ExtractData<BuildVertexWeightMapping(glTF2::Mesh::Primitive&, std::__1::vector<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> >, std::__1::allocator<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> > > >&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*)::Indices16>(BuildVertexWeightMapping(glTF2::Mesh::Primitive&, std::__1::vector<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> >, std::__1::allocator<std::__1::vector<aiVertexWeight, std::__1::allocator<aiVertexWeight> > > >&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*)::Indices16*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 1.21k | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 1.21k | uint8_t *data = GetPointer(); | 1023 | 1.21k | if (!data) { | 1024 | 16 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 16 | } | 1026 | | | 1027 | 1.19k | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 1.19k | const size_t elemSize = GetElementSize(); | 1029 | 1.19k | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 1.19k | const size_t stride = GetStride(); | 1032 | | | 1033 | 1.19k | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 1.19k | if (elemSize > targetElemSize) { | 1036 | 7 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 7 | } | 1038 | | | 1039 | 1.18k | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 1.18k | outData = new T[usedCount]; | 1042 | | | 1043 | 1.18k | if (remappingIndices != nullptr) { | 1044 | 1.01k | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 4.89k | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 3.87k | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 3.87k | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 3.87k | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 3.87k | } | 1052 | 1.01k | } else { // non-indexed cases | 1053 | 170 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 170 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 121 | memcpy(outData, data, totalSize); | 1058 | 121 | } else { | 1059 | 315 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 266 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 266 | } | 1062 | 49 | } | 1063 | 170 | } | 1064 | 1.18k | return usedCount; | 1065 | 1.18k | } |
unsigned long glTF2::Accessor::ExtractData<aiVector3t<float> >(aiVector3t<float>*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 6.68k | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 6.68k | uint8_t *data = GetPointer(); | 1023 | 6.68k | if (!data) { | 1024 | 28 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 28 | } | 1026 | | | 1027 | 6.65k | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 6.65k | const size_t elemSize = GetElementSize(); | 1029 | 6.65k | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 6.65k | const size_t stride = GetStride(); | 1032 | | | 1033 | 6.65k | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 6.65k | if (elemSize > targetElemSize) { | 1036 | 5 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 5 | } | 1038 | | | 1039 | 6.65k | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 6.65k | outData = new T[usedCount]; | 1042 | | | 1043 | 6.65k | if (remappingIndices != nullptr) { | 1044 | 4.71k | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 36.4k | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 31.7k | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 31.7k | if (srcIdx >= maxIndexCount) { | 1048 | 2 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 2 | } | 1050 | 31.7k | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 31.7k | } | 1052 | 4.71k | } else { // non-indexed cases | 1053 | 1.93k | if (usedCount * stride > maxSize) { | 1054 | 4 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 4 | } | 1056 | 1.93k | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 631 | memcpy(outData, data, totalSize); | 1058 | 1.29k | } else { | 1059 | 48.0k | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 46.7k | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 46.7k | } | 1062 | 1.29k | } | 1063 | 1.93k | } | 1064 | 6.64k | return usedCount; | 1065 | 6.65k | } |
glTF2Importer.cpp:unsigned long glTF2::Accessor::ExtractData<(anonymous namespace)::Tangent>((anonymous namespace)::Tangent*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 37 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 37 | uint8_t *data = GetPointer(); | 1023 | 37 | if (!data) { | 1024 | 1 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 1 | } | 1026 | | | 1027 | 36 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 36 | const size_t elemSize = GetElementSize(); | 1029 | 36 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 36 | const size_t stride = GetStride(); | 1032 | | | 1033 | 36 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 36 | if (elemSize > targetElemSize) { | 1036 | 0 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 0 | } | 1038 | | | 1039 | 36 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 36 | outData = new T[usedCount]; | 1042 | | | 1043 | 36 | if (remappingIndices != nullptr) { | 1044 | 23 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 164 | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 141 | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 141 | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 141 | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 141 | } | 1052 | 23 | } else { // non-indexed cases | 1053 | 13 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 13 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 3 | memcpy(outData, data, totalSize); | 1058 | 10 | } else { | 1059 | 250 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 240 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 240 | } | 1062 | 10 | } | 1063 | 13 | } | 1064 | 36 | return usedCount; | 1065 | 36 | } |
unsigned long glTF2::Accessor::ExtractData<aiColor4t<float> >(aiColor4t<float>*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 464 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 464 | uint8_t *data = GetPointer(); | 1023 | 464 | if (!data) { | 1024 | 5 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 5 | } | 1026 | | | 1027 | 459 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 459 | const size_t elemSize = GetElementSize(); | 1029 | 459 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 459 | const size_t stride = GetStride(); | 1032 | | | 1033 | 459 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 459 | if (elemSize > targetElemSize) { | 1036 | 0 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 0 | } | 1038 | | | 1039 | 459 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 459 | outData = new T[usedCount]; | 1042 | | | 1043 | 459 | if (remappingIndices != nullptr) { | 1044 | 364 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 1.68k | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 1.31k | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 1.31k | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 1.31k | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 1.31k | } | 1052 | 364 | } else { // non-indexed cases | 1053 | 95 | if (usedCount * stride > maxSize) { | 1054 | 1 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 1 | } | 1056 | 94 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 58 | memcpy(outData, data, totalSize); | 1058 | 58 | } else { | 1059 | 780 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 744 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 744 | } | 1062 | 36 | } | 1063 | 94 | } | 1064 | 458 | return usedCount; | 1065 | 459 | } |
unsigned long glTF2::Accessor::ExtractData<aiColor4t<unsigned char> >(aiColor4t<unsigned char>*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 16 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 16 | uint8_t *data = GetPointer(); | 1023 | 16 | if (!data) { | 1024 | 2 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 2 | } | 1026 | | | 1027 | 14 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 14 | const size_t elemSize = GetElementSize(); | 1029 | 14 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 14 | const size_t stride = GetStride(); | 1032 | | | 1033 | 14 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 14 | if (elemSize > targetElemSize) { | 1036 | 0 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 0 | } | 1038 | | | 1039 | 14 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 14 | outData = new T[usedCount]; | 1042 | | | 1043 | 14 | if (remappingIndices != nullptr) { | 1044 | 1 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 5 | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 4 | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 4 | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 4 | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 4 | } | 1052 | 13 | } else { // non-indexed cases | 1053 | 13 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 13 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 0 | memcpy(outData, data, totalSize); | 1058 | 13 | } else { | 1059 | 65 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 52 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 52 | } | 1062 | 13 | } | 1063 | 13 | } | 1064 | 14 | return usedCount; | 1065 | 14 | } |
unsigned long glTF2::Accessor::ExtractData<aiColor4t<unsigned short> >(aiColor4t<unsigned short>*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 17 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 17 | uint8_t *data = GetPointer(); | 1023 | 17 | if (!data) { | 1024 | 2 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 2 | } | 1026 | | | 1027 | 15 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 15 | const size_t elemSize = GetElementSize(); | 1029 | 15 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 15 | const size_t stride = GetStride(); | 1032 | | | 1033 | 15 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 15 | if (elemSize > targetElemSize) { | 1036 | 0 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 0 | } | 1038 | | | 1039 | 15 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 15 | outData = new T[usedCount]; | 1042 | | | 1043 | 15 | if (remappingIndices != nullptr) { | 1044 | 5 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 25 | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 20 | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 20 | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 20 | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 20 | } | 1052 | 10 | } else { // non-indexed cases | 1053 | 10 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 10 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 8 | memcpy(outData, data, totalSize); | 1058 | 8 | } else { | 1059 | 10 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 8 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 8 | } | 1062 | 2 | } | 1063 | 10 | } | 1064 | 15 | return usedCount; | 1065 | 15 | } |
unsigned long glTF2::Accessor::ExtractData<float [16]>(float (*&) [16], std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 545 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 545 | uint8_t *data = GetPointer(); | 1023 | 545 | if (!data) { | 1024 | 19 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 19 | } | 1026 | | | 1027 | 526 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 526 | const size_t elemSize = GetElementSize(); | 1029 | 526 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 526 | const size_t stride = GetStride(); | 1032 | | | 1033 | 526 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 526 | if (elemSize > targetElemSize) { | 1036 | 0 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 0 | } | 1038 | | | 1039 | 526 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 526 | outData = new T[usedCount]; | 1042 | | | 1043 | 526 | if (remappingIndices != nullptr) { | 1044 | 0 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 0 | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 0 | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 0 | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 0 | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 0 | } | 1052 | 526 | } else { // non-indexed cases | 1053 | 526 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 526 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 402 | memcpy(outData, data, totalSize); | 1058 | 402 | } else { | 1059 | 1.69k | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 1.56k | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 1.56k | } | 1062 | 124 | } | 1063 | 526 | } | 1064 | 526 | return usedCount; | 1065 | 526 | } |
unsigned long glTF2::Accessor::ExtractData<float>(float*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 120 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 120 | uint8_t *data = GetPointer(); | 1023 | 120 | if (!data) { | 1024 | 1 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 1 | } | 1026 | | | 1027 | 119 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 119 | const size_t elemSize = GetElementSize(); | 1029 | 119 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 119 | const size_t stride = GetStride(); | 1032 | | | 1033 | 119 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 119 | if (elemSize > targetElemSize) { | 1036 | 3 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 3 | } | 1038 | | | 1039 | 116 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 116 | outData = new T[usedCount]; | 1042 | | | 1043 | 116 | if (remappingIndices != nullptr) { | 1044 | 0 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 0 | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 0 | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 0 | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 0 | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 0 | } | 1052 | 116 | } else { // non-indexed cases | 1053 | 116 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 116 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 84 | memcpy(outData, data, totalSize); | 1058 | 84 | } else { | 1059 | 370 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 338 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 338 | } | 1062 | 32 | } | 1063 | 116 | } | 1064 | 116 | return usedCount; | 1065 | 116 | } |
unsigned long glTF2::Accessor::ExtractData<vec4f>(vec4f*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 41 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 41 | uint8_t *data = GetPointer(); | 1023 | 41 | if (!data) { | 1024 | 3 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 3 | } | 1026 | | | 1027 | 38 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 38 | const size_t elemSize = GetElementSize(); | 1029 | 38 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 38 | const size_t stride = GetStride(); | 1032 | | | 1033 | 38 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 38 | if (elemSize > targetElemSize) { | 1036 | 1 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 1 | } | 1038 | | | 1039 | 37 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 37 | outData = new T[usedCount]; | 1042 | | | 1043 | 37 | if (remappingIndices != nullptr) { | 1044 | 0 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 0 | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 0 | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 0 | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 0 | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 0 | } | 1052 | 37 | } else { // non-indexed cases | 1053 | 37 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 37 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 6 | memcpy(outData, data, totalSize); | 1058 | 31 | } else { | 1059 | 575 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 544 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 544 | } | 1062 | 31 | } | 1063 | 37 | } | 1064 | 37 | return usedCount; | 1065 | 37 | } |
unsigned long glTF2::Accessor::ExtractData<aiQuaterniont<float> >(aiQuaterniont<float>*&, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const*) Line | Count | Source | 1021 | 74 | size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) { | 1022 | 74 | uint8_t *data = GetPointer(); | 1023 | 74 | if (!data) { | 1024 | 1 | throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name)); | 1025 | 1 | } | 1026 | | | 1027 | 73 | const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count; | 1028 | 73 | const size_t elemSize = GetElementSize(); | 1029 | 73 | const size_t totalSize = elemSize * usedCount; | 1030 | | | 1031 | 73 | const size_t stride = GetStride(); | 1032 | | | 1033 | 73 | const size_t targetElemSize = sizeof(T); | 1034 | | | 1035 | 73 | if (elemSize > targetElemSize) { | 1036 | 1 | throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name)); | 1037 | 1 | } | 1038 | | | 1039 | 72 | const size_t maxSize = GetMaxByteSize(); | 1040 | | | 1041 | 72 | outData = new T[usedCount]; | 1042 | | | 1043 | 72 | if (remappingIndices != nullptr) { | 1044 | 0 | const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); | 1045 | 0 | for (size_t i = 0; i < usedCount; ++i) { | 1046 | 0 | size_t srcIdx = (*remappingIndices)[i]; | 1047 | 0 | if (srcIdx >= maxIndexCount) { | 1048 | 0 | throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1049 | 0 | } | 1050 | 0 | memcpy(outData + i, data + srcIdx * stride, elemSize); | 1051 | 0 | } | 1052 | 72 | } else { // non-indexed cases | 1053 | 72 | if (usedCount * stride > maxSize) { | 1054 | 0 | throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); | 1055 | 0 | } | 1056 | 72 | if (stride == elemSize && targetElemSize == elemSize) { | 1057 | 25 | memcpy(outData, data, totalSize); | 1058 | 47 | } else { | 1059 | 868 | for (size_t i = 0; i < usedCount; ++i) { | 1060 | 821 | memcpy(outData + i, data + i * stride, elemSize); | 1061 | 821 | } | 1062 | 47 | } | 1063 | 72 | } | 1064 | 72 | return usedCount; | 1065 | 72 | } |
|
1066 | | |
1067 | 0 | inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t src_stride) { |
1068 | 0 | uint8_t *buffer_ptr = bufferView->buffer->GetPointer(); |
1069 | 0 | size_t offset = byteOffset + bufferView->byteOffset; |
1070 | 0 |
|
1071 | 0 | size_t dst_stride = GetNumComponents() * GetBytesPerComponent(); |
1072 | 0 |
|
1073 | 0 | const uint8_t *src = reinterpret_cast<const uint8_t *>(src_buffer); |
1074 | 0 | uint8_t *dst = reinterpret_cast<uint8_t *>(buffer_ptr + offset); |
1075 | 0 |
|
1076 | 0 | ai_assert(dst + _count * dst_stride <= buffer_ptr + bufferView->buffer->byteLength); |
1077 | 0 | CopyData(_count, src, src_stride, dst, dst_stride); |
1078 | 0 | } |
1079 | | |
1080 | 0 | inline void Accessor::WriteSparseValues(size_t _count, const void *src_data, size_t src_dataStride) { |
1081 | 0 | if (!sparse) |
1082 | 0 | return; |
1083 | 0 |
|
1084 | 0 | // values |
1085 | 0 | uint8_t *value_buffer_ptr = sparse->values->buffer->GetPointer(); |
1086 | 0 | size_t value_offset = sparse->valuesByteOffset + sparse->values->byteOffset; |
1087 | 0 | size_t value_dst_stride = GetNumComponents() * GetBytesPerComponent(); |
1088 | 0 | const uint8_t *value_src = reinterpret_cast<const uint8_t *>(src_data); |
1089 | 0 | uint8_t *value_dst = reinterpret_cast<uint8_t *>(value_buffer_ptr + value_offset); |
1090 | 0 | ai_assert(value_dst + _count * value_dst_stride <= value_buffer_ptr + sparse->values->buffer->byteLength); |
1091 | 0 | CopyData(_count, value_src, src_dataStride, value_dst, value_dst_stride); |
1092 | 0 | } |
1093 | | |
1094 | 0 | inline void Accessor::WriteSparseIndices(size_t _count, const void *src_idx, size_t src_idxStride) { |
1095 | 0 | if (!sparse) |
1096 | 0 | return; |
1097 | 0 |
|
1098 | 0 | // indices |
1099 | 0 | uint8_t *indices_buffer_ptr = sparse->indices->buffer->GetPointer(); |
1100 | 0 | size_t indices_offset = sparse->indicesByteOffset + sparse->indices->byteOffset; |
1101 | 0 | size_t indices_dst_stride = 1 * sizeof(unsigned short); |
1102 | 0 | const uint8_t *indices_src = reinterpret_cast<const uint8_t *>(src_idx); |
1103 | 0 | uint8_t *indices_dst = reinterpret_cast<uint8_t *>(indices_buffer_ptr + indices_offset); |
1104 | 0 | ai_assert(indices_dst + _count * indices_dst_stride <= indices_buffer_ptr + sparse->indices->buffer->byteLength); |
1105 | 0 | CopyData(_count, indices_src, src_idxStride, indices_dst, indices_dst_stride); |
1106 | 0 | } |
1107 | | |
1108 | | inline Accessor::Indexer::Indexer(Accessor &acc) : |
1109 | 2.47k | accessor(acc), |
1110 | 2.47k | data(acc.GetPointer()), |
1111 | 2.47k | elemSize(acc.GetElementSize()), |
1112 | 2.47k | stride(acc.GetStride()) { |
1113 | 2.47k | } |
1114 | | |
1115 | | //! Accesses the i-th value as defined by the accessor |
1116 | | template <class T> |
1117 | 60.3k | T Accessor::Indexer::GetValue(int i) { |
1118 | 60.3k | ai_assert(data); |
1119 | 60.3k | if (i * stride >= accessor.GetMaxByteSize()) { |
1120 | 1 | throw DeadlyImportError("GLTF: Invalid index ", i, ", count out of range for buffer with stride ", stride, " and size ", accessor.GetMaxByteSize(), "."); |
1121 | 1 | } |
1122 | | // Ensure that the memcpy doesn't overwrite the local. |
1123 | 60.3k | const size_t sizeToCopy = std::min(elemSize, sizeof(T)); |
1124 | 60.3k | T value = T(); |
1125 | | // Assume platform endianness matches GLTF binary data (which is little-endian). |
1126 | 60.3k | memcpy(&value, data + i * stride, sizeToCopy); |
1127 | 60.3k | return value; |
1128 | 60.3k | } |
1129 | | |
1130 | | inline Image::Image() : |
1131 | 258 | width(0), |
1132 | 258 | height(0), |
1133 | 258 | mDataLength(0) { |
1134 | 258 | } |
1135 | | |
1136 | 258 | inline void Image::Read(Value &obj, Asset &r) { |
1137 | | //basisu: no need to handle .ktx2, .basis, load as is |
1138 | 258 | if (!mDataLength) { |
1139 | 258 | Value *curUri = FindString(obj, "uri"); |
1140 | 258 | if (nullptr != curUri) { |
1141 | 129 | const char *uristr = curUri->GetString(); |
1142 | | |
1143 | 129 | glTFCommon::Util::DataURI dataURI; |
1144 | 129 | if (ParseDataURI(uristr, curUri->GetStringLength(), dataURI)) { |
1145 | 108 | mimeType = dataURI.mediaType; |
1146 | 108 | if (dataURI.base64) { |
1147 | 101 | uint8_t *ptr = nullptr; |
1148 | 101 | mDataLength = Base64::Decode(dataURI.data, dataURI.dataLength, ptr); |
1149 | 101 | mData.reset(ptr); |
1150 | 101 | } |
1151 | 108 | } else { |
1152 | 21 | this->uri = uristr; |
1153 | 21 | } |
1154 | 129 | } else if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { |
1155 | 124 | this->bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); |
1156 | 124 | if (Value *mtype = FindString(obj, "mimeType")) { |
1157 | 119 | this->mimeType = mtype->GetString(); |
1158 | 119 | } |
1159 | 124 | if (!this->bufferView || this->mimeType.empty()) { |
1160 | 2 | throw DeadlyImportError("GLTF2: ", getContextForErrorMessages(id, name), " does not have a URI, so it must have a valid bufferView and mimetype"); |
1161 | 2 | } |
1162 | | |
1163 | 122 | Ref<Buffer> buffer = this->bufferView->buffer; |
1164 | | |
1165 | 122 | this->mDataLength = this->bufferView->byteLength; |
1166 | | // maybe this memcpy could be avoided if aiTexture does not delete[] pcData at destruction. |
1167 | | |
1168 | 122 | this->mData.reset(new uint8_t[this->mDataLength]); |
1169 | 122 | memcpy(this->mData.get(), buffer->GetPointer() + this->bufferView->byteOffset, this->mDataLength); |
1170 | 122 | } else { |
1171 | 5 | throw DeadlyImportError("GLTF2: ", getContextForErrorMessages(id, name), " should have either a URI of a bufferView and mimetype"); |
1172 | 5 | } |
1173 | 258 | } |
1174 | 258 | } |
1175 | | |
1176 | 165 | inline uint8_t *Image::StealData() { |
1177 | 165 | mDataLength = 0; |
1178 | 165 | return mData.release(); |
1179 | 165 | } |
1180 | | |
1181 | | // Never take over the ownership of data whenever binary or not |
1182 | 0 | inline void Image::SetData(uint8_t *data, size_t length, Asset &r) { |
1183 | 0 | Ref<Buffer> b = r.GetBodyBuffer(); |
1184 | 0 | if (b) { // binary file: append to body |
1185 | 0 | std::string bvId = r.FindUniqueID(this->id, "imgdata"); |
1186 | 0 | bufferView = r.bufferViews.Create(bvId); |
1187 | 0 |
|
1188 | 0 | bufferView->buffer = b; |
1189 | 0 | bufferView->byteLength = length; |
1190 | 0 | bufferView->byteOffset = b->AppendData(data, length); |
1191 | 0 | } else { // text file: will be stored as a data uri |
1192 | 0 | uint8_t *temp = new uint8_t[length]; |
1193 | 0 | memcpy(temp, data, length); |
1194 | 0 | this->mData.reset(temp); |
1195 | 0 | this->mDataLength = length; |
1196 | 0 | } |
1197 | 0 | } |
1198 | | |
1199 | 224 | inline void Sampler::Read(Value &obj, Asset & /*r*/) { |
1200 | 224 | SetDefaults(); |
1201 | | |
1202 | 224 | ReadMember(obj, "name", name); |
1203 | 224 | ReadMember(obj, "magFilter", magFilter); |
1204 | 224 | ReadMember(obj, "minFilter", minFilter); |
1205 | 224 | ReadMember(obj, "wrapS", wrapS); |
1206 | 224 | ReadMember(obj, "wrapT", wrapT); |
1207 | 224 | } |
1208 | | |
1209 | 448 | inline void Sampler::SetDefaults() { |
1210 | | //only wrapping modes have defaults |
1211 | 448 | wrapS = SamplerWrap::Repeat; |
1212 | 448 | wrapT = SamplerWrap::Repeat; |
1213 | 448 | magFilter = SamplerMagFilter::UNSET; |
1214 | 448 | minFilter = SamplerMinFilter::UNSET; |
1215 | 448 | } |
1216 | | |
1217 | 299 | inline void Texture::Read(Value &obj, Asset &r) { |
1218 | 299 | if (Value *sourceVal = FindUInt(obj, "source")) { |
1219 | 268 | source = r.images.Retrieve(sourceVal->GetUint()); |
1220 | 268 | } |
1221 | | |
1222 | 299 | if (Value *samplerVal = FindUInt(obj, "sampler")) { |
1223 | 238 | sampler = r.samplers.Retrieve(samplerVal->GetUint()); |
1224 | 238 | } |
1225 | | |
1226 | 299 | if (Value *extensions = FindObject(obj, "extensions")) { |
1227 | 0 | if (r.extensionsUsed.KHR_texture_basisu) { |
1228 | 0 | if (Value *curBasisU = FindObject(*extensions, "KHR_texture_basisu")) { |
1229 | |
|
1230 | 0 | if (Value *sourceVal = FindUInt(*curBasisU, "source")) { |
1231 | 0 | source = r.images.Retrieve(sourceVal->GetUint()); |
1232 | 0 | } |
1233 | 0 | } |
1234 | 0 | } else if(r.extensionsUsed.EXT_texture_webp) { |
1235 | 0 | if (Value *curBasisU = FindObject(*extensions, "EXT_texture_webp")) { |
1236 | |
|
1237 | 0 | if (Value *sourceVal = FindUInt(*curBasisU, "source")) { |
1238 | 0 | source = r.images.Retrieve(sourceVal->GetUint()); |
1239 | 0 | } |
1240 | 0 | } |
1241 | 0 | } |
1242 | 0 | } |
1243 | 299 | } |
1244 | | |
1245 | 409 | void Material::SetTextureProperties(Asset &r, Value *prop, TextureInfo &out) { |
1246 | 409 | if (r.extensionsUsed.KHR_texture_transform) { |
1247 | 4 | if (Value *pKHR_texture_transform = FindExtension(*prop, "KHR_texture_transform")) { |
1248 | 0 | out.textureTransformSupported = true; |
1249 | 0 | if (Value *array = FindArray(*pKHR_texture_transform, "offset")) { |
1250 | 0 | out.TextureTransformExt_t.offset[0] = (*array)[0].GetFloat(); |
1251 | 0 | out.TextureTransformExt_t.offset[1] = (*array)[1].GetFloat(); |
1252 | 0 | } else { |
1253 | 0 | out.TextureTransformExt_t.offset[0] = 0; |
1254 | 0 | out.TextureTransformExt_t.offset[1] = 0; |
1255 | 0 | } |
1256 | |
|
1257 | 0 | if (!ReadMember(*pKHR_texture_transform, "rotation", out.TextureTransformExt_t.rotation)) { |
1258 | 0 | out.TextureTransformExt_t.rotation = 0; |
1259 | 0 | } |
1260 | |
|
1261 | 0 | if (Value *array = FindArray(*pKHR_texture_transform, "scale")) { |
1262 | 0 | out.TextureTransformExt_t.scale[0] = (*array)[0].GetFloat(); |
1263 | 0 | out.TextureTransformExt_t.scale[1] = (*array)[1].GetFloat(); |
1264 | 0 | } else { |
1265 | 0 | out.TextureTransformExt_t.scale[0] = 1; |
1266 | 0 | out.TextureTransformExt_t.scale[1] = 1; |
1267 | 0 | } |
1268 | 0 | } |
1269 | 4 | } |
1270 | | |
1271 | 409 | if (Value *indexProp = FindUInt(*prop, "index")) { |
1272 | 400 | out.texture = r.textures.Retrieve(indexProp->GetUint()); |
1273 | 400 | } |
1274 | | |
1275 | 409 | if (Value *texcoord = FindUInt(*prop, "texCoord")) { |
1276 | 1 | out.texCoord = texcoord->GetUint(); |
1277 | 1 | } |
1278 | 409 | } |
1279 | | |
1280 | 13.0k | inline void Material::ReadTextureProperty(Asset &r, Value &vals, const char *propName, TextureInfo &out) { |
1281 | 13.0k | if (Value *prop = FindMember(vals, propName)) { |
1282 | 409 | SetTextureProperties(r, prop, out); |
1283 | 409 | } |
1284 | 13.0k | } |
1285 | | |
1286 | 4.74k | inline void Material::ReadTextureProperty(Asset &r, Value &vals, const char *propName, NormalTextureInfo &out) { |
1287 | 4.74k | if (Value *prop = FindMember(vals, propName)) { |
1288 | 0 | SetTextureProperties(r, prop, out); |
1289 | |
|
1290 | 0 | if (Value *scale = FindNumber(*prop, "scale")) { |
1291 | 0 | out.scale = static_cast<float>(scale->GetDouble()); |
1292 | 0 | } |
1293 | 0 | } |
1294 | 4.74k | } |
1295 | | |
1296 | 4.74k | inline void Material::ReadTextureProperty(Asset &r, Value &vals, const char *propName, OcclusionTextureInfo &out) { |
1297 | 4.74k | if (Value *prop = FindMember(vals, propName)) { |
1298 | 0 | SetTextureProperties(r, prop, out); |
1299 | |
|
1300 | 0 | if (Value *strength = FindNumber(*prop, "strength")) { |
1301 | 0 | out.strength = static_cast<float>(strength->GetDouble()); |
1302 | 0 | } |
1303 | 0 | } |
1304 | 4.74k | } |
1305 | | |
1306 | 4.80k | inline void Material::Read(Value &material, Asset &r) { |
1307 | 4.80k | SetDefaults(); |
1308 | | |
1309 | 4.80k | if (Value *curPbrMetallicRoughness = FindObject(material, "pbrMetallicRoughness")) { |
1310 | 4.19k | ReadMember(*curPbrMetallicRoughness, "baseColorFactor", this->pbrMetallicRoughness.baseColorFactor); |
1311 | 4.19k | ReadTextureProperty(r, *curPbrMetallicRoughness, "baseColorTexture", this->pbrMetallicRoughness.baseColorTexture); |
1312 | 4.19k | ReadTextureProperty(r, *curPbrMetallicRoughness, "metallicRoughnessTexture", this->pbrMetallicRoughness.metallicRoughnessTexture); |
1313 | 4.19k | ReadMember(*curPbrMetallicRoughness, "metallicFactor", this->pbrMetallicRoughness.metallicFactor); |
1314 | 4.19k | ReadMember(*curPbrMetallicRoughness, "roughnessFactor", this->pbrMetallicRoughness.roughnessFactor); |
1315 | 4.19k | } |
1316 | | |
1317 | 4.80k | ReadTextureProperty(r, material, "normalTexture", this->normalTexture); |
1318 | 4.80k | ReadTextureProperty(r, material, "occlusionTexture", this->occlusionTexture); |
1319 | 4.80k | ReadTextureProperty(r, material, "emissiveTexture", this->emissiveTexture); |
1320 | 4.80k | ReadMember(material, "emissiveFactor", this->emissiveFactor); |
1321 | | |
1322 | 4.80k | ReadMember(material, "doubleSided", this->doubleSided); |
1323 | 4.80k | ReadMember(material, "alphaMode", this->alphaMode); |
1324 | 4.80k | ReadMember(material, "alphaCutoff", this->alphaCutoff); |
1325 | | |
1326 | 4.80k | if (Value *extensions = FindObject(material, "extensions")) { |
1327 | 0 | if (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { |
1328 | 0 | if (Value *curPbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) { |
1329 | 0 | PbrSpecularGlossiness pbrSG; |
1330 | |
|
1331 | 0 | ReadMember(*curPbrSpecularGlossiness, "diffuseFactor", pbrSG.diffuseFactor); |
1332 | 0 | ReadTextureProperty(r, *curPbrSpecularGlossiness, "diffuseTexture", pbrSG.diffuseTexture); |
1333 | 0 | ReadTextureProperty(r, *curPbrSpecularGlossiness, "specularGlossinessTexture", pbrSG.specularGlossinessTexture); |
1334 | 0 | ReadMember(*curPbrSpecularGlossiness, "specularFactor", pbrSG.specularFactor); |
1335 | 0 | ReadMember(*curPbrSpecularGlossiness, "glossinessFactor", pbrSG.glossinessFactor); |
1336 | |
|
1337 | 0 | this->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG); |
1338 | 0 | } |
1339 | 0 | } |
1340 | |
|
1341 | 0 | if (r.extensionsUsed.KHR_materials_specular) { |
1342 | 0 | if (Value *curMatSpecular = FindObject(*extensions, "KHR_materials_specular")) { |
1343 | 0 | MaterialSpecular specular; |
1344 | |
|
1345 | 0 | ReadMember(*curMatSpecular, "specularFactor", specular.specularFactor); |
1346 | 0 | ReadTextureProperty(r, *curMatSpecular, "specularTexture", specular.specularTexture); |
1347 | 0 | ReadMember(*curMatSpecular, "specularColorFactor", specular.specularColorFactor); |
1348 | 0 | ReadTextureProperty(r, *curMatSpecular, "specularColorTexture", specular.specularColorTexture); |
1349 | |
|
1350 | 0 | this->materialSpecular = Nullable<MaterialSpecular>(specular); |
1351 | 0 | } |
1352 | 0 | } |
1353 | | |
1354 | | // Extension KHR_texture_transform is handled in ReadTextureProperty |
1355 | |
|
1356 | 0 | if (r.extensionsUsed.KHR_materials_sheen) { |
1357 | 0 | if (Value *curMaterialSheen = FindObject(*extensions, "KHR_materials_sheen")) { |
1358 | 0 | MaterialSheen sheen; |
1359 | |
|
1360 | 0 | ReadMember(*curMaterialSheen, "sheenColorFactor", sheen.sheenColorFactor); |
1361 | 0 | ReadTextureProperty(r, *curMaterialSheen, "sheenColorTexture", sheen.sheenColorTexture); |
1362 | 0 | ReadMember(*curMaterialSheen, "sheenRoughnessFactor", sheen.sheenRoughnessFactor); |
1363 | 0 | ReadTextureProperty(r, *curMaterialSheen, "sheenRoughnessTexture", sheen.sheenRoughnessTexture); |
1364 | |
|
1365 | 0 | this->materialSheen = Nullable<MaterialSheen>(sheen); |
1366 | 0 | } |
1367 | 0 | } |
1368 | |
|
1369 | 0 | if (r.extensionsUsed.KHR_materials_clearcoat) { |
1370 | 0 | if (Value *curMaterialClearcoat = FindObject(*extensions, "KHR_materials_clearcoat")) { |
1371 | 0 | MaterialClearcoat clearcoat; |
1372 | |
|
1373 | 0 | ReadMember(*curMaterialClearcoat, "clearcoatFactor", clearcoat.clearcoatFactor); |
1374 | 0 | ReadTextureProperty(r, *curMaterialClearcoat, "clearcoatTexture", clearcoat.clearcoatTexture); |
1375 | 0 | ReadMember(*curMaterialClearcoat, "clearcoatRoughnessFactor", clearcoat.clearcoatRoughnessFactor); |
1376 | 0 | ReadTextureProperty(r, *curMaterialClearcoat, "clearcoatRoughnessTexture", clearcoat.clearcoatRoughnessTexture); |
1377 | 0 | ReadTextureProperty(r, *curMaterialClearcoat, "clearcoatNormalTexture", clearcoat.clearcoatNormalTexture); |
1378 | |
|
1379 | 0 | this->materialClearcoat = Nullable<MaterialClearcoat>(clearcoat); |
1380 | 0 | } |
1381 | 0 | } |
1382 | |
|
1383 | 0 | if (r.extensionsUsed.KHR_materials_transmission) { |
1384 | 0 | if (Value *curMaterialTransmission = FindObject(*extensions, "KHR_materials_transmission")) { |
1385 | 0 | MaterialTransmission transmission; |
1386 | |
|
1387 | 0 | ReadMember(*curMaterialTransmission, "transmissionFactor", transmission.transmissionFactor); |
1388 | 0 | ReadTextureProperty(r, *curMaterialTransmission, "transmissionTexture", transmission.transmissionTexture); |
1389 | |
|
1390 | 0 | this->materialTransmission = Nullable<MaterialTransmission>(transmission); |
1391 | 0 | } |
1392 | 0 | } |
1393 | |
|
1394 | 0 | if (r.extensionsUsed.KHR_materials_volume) { |
1395 | 0 | if (Value *curMaterialVolume = FindObject(*extensions, "KHR_materials_volume")) { |
1396 | 0 | MaterialVolume volume; |
1397 | |
|
1398 | 0 | ReadMember(*curMaterialVolume, "thicknessFactor", volume.thicknessFactor); |
1399 | 0 | ReadTextureProperty(r, *curMaterialVolume, "thicknessTexture", volume.thicknessTexture); |
1400 | 0 | ReadMember(*curMaterialVolume, "attenuationDistance", volume.attenuationDistance); |
1401 | 0 | ReadMember(*curMaterialVolume, "attenuationColor", volume.attenuationColor); |
1402 | |
|
1403 | 0 | this->materialVolume = Nullable<MaterialVolume>(volume); |
1404 | 0 | } |
1405 | 0 | } |
1406 | |
|
1407 | 0 | if (r.extensionsUsed.KHR_materials_ior) { |
1408 | 0 | if (Value *curMaterialIOR = FindObject(*extensions, "KHR_materials_ior")) { |
1409 | 0 | MaterialIOR ior; |
1410 | |
|
1411 | 0 | ReadMember(*curMaterialIOR, "ior", ior.ior); |
1412 | |
|
1413 | 0 | this->materialIOR = Nullable<MaterialIOR>(ior); |
1414 | 0 | } |
1415 | 0 | } |
1416 | |
|
1417 | 0 | if (r.extensionsUsed.KHR_materials_emissive_strength) { |
1418 | 0 | if (Value *curMaterialEmissiveStrength = FindObject(*extensions, "KHR_materials_emissive_strength")) { |
1419 | 0 | MaterialEmissiveStrength emissiveStrength; |
1420 | |
|
1421 | 0 | ReadMember(*curMaterialEmissiveStrength, "emissiveStrength", emissiveStrength.emissiveStrength); |
1422 | |
|
1423 | 0 | this->materialEmissiveStrength = Nullable<MaterialEmissiveStrength>(emissiveStrength); |
1424 | 0 | } |
1425 | 0 | } |
1426 | |
|
1427 | 0 | if (r.extensionsUsed.KHR_materials_anisotropy) { |
1428 | 0 | if (Value *curMaterialAnisotropy = FindObject(*extensions, "KHR_materials_anisotropy")) { |
1429 | 0 | MaterialAnisotropy anisotropy; |
1430 | |
|
1431 | 0 | ReadMember(*curMaterialAnisotropy, "anisotropyStrength", anisotropy.anisotropyStrength); |
1432 | 0 | ReadMember(*curMaterialAnisotropy, "anisotropyRotation", anisotropy.anisotropyRotation); |
1433 | 0 | ReadTextureProperty(r, *curMaterialAnisotropy, "anisotropyTexture", anisotropy.anisotropyTexture); |
1434 | |
|
1435 | 0 | this->materialAnisotropy = Nullable<MaterialAnisotropy>(anisotropy); |
1436 | 0 | } |
1437 | 0 | } |
1438 | |
|
1439 | 0 | unlit = nullptr != FindObject(*extensions, "KHR_materials_unlit"); |
1440 | 0 | } |
1441 | 4.80k | } |
1442 | | |
1443 | 13.8k | inline void Material::SetDefaults() { |
1444 | | //pbr materials |
1445 | 13.8k | SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor); |
1446 | 13.8k | pbrMetallicRoughness.metallicFactor = 1.0f; |
1447 | 13.8k | pbrMetallicRoughness.roughnessFactor = 1.0f; |
1448 | | |
1449 | 13.8k | SetVector(emissiveFactor, defaultEmissiveFactor); |
1450 | 13.8k | alphaMode = "OPAQUE"; |
1451 | 13.8k | alphaCutoff = 0.5f; |
1452 | 13.8k | doubleSided = false; |
1453 | 13.8k | unlit = false; |
1454 | 13.8k | } |
1455 | | |
1456 | 9.04k | inline void PbrSpecularGlossiness::SetDefaults() { |
1457 | | //pbrSpecularGlossiness properties |
1458 | 9.04k | SetVector(diffuseFactor, defaultDiffuseFactor); |
1459 | 9.04k | SetVector(specularFactor, defaultSpecularFactor); |
1460 | 9.04k | glossinessFactor = 1.0f; |
1461 | 9.04k | } |
1462 | | |
1463 | 9.04k | inline void MaterialSpecular::SetDefaults() { |
1464 | | //KHR_materials_specular properties |
1465 | 9.04k | SetVector(specularColorFactor, defaultSpecularColorFactor); |
1466 | 9.04k | specularFactor = 1.f; |
1467 | 9.04k | } |
1468 | | |
1469 | 9.04k | inline void MaterialSheen::SetDefaults() { |
1470 | | //KHR_materials_sheen properties |
1471 | 9.04k | SetVector(sheenColorFactor, defaultSheenFactor); |
1472 | 9.04k | sheenRoughnessFactor = 0.f; |
1473 | 9.04k | } |
1474 | | |
1475 | 9.04k | inline void MaterialVolume::SetDefaults() { |
1476 | | //KHR_materials_volume properties |
1477 | 9.04k | thicknessFactor = 0.f; |
1478 | 9.04k | attenuationDistance = std::numeric_limits<float>::infinity(); |
1479 | 9.04k | SetVector(attenuationColor, defaultAttenuationColor); |
1480 | 9.04k | } |
1481 | | |
1482 | 9.04k | inline void MaterialIOR::SetDefaults() { |
1483 | | //KHR_materials_ior properties |
1484 | 9.04k | ior = 1.5f; |
1485 | 9.04k | } |
1486 | | |
1487 | 9.04k | inline void MaterialEmissiveStrength::SetDefaults() { |
1488 | | //KHR_materials_emissive_strength properties |
1489 | 9.04k | emissiveStrength = 0.f; |
1490 | 9.04k | } |
1491 | | |
1492 | 9.04k | inline void MaterialAnisotropy::SetDefaults() { |
1493 | | //KHR_materials_anisotropy properties |
1494 | 9.04k | anisotropyStrength = 0.f; |
1495 | 9.04k | anisotropyRotation = 0.f; |
1496 | 9.04k | } |
1497 | | |
1498 | 6.60k | inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) { |
1499 | 6.60k | Value *curName = FindMember(pJSON_Object, "name"); |
1500 | 6.60k | if (nullptr != curName && curName->IsString()) { |
1501 | 4.91k | name = curName->GetString(); |
1502 | 4.91k | } |
1503 | | |
1504 | | /****************** Mesh primitives ******************/ |
1505 | 6.60k | Value *curPrimitives = FindArray(pJSON_Object, "primitives"); |
1506 | 6.60k | if (nullptr != curPrimitives) { |
1507 | 6.20k | this->primitives.resize(curPrimitives->Size()); |
1508 | 12.7k | for (unsigned int i = 0; i < curPrimitives->Size(); ++i) { |
1509 | 6.57k | Value &primitive = (*curPrimitives)[i]; |
1510 | | |
1511 | 6.57k | Primitive &prim = this->primitives[i]; |
1512 | 6.57k | prim.mode = MemberOrDefault(primitive, "mode", PrimitiveMode_TRIANGLES); |
1513 | | |
1514 | 6.57k | if (Value *indices = FindUInt(primitive, "indices")) { |
1515 | 5.00k | prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint()); |
1516 | 5.00k | } |
1517 | | |
1518 | 6.57k | if (Value *material = FindUInt(primitive, "material")) { |
1519 | 4.88k | prim.material = pAsset_Root.materials.Retrieve(material->GetUint()); |
1520 | 4.88k | } |
1521 | | |
1522 | 6.57k | if (Value *attrs = FindObject(primitive, "attributes")) { |
1523 | 22.7k | for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) { |
1524 | 16.9k | if (!it->value.IsUint()) continue; |
1525 | 16.9k | const char *attr = it->name.GetString(); |
1526 | | // Valid attribute semantics include POSITION, NORMAL, TANGENT, TEXCOORD, COLOR, JOINT, JOINTMATRIX, |
1527 | | // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. |
1528 | | |
1529 | 16.9k | int undPos = 0; |
1530 | 16.9k | Mesh::AccessorList *vec = nullptr; |
1531 | 16.9k | if (GetAttribVector(prim, attr, vec, undPos)) { |
1532 | 15.9k | size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; |
1533 | 15.9k | if ((*vec).size() != idx) { |
1534 | 46 | throw DeadlyImportError("GLTF: Invalid attribute in mesh: ", name, " primitive: ", i, "attrib: ", attr, |
1535 | 46 | ". All indices for indexed attribute semantics must start with 0 and be continuous positive integers: TEXCOORD_0, TEXCOORD_1, etc."); |
1536 | 46 | } |
1537 | 15.9k | (*vec).resize(idx + 1); |
1538 | 15.9k | (*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint()); |
1539 | 15.9k | } |
1540 | 16.9k | } |
1541 | 5.83k | } |
1542 | | |
1543 | | #ifdef ASSIMP_ENABLE_DRACO |
1544 | | // KHR_draco_mesh_compression spec: Draco can only be used for glTF Triangles or Triangle Strips |
1545 | | if (pAsset_Root.extensionsUsed.KHR_draco_mesh_compression && (prim.mode == PrimitiveMode_TRIANGLES || prim.mode == PrimitiveMode_TRIANGLE_STRIP)) { |
1546 | | // Look for draco mesh compression extension and bufferView |
1547 | | // Skip if any missing |
1548 | | if (Value *dracoExt = FindExtension(primitive, "KHR_draco_mesh_compression")) { |
1549 | | if (Value *bufView = FindUInt(*dracoExt, "bufferView")) { |
1550 | | // Attempt to load indices and attributes using draco compression |
1551 | | auto bufferView = pAsset_Root.bufferViews.Retrieve(bufView->GetUint()); |
1552 | | // Attempt to perform the draco decode on the buffer data |
1553 | | const char *bufferViewData = reinterpret_cast<const char *>(bufferView->buffer->GetPointer() + bufferView->byteOffset); |
1554 | | draco::DecoderBuffer decoderBuffer; |
1555 | | decoderBuffer.Init(bufferViewData, bufferView->byteLength); |
1556 | | draco::Decoder decoder; |
1557 | | auto decodeResult = decoder.DecodeMeshFromBuffer(&decoderBuffer); |
1558 | | if (!decodeResult.ok()) { |
1559 | | // A corrupt Draco isn't actually fatal if the primitive data is also provided in a standard buffer, but does anyone do that? |
1560 | | throw DeadlyImportError("GLTF: Invalid Draco mesh compression in mesh: ", name, " primitive: ", i, ": ", decodeResult.status().error_msg_string()); |
1561 | | } |
1562 | | |
1563 | | // Now we have a draco mesh |
1564 | | const std::unique_ptr<draco::Mesh> &pDracoMesh = decodeResult.value(); |
1565 | | |
1566 | | // Redirect the accessors to the decoded data |
1567 | | |
1568 | | // Indices |
1569 | | SetDecodedIndexBuffer_Draco(*pDracoMesh, prim); |
1570 | | |
1571 | | // Vertex attributes |
1572 | | if (Value *attrs = FindObject(*dracoExt, "attributes")) { |
1573 | | for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) { |
1574 | | if (!it->value.IsUint()) continue; |
1575 | | const char *attr = it->name.GetString(); |
1576 | | |
1577 | | int undPos = 0; |
1578 | | Mesh::AccessorList *vec = nullptr; |
1579 | | if (GetAttribVector(prim, attr, vec, undPos)) { |
1580 | | size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; |
1581 | | if (idx >= (*vec).size()) { |
1582 | | throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr, |
1583 | | ". All indices for indexed attribute semantics must start with 0 and be continuous positive integers: TEXCOORD_0, TEXCOORD_1, etc."); |
1584 | | } |
1585 | | |
1586 | | if (!(*vec)[idx]) { |
1587 | | throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr, |
1588 | | ". All draco-encoded attributes must also define an accessor."); |
1589 | | } |
1590 | | |
1591 | | Accessor &attribAccessor = *(*vec)[idx]; |
1592 | | if (attribAccessor.count == 0) |
1593 | | throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr); |
1594 | | |
1595 | | // Redirect this accessor to the appropriate Draco vertex attribute data |
1596 | | const uint32_t dracoAttribId = it->value.GetUint(); |
1597 | | SetDecodedAttributeBuffer_Draco(*pDracoMesh, dracoAttribId, attribAccessor); |
1598 | | } |
1599 | | } |
1600 | | } |
1601 | | } |
1602 | | } |
1603 | | } |
1604 | | #endif |
1605 | | |
1606 | 6.52k | Value *targetsArray = FindArray(primitive, "targets"); |
1607 | 6.52k | if (nullptr != targetsArray) { |
1608 | 20 | prim.targets.resize(targetsArray->Size()); |
1609 | 56 | for (unsigned int j = 0; j < targetsArray->Size(); ++j) { |
1610 | 36 | Value &target = (*targetsArray)[j]; |
1611 | 36 | if (!target.IsObject()) { |
1612 | 1 | continue; |
1613 | 1 | } |
1614 | 85 | for (Value::MemberIterator it = target.MemberBegin(); it != target.MemberEnd(); ++it) { |
1615 | 50 | if (!it->value.IsUint()) { |
1616 | 6 | continue; |
1617 | 6 | } |
1618 | 44 | const char *attr = it->name.GetString(); |
1619 | | // Valid attribute semantics include POSITION, NORMAL, TANGENT |
1620 | 44 | int undPos = 0; |
1621 | 44 | Mesh::AccessorList *vec = nullptr; |
1622 | 44 | if (GetAttribTargetVector(prim, j, attr, vec, undPos)) { |
1623 | 20 | size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; |
1624 | 20 | if ((*vec).size() <= idx) { |
1625 | 17 | (*vec).resize(idx + 1); |
1626 | 17 | } |
1627 | 20 | (*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint()); |
1628 | 20 | } |
1629 | 44 | } |
1630 | 35 | } |
1631 | 20 | } |
1632 | | |
1633 | 6.52k | if(this->targetNames.empty()) |
1634 | 5.60k | { |
1635 | 5.60k | Value *curExtras = FindObject(primitive, "extras"); |
1636 | 5.60k | if (nullptr != curExtras) { |
1637 | 1 | if (Value *curTargetNames = FindArray(*curExtras, "targetNames")) { |
1638 | 0 | this->targetNames.resize(curTargetNames->Size()); |
1639 | 0 | for (unsigned int j = 0; j < curTargetNames->Size(); ++j) { |
1640 | 0 | Value &targetNameValue = (*curTargetNames)[j]; |
1641 | 0 | if (targetNameValue.IsString()) { |
1642 | 0 | this->targetNames[j] = targetNameValue.GetString(); |
1643 | 0 | } |
1644 | 0 | } |
1645 | 0 | } |
1646 | 1 | } |
1647 | 5.60k | } |
1648 | 6.52k | } |
1649 | 6.20k | } |
1650 | | |
1651 | 6.55k | Value *curWeights = FindArray(pJSON_Object, "weights"); |
1652 | 6.55k | if (nullptr != curWeights) { |
1653 | 13 | this->weights.resize(curWeights->Size()); |
1654 | 40 | for (unsigned int i = 0; i < curWeights->Size(); ++i) { |
1655 | 27 | Value &weightValue = (*curWeights)[i]; |
1656 | 27 | if (weightValue.IsNumber()) { |
1657 | 27 | this->weights[i] = weightValue.GetFloat(); |
1658 | 27 | } |
1659 | 27 | } |
1660 | 13 | } |
1661 | | |
1662 | 6.55k | Value *curExtras = FindObject(pJSON_Object, "extras"); |
1663 | 6.55k | if (nullptr != curExtras) { |
1664 | 0 | if (Value *curTargetNames = FindArray(*curExtras, "targetNames")) { |
1665 | 0 | this->targetNames.resize(curTargetNames->Size()); |
1666 | 0 | for (unsigned int i = 0; i < curTargetNames->Size(); ++i) { |
1667 | 0 | Value &targetNameValue = (*curTargetNames)[i]; |
1668 | 0 | if (targetNameValue.IsString()) { |
1669 | 0 | this->targetNames[i] = targetNameValue.GetString(); |
1670 | 0 | } |
1671 | 0 | } |
1672 | 0 | } |
1673 | 0 | } |
1674 | 6.55k | } |
1675 | | |
1676 | 110 | inline void Camera::Read(Value &obj, Asset & /*r*/) { |
1677 | 110 | std::string type_string = std::string(MemberOrDefault(obj, "type", "perspective")); |
1678 | 110 | if (type_string == "orthographic") { |
1679 | 20 | type = Camera::Orthographic; |
1680 | 90 | } else { |
1681 | 90 | type = Camera::Perspective; |
1682 | 90 | } |
1683 | | |
1684 | 110 | const char *subobjId = (type == Camera::Orthographic) ? "orthographic" : "perspective"; |
1685 | | |
1686 | 110 | Value *it = FindObject(obj, subobjId); |
1687 | 110 | if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters"); |
1688 | | |
1689 | 99 | if (type == Camera::Perspective) { |
1690 | 79 | cameraProperties.perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f); |
1691 | 79 | cameraProperties.perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f / 2.f); |
1692 | 79 | cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f); |
1693 | 79 | cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f); |
1694 | 79 | } else { |
1695 | 20 | cameraProperties.ortographic.xmag = MemberOrDefault(*it, "xmag", 1.f); |
1696 | 20 | cameraProperties.ortographic.ymag = MemberOrDefault(*it, "ymag", 1.f); |
1697 | 20 | cameraProperties.ortographic.zfar = MemberOrDefault(*it, "zfar", 100.f); |
1698 | 20 | cameraProperties.ortographic.znear = MemberOrDefault(*it, "znear", 0.01f); |
1699 | 20 | } |
1700 | 99 | } |
1701 | | |
1702 | 0 | inline void Light::Read(Value &obj, Asset & /*r*/) { |
1703 | | #ifndef M_PI |
1704 | | const float M_PI = 3.14159265358979323846f; |
1705 | | #endif |
1706 | |
|
1707 | 0 | std::string type_string; |
1708 | 0 | ReadMember(obj, "type", type_string); |
1709 | 0 | if (type_string == "directional") |
1710 | 0 | type = Light::Directional; |
1711 | 0 | else if (type_string == "point") |
1712 | 0 | type = Light::Point; |
1713 | 0 | else |
1714 | 0 | type = Light::Spot; |
1715 | |
|
1716 | 0 | name = MemberOrDefault(obj, "name", ""); |
1717 | |
|
1718 | 0 | SetVector(color, vec3{ 1.0f, 1.0f, 1.0f }); |
1719 | 0 | ReadMember(obj, "color", color); |
1720 | |
|
1721 | 0 | intensity = MemberOrDefault(obj, "intensity", 1.0f); |
1722 | |
|
1723 | 0 | ReadMember(obj, "range", range); |
1724 | |
|
1725 | 0 | if (type == Light::Spot) { |
1726 | 0 | Value *spot = FindObject(obj, "spot"); |
1727 | 0 | if (!spot) throw DeadlyImportError("GLTF: Light missing its spot parameters"); |
1728 | 0 | innerConeAngle = MemberOrDefault(*spot, "innerConeAngle", 0.0f); |
1729 | 0 | outerConeAngle = MemberOrDefault(*spot, "outerConeAngle", static_cast<float>(M_PI / 4.0f)); |
1730 | 0 | } |
1731 | 0 | } |
1732 | | |
1733 | 27.4k | inline void Node::Read(Value &obj, Asset &r) { |
1734 | 27.4k | if (name.empty()) { |
1735 | 8.95k | name = id; |
1736 | 8.95k | } |
1737 | | |
1738 | 27.4k | Value *curChildren = FindArray(obj, "children"); |
1739 | 27.4k | if (nullptr != curChildren) { |
1740 | 11.9k | this->children.reserve(curChildren->Size()); |
1741 | 33.6k | for (unsigned int i = 0; i < curChildren->Size(); ++i) { |
1742 | 21.7k | Value &child = (*curChildren)[i]; |
1743 | 21.7k | if (child.IsUint()) { |
1744 | | // get/create the child node |
1745 | 21.1k | Ref<Node> chn = r.nodes.Retrieve(child.GetUint()); |
1746 | 21.1k | if (chn) { |
1747 | 20.3k | this->children.push_back(chn); |
1748 | 20.3k | } |
1749 | 21.1k | } |
1750 | 21.7k | } |
1751 | 11.9k | } |
1752 | | |
1753 | 27.4k | Value *curMatrix = FindArray(obj, "matrix"); |
1754 | 27.4k | if (nullptr != curMatrix) { |
1755 | 19.0k | ReadValue(*curMatrix, this->matrix); |
1756 | 19.0k | } else { |
1757 | 8.32k | ReadMember(obj, "translation", translation); |
1758 | 8.32k | ReadMember(obj, "scale", scale); |
1759 | 8.32k | ReadMember(obj, "rotation", rotation); |
1760 | 8.32k | } |
1761 | | |
1762 | 27.4k | Value *curMesh = FindUInt(obj, "mesh"); |
1763 | 27.4k | if (nullptr != curMesh) { |
1764 | 8.56k | unsigned int numMeshes = 1; |
1765 | 8.56k | this->meshes.reserve(numMeshes); |
1766 | 8.56k | Ref<Mesh> meshRef = r.meshes.Retrieve((*curMesh).GetUint()); |
1767 | 8.56k | if (meshRef) { |
1768 | 7.51k | this->meshes.push_back(meshRef); |
1769 | 7.51k | } |
1770 | 8.56k | } |
1771 | | |
1772 | | // Do not retrieve a skin here, just take a reference, to avoid infinite recursion |
1773 | | // Skins will be properly loaded later |
1774 | 27.4k | Value *curSkin = FindUInt(obj, "skin"); |
1775 | 27.4k | if (nullptr != curSkin) { |
1776 | 967 | this->skin = r.skins.Get(curSkin->GetUint()); |
1777 | 967 | } |
1778 | | |
1779 | 27.4k | Value *curCamera = FindUInt(obj, "camera"); |
1780 | 27.4k | if (nullptr != curCamera) { |
1781 | 130 | this->camera = r.cameras.Retrieve(curCamera->GetUint()); |
1782 | 130 | if (this->camera) { |
1783 | 103 | this->camera->id = this->id; |
1784 | 103 | } |
1785 | 130 | } |
1786 | | |
1787 | 27.4k | Value *curExtensions = FindObject(obj, "extensions"); |
1788 | 27.4k | if (nullptr != curExtensions) { |
1789 | 0 | if (r.extensionsUsed.KHR_lights_punctual) { |
1790 | 0 | if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) { |
1791 | 0 | Value *curLight = FindUInt(*ext, "light"); |
1792 | 0 | if (nullptr != curLight) { |
1793 | 0 | this->light = r.lights.Retrieve(curLight->GetUint()); |
1794 | 0 | if (this->light) { |
1795 | 0 | this->light->id = this->id; |
1796 | 0 | } |
1797 | 0 | } |
1798 | 0 | } |
1799 | 0 | } |
1800 | 0 | } |
1801 | 27.4k | } |
1802 | | |
1803 | 5.44k | inline void Scene::Read(Value &obj, Asset &r) { |
1804 | 5.44k | if (Value *scene_name = FindString(obj, "name")) { |
1805 | 177 | if (scene_name->IsString()) { |
1806 | 177 | this->name = scene_name->GetString(); |
1807 | 177 | } |
1808 | 177 | } |
1809 | 5.44k | if (Value *array = FindArray(obj, "nodes")) { |
1810 | 11.9k | for (unsigned int i = 0; i < array->Size(); ++i) { |
1811 | 6.72k | if (!(*array)[i].IsUint()) continue; |
1812 | 6.61k | Ref<Node> node = r.nodes.Retrieve((*array)[i].GetUint()); |
1813 | 6.61k | if (node) |
1814 | 5.33k | this->nodes.push_back(node); |
1815 | 6.61k | } |
1816 | 5.26k | } |
1817 | 5.44k | } |
1818 | | |
1819 | 3.96k | inline void Skin::Read(Value &obj, Asset &r) { |
1820 | 3.96k | if (Value *matrices = FindUInt(obj, "inverseBindMatrices")) { |
1821 | 898 | inverseBindMatrices = r.accessors.Retrieve(matrices->GetUint()); |
1822 | 898 | } |
1823 | | |
1824 | 3.96k | if (Value *joints = FindArray(obj, "joints")) { |
1825 | 6.82k | for (unsigned i = 0; i < joints->Size(); ++i) { |
1826 | 5.97k | if (!(*joints)[i].IsUint()) continue; |
1827 | 5.90k | Ref<Node> node = r.nodes.Retrieve((*joints)[i].GetUint()); |
1828 | 5.90k | if (node) { |
1829 | 5.87k | this->jointNames.push_back(node); |
1830 | 5.87k | } |
1831 | 5.90k | } |
1832 | 852 | } |
1833 | 3.96k | } |
1834 | | |
1835 | 325 | inline void Animation::Read(Value &obj, Asset &r) { |
1836 | 325 | Value *curSamplers = FindArray(obj, "samplers"); |
1837 | 325 | if (nullptr != curSamplers) { |
1838 | 490 | for (unsigned i = 0; i < curSamplers->Size(); ++i) { |
1839 | 267 | Value &sampler = (*curSamplers)[i]; |
1840 | | |
1841 | 267 | Sampler s; |
1842 | 267 | if (Value *input = FindUInt(sampler, "input")) { |
1843 | 217 | s.input = r.accessors.Retrieve(input->GetUint()); |
1844 | 217 | } |
1845 | 267 | if (Value *output = FindUInt(sampler, "output")) { |
1846 | 173 | s.output = r.accessors.Retrieve(output->GetUint()); |
1847 | 173 | } |
1848 | 267 | s.interpolation = Interpolation_LINEAR; |
1849 | 267 | if (Value *interpolation = FindString(sampler, "interpolation")) { |
1850 | 140 | const std::string interp = interpolation->GetString(); |
1851 | 140 | if (interp == "LINEAR") { |
1852 | 119 | s.interpolation = Interpolation_LINEAR; |
1853 | 119 | } else if (interp == "STEP") { |
1854 | 0 | s.interpolation = Interpolation_STEP; |
1855 | 21 | } else if (interp == "CUBICSPLINE") { |
1856 | 0 | s.interpolation = Interpolation_CUBICSPLINE; |
1857 | 0 | } |
1858 | 140 | } |
1859 | 267 | this->samplers.push_back(s); |
1860 | 267 | } |
1861 | 223 | } |
1862 | | |
1863 | 325 | Value *curChannels = FindArray(obj, "channels"); |
1864 | 325 | if (nullptr != curChannels) { |
1865 | 482 | for (unsigned i = 0; i < curChannels->Size(); ++i) { |
1866 | 247 | Value &channel = (*curChannels)[i]; |
1867 | | |
1868 | 247 | Channel c; |
1869 | 247 | Value *curSampler = FindUInt(channel, "sampler"); |
1870 | 247 | if (nullptr != curSampler) { |
1871 | 219 | c.sampler = curSampler->GetUint(); |
1872 | 219 | } |
1873 | | |
1874 | 247 | if (Value *target = FindObject(channel, "target")) { |
1875 | 182 | if (Value *node = FindUInt(*target, "node")) { |
1876 | 145 | c.target.node = r.nodes.Retrieve(node->GetUint()); |
1877 | 145 | } |
1878 | 182 | if (Value *path = FindString(*target, "path")) { |
1879 | 160 | const std::string p = path->GetString(); |
1880 | 160 | if (p == "translation") { |
1881 | 0 | c.target.path = AnimationPath_TRANSLATION; |
1882 | 160 | } else if (p == "rotation") { |
1883 | 128 | c.target.path = AnimationPath_ROTATION; |
1884 | 128 | } else if (p == "scale") { |
1885 | 0 | c.target.path = AnimationPath_SCALE; |
1886 | 32 | } else if (p == "weights") { |
1887 | 7 | c.target.path = AnimationPath_WEIGHTS; |
1888 | 7 | } |
1889 | 160 | } |
1890 | 182 | } |
1891 | 247 | this->channels.push_back(c); |
1892 | 247 | } |
1893 | 235 | } |
1894 | 325 | } |
1895 | | |
1896 | 12.5k | inline void AssetMetadata::Read(Document &doc) { |
1897 | 12.5k | if (Value *obj = FindObject(doc, "asset")) { |
1898 | 11.9k | ReadMember(*obj, "copyright", copyright); |
1899 | 11.9k | ReadMember(*obj, "generator", generator); |
1900 | | |
1901 | 11.9k | if (Value *versionString = FindStringInContext(*obj, "version", "\"asset\"")) { |
1902 | 11.1k | version = versionString->GetString(); |
1903 | 11.1k | } |
1904 | 11.9k | Value *curProfile = FindObjectInContext(*obj, "profile", "\"asset\""); |
1905 | 11.9k | if (nullptr != curProfile) { |
1906 | 58 | ReadMember(*curProfile, "api", this->profile.api); |
1907 | 58 | ReadMember(*curProfile, "version", this->profile.version); |
1908 | 58 | } |
1909 | 11.9k | } |
1910 | | |
1911 | 12.5k | if (version.empty() || version[0] != '2') { |
1912 | 748 | throw DeadlyImportError("GLTF: Unsupported glTF version: ", version); |
1913 | 748 | } |
1914 | 12.5k | } |
1915 | | |
1916 | | // |
1917 | | // Asset methods implementation |
1918 | | // |
1919 | | |
1920 | 7.98k | inline void Asset::ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData) { |
1921 | 7.98k | ASSIMP_LOG_DEBUG("Reading GLTF2 binary"); |
1922 | 7.98k | GLB_Header header; |
1923 | 7.98k | if (stream.Read(&header, sizeof(header), 1) != 1) { |
1924 | 0 | throw DeadlyImportError("GLTF: Unable to read the file header"); |
1925 | 0 | } |
1926 | | |
1927 | 7.98k | if (strncmp((char *)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) { |
1928 | 0 | throw DeadlyImportError("GLTF: Invalid binary glTF file"); |
1929 | 0 | } |
1930 | | |
1931 | 7.98k | AI_SWAP4(header.version); |
1932 | 7.98k | asset.version = ai_to_string(header.version); |
1933 | 7.98k | if (header.version != 2) { |
1934 | 273 | throw DeadlyImportError("GLTF: Unsupported binary glTF version"); |
1935 | 273 | } |
1936 | | |
1937 | 7.71k | GLB_Chunk chunk; |
1938 | 7.71k | if (stream.Read(&chunk, sizeof(chunk), 1) != 1) { |
1939 | 0 | throw DeadlyImportError("GLTF: Unable to read JSON chunk"); |
1940 | 0 | } |
1941 | | |
1942 | 7.71k | AI_SWAP4(chunk.chunkLength); |
1943 | 7.71k | AI_SWAP4(chunk.chunkType); |
1944 | | |
1945 | 7.71k | if (chunk.chunkType != ChunkType_JSON) { |
1946 | 50 | throw DeadlyImportError("GLTF: JSON chunk missing"); |
1947 | 50 | } |
1948 | | |
1949 | | // read the scene data, ensure null termination |
1950 | 7.66k | static_assert(std::numeric_limits<uint32_t>::max() <= std::numeric_limits<size_t>::max(), "size_t must be at least 32bits"); |
1951 | 7.66k | mSceneLength = chunk.chunkLength; // Can't be larger than 4GB (max. uint32_t) |
1952 | 7.66k | sceneData.resize(mSceneLength + 1); |
1953 | 7.66k | sceneData[mSceneLength] = '\0'; |
1954 | | |
1955 | 7.66k | if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { |
1956 | 88 | throw DeadlyImportError("GLTF: Could not read the file contents"); |
1957 | 88 | } |
1958 | | |
1959 | 7.57k | uint32_t padding = ((chunk.chunkLength + 3) & ~3) - chunk.chunkLength; |
1960 | 7.57k | if (padding > 0) { |
1961 | 142 | stream.Seek(padding, aiOrigin_CUR); |
1962 | 142 | } |
1963 | | |
1964 | 7.57k | AI_SWAP4(header.length); |
1965 | 7.57k | mBodyOffset = 12 + 8 + chunk.chunkLength + padding + 8; |
1966 | 7.57k | if (header.length >= mBodyOffset) { |
1967 | 7.45k | if (stream.Read(&chunk, sizeof(chunk), 1) != 1) { |
1968 | 38 | throw DeadlyImportError("GLTF: Unable to read BIN chunk"); |
1969 | 38 | } |
1970 | | |
1971 | 7.41k | AI_SWAP4(chunk.chunkLength); |
1972 | 7.41k | AI_SWAP4(chunk.chunkType); |
1973 | | |
1974 | 7.41k | if (chunk.chunkType != ChunkType_BIN) { |
1975 | 244 | throw DeadlyImportError("GLTF: BIN chunk missing"); |
1976 | 244 | } |
1977 | | |
1978 | 7.16k | mBodyLength = chunk.chunkLength; |
1979 | 7.16k | } else { |
1980 | 122 | mBodyOffset = mBodyLength = 0; |
1981 | 122 | } |
1982 | 7.57k | } |
1983 | | |
1984 | 16.0k | inline rapidjson::Document Asset::ReadDocument(IOStream &stream, bool isBinary, std::vector<char> &sceneData) { |
1985 | 16.0k | ASSIMP_LOG_DEBUG("Loading GLTF2 asset"); |
1986 | | |
1987 | | // is binary? then read the header |
1988 | 16.0k | if (isBinary) { |
1989 | 7.98k | SetAsBinary(); // also creates the body buffer |
1990 | 7.98k | ReadBinaryHeader(stream, sceneData); |
1991 | 8.07k | } else { |
1992 | 8.07k | mSceneLength = stream.FileSize(); |
1993 | 8.07k | mBodyLength = 0; |
1994 | | |
1995 | | // Binary format only supports up to 4GB of JSON, use that as a maximum |
1996 | 8.07k | if (mSceneLength >= std::numeric_limits<uint32_t>::max()) { |
1997 | 0 | throw DeadlyImportError("GLTF: JSON size greater than 4GB"); |
1998 | 0 | } |
1999 | | |
2000 | | // read the scene data, ensure null termination |
2001 | 8.07k | sceneData.resize(mSceneLength + 1); |
2002 | 8.07k | sceneData[mSceneLength] = '\0'; |
2003 | | |
2004 | 8.07k | if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { |
2005 | 0 | throw DeadlyImportError("GLTF: Could not read the file contents"); |
2006 | 0 | } |
2007 | 8.07k | } |
2008 | | |
2009 | | // Smallest legal JSON file is "{}" Smallest loadable glTF file is larger than that but catch it later |
2010 | 16.0k | if (mSceneLength < 2) { |
2011 | 2 | throw DeadlyImportError("GLTF: No JSON file contents"); |
2012 | 2 | } |
2013 | | |
2014 | | // parse the JSON document |
2015 | 16.0k | ASSIMP_LOG_DEBUG("Parsing GLTF2 JSON"); |
2016 | 16.0k | Document doc; |
2017 | 16.0k | doc.ParseInsitu(&sceneData[0]); |
2018 | | |
2019 | 16.0k | if (doc.HasParseError()) { |
2020 | 2.44k | char buffer[32]; |
2021 | 2.44k | ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset())); |
2022 | 2.44k | throw DeadlyImportError("GLTF: JSON parse error, offset ", buffer, ": ", GetParseError_En(doc.GetParseError())); |
2023 | 2.44k | } |
2024 | | |
2025 | 13.6k | if (!doc.IsObject()) { |
2026 | 251 | throw DeadlyImportError("GLTF: JSON document root must be a JSON object"); |
2027 | 251 | } |
2028 | | |
2029 | 13.3k | return doc; |
2030 | 13.6k | } |
2031 | | |
2032 | | inline void Asset::Load(const std::string &pFile, bool isBinary) |
2033 | 5.88k | { |
2034 | 5.88k | mCurrentAssetDir.clear(); |
2035 | 5.88k | if (0 != strncmp(pFile.c_str(), AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { |
2036 | 0 | mCurrentAssetDir = glTFCommon::getCurrentAssetDir(pFile); |
2037 | 0 | } |
2038 | | |
2039 | 5.88k | shared_ptr<IOStream> stream(OpenFile(pFile.c_str(), "rb", true)); |
2040 | 5.88k | if (!stream) { |
2041 | 0 | throw DeadlyImportError("GLTF: Could not open file for reading"); |
2042 | 0 | } |
2043 | | |
2044 | 5.88k | std::vector<char> sceneData; |
2045 | 5.88k | rapidjson::Document doc = ReadDocument(*stream, isBinary, sceneData); |
2046 | | |
2047 | | // If a schemaDocumentProvider is available, see if the glTF schema is present. |
2048 | | // If so, use it to validate the document. |
2049 | 5.88k | if (mSchemaDocumentProvider) { |
2050 | 0 | if (const rapidjson::SchemaDocument *gltfSchema = mSchemaDocumentProvider->GetRemoteDocument("glTF.schema.json", 16)) { |
2051 | | // The schemas are found here: https://github.com/KhronosGroup/glTF/tree/main/specification/2.0/schema |
2052 | 0 | rapidjson::SchemaValidator validator(*gltfSchema); |
2053 | 0 | if (!doc.Accept(validator)) { |
2054 | 0 | rapidjson::StringBuffer pathBuffer; |
2055 | 0 | validator.GetInvalidSchemaPointer().StringifyUriFragment(pathBuffer); |
2056 | 0 | rapidjson::StringBuffer argumentBuffer; |
2057 | 0 | validator.GetInvalidDocumentPointer().StringifyUriFragment(argumentBuffer); |
2058 | 0 | throw DeadlyImportError("GLTF: The JSON document did not satisfy the glTF2 schema. Schema keyword: ", validator.GetInvalidSchemaKeyword(), ", document path: ", pathBuffer.GetString(), ", argument: ", argumentBuffer.GetString()); |
2059 | 0 | } |
2060 | 0 | } |
2061 | 0 | } |
2062 | | |
2063 | | // Fill the buffer instance for the current file embedded contents |
2064 | 5.88k | if (mBodyLength > 0) { |
2065 | 3.55k | if (!mBodyBuffer->LoadFromStream(*stream, mBodyLength, mBodyOffset)) { |
2066 | 30 | throw DeadlyImportError("GLTF: Unable to read gltf file"); |
2067 | 30 | } |
2068 | 3.55k | } |
2069 | | |
2070 | | // Load the metadata |
2071 | 5.85k | asset.Read(doc); |
2072 | 5.85k | ReadExtensionsUsed(doc); |
2073 | 5.85k | ReadExtensionsRequired(doc); |
2074 | | |
2075 | 5.85k | #ifndef ASSIMP_ENABLE_DRACO |
2076 | | // Is Draco required? |
2077 | 5.85k | if (extensionsRequired.KHR_draco_mesh_compression) { |
2078 | 4 | throw DeadlyImportError("GLTF: Draco mesh compression not supported."); |
2079 | 4 | } |
2080 | 5.85k | #endif |
2081 | | |
2082 | | // Prepare the dictionaries |
2083 | 86.1k | for (size_t i = 0; i < mDicts.size(); ++i) { |
2084 | 80.3k | mDicts[i]->AttachToDocument(doc); |
2085 | 80.3k | } |
2086 | | |
2087 | | // Read the "extensions" property, then add it to each scene's metadata. |
2088 | 5.85k | CustomExtension customExtensions; |
2089 | 5.85k | if (Value *extensionsObject = FindObject(doc, "extensions")) { |
2090 | 0 | customExtensions = glTF2::ReadExtensions("extensions", *extensionsObject); |
2091 | 0 | } |
2092 | | |
2093 | | // Read the "scene" property, which specifies which scene to load |
2094 | | // and recursively load everything referenced by it |
2095 | 5.85k | unsigned int sceneIndex = 0; |
2096 | 5.85k | Value *curScene = FindUInt(doc, "scene"); |
2097 | 5.85k | if (nullptr != curScene) { |
2098 | 4.20k | sceneIndex = curScene->GetUint(); |
2099 | 4.20k | } |
2100 | | |
2101 | 5.85k | if (Value *scenesArray = FindArray(doc, "scenes")) { |
2102 | 5.51k | if (sceneIndex < scenesArray->Size()) { |
2103 | 5.45k | this->scene = scenes.Retrieve(sceneIndex); |
2104 | | |
2105 | 5.45k | this->scene->customExtensions = customExtensions; |
2106 | 5.45k | } |
2107 | 5.51k | } |
2108 | | |
2109 | 5.85k | if (Value *skinsArray = FindArray(doc, "skins")) { |
2110 | 4.95k | for (unsigned int i = 0; i < skinsArray->Size(); ++i) { |
2111 | 3.96k | skins.Retrieve(i); |
2112 | 3.96k | } |
2113 | 990 | } |
2114 | | |
2115 | 5.85k | if (Value *animsArray = FindArray(doc, "animations")) { |
2116 | 639 | for (unsigned int i = 0; i < animsArray->Size(); ++i) { |
2117 | 326 | animations.Retrieve(i); |
2118 | 326 | } |
2119 | 313 | } |
2120 | | |
2121 | | // Clean up |
2122 | 65.2k | for (size_t i = 0; i < mDicts.size(); ++i) { |
2123 | 59.4k | mDicts[i]->DetachFromDocument(); |
2124 | 59.4k | } |
2125 | 5.85k | } |
2126 | | |
2127 | 10.1k | inline bool Asset::CanRead(const std::string &pFile, bool isBinary) { |
2128 | 10.1k | try { |
2129 | 10.1k | shared_ptr<IOStream> stream(OpenFile(pFile.c_str(), "rb", true)); |
2130 | 10.1k | if (!stream) { |
2131 | 0 | return false; |
2132 | 0 | } |
2133 | 10.1k | std::vector<char> sceneData; |
2134 | 10.1k | rapidjson::Document doc = ReadDocument(*stream, isBinary, sceneData); |
2135 | 10.1k | asset.Read(doc); |
2136 | 10.1k | } catch (...) { |
2137 | 4.28k | return false; |
2138 | 4.28k | } |
2139 | 5.88k | return true; |
2140 | 10.1k | } |
2141 | | |
2142 | 7.98k | inline void Asset::SetAsBinary() { |
2143 | 7.98k | if (!mBodyBuffer) { |
2144 | 7.98k | mBodyBuffer = buffers.Create("binary_glTF"); |
2145 | 7.98k | mBodyBuffer->MarkAsSpecial(); |
2146 | 7.98k | } |
2147 | 7.98k | } |
2148 | | |
2149 | | // As required extensions are only a concept in glTF 2.0, this is here |
2150 | | // instead of glTFCommon.h |
2151 | | #define CHECK_REQUIRED_EXT(EXT) \ |
2152 | 66 | if (exts.find(#EXT) != exts.end()) extensionsRequired.EXT = true; |
2153 | | |
2154 | 5.75k | inline void Asset::ReadExtensionsRequired(Document &doc) { |
2155 | 5.75k | Value *extsRequired = FindArray(doc, "extensionsRequired"); |
2156 | 5.75k | if (nullptr == extsRequired) { |
2157 | 5.73k | return; |
2158 | 5.73k | } |
2159 | | |
2160 | 22 | std::gltf_unordered_map<std::string, bool> exts; |
2161 | 51 | for (unsigned int i = 0; i < extsRequired->Size(); ++i) { |
2162 | 29 | if ((*extsRequired)[i].IsString()) { |
2163 | 22 | exts[(*extsRequired)[i].GetString()] = true; |
2164 | 22 | } |
2165 | 29 | } |
2166 | | |
2167 | 22 | CHECK_REQUIRED_EXT(KHR_draco_mesh_compression); |
2168 | 22 | CHECK_REQUIRED_EXT(KHR_texture_basisu); |
2169 | 22 | CHECK_REQUIRED_EXT(EXT_texture_webp); |
2170 | | |
2171 | 22 | #undef CHECK_REQUIRED_EXT |
2172 | 22 | } |
2173 | | |
2174 | 5.76k | inline void Asset::ReadExtensionsUsed(Document &doc) { |
2175 | 5.76k | Value *extsUsed = FindArray(doc, "extensionsUsed"); |
2176 | 5.76k | if (!extsUsed) return; |
2177 | | |
2178 | 1.02k | std::gltf_unordered_map<std::string, bool> exts; |
2179 | | |
2180 | 7.46k | for (unsigned int i = 0; i < extsUsed->Size(); ++i) { |
2181 | 6.43k | if ((*extsUsed)[i].IsString()) { |
2182 | 6.42k | exts[(*extsUsed)[i].GetString()] = true; |
2183 | 6.42k | } |
2184 | 6.43k | } |
2185 | | |
2186 | 1.02k | CHECK_EXT(KHR_materials_pbrSpecularGlossiness); |
2187 | 1.02k | CHECK_EXT(KHR_materials_specular); |
2188 | 1.02k | CHECK_EXT(KHR_materials_unlit); |
2189 | 1.02k | CHECK_EXT(KHR_lights_punctual); |
2190 | 1.02k | CHECK_EXT(KHR_texture_transform); |
2191 | 1.02k | CHECK_EXT(KHR_materials_sheen); |
2192 | 1.02k | CHECK_EXT(KHR_materials_clearcoat); |
2193 | 1.02k | CHECK_EXT(KHR_materials_transmission); |
2194 | 1.02k | CHECK_EXT(KHR_materials_volume); |
2195 | 1.02k | CHECK_EXT(KHR_materials_ior); |
2196 | 1.02k | CHECK_EXT(KHR_materials_emissive_strength); |
2197 | 1.02k | CHECK_EXT(KHR_materials_anisotropy); |
2198 | 1.02k | CHECK_EXT(KHR_draco_mesh_compression); |
2199 | 1.02k | CHECK_EXT(KHR_texture_basisu); |
2200 | 1.02k | CHECK_EXT(EXT_texture_webp); |
2201 | | |
2202 | 1.02k | #undef CHECK_EXT |
2203 | 1.02k | } |
2204 | | |
2205 | 16.3k | inline IOStream *Asset::OpenFile(const std::string &path, const char *mode, bool /*absolute*/) { |
2206 | 16.3k | #ifdef ASSIMP_API |
2207 | 16.3k | return mIOSystem->Open(path, mode); |
2208 | | #else |
2209 | | if (path.size() < 2) return nullptr; |
2210 | | if (!absolute && path[1] != ':' && path[0] != '/') { // relative? |
2211 | | path = mCurrentAssetDir + path; |
2212 | | } |
2213 | | FILE *f = fopen(path.c_str(), mode); |
2214 | | return f ? new IOStream(f) : nullptr; |
2215 | | #endif |
2216 | 16.3k | } |
2217 | | |
2218 | 0 | inline std::string Asset::FindUniqueID(const std::string &str, const char *suffix) { |
2219 | 0 | std::string id = str; |
2220 | 0 | int n = 1; |
2221 | 0 | if(!id.empty()) { |
2222 | 0 | n = lastUsedID[id]; |
2223 | 0 | if(!n) { |
2224 | 0 | lastUsedID[id] = n+1; |
2225 | 0 | return id; |
2226 | 0 | } |
2227 | 0 | id += "_"; |
2228 | 0 | } |
2229 | 0 |
|
2230 | 0 | if(suffix) { |
2231 | 0 | id += suffix; |
2232 | 0 | n = lastUsedID[id]; |
2233 | 0 | if(!n) { |
2234 | 0 | lastUsedID[id] = n+1; |
2235 | 0 | return id; |
2236 | 0 | } |
2237 | 0 | } |
2238 | 0 |
|
2239 | 0 | lastUsedID[id] = n+1; |
2240 | 0 | return id + "_" + std::to_string(n-1); |
2241 | 0 | } |
2242 | | |
2243 | | #if _MSC_VER |
2244 | | # pragma warning(pop) |
2245 | | #endif // _MSC_VER |
2246 | | |
2247 | | } // namespace glTF2 |