ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
Gradient.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 <Image.h>
11 #include <Logging.h>
12 
14 
15 namespace cloudViewer {
16 namespace visualization {
17 namespace rendering {
18 
19 namespace {
20 static const int kNGradientPixels = 512;
21 static const int kNChannels = 4;
22 
23 void SetPixel(std::vector<uint8_t>& img,
24  int idx,
25  const Eigen::Vector4f& color) {
26  int i = kNChannels * idx;
27  img[i] = uint8_t(std::round(255.0f * color[0]));
28  img[i + 1] = uint8_t(std::round(255.0f * color[1]));
29  img[i + 2] = uint8_t(std::round(255.0f * color[2]));
30  img[i + 3] = uint8_t(std::round(255.0f * color[3]));
31 }
32 
33 } // namespace
34 
36 
37 Gradient::Gradient(const std::vector<Gradient::Point>& points) {
38  points_ = points;
39 }
40 
42 
43 const std::vector<Gradient::Point>& Gradient::GetPoints() const {
44  return points_;
45 }
46 
47 void Gradient::SetPoints(const std::vector<Gradient::Point>& points) {
48  points_ = points;
49  for (size_t i = 0; i < points_.size(); ++i) {
50  if (points_[i].value < 0.0f || points_[i].value > 1.0f) {
52  "Gradient point {} must be in range [0.0, 1.0], clamping",
53  points_[i].value);
54  points_[i].value = std::max(0.0f, std::min(1.0f, points_[i].value));
55  }
56  }
57  textures_.clear();
58 }
59 
60 Gradient::Mode Gradient::GetMode() const { return mode_; }
61 
62 void Gradient::SetMode(Mode mode) {
63  if (mode != mode_) {
64  mode_ = mode;
65  textures_.clear();
66  }
67 }
68 
70  if (textures_.find(&renderer) == textures_.end()) {
71  auto img = std::make_shared<geometry::Image>();
72  if (!points_.empty()) {
73  int n_points = int(points_.size());
74  if (mode_ == Mode::kGradient) {
75  img->Prepare(kNGradientPixels, 1, kNChannels, 1);
76  auto n = float(kNGradientPixels - 1);
77  int idx = 0;
78  for (int img_idx = 0; img_idx < kNGradientPixels; ++img_idx) {
79  auto x = float(img_idx) / n;
80  while (idx < n_points && x > points_[idx].value) {
81  idx += 1;
82  }
83 
84  if (idx == 0) {
85  SetPixel(img->data_, img_idx, points_[0].color);
86  } else if (idx == n_points) {
87  SetPixel(img->data_, img_idx,
88  points_[n_points - 1].color);
89  } else {
90  auto& p0 = points_[idx - 1];
91  auto& p1 = points_[idx];
92  auto dist = p1.value - p0.value;
93  // Calc weights between 0 and 1
94  auto w0 = 1.0f - (x - p0.value) / dist;
95  auto w1 = (x - p0.value) / dist;
96  auto r = w0 * p0.color[0] + w1 * p1.color[0];
97  auto g = w0 * p0.color[1] + w1 * p1.color[1];
98  auto b = w0 * p0.color[2] + w1 * p1.color[2];
99  auto a = w0 * p0.color[3] + w1 * p1.color[3];
100  SetPixel(img->data_, img_idx, {r, g, b, a});
101  }
102  }
103  } else {
104  img->Prepare(n_points, 1, kNChannels, 1);
105  for (int i = 0; i < n_points; ++i) {
106  SetPixel(img->data_, i, points_[i].color);
107  }
108  }
109  } else {
110  img->Prepare(1, 1, kNChannels, 1);
111  SetPixel(img->data_, 0, {1.0f, 0.0, 1.0f, 1.0f});
112  }
113 
114  textures_[&renderer] = renderer.AddTexture(img);
115  }
116  return textures_[&renderer];
117 }
118 
119 } // namespace rendering
120 } // namespace visualization
121 } // namespace cloudViewer
int points
math::float4 color
TextureHandle GetTextureHandle(Renderer &renderer)
Definition: Gradient.cpp:69
const std::vector< Gradient::Point > & GetPoints() const
Definition: Gradient.cpp:43
void SetPoints(const std::vector< Gradient::Point > &points)
Definition: Gradient.cpp:47
virtual TextureHandle AddTexture(const ResourceLoadRequest &request, bool srgb=false)=0
#define LogWarning(...)
Definition: Logging.h:72
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
static double dist(double x1, double y1, double x2, double y2)
Definition: lsd.c:207
Generic file read and write utility for python interface.