Finding/shifting forwardVector into another vector.

Allrighty - Background: Trying to write a simple AI for a flight sim; at this point all the ai needs to do is every frame turn toward the opposing ship, (and eventually move/shoot at it)

Essentially, I need to (cumulatively) set my forward vector to the vector created by our corresponding positions

Im sure theres like a getRelativeVector() function but i was unsure

targetPos = self.target.getPos(render)
myPos = self.shipNodePath.getPos()
relativeVector = targetPos - myPos

Ok so now i can get my forward vector, and get the angle between these two vectors:

relativeVector.normalize()
forwardVector = self.shipNodePath.getQuat().getForward()
angleBetween = forwardVector.angleRad(relativeVector)

Now i have an angle between the two corresponding vectors (1) my forward vector (2) vector between me and him.

Problem here is, how do i change from angle between vectors into an HPR change? I cant seem to figure out the math to swap from this angle into a needed HPR.

Ive tried to actually additively change the forwardVector but doesnt look like interface is made to do that. And i could easily calculate the differences between their respective HPRs, but its not really what i want; the orientation of the opposing ship shouldnt matter just his position that i want to turn toward.

Im sure this problem has been attacked before; and there is a corresponding panda call for it, i just cant seem to find it :slight_smile:.

Any help would be GREATLY appreciated (pulling my hair out here).

Hmm, I think you’ll need to get matrices involved in this.

targetPos = self.target.getPos(render)
myPos = self.shipNodePath.getPos()
relativeVector = targetPos - myPos
relativeVector.normalize()
forwardVector = self.shipNodePath.getQuat().getForward()
angleBetween = forwardVector.angleDeg(relativeVector)

angleVector = forwardVector.cross(relativeVector)
myMat = self.shipNodePath.getMat()
rotMat = Mat4(Mat4.zerosMat())
turn_ratio = 0.25
rotMat.setRotateMat(angleBetween*turn_ratio, angleVector)
self.shipNodePath.setMat(myMat*rotMat)

Not tested that but I think my theory is sound

Come on, this is Panda. Why would you ever need to go to matrices? :slight_smile:

You can do with with HPR’s, like this:

# Get the current orientation, as a hpr
currentHpr = self.shipNodePath.getHpr()

# Get the orientation needed to face the target
self.shipNodePath.lookAt(self.target)
targetHpr = self.shipNodePath.getHpr()
self.shipNodePath.setHpr(currentHpr)

# Make sure the hpr's are both on the same side of the circle.
targetHpr = VBase3(fitDestAngle2Src(currentHpr[0], targetHpr[0]),
                   fitDestAngle2Src(currentHpr[1], targetHpr[1]),
                   fitDestAngle2Src(currentHpr[2], targetHpr[2]))

# Now rotate a bit torwards the target.
self.shipNodePath.setHpr(currentHpr + turn_ratio * (targetHpr - currentHpr))

That will linearly interpolate HPR angles componentwise, which works OK but it does require that weird call to fitDestAngle2Src (to prevent the rotation from going the wrong way around the circle). (fitDestAngle2Src is in direct.showbase.PythonUtil.) You can do exactly the same thing with quaternions instead, which tends to give a better result and doesn’t require that strange call:

# Get the current orientation, as a quaternion
currentQuat = self.shipNodePath.getQuat()

# Get the orientation needed to face the target
self.shipNodePath.lookAt(self.target)
targetQuat = self.shipNodePath.getQuat()
self.shipNodePath.setQuat(currentQuat)

# Now rotate a bit torwards the target.
self.shipNodePath.setQuat(currentQuat + turn_ratio * (targetQuat - currentQuat))

Of course, this assumes that you have a task-based system that will be making this call every frame with a small value of turn_ratio. If you can use an interval-based system instead, it’s even easier; just create a LerpQuatInterval and let it do all the work for you. :slight_smile:

David

I use this idem a lot:

currentHpr = self.shipNodePath.getHpr()
self.shipNodePath.lookAt(self.target)
targetHpr = self.shipNodePath.getHpr()
self.shipNodePath.setHpr(currentHpr) 

And new people always have problems with this i had to explain this on irc more then 3 occasions.

I feel there should be:
nodePath.getHrpByLookAt(node,pos)
nodePath.getForwardVector()
in c++.

It’s not a bad idea.

Hmm, much more elegant, I was aware of lookAt but didn’t think of using it that way.

That way is very clever; I knew of the look at but i didnt think about using the look at to create the HPR for you.

To think i started writing the matrix that glu uses …

Thanks a ton!
Roger