Overview
The SpeckleMesh format is different from most 3D libraries you’ve encountered. Understanding its unique structure is critical to avoid frustration when creating or consuming geometry.
Common Confusion: Speckle’s mesh format uses a packed face array with nGon support that’s fundamentally different from libraries like three.js, Babylon.js, or standard OBJ files. The
faces array encodes BOTH face size AND vertex indices in a single flat list.The Speckle Mesh Structure
Basic Properties
The Vertices Array: Simple
Thevertices array is straightforward - a flat list of XYZ coordinates:
- Always a multiple of 3 (X, Y, Z)
- Indexed starting from 0
- Units apply to these coordinates
The Faces Array: The Tricky Part
This is where it gets different! The
faces array is NOT a simple list of triangle indices. It’s a packed format that supports nGons (polygons with any number of sides).Face Array Format
Thefaces array encodes face information as:
- First number = how many vertices in this face
- Next N numbers = vertex indices for this face
- Then repeat for next face
Example: Triangle
Example: Quad (4-sided polygon)
Example: Multiple Faces
Why This Format? nGon Support
Most mesh libraries only support triangles (or triangles + quads). Speckle supports nGons - faces with any number of vertices. Advantages:- Preserves design intent - Doesn’t force triangulation
- BIM compatibility - Revit, Rhino often use quads and nGons
- Round-trip fidelity - Original face structure preserved
- Smaller data - No unnecessary triangulation
- More complex to parse
- Rendering engines must triangulate
Parsing the Faces Array
Reading Faces
Accessing Face Vertices
Triangulating nGons
Most rendering engines need triangles. Here’s how to triangulate:Vertex Colors
Colors are per-vertex ARGB integers (not per-face!):- Length of
colorsmust equal number of vertices - Colors interpolate across faces (gradient effect)
- If empty, viewer uses default material color
Converting RGB to ARGB
Render Materials
Render materials define the visual appearance of meshes using physically-based rendering properties. Unlike vertex colors (which are per-vertex), render materials apply to entire objects.RenderMaterial Properties
name(str, required): Material namediffuse(int, required): Base color as ARGB integer (see Vertex Colors)opacity(float): Transparency level (default: 1.0)metalness(float): Metallic appearance (default: 0.0)roughness(float): Surface roughness (default: 1.0)emissive(int): Self-illumination color as ARGB integer (default: 0xFF000000)
Direct Assignment
Assign a material directly to a mesh:RenderMaterialProxy for Collections
For efficiently sharing materials across multiple objects in a collection, useRenderMaterialProxy. This is the standard pattern used by Speckle connectors.
See the Proxification guide for detailed information on how
RenderMaterialProxy works, including:- How to create and use material proxies
- Resolving proxy references
- Best practices for large models
Material vs Vertex Colors
Use RenderMaterial when:- Applying consistent appearance to entire objects
- Using physically-based properties (metalness, roughness)
- Need transparency or emissive effects
- Sharing materials across multiple objects
- Per-vertex color variation (gradients, heatmaps)
- Visualizing analysis data
- Color-coding mesh regions
Vertex Normals
Normals control surface shading (smooth vs flat):- Length of
vertexNormalsmust be same asvertices(3x vertex count) - Normals should be unit vectors (length = 1)
- If empty, viewer auto-calculates normals
- Per-vertex normals = smooth shading
- Duplicated vertices with different normals = hard edges
Hard vs Soft Edges
Speckle connectors produce meshes with all hard-edged faces by default - meaning every face has its own duplicated vertices rather than sharing vertices between faces. This approach prioritizes conversion speed and ensures consistent rendering.
- Hard edges are the default - each face has its own vertices, creating sharp transitions
- Soft edges would require shared vertices with averaged normals, but connectors don’t typically create these
- This means most Speckle meshes have “flat” shading rather than smooth shading
If smooth shading or mixed hard/soft edges are required for your use case, mesh normalization can be performed as a server-side automation that processes the geometry and writes back properly normalized meshes with shared vertices where appropriate.
Two-Sidedness: Not Supported
Speckle doesn’t have a “two-sided” material flag. Faces have a front and back determined by winding order, but both sides render the same in the viewer.
- Right-hand rule determines front face
- Counter-clockwise = front (when viewed from front)
- Most viewers render both sides regardless
Creating Meshes: Complete Examples
Example 1: Simple Quad
Example 2: Colored Triangle
Example 3: Box with Triangulated Faces
Example 4: Box with Quad Faces (nGons)
Common Questions
Why does my mesh not display correctly?
Why does my mesh not display correctly?
The most common issue is forgetting the vertex count in the faces array. Speckle uses a packed format where each face starts with the number of vertices.
How do I ensure colors display properly?
How do I ensure colors display properly?
Colors must match the number of vertices exactly. Each vertex needs one color value.
Why should I always specify units?
Why should I always specify units?
Units are crucial for proper scaling and display. Without units, your geometry might appear at the wrong size or scale.
Why do my meshes look faceted/flat instead of smooth?
Why do my meshes look faceted/flat instead of smooth?
Speckle connectors produce meshes with all hard-edged faces by default - each face has its own duplicated vertices rather than sharing vertices between faces. This creates flat shading rather than smooth shading.If you need smooth shading, you can perform mesh normalization as a server-side automation to create shared vertices where appropriate.
Debugging Tools
Validate Mesh Structure
Visualize Mesh Info
Summary
Key takeaways:- Vertices = Flat list
[x,y,z, x,y,z, ...] - Faces = Packed format
[count, i1, i2, i3, count, ...] - nGons supported = Any number of vertices per face
- Colors = Per-vertex ARGB integers
- RenderMaterials = Physically-based materials with metalness, roughness, and opacity
- RenderMaterialProxy = Efficient material sharing across multiple objects
- Normals = Per-vertex, connectors produce all hard-edged faces (duplicated vertices)
- No two-sided flag = Must duplicate faces with reversed winding
- Always specify units
- ❌ Don’t forget the vertex count in faces array
- ❌ Colors/normals must match vertex count
- ❌ Connectors create flat shading by default (no shared vertices)
- ❌ No explicit two-sided support
- ✅ nGons are supported and preserved
Next Steps
Display Values
How meshes are used in displayValue for viewer visibility
Proxification
Learn about RenderMaterialProxy and other proxy patterns
Working with Geometry
Creating and manipulating geometry objects
Simple Data Patterns
Patterns for working with geometry and properties
Objects & Base
Understanding the Base class and detachment