1 
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29 
30 #pragma once
31 
32 // appleseed.renderer headers.
33 #include "renderer/global/globaltypes.h"
34 #include "renderer/kernel/intersection/intersectionsettings.h"
35 #include "renderer/kernel/intersection/probevisitorbase.h"
36 #include "renderer/kernel/intersection/trianglekey.h"
37 #include "renderer/kernel/intersection/trianglevertexinfo.h"
38 #include "renderer/modeling/scene/visibilityflags.h"
39 
40 // appleseed.foundation headers.
41 #include "foundation/core/concepts/noncopyable.h"
42 #include "foundation/math/aabb.h"
43 #include "foundation/math/bvh.h"
44 #include "foundation/math/ray.h"
45 #include "foundation/platform/types.h"
46 #include "foundation/utility/alignedvector.h"
47 #include "foundation/utility/lazy.h"
48 #include "foundation/utility/poolallocator.h"
49 #include "foundation/utility/uid.h"
50 
51 // Standard headers.
52 #include <cstddef>
53 #include <map>
54 #include <memory>
55 #include <vector>
56 
57 // Forward declarations.
58 namespace foundation    { class Statistics; }
59 namespace renderer      { class Assembly; }
60 namespace renderer      { class IntersectionFilter; }
61 namespace renderer      { class ParamArray; }
62 namespace renderer      { class Scene; }
63 namespace renderer      { class ShadingPoint; }
64 
65 namespace renderer
66 {
67 
68 typedef std::map<foundation::uint64, IntersectionFilter*> IntersectionFilterRepository;
69 
70 
71 //
72 // Triangle tree.
73 //
74 
75 class TriangleTree
76   : public foundation::bvh::Tree<
77                foundation::AlignedVector<
78                    foundation::bvh::Node<foundation::AABB3d>
79                >
80            >
81 {
82   public:
83     // Construction arguments.
84     struct Arguments
85     {
86         const Scene&                            m_scene;
87         const foundation::UniqueID              m_triangle_tree_uid;
88         const GAABB3                            m_bbox;
89         const Assembly&                         m_assembly;
90 
91         // Constructor.
92         Arguments(
93             const Scene&                        scene,
94             const foundation::UniqueID          triangle_tree_uid,
95             const GAABB3&                       bbox,
96             const Assembly&                     assembly);
97     };
98 
99     // Constructor, builds the tree for a given assembly.
100     explicit TriangleTree(const Arguments& arguments);
101 
102     // Destructor.
103     ~TriangleTree();
104 
105     // Update the non-geometry aspects of the tree.
106     void update_non_geometry(const bool enable_intersection_filters);
107 
108     // Return the number of static and moving triangles.
109     size_t get_static_triangle_count() const;
110     size_t get_moving_triangle_count() const;
111 
112     // Return the size (in bytes) of this object in memory.
113     size_t get_memory_size() const;
114 
115   private:
116     friend class TriangleLeafVisitor;
117     friend class TriangleLeafProbeVisitor;
118 
119     const Arguments                             m_arguments;
120 
121     size_t                                      m_static_triangle_count;
122     size_t                                      m_moving_triangle_count;
123 
124     std::vector<TriangleKey>                    m_triangle_keys;
125     std::vector<foundation::uint8>              m_leaf_data;
126 
127     IntersectionFilterRepository                m_intersection_filters_repository;
128     std::vector<const IntersectionFilter*>      m_intersection_filters;
129 
130     void build_bvh(
131         const ParamArray&                       params,
132         const double                            time,
133         const bool                              save_memory,
134         foundation::Statistics&                 statistics);
135 
136     void build_sbvh(
137         const ParamArray&                       params,
138         const double                            time,
139         const bool                              save_memory,
140         foundation::Statistics&                 statistics);
141 
142     std::vector<GAABB3> compute_motion_bboxes(
143         const std::vector<size_t>&              triangle_indices,
144         const std::vector<TriangleVertexInfo>&  triangle_vertex_infos,
145         const std::vector<GVector3>&            triangle_vertices,
146         const size_t                            node_index);
147 
148     void store_triangles(
149         const std::vector<size_t>&              triangle_indices,
150         const std::vector<TriangleVertexInfo>&  triangle_vertex_infos,
151         const std::vector<GVector3>&            triangle_vertices,
152         const std::vector<TriangleKey>&         triangle_keys,
153         foundation::Statistics&                 statistics);
154 
155     void update_intersection_filters();
156     void delete_intersection_filters();
157 };
158 
159 
160 //
161 // Triangle tree factory.
162 //
163 
164 class TriangleTreeFactory
165   : public foundation::ILazyFactory<TriangleTree>
166 {
167   public:
168     // Constructor.
169     explicit TriangleTreeFactory(
170         const TriangleTree::Arguments& arguments);
171 
172     // Create the triangle tree.
173     std::unique_ptr<TriangleTree> create() override;
174 
175   private:
176     TriangleTree::Arguments m_arguments;
177 };
178 
179 
180 //
181 // Some additional types.
182 //
183 
184 // Triangle tree container and iterator types.
185 typedef std::map<
186     foundation::UniqueID,
187     foundation::Lazy<TriangleTree>*
188 > TriangleTreeContainer;
189 typedef TriangleTreeContainer::iterator TriangleTreeIterator;
190 typedef TriangleTreeContainer::const_iterator TriangleTreeConstIterator;
191 
192 // Triangle tree access cache type.
193 typedef foundation::AccessCacheMap<
194     TriangleTreeContainer,
195     TriangleTreeAccessCacheLines,
196     TriangleTreeAccessCacheWays,
197     foundation::PoolAllocator<void, TriangleTreeAccessCacheLines * TriangleTreeAccessCacheWays>
198 > TriangleTreeAccessCache;
199 
200 
201 //
202 // Triangle leaf visitor, used during tree intersection.
203 //
204 
205 class TriangleLeafVisitor
206   : public foundation::NonCopyable
207 {
208   public:
209     // Constructor.
210     TriangleLeafVisitor(
211         const TriangleTree&                     tree,
212         ShadingPoint&                           shading_point);
213 
214     // Visit a leaf.
215     bool visit(
216         const TriangleTree::NodeType&           node,
217         const foundation::Ray3d&                ray,
218         const foundation::RayInfo3d&            ray_info,
219         double&                                 distance
220 #ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS
221         , foundation::bvh::TraversalStatistics& stats
222 #endif
223         );
224 
225     // Read additional data about the triangle that was hit, if any.
226     void read_hit_triangle_data() const;
227 
228   private:
229     const TriangleTree&     m_tree;
230     const bool              m_has_intersection_filters;
231     ShadingPoint&           m_shading_point;
232     GTriangleType           m_interpolated_triangle;
233     const GTriangleType*    m_hit_triangle;
234     size_t                  m_hit_triangle_index;
235 };
236 
237 
238 //
239 // Triangle leaf visitor for probe rays, only return boolean answers
240 // (whether an intersection was found or not).
241 //
242 
243 class TriangleLeafProbeVisitor
244   : public ProbeVisitorBase
245 {
246   public:
247     // Constructor.
248     TriangleLeafProbeVisitor(
249         const TriangleTree&                     tree,
250         const double                            ray_time,
251         const VisibilityFlags::Type             ray_flags);
252 
253     // Visit a leaf.
254     bool visit(
255         const TriangleTree::NodeType&           node,
256         const foundation::Ray3d&                ray,
257         const foundation::RayInfo3d&            ray_info,
258         double&                                 distance
259 #ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS
260         , foundation::bvh::TraversalStatistics& stats
261 #endif
262         );
263 
264   private:
265     const TriangleTree&         m_tree;
266     const double                m_ray_time;
267     const VisibilityFlags::Type m_ray_flags;
268     const bool                  m_has_intersection_filters;
269 };
270 
271 
272 //
273 // Triangle tree intersectors.
274 //
275 
276 typedef foundation::bvh::Intersector<
277     TriangleTree,
278     TriangleLeafVisitor,
279     foundation::Ray3d,          // make sure we pick the SSE2-optimized version of foundation::bvh::Intersector
280     TriangleTreeStackSize
281 > TriangleTreeIntersector;
282 
283 typedef foundation::bvh::Intersector<
284     TriangleTree,
285     TriangleLeafProbeVisitor,
286     foundation::Ray3d,          // make sure we pick the SSE2-optimized version of foundation::bvh::Intersector
287     TriangleTreeStackSize
288 > TriangleTreeProbeIntersector;
289 
290 
291 //
292 // TriangleTree class implementation.
293 //
294 
get_static_triangle_count()295 inline size_t TriangleTree::get_static_triangle_count() const
296 {
297     return m_static_triangle_count;
298 }
299 
get_moving_triangle_count()300 inline size_t TriangleTree::get_moving_triangle_count() const
301 {
302     return m_moving_triangle_count;
303 }
304 
305 
306 //
307 // TriangleLeafVisitor class implementation.
308 //
309 
TriangleLeafVisitor(const TriangleTree & tree,ShadingPoint & shading_point)310 inline TriangleLeafVisitor::TriangleLeafVisitor(
311     const TriangleTree&         tree,
312     ShadingPoint&               shading_point)
313   : m_tree(tree)
314   , m_has_intersection_filters(!tree.m_intersection_filters.empty())
315   , m_shading_point(shading_point)
316   , m_hit_triangle(nullptr)
317 {
318 }
319 
320 
321 //
322 // TriangleLeafProbeVisitor class implementation.
323 //
324 
TriangleLeafProbeVisitor(const TriangleTree & tree,const double ray_time,const VisibilityFlags::Type ray_flags)325 inline TriangleLeafProbeVisitor::TriangleLeafProbeVisitor(
326     const TriangleTree&         tree,
327     const double                ray_time,
328     const VisibilityFlags::Type ray_flags)
329   : m_tree(tree)
330   , m_ray_time(ray_time)
331   , m_ray_flags(ray_flags)
332   , m_has_intersection_filters(!tree.m_intersection_filters.empty())
333 {
334 }
335 
336 }   // namespace renderer
337