mesh_filter.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2013, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 /* Author: Suat Gedikli */
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 // include SSE headers
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)  // some default values for buffer sizes and clipping planes
00057   , depth_filter_(640, 480, 0.3, 10)
00058   , next_handle_(FirstLabel)  // 0 and 1 are reserved!
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     // first depth value without SSE until we reach aligned data
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     // rest of unaligned data at the end
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   // rest is aligned
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   // calculate metric depth values from OpenGL normalized depth buffer
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   //* SSE version
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     // first depth value without SSE until we reach aligned data
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     // rest of unaligned data at the end
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   // rest is aligned
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     // 0 = on near clipping plane -> we used 0 to mark invalid points -> not visible
00292     // points on far clipping plane needs to be removed too
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   // now filter the depth_map with the second rendering stage
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   // bind sensor depth
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   // bind depth map
00359   glActiveTexture(GL_TEXTURE2);
00360   glBindTexture(GL_TEXTURE_2D, depth_texture);
00361 
00362   // bind labels
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   // max allowed distance of vertices to be considered same! 1mm
00380   // to allow double-error from transformed vertices.
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   // redirect triangles to new vertices!
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   // create new Mesh structure
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     "}";


perception
Author(s): Ioan Sucan , Jon Binney , Suat Gedikli
autogenerated on Wed Jun 19 2019 19:24:12