solidPart static method
part scaled by (sx, sy, sz) as a physics-engine shape, placed where
it is; null for a hull of too few points.
Implementation
static Shape3D? solidPart(SolidPart part, double sx, double sy, double sz) {
final ax = sx.abs(), ay = sy.abs(), az = sz.abs();
Shape3D at(Shape3D shape, double x, double y, double z) =>
x == 0 && y == 0 && z == 0
? shape
: TransformedShape3D(shape, x: x * sx, y: y * sy, z: z * sz);
switch (part) {
case SolidBox(
:final halfX,
:final halfY,
:final halfZ,
:final x,
:final y,
:final z,
):
return at(
BoxShape3D(
math.max(halfX * ax, minExtent),
math.max(halfY * ay, minExtent),
math.max(halfZ * az, minExtent),
),
x,
y,
z,
);
case SolidSphere(:final radius, :final x, :final y, :final z):
return at(
SphereShape3D(
math.max(radius * math.max(ax, math.max(ay, az)), minExtent),
),
x,
y,
z,
);
case SolidCapsule(
:final halfHeight,
:final radius,
:final x,
:final y,
:final z,
):
final r = math.max(radius * math.max(ax, az), minExtent);
final half = (halfHeight + radius) * ay - r;
return at(
half <= 1e-4 ? SphereShape3D(r) : CapsuleShape3D(half, r),
x,
y,
z,
);
case SolidCylinder(
:final halfHeight,
:final radius,
:final x,
:final y,
:final z,
):
return at(
CylinderShape3D(
math.max(halfHeight * ay, minExtent),
math.max(radius * math.max(ax, az), minExtent),
),
x,
y,
z,
);
case SolidHull(:final points):
if (points.length < 12) return null;
final scaled = Float32List(points.length);
for (var i = 0; i < points.length; i += 3) {
scaled[i] = points[i] * sx;
scaled[i + 1] = points[i + 1] * sy;
scaled[i + 2] = points[i + 2] * sz;
}
return ConvexHullShape3D(scaled);
case SolidMesh(:final positions, :final indices):
if (indices.length < 3) return null;
final scaled = Float32List(positions.length);
for (var i = 0; i < positions.length; i += 3) {
scaled[i] = positions[i] * sx;
scaled[i + 1] = positions[i + 1] * sy;
scaled[i + 2] = positions[i + 2] * sz;
}
var turned = indices;
// A mirror turns triangles inside out; turn them back.
if (sx * sy * sz < 0) {
turned = Uint32List.fromList(indices);
for (var i = 0; i + 2 < turned.length; i += 3) {
final t = turned[i + 1];
turned[i + 1] = turned[i + 2];
turned[i + 2] = t;
}
}
return MeshShape3D(scaled, turned);
case SolidHeightField(
:final heights,
:final sampleCount,
:final cellSize,
:final x,
:final y,
:final z,
):
if (sampleCount < 4 || heights.length < sampleCount * sampleCount) {
return null;
}
final scaled = Float32List(sampleCount * sampleCount);
for (var i = 0; i < scaled.length; i++) {
final h = heights[i];
scaled[i] = h >= SolidHeightField.holeHeight ? h : h * ay;
}
return at(
HeightFieldShape3D(scaled, sampleCount, cellSize * ax),
x,
y,
z,
);
}
}