I have a playground which has 2 html attached to 2 mesh, one mesh should be in the front of the sphere, one should be in the back of the sphere, but I find the html always show, is there any way I can do to make just one html show when I turn the mesh? Is there any way for html element know the mesh it attached is on the back of the sphere, so it should not show?
For this case it would probably be easier to use the Babylon GUI instead of HTML elements The Babylon GUI | Babylon.js Documentation
I have to use html since the accessibility reason
You are going to have trouble partially obscuring an html button without some interesting transforms, but you can do simple css to see if it is “behind” the sphere distance-wise:
var meshDistance = camera.position.subtract(mesh.position).length();
var sphereDistance = camera.position.subtract(sphere.position).length();
button.style.display = (meshDistance > sphereDistance) ? 'none' : 'block';
You can also see if the mesh boundingInfo is in the camera frustum, etc. Probably there is even something better to check?
You can fire a ray from the camera towards the sign’s position in 3D space. If there is nothing in the way, you can render the sign.
But yeah, it’ll either be fully visible or not visible at all. You won’t be able to clip it.
pick with ray is good - that’s how the Html component does in react-babylonjs
- it also does other CSS that make it more realistic than what you have - you may find some useful snippets in here:
react-babylonjs/Html.tsx at master · brianzinn/react-babylonjs (github.com)
Perpetually in awe of the awesome work being done on
react-babylonjs
. Thanks for sharing!
Could you explain how to use the ray in more detailed way? How I can know the ray touch a mesh? But I guess it may won’t work, since the html is on the sphere
I do not know this library, thanks for sharing, do you have any example for react-babylon?
I was mainly sharing in case you wanted some babylon->CSS snippets, but that library may work for you if you were interested in some declarative (and also some a11y connections):
GUI - Html Text â‹… Storybook (brianzinn.github.io)
Here is the code for that sample:
let lastTime = Date.now();
function WithHtmlText() {
const [position, setPosition] = useState(Vector3.Zero());
const [rotation, setRotation] = useState(Vector3.Zero());
let timer;
let direction = 1;
const animate = (_) => {
if (position.x > 1) {
direction = -1;
} else if (position.x < -1) {
direction = 1;
}
const velocity = 0.005 * direction;
position.x += velocity;
const rpm = 10;
const now = Date.now();
const deltaTimeInMillis = now - lastTime;
lastTime = now;
const rotationRads = (rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000);
rotation.y += rotationRads;
setPosition(position.clone());
setRotation(rotation.clone());
timer = requestAnimationFrame(animate);
};
useEffect(() => {
timer = requestAnimationFrame(animate);
return () => cancelAnimationFrame(timer);
}, []);
return (
<transformNode
name="transform-node"
position={position}
rotation={rotation}
>
<sphere
name="sphere1"
diameter={2}
segments={16}
position={new Vector3(0, 1, 0)}
>
<Html name="html" center occlude={false}>
{
<div
style={{
backgroundColor: "white",
borderRadius: "5px",
border: "3px solid red",
padding: "8px",
}}
>
Text
</div>
}
</Html>
</sphere>
</transformNode>
);
}
I have lots of examples where DOM buttons are tied to the babylon scene though state. Above example could be simplified a bunch with useBeforeRender
hook that ties into scene.onBeforeRender observable. HTH