KiCad PCB EDA Suite
cmaterial.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include "cmaterial.h"
31 #include <3d_math.h>
32 #include <wx/debug.h>
33 
34 // This may be a good value if based on nr of lights
35 // that contribute to the illumination of that point
36 #define AMBIENT_FACTOR (1.0f / 6.0f)
37 #define SPECULAR_FACTOR 1.0f
38 
40 {
41  m_ambientColor = SFVEC3F( 0.2f, 0.2f, 0.2f );
42  m_emissiveColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
43  m_specularColor = SFVEC3F( 1.0f, 1.0f, 1.0f );
44  m_shinness = 50.2f;
45  m_transparency = 0.0f; // completely opaque
46  m_cast_shadows = true;
47  m_reflection = 0.0f;
48  m_absorbance = 1.0f;
51 
52  m_normal_perturbator = NULL;
53 }
54 
55 
56 CMATERIAL::CMATERIAL( const SFVEC3F &aAmbient,
57  const SFVEC3F &aEmissive,
58  const SFVEC3F &aSpecular,
59  float aShinness,
60  float aTransparency,
61  float aReflection )
62 {
63  wxASSERT( aReflection >= 0.0f );
64  wxASSERT( aReflection <= 1.0f );
65 
66  wxASSERT( aTransparency >= 0.0f );
67  wxASSERT( aTransparency <= 1.0f );
68 
69  wxASSERT( aShinness >= 0.0f );
70  wxASSERT( aShinness <= 180.0f );
71 
73 
74  m_emissiveColor = aEmissive;
75  m_specularColor = aSpecular;
76  m_shinness = aShinness;
77  m_transparency = aTransparency;
78  m_absorbance = 1.0f;
79  m_reflection = aReflection;
80  m_cast_shadows = true;
83 
84  m_normal_perturbator = NULL;
85 }
86 
87 
89  const RAY &aRay,
90  const HITINFO &aHitInfo ) const
91 {
93  {
94  aNormal = aNormal + m_normal_perturbator->Generate( aRay, aHitInfo );
95  aNormal = glm::normalize( aNormal );
96  }
97 }
98 
99 
100 // https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model
102  const HITINFO &aHitInfo,
103  float NdotL,
104  const SFVEC3F &aDiffuseObjColor,
105  const SFVEC3F &aDirToLight,
106  const SFVEC3F &aLightColor,
107  float aShadowAttenuationFactor ) const
108 {
109  wxASSERT( NdotL >= FLT_EPSILON );
110 
111  // This is a hack to get some kind of fake ambient illumination
112  // There is no logic behind this, just pure artistic experimentation
113  //const float ambientFactor = glm::max( ( (1.0f - NdotL) /** (1.0f - NdotL)*/ ) *
114  // ( AMBIENT_FACTOR + AMBIENT_FACTOR ),
115  // AMBIENT_FACTOR );
116 
117  if( aShadowAttenuationFactor > FLT_EPSILON )
118  {
119  // Calculate the diffuse light factoring in light color,
120  // power and the attenuation
121  const SFVEC3F diffuse = NdotL * aLightColor;
122 
123  // Calculate the half vector between the light vector and the view vector.
124  const SFVEC3F H = glm::normalize( aDirToLight - aRay.m_Dir );
125 
126  //Intensity of the specular light
127  const float NdotH = glm::dot( H, aHitInfo.m_HitNormal );
128  const float intensitySpecular = glm::pow( glm::max( NdotH, 0.0f ),
129  m_shinness );
130 
131  return m_ambientColor +
132  aShadowAttenuationFactor * ( diffuse * aDiffuseObjColor +
134  aLightColor *
135  intensitySpecular *
136  m_specularColor );
137  }
138 
139  return m_ambientColor;
140 }
141 
142 
144 {
145 }
146 
147 
149 {
150  m_scale = (2.0f * glm::pi<float>()) / aScale;
151 }
152 
153 
154 SFVEC3F CBOARDNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const
155 {
156  const SFVEC3F &hitPos = aHitInfo.m_HitPoint;
157 
158  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJzaW4oc2luKHNpbih4KSoxLjkpKjEuNSkiLCJjb2xvciI6IiMwMDAwMDAifSx7InR5cGUiOjEwMDAsIndpbmRvdyI6WyItMC45NjIxMDU3MDgwNzg1MjYyIiwiNy45NzE0MjYyNjc2MDE0MyIsIi0yLjUxNzYyMDM1MTQ4MjQ0OSIsIjIuOTc5OTM3Nzg3Mzk3NTMwMyJdLCJzaXplIjpbNjQ2LDM5Nl19XQ--
159 
160  // Implement a texture as the "measling crazing blistering" method of FR4
161 
162  const float x = (glm::sin(glm::sin( glm::sin( hitPos.x * m_scale ) * 1.9f ) * 1.5f ) + 0.0f) * 0.10f;
163  const float y = (glm::sin(glm::sin( glm::sin( hitPos.y * m_scale ) * 1.9f ) * 1.5f ) + 0.0f) * 0.10f;
164  const float z = glm::sin( 2.0f * hitPos.z * m_scale + Fast_RandFloat() * 1.0f ) * 0.2f;
165 
166  return SFVEC3F( x, y, z );
167 }
168 
169 
170 CCOPPERNORMAL::CCOPPERNORMAL( float aScale, const CPROCEDURALGENERATOR *aBoardNormalGenerator )
171 {
172  m_board_normal_generator = aBoardNormalGenerator;
174  m_scale = 1.0f / aScale;
175 }
176 
177 
178 SFVEC3F CCOPPERNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const
179 {
181  {
182  const SFVEC3F boardNormal = m_board_normal_generator->Generate( aRay, aHitInfo );
183 
184  SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
185 
186  const float noise = (m_copper_perlin.noise( hitPos.x + Fast_RandFloat() * 0.1f,
187  hitPos.y ) - 0.5f) * 2.0f;
188 
189  float scratchPattern = (m_copper_perlin.noise( hitPos.x / 100.0f, hitPos.y * 20.0f ) - 0.5f);
190 
191  scratchPattern = glm::clamp( scratchPattern * 5.0f, -1.0f, 1.0f );
192 
193  const float x = glm::clamp( (noise + scratchPattern) * 0.04f, -0.10f, 0.10f );
194  const float y = glm::clamp( (noise + (noise * scratchPattern)) * 0.04f, -0.10f, 0.10f );
195 
196  return SFVEC3F( x, y, 0.0f ) + boardNormal * 0.85f;
197  }
198  else
199  return SFVEC3F(0.0f);
200 }
201 
202 
204 {
205  m_copper_normal_generator = aCopperNormalGenerator;
206 }
207 
208 
209 SFVEC3F CSOLDERMASKNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const
210 {
212  {
213  const SFVEC3F copperNormal = m_copper_normal_generator->Generate( aRay, aHitInfo );
214 
215  return copperNormal * SFVEC3F(0.10f);
216  }
217  else
218  return SFVEC3F(0.0f);
219 }
220 
221 
223 {
224  m_scale = 1.0f / aScale;
225 }
226 
227 
228 SFVEC3F CPLASTICNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const
229 {
230  const SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
231 
232  const float noise1 = m_perlin.noise( hitPos.x * 1.0f,
233  hitPos.y * 1.0f,
234  hitPos.z * 1.0f ) - 0.5f;
235 
236  const float noise2 = m_perlin.noise( hitPos.x * 1.5f,
237  hitPos.y * 1.5f,
238  hitPos.z * 2.0f ) - 0.5f;
239 
240  const float noise3 = m_perlin.noise( hitPos.x * 2.0f,
241  hitPos.y * 2.0f,
242  hitPos.z * 2.0f ) - 0.5f;
243 
244  return SFVEC3F( noise1 * noise2 * noise3 * 4.00f,
245  noise1 * expf(noise2) * noise3 * 4.00f,
246  noise3 * noise3 * 1.00f );
247 }
248 
249 
251 {
252  m_scale = 1.0f / aScale;
253 }
254 
255 
256 SFVEC3F CPLASTICSHINENORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const
257 {
258  const SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
259 
260  const float noise1 = m_perlin.noise( hitPos.x * 0.05f,
261  hitPos.y * 0.05f,
262  hitPos.z * 0.05f ) - 0.5f;
263 
264  const float noise2 = m_perlin.noise( hitPos.x * 0.2f,
265  hitPos.y * 0.2f,
266  hitPos.z * 0.2f ) - 0.5f;
267 
268  const float noise3 = m_perlin.noise( hitPos.x * 0.5f,
269  hitPos.y * 0.5f,
270  hitPos.z * 0.5f ) - 0.5f;
271 
272  return SFVEC3F( noise1 * 0.5f, noise2 * 0.5f, noise3 * 0.5f );
273 }
274 
275 
277 {
278  m_scale = 1.0f / aScale;
279 }
280 
281 
282 SFVEC3F CMETALBRUSHEDNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const
283 {
284  const SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
285 
286  const SFVEC3F hitPosRelative = hitPos - glm::floor( hitPos );
287 
288  const float noiseX = (m_perlin.noise( hitPos.x * (60.0f),
289  hitPos.y * 1.0f,
290  hitPos.z * 1.0f ) - 0.5f);
291 
292  const float noiseY = (m_perlin.noise( hitPos.x * 1.0f,
293  hitPos.y * (60.0f),
294  hitPos.z * 1.0f ) - 0.5f);
295 
296  const float noise2 = (m_perlin.noise( hitPos.x * 1.0f,
297  hitPos.y * 1.0f,
298  hitPos.z * 1.0f ) - 0.5f);
299 
300  const float noise3X = (m_perlin.noise( hitPos.x * (80.0f + noise2 * 0.5f),
301  hitPos.y * 0.5f,
302  hitPos.z * 0.5f ) - 0.5f );
303 
304  const float noise3Y = (m_perlin.noise( hitPos.x * 0.5f,
305  hitPos.y * (80.0f + noise2 * 0.5f),
306  hitPos.z * 0.5f ) - 0.5f );
307 
308  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiIoKHgtZmxvb3IoeCkpK3Npbih4KSleMyIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi02LjcxNDAwMDAxOTAzMDA3NyIsIjcuMjQ0NjQzNjkyOTY5NzM5IiwiLTMuMTU1NTUyNjAxNDUyNTg4IiwiNS40MzQzODE5OTA1NDczMDY1Il0sInNpemUiOls2NDQsMzk0XX1d
309  // ((x - floor(x))+sin(x))^3
310 
311  float sawX = (hitPosRelative.x + glm::sin( 10.0f * hitPos.x + 5.0f * noise2 + Fast_RandFloat() ) );
312  sawX = sawX * sawX * sawX;
313 
314  float sawY = (hitPosRelative.y + glm::sin( 10.0f * hitPos.y + 5.0f * noise2 + Fast_RandFloat() ) );
315  sawY = sawY * sawY * sawY;
316 
317  float xOut = sawX * noise3X * 0.17f + noiseX * 0.25f + noise3X * 0.57f;
318  float yOut = sawY * noise3Y * 0.17f + noiseY * 0.25f + noise3Y * 0.57f;
319 
320  const float outLowFreqNoise = noise2 * 0.05f;
321 
322  return SFVEC3F( xOut + outLowFreqNoise,
323  yOut + outLowFreqNoise,
324  0.0f + outLowFreqNoise );
325 }
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate - Generates a 3D vector based on the ray and hit information depending on the implementation...
Definition: cmaterial.cpp:178
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate - Generates a 3D vector based on the ray and hit information depending on the implementation...
Definition: cmaterial.cpp:282
const CPROCEDURALGENERATOR * m_copper_normal_generator
Definition: cmaterial.h:104
PerlinNoise m_copper_perlin
Definition: cmaterial.h:89
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate - Generates a 3D vector based on the ray and hit information depending on the implementation...
Definition: cmaterial.cpp:209
Definition: ray.h:43
float m_reflection
1.0 completely reflective, 0.0 no reflective
Definition: cmaterial.h:237
float Fast_RandFloat()
Definition: 3d_fastmath.cpp:45
float m_transparency
1.0 is completely transparent, 0.0 completely opaque
Definition: cmaterial.h:235
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate - Generates a 3D vector based on the ray and hit information depending on the implementation...
Definition: cmaterial.cpp:154
float m_scale
Definition: cmaterial.h:69
SFVEC3F m_ambientColor
Definition: cmaterial.h:226
SFVEC3F m_HitPoint
(12) hit position
Definition: hitinfo.h:49
unsigned int m_reflections_nr_samples
nr of rays that will be interpolated for this material if it is reflective
Definition: cmaterial.h:240
const CPROCEDURALGENERATOR * m_normal_perturbator
Definition: cmaterial.h:242
PerlinNoise m_perlin
Definition: cmaterial.h:123
float m_shinness
Definition: cmaterial.h:234
PerlinNoise m_perlin
Definition: cmaterial.h:162
bool m_cast_shadows
true if this object will block the light
Definition: cmaterial.h:238
void PerturbeNormal(SFVEC3F &aNormal, const RAY &aRay, const HITINFO &aHitInfo) const
Definition: cmaterial.cpp:88
SFVEC3F Shade(const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, float aShadowAttenuationFactor) const override
Shade - Shades an intersection point.
Definition: cmaterial.cpp:101
virtual SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const =0
Generate - Generates a 3D vector based on the ray and hit information depending on the implementation...
PerlinNoise m_perlin
Definition: cmaterial.h:143
const CPROCEDURALGENERATOR * m_board_normal_generator
Definition: cmaterial.h:88
SFVEC3F m_Dir
Definition: ray.h:48
float noise(float x, float y, float z) const
Definition: PerlinNoise.cpp:97
Stores the hit information of a ray with a point on the surface of a object.
Definition: hitinfo.h:40
#define max(a, b)
Definition: auxiliary.h:86
glm::vec3 SFVEC3F
Definition: xv3d_types.h:47
#define AMBIENT_FACTOR
Definition: cmaterial.cpp:36
Defines math related functions.
#define SPECULAR_FACTOR
Definition: cmaterial.cpp:37
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition: hitinfo.h:42
float m_scale
Definition: cmaterial.h:90
SFVEC3F m_emissiveColor
Definition: cmaterial.h:232
SFVEC3F m_specularColor
Definition: cmaterial.h:233
unsigned int m_refraction_nr_samples
nr of rays that will be interpolated for this material if it is a transparent
Definition: cmaterial.h:239
A base class that can be used to derive a procedural generator implementation.
Definition: cmaterial.h:38
float m_absorbance
absorvance factor for the transparent material
Definition: cmaterial.h:236
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate - Generates a 3D vector based on the ray and hit information depending on the implementation...
Definition: cmaterial.cpp:228
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate - Generates a 3D vector based on the ray and hit information depending on the implementation...
Definition: cmaterial.cpp:256