VDB Data value visualize: 结论从houdini得知.

API常用文字:

interior:内部

Narrow-band:窄带

background:窄带外

SDF: XY plane Data visualize:

{

  (1)用法:vdb sdf levelset球,采样其体素值到对应的点位置的颜色观察。houdini节点vdb from polygons(参数上Exterior band voxels:3,Interior band voxels:3)没有开启Fill interior

  则形成体素值:

    interior是-0.3 (这个值是由Interior band voxels:3 得到)

    Narrow-band: 从interior到narrow-band方向:-0.3 到 0

      background:从narrow-band到background方向:0.3 (Exterior band voxels:3)

  (2)用法:

  假如要让interior成为一个梯度值,而不是恒定值,houdini做了一个牛逼的按钮,Fill interior.

  interior里的体素值立马成为梯度的,大概是从-3.73过渡到narrow-band

}

FOG Volume: XY plane Data visualize:

{

  (1) 普通不勾选fill interior:

  interior是1

  Narrow-band: 从interior到narrow-band方向:1 到 0

    background:从narrow-band到background方向:0

  (2) 勾选fill interior:

  interior到narrow-band方向从1->0.3有个过渡

  Narrow-band: 从interior到narrow-band方向:0.3 到 0

    background:从narrow-band到background方向:0

}

==================================================================START======================================================

<1> ,make vdb sphere,and convert to volume

#include <openvdb/openvdb.h>
#include <openvdb/tools/LevelSetSphere.h>
using namespace std; // Populate the given grid with a narrow-band level set representation of a sphere.
// The width of the narrow band is determined by the grid's background value.
// (Example code only; use tools::createSphereSDF() in production.)
template<class GridType>
void
static makeSphere(GridType& grid, float radius, const openvdb::Vec3f& c)
{
typedef typename GridType::ValueType ValueT;
// Distance value for the constant region exterior to the narrow band
const ValueT outside = grid.background();
// Distance value for the constant region interior to the narrow band
// (by convention, the signed distance is negative in the interior of
// a level set)
const ValueT inside = -outside;
// Use the background value as the width in voxels of the narrow band.
// (The narrow band is centered on the surface of the sphere, which
// has distance 0.)
int padding = int(openvdb::math::RoundUp(openvdb::math::Abs(outside)));
// The bounding box of the narrow band is 2*dim voxels on a side.
int dim = int(radius + padding);
// Get a voxel accessor.
typename GridType::Accessor accessor = grid.getAccessor();
// Compute the signed distance from the surface of the sphere of each
// voxel within the bounding box and insert the value into the grid
// if it is smaller in magnitude than the background value.
openvdb::Coord ijk;
int &i = ijk[];
int &j = ijk[];
int &k = ijk[];
for (i = c[] - dim; i < c[] + dim; ++i) {
const float x2 = openvdb::math::Pow2(i - c[]);
for (j = c[] - dim; j < c[] + dim; ++j) {
const float x2y2 = openvdb::math::Pow2(j - c[]) + x2;
for (k = c[] - dim; k < c[] + dim; ++k) {
// The distance from the sphere surface in voxels
const float dist = openvdb::math::Sqrt(x2y2
+ openvdb::math::Pow2(k - c[])) - radius;
// Convert the floating-point distance to the grid's value type.
ValueT val = ValueT(dist);
// Only insert distances that are smaller in magnitude than
// the background value.
if (val < inside || outside < val) continue;
// Set the distance for voxel (i,j,k).
accessor.setValue(ijk, val);
}
}
}
// Propagate the outside/inside sign information from the narrow band
// throughout the grid.
openvdb::tools::signedFloodFill(grid.tree()); } template <class T>
static void convertToVolume(T &grid)
{ // Convert the level set sphere to a narrow-band fog volume, in which
// interior voxels have value 1, exterior voxels have value 0, and
// narrow-band voxels have values varying linearly from 0 to 1.
const float outside = grid->background();
const float width = 2.0 * outside;
// Visit and update all of the grid's active values, which correspond to
// voxels on the narrow band.
for (openvdb::FloatGrid::ValueOnIter iter = grid->beginValueOn(); iter; ++iter) {
float dist = iter.getValue();
iter.setValue((outside - dist) / width);
}
// Visit all of the grid's inactive tile and voxel values and update the values
// that correspond to the interior region.
for (openvdb::FloatGrid::ValueOffIter iter = grid->beginValueOff(); iter; ++iter) {
if (iter.getValue() < 0.0) {
iter.setValue(1.0);
iter.setValueOff();
} else{
iter.setValue();
iter.setValueOff();
}
} } int main()
{ openvdb::initialize();
// Create a shared pointer to a newly-allocated grid of a built-in type:
// in this case, a FloatGrid, which stores one single-precision floating point
// value per voxel. Other built-in grid types include BoolGrid, DoubleGrid,
// Int32Grid and Vec3SGrid (see openvdb.h for the complete list).
// The grid comprises a sparse tree representation of voxel data,
// user-supplied metadata and a voxel space to world space transform,
// which defaults to the identity transform.
openvdb::FloatGrid::Ptr grid =
openvdb::FloatGrid::create(/*background value=*/2.0);
// Populate the grid with a sparse, narrow-band level set representation
// of a sphere with radius 50 voxels, located at (1.5, 2, 3) in index space.
makeSphere(*grid, /*radius=*/50.0, /*center=*/openvdb::Vec3f(1.5, , ));
// Associate some metadata with the grid.
grid->insertMeta("radius", openvdb::FloatMetadata(50.0));
// Associate a scaling transform with the grid that sets the voxel size
// to 0.5 units in world space.
grid->setTransform(
openvdb::math::Transform::createLinearTransform(/*voxel size=*/0.5));
// Identify the grid as a level set.
grid->setGridClass(openvdb::GRID_LEVEL_SET);
//grid->setGridClass(openvdb::GRID_FOG_VOLUME);
// Name the grid "LevelSetSphere".
grid->setName("LevelSetSphere");
// Create a VDB file object.
openvdb::io::File file("mygrids.vdb");
// Add the grid pointer to a container.
openvdb::GridPtrVec grids; // Write out the contents of the container. grids.push_back(grid);
file.write(grids);
file.close(); // ============================================================= convert level set sphere to a fog volume sphere =====================================================
std::cout << "read a new sdf volume and change it to fog\n";
openvdb::io::File readFile("mygrids.vdb");
readFile.open();
openvdb::GridBase::Ptr readGrid;
for(openvdb::io::File::NameIterator nameIter = readFile.beginName();nameIter!=readFile.endName();++nameIter)
{
if(nameIter.gridName() == "LevelSetSphere")
{
readGrid = readFile.readGrid(nameIter.gridName());
} else
{
std::cout << "skip other grid modifile " << nameIter.gridName() <<std::endl;
}
}
openvdb::FloatGrid::Ptr cast_grid = openvdb::gridPtrCast<openvdb::FloatGrid>(readGrid);
cast_grid->setGridClass(openvdb::GRID_FOG_VOLUME);
readFile.close();
convertToVolume(cast_grid);
openvdb::GridPtrVec WM_grids;
WM_grids.push_back(cast_grid);
openvdb::io::File WM_file("mygrids_convertToVolume.vdb");
WM_file.write(WM_grids);
WM_file.close(); return ;
}

<2> vdb from particles

主要观察粒子的density,velocity

#include <openvdb/openvdb.h>

#include <openvdb/tools/ParticlesToLevelSet.h>

#include <iostream>
#include <vector>

struct MyParticle
{
openvdb::Vec3R p, v;
openvdb::Real r;
}; class MyParticleList
{ // change protected to the public,direct find the mRadiusScale,mVelocityScale
public: openvdb::Real mRadiusScale;
openvdb::Real mVelocityScale;
std::vector<MyParticle> mParticleList; public:
std::vector<MyParticle> &get_mPartcileList()
{
return mParticleList;
} public: typedef openvdb::Vec3R PosType; MyParticleList(openvdb::Real rScale=, openvdb::Real vScale=)
: mRadiusScale(rScale), mVelocityScale(vScale) {}
void add(const openvdb::Vec3R &p, const openvdb::Real &r,
const openvdb::Vec3R &v=openvdb::Vec3R(,,))
{
MyParticle pa;
pa.p = p;
pa.r = r;
pa.v = v;
mParticleList.push_back(pa);
}
/// @return coordinate bbox in the space of the specified transfrom
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 = /grid.voxelSize()[];
for (size_t n=, 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=; i<; ++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;
}
//typedef int AttributeType;
// The methods below are only required for the unit-tests
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;} //////////////////////////////////////////////////////////////////////////////
/// The methods below are the only ones required by tools::ParticleToLevelSet
/// @note We return by value since the radius and velocities are modified
/// by the scaling factors! Also these methods are all assumed to
/// be thread-safe. /// Return the total number of particles in list.
/// Always required!
size_t size() const { return mParticleList.size(); } /// Get the world space position of n'th particle.
/// Required by ParticledToLevelSet::rasterizeSphere(*this,radius).
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;
}
// The method below is only required for attribute transfer
void getAtt(size_t n, openvdb::Index32& att) const { att = openvdb::Index32(n); }
};

Particles IO

Buiding the density,and write it out.

int main()
{ const float voxelSize = 0.2f, halfWidth = 2.0f;
openvdb::FloatGrid::Ptr density_grid = openvdb::createLevelSet<openvdb::FloatGrid>(voxelSize, halfWidth); MyParticleList pa(,); // this multiply is radius scale , velocity scale // This particle radius = 1 < 1.5 i.e. it's below the Nyquist frequency and hence ignored
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , ));
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , ));
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , ));
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , ));
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , )); openvdb::tools::ParticlesToLevelSet<openvdb::FloatGrid> raster(*density_grid);
raster.rasterizeTrails(pa, 0.75);//scale offset between two instances // always prune to produce a valid narrow-band level set.
raster.finalize(true); density_grid->setGridClass(openvdb::GRID_LEVEL_SET);
density_grid->setName("density");
convertToVolume(density_grid); // Create a VDB file object.
openvdb::io::File file("mygrids.vdb");
// Add the grid pointer to a container.
openvdb::GridPtrVec grids;
grids.push_back(density_grid); // Write out the contents of the container.
file.write(grids);
file.close(); }

particles to volume

一个更好的方法Buiding the density.and write it out

// Note densityGrid allocation memory in this function and transform same as densityGrid
void buildingDensityGrid(openvdb::FloatGrid::Ptr &densityGrid,
openvdb::math::Transform::Ptr &transform,MyParticleList &pa,bool isRasterToSphere = true)
{
float backGround = 0.1f;
float voxelSize = 0.1;
transform = openvdb::math::Transform::createLinearTransform(voxelSize);
densityGrid = openvdb::FloatGrid::create(backGround);
std::cout << "set density grid class type\n";
densityGrid->setGridClass(openvdb::GRID_LEVEL_SET);
densityGrid->setTransform(transform);
openvdb::tools::ParticlesToLevelSet<openvdb::FloatGrid> raster(*densityGrid);
if(isRasterToSphere)
{
raster.rasterizeSpheres(pa,pa.mRadiusScale);
} else{
raster.rasterizeTrails(pa,0.75);
}
raster.finalize(true);
std::cout << "raster to end\n";
} int main()
{
MyParticleList pa(,);
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , ));
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , ));
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , ));
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , ));
pa.add(openvdb::Vec3R( , , ), , openvdb::Vec3R( , , )); openvdb::FloatGrid::Ptr densityGrid;
openvdb::math::Transform::Ptr transform;
buildingDensityGrid(densityGrid,transform,pa);
densityGrid->setName("density");
convertToVolume(densityGrid); // Create a VDB file object.
std::cout << "write vdb \n";
openvdb::io::File file("mygrids.vdb");
// Add the grid pointer to a container.
openvdb::GridPtrVec grids;
grids.push_back(densityGrid);
// Write out the contents of the container.
file.write(grids);
file.close(); }

接下来VelocityBuilding,直接写了个包裹库,并且在houdini测试了下openvdb::Vec3sGrid的运动模糊。

GLY_OpenVdbWrapper.h

//
// Created by gearslogy on 4/13/17.
// #ifndef ARNOLDVDBPOINTS_GLY_OPENVDBWAPPER_H
#define ARNOLDVDBPOINTS_GLY_OPENVDBWAPPER_H #include <memory>
#include <openvdb/openvdb.h>
#include <openvdb/tools/ParticlesToLevelSet.h>
#include <openvdb/tools/LevelSetUtil.h>
#include <openvdb/tools/TopologyToLevelSet.h> // DEFINE OUR PARTICLES STRUCT
namespace TopVertex
{ struct MyParticle
{
openvdb::Vec3R p, v;
openvdb::Real r; // per particle has own radius
}; class MyParticleList
{
// change protected to the public,direct find the mRadiusScale,mVelocityScale
public:
openvdb::Real mRadiusScale;
openvdb::Real mVelocityScale;
std::vector<MyParticle> mParticleList;
typedef openvdb::Vec3R PosType;
MyParticleList(openvdb::Real rScale=, openvdb::Real vScale=)
: mRadiusScale(rScale), mVelocityScale(vScale) {}
void add(const openvdb::Vec3R &p, const openvdb::Real &r,
const openvdb::Vec3R &v=openvdb::Vec3R(,,))
{
MyParticle pa;
pa.p = p;
pa.r = r;
pa.v = v;
mParticleList.push_back(pa);
}
/// @return coordinate bbox in the space of the specified transfrom
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 = /grid.voxelSize()[];
for (size_t n=, 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=; i<; ++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;
}
//typedef int AttributeType;
// The methods below are only required for the unit-tests
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;} //////////////////////////////////////////////////////////////////////////////
/// The methods below are the only ones required by tools::ParticleToLevelSet
/// @note We return by value since the radius and velocities are modified
/// by the scaling factors! Also these methods are all assumed to
/// be thread-safe. /// Return the total number of particles in list.
/// Always required!
size_t size() const { return mParticleList.size(); } /// Get the world space position of n'th particle.
/// Required by ParticledToLevelSet::rasterizeSphere(*this,radius).
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;
}
// The method below is only required for attribute transfer
void getAtt(size_t n, openvdb::Index32& att) const { att = openvdb::Index32(n); }
}; } //
namespace TopVertex
{
class GLY_OpenVdbWrapper
{
public:
// Rater point parm
struct RasterParms
{
float backGround;
float voxelSize;
float halfWidth;
}; // define some variable type
using Ptr = std::shared_ptr<GLY_OpenVdbWrapper>;
using RasterT = openvdb::tools::ParticlesToLevelSet<openvdb::FloatGrid, openvdb::Index32>;
enum POINT_RASTER_TYPE{RS_Sphere=0x0,RS_trailer=0x1}; // define a static pointer to our class
static GLY_OpenVdbWrapper* creator(); //
GLY_OpenVdbWrapper();
~GLY_OpenVdbWrapper(); // SAMPLE POINTS API
void samplePointsSetPoints(const std::vector<openvdb::Vec3R> &posList);
void samplePointsSetPoints(double *array,int rawSize);
void samplePointsSetRadius(double *array,int rawSize);
void samplePointsSetRadius(const std::vector<openvdb::Real> &radiusList);
void samplePointsSetVelocity(const std::vector<openvdb::Vec3R> &vel);
void samplePointsSetVelocity(double *array,int rawsize);
void samplePointsSetRadiusScale(double radius);
void samplePointsSetVelocityScale(double v);
void samplePointsAppendPoint(openvdb::Vec3R p,openvdb::Vec3R v,openvdb::Real radius);
void samplePointsRasterDensityGrid(POINT_RASTER_TYPE type,openvdb::FloatGrid::Ptr &gridPtr,RasterParms &rasterParm);
void samplePointsRasterVelocityGrid(openvdb::math::Transform::Ptr &density_transform,openvdb::Vec3SGrid::Ptr &velocityGrid); private:
class SamplePoints;
std::unique_ptr<SamplePoints> mPimplSamplePoints;
};
} #endif //ARNOLDVDBPOINTS_GLY_OPENVDBWAPPER_H

GLY_OpenVdbWrapper.cpp

//
// Created by gearslogy on 4/13/17.
// #include "GLY_OpenVdbWrapper.h"
#include <assert.h>
#include <algorithm>
using namespace TopVertex; //=======================================SamplePoints details=================================
//
class GLY_OpenVdbWrapper::SamplePoints
{
public:
SamplePoints():mParticleListPtr(new MyParticleList(,))
{
}
~SamplePoints()
{
std::cout << "Release SamplePoints memory\n";
}
void setRadiusScale(double radius)
{
mParticleListPtr->mRadiusScale = radius;
}
void setVelocityScale(double v)
{
mParticleListPtr->mVelocityScale = v;
} void setPoints(const std::vector<openvdb::Vec3R> &posList)
{
auto &pa = mParticleListPtr->mParticleList;
pa.resize(posList.size());
for(int i=;i<posList.size();i++)
{
pa[i].p = posList[i];
}
}
void setPoints(double *array,int rawsize)
{
assert(rawsize%==);
auto &pa = mParticleListPtr->mParticleList;
pa.resize(rawsize/);
for(int i=;i<rawsize/;i++)
{
double x = array[i];
double y = array[i+];
double z = array[i+];
auto t = openvdb::Vec3R(x,y,z);
pa[i].p = t;
}
}
void setRadius(const std::vector<openvdb::Real> &radiusList)
{
assert(radiusList.size()==mParticleListPtr->mParticleList.size());
auto &pa = mParticleListPtr->mParticleList;
for(int i=;i<pa.size();i++)
{
pa[i].r = radiusList[i];
}
}
void setRadius(double *array,int pointsNum)
{
assert(pointsNum==mParticleListPtr->mParticleList.size());
auto &pa = mParticleListPtr->mParticleList;
for(int i=;i<pa.size();i++)
{
pa[i].r = array[i];
}
}
void setVelocity(const std::vector<openvdb::Vec3R> &vel)
{
assert(vel.size() == mParticleListPtr->mParticleList.size());
auto &pa = mParticleListPtr->mParticleList;
for(int i=;i<vel.size();i++)
{
pa[i].v = vel[i];
}
}
void setVelocity(double *array,int rawsize)
{
assert(rawsize%==);
auto &pa = mParticleListPtr->mParticleList;
for(int i=;i<rawsize/;i++)
{
double x = array[i];
double y = array[i+];
double z = array[i+];
auto t = openvdb::Vec3R(x,y,z);
pa[i].v = t;
}
}
void appendPoint(openvdb::Vec3R p,openvdb::Vec3R v,openvdb::Real radius)
{
mParticleListPtr->add(p,radius,v);
}
void clearPoints(){mParticleListPtr->mParticleList.clear();}
void rasterDensity(POINT_RASTER_TYPE type,openvdb::FloatGrid::Ptr &gridPtr,RasterParms &rasterParm)
{ std::cout << "Start process samplePoints Raster Density\n";
float backGround = rasterParm.backGround;
float voxelSize = rasterParm.voxelSize;
float halfWidth = rasterParm.halfWidth;
openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(voxelSize);
//gridPtr = openvdb::FloatGrid::create(backGround); //this is simple and can work
gridPtr = openvdb::createLevelSet<openvdb::FloatGrid>(voxelSize, halfWidth); gridPtr->setGridClass(openvdb::GRID_LEVEL_SET);
gridPtr->setTransform(transform);
openvdb::tools::ParticlesToLevelSet<openvdb::FloatGrid,openvdb::Index> raster(*gridPtr);
if(type==0x0) // RS_Sphere
{
raster.rasterizeSpheres(*mParticleListPtr);
} else
{
raster.rasterizeTrails(*mParticleListPtr,0.75);
}
raster.finalize(true);
openvdb::tools::sdfToFogVolume(*gridPtr);
gridPtr->setName("density");
mId=raster.attributeGrid();
} void rasterVelocityGrid(openvdb::math::Transform::Ptr &density_transform,openvdb::Vec3SGrid::Ptr &gridPtr)
{
typedef typename openvdb::Int32Grid::TreeType::ValueConverter<openvdb::Vec3s >::Type TreeTypeWarpVec;
typedef typename openvdb::Grid<TreeTypeWarpVec> GridType;
typename TreeTypeWarpVec::Ptr tree(
new TreeTypeWarpVec(mId->tree(), openvdb::Vec3s(,,) , openvdb::TopologyCopy()));
//typename GridType::Ptr velocity_grid(GridType::create(tree)); //为grid开辟内存*/ gridPtr = openvdb::Vec3SGrid::create(tree);
gridPtr->setVectorType(openvdb::VecType());
// MY Method
openvdb::Coord ijk;
openvdb::Vec3SGrid::Accessor vel_accessor = gridPtr->getAccessor();
for(auto iter = mId->beginValueOn();iter.test();++iter)
{
auto d = *iter;
//std::cout << " D:..." <<d <<std::endl;
ijk = iter.getCoord();
openvdb::math::Vec3s vel = mParticleListPtr->vel(d);
vel*=;
vel_accessor.setValue(ijk,vel); }
gridPtr->setName("vel");
gridPtr->setTransform(density_transform);
} private:
std::unique_ptr<MyParticleList > mParticleListPtr;
RasterT::AttGridType::Ptr mId; //remeber the id of point in voxel
}; // //============================================GLY_OpenVdbWrapper==================================================
// GLY_OpenVdbWrapper Details GLY_OpenVdbWrapper::GLY_OpenVdbWrapper():mPimplSamplePoints(new GLY_OpenVdbWrapper::SamplePoints())
{
}
GLY_OpenVdbWrapper::~GLY_OpenVdbWrapper()
{
std::cout << "Release Wrapper memory\n";
}
void GLY_OpenVdbWrapper::samplePointsSetPoints(const std::vector<openvdb::Vec3R> &posList)
{
mPimplSamplePoints->setPoints(posList);
}
void GLY_OpenVdbWrapper::samplePointsSetPoints(double *array,int rawSize)
{
mPimplSamplePoints->setPoints(array,rawSize);
}
void GLY_OpenVdbWrapper::samplePointsSetRadius(double *array, int rawSize) {
mPimplSamplePoints->setRadius(array,rawSize);
}
void GLY_OpenVdbWrapper::samplePointsSetRadius(const std::vector<openvdb::Real> &radiusList) {
mPimplSamplePoints->setRadius(radiusList);
}
void GLY_OpenVdbWrapper::samplePointsSetVelocity(const std::vector<openvdb::Vec3R> &vel) {
mPimplSamplePoints->setVelocity(vel);
}
void GLY_OpenVdbWrapper::samplePointsSetVelocity(double *array, int rawsize) {
mPimplSamplePoints->setVelocity(array,rawsize);
}
void GLY_OpenVdbWrapper::samplePointsSetRadiusScale(double radius) {
mPimplSamplePoints->setRadiusScale(radius);
}
void GLY_OpenVdbWrapper::samplePointsSetVelocityScale(double v) {
mPimplSamplePoints->setVelocityScale(v);
}
void GLY_OpenVdbWrapper::samplePointsAppendPoint(openvdb::Vec3R p, openvdb::Vec3R v, openvdb::Real radius)
{
mPimplSamplePoints->appendPoint(p,v,radius);
}
GLY_OpenVdbWrapper* GLY_OpenVdbWrapper::creator() {
return new GLY_OpenVdbWrapper;
}
void GLY_OpenVdbWrapper::samplePointsRasterDensityGrid(POINT_RASTER_TYPE type, openvdb::FloatGrid::Ptr &gridPtr,
RasterParms &rasterParm) {
mPimplSamplePoints->rasterDensity(type,gridPtr,rasterParm);
}
void GLY_OpenVdbWrapper::samplePointsRasterVelocityGrid(openvdb::math::Transform::Ptr &density_transform,
openvdb::Vec3SGrid::Ptr &velocityGrid)
{
mPimplSamplePoints->rasterVelocityGrid(density_transform,velocityGrid);
}

main.cpp:

//
// Created by gearslogy on 4/14/17.
// #include "GLY_OpenVdbWrapper.h"
using namespace std;
using namespace TopVertex;
int main()
{
GLY_OpenVdbWrapper::Ptr wrapper(GLY_OpenVdbWrapper::creator());
wrapper->samplePointsAppendPoint(openvdb::Vec3R(, , ), openvdb::Vec3R( , , ) ,);
wrapper->samplePointsAppendPoint(openvdb::Vec3R(, , ), openvdb::Vec3R( , , ) ,1.5);
wrapper->samplePointsAppendPoint(openvdb::Vec3R(, , ), openvdb::Vec3R( , , ) ,2.0);
wrapper->samplePointsAppendPoint(openvdb::Vec3R(, , ), openvdb::Vec3R( , , ) ,2.5);
wrapper->samplePointsAppendPoint(openvdb::Vec3R(, , ), openvdb::Vec3R( , , ) ,3.0); // create grid named "density"
openvdb::FloatGrid::Ptr densityGrid;
GLY_OpenVdbWrapper::RasterParms parms;
parms.backGround = 0.1;
parms.voxelSize = 0.1;
parms.halfWidth = 0.5;
wrapper->samplePointsRasterDensityGrid(GLY_OpenVdbWrapper::RS_Sphere,densityGrid,parms); // Create velocity Grid "velocity"
openvdb::Vec3SGrid::Ptr velocityGrid;
auto densityTransform = densityGrid->transformPtr();
wrapper->samplePointsRasterVelocityGrid(densityTransform,velocityGrid); // IO Operator
openvdb::io::File file("mygrids.vdb");
openvdb::GridPtrVec grids;
grids.push_back(densityGrid);
grids.push_back(velocityGrid);
file.write(grids);
file.close(); }

Test plugin for katana:

Update katana plugin:

升级了光线求交,直接快的飞起来

Arnold粒子体积渲染(Arnold particles volume rendering):

插件loading模式:AlembicAPI->OpenvdbAPI->ArnoldAPI

然后KatanaAPI再写个插件 读取这个ArnoldAPI写出来的proc,

update volume:

重要的事情不说两遍,static 关键字在一个so上被一个进程,2个instance调用,全局的static object内存地址是他妈一样的,也就是说是共享的地址。会导致你假如创建两个instance,你却希望有两份不一样的全局变量内容,结果,太感人了,确实是错的,是一样的。

如果独立进程,独立instance调用so上的全局变量,ok没问题。

Rendering the cd field:

VDB R&D的更多相关文章

  1. openstack搭建之-cinder配置(12)

    一. base节点配置 mysql -u root -proot CREATE DATABASE cinder; GRANT ALL PRIVILEGES ON cinder.* TO 'cinder ...

  2. openstack实验环境搭建

    Openstack实验文档 一.base节点 1.1配置网络 vim /etc/sysconfig/network-scripts/ifcfg-eth0 1.2关闭防火墙和selinux system ...

  3. S1_搭建分布式OpenStack集群_10 cinder 存储节点配置

    一.安装配置lvm2安装LVM包:# yum install -y lvm2 启动LVM元数据服务,并将其配置为在系统启动时启动:# systemctl enable lvm2-lvmetad.ser ...

  4. [原]CentOS7安装Rancher2.1并部署kubernetes (二)---部署kubernetes

    ##################    Rancher v2.1.7  +    Kubernetes 1.13.4  ################ ##################### ...

  5. 利用python进行数据分析2_数据采集与操作

    txt_filename = './files/python_baidu.txt' # 打开文件 file_obj = open(txt_filename, 'r', encoding='utf-8' ...

  6. Django项目:CRM(客户关系管理系统)--81--71PerfectCRM实现CRM项目首页

    {#portal.html#} {## ————————46PerfectCRM实现登陆后页面才能访问————————#} {#{% extends 'king_admin/table_index.h ...

  7. 【翻译】Awesome R资源大全中文版来了,全球最火的R工具包一网打尽,超过300+工具,还在等什么?

    0.前言 虽然很早就知道R被微软收购,也很早知道R在统计分析处理方面很强大,开始一直没有行动过...直到 直到12月初在微软技术大会,看到我软的工程师演示R的使用,我就震惊了,然后最近在网上到处了解和 ...

  8. 应用r.js来优化你的前端

    r.js是requireJS的优化(Optimizer)工具,可以实现前端文件的压缩与合并,在requireJS异步按需加载的基础上进一步提供前端优化,减小前端文件大小.减少对服务器的文件请求.要使用 ...

  9. 使用R画地图数据

    用R画地图数据 首先,从这里下载中国地图的GIS数据,这是一个压缩包,完全解压后包含三个文件(bou2_4p.dbf.bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下. ...

随机推荐

  1. Pyhton对象解释

    python的docstring提供了对每一个类.函数.方法的解释,在他们的定义下面可以有一行Python的标准字符串,该行字符串需要和下面的代码一样的缩进. docstring可以用单引号(')或者 ...

  2. jmeter中判断数据库是否存在相应的记录

    jmeter判断数据库中是否存在相应记录可以使用count 配合case,然后再加个断言,后面用 变量JMeterThread.last_sample_ok来判断是否存在相应记录 select cas ...

  3. Kafka技术内幕 读书笔记之(四) 新消费者——新消费者客户端(二)

    消费者拉取消息 消费者创建拉取请求的准备工作,和生产者创建生产请求的准备工作类似,它们都必须和分区的主副本交互.一个生产者写入的分区和消费者分配的分区都可能有多个,同时多个分区的主副本有可能在同一个节 ...

  4. mssql的 for xml path 与 mysql中的group_concat类似MSSQL For xml Path

    /****** Script for SelectTopNRows command from SSMS ******/ SELECT D_ID,[D_Name] as Name FROM [LFBMP ...

  5. HDU - 5119 Happy Matt Friends(dp)

    题目链接 题意:n个数,你可以从中选一些数,也可以不选,选出来的元素的异或和大于m时,则称满足情况.问满足情况的方案数为多少. 分析:本来以为是用什么特殊的数据结构来操作,没想到是dp,还好队友很强. ...

  6. hbase 实战项目

    首先 根据 hadoop 搭建 + hbase 搭建把 环境弄好 由于 hbase 依赖于 hdfs ,所以 需要 进入 hadoop -->sbin 下 启动 start-dfs.sh , s ...

  7. Python线程和协程-day10

    写在前面 上课第10天,打卡: 感谢Egon老师细致入微的讲解,的确有学到东西! 一.线程 1.关于线程的补充 线程:就是一条流水线的执行过程,一条流水线必须属于一个车间: 那这个车间的运行过程就是一 ...

  8. ASP.NET Web API 2 之参数验证

    Ø  前言 目前 C# 比较流行使用 ASP.NET Web API 来承载 Web 接口,提供与客户端之间的数据交互,现在的版本已经是 2.0 了.既然是接口就少不了对输入参数的验证,所以本文主要探 ...

  9. Javascript async异步操作库简介

    异步操作知识 在js世界中, 异步操作非常流行, nodejs就是特点基于异步非阻塞. js语言支持的异步语法包括, Promise  async await generator yield. 这些语 ...

  10. faster rcnn 做识别

    faster rcnn 主要分为四个部分: 1. convolutional part: 特征提取 可以使用vgg,resnet 等等 2.region proposal network: 生成 re ...