Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
skdtree.h
Go to the documentation of this file.
1 /*
2  This file is part of Mitsuba, a physically based rendering system.
3 
4  Copyright (c) 2007-2014 by Wenzel Jakob and others.
5 
6  Mitsuba is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Mitsuba is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 #if !defined(__MITSUBA_RENDER_SKDTREE_H_)
21 #define __MITSUBA_RENDER_SKDTREE_H_
22 
23 #include <mitsuba/render/shape.h>
26 
27 #if defined(MTS_KD_CONSERVE_MEMORY)
28 #if defined(MTS_HAS_COHERENT_RT)
29 #error MTS_KD_CONSERVE_MEMORY & MTS_HAS_COHERENT_RT are incompatible
30 #endif
31 #endif
32 
33 #if defined(SINGLE_PRECISION)
34 /// 64 byte temporary storage for intersection computations
35 #define MTS_KD_INTERSECTION_TEMP 64
36 #else
37 #define MTS_KD_INTERSECTION_TEMP 128
38 #endif
39 
41 
42 typedef const Shape * ConstShapePtr;
43 
44 /**
45  * \brief SAH KD-tree acceleration data structure for fast ray-triangle
46  * intersections.
47  *
48  * Implements the construction algorithm for 'perfect split' trees as outlined
49  * in the paper "On Bulding fast kd-Trees for Ray Tracing, and on doing that in
50  * O(N log N)" by Ingo Wald and Vlastimil Havran. Non-triangle shapes are
51  * supported, but most optimizations here target large triangle meshes.
52  * For more details regarding the construction algorithm, please refer to
53  * the class \ref GenericKDTree.
54  *
55  * This class offers a choice of two different triangle intersection algorithms:
56  * By default, intersections are computed using the "TriAccel" projection with
57  * pre-computation method from Ingo Wald's PhD thesis "Realtime Ray Tracing
58  * and Interactive Global Illumination". This adds an overhead of 48 bytes per
59  * triangle.
60  *
61  * When compiled with \c MTS_KD_CONSERVE_MEMORY, the Moeller-Trumbore intersection
62  * test is used instead, which doesn't need any extra storage. However, it also
63  * tends to be quite a bit slower.
64  *
65  * \sa GenericKDTree
66  * \ingroup librender
67  */
68 
69 class MTS_EXPORT_RENDER ShapeKDTree : public SAHKDTree3D<ShapeKDTree> {
71  friend class SAHKDTree3D<ShapeKDTree>;
72  friend class Instance;
73  friend class AnimatedInstance;
74  friend class SingleScatter;
75 
76 public:
77  // =============================================================
78  //! @{ \name Initialization and tree construction
79  // =============================================================
80  /// Create an empty kd-tree
81  ShapeKDTree();
82 
83  /// Add a shape to the kd-tree
84  void addShape(const Shape *shape);
85 
86  /// Return the list of stored shapes
87  inline const std::vector<const Shape *> &getShapes() const { return m_shapes; }
88 
89  /**
90  * \brief Return the total number of low-level primitives (triangles
91  * and other low-level primitives)
92  */
93  inline SizeType getPrimitiveCount() const {
94  return m_shapeMap[m_shapeMap.size()-1];
95  }
96 
97  /// Return an axis-aligned bounding box containing all primitives
98  inline const AABB &getAABB() const { return m_aabb; }
99 
100  /// Build the kd-tree (needs to be called before tracing any rays)
101  void build();
102 
103  //! @}
104  // =============================================================
105 
106  // =============================================================
107  //! @{ \name Ray tracing routines
108  // =============================================================
109 
110  /**
111  * \brief Intersect a ray against all primitives stored in the kd-tree
112  * and return detailed intersection information
113  *
114  * \param ray
115  * A 3-dimensional ray data structure with minimum/maximum
116  * extent information, as well as a time (which applies when
117  * the shapes are animated)
118  *
119  * \param its
120  * A detailed intersection record, which will be filled by the
121  * intersection query
122  *
123  * \return \c true if an intersection was found
124  */
125  bool rayIntersect(const Ray &ray, Intersection &its) const;
126 
127  /**
128  * \brief Intersect a ray against all primitives stored in the kd-tree
129  * and return the traveled distance and intersected shape
130  *
131  * This function represents a performance compromise when the
132  * intersected shape must be known, but there is no need for
133  * a detailed intersection record.
134  *
135  * \param ray
136  * A 3-dimensional ray data structure with minimum/maximum
137  * extent information, as well as a time (which applies when
138  * the shapes are animated)
139  *
140  * \param t
141  * The traveled ray distance will be stored in this parameter
142 
143  * \param shape
144  * A pointer to the intersected shape will be stored in this
145  * parameter
146  *
147  * \param n
148  * The geometric surface normal will be stored in this parameter
149  *
150  * \param uv
151  * The UV coordinates associated with the intersection will
152  * be stored here.
153  *
154  * \return \c true if an intersection was found
155  */
156  bool rayIntersect(const Ray &ray, Float &t, ConstShapePtr &shape,
157  Normal &n, Point2 &uv) const;
158 
159  /**
160  * \brief Test a ray for occlusion with respect to all primitives
161  * stored in the kd-tree.
162  *
163  * This function does not compute a detailed intersection record,
164  * and it never determines the closest intersection, which makes
165  * it quite a bit faster than the other two \c rayIntersect() methods.
166  * However, for this reason, it can only be used to check whether
167  * there is \a any occlusion along a ray or ray segment.
168  *
169  * \param ray
170  * A 3-dimensional ray data structure with minimum/maximum
171  * extent information, as well as a time (which applies when
172  * the shapes are animated)
173  *
174  * \return \c true if there is occlusion
175  */
176  bool rayIntersect(const Ray &ray) const;
177 
178 #if defined(MTS_HAS_COHERENT_RT)
179  /**
180  * \brief Intersect four rays with the stored triangle meshes while making
181  * use of ray coherence to do this very efficiently. Requires SSE.
182  */
183  void rayIntersectPacket(const RayPacket4 &packet,
184  const RayInterval4 &interval, Intersection4 &its, void *temp) const;
185 
186  /**
187  * \brief Fallback for incoherent rays
188  * \sa rayIntesectPacket
189  */
190  void rayIntersectPacketIncoherent(const RayPacket4 &packet,
191  const RayInterval4 &interval, Intersection4 &its, void *temp) const;
192 #endif
193  //! @}
194  // =============================================================
195 
197 protected:
198  /**
199  * \brief Return the shape index corresponding to a primitive index
200  * seen by the generic kd-tree implementation.
201  *
202  * When this is a triangle mesh, the \a idx parameter is updated to the
203  * triangle index within the mesh.
204  */
205  FINLINE IndexType findShape(IndexType &idx) const {
206  std::vector<IndexType>::const_iterator it = std::lower_bound(
207  m_shapeMap.begin(), m_shapeMap.end(), idx + 1) - 1;
208  idx -= *it;
209  return (IndexType) (it - m_shapeMap.begin());
210  }
211 
212  /// Return the axis-aligned bounding box of a certain primitive
213  FINLINE AABB getAABB(IndexType idx) const {
214  IndexType shapeIdx = findShape(idx);
215  const Shape *shape = m_shapes[shapeIdx];
216  if (m_triangleFlag[shapeIdx]) {
217  const TriMesh *mesh = static_cast<const TriMesh *>(shape);
218  return mesh->getTriangles()[idx].getAABB(mesh->getVertexPositions());
219  } else {
220  return shape->getAABB();
221  }
222  }
223 
224  /// Return the AABB of a primitive when clipped to another AABB
225  FINLINE AABB getClippedAABB(IndexType idx, const AABB &aabb) const {
226  IndexType shapeIdx = findShape(idx);
227  const Shape *shape = m_shapes[shapeIdx];
228  if (m_triangleFlag[shapeIdx]) {
229  const TriMesh *mesh = static_cast<const TriMesh *>(shape);
230  return mesh->getTriangles()[idx].getClippedAABB(mesh->getVertexPositions(), aabb);
231  } else {
232  return shape->getClippedAABB(aabb);
233  }
234  }
235 
236  /// Temporarily holds some intersection information
240  Float u, v;
241  };
242 
243  /**
244  * Check whether a primitive is intersected by the given ray. Some
245  * temporary space is supplied to store data that can later
246  * be used to create a detailed intersection record.
247  */
248  FINLINE bool intersect(const Ray &ray, IndexType idx, Float mint,
249  Float maxt, Float &t, void *temp) const {
250  IntersectionCache *cache =
251  static_cast<IntersectionCache *>(temp);
252 
253 #if defined(MTS_KD_CONSERVE_MEMORY)
254  IndexType shapeIdx = findShape(idx);
255  if (EXPECT_TAKEN(m_triangleFlag[shapeIdx])) {
256  const TriMesh *mesh =
257  static_cast<const TriMesh *>(m_shapes[shapeIdx]);
258  const Triangle &tri = mesh->getTriangles()[idx];
259  Float tempU, tempV, tempT;
260  if (tri.rayIntersect(mesh->getVertexPositions(), ray,
261  tempU, tempV, tempT)) {
262  if (tempT < mint || tempT > maxt)
263  return false;
264  t = tempT;
265  cache->shapeIndex = shapeIdx;
266  cache->primIndex = idx;
267  cache->u = tempU;
268  cache->v = tempV;
269  return true;
270  }
271  } else {
272  const Shape *shape = m_shapes[shapeIdx];
273  if (shape->rayIntersect(ray, mint, maxt, t,
274  reinterpret_cast<uint8_t*>(temp) + 2*sizeof(IndexType))) {
275  cache->shapeIndex = shapeIdx;
276  cache->primIndex = KNoTriangleFlag;
277  return true;
278  }
279  }
280 #else
281  const TriAccel &ta = m_triAccel[idx];
282  if (EXPECT_TAKEN(m_triAccel[idx].k != KNoTriangleFlag)) {
283  Float tempU, tempV, tempT;
284  if (ta.rayIntersect(ray, mint, maxt, tempU, tempV, tempT)) {
285  t = tempT;
286  cache->shapeIndex = ta.shapeIndex;
287  cache->primIndex = ta.primIndex;
288  cache->u = tempU;
289  cache->v = tempV;
290  return true;
291  }
292  } else {
293  uint32_t shapeIndex = ta.shapeIndex;
294  const Shape *shape = m_shapes[shapeIndex];
295  if (shape->rayIntersect(ray, mint, maxt, t,
296  reinterpret_cast<uint8_t*>(temp) + 2*sizeof(IndexType))) {
297  cache->shapeIndex = shapeIndex;
298  cache->primIndex = KNoTriangleFlag;
299  return true;
300  }
301  }
302 #endif
303  return false;
304  }
305 
306  /**
307  * Check whether a primitive is intersected by the given ray. This
308  * version is used for shadow rays, hence no temporary space is supplied.
309  */
310  FINLINE bool intersect(const Ray &ray, IndexType idx,
311  Float mint, Float maxt) const {
312 #if defined(MTS_KD_CONSERVE_MEMORY)
313  IndexType shapeIdx = findShape(idx);
314  if (EXPECT_TAKEN(m_triangleFlag[shapeIdx])) {
315  const TriMesh *mesh =
316  static_cast<const TriMesh *>(m_shapes[shapeIdx]);
317  const Triangle &tri = mesh->getTriangles()[idx];
318  Float tempU, tempV, tempT;
319  if (tri.rayIntersect(mesh->getVertexPositions(), ray, tempU, tempV, tempT))
320  return tempT >= mint && tempT <= maxt;
321  return false;
322  } else {
323  const Shape *shape = m_shapes[shapeIdx];
324  return shape->rayIntersect(ray, mint, maxt);
325  }
326 #else
327  const TriAccel &ta = m_triAccel[idx];
328  uint32_t shapeIndex = ta.shapeIndex;
329  const Shape *shape = m_shapes[shapeIndex];
330  if (EXPECT_TAKEN(m_triAccel[idx].k != KNoTriangleFlag)) {
331  Float tempU, tempV, tempT;
332  return ta.rayIntersect(ray, mint, maxt, tempU, tempV, tempT);
333  } else {
334  return shape->rayIntersect(ray, mint, maxt);
335  }
336 #endif
337  }
338 
339  /**
340  * \brief After having found a unique intersection, fill a proper record
341  * using the temporary information collected in \ref intersect()
342  */
343  template<bool BarycentricPos> FINLINE void fillIntersectionRecord(const Ray &ray,
344  const void *temp, Intersection &its) const {
345  const IntersectionCache *cache = reinterpret_cast<const IntersectionCache *>(temp);
346  const Shape *shape = m_shapes[cache->shapeIndex];
347  if (m_triangleFlag[cache->shapeIndex]) {
348  const TriMesh *trimesh = static_cast<const TriMesh *>(shape);
349  const Triangle &tri = trimesh->getTriangles()[cache->primIndex];
350  const Point *vertexPositions = trimesh->getVertexPositions();
351  const Normal *vertexNormals = trimesh->getVertexNormals();
352  const Point2 *vertexTexcoords = trimesh->getVertexTexcoords();
353  const Color3 *vertexColors = trimesh->getVertexColors();
354  const TangentSpace *vertexTangents = trimesh->getUVTangents();
355  const Vector b(1 - cache->u - cache->v, cache->u, cache->v);
356 
357  const uint32_t idx0 = tri.idx[0], idx1 = tri.idx[1], idx2 = tri.idx[2];
358  const Point &p0 = vertexPositions[idx0];
359  const Point &p1 = vertexPositions[idx1];
360  const Point &p2 = vertexPositions[idx2];
361 
362  if (BarycentricPos)
363  its.p = p0 * b.x + p1 * b.y + p2 * b.z;
364  else
365  its.p = ray(its.t);
366 
367  Vector side1(p1-p0), side2(p2-p0);
368  Normal faceNormal(cross(side1, side2));
369  Float length = faceNormal.length();
370  if (!faceNormal.isZero())
371  faceNormal /= length;
372 
373  if (EXPECT_NOT_TAKEN(vertexTangents)) {
374  const TangentSpace &ts = vertexTangents[cache->primIndex];
375  its.dpdu = ts.dpdu;
376  its.dpdv = ts.dpdv;
377  } else {
378  its.dpdu = side1;
379  its.dpdv = side2;
380  }
381 
382  if (EXPECT_TAKEN(vertexNormals)) {
383  const Normal
384  &n0 = vertexNormals[idx0],
385  &n1 = vertexNormals[idx1],
386  &n2 = vertexNormals[idx2];
387 
388  its.shFrame.n = normalize(n0 * b.x + n1 * b.y + n2 * b.z);
389 
390  /* Ensure that the geometric & shading normals face the same direction */
391  if (dot(faceNormal, its.shFrame.n) < 0)
392  faceNormal = -faceNormal;
393  } else {
394  its.shFrame.n = faceNormal;
395  }
396  its.geoFrame = Frame(faceNormal);
397 
398  if (EXPECT_TAKEN(vertexTexcoords)) {
399  const Point2 &t0 = vertexTexcoords[idx0];
400  const Point2 &t1 = vertexTexcoords[idx1];
401  const Point2 &t2 = vertexTexcoords[idx2];
402  its.uv = t0 * b.x + t1 * b.y + t2 * b.z;
403  } else {
404  its.uv = Point2(b.y, b.z);
405  }
406 
407  if (EXPECT_NOT_TAKEN(vertexColors)) {
408  const Color3 &c0 = vertexColors[idx0],
409  &c1 = vertexColors[idx1],
410  &c2 = vertexColors[idx2];
411  Color3 result(c0 * b.x + c1 * b.y + c2 * b.z);
412  its.color.fromLinearRGB(result[0], result[1],
413  result[2], Spectrum::EReflectance);
414  }
415 
416  its.shape = trimesh;
417  its.hasUVPartials = false;
418  its.primIndex = cache->primIndex;
419  its.instance = NULL;
420  its.time = ray.time;
421  } else {
422  shape->fillIntersectionRecord(ray,
423  reinterpret_cast<const uint8_t*>(temp) + 2*sizeof(IndexType), its);
424  }
425 
426  computeShadingFrame(its.shFrame.n, its.dpdu, its.shFrame);
427  its.wi = its.toLocal(-ray.d);
428  }
429 
430  /// Plain shadow ray query (used by the 'instance' plugin)
431  inline bool rayIntersect(const Ray &ray, Float _mint, Float _maxt) const {
432  Float mint, maxt, tempT = std::numeric_limits<Float>::infinity();
433  if (m_aabb.rayIntersect(ray, mint, maxt)) {
434  if (_mint > mint) mint = _mint;
435  if (_maxt < maxt) maxt = _maxt;
436 
437  if (EXPECT_TAKEN(maxt > mint))
438  return rayIntersectHavran<true>(ray, mint, maxt, tempT, NULL);
439  }
440  return false;
441  }
442 
443  /// Plain intersection query (used by the 'instance' plugin)
444  inline bool rayIntersect(const Ray &ray, Float _mint, Float _maxt, Float &t, void *temp) const {
445  Float mint, maxt, tempT = std::numeric_limits<Float>::infinity();
446  if (m_aabb.rayIntersect(ray, mint, maxt)) {
447  if (_mint > mint) mint = _mint;
448  if (_maxt < maxt) maxt = _maxt;
449 
450  if (EXPECT_TAKEN(maxt > mint)) {
451  if (rayIntersectHavran<false>(ray, mint, maxt, tempT, temp)) {
452  t = tempT;
453  return true;
454  }
455  }
456  }
457  return false;
458  }
459 
460  /// Virtual destructor
461  virtual ~ShapeKDTree();
462 private:
463  std::vector<const Shape *> m_shapes;
464  std::vector<bool> m_triangleFlag;
465  std::vector<IndexType> m_shapeMap;
466 #if !defined(MTS_KD_CONSERVE_MEMORY)
467  TriAccel *m_triAccel;
468 #endif
469 };
470 
472 
473 #endif /* __MITSUBA_RENDER_SKDTREE_H_ */
const Shape * shape
Pointer to the associated shape.
Definition: shape.h:132
AABB getClippedAABB(const Point *positions, const AABB &aabb) const
Returns the axis-aligned bounding box of a triangle after it has clipped to the extends of another gi...
FINLINE __m128 rayIntersectPacket(const TriAccel &tri, const RayPacket4 &packet, __m128 mint, __m128 maxt, __m128 inactive, Intersection4 &its)
Definition: triaccel_sse.h:27
Temporarily holds some intersection information.
Definition: skdtree.h:237
FINLINE void fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const
After having found a unique intersection, fill a proper record using the temporary information collec...
Definition: skdtree.h:343
Three-dimensional normal data structure.
Definition: normal.h:39
static FINLINE bool rayIntersect(const Point &p0, const Point &p1, const Point &p2, const Ray &ray, Float &u, Float &v, Float &t)
Ray-triangle intersection test.
Definition: triangle.h:109
Abstract triangle mesh base class.
Definition: trimesh.h:68
Stores a three-dimensional orthonormal coordinate frame.
Definition: frame.h:37
KDTreeBase< AABB >::SizeType SizeType
Definition: sahkdtree3.h:110
bool rayIntersect(const Ray &ray, Float _mint, Float _maxt) const
Plain shadow ray query (used by the &#39;instance&#39; plugin)
Definition: skdtree.h:431
Simple triangle class including a collection of routines for analysis and transformation.
Definition: triangle.h:35
Vector dpdu
Position partials wrt. the UV parameterization.
Definition: shape.h:150
uint32_t shapeIndex
Definition: triaccel.h:50
Normal n
Definition: frame.h:39
Vector dpdu
Position partial with respect to the U parameter of the local chart.
Definition: trimesh.h:40
virtual AABB getAABB() const =0
Return a bounding box containing the shape.
uint32_t idx[3]
Indices into a vertex buffer.
Definition: triangle.h:37
SAH KD-tree acceleration data structure for fast ray-triangle intersections.
Definition: skdtree.h:69
MTS_EXPORT_CORE void computeShadingFrame(const Vector &n, const Vector &dpdu, Frame &frame)
Given a smoothly varying shading normal and a tangent of a shape parameterization, compute a smoothly varying orthonormal frame.
Vector dpdv
Definition: shape.h:150
FINLINE AABB getAABB(IndexType idx) const
Return the axis-aligned bounding box of a certain primitive.
Definition: skdtree.h:213
FINLINE bool rayIntersect(const Ray &ray, Float mint, Float maxt, Float &u, Float &v, Float &t) const
Fast ray-triangle intersection test.
Definition: triaccel.h:96
Point2 uv
UV surface coordinates.
Definition: shape.h:147
const Normal * getVertexNormals() const
Return the vertex normals (const version)
Definition: trimesh.h:137
Normal normalize(const Normal &n)
Definition: normal.h:73
virtual bool rayIntersect(const Ray &ray, Float mint, Float maxt, Float &t, void *temp) const
Fast ray intersection test.
virtual void fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const
Given that an intersection has been found, create a detailed intersection record. ...
#define MTS_NAMESPACE_BEGIN
Definition: platform.h:137
const Point2 * getVertexTexcoords() const
Return the vertex texture coordinates (const version)
Definition: trimesh.h:151
bool hasUVPartials
Have texture coordinate partials been computed.
Definition: shape.h:165
KDTreeBase< AABB >::IndexType IndexType
Definition: sahkdtree3.h:111
AABB m_aabb
Definition: gkdtree.h:631
Abstract base class of all shapes.
Definition: shape.h:178
const Triangle * getTriangles() const
Return the triangle list (const version)
Definition: trimesh.h:127
RGB color data type.
Definition: spectrum.h:612
TPoint2< Float > Point2
Definition: fwd.h:129
const Shape * instance
Stores a pointer to the parent instance, if applicable.
Definition: shape.h:171
const std::vector< const Shape * > & getShapes() const
Return the list of stored shapes.
Definition: skdtree.h:87
const TangentSpace * getUVTangents() const
Return the per-triangle UV tangents (const version)
Definition: trimesh.h:158
Vector toLocal(const Vector &v) const
Convert a world-space vector into local shading coordinates.
Definition: shape.h:47
Definition: ray_sse.h:57
Axis-aligned bounding box data structure in three dimensions.
Definition: aabb.h:437
SizeType primIndex
Definition: skdtree.h:239
Vector wi
Incident direction in the local shading frame.
Definition: shape.h:162
Implements the 3D surface area heuristic for use by the GenericKDTree construction algorithm...
Definition: sahkdtree3.h:39
SIMD quad-packed ray for coherent ray tracing.
Definition: ray_sse.h:34
LengthType length() const
Return the 2-norm of this vector.
Definition: vector.h:571
Simple tangent space storage for surfaces.
Definition: trimesh.h:38
#define MTS_DECLARE_CLASS()
This macro must be used in the initial definition in classes that derive from Object.
Definition: class.h:158
Optimized KD-tree acceleration data structure for n-dimensional (n&lt;=4) shapes and various queries on ...
Definition: gkdtree.h:706
Definition: fwd.h:99
FINLINE bool intersect(const Ray &ray, IndexType idx, Float mint, Float maxt, Float &t, void *temp) const
Definition: skdtree.h:248
const AABB & getAABB() const
Return an axis-aligned bounding box containing all primitives.
Definition: skdtree.h:98
const Color3 * getVertexColors() const
Return the vertex colors (const version)
Definition: trimesh.h:144
Definition: ray_sse.h:74
uint32_t primIndex
Primitive index, e.g. the triangle ID (if applicable)
Definition: shape.h:168
virtual AABB getClippedAABB(const AABB &box) const
Returns the minimal axis-aligned bounding box of this shape when clipped to another bounding box...
Definition: fwd.h:65
AABB getAABB(const Point *positions) const
Construct an axis-aligned box, which contains the triangle.
Definition: triangle.h:40
const Shape * ConstShapePtr
Definition: skdtree.h:42
Definition: fwd.h:96
Frame shFrame
Shading frame.
Definition: shape.h:144
uint32_t primIndex
Definition: triaccel.h:51
Float time
Time value associated with the intersection.
Definition: shape.h:156
const Point * getVertexPositions() const
Return the vertex positions (const version)
Definition: trimesh.h:132
Pre-computed triangle representation based on Ingo Wald&#39;s TriAccel layout.
Definition: triaccel.h:37
bool rayIntersect(const Ray &ray, Float _mint, Float _maxt, Float &t, void *temp) const
Plain intersection query (used by the &#39;instance&#39; plugin)
Definition: skdtree.h:444
Spectrum color
Interpolated vertex color.
Definition: shape.h:159
Float t
Distance traveled along the ray.
Definition: shape.h:135
Container for all information related to a surface intersection.
Definition: shape.h:36
SizeType shapeIndex
Definition: skdtree.h:238
Float v
Definition: skdtree.h:240
Vector dpdv
Position partial with respect to the V parameter of the local chart.
Definition: trimesh.h:43
Definition: fwd.h:100
TVector3< T > cross(const TVector3< T > &v1, const TVector3< T > &v2)
Definition: vector.h:617
Frame geoFrame
Geometry frame.
Definition: shape.h:141
#define MTS_EXPORT_RENDER
Definition: platform.h:109
T dot(const TQuaternion< T > &q1, const TQuaternion< T > &q2)
Definition: quat.h:348
FINLINE AABB getClippedAABB(IndexType idx, const AABB &aabb) const
Return the AABB of a primitive when clipped to another AABB.
Definition: skdtree.h:225
Specializes GenericKDTree to a three-dimensional tree to be used for ray tracing. ...
Definition: sahkdtree3.h:107
SizeType getPrimitiveCount() const
Return the total number of low-level primitives (triangles and other low-level primitives) ...
Definition: skdtree.h:93
Point p
Definition: shape.h:138
Float u
Definition: skdtree.h:240
#define MTS_NAMESPACE_END
Definition: platform.h:138
FINLINE bool intersect(const Ray &ray, IndexType idx, Float mint, Float maxt) const
Definition: skdtree.h:310
bool isZero() const
Return whether or not this vector is identically zero.
Definition: vector.h:576
void fromLinearRGB(Float r, Float g, Float b, EConversionIntent intent=EReflectance)
Convert linear RGB colors into a plausible spectral power distribution.