Skip to content

Instantly share code, notes, and snippets.

@Mathiasb17
Created January 11, 2017 14:14
Show Gist options
  • Save Mathiasb17/5fb84d6be9745270f66a4dec6be9b9da to your computer and use it in GitHub Desktop.
Save Mathiasb17/5fb84d6be9745270f66a4dec6be9b9da to your computer and use it in GitHub Desktop.
#include <iostream>
#include <string>
#include <tinyxml.h>
#include <fstream>
#include <openvdb/openvdb.h>
#include <openvdb/tools/ParticlesToLevelSet.h>
#include <openvdb/Exceptions.h>
#include <openvdb/Types.h>
#include <openvdb/tree/LeafNode.h>
#include <openvdb/tools/Filter.h>
#include <openvdb/tools/LevelSetFilter.h>
#include <openvdb/tools/VolumeToMesh.h>
class ParticlesList
{
protected:
struct Particle
{
openvdb::Vec3R p, v;
openvdb::Real r;
};
openvdb::Real mRadiusScale;
openvdb::Real mVelocityScale;
std::vector<Particle> mParticleList;
public:
typedef openvdb::Vec3R value_type;
ParticlesList(openvdb::Real rScale=1, openvdb::Real vScale=1)
: mRadiusScale(rScale), mVelocityScale(vScale)
{
}
void add(const openvdb::Vec3R &p, const openvdb::Real &r, const openvdb::Vec3R &v=openvdb::Vec3R(0,0,0))
{
Particle part;
part.p = p;
part.r = r;
part.v = v;
mParticleList.push_back(part);
}
openvdb::CoordBBox getBBox(const openvdb::GridBase& grid)
{
openvdb::CoordBBox bbox;
openvdb::Coord &min= bbox.min(), &max = bbox.max();
openvdb::Vec3R pos;
openvdb::Real rad, invDx = 1/grid.voxelSize()[0];
for (size_t n=0, e=this->size(); n<e; ++n) {
this->getPosRad(n, pos, rad);
const openvdb::Vec3d xyz = grid.worldToIndex(pos);
const openvdb::Real r = rad * invDx;
for (int i=0; i<3; ++i) {
min[i] = openvdb::math::Min(min[i], openvdb::math::Floor(xyz[i] - r));
max[i] = openvdb::math::Max(max[i], openvdb::math::Ceil( xyz[i] + r));
}
}
return bbox;
}
openvdb::Vec3R pos(int n) const {return mParticleList[n].p;}
openvdb::Vec3R vel(int n) const {return mVelocityScale*mParticleList[n].v;}
openvdb::Real radius(int n) const {return mRadiusScale*mParticleList[n].r;}
size_t size() const { return mParticleList.size(); }
void getPos(size_t n, openvdb::Vec3R& pos) const { pos = mParticleList[n].p; }
void getPosRad(size_t n, openvdb::Vec3R& pos, openvdb::Real& rad) const
{
pos = mParticleList[n].p;
rad = mRadiusScale*mParticleList[n].r;
}
void getPosRadVel(size_t n, openvdb::Vec3R& pos, openvdb::Real& rad, openvdb::Vec3R& vel) const {
pos = mParticleList[n].p;
rad = mRadiusScale*mParticleList[n].r;
vel = mVelocityScale*mParticleList[n].v;
}
void getAtt(size_t n, openvdb::Index32& att) const { att = openvdb::Index32(n); }
};
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cerr << "usage : ./particlesToSurface.cpp scene.xml" << std::endl;
std::cerr << "this program expects a point cloud file to be referenced in the xml scene." << std::endl;
exit(1);
}
std::string filename = std::string(argv[1]);
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////XML LOADING //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
TiXmlDocument doc(filename);
doc.LoadFile();
TiXmlHandle hdl(&doc);
TiXmlElement *elem = hdl.FirstChildElement().FirstChildElement().Element();
TiXmlElement *medium = NULL;
std::string str_pcloud;
while (elem)
{
if (elem->ValueTStr() == "medium")
{
medium = elem;
std::cout << "type of medium : " << medium->Attribute("type") << std::endl;
std::cout << "id of medium : " << medium->Attribute("id") << std::endl;
str_pcloud = medium->FirstChildElement()->FirstChildElement()->Attribute("value");
std::cout << str_pcloud << std::endl;
break;
}
elem = elem->NextSiblingElement();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////BINARY PCLOUD LOADING /////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
std::fstream stream_pcloud;
stream_pcloud.open(str_pcloud.c_str(), std::ios_base::in);
char header[6];
int nb_particles;
stream_pcloud.read(header, 6);
stream_pcloud.read((char*)&nb_particles, sizeof(int));
std::cout << header << std::endl;
std::cout << nb_particles << std::endl;
float px, py, pz, vox, voy, voz, vnx, vny, vnz, r, m, dens, pres, cx, cy, cz, cw;
int sp;
float nx, ny, nz;
ParticlesList pl(1, 1);
int i = 0;
while (i < nb_particles)
{
stream_pcloud.read((char*)&px, sizeof(float));
stream_pcloud.read((char*)&py, sizeof(float));
stream_pcloud.read((char*)&pz, sizeof(float));
stream_pcloud.read((char*)&vox, sizeof(float));
stream_pcloud.read((char*)&voy, sizeof(float));
stream_pcloud.read((char*)&voz, sizeof(float));
stream_pcloud.read((char*)&vnx, sizeof(float));
stream_pcloud.read((char*)&vny, sizeof(float));
stream_pcloud.read((char*)&vnz, sizeof(float));
stream_pcloud.read((char*)&r, sizeof(float));
stream_pcloud.read((char*)&m, sizeof(float));
stream_pcloud.read((char*)&dens, sizeof(float));
stream_pcloud.read((char*)&pres, sizeof(float));
stream_pcloud.read((char*)&cx, sizeof(float));
stream_pcloud.read((char*)&cy, sizeof(float));
stream_pcloud.read((char*)&cz, sizeof(float));
stream_pcloud.read((char*)&cw, sizeof(float));
stream_pcloud.read((char*)&sp, sizeof(int));
stream_pcloud.read((char*)&nx, sizeof(float));
stream_pcloud.read((char*)&ny, sizeof(float));
stream_pcloud.read((char*)&nz, sizeof(float));
pl.add(openvdb::Vec3R(px, py, pz) , openvdb::Real(r), openvdb::Vec3R(0, 0, 0));
i++;
}
stream_pcloud.close();
std::cout << "fin pcloud loading" << std::endl;
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// OPENVDB PROCESSING ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
//const float voxelSize = 0.01f, halfWidth = 2.0f;
//const float voxelSize = 0.0025f, halfWidth = 32.0f;
const float minParticleSize = 0.01;
const float voxelSize = 0.5f * minParticleSize;// in world units
openvdb::FloatGrid::Ptr ls = openvdb::createLevelSet<openvdb::FloatGrid>(voxelSize);
openvdb::tools::ParticlesToLevelSet<openvdb::FloatGrid> raster(*ls);
raster.rasterizeTrails(pl, 0.75);//scale offset between two instances
openvdb::tools::LevelSetFilter<openvdb::FloatGrid> filterer(*ls);
filterer.mean();
std::vector<openvdb::Vec3s> points;
std::vector<openvdb::Vec4I> quads;
std::vector<openvdb::Vec3I> triangles;
//openvdb::tools::volumeToMesh(*ls, points, triangles, quads, 0.01, 0);
openvdb::tools::volumeToMesh(*ls, points, triangles, quads, 0.005, 0);
std::cout << "points " << points.size() << std::endl;
std::cout << "triangles " << triangles.size() << std::endl;
std::cout << "quads " << quads.size() << std::endl;
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// EXPORT MESH AS OBJ ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
std::ostringstream mesh_filename;
mesh_filename << filename << ".obj" ;
std::ofstream stream_mesh;
stream_mesh.open(mesh_filename.str().c_str(), std::ios_base::out);
for (unsigned int i = 0; i < points.size(); ++i) {
stream_mesh << "v " << points[i].x() << " " << points[i].y() << " " << points[i].z() << std::endl;
}
for (unsigned int i = 0; i < quads.size(); ++i) {
stream_mesh << "f " << quads[i].x()+1 << "// " << quads[i].y()+1 << "// " << quads[i].z()+1 << "// " << quads[i].w()+1 << "//" << std::endl;
}
for (unsigned int i = 0; i < triangles.size(); ++i) {
stream_mesh << "f " << triangles[i].x()+1 << "// " << triangles[i].y()+1 << "// " << triangles[i].z()+1 << "//" << std::endl;
}
stream_mesh.close();
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// DELETE POINTCLOUD ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
medium->RemoveChild(medium->FirstChild());
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// MODIFY AND REWRITE XML////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
TiXmlElement *bounds = new TiXmlElement("shape");
bounds->SetAttribute("type", "obj");
TiXmlElement *str_fname = new TiXmlElement("string");
str_fname->SetAttribute("name", "filename");
str_fname->SetAttribute("value", mesh_filename.str());
TiXmlElement *boolface = new TiXmlElement("boolean");
boolface->SetAttribute("name","faceNormals");
boolface->SetAttribute("value","true");
TiXmlElement *boolnorm = new TiXmlElement("boolean");
boolnorm->SetAttribute("name","flipNormals");
boolnorm->SetAttribute("value","true");
TiXmlElement* refwater = new TiXmlElement("ref");
refwater->SetAttribute("name", "interior");
refwater->SetAttribute("id", "water");
TiXmlElement *bounds_bsdf = new TiXmlElement("bsdf");
bounds_bsdf->SetAttribute("type", "dielectric");
TiXmlElement *dielectric_in = new TiXmlElement("string");
dielectric_in->SetAttribute("name", "intIOR");
dielectric_in->SetAttribute("value", "water");
TiXmlElement *dielectric_out = new TiXmlElement("string");
dielectric_out->SetAttribute("name", "extIOR");
dielectric_out->SetAttribute("value", "air");
//TiXmlElement *method = new TiXmlElement("string");
//method->SetAttribute("name", "method");
//method->SetAttribute("value", "simpson");
//medium->LinkEndChild(method);
bounds_bsdf->LinkEndChild(dielectric_in);
bounds_bsdf->LinkEndChild(dielectric_out);
bounds->LinkEndChild(bounds_bsdf);
bounds->LinkEndChild(str_fname);
bounds->LinkEndChild(refwater);
bounds->LinkEndChild(boolface);
bounds->LinkEndChild(boolnorm);
TiXmlElement* scene = hdl.FirstChildElement().Element();
scene->LinkEndChild(bounds);
doc.SaveFile();
return 0;
}
@SimonNgj
Copy link

I have an error of "PosType is not a member of ParticlesList" when trying to run this code. Did you face this error as well?

@SimonNgj
Copy link

The error happened in Line 202: raster.rasterizeTrails(pl, 0.75);//scale offset between two instances

@Mathiasb17
Copy link
Author

@SimonNgj sorry for late answer, i didn't have that problem at the time, it's most likely a problem with OpenVDB version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment