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 
41 #include <Eigen/Eigen>
42 #include <stdexcept>
44 #include <stdint.h>
45 
46 // include SSE headers
47 #ifdef HAVE_SSE_EXTENSIONS
48 #include <xmmintrin.h>
49 #endif
50 
51 using namespace std;
52 using namespace Eigen;
53 using shapes::Mesh;
54 
55 mesh_filter::MeshFilter::MeshFilter(const boost::function<bool(MeshFilter::MeshHandle, Affine3d&)>& 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 
100 mesh_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 
110 void 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 boost::function<bool(mesh_filter::MeshFilter::MeshHandle, Affine3d&)>& transform_callback)
121 {
122  transform_callback_ = transform_callback;
123 }
124 
125 void mesh_filter::MeshFilter::setPaddingCoefficients(const Eigen::Vector3f& padding_coefficients)
126 {
127  padding_coefficients_ = padding_coefficients;
128 }
129 
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 
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 
150 void mesh_filter::MeshFilter::getModelLabels(unsigned* labels) const
151 {
152  mesh_renderer_.getColorBuffer((unsigned char*)labels);
153 }
154 
155 namespace
156 {
157 inline unsigned alignment16(const void* pointer)
158 {
159  return ((uintptr_t)pointer & 15);
160 }
161 inline bool isAligned16(const void* pointer)
162 {
163  return (((uintptr_t)pointer & 15) == 0);
164 }
165 }
166 
167 void 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 
240 void 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 
303 void mesh_filter::MeshFilter::getFilteredLabels(unsigned* labels) const
304 {
305  depth_filter_.getColorBuffer((unsigned char*)labels);
306 }
307 
308 void 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  Affine3d 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 
371 void mesh_filter::MeshFilter::setClippingRange(float near, float far)
372 {
373  mesh_renderer_.setClippingRange(near, far);
374  depth_filter_.setClippingRange(near, far);
375 }
376 
377 void 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 
489 string 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 
501 string 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 
510 string 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  "}";
Chain d2()
void setTransformCallback(const TransformCallback &transform_callback)
set the callback for retrieving transformations for each mesh.
MeshFilter(const TransformCallback &transform_callback=TransformCallback(), const typename SensorType::Parameters &sensor_parameters=typename SensorType::Parameters())
Constructor.
Definition: mesh_filter.h:94
void getFilteredDepth(float *depth) const
retrieves the filtered depth values
MeshHandle addMesh(const shapes::Mesh &mesh)
adds a mesh to the filter object.
unsigned int * triangles
unsigned int vertex_count
void removeMesh(MeshHandle mesh_handle)
removes a mesh given by its handle
void swap(ChunkedFile &a, ChunkedFile &b)
unsigned int triangle_count
void getFilteredLabels(LabelType *labels) const
retrieves the labels of the input data
double * vertices
void getModelDepth(float *depth) const
retrieves the depth values of the rendered model
void getModelLabels(LabelType *labels) const
retrieves the labels of the rendered model
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
void setSize(unsigned int width, unsigned int height)
sets the size of the fram buffers
void setShadowThreshold(float threshold)
set the shadow threshold. points that are further away than the rendered model are filtered out...
void filter(const void *sensor_data, GLushort type, bool wait=false) const
label/remove pixels from input depth-image
unsigned int MeshHandle


perception
Author(s): Ioan Sucan , Jon Binney , Suat Gedikli
autogenerated on Thu Oct 18 2018 02:47:34