In SparkAR I want to have an element (called toRotate
) that always looks at the camera, similarly to what already asked here (but the accepted solution is not satisfactory to me and I do not have enough reputation to answer with a comment to it).
The catch is that this element is in a hierarchy that cannot be modified: the order must absolutely be root->planeTracker->parent->toRotate
as shown in this screenshot (seems like I do not have enough reputation to inbed the image).
By using the lookAt
function (thanks to this github repo I understood that I had to create a toRotateDuplicate
sibiling to toRotate
and with same local position, and then use its transform instead) I can have it working just fine when in the Editor but once I try it on device my toRotate
has a weird rotation instead..
After some tests, I could tell that the issue was coming from the fact that the planeTracker
has a rotaion equal to Quaternion.Identity only on editor, while on device the value varies.
This is also proved by the fact that if replacing the planeTracker
by an empty node and applying a not-identity rotation to it, we have the "weird rotation" issue even on editor.
This is my code:
const Scene = require("Scene");
const Reactive = require("Reactive");
const find = e => Scene.root.findFirst(e);
(async function () {
const toRotate = await find('toRotate');
const toRotateDuplicate = await find('toRotateDuplicate');
const camera = await find('Camera');
toRotate.worldTransform.rotation = toRotateDuplicate.worldTransform.lookAt(camera.worldTransform.position).rotation;
})();
Since I am using world transform I shouldn't have issues about rotations right?
What should I do then?
Please note that the solution accepted here doesn't work for me: the object only looks at the camera if the camera is looking at the center of the object, plus if I move the camera around without rotating it I can see that the object is not updating its rotation to continue to look at the camera.
I've found an "hacky" solution:
Create another sibiling to our toRotate
called cameraDuplicate
, which mirrors the worldPosition of the Camera
object.. Since all used transform in the lookAt
logic are on the same hierarchy level now, I can use local transforms instead of the world ones ^^'
This is the updated code:
const Scene = require("Scene");
const Reactive = require("Reactive");
const find = e => Scene.root.findFirst(e);
(async function () {
const toRotate = await find('toRotate');
const toRotateDuplicate = await find('toRotateDuplicate');
const camera = await find('Camera');
const cameraDuplicate = await find('cameraDuplicate');
cameraDuplicate.worldTransform.position = camera.worldTransform.position;
toRotate.transform.rotation = toRotateDuplicate.transform.lookAt(cameraDuplicate.transform.position).rotation;
})();
I'm not a big fan of it since: it implies creating a second sibiling (as if one wasn't enough) and doesn't clarify my rotation issue but only avoids it.. So please provide your solutions and I will accept it if less hacky than mine :)