Getting position of Mesh to replace it with another inside a Group

Hi guys. I’m currently replacing a mesh inside a Group with another mesh at runtime. My current code is like this:

        // Here I load the GLB that will replace the mesh
        loader.load( glb, gltf => {
          const meshToBeAdded = gltf.scene;
     
          // This makes the mesh to be added to get placed inside the Group properly
          object.children[ 0 ].getWorldQuaternion(
            meshToBeAdded.children[ 0 ].quaternion
          );
          object.children[ 0 ].getWorldScale(
            meshToBeAdded.children[ 0 ].scale
          );

            // Attach the new mesh and remove the one that will get replaced
          object.children[ 0 ].attach( glbObject.children[ 0 ] );
          meshToBeRemoved.removeFromParent();
        } );

So far I I got really close to my desired result:
Before:


After:

The old mesh gets deleted and the new mesh gets placed on position (0,0,0) of the group.
Now the problem I’m trying to solve is to try to move the newly added mesh to the old mesh position inside the group. The problem is, the old mesh does not have any position property:

The position Vector is just (0, 0, 0). So I do not find a way to dinamically position this new mesh based on the old mesh position within that group. Which property could I use instead? Thanks in advance

Edit: I tried extracting the position of the old mesh with the following method:

let vec = new THREE.Vector3();
vec.setFromMatrixPosition( object.children[ 0 ].matrix );
console.log( vec );

But the values in the Vector3 are just 0.

Edit2: I tried computing the center from the old mesh bounding box:

const vec = new Vector3();
const box = new THREE.Box3().setFromObject( meshToBeRemoved );
meshToBeAdded.position.copy( box.getCenter( vec ) );

And got this result:

I’m getting close, but I’m not sure if I can get a better result.

Edit3: Been trying to take the difference on size between the two meshes into account:

    const box1 = new THREE.Box3().setFromObject( meshToBeReplaced);
    meshToBeReplaced.size = box1.getSize( new THREE.Vector3() );

    const box2 = new THREE.Box3().setFromObject( glbObject );
    meshToBeAdded.size = box2.getSize( new THREE.Vector3() );

    const meshCenter = box1.getCenter( new Vector3() );

    const ratio = 100; // what value should I use here?
    const offsetX = ( meshToBeReplaced.size.x - meshToBeAdded.size.x ) / ratio;
    const offsetZ = ( meshToBeReplaced.size.z - meshToBeAdded.size.z ) / ratio;


    meshCenter.x *= offsetX;
    meshCenter.z *= offsetZ;

The result is still a bit off. Do not know if what I’m trying makes any sense. Any help would be greatly appreciated.

I’m not sure I understand your code, as it looks more complex than it should be. Maybe it does some additional things that I cannot comprehend at the moment (too late here, too tired now).

The position, scale and rotation of object A that is inside object B are relative to B. There should be no need to calculate the world position, scale and rotation of A if you want to replace it with another object. The local position, scale and rotation are sufficient. Or at least they should be.

Tomorrow, I might make a demo code, in case you like to see what I mean. Just let me know.

A demo of what I’m trying to do would be incredibly helpful. I realized some parts of my code were not doing anything later on. I did however need to calculate the scale, otherwise the object would get really small. Thanks for the tips you brought on this problem, looking forward to your response. :smile:

1 Like

Here is a demo. The ground and the racers are one group object – you can see it moving and spinning continuously. Racers are from a GLB file. When you press the [Change model] button, all racers are replaced by tractors (also a GLB file). Each tractor takes the position, orientation and scale from its racer; and then replaces it.

The actual copying of properties and replacing is done this way (lines 135-140):

newModel.position.copy( oldModel.position );
newModel.rotation.copy( oldModel.rotation );
newModel.scale.copy( oldModel.scale );
					
ground.remove( oldModel );
ground.add( newModel );

Online demo:
https://codepen.io/boytchev/full/mdGPpmW

image

4 Likes

Thanks a lot for the thorough explanation. I was able to implement it in my project just like that!

Hey, I have a very similar problem. I have a segmented mask, and I convert each point of that segmented mask’s 2D pixel points into 3D space coordinates. Now, with this 3D points array, I want to position a 3D object mesh on top. The 3D object’s position and rotation should be the same as the mask’s position, creating an occlusion effect on the image. It’s like mapping the 3D object to fit into the image, similar to an AR (Augmented Reality) effect. Can you please suggest if it’s possible?"