mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Tango: refactored shaders (to remove most "if" in them), added "Auto" to reconstruction depth option
This commit is contained in:
@@ -104,14 +104,13 @@ void onTangoEventAvailableRouter(void* context, const TangoEvent* event)
|
||||
const float CameraTango::bilateralFilteringSigmaS = 2.0f;
|
||||
const float CameraTango::bilateralFilteringSigmaR = 0.075f;
|
||||
|
||||
CameraTango::CameraTango(bool colorCamera, int decimation, bool autoExposure, bool publishRawScan, bool smoothing) :
|
||||
CameraTango::CameraTango(bool colorCamera, int decimation, bool publishRawScan, bool smoothing) :
|
||||
Camera(0),
|
||||
tango_config_(0),
|
||||
firstFrame_(true),
|
||||
stampEpochOffset_(0.0),
|
||||
colorCamera_(colorCamera),
|
||||
decimation_(decimation),
|
||||
autoExposure_(autoExposure),
|
||||
rawScanPublished_(publishRawScan),
|
||||
smoothing_(smoothing),
|
||||
cloudStamp_(0),
|
||||
@@ -219,31 +218,6 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
|
||||
LOGE("NativeRTABMap: config_enable_color_camera() failed with error code: %d", ret);
|
||||
return false;
|
||||
}
|
||||
// disable auto exposure (disabled, seems broken on latest Tango releases)
|
||||
ret = TangoConfig_setBool(tango_config_, "config_color_mode_auto", autoExposure_);
|
||||
if (ret != TANGO_SUCCESS)
|
||||
{
|
||||
LOGE("NativeRTABMap: config_color_mode_auto() failed with error code: %d", ret);
|
||||
//return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!autoExposure_)
|
||||
{
|
||||
ret = TangoConfig_setInt32(tango_config_, "config_color_iso", 800);
|
||||
if (ret != TANGO_SUCCESS)
|
||||
{
|
||||
LOGE("NativeRTABMap: config_color_iso() failed with error code: %d", ret);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool verifyAutoExposureState;
|
||||
int32_t verifyIso, verifyExp;
|
||||
TangoConfig_getBool( tango_config_, "config_color_mode_auto", &verifyAutoExposureState );
|
||||
TangoConfig_getInt32( tango_config_, "config_color_iso", &verifyIso );
|
||||
TangoConfig_getInt32( tango_config_, "config_color_exp", &verifyExp );
|
||||
LOGI( "NativeRTABMap: config_color autoExposure=%s %d %d", verifyAutoExposureState?"On" : "Off", verifyIso, verifyExp );
|
||||
}
|
||||
}
|
||||
|
||||
// Enable depth.
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
static const float bilateralFilteringSigmaR;
|
||||
|
||||
public:
|
||||
CameraTango(bool colorCamera, int decimation, bool autoExposure, bool publishRawScan, bool smoothing);
|
||||
CameraTango(bool colorCamera, int decimation, bool publishRawScan, bool smoothing);
|
||||
virtual ~CameraTango();
|
||||
|
||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||
@@ -87,7 +87,6 @@ public:
|
||||
void setColorCamera(bool enabled) {if(!this->isRunning()) colorCamera_ = enabled;}
|
||||
void setDecimation(int value) {decimation_ = value;}
|
||||
void setSmoothing(bool enabled) {smoothing_ = enabled;}
|
||||
void setAutoExposure(bool enabled) {autoExposure_ = enabled;}
|
||||
void setRawScanPublished(bool enabled) {rawScanPublished_ = enabled;}
|
||||
void setScreenRotation(TangoSupportRotation colorCameraToDisplayRotation) {colorCameraToDisplayRotation_ = colorCameraToDisplayRotation;}
|
||||
|
||||
@@ -112,7 +111,6 @@ private:
|
||||
double stampEpochOffset_;
|
||||
bool colorCamera_;
|
||||
int decimation_;
|
||||
bool autoExposure_;
|
||||
bool rawScanPublished_;
|
||||
bool smoothing_;
|
||||
cv::Mat cloud_;
|
||||
|
||||
@@ -50,13 +50,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <rtabmap/core/VWDictionary.h>
|
||||
#include <rtabmap/core/Memory.h>
|
||||
#include <rtabmap/core/GainCompensator.h>
|
||||
#include <pcl/common/common.h>
|
||||
#include <pcl/filters/extract_indices.h>
|
||||
#include <pcl/io/ply_io.h>
|
||||
#include <pcl/io/obj_io.h>
|
||||
#include <pcl/surface/poisson.h>
|
||||
#include <pcl/surface/vtk_smoothing/vtk_mesh_quadric_decimation.h>
|
||||
|
||||
#define LOW_RES_PIX 1
|
||||
#define LOW_RES_PIX 2
|
||||
//#define DEBUG_RENDERING_PERFORMANCE;
|
||||
|
||||
const int g_exportedMeshId = -100;
|
||||
@@ -150,7 +151,6 @@ RTABMapApp::RTABMapApp() :
|
||||
nodesFiltering_(false),
|
||||
localizationMode_(false),
|
||||
trajectoryMode_(false),
|
||||
autoExposure_(true),
|
||||
rawScanSaved_(false),
|
||||
smoothing_(true),
|
||||
cameraColor_(true),
|
||||
@@ -260,7 +260,7 @@ void RTABMapApp::onCreate(JNIEnv* env, jobject caller_activity)
|
||||
|
||||
this->registerToEventsManager();
|
||||
|
||||
camera_ = new rtabmap::CameraTango(cameraColor_, !cameraColor_ || fullResolution_?1:2, autoExposure_, rawScanSaved_, smoothing_);
|
||||
camera_ = new rtabmap::CameraTango(cameraColor_, !cameraColor_ || fullResolution_?1:2, rawScanSaved_, smoothing_);
|
||||
}
|
||||
|
||||
void RTABMapApp::setScreenRotation(int displayRotation, int cameraRotation)
|
||||
@@ -329,86 +329,113 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
|
||||
createdMeshes_.clear();
|
||||
int i=0;
|
||||
UTimer addTime;
|
||||
for(std::map<int, rtabmap::Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
|
||||
for(std::map<int, rtabmap::Transform>::iterator iter=poses.begin(); iter!=poses.end() && status==0; ++iter)
|
||||
{
|
||||
int id = iter->first;
|
||||
if(!iter->second.isNull())
|
||||
try
|
||||
{
|
||||
if(uContains(signatures, id))
|
||||
int id = iter->first;
|
||||
if(!iter->second.isNull())
|
||||
{
|
||||
UTimer timer;
|
||||
rtabmap::SensorData data = signatures.at(id).sensorData();
|
||||
|
||||
cv::Mat tmpA, depth;
|
||||
data.uncompressData(&tmpA, &depth);
|
||||
|
||||
if(!data.imageRaw().empty() && !data.depthRaw().empty())
|
||||
if(uContains(signatures, id))
|
||||
{
|
||||
// Voxelize and filter depending on the previous cloud?
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||
pcl::IndicesPtr indices(new std::vector<int>);
|
||||
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation_, maxCloudDepth_, minCloudDepth_, indices.get());
|
||||
if(cloud->size() && indices->size())
|
||||
{
|
||||
std::vector<pcl::Vertices> polygons;
|
||||
std::vector<pcl::Vertices> polygonsLowRes;
|
||||
if(main_scene_.isMeshRendering() && main_scene_.isMapRendering())
|
||||
{
|
||||
polygons = rtabmap::util3d::organizedFastMesh(cloud, meshAngleToleranceDeg_*M_PI/180.0, false, meshTrianglePix_);
|
||||
polygonsLowRes = rtabmap::util3d::organizedFastMesh(cloud, meshAngleToleranceDeg_*M_PI/180.0, false, meshTrianglePix_+LOW_RES_PIX);
|
||||
}
|
||||
UTimer timer;
|
||||
rtabmap::SensorData data = signatures.at(id).sensorData();
|
||||
|
||||
if((main_scene_.isMeshRendering() && polygons.size()) || !main_scene_.isMeshRendering() || !main_scene_.isMapRendering())
|
||||
cv::Mat tmpA, depth;
|
||||
data.uncompressData(&tmpA, &depth);
|
||||
if(!data.imageRaw().empty() && !data.depthRaw().empty())
|
||||
{
|
||||
// Voxelize and filter depending on the previous cloud?
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||
pcl::IndicesPtr indices(new std::vector<int>);
|
||||
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation_, maxCloudDepth_, minCloudDepth_, indices.get());
|
||||
if(cloud->size() && indices->size())
|
||||
{
|
||||
std::pair<std::map<int, Mesh>::iterator, bool> inserted = createdMeshes_.insert(std::make_pair(id, Mesh()));
|
||||
UASSERT(inserted.second);
|
||||
inserted.first->second.cloud = cloud;
|
||||
inserted.first->second.indices = indices;
|
||||
inserted.first->second.polygons = polygons;
|
||||
inserted.first->second.polygonsLowRes = polygonsLowRes;
|
||||
inserted.first->second.visible = true;
|
||||
inserted.first->second.cameraModel = data.cameraModels()[0];
|
||||
inserted.first->second.gains[0] = 1.0;
|
||||
inserted.first->second.gains[1] = 1.0;
|
||||
inserted.first->second.gains[2] = 1.0;
|
||||
if(main_scene_.isMeshTexturing() && main_scene_.isMapRendering())
|
||||
std::vector<pcl::Vertices> polygons;
|
||||
std::vector<pcl::Vertices> polygonsLowRes;
|
||||
if(main_scene_.isMeshRendering() && main_scene_.isMapRendering())
|
||||
{
|
||||
if(renderingTextureDecimation_>1)
|
||||
{
|
||||
cv::Size reducedSize(data.imageRaw().cols/renderingTextureDecimation_, data.imageRaw().rows/renderingTextureDecimation_);
|
||||
cv::resize(data.imageRaw(), inserted.first->second.texture, reducedSize, 0, 0, CV_INTER_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
inserted.first->second.texture = data.imageRaw();
|
||||
}
|
||||
polygons = rtabmap::util3d::organizedFastMesh(cloud, meshAngleToleranceDeg_*M_PI/180.0, false, meshTrianglePix_);
|
||||
polygonsLowRes = rtabmap::util3d::organizedFastMesh(cloud, meshAngleToleranceDeg_*M_PI/180.0, false, meshTrianglePix_+LOW_RES_PIX);
|
||||
}
|
||||
|
||||
if((main_scene_.isMeshRendering() && polygons.size()) || !main_scene_.isMeshRendering() || !main_scene_.isMapRendering())
|
||||
{
|
||||
std::pair<std::map<int, Mesh>::iterator, bool> inserted = createdMeshes_.insert(std::make_pair(id, Mesh()));
|
||||
UASSERT(inserted.second);
|
||||
inserted.first->second.cloud = cloud;
|
||||
inserted.first->second.indices = indices;
|
||||
inserted.first->second.polygons = polygons;
|
||||
inserted.first->second.polygonsLowRes = polygonsLowRes;
|
||||
inserted.first->second.visible = true;
|
||||
inserted.first->second.cameraModel = data.cameraModels()[0];
|
||||
inserted.first->second.gains[0] = 1.0;
|
||||
inserted.first->second.gains[1] = 1.0;
|
||||
inserted.first->second.gains[2] = 1.0;
|
||||
if(main_scene_.isMeshTexturing() && main_scene_.isMapRendering())
|
||||
{
|
||||
if(renderingTextureDecimation_>1)
|
||||
{
|
||||
cv::Size reducedSize(data.imageRaw().cols/renderingTextureDecimation_, data.imageRaw().rows/renderingTextureDecimation_);
|
||||
cv::resize(data.imageRaw(), inserted.first->second.texture, reducedSize, 0, 0, CV_INTER_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
inserted.first->second.texture = data.imageRaw();
|
||||
}
|
||||
}
|
||||
LOGI("Created cloud %d (%fs)", id, timer.ticks());
|
||||
}
|
||||
LOGI("Created cloud %d (%fs)", id, timer.ticks());
|
||||
}
|
||||
}
|
||||
}
|
||||
const rtabmap::Signature & s = signatures.at(id);
|
||||
processMemoryUsedBytes += data.imageCompressed().total();
|
||||
processMemoryUsedBytes += data.depthOrRightCompressed().total();
|
||||
processMemoryUsedBytes += data.laserScanCompressed().total();
|
||||
processMemoryUsedBytes += s.getWords().size()*4*8;
|
||||
processMemoryUsedBytes += s.getWords3().size()*4*4;
|
||||
if(!s.getWordsDescriptors().empty())
|
||||
{
|
||||
processMemoryUsedBytes +=s.getWordsDescriptors().size()*(4+s.getWordsDescriptors().begin()->second.total());
|
||||
else
|
||||
{
|
||||
UERROR("Failed to uncompress data!");
|
||||
status=-2;
|
||||
}
|
||||
const rtabmap::Signature & s = signatures.at(id);
|
||||
processMemoryUsedBytes += data.imageCompressed().total();
|
||||
processMemoryUsedBytes += data.depthOrRightCompressed().total();
|
||||
processMemoryUsedBytes += data.laserScanCompressed().total();
|
||||
processMemoryUsedBytes += s.getWords().size()*4*8;
|
||||
processMemoryUsedBytes += s.getWords3().size()*4*4;
|
||||
if(!s.getWordsDescriptors().empty())
|
||||
{
|
||||
processMemoryUsedBytes +=s.getWordsDescriptors().size()*(4+s.getWordsDescriptors().begin()->second.total());
|
||||
}
|
||||
}
|
||||
}
|
||||
++i;
|
||||
if(addTime.elapsed() >= 4.0f)
|
||||
{
|
||||
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, uFormat("Created clouds %d/%d", i, (int)poses.size())));
|
||||
addTime.restart();
|
||||
}
|
||||
}
|
||||
++i;
|
||||
if(addTime.elapsed() >= 4.0f)
|
||||
catch(const UException & e)
|
||||
{
|
||||
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, uFormat("Created clouds %d/%d", i, (int)poses.size())));
|
||||
addTime.restart();
|
||||
UERROR("Exception! msg=\"%s\"", e.what());
|
||||
status = -2;
|
||||
}
|
||||
catch (const cv::Exception & e)
|
||||
{
|
||||
UERROR("Exception! msg=\"%s\"", e.what());
|
||||
status = -2;
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
UERROR("Exception! msg=\"%s\"", e.what());
|
||||
status = -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(optimize)
|
||||
if(status < 0)
|
||||
{
|
||||
createdMeshes_.clear();
|
||||
}
|
||||
|
||||
if(optimize && status==0)
|
||||
{
|
||||
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Visual optimization..."));
|
||||
gainCompensation();
|
||||
@@ -1629,18 +1656,6 @@ void RTABMapApp::setGridVisible(bool visible)
|
||||
main_scene_.setGridVisible(visible);
|
||||
}
|
||||
|
||||
void RTABMapApp::setAutoExposure(bool enabled)
|
||||
{
|
||||
if(autoExposure_ != enabled)
|
||||
{
|
||||
autoExposure_ = enabled;
|
||||
if(camera_)
|
||||
{
|
||||
camera_->setAutoExposure(autoExposure_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RTABMapApp::setRawScanSaved(bool enabled)
|
||||
{
|
||||
if(rawScanSaved_ != enabled)
|
||||
@@ -2428,8 +2443,25 @@ bool RTABMapApp::exportMesh(
|
||||
}
|
||||
LOGI("Assembled clouds (%d)... done! %fs (total points=%d)", (int)cameraPoses.size(), timer.ticks(), (int)mergedClouds->size());
|
||||
|
||||
if(mergedClouds->size())
|
||||
if(mergedClouds->size()>=3)
|
||||
{
|
||||
if(optimizedDepth == 0)
|
||||
{
|
||||
Eigen::Vector4f min,max;
|
||||
pcl::getMinMax3D(*mergedClouds, min, max);
|
||||
float mapLength = uMax3(max[0]-min[0], max[1]-min[1], max[2]-min[2]);
|
||||
optimizedDepth = 12;
|
||||
for(int i=6; i<12; ++i)
|
||||
{
|
||||
if(mapLength/float(1<<i) < 0.03f)
|
||||
{
|
||||
optimizedDepth = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOGI("optimizedDepth=%d (map length=%f)", optimizedDepth, mapLength);
|
||||
}
|
||||
|
||||
// Mesh reconstruction
|
||||
LOGI("Mesh reconstruction...");
|
||||
pcl::PolygonMesh::Ptr mesh(new pcl::PolygonMesh);
|
||||
|
||||
@@ -127,7 +127,6 @@ class RTABMapApp : public UEventsHandler {
|
||||
void setNodesFiltering(bool enabled);
|
||||
void setGraphVisible(bool visible);
|
||||
void setGridVisible(bool visible);
|
||||
void setAutoExposure(bool enabled);
|
||||
void setRawScanSaved(bool enabled);
|
||||
void setCameraColor(bool enabled);
|
||||
void setFullResolution(bool enabled);
|
||||
@@ -192,7 +191,6 @@ class RTABMapApp : public UEventsHandler {
|
||||
bool nodesFiltering_;
|
||||
bool localizationMode_;
|
||||
bool trajectoryMode_;
|
||||
bool autoExposure_;
|
||||
bool rawScanSaved_;
|
||||
bool smoothing_;
|
||||
bool cameraColor_;
|
||||
|
||||
@@ -205,12 +205,6 @@ Java_com_introlab_rtabmap_RTABMapLib_setGridVisible(
|
||||
return app.setGridVisible(visible);
|
||||
}
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_introlab_rtabmap_RTABMapLib_setAutoExposure(
|
||||
JNIEnv*, jobject, bool enabled)
|
||||
{
|
||||
return app.setAutoExposure(enabled);
|
||||
}
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_introlab_rtabmap_RTABMapLib_setRawScanSaved(
|
||||
JNIEnv*, jobject, bool enabled)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "point_cloud_drawable.h"
|
||||
#include "rtabmap/utilite/ULogger.h"
|
||||
#include "rtabmap/utilite/UTimer.h"
|
||||
#include "rtabmap/utilite/UConversion.h"
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include "util.h"
|
||||
@@ -39,9 +40,264 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define LOW_DEC 2
|
||||
#define LOWLOW_DEC 4
|
||||
|
||||
enum PointCloudShaders
|
||||
{
|
||||
kPointCloud = 0,
|
||||
kPointCloudBlending = 1,
|
||||
kPointCloudLighting = 2,
|
||||
kPointCloudLightingBlending = 3,
|
||||
|
||||
kTexture = 4,
|
||||
kTextureBlending = 5,
|
||||
kTextureLighting = 6,
|
||||
kTextureLightingBlending = 7,
|
||||
|
||||
kDepthPacking = 8
|
||||
};
|
||||
|
||||
// PointCloud shaders
|
||||
const std::string kPointCloudVertexShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"attribute vec3 aVertex;\n"
|
||||
"attribute vec3 aColor;\n"
|
||||
|
||||
"uniform mat4 uMVP;\n"
|
||||
"uniform float uPointSize;\n"
|
||||
|
||||
"varying vec3 vColor;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
|
||||
"void main() {\n"
|
||||
" gl_Position = uMVP*vec4(aVertex.x, aVertex.y, aVertex.z, 1.0);\n"
|
||||
" gl_PointSize = uPointSize;\n"
|
||||
" vLightWeighting = 1.0;\n"
|
||||
" vColor = aColor;\n"
|
||||
"}\n";
|
||||
const std::string kPointCloudLightingVertexShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"attribute vec3 aVertex;\n"
|
||||
"attribute vec3 aNormal;\n"
|
||||
"attribute vec3 aColor;\n"
|
||||
|
||||
"uniform mat4 uMVP;\n"
|
||||
"uniform mat3 uN;\n"
|
||||
"uniform vec3 uLightingDirection;\n"
|
||||
"uniform float uPointSize;\n"
|
||||
|
||||
"varying vec3 vColor;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
|
||||
"void main() {\n"
|
||||
" gl_Position = uMVP*vec4(aVertex.x, aVertex.y, aVertex.z, 1.0);\n"
|
||||
" gl_PointSize = uPointSize;\n"
|
||||
" vec3 transformedNormal = uN * aNormal;\n"
|
||||
" vLightWeighting = max(dot(transformedNormal, uLightingDirection)*0.5+0.5, 0.0);\n"
|
||||
" if(vLightWeighting<0.5)"
|
||||
" vLightWeighting=0.5;\n"
|
||||
" vColor = aColor;\n"
|
||||
"}\n";
|
||||
|
||||
const std::string kPointCloudFragmentShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"uniform float uGainR;\n"
|
||||
"uniform float uGainG;\n"
|
||||
"uniform float uGainB;\n"
|
||||
"varying vec3 vColor;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
"void main() {\n"
|
||||
" vec4 textureColor = vec4(vColor.z, vColor.y, vColor.x, 1.0);\n"
|
||||
" gl_FragColor = vec4(textureColor.r * uGainR * vLightWeighting, textureColor.g * uGainG * vLightWeighting, textureColor.b * uGainB * vLightWeighting, textureColor.a);\n"
|
||||
"}\n";
|
||||
const std::string kPointCloudBlendingFragmentShader =
|
||||
"precision highp float;\n"
|
||||
"precision mediump int;\n"
|
||||
"uniform float uGainR;\n"
|
||||
"uniform float uGainG;\n"
|
||||
"uniform float uGainB;\n"
|
||||
"uniform float uNearZ;\n"
|
||||
"uniform float uFarZ;\n"
|
||||
"uniform sampler2D uDepthTexture;\n"
|
||||
"uniform vec2 uScreenScale;\n"
|
||||
"varying vec3 vColor;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
"void main() {\n"
|
||||
" vec4 textureColor = vec4(vColor.z, vColor.y, vColor.x, 1.0);\n"
|
||||
" float alpha = 1.0;\n"
|
||||
" vec2 coord = uScreenScale * gl_FragCoord.xy;\n;"
|
||||
" float depth = texture2D(uDepthTexture, coord).r;\n"
|
||||
" float num = (2.0 * uNearZ * uFarZ);\n"
|
||||
" float diff = (uFarZ - uNearZ);\n"
|
||||
" float add = (uFarZ + uNearZ);\n"
|
||||
" float ndcDepth = depth * 2.0 - 1.0;\n" // Back to NDC
|
||||
" float linearDepth = num / (add - ndcDepth * diff);\n" // inverse projection matrix
|
||||
" float ndcFragz = gl_FragCoord.z * 2.0 - 1.0;\n" // Back to NDC
|
||||
" float linearFragz = num / (add - ndcFragz * diff);\n" // inverse projection matrix
|
||||
" if(linearFragz > linearDepth + 0.05)\n"
|
||||
" alpha=0.0;\n"
|
||||
" gl_FragColor = vec4(textureColor.r * uGainR * vLightWeighting, textureColor.g * uGainG * vLightWeighting, textureColor.b * uGainB * vLightWeighting, alpha);\n"
|
||||
"}\n";
|
||||
|
||||
const std::string kPointCloudDepthPackingVertexShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"attribute vec3 aVertex;\n"
|
||||
"uniform mat4 uMVP;\n"
|
||||
"uniform float uPointSize;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = uMVP*vec4(aVertex.x, aVertex.y, aVertex.z, 1.0);\n"
|
||||
" gl_PointSize = uPointSize;\n"
|
||||
"}\n";
|
||||
const std::string kPointCloudDepthPackingFragmentShader =
|
||||
"precision highp float;\n"
|
||||
"precision mediump int;\n"
|
||||
"void main() {\n"
|
||||
" float toFixed = 255.0/256.0;\n"
|
||||
" vec4 enc = vec4(1.0, 255.0, 65025.0, 160581375.0) * toFixed * gl_FragCoord.z;\n"
|
||||
" enc = fract(enc);\n"
|
||||
" gl_FragColor = enc;\n"
|
||||
"}\n";
|
||||
|
||||
// Texture shaders
|
||||
const std::string kTextureMeshVertexShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"attribute vec3 aVertex;\n"
|
||||
"attribute vec2 aTexCoord;\n"
|
||||
|
||||
"uniform mat4 uMVP;\n"
|
||||
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
|
||||
"void main() {\n"
|
||||
" gl_Position = uMVP*vec4(aVertex.x, aVertex.y, aVertex.z, 1.0);\n"
|
||||
|
||||
" if(aTexCoord.x < 0.0) {\n"
|
||||
" vTexCoord.x = 1.0;\n"
|
||||
" vTexCoord.y = 1.0;\n" // bottom right corner
|
||||
" } else {\n"
|
||||
" vTexCoord = aTexCoord;\n"
|
||||
" }\n"
|
||||
|
||||
" vLightWeighting = 1.0;\n"
|
||||
"}\n";
|
||||
const std::string kTextureMeshLightingVertexShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"attribute vec3 aVertex;\n"
|
||||
"attribute vec3 aNormal;\n"
|
||||
"attribute vec2 aTexCoord;\n"
|
||||
|
||||
"uniform mat4 uMVP;\n"
|
||||
"uniform mat3 uN;\n"
|
||||
"uniform vec3 uLightingDirection;\n"
|
||||
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
|
||||
"void main() {\n"
|
||||
" gl_Position = uMVP*vec4(aVertex.x, aVertex.y, aVertex.z, 1.0);\n"
|
||||
|
||||
" if(aTexCoord.x < 0.0) {\n"
|
||||
" vTexCoord.x = 1.0;\n"
|
||||
" vTexCoord.y = 1.0;\n" // bottom right corner
|
||||
" } else {\n"
|
||||
" vTexCoord = aTexCoord;\n"
|
||||
" }\n"
|
||||
|
||||
" vec3 transformedNormal = uN * aNormal;\n"
|
||||
" vLightWeighting = max(dot(transformedNormal, uLightingDirection)*0.5+0.5, 0.0);\n"
|
||||
" if(vLightWeighting<0.5) \n"
|
||||
" vLightWeighting=0.5;\n"
|
||||
"}\n";
|
||||
const std::string kTextureMeshFragmentShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"uniform sampler2D uTexture;\n"
|
||||
"uniform float uGainR;\n"
|
||||
"uniform float uGainG;\n"
|
||||
"uniform float uGainB;\n"
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
""
|
||||
"void main() {\n"
|
||||
" vec4 textureColor = texture2D(uTexture, vTexCoord);\n"
|
||||
" gl_FragColor = vec4(textureColor.r * uGainR * vLightWeighting, textureColor.g * uGainG * vLightWeighting, textureColor.b * uGainB * vLightWeighting, textureColor.a);\n"
|
||||
"}\n";
|
||||
const std::string kTextureMeshBlendingFragmentShader =
|
||||
"precision highp float;\n"
|
||||
"precision mediump int;\n"
|
||||
"uniform sampler2D uTexture;\n"
|
||||
"uniform sampler2D uDepthTexture;\n"
|
||||
"uniform float uGainR;\n"
|
||||
"uniform float uGainG;\n"
|
||||
"uniform float uGainB;\n"
|
||||
"uniform vec2 uScreenScale;\n"
|
||||
"uniform float uNearZ;\n"
|
||||
"uniform float uFarZ;\n"
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
""
|
||||
"void main() {\n"
|
||||
" vec4 textureColor = texture2D(uTexture, vTexCoord);\n"
|
||||
" float alpha = 1.0;\n"
|
||||
" vec2 coord = uScreenScale * gl_FragCoord.xy;\n;"
|
||||
" float depth = texture2D(uDepthTexture, coord).r;\n"
|
||||
" float num = (2.0 * uNearZ * uFarZ);\n"
|
||||
" float diff = (uFarZ - uNearZ);\n"
|
||||
" float add = (uFarZ + uNearZ);\n"
|
||||
" float ndcDepth = depth * 2.0 - 1.0;\n" // Back to NDC
|
||||
" float linearDepth = num / (add - ndcDepth * diff);\n" // inverse projection matrix
|
||||
" float ndcFragz = gl_FragCoord.z * 2.0 - 1.0;\n" // Back to NDC
|
||||
" float linearFragz = num / (add - ndcFragz * diff);\n" // inverse projection matrix
|
||||
" if(linearFragz > linearDepth + 0.05)\n"
|
||||
" alpha=0.0;\n"
|
||||
" gl_FragColor = vec4(textureColor.r * uGainR * vLightWeighting, textureColor.g * uGainG * vLightWeighting, textureColor.b * uGainB * vLightWeighting, alpha);\n"
|
||||
"}\n";
|
||||
|
||||
std::vector<GLuint> PointCloudDrawable::shaderPrograms_;
|
||||
|
||||
void PointCloudDrawable::createShaderPrograms()
|
||||
{
|
||||
if(shaderPrograms_.empty())
|
||||
{
|
||||
shaderPrograms_.resize(9);
|
||||
|
||||
shaderPrograms_[kPointCloud] = tango_gl::util::CreateProgram(kPointCloudVertexShader.c_str(), kPointCloudFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kPointCloud] != 0);
|
||||
shaderPrograms_[kPointCloudBlending] = tango_gl::util::CreateProgram(kPointCloudVertexShader.c_str(), kPointCloudBlendingFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kPointCloudBlending] != 0);
|
||||
shaderPrograms_[kPointCloudLighting] = tango_gl::util::CreateProgram(kPointCloudLightingVertexShader.c_str(), kPointCloudFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kPointCloudLighting] != 0);
|
||||
shaderPrograms_[kPointCloudLightingBlending] = tango_gl::util::CreateProgram(kPointCloudLightingVertexShader.c_str(), kPointCloudBlendingFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kPointCloudLightingBlending] != 0);
|
||||
|
||||
shaderPrograms_[kTexture] = tango_gl::util::CreateProgram(kTextureMeshVertexShader.c_str(), kTextureMeshFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kTexture] != 0);
|
||||
shaderPrograms_[kTextureBlending] = tango_gl::util::CreateProgram(kTextureMeshVertexShader.c_str(), kTextureMeshBlendingFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kTextureBlending] != 0);
|
||||
shaderPrograms_[kTextureLighting] = tango_gl::util::CreateProgram(kTextureMeshLightingVertexShader.c_str(), kTextureMeshFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kTextureLighting] != 0);
|
||||
shaderPrograms_[kTextureLightingBlending] = tango_gl::util::CreateProgram(kTextureMeshLightingVertexShader.c_str(), kTextureMeshBlendingFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kTextureLightingBlending] != 0);
|
||||
|
||||
shaderPrograms_[kDepthPacking] = tango_gl::util::CreateProgram(kPointCloudDepthPackingVertexShader.c_str(), kPointCloudDepthPackingFragmentShader.c_str());
|
||||
UASSERT(shaderPrograms_[kDepthPacking] != 0);
|
||||
}
|
||||
}
|
||||
void PointCloudDrawable::releaseShaderPrograms()
|
||||
{
|
||||
for(unsigned int i=0; i<shaderPrograms_.size(); ++i)
|
||||
{
|
||||
glDeleteShader(shaderPrograms_[i]);
|
||||
}
|
||||
shaderPrograms_.clear();
|
||||
}
|
||||
|
||||
PointCloudDrawable::PointCloudDrawable(
|
||||
GLuint cloudShaderProgram,
|
||||
GLuint textureShaderProgram,
|
||||
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
||||
const pcl::IndicesPtr & indices,
|
||||
float gainR,
|
||||
@@ -54,8 +310,6 @@ PointCloudDrawable::PointCloudDrawable(
|
||||
poseGl_(1.0f),
|
||||
visible_(true),
|
||||
hasNormals_(false),
|
||||
cloud_shader_program_(cloudShaderProgram),
|
||||
texture_shader_program_(textureShaderProgram),
|
||||
gainR_(gainR),
|
||||
gainG_(gainG),
|
||||
gainB_(gainB)
|
||||
@@ -64,8 +318,6 @@ PointCloudDrawable::PointCloudDrawable(
|
||||
}
|
||||
|
||||
PointCloudDrawable::PointCloudDrawable(
|
||||
GLuint cloudShaderProgram,
|
||||
GLuint textureShaderProgram,
|
||||
const Mesh & mesh) :
|
||||
vertex_buffers_(0),
|
||||
textures_(0),
|
||||
@@ -74,8 +326,6 @@ PointCloudDrawable::PointCloudDrawable(
|
||||
poseGl_(1.0f),
|
||||
visible_(true),
|
||||
hasNormals_(false),
|
||||
cloud_shader_program_(cloudShaderProgram),
|
||||
texture_shader_program_(textureShaderProgram),
|
||||
gainR_(1.0f),
|
||||
gainG_(1.0f),
|
||||
gainB_(1.0f)
|
||||
@@ -321,9 +571,8 @@ void PointCloudDrawable::updateMesh(const Mesh & mesh)
|
||||
int oi_lowlow = 0;
|
||||
if(textures_ && polygons.size())
|
||||
{
|
||||
//LOGD("Organized mesh with texture");
|
||||
int items = hasNormals_?9:6;
|
||||
vertices = std::vector<float>(mesh.indices->size()*9);
|
||||
vertices = std::vector<float>(mesh.indices->size()*items);
|
||||
for(unsigned int i=0; i<mesh.indices->size(); ++i)
|
||||
{
|
||||
const pcl::PointXYZRGB & pt = mesh.cloud->at(mesh.indices->at(i));
|
||||
@@ -401,7 +650,6 @@ void PointCloudDrawable::updateMesh(const Mesh & mesh)
|
||||
}
|
||||
else // assume dense mesh with texCoords set to polygons
|
||||
{
|
||||
totalPoints = mesh.cloud->size();
|
||||
if(textures_ && polygons.size() && mesh.normals->size())
|
||||
{
|
||||
//LOGD("Dense mesh with texture (%d texCoords %d points %d polygons %dx%d)",
|
||||
@@ -411,8 +659,9 @@ void PointCloudDrawable::updateMesh(const Mesh & mesh)
|
||||
// tex_coordinates should be linked to points, not
|
||||
// polygon vertices. Points linked to multiple different texCoords (different textures) should
|
||||
// be duplicated.
|
||||
totalPoints = mesh.texCoords.size();
|
||||
vertices = std::vector<float>(mesh.texCoords.size()*9);
|
||||
organizedToDenseIndices_ = std::vector<unsigned int>(mesh.texCoords.size(), -1);
|
||||
organizedToDenseIndices_ = std::vector<unsigned int>(totalPoints, -1);
|
||||
|
||||
UASSERT_MSG(mesh.texCoords.size() == polygons[0].vertices.size()*polygons.size(),
|
||||
uFormat("%d vs %d x %d", (int)mesh.texCoords.size(), (int)polygons[0].vertices.size(), (int)polygons.size()).c_str());
|
||||
@@ -468,9 +717,10 @@ void PointCloudDrawable::updateMesh(const Mesh & mesh)
|
||||
}
|
||||
else
|
||||
{
|
||||
totalPoints = mesh.cloud->size();
|
||||
//LOGD("Dense mesh");
|
||||
int items = hasNormals_?7:4;
|
||||
organizedToDenseIndices_ = std::vector<unsigned int>(mesh.cloud->size(), -1);
|
||||
organizedToDenseIndices_ = std::vector<unsigned int>(totalPoints, -1);
|
||||
vertices = std::vector<float>(mesh.cloud->size()*items);
|
||||
for(unsigned int i=0; i<mesh.cloud->size(); ++i)
|
||||
{
|
||||
@@ -594,7 +844,8 @@ void PointCloudDrawable::updateAABBWorld(const rtabmap::Transform & pose)
|
||||
}
|
||||
|
||||
|
||||
void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix,
|
||||
void PointCloudDrawable::Render(
|
||||
const glm::mat4 & projectionMatrix,
|
||||
const glm::mat4 & viewMatrix,
|
||||
bool meshRendering,
|
||||
float pointSize,
|
||||
@@ -604,94 +855,171 @@ void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix,
|
||||
const GLuint & depthTexture,
|
||||
int screenWidth,
|
||||
int screenHeight,
|
||||
bool packDepthToColorChannel) {
|
||||
|
||||
if(vertex_buffers_ && nPoints_ && visible_)
|
||||
float nearClipPlane,
|
||||
float farClipPlane,
|
||||
bool packDepthToColorChannel) const
|
||||
{
|
||||
if(vertex_buffers_ && nPoints_ && visible_ && !shaderPrograms_.empty())
|
||||
{
|
||||
if(meshRendering && textureRendering && textures_ && (verticesLowRes_.empty() || distanceToCameraSqr<50.0f))
|
||||
if(packDepthToColorChannel || !hasNormals_)
|
||||
{
|
||||
glUseProgram(texture_shader_program_);
|
||||
lighting = false;
|
||||
}
|
||||
|
||||
GLuint mvp_handle = glGetUniformLocation(texture_shader_program_, "uMVP");
|
||||
glm::mat4 mv_mat = viewMatrix * poseGl_;
|
||||
glm::mat4 mvp_mat = projectionMatrix * mv_mat;
|
||||
glUniformMatrix4fv(mvp_handle, 1, GL_FALSE, glm::value_ptr(mvp_mat));
|
||||
|
||||
GLuint n_handle = glGetUniformLocation(texture_shader_program_, "uN");
|
||||
glm::mat3 normalMatrix(mv_mat);
|
||||
normalMatrix = glm::inverse(normalMatrix);
|
||||
normalMatrix = glm::transpose(normalMatrix);
|
||||
glUniformMatrix3fv(n_handle, 1, GL_FALSE, glm::value_ptr(normalMatrix));
|
||||
|
||||
if(!hasNormals_)
|
||||
{
|
||||
lighting = false;
|
||||
}
|
||||
|
||||
//lighting
|
||||
GLuint lighting_handle = glGetUniformLocation(texture_shader_program_, "uUseLighting");
|
||||
glUniform1i(lighting_handle, lighting?1:0);
|
||||
if(packDepthToColorChannel || !(meshRendering && textureRendering && textures_))
|
||||
{
|
||||
textureRendering = false;
|
||||
}
|
||||
|
||||
GLuint program;
|
||||
if(packDepthToColorChannel)
|
||||
{
|
||||
program = shaderPrograms_[kDepthPacking];
|
||||
}
|
||||
else if(textureRendering)
|
||||
{
|
||||
if(lighting)
|
||||
{
|
||||
GLuint ambiant_handle = glGetUniformLocation(texture_shader_program_, "uAmbientColor");
|
||||
glUniform3f(ambiant_handle,0.6,0.6,0.6);
|
||||
|
||||
GLuint lightingDirection_handle = glGetUniformLocation(texture_shader_program_, "uLightingDirection");
|
||||
glUniform3f(lightingDirection_handle, 0.0, 0.0, 1.0); // from the camera
|
||||
program = shaderPrograms_[depthTexture>0?kTextureLightingBlending:kTextureLighting];
|
||||
}
|
||||
else
|
||||
{
|
||||
program = shaderPrograms_[depthTexture>0?kTextureBlending:kTexture];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lighting)
|
||||
{
|
||||
program = shaderPrograms_[depthTexture>0?kPointCloudLightingBlending:kPointCloudLighting];
|
||||
}
|
||||
else
|
||||
{
|
||||
program = shaderPrograms_[depthTexture>0?kPointCloudBlending:kPointCloud];
|
||||
}
|
||||
}
|
||||
|
||||
// Texture activate unit 0
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
// Bind the texture to this unit.
|
||||
glBindTexture(GL_TEXTURE_2D, textures_);
|
||||
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
|
||||
GLuint texture_handle = glGetUniformLocation(texture_shader_program_, "uTexture");
|
||||
glUniform1i(texture_handle, 0);
|
||||
glUseProgram(program);
|
||||
tango_gl::util::CheckGlError("Pointcloud::Render() set program");
|
||||
|
||||
// Texture activate unit 1
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
// Bind the texture to this unit.
|
||||
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 1.
|
||||
GLuint depth_texture_handle = glGetUniformLocation(texture_shader_program_, "uDepthTexture");
|
||||
glUniform1i(depth_texture_handle, 1);
|
||||
GLuint mvp_handle = glGetUniformLocation(program, "uMVP");
|
||||
glm::mat4 mv_mat = viewMatrix * poseGl_;
|
||||
glm::mat4 mvp_mat = projectionMatrix * mv_mat;
|
||||
glUniformMatrix4fv(mvp_handle, 1, GL_FALSE, glm::value_ptr(mvp_mat));
|
||||
|
||||
GLuint gainR_handle = glGetUniformLocation(texture_shader_program_, "uGainR");
|
||||
GLuint gainG_handle = glGetUniformLocation(texture_shader_program_, "uGainG");
|
||||
GLuint gainB_handle = glGetUniformLocation(texture_shader_program_, "uGainB");
|
||||
GLint attribute_vertex = glGetAttribLocation(program, "aVertex");
|
||||
glEnableVertexAttribArray(attribute_vertex);
|
||||
GLint attribute_color = 0;
|
||||
GLint attribute_texture = 0;
|
||||
GLint attribute_normal = 0;
|
||||
|
||||
if(packDepthToColorChannel || !textureRendering)
|
||||
{
|
||||
GLuint point_size_handle_ = glGetUniformLocation(program, "uPointSize");
|
||||
glUniform1f(point_size_handle_, pointSize);
|
||||
}
|
||||
tango_gl::util::CheckGlError("Pointcloud::Render() vertex");
|
||||
|
||||
if(!packDepthToColorChannel)
|
||||
{
|
||||
GLuint gainR_handle = glGetUniformLocation(program, "uGainR");
|
||||
GLuint gainG_handle = glGetUniformLocation(program, "uGainG");
|
||||
GLuint gainB_handle = glGetUniformLocation(program, "uGainB");
|
||||
glUniform1f(gainR_handle, gainR_);
|
||||
glUniform1f(gainG_handle, gainG_);
|
||||
glUniform1f(gainB_handle, gainB_);
|
||||
|
||||
GLuint blending_handle = glGetUniformLocation(texture_shader_program_, "uBlending");
|
||||
glUniform1i(blending_handle, depthTexture>0?1:0);
|
||||
|
||||
GLuint screenScale_handle = glGetUniformLocation(texture_shader_program_, "uScreenScale");
|
||||
glUniform2f(screenScale_handle, 1.0f/(float)screenWidth, 1.0f/(float)screenHeight);
|
||||
|
||||
GLint attribute_vertex = glGetAttribLocation(texture_shader_program_, "aVertex");
|
||||
GLint attribute_texture = glGetAttribLocation(texture_shader_program_, "aTexCoord");
|
||||
GLint attribute_normal=0;
|
||||
if(hasNormals_)
|
||||
// blending
|
||||
if(depthTexture > 0)
|
||||
{
|
||||
attribute_normal = glGetAttribLocation(texture_shader_program_, "aNormal");
|
||||
// Texture activate unit 1
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
// Bind the texture to this unit.
|
||||
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 1.
|
||||
GLuint depth_texture_handle = glGetUniformLocation(program, "uDepthTexture");
|
||||
glUniform1i(depth_texture_handle, 1);
|
||||
|
||||
GLuint zNear_handle = glGetUniformLocation(program, "uNearZ");
|
||||
GLuint zFar_handle = glGetUniformLocation(program, "uFarZ");
|
||||
glUniform1f(zNear_handle, nearClipPlane);
|
||||
glUniform1f(zFar_handle, farClipPlane);
|
||||
|
||||
GLuint screenScale_handle = glGetUniformLocation(program, "uScreenScale");
|
||||
glUniform2f(screenScale_handle, 1.0f/(float)screenWidth, 1.0f/(float)screenHeight);
|
||||
}
|
||||
|
||||
glEnableVertexAttribArray(attribute_vertex);
|
||||
glEnableVertexAttribArray(attribute_texture);
|
||||
if(hasNormals_)
|
||||
if(lighting)
|
||||
{
|
||||
GLuint n_handle = glGetUniformLocation(program, "uN");
|
||||
glm::mat3 normalMatrix(mv_mat);
|
||||
normalMatrix = glm::inverse(normalMatrix);
|
||||
normalMatrix = glm::transpose(normalMatrix);
|
||||
glUniformMatrix3fv(n_handle, 1, GL_FALSE, glm::value_ptr(normalMatrix));
|
||||
|
||||
GLuint lightingDirection_handle = glGetUniformLocation(program, "uLightingDirection");
|
||||
glUniform3f(lightingDirection_handle, 0.0, 0.0, 1.0); // from the camera
|
||||
|
||||
attribute_normal = glGetAttribLocation(program, "aNormal");
|
||||
glEnableVertexAttribArray(attribute_normal);
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
|
||||
|
||||
if(textureRendering)
|
||||
{
|
||||
// Texture activate unit 0
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
// Bind the texture to this unit.
|
||||
glBindTexture(GL_TEXTURE_2D, textures_);
|
||||
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
|
||||
GLuint texture_handle = glGetUniformLocation(program, "uTexture");
|
||||
glUniform1i(texture_handle, 0);
|
||||
|
||||
attribute_texture = glGetAttribLocation(program, "aTexCoord");
|
||||
glEnableVertexAttribArray(attribute_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
attribute_color = glGetAttribLocation(program, "aColor");
|
||||
glEnableVertexAttribArray(attribute_color);
|
||||
}
|
||||
}
|
||||
tango_gl::util::CheckGlError("Pointcloud::Render() common");
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
|
||||
if(textures_)
|
||||
{
|
||||
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, (hasNormals_?9:6)*sizeof(GLfloat), 0);
|
||||
glVertexAttribPointer(attribute_texture, 2, GL_FLOAT, GL_FALSE, (hasNormals_?9:6)*sizeof(GLfloat), (GLvoid*) (4 * sizeof(GLfloat)));
|
||||
if(hasNormals_)
|
||||
if(textureRendering)
|
||||
{
|
||||
glVertexAttribPointer(attribute_texture, 2, GL_FLOAT, GL_FALSE, (hasNormals_?9:6)*sizeof(GLfloat), (GLvoid*) (4 * sizeof(GLfloat)));
|
||||
}
|
||||
else if(!packDepthToColorChannel)
|
||||
{
|
||||
glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, (hasNormals_?9:6)*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));
|
||||
}
|
||||
if(lighting && hasNormals_)
|
||||
{
|
||||
glVertexAttribPointer(attribute_normal, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), (GLvoid*) (6 * sizeof(GLfloat)));
|
||||
}
|
||||
if(distanceToCameraSqr<150.0f || polygonsLowRes_.empty())
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, (hasNormals_?7:4)*sizeof(GLfloat), 0);
|
||||
if(!packDepthToColorChannel)
|
||||
{
|
||||
glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, (hasNormals_?7:4)*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));
|
||||
}
|
||||
if(lighting && hasNormals_)
|
||||
{
|
||||
glVertexAttribPointer(attribute_normal, 3, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (GLvoid*) (4 * sizeof(GLfloat)));
|
||||
}
|
||||
}
|
||||
tango_gl::util::CheckGlError("Pointcloud::Render() set attribute pointer");
|
||||
|
||||
UTimer drawTime;
|
||||
if(textureRendering)
|
||||
{
|
||||
if(distanceToCameraSqr<16.0f || polygonsLowRes_.empty())
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_INT, polygons_.data());
|
||||
}
|
||||
@@ -700,135 +1028,44 @@ void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix,
|
||||
glDrawElements(GL_TRIANGLES, polygonsLowRes_.size(), GL_UNSIGNED_INT, polygonsLowRes_.data());
|
||||
}
|
||||
}
|
||||
else // point cloud or colored mesh
|
||||
else if(meshRendering && polygons_.size())
|
||||
{
|
||||
glUseProgram(cloud_shader_program_);
|
||||
|
||||
GLuint mvp_handle_ = glGetUniformLocation(cloud_shader_program_, "uMVP");
|
||||
glm::mat4 mv_mat = viewMatrix * poseGl_;
|
||||
glm::mat4 mvp_mat = projectionMatrix * mv_mat;
|
||||
glUniformMatrix4fv(mvp_handle_, 1, GL_FALSE, glm::value_ptr(mvp_mat));
|
||||
|
||||
GLuint n_handle = glGetUniformLocation(cloud_shader_program_, "uN");
|
||||
glm::mat3 normalMatrix(mv_mat);
|
||||
normalMatrix = glm::inverse(normalMatrix);
|
||||
normalMatrix = glm::transpose(normalMatrix);
|
||||
glUniformMatrix3fv(n_handle, 1, GL_FALSE, glm::value_ptr(normalMatrix));
|
||||
|
||||
if(!hasNormals_)
|
||||
if(distanceToCameraSqr<50.0f || polygonsLowRes_.empty())
|
||||
{
|
||||
lighting = false;
|
||||
}
|
||||
|
||||
//lighting
|
||||
GLuint lighting_handle = glGetUniformLocation(cloud_shader_program_, "uUseLighting");
|
||||
glUniform1i(lighting_handle, lighting?1:0);
|
||||
|
||||
if(lighting)
|
||||
{
|
||||
GLuint ambiant_handle = glGetUniformLocation(cloud_shader_program_, "uAmbientColor");
|
||||
glUniform3f(ambiant_handle,0.6,0.6,0.6);
|
||||
|
||||
GLuint lightingDirection_handle = glGetUniformLocation(cloud_shader_program_, "uLightingDirection");
|
||||
glUniform3f(lightingDirection_handle, 0.0, 0.0, 1.0); // from the camera
|
||||
}
|
||||
|
||||
GLuint point_size_handle_ = glGetUniformLocation(cloud_shader_program_, "uPointSize");
|
||||
glUniform1f(point_size_handle_, pointSize);
|
||||
|
||||
// Texture activate unit 1
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
// Bind the texture to this unit.
|
||||
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 1.
|
||||
GLuint depth_texture_handle = glGetUniformLocation(cloud_shader_program_, "uDepthTexture");
|
||||
glUniform1i(depth_texture_handle, 0);
|
||||
|
||||
GLuint gainR_handle = glGetUniformLocation(cloud_shader_program_, "uGainR");
|
||||
GLuint gainG_handle = glGetUniformLocation(cloud_shader_program_, "uGainG");
|
||||
GLuint gainB_handle = glGetUniformLocation(cloud_shader_program_, "uGainB");
|
||||
glUniform1f(gainR_handle, gainR_);
|
||||
glUniform1f(gainG_handle, gainG_);
|
||||
glUniform1f(gainB_handle, gainB_);
|
||||
|
||||
GLuint packing_handle = glGetUniformLocation(cloud_shader_program_, "uPackDepthToColor");
|
||||
glUniform1i(packing_handle, packDepthToColorChannel?1:0);
|
||||
|
||||
GLuint blending_handle = glGetUniformLocation(cloud_shader_program_, "uBlending");
|
||||
glUniform1i(blending_handle, depthTexture>0?1:0);
|
||||
|
||||
GLuint screenScale_handle = glGetUniformLocation(cloud_shader_program_, "uScreenScale");
|
||||
glUniform2f(screenScale_handle, 1.0f/(float)screenWidth, 1.0f/(float)screenHeight);
|
||||
|
||||
GLint attribute_vertex = glGetAttribLocation(cloud_shader_program_, "aVertex");
|
||||
GLint attribute_color = glGetAttribLocation(cloud_shader_program_, "aColor");
|
||||
GLint attribute_normal=0;
|
||||
if(hasNormals_)
|
||||
{
|
||||
attribute_normal = glGetAttribLocation(cloud_shader_program_, "aNormal");
|
||||
}
|
||||
|
||||
glEnableVertexAttribArray(attribute_vertex);
|
||||
glEnableVertexAttribArray(attribute_color);
|
||||
if(hasNormals_)
|
||||
{
|
||||
glEnableVertexAttribArray(attribute_normal);
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
|
||||
if(textures_)
|
||||
{
|
||||
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, (hasNormals_?9:6)*sizeof(GLfloat), 0);
|
||||
glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, (hasNormals_?9:6)*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));
|
||||
if(hasNormals_)
|
||||
{
|
||||
glVertexAttribPointer(attribute_normal, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), (GLvoid*) (6 * sizeof(GLfloat)));
|
||||
}
|
||||
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_INT, polygons_.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, (hasNormals_?7:4)*sizeof(GLfloat), 0);
|
||||
glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, (hasNormals_?7:4)*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));
|
||||
if(hasNormals_)
|
||||
{
|
||||
glVertexAttribPointer(attribute_normal, 3, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (GLvoid*) (4 * sizeof(GLfloat)));
|
||||
}
|
||||
glDrawElements(GL_TRIANGLES, polygonsLowRes_.size(), GL_UNSIGNED_INT, polygonsLowRes_.data());
|
||||
}
|
||||
if(meshRendering && polygons_.size())
|
||||
}
|
||||
else if(!verticesLowRes_.empty())
|
||||
{
|
||||
if(distanceToCameraSqr>600.0f)
|
||||
{
|
||||
if(distanceToCameraSqr<150.0f || polygonsLowRes_.empty())
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_INT, polygons_.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, polygonsLowRes_.size(), GL_UNSIGNED_INT, polygonsLowRes_.data());
|
||||
}
|
||||
glDrawElements(GL_POINTS, verticesLowLowRes_.size(), GL_UNSIGNED_INT, verticesLowLowRes_.data());
|
||||
}
|
||||
else if(!verticesLowRes_.empty())
|
||||
else if(distanceToCameraSqr>150.0f)
|
||||
{
|
||||
if(distanceToCameraSqr>600.0f)
|
||||
{
|
||||
glDrawElements(GL_POINTS, verticesLowLowRes_.size(), GL_UNSIGNED_INT, verticesLowLowRes_.data());
|
||||
}
|
||||
else if(distanceToCameraSqr>150.0f)
|
||||
{
|
||||
glDrawElements(GL_POINTS, verticesLowRes_.size(), GL_UNSIGNED_INT, verticesLowRes_.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
glDrawArrays(GL_POINTS, 0, nPoints_);
|
||||
}
|
||||
glDrawElements(GL_POINTS, verticesLowRes_.size(), GL_UNSIGNED_INT, verticesLowRes_.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
glDrawArrays(GL_POINTS, 0, nPoints_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glDrawArrays(GL_POINTS, 0, nPoints_);
|
||||
}
|
||||
//UERROR("drawTime=%fs", drawTime.ticks());
|
||||
tango_gl::util::CheckGlError("Pointcloud::Render() draw");
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glUseProgram(0);
|
||||
tango_gl::util::CheckGlError("Pointcloud::Render()");
|
||||
tango_gl::util::CheckGlError("Pointcloud::Render() cleaning");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,18 +40,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// PointCloudDrawable is responsible for the point cloud rendering.
|
||||
class PointCloudDrawable {
|
||||
public:
|
||||
static void createShaderPrograms();
|
||||
static void releaseShaderPrograms();
|
||||
|
||||
private:
|
||||
static std::vector<GLuint> shaderPrograms_;
|
||||
|
||||
public:
|
||||
PointCloudDrawable(
|
||||
GLuint cloudShaderProgram,
|
||||
GLuint textureShaderProgram,
|
||||
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
||||
const pcl::IndicesPtr & indices,
|
||||
float gainR = 1.0f,
|
||||
float gainG = 1.0f,
|
||||
float gainB = 1.0f);
|
||||
PointCloudDrawable(
|
||||
GLuint cloudShaderProgram,
|
||||
GLuint textureShaderProgram,
|
||||
const Mesh & mesh);
|
||||
virtual ~PointCloudDrawable();
|
||||
|
||||
@@ -77,7 +80,8 @@ class PointCloudDrawable {
|
||||
// @param view_mat: view matrix from current render camera.
|
||||
// @param model_mat: model matrix for this point cloud frame.
|
||||
// @param vertices: all vertices in this point cloud frame.
|
||||
void Render(const glm::mat4 & projectionMatrix,
|
||||
void Render(
|
||||
const glm::mat4 & projectionMatrix,
|
||||
const glm::mat4 & viewMatrix,
|
||||
bool meshRendering = true,
|
||||
float pointSize = 3.0f,
|
||||
@@ -85,9 +89,11 @@ class PointCloudDrawable {
|
||||
bool lighting = true,
|
||||
float distanceToCamSqr = 0.0f,
|
||||
const GLuint & depthTexture = 0,
|
||||
int screenWidth = 0,
|
||||
int screenHeight = 0,
|
||||
bool packDepthToColorChannel = false);
|
||||
int screenWidth = 0, // nonnull if depthTexture>0
|
||||
int screenHeight = 0, // nonnull if depthTexture>0
|
||||
float nearClipPlane = 0, // nonnull if depthTexture>0
|
||||
float farClipPlane = 0, // nonnull if depthTexture>0
|
||||
bool packDepthToColorChannel = false) const;
|
||||
|
||||
private:
|
||||
template<class PointT>
|
||||
@@ -117,9 +123,6 @@ class PointCloudDrawable {
|
||||
bool hasNormals_;
|
||||
std::vector<unsigned int> organizedToDenseIndices_;
|
||||
|
||||
GLuint cloud_shader_program_;
|
||||
GLuint texture_shader_program_;
|
||||
|
||||
float gainR_;
|
||||
float gainG_;
|
||||
float gainB_;
|
||||
|
||||
@@ -43,141 +43,6 @@ const tango_gl::Color kGridColor(0.85f, 0.85f, 0.85f);
|
||||
// Frustum scale.
|
||||
const glm::vec3 kFrustumScale = glm::vec3(0.4f, 0.3f, 0.5f);
|
||||
|
||||
const std::string kPointCloudVertexShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"attribute vec3 aVertex;\n"
|
||||
"attribute vec3 aNormal;\n"
|
||||
"attribute vec3 aColor;\n"
|
||||
|
||||
"uniform mat4 uMVP;\n"
|
||||
"uniform mat3 uN;\n"
|
||||
"uniform vec3 uAmbientColor;\n"
|
||||
"uniform vec3 uLightingDirection;\n"
|
||||
"uniform bool uUseLighting;\n"
|
||||
|
||||
"uniform float uPointSize;\n"
|
||||
"varying vec3 vColor;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
|
||||
"void main() {\n"
|
||||
" gl_Position = uMVP*vec4(aVertex.x, aVertex.y, aVertex.z, 1.0);\n"
|
||||
" gl_PointSize = uPointSize;\n"
|
||||
" if (!uUseLighting) {\n"
|
||||
" vLightWeighting = 1.0;\n"
|
||||
" } else {\n"
|
||||
" vec3 transformedNormal = uN * aNormal;\n"
|
||||
" vLightWeighting = max(dot(transformedNormal, uLightingDirection)*0.5+0.5, 0.0);\n"
|
||||
" if(vLightWeighting<0.5) vLightWeighting=0.5;\n"
|
||||
" }\n"
|
||||
" vColor = aColor;\n"
|
||||
"}\n";
|
||||
const std::string kPointCloudFragmentShader =
|
||||
"precision highp float;\n"
|
||||
"precision mediump int;\n"
|
||||
"uniform float uGainR;\n"
|
||||
"uniform float uGainG;\n"
|
||||
"uniform float uGainB;\n"
|
||||
"uniform sampler2D uDepthTexture;\n"
|
||||
"uniform bool uBlending;\n"
|
||||
"uniform vec2 uScreenScale;\n"
|
||||
"uniform bool uPackDepthToColor;\n"
|
||||
"varying vec3 vColor;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
"void main() {\n"
|
||||
" vec4 textureColor = vec4(vColor.z, vColor.y, vColor.x, 1.0);\n"
|
||||
" float alpha = 1.0;\n"
|
||||
" if(uBlending) {\n"
|
||||
" vec2 coord = uScreenScale * gl_FragCoord.xy;\n;"
|
||||
" float depth = texture2D(uDepthTexture, coord).r;\n"
|
||||
// " alpha = 0.5;\n"
|
||||
" float zNear = 0.2;\n"
|
||||
" float zFar = 1000.0;\n"
|
||||
" float ndcDepth = depth * 2.0 - 1.0;\n" // Back to NDC
|
||||
" float linearDepth = (2.0 * zNear * zFar) / (zFar + zNear - ndcDepth * (zFar - zNear));\n"
|
||||
" float ndcFragz = gl_FragCoord.z * 2.0 - 1.0;\n" // Back to NDC
|
||||
" float linearFragz = (2.0 * zNear * zFar) / (zFar + zNear - ndcFragz * (zFar - zNear));\n"
|
||||
" if(linearFragz > linearDepth + 0.05)\n"
|
||||
" alpha=0.0;\n"
|
||||
" }\n"
|
||||
" if(uPackDepthToColor) {\n"
|
||||
" float toFixed = 255.0/256.0;\n"
|
||||
" vec4 enc = vec4(1.0, 255.0, 65025.0, 160581375.0) * toFixed * gl_FragCoord.z;\n"
|
||||
" enc = fract(enc);\n"
|
||||
" gl_FragColor = enc;\n"
|
||||
" }\n"
|
||||
" else {"
|
||||
" gl_FragColor = vec4(textureColor.r * uGainR * vLightWeighting, textureColor.g * uGainG * vLightWeighting, textureColor.b * uGainB * vLightWeighting, alpha);\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const std::string kTextureMeshVertexShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
"attribute vec3 aVertex;\n"
|
||||
"attribute vec3 aNormal;\n"
|
||||
"attribute vec2 aTexCoord;\n"
|
||||
|
||||
"uniform mat4 uMVP;\n"
|
||||
"uniform mat3 uN;\n"
|
||||
"uniform vec3 uAmbientColor;\n"
|
||||
"uniform vec3 uLightingDirection;\n"
|
||||
"uniform bool uUseLighting;\n"
|
||||
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
|
||||
"void main() {\n"
|
||||
" gl_Position = uMVP*vec4(aVertex.x, aVertex.y, aVertex.z, 1.0);\n"
|
||||
|
||||
" if(aTexCoord.x < 0.0) {\n"
|
||||
" vTexCoord.x = 1.0;\n"
|
||||
" vTexCoord.y = 1.0;\n" // bottom right corner
|
||||
" } else {\n"
|
||||
" vTexCoord = aTexCoord;\n"
|
||||
" }\n"
|
||||
|
||||
" if (!uUseLighting) {\n"
|
||||
" vLightWeighting = 1.0;\n"
|
||||
" } else {\n"
|
||||
" vec3 transformedNormal = uN * aNormal;\n"
|
||||
" vLightWeighting = max(dot(transformedNormal, uLightingDirection)*0.5+0.5, 0.0);\n"
|
||||
" if(vLightWeighting<0.5) vLightWeighting=0.5;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
const std::string kTextureMeshFragmentShader =
|
||||
"precision highp float;\n"
|
||||
"precision mediump int;\n"
|
||||
"uniform sampler2D uTexture;\n"
|
||||
"uniform sampler2D uDepthTexture;\n"
|
||||
"uniform float uGainR;\n"
|
||||
"uniform float uGainG;\n"
|
||||
"uniform float uGainB;\n"
|
||||
"uniform bool uBlending;\n"
|
||||
"uniform vec2 uScreenScale;\n"
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"varying float vLightWeighting;\n"
|
||||
""
|
||||
"void main() {\n"
|
||||
" vec4 textureColor = texture2D(uTexture, vTexCoord);\n"
|
||||
" float alpha = 1.0;\n"
|
||||
" if(uBlending) {\n"
|
||||
" vec2 coord = uScreenScale * gl_FragCoord.xy;\n;"
|
||||
" float depth = texture2D(uDepthTexture, coord).r;\n"
|
||||
// " alpha = 0.5;\n"
|
||||
//Linearize depth: http://stackoverflow.com/questions/6652253/getting-the-true-z-value-from-the-depth-buffer
|
||||
" float zNear = 0.2;\n"
|
||||
" float zFar = 1000.0;\n"
|
||||
" float ndcDepth = depth * 2.0 - 1.0;\n" // Back to NDC
|
||||
" float linearDepth = (2.0 * zNear * zFar) / (zFar + zNear - ndcDepth * (zFar - zNear));\n"
|
||||
" float ndcFragz = gl_FragCoord.z * 2.0 - 1.0;\n" // Back to NDC
|
||||
" float linearFragz = (2.0 * zNear * zFar) / (zFar + zNear - ndcFragz * (zFar - zNear));\n"
|
||||
" if(linearFragz > linearDepth + 0.05)\n"
|
||||
" alpha=0.0;\n"
|
||||
" }\n"
|
||||
" gl_FragColor = vec4(textureColor.r * uGainR * vLightWeighting, textureColor.g * uGainG * vLightWeighting, textureColor.b * uGainB * vLightWeighting, alpha);\n"
|
||||
"}\n";
|
||||
|
||||
const std::string kGraphVertexShader =
|
||||
"precision mediump float;\n"
|
||||
"precision mediump int;\n"
|
||||
@@ -212,8 +77,6 @@ Scene::Scene() :
|
||||
traceVisible_(true),
|
||||
color_camera_to_display_rotation_(ROTATION_0),
|
||||
currentPose_(0),
|
||||
cloud_shader_program_(0),
|
||||
texture_mesh_shader_program_(0),
|
||||
graph_shader_program_(0),
|
||||
blending_(true),
|
||||
mapRendering_(true),
|
||||
@@ -253,38 +116,30 @@ void Scene::InitGLContent()
|
||||
UASSERT(axis_ == 0);
|
||||
|
||||
|
||||
axis_ = new tango_gl::Axis();
|
||||
frustum_ = new tango_gl::Frustum();
|
||||
trace_ = new tango_gl::Trace();
|
||||
grid_ = new tango_gl::Grid();
|
||||
box_ = new BoundingBoxDrawable();
|
||||
currentPose_ = new rtabmap::Transform();
|
||||
axis_ = new tango_gl::Axis();
|
||||
frustum_ = new tango_gl::Frustum();
|
||||
trace_ = new tango_gl::Trace();
|
||||
grid_ = new tango_gl::Grid();
|
||||
box_ = new BoundingBoxDrawable();
|
||||
currentPose_ = new rtabmap::Transform();
|
||||
|
||||
|
||||
axis_->SetScale(glm::vec3(0.5f,0.5f,0.5f));
|
||||
frustum_->SetColor(kTraceColor);
|
||||
trace_->ClearVertexArray();
|
||||
trace_->SetColor(kTraceColor);
|
||||
grid_->SetColor(kGridColor);
|
||||
grid_->SetPosition(-kHeightOffset);
|
||||
box_->SetShader();
|
||||
box_->SetColor(1,0,0);
|
||||
axis_->SetScale(glm::vec3(0.5f,0.5f,0.5f));
|
||||
frustum_->SetColor(kTraceColor);
|
||||
trace_->ClearVertexArray();
|
||||
trace_->SetColor(kTraceColor);
|
||||
grid_->SetColor(kGridColor);
|
||||
grid_->SetPosition(-kHeightOffset);
|
||||
box_->SetShader();
|
||||
box_->SetColor(1,0,0);
|
||||
|
||||
if(cloud_shader_program_ == 0)
|
||||
{
|
||||
cloud_shader_program_ = tango_gl::util::CreateProgram(kPointCloudVertexShader.c_str(), kPointCloudFragmentShader.c_str());
|
||||
UASSERT(cloud_shader_program_ != 0);
|
||||
}
|
||||
if(texture_mesh_shader_program_ == 0)
|
||||
{
|
||||
texture_mesh_shader_program_ = tango_gl::util::CreateProgram(kTextureMeshVertexShader.c_str(), kTextureMeshFragmentShader.c_str());
|
||||
UASSERT(texture_mesh_shader_program_ != 0);
|
||||
}
|
||||
if(graph_shader_program_ == 0)
|
||||
{
|
||||
graph_shader_program_ = tango_gl::util::CreateProgram(kGraphVertexShader.c_str(), kGraphFragmentShader.c_str());
|
||||
UASSERT(graph_shader_program_ != 0);
|
||||
}
|
||||
PointCloudDrawable::createShaderPrograms();
|
||||
|
||||
if(graph_shader_program_ == 0)
|
||||
{
|
||||
graph_shader_program_ = tango_gl::util::CreateProgram(kGraphVertexShader.c_str(), kGraphFragmentShader.c_str());
|
||||
UASSERT(graph_shader_program_ != 0);
|
||||
}
|
||||
}
|
||||
|
||||
//Should only be called in OpenGL thread!
|
||||
@@ -302,14 +157,8 @@ void Scene::DeleteResources() {
|
||||
delete box_;
|
||||
}
|
||||
|
||||
if (cloud_shader_program_) {
|
||||
glDeleteShader(cloud_shader_program_);
|
||||
cloud_shader_program_ = 0;
|
||||
}
|
||||
if (texture_mesh_shader_program_) {
|
||||
glDeleteShader(texture_mesh_shader_program_);
|
||||
texture_mesh_shader_program_ = 0;
|
||||
}
|
||||
PointCloudDrawable::releaseShaderPrograms();
|
||||
|
||||
if (graph_shader_program_) {
|
||||
glDeleteShader(graph_shader_program_);
|
||||
graph_shader_program_ = 0;
|
||||
@@ -535,7 +384,28 @@ int Scene::Render() {
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
-1.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
//Culling
|
||||
std::vector<glm::vec4> planes = computeFrustumPlanes(projectionMatrix*viewMatrix, true);
|
||||
std::vector<PointCloudDrawable*> cloudsToDraw(pointClouds_.size());
|
||||
int oi=0;
|
||||
for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
|
||||
{
|
||||
if(!mapRendering_ && iter->first > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(iter->second->isVisible())
|
||||
{
|
||||
if(intersectFrustumAABB(planes,
|
||||
iter->second->aabbMinWorld(),
|
||||
iter->second->aabbMaxWorld()))
|
||||
{
|
||||
cloudsToDraw[oi++] = iter->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
cloudsToDraw.resize(oi);
|
||||
|
||||
// First rendering to get depth texture
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@@ -556,8 +426,7 @@ int Scene::Render() {
|
||||
|
||||
UTimer timer;
|
||||
|
||||
bool onlineBlending = blending_ && mapRendering_ && meshRendering_ && pointClouds_.size()>1;
|
||||
std::set<int> usedForDepth;
|
||||
bool onlineBlending = blending_ && mapRendering_ && meshRendering_ && cloudsToDraw.size()>1;
|
||||
if(onlineBlending && fboId_)
|
||||
{
|
||||
// set the rendering destination to FBO
|
||||
@@ -568,23 +437,10 @@ int Scene::Render() {
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Draw scene
|
||||
for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
|
||||
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
|
||||
{
|
||||
if(iter->second->isVisible())
|
||||
{
|
||||
if(intersectFrustumAABB(planes,
|
||||
iter->second->aabbMinWorld(),
|
||||
iter->second->aabbMaxWorld()))
|
||||
{
|
||||
usedForDepth.insert(iter->first);
|
||||
Eigen::Vector3f cloudToCamera(
|
||||
iter->second->getPose().x() - openglCamera.x(),
|
||||
iter->second->getPose().y() - openglCamera.y(),
|
||||
iter->second->getPose().z() - openglCamera.z());
|
||||
float distanceToCameraSqr = 999.0f; // set it large to use low res polygons for fast processing
|
||||
iter->second->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, distanceToCameraSqr);
|
||||
}
|
||||
}
|
||||
// set large distance to cam to use low res polygons for fast processing
|
||||
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, 999.0f);
|
||||
}
|
||||
|
||||
// back to normal window-system-provided framebuffer
|
||||
@@ -597,17 +453,10 @@ int Scene::Render() {
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
|
||||
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
|
||||
{
|
||||
if((onlineBlending && usedForDepth.find(iter->first) != usedForDepth.end()) ||
|
||||
(!onlineBlending && iter->second->isVisible() &&
|
||||
intersectFrustumAABB(planes,
|
||||
iter->second->aabbMinWorld(),
|
||||
iter->second->aabbMaxWorld())))
|
||||
{
|
||||
float distanceToCameraSqr = 999.0f; // set it large to use low res polygons for fast processing
|
||||
iter->second->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_*10.0f, false, false, distanceToCameraSqr, 0, 0, 0, true);
|
||||
}
|
||||
// set large distance to cam to use low res polygons for fast processing
|
||||
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_*10.0f, false, false, 999.0f, 0, 0, 0, 0, 0, true);
|
||||
}
|
||||
|
||||
GLubyte zValue[4];
|
||||
@@ -661,75 +510,39 @@ int Scene::Render() {
|
||||
graph_->Render(projectionMatrix, viewMatrix);
|
||||
}
|
||||
|
||||
int cloudDrawn=0;
|
||||
if(mapRendering_)
|
||||
|
||||
if(onlineBlending)
|
||||
{
|
||||
if(onlineBlending)
|
||||
{
|
||||
glEnable (GL_BLEND);
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
|
||||
{
|
||||
if((onlineBlending && usedForDepth.find(iter->first) != usedForDepth.end()) ||
|
||||
(!onlineBlending && iter->second->isVisible() &&
|
||||
intersectFrustumAABB(planes,
|
||||
iter->second->aabbMinWorld(),
|
||||
iter->second->aabbMaxWorld())))
|
||||
{
|
||||
if(boundingBoxRendering_)
|
||||
{
|
||||
box_->updateVertices(iter->second->aabbMinWorld(), iter->second->aabbMaxWorld());
|
||||
box_->Render(projectionMatrix, viewMatrix);
|
||||
}
|
||||
|
||||
Eigen::Vector3f cloudToCamera(
|
||||
iter->second->getPose().x() - openglCamera.x(),
|
||||
iter->second->getPose().y() - openglCamera.y(),
|
||||
iter->second->getPose().z() - openglCamera.z());
|
||||
float distanceToCameraSqr = cloudToCamera[0]*cloudToCamera[0] + cloudToCamera[1]*cloudToCamera[1] + cloudToCamera[2]*cloudToCamera[2];
|
||||
|
||||
iter->second->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, meshRenderingTexture_, lighting_, distanceToCameraSqr, onlineBlending?depthTexture_:0, screenWidth_, screenHeight_);
|
||||
++cloudDrawn;
|
||||
}
|
||||
}
|
||||
|
||||
if(onlineBlending)
|
||||
{
|
||||
glDisable (GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
|
||||
{
|
||||
if(iter->first > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(iter->second->isVisible())
|
||||
{
|
||||
if(boundingBoxRendering_)
|
||||
{
|
||||
box_->updateVertices(iter->second->aabbMinWorld(), iter->second->aabbMaxWorld());
|
||||
box_->Render(projectionMatrix, viewMatrix);
|
||||
}
|
||||
|
||||
++cloudDrawn;
|
||||
Eigen::Vector3f cloudToCamera(
|
||||
iter->second->getPose().x() - openglCamera.x(),
|
||||
iter->second->getPose().y() - openglCamera.y(),
|
||||
iter->second->getPose().z() - openglCamera.z());
|
||||
float distanceToCameraSqr = cloudToCamera[0]*cloudToCamera[0] + cloudToCamera[1]*cloudToCamera[1] + cloudToCamera[2]*cloudToCamera[2];
|
||||
iter->second->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, meshRenderingTexture_, lighting_, distanceToCameraSqr, onlineBlending?depthTexture_:0, screenWidth_, screenHeight_);
|
||||
}
|
||||
}
|
||||
glEnable (GL_BLEND);
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
return 1;
|
||||
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
|
||||
{
|
||||
PointCloudDrawable * cloud = *iter;
|
||||
|
||||
if(boundingBoxRendering_)
|
||||
{
|
||||
box_->updateVertices(cloud->aabbMinWorld(), cloud->aabbMaxWorld());
|
||||
box_->Render(projectionMatrix, viewMatrix);
|
||||
}
|
||||
|
||||
Eigen::Vector3f cloudToCamera(
|
||||
cloud->getPose().x() - openglCamera.x(),
|
||||
cloud->getPose().y() - openglCamera.y(),
|
||||
cloud->getPose().z() - openglCamera.z());
|
||||
float distanceToCameraSqr = cloudToCamera[0]*cloudToCamera[0] + cloudToCamera[1]*cloudToCamera[1] + cloudToCamera[2]*cloudToCamera[2];
|
||||
|
||||
cloud->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, meshRenderingTexture_, lighting_, distanceToCameraSqr, onlineBlending?depthTexture_:0, screenWidth_, screenHeight_, gesture_camera_->getNearClipPlane(), gesture_camera_->getFarClipPlane());
|
||||
}
|
||||
|
||||
if(onlineBlending)
|
||||
{
|
||||
glDisable (GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
return (int)cloudsToDraw.size();
|
||||
}
|
||||
|
||||
void Scene::SetCameraType(tango_gl::GestureCamera::CameraType camera_type) {
|
||||
@@ -824,12 +637,7 @@ void Scene::addCloud(
|
||||
}
|
||||
|
||||
//create
|
||||
UASSERT(cloud_shader_program_ != 0 && texture_mesh_shader_program_!=0);
|
||||
PointCloudDrawable * drawable = new PointCloudDrawable(
|
||||
cloud_shader_program_,
|
||||
texture_mesh_shader_program_,
|
||||
cloud,
|
||||
indices);
|
||||
PointCloudDrawable * drawable = new PointCloudDrawable(cloud, indices);
|
||||
drawable->setPose(pose);
|
||||
pointClouds_.insert(std::make_pair(id, drawable));
|
||||
}
|
||||
@@ -848,11 +656,7 @@ void Scene::addMesh(
|
||||
}
|
||||
|
||||
//create
|
||||
UASSERT(cloud_shader_program_ != 0 && texture_mesh_shader_program_!=0);
|
||||
PointCloudDrawable * drawable = new PointCloudDrawable(
|
||||
cloud_shader_program_,
|
||||
texture_mesh_shader_program_,
|
||||
mesh);
|
||||
PointCloudDrawable * drawable = new PointCloudDrawable(mesh);
|
||||
drawable->setPose(pose);
|
||||
pointClouds_.insert(std::make_pair(id, drawable));
|
||||
}
|
||||
|
||||
@@ -167,8 +167,6 @@ class Scene {
|
||||
rtabmap::Transform * currentPose_;
|
||||
|
||||
// Shader to display point cloud.
|
||||
GLuint cloud_shader_program_;
|
||||
GLuint texture_mesh_shader_program_;
|
||||
GLuint graph_shader_program_;
|
||||
|
||||
bool blending_;
|
||||
|
||||
@@ -33,6 +33,8 @@ class Camera : public Transform {
|
||||
|
||||
glm::mat4 GetViewMatrix();
|
||||
glm::mat4 GetProjectionMatrix();
|
||||
float getNearClipPlane() const {return near_clip_plane_;}
|
||||
float getFarClipPlane() const {return far_clip_plane_;}
|
||||
|
||||
/**
|
||||
* Create an OpenGL perspective matrix from window size, camera intrinsics, and clip settings.
|
||||
|
||||
@@ -85,11 +85,6 @@
|
||||
android:summary="@string/pref_summary_append"
|
||||
android:defaultValue="@string/pref_default_append"/>
|
||||
<SwitchPreference
|
||||
android:key="@string/pref_key_auto_exposure"
|
||||
android:title="@string/pref_title_auto_exposure"
|
||||
android:summary="@string/pref_summary_auto_exposure"
|
||||
android:defaultValue="@string/pref_default_auto_exposure"/>
|
||||
<SwitchPreference
|
||||
android:key="@string/pref_key_resolution"
|
||||
android:title="@string/pref_title_resolution"
|
||||
android:summary="@string/pref_summary_resolution"
|
||||
@@ -270,7 +265,7 @@
|
||||
android:key="@string/pref_key_opt_depth"
|
||||
android:title="@string/pref_title_opt_depth"
|
||||
android:summary="@string/pref_summary_opt_depth"
|
||||
android:entries="@array/pref_opt_depth_values"
|
||||
android:entries="@array/pref_opt_depth_keys"
|
||||
android:entryValues="@array/pref_opt_depth_values"
|
||||
android:defaultValue="@string/pref_default_opt_depth"/>
|
||||
|
||||
|
||||
@@ -64,8 +64,6 @@
|
||||
<string name="pref_default_nodes_filtering">false</string>
|
||||
<string name="pref_key_append">pref_key_append</string>
|
||||
<string name="pref_default_append">true</string>
|
||||
<string name="pref_key_auto_exposure">pref_key_auto_exposure</string>
|
||||
<string name="pref_default_auto_exposure">true</string>
|
||||
<string name="pref_key_resolution">pref_key_resolution</string>
|
||||
<string name="pref_default_resolution">false</string>
|
||||
<string name="pref_key_smoothing">pref_key_smoothing</string>
|
||||
@@ -117,7 +115,7 @@
|
||||
<string name="pref_key_block_render">pref_key_block_render</string>
|
||||
<string name="pref_default_block_render">false</string>
|
||||
<string name="pref_key_opt_depth">pref_key_opt_depth</string>
|
||||
<string name="pref_default_opt_depth">8</string>
|
||||
<string name="pref_default_opt_depth">0</string>
|
||||
<string name="pref_key_opt_color_radius">pref_key_opt_color_radius</string>
|
||||
<string name="pref_default_opt_color_radius">0.05</string>
|
||||
<string name="pref_key_opt_clean_white">pref_key_opt_clean_white</string>
|
||||
@@ -299,8 +297,6 @@
|
||||
<string name="pref_title_mapping_database">Database</string>
|
||||
<string name="pref_title_append">Append Mode</string>
|
||||
<string name="pref_summary_append">When resuming mapping, wait for a relocalization on the current map before starting a new map.</string>
|
||||
<string name="pref_title_auto_exposure">Auto Exposure</string>
|
||||
<string name="pref_summary_auto_exposure">Adjust camera exposure depending on the lighting to get always maximum contrast. This may change texture color between scanned images. Color correction option in Post-Processing can help to uniformize colors. May not work on some devices.</string>
|
||||
<string name="pref_title_resolution">HD Mode</string>
|
||||
<string name="pref_summary_resolution">Save HD images of the color camera if you want very detailed textures. More memory will be required.</string>
|
||||
<string name="pref_title_smoothing">Smoothing</string>
|
||||
@@ -657,13 +653,24 @@
|
||||
<string name="pref_title_opt_voxel">Voxel Size</string>
|
||||
<string name="pref_summary_opt_voxel">Increasing this can reduce reconstruction time at the cost of less geometry precision.</string>
|
||||
<string name="pref_title_opt_depth">Reconstruction Depth</string>
|
||||
<string name="pref_summary_opt_depth">Lowering this parameter decreases reconstruction time, but geometry precision is lower.</string>
|
||||
<string name="pref_summary_opt_depth">Lowering this parameter decreases reconstruction time, but geometry precision is lower. Minimum polygon size: map length / 2^depth). \"Auto\" means that depth is chosen so that polygon size is just under 3 cm.</string>
|
||||
<string name="pref_title_opt_color_radius">Color Radius</string>
|
||||
<string name="pref_summary_opt_color_radius">Radius used to transfer nearest color from the point cloud to reconstructed mesh. When exporting with texture, if Clean Mesh is also enabled, this will limit the number of polygons textured in holes.</string>
|
||||
<string name="pref_title_opt_clean_white">Clean Mesh</string>
|
||||
<string name="pref_summary_opt_clean_white">Clean mesh from textureless or colorless reconstructed polygons.</string>
|
||||
|
||||
<string-array name="pref_opt_depth_keys">
|
||||
<item>"Auto"</item>
|
||||
<item>"12"</item>
|
||||
<item>"11"</item>
|
||||
<item>"10"</item>
|
||||
<item>"9"</item>
|
||||
<item>"8"</item>
|
||||
<item>"7"</item>
|
||||
<item>"6"</item>
|
||||
</string-array>
|
||||
<string-array name="pref_opt_depth_values">
|
||||
<item>"0"</item>
|
||||
<item>"12"</item>
|
||||
<item>"11"</item>
|
||||
<item>"10"</item>
|
||||
|
||||
@@ -500,7 +500,6 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
if(!DISABLE_LOG) Log.d(TAG, "set mapping parameters");
|
||||
RTABMapLib.setOnlineBlending(sharedPref.getBoolean(getString(R.string.pref_key_blending), Boolean.parseBoolean(getString(R.string.pref_default_blending))));
|
||||
RTABMapLib.setNodesFiltering(sharedPref.getBoolean(getString(R.string.pref_key_nodes_filtering), Boolean.parseBoolean(getString(R.string.pref_default_nodes_filtering))));
|
||||
RTABMapLib.setAutoExposure(sharedPref.getBoolean(getString(R.string.pref_key_auto_exposure), Boolean.parseBoolean(getString(R.string.pref_default_auto_exposure))));
|
||||
RTABMapLib.setRawScanSaved(sharedPref.getBoolean(getString(R.string.pref_key_raw_scan_saved), Boolean.parseBoolean(getString(R.string.pref_default_raw_scan_saved))));
|
||||
RTABMapLib.setFullResolution(sharedPref.getBoolean(getString(R.string.pref_key_resolution), Boolean.parseBoolean(getString(R.string.pref_default_resolution))));
|
||||
RTABMapLib.setSmoothing(sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing))));
|
||||
@@ -530,7 +529,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
RTABMapLib.setMeshTriangleSize(Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_triangle), getString(R.string.pref_default_triangle))));
|
||||
float bgColor = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_background_color), getString(R.string.pref_default_background_color)));
|
||||
RTABMapLib.setBackgroundColor(bgColor);
|
||||
mRenderer.setTextColor(bgColor==0.5f?0.4f:1.0f-bgColor);
|
||||
mRenderer.setTextColor(bgColor>=0.6f?0.0f:1.0f);
|
||||
|
||||
if(!DISABLE_LOG) Log.d(TAG, "set rendering parameters...");
|
||||
RTABMapLib.setClusterRatio(Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_cluster_ratio), getString(R.string.pref_default_cluster_ratio))));
|
||||
@@ -2121,6 +2120,27 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
})
|
||||
.show();
|
||||
}
|
||||
else if(status == -2)
|
||||
{
|
||||
mProgressDialog.dismiss();
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(false)
|
||||
.setTitle("Error")
|
||||
.setMessage("Failed to open database: Out of memory! Try "
|
||||
+ "again after lowering Point Cloud Density in Settings.")
|
||||
.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(getActivity(), SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
mBlockBack = true;
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Close", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// creating meshes...
|
||||
|
||||
@@ -68,7 +68,6 @@ public class RTABMapLib
|
||||
public static native void setNodesFiltering(boolean enabled);
|
||||
public static native void setGraphVisible(boolean visible);
|
||||
public static native void setGridVisible(boolean visible);
|
||||
public static native void setAutoExposure(boolean enabled);
|
||||
public static native void setRawScanSaved(boolean enabled);
|
||||
public static native void setFullResolution(boolean enabled);
|
||||
public static native void setSmoothing(boolean enabled);
|
||||
|
||||
Reference in New Issue
Block a user