2021-02-25 05:39:27 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "Physics/ComponentCollisionUtil.h"
|
|
|
|
|
|
2021-06-13 00:36:02 -04:00
|
|
|
#include "DynamicMesh/DynamicMesh3.h"
|
2021-02-25 05:39:27 -04:00
|
|
|
#include "ShapeApproximation/SimpleShapeSet3.h"
|
|
|
|
|
|
|
|
|
|
#include "Physics/PhysicsDataCollection.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "Components/StaticMeshComponent.h"
|
|
|
|
|
#include "Engine/StaticMesh.h"
|
|
|
|
|
#include "Engine/Classes/PhysicsEngine/BodySetup.h"
|
|
|
|
|
#include "PhysicsEngine/AggregateGeom.h"
|
|
|
|
|
|
2021-03-09 19:33:56 -04:00
|
|
|
using namespace UE::Geometry;
|
2021-02-25 05:39:27 -04:00
|
|
|
|
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs.
- Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module
- move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module
- Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options
- Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs
- Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget
- Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation
- Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate().
- Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets
- Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high).
- DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop
#rb none
#rnx
#jira none
#preflight 60ba50632c42ea0001cb54c5
[CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
|
|
|
bool UE::Geometry::ComponentTypeSupportsCollision(
|
|
|
|
|
const UPrimitiveComponent* Component)
|
|
|
|
|
{
|
|
|
|
|
// currently only supporting StaticMeshComponent
|
|
|
|
|
const UStaticMeshComponent* StaticMeshComponent = Cast<UStaticMeshComponent>(Component);
|
|
|
|
|
return (StaticMeshComponent != nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-03-09 19:33:56 -04:00
|
|
|
FComponentCollisionSettings UE::Geometry::GetCollisionSettings(const UPrimitiveComponent* Component)
|
2021-02-25 05:39:27 -04:00
|
|
|
{
|
|
|
|
|
FComponentCollisionSettings Settings;
|
|
|
|
|
|
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs.
- Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module
- move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module
- Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options
- Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs
- Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget
- Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation
- Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate().
- Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets
- Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high).
- DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop
#rb none
#rnx
#jira none
#preflight 60ba50632c42ea0001cb54c5
[CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
|
|
|
const UStaticMeshComponent* StaticMeshComponent = Cast<UStaticMeshComponent>(Component);
|
2021-02-25 05:39:27 -04:00
|
|
|
if (ensure(StaticMeshComponent))
|
|
|
|
|
{
|
|
|
|
|
const UStaticMesh* StaticMesh = StaticMeshComponent->GetStaticMesh();
|
|
|
|
|
if (ensure(StaticMesh))
|
|
|
|
|
{
|
|
|
|
|
UBodySetup* BodySetup = StaticMesh->GetBodySetup();
|
|
|
|
|
if (ensure(BodySetup))
|
|
|
|
|
{
|
|
|
|
|
Settings.CollisionTypeFlag = (int32)BodySetup->CollisionTraceFlag;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Settings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UE::Geometry::UpdateSimpleCollision(
|
|
|
|
|
UBodySetup* BodySetup,
|
|
|
|
|
const FKAggregateGeom* NewGeometry,
|
|
|
|
|
UStaticMesh* StaticMesh,
|
|
|
|
|
FComponentCollisionSettings CollisionSettings)
|
|
|
|
|
{
|
|
|
|
|
BodySetup->Modify();
|
|
|
|
|
BodySetup->RemoveSimpleCollision();
|
|
|
|
|
|
|
|
|
|
// set new collision geometry
|
|
|
|
|
BodySetup->AggGeom = *NewGeometry;
|
|
|
|
|
|
|
|
|
|
// update collision type
|
|
|
|
|
BodySetup->CollisionTraceFlag = (ECollisionTraceFlag)CollisionSettings.CollisionTypeFlag;
|
|
|
|
|
|
|
|
|
|
// rebuild physics meshes
|
|
|
|
|
BodySetup->CreatePhysicsMeshes();
|
|
|
|
|
|
|
|
|
|
// rebuild nav collision (? StaticMeshEditor does this)
|
|
|
|
|
StaticMesh->CreateNavCollision(/*bIsUpdate=*/true);
|
|
|
|
|
|
|
|
|
|
// update physics state on all components using this StaticMesh
|
|
|
|
|
for (FThreadSafeObjectIterator Iter(UStaticMeshComponent::StaticClass()); Iter; ++Iter)
|
|
|
|
|
{
|
|
|
|
|
UStaticMeshComponent* SMComponent = Cast<UStaticMeshComponent>(*Iter);
|
|
|
|
|
if (SMComponent->GetStaticMesh() == StaticMesh)
|
|
|
|
|
{
|
|
|
|
|
if (SMComponent->IsPhysicsStateCreated())
|
|
|
|
|
{
|
|
|
|
|
SMComponent->RecreatePhysicsState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mark static mesh as dirty so it gets resaved?
|
2021-10-28 19:47:45 -04:00
|
|
|
[[maybe_unused]] bool MarkedDirty = StaticMesh->MarkPackageDirty();
|
2021-02-25 05:39:27 -04:00
|
|
|
|
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
|
|
|
// mark the static mesh as having customized collision so it is not regenerated on reimport
|
|
|
|
|
StaticMesh->bCustomizedCollision = CollisionSettings.bIsGeneratedCollision;
|
|
|
|
|
#endif // WITH_EDITORONLY_DATA
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool UE::Geometry::SetSimpleCollision(
|
|
|
|
|
UPrimitiveComponent* Component,
|
|
|
|
|
const FSimpleShapeSet3d* ShapeSet,
|
|
|
|
|
FComponentCollisionSettings CollisionSettings)
|
|
|
|
|
{
|
|
|
|
|
FPhysicsDataCollection PhysicsData;
|
|
|
|
|
PhysicsData.InitializeFromComponent(Component, false);
|
|
|
|
|
if (ensure(PhysicsData.SourceComponent.IsValid()) == false || ensure(ShapeSet != nullptr) == false )
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PhysicsData.Geometry = *ShapeSet;
|
|
|
|
|
PhysicsData.CopyGeometryToAggregate();
|
|
|
|
|
|
|
|
|
|
// FPhysicsDataCollection stores its references as const, but the input Component was non-const so this is ok to do
|
|
|
|
|
UStaticMesh* StaticMesh = const_cast<UStaticMesh*>(PhysicsData.SourceStaticMesh.Get());
|
|
|
|
|
UBodySetup* BodySetup = StaticMesh->GetBodySetup();
|
|
|
|
|
UpdateSimpleCollision(BodySetup, &PhysicsData.AggGeom, StaticMesh, CollisionSettings);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool UE::Geometry::TransformSimpleCollision(
|
|
|
|
|
UPrimitiveComponent* Component,
|
|
|
|
|
const FTransform3d& Transform)
|
|
|
|
|
{
|
|
|
|
|
FPhysicsDataCollection PhysicsData;
|
|
|
|
|
PhysicsData.InitializeFromComponent(Component, true);
|
|
|
|
|
if ( ensure(PhysicsData.SourceComponent.IsValid()) == false)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FComponentCollisionSettings Settings = GetCollisionSettings(Component);
|
|
|
|
|
Settings.bIsGeneratedCollision = false;
|
|
|
|
|
|
|
|
|
|
PhysicsData.Geometry.ApplyTransform(Transform);
|
|
|
|
|
PhysicsData.ClearAggregate();
|
|
|
|
|
PhysicsData.CopyGeometryToAggregate();
|
|
|
|
|
|
|
|
|
|
// FPhysicsDataCollection stores its references as const, but the input Component was non-const so this is ok to do
|
|
|
|
|
UStaticMesh* StaticMesh = const_cast<UStaticMesh*>(PhysicsData.SourceStaticMesh.Get());
|
|
|
|
|
UBodySetup* BodySetup = StaticMesh->GetBodySetup();
|
|
|
|
|
UpdateSimpleCollision(BodySetup, &PhysicsData.AggGeom, StaticMesh, Settings);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool UE::Geometry::AppendSimpleCollision(
|
|
|
|
|
const UPrimitiveComponent* Component,
|
|
|
|
|
FSimpleShapeSet3d* ShapeSetOut,
|
|
|
|
|
const FTransform3d& Transform)
|
|
|
|
|
{
|
|
|
|
|
FPhysicsDataCollection PhysicsData;
|
|
|
|
|
PhysicsData.InitializeFromComponent(Component, true);
|
|
|
|
|
if (ensure(PhysicsData.SourceComponent.IsValid()) == false || ensure(ShapeSetOut != nullptr) == false)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShapeSetOut->Append(PhysicsData.Geometry, Transform);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool UE::Geometry::AppendSimpleCollision(
|
|
|
|
|
const UPrimitiveComponent* Component,
|
|
|
|
|
FSimpleShapeSet3d* ShapeSetOut,
|
|
|
|
|
const TArray<FTransform3d>& TransformSeqeuence)
|
|
|
|
|
{
|
|
|
|
|
FPhysicsDataCollection PhysicsData;
|
|
|
|
|
PhysicsData.InitializeFromComponent(Component, true);
|
|
|
|
|
if (ensure(PhysicsData.SourceComponent.IsValid()) == false || ensure(ShapeSetOut != nullptr) == false)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShapeSetOut->Append(PhysicsData.Geometry, TransformSeqeuence);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|