computeBounds function
@param {BufferGeometry} geometry @param {GLTF.Primitive} primitiveDef @param {GLTFParser} parser
Implementation
void computeBounds(BufferGeometry geometry, Map<String, dynamic> primitiveDef, GLTFParser parser) {
Map<String, dynamic> attributes = primitiveDef["attributes"];
final box = BoundingBox();
if (attributes["POSITION"] != null) {
final accessor = parser.json["accessors"][attributes["POSITION"]];
final min = accessor["min"];
final max = accessor["max"];
// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.
if (min != null && max != null) {
box.set(Vector3(min[0].toDouble(), min[1].toDouble(), min[2].toDouble()),
Vector3(max[0].toDouble(), max[1].toDouble(), max[2].toDouble()));
// todo normalized is bool ? int ?
if (accessor["normalized"] != null &&
accessor["normalized"] != false &&
accessor["normalized"] != 0) {
final boxScale = getNormalizedComponentScale( webglComponentTypes[accessor.componentType]);
box.min.scale(boxScale);
box.max.scale(boxScale);
}
}
else {
console.warning('GLTFLoader: Missing min/max properties for accessor POSITION.');
return;
}
} else {
return;
}
final targets = primitiveDef["targets"];
if (targets != null) {
final maxDisplacement = Vector3();
final vector = Vector3();
for (int i = 0, il = targets.length; i < il; i++) {
final target = targets[i];
if (target["POSITION"] != null) {
final accessor = parser.json["accessors"][target["POSITION"]];
final min = accessor["min"];
final max = accessor["max"];
// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.
if (min != null && max != null) {
// we need to get max of absolute components because target weight is [-1,1]
vector.setX(math.max<double>(min[0].abs().toDouble(), max[0].abs().toDouble()));
vector.setY(math.max<double>(min[1].abs().toDouble(), max[1].abs().toDouble()));
vector.setZ(math.max<double>(min[2].abs().toDouble(), max[2].abs().toDouble()));
if (accessor["normalized"] == true) {
final boxScale = getNormalizedComponentScale(webglComponentTypes[accessor.componentType]);
vector.scale(boxScale);
}
// Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative
// to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets
// are used to implement key-frame animations and as such only two are active at a time - this results in very large
// boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size.
maxDisplacement.max(vector);
}
else {
console.warning('GLTFLoader: Missing min/max properties for accessor POSITION.');
}
}
}
// As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets.
box.expandByVector(maxDisplacement);
}
geometry.boundingBox = box;
final sphere = BoundingSphere();
box.getCenter(sphere.center);
sphere.radius = box.min.distanceTo(box.max) / 2;
geometry.boundingSphere = sphere;
}