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) 2015-2018 Francois Beaune, 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/modeling/scene/visibilityflags.h"
33 
34 // Standard headers.
35 #include <cassert>
36 
37 namespace renderer
38 {
39 
40 //
41 // All possible scattering modes.
42 //
43 
44 class ScatteringMode
45 {
46   public:
47     enum ModeBitShift
48     {
49         DiffuseBitShift     = 0,
50         GlossyBitShift      = 1,
51         SpecularBitShift    = 2,
52         VolumeBitShift      = 3
53     };
54 
55     enum Mode
56     {
57         None                = 0,
58         Diffuse             = 1UL << DiffuseBitShift,
59         Glossy              = 1UL << GlossyBitShift,
60         Specular            = 1UL << SpecularBitShift,
61         Volume              = 1UL << VolumeBitShift,
62         All                 = Diffuse | Glossy | Specular | Volume
63     };
64 
65     // Test for the presence of specific scattering modes.
66     static bool has_diffuse(const int modes);
67     static bool has_glossy(const int modes);
68     static bool has_specular(const int modes);
69     static bool has_volume(const int modes);
70     static bool has_diffuse_or_glossy_or_volume(const int modes);
71     static bool has_diffuse_and_glossy(const int modes);
72     static bool has_diffuse_or_volume(const int modes);
73     static bool has_glossy_or_specular(const int modes);
74 
75     // Determine the appropriate visibility type for a given scattering mode.
76     static VisibilityFlags::Type get_vis_flags(const Mode mode);
77 };
78 
79 
80 //
81 // ScatteringMode class implementation.
82 //
83 
has_diffuse(const int modes)84 inline bool ScatteringMode::has_diffuse(const int modes)
85 {
86     return (modes & Diffuse) != 0;
87 }
88 
has_glossy(const int modes)89 inline bool ScatteringMode::has_glossy(const int modes)
90 {
91     return (modes & Glossy) != 0;
92 }
93 
has_specular(const int modes)94 inline bool ScatteringMode::has_specular(const int modes)
95 {
96     return (modes & Specular) != 0;
97 }
98 
has_volume(const int modes)99 inline bool ScatteringMode::has_volume(const int modes)
100 {
101     return (modes & Volume) != 0;
102 }
103 
has_diffuse_or_glossy_or_volume(const int modes)104 inline bool ScatteringMode::has_diffuse_or_glossy_or_volume(const int modes)
105 {
106     return (modes & (Diffuse | Glossy | Volume)) != 0;
107 }
108 
has_diffuse_and_glossy(const int modes)109 inline bool ScatteringMode::has_diffuse_and_glossy(const int modes)
110 {
111     return (modes & (Diffuse | Glossy)) == (Diffuse | Glossy);
112 }
113 
has_diffuse_or_volume(const int modes)114 inline bool ScatteringMode::has_diffuse_or_volume(const int modes)
115 {
116     return (modes & (Diffuse | Volume)) != 0;
117 }
118 
has_glossy_or_specular(const int modes)119 inline bool ScatteringMode::has_glossy_or_specular(const int modes)
120 {
121     return (modes & (Glossy | Specular)) != 0;
122 }
123 
get_vis_flags(const Mode mode)124 inline VisibilityFlags::Type ScatteringMode::get_vis_flags(const Mode mode)
125 {
126     switch (mode)
127     {
128       case Diffuse:
129         return VisibilityFlags::DiffuseRay;
130 
131       case Glossy:
132         return VisibilityFlags::GlossyRay;
133 
134       case Specular:
135         return VisibilityFlags::SpecularRay;
136 
137       default:
138         assert(!"Invalid scattering mode.");
139         return VisibilityFlags::DiffuseRay;
140     }
141 }
142 
143 }   // namespace renderer
144