scene.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2014 Google Inc. All Rights Reserved.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *      http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include <tango-gl/conversions.h>
00018 #include <tango-gl/gesture_camera.h>
00019 
00020 #include <rtabmap/utilite/ULogger.h>
00021 #include <rtabmap/utilite/UStl.h>
00022 #include <rtabmap/core/util3d_filtering.h>
00023 
00024 #include "scene.h"
00025 #include "util.h"
00026 
00027 // We want to represent the device properly with respect to the ground so we'll
00028 // add an offset in z to our origin. We'll set this offset to 1.3 meters based
00029 // on the average height of a human standing with a Tango device. This allows us
00030 // to place a grid roughly on the ground for most users.
00031 const glm::vec3 kHeightOffset = glm::vec3(0.0f, 1.3f, 0.0f);
00032 
00033 // Color of the motion tracking trajectory.
00034 const tango_gl::Color kTraceColor(0.66f, 0.66f, 0.66f);
00035 
00036 // Color of the ground grid.
00037 const tango_gl::Color kGridColor(0.85f, 0.85f, 0.85f);
00038 
00039 // Frustum scale.
00040 const glm::vec3 kFrustumScale = glm::vec3(0.4f, 0.3f, 0.5f);
00041 
00042 const std::string kPointCloudVertexShader =
00043     "precision mediump float;\n"
00044     "precision mediump int;\n"
00045     "attribute vec3 vertex;\n"
00046     "attribute vec3 color;\n"
00047     "uniform mat4 mvp;\n"
00048     "uniform float point_size;\n"
00049     "varying vec3 v_color;\n"
00050     "void main() {\n"
00051     "  gl_Position = mvp*vec4(vertex.x, vertex.y, vertex.z, 1.0);\n"
00052     "  gl_PointSize = point_size;\n"
00053     "  v_color = color;\n"
00054     "}\n";
00055 const std::string kPointCloudFragmentShader =
00056     "precision mediump float;\n"
00057     "precision mediump int;\n"
00058     "varying vec3 v_color;\n"
00059     "void main() {\n"
00060     "  gl_FragColor = vec4(v_color.z, v_color.y, v_color.x, 1.0);\n"
00061     "}\n";
00062 
00063 const std::string kTextureMeshVertexShader =
00064     "precision mediump float;\n"
00065     "precision mediump int;\n"
00066     "attribute vec3 vertex;\n"
00067     "attribute vec2 a_TexCoordinate;\n"
00068     "uniform mat4 mvp;\n"
00069     "varying vec2 v_TexCoordinate;\n"
00070     "void main() {\n"
00071     "  gl_Position = mvp*vec4(vertex.x, vertex.y, vertex.z, 1.0);\n"
00072     "  v_TexCoordinate = a_TexCoordinate;\n"
00073     "}\n";
00074 const std::string kTextureMeshFragmentShader =
00075     "precision mediump float;\n"
00076     "precision mediump int;\n"
00077         "uniform sampler2D u_Texture;\n"
00078     "varying vec2 v_TexCoordinate;\n"
00079     "void main() {\n"
00080     "  gl_FragColor = texture2D(u_Texture, v_TexCoordinate);\n"
00081     "}\n";
00082 
00083 const std::string kGraphVertexShader =
00084     "precision mediump float;\n"
00085     "precision mediump int;\n"
00086     "attribute vec3 vertex;\n"
00087     "uniform vec3 color;\n"
00088     "uniform mat4 mvp;\n"
00089     "varying vec3 v_color;\n"
00090     "void main() {\n"
00091     "  gl_Position = mvp*vec4(vertex.x, vertex.y, vertex.z, 1.0);\n"
00092     "  v_color = color;\n"
00093     "}\n";
00094 const std::string kGraphFragmentShader =
00095     "precision mediump float;\n"
00096     "precision mediump int;\n"
00097     "varying vec3 v_color;\n"
00098     "void main() {\n"
00099     "  gl_FragColor = vec4(v_color.z, v_color.y, v_color.x, 1.0);\n"
00100     "}\n";
00101 
00102 
00103 
00104 Scene::Scene() :
00105                 gesture_camera_(0),
00106                 axis_(0),
00107                 frustum_(0),
00108                 grid_(0),
00109                 trace_(0),
00110                 graph_(0),
00111                 graphVisible_(true),
00112                 traceVisible_(true),
00113                 currentPose_(0),
00114                 cloud_shader_program_(0),
00115                 texture_mesh_shader_program_(0),
00116                 graph_shader_program_(0),
00117                 mapRendering_(true),
00118                 meshRendering_(true),
00119                 pointSize_(3.0f) {}
00120 
00121 Scene::~Scene() {DeleteResources();}
00122 
00123 //Should only be called in OpenGL thread!
00124 void Scene::InitGLContent()
00125 {
00126         if(gesture_camera_ != 0)
00127         {
00128                 DeleteResources();
00129         }
00130 
00131         UASSERT(gesture_camera_ == 0);
00132 
00133   gesture_camera_ = new tango_gl::GestureCamera();
00134   axis_ = new tango_gl::Axis();
00135   frustum_ = new tango_gl::Frustum();
00136   trace_ = new tango_gl::Trace();
00137   grid_ = new tango_gl::Grid();
00138   currentPose_ = new rtabmap::Transform();
00139 
00140 
00141   axis_->SetScale(glm::vec3(0.5f,0.5f,0.5f));
00142   frustum_->SetColor(kTraceColor);
00143   trace_->ClearVertexArray();
00144   trace_->SetColor(kTraceColor);
00145   grid_->SetColor(kGridColor);
00146   grid_->SetPosition(-kHeightOffset);
00147   gesture_camera_->SetCameraType(
00148       tango_gl::GestureCamera::kFirstPerson);
00149 
00150   if(cloud_shader_program_ == 0)
00151   {
00152           cloud_shader_program_ = tango_gl::util::CreateProgram(kPointCloudVertexShader.c_str(), kPointCloudFragmentShader.c_str());
00153           UASSERT(cloud_shader_program_ != 0);
00154   }
00155   if(texture_mesh_shader_program_ == 0)
00156   {
00157           texture_mesh_shader_program_ = tango_gl::util::CreateProgram(kTextureMeshVertexShader.c_str(), kTextureMeshFragmentShader.c_str());
00158           UASSERT(texture_mesh_shader_program_ != 0);
00159   }
00160   if(graph_shader_program_ == 0)
00161   {
00162           graph_shader_program_ = tango_gl::util::CreateProgram(kGraphVertexShader.c_str(), kGraphFragmentShader.c_str());
00163           UASSERT(graph_shader_program_ != 0);
00164   }
00165 }
00166 
00167 //Should only be called in OpenGL thread!
00168 void Scene::DeleteResources() {
00169 
00170         LOGI("Scene::DeleteResources()");
00171         if(gesture_camera_)
00172         {
00173           delete gesture_camera_;
00174           delete axis_;
00175           delete frustum_;
00176           delete trace_;
00177           delete grid_;
00178           delete currentPose_;
00179           gesture_camera_ = 0;
00180         }
00181 
00182         if (cloud_shader_program_) {
00183                 glDeleteShader(cloud_shader_program_);
00184                 cloud_shader_program_ = 0;
00185           }
00186         if (texture_mesh_shader_program_) {
00187                 glDeleteShader(texture_mesh_shader_program_);
00188                 texture_mesh_shader_program_ = 0;
00189           }
00190         if (graph_shader_program_) {
00191                 glDeleteShader(graph_shader_program_);
00192                 graph_shader_program_ = 0;
00193           }
00194 
00195         clear();
00196 }
00197 
00198 //Should only be called in OpenGL thread!
00199 void Scene::clear()
00200 {
00201         LOGI("Scene::clear()");
00202         for(std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
00203         {
00204                 delete iter->second;
00205         }
00206         if(trace_)
00207         {
00208                 trace_->ClearVertexArray();
00209         }
00210         if(graph_)
00211         {
00212                 delete graph_;
00213                 graph_ = 0;
00214         }
00215         pointClouds_.clear();
00216 }
00217 
00218 //Should only be called in OpenGL thread!
00219 void Scene::SetupViewPort(int w, int h) {
00220   if (h == 0) {
00221     LOGE("Setup graphic height not valid");
00222   }
00223   UASSERT(gesture_camera_ != 0);
00224   gesture_camera_->SetAspectRatio(static_cast<float>(w) /
00225                                   static_cast<float>(h));
00226   glViewport(0, 0, w, h);
00227 }
00228 
00229 //Should only be called in OpenGL thread!
00230 int Scene::Render() {
00231         UASSERT(gesture_camera_ != 0);
00232 
00233   glEnable(GL_DEPTH_TEST);
00234   glEnable(GL_CULL_FACE);
00235 
00236   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
00237   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00238 
00239   if(!currentPose_->isNull())
00240   {
00241           glm::vec3 position(currentPose_->x(), currentPose_->y(), currentPose_->z());
00242           Eigen::Quaternionf quat = currentPose_->getQuaternionf();
00243           glm::quat rotation(quat.w(), quat.x(), quat.y(), quat.z());
00244 
00245           if (gesture_camera_->GetCameraType() == tango_gl::GestureCamera::kFirstPerson)
00246           {
00247                 // In first person mode, we directly control camera's motion.
00248                 gesture_camera_->SetPosition(position);
00249                 gesture_camera_->SetRotation(rotation);
00250           }
00251           else
00252           {
00253                 // In third person or top down more, we follow the camera movement.
00254                 gesture_camera_->SetAnchorPosition(position, rotation);
00255 
00256                 frustum_->SetPosition(position);
00257                 frustum_->SetRotation(rotation);
00258                 // Set the frustum scale to 4:3, this doesn't necessarily match the physical
00259                 // camera's aspect ratio, this is just for visualization purposes.
00260                 frustum_->SetScale(kFrustumScale);
00261                 frustum_->Render(gesture_camera_->GetProjectionMatrix(),
00262                                                  gesture_camera_->GetViewMatrix());
00263 
00264                 axis_->SetPosition(position);
00265                 axis_->SetRotation(rotation);
00266                 axis_->Render(gesture_camera_->GetProjectionMatrix(),
00267                                           gesture_camera_->GetViewMatrix());
00268           }
00269 
00270           trace_->UpdateVertexArray(position);
00271           if(traceVisible_)
00272           {
00273                   trace_->Render(gesture_camera_->GetProjectionMatrix(),
00274                                                  gesture_camera_->GetViewMatrix());
00275           }
00276   }
00277 
00278 
00279         grid_->Render(gesture_camera_->GetProjectionMatrix(),
00280                                   gesture_camera_->GetViewMatrix());
00281 
00282         bool frustumCulling = true;
00283         int cloudDrawn=0;
00284         if(mapRendering_ && frustumCulling)
00285         {
00286                 //Use camera frustum to cull nodes that don't need to be drawn
00287                 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
00288                 std::vector<int> ids(pointClouds_.size());
00289 
00290                 cloud->resize(pointClouds_.size());
00291                 ids.resize(pointClouds_.size());
00292                 int oi=0;
00293                 for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
00294                 {
00295                         if(!iter->second->getPose().isNull() && iter->second->isVisible())
00296                         {
00297                                 (*cloud)[oi] = pcl::PointXYZ(iter->second->getPose().x(), iter->second->getPose().y(), iter->second->getPose().z());
00298                                 ids[oi++] = iter->first;
00299                         }
00300                 }
00301                 cloud->resize(oi);
00302                 ids.resize(oi);
00303 
00304                 if(oi)
00305                 {
00306                         float fov = 45.0f;
00307                         rtabmap::Transform openglCamera = GetOpenGLCameraPose(&fov)*rtabmap::Transform(0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f);
00308                         // transform in same coordinate as frustum filtering
00309                         openglCamera *= rtabmap::Transform(
00310                                  0.0f,  0.0f,  1.0f, 0.0f,
00311                                  0.0f,  1.0f,  0.0f, 0.0f,
00312                                 -1.0f,  0.0f,  0.0f, 0.0f);
00313                         pcl::IndicesPtr indices = rtabmap::util3d::frustumFiltering(
00314                                         cloud,
00315                                         pcl::IndicesPtr(new std::vector<int>),
00316                                         openglCamera,
00317                                         fov*2.0f,
00318                                         fov*2.0f,
00319                                         0.1f,
00320                                         100.0f);
00321 
00322                         //LOGI("Frustum poses filtered = %d (showing %d/%d)",
00323                         //                      (int)(pointClouds_.size()-indices->size()),
00324                         //                      (int)indices->size(),
00325                         //                      (int)pointClouds_.size());
00326 
00327                         for(unsigned int i=0; i<indices->size(); ++i)
00328                         {
00329                                 ++cloudDrawn;
00330                                 pointClouds_.find(ids[indices->at(i)])->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_);
00331                         }
00332                 }
00333         }
00334         else
00335         {
00336                 for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
00337                 {
00338                         if((mapRendering_ || iter->first < 0) && iter->second->isVisible())
00339                         {
00340                                 ++cloudDrawn;
00341                                 iter->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_);
00342                         }
00343                 }
00344         }
00345 
00346         if(graphVisible_ && graph_)
00347         {
00348                 graph_->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix());
00349         }
00350 
00351         return cloudDrawn;
00352 }
00353 
00354 void Scene::SetCameraType(tango_gl::GestureCamera::CameraType camera_type) {
00355   gesture_camera_->SetCameraType(camera_type);
00356 }
00357 
00358 void Scene::SetCameraPose(const rtabmap::Transform & pose)
00359 {
00360         UASSERT(currentPose_ != 0);
00361         UASSERT(!pose.isNull());
00362         *currentPose_ = pose;
00363 }
00364 
00365 rtabmap::Transform Scene::GetOpenGLCameraPose(float * fov) const
00366 {
00367         if(fov)
00368         {
00369                 *fov = gesture_camera_->getFOV();
00370         }
00371         return glmToTransform(gesture_camera_->GetTransformationMatrix());
00372 
00373 }
00374 
00375 void Scene::OnTouchEvent(int touch_count,
00376                          tango_gl::GestureCamera::TouchEvent event, float x0,
00377                          float y0, float x1, float y1) {
00378         UASSERT(gesture_camera_ != 0);
00379   gesture_camera_->OnTouchEvent(touch_count, event, x0, y0, x1, y1);
00380 }
00381 
00382 void Scene::updateGraph(
00383                 const std::map<int, rtabmap::Transform> & poses,
00384                 const std::multimap<int, rtabmap::Link> & links)
00385 {
00386         LOGI("updateGraph");
00387         if(graph_)
00388         {
00389                 delete graph_;
00390                 graph_ = 0;
00391         }
00392 
00393         //create
00394         UASSERT(graph_shader_program_ != 0);
00395         graph_ = new GraphDrawable(graph_shader_program_, poses, links);
00396 }
00397 
00398 void Scene::setGraphVisible(bool visible)
00399 {
00400         graphVisible_ = visible;
00401 }
00402 
00403 void Scene::setTraceVisible(bool visible)
00404 {
00405         traceVisible_ = visible;
00406 }
00407 
00408 //Should only be called in OpenGL thread!
00409 void Scene::addCloud(
00410                 int id,
00411                 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
00412                 const std::vector<pcl::Vertices> & polygons,
00413                 const rtabmap::Transform & pose,
00414                 const cv::Mat & image)
00415 {
00416         LOGI("addOrUpdateCloud cloud %d", id);
00417         std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.find(id);
00418         if(iter != pointClouds_.end())
00419         {
00420                 delete iter->second;
00421                 pointClouds_.erase(iter);
00422         }
00423 
00424         //create
00425         UASSERT(cloud_shader_program_ != 0 && texture_mesh_shader_program_!=0);
00426         PointCloudDrawable * drawable = new PointCloudDrawable(
00427                         cloud_shader_program_,
00428                         texture_mesh_shader_program_,
00429                         cloud,
00430                         polygons,
00431                         image);
00432         drawable->setPose(pose);
00433         pointClouds_.insert(std::make_pair(id, drawable));
00434 }
00435 
00436 
00437 void Scene::setCloudPose(int id, const rtabmap::Transform & pose)
00438 {
00439         UASSERT(!pose.isNull());
00440         std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.find(id);
00441         if(iter != pointClouds_.end())
00442         {
00443                 iter->second->setPose(pose);
00444         }
00445 }
00446 
00447 void Scene::setCloudVisible(int id, bool visible)
00448 {
00449         std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.find(id);
00450         if(iter != pointClouds_.end())
00451         {
00452                 iter->second->setVisible(visible);
00453         }
00454 }
00455 
00456 bool Scene::hasCloud(int id) const
00457 {
00458         return pointClouds_.find(id) != pointClouds_.end();
00459 }
00460 
00461 std::set<int> Scene::getAddedClouds() const
00462 {
00463         return uKeysSet(pointClouds_);
00464 }


rtabmap
Author(s): Mathieu Labbe
autogenerated on Sat Jul 23 2016 11:44:17