Fluid: Updated Mantaflow source with latest OpenVDB changes

This updated set of Mantaflow files includes the improved  OpenVDB file IO. With this update it is finally possible to store multiple grids per file. It is also possible to save particle systems and particle data to OpenVDB files.
This commit is contained in:
Sebastián Barschkis 2020-06-24 12:00:13 +02:00
parent 6fec2e4db0
commit 9fe64948ab
Notes: blender-bot 2023-02-14 12:01:57 +01:00
Referenced by issue #77432, Mantaflow Liquid not work when "Data File Format" is changed to "OpenVDB"
19 changed files with 1380 additions and 506 deletions

View File

@ -54,6 +54,10 @@ if(WITH_OPENVDB)
add_definitions(-DOPENVDB_STATICLIB)
endif()
if(WITH_OPENVDB_BLOSC)
add_definitions(-DOPENVDB_BLOSC=1)
endif()
if(WIN32)
add_definitions(-D_USE_MATH_DEFINES)
endif()
@ -106,10 +110,12 @@ set(SRC
${MANTA_PP}/fastmarch.cpp
${MANTA_PP}/fastmarch.h
${MANTA_PP}/fastmarch.h.reg.cpp
${MANTA_PP}/fileio/ioutil.cpp
${MANTA_PP}/fileio/iogrids.cpp
${MANTA_PP}/fileio/iomeshes.cpp
${MANTA_PP}/fileio/ioparticles.cpp
${MANTA_PP}/fileio/ioutil.cpp
${MANTA_PP}/fileio/iovdb.cpp
${MANTA_PP}/fileio/mantaio.cpp
${MANTA_PP}/fileio/mantaio.h
${MANTA_PP}/fileio/mantaio.h.reg.cpp
${MANTA_PP}/fluidsolver.cpp

View File

@ -96,6 +96,37 @@ template<> PyObject *toPy<PbClass *>(const PbClass_Ptr &obj)
{
return obj->getPyObject();
}
template<> PyObject *toPy<std::vector<PbClass *>>(const std::vector<PbClass *> &vec)
{
PyObject *listObj = PyList_New(vec.size());
if (!listObj)
throw logic_error("Unable to allocate memory for Python list");
for (unsigned int i = 0; i < vec.size(); i++) {
PbClass *pb = vec[i];
PyObject *item = pb->getPyObject();
if (!item) {
Py_DECREF(listObj);
throw logic_error("Unable to allocate memory for Python list");
}
PyList_SET_ITEM(listObj, i, item);
}
return listObj;
}
template<> PyObject *toPy<std::vector<float>>(const std::vector<float> &vec)
{
PyObject *listObj = PyList_New(vec.size());
if (!listObj)
throw logic_error("Unable to allocate memory for Python list");
for (unsigned int i = 0; i < vec.size(); i++) {
PyObject *item = toPy<float>(vec[i]);
if (!item) {
Py_DECREF(listObj);
throw logic_error("Unable to allocate memory for Python list");
}
PyList_SET_ITEM(listObj, i, item);
}
return listObj;
}
template<> float fromPy<float>(PyObject *obj)
{
@ -125,6 +156,42 @@ template<> PyObject *fromPy<PyObject *>(PyObject *obj)
{
return obj;
}
template<> PbClass *fromPy<PbClass *>(PyObject *obj)
{
PbClass *pbo = Pb::objFromPy(obj);
if (!PyType_Check(obj))
return pbo;
const char *tname = ((PyTypeObject *)obj)->tp_name;
pbo->setName(tname);
return pbo;
}
template<> std::vector<PbClass *> fromPy<std::vector<PbClass *>>(PyObject *obj)
{
std::vector<PbClass *> vec;
if (PyList_Check(obj)) {
int sz = PyList_Size(obj);
for (int i = 0; i < sz; ++i) {
PyObject *lobj = PyList_GetItem(obj, i);
vec.push_back(fromPy<PbClass *>(lobj));
}
}
return vec;
}
template<> std::vector<float> fromPy<std::vector<float>>(PyObject *obj)
{
std::vector<float> vec;
if (PyList_Check(obj)) {
int sz = PyList_Size(obj);
for (int i = 0; i < sz; ++i) {
PyObject *lobj = PyList_GetItem(obj, i);
vec.push_back(fromPy<float>(lobj));
}
}
return vec;
}
template<> int fromPy<int>(PyObject *obj)
{
#if PY_MAJOR_VERSION <= 2
@ -259,11 +326,10 @@ template<class T> T *tmpAlloc(PyObject *obj, std::vector<void *> *tmp)
{
if (!tmp)
throw Error("dynamic de-ref not supported for this type");
void *ptr = malloc(sizeof(T));
tmp->push_back(ptr);
*((T *)ptr) = fromPy<T>(obj);
return (T *)ptr;
T *ptr = new T(fromPy<T>(obj));
tmp->push_back(ptr);
return ptr;
}
template<> float *fromPyPtr<float>(PyObject *obj, std::vector<void *> *tmp)
{
@ -301,6 +367,11 @@ template<> Vec4i *fromPyPtr<Vec4i>(PyObject *obj, std::vector<void *> *tmp)
{
return tmpAlloc<Vec4i>(obj, tmp);
}
template<>
std::vector<PbClass *> *fromPyPtr<std::vector<PbClass *>>(PyObject *obj, std::vector<void *> *tmp)
{
return tmpAlloc<std::vector<PbClass *>>(obj, tmp);
}
template<> bool isPy<float>(PyObject *obj)
{
@ -404,6 +475,18 @@ template<> bool isPy<PbType>(PyObject *obj)
{
return PyType_Check(obj);
}
template<> bool isPy<std::vector<PbClass *>>(PyObject *obj)
{
if (PyList_Check(obj))
return true;
return false;
}
template<> bool isPy<std::vector<float>>(PyObject *obj)
{
if (PyList_Check(obj))
return true;
return false;
}
//******************************************************************************
// PbArgs class defs
@ -417,7 +500,7 @@ PbArgs::PbArgs(PyObject *linarg, PyObject *dict) : mLinArgs(0), mKwds(0)
PbArgs::~PbArgs()
{
for (int i = 0; i < (int)mTmpStorage.size(); i++)
free(mTmpStorage[i]);
operator delete(mTmpStorage[i]);
mTmpStorage.clear();
}

View File

@ -57,6 +57,10 @@ template<> Vec3 *fromPyPtr<Vec3>(PyObject *obj, std::vector<void *> *tmp);
template<> Vec3i *fromPyPtr<Vec3i>(PyObject *obj, std::vector<void *> *tmp);
template<> Vec4 *fromPyPtr<Vec4>(PyObject *obj, std::vector<void *> *tmp);
template<> Vec4i *fromPyPtr<Vec4i>(PyObject *obj, std::vector<void *> *tmp);
template<>
std::vector<PbClass *> *fromPyPtr<std::vector<PbClass *>>(PyObject *obj, std::vector<void *> *tmp);
template<>
std::vector<float> *fromPyPtr<std::vector<float>>(PyObject *obj, std::vector<void *> *tmp);
PyObject *incref(PyObject *obj);
template<class T> PyObject *toPy(const T &v)
@ -99,6 +103,9 @@ template<> Vec4 fromPy<Vec4>(PyObject *obj);
template<> Vec4i fromPy<Vec4i>(PyObject *obj);
template<> PbType fromPy<PbType>(PyObject *obj);
template<> PbTypeVec fromPy<PbTypeVec>(PyObject *obj);
template<> PbClass *fromPy<PbClass *>(PyObject *obj);
template<> std::vector<PbClass *> fromPy<std::vector<PbClass *>>(PyObject *obj);
template<> std::vector<float> fromPy<std::vector<float>>(PyObject *obj);
template<> PyObject *toPy<int>(const int &v);
template<> PyObject *toPy<std::string>(const std::string &val);
@ -111,6 +118,8 @@ template<> PyObject *toPy<Vec4i>(const Vec4i &v);
template<> PyObject *toPy<Vec4>(const Vec4 &v);
typedef PbClass *PbClass_Ptr;
template<> PyObject *toPy<PbClass *>(const PbClass_Ptr &obj);
template<> PyObject *toPy<std::vector<PbClass *>>(const std::vector<PbClass *> &vec);
template<> PyObject *toPy<std::vector<float>>(const std::vector<float> &vec);
template<> bool isPy<float>(PyObject *obj);
template<> bool isPy<double>(PyObject *obj);
@ -124,6 +133,8 @@ template<> bool isPy<Vec3i>(PyObject *obj);
template<> bool isPy<Vec4>(PyObject *obj);
template<> bool isPy<Vec4i>(PyObject *obj);
template<> bool isPy<PbType>(PyObject *obj);
template<> bool isPy<std::vector<PbClass *>>(PyObject *obj);
template<> bool isPy<std::vector<float>>(PyObject *obj);
//! Encapsulation of python arguments
class PbArgs {

View File

@ -27,10 +27,6 @@ extern "C" {
}
#endif
#if OPENVDB == 1
# include "openvdb/openvdb.h"
#endif
#include "cnpy.h"
#include "mantaio.h"
#include "grid.h"
@ -279,54 +275,87 @@ static int unifyGridType(int type)
// grid data
//*****************************************************************************
template<class T> void writeGridTxt(const string &name, Grid<T> *grid)
template<class T> int writeGridTxt(const string &name, Grid<T> *grid)
{
debMsg("writing grid " << grid->getName() << " to text file " << name, 1);
ofstream ofs(name.c_str());
if (!ofs.good())
errMsg("writeGridTxt: can't open file " << name);
return 0;
FOR_IJK(*grid)
{
ofs << Vec3i(i, j, k) << " = " << (*grid)(i, j, k) << "\n";
}
ofs.close();
return 1;
}
template<class T> void writeGridRaw(const string &name, Grid<T> *grid)
int writeGridsTxt(const string &name, std::vector<PbClass *> *grids)
{
errMsg("writeGridsTxt: writing multiple grids to one .txt file not supported yet");
return 0;
}
int readGridsTxt(const string &name, std::vector<PbClass *> *grids)
{
errMsg("readGridsTxt: writing multiple grids from one .txt file not supported yet");
return 0;
}
template<class T> int writeGridRaw(const string &name, Grid<T> *grid)
{
debMsg("writing grid " << grid->getName() << " to raw file " << name, 1);
#if NO_ZLIB != 1
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("writeGridRaw: can't open file " << name);
return 0;
}
gzwrite(gzf, &((*grid)[0]), sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ());
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
template<class T> void readGridRaw(const string &name, Grid<T> *grid)
template<class T> int readGridRaw(const string &name, Grid<T> *grid)
{
debMsg("reading grid " << grid->getName() << " from raw file " << name, 1);
#if NO_ZLIB != 1
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "rb");
if (!gzf)
if (!gzf) {
errMsg("readGridRaw: can't open file " << name);
return 0;
}
IndexInt bytes = sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ();
IndexInt readBytes = gzread(gzf, &((*grid)[0]), bytes);
assertMsg(bytes == readBytes,
"can't read raw file, stream length does not match, " << bytes << " vs " << readBytes);
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
int writeGridsRaw(const string &name, std::vector<PbClass *> *grids)
{
errMsg("writeGridsRaw: writing multiple grids to one .raw file not supported yet");
return 0;
}
int readGridsRaw(const string &name, std::vector<PbClass *> *grids)
{
errMsg("readGridsRaw: reading multiple grids from one .raw file not supported yet");
return 0;
}
//! legacy headers for reading old files
typedef struct {
int dimX, dimY, dimZ;
@ -473,7 +502,7 @@ void PbRegister_printUniFileInfoString()
// actual read/write functions
template<class T> void writeGridUni(const string &name, Grid<T> *grid)
template<class T> int writeGridUni(const string &name, Grid<T> *grid)
{
debMsg("Writing grid " << grid->getName() << " to uni file " << name, 1);
@ -496,12 +525,16 @@ template<class T> void writeGridUni(const string &name, Grid<T> *grid)
head.elementType = 1;
else if (grid->getType() & GridBase::TypeVec3)
head.elementType = 2;
else
else {
errMsg("writeGridUni: unknown element type");
return 0;
}
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("writeGridUni: can't open file " << name);
return 0;
}
gzwrite(gzf, ID, 4);
# if FLOATINGPOINT_PRECISION != 1
@ -515,21 +548,24 @@ template<class T> void writeGridUni(const string &name, Grid<T> *grid)
gzwrite(gzf, &head, sizeof(UniHeader));
gzwrite(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ);
# endif
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
template<class T> void readGridUni(const string &name, Grid<T> *grid)
template<class T> int readGridUni(const string &name, Grid<T> *grid)
{
debMsg("Reading grid " << grid->getName() << " from uni file " << name, 1);
#if NO_ZLIB != 1
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "rb");
if (!gzf)
if (!gzf) {
errMsg("readGridUni: can't open file " << name);
return 0;
}
char ID[5] = {0, 0, 0, 0, 0};
gzread(gzf, ID, 4);
@ -609,17 +645,44 @@ template<class T> void readGridUni(const string &name, Grid<T> *grid)
}
else {
errMsg("readGridUni: Unknown header '" << ID << "' ");
return 0;
}
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
template<class T> void writeGridVol(const string &name, Grid<T> *grid)
int writeGridsUni(const string &name, std::vector<PbClass *> *grids)
{
errMsg("writeGridsUni: writing multiple grids to one .uni file not supported yet");
return 0;
}
int readGridsUni(const string &name, std::vector<PbClass *> *grids)
{
errMsg("readGridsUni: reading multiple grids from one .uni file not supported yet");
return 0;
}
template<class T> int writeGridVol(const string &name, Grid<T> *grid)
{
debMsg("writing grid " << grid->getName() << " to vol file " << name, 1);
errMsg("writeGridVol: Type not yet supported!");
return 0;
}
int writeGridsVol(const string &name, std::vector<PbClass *> *grids)
{
errMsg("writeGridsVol: writing multiple grids to one .vol file not supported yet");
return 0;
}
int readGridsVol(const string &name, std::vector<PbClass *> *grids)
{
errMsg("readGridsVol: reading multiple grids from one .vol file not supported yet");
return 0;
}
struct volHeader {
@ -631,7 +694,7 @@ struct volHeader {
Vec3 bboxMin, bboxMax;
};
template<> void writeGridVol<Real>(const string &name, Grid<Real> *grid)
template<> int writeGridVol<Real>(const string &name, Grid<Real> *grid)
{
debMsg("writing real grid " << grid->getName() << " to vol file " << name, 1);
@ -651,7 +714,7 @@ template<> void writeGridVol<Real>(const string &name, Grid<Real> *grid)
FILE *fp = fopen(name.c_str(), "wb");
if (fp == NULL) {
errMsg("writeGridVol: Cannot open '" << name << "'");
return;
return 0;
}
fwrite(&header, sizeof(volHeader), 1, fp);
@ -667,17 +730,17 @@ template<> void writeGridVol<Real>(const string &name, Grid<Real> *grid)
fwrite(&value, sizeof(float), 1, fp);
}
#endif
fclose(fp);
return (!fclose(fp));
};
template<class T> void readGridVol(const string &name, Grid<T> *grid)
template<class T> int readGridVol(const string &name, Grid<T> *grid)
{
debMsg("writing grid " << grid->getName() << " to vol file " << name, 1);
errMsg("readGridVol: Type not yet supported!");
return 0;
}
template<> void readGridVol<Real>(const string &name, Grid<Real> *grid)
template<> int readGridVol<Real>(const string &name, Grid<Real> *grid)
{
debMsg("reading real grid " << grid->getName() << " from vol file " << name, 1);
@ -685,7 +748,7 @@ template<> void readGridVol<Real>(const string &name, Grid<Real> *grid)
FILE *fp = fopen(name.c_str(), "rb");
if (fp == NULL) {
errMsg("readGridVol: Cannot open '" << name << "'");
return;
return 0;
}
// note, only very basic file format checks here!
@ -697,17 +760,17 @@ template<> void readGridVol<Real>(const string &name, Grid<Real> *grid)
<< grid->getSize());
#if FLOATINGPOINT_PRECISION != 1
errMsg("readGridVol: Double precision not yet supported");
return 0;
#else
const unsigned int s = sizeof(float) * header.dimX * header.dimY * header.dimZ;
assertMsg(fread(&((*grid)[0]), 1, s, fp) == s, "can't read file, no / not enough data");
#endif
fclose(fp);
return (!fclose(fp));
};
// 4d grids IO
template<class T> void writeGrid4dUni(const string &name, Grid4d<T> *grid)
template<class T> int writeGrid4dUni(const string &name, Grid4d<T> *grid)
{
debMsg("writing grid4d " << grid->getName() << " to uni file " << name, 1);
@ -733,12 +796,16 @@ template<class T> void writeGrid4dUni(const string &name, Grid4d<T> *grid)
head.elementType = 2;
else if (grid->getType() & Grid4dBase::TypeVec4)
head.elementType = 2;
else
else {
errMsg("writeGrid4dUni: unknown element type");
return 0;
}
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("writeGrid4dUni: can't open file " << name);
return 0;
}
gzwrite(gzf, ID, 4);
# if FLOATINGPOINT_PRECISION != 1
@ -753,16 +820,17 @@ template<class T> void writeGrid4dUni(const string &name, Grid4d<T> *grid)
gzwrite(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ * 1);
}
# endif
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
//! note, reading 4d uni grids is slightly more complicated than 3d ones
//! as it optionally supports sliced reading
template<class T>
void readGrid4dUni(
int readGrid4dUni(
const string &name, Grid4d<T> *grid, int readTslice, Grid4d<T> *slice, void **fileHandle)
{
if (grid)
@ -779,8 +847,10 @@ void readGrid4dUni(
// optionally - reuse file handle, if valid one is passed in fileHandle pointer...
if ((!fileHandle) || (fileHandle && (*fileHandle == NULL))) {
gzf = (gzFile)safeGzopen(name.c_str(), "rb");
if (!gzf)
if (!gzf) {
errMsg("readGrid4dUni: can't open file " << name);
return 0;
}
gzread(gzf, ID, 4);
if (fileHandle) {
@ -792,7 +862,7 @@ void readGrid4dUni(
gzf = (gzFile)(*fileHandle);
void *ptr = &((*slice)[0]);
gzread(gzf, ptr, sizeof(T) * slice->getStrideT() * 1); // quick and dirty...
return;
return 1;
}
if ((!strcmp(ID, "M4T2")) || (!strcmp(ID, "M4T3"))) {
@ -867,6 +937,7 @@ void readGrid4dUni(
# if FLOATINGPOINT_PRECISION != 1
errMsg("readGrid4dUni: NYI (2)"); // slice read not yet supported for double
return 0;
# else
assertMsg(slice, "No 3d slice grid data given");
assertMsg(readTslice < head.dimT,
@ -884,10 +955,12 @@ void readGrid4dUni(
}
if (!fileHandle) {
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
}
return 1;
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
void readGrid4dUniCleanup(void **fileHandle)
@ -900,296 +973,61 @@ void readGrid4dUniCleanup(void **fileHandle)
}
}
template<class T> void writeGrid4dRaw(const string &name, Grid4d<T> *grid)
template<class T> int writeGrid4dRaw(const string &name, Grid4d<T> *grid)
{
debMsg("writing grid4d " << grid->getName() << " to raw file " << name, 1);
#if NO_ZLIB != 1
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("writeGrid4dRaw: can't open file " << name);
return 0;
}
gzwrite(gzf,
&((*grid)[0]),
sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ() * grid->getSizeT());
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
template<class T> void readGrid4dRaw(const string &name, Grid4d<T> *grid)
template<class T> int readGrid4dRaw(const string &name, Grid4d<T> *grid)
{
debMsg("reading grid4d " << grid->getName() << " from raw file " << name, 1);
#if NO_ZLIB != 1
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "rb");
if (!gzf)
if (!gzf) {
errMsg("readGrid4dRaw: can't open file " << name);
return 0;
}
IndexInt bytes = sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ() *
grid->getSizeT();
IndexInt readBytes = gzread(gzf, &((*grid)[0]), bytes);
assertMsg(bytes == readBytes,
"can't read raw file, stream length does not match, " << bytes << " vs " << readBytes);
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
//*****************************************************************************
// optional openvdb export
#if OPENVDB == 1
template<class T> void writeGridVDB(const string &name, Grid<T> *grid)
{
debMsg("Writing grid " << grid->getName() << " to vdb file " << name << " not yet supported!",
1);
}
template<class T> void readGridVDB(const string &name, Grid<T> *grid)
{
debMsg("Reading grid " << grid->getName() << " from vdb file " << name << " not yet supported!",
1);
}
template<> void writeGridVDB(const string &name, Grid<int> *grid)
{
debMsg("Writing int grid " << grid->getName() << " to vdb file " << name, 1);
// Create an empty int32-point grid with background value 0.
openvdb::initialize();
openvdb::Int32Grid::Ptr gridVDB = openvdb::Int32Grid::create();
gridVDB->setTransform(
openvdb::math::Transform::createLinearTransform(1. / grid->getSizeX())); // voxel size
// Get an accessor for coordinate-based access to voxels.
openvdb::Int32Grid::Accessor accessor = gridVDB->getAccessor();
gridVDB->setGridClass(openvdb::GRID_UNKNOWN);
// Name the grid "density".
gridVDB->setName(grid->getName());
openvdb::io::File file(name);
FOR_IJK(*grid)
{
openvdb::Coord xyz(i, j, k);
accessor.setValue(xyz, (*grid)(i, j, k));
}
// Add the grid pointer to a container.
openvdb::GridPtrVec gridsVDB;
gridsVDB.push_back(gridVDB);
// Write out the contents of the container.
file.write(gridsVDB);
file.close();
}
template<> void readGridVDB(const string &name, Grid<int> *grid)
{
debMsg("Reading int grid " << grid->getName() << " from vdb file " << name, 1);
openvdb::initialize();
openvdb::io::File file(name);
file.open();
openvdb::GridBase::Ptr baseGrid;
for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
++nameIter) {
# ifndef BLENDER
// Read in only the grid we are interested in.
if (nameIter.gridName() == grid->getName()) {
baseGrid = file.readGrid(nameIter.gridName());
}
else {
debMsg("skipping grid " << nameIter.gridName(), 1);
}
# else
// For Blender, skip name check and pick first grid from loop
baseGrid = file.readGrid(nameIter.gridName());
break;
# endif
}
file.close();
openvdb::Int32Grid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::Int32Grid>(baseGrid);
openvdb::Int32Grid::Accessor accessor = gridVDB->getAccessor();
FOR_IJK(*grid)
{
openvdb::Coord xyz(i, j, k);
int v = accessor.getValue(xyz);
(*grid)(i, j, k) = v;
}
}
template<> void writeGridVDB(const string &name, Grid<Real> *grid)
{
debMsg("Writing real grid " << grid->getName() << " to vdb file " << name, 1);
// Create an empty floating-point grid with background value 0.
openvdb::initialize();
openvdb::FloatGrid::Ptr gridVDB = openvdb::FloatGrid::create();
gridVDB->setTransform(
openvdb::math::Transform::createLinearTransform(1. / grid->getSizeX())); // voxel size
// Get an accessor for coordinate-based access to voxels.
openvdb::FloatGrid::Accessor accessor = gridVDB->getAccessor();
// Identify the grid as a level set.
gridVDB->setGridClass(openvdb::GRID_FOG_VOLUME);
// Name the grid "density".
gridVDB->setName(grid->getName());
openvdb::io::File file(name);
FOR_IJK(*grid)
{
openvdb::Coord xyz(i, j, k);
accessor.setValue(xyz, (*grid)(i, j, k));
}
// Add the grid pointer to a container.
openvdb::GridPtrVec gridsVDB;
gridsVDB.push_back(gridVDB);
// Write out the contents of the container.
file.write(gridsVDB);
file.close();
};
template<> void readGridVDB(const string &name, Grid<Real> *grid)
{
debMsg("Reading real grid " << grid->getName() << " from vdb file " << name, 1);
openvdb::initialize();
openvdb::io::File file(name);
file.open();
openvdb::GridBase::Ptr baseGrid;
for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
++nameIter) {
# ifndef BLENDER
// Read in only the grid we are interested in.
if (nameIter.gridName() == grid->getName()) {
baseGrid = file.readGrid(nameIter.gridName());
}
else {
debMsg("skipping grid " << nameIter.gridName(), 1);
}
# else
// For Blender, skip name check and pick first grid from loop
baseGrid = file.readGrid(nameIter.gridName());
break;
# endif
}
file.close();
openvdb::FloatGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrid);
openvdb::FloatGrid::Accessor accessor = gridVDB->getAccessor();
FOR_IJK(*grid)
{
openvdb::Coord xyz(i, j, k);
float v = accessor.getValue(xyz);
(*grid)(i, j, k) = v;
}
};
template<> void writeGridVDB(const string &name, Grid<Vec3> *grid)
{
debMsg("Writing vec3 grid " << grid->getName() << " to vdb file " << name, 1);
openvdb::initialize();
openvdb::Vec3SGrid::Ptr gridVDB = openvdb::Vec3SGrid::create();
// note , warning - velocity content currently not scaled...
gridVDB->setTransform(
openvdb::math::Transform::createLinearTransform(1. / grid->getSizeX())); // voxel size
openvdb::Vec3SGrid::Accessor accessor = gridVDB->getAccessor();
// MAC or regular vec grid?
if (grid->getType() & GridBase::TypeMAC)
gridVDB->setGridClass(openvdb::GRID_STAGGERED);
else
gridVDB->setGridClass(openvdb::GRID_UNKNOWN);
gridVDB->setName(grid->getName());
openvdb::io::File file(name);
FOR_IJK(*grid)
{
openvdb::Coord xyz(i, j, k);
Vec3 v = (*grid)(i, j, k);
openvdb::Vec3f vo((float)v[0], (float)v[1], (float)v[2]);
accessor.setValue(xyz, vo);
}
openvdb::GridPtrVec gridsVDB;
gridsVDB.push_back(gridVDB);
file.write(gridsVDB);
file.close();
};
template<> void readGridVDB(const string &name, Grid<Vec3> *grid)
{
debMsg("Reading vec3 grid " << grid->getName() << " from vdb file " << name, 1);
openvdb::initialize();
openvdb::io::File file(name);
file.open();
openvdb::GridBase::Ptr baseGrid;
for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
++nameIter) {
# ifndef BLENDER
// Read in only the grid we are interested in.
if (nameIter.gridName() == grid->getName()) {
baseGrid = file.readGrid(nameIter.gridName());
}
else {
debMsg("skipping grid " << nameIter.gridName(), 1);
}
# else
// For Blender, skip name check and pick first grid from loop
baseGrid = file.readGrid(nameIter.gridName());
break;
# endif
}
file.close();
openvdb::Vec3SGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::Vec3SGrid>(baseGrid);
openvdb::Vec3SGrid::Accessor accessor = gridVDB->getAccessor();
FOR_IJK(*grid)
{
openvdb::Coord xyz(i, j, k);
openvdb::Vec3f v = accessor.getValue(xyz);
(*grid)(i, j, k).x = (float)v[0];
(*grid)(i, j, k).y = (float)v[1];
(*grid)(i, j, k).z = (float)v[2];
}
};
#endif // OPENVDB==1
//*****************************************************************************
// npz file support (warning - read works, but write generates uncompressed npz; i.e. not
// recommended for large volumes)
template<class T> void writeGridNumpy(const string &name, Grid<T> *grid)
template<class T> int writeGridNumpy(const string &name, Grid<T> *grid)
{
#if NO_ZLIB == 1
debMsg("file format not supported without zlib", 1);
return;
return 0;
#endif
#if FLOATINGPOINT_PRECISION != 1
errMsg("writeGridNumpy: Double precision not yet supported");
return 0;
#endif
// find suffix to differentiate between npy <-> npz , TODO: check for actual "npy" string
@ -1211,8 +1049,10 @@ template<class T> void writeGridNumpy(const string &name, Grid<T> *grid)
uDim = 1;
else if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC)
uDim = 3;
else
else {
errMsg("writeGridNumpy: unknown element type");
return 0;
}
const std::vector<size_t> shape = {static_cast<size_t>(grid->getSizeZ()),
static_cast<size_t>(grid->getSizeY()),
@ -1234,16 +1074,18 @@ template<class T> void writeGridNumpy(const string &name, Grid<T> *grid)
else {
cnpy::npy_save(name, &grid[0], shape, "w");
}
return 1;
};
template<class T> void readGridNumpy(const string &name, Grid<T> *grid)
template<class T> int readGridNumpy(const string &name, Grid<T> *grid)
{
#if NO_ZLIB == 1
debMsg("file format not supported without zlib", 1);
return;
return 0;
#endif
#if FLOATINGPOINT_PRECISION != 1
errMsg("readGridNumpy: Double precision not yet supported");
return 0;
#endif
// find suffix to differentiate between npy <-> npz
@ -1279,8 +1121,10 @@ template<class T> void readGridNumpy(const string &name, Grid<T> *grid)
uDim = 1;
else if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC)
uDim = 3;
else
else {
errMsg("readGridNumpy: unknown element type");
return 0;
}
assertMsg(gridArr.shape[3] == uDim,
"grid data dim doesn't match, " << gridArr.shape[3] << " vs " << uDim);
@ -1299,8 +1143,21 @@ template<class T> void readGridNumpy(const string &name, Grid<T> *grid)
memcpy(&((*grid)[0]),
gridArr.data<T>(),
sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ());
return 1;
};
int writeGridsNumpy(const string &name, std::vector<PbClass *> *grids)
{
errMsg("writeGridsNumpy: writing multiple grids to one .npz file not supported yet");
return 0;
}
int readGridsNumpy(const string &name, std::vector<PbClass *> *grids)
{
errMsg("readGridsNumpy: reading multiple grids from one .npz file not supported yet");
return 0;
}
// adopted from getUniFileSize
void getNpzFileSize(
const string &name, int &x, int &y, int &z, int *t = NULL, std::string *info = NULL)
@ -1521,77 +1378,63 @@ void PbRegister_quantizeGridVec3()
}
// explicit instantiation
template void writeGridRaw<int>(const string &name, Grid<int> *grid);
template void writeGridRaw<Real>(const string &name, Grid<Real> *grid);
template void writeGridRaw<Vec3>(const string &name, Grid<Vec3> *grid);
template void writeGridUni<int>(const string &name, Grid<int> *grid);
template void writeGridUni<Real>(const string &name, Grid<Real> *grid);
template void writeGridUni<Vec3>(const string &name, Grid<Vec3> *grid);
template void writeGridVol<int>(const string &name, Grid<int> *grid);
template void writeGridVol<Vec3>(const string &name, Grid<Vec3> *grid);
template void writeGridTxt<int>(const string &name, Grid<int> *grid);
template void writeGridTxt<Real>(const string &name, Grid<Real> *grid);
template void writeGridTxt<Vec3>(const string &name, Grid<Vec3> *grid);
template int writeGridRaw<int>(const string &name, Grid<int> *grid);
template int writeGridRaw<Real>(const string &name, Grid<Real> *grid);
template int writeGridRaw<Vec3>(const string &name, Grid<Vec3> *grid);
template int writeGridUni<int>(const string &name, Grid<int> *grid);
template int writeGridUni<Real>(const string &name, Grid<Real> *grid);
template int writeGridUni<Vec3>(const string &name, Grid<Vec3> *grid);
template int writeGridVol<int>(const string &name, Grid<int> *grid);
template int writeGridVol<Vec3>(const string &name, Grid<Vec3> *grid);
template int writeGridTxt<int>(const string &name, Grid<int> *grid);
template int writeGridTxt<Real>(const string &name, Grid<Real> *grid);
template int writeGridTxt<Vec3>(const string &name, Grid<Vec3> *grid);
template void readGridRaw<int>(const string &name, Grid<int> *grid);
template void readGridRaw<Real>(const string &name, Grid<Real> *grid);
template void readGridRaw<Vec3>(const string &name, Grid<Vec3> *grid);
template void readGridUni<int>(const string &name, Grid<int> *grid);
template void readGridUni<Real>(const string &name, Grid<Real> *grid);
template void readGridUni<Vec3>(const string &name, Grid<Vec3> *grid);
template void readGridVol<int>(const string &name, Grid<int> *grid);
template void readGridVol<Vec3>(const string &name, Grid<Vec3> *grid);
template int readGridRaw<int>(const string &name, Grid<int> *grid);
template int readGridRaw<Real>(const string &name, Grid<Real> *grid);
template int readGridRaw<Vec3>(const string &name, Grid<Vec3> *grid);
template int readGridUni<int>(const string &name, Grid<int> *grid);
template int readGridUni<Real>(const string &name, Grid<Real> *grid);
template int readGridUni<Vec3>(const string &name, Grid<Vec3> *grid);
template int readGridVol<int>(const string &name, Grid<int> *grid);
template int readGridVol<Vec3>(const string &name, Grid<Vec3> *grid);
template void readGrid4dUni<int>(
template int readGrid4dUni<int>(
const string &name, Grid4d<int> *grid, int readTslice, Grid4d<int> *slice, void **fileHandle);
template void readGrid4dUni<Real>(const string &name,
Grid4d<Real> *grid,
int readTslice,
Grid4d<Real> *slice,
void **fileHandle);
template void readGrid4dUni<Vec3>(const string &name,
Grid4d<Vec3> *grid,
int readTslice,
Grid4d<Vec3> *slice,
void **fileHandle);
template void readGrid4dUni<Vec4>(const string &name,
Grid4d<Vec4> *grid,
int readTslice,
Grid4d<Vec4> *slice,
void **fileHandle);
template void writeGrid4dUni<int>(const string &name, Grid4d<int> *grid);
template void writeGrid4dUni<Real>(const string &name, Grid4d<Real> *grid);
template void writeGrid4dUni<Vec3>(const string &name, Grid4d<Vec3> *grid);
template void writeGrid4dUni<Vec4>(const string &name, Grid4d<Vec4> *grid);
template int readGrid4dUni<Real>(const string &name,
Grid4d<Real> *grid,
int readTslice,
Grid4d<Real> *slice,
void **fileHandle);
template int readGrid4dUni<Vec3>(const string &name,
Grid4d<Vec3> *grid,
int readTslice,
Grid4d<Vec3> *slice,
void **fileHandle);
template int readGrid4dUni<Vec4>(const string &name,
Grid4d<Vec4> *grid,
int readTslice,
Grid4d<Vec4> *slice,
void **fileHandle);
template int writeGrid4dUni<int>(const string &name, Grid4d<int> *grid);
template int writeGrid4dUni<Real>(const string &name, Grid4d<Real> *grid);
template int writeGrid4dUni<Vec3>(const string &name, Grid4d<Vec3> *grid);
template int writeGrid4dUni<Vec4>(const string &name, Grid4d<Vec4> *grid);
template void readGrid4dRaw<int>(const string &name, Grid4d<int> *grid);
template void readGrid4dRaw<Real>(const string &name, Grid4d<Real> *grid);
template void readGrid4dRaw<Vec3>(const string &name, Grid4d<Vec3> *grid);
template void readGrid4dRaw<Vec4>(const string &name, Grid4d<Vec4> *grid);
template void writeGrid4dRaw<int>(const string &name, Grid4d<int> *grid);
template void writeGrid4dRaw<Real>(const string &name, Grid4d<Real> *grid);
template void writeGrid4dRaw<Vec3>(const string &name, Grid4d<Vec3> *grid);
template void writeGrid4dRaw<Vec4>(const string &name, Grid4d<Vec4> *grid);
template int readGrid4dRaw<int>(const string &name, Grid4d<int> *grid);
template int readGrid4dRaw<Real>(const string &name, Grid4d<Real> *grid);
template int readGrid4dRaw<Vec3>(const string &name, Grid4d<Vec3> *grid);
template int readGrid4dRaw<Vec4>(const string &name, Grid4d<Vec4> *grid);
template int writeGrid4dRaw<int>(const string &name, Grid4d<int> *grid);
template int writeGrid4dRaw<Real>(const string &name, Grid4d<Real> *grid);
template int writeGrid4dRaw<Vec3>(const string &name, Grid4d<Vec3> *grid);
template int writeGrid4dRaw<Vec4>(const string &name, Grid4d<Vec4> *grid);
template void writeGridNumpy<int>(const string &name, Grid<int> *grid);
template void writeGridNumpy<Real>(const string &name, Grid<Real> *grid);
template void writeGridNumpy<Vec3>(const string &name, Grid<Vec3> *grid);
template void readGridNumpy<int>(const string &name, Grid<int> *grid);
template void readGridNumpy<Real>(const string &name, Grid<Real> *grid);
template void readGridNumpy<Vec3>(const string &name, Grid<Vec3> *grid);
#if OPENVDB == 1
template void writeGridVDB<int>(const string &name, Grid<int> *grid);
template void writeGridVDB<Vec3>(const string &name, Grid<Vec3> *grid);
template void writeGridVDB<Real>(const string &name, Grid<Real> *grid);
template void readGridVDB<int>(const string &name, Grid<int> *grid);
template void readGridVDB<Vec3>(const string &name, Grid<Vec3> *grid);
template void readGridVDB<Real>(const string &name, Grid<Real> *grid);
#endif // OPENVDB==1
template int writeGridNumpy<int>(const string &name, Grid<int> *grid);
template int writeGridNumpy<Real>(const string &name, Grid<Real> *grid);
template int writeGridNumpy<Vec3>(const string &name, Grid<Vec3> *grid);
template int readGridNumpy<int>(const string &name, Grid<int> *grid);
template int readGridNumpy<Real>(const string &name, Grid<Real> *grid);
template int readGridNumpy<Vec3>(const string &name, Grid<Vec3> *grid);
} // namespace Manta
namespace Manta {
}

View File

@ -146,21 +146,25 @@ void mdataReadConvert<Vec3>(gzFile &gzf, MeshDataImpl<Vec3> &mdata, void *ptr, i
// mesh data
//*****************************************************************************
void readBobjFile(const string &name, Mesh *mesh, bool append)
int readBobjFile(const string &name, Mesh *mesh, bool append)
{
debMsg("reading mesh file " << name, 1);
if (!append)
mesh->clear();
else
else {
errMsg("readBobj: append not yet implemented!");
return 0;
}
#if NO_ZLIB != 1
const Real dx = mesh->getParent()->getDx();
const Vec3 gs = toVec3(mesh->getParent()->getGridSize());
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "rb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("readBobj: unable to open file");
return 0;
}
// read vertices
int num = 0;
@ -198,15 +202,16 @@ void readBobjFile(const string &name, Mesh *mesh, bool append)
}
}
// note - vortex sheet info ignored for now... (see writeBobj)
gzclose(gzf);
debMsg("read mesh , triangles " << mesh->numTris() << ", vertices " << mesh->numNodes() << " ",
1);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
void writeBobjFile(const string &name, Mesh *mesh)
int writeBobjFile(const string &name, Mesh *mesh)
{
debMsg("writing mesh file " << name, 1);
#if NO_ZLIB != 1
@ -214,8 +219,10 @@ void writeBobjFile(const string &name, Mesh *mesh)
const Vec3i gs = mesh->getParent()->getGridSize();
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("writeBobj: unable to open file");
return 0;
}
// write vertices
int numVerts = mesh->numNodes();
@ -292,18 +299,21 @@ void writeBobjFile(const string &name, Mesh *mesh)
}
}
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
void readObjFile(const std::string &name, Mesh *mesh, bool append)
int readObjFile(const std::string &name, Mesh *mesh, bool append)
{
ifstream ifs(name.c_str());
if (!ifs.good())
if (!ifs.good()) {
errMsg("can't open file '" + name + "'");
return 0;
}
if (!append)
mesh->clear();
@ -323,8 +333,10 @@ void readObjFile(const std::string &name, Mesh *mesh, bool append)
}
else if (id == "vn") {
// normals
if (!mesh->numNodes())
if (!mesh->numNodes()) {
errMsg("invalid amount of nodes");
return 0;
}
Node n = mesh->nodes(cnt);
ifs >> n.normal.x >> n.normal.y >> n.normal.z;
cnt++;
@ -349,8 +361,10 @@ void readObjFile(const std::string &name, Mesh *mesh, bool append)
if (face.find('/') != string::npos)
face = face.substr(0, face.find('/')); // ignore other indices
int idx = atoi(face.c_str()) - 1;
if (idx < 0)
if (idx < 0) {
errMsg("invalid face encountered");
return 0;
}
idx += nodebase;
t.c[i] = idx;
}
@ -363,17 +377,20 @@ void readObjFile(const std::string &name, Mesh *mesh, bool append)
getline(ifs, id);
}
ifs.close();
return 1;
}
// write regular .obj file, in line with bobj.gz output (but only verts & tris for now)
void writeObjFile(const string &name, Mesh *mesh)
int writeObjFile(const string &name, Mesh *mesh)
{
const Real dx = mesh->getParent()->getDx();
const Vec3i gs = mesh->getParent()->getGridSize();
ofstream ofs(name.c_str());
if (!ofs.good())
if (!ofs.good()) {
errMsg("writeObjFile: can't open file " << name);
return 0;
}
ofs << "o MantaMesh\n";
@ -405,16 +422,19 @@ void writeObjFile(const string &name, Mesh *mesh)
}
ofs.close();
return 1;
}
template<class T> void readMdataUni(const std::string &name, MeshDataImpl<T> *mdata)
template<class T> int readMdataUni(const std::string &name, MeshDataImpl<T> *mdata)
{
debMsg("reading mesh data " << mdata->getName() << " from uni file " << name, 1);
#if NO_ZLIB != 1
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "rb");
if (!gzf)
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
char ID[5] = {0, 0, 0, 0, 0};
gzread(gzf, ID, 4);
@ -440,13 +460,14 @@ template<class T> void readMdataUni(const std::string &name, MeshDataImpl<T> *md
<< readBytes);
# endif
}
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
template<class T> void writeMdataUni(const std::string &name, MeshDataImpl<T> *mdata)
template<class T> int writeMdataUni(const std::string &name, MeshDataImpl<T> *mdata)
{
debMsg("writing mesh data " << mdata->getName() << " to uni file " << name, 1);
@ -461,8 +482,10 @@ template<class T> void writeMdataUni(const std::string &name, MeshDataImpl<T> *m
head.timestamp = stamp.time;
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
gzwrite(gzf, ID, 4);
# if FLOATINGPOINT_PRECISION != 1
@ -474,19 +497,20 @@ template<class T> void writeMdataUni(const std::string &name, MeshDataImpl<T> *m
gzwrite(gzf, &head, sizeof(UniMeshHeader));
gzwrite(gzf, &(mdata->get(0)), sizeof(T) * head.dim);
# endif
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
// explicit instantiation
template void writeMdataUni<int>(const std::string &name, MeshDataImpl<int> *mdata);
template void writeMdataUni<Real>(const std::string &name, MeshDataImpl<Real> *mdata);
template void writeMdataUni<Vec3>(const std::string &name, MeshDataImpl<Vec3> *mdata);
template void readMdataUni<int>(const std::string &name, MeshDataImpl<int> *mdata);
template void readMdataUni<Real>(const std::string &name, MeshDataImpl<Real> *mdata);
template void readMdataUni<Vec3>(const std::string &name, MeshDataImpl<Vec3> *mdata);
template int writeMdataUni<int>(const std::string &name, MeshDataImpl<int> *mdata);
template int writeMdataUni<Real>(const std::string &name, MeshDataImpl<Real> *mdata);
template int writeMdataUni<Vec3>(const std::string &name, MeshDataImpl<Vec3> *mdata);
template int readMdataUni<int>(const std::string &name, MeshDataImpl<int> *mdata);
template int readMdataUni<Real>(const std::string &name, MeshDataImpl<Real> *mdata);
template int readMdataUni<Vec3>(const std::string &name, MeshDataImpl<Vec3> *mdata);
} // namespace Manta

View File

@ -158,7 +158,7 @@ void pdataReadConvert<Vec3>(gzFile &gzf,
static const int PartSysSize = sizeof(Vector3D<float>) + sizeof(int);
void writeParticlesUni(const std::string &name, const BasicParticleSystem *parts)
int writeParticlesUni(const std::string &name, const BasicParticleSystem *parts)
{
debMsg("writing particles " << parts->getName() << " to uni file " << name, 1);
@ -177,8 +177,10 @@ void writeParticlesUni(const std::string &name, const BasicParticleSystem *parts
head.timestamp = stamp.time;
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
gzwrite(gzf, ID, 4);
# if FLOATINGPOINT_PRECISION != 1
@ -195,26 +197,30 @@ void writeParticlesUni(const std::string &name, const BasicParticleSystem *parts
gzwrite(gzf, &head, sizeof(UniPartHeader));
gzwrite(gzf, &((*parts)[0]), PartSysSize * head.dim);
# endif
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
void readParticlesUni(const std::string &name, BasicParticleSystem *parts)
int readParticlesUni(const std::string &name, BasicParticleSystem *parts)
{
debMsg("reading particles " << parts->getName() << " from uni file " << name, 1);
#if NO_ZLIB != 1
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "rb");
if (!gzf)
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
char ID[5] = {0, 0, 0, 0, 0};
gzread(gzf, ID, 4);
if (!strcmp(ID, "PB01")) {
errMsg("particle uni file format v01 not supported anymore");
return 0;
}
else if (!strcmp(ID, "PB02")) {
// current file format
@ -249,13 +255,14 @@ void readParticlesUni(const std::string &name, BasicParticleSystem *parts)
parts->transformPositions(Vec3i(head.dimX, head.dimY, head.dimZ),
parts->getParent()->getGridSize());
}
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
template<class T> void writePdataUni(const std::string &name, ParticleDataImpl<T> *pdata)
template<class T> int writePdataUni(const std::string &name, ParticleDataImpl<T> *pdata)
{
debMsg("writing particle data " << pdata->getName() << " to uni file " << name, 1);
@ -274,8 +281,10 @@ template<class T> void writePdataUni(const std::string &name, ParticleDataImpl<T
head.timestamp = stamp.time;
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf)
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
gzwrite(gzf, ID, 4);
# if FLOATINGPOINT_PRECISION != 1
@ -287,21 +296,24 @@ template<class T> void writePdataUni(const std::string &name, ParticleDataImpl<T
gzwrite(gzf, &head, sizeof(UniPartHeader));
gzwrite(gzf, &(pdata->get(0)), sizeof(T) * head.dim);
# endif
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
template<class T> void readPdataUni(const std::string &name, ParticleDataImpl<T> *pdata)
template<class T> int readPdataUni(const std::string &name, ParticleDataImpl<T> *pdata)
{
debMsg("reading particle data " << pdata->getName() << " from uni file " << name, 1);
#if NO_ZLIB != 1
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "rb");
if (!gzf)
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
char ID[5] = {0, 0, 0, 0, 0};
gzread(gzf, ID, 4);
@ -327,18 +339,19 @@ template<class T> void readPdataUni(const std::string &name, ParticleDataImpl<T>
<< readBytes);
# endif
}
gzclose(gzf);
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
// explicit instantiation
template void writePdataUni<int>(const std::string &name, ParticleDataImpl<int> *pdata);
template void writePdataUni<Real>(const std::string &name, ParticleDataImpl<Real> *pdata);
template void writePdataUni<Vec3>(const std::string &name, ParticleDataImpl<Vec3> *pdata);
template void readPdataUni<int>(const std::string &name, ParticleDataImpl<int> *pdata);
template void readPdataUni<Real>(const std::string &name, ParticleDataImpl<Real> *pdata);
template void readPdataUni<Vec3>(const std::string &name, ParticleDataImpl<Vec3> *pdata);
template int writePdataUni<int>(const std::string &name, ParticleDataImpl<int> *pdata);
template int writePdataUni<Real>(const std::string &name, ParticleDataImpl<Real> *pdata);
template int writePdataUni<Vec3>(const std::string &name, ParticleDataImpl<Vec3> *pdata);
template int readPdataUni<int>(const std::string &name, ParticleDataImpl<int> *pdata);
template int readPdataUni<Real>(const std::string &name, ParticleDataImpl<Real> *pdata);
template int readPdataUni<Vec3>(const std::string &name, ParticleDataImpl<Vec3> *pdata);
} // namespace Manta

View File

@ -18,6 +18,10 @@
#include "mantaio.h"
#if OPENVDB == 1
# include "openvdb/openvdb.h"
#endif
#if NO_ZLIB != 1
extern "C" {
# include <zlib.h>
@ -40,7 +44,7 @@ static wstring stringToWstring(const char *str)
MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), &strWide[0], length_wc);
return strWide;
}
# endif
# endif // WIN32==1
void *safeGzopen(const char *filename, const char *mode)
{
@ -55,6 +59,54 @@ void *safeGzopen(const char *filename, const char *mode)
return gzfile;
}
#endif
#endif // NO_ZLIB != 1
#if defined(OPENVDB)
// Convert from OpenVDB value to Manta value.
template<class S, class T> void convertFrom(S &in, T *out)
{
errMsg("OpenVDB convertFrom Warning: Unsupported type conversion");
}
template<> void convertFrom(int &in, int *out)
{
(*out) = in;
}
template<> void convertFrom(float &in, Real *out)
{
(*out) = (Real)in;
}
template<> void convertFrom(openvdb::Vec3s &in, Vec3 *out)
{
(*out).x = in.x();
(*out).y = in.y();
(*out).z = in.z();
}
// Convert to OpenVDB value from Manta value.
template<class S, class T> void convertTo(S *out, T &in)
{
errMsg("OpenVDB convertTo Warning: Unsupported type conversion");
}
template<> void convertTo(int *out, int &in)
{
(*out) = in;
}
template<> void convertTo(float *out, Real &in)
{
(*out) = (float)in;
}
template<> void convertTo(openvdb::Vec3s *out, Vec3 &in)
{
(*out).x() = in.x;
(*out).y() = in.y;
(*out).z() = in.z;
}
#endif // OPENVDB==1
} // namespace

View File

@ -0,0 +1,618 @@
// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep generate).
/******************************************************************************
*
* MantaFlow fluid solver framework
* Copyright 2020 Sebastian Barschkis, Nils Thuerey
*
* This program is free software, distributed under the terms of the
* Apache License, Version 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Loading and writing grids and particles from and to OpenVDB files.
*
******************************************************************************/
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include "mantaio.h"
#include "grid.h"
#include "vector4d.h"
#include "grid4d.h"
#include "particle.h"
#if OPENVDB == 1
# include "openvdb/openvdb.h"
# include <openvdb/points/PointConversion.h>
# include <openvdb/points/PointCount.h>
#endif
#define POSITION_NAME "P"
#define FLAG_NAME "U"
using namespace std;
namespace Manta {
#if OPENVDB == 1
template<class GridType, class T> void importVDB(typename GridType::Ptr from, Grid<T> *to)
{
using ValueT = typename GridType::ValueType;
typename GridType::Accessor accessor = from->getAccessor();
FOR_IJK(*to)
{
openvdb::Coord xyz(i, j, k);
ValueT vdbValue = accessor.getValue(xyz);
T toMantaValue;
convertFrom(vdbValue, &toMantaValue);
to->set(i, j, k, toMantaValue);
}
}
template<class VDBType, class T>
void importVDB(VDBType vdbValue, ParticleDataImpl<T> *to, int index, float voxelSize)
{
(void)voxelSize; // Unused
T toMantaValue;
convertFrom(vdbValue, &toMantaValue);
to->set(index, toMantaValue);
}
void importVDB(openvdb::points::PointDataGrid::Ptr from,
BasicParticleSystem *to,
std::vector<ParticleDataBase *> &toPData,
float voxelSize)
{
openvdb::Index64 count = openvdb::points::pointCount(from->tree());
to->resizeAll(count);
int cnt = 0;
for (auto leafIter = from->tree().cbeginLeaf(); leafIter; ++leafIter) {
const openvdb::points::AttributeArray &positionArray = leafIter->constAttributeArray(
POSITION_NAME);
const openvdb::points::AttributeArray &flagArray = leafIter->constAttributeArray(FLAG_NAME);
openvdb::points::AttributeHandle<openvdb::Vec3s> positionHandle(positionArray);
openvdb::points::AttributeHandle<int> flagHandle(flagArray);
// Get vdb handles to pdata objects in pdata list
std::vector<std::tuple<int, openvdb::points::AttributeHandle<int>>> pDataHandlesInt;
std::vector<std::tuple<int, openvdb::points::AttributeHandle<float>>> pDataHandlesReal;
std::vector<std::tuple<int, openvdb::points::AttributeHandle<openvdb::Vec3s>>>
pDataHandlesVec3;
int pDataIndex = 0;
for (ParticleDataBase *pdb : toPData) {
std::string name = pdb->getName();
const openvdb::points::AttributeArray &pDataArray = leafIter->constAttributeArray(name);
if (pdb->getType() == ParticleDataBase::TypeInt) {
openvdb::points::AttributeHandle<int> intHandle(pDataArray);
std::tuple<int, openvdb::points::AttributeHandle<int>> tuple = std::make_tuple(pDataIndex,
intHandle);
pDataHandlesInt.push_back(tuple);
}
else if (pdb->getType() == ParticleDataBase::TypeReal) {
openvdb::points::AttributeHandle<float> floatHandle(pDataArray);
std::tuple<int, openvdb::points::AttributeHandle<float>> tuple = std::make_tuple(
pDataIndex, floatHandle);
pDataHandlesReal.push_back(tuple);
}
else if (pdb->getType() == ParticleDataBase::TypeVec3) {
openvdb::points::AttributeHandle<openvdb::Vec3s> vec3Handle(pDataArray);
std::tuple<int, openvdb::points::AttributeHandle<openvdb::Vec3s>> tuple = std::make_tuple(
pDataIndex, vec3Handle);
pDataHandlesVec3.push_back(tuple);
}
else {
errMsg("importVDB: unknown ParticleDataBase type");
}
++pDataIndex;
}
for (auto indexIter = leafIter->beginIndexOn(); indexIter; ++indexIter) {
// Extract the voxel-space position of the point (always between (-0.5, -0.5, -0.5) and (0.5,
// 0.5, 0.5)).
openvdb::Vec3s voxelPosition = positionHandle.get(*indexIter);
const openvdb::Vec3d xyz = indexIter.getCoord().asVec3d();
// Compute the world-space position of the point.
openvdb::Vec3f worldPosition = from->transform().indexToWorld(voxelPosition + xyz);
int flag = flagHandle.get(*indexIter);
Vec3 toMantaValue;
convertFrom(worldPosition, &toMantaValue);
(*to)[cnt].pos = toMantaValue;
(*to)[cnt].pos /= voxelSize; // convert from world space to grid space
(*to)[cnt].flag = flag;
for (std::tuple<int, openvdb::points::AttributeHandle<int>> tuple : pDataHandlesInt) {
int pDataIndex = std::get<0>(tuple);
int vdbValue = std::get<1>(tuple).get(*indexIter);
ParticleDataImpl<int> *pdi = dynamic_cast<ParticleDataImpl<int> *>(toPData[pDataIndex]);
importVDB<int, int>(vdbValue, pdi, cnt, voxelSize);
}
for (std::tuple<int, openvdb::points::AttributeHandle<float>> tuple : pDataHandlesReal) {
int pDataIndex = std::get<0>(tuple);
float vdbValue = std::get<1>(tuple).get(*indexIter);
ParticleDataImpl<Real> *pdi = dynamic_cast<ParticleDataImpl<Real> *>(toPData[pDataIndex]);
importVDB<float, Real>(vdbValue, pdi, cnt, voxelSize);
}
for (std::tuple<int, openvdb::points::AttributeHandle<openvdb::Vec3s>> tuple :
pDataHandlesVec3) {
int pDataIndex = std::get<0>(tuple);
openvdb::Vec3f voxelPosition = std::get<1>(tuple).get(*indexIter);
ParticleDataImpl<Vec3> *pdi = dynamic_cast<ParticleDataImpl<Vec3> *>(toPData[pDataIndex]);
importVDB<openvdb::Vec3s, Vec3>(voxelPosition, pdi, cnt, voxelSize);
}
++cnt;
}
}
}
template<class GridType>
static void setGridOptions(typename GridType::Ptr grid,
string name,
openvdb::GridClass cls,
float voxelSize,
bool precisionHalf)
{
grid->setTransform(openvdb::math::Transform::createLinearTransform(voxelSize));
grid->setGridClass(cls);
grid->setName(name);
grid->setSaveFloatAsHalf(precisionHalf);
}
template<class T, class GridType> typename GridType::Ptr exportVDB(Grid<T> *from)
{
using ValueT = typename GridType::ValueType;
typename GridType::Ptr to = GridType::create();
typename GridType::Accessor accessor = to->getAccessor();
FOR_IJK(*from)
{
openvdb::Coord xyz(i, j, k);
T fromMantaValue = (*from)(i, j, k);
ValueT vdbValue;
convertTo(&vdbValue, fromMantaValue);
accessor.setValue(xyz, vdbValue);
}
return to;
}
template<class MantaType, class VDBType>
void exportVDB(ParticleDataImpl<MantaType> *from,
openvdb::points::PointDataGrid::Ptr to,
openvdb::tools::PointIndexGrid::Ptr pIndex,
bool skipDeletedParts)
{
std::vector<VDBType> vdbValues;
std::string name = from->getName();
FOR_PARTS(*from)
{
// Optionally, skip exporting particles that have been marked as deleted
BasicParticleSystem *pp = dynamic_cast<BasicParticleSystem *>(from->getParticleSys());
if (skipDeletedParts && !pp->isActive(idx)) {
continue;
}
MantaType fromMantaValue = (*from)[idx];
VDBType vdbValue;
convertTo(&vdbValue, fromMantaValue);
vdbValues.push_back(vdbValue);
}
openvdb::NamePair attribute =
openvdb::points::TypedAttributeArray<VDBType, openvdb::points::NullCodec>::attributeType();
openvdb::points::appendAttribute(to->tree(), name, attribute);
// Create a wrapper around the vdb values vector.
const openvdb::points::PointAttributeVector<VDBType> wrapper(vdbValues);
// Populate the attribute on the points
openvdb::points::populateAttribute<openvdb::points::PointDataTree,
openvdb::tools::PointIndexTree,
openvdb::points::PointAttributeVector<VDBType>>(
to->tree(), pIndex->tree(), name, wrapper);
}
openvdb::points::PointDataGrid::Ptr exportVDB(BasicParticleSystem *from,
std::vector<ParticleDataBase *> &fromPData,
bool skipDeletedParts,
float voxelSize)
{
std::vector<openvdb::Vec3s> positions;
std::vector<int> flags;
FOR_PARTS(*from)
{
// Optionally, skip exporting particles that have been marked as deleted
if (skipDeletedParts && !from->isActive(idx)) {
continue;
}
Vector3D<float> pos = toVec3f((*from)[idx].pos);
pos *= voxelSize; // convert from grid space to world space
openvdb::Vec3s posVDB(pos.x, pos.y, pos.z);
positions.push_back(posVDB);
int flag = (*from)[idx].flag;
flags.push_back(flag);
}
const openvdb::points::PointAttributeVector<openvdb::Vec3s> positionsWrapper(positions);
openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(
voxelSize);
openvdb::tools::PointIndexGrid::Ptr pointIndexGrid =
openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(positionsWrapper,
*transform);
// TODO (sebbas): Use custom codec for attributes?
// using Codec = openvdb::points::FixedPointCodec</*1-byte=*/false, openvdb::points::UnitRange>;
openvdb::points::PointDataGrid::Ptr to =
openvdb::points::createPointDataGrid<openvdb::points::NullCodec /*Codec*/,
openvdb::points::PointDataGrid>(
*pointIndexGrid, positionsWrapper, *transform);
openvdb::NamePair flagAttribute =
openvdb::points::TypedAttributeArray<int,
openvdb::points::NullCodec /*Codec*/>::attributeType();
openvdb::points::appendAttribute(to->tree(), FLAG_NAME, flagAttribute);
// Create a wrapper around the flag vector.
openvdb::points::PointAttributeVector<int> flagWrapper(flags);
// Populate the "flag" attribute on the points
openvdb::points::populateAttribute<openvdb::points::PointDataTree,
openvdb::tools::PointIndexTree,
openvdb::points::PointAttributeVector<int>>(
to->tree(), pointIndexGrid->tree(), FLAG_NAME, flagWrapper);
// Add all already buffered pdata to this particle grid
for (ParticleDataBase *pdb : fromPData) {
if (pdb->getType() == ParticleDataBase::TypeInt) {
debMsg("Writing int particle data '" << pdb->getName() << "'", 1);
ParticleDataImpl<int> *pdi = dynamic_cast<ParticleDataImpl<int> *>(pdb);
exportVDB<int, int>(pdi, to, pointIndexGrid, skipDeletedParts);
}
else if (pdb->getType() == ParticleDataBase::TypeReal) {
debMsg("Writing real particle data '" << pdb->getName() << "'", 1);
ParticleDataImpl<Real> *pdi = dynamic_cast<ParticleDataImpl<Real> *>(pdb);
exportVDB<Real, float>(pdi, to, pointIndexGrid, skipDeletedParts);
}
else if (pdb->getType() == ParticleDataBase::TypeVec3) {
debMsg("Writing Vec3 particle data '" << pdb->getName() << "'", 1);
ParticleDataImpl<Vec3> *pdi = dynamic_cast<ParticleDataImpl<Vec3> *>(pdb);
exportVDB<Vec3, openvdb::Vec3s>(pdi, to, pointIndexGrid, skipDeletedParts);
}
else {
errMsg("exportVDB: unknown ParticleDataBase type");
}
}
return to;
}
static void registerCustomCodecs()
{
using Codec = openvdb::points::FixedPointCodec</*1-byte=*/false, openvdb::points::UnitRange>;
openvdb::points::TypedAttributeArray<int, Codec>::registerType();
}
int writeObjectsVDB(const string &filename,
std::vector<PbClass *> *objects,
float worldSize,
bool skipDeletedParts,
int compression,
bool precisionHalf)
{
openvdb::initialize();
openvdb::io::File file(filename);
openvdb::GridPtrVec gridsVDB;
// TODO (sebbas): Use custom codec for flag attribute?
// Register codecs one, this makes sure custom attributes can be read
// registerCustomCodecs();
std::vector<ParticleDataBase *> pdbBuffer;
for (std::vector<PbClass *>::iterator iter = objects->begin(); iter != objects->end(); ++iter) {
openvdb::GridClass gClass = openvdb::GRID_UNKNOWN;
openvdb::GridBase::Ptr vdbGrid;
PbClass *object = dynamic_cast<PbClass *>(*iter);
const Real dx = object->getParent()->getDx();
const Real voxelSize = worldSize * dx;
const string objectName = object->getName();
if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
if (mantaGrid->getType() & GridBase::TypeInt) {
debMsg("Writing int grid '" << mantaGrid->getName() << "' to vdb file " << filename, 1);
Grid<int> *mantaIntGrid = (Grid<int> *)mantaGrid;
vdbGrid = exportVDB<int, openvdb::Int32Grid>(mantaIntGrid);
gridsVDB.push_back(vdbGrid);
}
else if (mantaGrid->getType() & GridBase::TypeReal) {
debMsg("Writing real grid '" << mantaGrid->getName() << "' to vdb file " << filename, 1);
gClass = (mantaGrid->getType() & GridBase::TypeLevelset) ? openvdb::GRID_LEVEL_SET :
openvdb::GRID_FOG_VOLUME;
Grid<Real> *mantaRealGrid = (Grid<Real> *)mantaGrid;
vdbGrid = exportVDB<Real, openvdb::FloatGrid>(mantaRealGrid);
gridsVDB.push_back(vdbGrid);
}
else if (mantaGrid->getType() & GridBase::TypeVec3) {
debMsg("Writing vec3 grid '" << mantaGrid->getName() << "' to vdb file " << filename, 1);
gClass = (mantaGrid->getType() & GridBase::TypeMAC) ? openvdb::GRID_STAGGERED :
openvdb::GRID_UNKNOWN;
Grid<Vec3> *mantaVec3Grid = (Grid<Vec3> *)mantaGrid;
vdbGrid = exportVDB<Vec3, openvdb::Vec3SGrid>(mantaVec3Grid);
gridsVDB.push_back(vdbGrid);
}
else {
errMsg("writeObjectsVDB: unknown grid type");
return 0;
}
}
else if (BasicParticleSystem *mantaPP = dynamic_cast<BasicParticleSystem *>(*iter)) {
debMsg("Writing particle system '" << mantaPP->getName()
<< "' (and buffered pData) to vdb file " << filename,
1);
vdbGrid = exportVDB(mantaPP, pdbBuffer, skipDeletedParts, voxelSize);
gridsVDB.push_back(vdbGrid);
pdbBuffer.clear();
}
// Particle data will only be saved if there is a particle system too.
else if (ParticleDataBase *mantaPPImpl = dynamic_cast<ParticleDataBase *>(*iter)) {
debMsg("Buffering particle data '" << mantaPPImpl->getName() << "' to vdb file " << filename,
1);
pdbBuffer.push_back(mantaPPImpl);
}
else {
errMsg("writeObjectsVDB: Unsupported Python object. Cannot write to .vdb file " << filename);
return 0;
}
// Set additional grid attributes, e.g. name, grid class, compression level, etc.
if (vdbGrid) {
setGridOptions<openvdb::GridBase>(vdbGrid, objectName, gClass, voxelSize, precisionHalf);
}
}
// Give out a warning if pData items were present but could not be saved due to missing particle
// system.
if (!pdbBuffer.empty()) {
for (ParticleDataBase *pdb : pdbBuffer) {
debMsg("writeObjectsVDB Warning: Particle data '"
<< pdb->getName()
<< "' has not been saved. It's parent particle system was needs to be given too.",
1);
}
}
// Write only if the is at least one grid, optionally write with compression.
if (gridsVDB.size()) {
int vdb_flags = openvdb::io::COMPRESS_ACTIVE_MASK;
switch (compression) {
case COMPRESSION_NONE: {
vdb_flags = openvdb::io::COMPRESS_NONE;
break;
}
case COMPRESSION_ZIP: {
vdb_flags |= openvdb::io::COMPRESS_ZIP;
break;
}
case COMPRESSION_BLOSC: {
# if OPENVDB_BLOSC == 1
vdb_flags |= openvdb::io::COMPRESS_BLOSC;
# else
debMsg("OpenVDB was built without Blosc support, using Zip compression instead", 1);
vdb_flags |= openvdb::io::COMPRESS_ZIP;
# endif // OPENVDB_BLOSC==1
break;
}
}
file.setCompression(vdb_flags);
file.write(gridsVDB);
}
file.close();
return 1;
}
int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, float worldSize)
{
openvdb::initialize();
openvdb::io::File file(filename);
openvdb::GridPtrVec gridsVDB;
// TODO (sebbas): Use custom codec for flag attribute?
// Register codecs one, this makes sure custom attributes can be read
// registerCustomCodecs();
try {
file.setCopyMaxBytes(0);
file.open();
gridsVDB = *(file.getGrids());
openvdb::MetaMap::Ptr metadata = file.getMetadata();
(void)metadata; // Unused for now
}
catch (const openvdb::IoError &e) {
debMsg("readObjectsVDB: Could not open vdb file " << filename, 1);
file.close();
return 0;
}
file.close();
// A buffer to store a handle to pData objects. These will be read alongside a particle system.
std::vector<ParticleDataBase *> pdbBuffer;
for (std::vector<PbClass *>::iterator iter = objects->begin(); iter != objects->end(); ++iter) {
if (gridsVDB.empty()) {
debMsg("readObjectsVDB: No vdb grids in file " << filename, 1);
}
// If there is just one grid in this file, load it regardless of name match (to vdb caches per
// grid).
bool onlyGrid = (gridsVDB.size() == 1);
PbClass *object = dynamic_cast<PbClass *>(*iter);
const Real dx = object->getParent()->getDx();
const Real voxelSize = worldSize * dx;
// Particle data objects are treated separately - buffered and inserted when reading the
// particle system
if (ParticleDataBase *mantaPPImpl = dynamic_cast<ParticleDataBase *>(*iter)) {
debMsg("Buffering particle data '" << mantaPPImpl->getName() << "' from vdb file "
<< filename,
1);
pdbBuffer.push_back(mantaPPImpl);
continue;
}
// For every manta object, we loop through the vdb grid list and check for a match
for (const openvdb::GridBase::Ptr vdbGrid : gridsVDB) {
bool nameMatch = (vdbGrid->getName() == (*iter)->getName());
// Sanity checks: Only load valid grids and make sure names match.
if (!vdbGrid) {
debMsg("Skipping invalid vdb grid '" << vdbGrid->getName() << "' in file " << filename, 1);
continue;
}
if (!nameMatch && !onlyGrid) {
continue;
}
if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
if (mantaGrid->getType() & GridBase::TypeInt) {
debMsg("Reading into grid '" << mantaGrid->getName() << "' from int grid '"
<< vdbGrid->getName() << "' in vdb file " << filename,
1);
openvdb::Int32Grid::Ptr vdbIntGrid = openvdb::gridPtrCast<openvdb::Int32Grid>(vdbGrid);
Grid<int> *mantaIntGrid = (Grid<int> *)mantaGrid;
importVDB<openvdb::Int32Grid, int>(vdbIntGrid, mantaIntGrid);
}
else if (mantaGrid->getType() & GridBase::TypeReal) {
debMsg("Reading into grid '" << mantaGrid->getName() << "' from real grid '"
<< vdbGrid->getName() << "' in vdb file " << filename,
1);
openvdb::FloatGrid::Ptr vdbFloatGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(vdbGrid);
Grid<Real> *mantaRealGrid = (Grid<Real> *)mantaGrid;
importVDB<openvdb::FloatGrid, Real>(vdbFloatGrid, mantaRealGrid);
}
else if (mantaGrid->getType() & GridBase::TypeVec3) {
debMsg("Reading into grid '" << mantaGrid->getName() << "' from vec3 grid '"
<< vdbGrid->getName() << "' in vdb file " << filename,
1);
openvdb::Vec3SGrid::Ptr vdbVec3Grid = openvdb::gridPtrCast<openvdb::Vec3SGrid>(vdbGrid);
Grid<Vec3> *mantaVec3Grid = (Grid<Vec3> *)mantaGrid;
importVDB<openvdb::Vec3SGrid, Vec3>(vdbVec3Grid, mantaVec3Grid);
}
else {
errMsg("readObjectsVDB: unknown grid type");
return 0;
}
}
else if (BasicParticleSystem *mantaPP = dynamic_cast<BasicParticleSystem *>(*iter)) {
debMsg("Reading into particle system '" << mantaPP->getName() << "' from particle system '"
<< vdbGrid->getName() << "' in vdb file "
<< filename,
1);
openvdb::points::PointDataGrid::Ptr vdbPointGrid =
openvdb::gridPtrCast<openvdb::points::PointDataGrid>(vdbGrid);
importVDB(vdbPointGrid, mantaPP, pdbBuffer, voxelSize);
pdbBuffer.clear();
}
else {
errMsg("readObjectsVDB: Unsupported Python object. Cannot read from .vdb file "
<< filename);
return 0;
}
}
}
// Give out a warning if pData items were present but could not be read due to missing particle
// system.
if (!pdbBuffer.empty()) {
for (ParticleDataBase *pdb : pdbBuffer) {
debMsg("readObjectsVDB Warning: Particle data '"
<< pdb->getName()
<< "' has not been read. The parent particle system needs to be given too.",
1);
}
}
return 1;
}
template void importVDB<int, int>(int vdbValue,
ParticleDataImpl<int> *to,
int index,
float voxelSize = 1.0);
template void importVDB<float, Real>(float vdbValue,
ParticleDataImpl<Real> *to,
int index,
float voxelSize = 1.0);
template void importVDB<openvdb::Vec3f, Vec3>(openvdb::Vec3s vdbValue,
ParticleDataImpl<Vec3> *to,
int index,
float voxelSize = 1.0);
void importVDB(openvdb::points::PointDataGrid::Ptr from,
BasicParticleSystem *to,
std::vector<ParticleDataBase *> &toPData,
float voxelSize = 1.0);
template void importVDB<openvdb::Int32Grid, int>(openvdb::Int32Grid::Ptr from, Grid<int> *to);
template void importVDB<openvdb::FloatGrid, Real>(openvdb::FloatGrid::Ptr from, Grid<Real> *to);
template void importVDB<openvdb::Vec3SGrid, Vec3>(openvdb::Vec3SGrid::Ptr from, Grid<Vec3> *to);
template openvdb::Int32Grid::Ptr exportVDB<int, openvdb::Int32Grid>(Grid<int> *from);
template openvdb::FloatGrid::Ptr exportVDB<Real, openvdb::FloatGrid>(Grid<Real> *from);
template openvdb::Vec3SGrid::Ptr exportVDB<Vec3, openvdb::Vec3SGrid>(Grid<Vec3> *from);
openvdb::points::PointDataGrid::Ptr exportVDB(BasicParticleSystem *from,
std::vector<ParticleDataBase *> &fromPData,
bool skipDeletedParts = false,
float voxelSize = 1.0);
template void exportVDB<int, int>(ParticleDataImpl<int> *from,
openvdb::points::PointDataGrid::Ptr to,
openvdb::tools::PointIndexGrid::Ptr pIndex,
bool skipDeletedParts = false);
template void exportVDB<Real, float>(ParticleDataImpl<Real> *from,
openvdb::points::PointDataGrid::Ptr to,
openvdb::tools::PointIndexGrid::Ptr pIndex,
bool skipDeletedParts = false);
template void exportVDB<Vec3, openvdb::Vec3s>(ParticleDataImpl<Vec3> *from,
openvdb::points::PointDataGrid::Ptr to,
openvdb::tools::PointIndexGrid::Ptr pIndex,
bool skipDeletedParts = false);
#else
int writeObjectsVDB(const string &filename,
std::vector<PbClass *> *objects,
float worldSize,
bool skipDeletedParts,
int compression,
bool precisionHalf)
{
errMsg("Cannot save to .vdb file. Mantaflow has not been built with OpenVDB support.");
return 0;
}
int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, float worldSize)
{
errMsg("Cannot load from .vdb file. Mantaflow has not been built with OpenVDB support.");
return 0;
}
#endif // OPENVDB==1
} // namespace Manta

View File

@ -0,0 +1,144 @@
// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep generate).
/******************************************************************************
*
* MantaFlow fluid solver framework
* Copyright 2020 Sebastian Barschkis, Nils Thuerey
*
* This program is free software, distributed under the terms of the
* Apache License, Version 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* General functions that make use of functions from other io files.
*
******************************************************************************/
#include "mantaio.h"
using namespace std;
namespace Manta {
int load(const string &name, std::vector<PbClass *> &objects, float worldSize = 1.0)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".raw")
return readGridsRaw(name, &objects);
else if (ext == ".uni")
return readGridsUni(name, &objects);
else if (ext == ".vol")
return readGridsVol(name, &objects);
if (ext == ".vdb")
return readObjectsVDB(name, &objects, worldSize);
else if (ext == ".npz")
return readGridsNumpy(name, &objects);
else if (ext == ".txt")
return readGridsTxt(name, &objects);
else
errMsg("file '" + name + "' filetype not supported");
return 0;
}
static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "load", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const string &name = _args.get<string>("name", 0, &_lock);
std::vector<PbClass *> &objects = *_args.getPtr<std::vector<PbClass *>>(
"objects", 1, &_lock);
float worldSize = _args.getOpt<float>("worldSize", 2, 1.0, &_lock);
_retval = toPy(load(name, objects, worldSize));
_args.check();
}
pbFinalizePlugin(parent, "load", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("load", e.what());
return 0;
}
}
static const Pb::Register _RP_load("", "load", _W_0);
extern "C" {
void PbRegister_load()
{
KEEP_UNUSED(_RP_load);
}
}
int save(const string &name,
std::vector<PbClass *> &objects,
float worldSize = 1.0,
bool skipDeletedParts = false,
int compression = COMPRESSION_ZIP,
bool precisionHalf = true)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".raw")
return writeGridsRaw(name, &objects);
else if (ext == ".uni")
return writeGridsUni(name, &objects);
else if (ext == ".vol")
return writeGridsVol(name, &objects);
if (ext == ".vdb")
return writeObjectsVDB(
name, &objects, worldSize, skipDeletedParts, compression, precisionHalf);
else if (ext == ".npz")
return writeGridsNumpy(name, &objects);
else if (ext == ".txt")
return writeGridsTxt(name, &objects);
else
errMsg("file '" + name + "' filetype not supported");
return 0;
}
static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "save", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const string &name = _args.get<string>("name", 0, &_lock);
std::vector<PbClass *> &objects = *_args.getPtr<std::vector<PbClass *>>(
"objects", 1, &_lock);
float worldSize = _args.getOpt<float>("worldSize", 2, 1.0, &_lock);
bool skipDeletedParts = _args.getOpt<bool>("skipDeletedParts", 3, false, &_lock);
int compression = _args.getOpt<int>("compression", 4, COMPRESSION_ZIP, &_lock);
bool precisionHalf = _args.getOpt<bool>("precisionHalf", 5, true, &_lock);
_retval = toPy(save(name, objects, worldSize, skipDeletedParts, compression, precisionHalf));
_args.check();
}
pbFinalizePlugin(parent, "save", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("save", e.what());
return 0;
}
}
static const Pb::Register _RP_save("", "save", _W_1);
extern "C" {
void PbRegister_save()
{
KEEP_UNUSED(_RP_save);
}
}
} // namespace Manta

View File

@ -21,62 +21,98 @@
#include <string>
#include "manta.h"
// OpenVDB compression flags
#define COMPRESSION_NONE 0
#define COMPRESSION_ZIP 1
#define COMPRESSION_BLOSC 2
namespace Manta {
// forward decl.
// Forward declations
class Mesh;
class FlagGrid;
class GridBase;
template<class T> class Grid;
template<class T> class Grid4d;
class BasicParticleSystem;
template<class T> class ParticleDataImpl;
template<class T> class MeshDataImpl;
void writeObjFile(const std::string &name, Mesh *mesh);
void writeBobjFile(const std::string &name, Mesh *mesh);
void readObjFile(const std::string &name, Mesh *mesh, bool append);
void readBobjFile(const std::string &name, Mesh *mesh, bool append);
// Obj format
int writeObjFile(const std::string &name, Mesh *mesh);
int writeBobjFile(const std::string &name, Mesh *mesh);
int readObjFile(const std::string &name, Mesh *mesh, bool append);
int readBobjFile(const std::string &name, Mesh *mesh, bool append);
template<class T> void writeGridRaw(const std::string &name, Grid<T> *grid);
template<class T> void writeGridUni(const std::string &name, Grid<T> *grid);
template<class T> void writeGridVol(const std::string &name, Grid<T> *grid);
template<class T> void writeGridTxt(const std::string &name, Grid<T> *grid);
// Other formats (Raw, Uni, Vol)
template<class T> int readGridUni(const std::string &name, Grid<T> *grid);
template<class T> int readGridRaw(const std::string &name, Grid<T> *grid);
template<class T> int readGridVol(const std::string &name, Grid<T> *grid);
int readGridsRaw(const std::string &name, std::vector<PbClass *> *grids);
int readGridsUni(const std::string &name, std::vector<PbClass *> *grids);
int readGridsVol(const std::string &name, std::vector<PbClass *> *grids);
int readGridsTxt(const std::string &name, std::vector<PbClass *> *grids);
#if OPENVDB == 1
template<class T> void writeGridVDB(const std::string &name, Grid<T> *grid);
template<class T> void readGridVDB(const std::string &name, Grid<T> *grid);
#endif // OPENVDB==1
template<class T> void writeGridNumpy(const std::string &name, Grid<T> *grid);
template<class T> void readGridNumpy(const std::string &name, Grid<T> *grid);
template<class T> int writeGridRaw(const std::string &name, Grid<T> *grid);
template<class T> int writeGridUni(const std::string &name, Grid<T> *grid);
template<class T> int writeGridVol(const std::string &name, Grid<T> *grid);
template<class T> int writeGridTxt(const std::string &name, Grid<T> *grid);
int writeGridsRaw(const std::string &name, std::vector<PbClass *> *grids);
int writeGridsUni(const std::string &name, std::vector<PbClass *> *grids);
int writeGridsVol(const std::string &name, std::vector<PbClass *> *grids);
int writeGridsTxt(const std::string &name, std::vector<PbClass *> *grids);
template<class T> void readGridUni(const std::string &name, Grid<T> *grid);
template<class T> void readGridRaw(const std::string &name, Grid<T> *grid);
template<class T> void readGridVol(const std::string &name, Grid<T> *grid);
// OpenVDB
int writeObjectsVDB(const std::string &filename,
std::vector<PbClass *> *objects,
float scale = 1.0,
bool skipDeletedParts = false,
int compression = COMPRESSION_ZIP,
bool precisionHalf = true);
int readObjectsVDB(const std::string &filename,
std::vector<PbClass *> *objects,
float scale = 1.0);
template<class T> void writeGrid4dUni(const std::string &name, Grid4d<T> *grid);
// Numpy
template<class T> int writeGridNumpy(const std::string &name, Grid<T> *grid);
template<class T> int readGridNumpy(const std::string &name, Grid<T> *grid);
int writeGridsNumpy(const std::string &name, std::vector<PbClass *> *grids);
int readGridsNumpy(const std::string &name, std::vector<PbClass *> *grids);
// 4D Grids
template<class T> int writeGrid4dUni(const std::string &name, Grid4d<T> *grid);
template<class T>
void readGrid4dUni(const std::string &name,
Grid4d<T> *grid,
int readTslice = -1,
Grid4d<T> *slice = NULL,
void **fileHandle = NULL);
int readGrid4dUni(const std::string &name,
Grid4d<T> *grid,
int readTslice = -1,
Grid4d<T> *slice = NULL,
void **fileHandle = NULL);
void readGrid4dUniCleanup(void **fileHandle);
template<class T> void writeGrid4dRaw(const std::string &name, Grid4d<T> *grid);
template<class T> void readGrid4dRaw(const std::string &name, Grid4d<T> *grid);
template<class T> int writeGrid4dRaw(const std::string &name, Grid4d<T> *grid);
template<class T> int readGrid4dRaw(const std::string &name, Grid4d<T> *grid);
void writeParticlesUni(const std::string &name, const BasicParticleSystem *parts);
void readParticlesUni(const std::string &name, BasicParticleSystem *parts);
// Particles + particle data
int writeParticlesUni(const std::string &name, const BasicParticleSystem *parts);
int readParticlesUni(const std::string &name, BasicParticleSystem *parts);
template<class T> void writePdataUni(const std::string &name, ParticleDataImpl<T> *pdata);
template<class T> void readPdataUni(const std::string &name, ParticleDataImpl<T> *pdata);
template<class T> int writePdataUni(const std::string &name, ParticleDataImpl<T> *pdata);
template<class T> int readPdataUni(const std::string &name, ParticleDataImpl<T> *pdata);
template<class T> void writeMdataUni(const std::string &name, MeshDataImpl<T> *mdata);
template<class T> void readMdataUni(const std::string &name, MeshDataImpl<T> *mdata);
// Mesh data
template<class T> int writeMdataUni(const std::string &name, MeshDataImpl<T> *mdata);
template<class T> int readMdataUni(const std::string &name, MeshDataImpl<T> *mdata);
// Helpers
void getUniFileSize(
const std::string &name, int &x, int &y, int &z, int *t = NULL, std::string *info = NULL);
void *safeGzopen(const char *filename, const char *mode);
#if OPENVDB == 1
template<class S, class T> void convertFrom(S &in, T *out);
template<class S, class T> void convertTo(S *out, T &in);
#endif
} // namespace Manta

View File

@ -1,3 +1,3 @@
#define MANTA_GIT_VERSION "commit b61bf9efa7a1d8ca98635076a7e9f2c4dacb2914"
#define MANTA_GIT_VERSION "commit 2c83bddc59cd5140e5dd91b172167a7cba9d4960"

View File

@ -122,48 +122,52 @@ template<class T> void Grid<T>::swap(Grid<T> &other)
mData = dswap;
}
template<class T> void Grid<T>::load(string name)
template<class T> int Grid<T>::load(string name)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".raw")
readGridRaw(name, this);
return readGridRaw(name, this);
else if (ext == ".uni")
readGridUni(name, this);
return readGridUni(name, this);
else if (ext == ".vol")
readGridVol(name, this);
return readGridVol(name, this);
else if (ext == ".npz")
readGridNumpy(name, this);
#if OPENVDB == 1
else if (ext == ".vdb")
readGridVDB(name, this);
#endif // OPENVDB==1
return readGridNumpy(name, this);
else if (ext == ".vdb") {
std::vector<PbClass *> grids;
grids.push_back(this);
return readObjectsVDB(name, &grids);
}
else
errMsg("file '" + name + "' filetype not supported");
return 0;
}
template<class T> void Grid<T>::save(string name)
template<class T> int Grid<T>::save(string name)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".raw")
writeGridRaw(name, this);
return writeGridRaw(name, this);
else if (ext == ".uni")
writeGridUni(name, this);
return writeGridUni(name, this);
else if (ext == ".vol")
writeGridVol(name, this);
#if OPENVDB == 1
else if (ext == ".vdb")
writeGridVDB(name, this);
#endif // OPENVDB==1
return writeGridVol(name, this);
else if (ext == ".npz")
writeGridNumpy(name, this);
return writeGridNumpy(name, this);
else if (ext == ".vdb") {
std::vector<PbClass *> grids;
grids.push_back(this);
return writeObjectsVDB(name, &grids);
}
else if (ext == ".txt")
writeGridTxt(name, this);
return writeGridTxt(name, this);
else
errMsg("file '" + name + "' filetype not supported");
return 0;
}
//******************************************************************************

View File

@ -409,7 +409,7 @@ template<class T> class Grid : public GridBase {
typedef T BASETYPE;
typedef GridBase BASETYPE_GRID;
void save(std::string name);
int save(std::string name);
static PyObject *_W_10(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
@ -422,8 +422,7 @@ template<class T> class Grid : public GridBase {
ArgLocker _lock;
std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->save(name);
_retval = toPy(pbo->save(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "Grid::save", !noTiming);
@ -435,7 +434,7 @@ template<class T> class Grid : public GridBase {
}
}
void load(std::string name);
int load(std::string name);
static PyObject *_W_11(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
@ -448,8 +447,7 @@ template<class T> class Grid : public GridBase {
ArgLocker _lock;
std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->load(name);
_retval = toPy(pbo->load(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "Grid::load", !noTiming);
@ -554,6 +552,12 @@ template<class T> class Grid : public GridBase {
return mData[idx];
}
//! set data
inline void set(int i, int j, int k, T &val)
{
mData[index(i, j, k)] = val;
}
// interpolated access
inline T getInterpolated(const Vec3 &pos) const
{

View File

@ -121,30 +121,32 @@ template<class T> void Grid4d<T>::swap(Grid4d<T> &other)
mData = dswap;
}
template<class T> void Grid4d<T>::load(string name)
template<class T> int Grid4d<T>::load(string name)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".uni")
readGrid4dUni(name, this);
return readGrid4dUni(name, this);
else if (ext == ".raw")
readGrid4dRaw(name, this);
return readGrid4dRaw(name, this);
else
errMsg("file '" + name + "' filetype not supported");
return 0;
}
template<class T> void Grid4d<T>::save(string name)
template<class T> int Grid4d<T>::save(string name)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".uni")
writeGrid4dUni(name, this);
return writeGrid4dUni(name, this);
else if (ext == ".raw")
writeGrid4dRaw(name, this);
return writeGrid4dRaw(name, this);
else
errMsg("file '" + name + "' filetype not supported");
return 0;
}
//******************************************************************************

View File

@ -372,7 +372,7 @@ template<class T> class Grid4d : public Grid4dBase {
typedef T BASETYPE;
typedef Grid4dBase BASETYPE_GRID;
void save(std::string name);
int save(std::string name);
static PyObject *_W_9(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
@ -385,8 +385,7 @@ template<class T> class Grid4d : public Grid4dBase {
ArgLocker _lock;
std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->save(name);
_retval = toPy(pbo->save(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "Grid4d::save", !noTiming);
@ -398,7 +397,7 @@ template<class T> class Grid4d : public Grid4dBase {
}
}
void load(std::string name);
int load(std::string name);
static PyObject *_W_10(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
@ -411,8 +410,7 @@ template<class T> class Grid4d : public Grid4dBase {
ArgLocker _lock;
std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->load(name);
_retval = toPy(pbo->load(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "Grid4d::load", !noTiming);

View File

@ -214,20 +214,26 @@ void BasicParticleSystem::writeParticlesRawVelocityGz(const string name) const
#endif
}
void BasicParticleSystem::load(const string name)
int BasicParticleSystem::load(const string name)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".uni")
readParticlesUni(name, this);
return readParticlesUni(name, this);
else if (ext == ".vdb") {
std::vector<PbClass *> parts;
parts.push_back(this);
return readObjectsVDB(name, &parts);
}
else if (ext == ".raw") // raw = uni for now
readParticlesUni(name, this);
return readParticlesUni(name, this);
else
errMsg("particle '" + name + "' filetype not supported for loading");
return 0;
}
void BasicParticleSystem::save(const string name) const
int BasicParticleSystem::save(const string name)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
@ -235,16 +241,22 @@ void BasicParticleSystem::save(const string name) const
if (ext == ".txt")
this->writeParticlesText(name);
else if (ext == ".uni")
writeParticlesUni(name, this);
return writeParticlesUni(name, this);
else if (ext == ".raw") // raw = uni for now
writeParticlesUni(name, this);
// raw data formats, very basic for simple data transfer to other programs
return writeParticlesUni(name, this);
else if (ext == ".vdb") {
std::vector<PbClass *> parts;
parts.push_back(this);
return writeObjectsVDB(name, &parts);
// raw data formats, very basic for simple data transfer to other programs
}
else if (ext == ".posgz")
this->writeParticlesRawPositionsGz(name);
else if (ext == ".velgz")
this->writeParticlesRawVelocityGz(name);
else
errMsg("particle '" + name + "' filetype not supported for saving");
return 0;
}
void BasicParticleSystem::printParts(IndexInt start, IndexInt stop, bool printIndex)
@ -372,30 +384,42 @@ template<> void ParticleDataImpl<Vec3>::initNewValue(IndexInt idx, Vec3 pos)
}
}
template<typename T> void ParticleDataImpl<T>::load(string name)
template<typename T> int ParticleDataImpl<T>::load(string name)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".uni")
readPdataUni<T>(name, this);
return readPdataUni<T>(name, this);
else if (ext == ".vdb") {
std::vector<PbClass *> parts;
parts.push_back(this);
return readObjectsVDB(name, &parts);
}
else if (ext == ".raw") // raw = uni for now
readPdataUni<T>(name, this);
return readPdataUni<T>(name, this);
else
errMsg("particle data '" + name + "' filetype not supported for loading");
return 0;
}
template<typename T> void ParticleDataImpl<T>::save(string name)
template<typename T> int ParticleDataImpl<T>::save(string name)
{
if (name.find_last_of('.') == string::npos)
errMsg("file '" + name + "' does not have an extension");
string ext = name.substr(name.find_last_of('.'));
if (ext == ".uni")
writePdataUni<T>(name, this);
return writePdataUni<T>(name, this);
else if (ext == ".vdb") {
std::vector<PbClass *> parts;
parts.push_back(this);
return writeObjectsVDB(name, &parts);
}
else if (ext == ".raw") // raw = uni for now
writePdataUni<T>(name, this);
return writePdataUni<T>(name, this);
else
errMsg("particle data '" + name + "' filetype not supported for saving");
return 0;
}
// specializations

View File

@ -646,7 +646,7 @@ class BasicParticleSystem : public ParticleSystem<BasicParticleData> {
}
//! file io
void save(const std::string name) const;
int save(const std::string name);
static PyObject *_W_13(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
@ -659,8 +659,7 @@ class BasicParticleSystem : public ParticleSystem<BasicParticleData> {
ArgLocker _lock;
const std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->save(name);
_retval = toPy(pbo->save(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::save", !noTiming);
@ -672,7 +671,7 @@ class BasicParticleSystem : public ParticleSystem<BasicParticleData> {
}
}
void load(const std::string name);
int load(const std::string name);
static PyObject *_W_14(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
@ -685,8 +684,7 @@ class BasicParticleSystem : public ParticleSystem<BasicParticleData> {
ArgLocker _lock;
const std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->load(name);
_retval = toPy(pbo->load(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "BasicParticleSystem::load", !noTiming);
@ -1022,11 +1020,15 @@ class ParticleDataBase : public PbClass {
return;
}
//! set base pointer
//! set / get base pointer to parent particle system
void setParticleSys(ParticleBase *set)
{
mpParticleSys = set;
}
ParticleBase *getParticleSys()
{
return mpParticleSys;
}
//! debugging
inline void checkPartIndex(IndexInt idx) const;
@ -1094,6 +1096,13 @@ template<class T> class ParticleDataImpl : public ParticleDataBase {
return mData[idx];
}
//! set data
inline void set(const IndexInt idx, T &val)
{
DEBUG_ONLY(checkPartIndex(idx));
mData[idx] = val;
}
//! set all values to 0, note - different from particleSystem::clear! doesnt modify size of array
//! (has to stay in sync with parent system)
void clear();
@ -1716,7 +1725,7 @@ template<class T> class ParticleDataImpl : public ParticleDataBase {
}
//! file io
void save(const std::string name);
int save(const std::string name);
static PyObject *_W_46(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
@ -1729,8 +1738,7 @@ template<class T> class ParticleDataImpl : public ParticleDataBase {
ArgLocker _lock;
const std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->save(name);
_retval = toPy(pbo->save(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::save", !noTiming);
@ -1742,7 +1750,7 @@ template<class T> class ParticleDataImpl : public ParticleDataBase {
}
}
void load(const std::string name);
int load(const std::string name);
static PyObject *_W_47(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
@ -1755,8 +1763,7 @@ template<class T> class ParticleDataImpl : public ParticleDataBase {
ArgLocker _lock;
const std::string name = _args.get<std::string>("name", 0, &_lock);
pbo->_args.copy(_args);
_retval = getPyNone();
pbo->load(name);
_retval = toPy(pbo->load(name));
pbo->_args.check();
}
pbFinalizePlugin(pbo->getParent(), "ParticleDataImpl::load", !noTiming);

View File

@ -15,7 +15,8 @@ static const Pb::Register _reg(
"4\nTypeInflow = 8\nTypeOutflow = 16\nTypeStick = 64\nTypeReserved = 256\n\n# "
"integration mode\nIntEuler = 0\nIntRK2 = 1\nIntRK4 = 2\n\n# CG preconditioner\nPcNone "
" = 0\nPcMIC = 1\nPcMGDynamic = 2\nPcMGStatic = 3\n\n# particles\nPtypeSpray = "
"2\nPtypeBubble = 4\nPtypeFoam = 8\nPtypeTracer = 16\n\n\n\n\n");
"2\nPtypeBubble = 4\nPtypeFoam = 8\nPtypeTracer = 16\n\n# OpenVDB export "
"flags\nCompression_None = 0\nCompression_Zip = 1\nCompression_Blosc = 2\n\n\n\n\n");
extern "C" {
void PbRegister_file_0()
{

View File

@ -45,6 +45,8 @@ extern void PbRegister_printUniFileInfoString();
extern void PbRegister_getNpzFileSize();
extern void PbRegister_quantizeGrid();
extern void PbRegister_quantizeGridVec3();
extern void PbRegister_load();
extern void PbRegister_save();
extern void PbRegister_resetPhiInObs();
extern void PbRegister_advectSemiLagrange();
extern void PbRegister_addGravity();
@ -238,6 +240,8 @@ void MantaEnsureRegistration()
PbRegister_getNpzFileSize();
PbRegister_quantizeGrid();
PbRegister_quantizeGridVec3();
PbRegister_load();
PbRegister_save();
PbRegister_resetPhiInObs();
PbRegister_advectSemiLagrange();
PbRegister_addGravity();