8 const auto* version =
value.find(
"version");
9 if (version && version->isInt64() && version->asInt() == 1) {
12 throw std::runtime_error(
"fluids.volume/colliders");
14 for (
size_t i = 0; i <
source->arraySize(); ++i) {
15 auto collider =
source->at(i);
16 if (!collider.isObject() || collider.find(
"rotation") || collider.find(
"angularVelocity"))
17 throw std::runtime_error(
"fluids.volume/colliders");
18 collider.set(
"rotation", pack(glm::vec4(0, 0, 0, 1)));
19 collider.set(
"angularVelocity", pack(glm::vec3(0.f)));
20 colliders.push_back(std::move(collider));
22 migrated.set(
"colliders",
Value(std::move(colliders)));
23 migrated.set(
"version", 2);
25 const auto* migratedVersion = migrated.find(
"version");
26 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 2) {
27 if (migrated.find(
"attachments"))
throw std::runtime_error(
"fluids.volume/attachments");
29 migrated.set(
"version", 3);
31 migratedVersion = migrated.find(
"version");
32 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 3) {
33 const auto*
source = migrated.find(
"particles");
35 throw std::runtime_error(
"fluids.volume/particles");
37 particles.reserve(
source->arraySize());
38 for (
size_t i = 0; i <
source->arraySize(); ++i) {
39 auto particle =
source->at(i);
40 if (!particle.isObject() || particle.find(
"collisionFilter"))
41 throw std::runtime_error(
"fluids.volume/particles");
42 particle.set(
"collisionFilter", int64_t(0xffff0001u));
43 particles.push_back(std::move(particle));
45 migrated.set(
"particles",
Value(std::move(particles)));
46 migrated.set(
"version", 4);
48 migratedVersion = migrated.find(
"version");
49 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 4) {
50 const auto*
source = migrated.find(
"particles");
51 const auto*
settings = migrated.find(
"settings");
54 throw std::runtime_error(
"fluids.volume/particles");
57 particles.reserve(
source->arraySize());
58 for (
size_t i = 0; i <
source->arraySize(); ++i) {
59 auto particle =
source->at(i);
60 if (!particle.isObject() || particle.find(
"radii") || particle.find(
"orientation"))
61 throw std::runtime_error(
"fluids.volume/particles");
62 particle.set(
"radii", pack(glm::vec3(
radius)));
63 particle.set(
"orientation", pack(glm::vec4(0, 0, 0, 1)));
64 particles.push_back(std::move(particle));
66 migrated.set(
"particles",
Value(std::move(particles)));
67 migrated.set(
"version", 5);
69 migratedVersion = migrated.find(
"version");
70 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 5) {
71 const auto* particles = migrated.find(
"particles");
72 const auto* colliders = migrated.find(
"colliders");
73 const auto*
source = migrated.find(
"attachments");
74 if (!particles || !particles->isArray() || !colliders || !colliders->isArray() || !
source ||
76 throw std::runtime_error(
"fluids.volume/attachments");
78 attachments.reserve(
source->arraySize());
79 for (
size_t i = 0; i <
source->arraySize(); ++i) {
80 auto attachment =
source->at(i);
81 if (!attachment.isObject() || attachment.find(
"localOrientation"))
82 throw std::runtime_error(
"fluids.volume/attachments");
83 const auto*
index = attachment.find(
"particleIndex");
84 const auto*
label = attachment.find(
"colliderLabel");
86 size_t(
index->asInt()) >= particles->arraySize() || !
label || !
label->isInt64())
87 throw std::runtime_error(
"fluids.volume/attachments");
88 const auto* particleOrientation = particles->at(
size_t(
index->asInt())).find(
"orientation");
89 const Value* colliderRotation =
nullptr;
90 for (
size_t j = 0; j < colliders->arraySize(); ++j) {
91 const auto* candidate = colliders->
at(j).
find(
"label");
92 if (candidate && candidate->isInt64() && candidate->asInt() ==
label->asInt()) {
93 colliderRotation = colliders->
at(j).
find(
"rotation");
97 if (!particleOrientation || !colliderRotation)
throw std::runtime_error(
"fluids.volume/attachments");
98 glm::vec4 particleQ, colliderQ;
99 unpack(*particleOrientation, particleQ,
"fluids.volume/particles/orientation");
100 unpack(*colliderRotation, colliderQ,
"fluids.volume/colliders/rotation");
101 const auto world = glm::quat(particleQ.w, particleQ.x, particleQ.y, particleQ.z);
102 const auto frame = glm::quat(colliderQ.w, colliderQ.x, colliderQ.y, colliderQ.z);
103 const auto local = glm::normalize(glm::conjugate(frame) *
world);
105 attachments.push_back(std::move(attachment));
107 migrated.set(
"attachments",
Value(std::move(attachments)));
108 migrated.set(
"version", 6);
110 migratedVersion = migrated.find(
"version");
111 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 6) {
112 if (migrated.find(
"simplexes"))
throw std::runtime_error(
"fluids.volume/simplexes");
114 migrated.set(
"version", 7);
116 migratedVersion = migrated.find(
"version");
117 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 7) {
118 const auto*
source = migrated.find(
"colliders");
120 throw std::runtime_error(
"fluids.volume/colliders");
122 colliders.reserve(
source->arraySize());
123 for (
size_t i = 0; i <
source->arraySize(); ++i) {
124 auto collider =
source->at(i);
125 if (!collider.isObject() || collider.find(
"collisionFilter"))
126 throw std::runtime_error(
"fluids.volume/colliders");
127 collider.set(
"collisionFilter", int64_t(0xffff0001u));
128 colliders.push_back(std::move(collider));
130 migrated.set(
"colliders",
Value(std::move(colliders)));
131 migrated.set(
"version", 8);
133 migratedVersion = migrated.find(
"version");
134 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 8) {
135 const auto*
source = migrated.find(
"particles");
137 throw std::runtime_error(
"fluids.volume/particles");
139 particles.reserve(
source->arraySize());
140 for (
size_t i = 0; i <
source->arraySize(); ++i) {
141 auto particle =
source->at(i);
142 if (!particle.isObject() || particle.find(
"actorGroup") || particle.find(
"selfCollide"))
143 throw std::runtime_error(
"fluids.volume/particles");
144 particle.set(
"actorGroup", int64_t(0));
145 particle.set(
"selfCollide",
true);
146 particles.push_back(std::move(particle));
148 migrated.set(
"particles",
Value(std::move(particles)));
149 migrated.set(
"version", 9);
151 migratedVersion = migrated.find(
"version");
152 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 9) {
153 const auto*
source = migrated.find(
"particles");
155 throw std::runtime_error(
"fluids.volume/particles");
157 particles.reserve(
source->arraySize());
158 for (
size_t i = 0; i <
source->arraySize(); ++i) {
159 auto particle =
source->at(i);
160 auto*
material = particle.isObject() ? particle.find(
"material") :
nullptr;
162 throw std::runtime_error(
"fluids.volume/particles/material");
163 material->set(
"atmosphericPressure", 0.0);
164 particles.push_back(std::move(particle));
166 migrated.set(
"particles",
Value(std::move(particles)));
167 migrated.set(
"version", 10);
169 migratedVersion = migrated.find(
"version");
170 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 10) {
171 const auto*
source = migrated.find(
"particles");
173 throw std::runtime_error(
"fluids.volume/particles");
175 particles.reserve(
source->arraySize());
176 for (
size_t i = 0; i <
source->arraySize(); ++i) {
177 auto particle =
source->at(i);
178 auto*
material = particle.isObject() ? particle.find(
"material") :
nullptr;
180 throw std::runtime_error(
"fluids.volume/particles/material");
182 particles.push_back(std::move(particle));
184 migrated.set(
"particles",
Value(std::move(particles)));
185 migrated.set(
"version", 11);
187 migratedVersion = migrated.find(
"version");
188 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 11) {
189 const auto*
source = migrated.find(
"particles");
191 throw std::runtime_error(
"fluids.volume/particles");
193 particles.reserve(
source->arraySize());
194 for (
size_t i = 0; i <
source->arraySize(); ++i) {
195 auto particle =
source->at(i);
196 auto*
material = particle.isObject() ? particle.find(
"material") :
nullptr;
197 if (!
material || !
material->isObject() || particle.find(
"angularVelocity") ||
199 throw std::runtime_error(
"fluids.volume/particles/material");
200 particle.set(
"angularVelocity", pack(glm::vec3(0.f)));
201 material->set(
"rollingContacts",
false);
202 material->set(
"rollingFriction", 0.0);
203 particles.push_back(std::move(particle));
205 migrated.set(
"particles",
Value(std::move(particles)));
206 migrated.set(
"version", 12);
208 migratedVersion = migrated.find(
"version");
209 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 12) {
210 const auto*
source = migrated.find(
"particles");
212 throw std::runtime_error(
"fluids.volume/particles");
214 particles.reserve(
source->arraySize());
215 for (
size_t i = 0; i <
source->arraySize(); ++i) {
216 auto particle =
source->at(i);
217 auto*
material = particle.isObject() ? particle.find(
"material") :
nullptr;
220 throw std::runtime_error(
"fluids.volume/particles/material");
221 material->set(
"dynamicFriction", 0.2);
222 material->set(
"staticFriction", 0.2);
223 particles.push_back(std::move(particle));
225 migrated.set(
"particles",
Value(std::move(particles)));
226 migrated.set(
"version", 13);
228 migratedVersion = migrated.find(
"version");
229 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 13) {
230 if (migrated.find(
"sdfColliders"))
throw std::runtime_error(
"fluids.volume/sdfColliders");
232 migrated.set(
"version", 14);
234 migratedVersion = migrated.find(
"version");
235 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 14) {
236 if (migrated.find(
"heightFieldColliders"))
throw std::runtime_error(
"fluids.volume/heightFieldColliders");
238 migrated.set(
"version", 15);
240 migratedVersion = migrated.find(
"version");
241 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 15) {
242 for (
const char* field : {
"colliders",
"sdfColliders",
"heightFieldColliders"}) {
243 const auto*
source = migrated.find(field);
244 if (!
source || !
source->isArray())
throw std::runtime_error(std::string(
"fluids.volume/") + field);
246 colliders.reserve(
source->arraySize());
247 for (
size_t i = 0; i <
source->arraySize(); ++i) {
248 auto collider =
source->at(i);
249 if (!collider.isObject() || collider.find(
"isTrigger"))
250 throw std::runtime_error(std::string(
"fluids.volume/") + field +
"/isTrigger");
251 collider.set(
"isTrigger",
false);
252 colliders.push_back(std::move(collider));
254 migrated.set(field,
Value(std::move(colliders)));
256 migrated.set(
"version", 16);
258 migratedVersion = migrated.find(
"version");
259 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 16) {
260 const auto* sourceParticles = migrated.find(
"particles");
261 if (!sourceParticles || !sourceParticles->isArray())
throw std::runtime_error(
"fluids.volume/particles");
263 particles.reserve(sourceParticles->arraySize());
264 for (
size_t i = 0; i < sourceParticles->arraySize(); ++i) {
265 auto particle = sourceParticles->at(i);
266 auto*
material = particle.isObject() ? particle.find(
"material") :
nullptr;
269 material->find(
"stickinessCombine"))
270 throw std::runtime_error(
"fluids.volume/particles/material");
272 material->set(
"stickDistance", 0.0);
273 material->set(
"frictionCombine", 0);
274 material->set(
"stickinessCombine", 0);
275 particles.push_back(std::move(particle));
277 migrated.set(
"particles",
Value(std::move(particles)));
278 for (
const char* field : {
"colliders",
"sdfColliders",
"heightFieldColliders"}) {
279 const auto*
source = migrated.find(field);
280 if (!
source || !
source->isArray())
throw std::runtime_error(std::string(
"fluids.volume/") + field);
282 colliders.reserve(
source->arraySize());
283 for (
size_t i = 0; i <
source->arraySize(); ++i) {
284 auto collider =
source->at(i);
285 if (!collider.isObject() || collider.find(
"staticFriction") || collider.find(
"rollingFriction") ||
286 collider.find(
"stickiness") || collider.find(
"stickDistance") ||
287 collider.find(
"frictionCombine") || collider.find(
"stickinessCombine") ||
288 collider.find(
"rollingContacts"))
289 throw std::runtime_error(std::string(
"fluids.volume/") + field +
"/material");
290 collider.set(
"staticFriction", *collider.find(
"friction"));
291 collider.set(
"rollingFriction", 0.0);
292 collider.set(
"stickiness", 0.0);
293 collider.set(
"stickDistance", 0.0);
294 collider.set(
"frictionCombine", 0);
295 collider.set(
"stickinessCombine", 0);
296 collider.set(
"rollingContacts",
false);
297 colliders.push_back(std::move(collider));
299 migrated.set(field,
Value(std::move(colliders)));
301 migrated.set(
"version", 17);
303 migratedVersion = migrated.find(
"version");
304 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 17) {
305 const auto*
source = migrated.find(
"attachments");
306 if (!
source || !
source->isArray())
throw std::runtime_error(
"fluids.volume/attachments");
308 attachments.reserve(
source->arraySize());
309 for (
size_t i = 0; i <
source->arraySize(); ++i) {
310 auto attachment =
source->at(i);
311 if (!attachment.isObject() || attachment.find(
"constrainOrientation"))
312 throw std::runtime_error(
"fluids.volume/attachments/constrainOrientation");
314 attachment.set(
"constrainOrientation",
true);
315 attachments.push_back(std::move(attachment));
317 migrated.set(
"attachments",
Value(std::move(attachments)));
318 migrated.set(
"version", 18);
320 migratedVersion = migrated.find(
"version");
321 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 18) {
322 const auto*
source = migrated.find(
"attachments");
323 if (!
source || !
source->isArray())
throw std::runtime_error(
"fluids.volume/attachments");
325 attachments.reserve(
source->arraySize());
326 for (
size_t i = 0; i <
source->arraySize(); ++i) {
327 auto attachment =
source->at(i);
328 if (!attachment.isObject() || attachment.find(
"dynamic") || attachment.find(
"compliance") ||
329 attachment.find(
"breakThreshold"))
330 throw std::runtime_error(
"fluids.volume/attachments/dynamic");
331 attachment.set(
"dynamic",
false);
332 attachment.set(
"compliance", 0.0);
333 attachment.set(
"breakThreshold", 1e12);
334 attachments.push_back(std::move(attachment));
336 migrated.set(
"attachments",
Value(std::move(attachments)));
337 migrated.set(
"version", 19);
339 migratedVersion = migrated.find(
"version");
340 if (migratedVersion && migratedVersion->isInt64() && migratedVersion->asInt() == 19) {
341 if (migrated.find(
"stitches"))
throw std::runtime_error(
"fluids.volume/stitches");
343 migrated.set(
"version", 20);
345 unpack(migrated, decoded,
"fluids.volume");
346 }
catch (
const std::runtime_error&
error) {
352 auto valid = solver.value()->restore(decoded);