ShowFlag.MassProperties

ShowFlag.MassProperties

#Overview

name: ShowFlag.MassProperties

This variable is created as a Console Variable (cvar).

It is referenced in 23 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of ShowFlag.MassProperties is to enable the rendering of mass debug data in Unreal Engine’s visualization system. This setting is primarily used for debugging and development purposes, allowing developers to visualize the mass properties of objects in the game world.

Unreal Engine subsystems that rely on this setting include:

  1. The rendering system, particularly for debug visualization.
  2. The physics system, specifically for displaying mass-related debug information.
  3. Various scene proxies, such as FStaticMeshSceneProxy and FSkeletalMeshSceneProxy.

The value of this variable is typically set through the engine’s show flags system, which allows developers to toggle various debug visualization options.

Other variables that interact with ShowFlag.MassProperties include:

  1. EngineShowFlags.MassProperties, which is likely the actual flag that controls this feature.
  2. DebugMassData, which appears to store the mass data for debug rendering.

Developers should be aware that:

  1. This flag is intended for development and debugging purposes, not for use in shipping builds.
  2. Enabling this flag may have performance implications, as it adds additional rendering overhead.
  3. The mass properties visualization is only meaningful if the physics simulation is properly set up for the objects in question.

Best practices when using this variable include:

  1. Only enable it when actively debugging mass-related issues.
  2. Disable it in shipping builds to avoid unnecessary performance overhead.
  3. Use it in conjunction with other physics debug tools for a comprehensive understanding of the physics simulation.

Regarding the associated variable MassProperties:

The purpose of MassProperties is to store and manipulate mass-related data for physics objects in Unreal Engine. It includes information such as mass, volume, center of mass, inertia tensor, and rotation of mass.

This structure is used extensively in the physics system, particularly in:

  1. Calculating mass properties for various geometric shapes.
  2. Combining mass properties of complex objects.
  3. Transforming mass properties between different coordinate spaces.

The value of MassProperties is typically set through calculations based on the geometry and density of physics objects.

Developers should be aware that:

  1. Accurate mass properties are crucial for realistic physics simulation.
  2. The calculations can be computationally expensive, especially for complex geometries.
  3. MassProperties are often cached to improve performance.

Best practices when using MassProperties include:

  1. Ensure that the input geometry and density values are accurate.
  2. Cache and reuse MassProperties calculations when possible to improve performance.
  3. Be cautious when manually modifying MassProperties, as incorrect values can lead to unrealistic physics behavior.

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:217

Scope: file

Source code excerpt:

SHOWFLAG_FIXED_IN_SHIPPING(0, Constraints, SFG_Advanced, NSLOCTEXT("UnrealEd", "ConstraintsSF", "Constraints"))
/** Render mass debug data */
SHOWFLAG_FIXED_IN_SHIPPING(0, MassProperties, SFG_Advanced, NSLOCTEXT("UnrealEd", "MassPropertiesSF", "Mass Properties"))
/** Draws camera frustums */
SHOWFLAG_FIXED_IN_SHIPPING(0, CameraFrustums, SFG_Advanced, NSLOCTEXT("UnrealEd", "CameraFrustumsSF", "Camera Frustums"))
/** Draw sound actor radii */
SHOWFLAG_FIXED_IN_SHIPPING(0, AudioRadius, SFG_Advanced, NSLOCTEXT("UnrealEd", "AudioRadiusSF", "Audio Radius"))
/** Draw force feedback radii */
SHOWFLAG_FIXED_IN_SHIPPING(0, ForceFeedbackRadius, SFG_Advanced, NSLOCTEXT("UnrealEd", "ForceFeedbackSF", "Force Feedback Radius"))

#Associated Variable and Callsites

This variable is associated with another variable named MassProperties. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/GeometryCollection/GeometryCollectionTestMassProperties.cpp:54

Scope (from outer to inner):

file
namespace    GeometryCollectionTest
function     GTEST_TEST

Source code excerpt:

		Chaos::FTriangleMesh Surface(MoveTemp(Faces));

		FMassProperties MassProperties;
		MassProperties.Mass = 1.f;
		//Chaos::FMassProperties MassProperties = Chaos::CalculateMassProperties(Vertices, Surface.GetElements(), 1.f);
		{
			const auto& SurfaceElements = Surface.GetElements();
			CalculateVolumeAndCenterOfMass(Vertices, SurfaceElements, MassProperties.Volume, MassProperties.CenterOfMass);

			for (int32 Idx = 0; Idx < 8; ++Idx)
			{
				Vertices.SetX(Idx, Vertices.GetX(Idx) - MassProperties.CenterOfMass);
			}

			check(MassProperties.Mass > 0);
			check(MassProperties.Volume > SMALL_NUMBER);
			
			// @todo(chaos) : breaking
			CalculateInertiaAndRotationOfMass(Vertices, SurfaceElements, MassProperties.Mass / MassProperties.Volume, MassProperties.CenterOfMass, MassProperties.InertiaTensor, MassProperties.RotationOfMass);
		}
		EXPECT_EQ(MassProperties.Mass, 1.f);
		EXPECT_TRUE(MassProperties.CenterOfMass.Equals(FVector(1, 2, 3)));
		
		// This is just measured data to let us know when it changes. Ideally this would be derived. 
		FVector EulerAngle = MassProperties.RotationOfMass.Euler();
		EXPECT_TRUE(MassProperties.RotationOfMass.Euler().Equals(FVector(115.8153, -12.4347, 1.9705)));
		EXPECT_TRUE(FMath::IsNearlyEqual((FReal)MassProperties.InertiaTensor.M[0][0], static_cast<FReal>(14.9866095), (FReal)KINDA_SMALL_NUMBER));
		EXPECT_TRUE(FMath::IsNearlyEqual((FReal)MassProperties.InertiaTensor.M[1][1], static_cast<FReal>(1.40656376), (FReal)KINDA_SMALL_NUMBER));
		EXPECT_TRUE(FMath::IsNearlyEqual((FReal)MassProperties.InertiaTensor.M[2][2], static_cast<FReal>(13.7401619), (FReal)KINDA_SMALL_NUMBER));
	}

	GTEST_TEST(AllTraits, GeometryCollection_MassProperties_Cube)
	{
		using namespace Chaos;
		FVector GlobalTranslation(0); FQuat GlobalRotation = FQuat::MakeFromEuler(FVector(0));

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/GeometryCollection/GeometryCollectionTestMassProperties.cpp:126

Scope (from outer to inner):

file
namespace    GeometryCollectionTest
function     GTEST_TEST

Source code excerpt:

		TArray<FMassProperties> MassPropertiesArray;
		MassPropertiesArray.AddUninitialized(NumGeometries);
		FMassProperties& MassProperties = MassPropertiesArray[GeometryIndex];
		MassProperties.CenterOfMass = FVector(0);
		MassProperties.Mass = 1.0;

		FParticles MassSpaceParticles;
		MassSpaceParticles.AddParticles(Vertex.Num());
		for (int32 Idx = 0; Idx < Vertex.Num(); ++Idx)
		{
			MassSpaceParticles.SetX(Idx, Transform[BoneMap[Idx]].TransformPosition(FVector(Vertex[Idx])));
		}

		CalculateVolumeAndCenterOfMass(MassSpaceParticles, TriMesh->GetElements(), MassProperties.Volume, MassProperties.CenterOfMass);

		EXPECT_NEAR(MassProperties.Volume - 8.0, 0.0f, KINDA_SMALL_NUMBER); 
		EXPECT_NEAR(MassProperties.CenterOfMass.X - GlobalTranslation[0], 0.0f, KINDA_SMALL_NUMBER);
		EXPECT_NEAR(MassProperties.CenterOfMass.Y - GlobalTranslation[1], 0.0f, KINDA_SMALL_NUMBER);
		EXPECT_NEAR(MassProperties.CenterOfMass.Z - GlobalTranslation[2], 0.0f, KINDA_SMALL_NUMBER);

		for (int32 Idx = 0; Idx < Vertex.Num(); ++Idx)
		{
			MassSpaceParticles.SetX(Idx, MassSpaceParticles.GetX(Idx) - MassProperties.CenterOfMass);
		}

		FReal Density = 1.0;
		FVec3 ZeroVec(0);
		CalculateInertiaAndRotationOfMass(MassSpaceParticles, TriMesh->GetSurfaceElements(), Density, ZeroVec, MassProperties.InertiaTensor, MassProperties.RotationOfMass);

		EXPECT_EQ(MassProperties.Mass, 1.f);
		EXPECT_TRUE((MassProperties.CenterOfMass - GlobalTranslation).Size() < SMALL_NUMBER);

		// This is just measured data to let us know when it changes. Ideally this would be derived. 
		EXPECT_TRUE((MassProperties.RotationOfMass.Euler() - FVector(115.8153, -12.4347, 1.9705)).Size() > KINDA_SMALL_NUMBER);
		EXPECT_TRUE(FMath::IsNearlyEqual((FReal)MassProperties.InertiaTensor.M[0][0], static_cast<FReal>(4.99521351), (FReal)KINDA_SMALL_NUMBER));
		EXPECT_TRUE(FMath::IsNearlyEqual((FReal)MassProperties.InertiaTensor.M[1][1], static_cast<FReal>(4.07145357), (FReal)KINDA_SMALL_NUMBER));
		EXPECT_TRUE(FMath::IsNearlyEqual((FReal)MassProperties.InertiaTensor.M[2][2], static_cast<FReal>(4.26666689), (FReal)KINDA_SMALL_NUMBER));
	}

	GTEST_TEST(AllTraits, GeometryCollection_MassProperties_Sphere)
	{
		using namespace Chaos;
		FVector GlobalTranslation(10); FQuat GlobalRotation = FQuat::MakeFromEuler(FVector(0)); FVector Scale(1);

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/GeometryCollection/GeometryCollectionTestMassProperties.cpp:201

Scope (from outer to inner):

file
namespace    GeometryCollectionTest
function     GTEST_TEST

Source code excerpt:

		TArray<FMassProperties> MassPropertiesArray;
		MassPropertiesArray.AddUninitialized(NumGeometries);
		FMassProperties& MassProperties = MassPropertiesArray[GeometryIndex];

		FParticles MassSpaceParticles;
		MassSpaceParticles.AddParticles(Vertex.Num());
		for (int32 Idx = 0; Idx < Vertex.Num(); ++Idx)
		{
			MassSpaceParticles.SetX(Idx, Transform[BoneMap[Idx]].TransformPosition(FVector(Vertex[Idx])));
		}

		CalculateVolumeAndCenterOfMass(MassSpaceParticles, TriMesh->GetElements(), MassProperties.Volume, MassProperties.CenterOfMass);

		// Since we're intersecting triangles with a sphere, where the vertices of the 
		// triangle vertices are on the sphere surface, we're missing some volume.  Thus,
		// we'd expect the volume of the triangulation to approach the analytic volume as
		// the number of polygons goes to infinity (MakeSphereElement() currently does 
		// 16x16 divisions in U and V).
		const FReal AnalyticVolume = (4.0/3) * (22.0/7) * Scale[0] * Scale[0] * Scale[0];
		EXPECT_NEAR(MassProperties.Volume - AnalyticVolume, 0.0f, 0.2); // this should be 4.19047642
		EXPECT_NEAR(MassProperties.CenterOfMass.X - GlobalTranslation[0], 0.0f, KINDA_SMALL_NUMBER);
		EXPECT_NEAR(MassProperties.CenterOfMass.Y - GlobalTranslation[1], 0.0f, KINDA_SMALL_NUMBER);
		EXPECT_NEAR(MassProperties.CenterOfMass.Z - GlobalTranslation[2], 0.0f, KINDA_SMALL_NUMBER);


		for (int32 Idx = 0; Idx < Vertex.Num(); ++Idx)
		{
			MassSpaceParticles.SetX(Idx, MassSpaceParticles.GetX(Idx) - MassProperties.CenterOfMass);
		}

		FReal Density = 0.01;
		FVec3 ZeroVec(0);
		CalculateInertiaAndRotationOfMass(MassSpaceParticles, TriMesh->GetSurfaceElements(), Density, ZeroVec, MassProperties.InertiaTensor, MassProperties.RotationOfMass);

		// todo(chaos) : Check this. 
		// This is just measured data to let us know when it changes. Ideally this would be derived. 
		FVector EulerAngle = MassProperties.RotationOfMass.Euler();
		//EXPECT_TRUE((MassProperties.RotationOfMass.Euler() - FVector(115.8153, -12.4347, 1.9705)).Size() > SMALL_NUMBER);
		//EXPECT_TRUE(MassProperties.InertiaTensor.M[0][0] - 4.99521351 < SMALL_NUMBER);
		//EXPECT_TRUE(MassProperties.InertiaTensor.M[1][1] - 4.07145357 < SMALL_NUMBER);
		//EXPECT_TRUE(MassProperties.InertiaTensor.M[2][2] - 4.26666689 < SMALL_NUMBER);
	}


	GTEST_TEST(AllTraits, GeometryCollection_MassProperties_Tetrahedron)
	{
		using namespace Chaos;

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/GeometryCollection/GeometryCollectionTestMassProperties.cpp:281

Scope (from outer to inner):

file
namespace    GeometryCollectionTest
function     GTEST_TEST

Source code excerpt:

		TArray<FMassProperties> MassPropertiesArray;
		MassPropertiesArray.AddUninitialized(NumGeometries);
		FMassProperties& MassProperties = MassPropertiesArray[GeometryIndex];
		MassProperties.Mass = 1.0;
		MassProperties.CenterOfMass = FVector(0);

		FParticles MassSpaceParticles;
		MassSpaceParticles.AddParticles(Vertex.Num());
		for (int32 Idx = 0; Idx < Vertex.Num(); ++Idx)
		{
			MassSpaceParticles.SetX(Idx, Transform[BoneMap[Idx]].TransformPosition(FVector(Vertex[Idx])));
		}

		CalculateVolumeAndCenterOfMass(MassSpaceParticles, TriMesh->GetElements(), MassProperties.Volume, MassProperties.CenterOfMass);

		EXPECT_NEAR(MassProperties.Volume - 2.666666, 0.0f, KINDA_SMALL_NUMBER); // Tetrahedron with edge lengths 2.8284
		EXPECT_NEAR(MassProperties.CenterOfMass.X - GlobalTranslation[0], 0.0f, KINDA_SMALL_NUMBER);
		EXPECT_NEAR(MassProperties.CenterOfMass.Y - GlobalTranslation[1], 0.0f, KINDA_SMALL_NUMBER);
		EXPECT_NEAR(MassProperties.CenterOfMass.Z - GlobalTranslation[2], 0.0f, KINDA_SMALL_NUMBER);

		for (int32 Idx = 0; Idx < Vertex.Num(); ++Idx)
		{
			MassSpaceParticles.SetX(Idx, MassSpaceParticles.GetX(Idx) - MassProperties.CenterOfMass);
		}

		FReal Density = 0.01;
		FVec3 ZeroVec(0);
		CalculateInertiaAndRotationOfMass(MassSpaceParticles, TriMesh->GetSurfaceElements(), Density, ZeroVec, MassProperties.InertiaTensor, MassProperties.RotationOfMass);

		// todo(chaos) : Check this. 
		// This is just measured data to let us know when it changes. Ideally this would be derived. 
		FVector EulerAngle = MassProperties.RotationOfMass.Euler();
		//EXPECT_TRUE((MassProperties.RotationOfMass.Euler() - FVector(115.8153, -12.4347, 1.9705)).Size() > SMALL_NUMBER);
		//EXPECT_TRUE(MassProperties.InertiaTensor.M[0][0] - 4.99521351 < SMALL_NUMBER);
		//EXPECT_TRUE(MassProperties.InertiaTensor.M[1][1] - 4.07145357 < SMALL_NUMBER);
		//EXPECT_TRUE(MassProperties.InertiaTensor.M[2][2] - 4.26666689 < SMALL_NUMBER);
	}




	GTEST_TEST(AllTraits, GeometryCollection_MassProperties_ScaledSphere)

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/GeometryCollection/GeometryCollectionTestMassProperties.cpp:363

Scope (from outer to inner):

file
namespace    GeometryCollectionTest
function     GTEST_TEST

Source code excerpt:

		TArray<FMassProperties> MassPropertiesArray;
		MassPropertiesArray.AddUninitialized(NumGeometries);
		FMassProperties& MassProperties = MassPropertiesArray[GeometryIndex];

		TArray<FVector> SomeVec;
		FParticles MassSpaceParticles;
		MassSpaceParticles.AddParticles(Vertex.Num());
		for (int32 Idx = 0; Idx < Vertex.Num(); ++Idx)
		{

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/GeometryCollection/GeometryCollectionTestMassProperties.cpp:377

Scope (from outer to inner):

file
namespace    GeometryCollectionTest
function     GTEST_TEST

Source code excerpt:


		FBox Bounds(SomeVec);
		CalculateVolumeAndCenterOfMass(MassSpaceParticles, TriMesh->GetElements(), MassProperties.Volume, MassProperties.CenterOfMass);
		
		EXPECT_NEAR(MassProperties.CenterOfMass.X - GlobalTranslation[0], 0.0f, KINDA_SMALL_NUMBER);
		EXPECT_NEAR(MassProperties.CenterOfMass.Y - GlobalTranslation[1], 0.0f, KINDA_SMALL_NUMBER);
		EXPECT_NEAR(MassProperties.CenterOfMass.Z - GlobalTranslation[2], 0.0f, KINDA_SMALL_NUMBER);

		for (int32 Idx = 0; Idx < Vertex.Num(); ++Idx)
		{
			MassSpaceParticles.SetX(Idx, MassSpaceParticles.GetX(Idx) - MassProperties.CenterOfMass);
		}

		FReal Density = 0.01;
		FVec3 ZeroVec(0);
		CalculateInertiaAndRotationOfMass(MassSpaceParticles, TriMesh->GetSurfaceElements(), Density, ZeroVec, MassProperties.InertiaTensor, MassProperties.RotationOfMass);

		FVector RotationEulerClamped = MassProperties.RotationOfMass.Euler();
		if (RotationEulerClamped[0] < 0.)
		{
			RotationEulerClamped[0] += 180.f;
		}
		
		// rotational alignment.

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/GeometryCollection/GeometryCollectionTestMassProperties.cpp:403

Scope (from outer to inner):

file
namespace    GeometryCollectionTest
function     GTEST_TEST

Source code excerpt:

		EXPECT_NEAR(RotationEulerClamped[2], 0., KINDA_SMALL_NUMBER);
		// X dominate inertia tensor
		EXPECT_GT(MassProperties.InertiaTensor.M[0][0], MassProperties.InertiaTensor.M[2][2]);
		EXPECT_GT(MassProperties.InertiaTensor.M[0][0], MassProperties.InertiaTensor.M[1][1]);
	}

}

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/HeadlessChaosTestMassProperties.cpp:197

Scope (from outer to inner):

file
namespace    ChaosTest
function     void ComputeMassProperties

Source code excerpt:

		Faces[11] = TVec3<int32>(1, 5, 7);
		Chaos::FTriangleMesh Surface(MoveTemp(Faces));
		Chaos::FMassProperties MassProperties = Chaos::CalculateMassProperties(Particles, Surface.GetElements(), (FReal)1.0);
		EXPECT_TRUE(MassProperties.CenterOfMass.Size() < SMALL_NUMBER);
		EXPECT_TRUE(MassProperties.RotationOfMass.Euler().Size() < SMALL_NUMBER);
		EXPECT_TRUE(MassProperties.InertiaTensor.M[0][0] - ((FReal)2 / 3) < SMALL_NUMBER);
		EXPECT_TRUE(MassProperties.InertiaTensor.M[1][1] - ((FReal)2 / 3) < SMALL_NUMBER);
		EXPECT_TRUE(MassProperties.InertiaTensor.M[2][2] - ((FReal)2 / 3) < SMALL_NUMBER);
	}


	TEST(MassPropertyTests, TestTransformToLocalSpace1) {
		ChaosTest::TransformToLocalSpace1();
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsEngine/ImmediatePhysics/ImmediatePhysicsChaos/ImmediatePhysicsActorHandle_Chaos.cpp:164

Scope (from outer to inner):

file
namespace    ImmediatePhysics_Chaos
function     bool CreateGeometry

Source code excerpt:

			// as well as the dimension change even though we don't actually change the mass.
			const bool bInertaScaleIncludeMass = true;
			FMassProperties MassProperties = BodyUtils::ComputeMassProperties(BodyInstance, Shapes, bContributesToMass, FTransform::Identity, bInertaScaleIncludeMass);
			OutMass = MassProperties.Mass;
			OutInertia = MassProperties.InertiaTensor.GetDiagonal();
			OutCoMTransform = FTransform(MassProperties.RotationOfMass, MassProperties.CenterOfMass);
		}

		// If we have multiple root shapes, wrap them in a union
		if (Geoms.Num() == 1)
		{
			OutGeom = MoveTemp(Geoms[0]);

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PrimitiveDrawingUtils.cpp:1544

Scope (from outer to inner):

file
function     bool IsRichView

Source code excerpt:

		ViewFamily.EngineShowFlags.LODColoration ||
		ViewFamily.EngineShowFlags.HLODColoration ||
		ViewFamily.EngineShowFlags.MassProperties )
	{
		return true;
	}

	return false;
}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Rendering/NaniteResources.cpp:1530

Scope (from outer to inner):

file
namespace    Nanite
function     void FSceneProxy::GetDynamicMeshElements

Source code excerpt:

#endif // STATICMESH_ENABLE_DEBUG_RENDERING

				if (EngineShowFlags.MassProperties && DebugMassData.Num() > 0)
				{
					DebugMassData[0].DrawDebugMass(Collector.GetPDI(ViewIndex), FTransform(InstanceToWorld));
				}

				if (EngineShowFlags.StaticMeshes)
				{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkeletalMesh.cpp:6626

Scope (from outer to inner):

file
function     void FSkeletalMeshSceneProxy::GetMeshElementsConditionallySelectable

Source code excerpt:

			}

			if (EngineShowFlags.MassProperties && DebugMassData.Num() > 0)
			{
				FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
				if (MeshObject->GetComponentSpaceTransforms())
				{
					const TArray<FTransform>& ComponentSpaceTransforms = *MeshObject->GetComponentSpaceTransforms();

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/StaticMeshRender.cpp:1833

Scope (from outer to inner):

file
function     void FStaticMeshSceneProxy::GetDynamicMeshElements

Source code excerpt:

			}

			if(EngineShowFlags.MassProperties && DebugMassData.Num() > 0)
			{
				DebugMassData[0].DrawDebugMass(Collector.GetPDI(ViewIndex), FTransform(GetLocalToWorld()));
			}
	
			if (EngineShowFlags.StaticMeshes)
			{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:217

Scope: file

Source code excerpt:

SHOWFLAG_FIXED_IN_SHIPPING(0, Constraints, SFG_Advanced, NSLOCTEXT("UnrealEd", "ConstraintsSF", "Constraints"))
/** Render mass debug data */
SHOWFLAG_FIXED_IN_SHIPPING(0, MassProperties, SFG_Advanced, NSLOCTEXT("UnrealEd", "MassPropertiesSF", "Mass Properties"))
/** Draws camera frustums */
SHOWFLAG_FIXED_IN_SHIPPING(0, CameraFrustums, SFG_Advanced, NSLOCTEXT("UnrealEd", "CameraFrustumsSF", "Camera Frustums"))
/** Draw sound actor radii */
SHOWFLAG_FIXED_IN_SHIPPING(0, AudioRadius, SFG_Advanced, NSLOCTEXT("UnrealEd", "AudioRadiusSF", "Audio Radius"))
/** Draw force feedback radii */
SHOWFLAG_FIXED_IN_SHIPPING(0, ForceFeedbackRadius, SFG_Advanced, NSLOCTEXT("UnrealEd", "ForceFeedbackSF", "Force Feedback Radius"))

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/MassProperties.cpp:96

Scope (from outer to inner):

file
namespace    Chaos
function     void TransformToLocalSpace

Source code excerpt:

	}

	void TransformToLocalSpace(FMassProperties& MassProperties)
	{
		// Diagonalize inertia
		const FRotation3 InertiaRotation = TransformToLocalSpace(MassProperties.InertiaTensor);

		// Calculate net rotation
		MassProperties.RotationOfMass = MassProperties.RotationOfMass * InertiaRotation;
	}


	void CalculateVolumeAndCenterOfMass(const FBox& BoundingBox, FVector::FReal& OutVolume, FVector& OutCenterOfMass)
	{
		const FVector Extents = static_cast<FVector::FReal>(2) * BoundingBox.GetExtent(); // FBox::GetExtent() returns half the size, but FAABB::Extents() returns total size

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/MassProperties.cpp:127

Scope (from outer to inner):

file
namespace    Chaos
function     FMassProperties CalculateMassProperties

Source code excerpt:

	FMassProperties CalculateMassProperties(const FBox& BoundingBox, const FVector::FReal Density)
	{
		FMassProperties MassProperties;
		CalculateVolumeAndCenterOfMass(BoundingBox, MassProperties.Volume, MassProperties.CenterOfMass);
		check(Density > 0);
		MassProperties.Mass = MassProperties.Volume * Density;
		CalculateInertiaAndRotationOfMass(BoundingBox, Density, MassProperties.InertiaTensor, MassProperties.RotationOfMass);
		return MassProperties;
	}
	
	template<typename T, typename TVec, typename TSurfaces>
	void CalculateVolumeAndCenterOfMassImpl(const TArray<TVec>& Vertices, const TSurfaces& Surfaces, T& OutVolume, TVec& OutCenterOfMass)
	{
		if (!Surfaces.Num())

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/MassProperties.cpp:261

Scope (from outer to inner):

file
namespace    Chaos
function     FMassProperties CalculateMassProperties

Source code excerpt:

		const FReal Mass)
	{
		FMassProperties MassProperties;
		CalculateVolumeAndCenterOfMass(Vertices, Surfaces, MassProperties.Volume, MassProperties.CenterOfMass);

		check(Mass > 0);
		check(MassProperties.Volume > UE_SMALL_NUMBER);
		CalculateInertiaAndRotationOfMass(Vertices, Surfaces, Mass / MassProperties.Volume, MassProperties.CenterOfMass, MassProperties.InertiaTensor, MassProperties.RotationOfMass);
		
		return MassProperties;
	}

	FMassProperties Combine(const TArray<FMassProperties>& MPArray)
	{
		FMassProperties NewMP = CombineWorldSpace(MPArray);
		TransformToLocalSpace(NewMP);

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/MassProperties.cpp:344

Scope (from outer to inner):

file
namespace    Chaos
function     bool CalculateMassPropertiesOfImplicitUnion

Source code excerpt:

			if (const Chaos::FImplicitObject* ImplicitObject = ImplicitObjectUniquePtr.GetReference())
			{
				Chaos::FMassProperties MassProperties;
				if (CalculateMassPropertiesOfImplicitType(MassProperties, FTransform::Identity, ImplicitObject, InDensityKGPerCM))
				{
					MassPropertiesList.Add(MassProperties);
					TotalMass += MassProperties.Mass;
					TotalVolume += MassProperties.Volume;
					TotalCenterOfMass += MassProperties.CenterOfMass * MassProperties.Mass;
				}
			}
		}

		Chaos::FMatrix33 Tensor;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/MassProperties.cpp:457

Scope (from outer to inner):

file
namespace    Chaos
function     void CalculateMassPropertiesFromShapeCollection

Source code excerpt:

				if (const Chaos::FImplicitObject* ImplicitObject = Shape->GetGeometry())
				{
					Chaos::FMassProperties MassProperties;
					if (CalculateMassPropertiesOfImplicitType(MassProperties, FTransform::Identity, ImplicitObject, InDensityKGPerCM))
					{
						MassPropertiesList.Add(MassProperties);
						TotalMass += MassProperties.Mass;
						TotalVolume += MassProperties.Volume;
						TotalCenterOfMass += MassProperties.CenterOfMass * MassProperties.Mass;
					}
				}
			}
		}

		Chaos::FMatrix33 Tensor;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/PhysicsProxy/GeometryCollectionPhysicsProxy.cpp:5096

Scope (from outer to inner):

file
function     void FGeometryCollectionPhysicsProxy::InitializeSharedCollisionStructures
lambda-function

Source code excerpt:

		{
			TUniquePtr<FTriangleMesh>& TriMesh = TriangleMeshesArray[TransformGroupIndex];
			FMassProperties& MassProperties = MassPropertiesArray[GeometryIndex];

			const FReal Mass_i = FMath::Max(DesiredDensity * Volume_i, SharedParams.MinimumMassClamp);
			const FReal Density_i = Mass_i / Volume_i;
			CollectionMass[TransformGroupIndex] = (FRealSingle)Mass_i;

			// scale the mass properties inertia tensor by the Density_i ( as we computedit earlier with a density of one )

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/PhysicsProxy/GeometryCollectionPhysicsProxy.cpp:5107

Scope (from outer to inner):

file
function     void FGeometryCollectionPhysicsProxy::InitializeSharedCollisionStructures
lambda-function

Source code excerpt:

			CollectionInertiaTensor[TransformGroupIndex] = FVector3f((float)InertiaTensor.M[0][0], (float)InertiaTensor.M[1][1], (float)InertiaTensor.M[2][2]);

			CollectionMassToLocal[TransformGroupIndex] = FTransform(MassProperties.RotationOfMass, MassProperties.CenterOfMass);
		}
	});

	// we need the vertices in mass space to compute the collision particles
	// todo(chaos) we shoudl eventually get rid of that that's a waste of memory and performance
	FParticles MassSpaceParticles;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Public/Chaos/MassProperties.h:38

Scope (from outer to inner):

file
namespace    Chaos

Source code excerpt:

	template <typename T>
	TRotation<T,3> CHAOS_API TransformToLocalSpace(PMatrix<T,3,3>& Inertia);
	void CHAOS_API TransformToLocalSpace(FMassProperties& MassProperties);

	template<typename T, typename TSurfaces>
	void CHAOS_API CalculateVolumeAndCenterOfMass(const TParticles<T,3>& Vertices, const TSurfaces& Surfaces, T& OutVolume, TVec3<T>& OutCenterOfMass);

	template<typename T, typename TSurfaces>
	void CHAOS_API CalculateVolumeAndCenterOfMass(const TArray<TVec3<T>>& Vertices, const TSurfaces& Surfaces, T& OutVolume, TVec3<T>& OutCenterOfMass);