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