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/modeling/entity/entity.h"
35 #include "renderer/modeling/scene/containers.h"
36 
37 // appleseed.foundation headers.
38 #include "foundation/math/transform.h"
39 #include "foundation/platform/compiler.h"
40 #include "foundation/platform/types.h"
41 #include "foundation/utility/api/apiarray.h"
42 #include "foundation/utility/autoreleaseptr.h"
43 #include "foundation/utility/uid.h"
44 
45 // appleseed.main headers.
46 #include "main/dllsymbol.h"
47 
48 // Standard headers.
49 #include <cassert>
50 #include <cstddef>
51 
52 // Forward declarations.
53 namespace foundation    { class DictionaryArray; }
54 namespace foundation    { class IAbortSwitch; }
55 namespace foundation    { class StringDictionary; }
56 namespace renderer      { class Assembly; }
57 namespace renderer      { class Material; }
58 namespace renderer      { class Object; }
59 namespace renderer      { class OnFrameBeginRecorder; }
60 namespace renderer      { class ParamArray; }
61 namespace renderer      { class Project; }
62 
63 namespace renderer
64 {
65 
66 //
67 // An array of materials.
68 //
69 
70 APPLESEED_DECLARE_APIARRAY(MaterialArray, const Material*);
71 
72 // Return true if at least one material in the array emits light.
73 bool has_emitting_materials(const MaterialArray& materials);
74 
75 // Return true if at least one material in the array has an alpha map set.
76 bool uses_alpha_mapping(const MaterialArray& materials);
77 
78 
79 //
80 // An instance of an object.
81 //
82 
83 class APPLESEED_DLLSYMBOL ObjectInstance
84   : public Entity
85 {
86   public:
87     // Return the unique ID of this class of entities.
88     static foundation::UniqueID get_class_uid();
89 
90     // Delete this instance.
91     void release() override;
92 
93     // Compute and return the unique signature of this instance.
94     foundation::uint64 compute_signature() const override;
95 
96     // Return the name of the instantiated object.
97     const char* get_object_name() const;
98 
99     // Return the transform of this instance.
100     const foundation::Transformd& get_transform() const;
101 
102     // Return true if the transform of this instance swaps handedness.
103     bool transform_swaps_handedness() const;
104 
105     // Return true if the normals of this instance must be flipped.
106     bool must_flip_normals() const;
107 
108     // Return or set visibility flags of this instance.
109     foundation::uint32 get_vis_flags() const;
110     void set_vis_flags(const foundation::uint32 flags);
111 
112     // Return the medium priority of this instance.
113     foundation::int8 get_medium_priority() const;
114 
115     enum RayBiasMethod
116     {
117         RayBiasMethodNone,                  // no ray bias for this object instance
118         RayBiasMethodNormal,                // shift the ray's origin along the surface's geometric normal
119         RayBiasMethodIncomingDirection,     // shift the ray's origin along the incoming ray's direction
120         RayBiasMethodOutgoingDirection      // shift the ray's origin along the outgoing ray's direction
121     };
122 
123     // Return the ray bias settings. The bias distance is expressed in world space.
124     RayBiasMethod get_ray_bias_method() const;
125     double get_ray_bias_distance() const;
126 
127     // Check if this object instance is in the same SSS set as another.
128     bool is_in_same_sss_set(const ObjectInstance& other) const;
129 
130     // Find the object bound to this instance.
131     Object* find_object() const;
132 
133     // Compute the parent space bounding box of the instance.
134     GAABB3 compute_parent_bbox() const;
135 
136     // Sides of this object instance's surface.
137     enum Side
138     {
139         FrontSide = 1UL << 0,
140         BackSide  = 1UL << 1,
141         BothSides = FrontSide | BackSide
142     };
143 
144     // Clear all material assignments.
145     void clear_front_materials();
146     void clear_back_materials();
147 
148     // Assign a material to a given slot.
149     void assign_material(
150         const char*     slot,
151         const Side      side,
152         const char*     name);
153 
154     // Unassign a material from a given slot.
155     void unassign_material(
156         const char*     slot,
157         const Side      side);
158 
159     // Return the slot-to-material mappings of this instance.
160     foundation::StringDictionary& get_front_material_mappings() const;
161     foundation::StringDictionary& get_back_material_mappings() const;
162 
163     // Get the name of the material bound to a given primitive of this instance.
164     const char* get_material_name(const size_t pa_index, const Side side) const;
165 
166     // Object binding.
167     void unbind_object();
168     void bind_object(const ObjectContainer& objects);
169     void check_object() const;
170 
171     // Material binding.
172     void unbind_materials();
173     void bind_materials(const MaterialContainer& materials);
174     void check_materials() const;
175 
176     // Return the object bound to this instance.
177     Object& get_object() const;
178 
179     // Return the materials bound to this instance.
180     const MaterialArray& get_front_materials() const;
181     const MaterialArray& get_back_materials() const;
182 
183     // Return true if at least one of the material referenced by this instance
184     // has a volume assigned to it.
185     bool has_participating_media() const;
186 
187     // Return true if at least one of the material referenced by this instance has an alpha map set.
188     bool uses_alpha_mapping() const;
189 
190     bool on_frame_begin(
191         const Project&              project,
192         const BaseGroup*            parent,
193         OnFrameBeginRecorder&       recorder,
194         foundation::IAbortSwitch*   abort_switch = nullptr) override;
195 
196   private:
197     friend class ObjectInstanceFactory;
198 
199     struct Impl;
200     Impl* impl;
201 
202     foundation::uint32  m_vis_flags;
203     foundation::int8    m_medium_priority;
204     RayBiasMethod       m_ray_bias_method;
205     double              m_ray_bias_distance;
206     bool                m_transform_swaps_handedness;
207     bool                m_flip_normals;
208 
209     Object*             m_object;
210     MaterialArray       m_front_materials;
211     MaterialArray       m_back_materials;
212 
213     // Constructor.
214     ObjectInstance(
215         const char*                         name,
216         const ParamArray&                   params,
217         const char*                         object_name,
218         const foundation::Transformd&       transform,
219         const foundation::StringDictionary& front_material_mappings,
220         const foundation::StringDictionary& back_material_mappings);
221 
222     // Destructor.
223     ~ObjectInstance() override;
224 };
225 
226 
227 //
228 // Object instance factory.
229 //
230 
231 class APPLESEED_DLLSYMBOL ObjectInstanceFactory
232 {
233   public:
234     // Return a set of input metadata for object instance entities.
235     static foundation::DictionaryArray get_input_metadata();
236 
237     // Create a new object instance.
238     static foundation::auto_release_ptr<ObjectInstance> create(
239         const char*                         name,
240         const ParamArray&                   params,
241         const char*                         object_name,
242         const foundation::Transformd&       transform,
243         const foundation::StringDictionary& front_material_mappings,
244         const foundation::StringDictionary& back_material_mappings = foundation::StringDictionary());
245 };
246 
247 
248 //
249 // ObjectInstance class implementation.
250 //
251 
transform_swaps_handedness()252 inline bool ObjectInstance::transform_swaps_handedness() const
253 {
254     return m_transform_swaps_handedness;
255 }
256 
must_flip_normals()257 inline bool ObjectInstance::must_flip_normals() const
258 {
259     return m_flip_normals;
260 }
261 
get_vis_flags()262 inline foundation::uint32 ObjectInstance::get_vis_flags() const
263 {
264     return m_vis_flags;
265 }
266 
set_vis_flags(const foundation::uint32 flags)267 inline void ObjectInstance::set_vis_flags(const foundation::uint32 flags)
268 {
269     m_vis_flags = flags;
270 }
271 
get_medium_priority()272 inline foundation::int8 ObjectInstance::get_medium_priority() const
273 {
274     return m_medium_priority;
275 }
276 
get_ray_bias_method()277 inline ObjectInstance::RayBiasMethod ObjectInstance::get_ray_bias_method() const
278 {
279     return m_ray_bias_method;
280 }
281 
get_ray_bias_distance()282 inline double ObjectInstance::get_ray_bias_distance() const
283 {
284     return m_ray_bias_distance;
285 }
286 
get_object()287 inline Object& ObjectInstance::get_object() const
288 {
289     assert(m_object);
290     return *m_object;
291 }
292 
get_front_materials()293 inline const MaterialArray& ObjectInstance::get_front_materials() const
294 {
295     return m_front_materials;
296 }
297 
get_back_materials()298 inline const MaterialArray& ObjectInstance::get_back_materials() const
299 {
300     return m_back_materials;
301 }
302 
303 }   // namespace renderer
304