opennurbs_material.h
1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #if !defined(OPENNURBS_MATERIAL_INC_)
18 #define OPENNURBS_MATERIAL_INC_
19 
20 
21 ///////////////////////////////////////////////////////////////////////////////
22 //
23 // Class ON_Material
24 //
25 class ON_CLASS ON_Material : public ON_ModelComponent
26 {
27  ON_OBJECT_DECLARE(ON_Material);
28 
29 public:
30  static const double MaxShine; // maximum value of shine exponent = 255.0
31 
32  static const ON_Material Unset; // nil id
33  static const ON_Material Default; // persistent id
34 
35  /*
36  Parameters:
37  model_component_reference - [in]
38  none_return_value - [in]
39  value to return if ON_Material::Cast(model_component_ref.ModelComponent())
40  is nullptr
41  Returns:
42  If ON_Material::Cast(model_component_ref.ModelComponent()) is not nullptr,
43  that pointer is returned. Otherwise, none_return_value is returned.
44  */
45  static const ON_Material* FromModelComponentRef(
46  const class ON_ModelComponentReference& model_component_reference,
47  const ON_Material* none_return_value
48  );
49 
50  // compare everything except Index() value.
51  static int Compare(
52  const ON_Material& a,
53  const ON_Material& b
54  );
55 
56  // compare Id(), Name(), m_rdk_material_instance_id
57  static int CompareNameAndIds(
58  const ON_Material& a,
59  const ON_Material& b
60  );
61 
62  // Compare all settings (color, reflection, texture, plug-in id)
63  // that effect the appearance.
64  // Ignore Index(), Id(), Name(), m_rdk_material_instance_id.
65  static int CompareAppearance(
66  const ON_Material& a,
67  const ON_Material& b
68  );
69 
70  static int CompareColorAttributes(
71  const ON_Material& a,
72  const ON_Material& b
73  );
74 
75  static int CompareReflectionAttributes(
76  const ON_Material& a,
77  const ON_Material& b
78  );
79 
80  static int CompareTextureAttributes(
81  const ON_Material& a,
82  const ON_Material& b
83  );
84 
85 
86 
87  /*
88  Parameters:
89  fresnel_index_of_refraction - [in]
90  ON_Material::Material::Default.m_fresnel_index_of_refraction
91  is a good default
92  N - [in]
93  3d surface normal
94  R - [in]
95  3d reflection direction
96  Returns:
97  1.0:
98  The input values were not valid or the calculation failed due to
99  a divide by zero or some other numerical arithmetic failure.
100  fresnel reflection coefficient
101  1/2 * ((g-c)/(g+c))^2 * (1 + ( (c*(g+c) -1)/(c*(g+c) + 1) )^2)
102  where
103  c = N o (N-R); // c = 3d vector dot product of N and (N-R)
104  and
105  g = sqrt(fresnel_index_of_refraction*fresnel_index_of_refraction + c*c - 1.0).
106  */
107  static double FresnelReflectionCoefficient(
108  double fresnel_index_of_refraction,
109  const double N[3],
110  const double R[3]
111  );
112 
113 public:
114  ON_Material() ON_NOEXCEPT;
115  ON_Material(const ON_Material& src);
116  ~ON_Material() = default;
117  ON_Material& operator=(const ON_Material& src) = default;
118 
119 private:
120  void Internal_CopyFrom(
121  const ON_Material& src
122  );
123 
124 public:
125  /////////////////////////////////////////////////////////////////
126  // ON_Object overrides
127  bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
128 
129  void Dump(
130  ON_TextLog& text_log
131  ) const override;
132 
133  bool Write(
134  ON_BinaryArchive& archive
135  ) const override;
136 
137  bool Read(
138  ON_BinaryArchive& archive
139  ) override;
140 
141  ON::object_type ObjectType() const override;
142 
143  /////////////////////////////////////////////////////////////////
144  // Interface
145 
146  ON_Color Ambient() const;
147  ON_Color Diffuse() const;
148  ON_Color Emission() const;
149  ON_Color Specular() const;
150 
151  void SetAmbient( ON_Color );
152  void SetDiffuse( ON_Color );
153  void SetEmission( ON_Color );
154  void SetSpecular( ON_Color );
155 
156  // Shine values are in range 0.0 to ON_Material::MaxShine
157  double Shine() const;
158  void SetShine( double ); // 0 to ON_Material::MaxShine
159 
160  // Transparency values are in range 0.0 = opaque to 1.0 = transparent
161  double Transparency() const;
162  void SetTransparency( double ); // 0.0 = opaque, 1.0 = transparent
163 
164  // Transparency values are in range 0.0 = opaque to 1.0 = transparent
165  double Reflectivity() const;
166  void SetReflectivity( double ); // 0.0 = opaque, 1.0 = transparent
167 
168  // ID of the last plug-in to modify this material
169  ON_UUID MaterialPlugInId() const;
170  void SetMaterialPlugInId(
171  ON_UUID plugin_id
172  );
173 
174 public:
175  /*
176  Description:
177  Get the RDK material id.
178  Returns:
179  The RDK material id for this material.
180  Remarks:
181  The RDK material id identifies a material definition managed by
182  the RDK (rendering development kit). Multiple materials in
183  a Rhino or opennurbs model can reference the same RDK material.
184  */
185  ON_UUID RdkMaterialInstanceId() const;
186 
187  /*
188  Description:
189  Set this material's RDK material id.
190  Parameters:
191  rdk_material_id - [in]
192  RDK material id value.
193  Remarks:
194  The RDK material id identifies a material definition managed by
195  the RDK (rendering development kit). Multiple materials in
196  a Rhino or opennurbs model can reference the same RDK material.
197  */
198  void SetRdkMaterialInstanceId(
199  ON_UUID rdk_material_instance_id
200  );
201 
202  bool RdkMaterialInstanceIdIsNotNil() const;
203  bool RdkMaterialInstanceIdIsNil() const;
204 
205  /*
206  Returns:
207  True if the material can be shared.
208  Remarks:
209  If true, when an object using this material is copied,
210  the copy references the same material.
211  */
212  bool Shareable() const;
213  void SetShareable(
214  bool bShareable
215  );
216 
217  /*
218  Returns:
219  True if lighting is disabled.
220  Remarks:
221  True means render this object without
222  applying any modulation based on lights.
223  Basically, the diffuse, ambient, specular and
224  emissive channels get combined additively, clamped,
225  and then get treated as an emissive channel.
226  Another way to think about it is when
227  m_bDisableLighting is true, render the same way
228  OpenGL does when ::glDisable( GL_LIGHTING ) is called.
229  */
230  bool DisableLighting() const;
231 
232  void SetDisableLighting(
233  bool bDisableLighting
234  );
235 
236  //If m_bUseDiffuseTextureAlphaForObjectTransparencyTexture is true, the alpha channel
237  //of the texture in m_textures with m_type=bitmap_texture is used in addition to any
238  //textures with m_type=transparency_texture.
239  bool UseDiffuseTextureAlphaForObjectTransparencyTexture() const;
240  void SetUseDiffuseTextureAlphaForObjectTransparencyTexture(
241  bool bUseDiffuseTextureAlphaForObjectTransparencyTexture
242  );
243 
244  //////////////////////////////////////////////////////////////
245  //
246  // Reflection and Refraction settings
247  //
248 
249  // The bool m_bFresnelReflections enables fresnel scaling
250  // of reflection contributions to the diffuse color.
251  // True:
252  // The fresnel term is used to scale the reflection contribution
253  // before addition to the diffuse component.
254  // False:
255  // The reflection contribution is simply added to the diffuse component.
256  bool FresnelReflections() const;
257  void SetFresnelReflections(
258  bool bFresnelReflections
259  );
260 
261 
262 private:
263  // The value of m_rdk_material_id idetifies an RDK (rendering development kit)
264  // material. Multiple materials in a Rhino model can refer to the same
265  // RDK material id. In V5 this value is stored in user data. In V6 it is
266  // saved in the m_rdk_material_id field.
267  ON_UUID m_rdk_material_instance_id = ON_nil_uuid;
268 
269 public:
270  ON_Color m_ambient = ON_Color::Black;
271  ON_Color m_diffuse = ON_Color::Gray126;
272  ON_Color m_emission = ON_Color::Black;
273  ON_Color m_specular = ON_Color::White;
274  ON_Color m_reflection = ON_Color::White;
275  ON_Color m_transparent = ON_Color::White;
276 
277 private:
278  bool m_bShareable = false;
279 
280 private:
281  bool m_bDisableLighting = false;
282 
283 private:
284  bool m_bUseDiffuseTextureAlphaForObjectTransparencyTexture = false;
285 
286 private:
287  bool m_bFresnelReflections = false;
288 
289 private:
290  unsigned int m_reserved1 = 0;
291 
292 public:
293  double m_reflectivity = 0.0; // 0.0 = none, 1.0 = 100%
294  double m_shine = 0.0; // 0.0 = none to GetMaxShine()=maximum
295  double m_transparency = 0.0; // 0.0 = opaque to 1.0 = transparent (1.0-alpha)
296 
297  /*
298  m_reflection_glossiness:
299  Default is 0.0.
300  Values from 0.0 to 1.0 make sense.
301  - 0.0 reflections are perfectly specular.
302  - t > 0.0 permits reflection ray direction to vary
303  from the specular direction by up to t*pi/2.
304  */
305  double m_reflection_glossiness = 0.0;
306 
307  /*
308  m_refraction_glossiness:
309  Default is 0.0.
310  Values from 0.0 to 1.0 make sense.
311  - 0.0 refractions are perfectly specular.
312  - t > 0.0 permits refraction ray direction to vary
313  from the specular direction by up to t*pi/2.
314  */
315  double m_refraction_glossiness = 0.0;
317  /*
318  m_index_of_refraction:
319  Default is 1.0.
320  Physically, the index of refraction is >= 1.0 and is
321  the value (speed of light in vacum)/(speed of light in material).
322  Some rendering algorithms set m_index_of_refraction to zero or
323  values < 1.0 to generate desirable effects.
324  */
325  double m_index_of_refraction = 1.0;
326 
327  /*
328  m_fresnel_index_of_refraction:
329  Default is 1.56.
330  This is the value ON:Material::FresnelReflectionCoefficient() passes
331  as the first parameter to ON_FresnelReflectionCoefficient().
332  - Glass material types can be simulated with
333  m_index_of_refraction ~ 1.56
334  m_fresnel_index_of_refraction ~ 1.56
335  - Thin glass can be simulated with
336  m_fresnel_index_of_refraction = 1.56
337  m_index_of_refraction = 0.0
338  - Porcelain type materials can be simulated with
339  m_fresnel_index_of_refraction = 1.56
340  m_index_of_refraction = 1.0
341  m_transparency = 0.0
342  */
343  double m_fresnel_index_of_refraction = 1.56;
344 
345  /*
346  Parameters:
347  N - [in]
348  3d surface normal
349  R - [in]
350  3d reflection direction
351  Returns:
352  If m_bFresnelReflections is false, then 1.0 is returned.
353  If m_bFresnelReflections is true, then the value of the fresnel
354  reflection coefficient is returned. In typical rendering applications,
355  the reflection term is multiplied by the fresnel reflection coefficient
356  before it is added to the diffuse color.
357  If any input is not valid or the calculation fails, then 1.0 is returned.
358  Remarks:
359  When m_bFresnelReflections is true, the calculation is performed by
360  calling ON_FresnelReflectionCoefficient() with m_fresnel_index_of_refraction
361  as the fresnel index of refraction.
362  */
363  double FresnelReflectionCoefficient(
364  ON_3dVector N,
365  ON_3dVector R
366  ) const;
367 
368  /*
369  Description:
370  Searches for a texure with matching texture_id.
371  If more than one texture matches, the first match
372  is returned.
373  Parameters:
374  texture_id - [in]
375  Returns:
376  >=0 m_textures[] index of matching texture
377  -1 if no match is found.
378  */
379  int FindTexture(
380  ON_UUID texture_id
381  ) const;
382 
383  /*
384  Description:
385  Searches for a texure with matching filename and type.
386  If more than one texture matches, the first match
387  is returned.
388  Parameters:
389  filename - [in] If nullptr, then any filename matches.
390  type - [in] If ON_Texture::no_texture_type, then
391  any texture type matches.
392  i0 - [in] If i0 is < 0, the search begins at
393  m_textures[0], if i0 >= m_textures.Count(),
394  -1 is returnd, otherwise, the search begins
395  at m_textures[i0+1].
396  Example:
397  Iterate through all the the bitmap textures on
398  a material.
399 
400  ON_Material& mat = ...;
401  int ti = -1;
402  int bitmap_texture_count = 0;
403  for(;;)
404  {
405  ti = mat.FindTexture(
406  nullptr,
407  ON_Texture::TYPE::bitmap_texture,
408  ti );
409 
410  if ( ti < 0 )
411  {
412  // no more bitmap textures
413  break;
414  }
415 
416  // we have a bitmap texture
417  bitmap_texture_count++;
418  const ON_Texture& bitmap_texture = mat.m_textures[ti];
419  ...
420  }
421 
422  Returns:
423  >=0 m_textures[] index of matching texture
424  -1 if no match is found.
425  */
426  int FindTexture(
427  const wchar_t* filename,
428  ON_Texture::TYPE type,
429  int i0 = -1
430  ) const;
431 
432  /*
433  Description:
434  If there is already a texture with the same file name and
435  type, then that texture is modified, otherwise a new texture
436  is added. If tx has user data, the user data is copied
437  to the m_textures[] element.
438  Parameters:
439  tx - [in]
440  Returns:
441  Index of the added texture in the m_textures[] array.
442  Remarks:
443  This is intended to be a quick and simple way to add
444  textures to the material. If you need to do something
445  different, then just work on the m_textures[] array.
446  */
447  int AddTexture(
448  const ON_Texture& tx
449  );
450 
451  /*
452  Description:
453  If there is a texture with a matching type, that texture's
454  filename is modified, otherwise a new texture is added.
455  Parameters:
456  filename - [in] new filename
457  type - [in]
458  Returns:
459  Index of the added texture in the m_textures[] array.
460  Remarks:
461  This is intended to be a quick and simple way to add
462  textures to the material. If you need to do something
463  different, then just work on the m_textures[] array.
464  */
465  int AddTexture(
466  const wchar_t* filename,
467  ON_Texture::TYPE type
468  );
469 
470  /*
471  Description:
472  Deletes all texures with matching filenames and types.
473  Parameters:
474  filename - [in] If nullptr, then any filename matches.
475  type - [in] If ON_Texture::no_texture_type, then
476  any texture type matches.
477  Returns:
478  Number of textures deleted.
479  */
480  int DeleteTexture(
481  const wchar_t* filename,
482  ON_Texture::TYPE type
483  );
484 
485  ON_ObjectArray<ON_Texture> m_textures;
486 
487  /*
488  Description:
489  Used to provide per face material support.
490  The parent object reference a basic material.
491  When a brep face or mesh facet wants to use
492  a material besides the base material, it specifies
493  a channelSupports material channel. The default
494  material channel is 0 and that indicates the base
495  material. A channel of n > 0 means that face
496  used the material with id m_material_channel[n-1].
497  If (n-1) >= m_material_channel.Count(), then the base
498  material is used. The value of
499  m_material_channel[n].m_id is persistent. The
500  value of m_material_channel[n].m_i is a runtime
501  index in the CRhinoDoc::m_material_table[]. If
502  CRhinoDoc::m_material_table[m_i].m_uuid != m_id,
503  then m_id is assumed to be correct.
504  */
505  ON_SimpleArray<ON_UuidIndex> m_material_channel;
506 
507 private:
508  ON_UUID m_plugin_id = ON_nil_uuid;
509 
510 private:
511  bool Internal_ReadV3( ON_BinaryArchive& archive, int minor_version );
512  bool Internal_WriteV3( ON_BinaryArchive& archive ) const;
513  bool Internal_ReadV5( ON_BinaryArchive& archive );
514  bool Internal_WriteV5( ON_BinaryArchive& archive ) const;
515 };
516 
517 ON_DECL
518 bool operator==(const ON_Material&, const ON_Material&);
519 
520 ON_DECL
521 bool operator!=(const ON_Material&, const ON_Material&);
522 
523 #if defined(ON_DLL_TEMPLATE)
524 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_Material*>;
525 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<const ON_Material*>;
526 ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray<ON_Material>;
527 
528 // NO! // ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_Material>;
529 // It is a serious error to have an ON_ClassArray<ON_Material> and crashes
530 // will occur when user data back pointers are not updated.
531 #endif
532 
533 #endif
534 
static const ON_Material Unset
Definition: opennurbs_material.h:32
Definition: opennurbs_material.h:25
ON_UUID is a 16 byte universally unique identifier.
Definition: opennurbs_uuid.h:32
static const double MaxShine
Definition: opennurbs_material.h:30
The ON_ModelComponent class is a base class for all components in a model and manages the index...
Definition: opennurbs_model_component.h:24
Definition: opennurbs_array.h:36
static const ON_Material Default
Definition: opennurbs_material.h:33
ON_Object array is used to store lists of classes that are derived from ON_Object. It differs from ON_ClassArray in that the virtual ON_Object::MemoryRelocate function is called when growing the dynamic array requires changing the location of the memory buffer used to store the elements in the array.
Definition: opennurbs_array.h:725
Definition: opennurbs_color.h:24
Definition: opennurbs_textlog.h:20
Definition: opennurbs_archive.h:1783
Definition: opennurbs_model_component.h:1622
Definition: opennurbs_texture.h:31
Definition: opennurbs_point.h:1152