void UVaOceanBuoyancyComponent::PerformWaveReaction(float DeltaTime) { AActor* MyOwner = GetOwner(); if (!UpdatedComponent || MyOwner == NULL) { return; } UPrimitiveComponent* OldPrimitive = Cast<UPrimitiveComponent>(UpdatedComponent); const FVector OldLocation = MyOwner->GetActorLocation(); const FRotator OldRotation = MyOwner->GetActorRotation(); const FVector OldLinearVelocity = OldPrimitive->GetPhysicsLinearVelocity(); const FVector OldAngularVelocity = OldPrimitive->GetPhysicsAngularVelocity(); const FVector OldCenterOfMassWorld = OldLocation + OldRotation.RotateVector(COMOffset); const FVector OwnerScale = MyOwner->GetActorScale(); // XYZ === Throttle, Steering, Rise == Forwards, Sidewards, Upwards FVector X, Y, Z; GetAxes(OldRotation, X, Y, Z); // Process tension dots and get torque from wind/waves for (FVector TensionDot : TensionDots) { // Translate point to world coordinates FVector TensionDotDisplaced = OldRotation.RotateVector(TensionDot + COMOffset); FVector TensionDotWorld = OldLocation + TensionDotDisplaced; // Get point depth float DotAltitude = GetAltitude(TensionDotWorld); // Don't process dots above water if (DotAltitude > 0) { continue; } // Surface normal (not modified!) FVector DotSurfaceNormal = GetSurfaceNormal(TensionDotWorld) * GetSurfaceWavesNum(); // Modify normal with real Z value and normalize it DotSurfaceNormal.Z = GetOceanLevel(TensionDotWorld); DotSurfaceNormal.Normalize(); // Point dynamic pressure [http://en.wikipedia.org/wiki/Dynamic_pressure] // rho = 1.03f for ocean water FVector WaveVelocity = GetWaveVelocity(TensionDotWorld); float DotQ = 0.515f * FMath::Square(WaveVelocity.Size()); FVector WaveForce = FVector(0.0,0.0,1.0) * DotQ /* DotSurfaceNormal*/ * (-DotAltitude) * TensionDepthFactor; // We don't want Z to be affected by DotQ WaveForce.Z /= DotQ; // Scale to DeltaTime to break FPS addiction WaveForce *= DeltaTime; // Apply actor scale WaveForce *= OwnerScale.X;// *OwnerScale.Y * OwnerScale.Z; OldPrimitive->AddForceAtLocation(WaveForce * Mass, TensionDotWorld); } // Static metacentric forces (can be useful on small waves) if (bUseMetacentricForces) { FVector TensionTorqueResult = FVector(0.0f, 0.0f, 0.0f); // Calc recovering torque (transverce) FRotator RollRot = FRotator(0.0f, 0.0f, 0.0f); RollRot.Roll = OldRotation.Roll; FVector MetacenterDisplaced = RollRot.RotateVector(TransverseMetacenter + COMOffset); TensionTorqueResult += X * FVector::DotProduct((TransverseMetacenter - MetacenterDisplaced), FVector(0.0f, -1.0f, 0.0f)) * TensionTorqueRollFactor; // Calc recovering torque (longitude) FRotator PitchRot = FRotator(0.0f, 0.0f, 0.0f); PitchRot.Pitch = OldRotation.Pitch; MetacenterDisplaced = PitchRot.RotateVector(LongitudinalMetacenter + COMOffset); TensionTorqueResult += Y * FVector::DotProduct((LongitudinalMetacenter - MetacenterDisplaced), FVector(1.0f, 0.0f, 0.0f)) * TensionTorquePitchFactor; // Apply torque TensionTorqueResult *= DeltaTime; TensionTorqueResult *= OwnerScale.X;// *OwnerScale.Y * OwnerScale.Z; OldPrimitive->AddTorque(TensionTorqueResult); } }