transformed method

MeshData transformed(
  1. Matrix4 transform
)

This mesh placed by transform.

Positions move as points. normals are carried by the inverse transpose, so a non-uniform scale leaves them perpendicular to the surface, and tangents by transform itself; both are renormalized. Every other attribute carries through untouched.

A mirroring transform reverses orientation, so it flips the tangent handedness and reverses triangle winding to match. The renderer flips winding per node for a mirrored node transform, which cannot help once the mirror lives in the vertices. An unindexed triangle list comes back indexed, since that is where its winding lives.

Implementation

MeshData transformed(vm.Matrix4 transform) {
  final m = transform.storage;
  final outPositions = Float32List(vertexCount * 3);
  for (var v = 0; v < vertexCount; v++) {
    final i = v * 3;
    final x = positions[i];
    final y = positions[i + 1];
    final z = positions[i + 2];
    outPositions[i] = m[0] * x + m[4] * y + m[8] * z + m[12];
    outPositions[i + 1] = m[1] * x + m[5] * y + m[9] * z + m[13];
    outPositions[i + 2] = m[2] * x + m[6] * y + m[10] * z + m[14];
  }

  final linear = transform.getRotation();
  final mirrored = linear.determinant() < 0;

  Float32List? outNormals;
  final srcNormals = normals;
  if (srcNormals != null) {
    // A singular linear part has no inverse transpose; carrying normals
    // through unchanged beats emitting NaNs.
    final normalMatrix = vm.Matrix3.copy(linear);
    if (normalMatrix.invert() == 0.0) {
      normalMatrix.setFrom(linear);
    } else {
      normalMatrix.transpose();
    }
    outNormals = _transformVectors(srcNormals, normalMatrix, 3);
  }

  Float32List? outTangents;
  final srcTangents = tangents;
  if (srcTangents != null) {
    outTangents = _transformVectors(srcTangents, linear, 4);
    if (mirrored) {
      for (var v = 0; v < vertexCount; v++) {
        outTangents[v * 4 + 3] = -outTangents[v * 4 + 3];
      }
    }
  }

  return MeshData(
    positions: outPositions,
    vertexCount: vertexCount,
    normals: outNormals,
    texCoords: texCoords,
    texCoords1: texCoords1,
    colors: colors,
    tangents: outTangents,
    indices: mirrored ? _reversedWinding() : indices,
    primitiveType: primitiveType,
    customAttributes: customAttributes,
  );
}