mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-04 00:37:46 +08:00
Tango: added multi-texturing support (#189)
This commit is contained in:
+122
-39
@@ -1873,14 +1873,15 @@ double sqr(uchar v)
|
|||||||
return double(v)*double(v);
|
return double(v)*double(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::Mat RTABMapApp::mergeTextures(
|
std::vector<cv::Mat> RTABMapApp::mergeTextures(
|
||||||
pcl::TextureMesh & mesh,
|
pcl::TextureMesh & mesh,
|
||||||
int textureSize,
|
int textureSize,
|
||||||
|
int textureCount,
|
||||||
const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels) const
|
const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels) const
|
||||||
{
|
{
|
||||||
UASSERT(textureSize> 0);
|
UASSERT(textureSize> 0);
|
||||||
LOGD("textureSize = %d materials=%d", textureSize, mesh.tex_materials.size());
|
LOGD("textureSize = %d textureCount=%d materials=%d", textureSize, textureCount, mesh.tex_materials.size());
|
||||||
cv::Mat globalTexture;
|
std::vector<cv::Mat> globalTextures;
|
||||||
if(mesh.tex_materials.size() >= 1)
|
if(mesh.tex_materials.size() >= 1)
|
||||||
{
|
{
|
||||||
std::vector<int> textures(mesh.tex_materials.size(), -1);
|
std::vector<int> textures(mesh.tex_materials.size(), -1);
|
||||||
@@ -1914,14 +1915,19 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
{
|
{
|
||||||
float scale = 0.0f;
|
float scale = 0.0f;
|
||||||
std::vector<bool> materialsKept;
|
std::vector<bool> materialsKept;
|
||||||
rtabmap::util3d::concatenateTextureMaterials(mesh, imageSize, textureSize, 1, scale, &materialsKept);
|
rtabmap::util3d::concatenateTextureMaterials(mesh, imageSize, textureSize, textureCount, scale, &materialsKept);
|
||||||
LOGD("scale=%f materials=%d", scale, (int)mesh.tex_materials.size());
|
LOGD("scale=%f materials=%d", scale, (int)mesh.tex_materials.size());
|
||||||
if(scale && mesh.tex_materials.size()==1)
|
if(scale && mesh.tex_materials.size())
|
||||||
{
|
{
|
||||||
|
int materials = (int)mesh.tex_materials.size();
|
||||||
int cols = float(textureSize)/(scale*imageSize.width);
|
int cols = float(textureSize)/(scale*imageSize.width);
|
||||||
|
int rows = float(textureSize)/(scale*imageSize.height);
|
||||||
|
|
||||||
globalTexture = cv::Mat(textureSize, textureSize, imageType, cv::Scalar::all(255));
|
globalTextures.resize(materials);
|
||||||
cv::Mat globalTextureMask = cv::Mat(textureSize, textureSize, CV_8UC1, cv::Scalar::all(0));
|
for(int i=0; i<materials; ++i)
|
||||||
|
{
|
||||||
|
globalTextures[i] = cv::Mat(textureSize, textureSize, imageType, cv::Scalar::all(255));
|
||||||
|
}
|
||||||
|
|
||||||
// make a blank texture
|
// make a blank texture
|
||||||
cv::Mat emptyImage(int(imageSize.height*scale), int(imageSize.width*scale), imageType, cv::Scalar::all(255));
|
cv::Mat emptyImage(int(imageSize.height*scale), int(imageSize.width*scale), imageType, cv::Scalar::all(255));
|
||||||
@@ -1933,8 +1939,11 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
{
|
{
|
||||||
if(materialsKept.at(i))
|
if(materialsKept.at(i))
|
||||||
{
|
{
|
||||||
|
int indexMaterial = oi / (cols*rows);
|
||||||
|
UASSERT(indexMaterial < materials);
|
||||||
|
|
||||||
int u = oi%cols * emptyImage.cols;
|
int u = oi%cols * emptyImage.cols;
|
||||||
int v = oi/cols * emptyImage.rows;
|
int v = ((oi/cols) % rows ) * emptyImage.rows;
|
||||||
UASSERT(u < textureSize-emptyImage.cols);
|
UASSERT(u < textureSize-emptyImage.cols);
|
||||||
UASSERT(v < textureSize-emptyImage.rows);
|
UASSERT(v < textureSize-emptyImage.rows);
|
||||||
newCamIndex[i] = oi;
|
newCamIndex[i] = oi;
|
||||||
@@ -1967,13 +1976,12 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
cv::cvtColor(resizedImage,resizedImageColor,CV_GRAY2RGB);
|
cv::cvtColor(resizedImage,resizedImageColor,CV_GRAY2RGB);
|
||||||
resizedImage = resizedImageColor;
|
resizedImage = resizedImageColor;
|
||||||
}
|
}
|
||||||
UASSERT(resizedImage.type() == globalTexture.type());
|
UASSERT(resizedImage.type() == globalTextures[indexMaterial].type());
|
||||||
resizedImage.copyTo(globalTexture(cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
|
resizedImage.copyTo(globalTextures[indexMaterial](cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
|
||||||
emptyImageMask.copyTo(globalTextureMask(cv::Rect(u, v, emptyImageMask.cols, emptyImageMask.rows)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
emptyImage.copyTo(globalTexture(cv::Rect(u, v, emptyImage.cols, emptyImage.rows)));
|
emptyImage.copyTo(globalTextures[indexMaterial](cv::Rect(u, v, emptyImage.cols, emptyImage.rows)));
|
||||||
}
|
}
|
||||||
++oi;
|
++oi;
|
||||||
}
|
}
|
||||||
@@ -1988,6 +1996,7 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
|
|
||||||
if(vertexToPixels.size())
|
if(vertexToPixels.size())
|
||||||
{
|
{
|
||||||
|
LOGD("gain compensation");
|
||||||
// gain compensation
|
// gain compensation
|
||||||
const int num_images = static_cast<int>(oi);
|
const int num_images = static_cast<int>(oi);
|
||||||
cv::Mat_<int> N(num_images, num_images); N.setTo(0);
|
cv::Mat_<int> N(num_images, num_images); N.setTo(0);
|
||||||
@@ -2019,13 +2028,15 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
N(i, j) += 1;
|
N(i, j) += 1;
|
||||||
N(j, i) += 1;
|
N(j, i) += 1;
|
||||||
|
|
||||||
|
int indexMaterial = i / (cols*rows);
|
||||||
|
|
||||||
// uv in globalTexture
|
// uv in globalTexture
|
||||||
int ui = iter->second.x*emptyImage.cols + imageOrigin[iter->first].x;
|
int ui = iter->second.x*emptyImage.cols + imageOrigin[iter->first].x;
|
||||||
int vi = (1.0-iter->second.y)*emptyImage.rows + imageOrigin[iter->first].y;
|
int vi = (1.0-iter->second.y)*emptyImage.rows + imageOrigin[iter->first].y;
|
||||||
int uj = jter->second.x*emptyImage.cols + imageOrigin[jter->first].x;
|
int uj = jter->second.x*emptyImage.cols + imageOrigin[jter->first].x;
|
||||||
int vj = (1.0-jter->second.y)*emptyImage.rows + imageOrigin[jter->first].y;
|
int vj = (1.0-jter->second.y)*emptyImage.rows + imageOrigin[jter->first].y;
|
||||||
cv::Vec3b * pt1 = globalTexture.ptr<cv::Vec3b>(vi,ui);
|
cv::Vec3b * pt1 = globalTextures[indexMaterial].ptr<cv::Vec3b>(vi,ui);
|
||||||
cv::Vec3b * pt2 = globalTexture.ptr<cv::Vec3b>(vj,uj);
|
cv::Vec3b * pt2 = globalTextures[indexMaterial].ptr<cv::Vec3b>(vj,uj);
|
||||||
|
|
||||||
I(i, j) += std::sqrt(static_cast<double>(sqr(pt1->val[0]) + sqr(pt1->val[1]) + sqr(pt1->val[2])));
|
I(i, j) += std::sqrt(static_cast<double>(sqr(pt1->val[0]) + sqr(pt1->val[1]) + sqr(pt1->val[2])));
|
||||||
I(j, i) += std::sqrt(static_cast<double>(sqr(pt2->val[0]) + sqr(pt2->val[1]) + sqr(pt2->val[2])));
|
I(j, i) += std::sqrt(static_cast<double>(sqr(pt2->val[0]) + sqr(pt2->val[1]) + sqr(pt2->val[2])));
|
||||||
@@ -2044,9 +2055,16 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
|
|
||||||
for(int i=0; i<num_images; ++i)
|
for(int i=0; i<num_images; ++i)
|
||||||
{
|
{
|
||||||
for(int j=i+1; j<num_images; ++j)
|
for(int j=i; j<num_images; ++j)
|
||||||
{
|
{
|
||||||
if(N(i, j))
|
if(i == j)
|
||||||
|
{
|
||||||
|
if(N(i,j) == 0)
|
||||||
|
{
|
||||||
|
N(i,j) = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(N(i, j))
|
||||||
{
|
{
|
||||||
I(i, j) /= N(i, j);
|
I(i, j) /= N(i, j);
|
||||||
I(j, i) /= N(j, i);
|
I(j, i) /= N(j, i);
|
||||||
@@ -2113,7 +2131,8 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
int u = imageOrigin[t].x;
|
int u = imageOrigin[t].x;
|
||||||
int v = imageOrigin[t].y;
|
int v = imageOrigin[t].y;
|
||||||
|
|
||||||
cv::Mat roi = globalTexture(cv::Rect(u, v, emptyImage.cols, emptyImage.rows));
|
int indexMaterial = newCamIndex[t] / (cols*rows);
|
||||||
|
cv::Mat roi = globalTextures[indexMaterial](cv::Rect(u, v, emptyImage.cols, emptyImage.rows));
|
||||||
|
|
||||||
std::vector<cv::Mat> channels;
|
std::vector<cv::Mat> channels;
|
||||||
cv::split(roi, channels);
|
cv::split(roi, channels);
|
||||||
@@ -2127,6 +2146,7 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
progressionStatus_.increment();
|
progressionStatus_.increment();
|
||||||
|
|
||||||
// blending BGR
|
// blending BGR
|
||||||
|
LOGD("blending");
|
||||||
int decimation = 0;
|
int decimation = 0;
|
||||||
|
|
||||||
// determinate decimation to apply
|
// determinate decimation to apply
|
||||||
@@ -2168,7 +2188,13 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
|
|
||||||
if(decimation>0)
|
if(decimation>0)
|
||||||
{
|
{
|
||||||
cv::Mat blendGains(globalTexture.rows/decimation, globalTexture.cols/decimation, CV_32FC3, cv::Scalar::all(1.0f));
|
LOGD("blending decimation=%d", decimation);
|
||||||
|
std::vector<cv::Mat> blendGains(materials);
|
||||||
|
for(int i=0; i<materials;++i)
|
||||||
|
{
|
||||||
|
blendGains[i] = cv::Mat(globalTextures[i].rows/decimation, globalTextures[i].cols/decimation, CV_32FC3, cv::Scalar::all(1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
for(unsigned int p=0; p<vertexToPixels.size(); ++p)
|
for(unsigned int p=0; p<vertexToPixels.size(); ++p)
|
||||||
{
|
{
|
||||||
if(vertexToPixels[p].size() > 1)
|
if(vertexToPixels[p].size() > 1)
|
||||||
@@ -2191,7 +2217,8 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
{
|
{
|
||||||
weight = 0.0f;
|
weight = 0.0f;
|
||||||
}
|
}
|
||||||
cv::Vec3b * pt = globalTexture.ptr<cv::Vec3b>(v,u);
|
int indexMaterial = newCamIndex[iter->first] / (cols*rows);
|
||||||
|
cv::Vec3b * pt = globalTextures[indexMaterial].ptr<cv::Vec3b>(v,u);
|
||||||
gainsB[k] = static_cast<double>(pt->val[0]) * weight;
|
gainsB[k] = static_cast<double>(pt->val[0]) * weight;
|
||||||
gainsG[k] = static_cast<double>(pt->val[1]) * weight;
|
gainsG[k] = static_cast<double>(pt->val[1]) * weight;
|
||||||
gainsR[k] = static_cast<double>(pt->val[2]) * weight;
|
gainsR[k] = static_cast<double>(pt->val[2]) * weight;
|
||||||
@@ -2215,11 +2242,12 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
{
|
{
|
||||||
int u = iter->second.x*emptyImage.cols + imageOrigin[iter->first].x;
|
int u = iter->second.x*emptyImage.cols + imageOrigin[iter->first].x;
|
||||||
int v = (1.0-iter->second.y)*emptyImage.rows + imageOrigin[iter->first].y;
|
int v = (1.0-iter->second.y)*emptyImage.rows + imageOrigin[iter->first].y;
|
||||||
cv::Vec3b * pt = globalTexture.ptr<cv::Vec3b>(v,u);
|
int indexMaterial = newCamIndex[iter->first] / (cols*rows);
|
||||||
|
cv::Vec3b * pt = globalTextures[indexMaterial].ptr<cv::Vec3b>(v,u);
|
||||||
float gB = targetColor[0]/(pt->val[0]==0?1.0f:pt->val[0]);
|
float gB = targetColor[0]/(pt->val[0]==0?1.0f:pt->val[0]);
|
||||||
float gG = targetColor[1]/(pt->val[1]==0?1.0f:pt->val[1]);
|
float gG = targetColor[1]/(pt->val[1]==0?1.0f:pt->val[1]);
|
||||||
float gR = targetColor[2]/(pt->val[2]==0?1.0f:pt->val[2]);
|
float gR = targetColor[2]/(pt->val[2]==0?1.0f:pt->val[2]);
|
||||||
cv::Vec3f * ptr = blendGains.ptr<cv::Vec3f>(v/decimation, u/decimation);
|
cv::Vec3f * ptr = blendGains[indexMaterial].ptr<cv::Vec3f>(v/decimation, u/decimation);
|
||||||
ptr->val[0] = (gB>1.3f)?1.3f:(gB<0.7f)?0.7f:gB;
|
ptr->val[0] = (gB>1.3f)?1.3f:(gB<0.7f)?0.7f:gB;
|
||||||
ptr->val[1] = (gG>1.3f)?1.3f:(gG<0.7f)?0.7f:gG;
|
ptr->val[1] = (gG>1.3f)?1.3f:(gG<0.7f)?0.7f:gG;
|
||||||
ptr->val[2] = (gR>1.3f)?1.3f:(gR<0.7f)?0.7f:gR;
|
ptr->val[2] = (gR>1.3f)?1.3f:(gR<0.7f)?0.7f:gR;
|
||||||
@@ -2229,11 +2257,15 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::Mat dst;
|
LOGD("blending multiply");
|
||||||
cv::blur(blendGains, dst, cv::Size(3,3));
|
for(int i=0; i<materials; ++i)
|
||||||
cv::resize(dst, blendGains, globalTexture.size(), 0, 0, cv::INTER_LINEAR);
|
{
|
||||||
|
cv::Mat dst;
|
||||||
|
cv::blur(blendGains[i], dst, cv::Size(3,3));
|
||||||
|
cv::resize(dst, blendGains[i], globalTextures[i].size(), 0, 0, cv::INTER_LINEAR);
|
||||||
|
|
||||||
cv::multiply(globalTexture, blendGains, globalTexture, 1.0, CV_8UC3);
|
cv::multiply(globalTextures[i], blendGains[i], globalTextures[i], 1.0, CV_8UC3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
progressionStatus_.increment();
|
progressionStatus_.increment();
|
||||||
}
|
}
|
||||||
@@ -2252,7 +2284,7 @@ cv::Mat RTABMapApp::mergeTextures(
|
|||||||
UERROR("No image size set!");
|
UERROR("No image size set!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return globalTexture;
|
return globalTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTABMapApp::cancelProcessing()
|
void RTABMapApp::cancelProcessing()
|
||||||
@@ -2267,6 +2299,7 @@ bool RTABMapApp::exportMesh(
|
|||||||
bool regenerateCloud,
|
bool regenerateCloud,
|
||||||
bool meshing,
|
bool meshing,
|
||||||
int textureSize,
|
int textureSize,
|
||||||
|
int textureCount,
|
||||||
int normalK,
|
int normalK,
|
||||||
bool optimized,
|
bool optimized,
|
||||||
float optimizedVoxelSize,
|
float optimizedVoxelSize,
|
||||||
@@ -2336,7 +2369,7 @@ bool RTABMapApp::exportMesh(
|
|||||||
pcl::PolygonMesh::Ptr polygonMesh(new pcl::PolygonMesh);
|
pcl::PolygonMesh::Ptr polygonMesh(new pcl::PolygonMesh);
|
||||||
pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh);
|
pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh);
|
||||||
std::vector<std::map<int, pcl::PointXY> > vertexToPixels;
|
std::vector<std::map<int, pcl::PointXY> > vertexToPixels;
|
||||||
cv::Mat globalTexture;
|
std::vector<cv::Mat> globalTextures;
|
||||||
int totalPolygons = 0;
|
int totalPolygons = 0;
|
||||||
{
|
{
|
||||||
if(optimized)
|
if(optimized)
|
||||||
@@ -3046,7 +3079,7 @@ bool RTABMapApp::exportMesh(
|
|||||||
if(textureSize>0 && totalPolygons && textureMesh->tex_materials.size())
|
if(textureSize>0 && totalPolygons && textureMesh->tex_materials.size())
|
||||||
{
|
{
|
||||||
LOGI("Merging %d textures...", (int)textureMesh->tex_materials.size());
|
LOGI("Merging %d textures...", (int)textureMesh->tex_materials.size());
|
||||||
globalTexture = mergeTextures(*textureMesh, textureSize, vertexToPixels);
|
globalTextures = mergeTextures(*textureMesh, textureSize, textureCount, vertexToPixels);
|
||||||
|
|
||||||
if(progressionStatus_.isCanceled())
|
if(progressionStatus_.isCanceled())
|
||||||
{
|
{
|
||||||
@@ -3058,18 +3091,28 @@ bool RTABMapApp::exportMesh(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGD("Saving texture(s) (%d)", (int)globalTextures.size());
|
||||||
std::string baseName = uSplit(UFile::getName(filePath), '.').front();
|
std::string baseName = uSplit(UFile::getName(filePath), '.').front();
|
||||||
std::string textureDirectory = UDirectory::getDir(filePath);
|
std::string textureDirectory = UDirectory::getDir(filePath);
|
||||||
std::string fullPath = textureDirectory+UDirectory::separator()+baseName+".jpg";
|
UASSERT(textureMesh->tex_materials.size() == globalTextures.size());
|
||||||
textureMesh->tex_materials[0].tex_file = baseName+".jpg";
|
for(unsigned int i=0; i<textureMesh->tex_materials.size(); ++i)
|
||||||
LOGI("Saving texture to %s.", fullPath.c_str());
|
|
||||||
if(!cv::imwrite(fullPath, globalTexture))
|
|
||||||
{
|
{
|
||||||
LOGI("Failed saving %s!", fullPath.c_str());
|
std::string baseNameNum = baseName;
|
||||||
}
|
if(textureMesh->tex_materials.size()>1)
|
||||||
else
|
{
|
||||||
{
|
baseNameNum+=uNumber2Str(i);
|
||||||
LOGI("Saved %s (%d bytes).", fullPath.c_str(), globalTexture.total()*globalTexture.channels());
|
}
|
||||||
|
std::string fullPath = textureDirectory+UDirectory::separator()+baseNameNum+".jpg";
|
||||||
|
textureMesh->tex_materials[i].tex_file = baseNameNum+".jpg";
|
||||||
|
LOGI("Saving texture to %s.", fullPath.c_str());
|
||||||
|
if(!cv::imwrite(fullPath, globalTextures[i]))
|
||||||
|
{
|
||||||
|
LOGI("Failed saving %s!", fullPath.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGI("Saved %s (%d bytes).", fullPath.c_str(), globalTextures[i].total()*globalTextures[i].channels());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(progressionStatus_.isCanceled())
|
if(progressionStatus_.isCanceled())
|
||||||
@@ -3108,14 +3151,54 @@ bool RTABMapApp::exportMesh(
|
|||||||
}
|
}
|
||||||
else if(textureMesh->tex_materials.size())
|
else if(textureMesh->tex_materials.size())
|
||||||
{
|
{
|
||||||
UASSERT(textureMesh->tex_polygons.size() && (int)textureMesh->tex_polygons[0].size() == totalPolygons);
|
|
||||||
LOGI("Saving obj (%d vertices, %d polygons) to %s.", (int)textureMesh->cloud.data.size()/textureMesh->cloud.point_step, totalPolygons, filePath.c_str());
|
LOGI("Saving obj (%d vertices, %d polygons) to %s.", (int)textureMesh->cloud.data.size()/textureMesh->cloud.point_step, totalPolygons, filePath.c_str());
|
||||||
success = pcl::io::saveOBJFile(filePath, *textureMesh) == 0;
|
success = pcl::io::saveOBJFile(filePath, *textureMesh) == 0;
|
||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
LOGI("Saved obj to %s!", filePath.c_str());
|
LOGI("Saved obj to %s!", filePath.c_str());
|
||||||
exportedMesh_ = textureMesh;
|
exportedMesh_ = textureMesh;
|
||||||
exportedTexture_ = globalTexture;
|
if(globalTextures.size() == 1)
|
||||||
|
{
|
||||||
|
exportedTexture_ = globalTextures[0];
|
||||||
|
}
|
||||||
|
else if(globalTextures.size() > 1)
|
||||||
|
{
|
||||||
|
// Visualization doesn't support more than one material, so concatenate to 1
|
||||||
|
std::vector<bool> materialsKept;
|
||||||
|
float scale = 0.0f;
|
||||||
|
cv::Size imageSize = globalTextures[0].size();
|
||||||
|
int imageType = CV_8UC3;
|
||||||
|
rtabmap::util3d::concatenateTextureMaterials(*exportedMesh_, imageSize, textureSize, 1, scale, &materialsKept);
|
||||||
|
if(scale && exportedMesh_->tex_materials.size() == 1)
|
||||||
|
{
|
||||||
|
int cols = float(textureSize)/(scale*imageSize.width);
|
||||||
|
int rows = float(textureSize)/(scale*imageSize.height);
|
||||||
|
|
||||||
|
exportedTexture_ = cv::Mat(textureSize, textureSize, imageType, cv::Scalar::all(255));
|
||||||
|
|
||||||
|
// make a blank texture
|
||||||
|
cv::Size resizedImageSize(int(imageSize.width*scale), int(imageSize.height*scale));
|
||||||
|
int oi=0;
|
||||||
|
for(int i=0; i<(int)globalTextures.size(); ++i)
|
||||||
|
{
|
||||||
|
if(materialsKept.at(i))
|
||||||
|
{
|
||||||
|
int u = oi%cols * resizedImageSize.width;
|
||||||
|
int v = ((oi/cols) % rows ) * resizedImageSize.height;
|
||||||
|
UASSERT(u < textureSize-resizedImageSize.width);
|
||||||
|
UASSERT(v < textureSize-resizedImageSize.height);
|
||||||
|
|
||||||
|
cv::Mat resizedImage;
|
||||||
|
cv::resize(globalTextures[i], resizedImage, resizedImageSize, 0.0f, 0.0f, cv::INTER_AREA);
|
||||||
|
|
||||||
|
UASSERT(resizedImage.type() == exportedTexture_.type());
|
||||||
|
resizedImage.copyTo(exportedTexture_(cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
|
||||||
|
|
||||||
|
++oi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -146,8 +146,9 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
|
|
||||||
void resetMapping();
|
void resetMapping();
|
||||||
void save(const std::string & databasePath);
|
void save(const std::string & databasePath);
|
||||||
cv::Mat mergeTextures(pcl::TextureMesh & mesh,
|
std::vector<cv::Mat> mergeTextures(pcl::TextureMesh & mesh,
|
||||||
int textureSize,
|
int textureSize,
|
||||||
|
int textureCount,
|
||||||
const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels) const;
|
const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels) const;
|
||||||
void cancelProcessing();
|
void cancelProcessing();
|
||||||
bool exportMesh(
|
bool exportMesh(
|
||||||
@@ -156,6 +157,7 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
bool regenerateCloud,
|
bool regenerateCloud,
|
||||||
bool meshing,
|
bool meshing,
|
||||||
int textureSize,
|
int textureSize,
|
||||||
|
int textureCount,
|
||||||
int normalK,
|
int normalK,
|
||||||
bool optimized,
|
bool optimized,
|
||||||
float optimizedVoxelSize,
|
float optimizedVoxelSize,
|
||||||
|
|||||||
@@ -335,6 +335,7 @@ Java_com_introlab_rtabmap_RTABMapLib_exportMesh(
|
|||||||
bool regenerateCloud,
|
bool regenerateCloud,
|
||||||
bool meshing,
|
bool meshing,
|
||||||
int textureSize,
|
int textureSize,
|
||||||
|
int textureCount,
|
||||||
int normalK,
|
int normalK,
|
||||||
bool optimized,
|
bool optimized,
|
||||||
float optimizedVoxelSize,
|
float optimizedVoxelSize,
|
||||||
@@ -355,6 +356,7 @@ Java_com_introlab_rtabmap_RTABMapLib_exportMesh(
|
|||||||
regenerateCloud,
|
regenerateCloud,
|
||||||
meshing,
|
meshing,
|
||||||
textureSize,
|
textureSize,
|
||||||
|
textureCount,
|
||||||
normalK,
|
normalK,
|
||||||
optimized,
|
optimized,
|
||||||
optimizedVoxelSize,
|
optimizedVoxelSize,
|
||||||
|
|||||||
@@ -227,6 +227,14 @@
|
|||||||
android:entryValues="@array/pref_texture_size_values"
|
android:entryValues="@array/pref_texture_size_values"
|
||||||
android:defaultValue="@string/pref_default_texture_size"/>
|
android:defaultValue="@string/pref_default_texture_size"/>
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:key="@string/pref_key_texture_count"
|
||||||
|
android:title="@string/pref_title_texture_count"
|
||||||
|
android:summary="@string/pref_summary_texture_count"
|
||||||
|
android:entries="@array/pref_texture_count_keys"
|
||||||
|
android:entryValues="@array/pref_texture_count_values"
|
||||||
|
android:defaultValue="@string/pref_default_texture_count"/>
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:key="@string/pref_key_normal_k"
|
android:key="@string/pref_key_normal_k"
|
||||||
android:title="@string/pref_title_normal_k"
|
android:title="@string/pref_title_normal_k"
|
||||||
|
|||||||
@@ -109,6 +109,8 @@
|
|||||||
<string name="pref_default_cloud_voxel">0.01</string>
|
<string name="pref_default_cloud_voxel">0.01</string>
|
||||||
<string name="pref_key_texture_size">pref_key_texture_size</string>
|
<string name="pref_key_texture_size">pref_key_texture_size</string>
|
||||||
<string name="pref_default_texture_size">4096</string>
|
<string name="pref_default_texture_size">4096</string>
|
||||||
|
<string name="pref_key_texture_count">pref_key_texture_count</string>
|
||||||
|
<string name="pref_default_texture_count">1</string>
|
||||||
<string name="pref_key_normal_k">pref_key_normal_k</string>
|
<string name="pref_key_normal_k">pref_key_normal_k</string>
|
||||||
<string name="pref_default_normal_k">18</string>
|
<string name="pref_default_normal_k">18</string>
|
||||||
<string name="pref_key_max_texture_distance">pref_key_max_texture_distance</string>
|
<string name="pref_key_max_texture_distance">pref_key_max_texture_distance</string>
|
||||||
@@ -565,6 +567,8 @@
|
|||||||
<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_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_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_summary_texture_size">If the map is large, you may want to increase this to maximize the texture resolution.</string>
|
||||||
|
<string name="pref_title_texture_count">Maximum Output Textures</string>
|
||||||
|
<string name="pref_summary_texture_count">Note that all textures are still merged into one for visualization, but exported in multiple files.</string>
|
||||||
<string name="pref_title_normal_k">Normal K</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_summary_normal_k">K-nearest neighbors used for normal computation when a mesh is created.</string>
|
||||||
<string name="pref_title_max_texture_distance">Max Texture Distance</string>
|
<string name="pref_title_max_texture_distance">Max Texture Distance</string>
|
||||||
@@ -606,6 +610,26 @@
|
|||||||
<item>"2048"</item>
|
<item>"2048"</item>
|
||||||
<item>"1024"</item>
|
<item>"1024"</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="pref_texture_count_keys">
|
||||||
|
<item>"8"</item>
|
||||||
|
<item>"7"</item>
|
||||||
|
<item>"6"</item>
|
||||||
|
<item>"5"</item>
|
||||||
|
<item>"4"</item>
|
||||||
|
<item>"3"</item>
|
||||||
|
<item>"2"</item>
|
||||||
|
<item>"1"</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="pref_texture_count_values">
|
||||||
|
<item>"8"</item>
|
||||||
|
<item>"7"</item>
|
||||||
|
<item>"6"</item>
|
||||||
|
<item>"5"</item>
|
||||||
|
<item>"4"</item>
|
||||||
|
<item>"3"</item>
|
||||||
|
<item>"2"</item>
|
||||||
|
<item>"1"</item>
|
||||||
|
</string-array>
|
||||||
<string-array name="pref_normal_k_values">
|
<string-array name="pref_normal_k_values">
|
||||||
<item>"30"</item>
|
<item>"30"</item>
|
||||||
<item>"24"</item>
|
<item>"24"</item>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
public static final String EXTRA_VALUE_ADF = "ADF_LOAD_SAVE_PERMISSION";
|
public static final String EXTRA_VALUE_ADF = "ADF_LOAD_SAVE_PERMISSION";
|
||||||
|
|
||||||
public static final String RTABMAP_TMP_DB = "rtabmap.tmp.db";
|
public static final String RTABMAP_TMP_DB = "rtabmap.tmp.db";
|
||||||
public static final String RTABMAP_TMP_DIR = "tmp/";
|
public static final String RTABMAP_TMP_DIR = "tmp";
|
||||||
public static final String RTABMAP_TMP_FILENAME = "map";
|
public static final String RTABMAP_TMP_FILENAME = "map";
|
||||||
public static final String RTABMAP_SDCARD_PATH = "/sdcard/";
|
public static final String RTABMAP_SDCARD_PATH = "/sdcard/";
|
||||||
public static final String RTABMAP_EXPORT_DIR = "Export/";
|
public static final String RTABMAP_EXPORT_DIR = "Export/";
|
||||||
@@ -627,6 +627,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
break;
|
break;
|
||||||
case R.id.close_visualization_button:
|
case R.id.close_visualization_button:
|
||||||
updateState(State.STATE_IDLE);
|
updateState(State.STATE_IDLE);
|
||||||
|
RTABMapLib.postExportation(false);
|
||||||
break;
|
break;
|
||||||
case R.id.button_saveOnDevice:
|
case R.id.button_saveOnDevice:
|
||||||
saveOnDevice();
|
saveOnDevice();
|
||||||
@@ -1094,7 +1095,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
|
|
||||||
private RTABMapActivity getActivity() {return this;}
|
private RTABMapActivity getActivity() {return this;}
|
||||||
|
|
||||||
private String[] loadFileList(String directory) {
|
private String[] loadFileList(String directory, final boolean databasesOnly) {
|
||||||
File path = new File(directory);
|
File path = new File(directory);
|
||||||
String fileList[];
|
String fileList[];
|
||||||
try {
|
try {
|
||||||
@@ -1109,7 +1110,14 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
@Override
|
@Override
|
||||||
public boolean accept(File dir, String filename) {
|
public boolean accept(File dir, String filename) {
|
||||||
File sel = new File(dir, filename);
|
File sel = new File(dir, filename);
|
||||||
return filename.compareTo(RTABMAP_TMP_DB) != 0 && filename.endsWith(".db");
|
if(databasesOnly)
|
||||||
|
{
|
||||||
|
return filename.compareTo(RTABMAP_TMP_DB) != 0 && filename.endsWith(".db");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return sel.isFile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -1242,7 +1250,6 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
mItemModes.setEnabled(true);
|
mItemModes.setEnabled(true);
|
||||||
mButtonPause.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
|
mButtonPause.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
|
||||||
mItemDataRecorderMode.setEnabled(mButtonPause.isChecked());
|
mItemDataRecorderMode.setEnabled(mButtonPause.isChecked());
|
||||||
RTABMapLib.postExportation(false);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mButtonFirst.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
|
mButtonFirst.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
|
||||||
@@ -1713,7 +1720,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
else if(itemId == R.id.open)
|
else if(itemId == R.id.open)
|
||||||
{
|
{
|
||||||
final String[] files = loadFileList(mWorkingDirectory);
|
final String[] files = loadFileList(mWorkingDirectory, true);
|
||||||
if(files.length > 0)
|
if(files.length > 0)
|
||||||
{
|
{
|
||||||
String[] filesWithSize = new String[files.length];
|
String[] filesWithSize = new String[files.length];
|
||||||
@@ -1774,6 +1781,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
final String cloudVoxelSizeStr = sharedPref.getString(getString(R.string.pref_key_cloud_voxel), getString(R.string.pref_default_cloud_voxel));
|
final String cloudVoxelSizeStr = sharedPref.getString(getString(R.string.pref_key_cloud_voxel), getString(R.string.pref_default_cloud_voxel));
|
||||||
final float cloudVoxelSize = Float.parseFloat(cloudVoxelSizeStr);
|
final float cloudVoxelSize = Float.parseFloat(cloudVoxelSizeStr);
|
||||||
final int textureSize = isOBJ?Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_texture_size), getString(R.string.pref_default_texture_size))):0;
|
final int textureSize = isOBJ?Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_texture_size), getString(R.string.pref_default_texture_size))):0;
|
||||||
|
final int textureCount = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_texture_count), getString(R.string.pref_default_texture_count)));
|
||||||
final int normalK = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_normal_k), getString(R.string.pref_default_normal_k)));
|
final int normalK = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_normal_k), getString(R.string.pref_default_normal_k)));
|
||||||
final float maxTextureDistance = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_max_texture_distance), getString(R.string.pref_default_max_texture_distance)));
|
final float maxTextureDistance = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_max_texture_distance), getString(R.string.pref_default_max_texture_distance)));
|
||||||
final int minTextureClusterSize = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_min_texture_cluster_size), getString(R.string.pref_default_min_texture_cluster_size)));
|
final int minTextureClusterSize = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_min_texture_cluster_size), getString(R.string.pref_default_min_texture_cluster_size)));
|
||||||
@@ -1793,10 +1801,24 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
|
|
||||||
mExportProgressDialog.show();
|
mExportProgressDialog.show();
|
||||||
updateState(State.STATE_PROCESSING);
|
updateState(State.STATE_PROCESSING);
|
||||||
final String tmpPath = mWorkingDirectory + RTABMAP_TMP_DIR + RTABMAP_TMP_FILENAME + extension;
|
final String tmpPath = mWorkingDirectory + RTABMAP_TMP_DIR + "/" + RTABMAP_TMP_FILENAME + extension;
|
||||||
|
|
||||||
File tmpDir = new File(mWorkingDirectory + RTABMAP_TMP_DIR);
|
File tmpDir = new File(mWorkingDirectory + RTABMAP_TMP_DIR);
|
||||||
tmpDir.mkdirs();
|
tmpDir.mkdirs();
|
||||||
|
String[] fileNames = loadFileList(mWorkingDirectory + RTABMAP_TMP_DIR, false);
|
||||||
|
if(!DISABLE_LOG) Log.i(TAG, String.format("Deleting %d files in \"%s\"", fileNames.length, mWorkingDirectory + RTABMAP_TMP_DIR));
|
||||||
|
for(int i=0; i<fileNames.length; ++i)
|
||||||
|
{
|
||||||
|
File f = new File(mWorkingDirectory + RTABMAP_TMP_DIR + "/" + fileNames[i]);
|
||||||
|
if(f.delete())
|
||||||
|
{
|
||||||
|
if(!DISABLE_LOG) Log.i(TAG, String.format("Deleted \"%s\"", f.getPath()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!DISABLE_LOG) Log.i(TAG, String.format("Failed deleting \"%s\"", f.getPath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
File exportDir = new File(mWorkingDirectory + RTABMAP_EXPORT_DIR);
|
File exportDir = new File(mWorkingDirectory + RTABMAP_EXPORT_DIR);
|
||||||
exportDir.mkdirs();
|
exportDir.mkdirs();
|
||||||
|
|
||||||
@@ -1811,6 +1833,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
regenerateCloud,
|
regenerateCloud,
|
||||||
meshing,
|
meshing,
|
||||||
textureSize,
|
textureSize,
|
||||||
|
textureCount,
|
||||||
normalK,
|
normalK,
|
||||||
optimized,
|
optimized,
|
||||||
optimizedVoxelSize,
|
optimizedVoxelSize,
|
||||||
@@ -2043,22 +2066,32 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
final String zipOutput = mWorkingDirectory+RTABMAP_EXPORT_DIR+fileName+".zip";
|
final String zipOutput = mWorkingDirectory+RTABMAP_EXPORT_DIR+fileName+".zip";
|
||||||
pathHuman = mWorkingDirectoryHuman + RTABMAP_EXPORT_DIR + fileName + ".zip";
|
pathHuman = mWorkingDirectoryHuman + RTABMAP_EXPORT_DIR + fileName + ".zip";
|
||||||
|
|
||||||
String[] filesToZip = new String[3];
|
String[] fileNames = loadFileList(mWorkingDirectory + RTABMAP_TMP_DIR, false);
|
||||||
filesToZip[0] = mWorkingDirectory + RTABMAP_TMP_DIR + RTABMAP_TMP_FILENAME + ".obj";
|
if(fileNames.length > 0)
|
||||||
filesToZip[1] = mWorkingDirectory + RTABMAP_TMP_DIR + RTABMAP_TMP_FILENAME + ".mtl";
|
|
||||||
filesToZip[2] = mWorkingDirectory + RTABMAP_TMP_DIR + RTABMAP_TMP_FILENAME + ".jpg";
|
|
||||||
|
|
||||||
File toZIPFile = new File(zipOutput);
|
|
||||||
toZIPFile.delete();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
Util.zip(filesToZip, zipOutput);
|
String[] filesToZip = new String[fileNames.length];
|
||||||
mToast.makeText(getActivity(), String.format("Mesh \"%s\" successfully exported!", pathHuman), mToast.LENGTH_LONG).show();
|
for(int i=0; i<fileNames.length; ++i)
|
||||||
|
{
|
||||||
|
filesToZip[i] = mWorkingDirectory + RTABMAP_TMP_DIR + "/" + fileNames[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
File toZIPFile = new File(zipOutput);
|
||||||
|
toZIPFile.delete();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Util.zip(filesToZip, zipOutput);
|
||||||
|
mToast.makeText(getActivity(), String.format("Mesh \"%s\" successfully exported!", pathHuman), mToast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! Error=%s", pathHuman, e.getMessage()), mToast.LENGTH_LONG).show();
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(IOException e)
|
else
|
||||||
{
|
{
|
||||||
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! Error=%s", pathHuman, e.getMessage()), mToast.LENGTH_LONG).show();
|
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! No files found in tmp directory!?", pathHuman), mToast.LENGTH_LONG).show();
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2069,7 +2102,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
|
|
||||||
File toPLYFile = new File(path);
|
File toPLYFile = new File(path);
|
||||||
toPLYFile.delete();
|
toPLYFile.delete();
|
||||||
File fromPLYFile = new File(mWorkingDirectory + RTABMAP_TMP_DIR + RTABMAP_TMP_FILENAME + ".ply");
|
File fromPLYFile = new File(mWorkingDirectory + RTABMAP_TMP_DIR + "/" + RTABMAP_TMP_FILENAME + ".ply");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ public class RTABMapLib
|
|||||||
boolean regenerateCloud,
|
boolean regenerateCloud,
|
||||||
boolean meshing,
|
boolean meshing,
|
||||||
int textureSize,
|
int textureSize,
|
||||||
|
int textureCount,
|
||||||
int normalK,
|
int normalK,
|
||||||
boolean optimized,
|
boolean optimized,
|
||||||
float optimizedVoxelSize,
|
float optimizedVoxelSize,
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
|
|||||||
|
|
||||||
((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_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_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_texture_count))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_texture_count))).getEntry() + ") "+getString(R.string.pref_summary_texture_count));
|
||||||
((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_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_max_texture_distance))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_max_texture_distance))).getEntry() + ") "+getString(R.string.pref_summary_max_texture_distance));
|
((Preference)findPreference(getString(R.string.pref_key_max_texture_distance))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_max_texture_distance))).getEntry() + ") "+getString(R.string.pref_summary_max_texture_distance));
|
||||||
((Preference)findPreference(getString(R.string.pref_key_min_texture_cluster_size))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_min_texture_cluster_size))).getEntry() + ") "+getString(R.string.pref_summary_min_texture_cluster_size));
|
((Preference)findPreference(getString(R.string.pref_key_min_texture_cluster_size))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_min_texture_cluster_size))).getEntry() + ") "+getString(R.string.pref_summary_min_texture_cluster_size));
|
||||||
@@ -262,6 +263,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
|
|||||||
|
|
||||||
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_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_texture_size))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_texture_size));
|
||||||
|
if(key.compareTo(getString(R.string.pref_key_texture_count))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_texture_count));
|
||||||
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_normal_k))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_normal_k));
|
||||||
if(key.compareTo(getString(R.string.pref_key_max_texture_distance))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_max_texture_distance));
|
if(key.compareTo(getString(R.string.pref_key_max_texture_distance))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_max_texture_distance));
|
||||||
if(key.compareTo(getString(R.string.pref_key_min_texture_cluster_size))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_min_texture_cluster_size));
|
if(key.compareTo(getString(R.string.pref_key_min_texture_cluster_size))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_min_texture_cluster_size));
|
||||||
|
|||||||
Reference in New Issue
Block a user