Tango: Added Settings/Optimized Mesh/Sketchfab Upload

This commit is contained in:
matlabbe
2017-01-26 16:46:24 -05:00
parent 66ee792e8c
commit 3a73414972
27 changed files with 4441 additions and 2029 deletions

1
app/android/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/bin/

View File

@@ -2,7 +2,7 @@
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.introlab.rtabmap"
android:versionCode="30"
android:versionCode="31"
android:versionName="@RTABMAP_VERSION@">
<uses-permission android:name="android.permission.CAMERA" />
@@ -10,10 +10,12 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:glEsVersion="0x00020000" />
<!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="17" />
<uses-sdk android:minSdkVersion="19" />
<!-- This .apk has no Java code itself, so set hasCode to false. -->
<application
@@ -36,6 +38,8 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="SettingsActivity" android:label="@string/settings"/>
</application>
</manifest>

View File

@@ -32,6 +32,11 @@ configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/ant.properties.in"
"${CMAKE_CURRENT_BINARY_DIR}/ant.properties"
@ONLY)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/custom_rules.xml"
"${CMAKE_CURRENT_BINARY_DIR}/custom_rules.xml"
COPYONLY)
add_custom_target(NativeRTABMap-ant-configure ALL
COMMAND "${ANDROID_EXECUTABLE}"

View File

@@ -1,5 +1,6 @@
builddir=@CMAKE_CURRENT_BINARY_DIR@
srcdir=@CMAKE_CURRENT_SOURCE_DIR@
android.abi=@ANDROID_ABI@
source.dir=${srcdir}/src
gen.dir=${builddir}/gen

View File

@@ -0,0 +1,10 @@
<project>
<target name="-pre-build">
<copy todir="${jar.libs.dir}">
<fileset dir="${srcdir}/libs" includes="**/*.jar" excludes="**/*sources.jar, **/*javadoc.jar" />
</copy>
<copy todir="${native.libs.dir}/${android.abi}">
<fileset dir="${srcdir}/libs-c" includes="**/*.so"/>
</copy>
</target>
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UEventsHandler.h>
#include <boost/thread/mutex.hpp>
#include <pcl/pcl_base.h>
#include <pcl/TextureMesh.h>
// RTABMapApp handles the application lifecycle and resources.
class RTABMapApp : public UEventsHandler {
@@ -113,6 +114,8 @@ class RTABMapApp : public UEventsHandler {
void setMapCloudShown(bool shown);
void setOdomCloudShown(bool shown);
void setMeshRendering(bool enabled, bool withTexture);
void setPointSize(float value);
void setLighting(bool enabled);
void setLocalizationMode(bool enabled);
void setTrajectoryMode(bool enabled);
void setGraphOptimization(bool enabled);
@@ -132,7 +135,22 @@ class RTABMapApp : public UEventsHandler {
void resetMapping();
void save(const std::string & databasePath);
bool exportMesh(const std::string & filePath);
cv::Mat mergeTextures(pcl::TextureMesh & mesh, int textureSize) const;
bool exportMesh(
const std::string & filePath,
float cloudVoxelSize,
bool meshing,
int textureSize,
int normalK,
bool optimized,
float optimizedVoxelSize,
int optimizedDepth,
float optimizedDecimationFactor,
float optimizedColorRadius,
bool optimizedCleanWhitePolygons,
bool optimizedColorWhitePolygons,
bool blockRendering);
bool postExportation(bool visualize);
int postProcessing(int approach);
protected:
@@ -176,6 +194,11 @@ class RTABMapApp : public UEventsHandler {
int lastDrawnCloudsCount_;
float renderingTime_;
bool visualizingMesh_;
bool exportedMeshUpdated_;
pcl::TextureMesh::Ptr exportedMesh_;
cv::Mat exportedTexture_;
// main_scene_ includes all drawable object for visualizing Tango device's
// movement and point cloud.
Scene main_scene_;

View File

@@ -145,6 +145,18 @@ Java_com_introlab_rtabmap_RTABMapLib_setMeshRendering(
return app.setMeshRendering(enabled, withTexture);
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setPointSize(
JNIEnv*, jobject, float value)
{
return app.setPointSize(value);
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setLighting(
JNIEnv*, jobject, bool enabled)
{
return app.setLighting(enabled);
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setLocalizationMode(
JNIEnv*, jobject, bool enabled)
{
@@ -262,11 +274,44 @@ Java_com_introlab_rtabmap_RTABMapLib_save(
JNIEXPORT bool JNICALL
Java_com_introlab_rtabmap_RTABMapLib_exportMesh(
JNIEnv* env, jobject, jstring filePath)
JNIEnv* env, jobject,
jstring filePath,
float cloudVoxelSize,
bool meshing,
int textureSize,
int normalK,
bool optimized,
float optimizedVoxelSize,
int optimizedDepth,
float optimizedDecimationFactor,
float optimizedColorRadius,
bool optimizedCleanWhitePolygons,
bool optimizedColorWhitePolygons,
bool blockRendering)
{
std::string filePathC;
GetJStringContent(env,filePath,filePathC);
return app.exportMesh(filePathC);
return app.exportMesh(
filePathC,
cloudVoxelSize,
meshing,
textureSize,
normalK,
optimized,
optimizedVoxelSize,
optimizedDepth,
optimizedDecimationFactor,
optimizedColorRadius,
optimizedCleanWhitePolygons,
optimizedColorWhitePolygons,
blockRendering);
}
JNIEXPORT bool JNICALL
Java_com_introlab_rtabmap_RTABMapLib_postExportation(
JNIEnv* env, jobject, bool visualize)
{
return app.postExportation(visualize);
}
JNIEXPORT int JNICALL

View File

@@ -46,6 +46,7 @@ PointCloudDrawable::PointCloudDrawable(
nPoints_(0),
pose_(1.0f),
visible_(true),
hasNormals_(false),
cloud_shader_program_(cloudShaderProgram),
texture_shader_program_(textureShaderProgram),
gain_(1.0f)
@@ -63,6 +64,7 @@ PointCloudDrawable::PointCloudDrawable(
nPoints_(0),
pose_(1.0f),
visible_(true),
hasNormals_(false),
cloud_shader_program_(cloudShaderProgram),
texture_shader_program_(textureShaderProgram),
gain_(1.0f)
@@ -90,19 +92,20 @@ PointCloudDrawable::~PointCloudDrawable()
void PointCloudDrawable::updatePolygons(const std::vector<pcl::Vertices> & polygons)
{
LOGD("Update polygons");
polygons_.clear();
if(polygons.size() && organizedToDenseIndices_.size())
{
int polygonSize = polygons[0].vertices.size();
unsigned int polygonSize = polygons[0].vertices.size();
UASSERT(polygonSize == 3);
polygons_.resize(polygons.size() * polygonSize);
int oi = 0;
for(unsigned int i=0; i<polygons.size(); ++i)
{
UASSERT((int)polygons[i].vertices.size() == polygonSize);
for(int j=0; j<polygonSize; ++j)
UASSERT(polygons[i].vertices.size() == polygonSize);
for(unsigned int j=0; j<polygonSize; ++j)
{
polygons_[oi++] = organizedToDenseIndices_.at((unsigned short)polygons[i].vertices[j]);
polygons_[oi++] = organizedToDenseIndices_.at(polygons[i].vertices[j]);
}
}
}
@@ -110,7 +113,7 @@ void PointCloudDrawable::updatePolygons(const std::vector<pcl::Vertices> & polyg
void PointCloudDrawable::updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::IndicesPtr & indices, float gain)
{
UASSERT(cloud.get() && !cloud->empty() && indices.get() && !indices->empty());
UASSERT(cloud.get() && !cloud->empty());
nPoints_ = 0;
polygons_.clear();
gain_ = gain;
@@ -137,13 +140,31 @@ void PointCloudDrawable::updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Pt
}
LOGI("Creating cloud buffer %d", vertex_buffers_);
std::vector<float> vertices(indices->size()*4);
for(unsigned int i=0; i<indices->size(); ++i)
std::vector<float> vertices;
int totalPoints = 0;
if(indices.get() && indices->size())
{
vertices[i*4] = cloud->at(indices->at(i)).x;
vertices[i*4+1] = cloud->at(indices->at(i)).y;
vertices[i*4+2] = cloud->at(indices->at(i)).z;
vertices[i*4+3] = cloud->at(indices->at(i)).rgb;
totalPoints = indices->size();
vertices.resize(indices->size()*4);
for(unsigned int i=0; i<indices->size(); ++i)
{
vertices[i*4] = cloud->at(indices->at(i)).x;
vertices[i*4+1] = cloud->at(indices->at(i)).y;
vertices[i*4+2] = cloud->at(indices->at(i)).z;
vertices[i*4+3] = cloud->at(indices->at(i)).rgb;
}
}
else
{
totalPoints = cloud->size();
vertices.resize(cloud->size()*4);
for(unsigned int i=0; i<cloud->size(); ++i)
{
vertices[i*4] = cloud->at(i).x;
vertices[i*4+1] = cloud->at(i).y;
vertices[i*4+2] = cloud->at(i).z;
vertices[i*4+3] = cloud->at(i).rgb;
}
}
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
@@ -158,12 +179,12 @@ void PointCloudDrawable::updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Pt
return;
}
nPoints_ = indices->size();
nPoints_ = totalPoints;
}
void PointCloudDrawable::updateMesh(const Mesh & mesh, const cv::Mat & texture)
{
UASSERT(mesh.cloud.get() && !mesh.cloud->empty() && mesh.indices.get() && !mesh.indices->empty());
UASSERT(mesh.cloud.get() && !mesh.cloud->empty());
nPoints_ = 0;
if (vertex_buffers_)
@@ -196,7 +217,6 @@ void PointCloudDrawable::updateMesh(const Mesh & mesh, const cv::Mat & texture)
if(textureUpdate)
{
UASSERT(!mesh.cloud->is_dense);
glGenTextures(1, &textures_);
if(!textures_)
{
@@ -206,39 +226,155 @@ void PointCloudDrawable::updateMesh(const Mesh & mesh, const cv::Mat & texture)
}
}
LOGI("Creating cloud buffer %d", vertex_buffers_);
LOGD("Creating cloud buffer %d", vertex_buffers_);
std::vector<float> vertices;
organizedToDenseIndices_ = std::vector<int>(mesh.cloud->width*mesh.cloud->height, -1);
if(textures_)
int totalPoints = 0;
std::vector<pcl::Vertices> polygons = mesh.polygons;
hasNormals_ = mesh.normals.get() && mesh.normals->size() == mesh.cloud->size();
UASSERT(!hasNormals_ || mesh.cloud->size() == mesh.normals->size());
if(mesh.cloud->isOrganized()) // assume organized mesh
{
vertices = std::vector<float>(mesh.indices->size()*6);
for(unsigned int i=0; i<mesh.indices->size(); ++i)
organizedToDenseIndices_ = std::vector<unsigned int>(mesh.cloud->width*mesh.cloud->height, -1);
totalPoints = mesh.indices->size();
if(textures_ && polygons.size())
{
vertices[i*6] = mesh.cloud->at(mesh.indices->at(i)).x;
vertices[i*6+1] = mesh.cloud->at(mesh.indices->at(i)).y;
vertices[i*6+2] = mesh.cloud->at(mesh.indices->at(i)).z;
LOGD("Organized mesh with texture");
int items = hasNormals_?9:6;
vertices = std::vector<float>(mesh.indices->size()*9);
for(unsigned int i=0; i<mesh.indices->size(); ++i)
{
vertices[i*items] = mesh.cloud->at(mesh.indices->at(i)).x;
vertices[i*items+1] = mesh.cloud->at(mesh.indices->at(i)).y;
vertices[i*items+2] = mesh.cloud->at(mesh.indices->at(i)).z;
// rgb
vertices[i*6+3] = mesh.cloud->at(mesh.indices->at(i)).rgb;
// rgb
vertices[i*items+3] = mesh.cloud->at(mesh.indices->at(i)).rgb;
// texture uv
int index = mesh.indices->at(i);
vertices[i*6+4] = float(index % mesh.cloud->width)/float(mesh.cloud->width); //u
vertices[i*6+5] = float(index / mesh.cloud->width)/float(mesh.cloud->height); //v
// texture uv
int index = mesh.indices->at(i);
vertices[i*items+4] = float(index % mesh.cloud->width)/float(mesh.cloud->width); //u
vertices[i*items+5] = float(index / mesh.cloud->width)/float(mesh.cloud->height); //v
organizedToDenseIndices_[mesh.indices->at(i)] = i;
if(hasNormals_)
{
// normal
vertices[i*items+6] = mesh.normals->at(mesh.indices->at(i)).normal_x;
vertices[i*items+7] = mesh.normals->at(mesh.indices->at(i)).normal_y;
vertices[i*items+8] = mesh.normals->at(mesh.indices->at(i)).normal_z;
}
organizedToDenseIndices_[mesh.indices->at(i)] = i;
}
}
else
{
LOGD("Organized mesh");
int items = hasNormals_?7:4;
vertices = std::vector<float>(mesh.indices->size()*items);
for(unsigned int i=0; i<mesh.indices->size(); ++i)
{
vertices[i*items] = mesh.cloud->at(mesh.indices->at(i)).x;
vertices[i*items+1] = mesh.cloud->at(mesh.indices->at(i)).y;
vertices[i*items+2] = mesh.cloud->at(mesh.indices->at(i)).z;
vertices[i*items+3] = mesh.cloud->at(mesh.indices->at(i)).rgb;
if(hasNormals_)
{
// normal
vertices[i*items+4] = mesh.normals->at(mesh.indices->at(i)).normal_x;
vertices[i*items+5] = mesh.normals->at(mesh.indices->at(i)).normal_y;
vertices[i*items+6] = mesh.normals->at(mesh.indices->at(i)).normal_z;
}
organizedToDenseIndices_[mesh.indices->at(i)] = i;
}
}
}
else
else // assume dense mesh with texCoords set to polygons
{
vertices = std::vector<float>(mesh.indices->size()*4);
for(unsigned int i=0; i<mesh.indices->size(); ++i)
totalPoints = mesh.cloud->size();
if(textures_ && polygons.size() && mesh.normals->size())
{
vertices[i*4] = mesh.cloud->at(mesh.indices->at(i)).x;
vertices[i*4+1] = mesh.cloud->at(mesh.indices->at(i)).y;
vertices[i*4+2] = mesh.cloud->at(mesh.indices->at(i)).z;
vertices[i*4+3] = mesh.cloud->at(mesh.indices->at(i)).rgb;
organizedToDenseIndices_[mesh.indices->at(i)] = i;
LOGD("Dense mesh with texture (%d texCoords %d points %d polygons %dx%d)",
(int)mesh.texCoords.size(), (int)mesh.cloud->size(), (int)mesh.polygons.size(), texture.cols, texture.rows);
// Texturing issue:
// tex_coordinates should be linked to points, not
// polygon vertices. Points linked to multiple different texCoords (different textures) should
// be duplicated.
vertices = std::vector<float>(mesh.texCoords.size()*9);
organizedToDenseIndices_ = std::vector<unsigned int>(mesh.texCoords.size(), -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());
int items = hasNormals_?9:6;
unsigned int oi=0;
for(unsigned int i=0; i<polygons.size(); ++i)
{
pcl::Vertices & v = polygons[i];
for(unsigned int j=0; j<v.vertices.size(); ++j)
{
UASSERT(oi < mesh.texCoords.size());
UASSERT(v.vertices[j] < mesh.cloud->size());
vertices[oi*items] = mesh.cloud->at(v.vertices[j]).x;
vertices[oi*items+1] = mesh.cloud->at(v.vertices[j]).y;
vertices[oi*items+2] = mesh.cloud->at(v.vertices[j]).z;
// rgb
vertices[oi*items+3] = mesh.cloud->at(v.vertices[j]).rgb;
// texture uv
if(mesh.texCoords[oi][0]>=0.0f)
{
vertices[oi*items+4] = mesh.texCoords[oi][0]; //u
vertices[oi*items+5] = 1.0f-mesh.texCoords[oi][1]; //v
}
else
{
vertices[oi*items+4] = vertices[oi*items+5] = -1.0f;
}
if(hasNormals_)
{
// normal
vertices[oi*items+6] = mesh.normals->at(v.vertices[j]).normal_x;
vertices[oi*items+7] = mesh.normals->at(v.vertices[j]).normal_y;
vertices[oi*items+8] = mesh.normals->at(v.vertices[j]).normal_z;
}
v.vertices[j] = (int)oi; // new vertex index
UASSERT(oi < organizedToDenseIndices_.size());
organizedToDenseIndices_[oi] = oi;
++oi;
}
}
}
else
{
LOGD("Dense mesh");
int items = hasNormals_?7:4;
organizedToDenseIndices_ = std::vector<unsigned int>(mesh.cloud->size(), -1);
vertices = std::vector<float>(mesh.cloud->size()*items);
for(unsigned int i=0; i<mesh.cloud->size(); ++i)
{
vertices[i*items] = mesh.cloud->at(i).x;
vertices[i*items+1] = mesh.cloud->at(i).y;
vertices[i*items+2] = mesh.cloud->at(i).z;
vertices[i*items+3] = mesh.cloud->at(i).rgb;
if(hasNormals_)
{
vertices[i*items+4] = mesh.normals->at(i).normal_x;
vertices[i*items+5] = mesh.normals->at(i).normal_y;
vertices[i*items+6] = mesh.normals->at(i).normal_z;
}
organizedToDenseIndices_[i] = i;
}
}
}
@@ -256,6 +392,10 @@ void PointCloudDrawable::updateMesh(const Mesh & mesh, const cv::Mat & texture)
if(textures_ && textureUpdate)
{
GLint maxTextureSize = 0;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
LOGI("maxTextureSize=%d", maxTextureSize);
// gen texture from image
glBindTexture(GL_TEXTURE_2D, textures_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -276,11 +416,11 @@ void PointCloudDrawable::updateMesh(const Mesh & mesh, const cv::Mat & texture)
}
}
nPoints_ = mesh.indices->size();
nPoints_ = totalPoints;
if(polygons_.size() != mesh.polygons.size())
if(polygons_.size() != polygons.size())
{
updatePolygons(mesh.polygons);
updatePolygons(polygons);
}
}
@@ -291,7 +431,12 @@ void PointCloudDrawable::setPose(const rtabmap::Transform & pose)
pose_ = glmFromTransform(pose);
}
void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix, const glm::mat4 & viewMatrix, bool meshRendering, float pointSize, bool textureRendering) {
void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix,
const glm::mat4 & viewMatrix,
bool meshRendering,
float pointSize,
bool textureRendering,
bool lighting) {
if(vertex_buffers_ && nPoints_ && visible_)
{
@@ -299,65 +444,144 @@ void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix, const glm::m
{
glUseProgram(texture_shader_program_);
GLuint mvp_handle_ = glGetUniformLocation(texture_shader_program_, "mvp");
glm::mat4 mvp_mat = projectionMatrix * viewMatrix * pose_;
glUniformMatrix4fv(mvp_handle_, 1, GL_FALSE, glm::value_ptr(mvp_mat));
GLuint mvp_handle = glGetUniformLocation(texture_shader_program_, "uMVP");
glm::mat4 mv_mat = viewMatrix * pose_;
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(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
}
// 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_, "u_Texture");
GLuint texture_handle = glGetUniformLocation(texture_shader_program_, "uTexture");
glUniform1i(texture_handle, 0);
GLuint gain_handle = glGetUniformLocation(texture_shader_program_, "u_gain");
GLuint gain_handle = glGetUniformLocation(texture_shader_program_, "uGain");
glUniform1f(gain_handle, gain_);
GLint attribute_vertex = glGetAttribLocation(texture_shader_program_, "vertex");
GLint attribute_texture = glGetAttribLocation(texture_shader_program_, "a_TexCoordinate");
GLint attribute_vertex = glGetAttribLocation(texture_shader_program_, "aVertex");
GLint attribute_texture = glGetAttribLocation(texture_shader_program_, "aTexCoord");
GLint attribute_normal=0;
if(hasNormals_)
{
attribute_normal = glGetAttribLocation(texture_shader_program_, "aNormal");
}
glEnableVertexAttribArray(attribute_vertex);
glEnableVertexAttribArray(attribute_texture);
if(hasNormals_)
{
glEnableVertexAttribArray(attribute_normal);
}
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), 0);
glVertexAttribPointer(attribute_texture, 2, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*) (4 * sizeof(GLfloat)));
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_SHORT, polygons_.data());
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_)
{
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 // point cloud or colored mesh
{
glUseProgram(cloud_shader_program_);
GLuint mvp_handle_ = glGetUniformLocation(cloud_shader_program_, "mvp");
glm::mat4 mvp_mat = projectionMatrix * viewMatrix * pose_;
GLuint mvp_handle_ = glGetUniformLocation(cloud_shader_program_, "uMVP");
glm::mat4 mv_mat = viewMatrix * pose_;
glm::mat4 mvp_mat = projectionMatrix * mv_mat;
glUniformMatrix4fv(mvp_handle_, 1, GL_FALSE, glm::value_ptr(mvp_mat));
GLuint point_size_handle_ = glGetUniformLocation(cloud_shader_program_, "point_size");
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(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
}
GLuint point_size_handle_ = glGetUniformLocation(cloud_shader_program_, "uPointSize");
glUniform1f(point_size_handle_, pointSize);
GLuint gain_handle = glGetUniformLocation(cloud_shader_program_, "u_gain");
GLuint gain_handle = glGetUniformLocation(cloud_shader_program_, "uGain");
glUniform1f(gain_handle, gain_);
GLint attribute_vertex = glGetAttribLocation(cloud_shader_program_, "vertex");
GLint attribute_color = glGetAttribLocation(cloud_shader_program_, "color");
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, 6*sizeof(GLfloat), 0);
glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, 6*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));
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)));
}
}
else
{
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, 4*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));
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)));
}
}
if(meshRendering && polygons_.size())
{
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_SHORT, polygons_.data());
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_INT, polygons_.data());
}
else
{

View File

@@ -61,6 +61,7 @@ class PointCloudDrawable {
void setVisible(bool visible) {visible_=visible;}
rtabmap::Transform getPose() const {return glmToTransform(pose_);}
bool isVisible() const {return visible_;}
bool hasMesh() const {return polygons_.size()!=0;}
bool hasTexture() const {return textures_ != 0;}
// Update current point cloud data.
@@ -69,17 +70,23 @@ 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, const glm::mat4 & viewMatrix, bool meshRendering = true, float pointSize = 3.0f, bool textureRendering = false);
void Render(const glm::mat4 & projectionMatrix,
const glm::mat4 & viewMatrix,
bool meshRendering = true,
float pointSize = 3.0f,
bool textureRendering = false,
bool lighting = true);
private:
// Vertex buffer of the point cloud geometry.
GLuint vertex_buffers_;
GLuint textures_;
std::vector<GLushort> polygons_;
std::vector<GLuint> polygons_;
int nPoints_;
glm::mat4 pose_;
bool visible_;
std::vector<int> organizedToDenseIndices_;
bool hasNormals_;
std::vector<unsigned int> organizedToDenseIndices_;
GLuint cloud_shader_program_;
GLuint texture_shader_program_;

View File

@@ -42,47 +42,87 @@ 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 vertex;\n"
"attribute vec3 color;\n"
"uniform mat4 mvp;\n"
"uniform float point_size;\n"
"varying vec3 v_color;\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 = mvp*vec4(vertex.x, vertex.y, vertex.z, 1.0);\n"
" gl_PointSize = point_size;\n"
" v_color = color;\n"
" gl_Position = uMVP*vec4(aVertex.x, aVertex.y, aVertex.z, 1.0);\n"
" gl_PointSize = uPointSize;\n"
" if (!uUseLighting) {\n"
" vLightWeighting = vec3(1.0, 1.0, 1.0);\n"
" } else {\n"
" vec3 transformedNormal = uN * aNormal;\n"
" vLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);\n"
" if(vLightWeighting<0.1) vLightWeighting=0.1;\n"
" }\n"
" vColor = aColor;\n"
"}\n";
const std::string kPointCloudFragmentShader =
"precision mediump float;\n"
"precision mediump int;\n"
"uniform float u_gain;\n"
"varying vec3 v_color;\n"
"uniform float uGain;\n"
"varying vec3 vColor;\n"
"varying float vLightWeighting;\n"
"void main() {\n"
" gl_FragColor = vec4(v_color.z*u_gain, v_color.y*u_gain, v_color.x*u_gain, 1.0);\n"
" vec4 textureColor = vec4(vColor.z*uGain, vColor.y*uGain, vColor.x*uGain, 1.0);\n"
" gl_FragColor = vec4(textureColor.rgb * uGain * vLightWeighting, textureColor.a);\n"
"}\n";
const std::string kTextureMeshVertexShader =
"precision mediump float;\n"
"precision mediump int;\n"
"attribute vec3 vertex;\n"
"attribute vec2 a_TexCoordinate;\n"
"uniform mat4 mvp;\n"
"varying vec2 v_TexCoordinate;\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 = mvp*vec4(vertex.x, vertex.y, vertex.z, 1.0);\n"
" v_TexCoordinate = a_TexCoordinate;\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 = vec3(1.0, 1.0, 1.0);\n"
" } else {\n"
" vec3 transformedNormal = uN * aNormal;\n"
" vLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);\n"
" if(vLightWeighting<0.1) vLightWeighting=0.1;\n"
" }\n"
"}\n";
const std::string kTextureMeshFragmentShader =
"precision mediump float;\n"
"precision mediump int;\n"
"uniform sampler2D u_Texture;\n"
"uniform float u_gain;\n"
"varying vec2 v_TexCoordinate;\n"
"uniform sampler2D uTexture;\n"
"uniform float uGain;\n"
"varying vec2 vTexCoord;\n"
"varying float vLightWeighting;\n"
"void main() {\n"
" gl_FragColor = texture2D(u_Texture, v_TexCoordinate);\n"
" gl_FragColor.x *= u_gain;\n"
" gl_FragColor.y *= u_gain;\n"
" gl_FragColor.z *= u_gain;\n"
" vec4 textureColor = texture2D(uTexture, vTexCoord);\n"
" gl_FragColor = vec4(textureColor.rgb * uGain * vLightWeighting, textureColor.a);\n"
"}\n";
const std::string kGraphVertexShader =
@@ -123,21 +163,31 @@ Scene::Scene() :
mapRendering_(true),
meshRendering_(true),
meshRenderingTexture_(true),
pointSize_(3.0f) {}
pointSize_(5.0f),
frustumCulling_(true),
lighting_(true)
{
gesture_camera_ = new tango_gl::GestureCamera();
gesture_camera_->SetCameraType(
tango_gl::GestureCamera::kFirstPerson);
}
Scene::~Scene() {DeleteResources();}
Scene::~Scene() {
DeleteResources();
delete gesture_camera_;
}
//Should only be called in OpenGL thread!
void Scene::InitGLContent()
{
if(gesture_camera_ != 0)
if(axis_ != 0)
{
DeleteResources();
}
UASSERT(gesture_camera_ == 0);
UASSERT(axis_ == 0);
gesture_camera_ = new tango_gl::GestureCamera();
axis_ = new tango_gl::Axis();
frustum_ = new tango_gl::Frustum();
trace_ = new tango_gl::Trace();
@@ -151,8 +201,6 @@ void Scene::InitGLContent()
trace_->SetColor(kTraceColor);
grid_->SetColor(kGridColor);
grid_->SetPosition(-kHeightOffset);
gesture_camera_->SetCameraType(
tango_gl::GestureCamera::kFirstPerson);
if(cloud_shader_program_ == 0)
{
@@ -175,15 +223,14 @@ void Scene::InitGLContent()
void Scene::DeleteResources() {
LOGI("Scene::DeleteResources()");
if(gesture_camera_)
if(axis_)
{
delete gesture_camera_;
delete axis_;
axis_ = 0;
delete frustum_;
delete trace_;
delete grid_;
delete currentPose_;
gesture_camera_ = 0;
}
if (cloud_shader_program_) {
@@ -288,9 +335,8 @@ int Scene::Render() {
gesture_camera_->GetViewMatrix());
}
bool frustumCulling = true;
int cloudDrawn=0;
if(mapRendering_ && frustumCulling)
if(mapRendering_ && frustumCulling_)
{
//Use camera frustum to cull nodes that don't need to be drawn
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
@@ -336,7 +382,7 @@ int Scene::Render() {
for(unsigned int i=0; i<indices->size(); ++i)
{
++cloudDrawn;
pointClouds_.find(ids[indices->at(i)])->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_, meshRenderingTexture_);
pointClouds_.find(ids[indices->at(i)])->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_, meshRenderingTexture_, lighting_);
}
}
}
@@ -347,7 +393,7 @@ int Scene::Render() {
if((mapRendering_ || iter->first < 0) && iter->second->isVisible())
{
++cloudDrawn;
iter->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_, meshRenderingTexture_);
iter->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_, meshRenderingTexture_, lighting_);
}
}
}
@@ -426,7 +472,7 @@ void Scene::addCloud(
const pcl::IndicesPtr & indices,
const rtabmap::Transform & pose)
{
LOGI("add cloud %d", id);
LOGI("add cloud %d (%d points %d indices)", id, (int)cloud->size(), indices.get()?(int)indices->size():0);
std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.find(id);
if(iter != pointClouds_.end())
{
@@ -496,6 +542,11 @@ bool Scene::hasCloud(int id) const
return pointClouds_.find(id) != pointClouds_.end();
}
bool Scene::hasMesh(int id) const
{
return pointClouds_.find(id) != pointClouds_.end() && pointClouds_.at(id)->hasMesh();
}
bool Scene::hasTexture(int id) const
{
return pointClouds_.find(id) != pointClouds_.end() && pointClouds_.at(id)->hasTexture();

View File

@@ -111,6 +111,7 @@ class Scene {
void setCloudPose(int id, const rtabmap::Transform & pose);
void setCloudVisible(int id, bool visible);
bool hasCloud(int id) const;
bool hasMesh(int id) const;
bool hasTexture(int id) const;
std::set<int> getAddedClouds() const;
void updateCloudPolygons(int id, const std::vector<pcl::Vertices> & polygons);
@@ -119,9 +120,14 @@ class Scene {
void setMapRendering(bool enabled) {mapRendering_ = enabled;}
void setMeshRendering(bool enabled, bool withTexture) {meshRendering_ = enabled; meshRenderingTexture_ = withTexture;}
void setPointSize(float size) {pointSize_ = size;}
void setFrustumCulling(bool enabled) {frustumCulling_ = enabled;}
void setLighting(bool enabled) {lighting_ = enabled;}
bool isMeshRendering() const {return meshRendering_;}
bool isMeshTexturing() const {return meshRendering_ && meshRenderingTexture_;}
float getPointSize() const {return pointSize_;}
bool isFrustumCulling() const {return frustumCulling_;}
bool isLighting() const {return lighting_;}
private:
// Camera object that allows user to use touch input to interact with.
@@ -156,6 +162,8 @@ class Scene {
bool meshRendering_;
bool meshRenderingTexture_;
float pointSize_;
bool frustumCulling_;
bool lighting_;
};
#endif // TANGO_POINT_CLOUD_SCENE_H_

View File

@@ -143,15 +143,26 @@ inline rtabmap::Transform glmToTransform(const glm::mat4 & mat)
return transform;
}
struct Mesh
class Mesh
{
public:
Mesh() :
cloud(new pcl::PointCloud<pcl::PointXYZRGB>),
normals(new pcl::PointCloud<pcl::Normal>),
indices(new std::vector<int>),
visible(true),
gain(1.0f)
{}
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud; // organized cloud
pcl::PointCloud<pcl::Normal>::Ptr normals;
pcl::IndicesPtr indices;
std::vector<pcl::Vertices> polygons;
rtabmap::Transform pose; // in rtabmap coordinates
bool visible;
rtabmap::CameraModel cameraModel;
float gain;
std::vector<Eigen::Vector2f> texCoords;
};
#endif /* UTIL_H_ */

Binary file not shown.

Binary file not shown.

View File

@@ -22,13 +22,13 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="top" />
<LinearLayout
android:id="@+id/debug_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:orientation="vertical"
android:paddingLeft="5dp" >
@@ -203,6 +203,7 @@
android:id="@+id/inliers"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
@@ -237,7 +238,20 @@
</LinearLayout>
<Button
<ToggleButton
android:id="@+id/light_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_above="@+id/first_person_button"
android:layout_alignLeft="@+id/first_person_button"
android:layout_alignParentRight="true"
android:layout_marginBottom="15dp"
android:layout_marginRight="5dp"
android:paddingRight="5dp"
android:textOff="@string/light_off"
android:textOn="@string/light_on" />
<ToggleButton
android:id="@+id/first_person_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
@@ -247,19 +261,10 @@
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:paddingRight="5dp"
android:text="@string/first_person" />
<Button
android:id="@+id/top_down_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="5dp"
android:paddingRight="5dp"
android:text="@string/top_down" />
<Button
android:textOff="@string/first_person"
android:textOn="@string/first_person" />
<ToggleButton
android:id="@+id/third_person_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
@@ -268,6 +273,29 @@
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:paddingRight="5dp"
android:text="@string/third_person" />
android:textOff="@string/third_person"
android:textOn="@string/third_person" />
<ToggleButton
android:id="@+id/top_down_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="5dp"
android:paddingRight="5dp"
android:textOff="@string/top_down"
android:textOn="@string/top_down" />
<ToggleButton
android:id="@+id/pause_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/first_person_button"
android:layout_alignParentTop="true"
android:layout_marginTop="61dp"
android:paddingRight="5dp"
android:textOff="@string/pause"
android:textOn="@string/resume" />
</RelativeLayout>

View File

@@ -0,0 +1,195 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/pref_title_rendering">
<ListPreference
android:key="@string/pref_key_decimation"
android:title="@string/pref_title_decimation"
android:summary="@string/pref_summary_decimation"
android:entries="@array/pref_decimation_keys"
android:entryValues="@array/pref_decimation_values"
android:defaultValue="@string/pref_default_decimation"/>
<ListPreference
android:key="@string/pref_key_depth"
android:title="@string/pref_title_depth"
android:summary="@string/pref_summary_depth"
android:entries="@array/pref_depth_keys"
android:entryValues="@array/pref_depth_values"
android:defaultValue="@string/pref_default_depth"/>
<ListPreference
android:key="@string/pref_key_point_size"
android:title="@string/pref_title_point_size"
android:summary="@string/pref_summary_point_size"
android:entries="@array/pref_point_size_values"
android:entryValues="@array/pref_point_size_values"
android:defaultValue="@string/pref_default_point_size"/>
<ListPreference
android:key="@string/pref_key_angle"
android:title="@string/pref_title_angle"
android:summary="@string/pref_summary_angle"
android:entries="@array/pref_angle_keys"
android:entryValues="@array/pref_angle_values"
android:defaultValue="@string/pref_default_angle"/>
<ListPreference
android:key="@string/pref_key_triangle"
android:title="@string/pref_title_triangle"
android:summary="@string/pref_summary_triangle"
android:entries="@array/pref_triangle_keys"
android:entryValues="@array/pref_triangle_values"
android:defaultValue="@string/pref_default_triangle"/>
<SwitchPreference
android:key="@string/pref_key_nodes_filtering"
android:title="@string/pref_title_nodes_filtering"
android:summary="@string/pref_summary_nodes_filtering"
android:defaultValue="@string/pref_default_nodes_filtering"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_title_mapping">
<PreferenceScreen
android:key="pref_button_mapping"
android:title="@string/pref_title_mapping"
android:summary="@string/pref_summary_mapping"
android:persistent="false">
<SwitchPreference
android:key="@string/pref_key_append"
android:title="@string/pref_title_append"
android:summary="@string/pref_summary_append"
android:defaultValue="@string/pref_default_append"/>
<SwitchPreference
android:key="@string/pref_key_drift_correction"
android:title="@string/pref_title_drift_correction"
android:summary="@string/pref_summary_drift_correction"
android:defaultValue="@string/pref_default_drift_correction"/>
<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"
android:defaultValue="@string/pref_default_resolution"/>
<ListPreference
android:key="@string/pref_key_update_rate"
android:title="@string/pref_title_update_rate"
android:summary="@string/pref_summary_update_rate"
android:entries="@array/pref_update_rate_keys"
android:entryValues="@array/pref_update_rate_values"
android:defaultValue="@string/pref_default_update_rate"/>
<ListPreference
android:key="@string/pref_key_time_thr"
android:title="@string/pref_title_time_thr"
android:summary="@string/pref_summary_time_thr"
android:entries="@array/pref_time_thr_keys"
android:entryValues="@array/pref_time_thr_values"
android:defaultValue="@string/pref_default_time_thr"/>
<ListPreference
android:key="@string/pref_key_loop_thr"
android:title="@string/pref_title_loop_thr"
android:summary="@string/pref_summary_loop_thr"
android:entries="@array/pref_loop_thr_keys"
android:entryValues="@array/pref_loop_thr_values"
android:defaultValue="@string/pref_default_loop_thr"/>
<ListPreference
android:key="@string/pref_key_opt_error"
android:title="@string/pref_title_opt_error"
android:summary="@string/pref_summary_opt_error"
android:entries="@array/pref_opt_error_keys"
android:entryValues="@array/pref_opt_error_values"
android:defaultValue="@string/pref_default_opt_error"/>
<ListPreference
android:key="@string/pref_key_features"
android:title="@string/pref_title_features"
android:summary="@string/pref_summary_features"
android:entries="@array/pref_features_keys"
android:entryValues="@array/pref_features_values"
android:defaultValue="@string/pref_default_features"/>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_title_export">
<PreferenceScreen
android:key="pref_button_export"
android:title="@string/pref_title_export"
android:summary="@string/pref_summary_export"
android:persistent="false">
<ListPreference
android:key="@string/pref_key_cloud_voxel"
android:title="@string/pref_title_cloud_voxel"
android:summary="@string/pref_summary_cloud_voxel"
android:entries="@array/pref_cloud_voxel_keys"
android:entryValues="@array/pref_cloud_voxel_values"
android:defaultValue="@string/pref_default_cloud_voxel"/>
<ListPreference
android:key="@string/pref_key_texture_size"
android:title="@string/pref_title_texture_size"
android:summary="@string/pref_summary_texture_size"
android:entries="@array/pref_texture_size_keys"
android:entryValues="@array/pref_texture_size_values"
android:defaultValue="@string/pref_default_texture_size"/>
<ListPreference
android:key="@string/pref_key_normal_k"
android:title="@string/pref_title_normal_k"
android:summary="@string/pref_summary_normal_k"
android:entries="@array/pref_normal_k_values"
android:entryValues="@array/pref_normal_k_values"
android:defaultValue="@string/pref_default_normal_k"/>
<SwitchPreference
android:key="@string/pref_key_block_render"
android:title="@string/pref_title_block_render"
android:summary="@string/pref_summary_block_render"
android:defaultValue="@string/pref_default_block_render"/>
<PreferenceCategory
android:title="@string/pref_title_optimized">
<ListPreference
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:entryValues="@array/pref_opt_depth_values"
android:defaultValue="@string/pref_default_opt_depth"/>
<ListPreference
android:key="@string/pref_key_opt_decimation_factor"
android:title="@string/pref_title_opt_decimation_factor"
android:summary="@string/pref_summary_opt_decimation_factor"
android:entries="@array/pref_opt_decimation_factor_keys"
android:entryValues="@array/pref_opt_decimation_factor_values"
android:defaultValue="@string/pref_default_opt_decimation_factor"/>
<ListPreference
android:key="@string/pref_key_opt_color_radius"
android:title="@string/pref_title_opt_color_radius"
android:summary="@string/pref_summary_opt_color_radius"
android:entries="@array/pref_opt_color_radius_keys"
android:entryValues="@array/pref_opt_color_radius_values"
android:defaultValue="@string/pref_default_opt_color_radius"/>
<SwitchPreference
android:key="@string/pref_key_opt_clean_white"
android:title="@string/pref_title_opt_clean_white"
android:summary="@string/pref_summary_opt_clean_white"
android:defaultValue="@string/pref_default_opt_clean_white"/>
</PreferenceCategory>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_title_general">
<Preference android:title="@string/pref_title_reset_button"
android:key="@string/pref_key_reset_button"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<WebView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/webv"/>
</LinearLayout>

View File

@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/group_pause" android:checkableBehavior="all">
<item android:id="@+id/pause" android:checked="false" android:title="Pause"/>
</group>
<group android:id="@+id/group_actions">
<item android:id="@+id/post_processing" android:title="Post-Processing...">
<group android:checkableBehavior="single">
<item android:id="@+id/point_cloud" android:title="Point Cloud" />
<item android:id="@+id/mesh" android:title="Mesh" />
<item android:id="@+id/texture_mesh" android:checked="true" android:title="Texture Mesh" />
</group>
<item android:id="@+id/save" android:title="Save" android:showAsAction="ifRoom"/>
<item android:id="@+id/post_processing" android:title="Optimize" android:showAsAction="ifRoom">
<menu>
<item android:id="@+id/post_processing_standard" android:title="Standard Optimization" />
<item android:id="@+id/post_processing_advanced" android:title="Advanced..." >
@@ -23,35 +25,30 @@
</item>
</menu>
</item>
<item android:id="@+id/open" android:title="Open"/>
<item android:id="@+id/export" android:title="Export...">
<item android:id="@+id/export" android:showAsAction="ifRoom" android:title="Export">
<menu>
<group android:id="@+id/group_export">
<item android:id="@+id/export_ply" android:title="Mesh (.ply)" />
<item android:id="@+id/export_obj" android:title="Mesh with texture (*.obj)" />
</group>
<item android:id="@+id/export_point_cloud" android:title="Point Cloud (*.ply)" />
<item android:id="@+id/export_mesh_menu" android:title="Raw Mesh..." >
<menu>
<item android:id="@+id/export_mesh" android:title="Colored Mesh (*.ply)" />
<item android:id="@+id/export_mesh_texture" android:title="Textured Mesh (*.obj)" />
</menu>
</item>
<item android:id="@+id/export_optimized_mesh_menu" android:title="Optimized Mesh..." >
<menu>
<item android:id="@+id/export_optimized_mesh" android:title="Colored Mesh (*.ply)" />
<item android:id="@+id/export_optimized_mesh_texture" android:title="Textured Mesh (*.obj)" />
</menu>
</item>
</menu>
</item>
<item android:id="@+id/save" android:title="Save"/>
<item android:id="@+id/reset" android:title="Reset"/>
<item android:id="@+id/menu_rendering_settings" android:title="Rendering Options...">
<item android:id="@+id/open" android:title="Open" android:showAsAction="ifRoom"/>
<item android:id="@+id/menu_rendering_settings" android:title="Visibility...">
<menu >
<group android:id="@+id/group_rendering_visibility" android:checkableBehavior="all">
<item android:id="@+id/debug" android:checked="false" android:title="Debug" />
<item android:id="@+id/menu_rendering" android:checkable="false" android:title="Mesh Rendering..." >
<menu>
<group android:checkableBehavior="single">
<item android:id="@+id/point_cloud" android:title="Point Cloud" />
<item android:id="@+id/mesh" android:title="Mesh" />
<item android:id="@+id/texture_mesh" android:checked="true" android:title="Texture Mesh" />
</group>
<item android:id="@+id/mesh_decimation" android:checkable="false" android:title="Mesh Decimation..." />
<item android:id="@+id/mesh_angle_tolerance" android:checkable="false" android:title="Mesh Angle Tolerance..." />
<item android:id="@+id/mesh_triangle_size" android:checkable="false" android:title="Mesh Triangle Size..." />
<item android:id="@+id/max_depth" android:checkable="false" android:title="Max Depth..." />
</menu>
</item>
<item android:id="@+id/map_shown" android:checked="true" android:title="Map Visible" />
<item android:id="@+id/odom_shown" android:checked="true" android:title="Odom Visible" />
<item android:id="@+id/graph_visible" android:checked="true" android:title="Graph Visible" />
@@ -60,30 +57,17 @@
</group>
</menu>
</item>
<item android:id="@+id/menu_mapping_settings" android:title="Mapping Options...">
<item android:id="@+id/modes" android:title="Modes...">
<menu >
<group android:id="@+id/group_mapping_visibility" android:checkableBehavior="all">
<item android:id="@+id/localization_mode" android:checked="false" android:title="Localization Mode" />
<item android:id="@+id/trajectory_mode" android:checked="false" android:title="Trajectory Mode" />
<item android:id="@+id/append" android:checked="true" android:title="Append Mode" />
<item android:id="@+id/nodes_filtering" android:checked="false" android:title="Nodes Filtering" />
<item android:id="@+id/drift_correction" android:checked="false" android:title="Drift Correction" />
<item android:id="@+id/auto_exposure" android:checked="true" android:title="Auto Exposure" />
<item android:id="@+id/resolution" android:checked="false" android:title="HD Mode" />
<item android:id="@+id/data_recorder" android:checked="false" android:title="Data Recorder Mode" />
<item android:id="@+id/menu_param_settings" android:checkable="false" android:title="Parameters...">
<menu >
<item android:id="@+id/update_rate" android:title="Map Update Rate..." />
<item android:id="@+id/time_threshold" android:title="Time Threshold..." />
<item android:id="@+id/loop_threshold" android:title="Loop Closure Threshold..." />
<item android:id="@+id/optimize_error" android:title="Max Optimization Error..." />
<item android:id="@+id/features" android:title="Max Features Extracted..." />
</menu>
</item>
</group>
</menu>
</item>
<item android:id="@+id/settings" android:title="Settings"/>
<item android:id="@+id/reset" android:title="Reset"/>
<item android:id="@+id/about" android:title="About"/>
</group>
</menu>

View File

@@ -3,11 +3,17 @@
<string name="app_name">RTAB-Map</string>
<string name="sys_name">RTAB-Map</string>
<string name="menu_name">Real-Time Appearance-Based Mapping</string>
<string name="settings">Settings</string>
<string name="dropbox">Dropbox</string>
<string name="status">"Status: "</string>
<string name="words">"Words: "</string>
<string name="first_person">First</string>
<string name="third_person">Third</string>
<string name="top_down">Top</string>
<string name="pause">Pause</string>
<string name="resume">Paused</string>
<string name="light_on">Lighting</string>
<string name="light_off">Lighting</string>
<string name="start">Start</string>
<string name="nodes">"Nodes (WM): "</string>
<string name="points">"Number of points: "</string>
@@ -21,5 +27,392 @@
<string name="memory">"Memory (MB): "</string>
<string name="hypothesis">"Hypothesis: "</string>
<string name="fps">"FPS (rendering): "</string>
<!-- Preference keys: BEGIN -->
<string name="pref_key_rendering">pref_key_rendering</string><string name="pref_default_rendering">2</string>
<string name="pref_key_reset_button">pref_key_reset_button</string>
<string name="pref_key_decimation">pref_key_decimation</string> <string name="pref_default_decimation">0</string>
<string name="pref_key_depth">pref_key_depth</string> <string name="pref_default_depth">0</string>
<string name="pref_key_point_size">pref_key_point_size</string> <string name="pref_default_point_size">5</string>
<string name="pref_key_angle">pref_key_angle</string> <string name="pref_default_angle">15</string>
<string name="pref_key_triangle">pref_key_triangle</string> <string name="pref_default_triangle">2</string>
<string name="pref_key_nodes_filtering">pref_key_nodes_filtering</string> <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_drift_correction">pref_key_drift_correction</string> <string name="pref_default_drift_correction">false</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_update_rate">pref_key_update_rate</string> <string name="pref_default_update_rate">1</string>
<string name="pref_key_time_thr">pref_key_time_thr</string> <string name="pref_default_time_thr">800</string>
<string name="pref_key_loop_thr">pref_key_loop_thr</string> <string name="pref_default_loop_thr">0.11</string>
<string name="pref_key_opt_error">pref_key_opt_error</string> <string name="pref_default_opt_error">0.1</string>
<string name="pref_key_features">pref_key_features</string> <string name="pref_default_features">200</string>
<string name="pref_key_cloud_voxel">pref_key_cloud_voxel</string> <string name="pref_default_cloud_voxel">0</string>
<string name="pref_key_texture_size">pref_key_texture_size</string> <string name="pref_default_texture_size">4096</string>
<string name="pref_key_normal_k">pref_key_normal_k</string> <string name="pref_default_normal_k">6</string>
<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_key_opt_decimation_factor">pref_key_opt_decimation_factor</string><string name="pref_default_opt_decimation_factor">80</string>
<string name="pref_key_opt_color_radius">pref_key_opt_color_radius</string> <string name="pref_default_opt_color_radius">0.0</string>
<string name="pref_key_opt_clean_white">pref_key_opt_clean_white</string> <string name="pref_default_opt_clean_white">true</string>
<!-- Preference keys: END-->
<string name="pref_title_rendering">Rendering</string>
<string name="pref_title_decimation">Mesh Decimation</string>
<string name="pref_summary_decimation">Decimate the cloud size to reduce rendering time and memory.</string>
<string name="pref_title_angle">Mesh Angle Tolerance</string>
<string name="pref_summary_angle">Minimum polygon angle.</string>
<string name="pref_title_triangle">Mesh Triangle Size</string>
<string name="pref_summary_triangle">Size in pixels of the polygons created from the depth image.</string>
<string name="pref_title_depth">Max Depth</string>
<string name="pref_summary_depth">Points over the maximum depth are not rendered.</string>
<string name="pref_title_point_size">Point Size</string>
<string name="pref_summary_point_size">Size of the points when rendering only the point cloud.</string>
<string name="pref_title_nodes_filtering">Nodes Filtering</string>
<string name="pref_summary_nodes_filtering">Hide close point clouds from rendering.</string>
<string-array name="pref_decimation_keys">
<item>"High"</item>
<item>"Medium"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_decimation_values">
<item>"2"</item>
<item>"1"</item>
<item>"0"</item>
</string-array>
<string-array name="pref_depth_keys">
<item>"No Limit"</item>
<item>"5"</item>
<item>"4"</item>
<item>"3"</item>
<item>"2"</item>
<item>"1"</item>
</string-array>
<string-array name="pref_depth_values">
<item>"0"</item>
<item>"5"</item>
<item>"4"</item>
<item>"3"</item>
<item>"2"</item>
<item>"1"</item>
</string-array>
<string-array name="pref_point_size_values">
<item>"50"</item>
<item>"30"</item>
<item>"25"</item>
<item>"15"</item>
<item>"5"</item>
<item>"1"</item>
</string-array>
<string-array name="pref_angle_keys">
<item>"30 deg"</item>
<item>"25 deg"</item>
<item>"20 deg"</item>
<item>"15 deg"</item>
<item>"10 deg"</item>
<item>"5 deg"</item>
</string-array>
<string-array name="pref_angle_values">
<item>"30"</item>
<item>"25"</item>
<item>"20"</item>
<item>"15"</item>
<item>"10"</item>
<item>"5"</item>
</string-array>
<string-array name="pref_triangle_keys">
<item>"6 pix"</item>
<item>"5 pix"</item>
<item>"4 pix"</item>
<item>"3 pix"</item>
<item>"2 pix"</item>
</string-array>
<string-array name="pref_triangle_values">
<item>"6"</item>
<item>"5"</item>
<item>"4"</item>
<item>"3"</item>
<item>"2"</item>
</string-array>
<string name="pref_title_mapping">Mapping</string>
<string name="pref_summary_mapping">Advanced mapping parameters for fine tuning.</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_drift_correction">Drift Correction</string>
<string name="pref_summary_drift_correction">Iterative-closest-point (ICP) is done to refine geometrically the links in the map. Use only when environment is highly geometric. Camera should move slowly.</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 if you want very detailed textures. More memory will be required.</string>
<string name="pref_title_update_rate">Update Rate</string>
<string name="pref_summary_update_rate">Rate at which a new node is added to map.</string>
<string name="pref_title_time_thr">Time Limit</string>
<string name="pref_summary_time_thr">Maximum time allowed for map updates. If time to add a new node is above this theshold, some old parts of the map are temporarly forgotten to reduce time of next updates.</string>
<string name="pref_title_loop_thr">Loop Closure Threshold</string>
<string name="pref_summary_loop_thr">Threshold at which loop closure hypotheses are accepted. Higher means more robust to false loop closures while rejecting more good loop closures.</string>
<string name="pref_title_opt_error">Max Optimization Error</string>
<string name="pref_summary_opt_error">Reject any loop closures causing error corrections in the map higher than this threshold.</string>
<string name="pref_title_features">Max Features Extracted</string>
<string name="pref_summary_features">Extracting more features per image would result in better loop closure detection but more processing time required.</string>
<string-array name="pref_update_rate_keys">
<item>"Max"</item>
<item>"5 Hz"</item>
<item>"4 Hz"</item>
<item>"3 Hz"</item>
<item>"2 Hz"</item>
<item>"1 Hz"</item>
<item>"0.5 Hz"</item>
</string-array>
<string-array name="pref_update_rate_values">
<item>"0"</item>
<item>"5"</item>
<item>"4"</item>
<item>"3"</item>
<item>"2"</item>
<item>"1"</item>
<item>"0.5"</item>
</string-array>
<string-array name="pref_time_thr_keys">
<item>"No Limit"</item>
<item>"1500 ms"</item>
<item>"1400 ms"</item>
<item>"1300 ms"</item>
<item>"1200 ms"</item>
<item>"1100 ms"</item>
<item>"1000 ms"</item>
<item>"900 ms"</item>
<item>"800 ms"</item>
<item>"700 ms"</item>
<item>"600 ms"</item>
<item>"500 ms"</item>
<item>"400"</item>
</string-array>
<string-array name="pref_time_thr_values">
<item>"0"</item>
<item>"1500"</item>
<item>"1400"</item>
<item>"1300"</item>
<item>"1200"</item>
<item>"1100"</item>
<item>"1000"</item>
<item>"900"</item>
<item>"800"</item>
<item>"700"</item>
<item>"600"</item>
<item>"500"</item>
<item>"400"</item>
</string-array>
<string-array name="pref_loop_thr_keys">
<item>"0.90"</item>
<item>"0.80"</item>
<item>"0.70"</item>
<item>"0.60"</item>
<item>"0.50"</item>
<item>"0.40"</item>
<item>"0.30"</item>
<item>"0.20"</item>
<item>"0.11"</item>
</string-array>
<string-array name="pref_loop_thr_values">
<item>"0.90"</item>
<item>"0.80"</item>
<item>"0.70"</item>
<item>"0.60"</item>
<item>"0.50"</item>
<item>"0.40"</item>
<item>"0.30"</item>
<item>"0.20"</item>
<item>"0.11"</item>
</string-array>
<string-array name="pref_opt_error_keys">
<item>"1.0 m"</item>
<item>"0.5 m"</item>
<item>"0.35 m"</item>
<item>"0.2 m"</item>
<item>"0.1 m"</item>
<item>"0.05 m"</item>
<item>"0.025 m"</item>
<item>"0.01 m"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_opt_error_values">
<item>"1.0"</item>
<item>"0.5"</item>
<item>"0.35"</item>
<item>"0.2"</item>
<item>"0.1"</item>
<item>"0.05"</item>
<item>"0.025"</item>
<item>"0.01"</item>
<item>"0"</item>
</string-array>
<string-array name="pref_features_keys">
<item>"No Limit"</item>
<item>"1000"</item>
<item>"900"</item>
<item>"800"</item>
<item>"700"</item>
<item>"600"</item>
<item>"500"</item>
<item>"400"</item>
<item>"300"</item>
<item>"200"</item>
<item>"100"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_features_values">
<item>"0"</item>
<item>"1000"</item>
<item>"900"</item>
<item>"800"</item>
<item>"700"</item>
<item>"600"</item>
<item>"500"</item>
<item>"400"</item>
<item>"300"</item>
<item>"200"</item>
<item>"100"</item>
<item>"-1"</item>
</string-array>
<string name="pref_title_export">Exporting</string>
<string name="pref_summary_export">Advanced parameters used when exporting the map.</string>
<string name="pref_title_cloud_voxel">Voxel Size</string>
<string name="pref_summary_cloud_voxel">If you don\'t need a very precise point cloud, you can set this to reduce the output point cloud size. This is also used for optimized mesh.</string>
<string name="pref_title_texture_size">Texture Size</string>
<string name="pref_summary_texture_size">If the map is large, you may want to increase this to maximize the texture resolution.</string>
<string name="pref_title_normal_k">Normal K</string>
<string name="pref_summary_normal_k">K-nearest neighbors used for normal computation when a mesh is created.</string>
<string name="pref_title_block_render">Block Rendering Thread While Exporting</string>
<string name="pref_summary_block_render">This decreases exporting time, but freezes rendering while exporting.</string>
<string-array name="pref_cloud_voxel_keys">
<item>"0.2 m"</item>
<item>"0.1 m"</item>
<item>"0.05 m"</item>
<item>"0.02 m"</item>
<item>"0.01 m"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_cloud_voxel_values">
<item>"0.2"</item>
<item>"0.1"</item>
<item>"0.05"</item>
<item>"0.02"</item>
<item>"0.01"</item>
<item>"0"</item>
</string-array>
<string-array name="pref_texture_size_keys">
<item>"16384x16384"</item>
<item>"8192x8192"</item>
<item>"4096x4096"</item>
<item>"2048x2048"</item>
<item>"1024x1024"</item>
</string-array>
<string-array name="pref_texture_size_values">
<item>"16384"</item>
<item>"8192"</item>
<item>"4096"</item>
<item>"2048"</item>
<item>"1024"</item>
</string-array>
<string-array name="pref_normal_k_values">
<item>"30"</item>
<item>"24"</item>
<item>"18"</item>
<item>"12"</item>
<item>"6"</item>
</string-array>
<string name="pref_title_optimized">Optimized</string>
<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_title_opt_decimation_factor">Mesh Decimation Factor</string>
<string name="pref_summary_opt_decimation_factor">Reduce the number of the output polygons on plane areas by this factor. This also reduces texture projection time.</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.</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_values">
<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_decimation_factor_keys">
<item>"90%"</item>
<item>"80%"</item>
<item>"70%"</item>
<item>"60%"</item>
<item>"50%"</item>
<item>"40%"</item>
<item>"30%"</item>
<item>"20%"</item>
<item>"10%"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_opt_decimation_factor_values">
<item>"90"</item>
<item>"80"</item>
<item>"70"</item>
<item>"60"</item>
<item>"50"</item>
<item>"40"</item>
<item>"30"</item>
<item>"20"</item>
<item>"20"</item>
<item>"0"</item>
</string-array>
<string-array name="pref_opt_color_radius_keys">
<item>"Nearest"</item>
<item>"2 m"</item>
<item>"1 m"</item>
<item>"0.5 m"</item>
<item>"0.2 m"</item>
<item>"0.05 m"</item>
<item>"0.01 m"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_opt_color_radius_values">
<item>"0"</item>
<item>"2"</item>
<item>"1"</item>
<item>"0.5"</item>
<item>"0.2"</item>
<item>"0.05"</item>
<item>"0.01"</item>
<item>"-1"</item>
</string-array>
<string name="pref_title_general">General</string>
<string name="pref_title_reset_button">Restore All Default Settings</string>
</resources>

View File

@@ -0,0 +1,148 @@
package com.introlab.rtabmap;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/**
* This utility class provides an abstraction layer for sending multipart HTTP
* POST requests to a web server.
* @author www.codejava.net
* http://www.codejava.net/java-se/networking/upload-files-by-sending-multipart-request-programmatically
*
*/
public class MultipartUtility {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private HttpURLConnection httpConn;
private String charset;
private OutputStream outputStream;
private PrintWriter writer;
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
* @param requestURL
* @param charset
* @throws IOException
*/
public MultipartUtility(String requestURL, String token, String charset)
throws IOException {
this.charset = charset;
// creates a unique boundary based on time stamp
boundary = "===" + System.currentTimeMillis() + "===";
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
httpConn.setRequestProperty("Authorization", "Bearer " + token);
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
true);
}
/**
* Adds a form field to the request
* @param name field name
* @param value field value
*/
public void addFormField(String name, String value) {
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + name + "\"").append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=" + charset).append(LINE_FEED);
writer.append(LINE_FEED);
writer.append(value).append(LINE_FEED);
writer.flush();
}
/**
* Adds a upload file section to the request
* @param fieldName name attribute in <input type="file" name="..." />
* @param uploadFile a File to be uploaded
* @throws IOException
*/
public void addFilePart(String fieldName, File uploadFile)
throws IOException {
String fileName = uploadFile.getName();
writer.append("--" + boundary).append(LINE_FEED);
writer.append(
"Content-Disposition: form-data; name=\"" + fieldName
+ "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
writer.append(
"Content-Type: "
+ URLConnection.guessContentTypeFromName(fileName))
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
writer.append(LINE_FEED);
writer.flush();
}
/**
* Adds a header field to the request.
* @param name - name of the header field
* @param value - value of the header field
*/
public void addHeaderField(String name, String value) {
writer.append(name + ": " + value).append(LINE_FEED);
writer.flush();
}
/**
* Completes the request and receives response from the server.
* @return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* @throws IOException
*/
public List<String> finish() throws IOException {
List<String> response = new ArrayList<String>();
writer.append(LINE_FEED).flush();
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.close();
// checks server's status code first
int status = httpConn.getResponseCode();
if (status == 201) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpConn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
response.add(line);
}
reader.close();
httpConn.disconnect();
} else {
throw new IOException("Server returned non-OK status: " + status + ", msg: " + httpConn.getResponseMessage());
}
return response;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -72,6 +72,8 @@ public class RTABMapLib
public static native void setAppendMode(boolean enabled);
public static native void setDataRecorderMode(boolean enabled);
public static native void setMaxCloudDepth(float value);
public static native void setPointSize(float value);
public static native void setLighting(boolean enabled);
public static native void setMeshDecimation(int value);
public static native void setMeshAngleTolerance(float value);
public static native void setMeshTriangleSize(int value);
@@ -79,7 +81,21 @@ public class RTABMapLib
public static native void resetMapping();
public static native void save(String outputDatabasePath);
public static native boolean exportMesh(String filePath);
public static native boolean exportMesh(
String filePath,
float cloudVoxelSize,
boolean meshing,
int textureSize,
int normalK,
boolean optimized,
float optimizedVoxelSize,
int optimizedDepth,
float optimizedDecimationFactor,
float optimizedColorRadius,
boolean optimizedCleanWhitePolygons,
boolean optimizedColorWhitePolygons,
boolean blockRendering);
public static native boolean postExportation(boolean visualize);
public static native int postProcessing(int approach);
public static native String getStatus();

View File

@@ -0,0 +1,95 @@
package com.introlab.rtabmap;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.activity_settings);
Preference button = findPreference(getString(R.string.pref_key_reset_button));
button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
getPreferenceScreen().getSharedPreferences().edit().clear().commit();
recreate();
return true;
}
});
((Preference)findPreference(getString(R.string.pref_key_decimation))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_decimation))).getEntry() + ") "+getString(R.string.pref_summary_decimation));
((Preference)findPreference(getString(R.string.pref_key_depth))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_depth))).getEntry() + ") "+getString(R.string.pref_summary_depth));
((Preference)findPreference(getString(R.string.pref_key_point_size))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_point_size))).getEntry() + ") "+getString(R.string.pref_summary_point_size));
((Preference)findPreference(getString(R.string.pref_key_angle))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_angle))).getEntry() + ") "+getString(R.string.pref_summary_angle));
((Preference)findPreference(getString(R.string.pref_key_triangle))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_triangle))).getEntry() + ") "+getString(R.string.pref_summary_triangle));
((Preference)findPreference(getString(R.string.pref_key_update_rate))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_update_rate))).getEntry() + ") "+getString(R.string.pref_summary_update_rate));
((Preference)findPreference(getString(R.string.pref_key_time_thr))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_time_thr))).getEntry() + ") "+getString(R.string.pref_summary_time_thr));
((Preference)findPreference(getString(R.string.pref_key_loop_thr))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_loop_thr))).getEntry() + ") "+getString(R.string.pref_summary_loop_thr));
((Preference)findPreference(getString(R.string.pref_key_opt_error))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_error))).getEntry() + ") "+getString(R.string.pref_summary_opt_error));
((Preference)findPreference(getString(R.string.pref_key_features))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_features))).getEntry() + ") "+getString(R.string.pref_summary_features));
((Preference)findPreference(getString(R.string.pref_key_cloud_voxel))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_cloud_voxel))).getEntry() + ") "+getString(R.string.pref_summary_cloud_voxel));
((Preference)findPreference(getString(R.string.pref_key_texture_size))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_texture_size))).getEntry() + ") "+getString(R.string.pref_summary_texture_size));
((Preference)findPreference(getString(R.string.pref_key_normal_k))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_normal_k))).getEntry() + ") "+getString(R.string.pref_summary_normal_k));
((Preference)findPreference(getString(R.string.pref_key_opt_depth))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_depth))).getEntry() + ") "+getString(R.string.pref_summary_opt_depth));
((Preference)findPreference(getString(R.string.pref_key_opt_decimation_factor))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_decimation_factor))).getValue() + "%%) "+getString(R.string.pref_summary_opt_decimation_factor));
((Preference)findPreference(getString(R.string.pref_key_opt_color_radius))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_color_radius))).getEntry() + ") "+getString(R.string.pref_summary_opt_color_radius));
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
if(key.compareTo(getString(R.string.pref_key_decimation))==0) pref.setSummary("("+ ((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_decimation));
if(key.compareTo(getString(R.string.pref_key_depth))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_depth));
if(key.compareTo(getString(R.string.pref_key_point_size))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_point_size));
if(key.compareTo(getString(R.string.pref_key_angle))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_angle));
if(key.compareTo(getString(R.string.pref_key_triangle))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_triangle));
if(key.compareTo(getString(R.string.pref_key_update_rate))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_update_rate));
if(key.compareTo(getString(R.string.pref_key_time_thr))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_time_thr));
if(key.compareTo(getString(R.string.pref_key_loop_thr))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_loop_thr));
if(key.compareTo(getString(R.string.pref_key_opt_error))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_opt_error));
if(key.compareTo(getString(R.string.pref_key_features))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_features));
if(key.compareTo(getString(R.string.pref_key_cloud_voxel))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_cloud_voxel));
if(key.compareTo(getString(R.string.pref_key_texture_size))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_texture_size));
if(key.compareTo(getString(R.string.pref_key_normal_k))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_normal_k));
if(key.compareTo(getString(R.string.pref_key_opt_depth))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_opt_depth));
if(key.compareTo(getString(R.string.pref_key_opt_decimation_factor))==0) pref.setSummary("("+((ListPreference)pref).getValue() + "%%) "+getString(R.string.pref_summary_opt_decimation_factor));
if(key.compareTo(getString(R.string.pref_key_opt_color_radius))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_opt_color_radius));
}
}
@Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
}