The Mesh Face
The Atomic Surface
While a Polygon is an abstract mathematical boundary that implies an area, a Mesh Face is the absolute simplest form of physical surface in a computer. It is the atomic pixel of 3D geometry.
The Illusion of Smoothness: There are no true curves on a computer screen. Every smooth character in a video game is actually made of thousands of tiny, perfectly flat triangles or quadrilaterals.
Memory & Storage
A Mesh Face does not store coordinate data itself. Instead, it stores an array of integer Indices that point to a master list of Verticesstored by the parent Mesh.
1class MeshFace:2 """3 Represents a single triangle or quad face in a mesh.4 Stores indices pointing to a master vertex array.5 """6 def __init__(self, a: int, b: int, c: int, d: int = None):7 self.A = int(a)8 self.B = int(b)9 self.C = int(c)10 self.D = int(d) if d is not None else int(c)
Face Normal:
1def MeshFaceNormal(ptA: 'Point3d', ptB: 'Point3d', ptC: 'Point3d') -> 'Vector3d':2 """Calculates the normal vector of a triangular face."""34 # 1. Create two edge vectors5 edge1 = ptB - ptA6 edge2 = ptC - ptA78 # 2. Compute cross product9 normal = Vector3d.CrossProduct(edge1, edge2)1011 # 3. Unitize the normal (make length 1)12 normal.Unitize()1314 return normal
Winding & Flip:
1class MeshFace:2 def reverse(self) -> None:3 """Reverses winding order, flipping the face normal."""4 if self.is_triangle:5 self.A, self.C = self.C, self.A6 else:7 self.A, self.D = self.D, self.A8 self.B, self.C = self.C, self.B
Face Area:
1def MeshFaceArea(ptA: 'Point3d', ptB: 'Point3d', ptC: 'Point3d') -> float:2 """Calculates the area of a triangular face."""34 # 1. Create two edge vectors5 edge1 = ptB - ptA6 edge2 = ptC - ptA78 # 2. The magnitude of the cross product of two vectors9 # equals the area of the parallelogram they form.10 cross = Vector3d.CrossProduct(edge1, edge2)11 parallelogram_area = cross.Length1213 # 3. Triangle area is half of the parallelogram area14 return parallelogram_area * 0.5
Face Centroid:
1def get_face_centroid(vertices: list[Point3d]) -> Point3d:2 # The centroid of a face is the mathematical average of its vertex coordinates.3 n = len(vertices)4 if n == 0:5 return Point3d.Origin67 sum_x = sum(pt.X for pt in vertices)8 sum_y = sum(pt.Y for pt in vertices)9 sum_z = sum(pt.Z for pt in vertices)1011 return Point3d(sum_x / n, sum_y / n, sum_z / n)
Move Vertices:
A, the face stretches to accommodate.1# You cannot do: face.Move(vector)2# You must do:3parent_mesh.Vertices[face.A] += motion_vector4parent_mesh.Vertices[face.B] += motion_vector5# ... and so on for each index
Scale Vertices:
1# Scale all vertices referenced by this face from the origin2for idx in [face.A, face.B, face.C, face.D]:3 parent_mesh.Vertices[idx] *= scale_factor
Rotate Vertices:
1# Rotate vertex positions around a center point2for idx in [face.A, face.B, face.C, face.D]:3 v = parent_mesh.Vertices[idx]4 dx = v.X - center.X5 dy = v.Y - center.Y6 v.X = center.X + dx * cos(angle) - dy * sin(angle)7 v.Y = center.Y + dx * sin(angle) + dy * cos(angle)
Non-Planar Quad:
1def IsNonPlanar(self, vertices: list, tolerance: float = 0.001) -> bool:2 """A quad is non-planar if vertex D deviates from plane ABC."""3 if self.IsTriangle: return False45 a, b, c, d = [vertices[idx] for idx in [self.A, self.B, self.C, self.D]]6 normal = (b - a).CrossProduct(c - a)7 return abs(normal * (d - a)) > tolerance
Barycentric Coordinates:
P relative to a triangle's vertices (A, B, C). Any point on the plane is represented as P = u*A + v*B + w*C where u + v + w = 1.0. If all coordinates are between 0 and 1, the point is inside the triangle.1def calculate_barycentric(ptA: Point3d, ptB: Point3d, ptC: Point3d, ptP: Point3d):2 # Calculates barycentric coordinates (u, v, w) of point P relative to triangle ABC.3 v0 = ptB - ptA4 v1 = ptC - ptA5 v2 = ptP - ptA67 d00 = v0 * v08 d01 = v0 * v19 d11 = v1 * v110 d20 = v2 * v011 d21 = v2 * v11213 denom = d00 * d11 - d01 * d0114 if abs(denom) < 1e-9:15 return 0.0, 0.0, 0.0 # Collinear/degenerate triangle1617 v = (d11 * d20 - d01 * d21) / denom18 w = (d00 * d21 - d01 * d20) / denom19 u = 1.0 - v - w2021 return u, v, w
GetConnectedFaces:
1def get_adjacent_faces(faces: list[list[int]], face_idx: int) -> list[int]:2 """Returns indices of faces sharing an edge with the face at face_idx."""3 target_face = faces[face_idx]4 adjacent = []56 # Helper to get edges of a face (pairs of vertices)7 def get_edges(face):8 n = len(face)9 return {frozenset([face[i], face[(i + 1) % n]]) for i in range(n)}1011 target_edges = get_edges(target_face)1213 for idx, face in enumerate(faces):14 if idx == face_idx:15 continue16 # If face shares any edge with target face17 face_edges = get_edges(face)18 if target_edges.intersection(face_edges):19 adjacent.append(idx)2021 return adjacent
Aspect Ratio:
1# Manual calculation based on edge lengths23def AspectRatio(face: MeshFace, mesh: Mesh) -> float:4 """Calculates the ratio between the longest and shortest edge."""5 # Get physical 3D vertices6 verts = [mesh.Vertices[i] for i in [face.A, face.B, face.C, face.D] if i != face.C]7 if face.IsQuad:8 verts = [mesh.Vertices[i] for i in [face.A, face.B, face.C, face.D]]9 else:10 verts = [mesh.Vertices[i] for i in [face.A, face.B, face.C]]1112 # Calculate all edge lengths13 edges = [v2.DistanceTo(v1) for v1, v2 in zip(verts, verts[1:] + [verts[0]])]1415 # Aspect Ratio = Longest Edge / Shortest Edge16 return max(edges) / min(edges)
Circumcircle:
1def Circumcircle(A: Point3d, B: Point3d, C: Point3d) -> Circle:2 """Finds the unique circle passing through all 3 vertices."""3 # Midpoints of AB and BC4 midAB = (A + B) * 0.55 midBC = (B + C) * 0.567 # Directions8 dirAB = B - A9 dirBC = C - B1011 # Perpendicular normals in 2D plane12 perpAB = Vector3d(-dirAB.Y, dirAB.X, 0).Unitize()13 perpBC = Vector3d(-dirBC.Y, dirBC.X, 0).Unitize()1415 # 2D line intersection of perpendicular bisectors16 x1, y1 = midAB.X, midAB.Y17 x2, y2 = midAB.X + perpAB.X, midAB.Y + perpAB.Y18 x3, y3 = midBC.X, midBC.Y19 x4, y4 = midBC.X + perpBC.X, midBC.Y + perpBC.Y2021 denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)22 if abs(denom) < 1e-9:23 return None2425 cx = ((x1*y2 - y1*x2)*(x3 - x4) - (x1 - x2)*(x3*y4 - y3*x4)) / denom26 cy = ((x1*y2 - y1*x2)*(y3 - y4) - (y1 - y2)*(x3*y4 - y3*x4)) / denom2728 center = Point3d(cx, cy, 0)29 radius = (center - A).Length30 return Circle(center, radius)
Triangulate:
1def triangulate(face: MeshFace) -> list[tuple[int, int, int]]:2 """Splits a face into triangular faces (tuples of 3 vertex indices)."""3 if face.IsTriangle:4 return [(face.A, face.B, face.C)]56 # Quad face (A, B, C, D) splits into (A, B, C) and (A, C, D)7 return [(face.A, face.B, face.C), (face.A, face.C, face.D)]
Closest Point:
1def closest_point(face: MeshFace, vertices: list[Point3d], test_pt: Point3d) -> Point3d:2 """Projects a point onto the surface of a face."""3 pts = [vertices[face.A], vertices[face.B], vertices[face.C]]45 def closest_pt_on_tri(a, b, c, p):6 ab, ac, ap = b - a, c - a, p - a7 d1, d2 = ab.dot(ap), ac.dot(ap)8 if d1 <= 0 and d2 <= 0: return a910 bp = p - b11 d3, d4 = ab.dot(bp), ac.dot(bp)12 if d3 >= 0 and d4 <= d3: return b1314 vc = d1 * d4 - d3 * d215 if vc <= 0 and d1 >= 0 and d3 <= 0:16 return a + ab * (d1 / (d1 - d3))1718 cp = p - c19 d5, d6 = ab.dot(cp), ac.dot(cp)20 if d6 >= 0 and d5 <= d6: return c2122 vb = d5 * d2 - d1 * d623 if vb <= 0 and d2 >= 0 and d6 <= 0:24 return a + ac * (d2 / (d2 - d6))2526 va = d3 * d6 - d5 * d427 if va <= 0 and (d4 - d3) >= 0 and (d5 - d6) >= 0:28 return b + (c - b) * ((d4 - d3) / ((d4 - d3) + (d5 - d6)))2930 denom = 1.0 / (va + vb + vc)31 return a + ab * (vb * denom) + ac * (vc * denom)3233 p1 = closest_pt_on_tri(pts[0], pts[1], pts[2], test_pt)34 if not face.IsQuad:35 return p13637 p2 = closest_pt_on_tri(vertices[face.A], vertices[face.C], vertices[face.D], test_pt)38 return p1 if (test_pt - p1).Length < (test_pt - p2).Length else p2
Related Concepts
A complex 3D surface composed of a shared vertex pool and connected faces — the industry standard for 3D modeling.
The 'Final Boss' of 3D geometry — a hierarchical data structure of joined surfaces defining perfect solids for CAD and manufacturing.
The mathematical engine of spatial transformations.