Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,523 @@
// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep generate).
/******************************************************************************
*
* MantaFlow fluid solver framework
* Copyright 2011-2016 Tobias Pfaff, 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 meshes to disk
*
******************************************************************************/
#include <iostream>
#include <fstream>
#include <cstdlib>
#if NO_ZLIB != 1
extern "C" {
# include <zlib.h>
}
#endif
#include "mantaio.h"
#include "grid.h"
#include "mesh.h"
#include "vortexsheet.h"
#include <cstring>
using namespace std;
namespace Manta {
static const int STR_LEN_PDATA = 256;
//! mdata uni header, v3 (similar to grid header and mdata header)
typedef struct {
int dim; // number of vertices
int dimX, dimY, dimZ; // underlying solver resolution (all data in local coordinates!)
int elementType, bytesPerElement; // type id and byte size
char info[STR_LEN_PDATA]; // mantaflow build information
unsigned long long timestamp; // creation time
} UniMeshHeader;
//*****************************************************************************
// conversion functions for double precision
// (note - uni files always store single prec. values)
//*****************************************************************************
#if NO_ZLIB != 1
template<class T>
void mdataConvertWrite(gzFile &gzf, MeshDataImpl<T> &mdata, void *ptr, UniMeshHeader &head)
{
errMsg("mdataConvertWrite: unknown type, not yet supported");
}
template<>
void mdataConvertWrite(gzFile &gzf, MeshDataImpl<int> &mdata, void *ptr, UniMeshHeader &head)
{
gzwrite(gzf, &head, sizeof(UniMeshHeader));
gzwrite(gzf, &mdata[0], sizeof(int) * head.dim);
}
template<>
void mdataConvertWrite(gzFile &gzf, MeshDataImpl<double> &mdata, void *ptr, UniMeshHeader &head)
{
head.bytesPerElement = sizeof(float);
gzwrite(gzf, &head, sizeof(UniMeshHeader));
float *ptrf = (float *)ptr;
for (int i = 0; i < mdata.size(); ++i, ++ptrf) {
*ptrf = (float)mdata[i];
}
gzwrite(gzf, ptr, sizeof(float) * head.dim);
}
template<>
void mdataConvertWrite(gzFile &gzf, MeshDataImpl<Vec3> &mdata, void *ptr, UniMeshHeader &head)
{
head.bytesPerElement = sizeof(Vector3D<float>);
gzwrite(gzf, &head, sizeof(UniMeshHeader));
float *ptrf = (float *)ptr;
for (int i = 0; i < mdata.size(); ++i) {
for (int c = 0; c < 3; ++c) {
*ptrf = (float)mdata[i][c];
ptrf++;
}
}
gzwrite(gzf, ptr, sizeof(Vector3D<float>) * head.dim);
}
template<class T>
void mdataReadConvert(gzFile &gzf, MeshDataImpl<T> &grid, void *ptr, int bytesPerElement)
{
errMsg("mdataReadConvert: unknown mdata type, not yet supported");
}
template<>
void mdataReadConvert<int>(gzFile &gzf, MeshDataImpl<int> &mdata, void *ptr, int bytesPerElement)
{
gzread(gzf, ptr, sizeof(int) * mdata.size());
assertMsg(bytesPerElement == sizeof(int),
"mdata element size doesn't match " << bytesPerElement << " vs " << sizeof(int));
// int dont change in double precision mode - copy over
memcpy(&(mdata[0]), ptr, sizeof(int) * mdata.size());
}
template<>
void mdataReadConvert<double>(gzFile &gzf,
MeshDataImpl<double> &mdata,
void *ptr,
int bytesPerElement)
{
gzread(gzf, ptr, sizeof(float) * mdata.size());
assertMsg(bytesPerElement == sizeof(float),
"mdata element size doesn't match " << bytesPerElement << " vs " << sizeof(float));
float *ptrf = (float *)ptr;
for (int i = 0; i < mdata.size(); ++i, ++ptrf) {
mdata[i] = double(*ptrf);
}
}
template<>
void mdataReadConvert<Vec3>(gzFile &gzf, MeshDataImpl<Vec3> &mdata, void *ptr, int bytesPerElement)
{
gzread(gzf, ptr, sizeof(Vector3D<float>) * mdata.size());
assertMsg(bytesPerElement == sizeof(Vector3D<float>),
"mdata element size doesn't match " << bytesPerElement << " vs "
<< sizeof(Vector3D<float>));
float *ptrf = (float *)ptr;
for (int i = 0; i < mdata.size(); ++i) {
Vec3 v;
for (int c = 0; c < 3; ++c) {
v[c] = double(*ptrf);
ptrf++;
}
mdata[i] = v;
}
}
#endif // NO_ZLIB!=1
//*****************************************************************************
// mesh data
//*****************************************************************************
int readBobjFile(const string &name, Mesh *mesh, bool append)
{
debMsg("reading mesh file " << name, 1);
if (!append)
mesh->clear();
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) {
errMsg("readBobj: unable to open file");
return 0;
}
// read vertices
int num = 0;
gzread(gzf, &num, sizeof(int));
mesh->resizeNodes(num);
debMsg("read mesh , verts " << num, 1);
for (int i = 0; i < num; i++) {
Vector3D<float> pos;
gzread(gzf, &pos.value[0], sizeof(float) * 3);
mesh->nodes(i).pos = toVec3(pos);
// convert to grid space
mesh->nodes(i).pos /= dx;
mesh->nodes(i).pos += gs * 0.5;
}
// normals
num = 0;
gzread(gzf, &num, sizeof(int));
for (int i = 0; i < num; i++) {
Vector3D<float> pos;
gzread(gzf, &pos.value[0], sizeof(float) * 3);
mesh->nodes(i).normal = toVec3(pos);
}
// read tris
num = 0;
gzread(gzf, &num, sizeof(int));
mesh->resizeTris(num);
for (int t = 0; t < num; t++) {
for (int j = 0; j < 3; j++) {
int trip = 0;
gzread(gzf, &trip, sizeof(int));
mesh->tris(t).c[j] = trip;
}
}
// note - vortex sheet info ignored for now... (see writeBobj)
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
}
int writeBobjFile(const string &name, Mesh *mesh)
{
debMsg("writing mesh file " << name, 1);
#if NO_ZLIB != 1
const Real dx = mesh->getParent()->getDx();
const Vec3i gs = mesh->getParent()->getGridSize();
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf) {
errMsg("writeBobj: unable to open file");
return 0;
}
// write vertices
int numVerts = mesh->numNodes();
gzwrite(gzf, &numVerts, sizeof(int));
for (int i = 0; i < numVerts; i++) {
Vector3D<float> pos = toVec3f(mesh->nodes(i).pos);
// normalize to unit cube around 0
pos -= toVec3f(gs) * 0.5;
pos *= dx;
gzwrite(gzf, &pos.value[0], sizeof(float) * 3);
}
// normals
mesh->computeVertexNormals();
gzwrite(gzf, &numVerts, sizeof(int));
for (int i = 0; i < numVerts; i++) {
Vector3D<float> pos = toVec3f(mesh->nodes(i).normal);
gzwrite(gzf, &pos.value[0], sizeof(float) * 3);
}
// write tris
int numTris = mesh->numTris();
gzwrite(gzf, &numTris, sizeof(int));
for (int t = 0; t < numTris; t++) {
for (int j = 0; j < 3; j++) {
int trip = mesh->tris(t).c[j];
gzwrite(gzf, &trip, sizeof(int));
}
}
// per vertex smoke densities
if (mesh->getType() == Mesh::TypeVortexSheet) {
VortexSheetMesh *vmesh = (VortexSheetMesh *)mesh;
int densId[4] = {0, 'v', 'd', 'e'};
gzwrite(gzf, &densId[0], sizeof(int) * 4);
// compute densities
vector<float> triDensity(numTris);
for (int tri = 0; tri < numTris; tri++) {
Real area = vmesh->getFaceArea(tri);
if (area > 0)
triDensity[tri] = vmesh->sheet(tri).smokeAmount;
}
// project triangle data to vertex
vector<int> triPerVertex(numVerts);
vector<float> density(numVerts);
for (int tri = 0; tri < numTris; tri++) {
for (int c = 0; c < 3; c++) {
int vertex = mesh->tris(tri).c[c];
density[vertex] += triDensity[tri];
triPerVertex[vertex]++;
}
}
// averaged smoke densities
for (int point = 0; point < numVerts; point++) {
float dens = 0;
if (triPerVertex[point] > 0)
dens = density[point] / triPerVertex[point];
gzwrite(gzf, &dens, sizeof(float));
}
}
// vertex flags
if (mesh->getType() == Mesh::TypeVortexSheet) {
int Id[4] = {0, 'v', 'x', 'f'};
gzwrite(gzf, &Id[0], sizeof(int) * 4);
// averaged smoke densities
for (int point = 0; point < numVerts; point++) {
float alpha = (mesh->nodes(point).flags & Mesh::NfMarked) ? 1 : 0;
gzwrite(gzf, &alpha, sizeof(float));
}
}
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
int readObjFile(const std::string &name, Mesh *mesh, bool append)
{
ifstream ifs(name.c_str());
if (!ifs.good()) {
errMsg("can't open file '" + name + "'");
return 0;
}
const Real dx = mesh->getParent()->getDx();
const Vec3 gs = toVec3(mesh->getParent()->getGridSize());
if (!append)
mesh->clear();
int nodebase = mesh->numNodes();
int cntNodes = nodebase, cntNormals = nodebase;
while (ifs.good() && !ifs.eof()) {
string id;
ifs >> id;
if (id[0] == '#') {
// comment
getline(ifs, id);
continue;
}
if (id == "vt") {
// tex coord, ignore
}
else if (id == "vn") {
// normals
if (mesh->numNodes() != cntNodes) {
errMsg("invalid amount of nodes");
return 0;
}
Node *n = &mesh->nodes(cntNormals);
ifs >> n->normal.x >> n->normal.y >> n->normal.z;
cntNormals++;
}
else if (id == "v") {
// vertex
Node n;
ifs >> n.pos.x >> n.pos.y >> n.pos.z;
// convert to grid space
n.pos /= dx;
n.pos += gs * 0.5;
mesh->addNode(n);
cntNodes++;
}
else if (id == "g") {
// group
string group;
ifs >> group;
}
else if (id == "f") {
// face
string face;
Triangle t;
for (int i = 0; i < 3; i++) {
ifs >> face;
if (face.find('/') != string::npos)
face = face.substr(0, face.find('/')); // ignore other indices
int idx = atoi(face.c_str()) - 1;
if (idx < 0) {
errMsg("invalid face encountered");
return 0;
}
idx += nodebase;
t.c[i] = idx;
}
mesh->addTri(t);
}
else {
// whatever, ignore
}
// kill rest of line
getline(ifs, id);
}
ifs.close();
return 1;
}
// write regular .obj file, in line with bobj.gz output (but only verts & tris for now)
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()) {
errMsg("writeObjFile: can't open file " << name);
return 0;
}
ofs << "o MantaMesh\n";
// write vertices
int numVerts = mesh->numNodes();
for (int i = 0; i < numVerts; i++) {
Vector3D<float> pos = toVec3f(mesh->nodes(i).pos);
// normalize to unit cube around 0
pos -= toVec3f(gs) * 0.5;
pos *= dx;
ofs << "v " << pos.value[0] << " " << pos.value[1] << " " << pos.value[2] << " "
<< "\n";
}
// write normals
for (int i = 0; i < numVerts; i++) {
Vector3D<float> n = toVec3f(mesh->nodes(i).normal);
ofs << "vn " << n.value[0] << " " << n.value[1] << " " << n.value[2] << " "
<< "\n";
}
// write tris
int numTris = mesh->numTris();
for (int t = 0; t < numTris; t++) {
ofs << "f " << (mesh->tris(t).c[0] + 1) << " " << (mesh->tris(t).c[1] + 1) << " "
<< (mesh->tris(t).c[2] + 1) << " "
<< "\n";
}
ofs.close();
return 1;
}
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) {
errMsg("can't open file " << name);
return 0;
}
char ID[5] = {0, 0, 0, 0, 0};
gzread(gzf, ID, 4);
if (!strcmp(ID, "MD01")) {
UniMeshHeader head;
assertMsg(gzread(gzf, &head, sizeof(UniMeshHeader)) == sizeof(UniMeshHeader),
"can't read file, no header present");
mdata->resize(head.dim);
assertMsg(head.dim == mdata->size(), "mdata size doesn't match");
# if FLOATINGPOINT_PRECISION != 1
MeshDataImpl<T> temp(mdata->getParent());
temp.resize(mdata->size());
mdataReadConvert<T>(gzf, *mdata, &(temp[0]), head.bytesPerElement);
# else
assertMsg(((head.bytesPerElement == sizeof(T)) && (head.elementType == 1)),
"mdata type doesn't match");
IndexInt bytes = sizeof(T) * head.dim;
IndexInt readBytes = gzread(gzf, &(mdata->get(0)), sizeof(T) * head.dim);
assertMsg(bytes == readBytes,
"can't read uni file, stream length does not match, " << bytes << " vs "
<< readBytes);
# endif
}
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
template<class T> int writeMdataUni(const std::string &name, MeshDataImpl<T> *mdata)
{
debMsg("writing mesh data " << mdata->getName() << " to uni file " << name, 1);
#if NO_ZLIB != 1
char ID[5] = "MD01";
UniMeshHeader head;
head.dim = mdata->size();
head.bytesPerElement = sizeof(T);
head.elementType = 1; // 1 for mesh data, todo - add sub types?
snprintf(head.info, STR_LEN_PDATA, "%s", buildInfoString().c_str());
MuTime stamp;
head.timestamp = stamp.time;
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
gzwrite(gzf, ID, 4);
# if FLOATINGPOINT_PRECISION != 1
// always write float values, even if compiled with double precision (as for grids)
MeshDataImpl<T> temp(mdata->getParent());
temp.resize(mdata->size());
mdataConvertWrite(gzf, *mdata, &(temp[0]), head);
# else
gzwrite(gzf, &head, sizeof(UniMeshHeader));
gzwrite(gzf, &(mdata->get(0)), sizeof(T) * head.dim);
# endif
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
// explicit instantiation
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

@@ -0,0 +1,384 @@
// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep generate).
/******************************************************************************
*
* MantaFlow fluid solver framework
* Copyright 2011-2016 Tobias Pfaff, 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 meshes to disk
*
******************************************************************************/
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#if NO_ZLIB != 1
extern "C" {
# include <zlib.h>
}
#endif
#include "mantaio.h"
#include "grid.h"
#include "particle.h"
#include "vector4d.h"
#include "grid4d.h"
using namespace std;
namespace Manta {
static const int STR_LEN_PDATA = 256;
//! pdata uni header, v3 (similar to grid header)
typedef struct {
int dim; // number of partilces
int dimX, dimY, dimZ; // underlying solver resolution (all data in local coordinates!)
int elementType, bytesPerElement; // type id and byte size
char info[STR_LEN_PDATA]; // mantaflow build information
unsigned long long timestamp; // creation time
} UniPartHeader;
//*****************************************************************************
// conversion functions for double precision
// (note - uni files always store single prec. values)
//*****************************************************************************
#if NO_ZLIB != 1
template<class T>
void pdataConvertWrite(gzFile &gzf, ParticleDataImpl<T> &pdata, void *ptr, UniPartHeader &head)
{
errMsg("pdataConvertWrite: unknown type, not yet supported");
}
template<>
void pdataConvertWrite(gzFile &gzf, ParticleDataImpl<int> &pdata, void *ptr, UniPartHeader &head)
{
gzwrite(gzf, &head, sizeof(UniPartHeader));
gzwrite(gzf, &pdata[0], sizeof(int) * head.dim);
}
template<>
void pdataConvertWrite(gzFile &gzf,
ParticleDataImpl<double> &pdata,
void *ptr,
UniPartHeader &head)
{
head.bytesPerElement = sizeof(float);
gzwrite(gzf, &head, sizeof(UniPartHeader));
float *ptrf = (float *)ptr;
for (int i = 0; i < pdata.size(); ++i, ++ptrf) {
*ptrf = (float)pdata[i];
}
gzwrite(gzf, ptr, sizeof(float) * head.dim);
}
template<>
void pdataConvertWrite(gzFile &gzf, ParticleDataImpl<Vec3> &pdata, void *ptr, UniPartHeader &head)
{
head.bytesPerElement = sizeof(Vector3D<float>);
gzwrite(gzf, &head, sizeof(UniPartHeader));
float *ptrf = (float *)ptr;
for (int i = 0; i < pdata.size(); ++i) {
for (int c = 0; c < 3; ++c) {
*ptrf = (float)pdata[i][c];
ptrf++;
}
}
gzwrite(gzf, ptr, sizeof(Vector3D<float>) * head.dim);
}
template<class T>
void pdataReadConvert(gzFile &gzf, ParticleDataImpl<T> &grid, void *ptr, int bytesPerElement)
{
errMsg("pdataReadConvert: unknown pdata type, not yet supported");
}
template<>
void pdataReadConvert<int>(gzFile &gzf,
ParticleDataImpl<int> &pdata,
void *ptr,
int bytesPerElement)
{
gzread(gzf, ptr, sizeof(int) * pdata.size());
assertMsg(bytesPerElement == sizeof(int),
"pdata element size doesn't match " << bytesPerElement << " vs " << sizeof(int));
// int dont change in double precision mode - copy over
memcpy(&(pdata[0]), ptr, sizeof(int) * pdata.size());
}
template<>
void pdataReadConvert<double>(gzFile &gzf,
ParticleDataImpl<double> &pdata,
void *ptr,
int bytesPerElement)
{
gzread(gzf, ptr, sizeof(float) * pdata.size());
assertMsg(bytesPerElement == sizeof(float),
"pdata element size doesn't match " << bytesPerElement << " vs " << sizeof(float));
float *ptrf = (float *)ptr;
for (int i = 0; i < pdata.size(); ++i, ++ptrf) {
pdata[i] = double(*ptrf);
}
}
template<>
void pdataReadConvert<Vec3>(gzFile &gzf,
ParticleDataImpl<Vec3> &pdata,
void *ptr,
int bytesPerElement)
{
gzread(gzf, ptr, sizeof(Vector3D<float>) * pdata.size());
assertMsg(bytesPerElement == sizeof(Vector3D<float>),
"pdata element size doesn't match " << bytesPerElement << " vs "
<< sizeof(Vector3D<float>));
float *ptrf = (float *)ptr;
for (int i = 0; i < pdata.size(); ++i) {
Vec3 v;
for (int c = 0; c < 3; ++c) {
v[c] = double(*ptrf);
ptrf++;
}
pdata[i] = v;
}
}
#endif // NO_ZLIB!=1
//*****************************************************************************
// particles and particle data
//*****************************************************************************
static const int PartSysSize = sizeof(Vector3D<float>) + sizeof(int);
int writeParticlesUni(const std::string &name, const BasicParticleSystem *parts)
{
debMsg("writing particles " << parts->getName() << " to uni file " << name, 1);
#if NO_ZLIB != 1
char ID[5] = "PB02";
UniPartHeader head;
head.dim = parts->size();
Vec3i gridSize = parts->getParent()->getGridSize();
head.dimX = gridSize.x;
head.dimY = gridSize.y;
head.dimZ = gridSize.z;
head.bytesPerElement = PartSysSize;
head.elementType = 0; // 0 for base data
snprintf(head.info, STR_LEN_PDATA, "%s", buildInfoString().c_str());
MuTime stamp;
head.timestamp = stamp.time;
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
gzwrite(gzf, ID, 4);
# if FLOATINGPOINT_PRECISION != 1
// warning - hard coded conversion of byte size here...
gzwrite(gzf, &head, sizeof(UniPartHeader));
for (int i = 0; i < parts->size(); ++i) {
Vector3D<float> pos = toVec3f((*parts)[i].pos);
int flag = (*parts)[i].flag;
gzwrite(gzf, &pos, sizeof(Vector3D<float>));
gzwrite(gzf, &flag, sizeof(int));
}
# else
assertMsg(sizeof(BasicParticleData) == PartSysSize, "particle data size doesn't match");
gzwrite(gzf, &head, sizeof(UniPartHeader));
gzwrite(gzf, &((*parts)[0]), PartSysSize * head.dim);
# endif
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
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) {
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
UniPartHeader head;
assertMsg(gzread(gzf, &head, sizeof(UniPartHeader)) == sizeof(UniPartHeader),
"can't read file, no header present");
assertMsg(((head.bytesPerElement == PartSysSize) && (head.elementType == 0)),
"particle type doesn't match");
const Vec3i curGridSize = parts->getParent()->getGridSize();
const Vec3i headGridSize(head.dimX, head.dimY, head.dimZ);
# if BLENDER
// Correct grid size is only a soft requirement in Blender
if (headGridSize != curGridSize) {
debMsg("readPdataUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize, 1);
return 0;
}
# else
assertMsg(headGridSize == curGridSize,
"readPdataUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize);
# endif
// re-allocate all data
parts->resizeAll(head.dim);
assertMsg(head.dim == parts->size(), "particle size doesn't match");
# if FLOATINGPOINT_PRECISION != 1
for (int i = 0; i < parts->size(); ++i) {
Vector3D<float> pos;
int flag;
gzread(gzf, &pos, sizeof(Vector3D<float>));
gzread(gzf, &flag, sizeof(int));
(*parts)[i].pos = toVec3d(pos);
(*parts)[i].flag = flag;
}
# else
assertMsg(sizeof(BasicParticleData) == PartSysSize, "particle data size doesn't match");
IndexInt bytes = PartSysSize * head.dim;
IndexInt readBytes = gzread(gzf, &(parts->getData()[0]), bytes);
assertMsg(bytes == readBytes,
"can't read uni file, stream length does not match, " << bytes << " vs "
<< readBytes);
# endif
parts->transformPositions(Vec3i(head.dimX, head.dimY, head.dimZ),
parts->getParent()->getGridSize());
}
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
template<class T> int writePdataUni(const std::string &name, ParticleDataImpl<T> *pdata)
{
debMsg("writing particle data " << pdata->getName() << " to uni file " << name, 1);
#if NO_ZLIB != 1
char ID[5] = "PD01";
UniPartHeader head;
head.dim = pdata->size();
Vec3i gridSize = pdata->getParent()->getGridSize();
head.dimX = gridSize.x;
head.dimY = gridSize.y;
head.dimZ = gridSize.z;
head.bytesPerElement = sizeof(T);
head.elementType = 1; // 1 for particle data, todo - add sub types?
snprintf(head.info, STR_LEN_PDATA, "%s", buildInfoString().c_str());
MuTime stamp;
head.timestamp = stamp.time;
gzFile gzf = (gzFile)safeGzopen(name.c_str(), "wb1"); // do some compression
if (!gzf) {
errMsg("can't open file " << name);
return 0;
}
gzwrite(gzf, ID, 4);
# if FLOATINGPOINT_PRECISION != 1
// always write float values, even if compiled with double precision (as for grids)
ParticleDataImpl<T> temp(pdata->getParent());
temp.resize(pdata->size());
pdataConvertWrite(gzf, *pdata, &(temp[0]), head);
# else
gzwrite(gzf, &head, sizeof(UniPartHeader));
gzwrite(gzf, &(pdata->get(0)), sizeof(T) * head.dim);
# endif
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
};
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) {
errMsg("can't open file " << name);
return 0;
}
char ID[5] = {0, 0, 0, 0, 0};
gzread(gzf, ID, 4);
if (!strcmp(ID, "PD01")) {
UniPartHeader head;
assertMsg(gzread(gzf, &head, sizeof(UniPartHeader)) == sizeof(UniPartHeader),
"can't read file, no header present");
pdata->getParticleSys()->resize(head.dim); // ensure that parent particle system has same size
pdata->resize(head.dim);
const Vec3i curGridSize = pdata->getParent()->getGridSize();
const Vec3i headGridSize(head.dimX, head.dimY, head.dimZ);
# if BLENDER
// Correct grid size is only a soft requirement in Blender
if (headGridSize != curGridSize) {
debMsg("readPdataUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize, 1);
return 0;
}
# else
assertMsg(headGridSize == curGridSize,
"readPdataUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize);
# endif
assertMsg(head.dim == pdata->size(), "pdata size doesn't match");
# if FLOATINGPOINT_PRECISION != 1
ParticleDataImpl<T> temp(pdata->getParent());
temp.resize(pdata->size());
pdataReadConvert<T>(gzf, *pdata, &(temp[0]), head.bytesPerElement);
# else
assertMsg(((head.bytesPerElement == sizeof(T)) && (head.elementType == 1)),
"pdata type doesn't match");
IndexInt bytes = sizeof(T) * head.dim;
IndexInt readBytes = gzread(gzf, &(pdata->get(0)), sizeof(T) * head.dim);
assertMsg(bytes == readBytes,
"can't read uni file, stream length does not match, " << bytes << " vs "
<< readBytes);
# endif
}
return (gzclose(gzf) == Z_OK);
#else
debMsg("file format not supported without zlib", 1);
return 0;
#endif
}
// explicit instantiation
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

@@ -0,0 +1,124 @@
// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep generate).
/******************************************************************************
*
* MantaFlow fluid solver framework
* Copyright 2011-2020 Tobias Pfaff, 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
*
* Helper functions to handle file IO
*
******************************************************************************/
#include "mantaio.h"
#if OPENVDB == 1
# include "openvdb/openvdb.h"
#endif
#if NO_ZLIB != 1
extern "C" {
# include <zlib.h>
}
#endif
#if defined(WIN32) || defined(_WIN32)
# include <windows.h>
# include <string>
#endif
using namespace std;
namespace Manta {
#if defined(WIN32) || defined(_WIN32)
static wstring stringToWstring(const char *str)
{
const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), nullptr, 0);
wstring strWide(length_wc, 0);
MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), &strWide[0], length_wc);
return strWide;
}
#endif // WIN32==1
void *safeGzopen(const char *filename, const char *mode)
{
#if NO_ZLIB != 1
gzFile gzfile;
# if defined(WIN32) || defined(_WIN32)
wstring filenameWide = stringToWstring(filename);
gzfile = gzopen_w(filenameWide.c_str(), mode);
# else
gzfile = gzopen(filename, mode);
# endif
return gzfile;
#else
debMsg("safeGzopen not supported without zlib", 1);
return nullptr;
#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();
}
template<> void convertFrom(openvdb::Vec3i &in, Vec3i *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 Manta

View File

@@ -0,0 +1,908 @@
// 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"
# include "openvdb/tools/Clip.h"
# include "openvdb/tools/Dense.h"
#endif
#define POSITION_NAME "P"
#define FLAG_NAME "U"
#define META_BASE_RES "file_base_resolution"
#define META_VOXEL_SIZE "file_voxel_size"
#define META_BBOX_MAX "file_bbox_max"
#define META_BBOX_MIN "file_bbox_min"
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;
// Check if current grid is to be read as a sparse grid, active voxels (only) will be copied
if (to->saveSparse()) {
to->clear(); // Ensure that destination grid is empty before writing
for (typename GridType::ValueOnCIter iter = from->cbeginValueOn(); iter.test(); ++iter) {
ValueT vdbValue = *iter;
T toMantaValue;
convertFrom(vdbValue, &toMantaValue);
// #91174 #124064 - Check if iteration is Voxel or Tile
if (iter.isVoxelValue()) {
openvdb::Coord coord = iter.getCoord();
to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
}
else {
openvdb::CoordBBox bbox;
iter.getBoundingBox(bbox);
// If grid has 8x8x8 block with the same value, it is stored as Tile with single value.
// We need to iterate over the bounding box and copy such value to all voxels in 8x8x8 node.
for (openvdb::CoordBBox::Iterator<true> ijk(bbox); ijk; ++ijk) {
openvdb::Coord coord = *ijk;
to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
}
}
}
}
// When importing all grid cells, using a grid accessor is usually faster than a value iterator
else {
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)
{
unusedParameter(voxelSize); // Unused for now
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,
int precision)
{
grid->setTransform(openvdb::math::Transform::createLinearTransform(voxelSize));
grid->setGridClass(cls);
grid->setName(name);
grid->setSaveFloatAsHalf(precision == PRECISION_MINI || precision == PRECISION_HALF);
}
template<class T, class GridType>
typename GridType::Ptr exportVDB(Grid<T> *from, float clip, openvdb::FloatGrid::Ptr clipGrid)
{
using ValueT = typename GridType::ValueType;
typename GridType::Ptr to = GridType::create(ValueT(0));
// Copy data from grid by creating a vdb dense structure and then copying that into a vdb grid
// This is the fastest way to copy data for both dense and sparse grids -> if (true)
if (true) {
ValueT *data = (ValueT *)from->getData();
openvdb::math::CoordBBox bbox(
openvdb::Coord(0),
openvdb::Coord(from->getSizeX() - 1, from->getSizeY() - 1, from->getSizeZ() - 1));
openvdb::tools::Dense<ValueT, openvdb::tools::MemoryLayout::LayoutXYZ> dense(bbox, data);
// Use clip value, or (when not exporting in sparse mode) clear it in order to copy all values
// of dense grid
ValueT tmpClip = (from->saveSparse()) ? ValueT(clip) : ValueT(0);
// Copy from dense to sparse grid structure considering clip value
openvdb::tools::copyFromDense(dense, *to, tmpClip);
// If present, use clip grid to trim down current vdb grid even more
if (from->saveSparse() && clipGrid && !clipGrid->empty()) {
to = openvdb::tools::clip(*to, *clipGrid);
}
}
// Alternatively, reading all grid cells with an accessor (slightly slower) is possible like this
else {
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,
int precision)
{
std::vector<VDBType> vdbValues;
std::string name = from->getName();
BasicParticleSystem *pp = dynamic_cast<BasicParticleSystem *>(from->getParticleSys());
FOR_PARTS(*from)
{
// Optionally, skip exporting particles that have been marked as deleted
if (skipDeletedParts && !pp->isActive(idx)) {
continue;
}
MantaType fromMantaValue = (*from)[idx];
VDBType vdbValue;
convertTo(&vdbValue, fromMantaValue);
vdbValues.push_back(vdbValue);
}
// Use custom codec for precision of the attribute
openvdb::NamePair attribute;
if (precision == PRECISION_FULL) {
attribute =
openvdb::points::TypedAttributeArray<VDBType, openvdb::points::NullCodec>::attributeType();
}
else if (precision == PRECISION_HALF ||
precision == PRECISION_MINI) { // Mini uses same precision as half for now
attribute =
openvdb::points::TypedAttributeArray<VDBType,
openvdb::points::TruncateCodec>::attributeType();
}
else {
errMsg("exportVDB: invalid precision level");
}
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,
int precision)
{
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);
openvdb::points::PointDataGrid::Ptr to;
openvdb::NamePair flagAttribute;
using CodecNull = openvdb::points::NullCodec;
using CodecTrunc = openvdb::points::TruncateCodec;
using CodecFixPoint = openvdb::points::FixedPointCodec<true, openvdb::points::PositionRange>;
// Use custom codec for precision of the particle position and the flag attribute
if (precision == PRECISION_FULL) {
to = openvdb::points::createPointDataGrid<CodecNull, openvdb::points::PointDataGrid>(
*pointIndexGrid, positionsWrapper, *transform);
flagAttribute = openvdb::points::TypedAttributeArray<int, CodecNull>::attributeType();
}
else if (precision == PRECISION_HALF) {
to = openvdb::points::createPointDataGrid<CodecTrunc, openvdb::points::PointDataGrid>(
*pointIndexGrid, positionsWrapper, *transform);
flagAttribute = openvdb::points::TypedAttributeArray<int, CodecTrunc>::attributeType();
}
else if (precision == PRECISION_MINI) {
to = openvdb::points::createPointDataGrid<CodecFixPoint, openvdb::points::PointDataGrid>(
*pointIndexGrid, positionsWrapper, *transform);
flagAttribute = openvdb::points::TypedAttributeArray<int, CodecTrunc>::
attributeType(); // Use 16 bit trunc for flag for now
}
else {
errMsg("exportVDB: invalid precision level");
}
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, precision);
}
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, precision);
}
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, precision);
}
else {
errMsg("exportVDB: unknown ParticleDataBase type");
}
}
return to;
}
static void registerCustomCodecs()
{
openvdb::points::TypedAttributeArray<int, openvdb::points::TruncateCodec>::registerType();
openvdb::points::TypedAttributeArray<float, openvdb::points::TruncateCodec>::registerType();
openvdb::points::TypedAttributeArray<openvdb::Vec3s,
openvdb::points::TruncateCodec>::registerType();
}
int writeObjectsVDB(const string &filename,
std::vector<PbClass *> *objects,
float worldSize,
bool skipDeletedParts,
int compression,
int precision,
float clip,
const Grid<Real> *clipGrid,
const bool meta)
{
openvdb::initialize();
openvdb::io::File file(filename);
openvdb::GridPtrVec gridsVDB;
// Register custom codecs, this makes sure custom attributes can be read
registerCustomCodecs();
std::vector<ParticleDataBase *> pdbBuffer;
// Convert given clip grid to vdb clip grid
openvdb::FloatGrid::Ptr vdbClipGrid = nullptr;
if (clipGrid) {
vdbClipGrid = openvdb::FloatGrid::create();
Real *data = (Real *)clipGrid->getData();
openvdb::math::CoordBBox bbox(openvdb::Coord(0),
openvdb::Coord(clipGrid->getSizeX() - 1,
clipGrid->getSizeY() - 1,
clipGrid->getSizeZ() - 1));
openvdb::tools::Dense<float, openvdb::tools::MemoryLayout::LayoutXYZ> dense(bbox, data);
openvdb::tools::copyFromDense(dense, *vdbClipGrid, clip);
}
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;
if (clipGrid && mantaIntGrid->saveSparse()) {
assertMsg(clipGrid->getSize() == mantaGrid->getSize(),
"writeObjectsVDB: Clip grid and exported grid must have the same size "
<< clipGrid->getSize() << " vs " << mantaGrid->getSize());
}
vdbGrid = exportVDB<int, openvdb::Int32Grid>(mantaIntGrid, clip, vdbClipGrid);
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;
// Only supply clip grid if real grid is not equal to the clip grid
openvdb::FloatGrid::Ptr tmpClipGrid = (mantaRealGrid == clipGrid) ? nullptr : vdbClipGrid;
if (clipGrid && mantaRealGrid->saveSparse()) {
assertMsg(clipGrid->getSize() == mantaGrid->getSize(),
"writeObjectsVDB: Clip grid and exported grid must have the same size "
<< clipGrid->getSize() << " vs " << mantaGrid->getSize());
}
vdbGrid = exportVDB<Real, openvdb::FloatGrid>(mantaRealGrid, clip, tmpClipGrid);
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;
if (clipGrid && mantaVec3Grid->saveSparse()) {
assertMsg(clipGrid->getSize() == mantaGrid->getSize(),
"writeObjectsVDB: Clip grid and exported grid must have the same size "
<< clipGrid->getSize() << " vs " << mantaGrid->getSize());
}
vdbGrid = exportVDB<Vec3, openvdb::Vec3SGrid>(mantaVec3Grid, clip, vdbClipGrid);
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, precision);
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, precision);
// Optional metadata: Save additional simulation information per vdb object
if (meta) {
const Vec3i size = object->getParent()->getGridSize();
// The (dense) resolution of this grid
vdbGrid->insertMeta(META_BASE_RES,
openvdb::Vec3IMetadata(openvdb::Vec3i(size.x, size.y, size.z)));
// Length of one voxel side
vdbGrid->insertMeta(META_VOXEL_SIZE, openvdb::FloatMetadata(voxelSize));
}
}
}
// 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 there 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;
}
default:
case COMPRESSION_ZIP: {
vdb_flags |= openvdb::io::COMPRESS_ZIP;
break;
}
case COMPRESSION_BLOSC: {
# if OPENVDB_BLOSC == 1
// Cannot use |= here, causes segfault with blosc 1.5.0 (== recommended version)
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;
}
static void clearAll(std::vector<PbClass *> *objects, std::vector<ParticleDataBase *> pdbBuffer)
{
// Clear all data loaded into manta objects (e.g. during IO error)
for (std::vector<PbClass *>::iterator iter = objects->begin(); iter != objects->end(); ++iter) {
if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
if (mantaGrid->getType() & GridBase::TypeInt) {
Grid<int> *mantaIntGrid = (Grid<int> *)mantaGrid;
mantaIntGrid->clear();
}
else if (mantaGrid->getType() & GridBase::TypeReal) {
Grid<Real> *mantaRealGrid = (Grid<Real> *)mantaGrid;
mantaRealGrid->clear();
}
else if (mantaGrid->getType() & GridBase::TypeVec3) {
Grid<Vec3> *mantaVec3Grid = (Grid<Vec3> *)mantaGrid;
mantaVec3Grid->clear();
}
}
else if (BasicParticleSystem *mantaPP = dynamic_cast<BasicParticleSystem *>(*iter)) {
mantaPP->clear();
}
}
for (ParticleDataBase *pdb : pdbBuffer) {
if (pdb->getType() == ParticleDataBase::TypeInt) {
ParticleDataImpl<int> *mantaPDataInt = (ParticleDataImpl<int> *)pdb;
mantaPDataInt->clear();
}
else if (pdb->getType() == ParticleDataBase::TypeReal) {
ParticleDataImpl<Real> *mantaPDataReal = (ParticleDataImpl<Real> *)pdb;
mantaPDataReal->clear();
}
else if (pdb->getType() == ParticleDataBase::TypeVec3) {
ParticleDataImpl<Vec3> *mantaPDataVec3 = (ParticleDataImpl<Vec3> *)pdb;
mantaPDataVec3->clear();
}
}
}
int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, float worldSize)
{
openvdb::initialize();
openvdb::io::File file(filename);
openvdb::GridPtrVec gridsVDB;
// Register custom codecs, this makes sure custom attributes can be read
registerCustomCodecs();
try {
#ifdef OPENVDB_USE_DELAYED_LOADING
file.setCopyMaxBytes(0);
#endif
file.open();
gridsVDB = *(file.getGrids());
openvdb::MetaMap::Ptr metadata = file.getMetadata();
unusedParameter(metadata); // Unused for now
}
catch (const openvdb::IoError &e) {
unusedParameter(e); // Unused for now
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;
// Count how many objects could not be read correctly
int readFailure = 0;
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).
const bool onlyGrid = (gridsVDB.size() == 1);
PbClass *object = dynamic_cast<PbClass *>(*iter);
const Real dx = object->getParent()->getDx();
const Vec3i origRes = object->getParent()->getGridSize();
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;
}
// Metadata: If present in the file, meta data will be parsed into these fields
Real metaVoxelSize(0);
Vec3i metaRes(0), metaBBoxMax(0), metaBBoxMin(0);
// Loop to load all meta data that we care about
for (openvdb::MetaMap::MetaIterator iter = vdbGrid->beginMeta(); iter != vdbGrid->endMeta();
++iter) {
const std::string &name = iter->first;
const openvdb::Metadata::Ptr value = iter->second;
if (name.compare(META_BASE_RES) == 0) {
openvdb::Vec3i tmp = static_cast<openvdb::Vec3IMetadata &>(*value).value();
convertFrom(tmp, &metaRes);
}
else if (name.compare(META_VOXEL_SIZE) == 0) {
float tmp = static_cast<openvdb::FloatMetadata &>(*value).value();
convertFrom(tmp, &metaVoxelSize);
voxelSize = metaVoxelSize; // Make sure to update voxel size variable (used in
// pointgrid's importVDB())
if (worldSize != 1.0)
debMsg(
"readObjectsVDB: Found voxel size in meta data. worldSize parameter will be "
"ignored!",
1);
}
else if (name.compare(META_BBOX_MAX) == 0) {
openvdb::Vec3i tmp = static_cast<openvdb::Vec3IMetadata &>(*value).value();
convertFrom(tmp, &metaBBoxMax);
}
else if (name.compare(META_BBOX_MIN) == 0) {
openvdb::Vec3i tmp = static_cast<openvdb::Vec3IMetadata &>(*value).value();
convertFrom(tmp, &metaBBoxMin);
}
else {
debMsg("readObjectsVDB: Skipping unknown meta information '" << name << "'", 1);
}
}
// Compare metadata with allocated grid setup. This prevents invalid index access.
if (notZero(metaRes) && metaRes != origRes) {
debMsg("readObjectsVDB Warning: Grid '" << vdbGrid->getName()
<< "' has not been read. Meta grid res " << metaRes
<< " vs " << origRes << " current grid size",
1);
readFailure++;
break;
}
if (notZero(metaVoxelSize) && metaVoxelSize != voxelSize) {
debMsg("readObjectsVDB Warning: Grid '"
<< vdbGrid->getName() << "' has not been read. Meta voxel size "
<< metaVoxelSize << " vs " << voxelSize << " current voxel size",
1);
readFailure++;
break;
}
if (metaBBoxMax.x > origRes.x || metaBBoxMax.y > origRes.y || metaBBoxMax.z > origRes.z) {
debMsg("readObjectsVDB Warning: Grid '"
<< vdbGrid->getName() << "' has not been read. Vdb bbox max " << metaBBoxMax
<< " vs " << origRes << " current grid size",
1);
readFailure++;
break;
}
const Vec3i origOrigin(0);
if (metaBBoxMin.x < origOrigin.x || metaBBoxMin.y < origOrigin.y ||
metaBBoxMin.z < origOrigin.z) {
debMsg("readObjectsVDB Warning: Grid '"
<< vdbGrid->getName() << "' has not been read. Vdb bbox min " << metaBBoxMin
<< " vs " << origOrigin << " current grid origin",
1);
readFailure++;
break;
}
if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
if (mantaGrid->getType() & GridBase::TypeInt) {
openvdb::Int32Grid::Ptr vdbIntGrid = openvdb::gridPtrCast<openvdb::Int32Grid>(vdbGrid);
if (!vdbIntGrid)
continue; // Sanity check: Cast can fail if onlyGrid is true but object count > 1
Grid<int> *mantaIntGrid = (Grid<int> *)mantaGrid;
debMsg("Reading into grid '" << mantaGrid->getName() << "' from int grid '"
<< vdbGrid->getName() << "' in vdb file " << filename,
1);
importVDB<openvdb::Int32Grid, int>(vdbIntGrid, mantaIntGrid);
}
else if (mantaGrid->getType() & GridBase::TypeReal) {
openvdb::FloatGrid::Ptr vdbFloatGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(vdbGrid);
if (!vdbFloatGrid)
continue; // Sanity check: Cast can fail if onlyGrid is true but object count > 1
Grid<Real> *mantaRealGrid = (Grid<Real> *)mantaGrid;
debMsg("Reading into grid '" << mantaGrid->getName() << "' from real grid '"
<< vdbGrid->getName() << "' in vdb file " << filename,
1);
importVDB<openvdb::FloatGrid, Real>(vdbFloatGrid, mantaRealGrid);
}
else if (mantaGrid->getType() & GridBase::TypeVec3) {
openvdb::Vec3SGrid::Ptr vdbVec3Grid = openvdb::gridPtrCast<openvdb::Vec3SGrid>(vdbGrid);
if (!vdbVec3Grid)
continue; // Sanity check: Cast can fail if onlyGrid is true but object count > 1
Grid<Vec3> *mantaVec3Grid = (Grid<Vec3> *)mantaGrid;
debMsg("Reading into grid '" << mantaGrid->getName() << "' from vec3 grid '"
<< vdbGrid->getName() << "' in vdb file " << filename,
1);
importVDB<openvdb::Vec3SGrid, Vec3>(vdbVec3Grid, mantaVec3Grid);
}
else {
errMsg("readObjectsVDB: unknown grid type");
return 0;
}
}
else if (BasicParticleSystem *mantaPP = dynamic_cast<BasicParticleSystem *>(*iter)) {
openvdb::points::PointDataGrid::Ptr vdbPointGrid =
openvdb::gridPtrCast<openvdb::points::PointDataGrid>(vdbGrid);
if (!vdbPointGrid)
continue; // Sanity check: Cast can fail if onlyGrid is true but objects > 1
debMsg("Reading into particle system '" << mantaPP->getName() << "' from particle system '"
<< vdbGrid->getName() << "' in vdb file "
<< filename,
1);
importVDB(vdbPointGrid, mantaPP, pdbBuffer, voxelSize);
pdbBuffer.clear();
}
else {
errMsg("readObjectsVDB: Unsupported Python object. Cannot read from .vdb file "
<< filename);
return 0;
}
}
// Do not continue loading objects in this loop if there was a read error
if (readFailure > 0) {
break;
}
}
if (readFailure > 0) {
// Clear all data that has already been loaded into simulation objects
clearAll(objects, pdbBuffer);
pdbBuffer.clear();
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, float clip = 1e-4, openvdb::FloatGrid::Ptr clipGrid = nullptr);
template openvdb::FloatGrid::Ptr exportVDB<Real, openvdb::FloatGrid>(
Grid<Real> *from, float clip = 1e-4, openvdb::FloatGrid::Ptr clipGrid = nullptr);
template openvdb::Vec3SGrid::Ptr exportVDB<Vec3, openvdb::Vec3SGrid>(
Grid<Vec3> *from, float clip = 1e-4, openvdb::FloatGrid::Ptr clipGrid = nullptr);
openvdb::points::PointDataGrid::Ptr exportVDB(BasicParticleSystem *from,
std::vector<ParticleDataBase *> &fromPData,
bool skipDeletedParts = false,
float voxelSize = 1.0,
int precision = PRECISION_HALF);
template void exportVDB<int, int>(ParticleDataImpl<int> *from,
openvdb::points::PointDataGrid::Ptr to,
openvdb::tools::PointIndexGrid::Ptr pIndex,
bool skipDeletedParts = false,
int precision = PRECISION_HALF);
template void exportVDB<Real, float>(ParticleDataImpl<Real> *from,
openvdb::points::PointDataGrid::Ptr to,
openvdb::tools::PointIndexGrid::Ptr pIndex,
bool skipDeletedParts = false,
int precision = PRECISION_HALF);
template void exportVDB<Vec3, openvdb::Vec3s>(ParticleDataImpl<Vec3> *from,
openvdb::points::PointDataGrid::Ptr to,
openvdb::tools::PointIndexGrid::Ptr pIndex,
bool skipDeletedParts = false,
int precision = PRECISION_HALF);
#else
int writeObjectsVDB(const string &filename,
std::vector<PbClass *> *objects,
float worldSize,
bool skipDeletedParts,
int compression,
int precision,
float clip,
const Grid<Real> *clipGrid,
const bool meta)
{
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,167 @@
// 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 = nullptr;
{
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,
int precision = PRECISION_HALF,
float clip = 1e-4,
const Grid<Real> *clipGrid = nullptr,
const bool meta = false)
{
if (!precisionHalf) {
debMsg("Warning: precisionHalf argument is deprecated. Please use precision level instead", 0);
precision = PRECISION_HALF; // for backwards compatibility
}
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, precision, clip, clipGrid, meta);
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 = nullptr;
{
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);
int precision = _args.getOpt<int>("precision", 6, PRECISION_HALF, &_lock);
float clip = _args.getOpt<float>("clip", 7, 1e-4, &_lock);
const Grid<Real> *clipGrid = _args.getPtrOpt<Grid<Real>>("clipGrid", 8, nullptr, &_lock);
const bool meta = _args.getOpt<bool>("meta", 9, false, &_lock);
_retval = toPy(save(name,
objects,
worldSize,
skipDeletedParts,
compression,
precisionHalf,
precision,
clip,
clipGrid,
meta));
_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

@@ -0,0 +1,131 @@
// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep generate).
/******************************************************************************
*
* MantaFlow fluid solver framework
* Copyright 2011 Tobias Pfaff, 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 meshes to disk
*
******************************************************************************/
#ifndef _FILEIO_H
#define _FILEIO_H
#include <string>
#include "manta.h"
// OpenVDB compression flags
#define COMPRESSION_NONE 0
#define COMPRESSION_ZIP 1
#define COMPRESSION_BLOSC 2
// OpenVDB precision flags
#define PRECISION_FULL 0
#define PRECISION_HALF 1
#define PRECISION_MINI 2
namespace Manta {
// 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;
// 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);
// 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);
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);
// OpenVDB
int writeObjectsVDB(const std::string &filename,
std::vector<PbClass *> *objects,
float scale = 1.0,
bool skipDeletedParts = false,
int compression = COMPRESSION_ZIP,
int precision = PRECISION_HALF,
float clip = 1e-4,
const Grid<Real> *clipGrid = nullptr,
const bool meta = false);
int readObjectsVDB(const std::string &filename,
std::vector<PbClass *> *objects,
float scale = 1.0);
// 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>
int readGrid4dUni(const std::string &name,
Grid4d<T> *grid,
int readTslice = -1,
Grid4d<T> *slice = nullptr,
void **fileHandle = nullptr);
void readGrid4dUniCleanup(void **fileHandle);
template<class T> int writeGrid4dRaw(const std::string &name, Grid4d<T> *grid);
template<class T> int readGrid4dRaw(const std::string &name, Grid4d<T> *grid);
// Particles + particle data
int writeParticlesUni(const std::string &name, const BasicParticleSystem *parts);
int readParticlesUni(const std::string &name, BasicParticleSystem *parts);
template<class T> int writePdataUni(const std::string &name, ParticleDataImpl<T> *pdata);
template<class T> int readPdataUni(const std::string &name, ParticleDataImpl<T> *pdata);
// 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 = nullptr,
std::string *info = nullptr);
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
#endif

View File

@@ -0,0 +1,13 @@
// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep link).
#include "fileio/mantaio.h"
namespace Manta {
extern "C" {
void PbRegister_file_18()
{
}
}
} // namespace Manta