Understanding meshes in Grasshopper can be a little tricky. They have a somewhat unintuitive data structure that can make it hard to handle meshes in C# code.
You probably already know a little about meshes. They are a form of geometry that contain a collection of faces, and that each face can have no more than 4 corners. How does Grasshopper handle this?
The basics
A mesh is a collection of faces. Each face is defied by 3 or 4 vertices. A vertex is a 3D point. A single mesh can contain as many faces and vertices as you want.
In terms of data structures, a mesh contains 2 lists:
- A list of faces
- A list of vertices
Firstly, we define a list of vertices. This is a list of 3D points. For each point, we can also imagine an index. For example, the fourth point in the list has an index of 4.
Then, we define each face. For each face, we define three vertices for triangles called A, B and C, or four vertices for quads, A, B, C and D. In the face list, the vertices contain the indices for the vertices, and not the coordinates of the vertices themselves. This is important to remember!
What does this mean when Rhino reads this data and tries to display a mesh? Take the example in the image below.
The mesh contains 3 faces. For the first face, we have three values and therefore three vertices, so face 1 is a triangle. What are the coordinates of these three vertices? To do this, we need to also look at the vertices list. Face 1 contains vertices 4, 5 and 3. Remember, these are the indices for our vertices. We take these three values and cross-reference them with the vertex list – reading the coordinates for vertices 3, 5 and 4.
Why is it so complicated?
The above system actually makes sense from a data efficiency point of view. Of course, in most meshes, multiple faces will share vertices. With the sphere above, each vertex is shared between 4 neighbouring faces. With the above data structure, we only need to define our mesh points once.
Furthermore, if we want to move a point on our sphere, we just have to update our vertex list. We don’t have to search for every copy of a node or worry about ‘breaking’ our mesh when we move mesh points about.
Manipulating meshes: A C# example
Create a C# component in Grasshopper. Create an input called ‘mesh’ and set its data type to Mesh.
private void RunScript(Mesh mesh, ref object A) { //1) Let's read from an existing mesh //get faces from mesh Listfaces = new List (); foreach(MeshFace face in mesh.Faces) { faces.Add(face); } //get vertices from mesh List vertices = new List (); foreach(Point3d vertex in mesh.Vertices) { vertices.Add(vertex); } //2) Let's get the coordinates for a mesh face //get the indices for the 10th face int[] indices = new int[4]; indices[0] = mesh.Faces[10].A; indices[1] = mesh.Faces[10].B; indices[2] = mesh.Faces[10].C; indices[3] = mesh.Faces[10].D; //We can now get the coordinates for the 10th face from these indices Point3d[] facepts = new Point3d[4]; for (int i = 0; i < 4; i++) { facepts[i] = mesh.Vertices[indices[i]]; } //3) Let's make a new mesh from scratch Mesh rtnmesh = new Mesh(); //for the new mesh, we first need to define the vertices //we can add any points we like - let's just copy over the vertices list rtnmesh.Vertices.AddVertices(vertices); //now let's make a face and add it to the (currently empty) face list MeshFace tempface = new MeshFace(0, 1, 12, 11); rtnmesh.Faces.AddFace(tempface); }
Download an example
The code above is available in the file below.
Download
6 thoughts on “The mesh data structure in Grasshopper”