moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
mesh_filter.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2013, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Suat Gedikli */
36
39#include <geometric_shapes/shapes.h>
40#include <geometric_shapes/shape_operations.h>
41#include <Eigen/Eigen>
42#include <stdexcept>
43#include <sensor_msgs/image_encodings.h>
44#include <stdint.h>
45
46// include SSE headers
47#ifdef HAVE_SSE_EXTENSIONS
48#include <xmmintrin.h>
49#endif
50
51using namespace std;
52using namespace Eigen;
53using shapes::Mesh;
54
55mesh_filter::MeshFilter::MeshFilter(const std::function<bool(MeshFilter::MeshHandle, Isometry3d&)>& transform_callback)
56 : mesh_renderer_(640, 480, 0.3, 10) // some default values for buffer sizes and clipping planes
57 , depth_filter_(640, 480, 0.3, 10)
58 , next_handle_(FirstLabel) // 0 and 1 are reserved!
59 , transform_callback_(transform_callback)
60 , shadow_threshold_(0.5)
61{
62 mesh_renderer_.setShadersFromString(padding_vertex_shader_, "");
63 depth_filter_.setShadersFromString(filter_vertex_shader_, filter_fragment_shader_);
64
65 depth_filter_.begin();
66
67 glGenTextures(1, &sensor_depth_texture_);
68
69 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(), "sensor"), 0);
70 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(), "depth"), 2);
71 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(), "label"), 4);
72
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");
76
77 depth_filter_.end();
78
79 canvas_ = glGenLists(1);
80 glNewList(canvas_, GL_COMPILE);
81 glBegin(GL_QUADS);
82
83 glColor3f(1, 1, 1);
84 glTexCoord2f(0, 0);
85 glVertex3f(-1, -1, 0);
86
87 glTexCoord2f(1, 0);
88 glVertex3f(1, -1, 0);
89
90 glTexCoord2f(1, 1);
91 glVertex3f(1, 1, 0);
92
93 glTexCoord2f(0, 1);
94 glVertex3f(-1, 1, 0);
95
96 glEnd();
97 glEndList();
98}
99
100mesh_filter::MeshFilter::~MeshFilter()
101{
102 glDeleteLists(1, canvas_);
103 glDeleteTextures(1, &sensor_depth_texture_);
104
105 for (map<unsigned int, GLMesh*>::iterator meshIt = meshes_.begin(); meshIt != meshes_.end(); ++meshIt)
106 delete (meshIt->second);
107 meshes_.clear();
108}
109
110void mesh_filter::MeshFilter::setSize(unsigned width, unsigned height)
111{
112 mesh_renderer_.setBufferSize(width, height);
113 mesh_renderer_.setCameraParameters(width, width, width >> 1, height >> 1);
114
115 depth_filter_.setBufferSize(width, height);
116 depth_filter_.setCameraParameters(width, width, width >> 1, height >> 1);
117}
118
120 const std::function<bool(mesh_filter::MeshFilter::MeshHandle, Isometry3d&)>& transform_callback)
121{
122 transform_callback_ = transform_callback;
123}
124
125void mesh_filter::MeshFilter::setPaddingCoefficients(const Eigen::Vector3f& padding_coefficients)
126{
127 padding_coefficients_ = padding_coefficients;
128}
129
130mesh_filter::MeshFilter::MeshHandle mesh_filter::MeshFilter::addMesh(const Mesh& mesh)
131{
132 Mesh collapsedMesh(1, 1);
133 mergeVertices(mesh, collapsedMesh);
134 meshes_[next_handle_] = new GLMesh(collapsedMesh, next_handle_);
135 return next_handle_++;
136}
137
138void mesh_filter::MeshFilter::removeMesh(MeshFilter::MeshHandle handle)
139{
140 long unsigned int erased = meshes_.erase(handle);
141 if (erased == 0)
142 throw runtime_error("Could not remove mesh. Mesh not found!");
143}
144
146{
147 shadow_threshold_ = threshold;
148}
149
150void mesh_filter::MeshFilter::getModelLabels(unsigned* labels) const
151{
152 mesh_renderer_.getColorBuffer((unsigned char*)labels);
153}
154
155namespace
156{
157inline unsigned alignment16(const void* pointer)
158{
159 return ((uintptr_t)pointer & 15);
160}
161inline bool isAligned16(const void* pointer)
162{
163 return (((uintptr_t)pointer & 15) == 0);
164}
165} // namespace
166
167void mesh_filter::MeshFilter::getModelDepth(float* depth) const
168{
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);
177
178 float* depthEnd = depth + mesh_renderer_.getHeight() * mesh_renderer_.getWidth();
179 if (!isAligned16(depth))
180 {
181 // first depth value without SSE until we reach aligned data
182 unsigned first = 16 - alignment16(depth);
183 unsigned idx;
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;
188
189 while (depth < depthEnd && idx++ < first)
190 if (*depth != 0 && *depth != 1)
191 *depth = nf / (far - *depth * f_n);
192 else
193 *depth = 0;
194
195 // rest of unaligned data at the end
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);
201 else
202 *depth2 = 0;
203
204 depthEnd -= last;
205 }
206
207 const __m128* mmEnd = (__m128*)depthEnd;
208 __m128* mmDepth = (__m128*)depth;
209 // rest is aligned
210 while (mmDepth < mmEnd)
211 {
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);
217 ++mmDepth;
218 }
219
220#else
221 // calculate metric depth values from OpenGL normalized depth buffer
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;
226
227 const float* depthEnd = depth + mesh_renderer_.getHeight() * mesh_renderer_.getWidth();
228 while (depth < depthEnd)
229 {
230 if (*depth != 0 && *depth != 1)
231 *depth = nf / (far - *depth * f_n);
232 else
233 *depth = 0;
234
235 ++depth;
236 }
237#endif
238}
239
240void mesh_filter::MeshFilter::getFilteredDepth(float* depth) const
241{
242 depth_filter_.getDepthBuffer(depth);
243#if HAVE_SSE_EXTENSIONS
244 //* SSE version
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();
249
250 if (!isAligned16(depth))
251 {
252 // first depth value without SSE until we reach aligned data
253 unsigned first = 16 - alignment16(depth);
254 unsigned idx;
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;
260 else
261 *depth = 0;
262
263 // rest of unaligned data at the end
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;
269 else
270 *depth2 = 0;
271
272 depthEnd -= last;
273 }
274
275 const __m128* mmEnd = (__m128*)depthEnd;
276 __m128* mmDepth = (__m128*)depth;
277 // rest is aligned
278 while (mmDepth < mmEnd)
279 {
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)));
283 ++mmDepth;
284 }
285#else
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)
290 {
291 // 0 = on near clipping plane -> we used 0 to mark invalid points -> not visible
292 // points on far clipping plane needs to be removed too
293 if (*depth != 0 && *depth != 1.0)
294 *depth = *depth * scale + offset;
295 else
296 *depth = 0;
297
298 ++depth;
299 }
300#endif
301}
302
303void mesh_filter::MeshFilter::getFilteredLabels(unsigned* labels) const
304{
305 depth_filter_.getColorBuffer((unsigned char*)labels);
306}
307
308void mesh_filter::MeshFilter::filter(const float* sensor_data, unsigned width, unsigned height, float fx, float fy,
309 float cx, float cy) const
310{
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);
318
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]);
321
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);
326
327 mesh_renderer_.end();
328
329 // now filter the depth_map with the second rendering stage
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);
335 glCullFace(GL_BACK);
336 glDisable(GL_ALPHA_TEST);
337
338 glUniform1f(near_location_, depth_filter_.getNearClippingDistance());
339 glUniform1f(far_location_, depth_filter_.getFarClippingDistance());
340 glUniform1f(shadow_threshold_location_, shadow_threshold_);
341
342 GLuint depth_texture = mesh_renderer_.getDepthTexture();
343 GLuint color_texture = mesh_renderer_.getColorTexture();
344
345 // bind sensor depth
346 glActiveTexture(GL_TEXTURE0);
347 glBindTexture(GL_TEXTURE_2D, sensor_depth_texture_);
348
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);
357
358 // bind depth map
359 glActiveTexture(GL_TEXTURE2);
360 glBindTexture(GL_TEXTURE_2D, depth_texture);
361
362 // bind labels
363 glActiveTexture(GL_TEXTURE4);
364 glBindTexture(GL_TEXTURE_2D, color_texture);
365
366 glCallList(canvas_);
367 glDisable(GL_TEXTURE_2D);
368 depth_filter_.end();
369}
370
371void mesh_filter::MeshFilter::setClippingRange(float near, float far)
372{
373 mesh_renderer_.setClippingRange(near, far);
374 depth_filter_.setClippingRange(near, far);
375}
376
377void mesh_filter::MeshFilter::mergeVertices(const Mesh& mesh, Mesh& compressed)
378{
379 // max allowed distance of vertices to be considered same! 1mm
380 // to allow double-error from transformed vertices.
381 static const double thresholdSQR = pow(0.00001, 2);
382
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);
387
388 for (unsigned vIdx = 0; vIdx < mesh.vertex_count; ++vIdx)
389 {
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;
394 }
395
396 for (unsigned tIdx = 0; tIdx < mesh.triangle_count; ++tIdx)
397 {
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];
401 }
402
403 for (unsigned vIdx1 = 0; vIdx1 < mesh.vertex_count; ++vIdx1)
404 {
405 if (vertex_map[vIdx1] != vIdx1)
406 continue;
407
408 vertex_map[vIdx1] = compressed_vertices.size();
409 compressed_vertices.push_back(vertices[vIdx1]);
410
411 for (unsigned vIdx2 = vIdx1 + 1; vIdx2 < mesh.vertex_count; ++vIdx2)
412 {
413 double distanceSQR = (vertices[vIdx1] - vertices[vIdx2]).squaredNorm();
414 if (distanceSQR <= thresholdSQR)
415 vertex_map[vIdx2] = vertex_map[vIdx1];
416 }
417 }
418
419 // redirect triangles to new vertices!
420 for (unsigned tIdx = 0; tIdx < mesh.triangle_count; ++tIdx)
421 {
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]];
425 }
426
427 for (int vIdx = 0; vIdx < vertices.size(); ++vIdx)
428 {
429 if (vertices[vIdx][0] == vertices[vIdx][1] || vertices[vIdx][0] == vertices[vIdx][2] ||
430 vertices[vIdx][1] == vertices[vIdx][2])
431 {
432 vertices[vIdx] = vertices.back();
433 vertices.pop_back();
434 --vIdx;
435 }
436 }
437
438 // create new Mesh structure
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;
445
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)
449 {
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];
453 }
454
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)
458 {
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];
462 }
463
464 compressed.normals = new double[compressed.triangle_count * 3];
465 for (unsigned tIdx = 0; tIdx < compressed.triangle_count; ++tIdx)
466 {
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]];
469 Vector3d normal = d1.cross(d2);
470 normal.normalize();
471 Vector3d normal_;
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_);
476
477 if (cosAngle < 0)
478 {
479 swap(compressed.triangles[3 * tIdx + 1], compressed.triangles[3 * tIdx + 2]);
480 normal *= -1;
481 }
482
483 compressed.normals[tIdx * 3 + 0] = normal[0];
484 compressed.normals[tIdx * 3 + 1] = normal[1];
485 compressed.normals[tIdx * 3 + 2] = normal[2];
486 }
487}
488
489string mesh_filter::MeshFilter::padding_vertex_shader_ =
490 "#version 120\n"
491 "uniform vec3 padding_coefficients;"
492 "void main()"
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;}";
500
501string mesh_filter::MeshFilter::filter_vertex_shader_ = "#version 120\n"
502 "void main ()"
503 "{"
504 " gl_FrontColor = gl_Color;"
505 " gl_TexCoord[0] = gl_MultiTexCoord0;"
506 " gl_Position = gl_Vertex;"
507 " gl_Position.w = 1.0;"
508 "}";
509
510string mesh_filter::MeshFilter::filter_fragment_shader_ =
511 "#version 120\n"
512 "uniform sampler2D sensor;"
513 "uniform sampler2D depth;"
514 "uniform sampler2D label;"
515 "uniform float near;"
516 "uniform float far;"
517 "uniform float shadow_threshold;"
518 "float f_n = far - near;"
519 "float threshold = shadow_threshold / f_n;"
520 "void main()"
521 "{"
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;"
525 " if (diff < 0) {"
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));"
531 " } else {"
532 " gl_FragColor = vec4 (1,1,1,1);"
533 " gl_FragDepth = 0;"
534 " }"
535 "}";
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.
Definition mesh_filter.h:91
Vec3fX< details::Vec3Data< double > > Vector3d
Definition fcl_compat.h:89