18#ifndef OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED 
   19#define OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED 
   48template<
typename Gr
idT>
 
   52              size_t pixelSamples = 1,
 
   53              unsigned int seed = 0,
 
   54              bool threaded = 
true);
 
   57template<
typename Gr
idT, 
typename IntersectorT>
 
   62              size_t pixelSamples = 1,
 
   63              unsigned int seed = 0,
 
   64              bool threaded = 
true);
 
   71template<
typename Gr
idT, 
typename IntersectorT = tools::LevelSetRayIntersector<Gr
idT> >
 
   76    using Vec3Type = 
typename IntersectorT::Vec3Type;
 
   77    using RayType = 
typename IntersectorT::RayType;
 
   83                      size_t pixelSamples = 1,
 
   84                      unsigned int seed = 0);
 
   91                      size_t pixelSamples = 1,
 
   92                      unsigned int seed = 0);
 
  101    void setGrid(
const GridT& grid);
 
  130    void operator()(
const tbb::blocked_range<size_t>& range) 
const;
 
  133    const bool                          mIsMaster;
 
  136    std::unique_ptr<const BaseShader>   mShader;
 
 
  148template <
typename IntersectorT, 
typename SamplerT = tools::BoxSampler>
 
  154    using RayType = 
typename IntersectorT::RayType;
 
  158    static_assert(std::is_floating_point<ValueType>::value,
 
  159        "VolumeRender requires a floating-point-valued grid");
 
  175    void setIntersector(
const IntersectorT& inter);
 
  207    void print(std::ostream& os = std::cout, 
int verboseLevel = 1);
 
  211    void operator()(
const tbb::blocked_range<size_t>& range) 
const;
 
  215    AccessorType mAccessor;
 
  217    std::unique_ptr<IntersectorT> mPrimary, mShadow;
 
  218    Real  mPrimaryStep, mShadowStep, mCutOff, mLightGain;
 
  219    Vec3R mLightDir, mLightColor, mAbsorption, mScattering;
 
 
  236        explicit RGBA(
ValueT intensity) : 
r(intensity), 
g(intensity), 
b(intensity), 
a(1) {}
 
  238            r(_r), 
g(_g), 
b(_b), 
a(_a)
 
 
  240        RGBA(
double _r, 
double _g, 
double _b, 
double _a = 1.0)
 
 
  254            const float s = rhs.
a*(1.0f-
a);
 
 
 
  279        return mPixels[w + h*mWidth];
 
 
  286        return mPixels[w + h*mWidth];
 
 
  289    void fill(
const RGBA& rgb=
RGBA(0)) { 
for (
size_t i=0; i<mSize; ++i) mPixels[i] = rgb; }
 
  292        RGBA *p = mPixels.get();
 
  293        for (
size_t j = 0; j < mHeight; ++j) {
 
  294            for (
size_t i = 0; i < mWidth; ++i, ++p) {
 
  295                *p = ((i & size) ^ (j & size)) ? c1 : c2;
 
 
  300    template <
typename Type = 
unsigned char>
 
  303        const size_t totalSize = mSize * (alpha ? 4 : 3);
 
  304        std::unique_ptr<Type[]> buffer(
new Type[totalSize]);
 
  305        Type *q = buffer.get();
 
  309            *q++ = 
static_cast<Type>(255.0f*(*p).r);
 
  310            *q++ = 
static_cast<Type>(255.0f*(*p).g);
 
  311            *q++ = 
static_cast<Type>(255.0f*(*p).b);
 
  313                *q++ = 
static_cast<Type>(255.0f*(*p).a);
 
 
  321        std::string name(fileName);
 
  322        if (name.find_last_of(
".") == std::string::npos) name.append(
".ppm");
 
  324        std::ofstream os(name.c_str(), std::ios_base::binary);
 
  326            std::cerr << 
"Error opening PPM file \"" << name << 
"\"" << std::endl;
 
  331        unsigned char* tmp = buf.get();
 
  333        os << 
"P6\n" << mWidth << 
" " << mHeight << 
"\n255\n";
 
  334        os.write(
reinterpret_cast<const char*
>(&(*tmp)), 3 * mSize * 
sizeof(
unsigned char));
 
 
  337    size_t width()
       const { 
return mWidth; }
 
  338    size_t height()
      const { 
return mHeight; }
 
  343    size_t mWidth, mHeight, mSize;
 
  344    std::unique_ptr<RGBA[]> mPixels;
 
 
  355               double frameWidth, 
double nearPlane, 
double farPlane)
 
  365        this->
initRay(nearPlane, farPlane);
 
 
  382        const Vec3R dir  = orig - xyz;
 
 
  401        size_t i, 
size_t j, 
double iOffset = 0.5, 
double jOffset = 0.5) 
const = 0;
 
  406        mRay.setTimes(t0, t1);
 
 
 
  439                      double focalLength = 50.0,
 
  440                      double aperture    = 41.2136,
 
  441                      double nearPlane   = 1e-3,
 
  442                      double farPlane    = std::numeric_limits<double>::max())
 
  443        : 
BaseCamera(film, rotation, translation, 0.5*aperture/focalLength, nearPlane, farPlane)
 
 
  453        size_t i, 
size_t j, 
double iOffset = 0.5, 
double jOffset = 0.5)
 const override 
 
 
  497                       double frameWidth = 1.0,
 
  498                       double nearPlane  = 1e-3,
 
  499                       double farPlane   = std::numeric_limits<double>::max())
 
  500        : 
BaseCamera(film, rotation, translation, 0.5*frameWidth, nearPlane, farPlane)
 
 
  506        size_t i, 
size_t j, 
double iOffset = 0.5, 
double jOffset = 0.5)
 const override 
 
 
  547    MatteShader(
const GridT& grid) : mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
 
  553        SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
 
 
  559    typename GridT::ConstAccessor mAcc;
 
 
  564template<
typename SamplerType>
 
  589template<
typename GridT = Film::RGBA,
 
  594    NormalShader(
const GridT& grid) : mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
 
  600        SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
 
  601        return Film::RGBA(v[0]*(normal[0]+1.0), v[1]*(normal[1]+1.0), v[2]*(normal[2]+1.0));
 
 
  606    typename GridT::ConstAccessor mAcc;
 
 
  611template<
typename SamplerType>
 
  620        return mRGBA * 
Film::RGBA(normal[0] + 1.0, normal[1] + 1.0, normal[2] + 1.0);
 
 
 
  636template<
typename GridT = Film::RGBA,
 
  643        , mInvDim(1.0/bbox.extents())
 
  644        , mAcc(grid.getAccessor())
 
  645        , mXform(&grid.transform())
 
 
  653        SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
 
  654        const Vec3R rgb = (xyz - mMin) * mInvDim;
 
 
  660    const Vec3R mMin, mInvDim;
 
  661    typename GridT::ConstAccessor mAcc;
 
 
  666template<
typename SamplerType>
 
  671        : mMin(bbox.min()), mInvDim(1.0/bbox.extents()), mRGBA(c) {}
 
 
  676        const Vec3R rgb = (xyz - mMin)*mInvDim;
 
  677        return mRGBA*
Film::RGBA(rgb[0], rgb[1], rgb[2]);
 
 
  682    const Vec3R mMin, mInvDim;
 
 
  696template<
typename GridT = Film::RGBA,
 
  701    DiffuseShader(
const GridT& grid): mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
 
  707        SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
 
 
  716    typename GridT::ConstAccessor mAcc;
 
 
  721template <
typename SamplerType>
 
  750template<
typename Gr
idT>
 
  759        tracer(grid, shader, camera, pixelSamples, seed);
 
 
  764template<
typename Gr
idT, 
typename IntersectorT>
 
  766              const IntersectorT& inter,
 
 
  781template<
typename Gr
idT, 
typename IntersectorT>
 
  791      mShader(shader.copy()),
 
 
  797template<
typename Gr
idT, 
typename IntersectorT>
 
  807      mShader(shader.copy()),
 
 
  813template<
typename Gr
idT, 
typename IntersectorT>
 
  818    mInter(other.mInter),
 
  819    mShader(other.mShader->copy()),
 
  820    mCamera(other.mCamera),
 
  821    mSubPixels(other.mSubPixels)
 
 
  825template<
typename Gr
idT, 
typename IntersectorT>
 
  829    if (mIsMaster) 
delete [] mRand;
 
 
  832template<
typename Gr
idT, 
typename IntersectorT>
 
  837    mInter = IntersectorT(grid);
 
 
  840template<
typename Gr
idT, 
typename IntersectorT>
 
  848template<
typename Gr
idT, 
typename IntersectorT>
 
  853    mShader.reset(shader.
copy());
 
 
  856template<
typename Gr
idT, 
typename IntersectorT>
 
  864template<
typename Gr
idT, 
typename IntersectorT>
 
  869    if (pixelSamples == 0) {
 
  872    mSubPixels = pixelSamples - 1;
 
  874    if (mSubPixels > 0) {
 
  875        mRand = 
new double[16];
 
  877        for (
size_t i=0; i<16; ++i) mRand[i] = rand();
 
 
  883template<
typename Gr
idT, 
typename IntersectorT>
 
  887    tbb::blocked_range<size_t> range(0, mCamera->height());
 
  888    threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
 
 
  891template<
typename Gr
idT, 
typename IntersectorT>
 
  893operator()(
const tbb::blocked_range<size_t>& range)
 const 
  897    const float frac = 1.0f / (1.0f + float(mSubPixels));
 
  898    for (
size_t j=range.begin(), n=0, je = range.end(); j<je; ++j) {
 
  899        for (
size_t i=0, ie = mCamera->width(); i<ie; ++i) {
 
  901            RayType ray = mCamera->getRay(i, j);
 
  902            Film::RGBA c = mInter.intersectsWS(ray, xyz, nml) ? shader(xyz, nml, ray.dir()) : bg;
 
  903            for (
size_t k=0; k<mSubPixels; ++k, n +=2 ) {
 
  904                ray = mCamera->getRay(i, j, mRand[n & 15], mRand[(n+1) & 15]);
 
  905                c += mInter.intersectsWS(ray, xyz, nml) ? shader(xyz, nml, ray.dir()) : bg;
 
 
  914template<
typename IntersectorT, 
typename SampleT>
 
  917    : mAccessor(inter.grid().getConstAccessor())
 
  919    , mPrimary(new IntersectorT(inter))
 
  920    , mShadow(new IntersectorT(inter))
 
  925    , mLightDir(
Vec3R(0.3, 0.3, 0).unit())
 
  926    , mLightColor(0.7, 0.7, 0.7)
 
 
  932template<
typename IntersectorT, 
typename SampleT>
 
  935    : mAccessor(other.mAccessor)
 
  936    , mCamera(other.mCamera)
 
  937    , mPrimary(new IntersectorT(*(other.mPrimary)))
 
  938    , mShadow(new IntersectorT(*(other.mShadow)))
 
  939    , mPrimaryStep(other.mPrimaryStep)
 
  940    , mShadowStep(other.mShadowStep)
 
  941    , mCutOff(other.mCutOff)
 
  942    , mLightGain(other.mLightGain)
 
  943    , mLightDir(other.mLightDir)
 
  944    , mLightColor(other.mLightColor)
 
  945    , mAbsorption(other.mAbsorption)
 
  946    , mScattering(other.mScattering)
 
 
  950template<
typename IntersectorT, 
typename SampleT>
 
  952print(std::ostream& os, 
int verboseLevel)
 
  954    if (verboseLevel>0) {
 
  955        os << 
"\nPrimary step: " <<  mPrimaryStep
 
  956           << 
"\nShadow step: " << mShadowStep
 
  957           << 
"\nCutoff: " << mCutOff
 
  958           << 
"\nLightGain: " << mLightGain
 
  959           << 
"\nLightDir: " << mLightDir
 
  960           << 
"\nLightColor: " << mLightColor
 
  961           << 
"\nAbsorption: " << mAbsorption
 
  962           << 
"\nScattering: " << mScattering << std::endl;
 
  964    mPrimary->print(os, verboseLevel);
 
 
  967template<
typename IntersectorT, 
typename SampleT>
 
  971    mPrimary.reset(
new IntersectorT(inter));
 
  972    mShadow.reset( 
new IntersectorT(inter));
 
 
  975template<
typename IntersectorT, 
typename SampleT>
 
  979    tbb::blocked_range<size_t> range(0, mCamera->height());
 
  980    threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
 
 
  983template<
typename IntersectorT, 
typename SampleT>
 
  985operator()(
const tbb::blocked_range<size_t>& range)
 const 
  987    SamplerType sampler(mAccessor, mShadow->grid().transform());
 
  990    const Vec3R extinction = -mScattering-mAbsorption, One(1.0);
 
  991    const Vec3R albedo = mLightColor*mScattering/(mScattering+mAbsorption);
 
  992    const Real sGain = mLightGain;
 
  993    const Real pStep = mPrimaryStep;
 
  994    const Real sStep = mShadowStep;
 
  995    const Real cutoff = mCutOff;
 
 1004    std::vector<typename RayType::TimeSpan> pTS, sTS;
 
 1009    for (
size_t j=range.begin(), je = range.end(); j<je; ++j) {
 
 1010        for (
size_t i=0, ie = mCamera->width(); i<ie; ++i) {
 
 1012            bg.
a = bg.
r = bg.
g = bg.
b = 0;
 
 1013            RayType pRay = mCamera->getRay(i, j);
 
 1014            if( !mPrimary->setWorldRay(pRay)) 
continue;
 
 1015            Vec3R pTrans(1.0), pLumi(0.0);
 
 1018            while (mPrimary->march(pT0, pT1)) {
 
 1019                for (
Real pT = pStep*ceil(pT0/pStep); pT <= pT1; pT += pStep) {
 
 1021            mPrimary->hits(pTS);
 
 1022            for (
size_t k=0; k<pTS.size(); ++k) {
 
 1023                Real pT = pStep*ceil(pTS[k].t0/pStep), pT1=pTS[k].t1;
 
 1024                for (; pT <= pT1; pT += pStep) {
 
 1026                    Vec3R pPos = mPrimary->getWorldPos(pT);
 
 1028                    if (density < cutoff) 
continue;
 
 1032                    if( !mShadow->setWorldRay(sRay)) 
continue;
 
 1035                    while (mShadow->march(sT0, sT1)) {
 
 1036                        for (
Real sT = sStep*ceil(sT0/sStep); sT <= sT1; sT+= sStep) {
 
 1039                    for (
size_t l=0; l<sTS.size(); ++l) {
 
 1040                        Real sT = sStep*ceil(sTS[l].t0/sStep), sT1=sTS[l].t1;
 
 1041                        for (; sT <= sT1; sT+= sStep) {
 
 1043                            const Real d = sampler.
wsSample(mShadow->getWorldPos(sT));
 
 1044                            if (d < cutoff) 
continue;
 
 1045                            sTrans *= 
math::Exp(extinction * d * sStep/(1.0+sT*sGain));
 
 1046                            if (sTrans.
lengthSqr()<cutoff) 
goto Luminance;
 
 1050                    pLumi += albedo * sTrans * pTrans * (One-dT);
 
 1052                    if (pTrans.lengthSqr()<cutoff) 
goto Pixel;  
 
 
 1070#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 
 1072#ifdef OPENVDB_INSTANTIATE_RAYTRACER 
 1076#define _FUNCTION(TreeT) \ 
 1077    void rayTrace(const Grid<TreeT>&, const BaseShader&, BaseCamera&, size_t, unsigned int, bool) 
 1081#define _FUNCTION(TreeT) \ 
 1082    void rayTrace(const Grid<TreeT>&, const tools::LevelSetRayIntersector<Grid<TreeT>>&, const BaseShader&, BaseCamera&, size_t, unsigned int, bool) 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Accelerated intersection of a ray with a narrow-band level set or a generic (e.g. density) volume....
Definition Exceptions.h:65
A general linear transform using homogeneous coordinates to perform rotation, scaling,...
Definition Maps.h:296
Axis-aligned bounding box.
Definition BBox.h:24
void postTranslate(const Vec3< T0 > &tr)
Right multiplies by the specified translation matrix, i.e. (*this) * Trans.
Definition Mat4.h:714
Simple generator of random numbers over the range [0, 1)
Definition Math.h:167
const Vec3T & dir() const
Definition Ray.h:100
void setEye(const Vec3Type &eye)
Definition Ray.h:65
void setDir(const Vec3Type &dir)
Definition Ray.h:67
void scaleTimes(RealT scale)
Definition Ray.h:85
T dot(const Vec3< T > &v) const
Dot product.
Definition Vec3.h:192
T lengthSqr() const
Definition Vec3.h:212
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition Vec3.h:363
constexpr T pi()
Pi constant taken from Boost to match old behaviour.
Definition Math.h:119
Type Exp(const Type &x)
Return ex.
Definition Math.h:710
Coord Abs(const Coord &xyz)
Definition Coord.h:518
Mat4< double > Mat4d
Definition Mat4.h:1355
MatType aim(const Vec3< typename MatType::value_type > &direction, const Vec3< typename MatType::value_type > &vertical)
Return an orientation matrix such that z points along direction, and y is along the direction / verti...
Definition Mat.h:726
@ Z_AXIS
Definition Math.h:904
@ X_AXIS
Definition Math.h:902
@ Y_AXIS
Definition Math.h:903
double Real
Definition Types.h:60
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
math::Vec3< Real > Vec3R
Definition Types.h:72
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:158
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition version.h.in:162