seperate intensity and color vertices?
I am developing a point painting extension module for GLIM which adds RGB colors to GLIM maps. To display the result, I could use the vert_color shader attribute, but unfortunately that attribute is already used to show map intensity. Thus, it is necessary to overwrite the vertex data whenever I want to change color from intensity-based to point color.
Currently, GLIM maps intensity to RGB colors using fixed table, and use that data for vert_color input. Maybe it could make sense to have the following approach instead:
- use
in vec4 vert_colorfor raw RGB colors - use
in u8 vert_colormap_indexanduniform vec3 colormap[256]for intensity base coloring
To render intensity, the host would only convert the value to a u8 index and pass the colormap as uniform parameter. The advantage of this appraoch is that colormaps could be changed on the fly without the need to re-upload the points data.
Example PoC, where a vert_intensity is used in a new "colormap" mode. In order not to break existing code, I have kept the original add_intensity functions (which still write into the vert_color buffer), and simply added new add_intensity methods which don't take a colormap and use the new vert_intensity buffer:
diff --git a/data/shader/rainbow.vert b/data/shader/rainbow.vert
index f1bf380..9804c2c 100644
--- a/data/shader/rainbow.vert
+++ b/data/shader/rainbow.vert
@@ -20,6 +20,7 @@ uniform mat4 projection_matrix;
// colormode = 1 : material_color
// colormode = 2 : vert_color
// colormode = 3 : texture_color
+// colormode = 4 : colormap
uniform int color_mode;
uniform vec4 material_color;
uniform sampler2D colormap_sampler;
@@ -32,6 +33,7 @@ in vec3 vert_position;
in vec4 vert_color;
in vec2 vert_texcoord;
in vec3 vert_normal;
+in float vert_intensity; // in range [0, 1]
out vec4 frag_color;
out vec2 frag_texcoord;
@@ -42,6 +44,10 @@ vec4 rainbow(vec3 position) {
return texture(colormap_sampler, vec2(p, 0.0));
}
+vec4 colormap(float intensity) {
+ return texture(colormap_sampler, vec2(intensity, 0.0));
+}
+
void main() {
vec4 world_position = model_matrix * vec4(vert_position, 1.0);
vec3 frag_world_position = world_position.xyz;
@@ -64,6 +70,10 @@ void main() {
case 3:
frag_texcoord = vert_texcoord;
break;
+
+ case 4:
+ frag_color = colormap(vert_intensity);
+ break;
}
if(normal_enabled) {
diff --git a/include/glk/pointcloud_buffer.hpp b/include/glk/pointcloud_buffer.hpp
index 92f1818..9145ddf 100644
--- a/include/glk/pointcloud_buffer.hpp
+++ b/include/glk/pointcloud_buffer.hpp
@@ -59,10 +59,15 @@ public:
void add_intensity(glk::COLORMAP colormap, const std::vector<double>& intensities, float scale = 1.0f);
void add_intensity(glk::COLORMAP colormap, const float* intensities, const int num_points, float scale = 1.0f);
void add_intensity(glk::COLORMAP colormap, const double* intensities, const int num_points, float scale = 1.0f);
+ void add_intensity(const std::vector<float>& intensities, float scale = 1.0f);
+ void add_intensity(const std::vector<double>& intensities, float scale = 1.0f);
+ void add_intensity(const float* intensities, const int num_points, float scale = 1.0f);
+ void add_intensity(const double* intensities, const int num_points, float scale = 1.0f);
void add_normals(const float* data, int stride, int num_points);
void add_color(const float* data, int stride, int num_points);
void add_intensity(glk::COLORMAP colormap, const float* data, int stride, int num_points, float scale = 1.0f);
+ void add_intensity_buffer(const float* data, int stride, int num_points);
void add_buffer(const std::string& attribute_name, int dim, const float* data, int stride, int num_points);
// Partial attribute update methods (User must ensure that stride and dim are matched with existing attribute)
diff --git a/include/guik/viewer/shader_setting.hpp b/include/guik/viewer/shader_setting.hpp
index b58ed00..885b07d 100644
--- a/include/guik/viewer/shader_setting.hpp
+++ b/include/guik/viewer/shader_setting.hpp
@@ -13,7 +13,7 @@
namespace guik {
struct ColorMode {
- enum MODE { RAINBOW = 0, FLAT_COLOR = 1, VERTEX_COLOR = 2, TEXTURE_COLOR = 3 };
+ enum MODE { RAINBOW = 0, FLAT_COLOR = 1, VERTEX_COLOR = 2, TEXTURE_COLOR = 3, COLORMAP = 4 };
};
struct PointScaleMode {
diff --git a/src/glk/pointcloud_buffer.cpp b/src/glk/pointcloud_buffer.cpp
index 3e6904d..c3bff2e 100644
--- a/src/glk/pointcloud_buffer.cpp
+++ b/src/glk/pointcloud_buffer.cpp
@@ -89,6 +89,41 @@ void PointCloudBuffer::add_intensity(glk::COLORMAP colormap, const double* inten
return add_intensity(colormap, intensities_, scale);
}
+
+void PointCloudBuffer::add_intensity(const std::vector<float>& intensities, float scale) {
+ std::vector<float> intensities_;
+ intensities_.reserve(intensities.size());
+ std::transform(intensities.begin(), intensities.end(), std::back_inserter(intensities_),
+ [&](const auto intensity) { return scale * intensity; });
+
+ add_intensity_buffer(intensities_.data(), sizeof(float), intensities_.size());
+}
+
+void PointCloudBuffer::add_intensity(const std::vector<double>& intensities, float scale) {
+ std::vector<float> intensities_;
+ intensities_.reserve(intensities.size());
+ std::transform(intensities.begin(), intensities.end(), std::back_inserter(intensities_),
+ [&](const auto intensity) { return scale * intensity; });
+
+ add_intensity_buffer(intensities_.data(), sizeof(float), intensities_.size());
+}
+
+void PointCloudBuffer::add_intensity(const float* intensities, const int num_points, float scale) {
+ std::vector<float> intensities_(num_points);
+ for (int i = 0; i < num_points; ++i) {
+ intensities_[i] = scale * intensities[i];
+ }
+ add_intensity_buffer(intensities_.data(), sizeof(float), intensities_.size());
+}
+
+void PointCloudBuffer::add_intensity(const double* intensities, const int num_points, float scale) {
+ std::vector<float> intensities_(num_points);
+ for (int i = 0; i < num_points; ++i) {
+ intensities_[i] = scale * intensities[i];
+ }
+ add_intensity_buffer(intensities_.data(), sizeof(float), intensities_.size());
+}
+
void PointCloudBuffer::add_color(const Eigen::Vector4f* colors, int num_points) {
add_color(colors->data(), sizeof(float) * 4, num_points);
}
@@ -116,6 +151,10 @@ void PointCloudBuffer::add_intensity(glk::COLORMAP colormap, const float* data,
add_color(colors[0].data(), sizeof(Eigen::Vector4f), num_points);
}
+void PointCloudBuffer::add_intensity_buffer(const float* data, int stride, int num_points) {
+ add_buffer("vert_intensity", 1, data, stride, num_points);
+}
+
void PointCloudBuffer::add_buffer(const std::string& attribute_name, int dim, const float* data, int stride, int num_points) {
assert(this->num_points == num_points);
Example integration:
diff --git a/src/glim/viewer/interactive_viewer.cpp b/src/glim/viewer/interactive_viewer.cpp
index ad3b3d7..50e35e3 100644
--- a/src/glim/viewer/interactive_viewer.cpp
+++ b/src/glim/viewer/interactive_viewer.cpp
@@ -464,21 +465,27 @@ void InteractiveViewer::update_viewer(bool force_render) {
auto_z_range[1] = std::max(auto_z_range[1], submap_pose.translation().z());
auto drawable = viewer->find_drawable("submap_" + std::to_string(submap->id));
- if (drawable.first) {
- drawable.first->add("model_matrix", submap_pose.matrix());
+ auto update_shader_settings = [&](auto& shader_setting) {
+ shader_setting.add("model_matrix", submap_pose.matrix());
switch (color_mode) {
case 0:
- drawable.first->set_color_mode(guik::ColorMode::RAINBOW);
+ shader_setting.set_color_mode(guik::ColorMode::RAINBOW);
break;
- case 1:
- case 3:
- drawable.first->set_color_mode(guik::ColorMode::VERTEX_COLOR);
+ case 1: // intensity
+ shader_setting.set_color_mode(guik::ColorMode::COLORMAP);
break;
case 2:
- drawable.first->set_color_mode(guik::ColorMode::FLAT_COLOR);
+ shader_setting.set_color_mode(guik::ColorMode::FLAT_COLOR);
+ break;
+ case 3: // color
+ shader_setting.set_color_mode(guik::ColorMode::VERTEX_COLOR);
break;
}
+ };
+
+ if (drawable.first && !force_render) {
+ update_shader_settings(*drawable.first);
} else {
const Eigen::Vector4f color = glk::colormap_categoricalf(glk::COLORMAP::TURBO, submap->session_id, 6);
@@ -487,7 +494,7 @@ void InteractiveViewer::update_viewer(bool force_render) {
if (submap->frame->has_intensities()) {
cloud_buffer
- ->add_intensity(glk::COLORMAP::TURBO, submap->frame->intensities, submap->frame->size(), 1.0 / *std::max_element(submap->frame->intensities, submap->frame->intensities));
+ ->add_intensity(submap->frame->intensities, submap->frame->size(), 1.0 / *std::max_element(submap->frame->intensities, submap->frame->intensities + submap->frame->size()));
}
if (submap->frame->has_colors()) {
@@ -501,6 +508,8 @@ void InteractiveViewer::update_viewer(bool force_render) {
shader_setting.add("dynamic_object", 0).make_transparent();
}
+ update_shader_settings(shader_setting);
+
viewer->update_drawable("submap_" + std::to_string(submap->id), cloud_buffer, shader_setting);
}
In intensity mode:
In color mode:
Sorry for the late response. I think it would be good to add the colormap mode to iridescence. Are you willing to open a PR?
No problem!
How would you suggest naming things? In my PoC implementation, I have added in float vert_intensity and a few PointCloudBuffer::add_intensity() methods, but the behavior of these new add_intensity methods is different from the already existing add_intensity methods:
- new ones don't take a colormap and write data to
vert_intensity - old ones take a colormap, convert intensity to color and write the color to
vert_color
Having the same name for 2 different things feels a bit odd.
I feel with this change the existing add_intensity would be better renamed to something like add_color_from_intensity, or the functionality should be simply moved to a color_to_intensity helper. Obviously, this would mean breaking existing code. I don't know your policy regarding breaking changes.
Or do you have a suggestion of a better name than vert_intensity and add_intensity for this new functionality?