Initializing 3D Canvas...

The Mesh Face

1 min read1 page

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.

There are two primary types: Triangles (3 vertices) and Quads (4 vertices). Triangles are always perfectly flat, while Quads are simpler to model but can become non-planar.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.
2 min read1 page

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.

python
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)
By pointing to shared vertices, adjacent faces can connect without duplicating coordinate data in memory.
2 min read1 page

Face Normal:

A face normal is a vector that points strictly outward, perpendicular to the face surface. It is calculated by taking the Cross Product of two of its edges. The order of vertices (winding) determines which way the normal points (Right-Hand Rule).
python
1def MeshFaceNormal(ptA: 'Point3d', ptB: 'Point3d', ptC: 'Point3d') -> 'Vector3d':
2 """Calculates the normal vector of a triangular face."""
3
4 # 1. Create two edge vectors
5 edge1 = ptB - ptA
6 edge2 = ptC - ptA
7
8 # 2. Compute cross product
9 normal = Vector3d.CrossProduct(edge1, edge2)
10
11 # 3. Unitize the normal (make length 1)
12 normal.Unitize()
13
14 return normal
1 min read1 page

Winding & Flip:

The order of indices (winding order) defines which side of a face is the "front" and which is the "back". Reversing this order flips the direction of the face normal.
python
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.A
6 else:
7 self.A, self.D = self.D, self.A
8 self.B, self.C = self.C, self.B
Normals are computed using the cross product of edges (Right-Hand Rule). Swapping vertex positions (e.g., A and C) changes the winding direction, instantly reversing the normal vector.
Flip Winding
2 min read1 page

Face Area:

The area of a triangular face can be efficiently calculated using the length of the cross product of two of its edges. For a Quad face, it is split into two triangles and their areas are summed.
python
1def MeshFaceArea(ptA: 'Point3d', ptB: 'Point3d', ptC: 'Point3d') -> float:
2 """Calculates the area of a triangular face."""
3
4 # 1. Create two edge vectors
5 edge1 = ptB - ptA
6 edge2 = ptC - ptA
7
8 # 2. The magnitude of the cross product of two vectors
9 # equals the area of the parallelogram they form.
10 cross = Vector3d.CrossProduct(edge1, edge2)
11 parallelogram_area = cross.Length
12
13 # 3. Triangle area is half of the parallelogram area
14 return parallelogram_area * 0.5
2 min read1 page

Face Centroid:

The Centroid of a mesh face is its geometric center. It is calculated by taking the average of the coordinates of its vertices. Centroids are useful for placing labels, calculating distance offsets, or placing annotations.
python
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.Origin
6
7 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)
10
11 return Point3d(sum_x / n, sum_y / n, sum_z / n)
1 min read1 page

Move Vertices:

You do not move a Mesh Face directly. The face doesn't own its location — it only owns integer pointers. You move the parent vertices that its indices point to. If you move vertex A, the face stretches to accommodate.
python
1# You cannot do: face.Move(vector)
2# You must do:
3parent_mesh.Vertices[face.A] += motion_vector
4parent_mesh.Vertices[face.B] += motion_vector
5# ... and so on for each index
Vertex A → X
1.50
Vertex A → Y
1.00
1 min read1 page

Scale Vertices:

You cannot scale a Mesh Face independently without tearing it away from its neighboring faces. Scaling must happen to the parent pool.
python
1# Scale all vertices referenced by this face from the origin
2for idx in [face.A, face.B, face.C, face.D]:
3 parent_mesh.Vertices[idx] *= scale_factor
Scale Factor
1.50
2 min read1 page

Rotate Vertices:

Like translation and scaling, rotation is applied to the master vertex array. The face simply re-renders based on the new positions of its designated corners.
python
1# Rotate vertex positions around a center point
2for idx in [face.A, face.B, face.C, face.D]:
3 v = parent_mesh.Vertices[idx]
4 dx = v.X - center.X
5 dy = v.Y - center.Y
6 v.X = center.X + dx * cos(angle) - dy * sin(angle)
7 v.Y = center.Y + dx * sin(angle) + dy * cos(angle)
Angle (°)
45.00
2 min read1 page

Non-Planar Quad:

Triangles are always perfectly flat — any 3 points define a unique plane. A quadrilateral (4 points), however, can easily become bent or twisted in 3D space. Rendering engines handle non-planar quads by secretly triangulating them.
python
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 False
4
5 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
Vertex D Warp (Z)
2.00
3 min read1 page

Barycentric Coordinates:

Barycentric Coordinates define the position of a point 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.
python
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 - ptA
4 v1 = ptC - ptA
5 v2 = ptP - ptA
6
7 d00 = v0 * v0
8 d01 = v0 * v1
9 d11 = v1 * v1
10 d20 = v2 * v0
11 d21 = v2 * v1
12
13 denom = d00 * d11 - d01 * d01
14 if abs(denom) < 1e-9:
15 return 0.0, 0.0, 0.0 # Collinear/degenerate triangle
16
17 v = (d11 * d20 - d01 * d21) / denom
18 w = (d00 * d21 - d01 * d20) / denom
19 u = 1.0 - v - w
20
21 return u, v, w
Point X
0.00
Point Y
0.00
2 min read1 page

GetConnectedFaces:

Finds which faces share a common edge, forming the network of the mesh.
A mesh is not just a collection of disconnected triangles; it's a connected web. Topology maps out this connectivity, allowing algorithms to "walk" from one face to its neighbors. Will go more in depth when covering mesh topology.
python
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 = []
5
6 # 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)}
10
11 target_edges = get_edges(target_face)
12
13 for idx, face in enumerate(faces):
14 if idx == face_idx:
15 continue
16 # If face shares any edge with target face
17 face_edges = get_edges(face)
18 if target_edges.intersection(face_edges):
19 adjacent.append(idx)
20
21 return adjacent
This concept is required for smoothing meshes, computing vertex normals, unwrapping UVs, and flood-fill selections.
2 min read1 page

Aspect Ratio:

A common metric to determine the "quality" of a mesh face for simulation and fabrication.
python
1# Manual calculation based on edge lengths
2
3def AspectRatio(face: MeshFace, mesh: Mesh) -> float:
4 """Calculates the ratio between the longest and shortest edge."""
5 # Get physical 3D vertices
6 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]]
11
12 # Calculate all edge lengths
13 edges = [v2.DistanceTo(v1) for v1, v2 in zip(verts, verts[1:] + [verts[0]])]
14
15 # Aspect Ratio = Longest Edge / Shortest Edge
16 return max(edges) / min(edges)
A face with an aspect ratio of 1.0 is perfectly uniform (like an equilateral triangle or a square). As a face is stretched, its aspect ratio increases.
Stretch Face
2.50
4 min read1 page

Circumcircle:

The unique circle that perfectly touches all three vertices of a triangle.
Every triangle in existence has exactly one circumcircle. The center of this circle is called the "Circumcenter", and it represents the point equidistant from all three vertices.
python
1def Circumcircle(A: Point3d, B: Point3d, C: Point3d) -> Circle:
2 """Finds the unique circle passing through all 3 vertices."""
3 # Midpoints of AB and BC
4 midAB = (A + B) * 0.5
5 midBC = (B + C) * 0.5
6
7 # Directions
8 dirAB = B - A
9 dirBC = C - B
10
11 # Perpendicular normals in 2D plane
12 perpAB = Vector3d(-dirAB.Y, dirAB.X, 0).Unitize()
13 perpBC = Vector3d(-dirBC.Y, dirBC.X, 0).Unitize()
14
15 # 2D line intersection of perpendicular bisectors
16 x1, y1 = midAB.X, midAB.Y
17 x2, y2 = midAB.X + perpAB.X, midAB.Y + perpAB.Y
18 x3, y3 = midBC.X, midBC.Y
19 x4, y4 = midBC.X + perpBC.X, midBC.Y + perpBC.Y
20
21 denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
22 if abs(denom) < 1e-9:
23 return None
24
25 cx = ((x1*y2 - y1*x2)*(x3 - x4) - (x1 - x2)*(x3*y4 - y3*x4)) / denom
26 cy = ((x1*y2 - y1*x2)*(y3 - y4) - (y1 - y2)*(x3*y4 - y3*x4)) / denom
27
28 center = Point3d(cx, cy, 0)
29 radius = (center - A).Length
30 return Circle(center, radius)
This concept is the mathematical engine behind Delaunay Triangulation — the global standard algorithm for generating meshes from point clouds. Delaunay ensures that no vertex ever falls inside the circumcircle of any other triangle, maximizing the aspect ratio (quality) of the mesh.
Move Vertex A
0.00
2 min read1 page

Triangulate:

Triangulation splits a multi-sided polygon or Quad face into flat triangular faces.
python
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)]
5
6 # 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)]
GPUs only render triangles natively. Any Quad or N-gon face is internally split into triangles before rendering or running structural finite element analysis (FEA).
Split Diagonal (BD)
6 min read2 pages

Closest Point:

Finding the Closest Point on a polygon boundary is a search operation. The algorithm decomposes the polygon into a series of line segments, projects the test point onto every segment, and returns the result with the shortest absolute distance.
python
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]]
4
5 def closest_pt_on_tri(a, b, c, p):
6 ab, ac, ap = b - a, c - a, p - a
7 d1, d2 = ab.dot(ap), ac.dot(ap)
8 if d1 <= 0 and d2 <= 0: return a
9
10 bp = p - b
11 d3, d4 = ab.dot(bp), ac.dot(bp)
12 if d3 >= 0 and d4 <= d3: return b
13
14 vc = d1 * d4 - d3 * d2
15 if vc <= 0 and d1 >= 0 and d3 <= 0:
16 return a + ab * (d1 / (d1 - d3))
17
18 cp = p - c
19 d5, d6 = ab.dot(cp), ac.dot(cp)
20 if d6 >= 0 and d5 <= d6: return c
21
22 vb = d5 * d2 - d1 * d6
23 if vb <= 0 and d2 >= 0 and d6 <= 0:
24 return a + ac * (d2 / (d2 - d6))
25
26 va = d3 * d6 - d5 * d4
27 if va <= 0 and (d4 - d3) >= 0 and (d5 - d6) >= 0:
28 return b + (c - b) * ((d4 - d3) / ((d4 - d3) + (d5 - d6)))
29
30 denom = 1.0 / (va + vb + vc)
31 return a + ab * (vb * denom) + ac * (vc * denom)
32
33 p1 = closest_pt_on_tri(pts[0], pts[1], pts[2], test_pt)
34 if not face.IsQuad:
35 return p1
36
37 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
Finding the point on a face that is closest to an external point is a cornerstone of collision and interaction. The "closest point" is found by projecting the test point onto the plane of the face and then "clamping" it to the boundary using Barycentric Coordinates.
Search Pt X
1.00
Search Pt Y
1.00