I want to rotate a child mesh to match a specific facing direction vector in world space, but I’m struggling to figure out how to do it.
I have a playground to demonstrate the context of my scenario. There is a sailboat in the scene comprised of a “sailMesh” parented to a “hullMesh”. There is also a wind velocity vector defined indicating wind direction and speed in world space. I need to figure out code that will allow me to ensure that the sail is always rotated around it’s local Y axis to align with the global wind direction. Ideally, I want to be able to animate from the sail’s current rotation to the one needed to align with the wind over time rather than instantely, perhaps using some sort of lerp.
Treat the wind velocity as an offset of the boat. So If the wind is blowing (0, 0, 10) then just add the boat position to that velocity vector and use mesh.lookAtMesh | Babylon.js Documentation
To make the boat gradually turn you can do what you said and interpolate it. You don’t have to linearly interpolate it… though you could. I find using sigmoid or other such easing functions usually looks better assuming you aren’t worried about it being an accurate physics simulation.
There are a couple ways you can interpolate too, you could interpolate the rotation of the boat or you could just interpolate between the current and new velocity vectors and then call mesh.lookAt each frame and watch it smoothly transition as the point it’s “blowing towards” shifts into the new location.
Thanks for the suggestion. I’ll give this approach a try and post a playground with my progress. I need to be able to limit/clamp the rotation of the sail to a max of +/-90 degrees relative to the hull of the boat, so I imagine I might have some trouble there, but I’ll see what progress I can make before asking for further assistance.
I appreciate the attempt, @ajp, but your solution suffers from the same limitation some of my own previous attempts had. It only works if the hull hasn’t been rotated. You can see this when I enable the “turntable” rotation that I had commented out in my previous example, as in this updated version of your PG: https://playground.babylonjs.com/#PV2N5L#4
The sail always rotates to the same position relative to the hull, not relative to the global wind direction.
I feel like I could really use a convertWorldRotationToLocal() and convertLocalRotationToWorld() function, or mesh.getWorldRotation() and mesh.setWorldRotation(). But nothing like that seems to exist, am I correct?
Not sure if that was the confusion you had run into or not: if you where you trying to correct for turntable rotation by using turntable.rotation (like I did initially) then when you use the .rotate() function it sets turntable.rotationQuaternion and does not alter .rotation. The warning on this page kind of hints at that (though I only found the warning after I figured out the rotation information was being stored in rotationQuaternion):
You cannot use a rotationQuaternion followed by a rotation on the same mesh. Once a rotationQuaternion is applied any subsequent use of rotation will produce the wrong orientation, unless the rotationQuaternion is first set to null. Please be aware this often applies when importing models as many of these models already have a rotationQuaternion set.
…
Whenever you find rotation errors it is worth setting rotationQuaternion to null before updating rotation.
In our case we can instead use rotationQuaternion directly.
p.s. that playground has the nice added advantage that the sail angle is “dragged” in the direction of the rotating boat so on a close inspection it looks even more realistic.
Nawayz, this is partial helpful but be patient with me…linear algebra is not my strong suit. I understand how Matrics.decompose() provides me a way to turn local translation, rotation, and scale into world translation, rotation, and scale. But it’s the inverse that I’m unclear on how to accomplish. If I have a vector in world space (say x:4, y:0, z: 10) representing my wind velocity, how do I convert that to a vector in local space of my sail, regardless of how deeply it’s nested and how it’s ancestor tree elements are rotation, transformed, and scaled? If I could get that converted vector, than figuring out how I need to rotate my sail is easy.
I’ve figured out a solution I’m happy with! This solution allows me to keep the sail aligning with the wind regardless of how deeply it is nested and how much its parent tree elements have been transformed! The code looks like this…
// Create normalized direction vector for the wind.
const windDirection = windVelocity.normalize();
// The sail will need to rotate relative to its parent, so get the parent world matrix.
const parentMatrix = sailMesh.parent.getWorldMatrix().clone();
// Determine wind direction relative to parent.
const localWindDirection = BABYLON.Vector3.TransformNormal(windDirection, parentMatrix.invert());
// Align the sail with the wind.
sailMesh.lookAt(localWindDirection);
Here’s an updated playground. To truly battle test the logic, I upped the “difficulty” level by not only having the boat’s heading constantly changing, but also having that boat being dragged around a whirlpool. https://playground.babylonjs.com/#PV2N5L#9
The only thing my solution doesn’t currently take into account is if the sail’s pivot point isn’t at the exact same point as the hull’s pivot point, but I think that would be easy to add should I ever need to support that scenario.
And here’s an updated version with a simple solution for preventing the sail from rotating more than +/- 90 degrees relative to it’s parent (the hull). https://playground.babylonjs.com/#PV2N5L#10
Correct. I haven’t added in any easing animations, yet. That 180 snap happens on real sailboats, too! It’s called an “uncontrolled jibe” and is to be avoided at all costs because it can knock people overboard.