/src/assimp/code/AssetLib/glTF2/glTF2AssetWriter.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 <assimp/Base64.hpp> |
43 | | #include <rapidjson/stringbuffer.h> |
44 | | #include <rapidjson/writer.h> |
45 | | #include <rapidjson/prettywriter.h> |
46 | | |
47 | | namespace glTF2 { |
48 | | |
49 | | using rapidjson::StringBuffer; |
50 | | using rapidjson::PrettyWriter; |
51 | | using rapidjson::Writer; |
52 | | using rapidjson::StringRef; |
53 | | using rapidjson::StringRef; |
54 | | |
55 | | namespace { |
56 | | |
57 | | template<typename T, size_t N> |
58 | 0 | inline Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) { |
59 | 0 | val.SetArray(); |
60 | 0 | val.Reserve(N, al); |
61 | 0 | for (decltype(N) i = 0; i < N; ++i) { |
62 | 0 | val.PushBack(r[i], al); |
63 | 0 | } |
64 | 0 | return val; |
65 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<float, 4ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [4ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<float, 3ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [3ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<float, 16ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [16ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<float, 4ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [4ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<float, 3ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [3ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<float, 16ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [16ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
66 | | |
67 | | template<typename T> |
68 | 0 | inline Value& MakeValue(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) { |
69 | 0 | val.SetArray(); |
70 | 0 | val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al); |
71 | 0 | for (unsigned int i = 0; i < r.size(); ++i) { |
72 | 0 | val.PushBack(r[i], al); |
73 | 0 | } |
74 | 0 | return val; |
75 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<double>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, std::__1::vector<double, std::__1::allocator<double> > const&, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<double>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, std::__1::vector<double, std::__1::allocator<double> > const&, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
76 | | |
77 | | template<typename C, typename T> |
78 | 0 | inline Value& MakeValueCast(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) { |
79 | 0 | val.SetArray(); |
80 | 0 | val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al); |
81 | 0 | for (unsigned int i = 0; i < r.size(); ++i) { |
82 | 0 | val.PushBack(static_cast<C>(r[i]), al); |
83 | 0 | } |
84 | 0 | return val; |
85 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValueCast<long, double>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, std::__1::vector<double, std::__1::allocator<double> > const&, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValueCast<long, double>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, std::__1::vector<double, std::__1::allocator<double> > const&, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
86 | | |
87 | | template<typename T> |
88 | 0 | inline Value& MakeValue(Value& val, T r, MemoryPoolAllocator<>& /*al*/) { |
89 | 0 | val.Set(r); |
90 | |
|
91 | 0 | return val; |
92 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<float>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<char const*>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<double>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, double, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<unsigned long>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, unsigned long, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<long>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, long, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<bool>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, bool, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<float>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<char const*>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<double>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, double, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<unsigned long>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, unsigned long, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<long>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, long, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >& glTF2::(anonymous namespace)::MakeValue<bool>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, bool, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
93 | | |
94 | | template<class T> |
95 | 0 | inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) { |
96 | 0 | if (v.empty()) return; |
97 | 0 | Value lst; |
98 | 0 | lst.SetArray(); |
99 | 0 | lst.Reserve(unsigned(v.size()), al); |
100 | 0 | for (size_t i = 0; i < v.size(); ++i) { |
101 | 0 | lst.PushBack(v[i]->index, al); |
102 | 0 | } |
103 | 0 | obj.AddMember(StringRef(fieldId), lst, al); |
104 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:void glTF2::(anonymous namespace)::AddRefsVector<glTF2::Node>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, char const*, std::__1::vector<glTFCommon::Ref<glTF2::Node>, std::__1::allocator<glTFCommon::Ref<glTF2::Node> > >&, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:void glTF2::(anonymous namespace)::AddRefsVector<glTF2::Node>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, char const*, std::__1::vector<glTFCommon::Ref<glTF2::Node>, std::__1::allocator<glTFCommon::Ref<glTF2::Node> > >&, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
105 | | |
106 | | |
107 | | } |
108 | | |
109 | | inline void Write(Value& obj, Accessor& a, AssetWriter& w) |
110 | 0 | { |
111 | 0 | if (a.bufferView) { |
112 | 0 | obj.AddMember("bufferView", a.bufferView->index, w.mAl); |
113 | 0 | obj.AddMember("byteOffset", (unsigned int)a.byteOffset, w.mAl); |
114 | 0 | } |
115 | 0 | obj.AddMember("componentType", int(a.componentType), w.mAl); |
116 | 0 | obj.AddMember("count", (unsigned int)a.count, w.mAl); |
117 | 0 | obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); |
118 | 0 | Value vTmpMax, vTmpMin; |
119 | 0 | if (a.componentType == ComponentType_FLOAT) { |
120 | 0 | obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl); |
121 | 0 | obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl); |
122 | 0 | } else { |
123 | 0 | obj.AddMember("max", MakeValueCast<int64_t>(vTmpMax, a.max, w.mAl), w.mAl); |
124 | 0 | obj.AddMember("min", MakeValueCast<int64_t>(vTmpMin, a.min, w.mAl), w.mAl); |
125 | 0 | } |
126 | |
|
127 | 0 | if (a.sparse) { |
128 | 0 | Value sparseValue; |
129 | 0 | sparseValue.SetObject(); |
130 | | |
131 | | //count |
132 | 0 | sparseValue.AddMember("count", (unsigned int)a.sparse->count, w.mAl); |
133 | | |
134 | | //indices |
135 | 0 | Value indices; |
136 | 0 | indices.SetObject(); |
137 | 0 | indices.AddMember("bufferView", a.sparse->indices->index, w.mAl); |
138 | 0 | indices.AddMember("byteOffset", (unsigned int)a.sparse->indicesByteOffset, w.mAl); |
139 | 0 | indices.AddMember("componentType", int(a.sparse->indicesType), w.mAl); |
140 | 0 | sparseValue.AddMember("indices", indices, w.mAl); |
141 | | |
142 | | //values |
143 | 0 | Value values; |
144 | 0 | values.SetObject(); |
145 | 0 | values.AddMember("bufferView", a.sparse->values->index, w.mAl); |
146 | 0 | values.AddMember("byteOffset", (unsigned int)a.sparse->valuesByteOffset, w.mAl); |
147 | 0 | sparseValue.AddMember("values", values, w.mAl); |
148 | |
|
149 | 0 | obj.AddMember("sparse", sparseValue, w.mAl); |
150 | 0 | } |
151 | 0 | } |
152 | | |
153 | | inline void Write(Value& obj, Animation& a, AssetWriter& w) |
154 | 0 | { |
155 | | /****************** Channels *******************/ |
156 | 0 | Value channels; |
157 | 0 | channels.SetArray(); |
158 | 0 | channels.Reserve(unsigned(a.channels.size()), w.mAl); |
159 | |
|
160 | 0 | for (size_t i = 0; i < unsigned(a.channels.size()); ++i) { |
161 | 0 | Animation::Channel& c = a.channels[i]; |
162 | 0 | Value valChannel; |
163 | 0 | valChannel.SetObject(); |
164 | 0 | { |
165 | 0 | valChannel.AddMember("sampler", c.sampler, w.mAl); |
166 | |
|
167 | 0 | Value valTarget; |
168 | 0 | valTarget.SetObject(); |
169 | 0 | { |
170 | 0 | valTarget.AddMember("node", c.target.node->index, w.mAl); |
171 | 0 | switch (c.target.path) { |
172 | 0 | case AnimationPath_TRANSLATION: |
173 | 0 | valTarget.AddMember("path", "translation", w.mAl); |
174 | 0 | break; |
175 | 0 | case AnimationPath_ROTATION: |
176 | 0 | valTarget.AddMember("path", "rotation", w.mAl); |
177 | 0 | break; |
178 | 0 | case AnimationPath_SCALE: |
179 | 0 | valTarget.AddMember("path", "scale", w.mAl); |
180 | 0 | break; |
181 | 0 | case AnimationPath_WEIGHTS: |
182 | 0 | valTarget.AddMember("path", "weights", w.mAl); |
183 | 0 | break; |
184 | 0 | } |
185 | 0 | } |
186 | 0 | valChannel.AddMember("target", valTarget, w.mAl); |
187 | 0 | } |
188 | 0 | channels.PushBack(valChannel, w.mAl); |
189 | 0 | } |
190 | 0 | obj.AddMember("channels", channels, w.mAl); |
191 | | |
192 | | /****************** Samplers *******************/ |
193 | 0 | Value valSamplers; |
194 | 0 | valSamplers.SetArray(); |
195 | |
|
196 | 0 | for (size_t i = 0; i < unsigned(a.samplers.size()); ++i) { |
197 | 0 | Animation::Sampler& s = a.samplers[i]; |
198 | 0 | Value valSampler; |
199 | 0 | valSampler.SetObject(); |
200 | 0 | { |
201 | 0 | valSampler.AddMember("input", s.input->index, w.mAl); |
202 | 0 | switch (s.interpolation) { |
203 | 0 | case Interpolation_LINEAR: |
204 | 0 | valSampler.AddMember("interpolation", "LINEAR", w.mAl); |
205 | 0 | break; |
206 | 0 | case Interpolation_STEP: |
207 | 0 | valSampler.AddMember("interpolation", "STEP", w.mAl); |
208 | 0 | break; |
209 | 0 | case Interpolation_CUBICSPLINE: |
210 | 0 | valSampler.AddMember("interpolation", "CUBICSPLINE", w.mAl); |
211 | 0 | break; |
212 | 0 | } |
213 | 0 | valSampler.AddMember("output", s.output->index, w.mAl); |
214 | 0 | } |
215 | 0 | valSamplers.PushBack(valSampler, w.mAl); |
216 | 0 | } |
217 | 0 | obj.AddMember("samplers", valSamplers, w.mAl); |
218 | 0 | } |
219 | | |
220 | | inline void Write(Value& obj, Buffer& b, AssetWriter& w) |
221 | 0 | { |
222 | 0 | obj.AddMember("byteLength", static_cast<uint64_t>(b.byteLength), w.mAl); |
223 | |
|
224 | 0 | const auto uri = b.GetURI(); |
225 | 0 | const auto relativeUri = uri.substr(uri.find_last_of("/\\") + 1u); |
226 | 0 | obj.AddMember("uri", Value(relativeUri, w.mAl).Move(), w.mAl); |
227 | 0 | } |
228 | | |
229 | | inline void Write(Value& obj, BufferView& bv, AssetWriter& w) |
230 | 0 | { |
231 | 0 | obj.AddMember("buffer", bv.buffer->index, w.mAl); |
232 | 0 | obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl); |
233 | 0 | obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl); |
234 | 0 | if (bv.byteStride != 0) { |
235 | 0 | obj.AddMember("byteStride", bv.byteStride, w.mAl); |
236 | 0 | } |
237 | 0 | if (bv.target != BufferViewTarget_NONE) { |
238 | 0 | obj.AddMember("target", int(bv.target), w.mAl); |
239 | 0 | } |
240 | 0 | } |
241 | | |
242 | | inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/) |
243 | 0 | { |
244 | |
|
245 | 0 | } |
246 | | |
247 | | inline void Write(Value& /*obj*/, Light& /*c*/, AssetWriter& /*w*/) |
248 | 0 | { |
249 | |
|
250 | 0 | } |
251 | | |
252 | | inline void Write(Value& obj, Image& img, AssetWriter& w) |
253 | 0 | { |
254 | | //basisu: no need to handle .ktx2, .basis, write as is |
255 | 0 | if (img.bufferView) { |
256 | 0 | obj.AddMember("bufferView", img.bufferView->index, w.mAl); |
257 | 0 | obj.AddMember("mimeType", Value(img.mimeType, w.mAl).Move(), w.mAl); |
258 | 0 | } |
259 | 0 | else { |
260 | 0 | std::string uri; |
261 | 0 | if (img.HasData()) { |
262 | 0 | uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType); |
263 | 0 | uri += ";base64,"; |
264 | 0 | Base64::Encode(img.GetData(), img.GetDataLength(), uri); |
265 | 0 | } |
266 | 0 | else { |
267 | 0 | uri = img.uri; |
268 | 0 | } |
269 | |
|
270 | 0 | obj.AddMember("uri", Value(uri, w.mAl).Move(), w.mAl); |
271 | 0 | } |
272 | 0 | } |
273 | | |
274 | | namespace { |
275 | | inline void SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al) |
276 | 0 | { |
277 | 0 | tex.SetObject(); |
278 | 0 | tex.AddMember("index", t.texture->index, al); |
279 | |
|
280 | 0 | if (t.texCoord != 0) { |
281 | 0 | tex.AddMember("texCoord", t.texCoord, al); |
282 | 0 | } |
283 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:glTF2::(anonymous namespace)::SetTexBasic(glTF2::TextureInfo, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::SetTexBasic(glTF2::TextureInfo, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
284 | | |
285 | | inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al) |
286 | 0 | { |
287 | |
|
288 | 0 | if (t.texture) { |
289 | 0 | Value tex; |
290 | |
|
291 | 0 | SetTexBasic(t, tex, al); |
292 | |
|
293 | 0 | obj.AddMember(StringRef(propName), tex, al); |
294 | 0 | } |
295 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:glTF2::(anonymous namespace)::WriteTex(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, glTF2::TextureInfo, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::WriteTex(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, glTF2::TextureInfo, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
296 | | |
297 | | inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al) |
298 | 0 | { |
299 | |
|
300 | 0 | if (t.texture) { |
301 | 0 | Value tex; |
302 | |
|
303 | 0 | SetTexBasic(t, tex, al); |
304 | |
|
305 | 0 | if (t.scale != 1) { |
306 | 0 | tex.AddMember("scale", t.scale, al); |
307 | 0 | } |
308 | |
|
309 | 0 | obj.AddMember(StringRef(propName), tex, al); |
310 | 0 | } |
311 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:glTF2::(anonymous namespace)::WriteTex(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, glTF2::NormalTextureInfo, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::WriteTex(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, glTF2::NormalTextureInfo, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
312 | | |
313 | | inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al) |
314 | 0 | { |
315 | |
|
316 | 0 | if (t.texture) { |
317 | 0 | Value tex; |
318 | |
|
319 | 0 | SetTexBasic(t, tex, al); |
320 | |
|
321 | 0 | if (t.strength != 1) { |
322 | 0 | tex.AddMember("strength", t.strength, al); |
323 | 0 | } |
324 | |
|
325 | 0 | obj.AddMember(StringRef(propName), tex, al); |
326 | 0 | } |
327 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:glTF2::(anonymous namespace)::WriteTex(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, glTF2::OcclusionTextureInfo, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::WriteTex(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, glTF2::OcclusionTextureInfo, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
328 | | |
329 | | template<size_t N> |
330 | | inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al) |
331 | 0 | { |
332 | 0 | Value arr; |
333 | 0 | obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al); |
334 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:void glTF2::(anonymous namespace)::WriteVec<4ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [4ul], char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:void glTF2::(anonymous namespace)::WriteVec<3ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [3ul], char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:void glTF2::(anonymous namespace)::WriteVec<4ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [4ul], char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:void glTF2::(anonymous namespace)::WriteVec<3ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [3ul], char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
335 | | |
336 | | template<size_t N> |
337 | | inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, const float(&defaultVal)[N], MemoryPoolAllocator<>& al) |
338 | 0 | { |
339 | 0 | if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) { |
340 | 0 | WriteVec(obj, prop, propName, al); |
341 | 0 | } |
342 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:void glTF2::(anonymous namespace)::WriteVec<4ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [4ul], char const*, float const (&) [4ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Importer.cpp:void glTF2::(anonymous namespace)::WriteVec<3ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [3ul], char const*, float const (&) [3ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:void glTF2::(anonymous namespace)::WriteVec<4ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [4ul], char const*, float const (&) [4ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:void glTF2::(anonymous namespace)::WriteVec<3ul>(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float (&) [3ul], char const*, float const (&) [3ul], rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
343 | | |
344 | | inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al) |
345 | 0 | { |
346 | 0 | Value num; |
347 | 0 | obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al); |
348 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:glTF2::(anonymous namespace)::WriteFloat(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::WriteFloat(rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, float, char const*, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>&) |
349 | | } |
350 | | |
351 | | inline void Write(Value& obj, Material& m, AssetWriter& w) |
352 | 0 | { |
353 | 0 | Value pbrMetallicRoughness; |
354 | 0 | pbrMetallicRoughness.SetObject(); |
355 | 0 | { |
356 | 0 | WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl); |
357 | 0 | WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl); |
358 | 0 | WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultBaseColor, w.mAl); |
359 | |
|
360 | 0 | if (m.pbrMetallicRoughness.metallicFactor != 1) { |
361 | 0 | WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicFactor, "metallicFactor", w.mAl); |
362 | 0 | } |
363 | |
|
364 | 0 | if (m.pbrMetallicRoughness.roughnessFactor != 1) { |
365 | 0 | WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.roughnessFactor, "roughnessFactor", w.mAl); |
366 | 0 | } |
367 | 0 | } |
368 | |
|
369 | 0 | if (!pbrMetallicRoughness.ObjectEmpty()) { |
370 | 0 | obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl); |
371 | 0 | } |
372 | |
|
373 | 0 | WriteTex(obj, m.normalTexture, "normalTexture", w.mAl); |
374 | 0 | WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl); |
375 | 0 | WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl); |
376 | 0 | WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl); |
377 | |
|
378 | 0 | if (m.alphaCutoff != 0.5) { |
379 | 0 | WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl); |
380 | 0 | } |
381 | |
|
382 | 0 | if (m.alphaMode != "OPAQUE") { |
383 | 0 | obj.AddMember("alphaMode", Value(m.alphaMode, w.mAl).Move(), w.mAl); |
384 | 0 | } |
385 | |
|
386 | 0 | if (m.doubleSided) { |
387 | 0 | obj.AddMember("doubleSided", m.doubleSided, w.mAl); |
388 | 0 | } |
389 | |
|
390 | 0 | Value exts; |
391 | 0 | exts.SetObject(); |
392 | |
|
393 | 0 | if (m.pbrSpecularGlossiness.isPresent) { |
394 | 0 | Value pbrSpecularGlossiness; |
395 | 0 | pbrSpecularGlossiness.SetObject(); |
396 | |
|
397 | 0 | PbrSpecularGlossiness &pbrSG = m.pbrSpecularGlossiness.value; |
398 | | |
399 | | //pbrSpecularGlossiness |
400 | 0 | WriteVec(pbrSpecularGlossiness, pbrSG.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl); |
401 | 0 | WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); |
402 | |
|
403 | 0 | if (pbrSG.glossinessFactor != 1) { |
404 | 0 | WriteFloat(pbrSpecularGlossiness, pbrSG.glossinessFactor, "glossinessFactor", w.mAl); |
405 | 0 | } |
406 | |
|
407 | 0 | WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl); |
408 | 0 | WriteTex(pbrSpecularGlossiness, pbrSG.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); |
409 | |
|
410 | 0 | if (!pbrSpecularGlossiness.ObjectEmpty()) { |
411 | 0 | exts.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl); |
412 | 0 | } |
413 | 0 | } |
414 | |
|
415 | 0 | if (m.unlit) { |
416 | 0 | Value unlit; |
417 | 0 | unlit.SetObject(); |
418 | 0 | exts.AddMember("KHR_materials_unlit", unlit, w.mAl); |
419 | 0 | } |
420 | |
|
421 | 0 | if (m.materialSpecular.isPresent) { |
422 | 0 | Value materialSpecular(rapidjson::Type::kObjectType); |
423 | 0 | materialSpecular.SetObject(); |
424 | |
|
425 | 0 | MaterialSpecular &specular = m.materialSpecular.value; |
426 | |
|
427 | 0 | if (specular.specularFactor != 0.0f) { |
428 | 0 | WriteFloat(materialSpecular, specular.specularFactor, "specularFactor", w.mAl); |
429 | 0 | } |
430 | 0 | if (specular.specularColorFactor[0] != defaultSpecularColorFactor[0] && specular.specularColorFactor[1] != defaultSpecularColorFactor[1] && specular.specularColorFactor[2] != defaultSpecularColorFactor[2]) { |
431 | 0 | WriteVec(materialSpecular, specular.specularColorFactor, "specularColorFactor", w.mAl); |
432 | 0 | } |
433 | |
|
434 | 0 | WriteTex(materialSpecular, specular.specularTexture, "specularTexture", w.mAl); |
435 | 0 | WriteTex(materialSpecular, specular.specularColorTexture, "specularColorTexture", w.mAl); |
436 | |
|
437 | 0 | if (!materialSpecular.ObjectEmpty()) { |
438 | 0 | exts.AddMember("KHR_materials_specular", materialSpecular, w.mAl); |
439 | 0 | } |
440 | 0 | } |
441 | |
|
442 | 0 | if (m.materialSheen.isPresent) { |
443 | 0 | Value materialSheen(rapidjson::Type::kObjectType); |
444 | |
|
445 | 0 | MaterialSheen &sheen = m.materialSheen.value; |
446 | |
|
447 | 0 | WriteVec(materialSheen, sheen.sheenColorFactor, "sheenColorFactor", defaultSheenFactor, w.mAl); |
448 | |
|
449 | 0 | if (sheen.sheenRoughnessFactor != 0.f) { |
450 | 0 | WriteFloat(materialSheen, sheen.sheenRoughnessFactor, "sheenRoughnessFactor", w.mAl); |
451 | 0 | } |
452 | |
|
453 | 0 | WriteTex(materialSheen, sheen.sheenColorTexture, "sheenColorTexture", w.mAl); |
454 | 0 | WriteTex(materialSheen, sheen.sheenRoughnessTexture, "sheenRoughnessTexture", w.mAl); |
455 | |
|
456 | 0 | if (!materialSheen.ObjectEmpty()) { |
457 | 0 | exts.AddMember("KHR_materials_sheen", materialSheen, w.mAl); |
458 | 0 | } |
459 | 0 | } |
460 | |
|
461 | 0 | if (m.materialClearcoat.isPresent) { |
462 | 0 | Value materialClearcoat(rapidjson::Type::kObjectType); |
463 | |
|
464 | 0 | MaterialClearcoat &clearcoat = m.materialClearcoat.value; |
465 | |
|
466 | 0 | if (clearcoat.clearcoatFactor != 0.f) { |
467 | 0 | WriteFloat(materialClearcoat, clearcoat.clearcoatFactor, "clearcoatFactor", w.mAl); |
468 | 0 | } |
469 | |
|
470 | 0 | if (clearcoat.clearcoatRoughnessFactor != 0.f) { |
471 | 0 | WriteFloat(materialClearcoat, clearcoat.clearcoatRoughnessFactor, "clearcoatRoughnessFactor", w.mAl); |
472 | 0 | } |
473 | |
|
474 | 0 | WriteTex(materialClearcoat, clearcoat.clearcoatTexture, "clearcoatTexture", w.mAl); |
475 | 0 | WriteTex(materialClearcoat, clearcoat.clearcoatRoughnessTexture, "clearcoatRoughnessTexture", w.mAl); |
476 | 0 | WriteTex(materialClearcoat, clearcoat.clearcoatNormalTexture, "clearcoatNormalTexture", w.mAl); |
477 | |
|
478 | 0 | if (!materialClearcoat.ObjectEmpty()) { |
479 | 0 | exts.AddMember("KHR_materials_clearcoat", materialClearcoat, w.mAl); |
480 | 0 | } |
481 | 0 | } |
482 | |
|
483 | 0 | if (m.materialTransmission.isPresent) { |
484 | 0 | Value materialTransmission(rapidjson::Type::kObjectType); |
485 | |
|
486 | 0 | MaterialTransmission &transmission = m.materialTransmission.value; |
487 | |
|
488 | 0 | if (transmission.transmissionFactor != 0.f) { |
489 | 0 | WriteFloat(materialTransmission, transmission.transmissionFactor, "transmissionFactor", w.mAl); |
490 | 0 | } |
491 | |
|
492 | 0 | WriteTex(materialTransmission, transmission.transmissionTexture, "transmissionTexture", w.mAl); |
493 | |
|
494 | 0 | if (!materialTransmission.ObjectEmpty()) { |
495 | 0 | exts.AddMember("KHR_materials_transmission", materialTransmission, w.mAl); |
496 | 0 | } |
497 | 0 | } |
498 | |
|
499 | 0 | if (m.materialVolume.isPresent) { |
500 | 0 | Value materialVolume(rapidjson::Type::kObjectType); |
501 | |
|
502 | 0 | MaterialVolume &volume = m.materialVolume.value; |
503 | |
|
504 | 0 | if (volume.thicknessFactor != 0.f) { |
505 | 0 | WriteFloat(materialVolume, volume.thicknessFactor, "thicknessFactor", w.mAl); |
506 | 0 | } |
507 | |
|
508 | 0 | WriteTex(materialVolume, volume.thicknessTexture, "thicknessTexture", w.mAl); |
509 | |
|
510 | 0 | if (volume.attenuationDistance != std::numeric_limits<float>::infinity()) { |
511 | 0 | WriteFloat(materialVolume, volume.attenuationDistance, "attenuationDistance", w.mAl); |
512 | 0 | } |
513 | |
|
514 | 0 | WriteVec(materialVolume, volume.attenuationColor, "attenuationColor", defaultAttenuationColor, w.mAl); |
515 | |
|
516 | 0 | if (!materialVolume.ObjectEmpty()) { |
517 | 0 | exts.AddMember("KHR_materials_volume", materialVolume, w.mAl); |
518 | 0 | } |
519 | 0 | } |
520 | |
|
521 | 0 | if (m.materialIOR.isPresent) { |
522 | 0 | Value materialIOR(rapidjson::Type::kObjectType); |
523 | |
|
524 | 0 | MaterialIOR &ior = m.materialIOR.value; |
525 | |
|
526 | 0 | if (ior.ior != 1.5f) { |
527 | 0 | WriteFloat(materialIOR, ior.ior, "ior", w.mAl); |
528 | 0 | } |
529 | |
|
530 | 0 | if (!materialIOR.ObjectEmpty()) { |
531 | 0 | exts.AddMember("KHR_materials_ior", materialIOR, w.mAl); |
532 | 0 | } |
533 | 0 | } |
534 | |
|
535 | 0 | if (m.materialEmissiveStrength.isPresent) { |
536 | 0 | Value materialEmissiveStrength(rapidjson::Type::kObjectType); |
537 | |
|
538 | 0 | MaterialEmissiveStrength &emissiveStrength = m.materialEmissiveStrength.value; |
539 | |
|
540 | 0 | if (emissiveStrength.emissiveStrength != 0.f) { |
541 | 0 | WriteFloat(materialEmissiveStrength, emissiveStrength.emissiveStrength, "emissiveStrength", w.mAl); |
542 | 0 | } |
543 | |
|
544 | 0 | if (!materialEmissiveStrength.ObjectEmpty()) { |
545 | 0 | exts.AddMember("KHR_materials_emissive_strength", materialEmissiveStrength, w.mAl); |
546 | 0 | } |
547 | 0 | } |
548 | |
|
549 | 0 | if (m.materialAnisotropy.isPresent) { |
550 | 0 | Value materialAnisotropy(rapidjson::Type::kObjectType); |
551 | |
|
552 | 0 | MaterialAnisotropy &anisotropy = m.materialAnisotropy.value; |
553 | |
|
554 | 0 | if (anisotropy.anisotropyStrength != 0.f) { |
555 | 0 | WriteFloat(materialAnisotropy, anisotropy.anisotropyStrength, "anisotropyStrength", w.mAl); |
556 | 0 | } |
557 | |
|
558 | 0 | if (anisotropy.anisotropyRotation != 0.f) { |
559 | 0 | WriteFloat(materialAnisotropy, anisotropy.anisotropyRotation, "anisotropyRotation", w.mAl); |
560 | 0 | } |
561 | |
|
562 | 0 | WriteTex(materialAnisotropy, anisotropy.anisotropyTexture, "anisotropyTexture", w.mAl); |
563 | |
|
564 | 0 | if (!materialAnisotropy.ObjectEmpty()) { |
565 | 0 | exts.AddMember("KHR_materials_anisotropy", materialAnisotropy, w.mAl); |
566 | 0 | } |
567 | 0 | } |
568 | |
|
569 | 0 | if (!exts.ObjectEmpty()) { |
570 | 0 | obj.AddMember("extensions", exts, w.mAl); |
571 | 0 | } |
572 | 0 | } |
573 | | |
574 | | namespace { |
575 | | inline void WriteAttrs(AssetWriter& w, Value& attrs, Mesh::AccessorList& lst, |
576 | | const char* semantic, bool forceNumber = false) |
577 | 0 | { |
578 | 0 | if (lst.empty()) return; |
579 | 0 | if (lst.size() == 1 && !forceNumber) { |
580 | 0 | attrs.AddMember(StringRef(semantic), lst[0]->index, w.mAl); |
581 | 0 | } |
582 | 0 | else { |
583 | 0 | for (size_t i = 0; i < lst.size(); ++i) { |
584 | 0 | char buffer[32]; |
585 | 0 | ai_snprintf(buffer, 32, "%s_%d", semantic, int(i)); |
586 | 0 | attrs.AddMember(Value(buffer, w.mAl).Move(), lst[i]->index, w.mAl); |
587 | 0 | } |
588 | 0 | } |
589 | 0 | } Unexecuted instantiation: glTF2Importer.cpp:glTF2::(anonymous namespace)::WriteAttrs(glTF2::AssetWriter&, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, std::__1::vector<glTFCommon::Ref<glTF2::Accessor>, std::__1::allocator<glTFCommon::Ref<glTF2::Accessor> > >&, char const*, bool) Unexecuted instantiation: glTF2Exporter.cpp:glTF2::(anonymous namespace)::WriteAttrs(glTF2::AssetWriter&, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >&, std::__1::vector<glTFCommon::Ref<glTF2::Accessor>, std::__1::allocator<glTFCommon::Ref<glTF2::Accessor> > >&, char const*, bool) |
590 | | } |
591 | | |
592 | | inline void Write(Value& obj, Mesh& m, AssetWriter& w) |
593 | 0 | { |
594 | | /****************** Primitives *******************/ |
595 | 0 | Value primitives; |
596 | 0 | primitives.SetArray(); |
597 | 0 | primitives.Reserve(unsigned(m.primitives.size()), w.mAl); |
598 | |
|
599 | 0 | for (size_t i = 0; i < m.primitives.size(); ++i) { |
600 | 0 | Mesh::Primitive& p = m.primitives[i]; |
601 | 0 | Value prim; |
602 | 0 | prim.SetObject(); |
603 | | |
604 | | // Extensions |
605 | 0 | if (p.ngonEncoded) |
606 | 0 | { |
607 | 0 | Value exts; |
608 | 0 | exts.SetObject(); |
609 | |
|
610 | 0 | Value FB_ngon_encoding; |
611 | 0 | FB_ngon_encoding.SetObject(); |
612 | |
|
613 | 0 | exts.AddMember(StringRef("FB_ngon_encoding"), FB_ngon_encoding, w.mAl); |
614 | 0 | prim.AddMember("extensions", exts, w.mAl); |
615 | 0 | } |
616 | |
|
617 | 0 | { |
618 | 0 | prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl); |
619 | |
|
620 | 0 | if (p.material) |
621 | 0 | prim.AddMember("material", p.material->index, w.mAl); |
622 | |
|
623 | 0 | if (p.indices) |
624 | 0 | prim.AddMember("indices", p.indices->index, w.mAl); |
625 | |
|
626 | 0 | Value attrs; |
627 | 0 | attrs.SetObject(); |
628 | 0 | { |
629 | 0 | WriteAttrs(w, attrs, p.attributes.position, "POSITION"); |
630 | 0 | WriteAttrs(w, attrs, p.attributes.normal, "NORMAL"); |
631 | 0 | WriteAttrs(w, attrs, p.attributes.tangent, "TANGENT"); |
632 | 0 | WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true); |
633 | 0 | WriteAttrs(w, attrs, p.attributes.color, "COLOR", true); |
634 | 0 | WriteAttrs(w, attrs, p.attributes.joint, "JOINTS", true); |
635 | 0 | WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS", true); |
636 | 0 | } |
637 | 0 | prim.AddMember("attributes", attrs, w.mAl); |
638 | | |
639 | | // targets for blendshapes |
640 | 0 | if (p.targets.size() > 0) { |
641 | 0 | Value tjs; |
642 | 0 | tjs.SetArray(); |
643 | 0 | tjs.Reserve(unsigned(p.targets.size()), w.mAl); |
644 | 0 | for (unsigned int t = 0; t < p.targets.size(); ++t) { |
645 | 0 | Value tj; |
646 | 0 | tj.SetObject(); |
647 | 0 | { |
648 | 0 | WriteAttrs(w, tj, p.targets[t].position, "POSITION"); |
649 | 0 | WriteAttrs(w, tj, p.targets[t].normal, "NORMAL"); |
650 | 0 | WriteAttrs(w, tj, p.targets[t].tangent, "TANGENT"); |
651 | 0 | } |
652 | 0 | tjs.PushBack(tj, w.mAl); |
653 | 0 | } |
654 | 0 | prim.AddMember("targets", tjs, w.mAl); |
655 | 0 | } |
656 | 0 | } |
657 | 0 | primitives.PushBack(prim, w.mAl); |
658 | 0 | } |
659 | |
|
660 | 0 | obj.AddMember("primitives", primitives, w.mAl); |
661 | | // targetNames |
662 | 0 | if (m.targetNames.size() > 0) { |
663 | 0 | Value extras; |
664 | 0 | extras.SetObject(); |
665 | 0 | Value targetNames; |
666 | 0 | targetNames.SetArray(); |
667 | 0 | targetNames.Reserve(unsigned(m.targetNames.size()), w.mAl); |
668 | 0 | for (unsigned int n = 0; n < m.targetNames.size(); ++n) { |
669 | 0 | std::string name = m.targetNames[n]; |
670 | 0 | Value tname; |
671 | 0 | tname.SetString(name.c_str(), w.mAl); |
672 | 0 | targetNames.PushBack(tname, w.mAl); |
673 | 0 | } |
674 | 0 | extras.AddMember("targetNames", targetNames, w.mAl); |
675 | 0 | obj.AddMember("extras", extras, w.mAl); |
676 | 0 | } |
677 | 0 | } |
678 | | |
679 | 0 | inline void WriteExtrasValue(Value &parent, const CustomExtension &value, AssetWriter &w) { |
680 | 0 | Value valueNode; |
681 | |
|
682 | 0 | if (value.mStringValue.isPresent) { |
683 | 0 | MakeValue(valueNode, value.mStringValue.value.c_str(), w.mAl); |
684 | 0 | } else if (value.mDoubleValue.isPresent) { |
685 | 0 | MakeValue(valueNode, value.mDoubleValue.value, w.mAl); |
686 | 0 | } else if (value.mUint64Value.isPresent) { |
687 | 0 | MakeValue(valueNode, value.mUint64Value.value, w.mAl); |
688 | 0 | } else if (value.mInt64Value.isPresent) { |
689 | 0 | MakeValue(valueNode, value.mInt64Value.value, w.mAl); |
690 | 0 | } else if (value.mBoolValue.isPresent) { |
691 | 0 | MakeValue(valueNode, value.mBoolValue.value, w.mAl); |
692 | 0 | } else if (value.mValues.isPresent) { |
693 | 0 | valueNode.SetObject(); |
694 | 0 | for (auto const &subvalue : value.mValues.value) { |
695 | 0 | WriteExtrasValue(valueNode, subvalue, w); |
696 | 0 | } |
697 | 0 | } |
698 | |
|
699 | 0 | parent.AddMember(StringRef(value.name), valueNode, w.mAl); |
700 | 0 | } |
701 | | |
702 | 0 | inline void WriteExtras(Value &obj, const Extras &extras, AssetWriter &w) { |
703 | 0 | if (!extras.HasExtras()) { |
704 | 0 | return; |
705 | 0 | } |
706 | | |
707 | 0 | Value extrasNode; |
708 | 0 | extrasNode.SetObject(); |
709 | |
|
710 | 0 | for (auto const &value : extras.mValues) { |
711 | 0 | WriteExtrasValue(extrasNode, value, w); |
712 | 0 | } |
713 | |
|
714 | 0 | obj.AddMember("extras", extrasNode, w.mAl); |
715 | 0 | } |
716 | | |
717 | | inline void Write(Value& obj, Node& n, AssetWriter& w) |
718 | 0 | { |
719 | 0 | if (n.matrix.isPresent) { |
720 | 0 | Value val; |
721 | 0 | obj.AddMember("matrix", MakeValue(val, n.matrix.value, w.mAl).Move(), w.mAl); |
722 | 0 | } |
723 | |
|
724 | 0 | if (n.translation.isPresent) { |
725 | 0 | Value val; |
726 | 0 | obj.AddMember("translation", MakeValue(val, n.translation.value, w.mAl).Move(), w.mAl); |
727 | 0 | } |
728 | |
|
729 | 0 | if (n.scale.isPresent) { |
730 | 0 | Value val; |
731 | 0 | obj.AddMember("scale", MakeValue(val, n.scale.value, w.mAl).Move(), w.mAl); |
732 | 0 | } |
733 | 0 | if (n.rotation.isPresent) { |
734 | 0 | Value val; |
735 | 0 | obj.AddMember("rotation", MakeValue(val, n.rotation.value, w.mAl).Move(), w.mAl); |
736 | 0 | } |
737 | |
|
738 | 0 | AddRefsVector(obj, "children", n.children, w.mAl); |
739 | |
|
740 | 0 | if (!n.meshes.empty()) { |
741 | 0 | obj.AddMember("mesh", n.meshes[0]->index, w.mAl); |
742 | 0 | } |
743 | |
|
744 | 0 | if (n.skin) { |
745 | 0 | obj.AddMember("skin", n.skin->index, w.mAl); |
746 | 0 | } |
747 | | |
748 | | //gltf2 spec does not support "skeletons" under node |
749 | 0 | if(n.skeletons.size()) { |
750 | 0 | AddRefsVector(obj, "skeletons", n.skeletons, w.mAl); |
751 | 0 | } |
752 | |
|
753 | 0 | WriteExtras(obj, n.extras, w); |
754 | 0 | } |
755 | | |
756 | | inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/) |
757 | 0 | { |
758 | 0 |
|
759 | 0 | } |
760 | | |
761 | | inline void Write(Value& obj, Sampler& b, AssetWriter& w) |
762 | 0 | { |
763 | 0 | if (!b.name.empty()) { |
764 | 0 | obj.AddMember("name", b.name, w.mAl); |
765 | 0 | } |
766 | |
|
767 | 0 | if (b.wrapS != SamplerWrap::UNSET && b.wrapS != SamplerWrap::Repeat) { |
768 | 0 | obj.AddMember("wrapS", static_cast<unsigned int>(b.wrapS), w.mAl); |
769 | 0 | } |
770 | |
|
771 | 0 | if (b.wrapT != SamplerWrap::UNSET && b.wrapT != SamplerWrap::Repeat) { |
772 | 0 | obj.AddMember("wrapT", static_cast<unsigned int>(b.wrapT), w.mAl); |
773 | 0 | } |
774 | |
|
775 | 0 | if (b.magFilter != SamplerMagFilter::UNSET) { |
776 | 0 | obj.AddMember("magFilter", static_cast<unsigned int>(b.magFilter), w.mAl); |
777 | 0 | } |
778 | |
|
779 | 0 | if (b.minFilter != SamplerMinFilter::UNSET) { |
780 | 0 | obj.AddMember("minFilter", static_cast<unsigned int>(b.minFilter), w.mAl); |
781 | 0 | } |
782 | 0 | } |
783 | | |
784 | | inline void Write(Value& scene, Scene& s, AssetWriter& w) |
785 | 0 | { |
786 | 0 | AddRefsVector(scene, "nodes", s.nodes, w.mAl); |
787 | 0 | } |
788 | | |
789 | | inline void Write(Value& /*obj*/, Shader& /*b*/, AssetWriter& /*w*/) |
790 | 0 | { |
791 | 0 |
|
792 | 0 | } |
793 | | |
794 | | inline void Write(Value& obj, Skin& b, AssetWriter& w) |
795 | 0 | { |
796 | | /****************** jointNames *******************/ |
797 | 0 | Value vJointNames; |
798 | 0 | vJointNames.SetArray(); |
799 | 0 | vJointNames.Reserve(unsigned(b.jointNames.size()), w.mAl); |
800 | |
|
801 | 0 | for (size_t i = 0; i < unsigned(b.jointNames.size()); ++i) { |
802 | 0 | vJointNames.PushBack(b.jointNames[i]->index, w.mAl); |
803 | 0 | } |
804 | 0 | obj.AddMember("joints", vJointNames, w.mAl); |
805 | |
|
806 | 0 | if (b.bindShapeMatrix.isPresent) { |
807 | 0 | Value val; |
808 | 0 | obj.AddMember("bindShapeMatrix", MakeValue(val, b.bindShapeMatrix.value, w.mAl).Move(), w.mAl); |
809 | 0 | } |
810 | |
|
811 | 0 | if (b.inverseBindMatrices) { |
812 | 0 | obj.AddMember("inverseBindMatrices", b.inverseBindMatrices->index, w.mAl); |
813 | 0 | } |
814 | |
|
815 | 0 | } |
816 | | |
817 | | inline void Write(Value& obj, Texture& tex, AssetWriter& w) |
818 | 0 | { |
819 | 0 | if (tex.source) { |
820 | 0 | obj.AddMember("source", tex.source->index, w.mAl); |
821 | 0 | } |
822 | 0 | if (tex.sampler) { |
823 | 0 | obj.AddMember("sampler", tex.sampler->index, w.mAl); |
824 | 0 | } |
825 | 0 | } |
826 | | |
827 | | inline AssetWriter::AssetWriter(Asset& a) |
828 | 0 | : mDoc() |
829 | 0 | , mAsset(a) |
830 | 0 | , mAl(mDoc.GetAllocator()) |
831 | 0 | { |
832 | 0 | mDoc.SetObject(); |
833 | |
|
834 | 0 | WriteMetadata(); |
835 | 0 | WriteExtensionsUsed(); |
836 | | |
837 | | // Dump the contents of the dictionaries |
838 | 0 | for (size_t i = 0; i < a.mDicts.size(); ++i) { |
839 | 0 | a.mDicts[i]->WriteObjects(*this); |
840 | 0 | } |
841 | | |
842 | | // Add the target scene field |
843 | 0 | if (mAsset.scene) { |
844 | 0 | mDoc.AddMember("scene", mAsset.scene->index, mAl); |
845 | 0 | } |
846 | |
|
847 | 0 | if(mAsset.extras) { |
848 | 0 | mDoc.AddMember("extras", *mAsset.extras, mAl); |
849 | 0 | } |
850 | 0 | } |
851 | | |
852 | | inline void AssetWriter::WriteFile(const char* path) |
853 | 0 | { |
854 | 0 | std::unique_ptr<IOStream> jsonOutFile(mAsset.OpenFile(path, "wt", true)); |
855 | 0 |
|
856 | 0 | if (jsonOutFile == nullptr) { |
857 | 0 | throw DeadlyExportError("Could not open output file: " + std::string(path)); |
858 | 0 | } |
859 | 0 |
|
860 | 0 | StringBuffer docBuffer; |
861 | 0 |
|
862 | 0 | PrettyWriter<StringBuffer> writer(docBuffer); |
863 | 0 | if (!mDoc.Accept(writer)) { |
864 | 0 | throw DeadlyExportError("Failed to write scene data!"); |
865 | 0 | } |
866 | 0 |
|
867 | 0 | if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { |
868 | 0 | throw DeadlyExportError("Failed to write scene data!"); |
869 | 0 | } |
870 | 0 |
|
871 | 0 | // Write buffer data to separate .bin files |
872 | 0 | for (unsigned int i = 0; i < mAsset.buffers.Size(); ++i) { |
873 | 0 | Ref<Buffer> b = mAsset.buffers.Get(i); |
874 | 0 |
|
875 | 0 | std::string binPath = b->GetURI(); |
876 | 0 |
|
877 | 0 | std::unique_ptr<IOStream> binOutFile(mAsset.OpenFile(binPath, "wb", true)); |
878 | 0 |
|
879 | 0 | if (binOutFile == nullptr) { |
880 | 0 | throw DeadlyExportError("Could not open output file: " + binPath); |
881 | 0 | } |
882 | 0 |
|
883 | 0 | if (b->byteLength > 0) { |
884 | 0 | if (binOutFile->Write(b->GetPointer(), b->byteLength, 1) != 1) { |
885 | 0 | throw DeadlyExportError("Failed to write binary file: " + binPath); |
886 | 0 | } |
887 | 0 | } |
888 | 0 | } |
889 | 0 | } |
890 | | |
891 | | inline void AssetWriter::WriteGLBFile(const char* path) |
892 | 0 | { |
893 | 0 | std::unique_ptr<IOStream> outfile(mAsset.OpenFile(path, "wb", true)); |
894 | |
|
895 | 0 | if (outfile == nullptr) { |
896 | 0 | throw DeadlyExportError("Could not open output file: " + std::string(path)); |
897 | 0 | } |
898 | | |
899 | 0 | Ref<Buffer> bodyBuffer = mAsset.GetBodyBuffer(); |
900 | 0 | if (bodyBuffer->byteLength > 0) { |
901 | 0 | rapidjson::Value glbBodyBuffer; |
902 | 0 | glbBodyBuffer.SetObject(); |
903 | 0 | glbBodyBuffer.AddMember("byteLength", static_cast<uint64_t>(bodyBuffer->byteLength), mAl); |
904 | 0 | mDoc["buffers"].PushBack(glbBodyBuffer, mAl); |
905 | 0 | } |
906 | | |
907 | | // Padding with spaces as required by the spec |
908 | 0 | uint32_t padding = 0x20202020; |
909 | | |
910 | | // |
911 | | // JSON chunk |
912 | | // |
913 | |
|
914 | 0 | StringBuffer docBuffer; |
915 | 0 | Writer<StringBuffer> writer(docBuffer); |
916 | 0 | if (!mDoc.Accept(writer)) { |
917 | 0 | throw DeadlyExportError("Failed to write scene data!"); |
918 | 0 | } |
919 | | |
920 | 0 | uint32_t jsonChunkLength = static_cast<uint32_t>((docBuffer.GetSize() + 3) & ~3); // Round up to next multiple of 4 |
921 | 0 | auto paddingLength = jsonChunkLength - docBuffer.GetSize(); |
922 | |
|
923 | 0 | GLB_Chunk jsonChunk; |
924 | 0 | jsonChunk.chunkLength = jsonChunkLength; |
925 | 0 | jsonChunk.chunkType = ChunkType_JSON; |
926 | 0 | AI_SWAP4(jsonChunk.chunkLength); |
927 | |
|
928 | 0 | outfile->Seek(sizeof(GLB_Header), aiOrigin_SET); |
929 | 0 | if (outfile->Write(&jsonChunk, 1, sizeof(GLB_Chunk)) != sizeof(GLB_Chunk)) { |
930 | 0 | throw DeadlyExportError("Failed to write scene data header!"); |
931 | 0 | } |
932 | 0 | if (outfile->Write(docBuffer.GetString(), 1, docBuffer.GetSize()) != docBuffer.GetSize()) { |
933 | 0 | throw DeadlyExportError("Failed to write scene data!"); |
934 | 0 | } |
935 | 0 | if (paddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) { |
936 | 0 | throw DeadlyExportError("Failed to write scene data padding!"); |
937 | 0 | } |
938 | | |
939 | | // |
940 | | // Binary chunk |
941 | | // |
942 | | |
943 | 0 | int GLB_Chunk_count = 1; |
944 | 0 | uint32_t binaryChunkLength = 0; |
945 | 0 | if (bodyBuffer->byteLength > 0) { |
946 | 0 | binaryChunkLength = static_cast<uint32_t>((bodyBuffer->byteLength + 3) & ~3); // Round up to next multiple of 4 |
947 | |
|
948 | 0 | auto curPaddingLength = binaryChunkLength - bodyBuffer->byteLength; |
949 | 0 | ++GLB_Chunk_count; |
950 | |
|
951 | 0 | GLB_Chunk binaryChunk; |
952 | 0 | binaryChunk.chunkLength = binaryChunkLength; |
953 | 0 | binaryChunk.chunkType = ChunkType_BIN; |
954 | 0 | AI_SWAP4(binaryChunk.chunkLength); |
955 | |
|
956 | 0 | size_t bodyOffset = sizeof(GLB_Header) + sizeof(GLB_Chunk) + jsonChunk.chunkLength; |
957 | 0 | outfile->Seek(bodyOffset, aiOrigin_SET); |
958 | 0 | if (outfile->Write(&binaryChunk, 1, sizeof(GLB_Chunk)) != sizeof(GLB_Chunk)) { |
959 | 0 | throw DeadlyExportError("Failed to write body data header!"); |
960 | 0 | } |
961 | 0 | if (outfile->Write(bodyBuffer->GetPointer(), 1, bodyBuffer->byteLength) != bodyBuffer->byteLength) { |
962 | 0 | throw DeadlyExportError("Failed to write body data!"); |
963 | 0 | } |
964 | 0 | if (curPaddingLength && outfile->Write(&padding, 1, curPaddingLength) != curPaddingLength) { |
965 | 0 | throw DeadlyExportError("Failed to write body data padding!"); |
966 | 0 | } |
967 | 0 | } |
968 | | |
969 | | // |
970 | | // Header |
971 | | // |
972 | | |
973 | 0 | GLB_Header header; |
974 | 0 | memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)); |
975 | |
|
976 | 0 | header.version = 2; |
977 | 0 | AI_SWAP4(header.version); |
978 | |
|
979 | 0 | header.length = uint32_t(sizeof(GLB_Header) + GLB_Chunk_count * sizeof(GLB_Chunk) + jsonChunkLength + binaryChunkLength); |
980 | 0 | AI_SWAP4(header.length); |
981 | |
|
982 | 0 | outfile->Seek(0, aiOrigin_SET); |
983 | 0 | if (outfile->Write(&header, 1, sizeof(GLB_Header)) != sizeof(GLB_Header)) { |
984 | 0 | throw DeadlyExportError("Failed to write the header!"); |
985 | 0 | } |
986 | 0 | } Unexecuted instantiation: glTF2::AssetWriter::WriteGLBFile(char const*) Unexecuted instantiation: glTF2::AssetWriter::WriteGLBFile(char const*) |
987 | | |
988 | | inline void AssetWriter::WriteMetadata() |
989 | 0 | { |
990 | 0 | Value asset; |
991 | 0 | asset.SetObject(); |
992 | 0 | asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl); |
993 | 0 | asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); |
994 | 0 | if (!mAsset.asset.copyright.empty()) |
995 | 0 | asset.AddMember("copyright", Value(mAsset.asset.copyright, mAl).Move(), mAl); |
996 | 0 | mDoc.AddMember("asset", asset, mAl); |
997 | 0 | } |
998 | | |
999 | | inline void AssetWriter::WriteExtensionsUsed() |
1000 | 0 | { |
1001 | 0 | Value exts; |
1002 | 0 | exts.SetArray(); |
1003 | 0 | { |
1004 | 0 | // This is used to export pbrSpecularGlossiness materials with GLTF 2. |
1005 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { |
1006 | 0 | exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl); |
1007 | 0 | } |
1008 | 0 |
|
1009 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_unlit) { |
1010 | 0 | exts.PushBack(StringRef("KHR_materials_unlit"), mAl); |
1011 | 0 | } |
1012 | 0 |
|
1013 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_specular) { |
1014 | 0 | exts.PushBack(StringRef("KHR_materials_specular"), mAl); |
1015 | 0 | } |
1016 | 0 |
|
1017 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_sheen) { |
1018 | 0 | exts.PushBack(StringRef("KHR_materials_sheen"), mAl); |
1019 | 0 | } |
1020 | 0 |
|
1021 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_clearcoat) { |
1022 | 0 | exts.PushBack(StringRef("KHR_materials_clearcoat"), mAl); |
1023 | 0 | } |
1024 | 0 |
|
1025 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_transmission) { |
1026 | 0 | exts.PushBack(StringRef("KHR_materials_transmission"), mAl); |
1027 | 0 | } |
1028 | 0 |
|
1029 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_volume) { |
1030 | 0 | exts.PushBack(StringRef("KHR_materials_volume"), mAl); |
1031 | 0 | } |
1032 | 0 |
|
1033 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_ior) { |
1034 | 0 | exts.PushBack(StringRef("KHR_materials_ior"), mAl); |
1035 | 0 | } |
1036 | 0 |
|
1037 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_emissive_strength) { |
1038 | 0 | exts.PushBack(StringRef("KHR_materials_emissive_strength"), mAl); |
1039 | 0 | } |
1040 | 0 |
|
1041 | 0 | if (this->mAsset.extensionsUsed.KHR_materials_anisotropy) { |
1042 | 0 | exts.PushBack(StringRef("KHR_materials_anisotropy"), mAl); |
1043 | 0 | } |
1044 | 0 |
|
1045 | 0 | if (this->mAsset.extensionsUsed.FB_ngon_encoding) { |
1046 | 0 | exts.PushBack(StringRef("FB_ngon_encoding"), mAl); |
1047 | 0 | } |
1048 | 0 |
|
1049 | 0 | if (this->mAsset.extensionsUsed.KHR_texture_basisu) { |
1050 | 0 | exts.PushBack(StringRef("KHR_texture_basisu"), mAl); |
1051 | 0 | } |
1052 | 0 | } |
1053 | 0 |
|
1054 | 0 | if (!exts.Empty()) |
1055 | 0 | mDoc.AddMember("extensionsUsed", exts, mAl); |
1056 | 0 |
|
1057 | 0 | //basisu extensionRequired |
1058 | 0 | Value extsReq; |
1059 | 0 | extsReq.SetArray(); |
1060 | 0 | if (this->mAsset.extensionsUsed.KHR_texture_basisu) { |
1061 | 0 | extsReq.PushBack(StringRef("KHR_texture_basisu"), mAl); |
1062 | 0 | mDoc.AddMember("extensionsRequired", extsReq, mAl); |
1063 | 0 | } |
1064 | 0 | } |
1065 | | |
1066 | | template<class T> |
1067 | | void AssetWriter::WriteObjects(LazyDict<T>& d) |
1068 | 0 | { |
1069 | 0 | if (d.mObjs.empty()) return; |
1070 | | |
1071 | 0 | Value* container = &mDoc; |
1072 | 0 | const char* context = "Document"; |
1073 | |
|
1074 | 0 | if (d.mExtId) { |
1075 | 0 | Value* exts = FindObject(mDoc, "extensions"); |
1076 | 0 | if (nullptr != exts) { |
1077 | 0 | mDoc.AddMember("extensions", Value().SetObject().Move(), mDoc.GetAllocator()); |
1078 | 0 | exts = FindObject(mDoc, "extensions"); |
1079 | 0 | } |
1080 | |
|
1081 | 0 | container = FindObjectInContext(*exts, d.mExtId, "extensions"); |
1082 | 0 | if (nullptr != container) { |
1083 | 0 | exts->AddMember(StringRef(d.mExtId), Value().SetObject().Move(), mDoc.GetAllocator()); |
1084 | 0 | container = FindObjectInContext(*exts, d.mExtId, "extensions"); |
1085 | 0 | context = d.mExtId; |
1086 | 0 | } |
1087 | 0 | } |
1088 | |
|
1089 | 0 | Value *dict = FindArrayInContext(*container, d.mDictId, context); |
1090 | 0 | if (nullptr == dict) { |
1091 | 0 | container->AddMember(StringRef(d.mDictId), Value().SetArray().Move(), mDoc.GetAllocator()); |
1092 | 0 | dict = FindArrayInContext(*container, d.mDictId, context); |
1093 | 0 | if (nullptr == dict) { |
1094 | 0 | return; |
1095 | 0 | } |
1096 | 0 | } |
1097 | | |
1098 | 0 | for (size_t i = 0; i < d.mObjs.size(); ++i) { |
1099 | 0 | if (d.mObjs[i]->IsSpecial()) { |
1100 | 0 | continue; |
1101 | 0 | } |
1102 | | |
1103 | 0 | Value obj; |
1104 | 0 | obj.SetObject(); |
1105 | |
|
1106 | 0 | if (!d.mObjs[i]->name.empty()) { |
1107 | 0 | obj.AddMember("name", StringRef(d.mObjs[i]->name.c_str()), mAl); |
1108 | 0 | } |
1109 | |
|
1110 | 0 | Write(obj, *d.mObjs[i], *this); |
1111 | |
|
1112 | 0 | dict->PushBack(obj, mAl); |
1113 | 0 | } |
1114 | 0 | } Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Accessor>(glTF2::LazyDict<glTF2::Accessor>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Animation>(glTF2::LazyDict<glTF2::Animation>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Buffer>(glTF2::LazyDict<glTF2::Buffer>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::BufferView>(glTF2::LazyDict<glTF2::BufferView>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Camera>(glTF2::LazyDict<glTF2::Camera>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Light>(glTF2::LazyDict<glTF2::Light>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Image>(glTF2::LazyDict<glTF2::Image>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Material>(glTF2::LazyDict<glTF2::Material>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Mesh>(glTF2::LazyDict<glTF2::Mesh>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Node>(glTF2::LazyDict<glTF2::Node>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Sampler>(glTF2::LazyDict<glTF2::Sampler>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Scene>(glTF2::LazyDict<glTF2::Scene>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Skin>(glTF2::LazyDict<glTF2::Skin>&) Unexecuted instantiation: void glTF2::AssetWriter::WriteObjects<glTF2::Texture>(glTF2::LazyDict<glTF2::Texture>&) |
1115 | | |
1116 | | template<class T> |
1117 | | void WriteLazyDict(LazyDict<T>& d, AssetWriter& w) |
1118 | 0 | { |
1119 | 0 | w.WriteObjects(d); |
1120 | 0 | } Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Accessor>(glTF2::LazyDict<glTF2::Accessor>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Animation>(glTF2::LazyDict<glTF2::Animation>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Buffer>(glTF2::LazyDict<glTF2::Buffer>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::BufferView>(glTF2::LazyDict<glTF2::BufferView>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Camera>(glTF2::LazyDict<glTF2::Camera>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Light>(glTF2::LazyDict<glTF2::Light>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Image>(glTF2::LazyDict<glTF2::Image>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Material>(glTF2::LazyDict<glTF2::Material>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Mesh>(glTF2::LazyDict<glTF2::Mesh>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Node>(glTF2::LazyDict<glTF2::Node>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Sampler>(glTF2::LazyDict<glTF2::Sampler>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Scene>(glTF2::LazyDict<glTF2::Scene>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Skin>(glTF2::LazyDict<glTF2::Skin>&, glTF2::AssetWriter&) Unexecuted instantiation: void glTF2::WriteLazyDict<glTF2::Texture>(glTF2::LazyDict<glTF2::Texture>&, glTF2::AssetWriter&) |
1121 | | |
1122 | | } |