Take pivot matrix and inverse it. Inversed matrix, when applied, will place pivot to world origin and your object to somewhere else. Now your object is relative to pivot point [0,0,0].
Apply transforms, that you would like to make relative to pivot point.
- Reapply initial pivot matrix (hey, not inversed!) to place object where it was before.
My example does all steps separate, mainly to explain the logic. Of course, you should not transform pivot object (maybe you don't even have one). And all steps can be compressed in one line formula:
object.matrix = inverse(pivot.matrix)*someTranformationMatrix*pivot.matrix
Working demo you find here: https://jsfiddle.net/mmalex/hd8ex0ok/
// example for https://stackoverflow.com/questions/55116131/how-can-we-change-the-rotation-origin-pivot-point-of-a-three-js-object-without
let renderer;
let camera;
let controls;
let scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(54, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(new THREE.Color(0xfefefe));
document.body.appendChild(renderer.domElement);
camera.position.x = 4;
camera.position.y = 10;
camera.position.z = 4;
camera.lookAt(0, 0, 0);
controls = new THREE.OrbitControls(camera);
// white spotlight shining from the side, casting a shadow
let spotLight = new THREE.SpotLight(0xffffff, 2.5, 25, Math.PI / 6);
spotLight.position.set(9, 10, 1);
scene.add(spotLight);
var light = new THREE.AmbientLight(0x202020); // soft white light
scene.add(light);
// example starts here
let gridHelper = new THREE.GridHelper(4, 4);
scene.add(gridHelper);
var axesHelper = new THREE.AxesHelper(1);
axesHelper.applyMatrix(new THREE.Matrix4().makeTranslation(1.5, 0, -1.5));
axesHelper.updateMatrixWorld(true);
scene.add(axesHelper);
document.changePivot = function() {
axesHelper.position.set(-2 + 4*Math.random(), -2 + 4*Math.random(), -2 + 4*Math.random());
axesHelper.updateMatrixWorld(true);
}
const geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
const material = new THREE.MeshStandardMaterial({
color: 0xff0000
});
const topBox = new THREE.Mesh(geometry, material);
topBox.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI / 8));
topBox.applyMatrix(new THREE.Matrix4().makeTranslation(0.5, 1, -0.5));
scene.add(topBox);
let animate = function() {
requestAnimationFrame(animate);
// get world transforms from desired pivot
var pivot_matrix = axesHelper.matrixWorld.clone();
// inverse it to know how to move pivot to [0,0,0]
let pivot_inv = new THREE.Matrix4().getInverse(pivot_matrix, false);
// place pivot to [0,0,0]
// apply same transforms to object
axesHelper.applyMatrix(pivot_inv);
topBox.applyMatrix(pivot_inv);
// say, we want to rotate 0.1deg around Y axis of pivot
var desiredTransform = new THREE.Matrix4().makeRotationY(Math.PI / 180);
axesHelper.applyMatrix(desiredTransform);
topBox.applyMatrix(desiredTransform);
// and put things back, i.e. apply pivot initial transformation
axesHelper.applyMatrix(pivot_matrix);
topBox.applyMatrix(pivot_matrix);
controls.update();
renderer.render(scene, camera);
};
animate();
body {
margin: 0;
}
<button onclick="changePivot()">set random pivot</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

let renderer;
let camera;
let controls;
let scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(54, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(new THREE.Color(0xfefefe));
document.body.appendChild(renderer.domElement);
camera.position.x = 5;
camera.position.y = 15.5;
camera.position.z = 5.5;
camera.lookAt(0, 0, 0);
controls = new THREE.OrbitControls(camera);
// white spotlight shining from the side, casting a shadow
let spotLight = new THREE.SpotLight(0xffffff, 2.5, 25, Math.PI / 6);
spotLight.position.set(9, 10, 1);
scene.add(spotLight);
var light = new THREE.AmbientLight(0x202020); // soft white light
scene.add(light);
// example starts here
let gridHelper = new THREE.GridHelper(4, 4);
scene.add(gridHelper);
var axesHelper = new THREE.AxesHelper(1);
axesHelper.applyMatrix(new THREE.Matrix4().makeTranslation(1.5, 0, -1.5));
scene.add(axesHelper);
const geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
const material = new THREE.MeshStandardMaterial({
color: 0xff0000
});
const topBox = new THREE.Mesh(geometry, material);
topBox.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI / 8));
topBox.applyMatrix(new THREE.Matrix4().makeTranslation(0.5, 1, -0.5));
scene.add(topBox);
let animate = function() {
requestAnimationFrame(animate);
// get world transforms from desired pivot
axesHelper.updateMatrixWorld(true);
var pivot_matrix = axesHelper.matrixWorld.clone();
// inverse it to know how to move pivot to [0,0,0]
let pivot_inv = new THREE.Matrix4().getInverse(pivot_matrix, false);
// place pivot to [0,0,0]
// apply same transforms to object
axesHelper.applyMatrix(pivot_inv);
topBox.applyMatrix(pivot_inv);
// say, we want to rotate 0.1deg around Y axis of pivot
var desiredTransform = new THREE.Matrix4().makeRotationY(Math.PI / 180);
axesHelper.applyMatrix(desiredTransform);
topBox.applyMatrix(desiredTransform);
// and put things back, i.e. apply pivot initial transformation
axesHelper.applyMatrix(pivot_matrix);
topBox.applyMatrix(pivot_matrix);
controls.update();
renderer.render(scene, camera);
};
animate();