[SOLVED] Zappar AR and lookAt weird result

Hi all, I’m using the zappar API to do some AR stuff.

For now I’m trying to move some objects through waypoints using the Z axis, but when I use the LookAt method it rotates with the camera, I don’t understand why. If anyone has any clues as to what might be going on, it would help me a lot.

You can see the issue in the sample project I’m using HERE

I’ll also leave the code here to see if I’m doing something wrong:

var MoveObjectWaypoints = pc.createScript('moveObjectWaypoints');

MoveObjectWaypoints.attributes.add('waypoints', {
    type: 'entity',
    title: "points",
    array: true
});

MoveObjectWaypoints.attributes.add('speed',{
    type: 'number',
    default: 0.5
});

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

function GetWaypointDist(a,b)
{
    var dist = a.sub(b);
    return dist.normalize();
}

function GetNextPoint(currentPoint)
{
    var rand = getRandomInt(currentPoint.script.waypointScript.connections.length);
    return currentPoint.script.waypointScript.connections[rand];
}

// initialize code called once per entity
MoveObjectWaypoints.prototype.initialize = function() {
    this.nextWaypoint = GetNextPoint(this.waypoints[0]);
    console.log(this.nextWaypoint);
    this.nextPosition = GetWaypointDist(this.entity.getPosition(), this.nextWaypoint.getPosition());
    
    this.entity.lookAtReverse(this.nextWaypoint.getPosition());
};

pc.GraphNode.prototype.lookAtReverse = function(target) {
    this.lookAt(target);
    this.rotateLocal(0, 180, 0);
};

// update code called every frame
MoveObjectWaypoints.prototype.update = function(dt) 
{
    if(this.nextWaypoint != null)
    {
        var entityPos2D = new pc.Vec2(this.entity.getPosition().x, this.entity.getPosition().z);
        var targetPos2D = new pc.Vec2(this.nextWaypoint.getPosition().x, this.nextWaypoint.getPosition().z);
        console.log(entityPos2D.distance(targetPos2D));
        
        if(entityPos2D.distance(targetPos2D) < 0.05)
        {
            this.nextWaypoint = GetNextPoint(this.nextWaypoint);
            console.log(this.nextWaypoint);
            this.nextPosition = GetWaypointDist(this.entity.getPosition(), this.nextWaypoint.getPosition());
        }
        this.entity.lookAtReverse(this.nextWaypoint.getPosition());

        this.entity.translateLocal(0,0, this.speed * dt);
    }
};

Thanks!

Hi @femoreti and welcome,

Most likely this isn’t related to Zappar/AR, just lookAt() not finding the right angle (gimbal lock?). I can’t debug this visually, the object seems to be moving not only in one direction but two?

By the way this example project may be of help, it uses lookAt and passes a second value for the up axis direction to allow for rolling and gimbal lock prevention:

https://developer.playcanvas.com/en/tutorials/camera-following-a-path/

I am having the same problem as describe here

Trying to move an object from point A to point B
used the example to try and see if its something with the example code or with zappar, but its with zappar indeed

I copy the classes from the example, and put on a Cube with a pointing direction, when i set with zappar, the cube just float around the camera, not following the points. If I change in the class where says “getPosition” or "setPosition to “getLocalPosition”/“setLocalPosition”, the cube moves in the area, but looking in a wrong direction

Without zappar, the cube follow as should be, if I change to getLocalPostion/setLocalPosition, the cube just look at the oposite direction of the point.

https://playcanvas.com/project/879716/overview/zappar_moviment

I set four different scenes on this project, two with zappar, with “getPosition” and “getLocalPosition”, and without zappar with “getPosition” and “getLocalPosition” test to see what happens

Later I can try with @femoreti class examples

Sorry if it’s not possible to do a double post, but I created 2 new scene as examples using only LookAt
One with zappar, and other without

Without zappar works as should be, the only thing weird is that i need to invert position on lookat at X and Z positions, to make the object using his Forward

WITH zappar the thing is different… even looking in a different direction, when I move the camera, the object move together the camera…
this is really weird…

Worth asking on the Zappar forums, they look like they are pretty responsive there: https://forum.zap.works/

1 Like

Lol @yaustar, I’m a Zappar client as well. They don’t answer these questions, and instead tell us to reach out to the devs of the framework we’re using. So now poor @femoreti is probably running in circles :joy:

Hmm… okay. I see if I get some time to look at this tomorrow then since multiple people have the same issue

I was really running in circles with this bug!

But now I finally managed to solve this problem, not the way I would like, but it worked.

Basically I decided to do an math to find the angle between two points and based on that angle I apply the rotation at point A to make the object look at point B, that way it stopped rotating along with the camera when using Zappar.

I’ll leave the code here for those who want to know more:

function GetNextPointAngle(source,target)

{

    const angle = (anchor, point) => Math.atan2(anchor.y - point.y, anchor.x - point.x) * 180 / Math.PI + 180;

    var a = {

        x: target.x,

        y: target.z

    };

    var p = {

        x: source.x,

        y: source.z

    };

    //console.log(target, source);

    //console.log(a,p);

    angle(a, p); // 225

    // angle in degrees, from example, same data

    angleDeg = Math.atan2(a.y - p.y, a.x - p.x) * 180 / Math.PI; // 45

    return angleDeg;

}

function LookToTarget(source, target)

{

    var entityPos = source.getLocalPosition().clone();

    var targetPos = target.getLocalPosition().clone();

    var angleToRotate = GetNextPointAngle(entityPos, targetPos);

    //console.log(angleToRotate);

    if(angleToRotate < 0)

    {

        angleToRotate = -((angleToRotate + 360)) + 90;

    }

    else

    {

        angleToRotate = 90 - angleToRotate;

    }

    //console.log(angleToRotate);

    source.setLocalEulerAngles(0,angleToRotate,0);

}

And the link to the project with the code working ~here~

It would be interesting to find out how to make it work using the native LookAt along with Zappar api, but as I had a deadline to finish it, I managed to do it this way.

Thank you guys!

1 Like

See below for Office Hours video on this. Jump to 11:59 for the answer

What is happening is that Zappar is orientating the Instant Tracker entity to match the orientation of the thing it is tracking.

When that happens, the Char entity local up vector no longer matches the world up vector so when lookAt is used with just a pointer vector to look at, it looks like it is rotated on the local Z axis because the lookAt function uses the world up vector by default to rotate the Char entity with.

To fix this, we can pass the Instant Tracker’s up vector to the lookAt function to rotate the Char entity with and orientate it correctly to match the Instant Tracker’s orientation.

Fixed project: https://playcanvas.com/project/881180/overview/f-zappar-lookat-issue

3 Likes

Amazing @yaustar ! Thanks a lot for your help!

I’ll fix that on my project using the lookAt method, I think we can close this thread and mark as Solved!

Thanks again!