# Mesh and Point Cloud I/O

**If your file can be imported into MeshLab, we can read it!**

Point Cloud Utils supports reading and writing many common 3D formats (PLY, STL, OFF, OBJ, 3DS, VRML 2.0, X3D, COLLADA). In all the functions in this section, the type of file is inferred from its file extension.

## 3D Data Representation in Point Cloud Utils

Point Cloud Utils uses NumPy arrays as a fundamental data structure for storing 3D data.

### Representing Point Clouds

A point cloud with `#p`

points is represented as a simple Numpy array with shape `(#p, 3)`

(one point per row). The example below illustrates a point cloud with six points.

### Representing Triangle Meshes

A triangle mesh with `#v`

vertices and `#f`

faces is stored using a pair of NumPy arrays `v, f`

with
shape `(#v, 3)`

and `(#f, 3)`

respectively. Each row of `v`

stores a vertex coordinate and each row of `f`

stores
three integer indexes into `v`

denoting the three vertices forming that face. Per-vertex attributes are stored as
separate NumPy arrays with `#v`

rows (one row per vertex).

For example, consider the mesh with 6 vertices and 5 faces illustrated above.
We would store this as two numpy arrays `v, f`

with `v.shape = (6, 3)`

and `f.shape = (5, 3)`

. The i^{th} row
of `v`

is a 3D vector encoding the position of the vertex *v _{i}*, and j

^{th}row of

`f`

holds three indices to each of the vertices of the j^{th}face. In the figure, the second face is formed by the vertices

*v*, so the second row of

_{1}, v_{2}, v_{5}`f`

are the integers `(1, 2, 5)`

.### Representing Point and Face Attributes

In addition to vertices and face data, we often want to store attributes alongside a point cloud or mesh. Attributes can be stored per-point as well as per-face. Attributes are stored as NumPy arrays with one attribute per row. Examples of attributes include point cloud normals, point colors, per-face colors, or per-vertex texture coordinates.

**Example - Storing face colors and vertex normals in a mesh:**
For example, consider the mesh described above with 6 vertices and 5 faces, stored as two arrays `v`

and `f`

with shapes `(6, 3)`

and `(5, 3)`

respectively. We could store per-face colors as
a NumPy array with shape `(5, 3)`

each row is the color of the correponding face:

We could store per-vertex normals as a NumPy array of shape `(6, 3)`

where each row contains the normal at the corresponding vertex:

## Shorthand functions for loading and saving 3D data

Many times, we only need to load a few attributes from a mesh or point cloud. For example, we may only want the vertices, faces, and vertex colors for mesh. Point Cloud Utils provides a number of
shorthand helper functions which can load these attributes directly into NumPy arrays. These functions have the form `load_mesh_*`

and `save_mesh_*`

where `*`

indicates which data to load. If some attribute is not present in the file being loaded, these functions will simply return an empty array.

#### Load/Save only points

```
import point_cloud_utils as pcu
# v is a NumPy array of shape (#v, 3) of points
v = pcu.load_mesh_v("path/to/mesh")
pcu.save_mesh_v("path/to/mash", v)
```

#### Load/Save mesh vertices and faces

```
import point_cloud_utils as pcu
# v is a NumPy array of shape (#v, 3) of points
# f is a NumPy array of shape (#f, 3) of face indices
v, f = pcu.load_mesh_vf("path/to/mesh")
pcu.save_mesh_vf("path/to/mash", v, f)
```

#### Load/Save points and per-point normals

```
import point_cloud_utils as pcu
# v is a NumPy array of shape (#v, 3) of points
# n is a NumPy array of shape (#v, 3) of per-vertex normals
v, n = pcu.load_mesh_vn("path/to/mesh")
pcu.save_mesh_vn("path/to/mash", v, n)
```

#### Load/Save mesh vertices, faces, and vertex colors

```
import point_cloud_utils as pcu
# v is a NumPy array of shape (#v, 3) of points
# f is a NumPy array of shape (#f, 3) of face indices
# c is a NumPy array of shape (#v, 4) of RBGA per-vertex colors
v, f, c = pcu.load_mesh_vfc("path/to/mesh")
pcu.save_mesh_vfc("path/to/mash", v, f, c)
```

#### Load/Save mesh vertices, faces, and vertex normals

```
import point_cloud_utils as pcu
# v is a NumPy array of shape (#v, 3) of points
# f is a NumPy array of shape (#f, 3) of face indices
# n is a NumPy array of shape (#v, 3) of per-vertex normals
v, f, n = pcu.load_mesh_vfn("path/to/mesh")
pcu.save_mesh_vfn("path/to/mash", v, f, n)
```

#### Load/Save mesh vertices, faces, vertex normals, and vertex colors

```
import point_cloud_utils as pcu
# v is a NumPy array of shape (#v, 3) of points
# f is a NumPy array of shape (#f, 3) of face indices
# n is a NumPy array of shape (#v, 3) of per-vertex normals
# c is a NumPy array of shape (#v, 4) of RBGA per-vertex colors
v, f, n, c = pcu.load_mesh_vfn("path/to/mesh")
pcu.save_mesh_vfnc("path/to/mash", v, f, n, c)
```

## Loading 3D data with all attributes

Some meshes or point clouds may have more complex attribute structures, or we may not know which attributes are stored
in the mesh file before loading it. In this case, Point Cloud Utils provides utilities to load a mesh into
a `TriangleMesh`

class. `TriangleMesh`

is a lightweight container containing numpy arrays for
vertices, faces, textures, and other attributes.

To load a mesh into a `TriangleMesh`

class simply construct it with the path to the mesh:

```
import point_cloud_utils as pcu
mesh = pcu.TriangleMesh("path/to/mesh")
```

To save a `TriangleMesh`

object, simply call the `save`

method with the desired path:

```
mesh.save("path/to/mesh")
```

The `TriangleMesh`

class contains attributes encoding vertex and face data as well as texture information. It is structured as follows:

:`TriangleMesh`

:`vertex_data`

: (#v, 3)-shaped NumPy array of per-vertex positions`positions`

: (#v, 3)-shaped NumPy array of per-vertex normals (or`normals`

`None`

): (#v, 2)-shaped NumPy array of per-vertex uv coordinates (or`texcoords`

`None`

): (#v,)-shaped NumPy array of integer indices into TriangleMesh.textures indicating which texture to use at this vertex (or`tex_ids`

`None`

): (#v, 4)-shaped NumPy array of per-vertex RBGA colors in`colors`

`[0.0, 1.0]`

(or`None`

): (#v,)-shaped NumPy array of per-vertex curvature radii (or`radius`

`None`

): (#v,)-shaped NumPy array of per-vertex quality measures (or`quality`

`None`

): (#v,)-shaped NumPy array of 32-bit integer flags per vertex (or`flags`

`None`

)

:`face_data`

: (#f, 3)-shaped NumPy array of integer face indices into`vertex_ids`

`TrianglMesh.vertex_data.positions`

: (#f, 3)-shaped NumPy array of per-face normals (or`normals`

`None`

): (#f, 4)-shaped NumPy array of per-face RBGA colors in`colors`

`[0.0, 1.0]`

(or`None`

): (#f,)-shaped NumPy array of per-face quality measures (or`quality`

`None`

): (#f,(-shaped NumPy array of 32-bit integer flags per face (or`flags`

`None`

): (#f, 3, 4)-shaped NumPy array of per-wedge RBGA colors in`wedge_colors`

`[0.0, 1.0]`

(or`None`

): (#f, 3, 3)-shaped NumPy array of per-wedge normals (or`wedge_normals`

`None`

): (#f, 3, 2)-shaped NumPy array of per-wedge] uv coordinates (or`wedge_texcoords`

`None`

): (#f, 3)-shaped NumPy array of integer indices into`wedge_tex_ids`

`TriangleMesh.textures`

indicating which texture to use at this wedge (or`None`

)

: A list of paths to texture image files for this mesh`textures`

: A list of paths to texture image files for this mesh`normal_maps`

The hierarchy of the list above denotes composition. For example, to access the vertex colors of a `TriangleMesh`

, you would
read the `TriangleMesh.vertex_data.colors`

property.

Remark on wedge face attributes

The `face_data`

member of the `TriangleMesh`

class contains a number of `wedge`

attributes. These all start with
`wedge_`

. In this context a *wedge* is a corner of a triangle face. Each face contains three wedges corresponding
to each corner. Wedge attributes have shape `(#f, 3, d)`

where `d`

is the dimension of the attribute.
Wedges attributes are useful for storing which are discontinous across face boundaries.