CC_FILE_ERROR UltFilter::loadFile(const char* filename, ccHObject& container, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, double* coordinatesShift/*=0*/) { //ccConsole::Print("[BinFilter::loadFile] Opening binary file '%s'...\n",filename); assert(filename); //file size long size = QFileInfo(filename).size(); if ( size == 0 || ((size % sizeof(MarkersFrame)) != 0)) return CC_FERR_MALFORMED_FILE; //number of transformations in file long count = size / sizeof(MarkersFrame); ccConsole::Print("[TransBuffer] Found %i trans. in file '%s'",count,filename); if (count<1) return CC_FERR_NO_LOAD; ccPointCloud* cloud = new ccPointCloud(); if (!cloud->reserve(count) || !cloud->enableScalarField()) { delete cloud; return CC_FERR_NOT_ENOUGH_MEMORY; } ccProgressDialog pdlg(true); pdlg.setMethodTitle("Open Ult File"); CCLib::NormalizedProgress nprogress(&pdlg,count); pdlg.reset(); pdlg.setInfo(qPrintable(QString("Transformations: %1").arg(count))); pdlg.start(); QApplication::processEvents(); FILE* fp = fopen(filename,"rb"); if (!fp) { delete cloud; return CC_FERR_READING; } //which marker is the reference? QMessageBox::StandardButton tibiaIsRef = QMessageBox::question(0, "Choose reference", "Tibia as reference (yes)? Or femur (no)? Or none (no to all)", QMessageBox::Yes | QMessageBox::No | QMessageBox::NoToAll, QMessageBox::Yes ); MARKER_ROLE referenceRole = MARKER_LOCALIZER; if (tibiaIsRef == QMessageBox::Yes) referenceRole = MARKER_TIBIA; else if (tibiaIsRef == QMessageBox::No) referenceRole = MARKER_FEMUR; //To apply a predefined pointer tip //CCVector3 tip(0,0,0); CCVector3 tip(-90.07f, -17.68f, 18.29f); MarkersFrame currentframe; MarkerState& currentMarker = currentframe.states[MARKER_POINTER]; MarkerState* referenceMarker = 0; if (referenceRole != MARKER_LOCALIZER) referenceMarker = currentframe.states+referenceRole; unsigned MarkersFrameSize = sizeof(MarkersFrame); unsigned realCount=0; for (long i=0;i<count;++i) { if (fread(¤tframe,MarkersFrameSize,1,fp)==0) { fclose(fp); delete cloud; return CC_FERR_READING; } if (currentMarker.visible && (!referenceMarker || referenceMarker->visible)) { CCVector3 P(tip); ccGLMatrix trans = currentMarker.pos; if (referenceMarker) trans = referenceMarker->pos.inverse() * trans; trans.apply(P); cloud->addPoint(P); cloud->setPointScalarValue(realCount,currentMarker.pos.timestamp); ++realCount; } if (!nprogress.oneStep()) break; } fclose(fp); if (realCount==0) { delete cloud; return CC_FERR_NO_LOAD; } cloud->resize(realCount); //we update scalar field CCLib::ScalarField* sf = cloud->getCurrentInScalarField(); if (sf) { sf->setPositive(true); sf->computeMinAndMax(); cloud->setCurrentDisplayedScalarField(cloud->getCurrentInScalarFieldIndex()); } container.addChild(cloud); return CC_FERR_NO_ERROR; }
CC_FILE_ERROR PlyFilter::loadFile(const char* filename, ccHObject& container, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, double* coordinatesShift/*=0*/) { //reset statics! s_triCount = 0; s_unsupportedPolygonType = false; s_scalarCount=0; s_IntensityCount=0; s_ColorCount=0; s_NormalCount=0; s_PointCount=0; s_PointDataCorrupted=false; s_AlwaysDisplayLoadDialog=alwaysDisplayLoadDialog; s_ShiftApplyAll=false; s_ShiftAlreadyEnabled = (coordinatesShiftEnabled && *coordinatesShiftEnabled && coordinatesShift); if (s_ShiftAlreadyEnabled) memcpy(s_Pshift,coordinatesShift,sizeof(double)*3); else memset(s_Pshift,0,sizeof(double)*3); /****************/ /*** Header ***/ /****************/ //open a PLY file for reading p_ply ply = ply_open(filename,NULL, 0, NULL); if (!ply) return CC_FERR_READING; ccConsole::PrintDebug("[PLY] Opening file '%s' ...",filename); if (!ply_read_header(ply)) { ply_close(ply); return CC_FERR_WRONG_FILE_TYPE; } //storage mode: little/big endian e_ply_storage_mode storage_mode; get_plystorage_mode(ply,&storage_mode); /******************/ /*** Comments ***/ /******************/ //display comments const char* lastComment = NULL; while ((lastComment = ply_get_next_comment(ply, lastComment))) ccConsole::Print("[PLY][Comment] %s",lastComment); /*******************************/ /*** Elements & properties ***/ /*******************************/ //Point-based elements (points, colors, normals, etc.) std::vector<plyElement> pointElements; //Mesh-based elements (vertices, etc.) std::vector<plyElement> meshElements; //Point-based element properties (coordinates, color components, etc.) std::vector<plyProperty> stdProperties; //Mesh-based element properties (vertex indexes, etc.) std::vector<plyProperty> listProperties; unsigned i=0; //last read element plyElement lastElement; lastElement.elem = 0; while ((lastElement.elem = ply_get_next_element(ply, lastElement.elem))) { //we get next element info ply_get_element_info(lastElement.elem, &lastElement.elementName, &lastElement.elementInstances); if (lastElement.elementInstances == 0) { ccConsole::Warning("[PLY] Element '%s' was ignored as it has 0 instance!",lastElement.elementName); continue; } lastElement.properties.clear(); lastElement.propertiesCount=0; lastElement.isList=false; //printf("Element: %s\n",lastElement.elementName); //last read property plyProperty lastProperty; lastProperty.prop = 0; lastProperty.elemIndex = 0; while ((lastProperty.prop = ply_get_next_property(lastElement.elem,lastProperty.prop))) { //we get next property info ply_get_property_info(lastProperty.prop, &lastProperty.propName, &lastProperty.type, &lastProperty.length_type, &lastProperty.value_type); //printf("\tProperty: %s (%s)\n",lastProperty.propName,e_ply_type_names[lastProperty.type]); if (lastProperty.type == 16) //PLY_LIST lastElement.isList = true; lastElement.properties.push_back(lastProperty); ++lastElement.propertiesCount; } //if we have a "mesh-like" element if (lastElement.isList) { //we store its properties in 'listProperties' for (i=0;i<lastElement.properties.size();++i) { plyProperty& prop = lastElement.properties[i]; prop.elemIndex = meshElements.size(); //we only keep track of lists (we can't handle per triangle scalars) if (prop.type == 16) listProperties.push_back(prop); else { ccConsole::Warning("[PLY] Unhandled property: [%s:%s] (%s)", lastElement.elementName, prop.propName, e_ply_type_names[prop.type]); } } meshElements.push_back(lastElement); } else //else if we have a "point-like" element { //we store its properties in 'stdProperties' for (i=0;i<lastElement.properties.size();++i) { plyProperty& prop = lastElement.properties[i]; prop.elemIndex = pointElements.size(); stdProperties.push_back(prop); } pointElements.push_back(lastElement); } } //We need some points at least! if (pointElements.empty()) { ply_close(ply); return CC_FERR_NO_LOAD; } /**********************/ /*** Objects info ***/ /**********************/ const char* lastObjInfo = NULL; while ((lastObjInfo = ply_get_next_obj_info(ply, lastObjInfo))) ccConsole::Print("[PLY][Info] %s",lastObjInfo); /****************/ /*** Dialog ***/ /****************/ //properties indexes (0=unassigned) static const unsigned nStdProp=11; int stdPropIndexes[nStdProp]={0,0,0,0,0,0,0,0,0,0,0}; int& xIndex = stdPropIndexes[0]; int& yIndex = stdPropIndexes[1]; int& zIndex = stdPropIndexes[2]; int& nxIndex = stdPropIndexes[3]; int& nyIndex = stdPropIndexes[4]; int& nzIndex = stdPropIndexes[5]; int& rIndex = stdPropIndexes[6]; int& gIndex = stdPropIndexes[7]; int& bIndex = stdPropIndexes[8]; int& iIndex = stdPropIndexes[9]; int& sfIndex = stdPropIndexes[10]; static const unsigned nListProp=1; int listPropIndexes[nListProp]={0}; int& facesIndex = listPropIndexes[0]; //Combo box items for standard properties (coordinates, color components, etc.) QStringList stdPropsText; stdPropsText << QString("None"); for (i=1; i<=stdProperties.size(); ++i) { plyProperty& pp = stdProperties[i-1]; QString itemText = QString("%1 - %2 [%3]").arg(pointElements[pp.elemIndex].elementName).arg(pp.propName).arg(e_ply_type_names[pp.type]); assert(pp.type!=16); //we don't want any PLY_LIST here stdPropsText << itemText; QString elementName = QString(pointElements[pp.elemIndex].elementName).toUpper(); QString propName = QString(pp.propName).toUpper(); if (nxIndex == 0 && (propName.contains("NX") || (elementName.contains("NORM") && propName.endsWith("X")))) nxIndex = i; else if (nyIndex == 0 && (propName.contains("NY") || (elementName.contains("NORM") && propName.endsWith("Y")))) nyIndex = i; else if (nzIndex == 0 && (propName.contains("NZ") || (elementName.contains("NORM") && propName.endsWith("Z")))) nzIndex = i; else if (rIndex == 0 && (propName.contains("RED") || (elementName.contains("COL") && propName.endsWith("R")))) rIndex = i; else if (gIndex == 0 && (propName.contains("GREEN") || (elementName.contains("COL") && propName.endsWith("G")))) gIndex = i; else if (bIndex == 0 && (propName.contains("BLUE") || (elementName.contains("COL") && propName.endsWith("B")))) bIndex = i; else if (iIndex == 0 && (propName.contains("INTENSITY") || propName.contains("GRAY") || propName.contains("GREY") || (elementName.contains("COL") && propName.endsWith("I")))) iIndex = i; else if (elementName.contains("VERT") || elementName.contains("POINT")) { if (sfIndex == 0 && propName.contains("SCAL")) sfIndex = i; else if (xIndex == 0 && propName.endsWith("X")) xIndex = i; else if (yIndex == 0 && propName.endsWith("Y")) yIndex = i; else if (zIndex == 0 && propName.endsWith("Z")) zIndex = i; } else if (sfIndex == 0 && (propName.contains("SCAL") || propName.contains("VAL"))) sfIndex = i; } //Combo box items for list properties (vertex indexes, etc.) QStringList listPropsText; listPropsText << QString("None"); for (i=0; i<listProperties.size(); ++i) { plyProperty& pp = listProperties[i]; QString itemText = QString("%0 - %1 [%2]").arg(meshElements[pp.elemIndex].elementName).arg(pp.propName).arg(e_ply_type_names[pp.type]); assert(pp.type==16); //we only want PLY_LIST here listPropsText << itemText; QString elementName = QString(meshElements[pp.elemIndex].elementName).toUpper(); QString propName = QString(pp.propName).toUpper(); if (facesIndex == 0 && (elementName.contains("FACE") || elementName.contains("TRI")) && propName.contains("IND")) facesIndex = i+1; } //combo-box max visible items int stdPropsCount = stdPropsText.count(); int listPropsCount = listPropsText.count(); //we need at least 2 coordinates! if (stdPropsCount<2) { return CC_FERR_BAD_ENTITY_TYPE; } else if (stdPropsCount<4 && !alwaysDisplayLoadDialog) { //brute force heuristic xIndex = 1; yIndex = 2; zIndex = (stdPropsCount>3 ? 3 : 0); facesIndex = (listPropsCount>1 ? 1 : 0); } else { //we count all assigned properties int assignedStdProperties = 0; for (i=0;i<nStdProp;++i) if (stdPropIndexes[i]>0) ++assignedStdProperties; int assignedListProperties = 0; for (i=0;i<nListProp;++i) if (listPropIndexes[i]>0) ++assignedListProperties; if (alwaysDisplayLoadDialog || stdPropsCount > assignedStdProperties+1 || //+1 because of the first item in the combo box ('none') listPropsCount > assignedListProperties+1) //+1 because of the first item in the combo box ('none') { PlyOpenDlg pod/*(MainWindow::TheInstance())*/; pod.plyTypeEdit->setText(e_ply_storage_mode_names[storage_mode]); pod.elementsEdit->setText(QString::number(pointElements.size())); pod.propertiesEdit->setText(QString::number(listProperties.size()+stdProperties.size())); //we fill every combo box pod.xComboBox->addItems(stdPropsText); pod.xComboBox->setCurrentIndex(xIndex); pod.xComboBox->setMaxVisibleItems(stdPropsCount); pod.yComboBox->addItems(stdPropsText); pod.yComboBox->setCurrentIndex(yIndex); pod.yComboBox->setMaxVisibleItems(stdPropsCount); pod.zComboBox->addItems(stdPropsText); pod.zComboBox->setCurrentIndex(zIndex); pod.zComboBox->setMaxVisibleItems(stdPropsCount); pod.rComboBox->addItems(stdPropsText); pod.rComboBox->setCurrentIndex(rIndex); pod.rComboBox->setMaxVisibleItems(stdPropsCount); pod.gComboBox->addItems(stdPropsText); pod.gComboBox->setCurrentIndex(gIndex); pod.gComboBox->setMaxVisibleItems(stdPropsCount); pod.bComboBox->addItems(stdPropsText); pod.bComboBox->setCurrentIndex(bIndex); pod.bComboBox->setMaxVisibleItems(stdPropsCount); pod.iComboBox->addItems(stdPropsText); pod.iComboBox->setCurrentIndex(iIndex); pod.iComboBox->setMaxVisibleItems(stdPropsCount); pod.sfComboBox->addItems(stdPropsText); pod.sfComboBox->setCurrentIndex(sfIndex); pod.sfComboBox->setMaxVisibleItems(stdPropsCount); pod.nxComboBox->addItems(stdPropsText); pod.nxComboBox->setCurrentIndex(nxIndex); pod.nxComboBox->setMaxVisibleItems(stdPropsCount); pod.nyComboBox->addItems(stdPropsText); pod.nyComboBox->setCurrentIndex(nyIndex); pod.nyComboBox->setMaxVisibleItems(stdPropsCount); pod.nzComboBox->addItems(stdPropsText); pod.nzComboBox->setCurrentIndex(nzIndex); pod.nzComboBox->setMaxVisibleItems(stdPropsCount); pod.facesComboBox->addItems(listPropsText); pod.facesComboBox->setCurrentIndex(facesIndex); pod.facesComboBox->setMaxVisibleItems(listPropsCount); //We execute dialog if (!pod.exec()) { ply_close(ply); return CC_FERR_CANCELED_BY_USER; } //Force events processing (to hide dialog) QCoreApplication::processEvents(); xIndex = pod.xComboBox->currentIndex(); yIndex = pod.yComboBox->currentIndex(); zIndex = pod.zComboBox->currentIndex(); nxIndex = pod.nxComboBox->currentIndex(); nyIndex = pod.nyComboBox->currentIndex(); nzIndex = pod.nzComboBox->currentIndex(); rIndex = pod.rComboBox->currentIndex(); gIndex = pod.gComboBox->currentIndex(); bIndex = pod.bComboBox->currentIndex(); iIndex = pod.iComboBox->currentIndex(); facesIndex = pod.facesComboBox->currentIndex(); sfIndex = pod.sfComboBox->currentIndex(); } } /*************************/ /*** Callbacks setup ***/ /*************************/ //Main point cloud ccPointCloud* cloud = new ccPointCloud("unnamed - Cloud"); /* POINTS (X,Y,Z) */ unsigned numberOfPoints=0; assert(xIndex != yIndex && xIndex != zIndex && yIndex != zIndex); //POINTS (X) if (xIndex>0) { long flags = ELEM_POS_0; //X coordinate if (xIndex > yIndex && xIndex > zIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[xIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, vertex_cb, cloud, flags); numberOfPoints = pointElements[pp.elemIndex].elementInstances; } //POINTS (Y) if (yIndex>0) { long flags = ELEM_POS_1; //Y coordinate if (yIndex > xIndex && yIndex > zIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[yIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, vertex_cb, cloud, flags); if (numberOfPoints > 0) { if ((long)numberOfPoints != pointElements[pp.elemIndex].elementInstances) { ccConsole::Warning("[PLY] Bad/uncompatible assignation of point properties!"); delete cloud; ply_close(ply); return CC_FERR_BAD_ENTITY_TYPE; } } else numberOfPoints = pointElements[pp.elemIndex].elementInstances; } //POINTS (Z) if (zIndex>0) { long flags = ELEM_POS_2; //Z coordinate if (zIndex > xIndex && zIndex > yIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[zIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, vertex_cb, cloud, flags); if (numberOfPoints > 0) { if ((long)numberOfPoints != pointElements[pp.elemIndex].elementInstances) { ccConsole::Warning("[PLY] Bad/uncompatible assignation of point properties!"); delete cloud; ply_close(ply); return CC_FERR_BAD_ENTITY_TYPE; } } else numberOfPoints = pointElements[pp.elemIndex].elementInstances; } if (numberOfPoints == 0 || !cloud->reserveThePointsTable(numberOfPoints)) { delete cloud; ply_close(ply); return CC_FERR_NOT_ENOUGH_MEMORY; } /* NORMALS (X,Y,Z) */ unsigned numberOfNormals=0; assert(nxIndex == 0 || (nxIndex != nyIndex && nxIndex != nzIndex)); assert(nyIndex == 0 || (nyIndex != nxIndex && nyIndex != nzIndex)); assert(nzIndex == 0 || (nzIndex != nxIndex && nzIndex != nyIndex)); //NORMALS (X) if (nxIndex>0) { long flags = ELEM_POS_0; //Nx if (nxIndex > nyIndex && nxIndex > nzIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[nxIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, normal_cb, cloud, flags); numberOfNormals = pointElements[pp.elemIndex].elementInstances; } //NORMALS (Y) if (nyIndex>0) { long flags = ELEM_POS_1; //Ny if (nyIndex > nxIndex && nyIndex > nzIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[nyIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, normal_cb, cloud, flags); numberOfNormals = ccMax(numberOfNormals, (unsigned)pointElements[pp.elemIndex].elementInstances); } //NORMALS (Z) if (nzIndex>0) { long flags = ELEM_POS_2; //Nz if (nzIndex > nxIndex && nzIndex > nyIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[nzIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, normal_cb, cloud, flags); numberOfNormals = ccMax(numberOfNormals, (unsigned)pointElements[pp.elemIndex].elementInstances); } //We check that the number of normals corresponds to the number of points if (numberOfNormals > 0) { if (numberOfPoints != numberOfNormals) { ccConsole::Warning("[PLY] The number of normals doesn't match the number of points!"); delete cloud; ply_close(ply); return CC_FERR_BAD_ENTITY_TYPE; } if (!cloud->reserveTheNormsTable()) { delete cloud; ply_close(ply); return CC_FERR_NOT_ENOUGH_MEMORY; } cloud->showNormals(true); } /* COLORS (R,G,B) */ unsigned numberOfColors=0; assert(rIndex == 0 || (rIndex != gIndex && rIndex != bIndex)); assert(gIndex == 0 || (gIndex != rIndex && gIndex != bIndex)); assert(bIndex == 0 || (bIndex != rIndex && bIndex != gIndex)); if (rIndex>0) { long flags = ELEM_POS_0; //R if (rIndex > gIndex && rIndex > bIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[rIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, rgb_cb, cloud, flags); numberOfColors = pointElements[pp.elemIndex].elementInstances; } if (gIndex>0) { long flags = ELEM_POS_1; //G if (gIndex > rIndex && gIndex > bIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[gIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, rgb_cb, cloud, flags); numberOfColors = ccMax(numberOfColors, (unsigned)pointElements[pp.elemIndex].elementInstances); } if (bIndex>0) { long flags = ELEM_POS_2; //B if (bIndex > rIndex && bIndex > gIndex) flags |= ELEM_EOL; plyProperty& pp = stdProperties[bIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, rgb_cb, cloud, flags); numberOfColors = ccMax(numberOfColors, (unsigned)pointElements[pp.elemIndex].elementInstances); } /* Intensity (I) */ //INTENSITE (G) if (iIndex>0) { if (numberOfColors>0) { ccConsole::Error("Can't import colors AND intensity (intensities will be ignored)!"); ccConsole::Warning("[PLY] intensities will be ignored"); } else { plyProperty pp = stdProperties[iIndex-1]; ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, grey_cb, cloud, 0); numberOfColors = pointElements[pp.elemIndex].elementInstances; } } //We check that the number of colors corresponds to the number of points if (numberOfColors > 0) { if (numberOfPoints != numberOfColors) { ccConsole::Warning("The number of colors doesn't match the number of points!"); delete cloud; ply_close(ply); return CC_FERR_BAD_ENTITY_TYPE; } if (!cloud->reserveTheRGBTable()) { delete cloud; ply_close(ply); return CC_FERR_NOT_ENOUGH_MEMORY; } cloud->showColors(true); } /* SCALAR FIELD (SF) */ unsigned numberOfScalars=0; if (sfIndex>0) { plyProperty& pp = stdProperties[sfIndex-1]; numberOfScalars = pointElements[pp.elemIndex].elementInstances; //does the number of scalars matches the number of points? if (numberOfPoints != numberOfScalars) { ccConsole::Error("The number of scalars doesn't match the number of points (they will be ignored)!"); ccConsole::Warning("[PLY] Scalar field ignored!"); numberOfScalars = 0; } else if (!cloud->enableScalarField()) { ccConsole::Error("Not enough memory to load scalar field (they will be ignored)!"); ccConsole::Warning("[PLY] Scalar field ignored!"); numberOfScalars = 0; } else { CCLib::ScalarField* sf = cloud->getCurrentInScalarField(); if (sf) { QString qPropName(pp.propName); if (qPropName.startsWith("scalar_") && qPropName.length()>7) { //remove the 'scalar_' prefix added when saving SF with CC! qPropName = qPropName.mid(7).replace('_',' '); sf->setName(qPrintable(qPropName)); } else { sf->setName(pp.propName); } } ply_set_read_cb(ply, pointElements[pp.elemIndex].elementName, pp.propName, scalar_cb, cloud, 1); } cloud->showSF(true); } /* MESH FACETS (TRI) */ ccMesh* mesh = 0; unsigned numberOfFacets=0; if (facesIndex>0) { plyProperty& pp = listProperties[facesIndex-1]; assert(pp.type==16); //we only accept PLY_LIST here! mesh = new ccMesh(cloud); numberOfFacets = meshElements[pp.elemIndex].elementInstances; if (!mesh->reserve(numberOfFacets)) { ccConsole::Error("Not enough memory to load facets (they will be ignored)!"); ccConsole::Warning("[PLY] Mesh ignored!"); delete mesh; mesh = 0; numberOfFacets = 0; } else { ply_set_read_cb(ply, meshElements[pp.elemIndex].elementName, pp.propName, face_cb, mesh, 0); } } QProgressDialog progressDlg(QString("Loading in progress..."),0,0,0,0,Qt::Popup); progressDlg.setMinimumDuration(0); progressDlg.setModal(true); progressDlg.show(); QApplication::processEvents(); int success = ply_read(ply); progressDlg.close(); ply_close(ply); if (success<1) { if (mesh) delete mesh; delete cloud; return CC_FERR_READING; } //we check mesh if (mesh && mesh->size()==0) { if (s_unsupportedPolygonType) ccConsole::Error("Mesh is not triangular! (unsupported)"); else ccConsole::Error("Mesh is empty!"); delete mesh; mesh=0; } //we save coordinates shift information if (s_ShiftApplyAll && coordinatesShiftEnabled && coordinatesShift) { *coordinatesShiftEnabled = true; coordinatesShift[0] = s_Pshift[0]; coordinatesShift[1] = s_Pshift[1]; coordinatesShift[2] = s_Pshift[2]; } //we update scalar field CCLib::ScalarField* sf = cloud->getCurrentInScalarField(); if (sf) { sf->setPositive(!s_negSF); sf->computeMinAndMax(); int sfIdx = cloud->getCurrentInScalarFieldIndex(); cloud->setCurrentDisplayedScalarField(sfIdx); cloud->showSF(sfIdx>=0); } if (mesh) { assert(s_triCount > 0); //check number of loaded facets against 'theoretical' number if (s_triCount<numberOfFacets) { mesh->resize(s_triCount); ccConsole::Warning("[PLY] Missing vertex indexes!"); } //check that vertex indices start at 0 unsigned minVertIndex=numberOfPoints,maxVertIndex=0; for (unsigned i=0;i<s_triCount;++i) { const CCLib::TriangleSummitsIndexes* tri = mesh->getTriangleIndexes(i); if (tri->i1 < minVertIndex) minVertIndex = tri->i1; else if (tri->i1 > maxVertIndex) maxVertIndex = tri->i1; if (tri->i2 < minVertIndex) minVertIndex = tri->i2; else if (tri->i2 > maxVertIndex) maxVertIndex = tri->i2; if (tri->i3 < minVertIndex) minVertIndex = tri->i3; else if (tri->i3 > maxVertIndex) maxVertIndex = tri->i3; } if (maxVertIndex>=numberOfPoints) { if (maxVertIndex == numberOfPoints && minVertIndex > 0) { ccLog::Warning("[PLY] Vertex indices seem to be shifted (+1)! We will try to 'unshift' indices (otherwise file is corrupted...)"); for (unsigned i=0;i<s_triCount;++i) { CCLib::TriangleSummitsIndexes* tri = mesh->getTriangleIndexes(i); --tri->i1; --tri->i2; --tri->i3; } } else //file is definitely corrupted! { ccLog::Warning("[PLY] Invalid vertex indices!"); delete mesh; delete cloud; return CC_FERR_MALFORMED_FILE; } } mesh->addChild(cloud); cloud->setEnabled(false); cloud->setName("Vertices"); //cloud->setLocked(true); //DGM: no need to lock it as it is only used by one mesh! if (cloud->hasColors()) mesh->showColors(true); if (cloud->hasDisplayedScalarField()) mesh->showSF(true); if (cloud->hasNormals()) mesh->showNormals(true); else mesh->computeNormals(); container.addChild(mesh); } else { container.addChild(cloud); } return CC_FERR_NO_ERROR; }
CC_FILE_ERROR BinFilter::loadFileV1(QFile& in, ccHObject& container, unsigned nbScansTotal) { if (nbScansTotal>99) { if (QMessageBox::question(0, QString("Oups"), QString("Hum, do you really expect %1 point clouds?").arg(nbScansTotal))==QMessageBox::No) return CC_FERR_WRONG_FILE_TYPE; } else if (nbScansTotal==0) { return CC_FERR_NO_LOAD; } ccProgressDialog pdlg(true); pdlg.setMethodTitle("Open Bin file (old style)"); for (unsigned k=0;k<nbScansTotal;k++) { HeaderFlags header; unsigned nbOfPoints=0; if (ReadEntityHeader(in,nbOfPoints,header) < 0) return CC_FERR_READING; //Console::print("[BinFilter::loadModelFromBinaryFile] Entity %i : %i points, color=%i, norms=%i, dists=%i\n",k,nbOfPoints,color,norms,distances); //progress for this cloud CCLib::NormalizedProgress nprogress(&pdlg,nbOfPoints); pdlg.reset(); char buffer[256]; sprintf(buffer,"cloud %i/%i (%i points)",k+1,nbScansTotal,nbOfPoints); pdlg.setInfo(buffer); pdlg.start(); QApplication::processEvents(); if (nbOfPoints==0) { //Console::print("[BinFilter::loadModelFromBinaryFile] rien a faire !\n"); continue; } //Cloud name char cloudName[256]="unnamed"; if (header.name) { for (int i=0;i<256;++i) { if (in.read(cloudName+i,1)<0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the cloud name!\n"); return CC_FERR_READING; } if (cloudName[i]==0) break; } //we force the end of the name in case it is too long! cloudName[255]=0; } else { sprintf(cloudName,"unnamed - Cloud #%i",k); } //Cloud name char sfName[1024]="unnamed"; if (header.sfName) { for (int i=0;i<1024;++i) { if (in.read(sfName+i,1)<0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the cloud name!\n"); return CC_FERR_READING; } if (sfName[i]==0) break; } //we force the end of the name in case it is too long! sfName[1023]=0; } else { strcpy(sfName,"Loaded scalar field"); } //Creation ccPointCloud* loadedCloud = new ccPointCloud(cloudName); if (!loadedCloud) return CC_FERR_NOT_ENOUGH_MEMORY; unsigned fileChunkPos = 0; unsigned fileChunkSize = ccMin(nbOfPoints,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD); loadedCloud->reserveThePointsTable(fileChunkSize); if (header.colors) { loadedCloud->reserveTheRGBTable(); loadedCloud->showColors(true); } if (header.normals) { loadedCloud->reserveTheNormsTable(); loadedCloud->showNormals(true); } if (header.scalarField) loadedCloud->enableScalarField(); CCVector3 P; unsigned char C[3]; double D; //does the associated scalar field is negative? bool negSF = false; unsigned lineReaded=0; int parts = 0; //lecture du fichier for (unsigned i=0;i<nbOfPoints;++i) { if (lineReaded == fileChunkPos+fileChunkSize) { if (header.scalarField) loadedCloud->getCurrentInScalarField()->computeMinAndMax(); container.addChild(loadedCloud); fileChunkPos = lineReaded; fileChunkSize = ccMin(nbOfPoints-lineReaded,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD); char partName[64]; ++parts; sprintf(partName,"%s.part_%i",cloudName,parts); loadedCloud = new ccPointCloud(partName); loadedCloud->reserveThePointsTable(fileChunkSize); if (header.colors) { loadedCloud->reserveTheRGBTable(); loadedCloud->showColors(true); } if (header.normals) { loadedCloud->reserveTheNormsTable(); loadedCloud->showNormals(true); } if (header.scalarField) loadedCloud->enableScalarField(); } if (in.read((char*)P.u,sizeof(float)*3)<0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity point !\n",k); return CC_FERR_READING; } loadedCloud->addPoint(P); if (header.colors) { if (in.read((char*)C,sizeof(colorType)*3)<0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity colors !\n",k); return CC_FERR_READING; } loadedCloud->addRGBColor(C); } if (header.normals) { if (in.read((char*)P.u,sizeof(float)*3)<0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity norms !\n",k); return CC_FERR_READING; } loadedCloud->addNorm(P.u); } if (header.scalarField) { if (in.read((char*)&D,sizeof(double))<0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity distance !\n",k); return CC_FERR_READING; } DistanceType d = (DistanceType)D; //if there are negative values, we test if they are particular values (HIDDEN_VALUE, etc.) //or not particular (in which case we have a non strictly positive SF) if (d<0.0 && !negSF) { //we must test if the value is a particular one if (d != HIDDEN_VALUE && d != OUT_VALUE && d != SEGMENTED_VALUE) negSF = true; } loadedCloud->setPointScalarValue(i,d); } lineReaded++; if (!nprogress.oneStep()) { loadedCloud->resize(i+1-fileChunkPos); k=nbScansTotal; i=nbOfPoints; } } if (header.scalarField) { CCLib::ScalarField* sf = loadedCloud->getCurrentInScalarField(); assert(sf); sf->setName(sfName); sf->setPositive(!negSF); sf->computeMinAndMax(); loadedCloud->setCurrentDisplayedScalarField(loadedCloud->getCurrentInScalarFieldIndex()); loadedCloud->showSF(true); } container.addChild(loadedCloud); } return CC_FERR_NO_ERROR; }