Esempio n. 1
0
bool PhysicsMesh::LoadFrom(Mesh * mesh)
{
	// Clear old
	triangles.ClearAndDelete();
	quads.ClearAndDelete();

	name = mesh->name;
	source = mesh->source; 
	aabb = *mesh->aabb;

	for (int i = 0; i < mesh->numFaces; ++i)
	{
		// Just copy shit from it
		MeshFace * faces = &mesh->faces[i];
		assert((faces->numVertices <= 4 || faces->numVertices >= 3) && "Bad vertices count in faces");

		int vi0 = faces->vertices[0],
			vi1 = faces->vertices[1],
			vi2 = faces->vertices[2];

		assert(vi0 < mesh->vertices.Size() && 
			vi0 >= 0);

		Vector3f p1 = mesh->vertices[vi0],
			p2 = mesh->vertices[vi1],
			p3 = mesh->vertices[vi2];

		if (faces->numVertices == 4){
			Vector3f p4 = mesh->vertices[faces->vertices[3]];
			Quad * quad = new Quad();
			quad->Set4Points(p1, p2, p3, p4);
			quads.Add(quad);
		}
		else if (faces->numVertices == 3){
			Triangle * tri = new Triangle();
			tri->Set3Points(p1, p2, p3);
			triangles.Add(tri);
		}
	}
	if (quads.Size() == 0 && triangles.Size() == 0)
		assert(false && "Unable to load physicsmesh from mesh source!");
	else
		std::cout<<"\nCreated physics mesh for \""<<source<<"\": ";
	if (triangles.Size())
		std::cout<<"\n- "<<triangles.Size()<<" triangles";
	if (quads.Size())
		std::cout<<"\n- "<<quads.Size()<<" quads";

	// Re-generate it.
	if (useCollisionShapeOctrees)
		GenerateCollisionShapeOctree();
	return true;
}
Esempio n. 2
0
int CVFindQuads::Process(CVPipeline * pipe)
{
	pipe->quads.Clear();
	good = false;
	/// Check for ... in pipeline
	if (pipe->corners.size() == 0 &&
		pipe->lines.Size() == 0)
	{
		errorString = "No corners or lines in pipeline.";
		return -1;
	}
	float minimumWidthSquared = minimumWidth->GetInt() * minimumWidth->GetInt();
	// Line-style!
	if (pipe->lines.Size())
	{
		int linesAtStart = pipe->lines.Size();
		std::cout<<"\nLines: "<<linesAtStart;
		
		/// Then try to locate at least 2 lines that are parallel first?
		// Approximate, assume 2 horizontal lines, and pick those two which are extremes (highest and lowest).
		List<Line> singleLines;
		for (int i = 0; i < pipe->lines.Size(); ++i)
		{
			Line line = pipe->lines[i];
			Line line2;
			bool foundPair = false;
			// Compare with list of lines.
			for (int j = 0; j < singleLines.Size(); ++j)
			{
				line2 = singleLines[j];
				// Any suitable? 
				// First check length.
				if (AbsoluteValue(line.Length() - line2.Length()) > maxLengthDiff->GetFloat())
					continue;

				// Ensure both the start and end points are pretty parallel
				if (AbsoluteValue(line.start.x - line2.start.x) > maxCornerXDiff->GetFloat())
					continue;
				if (AbsoluteValue(line.stop.x - line2.stop.x) > maxCornerXDiff->GetFloat())
					continue;

				foundPair = true;
				break;
			}

			if (foundPair)
			{
		// Limit the range in X for both lines so that they work "together" (overlapping)
#define Minimum(a,b) ( (a < b) ? a : b)
#define Maximum(a,b) ( (a > b) ? a : b)
				Line min, max;
				if (line.start.y < line2.start.y){
					min = line;
					max = line2;
				}
				else {
					min = line2;
					max = line;
				}
				min.stop.x = max.stop.x = Minimum(min.stop.x, max.stop.x);
				min.start.x = max.start.x = Maximum(min.start.x, max.start.x);

				// Create rectangle using these two lines! o-o
				Quad quad;
				quad.Set4Points(min.start, min.stop, max.stop, max.start);
				pipe->quads.Add(quad);
				good = true;
			}
			// If not, add this line to the list.
			else
				singleLines.Add(line);
		}
	
	}
	// Use corners if we have any.
	if (pipe->corners.size()){
		// Constraint for now...
		if (pipe->corners.size() != 4){
			errorString = "Skipping. Simple algorithm requires exactly 4 corners.";
			return -1;
		}
		// Look through all corners. Find the top 2 and bottom 2.
		List<cv::Point2f> sortedList, unsortedList;
		for (int i = 0; i < pipe->corners.size(); ++i)
			unsortedList.Add(pipe->corners[i]);
		/// Sort by Y-position.
		while (unsortedList.Size())
		{
			cv::Point2f max = unsortedList[0];
			int maxIndex = 0;
			for (int i = 1; i < unsortedList.Size(); ++i)
			{
				cv::Point2f point = pipe->corners[i];
				if (point.y > max.y){
					max = point;
					maxIndex = i;
				}
			}
			// Add the max to the sortedList and remove it from the list to be sorted.
			sortedList.Add(max);
			unsortedList.RemoveIndex(maxIndex);
			std::cout<<"\nAdded item"<<sortedList.Size()<<": "<<max;
		}
		/// Now, store top and bottom.
		List<cv::Point2f> top, bottom;
		top.Add(sortedList[0]);
		top.Add(sortedList[1]);
		bottom.Add(sortedList[2]);
		bottom.Add(sortedList[3]);
	
	#define ToVec3f(cvVec) (Vector3f(cvVec.x, cvVec.y, 0))
	
		if (top[0].x < top[1].x)
		{
			topLeft = ToVec3f(top[0]);
			topRight = ToVec3f(top[1]);
		}
		else {
			topLeft = ToVec3f(top[1]);
			topRight = ToVec3f(top[0]);
		}
		if (bottom[0].x < bottom[1].x)
		{
			bottomLeft = ToVec3f(bottom[0]);
			bottomRight = ToVec3f(bottom[1]);
		}
		else 
		{
			bottomLeft = ToVec3f(bottom[1]);
			bottomRight = ToVec3f(bottom[0]);
		}

		// Fetch vectors for lines between the top and bottom points.
		// From left to right.
		topLine = Vector2f(topRight.x - topLeft.x, topRight.y - topLeft.y);
		bottomLine = Vector2f(bottomRight.x - bottomLeft.x, bottomRight.y - bottomLeft.y);
	
		// Normalize them before dot-product
		topLine.Normalize();
		bottomLine.Normalize();

		// Check that they are parralel
		float dotProduct = topLine.DotProduct(bottomLine);
		if (AbsoluteValue(dotProduct) < 0.9f)
		{
			errorString = "Bottom and top lines not parralell enough.";
			return -1;
		}

		// Fetch vector between left top and left bottom.
		Vector2f topLeftToBottomLeft(bottomLeft.x - topLeft.x, bottomLeft.y - topLeft.y);

		// Check that it is perpendicular to either top or bottom lines.
		topLeftToBottomLeft.Normalize();
		dotProduct = topLine.DotProduct(topLeftToBottomLeft);
		if (AbsoluteValue(dotProduct) > 0.1f)
		{
			errorString = "Left and top lines not perpendicular enough.";
			return -1;
		}


		// We have a quad if we reach here!
		Quad quad;
		quad.Set4Points(ToVec3f(bottomLeft), ToVec3f(bottomRight), ToVec3f(topRight), ToVec3f(topLeft));
		pipe->quads.Add(quad);
	
		good = true;
	}
	returnType = CVReturnType::QUADS;
	return returnType;
}