Implement hydrostatic forces
Implement hydrostatic forces
This commit is contained in:
parent
607a29aa16
commit
f6ecbc44e5
BIN
Content/Maps/ShipTest.umap
(Stored with Git LFS)
BIN
Content/Maps/ShipTest.umap
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Maps/ShipTest_BuiltData.uasset
(Stored with Git LFS)
BIN
Content/Maps/ShipTest_BuiltData.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/BP_Ship.uasset
(Stored with Git LFS)
BIN
Content/Ships/BP_Ship.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/BP_TestCube.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Ships/BP_TestCube.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Ships/BP_TestShip.uasset
(Stored with Git LFS)
BIN
Content/Ships/BP_TestShip.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/_defaultMat.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/_defaultMat.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/iron.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/iron.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_front.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_front.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_front1.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_front1.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left2.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left2.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left3.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left3.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left4.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left4.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left5.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left5.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left6.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_left6.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right10.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right10.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right11.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right11.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right7.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right7.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right8.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right8.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right9.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_cannon_right9.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_sail_back.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_sail_back.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_sail_front.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_sail_front.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_sail_middle.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_sail_middle.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_ship_dark_8angles.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_ship_dark_8angles.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/ship_dark_steering.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/ship_dark_steering.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/window.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/window.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/wood.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/wood.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Ships/Ship_Dark/woodDark.uasset
(Stored with Git LFS)
BIN
Content/Ships/Ship_Dark/woodDark.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Test/TestBoat.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Test/TestBoat.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -22,16 +22,16 @@ UBuoyancyComponent::UBuoyancyComponent()
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
// Called when the game starts
|
||||
void UBuoyancyComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
// ...
|
||||
UStaticMeshComponent* MeshComp = Cast<UStaticMeshComponent>(GetOwner()->GetRootComponent());
|
||||
VolumeMesh = MeshComp->GetStaticMesh();
|
||||
|
||||
|
||||
VolumeAsPrimComp = Cast<UPrimitiveComponent>(MeshComp);
|
||||
|
||||
SubmergedTriangles = TArray<FTriangleData>();
|
||||
SubmergedTriangles.SetNum(GetNumTriangles(), false);
|
||||
}
|
||||
@ -46,7 +46,7 @@ void UBuoyancyComponent::TickComponent(float DeltaTime, ELevelTick TickType, FAc
|
||||
|
||||
// determine height of vertices above or below surface of water
|
||||
ASOCGameState* State = Cast<ASOCGameState>(GetWorld()->GetGameState());
|
||||
AOcean* Ocean = nullptr;
|
||||
Ocean = nullptr;
|
||||
if(State)
|
||||
{
|
||||
Ocean = State->GetOcean();
|
||||
@ -70,11 +70,10 @@ void UBuoyancyComponent::TickComponent(float DeltaTime, ELevelTick TickType, FAc
|
||||
|
||||
if(V1.Depth < 0.0f || V2.Depth < 0.0f || V3.Depth < 0.0f)
|
||||
{
|
||||
FTriangleData temp(V1, V2, V3);
|
||||
FTriangleData temp(V1, V2, V3, Ocean->GetOceanHeight());
|
||||
Triangles.Add(temp);
|
||||
FVector Center = (V1.Position + V2.Position + V3.Position) / 3.0f;
|
||||
if(DebugBuoyancy)
|
||||
DrawDebugSphere(GetWorld(), Center, 5.0f, 12, FColor::Yellow, false, 0.0f, 0, 1.0f);
|
||||
DrawDebugSphere(GetWorld(), temp.Center, 5.0f, 12, FColor::Yellow, false, 0.0f, 0, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,18 +83,33 @@ void UBuoyancyComponent::TickComponent(float DeltaTime, ELevelTick TickType, FAc
|
||||
{
|
||||
FString DebugMsg = FString::Printf(TEXT("Num Submerged Triangles: %d\nNum Generated Triangles: %d"),
|
||||
Triangles.Num(), SubmergedTriangles.Num());
|
||||
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Cyan, DebugMsg);
|
||||
GEngine->AddOnScreenDebugMessage(-1, -1.0f, FColor::Cyan, DebugMsg);
|
||||
|
||||
for (auto Triangle : SubmergedTriangles)
|
||||
{
|
||||
DrawDebugSphere(GetWorld(), Triangle.Highest.Position, 2.0f, 12, FColor::Red,
|
||||
DrawDebugSphere(GetWorld(), Triangle.V3.GlobalPosition, 2.0f, 12, FColor::Red,
|
||||
false, 0.0f, 0, 1.0f);
|
||||
DrawDebugSphere(GetWorld(), Triangle.Middle.Position, 2.0f, 12, FColor::Red,
|
||||
DrawDebugSphere(GetWorld(), Triangle.V2.GlobalPosition, 2.0f, 12, FColor::Red,
|
||||
false, 0.0f, 0, 1.0f);
|
||||
DrawDebugSphere(GetWorld(), Triangle.Lowest.Position, 2.0f, 12, FColor::Red,
|
||||
DrawDebugSphere(GetWorld(), Triangle.V1.GlobalPosition, 2.0f, 12, FColor::Red,
|
||||
false, 0.0f, 0, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if(VolumeAsPrimComp)
|
||||
{
|
||||
for (auto Triangle : SubmergedTriangles)
|
||||
{
|
||||
float rhoInKgCm3 = 0.001025f;
|
||||
// F = -p*g*Hcenter*normal
|
||||
FVector Force = -rhoInKgCm3 * GetWorld()->GetGravityZ() * Triangle.DistanceToSurface * Triangle.Area * Triangle.Normal;
|
||||
FVector VerticalForce(0.0f, 0.0f, Force.Z);
|
||||
VolumeAsPrimComp->AddForceAtLocation(VerticalForce, Triangle.Center);
|
||||
}
|
||||
}
|
||||
|
||||
FString DebugMsg = FString::Printf(TEXT("Velocity.Z: %s"), *FString::SanitizeFloat(VolumeAsPrimComp->GetPhysicsLinearVelocity().Z));
|
||||
GEngine->AddOnScreenDebugMessage(-1, -1.0f, FColor::Magenta, DebugMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +147,7 @@ TArray<FVertexData> UBuoyancyComponent::GetVertexPositions()
|
||||
// convert asset space vertex position to world space
|
||||
FVector WorldSpaceVertexPos = GetOwner()->GetActorLocation() + GetOwner()->GetTransform().TransformVector(VertexBuffer->VertexPosition(idx));
|
||||
FVertexData temp;
|
||||
temp.Position = WorldSpaceVertexPos;
|
||||
temp.GlobalPosition = WorldSpaceVertexPos;
|
||||
VertexPositions.Add(temp);
|
||||
}
|
||||
}
|
||||
@ -175,12 +189,21 @@ void UBuoyancyComponent::ProcessTriangles(TArray<FTriangleData>& Triangles)
|
||||
}
|
||||
else if (NumSubmergedVertices == 2)
|
||||
{
|
||||
FVector H = Triangle.Highest.Position;
|
||||
FVector M = Triangle.Middle.Position;
|
||||
FVector L = Triangle.Lowest.Position;
|
||||
float hH = Triangle.Highest.Depth;
|
||||
float hM = Triangle.Middle.Depth;
|
||||
float hL = Triangle.Lowest.Depth;
|
||||
FVertexData V1 = Triangle.V1;
|
||||
FVertexData V2 = Triangle.V2;
|
||||
FVertexData V3 = Triangle.V3;
|
||||
TArray<FVertexData> Vertices = {V1, V2, V3};
|
||||
Vertices.Sort();
|
||||
V1 = Vertices[0];
|
||||
V2 = Vertices[1];
|
||||
V3 = Vertices[2];
|
||||
|
||||
FVector H = V3.GlobalPosition;
|
||||
FVector M = V2.GlobalPosition;
|
||||
FVector L = V1.GlobalPosition;
|
||||
float hH = V3.Depth;
|
||||
float hM = V2.Depth;
|
||||
float hL = V1.Depth;
|
||||
|
||||
FVector MH = H - M;
|
||||
float tM = -hL/(hH - hL);
|
||||
@ -192,17 +215,26 @@ void UBuoyancyComponent::ProcessTriangles(TArray<FTriangleData>& Triangles)
|
||||
FVector LIL = tL * LH;
|
||||
FVector IL = LIL + L;
|
||||
|
||||
SubmergedTriangles.Add(FTriangleData(IM, IL, L));
|
||||
SubmergedTriangles.Add(FTriangleData(M, IM, L));
|
||||
SubmergedTriangles.Add(FTriangleData(L, IL, IM, Ocean->GetOceanHeight()));
|
||||
SubmergedTriangles.Add(FTriangleData(M, L, IM, Ocean->GetOceanHeight()));
|
||||
}
|
||||
else if (NumSubmergedVertices == 1)
|
||||
{
|
||||
FVector H = Triangle.Highest.Position;
|
||||
FVector M = Triangle.Middle.Position;
|
||||
FVector L = Triangle.Lowest.Position;
|
||||
float hH = Triangle.Highest.Depth;
|
||||
float hM = Triangle.Middle.Depth;
|
||||
float hL = Triangle.Lowest.Depth;
|
||||
FVertexData V1 = Triangle.V1;
|
||||
FVertexData V2 = Triangle.V2;
|
||||
FVertexData V3 = Triangle.V3;
|
||||
TArray<FVertexData> Vertices = {V1, V2, V3};
|
||||
Vertices.Sort();
|
||||
V1 = Vertices[0];
|
||||
V2 = Vertices[1];
|
||||
V3 = Vertices[2];
|
||||
|
||||
FVector H = V3.GlobalPosition;
|
||||
FVector M = V2.GlobalPosition;
|
||||
FVector L = V1.GlobalPosition;
|
||||
float hH = V3.Depth;
|
||||
float hM = V2.Depth;
|
||||
float hL = V1.Depth;
|
||||
|
||||
FVector LM = M - L;
|
||||
float tM = -hL/(hM - hL);
|
||||
@ -214,7 +246,7 @@ void UBuoyancyComponent::ProcessTriangles(TArray<FTriangleData>& Triangles)
|
||||
FVector LJH = tH * LH;
|
||||
FVector JH = LJH + L;
|
||||
|
||||
SubmergedTriangles.Add(FTriangleData(JH, JM, L));
|
||||
SubmergedTriangles.Add(FTriangleData(L, JH, JM, Ocean->GetOceanHeight()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,13 @@ AShipBase::AShipBase()
|
||||
|
||||
ShipMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipMesh"));
|
||||
ShipMesh->SetupAttachment(RootComponent);
|
||||
UPrimitiveComponent* ShipMeshAsPrim = Cast<UPrimitiveComponent>(ShipMesh);
|
||||
if(ShipMeshAsPrim)
|
||||
{
|
||||
ShipMeshAsPrim->SetSimulatePhysics(true);
|
||||
ShipMeshAsPrim->SetMassOverrideInKg(NAME_None, 800.0f, true);
|
||||
ShipMeshAsPrim->SetLinearDamping(0.05f);
|
||||
}
|
||||
|
||||
BuoyancyComp = CreateDefaultSubobject<UBuoyancyComponent>(TEXT("BuoyancyComponent"));
|
||||
}
|
||||
|
@ -4,14 +4,17 @@
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "Game/SOCGameState.h"
|
||||
|
||||
#include "BuoyancyComponent.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
USTRUCT(BlueprintType)
|
||||
struct FVertexData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FVector Position;
|
||||
FVector GlobalPosition;
|
||||
|
||||
// depth of the vertex above the surface of the water
|
||||
// negative value means the vertex is submerged
|
||||
float Depth;
|
||||
@ -22,19 +25,19 @@ struct FVertexData
|
||||
|
||||
FVertexData(FVector Position)
|
||||
{
|
||||
this->Position = Position;
|
||||
this->GlobalPosition = Position;
|
||||
Depth = 0.0f;
|
||||
}
|
||||
|
||||
FVertexData(FVector Position, float Depth)
|
||||
{
|
||||
this->Position = Position;
|
||||
this->GlobalPosition = Position;
|
||||
this->Depth = Depth;
|
||||
}
|
||||
|
||||
void CalculateDepth(float SurfaceHeight)
|
||||
{
|
||||
Depth = Position.Z - SurfaceHeight;
|
||||
Depth = GlobalPosition.Z - SurfaceHeight;
|
||||
}
|
||||
|
||||
bool operator< (const FVertexData& rhs) const
|
||||
@ -43,38 +46,61 @@ struct FVertexData
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
USTRUCT(BlueprintType)
|
||||
struct FTriangleData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FVertexData V1; // lowest
|
||||
FVertexData V2; // middle
|
||||
FVertexData V3; // highest
|
||||
|
||||
FVertexData Highest;
|
||||
FVertexData Middle;
|
||||
FVertexData Lowest;
|
||||
FVector Center;
|
||||
|
||||
float DistanceToSurface;
|
||||
|
||||
FVector Normal;
|
||||
|
||||
float Area;
|
||||
|
||||
FTriangleData() {}
|
||||
|
||||
FTriangleData(FVertexData V1, FVertexData V2, FVertexData V3)
|
||||
FTriangleData(const FVertexData V1, const FVertexData V2, const FVertexData V3, float OceanHeight)
|
||||
{
|
||||
TArray<FVertexData> Vertices = {V1, V2, V3};
|
||||
Vertices.Sort();
|
||||
Lowest = Vertices[0];
|
||||
Middle = Vertices[1];
|
||||
Highest = Vertices[2];
|
||||
}
|
||||
this->V1 = V1;
|
||||
this->V2 = V2;
|
||||
this->V3 = V3;
|
||||
|
||||
int32 GetNumSubmergedVertices()
|
||||
Center = (V1.GlobalPosition + V2.GlobalPosition + V3.GlobalPosition) / 3.0f;
|
||||
|
||||
DistanceToSurface = FMath::Abs(OceanHeight - Center.Z);
|
||||
|
||||
Normal = FVector::CrossProduct(V2.GlobalPosition - V1.GlobalPosition, V3.GlobalPosition - V1.GlobalPosition);
|
||||
Normal.Normalize();
|
||||
|
||||
// Heron's formula
|
||||
float V12 = FVector::Distance(V1.GlobalPosition, V2.GlobalPosition);
|
||||
float V23 = FVector::Distance(V2.GlobalPosition, V3.GlobalPosition);
|
||||
float V13 = FVector::Distance(V1.GlobalPosition, V3.GlobalPosition);
|
||||
|
||||
// Half Triangle Perimeter
|
||||
float S = (V12 + V23 + V13) / 2.0f;
|
||||
|
||||
Area = FMath::Sqrt(S * (S - V12) * (S - V23) * (S - V13));
|
||||
}
|
||||
|
||||
int32 GetNumSubmergedVertices() const
|
||||
{
|
||||
int32 result = 0;
|
||||
if(Highest.Depth < 0.0f)
|
||||
if(V3.Depth < 0.0f)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
if(Middle.Depth < 0.0f)
|
||||
if(V2.Depth < 0.0f)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
if(Lowest.Depth < 0.0f)
|
||||
if(V1.Depth < 0.0f)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
@ -90,13 +116,15 @@ class SEAOFCROOKS_API UBuoyancyComponent : public UActorComponent
|
||||
public:
|
||||
// Sets default values for this component's properties
|
||||
UBuoyancyComponent();
|
||||
|
||||
|
||||
protected:
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
UStaticMesh* VolumeMesh;
|
||||
|
||||
UPROPERTY()
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
TArray<FTriangleData> SubmergedTriangles;
|
||||
|
||||
AOcean* Ocean;
|
||||
|
||||
// Called when the game starts
|
||||
virtual void BeginPlay() override;
|
||||
@ -106,6 +134,8 @@ public:
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
private:
|
||||
UPrimitiveComponent* VolumeAsPrimComp;
|
||||
|
||||
int32 GetNumTriangles();
|
||||
|
||||
TArray<FVertexData> GetVertexPositions();
|
||||
|
@ -8,7 +8,7 @@ public class SeaOfCrooks : ModuleRules
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "RenderCore", "RHI" });
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ProceduralMeshComponent", "RenderCore", "RHI" });
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { });
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user