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) 2017-2018 Petra Gospodnetic, The appleseedhq Organization
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27 //
28 
29 #pragma once
30 
31 // appleseed.renderer headers.
32 #include "renderer/kernel/intersection/intersectionsettings.h"
33 #include "renderer/utility/transformsequence.h"
34 
35 // appleseed.foundation headers.
36 #include "foundation/math/aabb.h"
37 #include "foundation/math/vector.h"
38 #include "foundation/utility/stampedptr.h"
39 
40 // Standard headers.
41 #include <cstddef>
42 
43 // Forward declarations.
44 namespace renderer  { class AssemblyInstance; }
45 namespace renderer  { class BackwardLightSampler; }
46 namespace renderer  { class Intersector; }
47 namespace renderer  { class Light; }
48 namespace renderer  { class LightSample; }
49 namespace renderer  { class Material; }
50 namespace renderer  { class ShadingPoint; }
51 
52 namespace renderer
53 {
54 
55 enum LightType
56 {
57     NonPhysicalLightType = 0,
58     EmittingShapeType = 1
59 };
60 
61 
62 //
63 // A non-physical light.
64 //
65 
66 class NonPhysicalLightInfo
67 {
68   public:
69     TransformSequence   m_transform_sequence;   // assembly instance (parent of the light) space to world space
70     const Light*        m_light;
71 };
72 
73 
74 //
75 // A light-emitting shape.
76 //
77 
78 class EmittingShape
79 {
80   public:
81     enum ShapeType
82     {
83         TriangleShape = 0,
84         RectangleShape,
85         SphereShape,
86         DiskShape
87     };
88 
89     static EmittingShape create_triangle_shape(
90         const AssemblyInstance*     assembly_instance,
91         const size_t                object_instance_index,
92         const size_t                primitive_index,
93         const Material*             material,
94         const double                area,
95         const foundation::Vector3d& v0,
96         const foundation::Vector3d& v1,
97         const foundation::Vector3d& v2,
98         const foundation::Vector3d& n0,
99         const foundation::Vector3d& n1,
100         const foundation::Vector3d& n2,
101         const foundation::Vector3d& geometric_normal);
102 
103     static EmittingShape create_rectangle_shape(
104         const AssemblyInstance*     assembly_instance,
105         const size_t                object_instance_index,
106         const Material*             material,
107         const double                area,
108         const foundation::Vector3d& o,
109         const foundation::Vector3d& x,
110         const foundation::Vector3d& y,
111         const foundation::Vector3d& n);
112 
113     static EmittingShape create_sphere_shape(
114         const AssemblyInstance*     assembly_instance,
115         const size_t                object_instance_index,
116         const Material*             material,
117         const double                area,
118         const foundation::Vector3d& center,
119         const double                radius);
120 
121     static EmittingShape create_disk_shape(
122         const AssemblyInstance*     assembly_instance,
123         const size_t                object_instance_index,
124         const Material*             material,
125         const double                area,
126         const foundation::Vector3d& c,
127         const double                r,
128         const foundation::Vector3d& n,
129         const foundation::Vector3d& x,
130         const foundation::Vector3d& y);
131 
132     ShapeType get_shape_type() const;
133 
134     const AssemblyInstance* get_assembly_instance() const;
135 
136     size_t get_object_instance_index() const;
137 
138     size_t get_primitive_index() const;
139 
140     float get_area() const;
141     float get_rcp_area() const;
142 
143     float get_shape_prob() const;
144     void set_shape_prob(const float prob);
145 
146     const Material* get_material() const;
147 
148     const foundation::AABB3d& get_bbox() const;
149 
150     const foundation::Vector3d& get_centroid() const;
151 
152     void sample_uniform(
153         const foundation::Vector2f& s,
154         const float                 shape_prob,
155         LightSample&                light_sample) const;
156 
157     float evaluate_pdf_uniform() const;
158 
159     void make_shading_point(
160         ShadingPoint&               shading_point,
161         const foundation::Vector3d& point,
162         const foundation::Vector3d& direction,
163         const foundation::Vector2f& bary,
164         const Intersector&          intersector) const;
165 
166     // Estimate average and maximum radiant flux emitted by this shape.
167     void estimate_flux();
168 
169     // Return estimated average and maximum radiant flux in W emitted by this shape.
170     float get_average_flux() const;
171     float get_max_flux() const;
172 
173   private:
174     friend class LightSamplerBase;
175     friend class BackwardLightSampler;
176 
177     struct Triangle
178     {
179         foundation::Vector3d    m_v0, m_v1, m_v2;               // world space vertices of the shape
180         foundation::Vector3d    m_n0, m_n1, m_n2;               // world space vertex normals
181         foundation::Vector3d    m_geometric_normal;             // world space geometric normal, unit-length
182         double  m_plane_dist;
183     };
184 
185     struct Rectangle
186     {
187         foundation::Vector3d    m_origin;                       // world space position of the bottom left corner of the rectangle
188         foundation::Vector3d    m_x, m_y;                       // world space x and y axes
189         double                  m_width;                        // rectangle width
190         double                  m_height;                       // rectangle height
191         foundation::Vector3d    m_geometric_normal;             // world space geometric normal, unit-length
192         double                  m_plane_dist;
193     };
194 
195     struct Sphere
196     {
197         foundation::Vector3d    m_center;                       // world space center of the sphere
198         double                  m_radius;                       // sphere radius
199     };
200 
201     struct Disk
202     {
203         foundation::Vector3d    m_center;               // world space center of the disk
204         foundation::Vector3d    m_geometric_normal;     // world space geometric normal, unit-length
205         double                  m_radius;               // world space disk radius
206         foundation::Vector3d    m_x, m_y;               // world space x and y axes
207     };
208 
209     union Geom
210     {
211         Triangle    m_triangle;
212         Rectangle   m_rectangle;
213         Sphere      m_sphere;
214         Disk        m_disk;
215     };
216 
217     typedef foundation::stamped_ptr<const AssemblyInstance> AssemblyInstanceAndType;
218 
219     AssemblyInstanceAndType     m_assembly_instance_and_type;
220     size_t                      m_object_instance_index;
221     size_t                      m_light_tree_node_index;
222     size_t                      m_primitive_index;
223     Geom                        m_geom;
224     TriangleSupportPlaneType    m_shape_support_plane;          // support plane of the shape in assembly space
225     float                       m_area;                         // world space shape area
226     float                       m_rcp_area;                     // world space shape area reciprocal
227     float                       m_shape_prob;                   // probability density of this shape
228     float                       m_average_flux;                 // estimated average radiant flux in W emitted by this shape
229     float                       m_max_flux;                     // estimated maximum radiant flux in W emitted by this shape
230     const Material*             m_material;
231     foundation::AABB3d          m_bbox;
232     foundation::Vector3d        m_centroid;
233 
234     // Constructor.
235     EmittingShape(
236         const ShapeType             shape_type,
237         const AssemblyInstance*     assembly_instance,
238         const size_t                object_instance_index,
239         const size_t                primitive_index,
240         const Material*             material);
241 };
242 
243 
244 //
245 // EmittingShape class implementation.
246 //
247 
get_shape_type()248 inline EmittingShape::ShapeType EmittingShape::get_shape_type() const
249 {
250     return static_cast<ShapeType>(m_assembly_instance_and_type.get_stamp());
251 }
252 
get_assembly_instance()253 inline const AssemblyInstance* EmittingShape::get_assembly_instance() const
254 {
255     return m_assembly_instance_and_type.get_ptr();
256 }
257 
get_primitive_index()258 inline size_t EmittingShape::get_primitive_index() const
259 {
260     return m_primitive_index;
261 }
262 
get_object_instance_index()263 inline size_t EmittingShape::get_object_instance_index() const
264 {
265     return m_object_instance_index;
266 }
267 
get_area()268 inline float EmittingShape::get_area() const
269 {
270     return m_area;
271 }
272 
get_rcp_area()273 inline float EmittingShape::get_rcp_area() const
274 {
275     return m_rcp_area;
276 }
277 
get_shape_prob()278 inline float EmittingShape::get_shape_prob() const
279 {
280     return m_shape_prob;
281 }
282 
set_shape_prob(const float prob)283 inline void EmittingShape::set_shape_prob(const float prob)
284 {
285     m_shape_prob = prob;
286 }
287 
get_material()288 inline const Material* EmittingShape::get_material() const
289 {
290     return m_material;
291 }
292 
get_bbox()293 inline const foundation::AABB3d& EmittingShape::get_bbox() const
294 {
295     return m_bbox;
296 }
297 
get_centroid()298 inline const foundation::Vector3d& EmittingShape::get_centroid() const
299 {
300     return m_centroid;
301 }
302 
get_average_flux()303 inline float EmittingShape::get_average_flux() const
304 {
305     return m_average_flux;
306 }
307 
get_max_flux()308 inline float EmittingShape::get_max_flux() const
309 {
310     return m_max_flux;
311 }
312 
313 }   // namespace renderer
314