Hey everyone,
I came across the following issue:
Whenever I try to apply a decal to certain meshes while the rightHandedCoordinate system is enabled, the decals get placed on the inside of the mesh, I’ve tried inversing the normals but I couldn’t get the decals to unflip, I’m not sure if this is a bug or not. When you turn on right hand with the default decal scene’s cat model, this issue isn’t there…
I have the following scene as an example, for some reason my playground won’t save so you’ll have to paste it in the playground manually:
var createScene = function () {
var scene = new BABYLON.Scene(engine);
//Adding a light
var light = new BABYLON.HemisphericLight("Hemi", new BABYLON.Vector3(0, 1, 0), scene);
//Adding an Arc Rotate Camera
var camera = new BABYLON.ArcRotateCamera("Camera", -1.85, 1.2, 200, BABYLON.Vector3.Zero(), scene);
scene.useRightHandedSystem = true
camera.attachControl(canvas, true);
// The first parameter can be used to specify which mesh to import. Here we import all meshes
BABYLON.SceneLoader.ImportMesh("", Assets.meshes.flightHelmet.rootUrl, Assets.meshes.flightHelmet.filename, scene, function (newMeshes) {
var cat = newMeshes[0];
// Set the target of the camera to the first imported mesh
camera.setTarget(cat);
var decalMaterial = new BABYLON.StandardMaterial("decalMat", scene);
decalMaterial.diffuseTexture = new BABYLON.Texture("/textures/impact.png", scene);
decalMaterial.diffuseTexture.hasAlpha = true;
decalMaterial.zOffset = -2;
var onPointerDown = function (evt) {
if (evt.button !== 0) {
return;
}
var pickInfo = scene.pick(scene.pointerX, scene.pointerY, function (mesh) { return newMeshes.findIndex(m => m.uid == mesh.uid) > -1 });
if (pickInfo.hit) {
var decalSize = new BABYLON.Vector3(10, 10, 10);
console.log(pickInfo.pickedMesh)
var decal = BABYLON.MeshBuilder.CreateDecal("decal", pickInfo.pickedMesh, {
position: pickInfo.pickedPoint,
normal: pickInfo.getNormal(true),
size: decalSize,
});
decal.material = decalMaterial;
decal.setParent(pickInfo.pickedMesh);
}
}
var canvas = engine.getRenderingCanvas();
canvas.addEventListener("pointerdown", onPointerDown, false);
scene.onDispose = function () {
canvas.removeEventListener("pointerdown", onPointerDown);
}
});
return scene;
};
Like this? Babylon.js Playground There is some distortion though around the wooden base thingy.
Yes, thank you. I coincidentally also just ran into this solution myself. I’m a bit confused why this is required for some models and not for others though. As long as it works it’s fine for the most part however.
As a further example, it actually even breaks it here (the documentation provided example scene):
var createScene = function () {
var scene = new BABYLON.Scene(engine);
//Adding a light
var light = new BABYLON.HemisphericLight("Hemi", new BABYLON.Vector3(0, 1, 0), scene);
scene.useRightHandedSystem = true
//Adding an Arc Rotate Camera
var camera = new BABYLON.ArcRotateCamera("Camera", -1.85, 1.2, 200, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
// The first parameter can be used to specify which mesh to import. Here we import all meshes
BABYLON.SceneLoader.ImportMesh("Shcroendiger'scat", "/scenes/", "SSAOcat.babylon", scene, function (newMeshes) {
var cat = newMeshes[0];
// Set the target of the camera to the first imported mesh
camera.target = cat;
setInterval(()=>{
cat.rotation.y += 0.1
}, 100);
var decalMaterial = new BABYLON.StandardMaterial("decalMat", scene);
decalMaterial.sideOrientation = BABYLON.StandardMaterial.CounterClockWiseSideOrientation;
decalMaterial.diffuseTexture = new BABYLON.Texture("/textures/impact.png", scene);
decalMaterial.diffuseTexture.hasAlpha = true;
decalMaterial.zOffset = -2;
var onPointerDown = function (evt) {
if (evt.button !== 0) {
return;
}
// check if we are under a mesh
var pickInfo = scene.pick(scene.pointerX, scene.pointerY, function (mesh) { return mesh === cat; });
if (pickInfo.hit) {
var decalSize = new BABYLON.Vector3(10, 10, 10);
/**************************CREATE DECAL*************************************************/
var decal = BABYLON.MeshBuilder.CreateDecal("decal", cat, {position: pickInfo.pickedPoint, normal: pickInfo.getNormal(true), size: decalSize});
decal.material = decalMaterial;
decal.setParent(cat); // this won't work too
/***************************************************************************************/
}
}
var canvas = engine.getRenderingCanvas();
canvas.addEventListener("pointerdown", onPointerDown, false);
scene.onDispose = function () {
canvas.removeEventListener("pointerdown", onPointerDown);
}
});
return scene;
};
I will have a look as soon as possible.
1 Like
Hi, not trying to be pushy. But did you have time yet to look into this?
It’s not really a bug, the problem is that meshes loaded from a .glb file have a right-handed geometry, so the decal mesh is also created as a right-handed geometry mesh.
To fix the problem, you either have to change the orientation of the material to BABYLON.Material.CounterClockWiseSideOrientation
, or set the decal mesh overrideMaterialSideOrientation
property to BABYLON.Material.CounterClockWiseSideOrientation
.
There’s no problem with Schrodinger’s cat, because it comes from a .babylon file, which is left-handed.
2 Likes