The performance issue I foresee with centredImesh is that 2 for loops are required: The first for-loop to determine the centrepoint and a 2nd for-loop to populated the instancedmesh (i.e. the centrepoint needs to be known ‘a priori’). I am not so familiar with the three.js api to do it with one for-loop where the instancedmesh is centred after being populated.
Below my full example
// threejs.org/examples/#misc_controls_transform
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { TransformControls } from 'three/addons/controls/TransformControls.js';
import './main.css'
let cameraPersp, cameraOrtho, currentCamera;
let scene, renderer, control, orbit;
init();
render();
function init() {
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const aspect = window.innerWidth / window.innerHeight;
cameraPersp = new THREE.PerspectiveCamera(50, aspect, 0.01, 30000);
cameraOrtho = new THREE.OrthographicCamera(- 600 * aspect, 600 * aspect, 600, - 600, 0.01, 30000);
currentCamera = cameraPersp;
currentCamera.position.set(5, 2.5, 5);
scene = new THREE.Scene();
scene.add(new THREE.GridHelper(4, 4, 0x888888, 0x444444));
const ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);
const light = new THREE.DirectionalLight(0xffffff, 4);
light.position.set(1, 1, 1);
scene.add(light);
orbit = new OrbitControls(currentCamera, renderer.domElement);
orbit.update();
orbit.addEventListener('change', render);
control = new TransformControls(currentCamera, renderer.domElement);
control.addEventListener('change', render);
control.addEventListener('dragging-changed', function (event) {
orbit.enabled = !event.value;
});
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshLambertMaterial();
const iMesh = centredImesh([{ x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 2 }])
scene.add(iMesh)
control.attach(iMesh)
scene.add(control);
function centredImesh(userData) {
const n = userData.length
const cImesh = new THREE.InstancedMesh(geometry, material, n)
let { x, y, z } = userData[0]
let xMax = x
let xMin = x
let yMax = y
let yMin = y
let zMax = z
let zMin = z
for (let i = 0; i < n; i++) {
({ x, y, z } = userData[i])
xMax = Math.max(xMax, x)
xMin = Math.min(xMin, x)
yMax = Math.max(yMax, y)
yMin = Math.min(yMin, y)
zMax = Math.max(zMax, z)
zMin = Math.min(zMin, z)
}
const xc = (xMax + xMin) / 2
const yc = (yMax + yMin) / 2
const zc = (zMax + zMin) / 2
const obj3d = new THREE.Object3D()
for (let i = 0; i < n; i++) {
({ x, y, z } = userData[i])
obj3d.position.set(x - xc, y - yc, z - zc)
obj3d.updateMatrix()
cImesh.setMatrixAt(i, obj3d.matrix)
}
cImesh.position.set(xc, yc, zc)
cImesh.userData = userData
return cImesh
}
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
const aspect = window.innerWidth / window.innerHeight;
cameraPersp.aspect = aspect;
cameraPersp.updateProjectionMatrix();
cameraOrtho.left = cameraOrtho.bottom * aspect;
cameraOrtho.right = cameraOrtho.top * aspect;
cameraOrtho.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
function render() {
renderer.render(scene, currentCamera);
}