00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <moveit/mesh_filter/mesh_filter.h>
00038 #include <moveit/mesh_filter/gl_mesh.h>
00039 #include <geometric_shapes/shapes.h>
00040 #include <geometric_shapes/shape_operations.h>
00041 #include <Eigen/Eigen>
00042 #include <stdexcept>
00043 #include <sensor_msgs/image_encodings.h>
00044 #include <stdint.h>
00045
00046
00047 #ifdef HAVE_SSE_EXTENSIONS
00048 #include <xmmintrin.h>
00049 #endif
00050
00051 using namespace std;
00052 using namespace Eigen;
00053 using shapes::Mesh;
00054
00055 mesh_filter::MeshFilter::MeshFilter(const boost::function<bool(MeshFilter::MeshHandle, Affine3d&)>& transform_callback)
00056 : mesh_renderer_(640, 480, 0.3, 10)
00057 , depth_filter_(640, 480, 0.3, 10)
00058 , next_handle_(FirstLabel)
00059 , transform_callback_(transform_callback)
00060 , shadow_threshold_(0.5)
00061 {
00062 mesh_renderer_.setShadersFromString(padding_vertex_shader_, "");
00063 depth_filter_.setShadersFromString(filter_vertex_shader_, filter_fragment_shader_);
00064
00065 depth_filter_.begin();
00066
00067 glGenTextures(1, &sensor_depth_texture_);
00068
00069 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(), "sensor"), 0);
00070 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(), "depth"), 2);
00071 glUniform1i(glGetUniformLocation(depth_filter_.getProgramID(), "label"), 4);
00072
00073 near_location_ = glGetUniformLocation(depth_filter_.getProgramID(), "near");
00074 far_location_ = glGetUniformLocation(depth_filter_.getProgramID(), "far");
00075 shadow_threshold_location_ = glGetUniformLocation(depth_filter_.getProgramID(), "shadow_threshold");
00076
00077 depth_filter_.end();
00078
00079 canvas_ = glGenLists(1);
00080 glNewList(canvas_, GL_COMPILE);
00081 glBegin(GL_QUADS);
00082
00083 glColor3f(1, 1, 1);
00084 glTexCoord2f(0, 0);
00085 glVertex3f(-1, -1, 0);
00086
00087 glTexCoord2f(1, 0);
00088 glVertex3f(1, -1, 0);
00089
00090 glTexCoord2f(1, 1);
00091 glVertex3f(1, 1, 0);
00092
00093 glTexCoord2f(0, 1);
00094 glVertex3f(-1, 1, 0);
00095
00096 glEnd();
00097 glEndList();
00098 }
00099
00100 mesh_filter::MeshFilter::~MeshFilter()
00101 {
00102 glDeleteLists(1, canvas_);
00103 glDeleteTextures(1, &sensor_depth_texture_);
00104
00105 for (map<unsigned int, GLMesh*>::iterator meshIt = meshes_.begin(); meshIt != meshes_.end(); ++meshIt)
00106 delete (meshIt->second);
00107 meshes_.clear();
00108 }
00109
00110 void mesh_filter::MeshFilter::setSize(unsigned width, unsigned height)
00111 {
00112 mesh_renderer_.setBufferSize(width, height);
00113 mesh_renderer_.setCameraParameters(width, width, width >> 1, height >> 1);
00114
00115 depth_filter_.setBufferSize(width, height);
00116 depth_filter_.setCameraParameters(width, width, width >> 1, height >> 1);
00117 }
00118
00119 void mesh_filter::MeshFilter::setTransformCallback(
00120 const boost::function<bool(mesh_filter::MeshFilter::MeshHandle, Affine3d&)>& transform_callback)
00121 {
00122 transform_callback_ = transform_callback;
00123 }
00124
00125 void mesh_filter::MeshFilter::setPaddingCoefficients(const Eigen::Vector3f& padding_coefficients)
00126 {
00127 padding_coefficients_ = padding_coefficients;
00128 }
00129
00130 mesh_filter::MeshFilter::MeshHandle mesh_filter::MeshFilter::addMesh(const Mesh& mesh)
00131 {
00132 Mesh collapsedMesh(1, 1);
00133 mergeVertices(mesh, collapsedMesh);
00134 meshes_[next_handle_] = new GLMesh(collapsedMesh, next_handle_);
00135 return next_handle_++;
00136 }
00137
00138 void mesh_filter::MeshFilter::removeMesh(MeshFilter::MeshHandle handle)
00139 {
00140 long unsigned int erased = meshes_.erase(handle);
00141 if (erased == 0)
00142 throw runtime_error("Could not remove mesh. Mesh not found!");
00143 }
00144
00145 void mesh_filter::MeshFilter::setShadowThreshold(float threshold)
00146 {
00147 shadow_threshold_ = threshold;
00148 }
00149
00150 void mesh_filter::MeshFilter::getModelLabels(unsigned* labels) const
00151 {
00152 mesh_renderer_.getColorBuffer((unsigned char*)labels);
00153 }
00154
00155 namespace
00156 {
00157 inline unsigned alignment16(const void* pointer)
00158 {
00159 return ((uintptr_t)pointer & 15);
00160 }
00161 inline bool isAligned16(const void* pointer)
00162 {
00163 return (((uintptr_t)pointer & 15) == 0);
00164 }
00165 }
00166
00167 void mesh_filter::MeshFilter::getModelDepth(float* depth) const
00168 {
00169 mesh_renderer_.getDepthBuffer(depth);
00170 #if HAVE_SSE_EXTENSIONS
00171 const __m128 mmNear = _mm_set1_ps(mesh_renderer_.getNearClippingDistance());
00172 const __m128 mmFar = _mm_set1_ps(mesh_renderer_.getFarClippingDistance());
00173 const __m128 mmNF = _mm_mul_ps(mmNear, mmFar);
00174 const __m128 mmF_N = _mm_sub_ps(mmFar, mmNear);
00175 static const __m128 mmOnes = _mm_set1_ps(1);
00176 static const __m128 mmZeros = _mm_set1_ps(0);
00177
00178 float* depthEnd = depth + mesh_renderer_.getHeight() * mesh_renderer_.getWidth();
00179 if (!isAligned16(depth))
00180 {
00181
00182 unsigned first = 16 - alignment16(depth);
00183 unsigned idx;
00184 const float near = mesh_renderer_.getNearClippingDistance();
00185 const float far = mesh_renderer_.getFarClippingDistance();
00186 const float nf = near * far;
00187 const float f_n = far - near;
00188
00189 while (depth < depthEnd && idx++ < first)
00190 if (*depth != 0 && *depth != 1)
00191 *depth = nf / (far - *depth * f_n);
00192 else
00193 *depth = 0;
00194
00195
00196 unsigned last = (depth_filter_.getWidth() * depth_filter_.getHeight() - first) & 15;
00197 float* depth2 = depthEnd - last;
00198 while (depth2 < depthEnd)
00199 if (*depth2 != 0 && *depth2 != 1)
00200 *depth2 = nf / (far - *depth2 * f_n);
00201 else
00202 *depth2 = 0;
00203
00204 depthEnd -= last;
00205 }
00206
00207 const __m128* mmEnd = (__m128*)depthEnd;
00208 __m128* mmDepth = (__m128*)depth;
00209
00210 while (mmDepth < mmEnd)
00211 {
00212 __m128 mask = _mm_and_ps(_mm_cmpneq_ps(*mmDepth, mmOnes), _mm_cmpneq_ps(*mmDepth, mmZeros));
00213 *mmDepth = _mm_mul_ps(*mmDepth, mmF_N);
00214 *mmDepth = _mm_sub_ps(mmFar, *mmDepth);
00215 *mmDepth = _mm_div_ps(mmNF, *mmDepth);
00216 *mmDepth = _mm_and_ps(*mmDepth, mask);
00217 ++mmDepth;
00218 }
00219
00220 #else
00221
00222 const float near = mesh_renderer_.getNearClippingDistance();
00223 const float far = mesh_renderer_.getFarClippingDistance();
00224 const float nf = near * far;
00225 const float f_n = far - near;
00226
00227 const float* depthEnd = depth + mesh_renderer_.getHeight() * mesh_renderer_.getWidth();
00228 while (depth < depthEnd)
00229 {
00230 if (*depth != 0 && *depth != 1)
00231 *depth = nf / (far - *depth * f_n);
00232 else
00233 *depth = 0;
00234
00235 ++depth;
00236 }
00237 #endif
00238 }
00239
00240 void mesh_filter::MeshFilter::getFilteredDepth(float* depth) const
00241 {
00242 depth_filter_.getDepthBuffer(depth);
00243 #if HAVE_SSE_EXTENSIONS
00244
00245 const __m128 mmNear = _mm_set1_ps(depth_filter_.getNearClippingDistance());
00246 const __m128 mmFar = _mm_set1_ps(depth_filter_.getFarClippingDistance());
00247 const __m128 mmScale = _mm_sub_ps(mmFar, mmNear);
00248 float* depthEnd = depth + depth_filter_.getWidth() * depth_filter_.getHeight();
00249
00250 if (!isAligned16(depth))
00251 {
00252
00253 unsigned first = 16 - alignment16(depth);
00254 unsigned idx;
00255 const float scale = depth_filter_.getFarClippingDistance() - depth_filter_.getNearClippingDistance();
00256 const float offset = depth_filter_.getNearClippingDistance();
00257 while (depth < depthEnd && idx++ < first)
00258 if (*depth != 0 && *depth != 1.0)
00259 *depth = *depth * scale + offset;
00260 else
00261 *depth = 0;
00262
00263
00264 unsigned last = (depth_filter_.getWidth() * depth_filter_.getHeight() - first) & 15;
00265 float* depth2 = depthEnd - last;
00266 while (depth2 < depthEnd)
00267 if (*depth2 != 0 && *depth != 1.0)
00268 *depth2 = *depth2 * scale + offset;
00269 else
00270 *depth2 = 0;
00271
00272 depthEnd -= last;
00273 }
00274
00275 const __m128* mmEnd = (__m128*)depthEnd;
00276 __m128* mmDepth = (__m128*)depth;
00277
00278 while (mmDepth < mmEnd)
00279 {
00280 *mmDepth = _mm_mul_ps(*mmDepth, mmScale);
00281 *mmDepth = _mm_add_ps(*mmDepth, mmNear);
00282 *mmDepth = _mm_and_ps(*mmDepth, _mm_and_ps(_mm_cmpneq_ps(*mmDepth, mmNear), _mm_cmpneq_ps(*mmDepth, mmFar)));
00283 ++mmDepth;
00284 }
00285 #else
00286 const float* depthEnd = depth + depth_filter_.getWidth() * depth_filter_.getHeight();
00287 const float scale = depth_filter_.getFarClippingDistance() - depth_filter_.getNearClippingDistance();
00288 const float offset = depth_filter_.getNearClippingDistance();
00289 while (depth < depthEnd)
00290 {
00291
00292
00293 if (*depth != 0 && *depth != 1.0)
00294 *depth = *depth * scale + offset;
00295 else
00296 *depth = 0;
00297
00298 ++depth;
00299 }
00300 #endif
00301 }
00302
00303 void mesh_filter::MeshFilter::getFilteredLabels(unsigned* labels) const
00304 {
00305 depth_filter_.getColorBuffer((unsigned char*)labels);
00306 }
00307
00308 void mesh_filter::MeshFilter::filter(const float* sensor_data, unsigned width, unsigned height, float fx, float fy,
00309 float cx, float cy) const
00310 {
00311 mesh_renderer_.setBufferSize(width, height);
00312 mesh_renderer_.setCameraParameters(fx, fy, cx, cy);
00313 mesh_renderer_.begin();
00314 glEnable(GL_DEPTH_TEST);
00315 glEnable(GL_CULL_FACE);
00316 glCullFace(GL_FRONT);
00317 glDisable(GL_ALPHA_TEST);
00318
00319 GLuint padding_coefficients_id = glGetUniformLocation(mesh_renderer_.getProgramID(), "padding_coefficients");
00320 glUniform3f(padding_coefficients_id, padding_coefficients_[0], padding_coefficients_[1], padding_coefficients_[2]);
00321
00322 Affine3d transform;
00323 for (map<unsigned int, GLMesh*>::const_iterator meshIt = meshes_.begin(); meshIt != meshes_.end(); ++meshIt)
00324 if (transform_callback_(meshIt->first, transform))
00325 meshIt->second->render(transform);
00326
00327 mesh_renderer_.end();
00328
00329
00330 depth_filter_.setBufferSize(width, height);
00331 depth_filter_.setCameraParameters(fx, fy, cx, cy);
00332 depth_filter_.begin();
00333 glEnable(GL_DEPTH_TEST);
00334 glEnable(GL_CULL_FACE);
00335 glCullFace(GL_BACK);
00336 glDisable(GL_ALPHA_TEST);
00337
00338 glUniform1f(near_location_, depth_filter_.getNearClippingDistance());
00339 glUniform1f(far_location_, depth_filter_.getFarClippingDistance());
00340 glUniform1f(shadow_threshold_location_, shadow_threshold_);
00341
00342 GLuint depth_texture = mesh_renderer_.getDepthTexture();
00343 GLuint color_texture = mesh_renderer_.getColorTexture();
00344
00345
00346 glActiveTexture(GL_TEXTURE0);
00347 glBindTexture(GL_TEXTURE_2D, sensor_depth_texture_);
00348
00349 float scale = 1.0 / (depth_filter_.getFarClippingDistance() - depth_filter_.getNearClippingDistance());
00350 glPixelTransferf(GL_DEPTH_SCALE, scale);
00351 glPixelTransferf(GL_DEPTH_BIAS, -scale * depth_filter_.getNearClippingDistance());
00352 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, sensor_data);
00353 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00354 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00357
00358
00359 glActiveTexture(GL_TEXTURE2);
00360 glBindTexture(GL_TEXTURE_2D, depth_texture);
00361
00362
00363 glActiveTexture(GL_TEXTURE4);
00364 glBindTexture(GL_TEXTURE_2D, color_texture);
00365
00366 glCallList(canvas_);
00367 glDisable(GL_TEXTURE_2D);
00368 depth_filter_.end();
00369 }
00370
00371 void mesh_filter::MeshFilter::setClippingRange(float near, float far)
00372 {
00373 mesh_renderer_.setClippingRange(near, far);
00374 depth_filter_.setClippingRange(near, far);
00375 }
00376
00377 void mesh_filter::MeshFilter::mergeVertices(const Mesh& mesh, Mesh& compressed)
00378 {
00379
00380
00381 static const double thresholdSQR = pow(0.00001, 2);
00382
00383 vector<unsigned> vertex_map(mesh.vertex_count);
00384 vector<Vector3d> vertices(mesh.vertex_count);
00385 vector<Vector3d> compressed_vertices;
00386 vector<Vector3i> triangles(mesh.triangle_count);
00387
00388 for (unsigned vIdx = 0; vIdx < mesh.vertex_count; ++vIdx)
00389 {
00390 vertices[vIdx][0] = mesh.vertices[3 * vIdx];
00391 vertices[vIdx][1] = mesh.vertices[3 * vIdx + 1];
00392 vertices[vIdx][2] = mesh.vertices[3 * vIdx + 2];
00393 vertex_map[vIdx] = vIdx;
00394 }
00395
00396 for (unsigned tIdx = 0; tIdx < mesh.triangle_count; ++tIdx)
00397 {
00398 triangles[tIdx][0] = mesh.triangles[3 * tIdx];
00399 triangles[tIdx][1] = mesh.triangles[3 * tIdx + 1];
00400 triangles[tIdx][2] = mesh.triangles[3 * tIdx + 2];
00401 }
00402
00403 for (unsigned vIdx1 = 0; vIdx1 < mesh.vertex_count; ++vIdx1)
00404 {
00405 if (vertex_map[vIdx1] != vIdx1)
00406 continue;
00407
00408 vertex_map[vIdx1] = compressed_vertices.size();
00409 compressed_vertices.push_back(vertices[vIdx1]);
00410
00411 for (unsigned vIdx2 = vIdx1 + 1; vIdx2 < mesh.vertex_count; ++vIdx2)
00412 {
00413 double distanceSQR = (vertices[vIdx1] - vertices[vIdx2]).squaredNorm();
00414 if (distanceSQR <= thresholdSQR)
00415 vertex_map[vIdx2] = vertex_map[vIdx1];
00416 }
00417 }
00418
00419
00420 for (unsigned tIdx = 0; tIdx < mesh.triangle_count; ++tIdx)
00421 {
00422 triangles[tIdx][0] = vertex_map[triangles[tIdx][0]];
00423 triangles[tIdx][1] = vertex_map[triangles[tIdx][1]];
00424 triangles[tIdx][2] = vertex_map[triangles[tIdx][2]];
00425 }
00426
00427 for (int vIdx = 0; vIdx < vertices.size(); ++vIdx)
00428 {
00429 if (vertices[vIdx][0] == vertices[vIdx][1] || vertices[vIdx][0] == vertices[vIdx][2] ||
00430 vertices[vIdx][1] == vertices[vIdx][2])
00431 {
00432 vertices[vIdx] = vertices.back();
00433 vertices.pop_back();
00434 --vIdx;
00435 }
00436 }
00437
00438
00439 if (compressed.vertex_count > 0 && compressed.vertices)
00440 delete[] compressed.vertices;
00441 if (compressed.triangle_count > 0 && compressed.triangles)
00442 delete[] compressed.triangles;
00443 if (compressed.triangle_count > 0 && compressed.normals)
00444 delete[] compressed.normals;
00445
00446 compressed.vertex_count = compressed_vertices.size();
00447 compressed.vertices = new double[compressed.vertex_count * 3];
00448 for (unsigned vIdx = 0; vIdx < compressed.vertex_count; ++vIdx)
00449 {
00450 compressed.vertices[3 * vIdx + 0] = compressed_vertices[vIdx][0];
00451 compressed.vertices[3 * vIdx + 1] = compressed_vertices[vIdx][1];
00452 compressed.vertices[3 * vIdx + 2] = compressed_vertices[vIdx][2];
00453 }
00454
00455 compressed.triangle_count = triangles.size();
00456 compressed.triangles = new unsigned int[compressed.triangle_count * 3];
00457 for (unsigned tIdx = 0; tIdx < compressed.triangle_count; ++tIdx)
00458 {
00459 compressed.triangles[3 * tIdx + 0] = triangles[tIdx][0];
00460 compressed.triangles[3 * tIdx + 1] = triangles[tIdx][1];
00461 compressed.triangles[3 * tIdx + 2] = triangles[tIdx][2];
00462 }
00463
00464 compressed.normals = new double[compressed.triangle_count * 3];
00465 for (unsigned tIdx = 0; tIdx < compressed.triangle_count; ++tIdx)
00466 {
00467 Vector3d d1 = compressed_vertices[triangles[tIdx][1]] - compressed_vertices[triangles[tIdx][0]];
00468 Vector3d d2 = compressed_vertices[triangles[tIdx][2]] - compressed_vertices[triangles[tIdx][0]];
00469 Vector3d normal = d1.cross(d2);
00470 normal.normalize();
00471 Vector3d normal_;
00472 normal_[0] = mesh.normals[3 * tIdx];
00473 normal_[1] = mesh.normals[3 * tIdx + 1];
00474 normal_[2] = mesh.normals[3 * tIdx + 2];
00475 double cosAngle = normal.dot(normal_);
00476
00477 if (cosAngle < 0)
00478 {
00479 swap(compressed.triangles[3 * tIdx + 1], compressed.triangles[3 * tIdx + 2]);
00480 normal *= -1;
00481 }
00482
00483 compressed.normals[tIdx * 3 + 0] = normal[0];
00484 compressed.normals[tIdx * 3 + 1] = normal[1];
00485 compressed.normals[tIdx * 3 + 2] = normal[2];
00486 }
00487 }
00488
00489 string mesh_filter::MeshFilter::padding_vertex_shader_ =
00490 "#version 120\n"
00491 "uniform vec3 padding_coefficients;"
00492 "void main()"
00493 "{gl_FrontColor = gl_Color;"
00494 "vec4 vertex = gl_ModelViewMatrix * gl_Vertex;"
00495 "vec3 normal = normalize(gl_NormalMatrix * gl_Normal);"
00496 "float lambda = padding_coefficients.x * vertex.z * vertex.z + padding_coefficients.y * vertex.z + "
00497 "padding_coefficients.z;"
00498 "gl_Position = gl_ProjectionMatrix * (vertex + lambda * vec4(normal,0) );"
00499 "gl_Position.y = -gl_Position.y;}";
00500
00501 string mesh_filter::MeshFilter::filter_vertex_shader_ = "#version 120\n"
00502 "void main ()"
00503 "{"
00504 " gl_FrontColor = gl_Color;"
00505 " gl_TexCoord[0] = gl_MultiTexCoord0;"
00506 " gl_Position = gl_Vertex;"
00507 " gl_Position.w = 1.0;"
00508 "}";
00509
00510 string mesh_filter::MeshFilter::filter_fragment_shader_ =
00511 "#version 120\n"
00512 "uniform sampler2D sensor;"
00513 "uniform sampler2D depth;"
00514 "uniform sampler2D label;"
00515 "uniform float near;"
00516 "uniform float far;"
00517 "uniform float shadow_threshold;"
00518 "float f_n = far - near;"
00519 "float threshold = shadow_threshold / f_n;"
00520 "void main()"
00521 "{"
00522 " float dValue = float(texture2D(depth, gl_TexCoord[0].st));"
00523 " float zValue = dValue * near / (far - dValue * f_n);"
00524 " float diff = float(texture2D(sensor, gl_TexCoord[0].st)) - zValue;"
00525 " if (diff < 0) {"
00526 " gl_FragColor = vec4 (0, 0, 0, 0);"
00527 " gl_FragDepth = float(texture2D(sensor, gl_TexCoord[0].st));"
00528 " } else if (diff > threshold) {"
00529 " gl_FragColor = vec4 (0.003921569, 0, 0, 0);"
00530 " gl_FragDepth = float(texture2D(sensor, gl_TexCoord[0].st));"
00531 " } else {"
00532 " gl_FragColor = vec4 (1,1,1,1);"
00533 " gl_FragDepth = 0;"
00534 " }"
00535 "}";