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/kernel/lighting/lighttypes.h"
34 
35 // appleseed.foundation headers.
36 #include "foundation/math/hash.h"
37 #include "foundation/utility/containers/hashtable.h"
38 #include "foundation/utility/uid.h"
39 
40 // Standard headers.
41 #include <cstddef>
42 #include <vector>
43 
44 // Forward declarations.
45 namespace renderer  { class Intersector; }
46 namespace renderer  { class Light; }
47 namespace renderer  { class ShadingPoint; }
48 
49 namespace renderer
50 {
51 //
52 // A key to uniquely identify a light-emitting shape in a hash table.
53 //
54 
55 class EmittingShapeKey
56 {
57   public:
58     foundation::UniqueID            m_assembly_instance_uid;
59     foundation::uint32              m_object_instance_index;
60     foundation::uint32              m_primitive_index;
61 
62     EmittingShapeKey();
63     EmittingShapeKey(
64         const foundation::UniqueID  assembly_instance_uid,
65         const size_t                object_instance_index,
66         const size_t                primitive_index);
67 
68     bool operator==(const EmittingShapeKey& rhs) const;
69 };
70 
71 
72 //
73 // A hash table of light-emitting shapes.
74 //
75 
76 struct EmittingShapeKeyHasher
77 {
78     size_t operator()(const EmittingShapeKey& key) const;
79 };
80 
81 typedef foundation::HashTable<
82     EmittingShapeKey,
83     EmittingShapeKeyHasher,
84     const EmittingShape*
85 > EmittingShapeHashTable;
86 
87 
88 //
89 // Light sample: the result of sampling sets of non-physical lights and
90 // light-emitting shapes.
91 //
92 
93 class LightSample
94 {
95   public:
96     LightSample();
97 
98     // Data for a light-emitting shape sample.
99     const EmittingShape*        m_shape;
100     foundation::Vector2f        m_param_coords;                 // parametric coordinates of the sample
101     foundation::Vector3d        m_point;                        // world space position of the sample
102     foundation::Vector3d        m_shading_normal;               // world space shading normal at the sample, unit-length
103     foundation::Vector3d        m_geometric_normal;             // world space geometric normal at the sample, unit-length
104 
105     // Data for a non-physical light sample.
106     const Light*                m_light;
107     foundation::Transformd      m_light_transform;              // light space to world space transform
108 
109     // Data common to all sample types.
110     float                       m_probability;                  // probability density of this sample
111 
112     // Construct a shading point out of this light sample and a given direction.
113     void make_shading_point(
114         ShadingPoint&                   shading_point,
115         const foundation::Vector3d&     direction,
116         const Intersector&              intersector) const;
117 };
118 
119 
120 //
121 // EmittingShapeKey class implementation.
122 //
123 
EmittingShapeKey()124 inline EmittingShapeKey::EmittingShapeKey()
125 {
126 }
127 
EmittingShapeKey(const foundation::UniqueID assembly_instance_uid,const size_t object_instance_index,const size_t primitive_index)128 inline EmittingShapeKey::EmittingShapeKey(
129     const foundation::UniqueID              assembly_instance_uid,
130     const size_t                            object_instance_index,
131     const size_t                            primitive_index)
132   : m_assembly_instance_uid(static_cast<foundation::uint32>(assembly_instance_uid))
133   , m_object_instance_index(static_cast<foundation::uint32>(object_instance_index))
134   , m_primitive_index(static_cast<foundation::uint32>(primitive_index))
135 {
136 }
137 
138 inline bool EmittingShapeKey::operator==(const EmittingShapeKey& rhs) const
139 {
140     return
141         m_primitive_index == rhs.m_primitive_index &&
142         m_object_instance_index == rhs.m_object_instance_index &&
143         m_assembly_instance_uid == rhs.m_assembly_instance_uid;
144 }
145 
146 
147 //
148 // EmittingShapeKeyHasher class implementation.
149 //
150 
operator()151 inline size_t EmittingShapeKeyHasher::operator()(const EmittingShapeKey& key) const
152 {
153     return
154         foundation::mix_uint32(
155             static_cast<foundation::uint32>(key.m_assembly_instance_uid),
156             key.m_object_instance_index,
157             key.m_primitive_index);
158 }
159 
160 
161 //
162 // LightSample class implementation.
163 //
164 
LightSample()165 inline LightSample::LightSample()
166   : m_shape(nullptr)
167   , m_light(nullptr)
168 {
169 }
170 
make_shading_point(ShadingPoint & shading_point,const foundation::Vector3d & direction,const Intersector & intersector)171 inline void LightSample::make_shading_point(
172     ShadingPoint&               shading_point,
173     const foundation::Vector3d& direction,
174     const Intersector&          intersector) const
175 {
176     assert(m_shape && !m_light);
177 
178     m_shape->make_shading_point(
179         shading_point,
180         m_point,
181         direction,
182         m_param_coords,
183         intersector);
184 }
185 
186 }   // namespace renderer
187