44 #ifndef OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
45 #define OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
47 #include <openvdb/Types.h>
48 #include <openvdb/math/Ray.h>
49 #include <openvdb/math/Math.h>
50 #include <openvdb/tools/RayIntersector.h>
51 #include <boost/scoped_ptr.hpp>
54 #ifdef OPENVDB_TOOLS_RAYTRACER_USE_EXR
55 #include <OpenEXR/ImfPixelType.h>
56 #include <OpenEXR/ImfChannelList.h>
57 #include <OpenEXR/ImfOutputFile.h>
58 #include <OpenEXR/ImfHeader.h>
59 #include <OpenEXR/ImfFrameBuffer.h>
72 template<
typename Gr
idT>
76 size_t pixelSamples = 1,
77 unsigned int seed = 0,
78 bool threaded =
true);
81 template<
typename Gr
idT,
typename IntersectorT>
86 size_t pixelSamples = 1,
87 unsigned int seed = 0,
88 bool threaded =
true);
95 template<
typename Gr
idT,
typename IntersectorT = tools::LevelSetRayIntersector<Gr
idT> >
101 typedef typename IntersectorT::RayType
RayType;
106 size_t pixelSamples = 1,
107 unsigned int seed = 0);
111 size_t pixelSamples = 1,
112 unsigned int seed = 0);
115 void setGrid(
const GridT& grid);
116 void setIntersector(
const IntersectorT& inter);
119 void setPixelSamples(
size_t pixelSamples,
unsigned int seed = 0);
120 void trace(
bool threaded =
true);
121 void operator()(
const tbb::blocked_range<size_t>& range)
const;
124 const bool mIsMaster;
127 boost::scoped_ptr<const BaseShader> mShader;
146 RGBA() : r(0), g(0), b(0), a(1) {}
147 explicit RGBA(
ValueT intensity) : r(intensity), g(intensity), b(intensity), a(1) {}
157 const float s = rhs.
a*(1.0f-a);
168 Film(
size_t width,
size_t height)
169 : mWidth(width), mHeight(height), mSize(width*height), mPixels(new
RGBA[mSize])
173 : mWidth(width), mHeight(height), mSize(width*height), mPixels(new
RGBA[mSize])
183 return mPixels[w + h*mWidth];
190 return mPixels[w + h*mWidth];
193 void fill(
const RGBA& rgb=
RGBA(0)) {
for (
size_t i=0; i<mSize; ++i) mPixels[i] = rgb; }
197 for (
size_t j = 0; j < mHeight; ++j) {
198 for (
size_t i = 0; i < mWidth; ++i, ++p) {
199 *p = ((i & size) ^ (j & size)) ? c1 : c2;
206 std::string name(fileName +
".ppm");
207 unsigned char* tmp =
new unsigned char[3*mSize], *q = tmp;
211 *q++ =
static_cast<unsigned char>(255.0f*(*p ).r);
212 *q++ =
static_cast<unsigned char>(255.0f*(*p ).g);
213 *q++ =
static_cast<unsigned char>(255.0f*(*p++).b);
216 std::ofstream os(name.c_str(), std::ios_base::binary);
218 std::cerr <<
"Error opening PPM file \"" << name <<
"\"" << std::endl;
222 os <<
"P6\n" << mWidth <<
" " << mHeight <<
"\n255\n";
223 os.write((
const char *)&(*tmp), 3*mSize*
sizeof(
unsigned char));
227 #ifdef OPENVDB_TOOLS_RAYTRACER_USE_EXR
228 void saveEXR(
const std::string& fileName,
size_t compression = 2,
size_t threads = 8)
230 std::string name(fileName +
".exr");
232 if (threads>0) Imf::setGlobalThreadCount(threads);
233 Imf::Header header(mWidth, mHeight);
234 if (compression==0) header.compression() = Imf::NO_COMPRESSION;
235 if (compression==1) header.compression() = Imf::RLE_COMPRESSION;
236 if (compression>=2) header.compression() = Imf::ZIP_COMPRESSION;
237 header.channels().insert(
"R", Imf::Channel(Imf::FLOAT));
238 header.channels().insert(
"G", Imf::Channel(Imf::FLOAT));
239 header.channels().insert(
"B", Imf::Channel(Imf::FLOAT));
240 header.channels().insert(
"A", Imf::Channel(Imf::FLOAT));
242 Imf::FrameBuffer framebuffer;
243 framebuffer.insert(
"R", Imf::Slice( Imf::FLOAT, (
char *) &(mPixels[0].r),
244 sizeof (RGBA),
sizeof (RGBA) * mWidth));
245 framebuffer.insert(
"G", Imf::Slice( Imf::FLOAT, (
char *) &(mPixels[0].g),
246 sizeof (RGBA),
sizeof (RGBA) * mWidth));
247 framebuffer.insert(
"B", Imf::Slice( Imf::FLOAT, (
char *) &(mPixels[0].b),
248 sizeof (RGBA),
sizeof (RGBA) * mWidth));
249 framebuffer.insert(
"A", Imf::Slice( Imf::FLOAT, (
char *) &(mPixels[0].a),
250 sizeof (RGBA),
sizeof (RGBA) * mWidth));
252 Imf::OutputFile file(name.c_str(), header);
253 file.setFrameBuffer(framebuffer);
254 file.writePixels(mHeight);
258 size_t width()
const {
return mWidth; }
259 size_t height()
const {
return mHeight; }
264 size_t mWidth, mHeight, mSize;
276 double frameWidth,
double nearPlane,
double farPlane)
278 , mScaleWidth(frameWidth)
279 , mScaleHeight(frameWidth*film.height()/double(film.width()))
281 assert(nearPlane > 0 && farPlane > nearPlane);
282 mScreenToWorld.accumPostRotation(
math::X_AXIS, rotation[0] * M_PI / 180.0);
283 mScreenToWorld.accumPostRotation(
math::Y_AXIS, rotation[1] * M_PI / 180.0);
284 mScreenToWorld.accumPostRotation(
math::Z_AXIS, rotation[2] * M_PI / 180.0);
285 mScreenToWorld.accumPostTranslation(translation);
286 this->initRay(nearPlane, farPlane);
293 size_t width()
const {
return mFilm->width(); }
294 size_t height()
const {
return mFilm->height(); }
302 const Vec3R orig = mScreenToWorld.applyMap(
Vec3R(0.0));
303 const Vec3R dir = orig - xyz;
305 Mat4d xform = math::aim<Mat4d>(dir, up);
308 this->initRay(mRay.t0(), mRay.t1());
314 return Vec3R( (2 * i / mFilm->width() - 1) * mScaleWidth,
315 (1 - 2 * j / mFilm->height()) * mScaleHeight, z );
322 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const = 0;
327 mRay.setTimes(znear, zfar);
328 mRay.setEye(mScreenToWorld.applyMap(
Vec3R(0.0)));
329 mRay.setDir(mScreenToWorld.applyJacobian(
Vec3R(0.0, 0.0, -1.0)));
360 double focalLength = 50.0,
361 double aperture = 41.2136,
362 double nearPlane = 1e-3,
364 :
BaseCamera(film,
rotation, translation, 0.5*aperture/focalLength, nearPlane, farPlane)
374 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const
377 Vec3R dir = BaseCamera::rasterToScreen(i + iOffset, j + jOffset, -1.0);
378 dir = BaseCamera::mScreenToWorld.applyJacobian(dir);
389 return 360.0 / M_PI * atan(aperture/(2.0*length));
395 return aperture/(2.0*(tan(fov * M_PI / 360.0)));
418 double frameWidth = 1.0,
419 double nearPlane = 1e-3,
427 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const
430 Vec3R eye = BaseCamera::rasterToScreen(i + iOffset, j + jOffset, 0.0);
431 ray.
setEye(BaseCamera::mScreenToWorld.applyMap(eye));
477 return mRGBA*
Film::RGBA(normal[0]+1.0f, normal[1]+1.0f, normal[2]+1.0f);
518 template<
typename Gr
idT>
527 tracer(grid, shader, camera, pixelSamples, seed);
528 tracer.
trace(threaded);
532 template<
typename Gr
idT,
typename IntersectorT>
534 const IntersectorT& inter,
542 tracer.
trace(threaded);
549 template<
typename Gr
idT,
typename IntersectorT>
550 inline LevelSetRayTracer<GridT, IntersectorT>::
551 LevelSetRayTracer(
const GridT& grid,
559 mShader(shader.copy()),
565 template<
typename Gr
idT,
typename IntersectorT>
575 mShader(shader.copy()),
581 template<
typename Gr
idT,
typename IntersectorT>
586 mInter(other.mInter),
587 mShader(other.mShader->copy()),
588 mCamera(other.mCamera),
589 mSubPixels(other.mSubPixels)
593 template<
typename Gr
idT,
typename IntersectorT>
597 if (mIsMaster)
delete [] mRand;
600 template<
typename Gr
idT,
typename IntersectorT>
605 mInter = IntersectorT(grid);
608 template<
typename Gr
idT,
typename IntersectorT>
616 template<
typename Gr
idT,
typename IntersectorT>
621 mShader.reset(shader.
copy());
624 template<
typename Gr
idT,
typename IntersectorT>
632 template<
typename Gr
idT,
typename IntersectorT>
637 assert(pixelSamples>0);
638 mSubPixels = pixelSamples - 1;
640 if (mSubPixels > 0) {
641 mRand =
new double[16];
643 for (
size_t i=0; i<16; ++i) mRand[i] = rand();
649 template<
typename Gr
idT,
typename IntersectorT>
653 tbb::blocked_range<size_t> range(0, mCamera->height());
654 threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
657 template<
typename Gr
idT,
typename IntersectorT>
662 const float frac = 1.0f / (1.0f + mSubPixels);
663 for (
size_t j=range.begin(), n=0, je = range.end(); j<je; ++j) {
664 for (
size_t i=0, ie = mCamera->width(); i<ie; ++i) {
666 RayType ray = mCamera->getRay(i, j);
667 Film::RGBA c = mInter.intersectsWS(ray, xyz, nml) ? (*mShader)(xyz, nml, ray) : bg;
668 for (
size_t k=0; k<mSubPixels; ++k, n +=2 ) {
669 ray = mCamera->getRay(i, j, mRand[n & 15], mRand[n+1 & 15]);
670 c += mInter.intersectsWS(ray, xyz, nml) ? (*mShader)(xyz, nml, ray) : bg;
681 #endif // OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
void postTranslate(const Vec3< T0 > &tr)
Right multiplies by the specified translation matrix, i.e. (*this) * Trans.
Definition: Mat4.h:728
void setDir(const Vec3Type &dir)
Definition: Ray.h:69
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=1.0e-8)
Definition: Mat.h:157
#define OPENVDB_VERSION_NAME
Definition: version.h:45
math::Vec3< Real > Vec3R
Definition: Types.h:74
Simple generator of random numbers over the range [0, 1)
Definition: Math.h:136
Vec3< typename promote< T, typename Coord::ValueType >::type > operator+(const Vec3< T > &v0, const Coord &v1)
Allow a Coord to be added to or subtracted from a Vec3.
Definition: Coord.h:382
A general linear transform using homogeneous coordinates to perform rotation, scaling, shear and translation.
Definition: Maps.h:323
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:199
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:328
MatType scale(const Vec3< typename MatType::value_type > &scaling)
Definition: Mat.h:595
const Vec3T & dir() const
Definition: Ray.h:93
void setEye(const Vec3Type &eye)
Definition: Ray.h:67
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:246
void scaleTimes(RealT scale)
Definition: Ray.h:81
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:56
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Matrix multiplication.
Definition: Mat3.h:608