### 11 unstable releases

0.6.0 | Apr 27, 2023 |
---|---|

0.5.2 | May 6, 2022 |

0.5.1 | Apr 21, 2022 |

0.4.0 | Mar 29, 2022 |

0.1.3 | Nov 12, 2021 |

#**3** in Data formats

**68** downloads per month

Used in **2** crates

**MIT/Apache**

700KB

15K
SLoC

# meshx

A mesh exchange library for providing convenient conversion utilities between popular mesh formats.

Disclamer:

is still in the early stage of its development and using it in a production
environment is not recommended. The `meshx`

API is not stable and is subject to change.`meshx`

# Overview

This library is designed to simplify interoperability between different 3D applications using mesh data
structures.

also provides common mesh types and related traits to work with attributes.`meshx`

Different components of this library can be useful in different circumstances. To name a few use
cases,

can be used to`meshx`

- import or export meshes from files,
- build plugins for 3D applications
- store untyped mesh data for long term use
- build a visualization tool to display mesh attributes
- build new mesh types specific to your application using a familiar API.
For more details please refer to the

.`documentation`

# Quick Tutorial

Here we'll explore different uses of

.`meshx`

## Building meshes

This library includes a few concrete built-in mesh types like

for triangle meshes,
`TriMesh`

for polygonal meshes and `PolyMesh`

for tetrahedral meshes often used in finite element
simulations. Let's create a simple triangle mesh consisting of two triangles to start:`TetMesh`

`use` `meshx``::`TriMesh`;`
`//` Four corners of a [0,0]x[1,1] square in the xy-plane.
`let` vertices `=` `vec!``[`
`[``0.``0``f64``,` `0.``0``,` `0.``0``]``,`
`[``1.``0``,` `0.``0``,` `0.``0``]``,`
`[``0.``0``,` `1.``0``,` `0.``0``]``,`
`[``1.``0``,` `1.``0``,` `0.``0``]``,`
`]``;`
`//` Two triangles making up a square.
`let` indices `=` `vec!``[``[``0``,` `1``,` `2``]``,` `[``1``,` `3``,` `2``]``]``;`
`//` Create the triangle mesh
`//` NOTE: TriMesh is generic over position type, so you need to
`//` specify the specific float type somewhere.
`let` trimesh `=` `TriMesh``::`new`(`vertices`,` indices`)``;`

## Simple count queries

Our new triangle mesh interprets the passed vertices and inidices as mesh data, which gives us information about the mesh. We can now ask for relevant quantities as follows:

`use` `meshx``::`topology`:``*``;` `//` Prepare to get topology information.
`println!``(``"`number of vertices: `{}``"``,` mesh`.``num_vertices``(``)``)``;`
`println!``(``"`number of faces: `{}``"``,` mesh`.``num_faces``(``)``)``;`
`println!``(``"`number of face-edges: `{}``"``,` mesh`.``num_face_edges``(``)``)``;`
`println!``(``"`number of face-vertices: `{}``"``,` mesh`.``num_face_vertices``(``)``)``;`

which prints

`number of vertices``:` `4`
number of faces`:` `2`
number of face`-`edges`:` `6`
number of face`-`vertices`:` `6`

In the next section we will explore what is meant by

and `face-edges`

here.`face-vertices`

## Topology queries

Our simple triangle mesh is represented by 2 triangles, each pointing to 3 vertices on our array of 4 vertices. This connectivity relationship solely defines a triangle mesh. We can visualize our particular example in ASCII with vertices numbered outside and triangle indices inside:

` ``2` `3`
`+``-``-``-``-``-``-``-``-``+`
`|`\ `|`
`|` \ `1` `|`
`|` \ `|`
`|` \ `|`
`|` \ `|`
`|` \ `|`
`|` `0` \ `|`
`|` \`|`
y `+``-``-``-``-``-``-``-``-``+`
`^` `0` `1`
`|`
`+``-``->` x

If we number each of the triangle indices in a row, we will come up with a total of 6 indices.
These are called *face-vertices* in

. For our example, we write linear face-vertex indices
inside the triangles:`meshx`

` ``2` `3`
`+``-``-``-``-``-``-``-``-``+`
`|`\`5` `4``|`
`|``2`\ `|`
`|` \ `|`
`|` \ `|`
`|` \ `|`
`|` \ `|`
`|` \`3``|`
`|``0` `1`\`|`
y `+``-``-``-``-``-``-``-``-``+`
`^` `0` `1`
`|`
`+``-``->` x

In turn *face-edges* are the directed edges inside each face that start at each of t he
face-vertices in a counter-clockwise direction. For example the first face-edge correspondes to the
0->1 edge in the first triangle at index 0.

This structure can be easily generalized to other meshes following a similar naming convention. We
use the words *vertex*, *edge*, *face* and *cell* to represent 0, 1, 2, and 3 dimensional elements respectively.
When face and cell types are mixed like in unstructured meshes (e.g. the

type), we refer to
them simply as cells to be consistent with other libraries like VTK.`Mesh`

Knowing this we can query a particular face, face-edge, face-vertex or vertex in our triangle mesh:

`//` Get triangle indices:
`println!``(``"`face 1: `{:?}``"``,` mesh`.``face``(``1``)``)``;`
`//` Face-edge topology:
`//` These functions are provided by the FaceEdge trait.
`println!``(``"`face-edge index of edge 2 on face 1: `{:?}``"``,` mesh`.``face_edge``(``1``,` `2``)``)``;`
`println!``(``"`edge index of face-edge 5: `{:?}``"``,` mesh`.``edge``(``5``)``)``;`
`println!``(``"`edge index of edge 2 on face 1: `{:?}``"``,` mesh`.``face_to_edge``(``1``,` `2``)``)``;`
`//` Face-vertex topology:
`//` These functions are provided by the FaceVertex trait.
`println!``(``"`face-vertex index of vertex 1 on face 0: `{:?}``"``,` mesh`.``face_vertex``(``0``,` `1``)``)``;`
`println!``(``"`vertex index of face-vertex 1: `{:?}``"``,` mesh`.``vertex``(``1``)``)``;`
`println!``(``"`vertex index of vertex 1 on face 0: `{:?}``"``,` mesh`.``face_vertex``(``0``,` `1``)``)``;`

which outputs:

`face ``1``:` `[``1``,` `3``,` `2``]`
face`-`edge index of edge `2` on face `1``:` `Some``(`FaceEdgeIndex`(``5``)``)`
edge index of face`-`edge `5``:` EdgeIndex`(``2``)`
edge index of edge `2` on face `1``:` `Some``(`EdgeIndex`(``2``)``)`
face`-`vertex index of vertex `1` on face `0``:` `Some``(`FaceVertexIndex`(``1``)``)`
vertex index of face`-`vertex `1``:` VertexIndex`(``1``)`
vertex index of vertex `1` on face `0``:` `Some``(`FaceVertexIndex`(``1``)``)`

For now the topology query functions here return an

when given an index within an element,
since these are not typed. In that case `Option`

is returned for out-of-bounds indices. Typed indices
(e.g. EdgeIndex, FaceVertexIndex) are expected to be correctly bounded. If an incorrect typed
index is given, the function will panic.`None`

topology is commonly used to assign `FaceVertex`

or `uv`

coordinates to meshes.
`texture`

topology can be used to define a
half-edge interface on meshes.`FaceEdge`

## Attributes

When working with meshes in 3D applications, it is essential to be able to load and store values for different elements of the mesh. Each element (vertex, edge, face, or cell) or topology element (e.g. face-edge, face-vertex) supported by a mesh can store values of any type associated with that element.

For instance we can store vertex normals at vertices, or texture coordinates on face-vertices to indicate where on a texture to map each triangle.

Let's add some associated vectors to the vertices on our mesh pointing up (+z) and away from the mesh. This can represent physical quantities like forces or velocities, or normals used for shading.

`use` `meshx``::``attrib``::``*``;`
`let` `mut` mesh `=` mesh`;` `//` Make mesh mutable.
`let` vectors `=` `vec!``[`
`[``-``1.``0``,` `-``1.``0``,` `1.``0``]``,`
`[``1.``0``,` `-``1.``0``,` `1.``0``]``,`
`[``-``1.``0``,` `1.``0``,` `1.``0``]``,`
`[``1.``0``,` `1.``0``,` `1.``0``]``,`
`]``;`
mesh`.``insert_attrib_data``::``<``[``f32``;` `3``]`, VertexIndex`>``(``"`up_and_away`"``,` vectors`)``.``unwrap``(``)``;`

supports many ways of manipulating attributes, down to destructuring the mesh to expose
the structures that store these attributes. For more details see the
`meshx`

module and the
`attrib`

trait.`attrib ::`Attrib

## IO: loading and saving meshes

Using the

module we can load and store meshes. To save our triangle mesh to a file, we can
simply call `io`

specifying a path:`save_trimesh`

`meshx``::``io``::`save_trimesh`(``&`mesh`,` `"`tests/artifacts/tutorial_trimesh.vtk`"``)``.``unwrap``(``)``;`

This can then be loaded from another application like ParaView. Here is our mesh with the associated vectors shown as arrows:

We can also load this file back using

.`load_trimesh`

`let` loaded_mesh `=` `meshx``::``io``::`load_trimesh`(``"`tests/artifacts/tutorial_trimesh.vtk`"``)``.``unwrap``(``)``;`

See the

module for supported formats.`io`

Since the vertex positions and attributes happen to be exactly representable with floats, we can expect the two meshes to be identical:

`assert_eq!``(`mesh`,` loaded_mesh`)``;`

Although this may not always be true in general when meshes can cache attribute data.

## Conclusion

In this short tutorial we have covered

- Building a mesh
- Getting element and connection counts on a mesh with

functions`num_``*` - Accessing various indices associated with a mesh
- Inserting attribute data on mesh vertices
- Saving and loading a mesh to and from a file.

The code in this tutorial is available in

and can be
run with`examples /tutorial.rs`

`$`` cargo run`` --`example tutorial

For more details on the API, please consult the documentation.

# License

This repository is licensed under either of

- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or https://opensource.org/licenses/MIT)

at your option.

#### Dependencies

~7MB

~144K SLoC