using System.Collections.Generic; using System.Numerics; namespace ACE.Server.Entity { /// /// Represents a 3D triangle for meshes, /// with some methods that operate in 2-space /// public class Triangle { /// /// To avoid storing many redundant vertices, /// only indices into the mesh vertices /// public int[] Indices; /// /// Default constructor /// public Triangle() { Indices = new int[3]; } /// /// Constructs a new triangle from 3 vertex indices /// public Triangle(int a, int b, int c) { Indices = new int[3] { a, b, c }; } /// /// Returns the vertices of the triangle /// public Vector3[] GetVertices(List vertices) { // TODO: out-of-bounds exception return new Vector3[] { vertices[Indices[0]], vertices[Indices[1]], vertices[Indices[2]] }; } /// /// Returns TRUE if point is contained within triangle /// public bool Contains(Vector2 point, List vertices) { var p1 = vertices[Indices[0]]; var p2 = vertices[Indices[1]]; var p3 = vertices[Indices[2]]; // TODO: further optimizations listed // https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle var area = Area(p1, p2, p3); var s = 1.0f / (2 * area) * (p1.Y * p3.X - p1.X * p3.Y + (p3.Y - p1.Y) * point.X + (p1.X - p3.X) * point.Y); if (s < 0) return false; var t = 1.0f / (2 * area) * (p1.X * p2.Y - p1.Y * p2.X + (p1.Y - p2.Y) * point.X + (p2.X - p1.X) * point.Y); if (t < 0 || 1 - s - t < 0) return false; return true; } /// /// Returns the area of the 2D triangle /// public static float Area(Vector3 p1, Vector3 p2, Vector3 p3) { return 0.5f * (-p2.Y * p3.X + p1.Y * (-p2.X + p3.X) + p1.X * (p2.Y - p3.Y) + p2.X * p3.Y); } /// /// Consider the triangle as a plane, /// find the Z-coordinate for a 2D coordinate on the plane /// public float GetZ(List vertices, Vector2 point) { // Reference: // https://social.msdn.microsoft.com/Forums/en-US/1b32dc40-f84d-4365-a677-b59e49d41eb0/how-to-calculate-a-point-on-a-plane-based-on-a-plane-from-3-points Vector3 v1 = new Vector3(); Vector3 v2 = new Vector3(); Vector3 abc = new Vector3(); var p1 = vertices[Indices[0]]; var p2 = vertices[Indices[1]]; var p3 = vertices[Indices[2]]; v1.X = p1.X - p3.X; v1.Y = p1.Y - p3.Y; v1.Z = p1.Z - p3.Z; v2.X = p2.X - p3.X; v2.Y = p2.Y - p3.Y; v2.Z = p2.Z - p3.Z; abc.X = (v1.Y * v2.Z) - (v1.Z * v2.Y); abc.Y = (v1.Z * v2.X) - (v1.X * v2.Z); abc.Z = (v1.X * v2.Y) - (v1.Y * v2.X); float d = (abc.X * p3.X) + (abc.Y * p3.Y) + (abc.Z * p3.Z); float z = (d - (abc.X * point.X) - (abc.Y * point.Y)) / abc.Z; return z; } } }