MeshGeometry.fromArrays constructor

MeshGeometry.fromArrays({
  1. required Float32List positions,
  2. Float32List? normals,
  3. Float32List? texCoords,
  4. Float32List? colors,
  5. List<int>? indices,
  6. PrimitiveType primitiveType = gpu.PrimitiveType.triangle,
  7. GeometryStorage storage = GeometryStorage.fixed,
})

Builds a mesh from structure-of-arrays vertex attributes.

positions is required and holds three floats per vertex. The optional attributes hold, per vertex, three floats for normals, two for texCoords, and four for colors; each must match the vertex count implied by positions when supplied. Absent attributes fall back to defaults: texture coordinate (0, 0) and color opaque white.

When normals is omitted and primitiveType is a triangle list, area-weighted vertex normals are generated from the faces; for line and point primitives, absent normals keep their default. indices, when supplied, is an index list; when omitted a triangle mesh must have a vertex count that is a multiple of three.

primitiveType selects how the vertex/index data is assembled into primitives when drawn, and defaults to a triangle list.

storage selects whether the mesh can later be updated in place. An updatable mesh fixes its indexed-or-not state at construction: supplying indices makes rebuild require indices thereafter, and omitting them makes it reject them. To start empty, pass a zero-length positions array with GeometryStorage.updatable.

Implementation

MeshGeometry.fromArrays({
  required Float32List positions,
  Float32List? normals,
  Float32List? texCoords,
  Float32List? colors,
  List<int>? indices,
  gpu.PrimitiveType primitiveType = gpu.PrimitiveType.triangle,
  this.storage = GeometryStorage.fixed,
}) {
  if (positions.length % 3 != 0) {
    throw ArgumentError(
      'positions has ${positions.length} floats; expected a multiple of '
      'three (one vec3 per vertex)',
    );
  }
  final vertexCount = positions.length ~/ 3;
  this.primitiveType = primitiveType;

  // Normals are generated from triangle faces; line and point
  // geometry has none, so absent normals are left at their default.
  final resolvedNormals =
      normals ??
      (vertexCount > 0 && primitiveType == gpu.PrimitiveType.triangle
          ? InterleavedLayoutAdapter.generateNormals(
            positions: positions,
            vertexCount: vertexCount,
            indices: indices,
          )
          : null);

  if (storage == GeometryStorage.fixed) {
    _uploadFixed(
      positions,
      vertexCount,
      resolvedNormals,
      texCoords,
      colors,
      indices,
    );
  } else {
    _indexed = indices != null;
    _setCpuStreams(
      positions,
      vertexCount,
      resolvedNormals,
      texCoords,
      colors,
    );
    _vertexCapacity = nextBufferCapacity(vertexCount);
    _vertexBuffer = gpu.gpuContext.createDeviceBuffer(
      gpu.StorageMode.hostVisible,
      _vertexCapacity * kInterleavedVertexBytes,
    );
    _liveVertexCount = vertexCount;
    _uploadVertexBytes();
    if (_indexed) _uploadIndices(indices!);
    _recomputeBounds();
  }
}