public static Vector3 BuoyancyForce(float densityOfWater, TriangleInfo triangle) { Vector3 buoyancyForce = densityOfWater * Physics.gravity.y * -1 * triangle.height * triangle.area * triangle.normal; // The vertical component of the hydrostatic forces don't cancel out but the horizontal do buoyancyForce.x = 0f; buoyancyForce.z = 0f; return(buoyancyForce); }
public static Vector3 PressureDragForce(TriangleInfo triangle, float referenceVelocity, float pdCoefficient1, float pdCoefficient2, float pdFallOffPower, float sdCoefficient1, float sdCoefficient2, float sdFallOffPower) { float speed = triangle.velocity.magnitude / referenceVelocity; float cosine = triangle.cosine; if (cosine > 0) { return(-1 * (pdCoefficient1 * speed + pdCoefficient2 * speed * speed) * triangle.area * Mathf.Pow(cosine, pdFallOffPower) * triangle.normal); } else { return((sdCoefficient1 * speed + sdCoefficient2 * speed * speed) * triangle.area * Mathf.Pow(-cosine, sdFallOffPower) * triangle.normal); } }
private float CuttingAlgorithmHorizontal(VertexInfo top, VertexInfo mid, VertexInfo bottom, int triangleIndex) { if (top.height - mid.height < epsilon) { int triangleType = (mid.height - bottom.height < epsilon) ? 2 : 1; TriangleInfo triangle; if ((top.clockwiseOrder + 1) % 3 == mid.clockwiseOrder) { triangle = new TriangleInfo(top, mid, bottom, triangleType, Rigidbody3d, timeStamp); } else { triangle = new TriangleInfo(mid, top, bottom, triangleType, Rigidbody3d, timeStamp); } TriangleBufferIndices.Add(triangleIndex); SubmergedTriangles.Add(triangle); return(triangle.area); } else if (mid.height - bottom.height < epsilon) { TriangleInfo triangle; if ((top.clockwiseOrder + 1) % 3 == mid.clockwiseOrder) { triangle = new TriangleInfo(top, mid, bottom, 0, Rigidbody3d, timeStamp); } else { triangle = new TriangleInfo(top, bottom, mid, 0, Rigidbody3d, timeStamp); } TriangleBufferIndices.Add(triangleIndex); SubmergedTriangles.Add(triangle); return(triangle.area); } float tPointCutTB = (mid.height - bottom.height) / (top.height - bottom.height); Vector3 pointCutTB = bottom.globalVertex + (top.globalVertex - bottom.globalVertex) * tPointCutTB; VertexInfo cutTB = new VertexInfo { clockwiseOrder = -1, // no more use globalVertex = pointCutTB, height = WaterPatch.instance.DistanceToWater(pointCutTB, timeStamp), }; TriangleInfo upside, downside; if ((top.clockwiseOrder + 1) % 3 == mid.clockwiseOrder) { // downLeft: bottom, downRight: mid upside = new TriangleInfo(top, mid, cutTB, 0, Rigidbody3d, timeStamp); downside = new TriangleInfo(cutTB, mid, bottom, 1, Rigidbody3d, timeStamp); } else { // downLeft: mid, downRight: bottom upside = new TriangleInfo(top, cutTB, mid, 0, Rigidbody3d, timeStamp); downside = new TriangleInfo(mid, cutTB, bottom, 1, Rigidbody3d, timeStamp); } TriangleBufferIndices.Add(triangleIndex); TriangleBufferIndices.Add(triangleIndex); SubmergedTriangles.Add(upside); SubmergedTriangles.Add(downside); return(upside.area + downside.area); }
public static Vector3 ViscousWaterResistance(float densityOfWater, float viscosityCoefficient, TriangleInfo triangle) { Vector3 velocity = triangle.velocity; Vector3 normal = triangle.normal; Vector3 tangentialVelocity = velocity - Vector3.Dot(velocity, normal) * normal; tangentialVelocity *= -1; tangentialVelocity.Normalize(); return(0.5f * densityOfWater * viscosityCoefficient * triangle.area * velocity.magnitude * velocity.magnitude * tangentialVelocity); }
public static Vector3 SlammingForce(TriangleBuffer previousBuffer, TriangleBuffer currentBuffer, TriangleInfo triangle, float maxAcceleration, float rampUpPower, float totalMass, float totalArea) { if (triangle.cosine < 0f) { return(Vector3.zero); } Vector3 currentDeltaVolume = currentBuffer.submergedArea * currentBuffer.velocity; Vector3 previousDeltaVolume = previousBuffer.submergedArea * previousBuffer.velocity; Vector3 acceleration = (currentDeltaVolume - previousDeltaVolume) / (currentBuffer.originalArea * Time.fixedDeltaTime); Vector3 stoppingForce = totalMass * triangle.velocity * (2f * triangle.area / totalArea); float realAcceleration = Mathf.Clamp01(acceleration.magnitude / maxAcceleration); return(-1 * Mathf.Pow(realAcceleration, rampUpPower) * triangle.cosine * stoppingForce); }
private void CalculateForce() { float zMin = float.MaxValue; float zMax = float.MinValue; for (int i = 0; i < triangleBuilder.SubmergedTriangles.Count; ++i) { TriangleInfo triangle = triangleBuilder.SubmergedTriangles[i]; if (triangle.center.z < zMin) { zMin = triangle.center.z; } if (triangle.center.z > zMax) { zMax = triangle.center.z; } } float logRigidbodyVelocity = Mathf.Log10(Rigidbody3d.velocity.magnitude); float travelLengthScaleFactor = Mathf.Log10(zMax - zMin) * 2; for (int i = 0; i < triangleBuilder.SubmergedTriangles.Count; ++i) { TriangleInfo triangle = triangleBuilder.SubmergedTriangles[i]; if (triangle.height > 0f) { continue; } float lookUpKey = (triangle.center.z - zMin) / (zMax - zMin); float logFluidTravelLength = curveLookUpTable.LookUp(lookUpKey) * travelLengthScaleFactor; float viscosityCoefficient = WaterInteractionUtils.CalculateViscosityCoefficient(logRigidbodyVelocity, logFluidTravelLength, logViscosity); int TriangleBufferIndex = triangleBuilder.TriangleBufferIndices[i]; Vector3 buoyancyForce = WaterInteractionUtils.BuoyancyForce(densityOfWater, triangle); Vector3 viscousWaterResistance = WaterInteractionUtils.ViscousWaterResistance(densityOfWater, viscosityCoefficient, triangle); Vector3 pressureDragForce = WaterInteractionUtils.PressureDragForce(triangle, referenceSpeed, pdCoefficient1, pdCoefficient2, pdFallOffPower, sdCoefficient1, sdCoefficient2, sdFallOffPower); Vector3 slammingForce = WaterInteractionUtils.SlammingForce(triangleBuilder.PreviousBuffers[TriangleBufferIndex], triangleBuilder.CurrentBuffers[TriangleBufferIndex], triangle, maxAcceleration, smRampUpPower, Rigidbody3d.mass, TotalArea); Vector3 netForce = Vector3.zero; if (debugBuoyancyForce) { netForce += buoyancyForce; } if (debugViscousWaterResistance) { netForce += viscousWaterResistance; } if (debugPressureDrag) { netForce += pressureDragForce; } if (debugSlammingForce) { netForce += slammingForce; } Rigidbody3d.AddForceAtPosition(netForce, triangle.center); // Debug.DrawRay(triangle.center, slammingForce, Color.white); // Debug.DrawRay(triangle.center, triangle.normal, Color.white); // Debug.DrawRay(triangle.center, buoyancyForce, Color.blue); // Debug.DrawRay(triangle.center, viscousWaterResistance, Color.green); } }