示例#1
0
//helper: computes a facet horizontal and vertical extensions
void ComputeFacetExtensions(CCVector3& N, ccPolyline* facetContour, double& horizExt, double& vertExt)
{
	//horizontal and vertical extensions
	horizExt = vertExt = 0;
	
	CCLib::GenericIndexedCloudPersist* vertCloud = facetContour->getAssociatedCloud();
	if (vertCloud)
	{
		//oriRotMat.applyRotation(N); //DGM: oriRotMat is only for display!
		//we assume that at this point the "up" direction is always (0,0,1)
		CCVector3 Xf(1,0,0), Yf(0,1,0);
		//we get the horizontal vector on the plane
		CCVector3 D = CCVector3(0,0,1).cross(N);
		if (D.norm2() > ZERO_TOLERANCE) //otherwise the facet is horizontal!
		{
			Yf = D;
			Yf.normalize();
			Xf = N.cross(Yf);
		}

		const CCVector3* G = CCLib::Neighbourhood(vertCloud).getGravityCenter();

		ccBBox box;
		for (unsigned i=0; i<vertCloud->size(); ++i)
		{
			const CCVector3 P = *(vertCloud->getPoint(i)) - *G;
			CCVector3 p( P.dot(Xf), P.dot(Yf), 0 );
			box.add(p);
		}

		vertExt = box.getDiagVec().x;
		horizExt = box.getDiagVec().y;
	}
}
示例#2
0
void CCMiscTools::ComputeBaseVectors(const CCVector3 &N, CCVector3& X, CCVector3& Y)
{
	CCVector3 Nunit = N;
	Nunit.normalize();

	//we create a first vector orthogonal to the input one
	X = Nunit.orthogonal(); //X is also normalized

	//we deduce the orthogonal vector to the input one and X
	Y = N.cross(X);
	//Y.normalize(); //should already be normalized!
}
示例#3
0
SimpleCloud* MeshSamplingTools::samplePointsOnMesh(GenericMesh* theMesh,
													double samplingDensity,
													unsigned theoricNumberOfPoints,
													GenericProgressCallback* progressCb,
													GenericChunkedArray<1,unsigned>* triIndices/*=0*/)
{
	assert(theMesh);
	unsigned triCount = (theMesh ? theMesh->size() : 0);
	if (triCount==0)
		return 0;

	if (theoricNumberOfPoints < 1)
        return 0;


	SimpleCloud* sampledCloud = new SimpleCloud();
	if (!sampledCloud->reserve(theoricNumberOfPoints)) //not enough memory
	{
		delete sampledCloud;
		return 0;
	}

	if (triIndices)
	{
	    triIndices->clear();
		//not enough memory? DGM TODO: we should warn the caller
		if (!triIndices->reserve(theoricNumberOfPoints) || triIndices->capacity() < theoricNumberOfPoints)
		{
			delete sampledCloud;
			triIndices->clear();
			return 0;
		}
	}

	NormalizedProgress* normProgress=0;
    if(progressCb)
    {
		normProgress = new NormalizedProgress(progressCb,triCount);
		progressCb->setMethodTitle("Mesh sampling");
		char buffer[256];
		sprintf(buffer,"Triangles: %i\nPoints: %i",triCount,theoricNumberOfPoints);
		progressCb->setInfo(buffer);
        progressCb->reset();
		progressCb->start();
	}

	unsigned addedPoints=0;

	//for each triangle
	theMesh->placeIteratorAtBegining();
	for (unsigned n=0;n<triCount;++n)
	{
		const GenericTriangle* tri = theMesh->_getNextTriangle();

		//summits (OAB)
		const CCVector3 *O = tri->_getA();
		const CCVector3 *A = tri->_getB();
		const CCVector3 *B = tri->_getC();

		//edges (OA and OB)
		CCVector3 u = *A - *O;
		CCVector3 v = *B - *O;

		//we compute the (twice) the triangle area
		CCVector3 N = u.cross(v);
		double S = N.norm()/2.0;

		//we deduce the number of points to generate on this face
		double fPointsToAdd = S*samplingDensity;
		unsigned pointsToAdd = static_cast<unsigned>(fPointsToAdd);

        //if the face area is smaller than the surface/random point
		if (pointsToAdd == 0)
		{
			//we add a point with the same probability as its (relative) area
			if (static_cast<double>(rand()) <= fPointsToAdd * static_cast<double>(RAND_MAX))
                pointsToAdd = 1;
		}

		if (pointsToAdd)
		{
			if (addedPoints + pointsToAdd >= theoricNumberOfPoints)
			{
				theoricNumberOfPoints+=pointsToAdd;
				if (!sampledCloud->reserve(theoricNumberOfPoints)
					|| (triIndices && triIndices->capacity() < theoricNumberOfPoints && !triIndices->reserve(theoricNumberOfPoints))) //not enough memory
				{
					delete sampledCloud;
					sampledCloud = 0;
					triIndices->clear();
					break;
				}
			}

			for (unsigned i=0; i<pointsToAdd; ++i)
			{
				//we generates random points as in:
				//'Greg Turk. Generating random points in triangles. In A. S. Glassner, editor,Graphics Gems, pages 24-28. Academic Press, 1990.'
				double x = static_cast<double>(rand())/static_cast<double>(RAND_MAX);
				double y = static_cast<double>(rand())/static_cast<double>(RAND_MAX);

				//we test if the generated point lies on the right side of (AB)
				if (x+y > 1.0)
				{
                    x = 1.0-x;
                    y = 1.0-y;
                }

				CCVector3 P = (*O) + static_cast<PointCoordinateType>(x) * u + static_cast<PointCoordinateType>(y) * v;

				sampledCloud->addPoint(P);
				if (triIndices)
					triIndices->addElement(n);
				++addedPoints;
			}
		}

		if (normProgress && !normProgress->oneStep())
			break;
	}

	if (normProgress)
	{
        delete normProgress;
		normProgress = 0;
	}

	if (sampledCloud) //can be in case of memory overflow!
	{
		if (addedPoints)
		{
			sampledCloud->resize(addedPoints); //should always be ok as addedPoints<theoricNumberOfPoints
			if (triIndices)
				triIndices->resize(addedPoints);
		}
		else
		{
			delete sampledCloud;
			sampledCloud = 0;
			if (triIndices)
				triIndices->clear();
		}
	}

	return sampledCloud;
}
示例#4
0
ccGLMatrix ccGLMatrix::FromToRotation(const CCVector3& from, const CCVector3& to)
{
	float e = from.dot(to);
	float f = (e < 0 ? -e : e);
	ccGLMatrix result;
	float* mat = result.data();

	if (f > 1.0-ZERO_TOLERANCE)     //"from" and "to"-vector almost parallel
	{
		CCVector3 x;       // vector most nearly orthogonal to "from"
		x.x = (from.x > 0 ? from.x : -from.x);
		x.y = (from.y > 0 ? from.y : -from.y);
		x.z = (from.z > 0 ? from.z : -from.z);

		if (x.x < x.y)
		{
			if (x.x < x.z)
			{
				x.x = 1.0f; x.y = x.z = 0;
			}
			else
			{
				x.z = 1.0f; x.x = x.y = 0;
			}
		}
		else
		{
			if (x.y < x.z)
			{
				x.y = 1.0f; x.x = x.z = 0;
			}
			else
			{
				x.z = 1.0f; x.x = x.y = 0;
			}
		}

		CCVector3 u(x.x-from.x, x.y-from.y, x.z-from.z);
		CCVector3 v(x.x-to.x, x.y-to.y, x.z-to.z);

		float c1 = 2.0f / u.dot(u);
		float c2 = 2.0f / v.dot(v);
		float c3 = c1 * c2  * u.dot(v);

		for (unsigned i = 0; i < 3; i++)
		{
			for (unsigned j = 0; j < 3; j++)
			{
				mat[i*4+j]=  c3 * v.u[i] * u.u[j]
						   - c2 * v.u[i] * v.u[j]
						   - c1 * u.u[i] * u.u[j];
			}
			mat[i*4+i] += 1.0f;
		}
	}
	else  // the most common case, unless "from"="to", or "from"=-"to"
	{
		//hand optimized version (9 mults less)
		CCVector3 v = from.cross(to);
		float h = 1.0f/(1.0f + e);
		float hvx = h * v.x;
		float hvz = h * v.z;
		float hvxy = hvx * v.y;
		float hvxz = hvx * v.z;
		float hvyz = hvz * v.y;

		mat[0] = e + hvx * v.x;
		mat[1] = hvxy - v.z;
		mat[2] = hvxz + v.y;

		mat[4] = hvxy + v.z;
		mat[5] = e + h * v.y * v.y;
		mat[6] = hvyz - v.x;

		mat[8] = hvxz - v.y;
		mat[9] = hvyz + v.x;
		mat[10] = e + hvz * v.z;
	}

	return result;
}
示例#5
0
文件: ccClipBox.cpp 项目: jebd/trunk
bool ccClipBox::move3D(const CCVector3& uInput)
{
	if (m_activeComponent == NONE || !m_box.isValid())
		return false;

	CCVector3 u = uInput;

	//Arrows
	if (m_activeComponent >= X_MINUS_ARROW && m_activeComponent <= CROSS)
	{
		if (m_glTransEnabled)
			m_glTrans.inverse().applyRotation(u);

		switch(m_activeComponent)
		{
		case X_MINUS_ARROW:
			m_box.minCorner().x += u.x;
			if (m_box.minCorner().x > m_box.maxCorner().x)
				m_box.minCorner().x = m_box.maxCorner().x;
			break;
		case X_PLUS_ARROW:
			m_box.maxCorner().x += u.x;
			if (m_box.minCorner().x > m_box.maxCorner().x)
				m_box.maxCorner().x = m_box.minCorner().x;
			break;
		case Y_MINUS_ARROW:
			m_box.minCorner().y += u.y;
			if (m_box.minCorner().y > m_box.maxCorner().y)
				m_box.minCorner().y = m_box.maxCorner().y;
			break;
		case Y_PLUS_ARROW:
			m_box.maxCorner().y += u.y;
			if (m_box.minCorner().y > m_box.maxCorner().y)
				m_box.maxCorner().y = m_box.minCorner().y;
			break;
		case Z_MINUS_ARROW:
			m_box.minCorner().z += u.z;
			if (m_box.minCorner().z > m_box.maxCorner().z)
				m_box.minCorner().z = m_box.maxCorner().z;
			break;
		case Z_PLUS_ARROW:
			m_box.maxCorner().z += u.z;
			if (m_box.minCorner().z > m_box.maxCorner().z)
				m_box.maxCorner().z = m_box.minCorner().z;
			break;
		case CROSS:
			m_box.minCorner() += u;
			m_box.maxCorner() += u;
			break;
		default:
			assert(false);
			return false;
		}
		
		//send 'modified' signal
		emit boxModified(&m_box);
	}
	else if (m_activeComponent == SPHERE)
	{
		//handled by move2D!
		return false;
	}
	else if (m_activeComponent >= X_MINUS_TORUS && m_activeComponent <= Z_PLUS_TORUS)
	{
		//we guess the rotation order by comparing the current screen 'normal'
		//and the vector prod of u and the current rotation axis
		CCVector3 Rb(0.0,0.0,0.0);
		switch(m_activeComponent)
		{
		case X_MINUS_TORUS:
			Rb.x = -1.0;
			break;
		case X_PLUS_TORUS:
			Rb.x = 1.0;
			break;
		case Y_MINUS_TORUS:
			Rb.y = -1.0;
			break;
		case Y_PLUS_TORUS:
			Rb.y = 1.0;
			break;
		case Z_MINUS_TORUS:
			Rb.z = -1.0;
			break;
		case Z_PLUS_TORUS:
			Rb.z = 1.0;
			break;
		default:
			assert(false);
			return false;
		}
		
		CCVector3 R = Rb;
		if (m_glTransEnabled)
			m_glTrans.applyRotation(R);

		CCVector3 RxU = R.cross(u);

		//look for the most parallel dimension
		int minDim = 0;
		PointCoordinateType maxDot = CCVector3(m_viewMatrix.getColumn(0)).dot(RxU);
		for (int i=1;i<3;++i)
		{
			PointCoordinateType dot = CCVector3(m_viewMatrix.getColumn(i)).dot(RxU);
			if (fabs(dot) > fabs(maxDot))
			{
				maxDot = dot;
				minDim = i;
			}
		}

		//angle is proportional to absolute displacement
		PointCoordinateType angle_rad = u.norm()/m_box.getDiagNorm() * M_PI;
		if (maxDot < 0.0)
			angle_rad = -angle_rad;

		ccGLMatrix rotMat;
		rotMat.initFromParameters(angle_rad,Rb,CCVector3(0.0,0.0,0.0));

		CCVector3 C = m_box.getCenter();
		ccGLMatrix transMat;
		transMat.setTranslation(-C);
		transMat = rotMat * transMat;
		transMat.setTranslation(CCVector3(transMat.getTranslation())+C);

		m_glTrans = m_glTrans * transMat.inverse();
		enableGLTransformation(true);
	}
	else
	{
		assert(false);
		return false;
	}

	update();

	return true;
}