reckfellENGINE

ArrayMesh

Mesh built from vertex/attribute arrays with separate surfaces.

On this page
class ArrayMeshReckfellSharpInherits Mesh

ArrayMesh stores geometry; MeshInstance3D places it in the world. It is a resource rather than an Entity. Every AddSurfaceFromArrays appends a surface; assign its material separately with SurfaceSetMaterial. Surface indices start at zero and shift after SurfaceRemove. Positions and optional indices are sufficient for a first mesh.

C#
using var mesh = new ArrayMesh();
using var arrays = new Reckfell.Collections.Array();
arrays.Resize((int)Mesh.ArrayType.Max);
arrays[(int)Mesh.ArrayType.Vertex] = new Vector3[] {
    new(0, 0, 0), new(1, 0, 0), new(1, 1, 0), new(0, 1, 0)
};
arrays[(int)Mesh.ArrayType.Index] = new int[] { 0, 1, 2, 0, 2, 3 };
mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);
int vertexCount = mesh.SurfaceGetArrayLen(0); // 4
int indexCount = mesh.SurfaceGetArrayIndexLen(0); // 6

The example checks data without creating a visible object. To display it, assign the resource to MeshInstance3D.Mesh and add the instance to the tree; keep the mesh alive while used rather than ending its using scope early. Prepare material, normals and UVs for the intended result. Triangle front faces use clockwise winding.

The arrays container must have Mesh.ArrayType.Max slots; unused slots remain Nil. Vertex accepts Vector3[] or Vector2[]; Index accepts int[] with indices inside the vertex count. Supply Normal/UV/Color for every vertex and four floats per vertex for Tangent. Bones/Weights need matching influence counts and a valid format. Index count is not triangle count: for Triangles it is divisible by three. Validate lengths, values and primitive before adding. SurfaceGetArrays returns a snapshot: editing returned arrays does not edit a surface.

Define blend-shape names before adding surfaces; each surface needs one array per shape in the same order. Vertex/Normal/Tangent channels must match the base format. Default mode is Relative. ClearSurfaces retains blend definitions and mode; ClearBlendShapes can then remove names. Supply LODs as a Dictionary of positive numeric thresholds and shorter int[] index lists addressing the same vertices. These are prepared levels, not automatic simplification. There is no public C# SurfaceGetLods: do not copy that C++ name into a managed example.

SurfaceUpdateVertexRegion/AttributeRegion/SkinRegion operate on packed buffer bytes rather than Vector3 indices. Format, offsets and stride depend on channels/compression; use the corresponding RenderingServer MeshSurfaceGetFormat methods. Such writes cannot change lengths or topology. Expand CustomAabb for deformation culling; setting CustomAabb does not change geometric GetAabb. A Changed notification does not establish CPU-cache, bounds or collision recomputation. The headless backend does not perform these region writes at all.

RegenNormalMaps rebuilds surfaces through SurfaceTool and generates tangents when normals and UVs exist; it neither creates normal-map images nor generates normals. It is not a lossless preservation path for names, blend shapes, LODs or custom channels. LightmapUnwrap creates UV2 and can change vertex splitting; it does not bake lighting. It requires an unwrap callback in the build, Triangles with normals, positive texelSize and no blend shapes.

ClearSurfaces does not emit Changed; SurfaceRemove, surface append, name changes and CustomAabb changes do. Call EmitChanged explicitly after clearing if your consumer relies on that signal. ShadowMesh is shared additional geometry for shadows/depth prepass with identical positions, including LODs, rather than a replacement visible mesh. Initialize the main mesh by adding a surface or calling GetRid before assigning ShadowMesh.

20 Windows headless checks covered metadata, CPU snapshots, names, clearing, bounds, shared references and a simple blend/LOD package. GPU updates, visible deformation, LOD selection, light baking/UV2 quality and performance were not tested.

Declarations checked against C# SDK 1.0.0. Expand a name to see declarations and documentation.

Constructors1

ArrayMeshConstructor
# ArrayMesh
C#
public ArrayMesh();

Creates an owned empty Mesh without surfaces or blend shapes. Mode is Relative; release after all consumers finish using it.

Properties5

BlendShapeModeProperty
# BlendShapeMode
C#
public Mesh.BlendShapeMode BlendShapeMode { get; set; }

Blend-data interpretation mode: Relative by default, or Normalized blending. Does not automatically convert existing arrays.

CustomAabbProperty
# CustomAabb
C#
public Aabb CustomAabb { get; set; }

Custom culling bounds, useful for shader deformation. Zero Aabb disables the override. Does not alter vertices or GetAabb; setter emits Changed.

ShadowMeshProperty
# ShadowMesh
C#
public ArrayMesh ShadowMesh { get; set; }

Shared auxiliary mesh for shadows/depth prepass. Positions must match the main mesh including LODs; seam vertices can be fused and unnecessary attributes omitted. Does not replace visible material/geometry.

_BlendShapeNamesProperty
# _BlendShapeNames
C#
public string[] _BlendShapeNames { get; set; }

Hidden SDK serialization property for shape names. Use AddBlendShape/SetBlendShapeName/ClearBlendShapes in ordinary code; not an animation-weight array.

_SurfacesProperty
# _Surfaces
C#
public Reckfell.Collections.Array _Surfaces { get; set; }

Hidden SDK serialization property for packed surfaces. An Array of dictionaries containing format, vertex_data, counts and optional blocks, not AddSurfaceFromArrays channel arrays. Do not hand-edit binary dictionaries. The getter returns a caller-owned container.

Methods29

AddBlendShapevoid
# AddBlendShape
C#
public void AddBlendShape(StringName name);

Adds a name before surface creation. Duplicates receive suffixes " 2", " 3", etc. Changing the count after surfaces exist is rejected.

Parameters
NameTypeDefault
nameStringName—
name

Shape name; conflicts automatically receive an available numeric suffix.

AddSurfaceFromArraysvoid
# AddSurfaceFromArrays
C#
public void AddSurfaceFromArrays(Mesh.PrimitiveType primitive, Reckfell.Collections.Array arrays, Reckfell.Collections.Array<Reckfell.Collections.Array> blendShapes = null, Reckfell.Collections.Dictionary lods = null, Mesh.ArrayFormat flags = (Mesh.ArrayFormat)0);

Appends rather than replaces a surface. Requires Max slots, consistent channels and one array per declared blend shape. Data/flags determine format; emits Changed on success. Returns void: inspect surface count and diagnostics.

Parameters
NameTypeDefault
primitiveMesh.PrimitiveType—
arraysReckfell.Collections.Array—
blendShapesReckfell.Collections.Array<Reckfell.Collections.Array>null
lodsReckfell.Collections.Dictionarynull
flagsMesh.ArrayFormat(Mesh.ArrayFormat)0
primitive

Primitive assembly mode; Triangles needs a corner/index count divisible by three.

arrays

Exactly Mesh.ArrayType.Max slots containing packed arrays of matching types/lengths; unused slots Nil.

blendShapes

One Max-slot array per declared shape in the same order; matching Vertex/Normal/Tangent channels. null only with no declared shapes.

lods

Optional Dictionary: positive threshold → shorter int[] addressing base vertices. Validate indices yourself; not a new vertex grid.

flags

Mesh.ArrayFormat flags for packing/update and custom-channel formats. Default 0; base channel bits are derived from arrays.

ClearBlendShapesvoid
# ClearBlendShapes
C#
public void ClearBlendShapes();

Removes blend definitions only when no surfaces exist. Call ClearSurfaces first. Does not itself emit Changed.

ClearSurfacesvoid
# ClearSurfaces
C#
public void ClearSurfaces();

Removes all surfaces and resets geometric Aabb. Retains blend names/mode, CustomAabb and ShadowMesh. Does not emit Changed and is not a full resource reset.

GetBlendShapeCountint
# GetBlendShapeCount
C#
public int GetBlendShapeCount();

Returns the declared shape count rather than surface count or active MeshInstance3D weight count.

Returns int

Declared shape count, including definitions retained after ClearSurfaces.

GetBlendShapeModeMesh.BlendShapeMode
# GetBlendShapeMode
C#
public Mesh.BlendShapeMode GetBlendShapeMode();

Reads the current mode, also exposed by BlendShapeMode. Initially Relative.

Returns Mesh.BlendShapeMode

Current Mesh.BlendShapeMode; Relative for a new mesh.

GetBlendShapeNameStringName
# GetBlendShapeName
C#
public StringName GetBlendShapeName(int index);

Reads a shape name in declaration order. An empty invalid-index fallback does not establish that a shape exists.

Parameters
NameTypeDefault
indexint—
index

Shape index from 0 to GetBlendShapeCount()-1 rather than a surface index.

Returns StringName

Current shape StringName; empty fallback for an invalid index.

GetCustomAabbAabb
# GetCustomAabb
C#
public Aabb GetCustomAabb();

Reads the CustomAabb culling override rather than merged geometric surface bounds.

Returns Aabb

Stored custom override; zero Aabb by default.

GetShadowMeshArrayMesh
# GetShadowMesh
C#
public ArrayMesh GetShadowMesh();

Returns the shared ShadowMesh reference or null. Does not copy the resource; do not release this alias ahead of its owner.

Returns ArrayMesh

Shared ArrayMesh reference or null, not a copy or separately owned object to Dispose early.

LightmapUnwrapError
# LightmapUnwrap
C#
public Error LightmapUnwrap(Transform3D transform, float texelSize);

Builds lightmap UV2 without baking lighting. Requires an unwrap callback, Triangles with normals, texelSize > 0 and no blend shapes. Uses transform scale and can rebuild vertices/indices. Work on a copy and inspect the result separately.

Parameters
NameTypeDefault
transformTransform3D—
texelSizefloat—
transform

Placement scale for UV2 density. The implementation extracts basis-column lengths; translation/rotation are not baked into vertices.

texelSize

Positive finite texel size in scaled-geometry units; smaller values increase required resolution.

Returns Error

Error.Ok on completed unwrap; Unconfigured without a callback, Unavailable for blend shapes/unsupported geometry, ParameterRangeError for texelSize ≤ 0. Also inspect other errors, new UV2 and diagnostics.

RegenNormalMapsvoid
# RegenNormalMaps
C#
public void RegenNormalMaps();

Rebuilds surfaces via SurfaceTool.GenerateTangents. Requires normals and UVs; does not generate normals or normal-map images. Does not guarantee names, blend shapes, LODs or custom-channel preservation.

SetBlendShapeModevoid
# SetBlendShapeMode
C#
public void SetBlendShapeMode(Mesh.BlendShapeMode mode);

Sets the mode also exposed by BlendShapeMode. Does not convert shape data or emit Changed.

Parameters
NameTypeDefault
modeMesh.BlendShapeMode—
mode

Relative or Normalized to match shape data. A blending mode rather than a conversion command.

SetBlendShapeNamevoid
# SetBlendShapeName
C#
public void SetBlendShapeName(int index, StringName name);

Renames a shape without changing its index/data. A conflict with another name receives the next available numeric suffix; does not emit Changed.

Parameters
NameTypeDefault
indexint—
nameStringName—
index

Shape index from 0 to GetBlendShapeCount()-1 rather than a surface index.

name

Shape name; conflicts automatically receive an available numeric suffix.

SetCustomAabbvoid
# SetCustomAabb
C#
public void SetCustomAabb(Aabb aabb);

Sets CustomAabb for culling and emits Changed. Does not alter geometric GetAabb or collision.

Parameters
NameTypeDefault
aabbAabb—
aabb

Finite bounds enclosing deformation; zero Aabb disables the override. Not new geometry.

SetShadowMeshvoid
# SetShadowMesh
C#
public void SetShadowMesh(ArrayMesh mesh);

Assigns a shared auxiliary mesh or null. Self-reference is rejected. Initialize the main mesh RID first; this method does not itself call GetRid or emit Changed.

Parameters
NameTypeDefault
meshArrayMesh—
mesh

Shared ArrayMesh with matching positions, or null to disable. Not this; the main RID must already be initialized.

SurfaceFindByNameint
# SurfaceFindByName
C#
public int SurfaceFindByName(string name);

Returns the first exact name match or -1. Names need not be unique; empty names participate in lookup too.

Parameters
NameTypeDefault
namestring—
name

Exact surface name string; uniqueness is not required.

Returns int

First matching index or -1 if no name matches.

SurfaceGetArrayIndexLenint
# SurfaceGetArrayIndexLen
C#
public int SurfaceGetArrayIndexLen(int surfIdx);

Surface Index element count; 0 for nonindexed geometry. Not triangle count.

Parameters
NameTypeDefault
surfIdxint—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

Returns int

Index count; 0 without Index, -1 on invalid surface index.

SurfaceGetArrayLenint
# SurfaceGetArrayLen
C#
public int SurfaceGetArrayLen(int surfIdx);

Surface vertex count rather than index, byte or triangle count.

Parameters
NameTypeDefault
surfIdxint—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

Returns int

Vertex count; -1 on invalid surface index.

SurfaceGetFormatMesh.ArrayFormat
# SurfaceGetFormat
C#
public Mesh.ArrayFormat SurfaceGetFormat(int surfIdx);

Bit mask of the stored format: channels, packing and flags. Use it to calculate layout rather than assuming every channel is a plain float array.

Parameters
NameTypeDefault
surfIdxint—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

Returns Mesh.ArrayFormat

Stored Mesh.ArrayFormat mask; 0 on diagnosed invalid surface index.

SurfaceGetNamestring
# SurfaceGetName
C#
public string SurfaceGetName(int surfIdx);

Returns a surface name, which can be empty or duplicated. Not a persistent unique ID.

Parameters
NameTypeDefault
surfIdxint—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

Returns string

Possibly empty name; an empty fallback is also used for an invalid surface index.

SurfaceGetPrimitiveTypeMesh.PrimitiveType
# SurfaceGetPrimitiveType
C#
public Mesh.PrimitiveType SurfaceGetPrimitiveType(int surfIdx);

Returns the surface primitive assembly mode. The invalid-index Lines fallback does not establish a valid surface.

Parameters
NameTypeDefault
surfIdxint—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

Returns Mesh.PrimitiveType

Stored primitive; Lines on diagnosed invalid surface index.

SurfaceRemovevoid
# SurfaceRemove
C#
public void SurfaceRemove(int surfIdx);

Removes one surface, shifts subsequent indices, clears Mesh cache, recomputes geometric Aabb and emits Changed. Update externally retained surface IDs yourself.

Parameters
NameTypeDefault
surfIdxint—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

SurfaceSetNamevoid
# SurfaceSetName
C#
public void SurfaceSetName(int surfIdx, string name);

Sets a surface name without uniqueness validation; emits Changed even when writing the same name again.

Parameters
NameTypeDefault
surfIdxint—
namestring—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

name

Exact surface name string; uniqueness is not required.

SurfaceUpdateAttributeRegion2 overloads
# SurfaceUpdateAttributeRegion · 1/2
C#
public void SurfaceUpdateAttributeRegion(int surfIdx, int offset, byte[] data);

Writes a nonempty byte block into the existing buffer for attributes (color, UV, custom). offset is in bytes. Requires exact layout and bounds; does not change topology/count or recompute Aabb/collision. Array/span overloads share semantics. Emits Changed; dummy backend does not perform the write.

Parameters
NameTypeDefault
surfIdxint—
offsetint—
databyte[]—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

offset

Byte offset inside the corresponding packed buffer; offset plus data length must fit its allocated range.

data

Nonempty bytes matching the current SurfaceGetFormat layout. Not a serialized Vector3[] or Variant values; the call does not grow the buffer.

# SurfaceUpdateAttributeRegion · 2/2
C#
public void SurfaceUpdateAttributeRegion(int surfIdx, int offset, ReadOnlySpan<byte> data);

Writes a nonempty byte block into the existing buffer for attributes (color, UV, custom). offset is in bytes. Requires exact layout and bounds; does not change topology/count or recompute Aabb/collision. Array/span overloads share semantics. Emits Changed; dummy backend does not perform the write.

Parameters
NameTypeDefault
surfIdxint—
offsetint—
dataReadOnlySpan<byte>—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

offset

Byte offset inside the corresponding packed buffer; offset plus data length must fit its allocated range.

data

Nonempty bytes matching the current SurfaceGetFormat layout. Not a serialized Vector3[] or Variant values; the call does not grow the buffer.

SurfaceUpdateSkinRegion2 overloads
# SurfaceUpdateSkinRegion · 1/2
C#
public void SurfaceUpdateSkinRegion(int surfIdx, int offset, byte[] data);

Writes a nonempty byte block into the existing buffer for bones and weights. offset is in bytes. Requires exact layout and bounds; does not change topology/count or recompute Aabb/collision. Array/span overloads share semantics. Emits Changed; dummy backend does not perform the write.

Parameters
NameTypeDefault
surfIdxint—
offsetint—
databyte[]—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

offset

Byte offset inside the corresponding packed buffer; offset plus data length must fit its allocated range.

data

Nonempty bytes matching the current SurfaceGetFormat layout. Not a serialized Vector3[] or Variant values; the call does not grow the buffer.

# SurfaceUpdateSkinRegion · 2/2
C#
public void SurfaceUpdateSkinRegion(int surfIdx, int offset, ReadOnlySpan<byte> data);

Writes a nonempty byte block into the existing buffer for bones and weights. offset is in bytes. Requires exact layout and bounds; does not change topology/count or recompute Aabb/collision. Array/span overloads share semantics. Emits Changed; dummy backend does not perform the write.

Parameters
NameTypeDefault
surfIdxint—
offsetint—
dataReadOnlySpan<byte>—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

offset

Byte offset inside the corresponding packed buffer; offset plus data length must fit its allocated range.

data

Nonempty bytes matching the current SurfaceGetFormat layout. Not a serialized Vector3[] or Variant values; the call does not grow the buffer.

SurfaceUpdateVertexRegion2 overloads
# SurfaceUpdateVertexRegion · 1/2
C#
public void SurfaceUpdateVertexRegion(int surfIdx, int offset, byte[] data);

Writes a nonempty byte block into the existing buffer for vertices and packed normals/tangents. offset is in bytes. Requires exact layout and bounds; does not change topology/count or recompute Aabb/collision. Array/span overloads share semantics. Emits Changed; dummy backend does not perform the write.

Parameters
NameTypeDefault
surfIdxint—
offsetint—
databyte[]—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

offset

Byte offset inside the corresponding packed buffer; offset plus data length must fit its allocated range.

data

Nonempty bytes matching the current SurfaceGetFormat layout. Not a serialized Vector3[] or Variant values; the call does not grow the buffer.

# SurfaceUpdateVertexRegion · 2/2
C#
public void SurfaceUpdateVertexRegion(int surfIdx, int offset, ReadOnlySpan<byte> data);

Writes a nonempty byte block into the existing buffer for vertices and packed normals/tangents. offset is in bytes. Requires exact layout and bounds; does not change topology/count or recompute Aabb/collision. Array/span overloads share semantics. Emits Changed; dummy backend does not perform the write.

Parameters
NameTypeDefault
surfIdxint—
offsetint—
dataReadOnlySpan<byte>—
surfIdx

Current surface index from 0 to GetSurfaceCount()-1; removal can shift indices.

offset

Byte offset inside the corresponding packed buffer; offset plus data length must fit its allocated range.

data

Nonempty bytes matching the current SurfaceGetFormat layout. Not a serialized Vector3[] or Variant values; the call does not grow the buffer.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.