# InstancedMesh.center()?

Hi,

What is the recommended way to center an instancedmesh?

I could not find a .center() method.

I am able to get the center vector as follows:

``````const center = new THREE.Vector3()
instancedMesh.computeBoundingBox()
instancedMesh.boundingBox.getCenter(center)
``````

I am not sure how translate the instancedMesh by the negative value of this center vector…

Something like this?!?

``````instancedMesh.position.sub( center );
``````

Alternatively, you can loop through all instances and move them individually.

1 Like

My main objective was to have the transform control at the centre of an instancedmesh.

This was the function I came up with

``````    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)
return cImesh
}
``````

It works, but I would be interested hear from anyone if there is room for performance improvement.

May be a jsfiddle may help a lot, The code snippet is missing a lot of information。And I’ve encounted similar issue with you, see Access instancedMesh's sub-instance origin and tranform with pivot Appreciate any help

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();

const ambientLight = new THREE.AmbientLight(0xffffff);

const light = new THREE.DirectionalLight(0xffffff, 4);
light.position.set(1, 1, 1);

orbit = new OrbitControls(currentCamera, renderer.domElement);
orbit.update();

control = new TransformControls(currentCamera, renderer.domElement);
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 }])
control.attach(iMesh)

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
}

}

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);
}

``````

Here is a solution:

`````` function centredImesh(userData) {
const n = userData.length
const cImesh = new THREE.InstancedMesh(geometry, material, n)
let { x, y, z } = userData[0]
const obj3d = new THREE.Object3D()
for (let i = 0; i < n; i++) {
;({ x, y, z } = userData[i])
obj3d.position.set(x, y, z)
obj3d.updateMatrix()
cImesh.setMatrixAt(i, obj3d.matrix)
cImesh.instanceMatrix.needsUpdate = true
}

cImesh.computeBoundingBox()
const box3 = cImesh.boundingBox

const center = new THREE.Vector3()
box3.getCenter(center)

//move instances to the center
for (let i = 0; i < 2; i++) {
const matrix = new THREE.Matrix4()
cImesh.getMatrixAt(i, matrix)
const offset = center.clone().multiplyScalar(-1)
const translationMatrix = new THREE.Matrix4().makeTranslation(offset.x, offset.y, offset.z)
matrix.multiply(translationMatrix)
cImesh.setMatrixAt(i, matrix)
cImesh.instanceMatrix.needsUpdate = true
}
return cImesh
}
``````