diff options
Diffstat (limited to 'extern/mantaflow/preprocessed/fileio')
-rw-r--r-- | extern/mantaflow/preprocessed/fileio/iogrids.cpp | 1524 | ||||
-rw-r--r-- | extern/mantaflow/preprocessed/fileio/iomeshes.cpp | 490 | ||||
-rw-r--r-- | extern/mantaflow/preprocessed/fileio/ioparticles.cpp | 342 | ||||
-rw-r--r-- | extern/mantaflow/preprocessed/fileio/mantaio.h | 81 | ||||
-rw-r--r-- | extern/mantaflow/preprocessed/fileio/mantaio.h.reg.cpp | 13 |
5 files changed, 2450 insertions, 0 deletions
diff --git a/extern/mantaflow/preprocessed/fileio/iogrids.cpp b/extern/mantaflow/preprocessed/fileio/iogrids.cpp new file mode 100644 index 00000000000..2f6cdaa6209 --- /dev/null +++ b/extern/mantaflow/preprocessed/fileio/iogrids.cpp @@ -0,0 +1,1524 @@ + + +// 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 + +#if OPENVDB == 1 +# include "openvdb/openvdb.h" +#endif + +#include "cnpy.h" +#include "mantaio.h" +#include "grid.h" +#include "vector4d.h" +#include "grid4d.h" + +using namespace std; + +namespace Manta { + +static const int STR_LEN_GRID = 252; + +//! uni file header, v4 +typedef struct { + int dimX, dimY, dimZ; // grid size + int gridType, elementType, bytesPerElement; // data type info + char info[STR_LEN_GRID]; // mantaflow build information + int dimT; // optionally store forth dimension for 4d grids + unsigned long long timestamp; // creation time +} UniHeader; + +// note: header v4 only uses 4 bytes of the info string to store the fourth dimension, not needed +// for pdata + +//***************************************************************************** +// conversion functions for double precision +// (note - uni files always store single prec. values) +//***************************************************************************** + +#if NO_ZLIB != 1 +template<class GRIDT> void gridConvertWrite(gzFile &gzf, GRIDT &grid, void *ptr, UniHeader &head) +{ + errMsg("gridConvertWrite: unknown type, not yet supported"); +} + +template<> void gridConvertWrite(gzFile &gzf, Grid<int> &grid, void *ptr, UniHeader &head) +{ + gzwrite(gzf, &head, sizeof(UniHeader)); + gzwrite(gzf, &grid[0], sizeof(int) * head.dimX * head.dimY * head.dimZ); +} +template<> void gridConvertWrite(gzFile &gzf, Grid<double> &grid, void *ptr, UniHeader &head) +{ + head.bytesPerElement = sizeof(float); + gzwrite(gzf, &head, sizeof(UniHeader)); + float *ptrf = (float *)ptr; + for (int i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i, ++ptrf) { + *ptrf = (float)grid[i]; + } + gzwrite(gzf, ptr, sizeof(float) * head.dimX * head.dimY * head.dimZ); +} +template<> +void gridConvertWrite(gzFile &gzf, Grid<Vector3D<double>> &grid, void *ptr, UniHeader &head) +{ + head.bytesPerElement = sizeof(Vector3D<float>); + gzwrite(gzf, &head, sizeof(UniHeader)); + float *ptrf = (float *)ptr; + for (int i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i) { + for (int c = 0; c < 3; ++c) { + *ptrf = (float)grid[i][c]; + ptrf++; + } + } + gzwrite(gzf, ptr, sizeof(Vector3D<float>) * head.dimX * head.dimY * head.dimZ); +} + +template<> void gridConvertWrite(gzFile &gzf, Grid4d<int> &grid, void *ptr, UniHeader &head) +{ + gzwrite(gzf, &head, sizeof(UniHeader)); + gzwrite(gzf, &grid[0], sizeof(int) * head.dimX * head.dimY * head.dimZ * head.dimT); +} +template<> void gridConvertWrite(gzFile &gzf, Grid4d<double> &grid, void *ptr, UniHeader &head) +{ + head.bytesPerElement = sizeof(float); + gzwrite(gzf, &head, sizeof(UniHeader)); + float *ptrf = (float *)ptr; + IndexInt s = grid.getStrideT() * grid.getSizeT(); + for (IndexInt i = 0; i < s; ++i, ++ptrf) { + *ptrf = (float)grid[i]; + } + gzwrite(gzf, ptr, sizeof(float) * s); +} +template<> +void gridConvertWrite(gzFile &gzf, Grid4d<Vector3D<double>> &grid, void *ptr, UniHeader &head) +{ + head.bytesPerElement = sizeof(Vector3D<float>); + gzwrite(gzf, &head, sizeof(UniHeader)); + float *ptrf = (float *)ptr; + IndexInt s = grid.getStrideT() * grid.getSizeT(); + for (IndexInt i = 0; i < s; ++i) { + for (int c = 0; c < 3; ++c) { + *ptrf = (float)grid[i][c]; + ptrf++; + } + } + gzwrite(gzf, ptr, sizeof(Vector3D<float>) * s); +} +template<> +void gridConvertWrite(gzFile &gzf, Grid4d<Vector4D<double>> &grid, void *ptr, UniHeader &head) +{ + head.bytesPerElement = sizeof(Vector4D<float>); + gzwrite(gzf, &head, sizeof(UniHeader)); + float *ptrf = (float *)ptr; + IndexInt s = grid.getStrideT() * grid.getSizeT(); + for (IndexInt i = 0; i < s; ++i) { + for (int c = 0; c < 4; ++c) { + *ptrf = (float)grid[i][c]; + ptrf++; + } + } + gzwrite(gzf, ptr, sizeof(Vector4D<float>) * s); +} + +template<class T> void gridReadConvert(gzFile &gzf, Grid<T> &grid, void *ptr, int bytesPerElement) +{ + errMsg("gridReadConvert: unknown type, not yet supported"); +} + +template<> void gridReadConvert<int>(gzFile &gzf, Grid<int> &grid, void *ptr, int bytesPerElement) +{ + gzread(gzf, ptr, sizeof(int) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); + assertMsg(bytesPerElement == sizeof(int), + "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(int)); + // easy, nothing to do for ints + memcpy(&(grid[0]), ptr, sizeof(int) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); +} + +template<> +void gridReadConvert<double>(gzFile &gzf, Grid<double> &grid, void *ptr, int bytesPerElement) +{ + gzread(gzf, ptr, sizeof(float) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); + assertMsg(bytesPerElement == sizeof(float), + "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(float)); + float *ptrf = (float *)ptr; + for (int i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i, ++ptrf) { + grid[i] = (double)(*ptrf); + } +} + +template<> +void gridReadConvert<Vec3>(gzFile &gzf, Grid<Vec3> &grid, void *ptr, int bytesPerElement) +{ + gzread(gzf, ptr, sizeof(Vector3D<float>) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); + assertMsg(bytesPerElement == sizeof(Vector3D<float>), + "grid element size doesn't match " << bytesPerElement << " vs " + << sizeof(Vector3D<float>)); + float *ptrf = (float *)ptr; + for (int i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i) { + Vec3 v; + for (int c = 0; c < 3; ++c) { + v[c] = double(*ptrf); + ptrf++; + } + grid[i] = v; + } +} + +template<class T> +void gridReadConvert4d(gzFile &gzf, Grid4d<T> &grid, void *ptr, int bytesPerElement, int t) +{ + errMsg("gridReadConvert4d: unknown type, not yet supported"); +} + +template<> +void gridReadConvert4d<int>(gzFile &gzf, Grid4d<int> &grid, void *ptr, int bytesPerElement, int t) +{ + gzread(gzf, ptr, sizeof(int) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); + assertMsg(bytesPerElement == sizeof(int), + "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(int)); + // nothing to do for ints + memcpy(&(grid[grid.getSizeX() * grid.getSizeY() * grid.getSizeZ() * t]), + ptr, + sizeof(int) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); +} + +template<> +void gridReadConvert4d<double>( + gzFile &gzf, Grid4d<double> &grid, void *ptr, int bytesPerElement, int t) +{ + assertMsg(bytesPerElement == sizeof(float), + "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(float)); + + float *ptrf = (float *)ptr; + gzread(gzf, ptr, sizeof(float) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); + for (IndexInt i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i, ++ptrf) { + grid[grid.getSizeX() * grid.getSizeY() * grid.getSizeZ() * t + i] = (double)(*ptrf); + } +} + +template<> +void gridReadConvert4d<Vec3>( + gzFile &gzf, Grid4d<Vec3> &grid, void *ptr, int bytesPerElement, int t) +{ + assertMsg(bytesPerElement == sizeof(Vector3D<float>), + "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(float)); + + gzread(gzf, ptr, sizeof(Vector3D<float>) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); + float *ptrf = (float *)ptr; + for (IndexInt i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i) { + Vec3 v; + for (int c = 0; c < 3; ++c) { + v[c] = double(*ptrf); + ptrf++; + } + grid[grid.getSizeX() * grid.getSizeY() * grid.getSizeZ() * t + i] = v; + } +} + +template<> +void gridReadConvert4d<Vec4>( + gzFile &gzf, Grid4d<Vec4> &grid, void *ptr, int bytesPerElement, int t) +{ + assertMsg(bytesPerElement == sizeof(Vector4D<float>), + "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(float)); + + gzread(gzf, ptr, sizeof(Vector4D<float>) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ()); + float *ptrf = (float *)ptr; + for (IndexInt i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i) { + Vec4 v; + for (int c = 0; c < 4; ++c) { + v[c] = double(*ptrf); + ptrf++; + } + grid[grid.getSizeX() * grid.getSizeY() * grid.getSizeZ() * t + i] = v; + } +} + +// make sure compatible grid types dont lead to errors... +static int unifyGridType(int type) +{ + // real <> levelset + if (type & GridBase::TypeReal) + type |= GridBase::TypeLevelset; + if (type & GridBase::TypeLevelset) + type |= GridBase::TypeReal; + // vec3 <> mac + if (type & GridBase::TypeVec3) + type |= GridBase::TypeMAC; + if (type & GridBase::TypeMAC) + type |= GridBase::TypeVec3; + return type; +} + +#endif // NO_ZLIB!=1 + +//***************************************************************************** +// grid data +//***************************************************************************** + +template<class T> void 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); + FOR_IJK(*grid) + { + ofs << Vec3i(i, j, k) << " = " << (*grid)(i, j, k) << "\n"; + } + ofs.close(); +} + +template<class T> void writeGridRaw(const string &name, Grid<T> *grid) +{ + debMsg("writing grid " << grid->getName() << " to raw file " << name, 1); + +#if NO_ZLIB != 1 + gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression + if (!gzf) + errMsg("writeGridRaw: can't open file " << name); + gzwrite(gzf, &((*grid)[0]), sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ()); + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#endif +} + +template<class T> void readGridRaw(const string &name, Grid<T> *grid) +{ + debMsg("reading grid " << grid->getName() << " from raw file " << name, 1); + +#if NO_ZLIB != 1 + gzFile gzf = gzopen(name.c_str(), "rb"); + if (!gzf) + errMsg("readGridRaw: can't open file " << name); + + 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); +#else + debMsg("file format not supported without zlib", 1); +#endif +} + +//! legacy headers for reading old files +typedef struct { + int dimX, dimY, dimZ; + int frames, elements, elementType, bytesPerElement, bytesPerFrame; +} UniLegacyHeader; + +typedef struct { + int dimX, dimY, dimZ; + int gridType, elementType, bytesPerElement; +} UniLegacyHeader2; + +typedef struct { + int dimX, dimY, dimZ; + int gridType, elementType, bytesPerElement; + char info[256]; + unsigned long long timestamp; +} UniLegacyHeader3; + +//! for auto-init & check of results of test runs , optionally returns info string of header +void getUniFileSize(const string &name, int &x, int &y, int &z, int *t, std::string *info) +{ + x = y = z = 0; +#if NO_ZLIB != 1 + gzFile gzf = gzopen(name.c_str(), "rb"); + if (gzf) { + char ID[5] = {0, 0, 0, 0, 0}; + gzread(gzf, ID, 4); + + // v3 + if ((!strcmp(ID, "MNT2")) || (!strcmp(ID, "M4T2"))) { + UniLegacyHeader3 head; + assertMsg(gzread(gzf, &head, sizeof(UniLegacyHeader3)) == sizeof(UniLegacyHeader3), + "can't read file, no header present"); + x = head.dimX; + y = head.dimY; + z = head.dimZ; + + // optionally , read fourth dim + if ((!strcmp(ID, "M4T2")) && t) { + int dimT = 0; + gzread(gzf, &dimT, sizeof(int)); + (*t) = dimT; + } + } + + // v4 + if ((!strcmp(ID, "MNT3")) || (!strcmp(ID, "M4T3"))) { + UniHeader head; + assertMsg(gzread(gzf, &head, sizeof(UniHeader)) == sizeof(UniHeader), + "can't read file, no header present"); + x = head.dimX; + y = head.dimY; + z = head.dimZ; + if (t) + (*t) = head.dimT; + } + + gzclose(gzf); + } +#endif + if (info) { + std::ostringstream out; + out << x << "," << y << "," << z; + if (t && (*t) > 0) + out << "," << (*t); + *info = out.str(); + } +} +Vec3 getUniFileSize(const string &name) +{ + int x, y, z; + getUniFileSize(name, x, y, z); + return Vec3(Real(x), Real(y), Real(z)); +} +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, "getUniFileSize", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + const string &name = _args.get<string>("name", 0, &_lock); + _retval = toPy(getUniFileSize(name)); + _args.check(); + } + pbFinalizePlugin(parent, "getUniFileSize", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("getUniFileSize", e.what()); + return 0; + } +} +static const Pb::Register _RP_getUniFileSize("", "getUniFileSize", _W_0); +extern "C" { +void PbRegister_getUniFileSize() +{ + KEEP_UNUSED(_RP_getUniFileSize); +} +} + +//! for test run debugging +void printUniFileInfoString(const string &name) +{ + std::string info("<file not found>"); + int x = -1, y = -1, z = -1, t = -1; + // use getUniFileSize to parse the different headers + getUniFileSize(name, x, y, z, &t, &info); + debMsg("File '" << name << "' info: " << info, 1); +} +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, "printUniFileInfoString", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + const string &name = _args.get<string>("name", 0, &_lock); + _retval = getPyNone(); + printUniFileInfoString(name); + _args.check(); + } + pbFinalizePlugin(parent, "printUniFileInfoString", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("printUniFileInfoString", e.what()); + return 0; + } +} +static const Pb::Register _RP_printUniFileInfoString("", "printUniFileInfoString", _W_1); +extern "C" { +void PbRegister_printUniFileInfoString() +{ + KEEP_UNUSED(_RP_printUniFileInfoString); +} +} + +// actual read/write functions + +template<class T> void writeGridUni(const string &name, Grid<T> *grid) +{ + debMsg("Writing grid " << grid->getName() << " to uni file " << name, 1); + +#if NO_ZLIB != 1 + char ID[5] = "MNT3"; + UniHeader head; + head.dimX = grid->getSizeX(); + head.dimY = grid->getSizeY(); + head.dimZ = grid->getSizeZ(); + head.dimT = 0; + head.gridType = grid->getType(); + head.bytesPerElement = sizeof(T); + snprintf(head.info, STR_LEN_GRID, "%s", buildInfoString().c_str()); + MuTime stamp; + head.timestamp = stamp.time; + + if (grid->getType() & GridBase::TypeInt) + head.elementType = 0; + else if (grid->getType() & GridBase::TypeReal) + head.elementType = 1; + else if (grid->getType() & GridBase::TypeVec3) + head.elementType = 2; + else + errMsg("writeGridUni: unknown element type"); + + gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression + if (!gzf) + errMsg("writeGridUni: can't open file " << name); + + gzwrite(gzf, ID, 4); +# if FLOATINGPOINT_PRECISION != 1 + // always write float values, even if compiled with double precision... + Grid<T> temp(grid->getParent()); + // "misuse" temp grid as storage for floating point values (we have double, so it will always + // fit) + gridConvertWrite(gzf, *grid, &(temp[0]), head); +# else + void *ptr = &((*grid)[0]); + gzwrite(gzf, &head, sizeof(UniHeader)); + gzwrite(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ); +# endif + gzclose(gzf); + +#else + debMsg("file format not supported without zlib", 1); +#endif +}; + +template<class T> void readGridUni(const string &name, Grid<T> *grid) +{ + debMsg("Reading grid " << grid->getName() << " from uni file " << name, 1); + +#if NO_ZLIB != 1 + gzFile gzf = gzopen(name.c_str(), "rb"); + if (!gzf) + errMsg("readGridUni: can't open file " << name); + + char ID[5] = {0, 0, 0, 0, 0}; + gzread(gzf, ID, 4); + + if (!strcmp(ID, "DDF2")) { + // legacy file format + UniLegacyHeader head; + assertMsg(gzread(gzf, &head, sizeof(UniLegacyHeader)) == sizeof(UniLegacyHeader), + "can't read file, no header present"); + assertMsg(head.dimX == grid->getSizeX() && head.dimY == grid->getSizeY() && + head.dimZ == grid->getSizeZ(), + "grid dim doesn't match"); + assertMsg(head.bytesPerElement * head.elements == sizeof(T), "grid type doesn't match"); + // skip flags + int numEl = head.dimX * head.dimY * head.dimZ; + gzseek(gzf, numEl, SEEK_CUR); + // actual grid read + gzread(gzf, &((*grid)[0]), sizeof(T) * numEl); + } + else if (!strcmp(ID, "MNT1")) { + // legacy file format 2 + UniLegacyHeader2 head; + assertMsg(gzread(gzf, &head, sizeof(UniLegacyHeader2)) == sizeof(UniLegacyHeader2), + "can't read file, no header present"); + assertMsg(head.dimX == grid->getSizeX() && head.dimY == grid->getSizeY() && + head.dimZ == grid->getSizeZ(), + "grid dim doesn't match, " << Vec3(head.dimX, head.dimY, head.dimZ) << " vs " + << grid->getSize()); + assertMsg(head.gridType == grid->getType(), + "grid type doesn't match " << head.gridType << " vs " << grid->getType()); + assertMsg(head.bytesPerElement == sizeof(T), + "grid element size doesn't match " << head.bytesPerElement << " vs " << sizeof(T)); + gzread(gzf, &((*grid)[0]), sizeof(T) * head.dimX * head.dimY * head.dimZ); + } + else if (!strcmp(ID, "MNT2")) { + // a bit ugly, almost identical to MNT3 + UniLegacyHeader3 head; + assertMsg(gzread(gzf, &head, sizeof(UniLegacyHeader3)) == sizeof(UniLegacyHeader3), + "can't read file, no header present"); + assertMsg(head.dimX == grid->getSizeX() && head.dimY == grid->getSizeY() && + head.dimZ == grid->getSizeZ(), + "grid dim doesn't match, " << Vec3(head.dimX, head.dimY, head.dimZ) << " vs " + << grid->getSize()); + assertMsg(unifyGridType(head.gridType) == unifyGridType(grid->getType()), + "grid type doesn't match " << head.gridType << " vs " << grid->getType()); +# if FLOATINGPOINT_PRECISION != 1 + Grid<T> temp(grid->getParent()); + void *ptr = &(temp[0]); + gridReadConvert<T>(gzf, *grid, ptr, head.bytesPerElement); +# else + assertMsg(head.bytesPerElement == sizeof(T), + "grid element size doesn't match " << head.bytesPerElement << " vs " << sizeof(T)); + gzread(gzf, &((*grid)[0]), sizeof(T) * head.dimX * head.dimY * head.dimZ); +# endif + } + else if (!strcmp(ID, "MNT3")) { + // current file format + UniHeader head; + assertMsg(gzread(gzf, &head, sizeof(UniHeader)) == sizeof(UniHeader), + "can't read file, no header present"); + assertMsg(head.dimX == grid->getSizeX() && head.dimY == grid->getSizeY() && + head.dimZ == grid->getSizeZ(), + "grid dim doesn't match, " << Vec3(head.dimX, head.dimY, head.dimZ) << " vs " + << grid->getSize()); + assertMsg(unifyGridType(head.gridType) == unifyGridType(grid->getType()), + "grid type doesn't match " << head.gridType << " vs " << grid->getType()); +# if FLOATINGPOINT_PRECISION != 1 + // convert float to double + Grid<T> temp(grid->getParent()); + void *ptr = &(temp[0]); + gridReadConvert<T>(gzf, *grid, ptr, head.bytesPerElement); +# else + assertMsg(head.bytesPerElement == sizeof(T), + "grid element size doesn't match " << head.bytesPerElement << " vs " << sizeof(T)); + gzread(gzf, &((*grid)[0]), sizeof(T) * head.dimX * head.dimY * head.dimZ); +# endif + } + else { + errMsg("readGridUni: Unknown header '" << ID << "' "); + } + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#endif +}; + +template<class T> void writeGridVol(const string &name, Grid<T> *grid) +{ + debMsg("writing grid " << grid->getName() << " to vol file " << name, 1); + errMsg("writeGridVol: Type not yet supported!"); +} + +struct volHeader { + char ID[3]; + char version; + int encoding; + int dimX, dimY, dimZ; + int channels; + Vec3 bboxMin, bboxMax; +}; + +template<> void writeGridVol<Real>(const string &name, Grid<Real> *grid) +{ + debMsg("writing real grid " << grid->getName() << " to vol file " << name, 1); + + volHeader header; + header.ID[0] = 'V'; + header.ID[1] = 'O'; + header.ID[2] = 'L'; + header.version = 3; + header.encoding = 1; // float32 precision + header.dimX = grid->getSizeX(); + header.dimY = grid->getSizeY(); + header.dimZ = grid->getSizeZ(); + header.channels = 1; // only 1 channel + header.bboxMin = Vec3(-0.5); + header.bboxMax = Vec3(0.5); + + FILE *fp = fopen(name.c_str(), "wb"); + if (fp == NULL) { + errMsg("writeGridVol: Cannot open '" << name << "'"); + return; + } + + fwrite(&header, sizeof(volHeader), 1, fp); + +#if FLOATINGPOINT_PRECISION == 1 + // for float, write one big chunk + fwrite(&(*grid)[0], sizeof(float), grid->getSizeX() * grid->getSizeY() * grid->getSizeZ(), fp); +#else + // explicitly convert each entry to float - we might have double precision in mantaflow + FOR_IDX(*grid) + { + float value = (*grid)[idx]; + fwrite(&value, sizeof(float), 1, fp); + } +#endif + + fclose(fp); +}; + +template<class T> void readGridVol(const string &name, Grid<T> *grid) +{ + debMsg("writing grid " << grid->getName() << " to vol file " << name, 1); + errMsg("readGridVol: Type not yet supported!"); +} + +template<> void readGridVol<Real>(const string &name, Grid<Real> *grid) +{ + debMsg("reading real grid " << grid->getName() << " from vol file " << name, 1); + + volHeader header; + FILE *fp = fopen(name.c_str(), "rb"); + if (fp == NULL) { + errMsg("readGridVol: Cannot open '" << name << "'"); + return; + } + + // note, only very basic file format checks here! + assertMsg(fread(&header, 1, sizeof(volHeader), fp) == sizeof(volHeader), + "can't read file, no header present"); + if (header.dimX != grid->getSizeX() || header.dimY != grid->getSizeY() || + header.dimZ != grid->getSizeZ()) + errMsg("grid dim doesn't match, " << Vec3(header.dimX, header.dimY, header.dimZ) << " vs " + << grid->getSize()); +#if FLOATINGPOINT_PRECISION != 1 + errMsg("readGridVol: Double precision not yet supported"); +#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); +}; + +// 4d grids IO + +template<class T> void writeGrid4dUni(const string &name, Grid4d<T> *grid) +{ + debMsg("writing grid4d " << grid->getName() << " to uni file " << name, 1); + +#if NO_ZLIB != 1 + char ID[5] = "M4T3"; + UniHeader head; + head.dimX = grid->getSizeX(); + head.dimY = grid->getSizeY(); + head.dimZ = grid->getSizeZ(); + head.dimT = grid->getSizeT(); + head.gridType = grid->getType(); + head.bytesPerElement = sizeof(T); + snprintf(head.info, STR_LEN_GRID, "%s", buildInfoString().c_str()); + MuTime stamp; + stamp.get(); + head.timestamp = stamp.time; + + if (grid->getType() & Grid4dBase::TypeInt) + head.elementType = 0; + else if (grid->getType() & Grid4dBase::TypeReal) + head.elementType = 1; + else if (grid->getType() & Grid4dBase::TypeVec3) + head.elementType = 2; + else if (grid->getType() & Grid4dBase::TypeVec4) + head.elementType = 2; + else + errMsg("writeGrid4dUni: unknown element type"); + + gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression + if (!gzf) + errMsg("writeGrid4dUni: can't open file " << name); + + gzwrite(gzf, ID, 4); +# if FLOATINGPOINT_PRECISION != 1 + Grid4d<T> temp(grid->getParent()); + gridConvertWrite<Grid4d<T>>(gzf, *grid, &(temp[0]), head); +# else + gzwrite(gzf, &head, sizeof(UniHeader)); + + // can be too large - write in chunks + for (int t = 0; t < head.dimT; ++t) { + void *ptr = &((*grid)[head.dimX * head.dimY * head.dimZ * t]); + gzwrite(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ * 1); + } +# endif + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#endif +}; + +//! note, reading 4d uni grids is slightly more complicated than 3d ones +//! as it optionally supports sliced reading +template<class T> +void readGrid4dUni( + const string &name, Grid4d<T> *grid, int readTslice, Grid4d<T> *slice, void **fileHandle) +{ + if (grid) + debMsg("reading grid " << grid->getName() << " from uni file " << name, 1); + if (slice) + debMsg("reading slice " << slice->getName() << ",t=" << readTslice << " from uni file " + << name, + 1); + +#if NO_ZLIB != 1 + gzFile gzf = NULL; + char ID[5] = {0, 0, 0, 0, 0}; + + // optionally - reuse file handle, if valid one is passed in fileHandle pointer... + if ((!fileHandle) || (fileHandle && (*fileHandle == NULL))) { + gzf = gzopen(name.c_str(), "rb"); + if (!gzf) + errMsg("readGrid4dUni: can't open file " << name); + + gzread(gzf, ID, 4); + if (fileHandle) { + *fileHandle = gzf; + } + } + else { + // optimized read - reduced sanity checks + gzf = (gzFile)(*fileHandle); + void *ptr = &((*slice)[0]); + gzread(gzf, ptr, sizeof(T) * slice->getStrideT() * 1); // quick and dirty... + return; + } + + if ((!strcmp(ID, "M4T2")) || (!strcmp(ID, "M4T3"))) { + int headerSize = -1; + + // current file format + UniHeader head; + if (!strcmp(ID, "M4T3")) { + headerSize = sizeof(UniHeader); + assertMsg(gzread(gzf, &head, sizeof(UniHeader)) == sizeof(UniHeader), + "can't read file, no 4d header present"); + if (FLOATINGPOINT_PRECISION == 1) + assertMsg(head.bytesPerElement == sizeof(T), + "4d grid element size doesn't match " << head.bytesPerElement << " vs " + << sizeof(T)); + } + // old header + if (!strcmp(ID, "M4T2")) { + UniLegacyHeader3 lhead; + headerSize = sizeof(UniLegacyHeader3) + sizeof(int); + assertMsg(gzread(gzf, &lhead, sizeof(UniLegacyHeader3)) == sizeof(UniLegacyHeader3), + "can't read file, no 4dl header present"); + if (FLOATINGPOINT_PRECISION == 1) + assertMsg(lhead.bytesPerElement == sizeof(T), + "4d grid element size doesn't match " << lhead.bytesPerElement << " vs " + << sizeof(T)); + + int fourthDim = 0; + gzread(gzf, &fourthDim, sizeof(fourthDim)); + + head.dimX = lhead.dimX; + head.dimY = lhead.dimY; + head.dimZ = lhead.dimZ; + head.dimT = fourthDim; + head.gridType = lhead.gridType; + } + + if (readTslice < 0) { + assertMsg(head.dimX == grid->getSizeX() && head.dimY == grid->getSizeY() && + head.dimZ == grid->getSizeZ(), + "grid dim doesn't match, " << Vec3(head.dimX, head.dimY, head.dimZ) << " vs " + << grid->getSize()); + assertMsg(unifyGridType(head.gridType) == unifyGridType(grid->getType()), + "grid type doesn't match " << head.gridType << " vs " << grid->getType()); + + // read full 4d grid + assertMsg(head.dimT == grid->getSizeT(), + "grid dim4 doesn't match, " << head.dimT << " vs " << grid->getSize()); + + // can be too large - read in chunks +# if FLOATINGPOINT_PRECISION != 1 + Grid4d<T> temp(grid->getParent()); + void *ptr = &(temp[0]); + for (int t = 0; t < head.dimT; ++t) { + gridReadConvert4d<T>(gzf, *grid, ptr, head.bytesPerElement, t); + } +# else + for (int t = 0; t < head.dimT; ++t) { + void *ptr = &((*grid)[head.dimX * head.dimY * head.dimZ * t]); + gzread(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ * 1); + } +# endif + } + else { + // read chosen slice only + assertMsg(head.dimX == slice->getSizeX() && head.dimY == slice->getSizeY() && + head.dimZ == slice->getSizeZ(), + "grid dim doesn't match, " << Vec3(head.dimX, head.dimY, head.dimZ) << " vs " + << slice->getSize()); + assertMsg(unifyGridType(head.gridType) == unifyGridType(slice->getType()), + "grid type doesn't match " << head.gridType << " vs " << slice->getType()); + +# if FLOATINGPOINT_PRECISION != 1 + errMsg("readGrid4dUni: NYI (2)"); // slice read not yet supported for double +# else + assertMsg(slice, "No 3d slice grid data given"); + assertMsg(readTslice < head.dimT, + "grid dim4 slice too large " << readTslice << " vs " << head.dimT); + void *ptr = &((*slice)[0]); + gzseek(gzf, + sizeof(T) * head.dimX * head.dimY * head.dimZ * readTslice + headerSize + 4, + SEEK_SET); + gzread(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ * 1); +# endif + } + } + else { + debMsg("Unknown header!", 1); + } + + if (!fileHandle) { + gzclose(gzf); + } +#else + debMsg("file format not supported without zlib", 1); +#endif +}; +void readGrid4dUniCleanup(void **fileHandle) +{ + gzFile gzf = NULL; + if (fileHandle) { + gzf = (gzFile)(*fileHandle); + gzclose(gzf); + *fileHandle = NULL; + } +} + +template<class T> void writeGrid4dRaw(const string &name, Grid4d<T> *grid) +{ + debMsg("writing grid4d " << grid->getName() << " to raw file " << name, 1); + +#if NO_ZLIB != 1 + gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression + if (!gzf) + errMsg("writeGrid4dRaw: can't open file " << name); + gzwrite(gzf, + &((*grid)[0]), + sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ() * grid->getSizeT()); + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#endif +} + +template<class T> void readGrid4dRaw(const string &name, Grid4d<T> *grid) +{ + debMsg("reading grid4d " << grid->getName() << " from raw file " << name, 1); + +#if NO_ZLIB != 1 + gzFile gzf = gzopen(name.c_str(), "rb"); + if (!gzf) + errMsg("readGrid4dRaw: can't open file " << name); + + 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); +#else + debMsg("file format not supported without zlib", 1); +#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<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) +{ +#if NO_ZLIB == 1 + debMsg("file format not supported without zlib", 1); + return; +#endif +#if FLOATINGPOINT_PRECISION != 1 + errMsg("writeGridNumpy: Double precision not yet supported"); +#endif + + // find suffix to differentiate between npy <-> npz , TODO: check for actual "npy" string + std::string::size_type idx; + bool bUseNpz = false; + idx = name.rfind('.'); + if (idx != std::string::npos) { + bUseNpz = name.substr(idx + 1) == "npz"; + debMsg("Writing grid " << grid->getName() << " to npz file " << name, 1); + } + else { + debMsg("Writing grid " << grid->getName() << " to npy file " << name, 1); + } + + // storage code + size_t uDim = 1; + if (grid->getType() & GridBase::TypeInt || grid->getType() & GridBase::TypeReal || + grid->getType() & GridBase::TypeLevelset) + uDim = 1; + else if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC) + uDim = 3; + else + errMsg("writeGridNumpy: unknown element type"); + + const std::vector<size_t> shape = {static_cast<size_t>(grid->getSizeZ()), + static_cast<size_t>(grid->getSizeY()), + static_cast<size_t>(grid->getSizeX()), + uDim}; + + if (bUseNpz) { + // note, the following generates a zip file without compression + if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC) { + // cast to float* for export! + float *ptr = (float *)&((*grid)[0]); + cnpy::npz_save(name, "arr_0", ptr, shape, "w"); + } + else { + T *ptr = &((*grid)[0]); + cnpy::npz_save(name, "arr_0", ptr, shape, "w"); + } + } + else { + cnpy::npy_save(name, &grid[0], shape, "w"); + } +}; + +template<class T> void readGridNumpy(const string &name, Grid<T> *grid) +{ +#if NO_ZLIB == 1 + debMsg("file format not supported without zlib", 1); + return; +#endif +#if FLOATINGPOINT_PRECISION != 1 + errMsg("readGridNumpy: Double precision not yet supported"); +#endif + + // find suffix to differentiate between npy <-> npz + std::string::size_type idx; + bool bUseNpz = false; + idx = name.rfind('.'); + if (idx != std::string::npos) { + bUseNpz = name.substr(idx + 1) == "npz"; + debMsg("Reading grid " << grid->getName() << " as npz file " << name, 1); + } + else { + debMsg("Reading grid " << grid->getName() << " as npy file " << name, 1); + } + + cnpy::NpyArray gridArr; + if (bUseNpz) { + cnpy::npz_t fNpz = cnpy::npz_load(name); + gridArr = fNpz["arr_0"]; + } + else { + gridArr = cnpy::npy_load(name); + } + + // Check the file meta information + assertMsg(gridArr.shape[2] == grid->getSizeX() && gridArr.shape[1] == grid->getSizeY() && + gridArr.shape[0] == grid->getSizeZ(), + "grid dim doesn't match, " + << Vec3(gridArr.shape[2], gridArr.shape[1], gridArr.shape[0]) << " vs " + << grid->getSize()); + size_t uDim = 1; + if (grid->getType() & GridBase::TypeInt || grid->getType() & GridBase::TypeReal || + grid->getType() & GridBase::TypeLevelset) + uDim = 1; + else if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC) + uDim = 3; + else + errMsg("readGridNumpy: unknown element type"); + assertMsg(gridArr.shape[3] == uDim, + "grid data dim doesn't match, " << gridArr.shape[3] << " vs " << uDim); + + if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC) { + // treated as float* for export , thus consider 3 elements + assertMsg(3 * gridArr.word_size == sizeof(T), + "vec3 grid data size doesn't match, " << 3 * gridArr.word_size << " vs " + << sizeof(T)); + } + else { + assertMsg(gridArr.word_size == sizeof(T), + "grid data size doesn't match, " << gridArr.word_size << " vs " << sizeof(T)); + } + + // copy back, TODO: beautify... + memcpy(&((*grid)[0]), + gridArr.data<T>(), + sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ()); +}; + +// adopted from getUniFileSize +void getNpzFileSize( + const string &name, int &x, int &y, int &z, int *t = NULL, std::string *info = NULL) +{ + x = y = z = 0; +#if NO_ZLIB != 1 + debMsg("file format not supported without zlib", 1); + return; +#endif +#if FLOATINGPOINT_PRECISION != 1 + errMsg("getNpzFileSize: Double precision not yet supported"); +#endif + // find suffix to differentiate between npy <-> npz + cnpy::NpyArray gridArr; + cnpy::npz_t fNpz = cnpy::npz_load(name); + gridArr = fNpz["arr_0"]; + + z = gridArr.shape[0]; + y = gridArr.shape[1]; + x = gridArr.shape[2]; + if (t) + (*t) = 0; // unused for now +} +Vec3 getNpzFileSize(const string &name) +{ + int x, y, z; + getNpzFileSize(name, x, y, z); + return Vec3(Real(x), Real(y), Real(z)); +} +static PyObject *_W_2(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, "getNpzFileSize", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + const string &name = _args.get<string>("name", 0, &_lock); + _retval = toPy(getNpzFileSize(name)); + _args.check(); + } + pbFinalizePlugin(parent, "getNpzFileSize", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("getNpzFileSize", e.what()); + return 0; + } +} +static const Pb::Register _RP_getNpzFileSize("", "getNpzFileSize", _W_2); +extern "C" { +void PbRegister_getNpzFileSize() +{ + KEEP_UNUSED(_RP_getNpzFileSize); +} +} + +//***************************************************************************** +// helper functions + +void quantizeReal(Real &v, const Real step) +{ + int q = int(v / step + step * 0.5); + double qd = q * (double)step; + v = (Real)qd; +} +struct knQuantize : public KernelBase { + knQuantize(Grid<Real> &grid, Real step) : KernelBase(&grid, 0), grid(grid), step(step) + { + runMessage(); + run(); + } + inline void op(IndexInt idx, Grid<Real> &grid, Real step) const + { + quantizeReal(grid(idx), step); + } + inline Grid<Real> &getArg0() + { + return grid; + } + typedef Grid<Real> type0; + inline Real &getArg1() + { + return step; + } + typedef Real type1; + void runMessage() + { + debMsg("Executing kernel knQuantize ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range<IndexInt> &__r) const + { + for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) + op(idx, grid, step); + } + void run() + { + tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this); + } + Grid<Real> &grid; + Real step; +}; +void quantizeGrid(Grid<Real> &grid, Real step) +{ + knQuantize(grid, step); +} +static PyObject *_W_3(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, "quantizeGrid", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + Grid<Real> &grid = *_args.getPtr<Grid<Real>>("grid", 0, &_lock); + Real step = _args.get<Real>("step", 1, &_lock); + _retval = getPyNone(); + quantizeGrid(grid, step); + _args.check(); + } + pbFinalizePlugin(parent, "quantizeGrid", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("quantizeGrid", e.what()); + return 0; + } +} +static const Pb::Register _RP_quantizeGrid("", "quantizeGrid", _W_3); +extern "C" { +void PbRegister_quantizeGrid() +{ + KEEP_UNUSED(_RP_quantizeGrid); +} +} + +struct knQuantizeVec3 : public KernelBase { + knQuantizeVec3(Grid<Vec3> &grid, Real step) : KernelBase(&grid, 0), grid(grid), step(step) + { + runMessage(); + run(); + } + inline void op(IndexInt idx, Grid<Vec3> &grid, Real step) const + { + for (int c = 0; c < 3; ++c) + quantizeReal(grid(idx)[c], step); + } + inline Grid<Vec3> &getArg0() + { + return grid; + } + typedef Grid<Vec3> type0; + inline Real &getArg1() + { + return step; + } + typedef Real type1; + void runMessage() + { + debMsg("Executing kernel knQuantizeVec3 ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range<IndexInt> &__r) const + { + for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++) + op(idx, grid, step); + } + void run() + { + tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this); + } + Grid<Vec3> &grid; + Real step; +}; +void quantizeGridVec3(Grid<Vec3> &grid, Real step) +{ + knQuantizeVec3(grid, step); +} +static PyObject *_W_4(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, "quantizeGridVec3", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + Grid<Vec3> &grid = *_args.getPtr<Grid<Vec3>>("grid", 0, &_lock); + Real step = _args.get<Real>("step", 1, &_lock); + _retval = getPyNone(); + quantizeGridVec3(grid, step); + _args.check(); + } + pbFinalizePlugin(parent, "quantizeGridVec3", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("quantizeGridVec3", e.what()); + return 0; + } +} +static const Pb::Register _RP_quantizeGridVec3("", "quantizeGridVec3", _W_4); +extern "C" { +void PbRegister_quantizeGridVec3() +{ + KEEP_UNUSED(_RP_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 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 void 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 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 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 + +} // namespace Manta + +namespace Manta { + +} diff --git a/extern/mantaflow/preprocessed/fileio/iomeshes.cpp b/extern/mantaflow/preprocessed/fileio/iomeshes.cpp new file mode 100644 index 00000000000..fc57e2a8c2b --- /dev/null +++ b/extern/mantaflow/preprocessed/fileio/iomeshes.cpp @@ -0,0 +1,490 @@ + + +// 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 +//***************************************************************************** + +void 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!"); + +#if NO_ZLIB != 1 + const Real dx = mesh->getParent()->getDx(); + const Vec3 gs = toVec3(mesh->getParent()->getGridSize()); + + gzFile gzf = gzopen(name.c_str(), "rb1"); // do some compression + if (!gzf) + errMsg("readBobj: unable to open file"); + + // 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) + gzclose(gzf); + debMsg("read mesh , triangles " << mesh->numTris() << ", vertices " << mesh->numNodes() << " ", + 1); +#else + debMsg("file format not supported without zlib", 1); +#endif +} + +void 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 = gzopen(name.c_str(), "wb1"); // do some compression + if (!gzf) + errMsg("writeBobj: unable to open file"); + + // 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)); + } + } + + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#endif +} + +void readObjFile(const std::string &name, Mesh *mesh, bool append) +{ + ifstream ifs(name.c_str()); + + if (!ifs.good()) + errMsg("can't open file '" + name + "'"); + + if (!append) + mesh->clear(); + int nodebase = mesh->numNodes(); + int cnt = 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()) + errMsg("invalid amount of nodes"); + Node n = mesh->nodes(cnt); + ifs >> n.normal.x >> n.normal.y >> n.normal.z; + cnt++; + } + else if (id == "v") { + // vertex + Node n; + ifs >> n.pos.x >> n.pos.y >> n.pos.z; + mesh->addNode(n); + } + 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"); + idx += nodebase; + t.c[i] = idx; + } + mesh->addTri(t); + } + else { + // whatever, ignore + } + // kill rest of line + getline(ifs, id); + } + ifs.close(); +} + +// write regular .obj file, in line with bobj.gz output (but only verts & tris for now) +void 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); + + 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); + // normalize to unit cube around 0 + 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(); +} + +template<class T> void 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 = gzopen(name.c_str(), "rb"); + if (!gzf) + errMsg("can't open file " << name); + + 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"); + 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 + } + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#endif +} + +template<class T> void 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 = gzopen(name.c_str(), "wb1"); // do some compression + if (!gzf) + errMsg("can't open file " << name); + 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 + gzclose(gzf); + +#else + debMsg("file format not supported without zlib", 1); +#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); + +} // namespace Manta diff --git a/extern/mantaflow/preprocessed/fileio/ioparticles.cpp b/extern/mantaflow/preprocessed/fileio/ioparticles.cpp new file mode 100644 index 00000000000..432cbc9f100 --- /dev/null +++ b/extern/mantaflow/preprocessed/fileio/ioparticles.cpp @@ -0,0 +1,342 @@ + + +// 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); + +void 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 = gzopen(name.c_str(), "wb1"); // do some compression + if (!gzf) + errMsg("can't open file " << name); + + 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 + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#endif +}; + +void readParticlesUni(const std::string &name, BasicParticleSystem *parts) +{ + debMsg("reading particles " << parts->getName() << " from uni file " << name, 1); + +#if NO_ZLIB != 1 + gzFile gzf = gzopen(name.c_str(), "rb"); + if (!gzf) + errMsg("can't open file " << name); + + 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"); + } + 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"); + + // 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()); + } + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#endif +}; + +template<class T> void 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 = gzopen(name.c_str(), "wb1"); // do some compression + if (!gzf) + errMsg("can't open file " << name); + 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 + gzclose(gzf); + +#else + debMsg("file format not supported without zlib", 1); +#endif +}; + +template<class T> void 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 = gzopen(name.c_str(), "rb"); + if (!gzf) + errMsg("can't open file " << name); + + 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"); + 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 + } + gzclose(gzf); +#else + debMsg("file format not supported without zlib", 1); +#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); + +} // namespace Manta diff --git a/extern/mantaflow/preprocessed/fileio/mantaio.h b/extern/mantaflow/preprocessed/fileio/mantaio.h new file mode 100644 index 00000000000..8bb0a5af6a4 --- /dev/null +++ b/extern/mantaflow/preprocessed/fileio/mantaio.h @@ -0,0 +1,81 @@ + + +// 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> + +namespace Manta { + +// forward decl. +class Mesh; +class FlagGrid; +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); + +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); + +#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> 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); + +template<class T> void 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); +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); + +void writeParticlesUni(const std::string &name, const BasicParticleSystem *parts); +void 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> void writeMdataUni(const std::string &name, MeshDataImpl<T> *mdata); +template<class T> void readMdataUni(const std::string &name, MeshDataImpl<T> *mdata); + +void getUniFileSize( + const std::string &name, int &x, int &y, int &z, int *t = NULL, std::string *info = NULL); + +} // namespace Manta + +#endif diff --git a/extern/mantaflow/preprocessed/fileio/mantaio.h.reg.cpp b/extern/mantaflow/preprocessed/fileio/mantaio.h.reg.cpp new file mode 100644 index 00000000000..6520786181e --- /dev/null +++ b/extern/mantaflow/preprocessed/fileio/mantaio.h.reg.cpp @@ -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
\ No newline at end of file |