ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
MultiTextureRenderer.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <CVLog.h>
11 #include <CVTools.h>
12 #include <FileSystem.h>
13 #include <ecvMaterial.h>
14 #include <ecvMaterialSet.h>
15 
16 #include <cmath>
17 #include <map>
18 #include <set>
19 #include <sstream>
20 
23 
24 // VTK
25 #include <vtkActor.h>
26 #include <vtkBMPReader.h>
27 #include <vtkDataArray.h>
28 #include <vtkJPEGReader.h>
29 #include <vtkLODActor.h>
30 #include <vtkOpenGLRenderWindow.h>
31 #include <vtkPNGReader.h>
32 #include <vtkPNMReader.h>
33 #include <vtkPointData.h>
34 #include <vtkPolyData.h>
35 #include <vtkPolyDataMapper.h>
36 #include <vtkProperty.h>
37 #include <vtkQImageToImageSource.h>
38 #include <vtkRenderWindow.h>
39 #include <vtkRenderer.h>
40 #include <vtkTIFFReader.h>
41 #include <vtkTexture.h>
42 #include <vtkTextureUnitManager.h>
43 
44 #include <sstream>
45 
46 namespace PclUtils {
47 namespace renders {
48 
50 
51 bool MultiTextureRenderer::CanHandle(size_t material_count,
52  bool has_pbr_textures,
53  bool has_multiple_map_kd) const {
54  // Multi-texture renderer handles:
55  // 1. Multiple map_Kd textures (VTK PBR limitation) - highest priority
56  // 2. Traditional multi-texture scenarios (multiple materials)
57  // 3. Single material with traditional textures (not PBR)
58  // Note: If has_pbr_textures is true but has_multiple_map_kd is false,
59  // PBRRenderer should handle it instead
60  return has_multiple_map_kd || (material_count > 1 && !has_pbr_textures);
61 }
62 
65 }
66 
67 bool MultiTextureRenderer::Apply(vtkLODActor* actor,
68  const ccMaterialSet* materials,
69  vtkPolyData* polydata,
70  vtkRenderer* renderer) {
71  if (!ValidateActor(actor) || !ValidateMaterials(materials)) {
72  return false;
73  }
74 
76  "[MultiTextureRenderer::Apply] Applying multi-texture rendering "
77  "for %zu materials",
78  materials->size());
79 
80  // Get render window
81  vtkRenderWindow* render_window = nullptr;
82  if (renderer) {
83  render_window = renderer->GetRenderWindow();
84  }
85  if (!render_window) {
86  CVLog::Error("[MultiTextureRenderer::Apply] Cannot get render window");
87  return false;
88  }
89 
90  // Get texture unit manager
91  ::vtkTextureUnitManager* tex_manager = GetTextureUnitManager(render_window);
92  if (!tex_manager) {
94  "[MultiTextureRenderer::Apply] Cannot get texture unit "
95  "manager");
96  return false;
97  }
98 
99  // Check available texture units
100  int texture_units = tex_manager->GetNumberOfTextureUnits();
101  if (static_cast<size_t>(texture_units) < materials->size()) {
103  "[MultiTextureRenderer::Apply] GPU texture units %d < mesh "
104  "textures %zu!",
105  texture_units, materials->size());
106  }
107 
108  // Collect all map_Kd textures from all materials
109  // A material may have multiple map_Kd textures, so we need to collect them
110  // all
111  struct TextureInfo {
112  ccMaterial::CShared material;
113  QString texturePath;
114  size_t materialIndex;
115  size_t textureIndexInMaterial;
116  };
117  std::vector<TextureInfo> allMapKdTextures;
118 
119  using TexType = ccMaterial::TextureMapType;
120  for (size_t mat_idx = 0; mat_idx < materials->size(); ++mat_idx) {
121  auto material = materials->at(mat_idx);
122  if (!material) continue;
123 
124  // Get all DIFFUSE (map_Kd) textures for this material
125  std::vector<QString> diffuseTextures =
126  material->getTextureFilenames(TexType::DIFFUSE);
127 
128  for (size_t tex_idx = 0; tex_idx < diffuseTextures.size(); ++tex_idx) {
129  if (!diffuseTextures[tex_idx].isEmpty()) {
130  TextureInfo info;
131  info.material = material;
132  info.texturePath = diffuseTextures[tex_idx];
133  info.materialIndex = mat_idx;
134  info.textureIndexInMaterial = tex_idx;
135  allMapKdTextures.push_back(info);
136  }
137  }
138  }
139 
140  // Count map_Kd textures for intensity scaling
141  // IMPORTANT: All textures from all materials will be blended together,
142  // so we need a unified intensity scaling strategy to maintain balanced
143  // brightness and visual quality
144  int map_kd_count = static_cast<int>(allMapKdTextures.size());
145 
146  // Calculate per-material texture counts (for logging and per-material
147  // scaling)
148  std::map<size_t, int> materialTextureCounts;
149  for (const auto& texInfo : allMapKdTextures) {
150  materialTextureCounts[texInfo.materialIndex]++;
151  }
152 
153  // Global intensity scale: apply to ALL textures to maintain balanced
154  // brightness Use a more conservative scaling approach to prevent
155  // over-darkening Formula: 1.0 / sqrt(N) for better visual balance with
156  // MODULATE blending This provides better results than logarithmic scaling
157  // for MODULATE mode
158  float global_intensity_scale = 1.0f;
159  if (map_kd_count > 1) {
160  // Use square root scaling for MODULATE blending
161  // For 2 textures: ~0.71, for 4 textures: ~0.5, for 8 textures: ~0.35
162  // This prevents over-darkening while maintaining balanced brightness
163  global_intensity_scale = 1.0f / map_kd_count;
164  }
165 
166  if (map_kd_count > 1) {
167  CVLog::Print(
168  "[MultiTextureRenderer::Apply] Detected %d map_Kd textures "
169  "across %zu materials. Applying global intensity scale %.3f "
170  "to maintain balanced brightness. All textures will be "
171  "rendered "
172  "and blended together.",
173  map_kd_count, materials->size(), global_intensity_scale);
174  } else if (map_kd_count == 0) {
176  "[MultiTextureRenderer::Apply] No map_Kd textures found in "
177  "materials");
178  return false;
179  }
180 
181  // Clear existing textures
182  ClearTextures(actor);
183 
184  // Apply textures
185  size_t last_tex_id = std::min(allMapKdTextures.size(),
186  static_cast<size_t>(texture_units));
187  vtkPolyDataMapper* mapper =
188  vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
189 
190  // Track which materials have been applied to avoid duplicate material
191  // property application
192  std::set<size_t> appliedMaterials;
193 
194  for (size_t tex_id = 0; tex_id < last_tex_id; ++tex_id) {
195  const TextureInfo& texInfo = allMapKdTextures[tex_id];
196 
197  // Get texture unit
198 #if (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 2) || VTK_MAJOR_VERSION > 8
199  std::string tex_name =
200  CVTools::FromQString(texInfo.material->getName());
201  std::stringstream tu_ss;
202  tu_ss << tex_name << "_tex" << tex_id;
203  std::string tu_str = tu_ss.str();
204  const char* tu = tu_str.c_str();
205 #else
206  int tu = vtkProperty::VTK_TEXTURE_UNIT_0 + tex_id;
207 #endif
208 
209  // Load texture from the specific path
212  QImage qimage = ccMaterial::GetTexture(texInfo.texturePath);
213  if (qimage.isNull()) {
215  "[MultiTextureRenderer::Apply] Failed to load texture %s "
216  "for material %s, skipping!",
217  CVTools::FromQString(texInfo.texturePath).c_str(),
218  CVTools::FromQString(texInfo.material->getName()).c_str());
219  continue;
220  }
221 
222  // Check if texture has alpha channel (transparency support)
223  bool hasAlpha = qimage.hasAlphaChannel();
224  if (hasAlpha) {
225  // Convert to RGBA format to preserve alpha channel
226  if (qimage.format() != QImage::Format_RGBA8888 &&
227  qimage.format() != QImage::Format_ARGB32 &&
228  qimage.format() != QImage::Format_ARGB32_Premultiplied) {
229  qimage = qimage.convertToFormat(QImage::Format_RGBA8888);
230  }
232  "[MultiTextureRenderer::Apply] Texture %zu has alpha "
233  "channel, "
234  "enabling transparency support",
235  tex_id);
236  }
237 
238  vtkSmartPointer<vtkQImageToImageSource> qimageToImageSource =
240  qimageToImageSource->SetQImage(&qimage);
241  qimageToImageSource->Update();
242  texture->SetInputConnection(qimageToImageSource->GetOutputPort());
243 
244  // Enable alpha blending for textures with transparency
245  if (hasAlpha) {
246  texture->SetBlendingMode(
247  vtkTexture::VTK_TEXTURE_BLENDING_MODE_INTERPOLATE);
248  CVLog::Print(
249  "[MultiTextureRenderer::Apply] Texture %zu: Using "
250  "INTERPOLATE "
251  "blending mode for alpha transparency",
252  tex_id);
253  }
254 
255  // Set blending mode for unified multi-texture rendering
256  // Strategy: All textures from all materials will be blended together
257  // 1. First texture: REPLACE (base layer - establishes the foundation)
258  // 2. All subsequent textures: MODULATE (multiply blending - prevents
259  // over-brightness) MODULATE is better than ADD because:
260  // - ADD causes exponential brightness increase with multiple textures
261  // - MODULATE maintains color balance and prevents over-saturation
262  // - Works well with intensity scaling to achieve balanced results
263  // NOTE: If texture has alpha channel, blending mode is already set to
264  // INTERPOLATE above
265  if (!hasAlpha) {
266  if (tex_id == 0) {
267  texture->SetBlendingMode(
268  vtkTexture::VTK_TEXTURE_BLENDING_MODE_REPLACE);
270  "[MultiTextureRenderer::Apply] Texture %zu (material "
271  "%zu): "
272  "REPLACE mode (base layer)",
273  tex_id, texInfo.materialIndex);
274  } else {
275  texture->SetBlendingMode(
276  vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);
278  "[MultiTextureRenderer::Apply] Texture %zu (material "
279  "%zu): "
280  "MODULATE mode (blending layer)",
281  tex_id, texInfo.materialIndex);
282  }
283  }
284 
285  // Map texture coordinates to multi-texture attribute
286  // MapDataArrayToMultiTextureAttribute purpose:
287  // 1. Maps texture coordinate arrays in polydata (e.g., "TCoords0",
288  // "TCoords1") to the specified texture unit (tu)
289  // 2. Parameter description:
290  // - tu: Texture unit identifier, can be a string or integer
291  // - coords_name: Name of the texture coordinate array (e.g.,
292  // "TCoords0")
293  // - FIELD_ASSOCIATION_POINTS:
294  // Specifies that data is associated with points, not cells
295  // 3. This tells VTK which texture coordinate array to use for which
296  // texture unit during rendering
297  // 4. For multi-texture rendering, each texture needs its own texture
298  // coordinate array
299  // CRITICAL: Use global texture index (tex_id) instead of material index
300  // because ApplyTexturesFromMaterialSet creates separate TCoords arrays
301  // for each texture (TCoords0, TCoords1, ...) regardless of material
302  if (mapper && polydata) {
303  std::stringstream ss;
304  // Use global texture index (tex_id) to find corresponding TCoords
305  // array This matches the naming convention in
306  // ApplyTexturesFromMaterialSet
307  if (last_tex_id == 1) {
308  ss << "TCoords";
309  } else {
310  ss << "TCoords" << tex_id;
311  }
312  std::string coords_name = ss.str();
313 
314  // Check if the texture coordinates array exists
315  vtkDataArray* tcoords_array =
316  polydata->GetPointData()->GetArray(coords_name.c_str());
317  if (tcoords_array) {
318  mapper->MapDataArrayToMultiTextureAttribute(
319  tu, coords_name.c_str(),
320  vtkDataObject::FIELD_ASSOCIATION_POINTS);
322  "[MultiTextureRenderer::Apply] Mapped texture %zu to "
323  "texture coordinates array '%s'",
324  tex_id, coords_name.c_str());
325  } else {
327  "[MultiTextureRenderer::Apply] Texture coordinates "
328  "array "
329  "'%s' not found for texture %zu (material %zu, texture "
330  "index %zu), texture may not display correctly",
331  coords_name.c_str(), tex_id, texInfo.materialIndex,
332  texInfo.textureIndexInMaterial);
333  }
334  }
335 
336  // Set texture
337  actor->GetProperty()->SetTexture(tu, texture);
338 
339  // Apply material properties only once per material (not per texture)
340  // Use unified global intensity scaling to maintain balanced brightness
341  // across all materials and textures
342  if (appliedMaterials.find(texInfo.materialIndex) ==
343  appliedMaterials.end()) {
344  // Apply global intensity scale to all materials uniformly
345  // This ensures balanced brightness when textures from different
346  // materials are blended together
347  ApplyMaterial(texInfo.material, actor, global_intensity_scale);
348  appliedMaterials.insert(texInfo.materialIndex);
349  }
350  }
351 
352  // Set model transparency based on material opacity
353  // This allows the entire textured model to be transparent, regardless of
354  // whether textures themselves have alpha channels
355  // The opacity can be set externally via actor->GetProperty()->SetOpacity()
356  // and will be respected here
357  float modelOpacity = 1.0f;
358  bool hasMaterialOpacity = false;
359 
360  // Check material opacity values
361  for (size_t i = 0; i < materials->size(); ++i) {
362  auto mat = materials->at(i);
363  if (mat) {
364  const ecvColor::Rgbaf& diffuse = mat->getDiffuseFront();
365  const ecvColor::Rgbaf& ambient = mat->getAmbient();
366  float opacity = std::max(diffuse.a, ambient.a);
367  if (opacity < 1.0f) {
368  hasMaterialOpacity = true;
369  modelOpacity = std::min(modelOpacity, opacity);
370  }
371  }
372  }
373 
374  // Get current opacity from actor property (may have been set externally)
375  float currentOpacity = actor->GetProperty()->GetOpacity();
376 
377  // If material has opacity, use it; otherwise preserve external setting
378  // If external setting is less than 1.0, it means transparency was requested
379  if (hasMaterialOpacity) {
380  // Material defines opacity, use it
381  actor->GetProperty()->SetOpacity(modelOpacity);
382  CVLog::Print(
383  "[MultiTextureRenderer::Apply] Set model opacity from "
384  "material: "
385  "%.3f",
386  modelOpacity);
387  } else if (currentOpacity < 1.0f) {
388  // External opacity setting exists, preserve it
389  actor->GetProperty()->SetOpacity(currentOpacity);
390  CVLog::Print(
391  "[MultiTextureRenderer::Apply] Preserving external opacity "
392  "setting: %.3f",
393  currentOpacity);
394  } else {
395  // Default: fully opaque
396  actor->GetProperty()->SetOpacity(1.0f);
397  }
398 
399  // Enable transparency rendering support if opacity < 1.0
400  float finalOpacity = actor->GetProperty()->GetOpacity();
401  if (finalOpacity < 1.0f) {
402  // Configure renderer for transparency rendering
403  if (renderer) {
404  vtkRenderWindow* renderWindow = renderer->GetRenderWindow();
405  if (renderWindow) {
406  // Enable alpha bit planes for transparency rendering
407  renderWindow->SetAlphaBitPlanes(1);
408 
409  // Enable depth sorting for proper transparency rendering
410  // VTK will automatically sort transparent objects by depth
411  renderer->SetUseDepthPeeling(1);
412  renderer->SetMaximumNumberOfPeels(4); // Reasonable default
413  renderer->SetOcclusionRatio(0.0); // Full transparency support
414 
415  CVLog::Print(
416  "[MultiTextureRenderer::Apply] Enabled transparency "
417  "rendering support: opacity=%.3f, depth peeling "
418  "enabled",
419  finalOpacity);
420  }
421  }
422  }
423 
424  actor->Modified();
425  return true;
426 }
427 
428 bool MultiTextureRenderer::Update(vtkActor* actor,
429  const ccMaterialSet* materials,
430  vtkPolyData* polydata,
431  vtkRenderer* renderer) {
432  if (!ValidateActor(actor) || !ValidateMaterials(materials)) {
433  return false;
434  }
435 
436  vtkLODActor* lod_actor = vtkLODActor::SafeDownCast(actor);
437  if (!lod_actor) {
439  "[MultiTextureRenderer::Update] Actor is not a vtkLODActor");
440  return false;
441  }
442 
443  return Apply(lod_actor, materials, polydata, renderer);
444 }
445 
446 std::string MultiTextureRenderer::GetName() const {
447  return "MultiTextureRenderer";
448 }
449 
450 int MultiTextureRenderer::LoadTexture(ccMaterial::CShared material,
451  ::vtkTexture* vtk_tex) const {
452  if (!material || !vtk_tex) {
453  return -1;
454  }
455 
456  // For traditional multi-texture rendering, prioritize DIFFUSE texture
457  // If not available, try other texture types
458  using TexType = ccMaterial::TextureMapType;
459  QString tex_file = material->getTextureFilename(TexType::DIFFUSE);
460  if (tex_file.isEmpty()) {
461  // Fallback to legacy texture filename (for backward compatibility)
462  tex_file = material->getTextureFilename();
463  }
464  QImage qimage = ccMaterial::GetTexture(tex_file);
465  if (!qimage.isNull()) {
466  vtkSmartPointer<vtkQImageToImageSource> qimageToImageSource =
468  qimageToImageSource->SetQImage(&qimage);
469  qimageToImageSource->Update();
470  vtk_tex->SetInputConnection(qimageToImageSource->GetOutputPort());
471  return 1;
472  }
473 
474  if (tex_file.isEmpty()) {
475  return -1;
476  }
477 
478  std::string full_path = CVTools::FromQString(tex_file);
480  std::string parent_dir =
482  full_path);
483  std::string upper_filename = cloudViewer::utility::ToUpper(full_path);
484  std::string real_name;
485 
486  try {
488  parent_dir)) {
490  "[MultiTextureRenderer::LoadTexture] Parent directory "
491  "'%s' doesn't exist!",
492  parent_dir.c_str());
493  return -1;
494  }
495 
498  "[MultiTextureRenderer::LoadTexture] Parent '%s' is "
499  "not "
500  "a directory !",
501  parent_dir.c_str());
502  return -1;
503  }
504 
505  std::vector<std::string> paths_vector;
507  parent_dir, paths_vector);
508 
509  for (const auto& path : paths_vector) {
511  if (cloudViewer::utility::ToUpper(path) == upper_filename) {
512  real_name = path;
513  break;
514  }
515  }
516  }
517 
518  if (real_name.empty()) {
520  "[MultiTextureRenderer::LoadTexture] Can not find "
521  "texture file %s!",
522  full_path.c_str());
523  return -1;
524  }
525  } catch (const std::exception& ex) {
527  "[MultiTextureRenderer::LoadTexture] Error %s when "
528  "looking for file %s!",
529  ex.what(), full_path.c_str());
530  return -1;
531  }
532 
533  full_path = real_name;
534  }
535 
536  std::string extension =
538  full_path);
539 
540  if ((extension == "jpg") || (extension == "jpeg")) {
541  vtkSmartPointer<vtkJPEGReader> jpeg_reader =
543  jpeg_reader->SetFileName(full_path.c_str());
544  jpeg_reader->Update();
545  vtk_tex->SetInputConnection(jpeg_reader->GetOutputPort());
546  } else if (extension == "bmp") {
547  vtkSmartPointer<vtkBMPReader> bmp_reader =
549  bmp_reader->SetFileName(full_path.c_str());
550  bmp_reader->Update();
551  vtk_tex->SetInputConnection(bmp_reader->GetOutputPort());
552  } else if (extension == "pnm") {
553  vtkSmartPointer<vtkPNMReader> pnm_reader =
555  pnm_reader->SetFileName(full_path.c_str());
556  pnm_reader->Update();
557  vtk_tex->SetInputConnection(pnm_reader->GetOutputPort());
558  } else if (extension == "png") {
559  vtkSmartPointer<vtkPNGReader> png_reader =
561  png_reader->SetFileName(full_path.c_str());
562  png_reader->Update();
563  vtk_tex->SetInputConnection(png_reader->GetOutputPort());
564  } else if ((extension == "tiff") || (extension == "tif")) {
565  vtkSmartPointer<vtkTIFFReader> tiff_reader =
567  tiff_reader->SetFileName(full_path.c_str());
568  tiff_reader->Update();
569  vtk_tex->SetInputConnection(tiff_reader->GetOutputPort());
570  } else {
572  "[MultiTextureRenderer::LoadTexture] Unhandled image %s "
573  "(extension: '%s') for material %s!",
574  full_path.c_str(), extension.c_str(),
575  CVTools::FromQString(material->getName()).c_str());
576  return -1;
577  }
578 
579  return 1;
580 }
581 
583  vtkActor* actor,
584  float intensity_scale) const {
585  if (!actor || !material) return false;
586 
587  const ecvColor::Rgbaf& ambientColor = material->getAmbient();
588  const ecvColor::Rgbaf& diffuseColor = material->getDiffuseFront();
589  const ecvColor::Rgbaf& specularColor = material->getSpecular();
590  actor->GetProperty()->SetDiffuseColor(diffuseColor.r, diffuseColor.g,
591  diffuseColor.b);
592  actor->GetProperty()->SetSpecularColor(specularColor.r, specularColor.g,
593  specularColor.b);
594  actor->GetProperty()->SetAmbientColor(ambientColor.r, ambientColor.g,
595  ambientColor.b);
596  // Opacity: prefer from diffuse alpha, then ambient alpha
597  // Note: This sets the base opacity from material, but external opacity
598  // settings (via actor->GetProperty()->SetOpacity()) will override this
599  float materialOpacity = std::max(0.0f, std::min(1.0f, diffuseColor.a));
600  if (materialOpacity <= 0.0f) {
601  materialOpacity = std::max(0.0f, std::min(1.0f, ambientColor.a));
602  }
603 
604  // Only set opacity if it's different from current, or if current is 1.0
605  // This preserves external opacity settings
606  float currentOpacity = actor->GetProperty()->GetOpacity();
607  if (currentOpacity >= 1.0f || materialOpacity < currentOpacity) {
608  actor->GetProperty()->SetOpacity(materialOpacity);
609  }
610  actor->GetProperty()->SetInterpolationToPhong();
611 
612  // Apply illumination mode with proper intensity scaling
613  // MTL illumination modes:
614  // 0 = Color on and Ambient off (no lighting, use diffuse color)
615  // 1 = Color on and Ambient on (diffuse lighting only, no specular)
616  // 2 = Highlight on (Phong shading with specular)
617  switch (material->getIllum()) {
618  case 1: {
619  // Diffuse only: disable specular, enable diffuse and ambient
620  actor->GetProperty()->SetDiffuse(1.0f * intensity_scale);
621  actor->GetProperty()->SetSpecular(0.0f);
622  actor->GetProperty()->SetAmbient(1.0f * intensity_scale);
623  break;
624  }
625  case 2: {
626  // Phong with specular: enable all components
627  actor->GetProperty()->SetDiffuse(1.0f * intensity_scale);
628  actor->GetProperty()->SetSpecular(1.0f * intensity_scale);
629  actor->GetProperty()->SetAmbient(1.0f * intensity_scale);
630  // Use material's shininess for specular power
631  float shininess = std::max(
632  0.0f, std::min(128.0f, material->getShininessFront()));
633  actor->GetProperty()->SetSpecularPower(shininess > 0.0f ? shininess
634  : 4.0f);
635  break;
636  }
637  default:
638  case 0: {
639  // No lighting: disable lighting, use diffuse color directly
640  actor->GetProperty()->SetLighting(false);
641  actor->GetProperty()->SetDiffuse(0.0f);
642  actor->GetProperty()->SetSpecular(0.0f);
643  actor->GetProperty()->SetAmbient(1.0f * intensity_scale);
644  actor->GetProperty()->SetColor(diffuseColor.r, diffuseColor.g,
645  diffuseColor.b);
646  break;
647  }
648  }
649 
650  return true;
651 }
652 
653 ::vtkTextureUnitManager* MultiTextureRenderer::GetTextureUnitManager(
654  ::vtkRenderWindow* render_window) const {
655  if (!render_window) {
656  return nullptr;
657  }
658 
659  vtkOpenGLRenderWindow* gl_window =
660  vtkOpenGLRenderWindow::SafeDownCast(render_window);
661  if (!gl_window) {
662  return nullptr;
663  }
664 
665  return gl_window->GetTextureUnitManager();
666 }
667 
668 } // namespace renders
669 } // namespace PclUtils
static bool PrintDebug(const char *format,...)
Same as Print, but works only in Debug mode.
Definition: CVLog.cpp:153
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
static std::string FromQString(const QString &qs)
Definition: CVTools.cpp:100
RenderingMode GetMode() const override
Get the rendering mode this renderer implements.
bool Update(vtkActor *actor, const class ccMaterialSet *materials, vtkPolyData *polydata, vtkRenderer *renderer) override
Update existing actor with new materials.
bool Apply(vtkLODActor *actor, const class ccMaterialSet *materials, vtkPolyData *polydata, vtkRenderer *renderer) override
Apply rendering to actor.
std::string GetName() const override
Get renderer name for logging.
bool CanHandle(size_t material_count, bool has_pbr_textures, bool has_multiple_map_kd) const override
Check if this renderer can handle the given material.
bool ApplyMaterial(ccMaterial::CShared material, vtkActor *actor, float intensity_scale=1.0f) const
Apply material properties to actor.
void ClearTextures(vtkActor *actor)
Helper: Clear all textures from actor.
bool ValidateActor(vtkActor *actor) const
Helper: Validate actor.
bool ValidateMaterials(const class ccMaterialSet *materials) const
Helper: Validate materials.
Mesh (triangle) material.
TextureMapType
Texture map types for PBR materials.
Definition: ecvMaterial.h:176
QSharedPointer< const ccMaterial > CShared
Const + Shared type.
Definition: ecvMaterial.h:31
static QImage GetTexture(const QString &absoluteFilename)
Returns the texture image associated to a given name.
RGBA color structure.
RenderingMode
Rendering mode enumeration.
static const std::string path
Definition: PointCloud.cpp:59
bool ListFilesInDirectory(const std::string &directory, std::vector< std::string > &filenames)
Definition: FileSystem.cpp:561
bool IsDirectory(const std::string &directory)
Definition: FileSystem.cpp:454
std::string GetFileParentDirectory(const std::string &filename)
Definition: FileSystem.cpp:314
bool DirectoryExists(const std::string &directory)
Definition: FileSystem.cpp:473
std::string GetFileExtensionInLowerCase(const std::string &filename)
Definition: FileSystem.cpp:281
bool FileExists(const std::string &filename)
Definition: FileSystem.cpp:524
bool IsFile(const std::string &filename)
Definition: FileSystem.cpp:435
std::string ToUpper(const std::string &s)
Convert string to the upper case.
Definition: Helper.cpp:249