zoukankan      html  css  js  c++  java
  • VDB R&D

    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[0];
        int &j = ijk[1];
        int &k = ijk[2];
        for (i = c[0] - dim; i < c[0] + dim; ++i) {
            const float x2 = openvdb::math::Pow2(i - c[0]);
            for (j = c[1] - dim; j < c[1] + dim; ++j) {
                const float x2y2 = openvdb::math::Pow2(j - c[1]) + x2;
                for (k = c[2] - dim; k < c[2] + dim; ++k) {
                    // The distance from the sphere surface in voxels
                    const float dist = openvdb::math::Sqrt(x2y2
                                                           + openvdb::math::Pow2(k - c[2])) - 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(0);
                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, 2, 3));
        // 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
    ";
        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 0;
    }

    <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=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))
        {
            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 = 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;
        }
        //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(1,1); // 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( 0,  0,  0), 1, openvdb::Vec3R( 0, 0, 1));
        pa.add(openvdb::Vec3R( 0,  5,  0), 1, openvdb::Vec3R( 0, 0, 2));
        pa.add(openvdb::Vec3R( 0, 10,  0), 1, openvdb::Vec3R( 0, 0, 3));
        pa.add(openvdb::Vec3R( 0, 15,  0), 1, openvdb::Vec3R( 0, 0, 4));
        pa.add(openvdb::Vec3R( 0, 20,  0), 1, openvdb::Vec3R( 0, 0, 5));
    
        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
    ";
        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
    ";
    }
    
    
    int main()
    {
        MyParticleList pa(1,1);
        pa.add(openvdb::Vec3R( 0,  0,  0), 1, openvdb::Vec3R( 0, 0, 1));
        pa.add(openvdb::Vec3R( 0,  5,  0), 1, openvdb::Vec3R( 0, 0, 2));
        pa.add(openvdb::Vec3R( 0, 10,  0), 1, openvdb::Vec3R( 0, 0, 3));
        pa.add(openvdb::Vec3R( 0, 15,  0), 1, openvdb::Vec3R( 0, 0, 4));
        pa.add(openvdb::Vec3R( 0, 20,  0), 1, openvdb::Vec3R( 0, 0, 5));
    
        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 
    ";
        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();
    
    
    }
    View Code

    接下来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=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))
            {
                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 = 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;
            }
            //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(1,1))
        {
        }
        ~SamplePoints()
        {
            std::cout << "Release SamplePoints memory
    ";
        }
        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=0;i<posList.size();i++)
            {
                pa[i].p = posList[i];
            }
        }
        void setPoints(double *array,int rawsize)
        {
            assert(rawsize%3==0);
            auto &pa = mParticleListPtr->mParticleList;
            pa.resize(rawsize/3);
            for(int i=0;i<rawsize/3;i++)
            {
                double x = array[i];
                double y = array[i+1];
                double z = array[i+2];
                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=0;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=0;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=0;i<vel.size();i++)
            {
                pa[i].v = vel[i];
            }
        }
        void setVelocity(double *array,int rawsize)
        {
            assert(rawsize%3==0);
            auto &pa = mParticleListPtr->mParticleList;
            for(int i=0;i<rawsize/3;i++)
            {
                double x = array[i];
                double y = array[i+1];
                double z = array[i+2];
                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
    ";
            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(0,0,0) , openvdb::TopologyCopy()));
            //typename GridType::Ptr velocity_grid(GridType::create(tree)); //为grid开辟内存*/
    
            gridPtr = openvdb::Vec3SGrid::create(tree);
            gridPtr->setVectorType(openvdb::VecType(0));
            // 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*=140;
                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
    ";
    }
    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(0,  0,  0), openvdb::Vec3R( 0, 0, 1) ,1);
        wrapper->samplePointsAppendPoint(openvdb::Vec3R(0,  5,  0), openvdb::Vec3R( 0, 0, 2) ,1.5);
        wrapper->samplePointsAppendPoint(openvdb::Vec3R(0,  10,  0), openvdb::Vec3R( 0, 0, 3) ,2.0);
        wrapper->samplePointsAppendPoint(openvdb::Vec3R(0,  15,  0), openvdb::Vec3R( 0, 0, 4) ,2.5);
        wrapper->samplePointsAppendPoint(openvdb::Vec3R(0,  20,  0), openvdb::Vec3R( 0, 0, 5) ,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:

  • 相关阅读:
    域环境的搭建 (超级详细)
    sqli-labs(10)
    sqli-labs(9)
    mysql源码安装(5.1)
    查看mysql apache php nginx的编译参数
    LAMP的安装
    Mysql的安装(二进制免编译包) 5.1版本
    更改yum网易 阿里云的yum源。
    yum安裝的包如何保留到本地
    磁盘分区
  • 原文地址:https://www.cnblogs.com/gearslogy/p/6544003.html
Copyright © 2011-2022 走看看