using UnityEngine; using System.Collections; using System.Collections.Generic; public static class AdvancedMath { public static float TriangleSquare(Vector3 va, Vector3 vb, Vector3 vc){ float a = Vector3.Distance (va, vb); float b = Vector3.Distance (vb, vc); float c = Vector3.Distance (vc, va); float p = (a + b + c) * 0.5f; return Mathf.Sqrt (p * (p - a) * (p - b) * (p - c)); } public static float CircleSegmentChordLength(float r, float angle) { return 2.0f*r*Mathf.Sin(angle*0.5f); } public static float CircleSegmentHeight(float r, float angle) { return r * (1.0f - Mathf.Cos(angle * 0.5f)); } public static Vector3 PrismCenterOfMass(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 normal, float h0, float h1, float h2){ Vector3 a = v0 + normal * (h0 * 0.5f); Vector3 c = v1 + normal * (h1 * 0.5f); Vector3 b = v2 + normal * (h2 * 0.5f); Vector3 f = (a + b + c) / 3.0f; return (h0 * ((3.0f * f + a) / 4.0f) + h1 * ((3.0f * f + c) / 4.0f) + h2 * ((3.0f * f + b) / 4.0f)) / (h0 + h1 + h2); } public static float CylinderVolume(float r, float h){ return Mathf.PI * (r * r) * h; } public static Vector3 TriangleNormal(Vector3 va, Vector3 vb, Vector3 vc){ Vector3 ba = vb - va; Vector3 ca = vc - va; return Vector3.Cross(ba, ca).normalized; } public static Vector3 LineNearestPoint(Vector3 a, Vector3 b, Vector3 p){ Vector3 n = (b - a).normalized; Vector3 pa = p - a; float d = Vector3.Dot (n, pa); return a + n * d; } public static Vector2 LineNearestPoint(Vector2 a, Vector2 b, Vector2 p) { Vector2 n = (b - a).normalized; Vector2 pa = p - a; float d = Vector2.Dot(n, pa); return a + n * d; } public static Vector2 SegmentNearestPoint(Vector2 a, Vector2 b, Vector2 p) { Vector2 n = (b - a); float dist = n.magnitude; n.Normalize(); Vector2 pa = p - a; float d = Vector2.Dot(n, pa); d = Mathf.Clamp(d, 0, dist); return a + n * d; } public static float LineDistance(Vector3 a, Vector3 b, Vector3 p){ Vector3 lp = LineNearestPoint(a, b, p); return Vector3.Distance (lp, p); } public static float Drag(float envDensity, float objVelocity, float dragCoeff, float referenceaArea){ return (envDensity * (objVelocity * objVelocity) * dragCoeff * referenceaArea) * 0.5f; } public static float SphereDrag(float envDensity, float objVelocity, float radius){ return Drag (envDensity, objVelocity, 0.47f, Mathf.PI * (radius * radius)); } public static float BuoyantForce(float objectV, float objectDensity, float envDensity, float g){ return objectV * envDensity * g * ((3.0f * objectDensity) / (envDensity + 2.0f * objectDensity)); } public static float SphereSegmentVolume(float r, float h){ return (Mathf.PI * (h * h) * (3.0f * r - h)) / 3.0f; } public static float SphereVolume(float r){ return (4.0f * Mathf.PI * (r * r * r)) / 3.0f; } public static float SphereSurfaceArea(float r){ return 4.0f * Mathf.PI * (r * r); } public static float PrismVolume(float baseArea, float h){ return baseArea * h; } public static float ConeVolume(float r, float h){ return (Mathf.PI * (r * r) * h) / 3.0f; } public static float PyramidVolume(float baseArea, float h){ return (baseArea * h) / 3.0f; } public static float RightTriangleArea(float a, float b){ return a * b * 0.5f; } public static float MeshVolume(Vector3[] srcVertices, int[] srcIndices, Matrix4x4 tf){ Vector3[] vertices = new Vector3[srcVertices.Length]; vertices[0] = tf.MultiplyPoint3x4(srcVertices[0]); Vector3 vMin = vertices [0]; Vector3 vMax = vertices [0]; for (int i = 1; i < vertices.Length; ++i) { vertices[i] = tf.MultiplyPoint3x4(srcVertices[i]); vMin = Vector3.Min(vMin, vertices[i]); vMax = Vector3.Max(vMax, vertices[i]); } Plane p = new Plane (Vector3.up, vMax + Vector3.up); //split mesh by plane List cuttedTriangles = AdvancedUtils.CutMesh (vertices, srcIndices, p); float totalVolume = 0.0f; for (int i = 0; i < cuttedTriangles.Count; i+=3) { Vector3 v0 = cuttedTriangles[i + 0]; Vector3 v1 = cuttedTriangles[i + 1]; Vector3 v2 = cuttedTriangles[i + 2]; Vector3 normal = AdvancedMath.TriangleNormal(v0, v1, v2); float sign = Mathf.Sign(Vector3.Dot (normal, p.normal)); float h0 = p.GetDistanceToPoint(v0); float h1 = p.GetDistanceToPoint(v1); float h2 = p.GetDistanceToPoint(v2); float avgH = (h0 + h1 + h2) / 3.0f; Vector3 vp0 = v0 - p.normal * h0; Vector3 vp1 = v1 - p.normal * h1; Vector3 vp2 = v2 - p.normal * h2; float triangleSquare = AdvancedMath.TriangleSquare(vp0, vp1, vp2); float prismVolume = AdvancedMath.PrismVolume(triangleSquare, avgH) * sign; totalVolume += prismVolume; } return totalVolume; } }