1
2
3 // DO NOT EDIT !
4 // This file is generated using the MantaFlow preprocessor (prep generate).
5
6 /******************************************************************************
7 *
8 * MantaFlow fluid solver framework
9 * Copyright 2020 Sebastian Barschkis, Nils Thuerey
10 *
11 * This program is free software, distributed under the terms of the
12 * Apache License, Version 2.0
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Loading and writing grids and particles from and to OpenVDB files.
16 *
17 ******************************************************************************/
18
19 #include <iostream>
20 #include <fstream>
21 #include <cstdlib>
22 #include <cstring>
23
24 #include "mantaio.h"
25 #include "grid.h"
26 #include "vector4d.h"
27 #include "grid4d.h"
28 #include "particle.h"
29
30 #if OPENVDB == 1
31 # include "openvdb/openvdb.h"
32 # include <openvdb/points/PointConversion.h>
33 # include <openvdb/points/PointCount.h>
34 #endif
35
36 #define POSITION_NAME "P"
37 #define FLAG_NAME "U"
38
39 using namespace std;
40
41 namespace Manta {
42
43 #if OPENVDB == 1
44
importVDB(typename GridType::Ptr from,Grid<T> * to)45 template<class GridType, class T> void importVDB(typename GridType::Ptr from, Grid<T> *to)
46 {
47 using ValueT = typename GridType::ValueType;
48 typename GridType::Accessor accessor = from->getAccessor();
49
50 FOR_IJK(*to)
51 {
52 openvdb::Coord xyz(i, j, k);
53 ValueT vdbValue = accessor.getValue(xyz);
54 T toMantaValue;
55 convertFrom(vdbValue, &toMantaValue);
56 to->set(i, j, k, toMantaValue);
57 }
58 }
59
60 template<class VDBType, class T>
importVDB(VDBType vdbValue,ParticleDataImpl<T> * to,int index,float voxelSize)61 void importVDB(VDBType vdbValue, ParticleDataImpl<T> *to, int index, float voxelSize)
62 {
63 unusedParameter(voxelSize); // Unused for now
64 T toMantaValue;
65 convertFrom(vdbValue, &toMantaValue);
66 to->set(index, toMantaValue);
67 }
68
importVDB(openvdb::points::PointDataGrid::Ptr from,BasicParticleSystem * to,std::vector<ParticleDataBase * > & toPData,float voxelSize)69 void importVDB(openvdb::points::PointDataGrid::Ptr from,
70 BasicParticleSystem *to,
71 std::vector<ParticleDataBase *> &toPData,
72 float voxelSize)
73 {
74 openvdb::Index64 count = openvdb::points::pointCount(from->tree());
75 to->resizeAll(count);
76
77 int cnt = 0;
78 for (auto leafIter = from->tree().cbeginLeaf(); leafIter; ++leafIter) {
79 const openvdb::points::AttributeArray &positionArray = leafIter->constAttributeArray(
80 POSITION_NAME);
81 const openvdb::points::AttributeArray &flagArray = leafIter->constAttributeArray(FLAG_NAME);
82
83 openvdb::points::AttributeHandle<openvdb::Vec3s> positionHandle(positionArray);
84 openvdb::points::AttributeHandle<int> flagHandle(flagArray);
85
86 // Get vdb handles to pdata objects in pdata list
87 std::vector<std::tuple<int, openvdb::points::AttributeHandle<int>>> pDataHandlesInt;
88 std::vector<std::tuple<int, openvdb::points::AttributeHandle<float>>> pDataHandlesReal;
89 std::vector<std::tuple<int, openvdb::points::AttributeHandle<openvdb::Vec3s>>>
90 pDataHandlesVec3;
91
92 int pDataIndex = 0;
93 for (ParticleDataBase *pdb : toPData) {
94 std::string name = pdb->getName();
95 const openvdb::points::AttributeArray &pDataArray = leafIter->constAttributeArray(name);
96
97 if (pdb->getType() == ParticleDataBase::TypeInt) {
98 openvdb::points::AttributeHandle<int> intHandle(pDataArray);
99 std::tuple<int, openvdb::points::AttributeHandle<int>> tuple = std::make_tuple(pDataIndex,
100 intHandle);
101 pDataHandlesInt.push_back(tuple);
102 }
103 else if (pdb->getType() == ParticleDataBase::TypeReal) {
104 openvdb::points::AttributeHandle<float> floatHandle(pDataArray);
105 std::tuple<int, openvdb::points::AttributeHandle<float>> tuple = std::make_tuple(
106 pDataIndex, floatHandle);
107 pDataHandlesReal.push_back(tuple);
108 }
109 else if (pdb->getType() == ParticleDataBase::TypeVec3) {
110 openvdb::points::AttributeHandle<openvdb::Vec3s> vec3Handle(pDataArray);
111 std::tuple<int, openvdb::points::AttributeHandle<openvdb::Vec3s>> tuple = std::make_tuple(
112 pDataIndex, vec3Handle);
113 pDataHandlesVec3.push_back(tuple);
114 }
115 else {
116 errMsg("importVDB: unknown ParticleDataBase type");
117 }
118 ++pDataIndex;
119 }
120
121 for (auto indexIter = leafIter->beginIndexOn(); indexIter; ++indexIter) {
122 // Extract the voxel-space position of the point (always between (-0.5, -0.5, -0.5) and (0.5,
123 // 0.5, 0.5)).
124 openvdb::Vec3s voxelPosition = positionHandle.get(*indexIter);
125 const openvdb::Vec3d xyz = indexIter.getCoord().asVec3d();
126 // Compute the world-space position of the point.
127 openvdb::Vec3f worldPosition = from->transform().indexToWorld(voxelPosition + xyz);
128 int flag = flagHandle.get(*indexIter);
129
130 Vec3 toMantaValue;
131 convertFrom(worldPosition, &toMantaValue);
132 (*to)[cnt].pos = toMantaValue;
133 (*to)[cnt].pos /= voxelSize; // convert from world space to grid space
134 (*to)[cnt].flag = flag;
135
136 for (std::tuple<int, openvdb::points::AttributeHandle<int>> tuple : pDataHandlesInt) {
137 int pDataIndex = std::get<0>(tuple);
138 int vdbValue = std::get<1>(tuple).get(*indexIter);
139
140 ParticleDataImpl<int> *pdi = dynamic_cast<ParticleDataImpl<int> *>(toPData[pDataIndex]);
141 importVDB<int, int>(vdbValue, pdi, cnt, voxelSize);
142 }
143 for (std::tuple<int, openvdb::points::AttributeHandle<float>> tuple : pDataHandlesReal) {
144 int pDataIndex = std::get<0>(tuple);
145 float vdbValue = std::get<1>(tuple).get(*indexIter);
146
147 ParticleDataImpl<Real> *pdi = dynamic_cast<ParticleDataImpl<Real> *>(toPData[pDataIndex]);
148 importVDB<float, Real>(vdbValue, pdi, cnt, voxelSize);
149 }
150 for (std::tuple<int, openvdb::points::AttributeHandle<openvdb::Vec3s>> tuple :
151 pDataHandlesVec3) {
152 int pDataIndex = std::get<0>(tuple);
153 openvdb::Vec3f voxelPosition = std::get<1>(tuple).get(*indexIter);
154
155 ParticleDataImpl<Vec3> *pdi = dynamic_cast<ParticleDataImpl<Vec3> *>(toPData[pDataIndex]);
156 importVDB<openvdb::Vec3s, Vec3>(voxelPosition, pdi, cnt, voxelSize);
157 }
158 ++cnt;
159 }
160 }
161 }
162
163 template<class GridType>
setGridOptions(typename GridType::Ptr grid,string name,openvdb::GridClass cls,float voxelSize,int precision)164 static void setGridOptions(typename GridType::Ptr grid,
165 string name,
166 openvdb::GridClass cls,
167 float voxelSize,
168 int precision)
169 {
170 grid->setTransform(openvdb::math::Transform::createLinearTransform(voxelSize));
171 grid->setGridClass(cls);
172 grid->setName(name);
173 grid->setSaveFloatAsHalf(precision == PRECISION_MINI || precision == PRECISION_HALF);
174 }
175
exportVDB(Grid<T> * from)176 template<class T, class GridType> typename GridType::Ptr exportVDB(Grid<T> *from)
177 {
178 using ValueT = typename GridType::ValueType;
179 typename GridType::Ptr to = GridType::create();
180 typename GridType::Accessor accessor = to->getAccessor();
181
182 FOR_IJK(*from)
183 {
184 openvdb::Coord xyz(i, j, k);
185 T fromMantaValue = (*from)(i, j, k);
186 ValueT vdbValue;
187 convertTo(&vdbValue, fromMantaValue);
188 accessor.setValue(xyz, vdbValue);
189 }
190 return to;
191 }
192
193 template<class MantaType, class VDBType>
exportVDB(ParticleDataImpl<MantaType> * from,openvdb::points::PointDataGrid::Ptr to,openvdb::tools::PointIndexGrid::Ptr pIndex,bool skipDeletedParts,int precision)194 void exportVDB(ParticleDataImpl<MantaType> *from,
195 openvdb::points::PointDataGrid::Ptr to,
196 openvdb::tools::PointIndexGrid::Ptr pIndex,
197 bool skipDeletedParts,
198 int precision)
199 {
200 std::vector<VDBType> vdbValues;
201 std::string name = from->getName();
202
203 FOR_PARTS(*from)
204 {
205 // Optionally, skip exporting particles that have been marked as deleted
206 BasicParticleSystem *pp = dynamic_cast<BasicParticleSystem *>(from->getParticleSys());
207 if (skipDeletedParts && !pp->isActive(idx)) {
208 continue;
209 }
210 MantaType fromMantaValue = (*from)[idx];
211 VDBType vdbValue;
212 convertTo(&vdbValue, fromMantaValue);
213 vdbValues.push_back(vdbValue);
214 }
215
216 // Use custom codec for precision of the attribute
217 openvdb::NamePair attribute;
218 if (precision == PRECISION_FULL) {
219 attribute =
220 openvdb::points::TypedAttributeArray<VDBType, openvdb::points::NullCodec>::attributeType();
221 }
222 else if (precision == PRECISION_HALF ||
223 precision == PRECISION_MINI) { // Mini uses same precision as half for now
224 attribute =
225 openvdb::points::TypedAttributeArray<VDBType,
226 openvdb::points::TruncateCodec>::attributeType();
227 }
228 else {
229 errMsg("exportVDB: invalid precision level");
230 }
231 openvdb::points::appendAttribute(to->tree(), name, attribute);
232
233 // Create a wrapper around the vdb values vector.
234 const openvdb::points::PointAttributeVector<VDBType> wrapper(vdbValues);
235
236 // Populate the attribute on the points
237 openvdb::points::populateAttribute<openvdb::points::PointDataTree,
238 openvdb::tools::PointIndexTree,
239 openvdb::points::PointAttributeVector<VDBType>>(
240 to->tree(), pIndex->tree(), name, wrapper);
241 }
242
exportVDB(BasicParticleSystem * from,std::vector<ParticleDataBase * > & fromPData,bool skipDeletedParts,float voxelSize,int precision)243 openvdb::points::PointDataGrid::Ptr exportVDB(BasicParticleSystem *from,
244 std::vector<ParticleDataBase *> &fromPData,
245 bool skipDeletedParts,
246 float voxelSize,
247 int precision)
248 {
249 std::vector<openvdb::Vec3s> positions;
250 std::vector<int> flags;
251
252 FOR_PARTS(*from)
253 {
254 // Optionally, skip exporting particles that have been marked as deleted
255 if (skipDeletedParts && !from->isActive(idx)) {
256 continue;
257 }
258 Vector3D<float> pos = toVec3f((*from)[idx].pos);
259 pos *= voxelSize; // convert from grid space to world space
260 openvdb::Vec3s posVDB(pos.x, pos.y, pos.z);
261 positions.push_back(posVDB);
262
263 int flag = (*from)[idx].flag;
264 flags.push_back(flag);
265 }
266
267 const openvdb::points::PointAttributeVector<openvdb::Vec3s> positionsWrapper(positions);
268 openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(
269 voxelSize);
270
271 openvdb::tools::PointIndexGrid::Ptr pointIndexGrid =
272 openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(positionsWrapper,
273 *transform);
274
275 openvdb::points::PointDataGrid::Ptr to;
276 openvdb::NamePair flagAttribute;
277
278 using CodecNull = openvdb::points::NullCodec;
279 using CodecTrunc = openvdb::points::TruncateCodec;
280 using CodecFixPoint = openvdb::points::FixedPointCodec<true, openvdb::points::PositionRange>;
281
282 // Use custom codec for precision of the particle position and the flag attribute
283 if (precision == PRECISION_FULL) {
284 to = openvdb::points::createPointDataGrid<CodecNull, openvdb::points::PointDataGrid>(
285 *pointIndexGrid, positionsWrapper, *transform);
286 flagAttribute = openvdb::points::TypedAttributeArray<int, CodecNull>::attributeType();
287 }
288 else if (precision == PRECISION_HALF) {
289 to = openvdb::points::createPointDataGrid<CodecTrunc, openvdb::points::PointDataGrid>(
290 *pointIndexGrid, positionsWrapper, *transform);
291 flagAttribute = openvdb::points::TypedAttributeArray<int, CodecTrunc>::attributeType();
292 }
293 else if (precision == PRECISION_MINI) {
294 to = openvdb::points::createPointDataGrid<CodecFixPoint, openvdb::points::PointDataGrid>(
295 *pointIndexGrid, positionsWrapper, *transform);
296 flagAttribute = openvdb::points::TypedAttributeArray<int, CodecTrunc>::
297 attributeType(); // Use 16 bit trunc for flag for now
298 }
299 else {
300 errMsg("exportVDB: invalid precision level");
301 }
302
303 openvdb::points::appendAttribute(to->tree(), FLAG_NAME, flagAttribute);
304 // Create a wrapper around the flag vector.
305 openvdb::points::PointAttributeVector<int> flagWrapper(flags);
306 // Populate the "flag" attribute on the points
307 openvdb::points::populateAttribute<openvdb::points::PointDataTree,
308 openvdb::tools::PointIndexTree,
309 openvdb::points::PointAttributeVector<int>>(
310 to->tree(), pointIndexGrid->tree(), FLAG_NAME, flagWrapper);
311
312 // Add all already buffered pdata to this particle grid
313 for (ParticleDataBase *pdb : fromPData) {
314 if (pdb->getType() == ParticleDataBase::TypeInt) {
315 debMsg("Writing int particle data '" << pdb->getName() << "'", 1);
316 ParticleDataImpl<int> *pdi = dynamic_cast<ParticleDataImpl<int> *>(pdb);
317 exportVDB<int, int>(pdi, to, pointIndexGrid, skipDeletedParts, precision);
318 }
319 else if (pdb->getType() == ParticleDataBase::TypeReal) {
320 debMsg("Writing real particle data '" << pdb->getName() << "'", 1);
321 ParticleDataImpl<Real> *pdi = dynamic_cast<ParticleDataImpl<Real> *>(pdb);
322 exportVDB<Real, float>(pdi, to, pointIndexGrid, skipDeletedParts, precision);
323 }
324 else if (pdb->getType() == ParticleDataBase::TypeVec3) {
325 debMsg("Writing Vec3 particle data '" << pdb->getName() << "'", 1);
326 ParticleDataImpl<Vec3> *pdi = dynamic_cast<ParticleDataImpl<Vec3> *>(pdb);
327 exportVDB<Vec3, openvdb::Vec3s>(pdi, to, pointIndexGrid, skipDeletedParts, precision);
328 }
329 else {
330 errMsg("exportVDB: unknown ParticleDataBase type");
331 }
332 }
333 return to;
334 }
335
registerCustomCodecs()336 static void registerCustomCodecs()
337 {
338 openvdb::points::TypedAttributeArray<int, openvdb::points::TruncateCodec>::registerType();
339 openvdb::points::TypedAttributeArray<float, openvdb::points::TruncateCodec>::registerType();
340 openvdb::points::TypedAttributeArray<openvdb::Vec3s,
341 openvdb::points::TruncateCodec>::registerType();
342 }
343
writeObjectsVDB(const string & filename,std::vector<PbClass * > * objects,float worldSize,bool skipDeletedParts,int compression,int precision)344 int writeObjectsVDB(const string &filename,
345 std::vector<PbClass *> *objects,
346 float worldSize,
347 bool skipDeletedParts,
348 int compression,
349 int precision)
350 {
351 openvdb::initialize();
352 openvdb::io::File file(filename);
353 openvdb::GridPtrVec gridsVDB;
354
355 // Register custom codecs, this makes sure custom attributes can be read
356 registerCustomCodecs();
357
358 std::vector<ParticleDataBase *> pdbBuffer;
359
360 for (std::vector<PbClass *>::iterator iter = objects->begin(); iter != objects->end(); ++iter) {
361 openvdb::GridClass gClass = openvdb::GRID_UNKNOWN;
362 openvdb::GridBase::Ptr vdbGrid;
363
364 PbClass *object = dynamic_cast<PbClass *>(*iter);
365 const Real dx = object->getParent()->getDx();
366 const Real voxelSize = worldSize * dx;
367 const string objectName = object->getName();
368
369 if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
370
371 if (mantaGrid->getType() & GridBase::TypeInt) {
372 debMsg("Writing int grid '" << mantaGrid->getName() << "' to vdb file " << filename, 1);
373 Grid<int> *mantaIntGrid = (Grid<int> *)mantaGrid;
374 vdbGrid = exportVDB<int, openvdb::Int32Grid>(mantaIntGrid);
375 gridsVDB.push_back(vdbGrid);
376 }
377 else if (mantaGrid->getType() & GridBase::TypeReal) {
378 debMsg("Writing real grid '" << mantaGrid->getName() << "' to vdb file " << filename, 1);
379 gClass = (mantaGrid->getType() & GridBase::TypeLevelset) ? openvdb::GRID_LEVEL_SET :
380 openvdb::GRID_FOG_VOLUME;
381 Grid<Real> *mantaRealGrid = (Grid<Real> *)mantaGrid;
382 vdbGrid = exportVDB<Real, openvdb::FloatGrid>(mantaRealGrid);
383 gridsVDB.push_back(vdbGrid);
384 }
385 else if (mantaGrid->getType() & GridBase::TypeVec3) {
386 debMsg("Writing vec3 grid '" << mantaGrid->getName() << "' to vdb file " << filename, 1);
387 gClass = (mantaGrid->getType() & GridBase::TypeMAC) ? openvdb::GRID_STAGGERED :
388 openvdb::GRID_UNKNOWN;
389 Grid<Vec3> *mantaVec3Grid = (Grid<Vec3> *)mantaGrid;
390 vdbGrid = exportVDB<Vec3, openvdb::Vec3SGrid>(mantaVec3Grid);
391 gridsVDB.push_back(vdbGrid);
392 }
393 else {
394 errMsg("writeObjectsVDB: unknown grid type");
395 return 0;
396 }
397 }
398 else if (BasicParticleSystem *mantaPP = dynamic_cast<BasicParticleSystem *>(*iter)) {
399 debMsg("Writing particle system '" << mantaPP->getName()
400 << "' (and buffered pData) to vdb file " << filename,
401 1);
402 vdbGrid = exportVDB(mantaPP, pdbBuffer, skipDeletedParts, voxelSize, precision);
403 gridsVDB.push_back(vdbGrid);
404 pdbBuffer.clear();
405 }
406 // Particle data will only be saved if there is a particle system too.
407 else if (ParticleDataBase *mantaPPImpl = dynamic_cast<ParticleDataBase *>(*iter)) {
408 debMsg("Buffering particle data '" << mantaPPImpl->getName() << "' to vdb file " << filename,
409 1);
410 pdbBuffer.push_back(mantaPPImpl);
411 }
412 else {
413 errMsg("writeObjectsVDB: Unsupported Python object. Cannot write to .vdb file " << filename);
414 return 0;
415 }
416
417 // Set additional grid attributes, e.g. name, grid class, compression level, etc.
418 if (vdbGrid) {
419 setGridOptions<openvdb::GridBase>(vdbGrid, objectName, gClass, voxelSize, precision);
420 }
421 }
422
423 // Give out a warning if pData items were present but could not be saved due to missing particle
424 // system.
425 if (!pdbBuffer.empty()) {
426 for (ParticleDataBase *pdb : pdbBuffer) {
427 debMsg("writeObjectsVDB Warning: Particle data '"
428 << pdb->getName()
429 << "' has not been saved. It's parent particle system was needs to be given too.",
430 1);
431 }
432 }
433
434 // Write only if the is at least one grid, optionally write with compression.
435 if (gridsVDB.size()) {
436 int vdb_flags = openvdb::io::COMPRESS_ACTIVE_MASK;
437 switch (compression) {
438 case COMPRESSION_NONE: {
439 vdb_flags = openvdb::io::COMPRESS_NONE;
440 break;
441 }
442 default:
443 case COMPRESSION_ZIP: {
444 vdb_flags |= openvdb::io::COMPRESS_ZIP;
445 break;
446 }
447 case COMPRESSION_BLOSC: {
448 # if OPENVDB_BLOSC == 1
449 vdb_flags |= openvdb::io::COMPRESS_BLOSC;
450 # else
451 debMsg("OpenVDB was built without Blosc support, using Zip compression instead", 1);
452 vdb_flags |= openvdb::io::COMPRESS_ZIP;
453 # endif // OPENVDB_BLOSC==1
454 break;
455 }
456 }
457 file.setCompression(vdb_flags);
458 file.write(gridsVDB);
459 }
460 file.close();
461 return 1;
462 }
463
readObjectsVDB(const string & filename,std::vector<PbClass * > * objects,float worldSize)464 int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, float worldSize)
465 {
466
467 openvdb::initialize();
468 openvdb::io::File file(filename);
469 openvdb::GridPtrVec gridsVDB;
470
471 // Register custom codecs, this makes sure custom attributes can be read
472 registerCustomCodecs();
473
474 try {
475 file.setCopyMaxBytes(0);
476 file.open();
477 gridsVDB = *(file.getGrids());
478 openvdb::MetaMap::Ptr metadata = file.getMetadata();
479 unusedParameter(metadata); // Unused for now
480 }
481 catch (const openvdb::IoError &e) {
482 unusedParameter(e); // Unused for now
483 debMsg("readObjectsVDB: Could not open vdb file " << filename, 1);
484 file.close();
485 return 0;
486 }
487 file.close();
488
489 // A buffer to store a handle to pData objects. These will be read alongside a particle system.
490 std::vector<ParticleDataBase *> pdbBuffer;
491
492 for (std::vector<PbClass *>::iterator iter = objects->begin(); iter != objects->end(); ++iter) {
493
494 if (gridsVDB.empty()) {
495 debMsg("readObjectsVDB: No vdb grids in file " << filename, 1);
496 }
497 // If there is just one grid in this file, load it regardless of name match (to vdb caches per
498 // grid).
499 bool onlyGrid = (gridsVDB.size() == 1);
500
501 PbClass *object = dynamic_cast<PbClass *>(*iter);
502 const Real dx = object->getParent()->getDx();
503 const Real voxelSize = worldSize * dx;
504
505 // Particle data objects are treated separately - buffered and inserted when reading the
506 // particle system
507 if (ParticleDataBase *mantaPPImpl = dynamic_cast<ParticleDataBase *>(*iter)) {
508 debMsg("Buffering particle data '" << mantaPPImpl->getName() << "' from vdb file "
509 << filename,
510 1);
511 pdbBuffer.push_back(mantaPPImpl);
512 continue;
513 }
514
515 // For every manta object, we loop through the vdb grid list and check for a match
516 for (const openvdb::GridBase::Ptr &vdbGrid : gridsVDB) {
517 bool nameMatch = (vdbGrid->getName() == (*iter)->getName());
518
519 // Sanity checks: Only load valid grids and make sure names match.
520 if (!vdbGrid) {
521 debMsg("Skipping invalid vdb grid '" << vdbGrid->getName() << "' in file " << filename, 1);
522 continue;
523 }
524 if (!nameMatch && !onlyGrid) {
525 continue;
526 }
527 if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
528
529 if (mantaGrid->getType() & GridBase::TypeInt) {
530 openvdb::Int32Grid::Ptr vdbIntGrid = openvdb::gridPtrCast<openvdb::Int32Grid>(vdbGrid);
531 if (!vdbIntGrid)
532 continue; // Sanity check: Cast can fail if onlyGrid is true but object count > 1
533
534 Grid<int> *mantaIntGrid = (Grid<int> *)mantaGrid;
535 debMsg("Reading into grid '" << mantaGrid->getName() << "' from int grid '"
536 << vdbGrid->getName() << "' in vdb file " << filename,
537 1);
538 importVDB<openvdb::Int32Grid, int>(vdbIntGrid, mantaIntGrid);
539 }
540 else if (mantaGrid->getType() & GridBase::TypeReal) {
541 openvdb::FloatGrid::Ptr vdbFloatGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(vdbGrid);
542 if (!vdbFloatGrid)
543 continue; // Sanity check: Cast can fail if onlyGrid is true but object count > 1
544
545 Grid<Real> *mantaRealGrid = (Grid<Real> *)mantaGrid;
546 debMsg("Reading into grid '" << mantaGrid->getName() << "' from real grid '"
547 << vdbGrid->getName() << "' in vdb file " << filename,
548 1);
549 importVDB<openvdb::FloatGrid, Real>(vdbFloatGrid, mantaRealGrid);
550 }
551 else if (mantaGrid->getType() & GridBase::TypeVec3) {
552 openvdb::Vec3SGrid::Ptr vdbVec3Grid = openvdb::gridPtrCast<openvdb::Vec3SGrid>(vdbGrid);
553 if (!vdbVec3Grid)
554 continue; // Sanity check: Cast can fail if onlyGrid is true but object count > 1
555
556 Grid<Vec3> *mantaVec3Grid = (Grid<Vec3> *)mantaGrid;
557 debMsg("Reading into grid '" << mantaGrid->getName() << "' from vec3 grid '"
558 << vdbGrid->getName() << "' in vdb file " << filename,
559 1);
560 importVDB<openvdb::Vec3SGrid, Vec3>(vdbVec3Grid, mantaVec3Grid);
561 }
562 else {
563 errMsg("readObjectsVDB: unknown grid type");
564 return 0;
565 }
566 }
567 else if (BasicParticleSystem *mantaPP = dynamic_cast<BasicParticleSystem *>(*iter)) {
568 openvdb::points::PointDataGrid::Ptr vdbPointGrid =
569 openvdb::gridPtrCast<openvdb::points::PointDataGrid>(vdbGrid);
570 if (!vdbPointGrid)
571 continue; // Sanity check: Cast can fail if onlyGrid is true but objects > 1
572
573 debMsg("Reading into particle system '" << mantaPP->getName() << "' from particle system '"
574 << vdbGrid->getName() << "' in vdb file "
575 << filename,
576 1);
577 importVDB(vdbPointGrid, mantaPP, pdbBuffer, voxelSize);
578 pdbBuffer.clear();
579 }
580 else {
581 errMsg("readObjectsVDB: Unsupported Python object. Cannot read from .vdb file "
582 << filename);
583 return 0;
584 }
585 }
586 }
587
588 // Give out a warning if pData items were present but could not be read due to missing particle
589 // system.
590 if (!pdbBuffer.empty()) {
591 for (ParticleDataBase *pdb : pdbBuffer) {
592 debMsg("readObjectsVDB Warning: Particle data '"
593 << pdb->getName()
594 << "' has not been read. The parent particle system needs to be given too.",
595 1);
596 }
597 }
598
599 return 1;
600 }
601
602 template void importVDB<int, int>(int vdbValue,
603 ParticleDataImpl<int> *to,
604 int index,
605 float voxelSize = 1.0);
606 template void importVDB<float, Real>(float vdbValue,
607 ParticleDataImpl<Real> *to,
608 int index,
609 float voxelSize = 1.0);
610 template void importVDB<openvdb::Vec3f, Vec3>(openvdb::Vec3s vdbValue,
611 ParticleDataImpl<Vec3> *to,
612 int index,
613 float voxelSize = 1.0);
614
615 void importVDB(openvdb::points::PointDataGrid::Ptr from,
616 BasicParticleSystem *to,
617 std::vector<ParticleDataBase *> &toPData,
618 float voxelSize = 1.0);
619 template void importVDB<openvdb::Int32Grid, int>(openvdb::Int32Grid::Ptr from, Grid<int> *to);
620 template void importVDB<openvdb::FloatGrid, Real>(openvdb::FloatGrid::Ptr from, Grid<Real> *to);
621 template void importVDB<openvdb::Vec3SGrid, Vec3>(openvdb::Vec3SGrid::Ptr from, Grid<Vec3> *to);
622
623 template openvdb::Int32Grid::Ptr exportVDB<int, openvdb::Int32Grid>(Grid<int> *from);
624 template openvdb::FloatGrid::Ptr exportVDB<Real, openvdb::FloatGrid>(Grid<Real> *from);
625 template openvdb::Vec3SGrid::Ptr exportVDB<Vec3, openvdb::Vec3SGrid>(Grid<Vec3> *from);
626
627 openvdb::points::PointDataGrid::Ptr exportVDB(BasicParticleSystem *from,
628 std::vector<ParticleDataBase *> &fromPData,
629 bool skipDeletedParts = false,
630 float voxelSize = 1.0,
631 int precision = PRECISION_HALF);
632 template void exportVDB<int, int>(ParticleDataImpl<int> *from,
633 openvdb::points::PointDataGrid::Ptr to,
634 openvdb::tools::PointIndexGrid::Ptr pIndex,
635 bool skipDeletedParts = false,
636 int precision = PRECISION_HALF);
637 template void exportVDB<Real, float>(ParticleDataImpl<Real> *from,
638 openvdb::points::PointDataGrid::Ptr to,
639 openvdb::tools::PointIndexGrid::Ptr pIndex,
640 bool skipDeletedParts = false,
641 int precision = PRECISION_HALF);
642 template void exportVDB<Vec3, openvdb::Vec3s>(ParticleDataImpl<Vec3> *from,
643 openvdb::points::PointDataGrid::Ptr to,
644 openvdb::tools::PointIndexGrid::Ptr pIndex,
645 bool skipDeletedParts = false,
646 int precision = PRECISION_HALF);
647
648 #else
649
650 int writeObjectsVDB(const string &filename,
651 std::vector<PbClass *> *objects,
652 float worldSize,
653 bool skipDeletedParts,
654 int compression,
655 int precision)
656 {
657 errMsg("Cannot save to .vdb file. Mantaflow has not been built with OpenVDB support.");
658 return 0;
659 }
660
661 int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, float worldSize)
662 {
663 errMsg("Cannot load from .vdb file. Mantaflow has not been built with OpenVDB support.");
664 return 0;
665 }
666
667 #endif // OPENVDB==1
668
669 } // namespace Manta
670