Exemple #1
0
bool ccGenericMesh::computeNormals()
{
    if (!m_associatedCloud || !m_associatedCloud->isA(CC_POINT_CLOUD)) //TODO
        return false;

    unsigned triCount = size();
    if (triCount==0)
    {
        ccLog::Error("[ccGenericMesh::computeNormals] Empty mesh!");
        return false;
    }
    unsigned vertCount=m_associatedCloud->size();
    if (vertCount<3)
    {
        ccLog::Error("[ccGenericMesh::computeNormals] Not enough vertices! (<3)");
        return false;
    }

    ccPointCloud* cloud = static_cast<ccPointCloud*>(m_associatedCloud);

    //we instantiate a temporary structure to store each vertex normal (uncompressed)
    NormsTableType* theNorms = new NormsTableType;
    if (!theNorms->reserve(vertCount))
    {
        theNorms->release();
        return false;
    }
    theNorms->fill(0);

    //allocate compressed normals array on vertices cloud
    bool normalsWereAllocated = cloud->hasNormals();
    if (!normalsWereAllocated && !cloud->resizeTheNormsTable())
    {
        theNorms->release();
        return false;
    }

    //for each triangle
    placeIteratorAtBegining();
    {
        for (unsigned i=0; i<triCount; ++i)
        {
            CCLib::TriangleSummitsIndexes* tsi = getNextTriangleIndexes();

            assert(tsi->i1<vertCount && tsi->i2<vertCount && tsi->i3<vertCount);
            const CCVector3 *A = cloud->getPoint(tsi->i1);
            const CCVector3 *B = cloud->getPoint(tsi->i2);
            const CCVector3 *C = cloud->getPoint(tsi->i3);

            //compute face normal (right hand rule)
            CCVector3 N = (*B-*A).cross(*C-*A);
            //N.normalize(); //DGM: no normalization = weighting by surface!

            //we add this normal to all triangle vertices
            PointCoordinateType* N1 = theNorms->getValue(tsi->i1);
            CCVector3::vadd(N1,N.u,N1);
            PointCoordinateType* N2 = theNorms->getValue(tsi->i2);
            CCVector3::vadd(N2,N.u,N2);
            PointCoordinateType* N3 = theNorms->getValue(tsi->i3);
            CCVector3::vadd(N3,N.u,N3);
        }
    }

    //for each vertex
    {
        for (unsigned i=0; i<vertCount; i++)
        {
            PointCoordinateType* N = theNorms->getValue(i);
            CCVector3::vnormalize(N);
            cloud->setPointNormal(i,N);
            theNorms->forwardIterator();
        }
    }

    showNormals(true);
    if (!normalsWereAllocated)
        cloud->showNormals(true);

    //theNorms->clear();
    theNorms->release();
    theNorms=0;

    return true;
}
CC_FILE_ERROR DepthMapFileFilter::saveToFile(QString filename, ccGBLSensor* sensor)
{
	assert(sensor);
	if (!sensor)
	{
		return CC_FERR_BAD_ARGUMENT;
	}

	//the depth map associated to this sensor
	const ccGBLSensor::DepthBuffer& db = sensor->getDepthBuffer();
	if (db.zBuff.empty())
	{
		ccLog::Warning(QString("[DepthMap] sensor '%1' has no associated depth map (you must compute it first)").arg(sensor->getName()));
		return CC_FERR_NO_SAVE; //this is not a severe error (the process can go on)
	}

	ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(sensor->getParent());
	if (!cloud)
	{
		ccLog::Warning(QString("[DepthMap] sensor '%1' is not associated to a point cloud!").arg(sensor->getName()));
		//this is not a severe error (the process can go on)
	}

	//opening file
	FILE* fp = fopen(qPrintable(filename),"wt");
	if (!fp)
	{
		ccLog::Error(QString("[DepthMap] Can't open file '%1' for writing!").arg(filename));
		return CC_FERR_WRITING;
	}

	fprintf(fp,"// SENSOR DEPTH MAP\n");
	fprintf(fp,"// Associated cloud: %s\n",qPrintable(cloud ? cloud->getName() : "none"));
	fprintf(fp,"// Pitch  = %f [ %f : %f ]\n",
		sensor->getPitchStep(),
		sensor->getMinPitch(),
		sensor->getMaxPitch());
	fprintf(fp,"// Yaw   = %f [ %f : %f ]\n",
		sensor->getYawStep(),
		sensor->getMinYaw(),
		sensor->getMaxYaw());
	fprintf(fp,"// Range  = %f\n",sensor->getSensorRange());
	fprintf(fp,"// L      = %i\n",db.width);
	fprintf(fp,"// H      = %i\n",db.height);
	fprintf(fp,"/////////////////////////\n");

	//an array of projected normals (same size a depth map)
	ccGBLSensor::NormalGrid* theNorms = NULL;
	//an array of projected colors (same size a depth map)
	ccGBLSensor::ColorGrid* theColors = NULL;

	//if the sensor is associated to a "ccPointCloud", we may also extract
	//normals and color!
	if (cloud && cloud->isA(CC_TYPES::POINT_CLOUD))
	{
		ccPointCloud* pc = static_cast<ccPointCloud*>(cloud);

		unsigned nbPoints = cloud->size();
		if (nbPoints == 0)
		{
			ccLog::Warning(QString("[DepthMap] sensor '%1' is associated to an empty cloud?!").arg(sensor->getName()));
			//this is not a severe error (the process can go on)
		}
		else
		{
			//if possible, we create the array of projected normals
			if (pc->hasNormals())
			{
				NormsTableType* decodedNorms = new NormsTableType;
				if (decodedNorms->reserve(nbPoints))
				{
					for (unsigned i=0; i<nbPoints; ++i)
						decodedNorms->addElement(pc->getPointNormal(i).u);

					theNorms = sensor->projectNormals(pc,*decodedNorms);
					decodedNorms->clear();
				}
				else
				{
					ccLog::Warning(QString("[DepthMap] not enough memory to load normals on sensor '%1'!").arg(sensor->getName()));
				}
				decodedNorms->release();
				decodedNorms = 0;
			}

			//if possible, we create the array of projected colors
			if (pc->hasColors())
			{
				GenericChunkedArray<3,ColorCompType>* rgbColors = new GenericChunkedArray<3,ColorCompType>();
				rgbColors->reserve(nbPoints);

				for (unsigned i=0; i<nbPoints; ++i)
				{
					//conversion from ColorCompType[3] to unsigned char[3]
					const ColorCompType* col = pc->getPointColor(i);
					rgbColors->addElement(col);
				}

				theColors = sensor->projectColors(pc,*rgbColors);
				rgbColors->clear();
				rgbColors->release();
				rgbColors = 0;
			}
		}
	}

	const ScalarType* _zBuff = &(db.zBuff.front());
	if (theNorms)
		theNorms->placeIteratorAtBegining();
	if (theColors)
		theColors->placeIteratorAtBegining();
	for (unsigned k=0; k<db.height; ++k)
	{
		for (unsigned j=0; j<db.width; ++j, ++_zBuff)
		{
			//grid index and depth
			fprintf(fp,"%u %u %.12f",j,k,*_zBuff);

			//color
			if (theColors)
			{
				const ColorCompType* C = theColors->getCurrentValue();
				fprintf(fp," %i %i %i",C[0],C[1],C[2]);
				theColors->forwardIterator();
			}

			//normal
			if (theNorms)
			{
				const PointCoordinateType* N = theNorms->getCurrentValue();
				fprintf(fp," %f %f %f",N[0],N[1],N[2]);
				theNorms->forwardIterator();
			}

			fprintf(fp,"\n");
		}
	}

	fclose(fp);
	fp = 0;

	if (theNorms)
	{
		theNorms->release();
		theNorms = 0;
	}
	if (theColors)
	{
		theColors->release();
		theColors = 0;
	}

	return CC_FERR_NO_ERROR;
}
Exemple #3
0
CC_FILE_ERROR DepthMapFileFilter::saveToOpenedFile(FILE* fp, ccGBLSensor* sensor)
{
	assert(fp && sensor);

	if (!sensor->getParent()->isKindOf(CC_TYPES::POINT_CLOUD))
	{
		ccLog::Warning(QString("[DepthMap] sensor '%1' is not associated to a point cloud!").arg(sensor->getName()));
		return CC_FERR_NO_ERROR; //this is not a severe error (the process can go on)
	}

	ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(sensor->getParent());

	//the depth map associated to this sensor
	const ccGBLSensor::DepthBuffer& db = sensor->getDepthBuffer();

	fprintf(fp,"// CLOUDCOMPARE DEPTH MAP\n");
	fprintf(fp,"// Associated cloud: %s\n",qPrintable(cloud->getName()));
	fprintf(fp,"// dPhi   = %f [ %f : %f ]\n",
		sensor->getDeltaPhi(),
		sensor->getPhiMin(),
		sensor->getPhiMax());
	fprintf(fp,"// dTheta = %f [ %f : %f ]\n",
		sensor->getDeltaTheta(),
		sensor->getThetaMin(),
		sensor->getThetaMax());
	fprintf(fp,"// pMax   = %f\n",sensor->getSensorRange());
	fprintf(fp,"// L      = %i\n",db.width);
	fprintf(fp,"// H      = %i\n",db.height);
	fprintf(fp,"/////////////////////////\n");

	//an array of projected normals (same size a depth map)
	PointCoordinateType* theNorms = NULL;
	//an array of projected colors (same size a depth map)
	colorType* theColors = NULL;

	//if the sensor is associated to a "ccPointCloud", we may also extract
	//normals and color!
	if (cloud->isA(CC_TYPES::POINT_CLOUD))
	{
		ccPointCloud* pc = static_cast<ccPointCloud*>(cloud);

		unsigned nbPoints = cloud->size();
		if (nbPoints == 0)
		{
			ccLog::Warning(QString("[DepthMap] sensor '%1' is associated to an empty cloud!").arg(sensor->getName()));
			return CC_FERR_NO_ERROR; //this is not a severe error (the process can go on)
		}
		else
		{
			//if possible, we create the array of projected normals
			if (pc->hasNormals())
			{
				NormsTableType* decodedNorms = new NormsTableType;
				if (decodedNorms->reserve(nbPoints))
				{
					for (unsigned i=0; i<nbPoints; ++i)
						decodedNorms->addElement(pc->getPointNormal(i).u);

					theNorms = sensor->projectNormals(pc,*decodedNorms);
					decodedNorms->clear();
				}
				else
				{
					ccLog::Warning(QString("[DepthMap] not enough memory to load normals on sensor '%1'!").arg(sensor->getName()));
				}
				decodedNorms->release();
				decodedNorms = 0;
			}

			//if possible, we create the array of projected colors
			if (pc->hasColors())
			{
				GenericChunkedArray<3,colorType>* rgbColors = new GenericChunkedArray<3,colorType>();
				rgbColors->reserve(nbPoints);

				for (unsigned i=0; i<nbPoints; ++i)
				{
					//conversion from colorType[3] to unsigned char[3]
					const colorType* col = pc->getPointColor(i);
					rgbColors->addElement(col);
				}

				theColors = sensor->projectColors(pc,*rgbColors);
				rgbColors->clear();
				rgbColors->release();
				rgbColors = 0;
			}
		}
	}

	PointCoordinateType* _theNorms = theNorms;
	colorType* _theColors = theColors;
	ScalarType* _zBuff = db.zBuff;

	for (unsigned k=0; k<db.height; ++k)
	{
		for (unsigned j=0; j<db.width; ++j)
		{
			//grid index and depth
			fprintf(fp,"%i %i %.12f",j,k,*_zBuff++);

			//color
			if (_theColors)
			{
				fprintf(fp," %i %i %i",_theColors[0],_theColors[1],_theColors[2]);
				_theColors += 3;
			}

			//normal
			if (_theNorms)
			{
				fprintf(fp," %f %f %f",_theNorms[0],_theNorms[1],_theNorms[2]);
				_theNorms += 3;
			}

			fprintf(fp,"\n");
		}
	}

	if (theNorms)
		delete[] theNorms;
	if (theColors)
		delete[] theColors;

	return CC_FERR_NO_ERROR;
}