Local mesh decal positioning

Hi,

I have a certain mesh decal configuration (position, normal, size, angle) and want to create decals with the same configuration on different meshes.
In this example I have 2 boxes, whereas one is located on the world origin and the other one is transformed and rotated.
=> https://playground.babylonjs.com/#CLMCQA#2

Now the issue is that the decal is only created on the first box, as there is no intersection with the second one.

One could expect that localMode: true would make the decal interpret the position, normal, etc… relative to the given source mesh, but it seems like it’s always in world coordinates.
Since most of the examples are based on hit testing I understand why this is the case, as the hit test points are all in world coordinates as well.

Still I think it would be awesome being able to make the decal configuration in local coordinates.
Otherwise it’s nearly impossible to choose suitable values on rotated meshes without hit testing.
What do you think about that?

I was also trying to make the conversion by myself.
Getting the world position and normal worked out fine, but I wasn’t able to convert the angle value. If someone is able to help me out with the math, I would be very happy :sweat_smile:

best regards
Markus

2 Likes

cc @Evgeni_Popov

localMode is used to generate the decal mesh in local coordinates so that it can move properly with the parent mesh.

In your case, you simply have to transform the position/normal you pass to createDecal according to the mesh transformation matrix:

I don’t think we need a flag for that, as it is really easy to do yourself, and most of the time you already have this data in world space coordinates anyway.

1 Like

@Evgeni_Popov
position and normal transformation is fine, the problem is the angle value.
You can see the effect very clearly in this example.
The left red square is 45° off, which is the rotation of the source mesh.
Easy to fix for this example but quite hard if other rotation axes are involved as well like in the original example.

You’ll have to calculate the angle yourself, depending on what you want to achieve. I don’t think there’s a general solution to the problem: it may be obvious with a cube, but with any mesh, I can’t see how to calculate a correct angle automatically.

1 Like

@Evgeni_Popov ok here is my understanding of the normal and angle relationship:

Since the normal vector has just 2 DOF, you need the angle parameter to make the final rotation for the decal. This could also be defined in YPR.

  • Normal: Yaw / Pitch
  • Angle: Roll

So from this point on we can create a rotation matrix, transform the rotation matrix in world space and finally extract normal and angle values again.
I somehow just can’t make it work.
If you could have a quick look at my code again I would be very glad if you can tell me where the error (conceptual or mathematical) is located.
https://playground.babylonjs.com/#CLMCQA#6 (starting from line 54)

I think this might help.

Aligning normals leaves one DoF unspecified: rotation around the normal. Calculate the angle from local to world space with a reference vector pointing in the local-space direction of angle=0.

const worldNormal = BABYLON.Vector3.TransformNormal(decalNormal, cube2.getWorldMatrix());
const localRotationZero = BABYLON.Axis.X;
const worldRotationZero = BABYLON.Vector3.TransformNormal(localRotationZero,cube2.getWorldMatrix());
const decal2Angle = BABYLON.Vector3.GetAngleBetweenVectors(localRotationZero,worldRotationZero,worldNormal);

Lines 48-52:

1 Like

@HiGreg
thx a lot :+1:

It misses the decalAngle, but I think I am able to integrate it like this.

Anyway I will test this and let you know.

Aren’t your sin/cos calculations doing the same thing as adding decalAngle to decal2Angle?