MeshLib::Mesh* RasterToMesh::convert( double const* img, GeoLib::RasterHeader const& header, MeshElemType elem_type, UseIntensityAs intensity_type, std::string const& array_name) { if ((elem_type != MeshElemType::TRIANGLE) && (elem_type != MeshElemType::QUAD)) { ERR("Invalid Mesh Element Type."); return nullptr; } std::size_t const incHeight (header.n_rows+1); std::size_t const incWidth (header.n_cols+1); std::vector<double> pix_val (incHeight * incWidth, std::numeric_limits<double>::max()); std::vector<bool> pix_vis (incHeight * incWidth, false); for (std::size_t i = 0; i < header.n_rows; i++) for (std::size_t j = 0; j < header.n_cols; j++) { std::size_t const img_idx = i*header.n_cols + j; std::size_t const fld_idx = i*incWidth + j; if (img[img_idx] == -9999) continue; pix_vis[img_idx] = true; pix_val[fld_idx] = img[img_idx]; pix_val[fld_idx+1] = img[img_idx]; pix_val[fld_idx+incWidth] = img[img_idx]; pix_val[fld_idx+incWidth+1] = img[img_idx]; } return constructMesh(pix_val, array_name, pix_vis, header, elem_type, intensity_type); }
int main() { // Load frames std::cout << "Loading frames" << std::endl; auto frames = Frame3D::loadFrames("../3dframes/"); // Merge clouds std::cout << "Merge clouds" << std::endl; pcl::PointCloud<pcl::PointNormal> mergedCloud; pcl::PointCloud<pcl::PointNormal>::Ptr mergedCloudPtr(&mergedCloud); mergePointClouds(frames, mergedCloud); // Construct mesh std::cout << "Construct Mesh" << std::endl; auto mesh = constructMesh (mergedCloudPtr); // Add texture to point cloud std::cout << "Add texture" << std::endl; addTexture(mesh, frames); // Visualize mesh std::cout << "Visualise mesh" << std::endl; visualiseMesh(mesh); return 1; }
MeshLib::Mesh* RasterToMesh::convert( vtkImageData* img, const double origin[3], const double scalingFactor, MeshElemType elem_type, UseIntensityAs intensity_type, std::string const& array_name) { if ((elem_type != MeshElemType::TRIANGLE) && (elem_type != MeshElemType::QUAD)) { ERR("VtkMeshConverter::convertImgToMesh(): Invalid Mesh Element Type."); return nullptr; } vtkSmartPointer<vtkDataArray> pixelData = vtkSmartPointer<vtkDataArray>(img->GetPointData()->GetScalars()); int* dims = img->GetDimensions(); int nTuple = pixelData->GetNumberOfComponents(); if (nTuple < 1 || nTuple > 4) { ERR("VtkMeshConverter::convertImgToMesh(): Unsupported pixel composition!"); return nullptr; } MathLib::Point3d const orig (std::array<double,3>{{origin[0], origin[1], origin[2]}}); GeoLib::RasterHeader const header = {static_cast<std::size_t>(dims[0]), static_cast<std::size_t>(dims[1]), orig, scalingFactor, -9999}; const std::size_t incHeight = header.n_rows+1; const std::size_t incWidth = header.n_cols+1; std::vector<double> pix_val (incHeight * incWidth, std::numeric_limits<double>::max()); std::vector<bool> pix_vis (header.n_rows * header.n_cols, false); for (std::size_t i = 0; i < header.n_rows; i++) for (std::size_t j = 0; j < header.n_cols; j++) { std::size_t const img_idx = i*header.n_cols + j; std::size_t const fld_idx = i*incWidth + j; // colour of current pixel double* colour = pixelData->GetTuple(img_idx); // is current pixel visible? bool const visible = (nTuple == 2 || nTuple == 4) ? (colour[nTuple-1] != 0) : true; if (!visible) continue; double const value = (nTuple < 3) ? colour[0] : // grey (+ alpha) (0.3 * colour[0] + 0.6 * colour[1] + 0.1 * colour[2]); // rgb(a) pix_vis[img_idx] = true; pix_val[fld_idx] = value; pix_val[fld_idx+1] = value; pix_val[fld_idx+incWidth] = value; pix_val[fld_idx+incWidth+1] = value; } return constructMesh(pix_val, array_name, pix_vis, header, elem_type, intensity_type); }
MeshLib::Mesh* VtkMeshConverter::convertImgToMesh(const double* img, const double origin[3], const size_t imgHeight, const size_t imgWidth, const double &scalingFactor, MeshElemType elem_type, UseIntensityAs intensity_type) { const size_t incHeight = imgHeight+1; const size_t incWidth = imgWidth+1; double* pixVal (new double[incHeight * incWidth]); bool* visNodes(new bool[incWidth * incHeight]); int* node_idx_map(new int[incWidth * incHeight]); double noDataValue = getExistingValue(img, imgWidth*imgHeight); for (size_t j = 0; j < imgHeight; j++) { pixVal[j]=0; visNodes[j]=false; node_idx_map[j]=-1; } for (size_t i = 0; i < imgWidth; i++) { for (size_t j = 0; j < imgHeight; j++) { const size_t img_idx = i * imgHeight + j; const size_t index = (i+1) * incHeight + j; if (img[img_idx] == -9999) { visNodes[index] = false; pixVal[index] = noDataValue; } else { pixVal[index] = img[img_idx]; visNodes[index] = true; } node_idx_map[index]=-1; } pixVal[(i+2)*incHeight-1]=0; visNodes[(i+2)*incHeight-1]=false; node_idx_map[(i+2)*incHeight-1]=-1; } MeshLib::Mesh* mesh = constructMesh(pixVal, node_idx_map, visNodes, origin, imgHeight, imgWidth, scalingFactor, elem_type, intensity_type); delete [] pixVal; delete [] visNodes; delete [] node_idx_map; return mesh; }
void OnOpenMesh(MeshSegment*& meshSeg, char* fileName) { char tFileName[400]; strcpy(tFileName, fileName); char FileType[400]; for (int i = strlen(tFileName) - 1; i >= 0; i--){ if (tFileName[i] == '.'){ i++; unsigned tsize = strlen(tFileName) - i; for (unsigned j = 0; j < tsize; j++){ FileType[j] = tFileName[i + j]; } FileType[tsize] = '\0'; break; } } cout << "file:" << fileName << "." << FileType << endl; constructMesh(meshSeg, fileName, FileType); }
MeshLib::Mesh* ConvertRasterToMesh::execute() const { const size_t height(_raster.getNRows()+1); const size_t width(_raster.getNCols()+1); const size_t size(height*width); double* pix_vals(new double[size]); bool* vis_nodes(new bool[size]); // determine a valid value for substitution of no data values double substitution(getExistingValue(_raster.begin(), _raster.end())); // fill first row with non visual nodes for (size_t j = 0; j < _raster.getNCols(); j++) { pix_vals[j] = 0; vis_nodes[j] = false; } GeoLib::Raster::const_iterator raster_it(_raster.begin()); for (size_t i = 0; i < _raster.getNRows(); ++i) { for (size_t j = 0; j < _raster.getNCols(); ++j) { const size_t index = (i+1) * width + j; if (*raster_it == _raster.getNoDataValue()) { pix_vals[index] = substitution; vis_nodes[index] = false; } else { pix_vals[index] = *raster_it; vis_nodes[index] = true; } ++raster_it; } // fill last column with non-visual nodes pix_vals[(i + 2) * width - 1] = 0; vis_nodes[(i + 2) * width - 1] = false; } MeshLib::Mesh* mesh = constructMesh(pix_vals, vis_nodes); delete [] pix_vals; delete [] vis_nodes; return mesh; }
/// pose: current transform /// scanned : scanned model /// void MeshFusion::meshMerge(ITMMesh * mesh, ITMPose * pose, MyTri * scanned) { Vector4f intrinRGB = mainView->calib->intrinsics_rgb.projectionParamsSimple.all; Matrix4f m = pose->GetM(); Matrix4f invm = pose->GetInvM(); //meshVertex.clear(); scanned->project(&m, intrinRGB); currTri.project(NULL, intrinRGB); float* dp = proDepth->GetData(MEMORYDEVICE_CPU); int w = proDepth->noDims.x; //currTri.stat 判斷目前mesh 上的vertex 是否在scanned mesh 上,如果是的話state 為true memset(currTri.stat, 0x00, sizeof(bool) * 2048); for (int j = 0; j < currTri.totalVertex; j++) { float dz= currTri.meshDepth[j]; float ed = scanned->locateAt(currTri.meshProj[j]); if ( ed >=0 && fabs(dz-ed) <5) currTri.stat[j] = true; };//end of for loop to check vertex //project merged boundary as constrain from scanned model into current model // int nstart = 0; int nend = scanned->nboundary; if (scanned->ncontour > 1) { int maxnv = 0; int currnv; for (int i = 0; i < scanned->ncontour; i++) { currnv = scanned->contour[i + 1] - scanned->contour[i]; if (currnv > maxnv) { maxnv = currnv; nstart = scanned->contour[i]; nend = scanned->contour[i + 1]-1; // i+1 是下一個countour 的起點, 該點-1 是這個countour 的終點,但也是起點(繞一圈). -2 正好才是終點 } } } //scanned model的vertex 保持不變, //1.要新增新model 的點 //2.舊點的位置,要根據新的depth作調整 int begi = -1; int lasti = -1; for (int i = nstart; i < nend; i++) { int bnode = scanned->boundary[i];// vertex index float dz = scanned->meshDepth[bnode]; float ed= currTri.locateAt(scanned->meshProj[bnode]); if (ed >= 0 && fabs(ed-dz) < 5) { if (lasti != -1 && lasti == (i - 1)) { constrainbeg.push_back(scanned->meshProj[scanned->boundary[lasti]]); constrainend.push_back(scanned->meshProj[bnode]); } vInputPoints.push_back(scanned->meshProj[bnode]); lasti = i; if (begi < 0) begi = i; } } if (lasti == (nend - 1) && begi == nstart) { constrainbeg.push_back(scanned->meshProj[scanned->boundary[lasti]]); constrainend.push_back(scanned->meshProj[scanned->boundary[begi]]); } //新scanned 的data,建新的mesh constructMesh(NULL, &currTri); //將新mesh 加到原有的mesh data 上 intoMesh(invm, &currTri); //build new triangle // for each new corner check whether it is belong to a triangle or not //for (int i = 0; i < _corners.size(); i++) //{ // cv::Point2f p = _corners[i]; // for (int j = 0; j < meshold->noTotalTriangles; j++) // { // // } //} }
IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file) { u32 i; u32 id; // HEADER file->read(&Header, sizeof(SLMTSHeader)); if (Header.MagicID == 0x4C4D5354) { FlipEndianess = true; Header.MagicID = os::Byteswap::byteswap(Header.MagicID); Header.Version = os::Byteswap::byteswap(Header.Version); Header.HeaderSize = os::Byteswap::byteswap(Header.HeaderSize); Header.TextureCount = os::Byteswap::byteswap(Header.TextureCount); Header.SubsetCount = os::Byteswap::byteswap(Header.SubsetCount); Header.TriangleCount = os::Byteswap::byteswap(Header.TriangleCount); Header.SubsetSize = os::Byteswap::byteswap(Header.SubsetSize); Header.VertexSize = os::Byteswap::byteswap(Header.VertexSize); } if (Header.MagicID != 0x53544D4C) { // "LMTS" os::Printer::log("LMTS ERROR: wrong header magic id!", ELL_ERROR); return 0; } //Skip any User Data (arbitrary app specific data) const s32 userSize = Header.HeaderSize - sizeof(SLMTSHeader); if (userSize>0) file->seek(userSize,true); // TEXTURES file->read(&id, sizeof(u32)); if (FlipEndianess) id = os::Byteswap::byteswap(id); if (id != 0x54584554) { // "TEXT" os::Printer::log("LMTS ERROR: wrong texture magic id!", ELL_ERROR); return 0; } Textures = new SLMTSTextureInfoEntry[Header.TextureCount]; file->read(Textures, sizeof(SLMTSTextureInfoEntry)*Header.TextureCount); if (FlipEndianess) { for (i=0; i<Header.TextureCount; ++i) Textures[i].Flags = os::Byteswap::byteswap(Textures[i].Flags); } // SUBSETS file->read(&id, sizeof(u32)); if (FlipEndianess) id = os::Byteswap::byteswap(id); if (id != 0x53425553) // "SUBS" { os::Printer::log("LMTS ERROR: wrong subset magic id!", ELL_ERROR); cleanup(); return 0; } Subsets = new SLMTSSubsetInfoEntry[Header.SubsetCount]; const s32 subsetUserSize = Header.SubsetSize - sizeof(SLMTSSubsetInfoEntry); for (i=0; i<Header.SubsetCount; ++i) { file->read(&Subsets[i], sizeof(SLMTSSubsetInfoEntry)); if (FlipEndianess) { Subsets[i].Offset = os::Byteswap::byteswap(Subsets[i].Offset); Subsets[i].Count = os::Byteswap::byteswap(Subsets[i].Count); Subsets[i].TextID1 = os::Byteswap::byteswap(Subsets[i].TextID1); Subsets[i].TextID2 = os::Byteswap::byteswap(Subsets[i].TextID2); } if (subsetUserSize>0) file->seek(subsetUserSize,true); } // TRIANGLES file->read(&id, sizeof(u32)); if (FlipEndianess) id = os::Byteswap::byteswap(id); if (id != 0x53495254) // "TRIS" { os::Printer::log("LMTS ERROR: wrong triangle magic id!", ELL_ERROR); cleanup(); return 0; } Triangles = new SLMTSTriangleDataEntry[(Header.TriangleCount*3)]; const s32 triUserSize = Header.VertexSize - sizeof(SLMTSTriangleDataEntry); for (i=0; i<(Header.TriangleCount*3); ++i) { file->read(&Triangles[i], sizeof(SLMTSTriangleDataEntry)); if (FlipEndianess) { Triangles[i].X = os::Byteswap::byteswap(Triangles[i].X); Triangles[i].Y = os::Byteswap::byteswap(Triangles[i].Y); Triangles[i].Z = os::Byteswap::byteswap(Triangles[i].Z); Triangles[i].U1 = os::Byteswap::byteswap(Triangles[i].U1); Triangles[i].V1 = os::Byteswap::byteswap(Triangles[i].U2); Triangles[i].U2 = os::Byteswap::byteswap(Triangles[i].V1); Triangles[i].V2 = os::Byteswap::byteswap(Triangles[i].V2); } if (triUserSize>0) file->seek(triUserSize,true); } ///////////////////////////////////////////////////////////////// SMesh* mesh = new SMesh(); constructMesh(mesh); loadTextures(mesh); cleanup(); SAnimatedMesh* am = new SAnimatedMesh(); am->Type = EAMT_LMTS; // not unknown to irrlicht anymore am->addMesh(mesh); am->recalculateBoundingBox(); mesh->drop(); return am; }
MeshLib::Mesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, const double origin[3], const double scalingFactor, MeshElemType elem_type, UseIntensityAs intensity_type) { if ((elem_type != MeshElemType::TRIANGLE) && (elem_type != MeshElemType::QUAD)) { ERR("VtkMeshConverter::convertImgToMesh(): Invalid Mesh Element Type."); return nullptr; } vtkSmartPointer<vtkDataArray> pixelData = vtkSmartPointer<vtkDataArray>(img->GetPointData()->GetScalars()); int* dims = img->GetDimensions(); int nTuple = pixelData->GetNumberOfComponents(); if (nTuple < 1 || nTuple > 4) { ERR("VtkMeshConverter::convertImgToMesh(): Unsupported pixel composition!"); return nullptr; } const size_t imgHeight = dims[0]; const size_t imgWidth = dims[1]; const size_t incHeight = imgHeight+1; const size_t incWidth = imgWidth+1; double* pixVal (new double[incHeight * incWidth]); bool* visNodes(new bool[incWidth * incHeight]); int* node_idx_map(new int[incWidth * incHeight]); for (size_t j = 0; j < incHeight; j++) { pixVal[j]=0; visNodes[j]=false; node_idx_map[j]=-1; } for (size_t i = 0; i < imgWidth; i++) { for (size_t j = 0; j < imgHeight; j++) { const size_t img_idx = i * imgHeight + j; const size_t index = (i+1) * incHeight + j; double* colour = pixelData->GetTuple(img_idx); if (nTuple < 3) // Grey (+ Alpha) pixVal[index] = colour[0]; else // RGB(A) pixVal[index] = 0.3 * colour[0] + 0.6 * colour[1] + 0.1 * colour[2]; // is current pixel visible if (nTuple == 2 || nTuple == 4) visNodes[index] = (colour[nTuple-1] != 0); else visNodes[index] = true; node_idx_map[index]=-1; } pixVal[(i+2)*incHeight-1]=0; visNodes[(i+2)*incHeight-1]=false; node_idx_map[(i+2)*incHeight-1]=-1; } MeshLib::Mesh* mesh = constructMesh(pixVal, node_idx_map, visNodes, origin, imgHeight, imgWidth, scalingFactor, elem_type, intensity_type); delete [] pixVal; delete [] visNodes; delete [] node_idx_map; return mesh; }
int main (int argc, char* argv[]) { ApplicationsLib::LogogSetup logog_setup; TCLAP::CmdLine cmd( "Prepares OGS-meshes for use in Unity.\n\n" "OpenGeoSys-6 software, version " + BaseLib::BuildInfo::git_describe + ".\n" "Copyright (c) 2012-2019, OpenGeoSys Community " "(http://www.opengeosys.org)", ' ', BaseLib::BuildInfo::git_describe); TCLAP::ValueArg<std::string> mesh_arg("i", "input", "the file containing the original OGS mesh", true, "", "input file name"); cmd.add(mesh_arg); TCLAP::ValueArg<std::string> mesh_out_arg("o", "output", "the file name the result will be written to", true, "", "output file name"); cmd.add(mesh_out_arg); cmd.parse(argc, argv); INFO("Reading mesh '%s' ... ", mesh_arg.getValue().c_str()); std::unique_ptr<MeshLib::Mesh> mesh {MeshLib::IO::readMeshFromFile(mesh_arg.getValue())}; if (!mesh) return EXIT_FAILURE; INFO("done.\n"); INFO("Checking for line elements..."); std::array<unsigned, 7> const& n_element_types = MeshLib::MeshInformation::getNumberOfElementTypes(*mesh); std::unique_ptr<MeshLib::Mesh> result; if (n_element_types[0] == 0) { INFO ("No line elements found.\n"); result = std::move(mesh); } else if (n_element_types[0] == mesh->getNumberOfElements()) { INFO ("Keeping line mesh.\n"); result = std::move(mesh); } else { MeshLib::ElementSearch searcher(*mesh); std::size_t const n_rem_elems = searcher.searchByElementType(MeshLib::MeshElemType::LINE); result.reset(MeshLib::removeElements(*mesh, searcher.getSearchedElementIDs(), "temp mesh")); INFO ("%d line elements found and removed.\n", n_rem_elems); } INFO("Checking for cell-arrays..."); if (containsCellVecs(*result)) result.reset(constructMesh(*result)); else INFO("No cell arrays found, keeping mesh structure.\n"); INFO("Writing mesh '%s' ... ", mesh_out_arg.getValue().c_str()); MeshLib::IO::VtuInterface writer(result.get(), vtkXMLWriter::Ascii, false); writer.writeToFile(mesh_out_arg.getValue()); INFO("done."); return EXIT_SUCCESS; }
IAnimatedMesh* CLMTSMeshFileLoader::createMesh(irr::io::IReadFile* file) { u32 i; u32 id; // HEADER file->read(&Header, sizeof(SLMTSHeader)); if (Header.MagicID != 0x53544D4C) { // "LMTS" LMTS_LOG("LMTS ERROR: wrong header magic id!", ELL_ERROR); return 0; } // TEXTURES file->read(&id, sizeof(u32)); if (id != 0x54584554) { // "TEXT" LMTS_LOG("LMTS ERROR: wrong texture magic id!", ELL_ERROR); return 0; } Textures = new SLMTSTextureInfoEntry[Header.TextureCount]; TextureIDs = new u16[Header.TextureCount]; NumLightMaps = NumTextures = 0; for (i=0; i<Header.TextureCount; i++) { file->read(&Textures[i], sizeof(SLMTSTextureInfoEntry)); if (Textures[i].Flags & 1) { TextureIDs[i] = NumLightMaps; NumLightMaps++; } else { TextureIDs[i] = NumTextures; NumTextures++; } } // SUBSETS file->read(&id, sizeof(u32)); if (id != 0x53425553) { // "SUBS" LMTS_LOG("LMTS ERROR: wrong subset magic id!", ELL_ERROR); cleanup(); return 0; } Subsets = new SLMTSSubsetInfoEntry[Header.SubsetCount]; for (i=0; i<Header.SubsetCount; i++) { file->read(&Subsets[i], sizeof(SLMTSSubsetInfoEntry)); } // TRIANGLES file->read(&id, sizeof(u32)); if (id != 0x53495254) { // "TRIS" LMTS_LOG("LMTS ERROR: wrong triangle magic id!", ELL_ERROR); cleanup(); return 0; } Triangles = new SLMTSTriangleDataEntry[(Header.TriangleCount*3)]; for (i=0; i<(Header.TriangleCount*3); i++) { file->read(&Triangles[i], sizeof(SLMTSTriangleDataEntry)); } ///////////////////////////////////////////////////////////////// constructMesh(); loadTextures(); cleanup(); SAnimatedMesh* am = new SAnimatedMesh(); am->Type = EAMT_LMTS; // not unknown to irrlicht anymore am->addMesh(Mesh); am->recalculateBoundingBox(); Mesh->drop(); Mesh = 0; return am; }