Esempio n. 1
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;
	}
}
float UKismetMathLibrary::GetMaxElement(FVector A)
{
	return A.GetMax();
}
Esempio n. 3
0
float AGameObject::HitBoundsSphericalRadius()
{
  FVector extents = hitBox->GetScaledBoxExtent();
  return extents.GetMax();
}
// Called every frame
void ASpacePartioner::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

	//check(bInitialized);
	//check(bDrawDebugInfo);

	if (bInitialized && bDrawDebugInfo)
	{

		int level = 0;
		float max;
		float offsetMax;
		float offset;
		FVector maxExtent;
		FVector center;
		FVector tempForCoercion;
		FBoxCenterAndExtent OldBounds = FBoxCenterAndExtent();

		int nodeCount = 0;
		int elementCount = 0;

		// Go through the nodes of the octree
		for (FSimpleOctree::TConstIterator<> NodeIt(*OctreeData); NodeIt.HasPendingNodes(); NodeIt.Advance())
		{
			const FSimpleOctree::FNode& CurrentNode = NodeIt.GetCurrentNode();
			const FOctreeNodeContext& CurrentContext = NodeIt.GetCurrentContext();
			const FBoxCenterAndExtent& CurrentBounds = CurrentContext.Bounds;

			nodeCount++;

			FOREACH_OCTREE_CHILD_NODE(ChildRef)
			{
				if (CurrentNode.HasChild(ChildRef))
				{
					NodeIt.PushChild(ChildRef);
				}
			}

			// If the extents have changed then we have moved a level.
			if (!OldBounds.Extent.Equals(CurrentBounds.Extent))
			{
				level++;
			}
			OldBounds = CurrentBounds;

			// UE_LOG(LogTemp, Log, TEXT("Level: %d"), level);

			// Draw Node Bounds
			tempForCoercion = CurrentBounds.Extent;
			max = tempForCoercion.GetMax();
			center = CurrentBounds.Center;

			// UE_LOG(LogTemp, Log, TEXT("center before: %s"), *center.ToString());
			
			// To understand the math here check out the constructors in FOctreeNodeContext
			// Offset nodes that are not the root bounds
			if (!OctreeData->GetRootBounds().Extent.Equals(CurrentBounds.Extent))
			{
				for (int i = 1; i < level; i++)
				{
					// Calculate offset
					offsetMax = max / (1.0f + (1.0f / FOctreeNodeContext::LoosenessDenominator));
					offset = max - offsetMax;
					max = offsetMax;
				
					// Calculate Center Offset
					if (center.X > 0)
					{
						center.X = center.X + offset;
					}
					else
					{
						center.X = center.X - offset;
					}

					if (center.Y > 0)
					{
						center.Y = center.Y + offset;
					}
					else
					{
						center.Y = center.Y - offset;
					}

					if (center.Z > 0)
					{
						center.Z = center.Z + offset;
					}
					else
					{
						center.Z = center.Z - offset;
					}
				}
			}

			UE_LOG(LogTemp, Log, TEXT("max: %f"), max);
			// UE_LOG(LogTemp, Log, TEXT("center of nodes: %s"), *center.ToString());

			maxExtent = FVector(max, max, max);
			

			// UE_LOG(LogTemp, Log, TEXT("Extent of nodes: %s"), *tempForCoercion.ToString());

			DrawDebugBox(GetWorld(), center, maxExtent, FColor().Blue, false, 0.0f);
			DrawDebugSphere(GetWorld(), center + maxExtent, 4.0f, 12, FColor().Green, false, 0.0f);
			DrawDebugSphere(GetWorld(), center - maxExtent, 4.0f, 12, FColor().Red, false, 0.0f);

			for (FSimpleOctree::ElementConstIt ElementIt(CurrentNode.GetElementIt()); ElementIt; ++ElementIt)
			{
				const FOctreeElement& Sample = *ElementIt;

				// Draw debug boxes around elements
				max = Sample.BoxSphereBounds.BoxExtent.GetMax();
				maxExtent = FVector(max, max, max);
				center = Sample.MyActor->GetActorLocation();

				DrawDebugBox(GetWorld(), center, maxExtent, FColor().Blue, false, 0.0f);
				DrawDebugSphere(GetWorld(), center + maxExtent, 4.0f, 12, FColor().White, false, 0.0f);
				DrawDebugSphere(GetWorld(), center - maxExtent, 4.0f, 12, FColor().White, false, 0.0f);
				elementCount++;
			}
		}
		// UE_LOG(LogTemp, Log, TEXT("Node Count: %d, Element Count: %d"), nodeCount, elementCount);
	}
// This algorithm taken from Ritter, 1990
// This one seems to do well with asymmetric input.
static void CalcBoundingSphere(const FRawMesh& RawMesh, FSphere& sphere, FVector& LimitVec)
{
	if(RawMesh.VertexPositions.Num() == 0)
		return;

	FBox Box;

	// First, find AABB, remembering furthest points in each dir.
	Box.Min = RawMesh.VertexPositions[0] * LimitVec;
	Box.Max = Box.Min;

	FIntVector minIx, maxIx; // Extreme points.

	minIx = FIntVector::ZeroValue;
	maxIx = FIntVector::ZeroValue;

	for(uint32 i=1; i<(uint32)RawMesh.VertexPositions.Num(); i++) 
	{
		FVector p = RawMesh.VertexPositions[i] * LimitVec;

		// X //
		if(p.X < Box.Min.X)
		{
			Box.Min.X = p.X;
			minIx.X = i;
		}
		else if(p.X > Box.Max.X)
		{
			Box.Max.X = p.X;
			maxIx.X = i;
		}

		// Y //
		if(p.Y < Box.Min.Y)
		{
			Box.Min.Y = p.Y;
			minIx.Y = i;
		}
		else if(p.Y > Box.Max.Y)
		{
			Box.Max.Y = p.Y;
			maxIx.Y = i;
		}

		// Z //
		if(p.Z < Box.Min.Z)
		{
			Box.Min.Z = p.Z;
			minIx.Z = i;
		}
		else if(p.Z > Box.Max.Z)
		{
			Box.Max.Z = p.Z;
			maxIx.Z = i;
		}
	}

	const FVector Extremes[3]={ (RawMesh.VertexPositions[maxIx.X] - RawMesh.VertexPositions[minIx.X]) * LimitVec,
								(RawMesh.VertexPositions[maxIx.Y] - RawMesh.VertexPositions[minIx.Y]) * LimitVec,
								(RawMesh.VertexPositions[maxIx.Z] - RawMesh.VertexPositions[minIx.Z]) * LimitVec };

	// Now find extreme points furthest apart, and initial center and radius of sphere.
	float d2 = 0.f;
	for(int32 i=0; i<3; i++)
	{
		const float tmpd2 = Extremes[i].SizeSquared();
		if(tmpd2 > d2)
		{
			d2 = tmpd2;
			sphere.Center = (RawMesh.VertexPositions[minIx(i)] + (0.5f * Extremes[i])) * LimitVec;
			sphere.W = 0.f;
		}
	}

	const FVector Extents = FVector(Extremes[0].X, Extremes[1].Y, Extremes[2].Z);

	// radius and radius squared
	float r = 0.5f * Extents.GetMax();
	float r2 = FMath::Square(r);

	// Now check each point lies within this sphere. If not - expand it a bit.
	for(uint32 i=0; i<(uint32)RawMesh.VertexPositions.Num(); i++) 
	{
		const FVector cToP = (RawMesh.VertexPositions[i] * LimitVec) - sphere.Center;

		const float pr2 = cToP.SizeSquared();

		// If this point is outside our current bounding sphere's radius
		if(pr2 > r2)
		{
			// ..expand radius just enough to include this point.
			const float pr = FMath::Sqrt(pr2);
			r = 0.5f * (r + pr);
			r2 = FMath::Square(r);

			sphere.Center += ((pr-r)/pr * cToP);
		}
	}

	sphere.W = r;
}