Created
January 11, 2017 14:14
-
-
Save Mathiasb17/5fb84d6be9745270f66a4dec6be9b9da to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
The error happened in Line 202: raster.rasterizeTrails(pl, 0.75);//scale offset between two instances
@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
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?