In three.js, I have a Points object and an InstancedMesh object. They both contain points/instances at the following locations:
const pointsData = [
{ x: -7505.97314453125, y: 182.7720489501953, z: 6319.98291015625 },
{ x: -3888.849853515625, y: 104.75480651855469, z: -8840.5166015625 },
{ x: 6898.529296875, y: 342.9034423828125, z: -495.22833251953125 },
{ x: 10786.9365234375, y: 311.8286437988281, z: 5985.064453125 },
];
The instances in the InstancedMesh are very tiny spheres with radius = 0.001 to mimic “points”.
When I calculate the BoundingSphere for the Points geometry and then for the InstancedMesh, and compare each of their BoundingSpheres, I get significantly different BoundingSphere values (center and radius) between the Points and InstancedMesh objects, even though they are using the same point/instance locations. The difference outweighs any effect that the tiny sphere geometry radius may have. Here are the values:
points.geometry.boundingSphere.center
x: 1640.481689453125
y: 223.8291244506836
z: -1260.266845703125
points.geometry.boundingSphere.radius
11879.373218935876
instancedMesh.boundingSphere.center
x: -807.2474263273366
y: 204.7621198590103
z: 137.41963115252497
instancedMesh.boundingSphere.radius
12985.820753310756
Is this a bug? Or am I doing something wrong? Here is my code:
JSFiddle: Edit fiddle - JSFiddle - Code Playground
import * as THREE from 'three';
(async function () {
const renderer = new THREE.WebGPURenderer({});
await renderer.init();
renderer.outputColorSpace = THREE.LinearSRGBColorSpace;
const scene = new THREE.Scene();
const body = document.body;
const camera = new THREE.PerspectiveCamera(
70,
body.offsetWidth / body.offsetHeight,
0.01,
1000,
);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 20;
scene.add(camera);
const canvas = renderer.domElement;
canvas.style.position = 'absolute';
canvas.style.inset = '0';
body.appendChild(canvas);
setCanvasSize();
function setCanvasSize() {
renderer.setSize(body.offsetWidth, body.offsetHeight);
camera.aspect = body.offsetWidth / body.offsetHeight;
camera.updateProjectionMatrix();
setTimeout(setCanvasSize, 1000);
}
const pointsData = [
{ x: -7505.97314453125, y: 182.7720489501953, z: 6319.98291015625 },
{ x: -3888.849853515625, y: 104.75480651855469, z: -8840.5166015625 },
{ x: 6898.529296875, y: 342.9034423828125, z: -495.22833251953125 },
{ x: 10786.9365234375, y: 311.8286437988281, z: 5985.064453125 },
];
{
const positions = new Float32Array(pointsData.length * 3);
pointsData.forEach((p, i) => {
positions[i * 3] = p.x;
positions[i * 3 + 1] = p.y;
positions[i * 3 + 2] = p.z;
});
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.computeBoundingBox();
geometry.computeBoundingSphere();
const center = geometry.boundingSphere.center;
document.getElementById('pointsCenterElem').innerHTML = `
x: ${center.x}<br/>
y: ${center.y}<br/>
z: ${center.z}
`;
const radius = geometry.boundingSphere.radius;
document.getElementById('pointsRadiusElem').innerHTML = radius;
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.1,
});
const points = new THREE.Points(geometry, material);
scene.add(points);
}
{
const geometry = new THREE.SphereGeometry(0.001, 8, 8);
geometry.computeBoundingBox();
geometry.computeBoundingSphere();
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
});
const instancedMesh = new THREE.InstancedMesh(
geometry,
material,
pointsData.length,
);
const temp = new THREE.Object3D();
pointsData.forEach((p, i) => {
temp.position.set(p.x, p.y, p.z);
temp.updateMatrix();
instancedMesh.setMatrixAt(i, temp.matrix);
});
instancedMesh.computeBoundingBox();
instancedMesh.computeBoundingSphere();
const center = instancedMesh.boundingSphere.center;
document.getElementById('instancedMeshCenterElem').innerHTML = `
x: ${center.x}<br/>
y: ${center.y}<br/>
z: ${center.z}
`;
const radius = instancedMesh.boundingSphere.radius;
document.getElementById('instancedMeshRadiusElem').innerHTML = radius;
scene.add(instancedMesh);
}
render();
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
})();