Пример #1
0
    public static Vector3 CalculateSlammingForce(TriangleData triangle, SlammingForceData slammingData, float slammingForceAmount, float bodyArea, float bodyMass)
    {
        //To capture the response of the fluid to sudden accelerations or penetrations

        //Add slamming if the normal is in the same direction as the velocity (the triangle is not receding from the water)
        //Also make sure thea area is not 0, which it sometimes is for some reason
        if (triangle.cosTheta < 0f || slammingData.originalArea <= 0f)
        {
            return(Vector3.zero);
        }

        //Step 1 - Calculate acceleration
        //Volume of water swept per second
        Vector3 dV          = slammingData.submergedArea * slammingData.velocity;
        Vector3 dV_previous = slammingData.previousSubmergedArea * slammingData.previousVelocity;

        //Calculate the acceleration of the center point of the original triangle (not the current underwater triangle)
        //But the triangle the underwater triangle is a part of
        Vector3 accVec = (dV - dV_previous) / (slammingData.originalArea * Time.fixedDeltaTime);

        //The magnitude of the acceleration
        float acc = accVec.magnitude;

        //Step 2 - Calculate slamming force
        Vector3 F_stop = bodyMass * triangle.velocity * ((2f * triangle.area) / bodyArea);

        float   p             = 2f;
        float   acc_max       = acc;
        Vector3 slammingForce = -Mathf.Pow(Mathf.Clamp01(acc / acc_max), p) * triangle.cosTheta * F_stop * slammingForceAmount;

        return(CheckForceIsValid(slammingForce));
    }
Пример #2
0
    public static Vector3 SlammingForce(SlammingForceData slammingData, TriangleData triangleData, float boatArea, float boatMass)
    {
        if (triangleData.cosTheta < 0f || slammingData.originalArea <= 0f)
        {
            return(Vector3.zero);
        }

        Vector3 dV          = slammingData.submergedArea * slammingData.velocity;
        Vector3 dV_previous = slammingData.previousSubmergedArea * slammingData.previousVelocity;

        Vector3 accVec = (dV - dV_previous) / (slammingData.originalArea * Time.fixedDeltaTime);

        float acc = accVec.magnitude;

        Vector3 F_stop        = boatMass * triangleData.velocity * ((2f * triangleData.area) / boatArea);
        float   p             = 2f;
        float   acc_max       = acc;
        float   slammingCheat = DebugPhysics.current.slammingCheat;
        Vector3 slammingForce = Mathf.Pow(Mathf.Clamp01(acc / acc_max), p) * triangleData.cosTheta * F_stop * slammingCheat;

        slammingForce *= -1f;
        slammingForce  = CheckForceIsValid(slammingForce, "Slamming");
        return(slammingForce);
    }
Пример #3
0
    void AddUnderWaterForces()
    {
        float Cf = BoatPhysicsMath.ResistanceCoefficient(
            rhoWater,
            boatRB.velocity.magnitude,
            modifyBoatMesh.CalculateUnderWaterLength());

        List <SlammingForceData> slammingForceData = modifyBoatMesh.slammingForceData;

        CalculateSlammingVelocities(slammingForceData);

        float boatArea = modifyBoatMesh.boatArea;
        float boatMass = boatRB.mass;

        List <int> indexOfOriginalTriangle = modifyBoatMesh.indexOfOriginalTriangle;

        List <TriangleData> underWaterTriangleData = modifyBoatMesh.underWaterTriangleData;

        for (int i = 0; i < underWaterTriangleData.Count; i++)
        {
            TriangleData triangleData = underWaterTriangleData[i];

            Vector3 forceToAdd = Vector3.zero;

            forceToAdd += BoatPhysicsMath.BuoyancyForce(rhoWater, triangleData);

            forceToAdd += BoatPhysicsMath.ViscousWaterResistanceForce(rhoWater, triangleData, Cf);

            forceToAdd += BoatPhysicsMath.PressureDragForce(triangleData);
            int originalTriangleIndex = indexOfOriginalTriangle[i];

            SlammingForceData slammingData = slammingForceData[originalTriangleIndex];
            forceToAdd += BoatPhysicsMath.SlammingForce(slammingData, triangleData, boatArea, boatMass);
            boatRB.AddForceAtPosition(forceToAdd, triangleData.center);
        }
    }
Пример #4
0
    //Force 3 - Slamming Force (Water Entry Force)
    public static Vector3 SlammingForce(SlammingForceData slammingData, TriangleData triangleData, float boatArea, float boatMass)
    {
        //To capture the response of the fluid to sudden accelerations or penetrations

        //Add slamming if the normal is in the same direction as the velocity (the triangle is not receding from the water)
        //Also make sure thea area is not 0, which it sometimes is for some reason
        if (triangleData.cosTheta < 0f || slammingData.originalArea <= 0f)
        {
            return(Vector3.zero);
        }


        //Step 1 - Calculate acceleration
        //Volume of water swept per second
        Vector3 dV          = slammingData.submergedArea * slammingData.velocity;
        Vector3 dV_previous = slammingData.previousSubmergedArea * slammingData.previousVelocity;

        //Calculate the acceleration of the center point of the original triangle (not the current underwater triangle)
        //But the triangle the underwater triangle is a part of
        Vector3 accVec = (dV - dV_previous) / (slammingData.originalArea * Time.fixedDeltaTime);

        //The magnitude of the acceleration
        float acc = accVec.magnitude;

        //Debug.Log(slammingForceData.originalArea);

        //Step 2 - Calculate slamming force
        // F = clamp(acc / acc_max, 0, 1)^p * cos(theta) * F_stop
        // p - power to ramp up slamming force - should be 2 or more

        // F_stop = m * v * (2A / S)
        // m - mass of the entire boat
        // v - velocity
        // A - this triangle's area
        // S - total surface area of the entire boat

        Vector3 F_stop = boatMass * triangleData.velocity * ((2f * triangleData.area) / boatArea);

        //float p = DebugPhysics.current.p;

        //float acc_max = DebugPhysics.current.acc_max;

        float p = 2f;

        float acc_max = acc;

        float slammingCheat = DebugPhysics.current.slammingCheat;

        Vector3 slammingForce = Mathf.Pow(Mathf.Clamp01(acc / acc_max), p) * triangleData.cosTheta * F_stop * slammingCheat;

        //Vector3 slammingForce = Vector3.zero;

        //Debug.Log(slammingForce);

        //The force acts in the opposite direction
        slammingForce *= -1f;

        slammingForce = CheckForceIsValid(slammingForce, "Slamming");

        return(slammingForce);
    }
Пример #5
0
    //Add all forces that act on the squares below the water
    void AddUnderWaterForces()
    {
        //The resistance coefficient - same for all triangles
        float Cf = BoatPhysicsMath.ResistanceCoefficient(
            rhoWater,
            boatRB.velocity.magnitude,
            modifyBoatMesh.CalculateUnderWaterLength());

        //To calculate the slamming force we need the velocity at each of the original triangles
        List <SlammingForceData> slammingForceData = modifyBoatMesh.slammingForceData;

        CalculateSlammingVelocities(slammingForceData);

        //Need this data for slamming forces
        float boatArea = modifyBoatMesh.boatArea;
        float boatMass = gameObject.GetComponent <Rigidbody>().mass;        //Replace this line with your boat's total mass

        //To connect the submerged triangles with the original triangles
        List <int> indexOfOriginalTriangle = modifyBoatMesh.indexOfOriginalTriangle;

        //Get all triangles
        List <TriangleData> underWaterTriangleData = modifyBoatMesh.underWaterTriangleData;

        for (int i = 0; i < underWaterTriangleData.Count; i++)
        {
            TriangleData triangleData = underWaterTriangleData[i];


            //Calculate the forces
            Vector3 forceToAdd = Vector3.zero;

            //Force 1 - The hydrostatic force (buoyancy)
            //forceToAdd += BoatPhysicsMath.BuoyancyForce(rhoWater, triangleData);

            //Force 2 - Viscous Water Resistance
            forceToAdd += BoatPhysicsMath.ViscousWaterResistanceForce(rhoWater, triangleData, Cf);

            //Force 3 - Pressure drag
            forceToAdd += BoatPhysicsMath.PressureDragForce(triangleData);

            //Force 4 - Slamming force
            //Which of the original triangles is this triangle a part of
            int originalTriangleIndex = indexOfOriginalTriangle[i];

            SlammingForceData slammingData = slammingForceData[originalTriangleIndex];

            forceToAdd += BoatPhysicsMath.SlammingForce(slammingData, triangleData, boatArea, boatMass);
            //Debug.Log(BoatPhysicsMath.SlammingForce(slammingData, triangleData, boatArea, boatMass));

            //Add the forces to the boat
            //Debug.Log("Adding force: " + forceToAdd + " to triangle " + i);
            boatRB.AddForceAtPosition(forceToAdd, triangleData.center);


            //Debug

            //Normal
            //Debug.DrawRay(triangleData.center, triangleData.normal * 3f, Color.white);

            //Buoyancy
            //Debug.DrawRay(triangleData.center, BoatPhysicsMath.BuoyancyForce(rhoWater, triangleData).normalized * -3f, Color.blue, 2f, true);

            //Velocity
            //Debug.DrawRay(triangleCenter, triangleVelocityDir * 3f, Color.black);

            //Viscous Water Resistance
            //Debug.DrawRay(triangleCenter, viscousWaterResistanceForce.normalized * 3f, Color.black);
        }
    }
Пример #6
0
    private void addTriangleForces()
    {
        float underwaterArea = 0;
        float underwaterMinZ = 0, underwaterMaxZ = 0;

        foreach (TriangleData triangle in underwaterTriangles)
        {
            if (triangle.distToWater < 0)
            {
                underwaterArea += triangle.area;
            }

            float z1 = (Quaternion.Inverse(transform.rotation) * (triangle.p1 - bodyMesh.transform.position)).z;
            float z2 = (Quaternion.Inverse(transform.rotation) * (triangle.p2 - bodyMesh.transform.position)).z;
            float z3 = (Quaternion.Inverse(transform.rotation) * (triangle.p3 - bodyMesh.transform.position)).z;
            if (z1 < underwaterMinZ || underwaterMinZ == 0)
            {
                underwaterMinZ = z1;
            }
            if (z2 < underwaterMinZ || underwaterMinZ == 0)
            {
                underwaterMinZ = z2;
            }
            if (z3 < underwaterMinZ || underwaterMinZ == 0)
            {
                underwaterMinZ = z3;
            }
            if (z1 > underwaterMaxZ || underwaterMaxZ == 0)
            {
                underwaterMaxZ = z1;
            }
            if (z2 > underwaterMaxZ || underwaterMaxZ == 0)
            {
                underwaterMaxZ = z2;
            }
            if (z3 > underwaterMaxZ || underwaterMaxZ == 0)
            {
                underwaterMaxZ = z3;
            }
        }

        float underwaterLength = underwaterMaxZ - underwaterMinZ;
        float resistanceCoeff  = ShipForces.ResistanceCoefficient(rigidbody.velocity.magnitude, underwaterLength);

        calculateSlammingVelocities();

        for (int i = 0; i < underwaterTriangles.Count; i++)
        {
            TriangleData triangle = underwaterTriangles[i];

            Vector3 buoyancyForce          = ShipForces.CalculateBuoyancyForce(triangle, waterDensity);
            Vector3 viscousWaterResistance = ShipForces.CalculateViscousWaterResistance(triangle, waterDensity, resistanceCoeff);
            Vector3 pressureDrag           = ShipForces.CalculatePressureDrag(triangle, pressureFalloff, pressureCoeff1, pressureCoeff2, suctionFalloff, suctionCoeff1, suctionCoeff2);

            int originalTriangleIndex       = underwaterTriangleIndices[i];
            SlammingForceData slammingData  = slammingForceData[originalTriangleIndex];
            Vector3           slammingForce = ShipForces.CalculateSlammingForce(triangle, slammingData, slammingForceAmount, bodySurfaceArea, rigidbody.mass);

            Vector3 totalForce = buoyancyForce + viscousWaterResistance + pressureDrag + slammingForce;

            rigidbody.AddForceAtPosition(totalForce, triangle.center);
        }
    }