Decal misaligned after moving model (DecalGeometry issue)

Hi everyone,

I’m running into a problem when using DecalGeometry to place a logo on a mesh after moving its parent group in the scene.

If I apply the decal right after loading the model, everything works perfectly. But when I move the group along the Y axis (e.g. group.position.y += 0.005) and then call the decal function, the logo appears offset — usually above or below where it should be.

Here’s the rough idea of what I’m doing:
// Move the model up
group.position.y += 0.005;

// Then apply decal
const box = new THREE.Box3().setFromObject(targetMesh);
const center = box.getCenter(new THREE.Vector3());

const decalGeometry = new DecalGeometry(
targetMesh,
center, // ← I suspect this becomes incorrect after moving
orientation,
size
);

const decal = new THREE.Mesh(decalGeometry, decalMaterial);
group.add(decal);

What’s the correct way to position a decal on a mesh after the group or model has been moved?

Thanks in advance!

What does happen if you update the matrix right after changing the position?

group.position.y += 0.005;
group.updateMatrixWorld(); // add this

And also this.

1 Like


Logos should be located like this. But after moving up or down, it looks like below:

Related functions are below:
const moveUp = () => {
if (playerGroup) {
playerGroup.position.y += 0.005
playerGroup.updateMatrixWorld()
camera.lookAt(playerGroup.position)
}

if(goalkeeperGroup) {
    goalkeeperGroup.position.y += 0.005
    goalkeeperGroup.updateMatrixWorld()
    camera.lookAt(goalkeeperGroup.position)
}

controls.update()

}

const moveDown = () => {
if (playerGroup) {
playerGroup.position.y -= 0.005
playerGroup.updateMatrixWorld()
camera.lookAt(playerGroup.position)
}

if(goalkeeperGroup) {
    goalkeeperGroup.position.y -= 0.005
    goalkeeperGroup.updateMatrixWorld()
    camera.lookAt(goalkeeperGroup.position)
}

controls.update()

}

Your suggestion didn’t work.

Maybe it is better to recreate the issue in a way that it could be debugged online. When I try with my code, it works fine, so in your code there might be something else, that is different, but only you can tell this.

Here is my test:

targetGroup.position.y += 5;
targetGroup.updateMatrixWorld( true, true );

const box = new THREE.Box3().setFromObject(targetMesh, true);
const center = box.getCenter(new THREE.Vector3());

var decal = new THREE.Mesh( new DecalGeometry(
								targetMesh,
								center,
								new THREE.Euler( 0.5, -1, 0 ),
								new THREE.Vector3( 30, 2, 2) ),
							decalMaterial );

Two changes:

  1. updateMatrixWorld( true, true ) is used
  2. setFromObject(targetMesh, true) is used

The online demo is here: https://codepen.io/boytchev/pen/gbprPqR?editors=0011. See lines 65-76.

image

By the way, the code above is for the case when the player is moved before the decal is created:

  1. player is created
  2. player is moved
  3. decal is created

If the player is moved after the decal is created, then it should be:

  1. player is created
  2. decal is created
  3. player is moved
  4. decal is moved
2 Likes