This module provides functions for working with indexed meshes. You can:
Create a mesh from an array of vertices and a list of face indices. For
example, to construct a square pyramid where a is the front right corner,
b is the front left corner, c is the back left corner, d is the back
right corner and e is the apex:
vertices =
Array.fromList [ a, b, c, d, e ]
faceIndices =
[ [ 0, 1, 2, 3 ]
, [ 0, 4, 1 ]
, [ 1, 4, 2 ]
, [ 2, 4, 3 ]
, [ 3, 4, 0 ]
]
pyramid =
Mesh.fromOrientedFaces vertices faceIndices
|> Result.withDefault Mesh.emptyThe return type here is a Result String (Mesh vertex) rather than just
a Mesh vertex so that a specific error message can be produced if there is
a problem with the input.
Try to convert a TriangularMesh instance into a Mesh. This could
potentially fail because a Mesh is more restrictive.
Triangulate each face of the mesh and return the result as a
TriangularMesh instance.
Combine a list of meshes into a single mesh. This concatenates the vertex arrays of each mesh and adjusts face indices to refer to the combined vertex array.
pyramid =
Mesh.fromOrientedFaces
(Array.fromList [ a, b, c, d, e ])
[ [ 0, 1, 2, 3 ]
, [ 0, 4, 1 ]
, [ 1, 4, 2 ]
, [ 2, 4, 3 ]
, [ 3, 4, 0 ]
]
tetrahedron =
Mesh.fromOrientedFaces
(Array.fromList [ A, B, C, D ])
[ [ 0, 1, 2 ]
, [ 0, 3, 1 ]
, [ 1, 3, 2 ]
, [ 2, 3, 0 ]
]
combined =
Mesh.combine [ pyramid, tetrahedron ]
Mesh.vertices combined
--> Array.fromList [ a, b, c, d, e, A, B, C, D ]
Mesh.faceIndices combined
--> [ [ 0, 1, 2, 3 ]
--> , [ 0, 4, 1 ]
--> , [ 1, 4, 2 ]
--> , [ 2, 4, 3 ]
--> , [ 0, 3, 4 ]
--> , [ 5, 6, 7 ]
--> , [ 5, 8, 6 ]
--> , [ 6, 8, 7 ]
--> , [ 5, 7, 8 ]
--> ]Get the vertices of a mesh.
Mesh.vertices pyramid
--> Array.fromList [ a, b, c, d, e ]Get a particular vertex of a mesh by index. If the index is out of range,
returns Nothing.
Mesh.vertex 1 pyramid
--> Just b
Mesh.vertex 5 pyramid
--> NothingGet the faces of a mesh as lists of vertex indices. Each face is normalized so that its smallest vertex index comes first.
Mesh.faceIndices pyramid
--> [ [ 0, 1, 2, 3 ]
--> , [ 0, 4, 1 ]
--> , [ 1, 4, 2 ]
--> , [ 2, 4, 3 ]
--> , [ 0, 3, 4 ]
--> ]Get the faces of a mesh as lists of vertices. The ordering of vertices
for each face is the same as in faceIndices.
Mesh.faceVertices pyramid
--> [ [ a, b, c, d ]
--> , [ a, e, b ]
--> , [ b, e, c ]
--> , [ c, e, d ]
--> , [ a, d, e ]
--> ]Get all of the edges of a mesh as pairs of vertex indices. Each edge will only be returned once, with the lower-index vertex listed first, and will be returned in sorted order.
Mesh.edgeIndices pyramid
--> [ ( 0, 1 )
--> , ( 0, 3 )
--> , ( 0, 4 )
--> , ( 1, 2 )
--> , ( 1, 4 )
--> , ( 2, 3 )
--> , ( 2, 4 )
--> , ( 3, 4 )
--> ]Get all of the edges of a mesh as pairs of vertices. Each edge will only be returned once, with the lower-index vertex listed first, and will be returned in sorted order (by index).
Mesh.edgeVertices pyramid
--> [ ( a, b )
--> , ( a, d )
--> , ( a, e )
--> , ( b, c )
--> , ( b, e )
--> , ( c, d )
--> , ( c, e )
--> , ( d, e )
--> ]Get the neighbors of all vertices as lists of vertex indices. The i-th entry in the output array corresponds to the i-th vertex of the mesh. The neighbors are ordered as one would encounter them while walking around the vertex in the same direction (clockwise or counterclockwise) as the vertices for each face are listed, starting from the one with the lowest vertex index.
Mesh.neighborIndices pyramid
--> [ [ 1, 3, 4 ]
--> , [ 0, 4, 2 ]
--> , [ 1, 4, 3 ]
--> , [ 0, 2, 4 ]
--> , [ 0, 3, 2, 1 ]
--> ]Get the neighbors of all vertices as lists of vertices. Further details
are as in neighborIndices.
Transform a mesh by applying the given function to each of its vertices. For
example, if you had a 2D mesh where each vertex was an ( x, y ) tuple and you
wanted to convert it to a 3D mesh on the XY plane, you might use
mesh2d : Mesh ( Float, Float )
mesh2d =
...
to3d : ( Float, Float ) -> ( Float, Float, Float )
to3d ( x, y ) =
( x, y, 0 )
mesh3d : Mesh ( Float, Float, Float )
mesh3d =
Mesh.mapVertices to3d mesh2dCalculate normals for a mesh. The first argument is a function that takes a vertex of the input mesh and returns its position as a Point3d. The second argument is a function that takes a vertex of the input mesh and its computed normal as a Vector3d, and returns the corresponding vertex for the output mesh.
Subdivide a mesh by first adding a new vertex in the center of each edge, subdividing each edge into two in the process, then adding a new vertex in the center of each face and splitting the face into quadrangles by connecting the new face center to the new edge centers.
The first argument is a function that takes a list of input vertices, namely the vertices of an edge or face to be subdivided, and returns the new "center" vertex.
Subdivide a mesh into quadrangles using the
Catmull-Clark
method. The connectivity of the result will be the same as in subdivide, but
the vertices will be repositioned to make it appear smoother.
The first argument is a function that returns True if the input vertex should
not be moved. The second argument is a function that returns the position of
an input vertex. The third argument is a function that takes a list of input
vertices and a computed output position and returns an output vertex.
A
Meshis an instance of a polygon mesh which is implemented as a so-called half-edge data structure. Each mesh consists of an array of vertices and some connectivity information that describes how faces, edges and vertices are related to each other. A face must have at least three vertices, but can also have four, five or more.The half-edge data structure guarantees that the mesh describes a surface with a consistent "orientation", which intuitively means that if one were to walk along on the surface of the mesh one could never find oneself back at the starting point but standing upside-down on the other side of the mesh.
Right now it is also not allowed to define a mesh with a boundary.
The vertices themselves can be any type you want. For a 2D mesh, you might have each vertex be simply a point:
For a 3D mesh, each vertex might be a (point, normal) tuple:
In more complex cases, each vertex might be a record: