Object3D.localToLocal

Object3D’s localToWorld and worldToLocal methods are really handy shortcuts, when like me you’re too lazy/focus/stupid to deal with .applyMatrix4 and .matrixWorld/.matrixWorldInverse[1].

And I was this morning: I wanted to express a vector vA of a meshA, in another meshB to obtain vB.

I didn’t want to think at all, so my brain ran to my best friend .world/localToSomething… Until I realize I didn’t care about the "world" part in the method name :sob:

What I wanted was literally .localToLocal! But sadly there was no such method…


Or maybe not yet!

What about a such utility method:

const _m1 = new THREE.Matrix4()

Object3D.prototype.localToLocal = function (v, obj) {
  this.updateWorldMatrix( true, false );
  obj.updateWorldMatrix( true, false );

  const objMatrixWorldInverse = _m1.copy(obj.matrixWorld).invert()
  return v.clone()
    .applyMatrix4(this.matrixWorld)
    .applyMatrix4(objMatrixWorldInverse);
};

or 2nd impl alternative (simpler thx to our best friends):

Object3D.prototype.localToLocal = function (v, obj) {
  const v_world = this.localToWorld(v);
  return obj.worldToLocal(v_world);
};

in my case, I could then turn off the brain and just consume it with:

const v_B = meshA.localToLocal(v_A, meshB)

TS version
declare module "three" {
  export interface Object3D {
    localToLocal: (v: THREE.Vector3, obj: THREE.Object3D) => THREE.Vector3;
  }
}
THREE.Object3D.prototype.localToLocal = function (v: THREE.Vector3, obj: THREE.Object3D) {
  const v_world = this.localToWorld(v);
  return obj.worldToLocal(v_world);
};

  1. I even wrote a full memo on this, but was too lazy to read it again :sweat_smile: ↩︎

2 Likes

inb4 Object3D.prototype.rotateYBy90Degrees and .translateXBy10

Ig what Im saying is that not every function you can imagine needs to be a class method. Having something like

function fromTo(obj1, obj2, vector) {
  return obj2.worldToLocal( obj1.localToWorld(vector) );
}

in your own code is not a crime :sweat_smile:

2 Likes

Thank you, I get your point and it is true that last implementation is kinda trivial thx to .localToWorld and worldToLocal

But those 2 methods impls themselves are at least as simple/trivial three.js/Object3D.js at 70cc4e192fe2ebd0bf8542a81c8c513d61984c58 · mrdoob/three.js · GitHub and they are still there in the API though.

I’m saying that including some user-friendly methods is not a crime either :sweat_smile:

Perhaps for someone experienced, .localToLocal or even .localToWorld/.worldToLocal shortcuts are totally useless, but maybe not for someone less experienced, like me

It’s probably also a matter of preference :slight_smile: