Skip to main content

Goal

Create or extract mesh and point geometry from Speckle model data when analysis needs vertices, areas, or lengths — not only BIM properties.

When to use this

Most AEC automation uses DataObject.properties for schedules and QA — start with Find objects by property. Read this guide when you need 3D geometry from displayValue or Speckle.Objects types.
Install separately: dotnet add package Speckle.Objects. Not a dependency of Speckle.Sdk.
  1. Receive model with Receive2
  2. Extract meshes via Flatten().OfType<Mesh>() or TryGetDisplayValue<Mesh>()
  3. For creating geometry to send, put primitives in DataObject.displayValue

Prerequisites

Complete Example

https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Complete example
using Speckle.Objects.Data;
using Speckle.Objects.Geometry;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;

var mesh = new Mesh
{
    vertices = new List<double> { 0, 0, 0, 1, 0, 0, 0, 1, 0 },
    faces = new List<int> { 3, 0, 1, 2 },
    units = Units.Meters,
};

var wall = new DataObject
{
    name = "Wall 01",
    properties = new Dictionary<string, object?>(),
    displayValue = new List<Base> { mesh },
};

Console.WriteLine($"Mesh has {mesh.VerticesCount} vertices");

Mesh Data Layout

Mesh.vertices and Mesh.faces are flat lists:
  • vertices: flat x, y, z, x, y, z, ... triples
  • faces: each face starts with vertex count (n-gon size), followed by indices — [3, 0, 1, 2, 4, 1, 2, 3, 4] is one triangle then one quad
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
for (var i = 0; i < mesh.vertices.Count; i += 3)
{
    double x = mesh.vertices[i];
    double y = mesh.vertices[i + 1];
    double z = mesh.vertices[i + 2];
}

List<Point> points = mesh.GetPoints(); // convenient; allocates per vertex
For large meshes, iterate vertices directly instead of GetPoints().
Speckle meshes support n-gons. Triangulate before handing off to triangle-only renderers — see MeshTriangulationHelper in Speckle.Objects.Utils.

Units

Geometry types carry a units string (Units.Meters, Units.Millimeters, etc.). Objects in the same graph can use different units.
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
var point = new Point(1.0, 2.0, 0.0, Units.Millimeters);

Extracting Geometry from Received Data

All meshes in a graph:
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
var meshes = receivedData.Flatten().OfType<Mesh>().ToList();
Most BIM geometry is in displayValue:
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
using Speckle.Sdk.Models.Extensions;

foreach (var obj in receivedData.Flatten())
{
    var displayMeshes = obj.TryGetDisplayValue<Mesh>();
    if (displayMeshes is null) continue;

    foreach (var mesh in displayMeshes)
    {
        Console.WriteLine($"{obj.TryGetName()}: {mesh.VerticesCount} vertices");
    }
}

Material

RenderMaterial (Speckle.Objects.Other) is typically set as a dynamic renderMaterial property on geometry. For shared materials across many objects, use RenderMaterialProxy — see Working with Proxies.

Common Pitfalls

vertices.Count must be a multiple of 3. Validate list lengths from untrusted sources.
The mesh likely contains n-gons — triangulate first.
Put geometry in a container’s displayValue — see Display values.

Next Steps

Objects and Traversal

displayValue and Base mechanics

Find objects by property

Extract meshes after receive

Operations API

Send and receive geometry graphs
Last modified on July 10, 2026