extractMeshData method
Copies this geometry's retained CPU vertex/index data out as an isolate-transferable MeshData snapshot.
The snapshot is always a copy (never a view of engine memory) with structure-of-arrays attributes regardless of how the data is stored internally, so it is safe to send to a background isolate and derive new geometry from (see MeshData.unweld, MeshData.extractEdges). Attributes the engine did not retain come back null; skinned geometry returns bind-pose positions and no joint data.
Throws a StateError when isReadable is false.
Implementation
MeshData extractMeshData() {
final interleaved = _cpuVertices;
final soaPositions = _cpuPositions;
if (interleaved == null && soaPositions == null) {
throw StateError(
'This geometry retains no CPU vertex data to extract '
'(isReadable is false). Caller-managed vertex buffers are not '
'readable.',
);
}
Float32List positions;
Float32List? normals;
Float32List? texCoords;
Float32List? colors;
if (interleaved != null) {
// Interleaved unskinned (12 floats) or skinned (20 floats, of which
// the leading 12 match the unskinned layout) vertices.
final stride = this is SkinnedGeometry ? 20 : 12;
final floats = Float32List.sublistView(interleaved);
positions = Float32List(_vertexCount * 3);
normals = Float32List(_vertexCount * 3);
texCoords = Float32List(_vertexCount * 2);
colors = Float32List(_vertexCount * 4);
for (var v = 0; v < _vertexCount; v++) {
final base = v * stride;
positions[v * 3] = floats[base];
positions[v * 3 + 1] = floats[base + 1];
positions[v * 3 + 2] = floats[base + 2];
normals[v * 3] = floats[base + 3];
normals[v * 3 + 1] = floats[base + 4];
normals[v * 3 + 2] = floats[base + 5];
texCoords[v * 2] = floats[base + 6];
texCoords[v * 2 + 1] = floats[base + 7];
colors[v * 4] = floats[base + 8];
colors[v * 4 + 1] = floats[base + 9];
colors[v * 4 + 2] = floats[base + 10];
colors[v * 4 + 3] = floats[base + 11];
}
} else {
positions = Float32List.fromList(soaPositions!);
final n = _cpuNormals;
final t = _cpuTexCoords;
final c = _cpuColors;
normals = n == null ? null : Float32List.fromList(n);
texCoords = t == null ? null : Float32List.fromList(t);
colors = c == null ? null : Float32List.fromList(c);
}
List<int>? indices;
final indexBytes = _cpuIndices;
if (indexBytes != null && _indexCount > 0) {
indices = _indexType == gpu.IndexType.int32
? Uint32List.fromList(Uint32List.sublistView(indexBytes))
: Uint16List.fromList(Uint16List.sublistView(indexBytes));
}
return MeshData(
positions: positions,
vertexCount: _vertexCount,
normals: normals,
texCoords: texCoords,
colors: colors,
indices: indices,
primitiveType: primitiveType,
customAttributes: {
for (final entry in _customAttributes.entries)
entry.key: MeshAttributeData(
Float32List.fromList(entry.value.data),
components: entry.value.components,
),
},
);
}