GridEditor::GridEditor(int& argc,char**& argv) :Vrui::Application(argc,argv), grid(0), exportSurfaceHelper("ExportedSurface.ply",".ply",Vrui::openDirectory(".")), mainMenu(0) { if(argc>=2) { /* Load the grid from a float-valued vol file: */ Misc::File volFile(argv[1],"rb",Misc::File::BigEndian); /* Read the file header: */ EditableGrid::Index numVertices; volFile.read<int>(numVertices.getComponents(),3); int borderSize=volFile.read<int>(); for(int i=0;i<3;++i) numVertices[i]+=borderSize*2; float domainSize[3]; volFile.read<float>(domainSize,3); EditableGrid::Size cellSize; for(int i=0;i<3;++i) cellSize[i]=domainSize[i]/float(numVertices[i]-borderSize*2-1); /* Create the grid: */ grid=new EditableGrid(numVertices,cellSize); /* Read all grid values: */ for(EditableGrid::Index i(0);i[0]<grid->getNumVertices(0);i.preInc(grid->getNumVertices())) grid->setValue(i,volFile.read<float>()); grid->invalidateVertices(EditableGrid::Index(0,0,0),grid->getNumVertices()); } else { /* Create a new grid: */ grid=new EditableGrid(EditableGrid::Index(256,256,256),EditableGrid::Size(1.0f,1.0f,1.0f)); } /* Create the program GUI: */ mainMenu=createMainMenu(); Vrui::setMainMenu(mainMenu); /* Initialize the navigation transformation: */ centerDisplayCallback(0); /* Initialize the tool classes: */ EditTool::initClass(*Vrui::getToolManager()); }
void GridEditor::saveGridCallback(Misc::CallbackData* cbData) { /* Write the current contents of the grid to a floating-point vol file: */ Misc::File volFile("Grid.fvol","wb",Misc::File::BigEndian); /* Write the vol file header: */ volFile.write<int>(grid->getNumVertices().getComponents(),3); volFile.write<int>(0); float domainSize[3]; for(int i=0;i<3;++i) domainSize[i]=float(grid->getNumVertices(i)-1)*grid->getCellSize(i); volFile.write<float>(domainSize,3); /* Write the grid data values: */ for(EditableGrid::Index i(0);i[0]<grid->getNumVertices(0);i.preInc(grid->getNumVertices())) volFile.write<float>(grid->getValue(i)); }
Visualization::Abstract::DataSet* MultiVolFile::load(const std::vector<std::string>& args,Comm::MulticastPipe* pipe) const { /* Create the result data set: */ Misc::SelfDestructPointer<DataSet> result(new DataSet); DS& dataSet=result->getDs(); /* Initialize the result data set's data value: */ DataValue& dataValue=result->getDataValue(); dataValue.initialize(&dataSet,0); /* Parse the module arguments: */ DS::Index gridSize(0); DS::Point gridOrigin=DS::Point::origin; DS::Size gridCellSize=DS::Size(0); bool gridInitialized=false; for(size_t argc=0;argc<args.size();argc+=2) { /* Open the vol file: */ Misc::File volFile(args[argc+1].c_str(),"rb",Misc::File::LittleEndian); /* Read the vol file header: */ DS::Index volGridSize; for(int i=0;i<3;++i) volGridSize[i]=volFile.read<int>(); DS::Point volGridOrigin; for(int i=0;i<3;++i) volGridOrigin[i]=Scalar(volFile.read<float>()); DS::Size volGridCellSize; for(int i=0;i<3;++i) volGridCellSize[i]=Scalar(volFile.read<float>()); bool volOk=true; if(gridInitialized) { /* Check the vol file for consistency: */ if(volGridSize!=gridSize||volGridOrigin!=gridOrigin||volGridCellSize!=gridCellSize) { std::cout<<"Vol file "<<args[argc+1]<<" does not match data set layout; skipping"<<std::endl; volOk=false; } } else { /* Initialize the result data set: */ gridSize=volGridSize; gridOrigin=volGridOrigin; gridCellSize=volGridCellSize; dataSet.setData(gridSize,gridCellSize,0); gridInitialized=true; } if(volOk) { /* Determine the vol file's value type: */ unsigned int volTypeSize=volFile.read<unsigned int>(); if(volTypeSize==1||volTypeSize==2||volTypeSize==4||volTypeSize==8) { /* Add a new slice to the data set: */ int newSliceIndex=dataSet.addSlice(); /* Add a new scalar variable to the data value: */ dataValue.addScalarVariable(args[argc].c_str()); /* Read the vol file: */ if(volTypeSize==1) readVolFile<unsigned char>(volFile,dataSet,newSliceIndex); else if(volTypeSize==2) readVolFile<signed short int>(volFile,dataSet,newSliceIndex); else if(volTypeSize==4) readVolFile<float>(volFile,dataSet,newSliceIndex); else readVolFile<double>(volFile,dataSet,newSliceIndex); } else std::cout<<"Vol file "<<args[argc+1]<<" has unknown data type; skipping"<<std::endl; } } return result.releaseTarget(); }
int main(int argc,char* argv[]) { /* Set up the volumetric grid: */ Box gridBox=Box(Point(-32.0,-64.0,16.0),Point(32.0,0.0,80.0)); Index gridSize(256,256,256); Grid grid(gridSize); /* Initialize the grid: */ for(Grid::iterator gIt=grid.begin();gIt!=grid.end();++gIt) *gIt=Voxel(255); /* Carve away the n-th facade from each depth stream file listed on the command line: */ unsigned int facadeIndex=atoi(argv[1]); for(int depthFileIndex=2;depthFileIndex<argc;++depthFileIndex) { try { /* Open the depth file: */ IO::AutoFile depthFile(IO::openFile(argv[depthFileIndex])); depthFile->setEndianness(IO::File::LittleEndian); /* Read the facade projection matrix and the projector transformation: */ Projection depthTransform; depthFile->read<double>(depthTransform.getMatrix().getEntries(),4*4); OGTransform projectorTransform=Misc::Marshaller<OGTransform>::read(*depthFile); /* Calculate the joint projective transformation from 3D world space into depth image space: */ Projection proj=Geometry::invert(Projection(projectorTransform)*depthTransform); /* Create a depth frame reader: */ DepthFrameReader depthFrameReader(*depthFile); /* Read the n-th facade: */ FrameBuffer frame; for(unsigned int i=0;i<facadeIndex;++i) frame=depthFrameReader.readNextFrame(); /* Run a sequence of morphological open and close operators on the frame to fill holes: */ #if 1 for(int i=0;i<8;++i) frame=open(frame); #endif #if 1 for(int i=0;i<8;++i) frame=close(frame); #endif /* Carve the facade out of the grid: */ std::cout<<"Processing depth file "<<argv[depthFileIndex]<<std::flush; double fmax[2]; for(int i=0;i<2;++i) fmax[i]=double(frame.getSize(i)); unsigned short* frameBuffer=static_cast<unsigned short*>(frame.getBuffer()); Size cellSize; for(int i=0;i<3;++i) cellSize[i]=(gridBox.max[i]-gridBox.min[i])/double(gridSize[i]); Index index; Point gridp; gridp[0]=gridBox.min[0]+0.5*cellSize[0]; for(index[0]=0;index[0]<gridSize[0];++index[0],gridp[0]+=cellSize[0]) { gridp[1]=gridBox.min[1]+0.5*cellSize[1]; for(index[1]=0;index[1]<gridSize[1];++index[1],gridp[1]+=cellSize[1]) { gridp[2]=gridBox.min[2]+0.5*cellSize[2]; for(index[2]=0;index[2]<gridSize[2];++index[2],gridp[2]+=cellSize[2]) { /* Project the grid point into the depth frame: */ Point fp=proj.transform(gridp); /* Check if the projected grid point is inside the depth frame: */ if(fp[0]>=0.0&&fp[0]<fmax[0]&&fp[1]>=0.0&&fp[1]<fmax[1]) { /* Check if the grid point is outside the facade: */ int x=int(fp[0]); int y=int(fp[1]); unsigned short depth=frameBuffer[y*frame.getSize(0)+x]; if(fp[2]<double(depth)) grid(index)=Voxel(0); } else grid(index)=Voxel(0); } } std::cout<<'.'<<std::flush; } std::cout<<"done"<<std::endl; } catch(std::runtime_error err) { std::cerr<<"Ignoring depth file "<<argv[depthFileIndex]<<" due to exception "<<err.what()<<std::endl; } catch(...) { std::cerr<<"Ignoring depth file "<<argv[depthFileIndex]<<" due to spurious exception"<<std::endl; } } /* Save the result grid to a volume file: */ IO::AutoFile volFile(IO::openFile("SpaceCarverOut.vol",IO::File::WriteOnly)); volFile->setEndianness(IO::File::BigEndian); for(int i=0;i<3;++i) volFile->write<int>(int(gridSize[i])); volFile->write<int>(0); for(int i=0;i<3;++i) volFile->write<float>((gridBox.max[i]-gridBox.min[i])*double(gridSize[i]-1)/double(gridSize[i])); volFile->write<Voxel>(grid.getArray(),grid.getNumElements()); return 0; }