VTK  9.2.6
Material.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "vtkLogger.h"
4 
5 #include "../Types.h"
6 #include "OSPRayMDL.h"
7 #include "Texture.h"
8 
9 #include <VisRTX.h>
10 #include <cassert>
11 #include <set>
12 #include <sstream>
13 #include <string>
14 
15 namespace RTW
16 {
17  class Material : public Object
18  {
19  friend class Geometry;
20 
21  public:
22  Material(const std::string& type) : Object(RTW_MATERIAL), type(type)
23 
24  {
25  VisRTX::Context* rtx = VisRTX_GetContext();
26 
27  /*
28  * Basic material
29  */
30  if (this->type == "obj" || this->type == "luminous")
31  {
32  this->material = rtx->CreateBasicMaterial();
33  }
34 
35  /*
36  * MDL material
37  */
38  else
39  {
40  //OSPRay 2.0 name backward compatibility.
41  if (this->type == "alloy")
42  this->type = "Alloy";
43  else if (this->type == "carPaint")
44  this->type = "CarPaint";
45  else if (this->type == "glass")
46  this->type = "Glass";
47  else if (this->type == "metal")
48  this->type = "Metal";
49  else if (this->type == "metallicPaint")
50  this->type = "MetallicPaint";
51  else if (this->type == "obj")
52  this->type = "OBJMaterial";
53  else if (this->type == "principled")
54  this->type = "Principled";
55  else if (this->type == "thinGlass")
56  this->type = "ThinGlass";
57 
58  const std::string materialname = "::ospray::" + this->type;
59  try
60  {
61  this->material = rtx->CreateMDLMaterial(materialname.c_str(), (char*)OSPRay_mdl, (uint32_t) sizeof(OSPRay_mdl), 0, nullptr, VisRTX::CompilationType::INSTANCE);
62  }
63  catch(const std::exception&)
64  {
65  vtkLogF(ERROR, "VisRTX Error: CreateMDLMaterial failed! Falling back to BasicMaterial.");
66  this->material = nullptr;
67  }
68  if (!this->material)
69  {
70  this->material = rtx->CreateBasicMaterial();
71  }
72  }
73  assert(this->material != nullptr);
74  }
75 
77  {
78  this->material->Release();
79  }
80 
81  void Commit() override
82  {
83  assert(this->material != nullptr);
84 
85  /*
86  * OBJMaterial (Basic material)
87  */
88  if (this->type == "obj" && this->material->GetType() == VisRTX::MaterialType::BASIC)
89  {
90  VisRTX::BasicMaterial* basicMaterial = dynamic_cast<VisRTX::BasicMaterial*>(this->material);
91  assert(basicMaterial);
92  if (!basicMaterial)
93  {
94  return;
95  }
96 
97  //this->PrintAllParameters();
98 
99  basicMaterial->SetDiffuse(this->GetVec3f({ "kd", "Kd" }, VisRTX::Vec3f(0.8f, 0.8f, 0.8f)));
100  basicMaterial->SetSpecular(this->GetVec3f({ "ks", "Ks" }, VisRTX::Vec3f(0.0f, 0.0f, 0.0f)));
101  basicMaterial->SetShininess(this->GetFloat({ "ns", "Ns" }, 10.0f));
102  basicMaterial->SetOpacity(this->GetFloat({ "d", "alpha" }, 1.0f));
103  basicMaterial->SetTransparencyFilter(this->GetVec3f({ "tf", "Tf" }, VisRTX::Vec3f(0.0f, 0.0f, 0.0f)));
104 
105  Texture* diffuseTex = this->GetObject<Texture>({ "map_Kd", "map_kd" });
106  if (diffuseTex)
107  basicMaterial->SetDiffuseTexture(diffuseTex->texture);
108 
109  Texture* specularTex = this->GetObject<Texture>({ "map_Ks", "map_ks" });
110  if (specularTex)
111  basicMaterial->SetSpecularTexture(specularTex->texture);
112 
113  Texture* shininessTex = this->GetObject<Texture>({ "map_Ns", "map_ns" });
114  if (shininessTex)
115  basicMaterial->SetShininessTexture(shininessTex->texture);
116 
117  Texture* opacityTex = this->GetObject<Texture>({ "map_d", "map_alpha" });
118  if (opacityTex)
119  basicMaterial->SetOpacityTexture(opacityTex->texture);
120 
121  Texture* bumpTex = this->GetObject<Texture>({ "map_Bump", "map_bump" });
122  if (bumpTex)
123  basicMaterial->SetBumpMapTexture(bumpTex->texture);
124  }
125 
126  /*
127  * Luminous (Basic material)
128  */
129  else if (this->type == "luminous" && this->material->GetType() == VisRTX::MaterialType::BASIC)
130  {
131  VisRTX::BasicMaterial* basicMaterial = dynamic_cast<VisRTX::BasicMaterial*>(this->material);
132  assert(basicMaterial);
133  if (!basicMaterial)
134  {
135  return;
136  }
137  basicMaterial->SetEmissive(this->GetVec3f({ "color" }, VisRTX::Vec3f(0.0f, 0.0f, 0.0f)));
138  basicMaterial->SetLuminosity(this->GetFloat({ "intensity" }, 0.0f));
139  }
140 
141  /*
142  * Others (MDL material)
143  */
144  else if (this->material->GetType() == VisRTX::MaterialType::MDL)
145  {
146  VisRTX::MDLMaterial* mdlMaterial = dynamic_cast<VisRTX::MDLMaterial*>(this->material);
147  assert(mdlMaterial);
148  if (!mdlMaterial)
149  {
150  return;
151  }
152 
153  std::set<std::string> ospparams_current = this->GetAllParameters();
154 
155 #define PRINT_MATERIAL_PARAMETERS 0
156 #if PRINT_MATERIAL_PARAMETERS
157  static std::set<std::string> mdltypes_printed;
158  if (mdltypes_printed.find(this->type) == mdltypes_printed.end())
159  {
160  std::vector<std::string> availableParams;
161  for (uint32_t i = 0; i < mdlMaterial->GetParameterCount(); ++i)
162  {
163  availableParams.push_back(mdlMaterial->GetParameterName(i));
164  }
165 
166  for (const auto &parameter : availableParams)
167  {
168  std::string parameterType;
169  switch (mdlMaterial->GetParameterType(parameter.c_str()))
170  {
171  case VisRTX::ParameterType::NONE:
172  parameterType = "none"; break;
173  case VisRTX::ParameterType::COLOR:
174  parameterType = "color"; break;
175  case VisRTX::ParameterType::DOUBLE:
176  parameterType = "double"; break;
177  case VisRTX::ParameterType::FLOAT:
178  parameterType = "float"; break;
179  case VisRTX::ParameterType::INT:
180  parameterType = "int"; break;
181  case VisRTX::ParameterType::BOOL:
182  parameterType = "bool"; break;
183  case VisRTX::ParameterType::TEXTURE:
184  parameterType = "texture"; break;
185  }
186  std::stringstream logStrBuf;
187  logStrBuf << "(mdl) " << this->type << ": " << parameterType << " " << parameter;
188  vtkLogF(INFO, "%s", logStrBuf.str().c_str());
189  }
190  mdltypes_printed.insert(this->type);
191  }
192 
193 
194  static std::set<std::string> ospparams_printed;
195 
196  for (auto param : ospparams_current)
197  {
198  std::string complete = this->type + ": " + param;
199  if (ospparams_printed.find(complete) == ospparams_printed.end())
200  {
201  vtkLogF(INFO, "(osp) %s", complete.c_str());
202  ospparams_printed.insert(complete);
203  }
204  }
205 #endif //PRINT_MATERIAL_PARAMETERS
206 
207 #define WARN_NOT_IMPLEMENTED() vtkLogF(WARNING, "Warning: type \"%s\" not implemented (Material: %s, %s)", paramType.c_str(), this->type.c_str(), paramName.c_str());
208 
209  for (const std::string &param : ospparams_current)
210  {
211  std::string paramType, paramName;
212  {
213  std::istringstream iss(param);
214  iss >> paramType;
215  iss >> paramName;
216  }
217 
218  //getters for osp materials require a vector of names
219  std::vector<std::string> names;
220  names.push_back(paramName);
221 
222  //rename parameters if needed (osp name -> mdl name)
223 
224  static const std::map<std::pair<std::string, std::string>, std::string> renameMap
225  {
226  { { "obj", "map_kd" }, "map_Kd"},
227  { { "obj", "map_bump" }, "map_Bump"},
228  { { "Glass", "etaInside" }, "eta"},
229  { { "obj", "alpha" }, "d"},
230  { { "ThinGlass", "transmission" }, "attenuationColor"}
231  };
232 
233  // explicit renames first
234  auto rename_it = renameMap.find(std::make_pair(this->type, paramName));
235  if (rename_it != renameMap.end())
236  {
237  paramName = rename_it->second;
238  }
239  else
240  {
241  //replace "...Map" with "map_..."
242  const std::string ospSuffix = "Map";
243  const std::string mdlPrefix = "map_";
244  if (paramName.length() >= ospSuffix.length()
245  && paramName.compare(paramName.length() - ospSuffix.length(),
246  ospSuffix.length(), ospSuffix) == 0)
247  {
248  std::string name =
249  paramName.substr(0, paramName.length() - ospSuffix.length());
250  paramName = mdlPrefix + name;
251  }
252  }
253 
254  //exceptions first, e.g. spectra; then handle parameters by type
255  if (paramName == std::string("ior") && paramType == std::string("object"))
256  {
257  Data* iorData = this->GetObject<Data>(names);
258  assert(iorData->GetElementDataType() == RTW_VEC3F);
259 
260  if (iorData->GetElementDataType() != RTW_VEC3F)
261  {
262  vtkLogF(ERROR, "Error: unexpected data type in ior object");
263  return;
264  }
265 
266  const unsigned n_input = iorData->GetNumElements();
267 
268  const VisRTX::Vec3f *input = (const VisRTX::Vec3f*)iorData->GetData();
269 
270  static const unsigned spectrum_size = 8;
271  static const float wavelength_begin = 430.f;
272  static const float wavelength_spacing = 35.f;
273 
274  float eta[spectrum_size], k[spectrum_size];
275 
276  //subsample ior array
277  unsigned iinput = 0u, iprev = 0u;
278  for (unsigned iwl = 0u; iwl < spectrum_size; iwl++)
279  {
280  const float currentwl = wavelength_begin + (float)iwl * wavelength_spacing;
281  for (; iinput < n_input - 1 && input[iinput].x < currentwl; ++iinput)
282  {
283  iprev = iinput;
284  }
285  if (input[iprev].x == input[iinput].x)
286  {
287  eta[iwl] = input[iprev].y;
288  k[iwl] = input[iprev].z;
289  }
290  else
291  {
292  const float t = (currentwl - input[iprev].x) / (input[iinput].x - input[iprev].x);
293  eta[iwl] = (1.f - t) * input[iprev].y + t * input[iinput].y;
294  k[iwl] = (1.f - t) * input[iprev].z + t * input[iinput].z;
295  }
296  }
297 
298  //response functions
299  static const float response_sRGB_r[spectrum_size] =
300  {
301  0.0598548,
302  -0.0234574,
303  -0.220138,
304  -0.238902,
305  0.316327,
306  0.738315,
307  0.323302,
308  0.0446981
309  };
310 
311  static const float response_sRGB_g[spectrum_size] =
312  {
313  -0.0567346,
314  -0.0160361,
315  0.223861,
316  0.531185,
317  0.337221,
318  0.0149718,
319  -0.0296053,
320  -0.00486239
321  };
322 
323  static const float response_sRGB_b[spectrum_size] =
324  {
325  0.420693,
326  0.616597,
327  0.0796766,
328  -0.0496266,
329  -0.0473149,
330  -0.0167536,
331  -0.00295686,
332  -0.000314818
333  };
334 
335  //apply response functions to convert to RGB
336  VisRTX::Vec3f eta3(0.f, 0.f, 0.f), k3(0.f, 0.f, 0.f);
337  for (unsigned iwl = 0u; iwl < spectrum_size; ++iwl)
338  {
339  VisRTX::Vec3f response(response_sRGB_r[iwl], response_sRGB_g[iwl], response_sRGB_b[iwl]);
340 
341  eta3.x += response.x * eta[iwl];
342  eta3.y += response.y * eta[iwl];
343  eta3.z += response.z * eta[iwl];
344  k3.x += response.x * k[iwl];
345  k3.y += response.y * k[iwl];
346  k3.z += response.z * k[iwl];
347  }
348 
349  mdlMaterial->SetParameterColor("eta", eta3);
350  mdlMaterial->SetParameterColor("k", k3);
351  }
352  else if (paramType == std::string("string"))
353  {
354  std::string ospParam = this->GetString(names);
356  }
357  else if (paramType == std::string("object"))
358  {
359  Texture* ospParam = this->GetObject<Texture>(names);
360  if (ospParam)
361  {
362  mdlMaterial->SetParameterTexture(paramName.c_str(), ospParam->texture);
363  }
364  else
365  {
366  vtkLogF(WARNING, "Object \"%s\" of material type \"%s\" is not a texture.", paramName.c_str(), this->type.c_str());
367  }
368  }
369  else if (paramType == std::string("int1"))
370  {
371  int ospParam = this->GetInt(names);
372 
373  if (mdlMaterial->GetParameterType(paramName.c_str()) == VisRTX::ParameterType::BOOL)
374  {
375  mdlMaterial->SetParameterBool(paramName.c_str(), ospParam > 0);
376  }
377  else
378  {
379  mdlMaterial->SetParameterInt(paramName.c_str(), ospParam);
380  }
381  }
382  else if (paramType == std::string("float1"))
383  {
384  float ospParam = this->GetFloat(names);
385 
386  if (mdlMaterial->GetParameterType(paramName.c_str()) == VisRTX::ParameterType::BOOL)
387  {
388  mdlMaterial->SetParameterBool(paramName.c_str(), ospParam > 0.0f);
389  }
390  else
391  {
392  mdlMaterial->SetParameterFloat(paramName.c_str(), ospParam);
393  }
394  }
395  else if (paramType == std::string("float2"))
396  {
397  VisRTX::Vec2f ospParam = this->GetVec2f(names);
399  }
400  else if (paramType == std::string("int3"))
401  {
402  VisRTX::Vec3i ospParam = this->GetVec3i(names);
404  }
405  else if (paramType == std::string("float3"))
406  {
407  VisRTX::Vec3f ospParam = this->GetVec3f(names);
408  mdlMaterial->SetParameterColor(paramName.c_str(), ospParam);
409  }
410  else if (paramType == std::string("float4"))
411  {
412  VisRTX::Vec4f ospParam = this->GetVec4f(names);
414  }
415  else
416  {
418  }
419  }
420 
421  mdlMaterial->Compile();
422  }
423  }
424 
425  private:
427  VisRTX::Material* material = nullptr;
428  };
429  }
std::set< std::string > GetAllParameters() const
Definition: Object.h:274
int32_t GetInt(const std::vector< std::string > &ids, int32_t defaultValue=0, bool *found=nullptr) const
Definition: Object.h:116
void * GetData() const
Definition: Data.h:146
Material(const std::string &type)
Definition: Material.h:22
Definition: Data.h:9
VisRTX::Vec2f GetVec2f(const std::vector< std::string > &ids, const VisRTX::Vec2f &defaultValue=VisRTX::Vec2f(), bool *found=nullptr) const
Definition: Object.h:167
const std::string GetString(const std::vector< std::string > &ids, const std::string &defaultValue="", bool *found=nullptr) const
Definition: Object.h:61
void Commit() override
Definition: Material.h:81
VisRTX::Vec4f GetVec4f(const std::vector< std::string > &ids, const VisRTX::Vec4f &defaultValue=VisRTX::Vec4f(), bool *found=nullptr) const
Definition: Object.h:218
size_t GetNumElements() const
Definition: Data.h:116
#define vtkLogF(verbosity_name,...)
Add to log given the verbosity level.
Definition: vtkLogger.h:467
VisRTX::Vec3i GetVec3i(const std::vector< std::string > &ids, const VisRTX::Vec3i &defaultValue=VisRTX::Vec3i(), bool *found=nullptr) const
Definition: Object.h:184
VisRTX::Vec3f GetVec3f(const std::vector< std::string > &ids, const VisRTX::Vec3f &defaultValue=VisRTX::Vec3f(), bool *found=nullptr) const
Definition: Object.h:201
Definition: Backend.h:5
unsigned char OSPRay_mdl[]
Definition: OSPRayMDL.h:6
float GetFloat(const std::vector< std::string > &ids, float defaultValue=0.0f, bool *found=nullptr) const
Definition: Object.h:133
#define WARN_NOT_IMPLEMENTED()
RTWDataType GetElementDataType() const
Definition: Data.h:136