lookAt when moving along a curve

I’m not a linear algebra guy, so when I encounter this kinda stuff I usually just pound on the keyboard until it works. Ran out of ideas though, so had a question about how to do a “lookAt” when moving a object along a curve so the actor is facing the direction it is moving.

I got the basic code for moving along a curve from https://developer.playcanvas.com/en/tutorials/camera-following-a-path. The problem with this approach is that the developer places empty entities in the workspace that represent the nodes of the curve. The entities have position information but they also appear to have rotation information. From what I can glean, the developer is getting the lookat values using the forward vector of the rotated entities. I just have X and Z positions, no rotation information because…

I implemented pathfinder.js. That’s where my curve nodes are coming from. The data looks like:

this.path = [
	[ 0, 0 ],
	[ 1, 0 ],
	[ 2, 0 ],
	[ 3, 0 ],
	[ 3, 1 ],
	[ 3, 2 ],
	[ 4, 2 ],
	[ 5, 2 ],
	[ 5, 3 ],
	[ 5, 4 ],
	[ 5, 5 ],
	[ 5, 6 ],
	[ 5, 7 ],
	[ 6, 7 ],
	[ 7, 7 ],
	[ 7, 8 ],
	[ 7, 9 ],
	[ 8, 9 ],
	[ 9, 9 ]
};

From this data I create two curves…this.px and this.py. The code below works, it moves along the two curves and positions the actor appropriately. Anybody have an idea how to set the lookAt value so the actor is looking along the curve?

Map.prototype.update = function(dt) {
    
    //curve movement
    this.time += dt;
    
    var percent = this.time / this.duration;
    
    if(this.path.length > 1) {        
        //set position along the curve
        var posX = this.px.value(percent);
        var posZ = this.pz.value(percent);
        this.actor.setPosition(new pc.Vec3(posX, 0.5, posZ));
        this.actor.lookAt(new pc.Vec(???, 0.5, ???));
    }      
};

(P.S. I also tried just doing lerps instead of curves. That has the benefit of being able to just point at the next node in the list when moving but the overall movement was kinda herky-jerky compared to the curve approach)

Thanks,
JEH

One cheat way to do it is for the lookAt position to be slightly ahead of the curve.

Map.prototype.update = function(dt) {
    
    //curve movement
    this.time += dt;
    
    var percent = this.time / this.duration;
    
    if(this.path.length > 1) {        
        //set position along the curve
        var posX = this.px.value(percent);
        var posZ = this.pz.value(percent);
        this.actor.setPosition(new pc.Vec3(posX, 0.5, posZ));

        var tX = this.px.value(percent+0.01);
        var tZ = this.pz.value(percent+0.01);
        this.actor.lookAt(new pc.Vec(tX, 0.5, tZ));
    }      
};

It’s not perfect and there is an edge case for when it reaches the end of the curve but you get the idea.

What I ended up doing is kinda like what the developer did in that camera-follow-a-path example. Since I didn’t have any rotation information I created curves for the lookAt using the next node in the pathfinding list.

The goal was to see if I could create a Diablo-type navigation in PlayCanvas. I’ve done it in Unity, but 95% of the pain is handled by Unity’s built-in pathfinding. In PlayCanvas you gotta do all that manually.

This pathfinding in this example is based on a 10 x 10 grid, so you can see some “aliasing” when the actor moves. I’m guessing I can solve that by making the grid bigger…say 100 x 100. That’s great…except I gotta manually type in a 100 x 100 dataset heh. I guess if I was going to take this further I’d write some kind of level designer that would let the user create the level graphically and then export a dataset.

Something like http://www.mapeditor.org/ would help with that.

Ah, nice. Thanks, I’ll check that out.

Would you mind sharing a snippet for that? I have an array of vec3 and need to get vectors between them. I tried just subtracting target - current but that wasn’t right.

Bruce