Example #1
0
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(&currentframe,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;
}
Example #2
0
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;
}
Example #3
0
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;
}