TransformControl and coordinates

Hello Needle Team,

I’m actually working with Transform Gizmo and I tried to display each time we drag (translate, rotation or scale) a control, it displays the mode, the axis and the value positive or negative after dragging…

My problem is that it takes world coordinates to make these comparisons, my control may be in local mode. I can’t get its local variation.

I have tried to calculate it using the Matrix 4 transformation but I get stuck

Would you know how to do it?

Original Post on Discord

by user 224464722878005248

Hi, are you using the builtin Transform gizmo component / the threejs version or are you building something custom?

Do I understand it right that you want to get the world coords of an object or point to display the moved distance?


It was a custom TransformControl component, and I succeed to manage it by changing the position of its parent when I move my objet, like it it’s always in the position/rotation zero.

by user 224464722878005248

Like it :
In start() :

this.controls = new TransformControls(this.context.mainCamera, this.context.renderer.domElement)
this.context.scene.add(this.controls) = "local"

this.controls.addEventListener('dragging-changed', (event) => this.handleDraggingChanged(event));

by user 224464722878005248

In the component :

handleDraggingChanged(event: any) {
    if (event.value) { // L'utilisateur commence à interagir avec le contrôle
        this.initialTransform = {
            position: this.controls.object.position.clone(),
            rotation: this.controls.object.rotation.clone(),
            scale: this.controls.object.scale.clone(),
        this.activeAxis = this.controls.axis.toLowerCase(); // Enregistrez l'axe actif
    } else { // L'utilisateur arrête d'interagir avec le contrôle
        this.initialTransform = null;
        this.activeAxis = null; // Réinitialisez l'axe actif


by user 224464722878005248

// Méthode pour gérer les changements de contrôles
  handleControlChange() {
    // On ne fait rien si les transformations initiales n'ont pas été enregistrées
    if (!this.initialTransform) return;

    // Comparaison des transformations initiales et finales
    ['x', 'y', 'z'].forEach(axis => {
        if (this.initialTransform!.position[axis] !== this.controls.object.position[axis]) {
                type: 'position' + axis.toUpperCase(),
                value: parseFloat((this.controls.object.position[axis] - this.initialTransform!.position[axis]).toFixed(2))
        if (this.initialTransform!.rotation[axis] !== this.controls.object.rotation[axis]) {
                type: 'rotation' + axis.toUpperCase(),
                value: parseFloat((this.controls.object.rotation[axis] - this.initialTransform!.rotation[axis]).toFixed(2))
        if (this.initialTransform!.scale[axis] !== this.controls.object.scale[axis]) {
                type: 'scale' + axis.toUpperCase(),
                value: parseFloat((this.controls.object.scale[axis] - this.initialTransform!.scale[axis]).toFixed(2))

by user 224464722878005248

let globalPosition = new THREE.Vector3();
    let globalQuaternion = new THREE.Quaternion();
    let globalScale = new THREE.Vector3();

    this.controls.object.matrixWorld.decompose(globalPosition, globalQuaternion, globalScale);

    this.controls.object.position.set(0, 0, 0);
    this.controls.object.quaternion.set(0, 0, 0, 1); // Reset to identity quaternion
    this.controls.object.scale.set(1, 1, 1);

    let inverseParentWorldMatrix = new THREE.Matrix4();
    let relativePosition = new THREE.Vector3();
    let relativeQuaternion = new THREE.Quaternion();
    let relativeScale = new THREE.Vector3();
    let relativeMatrix = new THREE.Matrix4();
    relativeMatrix.decompose(relativePosition, relativeQuaternion, relativeScale);



by user 224464722878005248

Great that you got it to work!