示例#1
0
void Mesh::createFaceNormals(void)
{
    //
    // Copy your previous (PA04) solution here.
    //

    // Calculate the number of qu(i)ds
    int nFaceI = (nI - 1) + wrapI,
        nFaceJ = (nJ - 1) + wrapJ;

    nFaces = (nFaceI * nFaceJ) * 2;

    // Allocate the arrays
    faceNormals = new Vector3[nFaces];
    centroids = new Point3[nFaces];

    for (int i = 0; i < nFaceI; i++)
    {
        for (int j = 0; j < nFaceJ; j++)
        {
            // Calculate both face indexes at (i, j)
            int uLeftIndex = faceIndex(i, j, true),
                lRrightIndex = faceIndex(i, j, false);

            // Get the points sorrounding the vertex
            Point3 *points = new Point3[4];

            // P3  P2 . . . p0, p1, p2, p3 (index positions)
            // P0  P1   
            quadBoundary(i, j, points); // double check third parameter

            // Calculate the two centroids
            Point3 uLeftCentroid  = triangleCentroid(points[0], points[2], points[3]);
            Point3 lRightCentroid = triangleCentroid(points[0], points[1], points[2]);

            // Calculate the two face normals
            Vector3 uLeftFaceNormal  = faceNormal(points[0], points[2], points[3]);
            Vector3 lRightFaceNormal = faceNormal(points[0], points[1], points[2]);

            // Add to the arrays
            faceNormals[uLeftIndex]   = uLeftFaceNormal;
            faceNormals[lRrightIndex] = lRightFaceNormal;

            centroids[uLeftIndex]   = uLeftCentroid;
            centroids[lRrightIndex] = lRightCentroid;

            delete [] points;
        }
    }
}
示例#2
0
CVector3 faceNormalByPoints(float x1,float y1,float z1,float x2,float y2,float z2,float x3,float y3,float z3)
{
 CVector3 p[3]; 
 p[0].setValues(x1,y1,z1);
 p[1].setValues(x2,y2,z2);
 p[2].setValues(x3,y2,z3);
 return faceNormal(p);
 
}
 forAll(faces, i)
 {
     point faceCentre(faces[i].centre(vertices_));
     vector faceNormal(faces[i].normal(vertices_));
     if (mag(faceNormal) > SMALL)
     {
         if (((faceCentre - blockCentre) & faceNormal) > 0)
         {
             outwardFaceCount++;
         }
         else
         {
             correctFaces[i] = false;
         }
     }
     else
     {
         outwardFaceCount++;
     }
 }
示例#4
0
文件: reduce.c 项目: pantaloons/Mesh
void render(void) {
	int i;
	Edge *edge;
	float normal[3];
	glPushMatrix();
	glTranslatef((dimensions[0] + dimensions[1])/2.0f, (dimensions[2] + dimensions[3])/2.0f, (dimensions[4] + dimensions[5])/2.0f);
	glRotatef(yrot, 1.0f, 0.0f, 0.0f);
	glRotatef(xrot, 0.0f, 1.0f, 0.0f);
	glTranslatef(-(dimensions[0] + dimensions[1])/2.0f, -(dimensions[2] + dimensions[3])/2.0f, -(dimensions[4] + dimensions[5])/2.0f);
	
	glBegin(GL_TRIANGLES);
	for(i = 0; i < mesh->numFaces; i++) {
		faceNormal(mesh->faces[i], normal);
		edge = mesh->faces[i]->edge;
		do {
			glNormal3f(normal[0], normal[1], normal[2]);
			glVertex3f(edge->vert->x, edge->vert->y, edge->vert->z);
			edge = edge->next;
		}
		while(edge != mesh->faces[i]->edge);
	}
	glPopMatrix();
	glEnd();
}
bool	btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin)
{

	if (m_polyhedron)
	{
		m_polyhedron->~btConvexPolyhedron();
		btAlignedFree(m_polyhedron);
	}
	
	void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
	m_polyhedron = new (mem) btConvexPolyhedron;

	btAlignedObjectArray<btVector3> orgVertices;

	for (int i=0;i<getNumVertices();i++)
	{
		btVector3& newVertex = orgVertices.expand();
		getVertex(i,newVertex);
	}
	
	btConvexHullComputer conv;
	
	if (shiftVerticesByMargin)
	{
		btAlignedObjectArray<btVector3> planeEquations;
		btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);

		btAlignedObjectArray<btVector3> shiftedPlaneEquations;
		for (int p=0;p<planeEquations.size();p++)
		{
			   btVector3 plane = planeEquations[p];
		//	   btScalar margin = getMargin();
			   plane[3] -= getMargin();
			   shiftedPlaneEquations.push_back(plane);
		}

		btAlignedObjectArray<btVector3> tmpVertices;

		btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
	
		conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
	} else
	{
		
		conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);
	}



	btAlignedObjectArray<btVector3> faceNormals;
	int numFaces = conv.faces.size();
	faceNormals.resize(numFaces);
	btConvexHullComputer* convexUtil = &conv;

	
	btAlignedObjectArray<btFace>	tmpFaces;
	tmpFaces.resize(numFaces);

	int numVertices = convexUtil->vertices.size();
	m_polyhedron->m_vertices.resize(numVertices);
	for (int p=0;p<numVertices;p++)
	{
		m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
	}


	for (int i=0;i<numFaces;i++)
	{
		int face = convexUtil->faces[i];
		//printf("face=%d\n",face);
		const btConvexHullComputer::Edge*  firstEdge = &convexUtil->edges[face];
		const btConvexHullComputer::Edge*  edge = firstEdge;

		btVector3 edges[3];
		int numEdges = 0;
		//compute face normals

		do
		{
			
			int src = edge->getSourceVertex();
			tmpFaces[i].m_indices.push_back(src);
			int targ = edge->getTargetVertex();
			btVector3 wa = convexUtil->vertices[src];

			btVector3 wb = convexUtil->vertices[targ];
			btVector3 newEdge = wb-wa;
			newEdge.normalize();
			if (numEdges<2)
				edges[numEdges++] = newEdge;

			edge = edge->getNextEdgeOfFace();
		} while (edge!=firstEdge);

		btScalar planeEq = 1e30f;

		
		if (numEdges==2)
		{
			faceNormals[i] = edges[0].cross(edges[1]);
			faceNormals[i].normalize();
			tmpFaces[i].m_plane[0] = faceNormals[i].getX();
			tmpFaces[i].m_plane[1] = faceNormals[i].getY();
			tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
			tmpFaces[i].m_plane[3] = planeEq;

		}
		else
		{
			btAssert(0);//degenerate?
			faceNormals[i].setZero();
		}

		for (int v=0;v<tmpFaces[i].m_indices.size();v++)
		{
			btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
			if (planeEq>eq)
			{
				planeEq=eq;
			}
		}
		tmpFaces[i].m_plane[3] = -planeEq;
	}

	//merge coplanar faces and copy them to m_polyhedron

	btScalar faceWeldThreshold= 0.999f;
	btAlignedObjectArray<int> todoFaces;
	for (int i=0;i<tmpFaces.size();i++)
		todoFaces.push_back(i);

	while (todoFaces.size())
	{
		btAlignedObjectArray<int> coplanarFaceGroup;
		int refFace = todoFaces[todoFaces.size()-1];

		coplanarFaceGroup.push_back(refFace);
		btFace& faceA = tmpFaces[refFace];
		todoFaces.pop_back();

		btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
		for (int j=todoFaces.size()-1;j>=0;j--)
		{
			int i = todoFaces[j];
			btFace& faceB = tmpFaces[i];
			btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
			if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
			{
				coplanarFaceGroup.push_back(i);
				todoFaces.remove(i);
			}
		}


		bool did_merge = false;
		if (coplanarFaceGroup.size()>1)
		{
			//do the merge: use Graham Scan 2d convex hull

			btAlignedObjectArray<GrahamVector3> orgpoints;
			btVector3 averageFaceNormal(0,0,0);

			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
//				m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);

				btFace& face = tmpFaces[coplanarFaceGroup[i]];
				btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
				averageFaceNormal+=faceNormal;
				for (int f=0;f<face.m_indices.size();f++)
				{
					int orgIndex = face.m_indices[f];
					btVector3 pt = m_polyhedron->m_vertices[orgIndex];
					
					bool found = false;

					for (int i=0;i<orgpoints.size();i++)
					{
						//if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
						if (orgpoints[i].m_orgIndex == orgIndex)
						{
							found=true;
							break;
						}
					}
					if (!found)
						orgpoints.push_back(GrahamVector3(pt,orgIndex));
				}
			}

			

			btFace combinedFace;
			for (int i=0;i<4;i++)
				combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];

			btAlignedObjectArray<GrahamVector3> hull;

			averageFaceNormal.normalize();
			GrahamScanConvexHull2D(orgpoints,hull,averageFaceNormal);

			for (int i=0;i<hull.size();i++)
			{
				combinedFace.m_indices.push_back(hull[i].m_orgIndex);
				for(int k = 0; k < orgpoints.size(); k++) 
				{
					if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex) 
					{
						orgpoints[k].m_orgIndex = -1; // invalidate...
						break;
					}
				}
			}

			// are there rejected vertices?
			bool reject_merge = false;
			


			for(int i = 0; i < orgpoints.size(); i++) {
				if(orgpoints[i].m_orgIndex == -1)
					continue; // this is in the hull...
				// this vertex is rejected -- is anybody else using this vertex?
				for(int j = 0; j < tmpFaces.size(); j++) {
					
					btFace& face = tmpFaces[j];
					// is this a face of the current coplanar group?
					bool is_in_current_group = false;
					for(int k = 0; k < coplanarFaceGroup.size(); k++) {
						if(coplanarFaceGroup[k] == j) {
							is_in_current_group = true;
							break;
						}
					}
					if(is_in_current_group) // ignore this face...
						continue;
					// does this face use this rejected vertex?
					for(int v = 0; v < face.m_indices.size(); v++) {
						if(face.m_indices[v] == orgpoints[i].m_orgIndex) {
							// this rejected vertex is used in another face -- reject merge
							reject_merge = true;
							break;
						}
					}
					if(reject_merge)
						break;
				}
				if(reject_merge)
					break;
			}

			if (!reject_merge)
			{
				// do this merge!
				did_merge = true;
				m_polyhedron->m_faces.push_back(combinedFace);
			}
		}
		if(!did_merge)
		{
			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
				btFace face = tmpFaces[coplanarFaceGroup[i]];
				m_polyhedron->m_faces.push_back(face);
			}

		} 



	}
	
	m_polyhedron->initialize();

	return true;
}
bool	btPolyhedralConvexShape::initializePolyhedralFeatures()
{

	if (m_polyhedron)
		btAlignedFree(m_polyhedron);
	
	void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
	m_polyhedron = new (mem) btConvexPolyhedron;

		btAlignedObjectArray<btVector3> orgVertices;

	for (int i=0;i<getNumVertices();i++)
	{
		btVector3& newVertex = orgVertices.expand();
		getVertex(i,newVertex);
	}

#if 0
	btAlignedObjectArray<btVector3> planeEquations;
	btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);

	btAlignedObjectArray<btVector3> shiftedPlaneEquations;
	for (int p=0;p<planeEquations.size();p++)
	{
		   btVector3 plane = planeEquations[p];
		   plane[3] -= getMargin();
		   shiftedPlaneEquations.push_back(plane);
	}

	btAlignedObjectArray<btVector3> tmpVertices;

	btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
	btConvexHullComputer conv;
	conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);

#else
	btConvexHullComputer conv;
	conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);

#endif



	btAlignedObjectArray<btVector3> faceNormals;
	int numFaces = conv.faces.size();
	faceNormals.resize(numFaces);
	btConvexHullComputer* convexUtil = &conv;

	
	btAlignedObjectArray<btFace>	tmpFaces;
	tmpFaces.resize(numFaces);

	int numVertices = convexUtil->vertices.size();
	m_polyhedron->m_vertices.resize(numVertices);
	for (int p=0;p<numVertices;p++)
	{
		m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
	}


	for (int i=0;i<numFaces;i++)
	{
		int face = convexUtil->faces[i];
		//printf("face=%d\n",face);
		const btConvexHullComputer::Edge*  firstEdge = &convexUtil->edges[face];
		const btConvexHullComputer::Edge*  edge = firstEdge;

		btVector3 edges[3];
		int numEdges = 0;
		//compute face normals

	//	btScalar maxCross2 = 0.f;
	//	int chosenEdge = -1;

		do
		{
			
			int src = edge->getSourceVertex();
			tmpFaces[i].m_indices.push_back(src);
			int targ = edge->getTargetVertex();
			btVector3 wa = convexUtil->vertices[src];

			btVector3 wb = convexUtil->vertices[targ];
			btVector3 newEdge = wb-wa;
			newEdge.normalize();
			if (numEdges<2)
				edges[numEdges++] = newEdge;

			edge = edge->getNextEdgeOfFace();
		} while (edge!=firstEdge);

		btScalar planeEq = 1e30f;

		
		if (numEdges==2)
		{
			faceNormals[i] = edges[0].cross(edges[1]);
			faceNormals[i].normalize();
			tmpFaces[i].m_plane[0] = faceNormals[i].getX();
			tmpFaces[i].m_plane[1] = faceNormals[i].getY();
			tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
			tmpFaces[i].m_plane[3] = planeEq;

		}
		else
		{
			btAssert(0);//degenerate?
			faceNormals[i].setZero();
		}

		for (int v=0;v<tmpFaces[i].m_indices.size();v++)
		{
			btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
			if (planeEq>eq)
			{
				planeEq=eq;
			}
		}
		tmpFaces[i].m_plane[3] = -planeEq;
	}

	//merge coplanar faces and copy them to m_polyhedron

	btScalar faceWeldThreshold= 0.999f;
	btAlignedObjectArray<int> todoFaces;
	for (int i=0;i<tmpFaces.size();i++)
		todoFaces.push_back(i);

	while (todoFaces.size())
	{
		btAlignedObjectArray<int> coplanarFaceGroup;
		int refFace = todoFaces[todoFaces.size()-1];

		coplanarFaceGroup.push_back(refFace);
		btFace& faceA = tmpFaces[refFace];
		todoFaces.pop_back();

		btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
		for (int j=todoFaces.size()-1;j>=0;j--)
		{
			int i = todoFaces[j];
			btFace& faceB = tmpFaces[i];
			btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
			if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
			{
				coplanarFaceGroup.push_back(i);
				todoFaces.remove(i);
			}
		}


		if (coplanarFaceGroup.size()>1)
		{
			//do the merge: use Graham Scan 2d convex hull

			btAlignedObjectArray<GrahamVector2> orgpoints;

			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
//				m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);

				btFace& face = tmpFaces[coplanarFaceGroup[i]];
				btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
				btVector3 xyPlaneNormal(0,0,1);

				btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal);
				
				for (int f=0;f<face.m_indices.size();f++)
				{
					int orgIndex = face.m_indices[f];
					btVector3 pt = m_polyhedron->m_vertices[orgIndex];
					btVector3 rotatedPt =  quatRotate(rotationArc,pt);
					rotatedPt.setZ(0);
					bool found = false;

					for (int i=0;i<orgpoints.size();i++)
					{
						if ((rotatedPt-orgpoints[i]).length2()<0.001)
						{
							found=true;
							break;
						}
					}
					if (!found)
						orgpoints.push_back(GrahamVector2(rotatedPt,orgIndex));
				}
			}

			btFace combinedFace;
			for (int i=0;i<4;i++)
				combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];

			btAlignedObjectArray<GrahamVector2> hull;
			GrahamScanConvexHull2D(orgpoints,hull);

			for (int i=0;i<hull.size();i++)
			{
				combinedFace.m_indices.push_back(hull[i].m_orgIndex);
			}
			m_polyhedron->m_faces.push_back(combinedFace);
		} else
		{
			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
				m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
			}

		}



	}
	
	m_polyhedron->initialize();

	return true;
}
示例#7
0
boost::shared_ptr<PrimVars> EmitterMesh::particlesOnFace(int faceIdx)
{
	const MeshFace& face = m_faces[faceIdx];

	boost::shared_ptr<PrimVars> interpVars(new PrimVars());

	float numParticlesCts = face.weight*m_totParticles;
	int numParticles = Aqsis::lfloor(face.weight*m_totParticles);
	if(numParticlesCts - numParticles > uRand())
		++numParticles;
	if(numParticles == 0)
		return boost::shared_ptr<PrimVars>();
	std::vector<int> storageCounts;
	// Create storage for all interpolated output parameters.
	for(PrimVars::const_iterator i = m_primVars->begin(), end = m_primVars->end();
			i != end; ++i)
	{
		if(i->token.Class() == Aqsis::class_constant
				|| i->token.Class() == Aqsis::class_uniform)
		{
			storageCounts.push_back(0);
			// uniform and constant primvars on the mesh interpolate to
			// constant primvars on the curves
			interpVars->append(Aqsis::CqPrimvarToken(Aqsis::class_constant,
				i->token.type(), i->token.count(), i->token.name() + "_emit"));
			// We can just copy over constant/uniform data; no interpolation needed.
			if(i->token.Class() == Aqsis::class_constant)
				*interpVars->back().value = *i->value;
			else
			{
				int stride = i->token.storageCount();
				interpVars->back().value->assign(
						i->value->begin() + stride*faceIdx,
						i->value->begin() + stride*(faceIdx+1));
			}
		}
		else
		{
			storageCounts.push_back(i->token.storageCount());
			// varying, vertex, facevarying and facevertex primvars interpolate
			// to uniform primvars on the curves
			interpVars->append(Aqsis::CqPrimvarToken(Aqsis::class_uniform,
				i->token.type(), i->token.count(), i->token.name() + "_emit"));
			// Allocate storage
			interpVars->back().value->assign(numParticles*storageCounts.back(), 0);
		}
	}

	// Float offsets for randomized quasi Monte-Carlo distribution
	float uOffset = float(std::rand())/RAND_MAX;
	float vOffset = float(std::rand())/RAND_MAX;
	// loop over child particles
	for(int particleNum = 0; particleNum < numParticles; ++particleNum)
	{
		// get random weights for the vertices of the current face.
		float u = uOffset + m_lowDiscrep.Generate(0, particleNum);
		if(u > 1)
			u -= 1;
		float v = vOffset + m_lowDiscrep.Generate(1, particleNum);
		if(v > 1)
			v -= 1;
		float weights[4];
		if(face.numVerts == 3)
		{
			if(u + v > 1)
			{
				u = 1-u;
				v = 1-v;
			}
			weights[0] = 1 - u - v;
			weights[1] = u;
			weights[2] = v;
			weights[3] = 0.0f;
		}
		else
		{
			weights[0] = (1-u)*(1-v);
			weights[1] = (1-u)*v;
			weights[2] = u*v;
			weights[3] = u*(1-v);
		}

		// loop over primitive variables.  Each varying/vertex/facevarying
		// /facevertex primvar is interpolated from the parent mesh to the
		// current child particle.
		int storageIndex = 0;
		PrimVars::iterator destVar = interpVars->begin();
		for(PrimVars::const_iterator srcVar = m_primVars->begin(),
				end = m_primVars->end(); srcVar != end;
				++srcVar, ++storageIndex, ++destVar)
		{
			int storageStride = storageCounts[storageIndex];
			// Get pointers to source parameters for the vertices
			const float* src[4] = {0,0,0,0};
			switch(srcVar->token.Class())
			{
				case Aqsis::class_varying:
				case Aqsis::class_vertex:
					for(int i = 0; i < face.numVerts; ++i)
						src[i] = &(*srcVar->value)[storageStride*face.v[i]];
					break;
				case Aqsis::class_facevarying:
				case Aqsis::class_facevertex:
					for(int i = 0; i < face.numVerts; ++i)
						src[i] = &(*srcVar->value)[
							storageStride*(face.faceVaryingIndex+i) ];
					break;
				default:
					// Other classes don't need any interpolation, so we just
					// go to the next primvar in m_primVars
					continue;
			}

			// Interpolate the primvar pointed to by srcVar to the current
			// particle position.  This is just a a weighted average of values
			// attached to vertices of the current face.
			float* dest = &(*destVar->value)[storageStride*particleNum];
			for(int k = 0; k < storageStride; ++k, ++dest)
			{
				*dest = 0;
				for(int i = 0; i < face.numVerts; ++i)
				{
					*dest += *src[i] * weights[i];
					++src[i];
				}
			}
		}
	}

	// Finally, add extra face-constant parameters.
	Vec3 Ng_emitVec = faceNormal(face);
	float Ng_emit[] = {Ng_emitVec.x(), Ng_emitVec.y(), Ng_emitVec.z()};
	interpVars->append(Aqsis::CqPrimvarToken(Aqsis::class_constant, Aqsis::type_normal,
				1, "Ng_emit"), FloatArray(Ng_emit, Ng_emit+3));

	return interpVars;
}
bool	btConvexUtility::initializePolyhedralFeatures(const btAlignedObjectArray<btVector3>& orgVertices, bool mergeCoplanarTriangles)
{
	

	btConvexHullComputer conv;
	conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);

	btAlignedObjectArray<btVector3> faceNormals;
	int numFaces = conv.faces.size();
	faceNormals.resize(numFaces);
	btConvexHullComputer* convexUtil = &conv;

	
	btAlignedObjectArray<btFace>	tmpFaces;
	tmpFaces.resize(numFaces);

	int numVertices = convexUtil->vertices.size();
	m_vertices.resize(numVertices);
	for (int p=0;p<numVertices;p++)
	{
		m_vertices[p] = convexUtil->vertices[p];
	}


	for (int i=0;i<numFaces;i++)
	{
		int face = convexUtil->faces[i];
		//printf("face=%d\n",face);
		const btConvexHullComputer::Edge*  firstEdge = &convexUtil->edges[face];
		const btConvexHullComputer::Edge*  edge = firstEdge;

		btVector3 edges[3];
		int numEdges = 0;
		//compute face normals

		btScalar maxCross2 = 0.f;
		int chosenEdge = -1;

		do
		{
			
			int src = edge->getSourceVertex();
			tmpFaces[i].m_indices.push_back(src);
			int targ = edge->getTargetVertex();
			btVector3 wa = convexUtil->vertices[src];

			btVector3 wb = convexUtil->vertices[targ];
			btVector3 newEdge = wb-wa;
			newEdge.normalize();
			if (numEdges<2)
				edges[numEdges++] = newEdge;

			edge = edge->getNextEdgeOfFace();
		} while (edge!=firstEdge);

		btScalar planeEq = 1e30f;

		
		if (numEdges==2)
		{
			faceNormals[i] = edges[0].cross(edges[1]);
			faceNormals[i].normalize();
			tmpFaces[i].m_plane[0] = faceNormals[i].getX();
			tmpFaces[i].m_plane[1] = faceNormals[i].getY();
			tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
			tmpFaces[i].m_plane[3] = planeEq;

		}
		else
		{
			btAssert(0);//degenerate?
			faceNormals[i].setZero();
		}

		for (int v=0;v<tmpFaces[i].m_indices.size();v++)
		{
			btScalar eq = m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
			if (planeEq>eq)
			{
				planeEq=eq;
			}
		}
		tmpFaces[i].m_plane[3] = -planeEq;
	}

	//merge coplanar faces

	btScalar faceWeldThreshold= 0.999f;
	btAlignedObjectArray<int> todoFaces;
	for (int i=0;i<tmpFaces.size();i++)
		todoFaces.push_back(i);

	while (todoFaces.size())
	{
		btAlignedObjectArray<int> coplanarFaceGroup;
		int refFace = todoFaces[todoFaces.size()-1];

		coplanarFaceGroup.push_back(refFace);
		btFace& faceA = tmpFaces[refFace];
		todoFaces.pop_back();

		btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
		for (int j=todoFaces.size()-1;j>=0;j--)
		{
			int i = todoFaces[j];
			btFace& faceB = tmpFaces[i];
			btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
			if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
			{
				coplanarFaceGroup.push_back(i);
				todoFaces.remove(i);
			}
		}


		bool did_merge = false;
		if (mergeCoplanarTriangles && coplanarFaceGroup.size()>1)
		{
			//do the merge: use Graham Scan 2d convex hull

			btAlignedObjectArray<GrahamVector2> orgpoints;

			for (int i=0;i<coplanarFaceGroup.size();i++)
			{

				btFace& face = tmpFaces[coplanarFaceGroup[i]];
				btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
				btVector3 xyPlaneNormal(0,0,1);

				btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal);
				
				for (int f=0;f<face.m_indices.size();f++)
				{
					int orgIndex = face.m_indices[f];
					btVector3 pt = m_vertices[orgIndex];
					btVector3 rotatedPt =  quatRotate(rotationArc,pt);
					rotatedPt.setZ(0);
					bool found = false;

					for (int i=0;i<orgpoints.size();i++)
					{
						//if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
						if (orgpoints[i].m_orgIndex == orgIndex)
						{
							found=true;
							break;
						}
					}
					if (!found)
						orgpoints.push_back(GrahamVector2(rotatedPt,orgIndex));
				}
			}

			btFace combinedFace;
			for (int i=0;i<4;i++)
				combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];

			btAlignedObjectArray<GrahamVector2> hull;
			GrahamScanConvexHull2D(orgpoints,hull);

			for (int i=0;i<hull.size();i++)
			{
				combinedFace.m_indices.push_back(hull[i].m_orgIndex);
				for(int k = 0; k < orgpoints.size(); k++) {
					if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex) {
						orgpoints[k].m_orgIndex = -1; // invalidate...
						break;
			}
				}
			}
			// are there rejected vertices?
			bool reject_merge = false;
			for(int i = 0; i < orgpoints.size(); i++) {
				if(orgpoints[i].m_orgIndex == -1)
					continue; // this is in the hull...
				// this vertex is rejected -- is anybody else using this vertex?
				for(int j = 0; j < tmpFaces.size(); j++) {
					btFace& face = tmpFaces[j];
					// is this a face of the current coplanar group?
					bool is_in_current_group = false;
					for(int k = 0; k < coplanarFaceGroup.size(); k++) {
						if(coplanarFaceGroup[k] == j) {
							is_in_current_group = true;
							break;
						}
					}
					if(is_in_current_group) // ignore this face...
						continue;
					// does this face use this rejected vertex?
					for(int v = 0; v < face.m_indices.size(); v++) {
						if(face.m_indices[v] == orgpoints[i].m_orgIndex) {
							// this rejected vertex is used in another face -- reject merge
							reject_merge = true;
							break;
						}
					}
					if(reject_merge)
						break;
				}
				if(reject_merge)
					break;
			}
			if(!reject_merge) {
				// do this merge!
				did_merge = true;
			m_faces.push_back(combinedFace);
			}
		}
		if(!did_merge)
		{
			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
				m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
			}
		}

	}
	return true;
}
示例#9
0
ParticleRenderable::ParticleRenderable(ShaderProgramPtr shaderProgram, ParticlePtr particle) :
    HierarchicalRenderable(shaderProgram),
    m_particle(particle),
    m_pBuffer(0), m_cBuffer(0), m_nBuffer(0)
{
    double radius = 1.0;
    int thetaStep = 40;
    int phiStep = 10;

    glm::vec3 center(0.0, 0.0, 0.0);

    for (int i = 0; i < thetaStep; ++i) {
        for(int j = 0; j < phiStep; ++j) {
            double curr_theta = i*(2.0*M_PI / (double) thetaStep);
            double curr_phi = j*(M_PI / (double)phiStep);

            double next_theta = (i+1) * (2.0 * M_PI / (double) thetaStep);
            double next_phi = (j+1) * (M_PI / (double) phiStep);

            glm::vec3 faceNormal(1, 0, 0);
            std::array<glm::vec3,3> vTriangles;
            vTriangles[0] = center
                + glm::vec3(radius * cos(curr_theta) * sin(curr_phi),
                            radius * sin(curr_theta) * sin(curr_phi),
                            radius * cos(curr_phi));
            vTriangles[1] = center
                + glm::vec3(radius * cos(next_theta) * sin(curr_phi),
                            radius * sin(next_theta) * sin(curr_phi),
                            radius * cos(curr_phi));
            vTriangles[2] = center
                + glm::vec3(radius * cos(next_theta) * sin(next_phi),
                            radius * sin(next_theta) * sin(next_phi),
                            radius * cos(next_phi));
            faceNormal = -glm::normalize(glm::cross(vTriangles[1]-vTriangles[0], vTriangles[2]-vTriangles[0]));

            m_positions.push_back(vTriangles[0]);
            m_positions.push_back(vTriangles[1]);
            m_positions.push_back(vTriangles[2]);
            m_normals.push_back(faceNormal);
            m_normals.push_back(faceNormal);
            m_normals.push_back(faceNormal);
            m_colors.push_back(glm::vec4(1.0,1.0,1.0,1.0));
            m_colors.push_back(glm::vec4(1.0,1.0,1.0,1.0));
            m_colors.push_back(glm::vec4(1.0,1.0,1.0,1.0));

            vTriangles[0] = center
                + glm::vec3(radius * cos(curr_theta) * sin(curr_phi),
                            radius * sin(curr_theta) * sin(curr_phi),
                            radius * cos(curr_phi));
            vTriangles[1] = center
                + glm::vec3(radius * cos(next_theta) * sin(next_phi),
                            radius * sin(next_theta) * sin(next_phi),
                            radius * cos(next_phi));
            vTriangles[2] = center
                + glm::vec3(radius * cos(curr_theta) * sin(next_phi),
                            radius * sin(curr_theta) * sin(next_phi),
                            radius * cos(next_phi));
            faceNormal = -glm::normalize(glm::cross( vTriangles[1]-vTriangles[0], vTriangles[2]-vTriangles[0] ));

            m_positions.push_back(vTriangles[0]);
            m_positions.push_back(vTriangles[1]);
            m_positions.push_back(vTriangles[2]);
            m_normals.push_back(faceNormal);
            m_normals.push_back(faceNormal);
            m_normals.push_back(faceNormal);
            m_colors.push_back(glm::vec4(1.0,1.0,1.0,1.0));
            m_colors.push_back(glm::vec4(1.0,1.0,1.0,1.0));
            m_colors.push_back(glm::vec4(1.0,1.0,1.0,1.0));

        }
    }

    //Create buffers
    glGenBuffers(1, &m_pBuffer); //vertices
    glGenBuffers(1, &m_cBuffer); //colors
    glGenBuffers(1, &m_nBuffer); //normals

    //Activate buffer and send data to the graphics card
    glcheck(glBindBuffer(GL_ARRAY_BUFFER, m_pBuffer));
    glcheck(glBufferData(GL_ARRAY_BUFFER, m_positions.size()*sizeof(glm::vec3), m_positions.data(), GL_STATIC_DRAW));
    glcheck(glBindBuffer(GL_ARRAY_BUFFER, m_cBuffer));
    glcheck(glBufferData(GL_ARRAY_BUFFER, m_colors.size()*sizeof(glm::vec4), m_colors.data(), GL_STATIC_DRAW));
    glcheck(glBindBuffer(GL_ARRAY_BUFFER, m_nBuffer));
    glcheck(glBufferData(GL_ARRAY_BUFFER, m_normals.size()*sizeof(glm::vec3), m_normals.data(), GL_STATIC_DRAW));
}
示例#10
0
void Mesh::createFaceNormals(void)
{
    //
    // ASSIGNMENT (PA04)
    //
    // Add code to instance the face normals. If `wrapI` is false,
    // there are `nI-1` quads in the `i` direction. If it's true,
    // there are `nI`. Similarly, `wrapJ` and `nJ` determine the number
    // of quads in the `j` direction. Each quad has two faces. Based
    // on these considerations, you can calculate `nFaces`, the number
    // of faces.  Use it to allocate arrays `faceNormals[]` and
    // `centroids[]` on the heap, then visit each face put its face
    // normal and centroid in those arrays, respectively.
    //
    // You may find the quadBoundary() function helpful here: Pass it
    // `i` and `j` for each quad and then use the points it returns to
    // build the normals and centroids of each of the two (triangular)
    // faces.
    //
    // 21 lines in instructor solution (YMMV)
    //


    /*
        THIS SOUNDS EASY
    */
    
    // Calculate the number of qu(i)ds
    int nFaceI = (nI - 1) + wrapI,
        nFaceJ = (nJ - 1) + wrapJ;

    nFaces = (nFaceI * nFaceJ) * 2;

    // Allocate the arrays
    faceNormals = new Vector3[nFaces];
    centroids = new Point3[nFaces];

    for (int i = 0; i < nFaceI; i++)
    {
        for (int j = 0; j < nFaceJ; j++)
        {
            // Calculate both face indexes at (i, j)
            int uLeftIndex = faceIndex(i, j, true),
                lRrightIndex = faceIndex(i, j, false);

            // Get the points sorrounding the vertex
            Point3 *points = new Point3[4];

            // P3  P2 . . . p0, p1, p2, p3 (index positions)
            // P0  P1   
            quadBoundary(i, j, points); // double check third parameter

            // Calculate the two centroids
            Point3 uLeftCentroid  = triangleCentroid(points[0], points[2], points[3]);
            Point3 lRightCentroid = triangleCentroid(points[0], points[1], points[2]);

            // Calculate the two face normals
            Vector3 uLeftFaceNormal  = faceNormal(points[0], points[2], points[3]);
            Vector3 lRightFaceNormal = faceNormal(points[0], points[1], points[2]);

            // Add to the arrays
            faceNormals[uLeftIndex]   = uLeftFaceNormal;
            faceNormals[lRrightIndex] = lRightFaceNormal;

            centroids[uLeftIndex]   = uLeftCentroid;
            centroids[lRrightIndex] = lRightCentroid;

            delete [] points;
        }
    }


}
示例#11
0
/*!
  Check if the polygon is visible in the image and if the angle between the normal
  to the face and the line vector going from the optical center to the cog of the face is below
  the given threshold.
  To do that, the polygon is projected into the image thanks to the camera pose.

  \param cMo : The pose of the camera.
  \param alpha : Maximum angle to detect if the face is visible (in rad).
  \param modulo : Indicates if the test should also consider faces that are not oriented
  counter clockwise. If true, the orientation of the face is without importance.
  \param cam : Camera parameters (intrinsics parameters)
  \param I : Image used to consider level of detail.

  \return Return true if the polygon is visible.
*/
bool
vpMbtPolygon::isVisible(const vpHomogeneousMatrix &cMo, const double alpha, const bool &modulo,
      const vpCameraParameters &cam, const vpImage<unsigned char> &I)
{
  //   std::cout << "Computing angle from MBT Face (cMo, alpha)" << std::endl;

  changeFrame(cMo);

  if(nbpt <= 2) {
    //Level of detail (LOD)
    if(useLod) {
      vpCameraParameters c = cam;
      if(clippingFlag > 3) { // Contains at least one FOV constraint
        c.computeFov(I.getWidth(), I.getHeight());
      }
      computePolygonClipped(c);
      std::vector<vpImagePoint> roiImagePoints;
      getRoiClipped(c, roiImagePoints);

      if (roiImagePoints.size() == 2) {
        double x1 = roiImagePoints[0].get_u();
        double y1 = roiImagePoints[0].get_v();
        double x2 = roiImagePoints[1].get_u();
        double y2 = roiImagePoints[1].get_v();
        double length = std::sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
//          std::cout << "Index=" << index << " ; Line length=" << length << " ; clippingFlag=" << clippingFlag << std::endl;
//        vpTRACE("index=%d lenght=%f minLineLengthThresh=%f", index, length, minLineLengthThresh);

        if (length < minLineLengthThresh) {
          isvisible = false;
          isappearing = false;
          return false;
        }
      }
    }

    /* a line is always visible when LOD is not used */
    isvisible = true;
    isappearing = false;
    return  true ;
  }

  // If the polygon has no orientation, the angle check visibility is always valid.
  // Feature mainly used for cylinders.
  if(!hasOrientation)
  {
    isvisible = true;
    isappearing = false;
    return true;
  }

  //Check visibility from normal
  //Newell's Method for calculating the normal of an arbitrary 3D polygon
  //https://www.opengl.org/wiki/Calculating_a_Surface_Normal
  vpColVector faceNormal(3);
  vpColVector currentVertex, nextVertex;
  for(unsigned int  i = 0; i<nbpt; i++) {
    currentVertex = p[i].cP;
    nextVertex = p[(i+1) % nbpt].cP;

    faceNormal[0] += (currentVertex[1] - nextVertex[1]) * (currentVertex[2] + nextVertex[2]);
    faceNormal[1] += (currentVertex[2] - nextVertex[2]) * (currentVertex[0] + nextVertex[0]);
    faceNormal[2] += (currentVertex[0] - nextVertex[0]) * (currentVertex[1] + nextVertex[1]);
  }
  faceNormal.normalize();

  vpColVector e4(3) ;
  vpPoint pt;
  for (unsigned int i = 0; i < nbpt; i += 1){
    pt.set_X(pt.get_X() + p[i].get_X());
    pt.set_Y(pt.get_Y() + p[i].get_Y());
    pt.set_Z(pt.get_Z() + p[i].get_Z());
  }
  e4[0] = -pt.get_X() / (double)nbpt;
  e4[1] = -pt.get_Y() / (double)nbpt;
  e4[2] = -pt.get_Z() / (double)nbpt;
  e4.normalize();

  double angle = acos(vpColVector::dotProd(e4, faceNormal));

//  vpCTRACE << angle << "/" << vpMath::deg(angle) << "/" << vpMath::deg(alpha) << std::endl;

  if( angle < alpha || (modulo && (M_PI - angle) < alpha)) {
    isvisible = true;
    isappearing = false;

    if (useLod) {
      vpCameraParameters c = cam;
      if(clippingFlag > 3) { // Contains at least one FOV constraint
        c.computeFov(I.getWidth(), I.getHeight());
      }
      computePolygonClipped(c);
      std::vector<vpImagePoint> roiImagePoints;
      getRoiClipped(c, roiImagePoints);

      vpPolygon roiPolygon(roiImagePoints);
      double area = roiPolygon.getArea();
//      std::cout << "After normal test ; Index=" << index << " ; area=" << area << " ; clippingFlag="
//          << clippingFlag << std::endl;
      if (area < minPolygonAreaThresh) {
        isappearing = false;
        isvisible = false;
        return false;
      }
    }

    return true;
  }

  if (angle < alpha+vpMath::rad(1) ){
    isappearing = true;
  }
  else if (modulo && (M_PI - angle) < alpha+vpMath::rad(1) ){
    isappearing = true;
  }
  else {
    isappearing = false;
  }

  isvisible = false ;
  return false ;
}
示例#12
0
    void Mesh::generateVertexNormals(const float& smoothingAngle)
    {
        // calculate the cosine of the angle (in degrees)
        float cos_angle = cos(smoothingAngle * M_PI / 180.0);

        // clear any previously cached normals
        _normals.clear();

        int numVerts = _vertices.size()/3;
        int numFaces = _faceIndices.size()/3;

        //Here we create a temporary list of face indices for each vertex
        //That is, a list of lists, where for each vertex, we have a list of
        //indices of the faces it belongs to
        std::vector< std::vector<int> > facesPerVertex;
        std::vector< std::vector<vec3> > faceNormalsPerVertex;
        for(int i=0; i<numVerts; ++i)
        {
            //Create an empty list of face indices
            std::vector<int> faceList;
            facesPerVertex.push_back(faceList);

            //Create an empty list of normals
            std::vector<vec3> normalList;
            faceNormalsPerVertex.push_back(normalList);
        }

        //First we iterate over all the faces and generate face normals
        //for each face in our mesh
        for(int i=0; i<numFaces; ++i)
        {
            int vertIndex1 = _faceIndices[3*i];
            int vertIndex2 = _faceIndices[3*i+1];
            int vertIndex3 = _faceIndices[3*i+2];

            //Register that face with index i, is part of the faceLists
            //for each of the above vertices
            facesPerVertex[vertIndex1].push_back(i);
            facesPerVertex[vertIndex2].push_back(i);
            facesPerVertex[vertIndex3].push_back(i);

            vec3 faceNormal(_faceNormals[3*i+0],
                            _faceNormals[3*i+1],
                            _faceNormals[3*i+2]);
            faceNormalsPerVertex[vertIndex1].push_back(faceNormal);
            faceNormalsPerVertex[vertIndex2].push_back(faceNormal);
            faceNormalsPerVertex[vertIndex3].push_back(faceNormal);
        }

        //Now we have a list of faces per vertex
        //We also have a list of face normals per vertex
        //We can now calculate the average normal
        for(int i=0; i<numVerts; ++i)
        {
            std::vector<vec3> normals = faceNormalsPerVertex[i];
            vec3 normalSum(0.f, 0.f, 0.f);
            for(int j=0; j<normals.size(); ++j)
            {
                normalSum += normals[j];    
            }
            normalSum.normalize();
            float* normCoords = normalSum.data();
            _normals.push_back(normCoords[0]);
            _normals.push_back(normCoords[1]);
            _normals.push_back(normCoords[2]);
        }

    }