39#include <geometric_shapes/shapes.h>
40#include <geometric_shapes/shape_operations.h>
43#include <sensor_msgs/image_encodings.h>
47#ifdef HAVE_SSE_EXTENSIONS
56 : mesh_renderer_(640, 480, 0.3, 10)
57 , depth_filter_(640, 480, 0.3, 10)
58 , next_handle_(FirstLabel)
59 , transform_callback_(transform_callback)
60 , shadow_threshold_(0.5)
62 mesh_renderer_.setShadersFromString(padding_vertex_shader_,
"");
63 depth_filter_.setShadersFromString(filter_vertex_shader_, filter_fragment_shader_);
65 depth_filter_.begin();
67 glGenTextures(1, &sensor_depth_texture_);
69 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(),
"sensor"), 0);
70 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(),
"depth"), 2);
71 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(),
"label"), 4);
73 near_location_ = glGetUniformLocation(depth_filter_.getProgramID(),
"near");
74 far_location_ = glGetUniformLocation(depth_filter_.getProgramID(),
"far");
75 shadow_threshold_location_ = glGetUniformLocation(depth_filter_.getProgramID(),
"shadow_threshold");
79 canvas_ = glGenLists(1);
80 glNewList(canvas_, GL_COMPILE);
85 glVertex3f(-1, -1, 0);
100mesh_filter::MeshFilter::~MeshFilter()
105 for (map<unsigned int, GLMesh*>::iterator meshIt =
meshes_.begin(); meshIt !=
meshes_.end(); ++meshIt)
106 delete (meshIt->second);
112 mesh_renderer_.setBufferSize(width, height);
113 mesh_renderer_.setCameraParameters(width, width, width >> 1, height >> 1);
115 depth_filter_.setBufferSize(width, height);
116 depth_filter_.setCameraParameters(width, width, width >> 1, height >> 1);
120 const std::function<
bool(mesh_filter::MeshFilter::MeshHandle, Isometry3d&)>& transform_callback)
122 transform_callback_ = transform_callback;
125void mesh_filter::MeshFilter::setPaddingCoefficients(
const Eigen::Vector3f& padding_coefficients)
127 padding_coefficients_ = padding_coefficients;
132 Mesh collapsedMesh(1, 1);
133 mergeVertices(mesh, collapsedMesh);
134 meshes_[next_handle_] =
new GLMesh(collapsedMesh, next_handle_);
135 return next_handle_++;
140 long unsigned int erased = meshes_.erase(handle);
142 throw runtime_error(
"Could not remove mesh. Mesh not found!");
147 shadow_threshold_ = threshold;
152 mesh_renderer_.getColorBuffer((
unsigned char*)labels);
157inline unsigned alignment16(
const void* pointer)
159 return ((uintptr_t)pointer & 15);
161inline bool isAligned16(
const void* pointer)
163 return (((uintptr_t)pointer & 15) == 0);
169 mesh_renderer_.getDepthBuffer(depth);
170#if HAVE_SSE_EXTENSIONS
171 const __m128 mmNear = _mm_set1_ps(mesh_renderer_.getNearClippingDistance());
172 const __m128 mmFar = _mm_set1_ps(mesh_renderer_.getFarClippingDistance());
173 const __m128 mmNF = _mm_mul_ps(mmNear, mmFar);
174 const __m128 mmF_N = _mm_sub_ps(mmFar, mmNear);
175 static const __m128 mmOnes = _mm_set1_ps(1);
176 static const __m128 mmZeros = _mm_set1_ps(0);
178 float* depthEnd = depth + mesh_renderer_.getHeight() * mesh_renderer_.getWidth();
179 if (!isAligned16(depth))
182 unsigned first = 16 - alignment16(depth);
184 const float near = mesh_renderer_.getNearClippingDistance();
185 const float far = mesh_renderer_.getFarClippingDistance();
186 const float nf = near * far;
187 const float f_n = far - near;
189 while (depth < depthEnd && idx++ < first)
190 if (*depth != 0 && *depth != 1)
191 *depth = nf / (far - *depth * f_n);
196 unsigned last = (depth_filter_.getWidth() * depth_filter_.getHeight() - first) & 15;
197 float* depth2 = depthEnd - last;
198 while (depth2 < depthEnd)
199 if (*depth2 != 0 && *depth2 != 1)
200 *depth2 = nf / (far - *depth2 * f_n);
207 const __m128* mmEnd = (__m128*)depthEnd;
208 __m128* mmDepth = (__m128*)depth;
210 while (mmDepth < mmEnd)
212 __m128 mask = _mm_and_ps(_mm_cmpneq_ps(*mmDepth, mmOnes), _mm_cmpneq_ps(*mmDepth, mmZeros));
213 *mmDepth = _mm_mul_ps(*mmDepth, mmF_N);
214 *mmDepth = _mm_sub_ps(mmFar, *mmDepth);
215 *mmDepth = _mm_div_ps(mmNF, *mmDepth);
216 *mmDepth = _mm_and_ps(*mmDepth, mask);
222 const float near = mesh_renderer_.getNearClippingDistance();
223 const float far = mesh_renderer_.getFarClippingDistance();
224 const float nf = near * far;
225 const float f_n = far - near;
227 const float* depthEnd = depth + mesh_renderer_.getHeight() * mesh_renderer_.getWidth();
228 while (depth < depthEnd)
230 if (*depth != 0 && *depth != 1)
231 *depth = nf / (far - *depth * f_n);
242 depth_filter_.getDepthBuffer(depth);
243#if HAVE_SSE_EXTENSIONS
245 const __m128 mmNear = _mm_set1_ps(depth_filter_.getNearClippingDistance());
246 const __m128 mmFar = _mm_set1_ps(depth_filter_.getFarClippingDistance());
247 const __m128 mmScale = _mm_sub_ps(mmFar, mmNear);
248 float* depthEnd = depth + depth_filter_.getWidth() * depth_filter_.getHeight();
250 if (!isAligned16(depth))
253 unsigned first = 16 - alignment16(depth);
255 const float scale = depth_filter_.getFarClippingDistance() - depth_filter_.getNearClippingDistance();
256 const float offset = depth_filter_.getNearClippingDistance();
257 while (depth < depthEnd && idx++ < first)
258 if (*depth != 0 && *depth != 1.0)
259 *depth = *depth * scale + offset;
264 unsigned last = (depth_filter_.getWidth() * depth_filter_.getHeight() - first) & 15;
265 float* depth2 = depthEnd - last;
266 while (depth2 < depthEnd)
267 if (*depth2 != 0 && *depth != 1.0)
268 *depth2 = *depth2 * scale + offset;
275 const __m128* mmEnd = (__m128*)depthEnd;
276 __m128* mmDepth = (__m128*)depth;
278 while (mmDepth < mmEnd)
280 *mmDepth = _mm_mul_ps(*mmDepth, mmScale);
281 *mmDepth = _mm_add_ps(*mmDepth, mmNear);
282 *mmDepth = _mm_and_ps(*mmDepth, _mm_and_ps(_mm_cmpneq_ps(*mmDepth, mmNear), _mm_cmpneq_ps(*mmDepth, mmFar)));
286 const float* depthEnd = depth + depth_filter_.getWidth() * depth_filter_.getHeight();
287 const float scale = depth_filter_.getFarClippingDistance() - depth_filter_.getNearClippingDistance();
288 const float offset = depth_filter_.getNearClippingDistance();
289 while (depth < depthEnd)
293 if (*depth != 0 && *depth != 1.0)
294 *depth = *depth * scale + offset;
305 depth_filter_.getColorBuffer((
unsigned char*)labels);
309 float cx,
float cy)
const
311 mesh_renderer_.setBufferSize(width, height);
312 mesh_renderer_.setCameraParameters(fx, fy, cx, cy);
313 mesh_renderer_.begin();
314 glEnable(GL_DEPTH_TEST);
315 glEnable(GL_CULL_FACE);
316 glCullFace(GL_FRONT);
317 glDisable(GL_ALPHA_TEST);
319 GLuint padding_coefficients_id = glGetUniformLocation(mesh_renderer_.getProgramID(),
"padding_coefficients");
320 glUniform3f(padding_coefficients_id, padding_coefficients_[0], padding_coefficients_[1], padding_coefficients_[2]);
322 Isometry3d transform;
323 for (map<unsigned int, GLMesh*>::const_iterator meshIt = meshes_.begin(); meshIt != meshes_.end(); ++meshIt)
324 if (transform_callback_(meshIt->first, transform))
325 meshIt->second->render(transform);
327 mesh_renderer_.end();
330 depth_filter_.setBufferSize(width, height);
331 depth_filter_.setCameraParameters(fx, fy, cx, cy);
332 depth_filter_.begin();
333 glEnable(GL_DEPTH_TEST);
334 glEnable(GL_CULL_FACE);
336 glDisable(GL_ALPHA_TEST);
338 glUniform1f(near_location_, depth_filter_.getNearClippingDistance());
339 glUniform1f(far_location_, depth_filter_.getFarClippingDistance());
340 glUniform1f(shadow_threshold_location_, shadow_threshold_);
342 GLuint depth_texture = mesh_renderer_.getDepthTexture();
343 GLuint color_texture = mesh_renderer_.getColorTexture();
346 glActiveTexture(GL_TEXTURE0);
347 glBindTexture(GL_TEXTURE_2D, sensor_depth_texture_);
349 float scale = 1.0 / (depth_filter_.getFarClippingDistance() - depth_filter_.getNearClippingDistance());
350 glPixelTransferf(GL_DEPTH_SCALE, scale);
351 glPixelTransferf(GL_DEPTH_BIAS, -scale * depth_filter_.getNearClippingDistance());
352 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, sensor_data);
353 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
354 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
359 glActiveTexture(GL_TEXTURE2);
360 glBindTexture(GL_TEXTURE_2D, depth_texture);
363 glActiveTexture(GL_TEXTURE4);
364 glBindTexture(GL_TEXTURE_2D, color_texture);
367 glDisable(GL_TEXTURE_2D);
371void mesh_filter::MeshFilter::setClippingRange(
float near,
float far)
373 mesh_renderer_.setClippingRange(near, far);
374 depth_filter_.setClippingRange(near, far);
377void mesh_filter::MeshFilter::mergeVertices(
const Mesh& mesh, Mesh& compressed)
381 static const double thresholdSQR = pow(0.00001, 2);
383 vector<unsigned> vertex_map(mesh.vertex_count);
384 vector<Vector3d> vertices(mesh.vertex_count);
385 vector<Vector3d> compressed_vertices;
386 vector<Vector3i> triangles(mesh.triangle_count);
388 for (
unsigned vIdx = 0; vIdx < mesh.vertex_count; ++vIdx)
390 vertices[vIdx][0] = mesh.vertices[3 * vIdx];
391 vertices[vIdx][1] = mesh.vertices[3 * vIdx + 1];
392 vertices[vIdx][2] = mesh.vertices[3 * vIdx + 2];
393 vertex_map[vIdx] = vIdx;
396 for (
unsigned tIdx = 0; tIdx < mesh.triangle_count; ++tIdx)
398 triangles[tIdx][0] = mesh.triangles[3 * tIdx];
399 triangles[tIdx][1] = mesh.triangles[3 * tIdx + 1];
400 triangles[tIdx][2] = mesh.triangles[3 * tIdx + 2];
403 for (
unsigned vIdx1 = 0; vIdx1 < mesh.vertex_count; ++vIdx1)
405 if (vertex_map[vIdx1] != vIdx1)
408 vertex_map[vIdx1] = compressed_vertices.size();
409 compressed_vertices.push_back(vertices[vIdx1]);
411 for (
unsigned vIdx2 = vIdx1 + 1; vIdx2 < mesh.vertex_count; ++vIdx2)
413 double distanceSQR = (vertices[vIdx1] - vertices[vIdx2]).squaredNorm();
414 if (distanceSQR <= thresholdSQR)
415 vertex_map[vIdx2] = vertex_map[vIdx1];
420 for (
unsigned tIdx = 0; tIdx < mesh.triangle_count; ++tIdx)
422 triangles[tIdx][0] = vertex_map[triangles[tIdx][0]];
423 triangles[tIdx][1] = vertex_map[triangles[tIdx][1]];
424 triangles[tIdx][2] = vertex_map[triangles[tIdx][2]];
427 for (
int vIdx = 0; vIdx < vertices.size(); ++vIdx)
429 if (vertices[vIdx][0] == vertices[vIdx][1] || vertices[vIdx][0] == vertices[vIdx][2] ||
430 vertices[vIdx][1] == vertices[vIdx][2])
432 vertices[vIdx] = vertices.back();
439 if (compressed.vertex_count > 0 && compressed.vertices)
440 delete[] compressed.vertices;
441 if (compressed.triangle_count > 0 && compressed.triangles)
442 delete[] compressed.triangles;
443 if (compressed.triangle_count > 0 && compressed.normals)
444 delete[] compressed.normals;
446 compressed.vertex_count = compressed_vertices.size();
447 compressed.vertices =
new double[compressed.vertex_count * 3];
448 for (
unsigned vIdx = 0; vIdx < compressed.vertex_count; ++vIdx)
450 compressed.vertices[3 * vIdx + 0] = compressed_vertices[vIdx][0];
451 compressed.vertices[3 * vIdx + 1] = compressed_vertices[vIdx][1];
452 compressed.vertices[3 * vIdx + 2] = compressed_vertices[vIdx][2];
455 compressed.triangle_count = triangles.size();
456 compressed.triangles =
new unsigned int[compressed.triangle_count * 3];
457 for (
unsigned tIdx = 0; tIdx < compressed.triangle_count; ++tIdx)
459 compressed.triangles[3 * tIdx + 0] = triangles[tIdx][0];
460 compressed.triangles[3 * tIdx + 1] = triangles[tIdx][1];
461 compressed.triangles[3 * tIdx + 2] = triangles[tIdx][2];
464 compressed.normals =
new double[compressed.triangle_count * 3];
465 for (
unsigned tIdx = 0; tIdx < compressed.triangle_count; ++tIdx)
467 Vector3d d1 = compressed_vertices[triangles[tIdx][1]] - compressed_vertices[triangles[tIdx][0]];
468 Vector3d d2 = compressed_vertices[triangles[tIdx][2]] - compressed_vertices[triangles[tIdx][0]];
472 normal_[0] = mesh.normals[3 * tIdx];
473 normal_[1] = mesh.normals[3 * tIdx + 1];
474 normal_[2] = mesh.normals[3 * tIdx + 2];
475 double cosAngle = normal.dot(normal_);
479 swap(compressed.triangles[3 * tIdx + 1], compressed.triangles[3 * tIdx + 2]);
483 compressed.normals[tIdx * 3 + 0] = normal[0];
484 compressed.normals[tIdx * 3 + 1] = normal[1];
485 compressed.normals[tIdx * 3 + 2] = normal[2];
489string mesh_filter::MeshFilter::padding_vertex_shader_ =
491 "uniform vec3 padding_coefficients;"
493 "{gl_FrontColor = gl_Color;"
494 "vec4 vertex = gl_ModelViewMatrix * gl_Vertex;"
495 "vec3 normal = normalize(gl_NormalMatrix * gl_Normal);"
496 "float lambda = padding_coefficients.x * vertex.z * vertex.z + padding_coefficients.y * vertex.z + "
497 "padding_coefficients.z;"
498 "gl_Position = gl_ProjectionMatrix * (vertex + lambda * vec4(normal,0) );"
499 "gl_Position.y = -gl_Position.y;}";
501string mesh_filter::MeshFilter::filter_vertex_shader_ =
"#version 120\n"
504 " gl_FrontColor = gl_Color;"
505 " gl_TexCoord[0] = gl_MultiTexCoord0;"
506 " gl_Position = gl_Vertex;"
507 " gl_Position.w = 1.0;"
510string mesh_filter::MeshFilter::filter_fragment_shader_ =
512 "uniform sampler2D sensor;"
513 "uniform sampler2D depth;"
514 "uniform sampler2D label;"
515 "uniform float near;"
517 "uniform float shadow_threshold;"
518 "float f_n = far - near;"
519 "float threshold = shadow_threshold / f_n;"
522 " float dValue = float(texture2D(depth, gl_TexCoord[0].st));"
523 " float zValue = dValue * near / (far - dValue * f_n);"
524 " float diff = float(texture2D(sensor, gl_TexCoord[0].st)) - zValue;"
526 " gl_FragColor = vec4 (0, 0, 0, 0);"
527 " gl_FragDepth = float(texture2D(sensor, gl_TexCoord[0].st));"
528 " } else if (diff > threshold) {"
529 " gl_FragColor = vec4 (0.003921569, 0, 0, 0);"
530 " gl_FragDepth = float(texture2D(sensor, gl_TexCoord[0].st));"
532 " gl_FragColor = vec4 (1,1,1,1);"
void setTransformCallback(const TransformCallback &transform_callback)
set the callback for retrieving transformations for each mesh.
void getModelLabels(LabelType *labels) const
retrieves the labels of the rendered model
std::map< MeshHandle, GLMeshPtr > meshes_
storage for meshed to be filtered
void filter(const void *sensor_data, GLushort type, bool wait=false) const
label/remove pixels from input depth-image
GLuint sensor_depth_texture_
handle depth texture from sensor data
void removeMesh(MeshHandle mesh_handle)
removes a mesh given by its handle
void setShadowThreshold(float threshold)
set the shadow threshold. points that are further away than the rendered model are filtered out....
MeshHandle addMesh(const shapes::Mesh &mesh)
adds a mesh to the filter object.
void getModelDepth(float *depth) const
retrieves the depth values of the rendered model
void getFilteredLabels(LabelType *labels) const
retrieves the labels of the input data
void getFilteredDepth(float *depth) const
retrieves the filtered depth values
void setSize(unsigned int width, unsigned int height)
sets the size of the frame buffers
GLuint canvas_
canvas element (screen-filling quad) for second pass
MeshFilter(const TransformCallback &transform_callback=TransformCallback(), const typename SensorType::Parameters &sensor_parameters=typename SensorType::Parameters())
Constructor.
Vec3fX< details::Vec3Data< double > > Vector3d