So I’ve been playing with camera paths and I took @carolhmj 's lovely camera track demo (thanks Carol!) and converted it to use Catmull-Rom splines in an attempt to make it smoother: https://playground.babylonjs.com/#SGVUBC#32. (BTW, I can sent a PR to add this PG to the docs along the original one, useful?).
New problem though, the camera tends to rotate as normals are computed along the way. I was wondering if there’s a stable way to compute normals so they “point up”, emphasis on stable.
My first try was to project the binormal into the XZ plane, and recompute the normal with a cross product, making sure that the normal always point “up” and never down (and fixing the binormal sign too). Code speaks more than words here:
for (let p = 0; p < curvePath.length; p++) {
// project into XZ
binormals[p].y = 0;
binormals[p].normalize();
// calculate normal
BABYLON.Vector3.CrossToRef(tangents[p], binormals[p], normals[p]);
// always up
normals[p].y = Math.abs(normals[p].y);
// now fix the binormal
BABYLON.Vector3.CrossToRef(normals[p], tangents[p], binormals[p]);
}
The problem is that when the path goes vertical or close to it, the projection doesn’t make sense anymore and wild rotations come into play. Since we have a path I guess what I want is “the normal should rotate around the path as little as possible”, which I couldn’t translate into a decent algorithm. This is pretty much a gimbal lock, but I couldn’t find anything about handling it stably along paths. I’m sure this was solved 30 years, though. I wish Knuth had a volume on 3D algorithms.
If I understand the path generation algorithm from Path3D
properly, it uses the binormal of the previous point as a guess, using it to compute the normal and then recomputing the actual binormal for the current point. I don’t know if other people have a reason to expect something from the normals since there’s no preferred direction (actually, I think you could reasonably define the normal as a direction orthogonal to the path pointing to the instantaneous center of rotation at that point in the path, but that won’t help my case). On the other hand, since you can pick the first normal, it might make sense to keep other normals as close to the first one as possible. That’s what I expected it to do.
So, has anybody ran into this issue before or knows a decent stable algorithm? I can send a PR with the results of this thread to Path3D
if it’s deemed useful.