Boolean ADCPMover_c::VelocityStrAtPoint(WorldPoint3D wp, char *diagnosticStr) { char uStr[32],sStr[32]; double lengthU, lengthS; VelocityRec velocity = {0.,0.}; Boolean useEddyUncertainty = false; double spillStartDepth = 0.; if (moverMap->IAm(TYPE_PTCURMAP)) spillStartDepth = (dynamic_cast<PtCurMap *>(moverMap))->GetSpillStartDepth(); wp.z = spillStartDepth; //velocity = this->GetPatValue(wp.p); velocity = GetVelocityAtPoint(wp); lengthU = sqrt(velocity.u * velocity.u + velocity.v * velocity.v); lengthS = this->refScale * lengthU; StringWithoutTrailingZeros(uStr,lengthU,4); StringWithoutTrailingZeros(sStr,lengthS,4); sprintf(diagnosticStr, " [grid: %s, unscaled: %s m/s, scaled: %s m/s]", this->className, uStr, sStr); return true; }
void UBuoyancyComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { if (!OceanManager || !UpdatedComponent || !UpdatedPrimitive) return; if (!UpdatedComponent->IsSimulatingPhysics()) { FVector waveHeight = OceanManager->GetWaveHeightValue(UpdatedComponent->GetComponentLocation()); UpdatedPrimitive->SetWorldLocation(FVector(UpdatedComponent->GetComponentLocation().X, UpdatedComponent->GetComponentLocation().Y, waveHeight.Z), true); return; } //ApplyUprightConstraint is apparently needed again at first tick for BP-updated components. //TODO: there has to be a better way than this(?), PostInitialize(?) if (!_hasTicked) { _hasTicked = true; ApplyUprightConstraint(); } float TotalPoints = TestPoints.Num(); if (TotalPoints < 1) return; int PointsUnderWater = 0; for (int pointIndex = 0; pointIndex < TotalPoints; pointIndex++) { if (!TestPoints.IsValidIndex(pointIndex)) return; //Array size changed during runtime bool isUnderwater = false; FVector testPoint = TestPoints[pointIndex]; FVector worldTestPoint = UpdatedComponent->GetComponentTransform().TransformPosition(testPoint); float waveHeight = OceanManager->GetWaveHeightValue(worldTestPoint).Z; //If test point radius is touching water add buoyancy force if (waveHeight > (worldTestPoint.Z + _SignedRadius)) { PointsUnderWater++; isUnderwater = true; float DepthMultiplier = (waveHeight - (worldTestPoint.Z + _SignedRadius)) / (TestPointRadius * 2); DepthMultiplier = FMath::Clamp(DepthMultiplier, 0.f, 1.f); //If we have a point density override, use the overriden value insted of MeshDensity float PointDensity = PointDensityOverride.IsValidIndex(pointIndex) ? PointDensityOverride[pointIndex] : MeshDensity; /** * -------- * Buoyancy force formula: (Volume(Mass / Density) * Fluid Density * -Gravity) / Total Points * Depth Multiplier * -------- */ float BuoyancyForceZ = UpdatedPrimitive->GetMass() / PointDensity * FluidDensity * -GetGravityZ() / TotalPoints * DepthMultiplier; //Experimental velocity damping using GetUnrealWorldVelocityAtPoint! FVector DampingForce = -GetVelocityAtPoint(UpdatedPrimitive, worldTestPoint) * VelocityDamper * UpdatedPrimitive->GetMass() * DepthMultiplier; //Wave push force if (EnableWaveForces) { float waveVelocity = FMath::Clamp(GetVelocityAtPoint(UpdatedPrimitive, worldTestPoint).Z, -20.f, 150.f) * (1 - DepthMultiplier); DampingForce += FVector(OceanManager->GlobalWaveDirection.X, OceanManager->GlobalWaveDirection.Y, 0) * UpdatedPrimitive->GetMass() * waveVelocity * WaveForceMultiplier / TotalPoints; } //Add force for this test point UpdatedPrimitive->AddForceAtLocation(FVector(DampingForce.X, DampingForce.Y, DampingForce.Z + BuoyancyForceZ), worldTestPoint); } if (DrawDebugPoints) { FColor DebugColor = FLinearColor(0.8, 0.7, 0.2, 0.8).ToRGBE(); if (isUnderwater) { DebugColor = FLinearColor(0, 0.2, 0.7, 0.8).ToRGBE(); } //Blue color underwater, yellow out of watter DrawDebugSphere(GetWorld(), worldTestPoint, TestPointRadius, 8, DebugColor); } } //Clamp the velocity to MaxUnderwaterVelocity if there is any point underwater if (ClampMaxVelocity && PointsUnderWater > 0 && UpdatedPrimitive->GetPhysicsLinearVelocity().Size() > MaxUnderwaterVelocity) { FVector Velocity = UpdatedPrimitive->GetPhysicsLinearVelocity().GetSafeNormal() * MaxUnderwaterVelocity; UpdatedPrimitive->SetPhysicsLinearVelocity(Velocity); } //Update damping based on number of underwater test points UpdatedPrimitive->SetLinearDamping(_baseLinearDamping + FluidLinearDamping / TotalPoints * PointsUnderWater); UpdatedPrimitive->SetAngularDamping(_baseAngularDamping + FluidAngularDamping / TotalPoints * PointsUnderWater); }