public static Vector3 GetTriangleCenter(VertexInfo vi1, VertexInfo vi2, VertexInfo vi3, int triangleType) { Vector3 v1 = vi1.globalVertex; Vector3 v2 = vi2.globalVertex; Vector3 v3 = vi3.globalVertex; if (triangleType == 0) { // vi1 is upside vertex and vi2, vi3 are horizontal downside vertices float z0 = vi1.height; float h = vi2.height - vi1.height; float tCenter = (4 * z0 + 3 * h) / (6 * z0 + 4 * h); Vector3 v1ToMid = (v2 + v3) / 2f - v1; return(v1 + v1ToMid * tCenter); } else if (triangleType == 1) { // vi1, vi2 are horizontal upside vertices and vi3 is downside vertex float z0 = vi1.height; float h = vi3.height - vi1.height; float tCenter = (2 * z0 + h) / (6 * z0 + 2 * h); Vector3 v3ToMid = (v1 + v2) / 2f - v3; return(v3 + v3ToMid * tCenter); } else { return((v1 + v2 + v3) / 3f); } }
private float CuttingAlgorithmOneAbove(VertexInfo top, VertexInfo mid, VertexInfo bottom, int triangleIndex) { float submergedArea = 0f; float tPointCutTB = -bottom.height / (top.height - bottom.height); Vector3 pointCutTB = bottom.globalVertex + (top.globalVertex - bottom.globalVertex) * tPointCutTB; VertexInfo cutTB = new VertexInfo { clockwiseOrder = -1, globalVertex = pointCutTB, height = WaterPatch.instance.DistanceToWater(pointCutTB, timeStamp), }; float tPointCutTM = -mid.height / (top.height - mid.height); Vector3 pointCutTM = mid.globalVertex + (top.globalVertex - mid.globalVertex) * tPointCutTM; VertexInfo cutTM = new VertexInfo { clockwiseOrder = -1, globalVertex = pointCutTM, height = WaterPatch.instance.DistanceToWater(pointCutTM, timeStamp), }; if ((top.clockwiseOrder + 1) % 3 == mid.clockwiseOrder) { // downLeft: bottom, downRight: mid cutTB.clockwiseOrder = (mid.clockwiseOrder + 1) % 3; cutTM.clockwiseOrder = (cutTB.clockwiseOrder + 1) % 3; } else { // downLeft: mid, downRight: bottom cutTM.clockwiseOrder = (mid.clockwiseOrder + 1) % 3; cutTB.clockwiseOrder = (cutTM.clockwiseOrder + 1) % 3; } VertexInfo[] sortingVertices = new VertexInfo[] { mid, cutTB, cutTM }; Array.Sort(sortingVertices); submergedArea += CuttingAlgorithmHorizontal(sortingVertices[0], sortingVertices[1], sortingVertices[2], triangleIndex); if ((top.clockwiseOrder + 1) % 3 == mid.clockwiseOrder) { // downLeft: bottom, downRight: mid bottom.clockwiseOrder = (mid.clockwiseOrder + 1) % 3; cutTB.clockwiseOrder = (bottom.clockwiseOrder + 1) % 3; } else { // downLeft: mid, downRight: bottom cutTB.clockwiseOrder = (mid.clockwiseOrder + 1) % 3; bottom.clockwiseOrder = (cutTB.clockwiseOrder + 1) % 3; } sortingVertices = new VertexInfo[] { mid, cutTB, bottom }; Array.Sort(sortingVertices); submergedArea += CuttingAlgorithmHorizontal(sortingVertices[0], sortingVertices[1], sortingVertices[2], triangleIndex); return(submergedArea); }
private float CuttingAlgorithmTwoAbove(VertexInfo top, VertexInfo mid, VertexInfo bottom, int triangleIndex) { float tPointCutTB = -bottom.height / (top.height - bottom.height); Vector3 pointCutTB = bottom.globalVertex + (top.globalVertex - bottom.globalVertex) * tPointCutTB; VertexInfo cutTB = new VertexInfo { clockwiseOrder = -1, globalVertex = pointCutTB, height = WaterPatch.instance.DistanceToWater(pointCutTB, timeStamp), }; float tPointCutMB = -bottom.height / (mid.height - bottom.height); Vector3 PointCutMB = bottom.globalVertex + (mid.globalVertex - bottom.globalVertex) * tPointCutMB; VertexInfo cutMB = new VertexInfo { clockwiseOrder = -1, globalVertex = PointCutMB, height = WaterPatch.instance.DistanceToWater(PointCutMB, timeStamp), }; if ((top.clockwiseOrder + 1) % 3 == mid.clockwiseOrder) { // downLeft: bottom, downRight: mid cutTB.clockwiseOrder = (bottom.clockwiseOrder + 1) % 3; cutMB.clockwiseOrder = (cutTB.clockwiseOrder + 1) % 3; } else { // downLeft: mid, downRight: bottom cutMB.clockwiseOrder = (bottom.clockwiseOrder + 1) % 3; cutTB.clockwiseOrder = (cutMB.clockwiseOrder + 1) % 3; } if (cutTB.height > cutMB.height) { return(CuttingAlgorithmHorizontal(cutTB, cutMB, bottom, triangleIndex)); } else { return(CuttingAlgorithmHorizontal(cutMB, cutTB, bottom, triangleIndex)); } }
public TriangleInfo(VertexInfo vi1, VertexInfo vi2, VertexInfo vi3, int triangleType, Rigidbody rB, float timeStamp) { Vector3 v1 = vi1.globalVertex; Vector3 v2 = vi2.globalVertex; Vector3 v3 = vi3.globalVertex; this.center = WaterInteractionUtils.GetTriangleCenter(vi1, vi2, vi3, triangleType); // beause of simplification. center distance can be positive in submerged triangle // if height is positive, don't add to force this.height = WaterPatch.instance.DistanceToWater(this.center, timeStamp); this.normal = Vector3.Cross(v2 - v1, v3 - v1).normalized; this.velocity = WaterInteractionUtils.GetTriangleVelocity(this.center, rB); if (this.velocity.magnitude < 0.0001f) { this.cosine = 0; } else { this.cosine = Vector3.Dot(this.velocity, this.normal) / this.velocity.magnitude; } this.area = WaterInteractionUtils.GetTriangleArea(v1, v2, v3); }
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); }