This example is somewhat similar to Draw surface normals on a 3D model using WPF and XAML except it draws vertex normals in addition to surface normals, a wireframe, and the surface itself. It uses the following code to create a `MeshGeometry3D` object holding segments showing vertex normals for an existing `MeshGeometry3D` object.

// Return a MeshGeometry3D representing the mesh's triangle normals. public static MeshGeometry3D ToVertexNormals( this MeshGeometry3D mesh, double length, double thickness) { // Copy existing vertex normals. Vector3D[] vertex_normals = new Vector3D[mesh.Positions.Count]; for (int i = 0; i < mesh.Normals.Count; i++) vertex_normals[i] = mesh.Normals[i]; // Calculate missing vetex normals. for (int vertex = mesh.Normals.Count; vertex < mesh.Positions.Count; vertex++) { Vector3D total_vector = new Vector3D(0, 0, 0); int num_triangles = 0; // Find the triangles that contain this vertex. for (int triangle = 0; triangle < mesh.TriangleIndices.Count; triangle += 3) { // See if this triangle contains the vertex. int vertex1 = mesh.TriangleIndices[triangle]; int vertex2 = mesh.TriangleIndices[triangle + 1]; int vertex3 = mesh.TriangleIndices[triangle + 2]; if ((vertex1 == vertex) || (vertex2 == vertex) || (vertex3 == vertex)) { // This triangle contains this vertex. // Calculate its surface normal. Vector3D normal = FindTriangleNormal( mesh.Positions[vertex1], mesh.Positions[vertex2], mesh.Positions[vertex3]); // Add the new normal to the total. total_vector = new Vector3D( total_vector.X + normal.X, total_vector.Y + normal.Y, total_vector.Z + normal.Z); num_triangles++; } } // Set the vertex's normal. if (num_triangles > 0) vertex_normals[vertex] = new Vector3D( total_vector.X / num_triangles, total_vector.Y / num_triangles, total_vector.Z / num_triangles); } // Make a mesh to hold the normals. MeshGeometry3D normals = new MeshGeometry3D(); // Convert the normal vectors into segments. for (int i = 0; i < mesh.Positions.Count; i++) { // Set the normal vector's length. vertex_normals[i] = ScaleVector(vertex_normals[i], length); // Find the other end point. Point3D endpoint = mesh.Positions[i] + vertex_normals[i]; // Create the segment. AddSegment(normals, mesh.Positions[i], endpoint, thickness); } return normals; }

This method first creates an array of `Vector3D` objects to hold normals for all of the mesh’s points. Then, if the mesh includes normal data, it copies that data into the array.

If the mesh is missing normal data for any of its points, the program loops through those points. For each such point, the code loops through the `TriangleIndices` array to see which triangles use that point. The code calls the `FindTriangleNormal` method (described in the earlier post) to get all of the triangles’ normals and averages them to create the vertex normal.

(This method of averaging triangle surface normals gives each triangle that contains the vertex the same weight. For example, if one side of the vertex has one big triangle and the other side has lots of little triangles, the little triangles will tend to overpower the big one. You could change that behavior, but I’m not sure how you would want to do that. I don’t know what algorithm WPF uses if you don’t specify vertex normals yourself.)

After it has calculated all of the vertex normals, the program loops through the normals and adds them to a `MeshGeometry3D` object for display.

please include the xaml code too.

These examples don’t do much in XAML except set up the 3D viewport. In theory you could do everything in XAML but in practice it’s too complicated for something like this.

You can see the XAML code in the earliest examples such as:

Draw a 3D surface with WPF, XAML, and C#

Of you can download this example and take a look at the XAML code.