void UPaperTerrainComponent::InsertConvexCollisionDataFromPolygon(const TArray<FVector2D>& ClosedPolyVertices2D)
{
	if (CachedBodySetup != nullptr && ClosedPolyVertices2D.Num() >= 3)
	{
		// Simplify polygon
		TArray<float> EmptyOffsetsList;
		TArray<FVector2D> LocalPolyVertices = ClosedPolyVertices2D;
		SimplifyPolygon(LocalPolyVertices, EmptyOffsetsList);

		// Always CCW and facing forward regardless of spline winding
		TArray<FVector2D> CorrectedSplineVertices;
		PaperGeomTools::CorrectPolygonWinding(CorrectedSplineVertices, LocalPolyVertices, false);

		TArray<FVector2D> TriangulatedPolygonVertices;
		PaperGeomTools::TriangulatePoly(/*out*/TriangulatedPolygonVertices, CorrectedSplineVertices, false);

		TArray<TArray<FVector2D>> ConvexHulls;
		PaperGeomTools::GenerateConvexPolygonsFromTriangles(ConvexHulls, TriangulatedPolygonVertices);

		for (TArray<FVector2D> ConvexHull : ConvexHulls)
		{
			FKConvexElem Convex;
			for (int J = 0; J < ConvexHull.Num(); ++J)
			{
				FVector2D& Vert = ConvexHull[J];
				new(Convex.VertexData) FVector(Vert.X, -0.5f * CollisionThickness, Vert.Y);
				new(Convex.VertexData) FVector(Vert.X, 0.5f * CollisionThickness, Vert.Y);
			}
			Convex.UpdateElemBox();

			CachedBodySetup->AggGeom.ConvexElems.Add(Convex);
		}
	}
}
void UPaperTerrainComponent::GenerateCollisionDataFromPolygon(const TArray<FVector2D>& SplinePolyVertices2D, const TArray<float>& TerrainOffsets, const TArray<FVector2D>& TriangulatedPolygonVertices)
{
	if (CachedBodySetup != nullptr && TriangulatedPolygonVertices.Num() >= 3)
	{
		// Generate polygon collider
		TArray<TArray<FVector2D>> ConvexHulls;
		PaperGeomTools::GenerateConvexPolygonsFromTriangles(ConvexHulls, TriangulatedPolygonVertices);
		TArray<float> ConvexHullEdgeExtrusionAmount;

		for (TArray<FVector2D> ConvexHull : ConvexHulls)
		{
			ConvexHullEdgeExtrusionAmount.Empty(ConvexHull.Num());

			// Find distances for each edge in this convex hull from the pair of points forming the edge
			// Not all edges will match edges in the original concave geometry, eg. newly created internal edges
			//TODO: Speed this up by using indices / vertex & edge identifiers instead of brute force search
			for (int ConvexHullPoint = 0; ConvexHullPoint < ConvexHull.Num(); ++ConvexHullPoint)
			{
				const FVector2D& A = ConvexHull[ConvexHullPoint];
				const FVector2D& B = ConvexHull[(ConvexHullPoint + 1) % ConvexHull.Num()];
				bool bFound = false;
				for (int Vertex = 0; Vertex < SplinePolyVertices2D.Num(); ++Vertex)
				{
					// The winding is might be different to the source polygon, compare both ways
					int NextVertexIndex = (Vertex + 1) % SplinePolyVertices2D.Num();
					if ((A.Equals(SplinePolyVertices2D[Vertex], THRESH_POINTS_ARE_SAME) && B.Equals(SplinePolyVertices2D[NextVertexIndex], THRESH_POINTS_ARE_SAME)) ||
						(B.Equals(SplinePolyVertices2D[Vertex], THRESH_POINTS_ARE_SAME) && A.Equals(SplinePolyVertices2D[NextVertexIndex], THRESH_POINTS_ARE_SAME)))
					{
						// Found an edge that matches the 2 vertex points
						ConvexHullEdgeExtrusionAmount.Add(TerrainOffsets[Vertex]);
						bFound = true;
						break;
					}
				}
				if (!bFound)
				{
					// Couldn't find this edge in the original polygon 
					ConvexHullEdgeExtrusionAmount.Add(0);
				}
			}
				
			TArray<FVector2D> ExtrudedConvexHull;
			CreateExtrudedConvexHull(ExtrudedConvexHull, ConvexHull, ConvexHullEdgeExtrusionAmount);
//			ExtrudedConvexHull = ConvexHull;

			// Generate convex hull
			FKConvexElem Convex;
			for (int J = 0; J < ExtrudedConvexHull.Num(); ++J)
			{
				FVector2D& Vert = ExtrudedConvexHull[J];
				new(Convex.VertexData) FVector(Vert.X, -0.5f * CollisionThickness, Vert.Y);
				new(Convex.VertexData) FVector(Vert.X, 0.5f * CollisionThickness, Vert.Y);
			}
			Convex.UpdateElemBox();

			CachedBodySetup->AggGeom.ConvexElems.Add(Convex);
		}
	}
}
Exemple #3
0
void UBodySetup::RescaleSimpleCollision( FVector BuildScale )
{
	if( BuildScale3D != BuildScale )
	{					
		// Back out the old scale when applying the new scale
		const FVector ScaleMultiplier3D = (BuildScale / BuildScale3D);

		for (int32 i = 0; i < AggGeom.ConvexElems.Num(); i++)
		{
			FKConvexElem* ConvexElem = &(AggGeom.ConvexElems[i]);

			FTransform ConvexTrans = ConvexElem->GetTransform();
			FVector ConvexLoc = ConvexTrans.GetLocation();
			ConvexLoc *= ScaleMultiplier3D;
			ConvexTrans.SetLocation(ConvexLoc);
			ConvexElem->SetTransform(ConvexTrans);

			TArray<FVector>& Vertices = ConvexElem->VertexData;
			for (int32 VertIndex = 0; VertIndex < Vertices.Num(); ++VertIndex)
			{
				Vertices[VertIndex] *= ScaleMultiplier3D;
			}

			ConvexElem->UpdateElemBox();
		}

		// @todo Deal with non-vector properties by just applying the max value for the time being
		const float ScaleMultiplier = ScaleMultiplier3D.GetMax();

		for (int32 i = 0; i < AggGeom.SphereElems.Num(); i++)
		{
			FKSphereElem* SphereElem = &(AggGeom.SphereElems[i]);

			SphereElem->Center *= ScaleMultiplier3D;
			SphereElem->Radius *= ScaleMultiplier;
		}

		for (int32 i = 0; i < AggGeom.BoxElems.Num(); i++)
		{
			FKBoxElem* BoxElem = &(AggGeom.BoxElems[i]);

			BoxElem->Center *= ScaleMultiplier3D;
			BoxElem->X *= ScaleMultiplier3D.X;
			BoxElem->Y *= ScaleMultiplier3D.Y;
			BoxElem->Z *= ScaleMultiplier3D.Z;
		}

		for (int32 i = 0; i < AggGeom.SphylElems.Num(); i++)
		{
			FKSphylElem* SphylElem = &(AggGeom.SphylElems[i]);

			SphylElem->Center *= ScaleMultiplier3D;
			SphylElem->Radius *= ScaleMultiplier;
			SphylElem->Length *= ScaleMultiplier;
		}

		BuildScale3D = BuildScale;
	}
}
/** Utility for adding one convex hull from the given verts */
void AddConvexGeomFromVertices( const TArray<FVector>& Verts, FKAggregateGeom* AggGeom, const TCHAR* ObjName )
{
    if(Verts.Num() == 0)
    {
        return;
    }

    FKConvexElem* ConvexElem = new(AggGeom->ConvexElems) FKConvexElem();
    ConvexElem->VertexData = Verts;
    ConvexElem->UpdateElemBox();
}
void UPaperTerrainComponent::InsertConvexCollisionDataFromPolygon(const TArray<FVector2D>& ClosedPolyVertices2D)
{
	if (CachedBodySetup != nullptr && ClosedPolyVertices2D.Num() >= 3)
	{
		// Simplify polygon
		TArray<float> EmptyOffsetsList;
		TArray<FVector2D> LocalPolyVertices = ClosedPolyVertices2D;

		// The merge / weld threshold should not be any lower / less than half the thickness
		float PolygonThickness = (ClosedPolyVertices2D[0] - ClosedPolyVertices2D[ClosedPolyVertices2D.Num() - 1]).Size();
		float SimplifyThreshold = PolygonThickness * 0.5f;
		SimplifyPolygon(LocalPolyVertices, EmptyOffsetsList, SimplifyThreshold);

		// Always CCW and facing forward regardless of spline winding
		TArray<FVector2D> CorrectedSplineVertices;
		PaperGeomTools::CorrectPolygonWinding(CorrectedSplineVertices, LocalPolyVertices, false);

		TArray<FVector2D> TriangulatedPolygonVertices;
		if (!PaperGeomTools::TriangulatePoly(/*out*/TriangulatedPolygonVertices, CorrectedSplineVertices, false))
		{
			// Triangulation failed, try triangulating the original non simplified polygon
			CorrectedSplineVertices.Empty();
			PaperGeomTools::CorrectPolygonWinding(/*out*/CorrectedSplineVertices, ClosedPolyVertices2D, false);
			TriangulatedPolygonVertices.Empty();
			PaperGeomTools::TriangulatePoly(/*out*/TriangulatedPolygonVertices, CorrectedSplineVertices, false);
		}

		TArray<TArray<FVector2D>> ConvexHulls;
		PaperGeomTools::GenerateConvexPolygonsFromTriangles(ConvexHulls, TriangulatedPolygonVertices);

		for (TArray<FVector2D> ConvexHull : ConvexHulls)
		{
			FKConvexElem Convex;
			for (int J = 0; J < ConvexHull.Num(); ++J)
			{
				FVector2D& Vert = ConvexHull[J];
				new(Convex.VertexData) FVector(Vert.X, -0.5f * CollisionThickness, Vert.Y);
				new(Convex.VertexData) FVector(Vert.X, 0.5f * CollisionThickness, Vert.Y);
			}
			Convex.UpdateElemBox();

			CachedBodySetup->AggGeom.ConvexElems.Add(Convex);
		}
	}
}