Advertisement
Guest User

BuoyancyComponent.cpp

a guest
Mar 26th, 2015
383
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.35 KB | None | 0 0
  1. ################  BuoyancyComponent.CPP   ############
  2.  
  3. #include "OceanPluginPrivatePCH.h"
  4. #include "BuoyancyComponent.h"
  5.  
  6.  
  7. UBuoyancyComponent::UBuoyancyComponent(const class FObjectInitializer& PCIP)
  8.     : Super(PCIP) {
  9.     //Defaults
  10.     //MeshDensity = 600.0f; //Nsomnnia >> Commented this out cause its now in the struct and shouldnt need to be initilized
  11.     FluidDensity = 1025.0f;
  12.     TestPointRadius = 10.0f;
  13.     FluidLinearDamping = 1.0f;
  14.     FluidAngularDamping = 1.0f;
  15.  
  16.     VelocityDamper = FVector(0.1, 0.1, 0.1);
  17.     MaxUnderwaterVelocity = 1000.f;
  18. }
  19.  
  20. void UBuoyancyComponent::InitializeComponent()
  21. {
  22.     Super::InitializeComponent();
  23.  
  24.     // If no OceanManager is defined auto-detect
  25.     if (!OceanManager)
  26.     {
  27.         for (TActorIterator<AOceanManager> ActorItr(GetWorld()); ActorItr; ++ActorItr)
  28.         {
  29.             OceanManager = Cast<AOceanManager>(*ActorItr);
  30.             break;
  31.         }
  32.     }
  33.  
  34.     TestPointRadius = abs(TestPointRadius);
  35.  
  36.     //Signed based on gravity, just in case we need an upside down world
  37.     _SignedRadius = FMath::Sign(GetGravityZ()) * TestPointRadius;
  38.  
  39.     _baseLinearDamping = UpdatedPrimitive->GetLinearDamping();
  40.     _baseAngularDamping = UpdatedPrimitive->GetAngularDamping();
  41. }
  42.  
  43. void UBuoyancyComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
  44. {
  45.     if (!OceanManager) return;
  46.  
  47.     if (!UpdatedComponent->IsSimulatingPhysics())
  48.     {
  49.         FVector waveHeight = OceanManager->GetWaveHeightValue(UpdatedComponent->GetComponentLocation());
  50.         UpdatedPrimitive->SetWorldLocation(FVector(UpdatedComponent->GetComponentLocation().X, UpdatedComponent->GetComponentLocation().Y, waveHeight.Z), true);
  51.         return;
  52.     }
  53.  
  54.     float TotalPoints = TestPoints.Num();
  55.     if (TotalPoints < 1) return;
  56.  
  57.     int PointsUnderWater = 0;
  58.     FTransform transform = UpdatedComponent->GetComponentTransform();
  59.  
  60.     for (int pointIndex = 0; pointIndex < TotalPoints; pointIndex++)
  61.     {
  62.         bool isUnderwater = false;
  63.         FBuoyancyTK testPoint = TestPoints[pointIndex]; //Nsomnia >> Changed FVector to FBuoyancyTestPointTK
  64.         FVector worldTestPoint = transform.TransformPosition(testPoint.Location);
  65.         float waveHeight = OceanManager->GetWaveHeightValue(worldTestPoint).Z;
  66.  
  67.         //If test point radius is touching water add buoyancy force
  68.         if (waveHeight > (worldTestPoint.Z + _SignedRadius))
  69.         {
  70.             PointsUnderWater++;
  71.             isUnderwater = true;
  72.  
  73.             float DepthMultiplier = (waveHeight - (worldTestPoint.Z + _SignedRadius)) / (TestPointRadius * 2);
  74.             DepthMultiplier = FMath::Clamp(DepthMultiplier, 0.f, 1.f);
  75.  
  76.             /**
  77.             * --------
  78.             * Buoyancy force formula: (Volume(Mass / Density) * Fluid Density * -Gravity) / Total Points * Depth Multiplier
  79.             * --------
  80.             */
  81.             float BuoyancyForceZ = UpdatedPrimitive->GetMass() / MeshDensity * FluidDensity * -GetGravityZ() / TotalPoints * DepthMultiplier;
  82.  
  83.             //Expiremental velocity damping using GetUnrealWorldVelocityAtPoint!
  84.             FVector DampingForce = -GetVelocityAtPoint(UpdatedPrimitive, worldTestPoint) * VelocityDamper * UpdatedPrimitive->GetMass() * DepthMultiplier;
  85.  
  86.             //Add force for this test point
  87.             UpdatedPrimitive->AddForceAtLocation(FVector(DampingForce.X, DampingForce.Y, DampingForce.Z + BuoyancyForceZ), worldTestPoint);
  88.         }
  89.  
  90.         if (DrawDebugPoints)
  91.         {
  92.             FColor DebugColor = FLinearColor(0.8, 0.7, 0.2, 0.8).ToRGBE();
  93.             if (isUnderwater) { DebugColor = FLinearColor(0, 0.2, 0.7, 0.8).ToRGBE(); } //Blue color underwater, yellow out of watter
  94.             DrawDebugSphere(GetWorld(), worldTestPoint, TestPointRadius, 8, DebugColor);
  95.         }
  96.     }
  97.  
  98.     if (ClampMaxVelocity && PointsUnderWater > 0
  99.         && UpdatedPrimitive->GetPhysicsLinearVelocity().Size() > MaxUnderwaterVelocity)
  100.     {
  101.         FVector Velocity = UpdatedPrimitive->GetPhysicsLinearVelocity().GetSafeNormal() * MaxUnderwaterVelocity;
  102.         UpdatedPrimitive->SetPhysicsLinearVelocity(Velocity);
  103.     }
  104.  
  105.     //Update damping based on number of underwater test points
  106.     UpdatedPrimitive->SetLinearDamping(_baseLinearDamping + FluidLinearDamping / TotalPoints * PointsUnderWater);
  107.     UpdatedPrimitive->SetAngularDamping(_baseAngularDamping + FluidAngularDamping / TotalPoints * PointsUnderWater);
  108. }
  109.  
  110. FVector UBuoyancyComponent::GetVelocityAtPoint(UPrimitiveComponent* Target, FVector Point, FName BoneName)
  111. {
  112.     FBodyInstance* BI = Target->GetBodyInstance(BoneName);
  113.     if (BI != NULL && BI->IsValidBodyInstance())
  114.     {
  115.         return BI->GetUnrealWorldVelocityAtPoint(Point);
  116.     }
  117.     return FVector::ZeroVector;
  118. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement