ImporterMesh
Intermediate CPU import-surface data that builds an ArrayMesh.
ImporterMesh is a RefCounted preparation-data object rather than a directly drawable Mesh or Entity. Add surfaces with AddSurface, set blend mode, lightmap hint and LODs, then call GetMesh. Assign the resulting ArrayMesh to MeshInstance3D or save it as a resource.
using var staged = new ImporterMesh();
using var arrays = new Reckfell.Collections.Array();
arrays.Resize((int)Mesh.ArrayType.Max);
arrays[(int)Mesh.ArrayType.Vertex] = new Vector3[] {
Vector3.Zero, 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 };
staged.AddSurface(Mesh.PrimitiveType.Triangles, arrays, name: "part");
using var mesh = staged.GetMesh();
int vertexCount = mesh.SurfaceGetArrayLen(0); // 4The example creates geometry without a visible instance/material. To display it, assign mesh to a consumer and keep it alive throughout use; the example using scope ends its lifetime after inspecting data. Finish staging before constructing the result. Default blend mode here is Normalized, whereas a new ArrayMesh defaults to Relative.
AddSurface takes exactly Mesh.ArrayType.Max slots with nonempty Vector3 positions. Prepare consistent channel lengths and valid indices. It does not validate all geometry later packed by ArrayMesh. GetSurfaceFormat returns supplied flags rather than a computed channel mask: 0 does not mean no vertices. Primary flags type is ulong; the uint overload forwards its value.
Unlike ArrayMesh, AddSurface retains a shared Array container; GetSurfaceArrays and GetSurfaceBlendShapeArrays return aliases. Replacing a slot changes staging data and the original container. AsVector3Array gives a managed copy, however: explicitly reassign it to the slot after editing. Copy containers beforehand for independent staging; Material resources can still remain shared. Shared-array edits neither invalidate the result cache nor emit Changed.
GetMesh caches its result and repeatedly returns the same reference. AddSurface, SetSurfaceName and SetSurfaceMaterial invalidate the cache, but an already-returned ArrayMesh remains the separate old result. SetBlendShapeMode and SetLightmapSizeHint do not invalidate it. Set them before the first GetMesh; reading again does not update the old resource. baseMesh is used only on initial construction and is not cleared: surfaces are appended. Supply an empty dedicated ArrayMesh for a controlled result rather than a resource that must not be mutated.
Declare shape names before surfaces. Colons become underscores without uniqueness enforcement. Every declared shape needs a Max-slot array with matching vertex count. Duplicate names can become different names when converted to ArrayMesh, so enforce uniqueness yourself. Staged LODs hold a numeric threshold and index list; the final renderer requires a positive threshold and a list shorter than the base. Generate LODs before the first GetMesh and inspect their quality separately.
FromMesh copies surfaces, blend data, LODs, resource name and metadata; Material remains shared. It uses ArrayMesh surface names, falling back to Material.ResourceName when empty. It is not a complete settings transfer: lightmap hint and shadow mesh are not copied. Clear removes surfaces, shape names and cache while retaining blend mode and lightmap hint; no automatic Changed notification occurs.
MergeImporterMeshes applies relative Transform3D values to static geometry. With deduplicateSurfaces = true, surfaces with matching name, primitive and flags can combine despite different materials: the first material wins. Disable deduplication for different materials. It concatenates vertices and offsets indices rather than welding. Blend shapes and LODs are discarded with warnings. Skeletons/bind poses are not remapped; nonuniform scale does not use inverse-transpose normals, and reflections leave tangent handedness unchanged. Do not treat it as a universal animated-model merge.
Hidden _Data is for serialization rather than safe editing. The current getter writes blend_shapes but the setter reads b_shapes; mode/lightmap hint are absent from the dictionary. Do not rely on a complete _Data roundtrip.
26 Windows headless checks covered staging, aliases, cache, a simple blend/LOD package and static surface merging. Visible rendering, new LOD generation, reflected/nonuniform/skinned merging and blend-shape serialization were not tested in this pass. Previously reviewed LOD prose retains its separate evidence report.
Declarations checked against C# SDK 1.0.0. Expand a name to see declarations and documentation.
Constructors1
ImporterMeshConstructor
public ImporterMesh();Creates an owned empty staging RefCounted: no surfaces/shapes, Normalized mode, lightmap hint (0,0). Not a drawable Mesh.
Properties1
_DataProperty
public Reckfell.Collections.Dictionary _Data { get; set; }Hidden serialization Dictionary containing staged arrays/shared references. Not an independent copy of the entire resource. Getter writes blend_shapes while setter reads b_shapes; mode/hint are absent. Not a guaranteed lossless roundtrip.
Methods26
AddBlendShapevoid
public void AddBlendShape(string name);Adds a name before surfaces. Replaces : with _ without ensuring uniqueness. Prevent duplicates beforehand to avoid different names after GetMesh.
| Name | Type | Default |
|---|---|---|
name | string | — |
nameShape name before : → _ sanitization; ensure uniqueness yourself.
AddSurface2 overloads
public void AddSurface(Mesh.PrimitiveType primitive, Reckfell.Collections.Array arrays, Reckfell.Collections.Array<Reckfell.Collections.Array> blendShapes, Reckfell.Collections.Dictionary lods, Material material, string name, uint flags);Appends a staging surface and invalidates GetMesh cache. Retains shared arrays/blend containers and material/name/flags; does not emit Changed. Input validation is partial: prepare valid channels/indices before building ArrayMesh. ulong is primary; uint is a forwarding overload.
| Name | Type | Default |
|---|---|---|
primitive | Mesh.PrimitiveType | — |
arrays | Reckfell.Collections.Array | — |
blendShapes | Reckfell.Collections.Array<Reckfell.Collections.Array> | — |
lods | Reckfell.Collections.Dictionary | — |
material | Material | — |
name | string | — |
flags | uint | — |
primitiveAssembly mode. For Triangles prepare a corner/index count divisible by three.
arraysExactly Mesh.ArrayType.Max slots with nonempty Vector3[] Vertex and consistent channels. The container is retained shared.
blendShapesOne Max-slot Array per declared shape in order, with the same vertex count. null only without declared shapes.
lodsOptional threshold → int[] Dictionary. Final ArrayMesh needs positive thresholds and shorter valid lists; staging does not fully validate this.
materialShared Material reference or null; not cloned.
nameStaged surface name; empty/duplicate names are allowed.
flagsulong packing/custom-format flags, default 0. The uint overload forwards to ulong without deriving channel flags from arrays.
public void AddSurface(Mesh.PrimitiveType primitive, Reckfell.Collections.Array arrays, Reckfell.Collections.Array<Reckfell.Collections.Array> blendShapes = null, Reckfell.Collections.Dictionary lods = null, Material material = null, string name = "", ulong flags = 0);Appends a staging surface and invalidates GetMesh cache. Retains shared arrays/blend containers and material/name/flags; does not emit Changed. Input validation is partial: prepare valid channels/indices before building ArrayMesh. ulong is primary; uint is a forwarding overload.
| Name | Type | Default |
|---|---|---|
primitive | Mesh.PrimitiveType | — |
arrays | Reckfell.Collections.Array | — |
blendShapes | Reckfell.Collections.Array<Reckfell.Collections.Array> | null |
lods | Reckfell.Collections.Dictionary | null |
material | Material | null |
name | string | "" |
flags | ulong | 0 |
primitiveAssembly mode. For Triangles prepare a corner/index count divisible by three.
arraysExactly Mesh.ArrayType.Max slots with nonempty Vector3[] Vertex and consistent channels. The container is retained shared.
blendShapesOne Max-slot Array per declared shape in order, with the same vertex count. null only without declared shapes.
lodsOptional threshold → int[] Dictionary. Final ArrayMesh needs positive thresholds and shorter valid lists; staging does not fully validate this.
materialShared Material reference or null; not cloned.
nameStaged surface name; empty/duplicate names are allowed.
flagsulong packing/custom-format flags, default 0. The uint overload forwards to ulong without deriving channel flags from arrays.
Clearvoid
public void Clear();Removes surfaces, blend-shape names and result cache. Retains blend mode/lightmap size hint; not a complete settings reset and does not emit Changed.
FromMeshImporterMesh
public static ImporterMesh FromMesh(Mesh mesh);Creates ImporterMesh from Mesh: surfaces, shapes/LODs, shared Materials, name and metadata. Falls back to material name for an empty surface name. Does not copy lightmap hint, shadow mesh or every other resource setting. null yields an empty ImporterMesh.
| Name | Type | Default |
|---|---|---|
mesh | Mesh | — |
meshSource Mesh with readable surfaces, or null for an empty result; not a full snapshot of every setting.
ImporterMeshNew owned ImporterMesh, empty for null. Materials and some data can remain shared.
GenerateLodsvoid
public void GenerateLods(float normalMergeAngle, float normalSplitAngle, Reckfell.Collections.Array boneTransformArray);Prepares additional triangle-surface index LODs. Call after AddSurface and before the first GetMesh. Source skips surfaces without indices; a call alone does not guarantee generated LODs. Check GetSurfaceLodCount and result quality.
| Name | Type | Default |
|---|---|---|
normalMergeAngle | float | — |
normalSplitAngle | float | — |
boneTransformArray | Reckfell.Collections.Array | — |
normalMergeAngleNormal merge angle in degrees; the example uses 60. Controls simplification preparation, not LOD switching distance.
normalSplitAnglePresent in the current signature but unused by the implementation. The example passes 0; changing it does not establish a changed result.
boneTransformArrayTransform3D array for bones when applicable. The unskinned static sphere passes an empty Array. Skinned/blend-shape cases are outside this example.
GetBlendShapeCountint
public int GetBlendShapeCount();Returns the staged declared shape count; 0 after Clear.
intNonnegative declared shape count.
GetBlendShapeModeMesh.BlendShapeMode
public Mesh.BlendShapeMode GetBlendShapeMode();Returns the staging mode, initially Normalized. It can differ from an already-cached GetMesh result.
Mesh.BlendShapeModeStaging Mesh.BlendShapeMode, initially Normalized.
GetBlendShapeNamestring
public string GetBlendShapeName(int blendShapeIdx);Reads the name after : becomes _. Duplicates are possible; not a guaranteed unique identifier.
| Name | Type | Default |
|---|---|---|
blendShapeIdx | int | — |
blendShapeIdxDeclared shape index from 0 to GetBlendShapeCount()-1. For the array getter the shape must exist in the selected surface.
stringStored string or an empty invalid-index fallback.
GetLightmapSizeHintVector2I
public Vector2I GetLightmapSizeHint();Reads the stored lightmap-size hint. Does not measure a baked texture/UV2 and can differ from a cached ArrayMesh.
Vector2IHint Vector2I; (0,0) for a new object.
GetMeshArrayMesh
public ArrayMesh GetMesh(ArrayMesh baseMesh = null);Obtains the prepared surfaces/LODs as an ArrayMesh. The result is cached: generate LODs before the first GetMesh rather than assuming repeated reads rebuild a previously returned resource.
| Name | Type | Default |
|---|---|---|
baseMesh | ArrayMesh | null |
baseMeshOptional ArrayMesh for initial result construction. Source uses it when no mesh is cached. Do not supply a resource that must not be modified.
ArrayMeshArrayMesh with prepared LODs, or null if no result can be obtained. The example saves .rdata, reloads without cache and re-verifies distant LOD through rendered primitive counts.
GetSurfaceArraysReckfell.Collections.Array
public Reckfell.Collections.Array GetSurfaceArrays(int surfaceIdx);Returns an alias of the shared surface Array. Slot replacement changes staging without invalidating GetMesh cache. Packed arrays obtained through AsVector3Array and similar methods are managed copies. Dispose your wrapper after use.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
surfaceIdxCurrent staging-surface index from 0 to GetSurfaceCount()-1.
Reckfell.Collections.ArrayOwned wrapper over the shared Array, not an independent snapshot. Empty container on invalid index.
GetSurfaceBlendShapeArraysReckfell.Collections.Array
public Reckfell.Collections.Array GetSurfaceBlendShapeArrays(int surfaceIdx, int blendShapeIdx);Returns an alias of one shared surface-shape Array. Slot edits affect staging and the original container without updating a built ArrayMesh.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
blendShapeIdx | int | — |
surfaceIdxCurrent staging-surface index from 0 to GetSurfaceCount()-1.
blendShapeIdxDeclared shape index from 0 to GetBlendShapeCount()-1. For the array getter the shape must exist in the selected surface.
Reckfell.Collections.ArrayOwned wrapper over the shared shape Array; empty container on diagnosed invalid indices.
GetSurfaceCountint
public int GetSurfaceCount();Staged surface count rather than the count of an arbitrary supplied baseMesh.
intStaged surface count; 0 for a new/cleared object.
GetSurfaceFormatulong
public ulong GetSurfaceFormat(int surfaceIdx);Returns flags supplied to AddSurface rather than deriving channels from arrays. 0 is valid with vertex/index data. Read actual packed layout from the built ArrayMesh.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
surfaceIdxCurrent staging-surface index from 0 to GetSurfaceCount()-1.
ulongSupplied ulong flags; 0 is also the invalid-surface-index fallback.
GetSurfaceLodCountint
public int GetSurfaceLodCount(int surfaceIdx);Reads the surface additional LOD count. Counts resource data levels, not visible objects or the renderer’s currently selected level.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
surfaceIdxExisting surface index starting at 0.
intAdditional level count; 0 means none. The full-detail base geometry is not included.
GetSurfaceLodIndicesint[]
public int[] GetSurfaceLodIndices(int surfaceIdx, int lodIdx);Gets one prepared LOD triangle-index array. Fewer indices reduce submitted primitives, not unload the source mesh or create a separate entity.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
lodIdx | int | — |
surfaceIdxSurface index.
lodIdxAdditional LOD index from 0 through GetSurfaceLodCount(surfaceIdx)-1.
int[]Integer index array. Valid triangle data has length divisible by 3; every tested additional level is shorter than the base array.
GetSurfaceLodSizefloat
public float GetSurfaceLodSize(int surfaceIdx, int lodIdx);Reads the level metric used for LOD selection. Source derives it from simplification error multiplied by geometry scale, not a ready-made world-space camera distance.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
lodIdx | int | — |
surfaceIdxSurface index.
lodIdxAdditional LOD index.
floatLevel error/scale metric. Actual selection also depends on projection, distance, object scale, LodBias and viewport threshold.
GetSurfaceMaterialMaterial
public Material GetSurfaceMaterial(int surfaceIdx);Returns the shared Material reference or null, not a copy. Do not release an alias ahead of its owner.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
surfaceIdxCurrent staging-surface index from 0 to GetSurfaceCount()-1.
MaterialShared Material or null; diagnosed invalid indices also return null.
GetSurfaceNamestring
public string GetSurfaceName(int surfaceIdx);Returns the staged name, possibly empty/duplicated. Not a persistent unique ID.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
surfaceIdxCurrent staging-surface index from 0 to GetSurfaceCount()-1.
stringName or empty string; emptiness does not establish a valid index.
GetSurfacePrimitiveTypeMesh.PrimitiveType
public Mesh.PrimitiveType GetSurfacePrimitiveType(int surfaceIdx);Reads the staged surface primitive. Invalid-index fallback Max is not valid geometry.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
surfaceIdxCurrent staging-surface index from 0 to GetSurfaceCount()-1.
Mesh.PrimitiveTypeStored primitive, or Max on invalid index.
MergeImporterMeshesImporterMesh
public static ImporterMesh MergeImporterMeshes(Reckfell.Collections.Array<ImporterMesh> importerMeshes, Reckfell.Collections.Array<Transform3D> relativeTransforms, bool deduplicateSurfaces = true);Merges static data using relative Transform3D values. By default equal name/primitive/flags combine without comparing Material, retaining the first. Not welding. Drops blend shapes/LODs with warnings and does not remap skeletons. Pass false for different materials; inspect nonuniform/reflected normals/tangents separately.
| Name | Type | Default |
|---|---|---|
importerMeshes | Reckfell.Collections.Array<ImporterMesh> | — |
relativeTransforms | Reckfell.Collections.Array<Transform3D> | — |
deduplicateSurfaces | bool | true |
importerMeshesNonempty typed array of nonnull ImporterMesh resources. Use consistent static 3D surfaces for a safe general case.
relativeTransformsOne Transform3D per input mesh in matching order, from its local space into result space.
deduplicateSurfacestrue combines matching name/primitive/flags without material checks. false retains separate surfaces and distinguishes conflicting names with suffixes.
ImporterMeshNew owned ImporterMesh, or null for rejected input. A nonnull result does not guarantee material, animation or shading fidelity.
SetBlendShapeModevoid
public void SetBlendShapeMode(Mesh.BlendShapeMode mode);Changes the staging mode without converting arrays, invalidating GetMesh cache or emitting Changed. Set before initial construction.
| Name | Type | Default |
|---|---|---|
mode | Mesh.BlendShapeMode | — |
modeNormalized or Relative to match prepared data; does not update a cached result automatically.
SetLightmapSizeHintvoid
public void SetLightmapSizeHint(Vector2I size);Stores a hint for subsequent ArrayMesh construction. Does not create UV2/a texture or invalidate an existing cache.
| Name | Type | Default |
|---|---|---|
size | Vector2I | — |
sizeNonnegative hint dimensions in texels; (0,0) means no specified hint. Not a generation command.
SetSurfaceMaterialvoid
public void SetSurfaceMaterial(int surfaceIdx, Material material);Changes the staged shared material reference and invalidates GetMesh cache. Already-returned ArrayMesh resources remain unchanged; no Changed notification.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
material | Material | — |
surfaceIdxCurrent staging-surface index from 0 to GetSurfaceCount()-1.
materialShared Material reference or null; not cloned.
SetSurfaceNamevoid
public void SetSurfaceName(int surfaceIdx, string name);Changes the staged name and invalidates GetMesh cache. Does not enforce uniqueness, edit the old result or emit Changed.
| Name | Type | Default |
|---|---|---|
surfaceIdx | int | — |
name | string | — |
surfaceIdxCurrent staging-surface index from 0 to GetSurfaceCount()-1.
nameStaged surface name; empty/duplicate names are allowed.