parent velocity

This commit is contained in:
Dave Schuyler 2003-10-30 04:38:32 +00:00
parent 435b705030
commit e6dae1d0d3

View File

@ -21,10 +21,15 @@ import DirectObject
import PhysicsManager
import math
import LineStream
class PhysicsWalker(DirectObject.DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker")
wantAvatarPhysicsIndicator = base.config.GetBool('want-avatar-physics-indicator', 1)
rotatePhysics = 1
# special methods
def __init__(self, gravity = -32.1740, standableGround=0.707,
@ -35,9 +40,14 @@ class PhysicsWalker(DirectObject.DirectObject):
self.__gravity=gravity
self.__standableGround=standableGround
self.__hardLandingForce=hardLandingForce
self.needToDeltaPos = 0
self.physVelocityIndicator=None
self.__old_contact=None
self.__oldAirborneHeight=None
self.getAirborneHeight=None
self.__oldContact=None
self.__oldPosDelta=Vec3(0)
self.__oldDt=0
self.__forwardButton=0
self.__reverseButton=0
self.__jumpButton=0
@ -49,6 +59,47 @@ class PhysicsWalker(DirectObject.DirectObject):
self.__vel=Vec3(0.0)
self.__slideButton = 0
def spawnTest(self):
assert(self.debugPrint("\n\nspawnTest()\n"))
from PandaModules import *
from IntervalGlobal import *
import MovingPlatform
if hasattr(self, "platform"):
# Remove the prior instantiation:
self.moveIval.pause()
del self.moveIval
self.platform.destroy()
del self.platform
model = loader.loadModelCopy('phase_7/models/cogHQ/platform1')
fakeId = id(self)
self.platform = MovingPlatform.MovingPlatform()
self.platform.setupCopyModel(fakeId, model, 'platformcollision')
self.platformRoot = render.attachNewNode("physicsWalker-spawnTest-%s"%fakeId)
self.platformRoot.setPos(toonbase.localToon, Vec3(0.0, 3.0, 1.0))
self.platformRoot.setHpr(toonbase.localToon, Vec3.zero())
self.platform.reparentTo(self.platformRoot)
startPos = Vec3(0.0, -15.0, 0.0)
endPos = Vec3(0.0, 15.0, 0.0)
distance = Vec3(startPos-endPos).length()
duration = distance/4
self.moveIval = Sequence(
WaitInterval(0.3),
LerpPosInterval(self.platform, duration,
endPos, startPos=startPos,
name='platformOut%s' % fakeId,
fluid = 1),
WaitInterval(0.3),
LerpPosInterval(self.platform, duration,
startPos, startPos=endPos,
name='platformBack%s' % fakeId,
fluid = 1),
name='platformIval%s' % fakeId,
)
self.moveIval.loop()
def setWalkSpeed(self, forward, jump, reverse, rotate):
assert(self.debugPrint("setWalkSpeed()"))
self.avatarControlForwardSpeed=forward
@ -90,7 +141,7 @@ class PhysicsWalker(DirectObject.DirectObject):
# Connect to Physics Manager:
self.actorNode=ActorNode("physicsActor")
self.actorNode.getPhysicsObject().setOriented(1)
self.actorNode.getPhysicsObject().setOriented(self.rotatePhysics)
self.actorNode.getPhysical(0).setViscosity(0.1)
physicsActor=NodePath(self.actorNode)
avatarNodePath.reparentTo(physicsActor)
@ -104,6 +155,16 @@ class PhysicsWalker(DirectObject.DirectObject):
gravity=LinearVectorForce(0.0, 0.0, self.__gravity)
fn.addForce(gravity)
self.phys.addLinearForce(gravity)
self.gravity = gravity
fn=ForceNode("priorParent")
fnp=NodePath(fn)
fnp.reparentTo(render)
priorParent=LinearVectorForce(0.0, 0.0, 0.0)
fn.addForce(priorParent)
self.phys.addLinearForce(priorParent)
self.priorParentNp = fnp
self.priorParent = priorParent
fn=ForceNode("viscosity")
fnp=NodePath(fn)
@ -132,6 +193,9 @@ class PhysicsWalker(DirectObject.DirectObject):
self.avatarNodePath = avatarNodePath
def setAirborneHeightFunc(self, getAirborneHeight):
self.getAirborneHeight = getAirborneHeight
def setAvatarPhysicsIndicator(self, indicator):
"""
indicator is a NodePath
@ -224,9 +288,11 @@ class PhysicsWalker(DirectObject.DirectObject):
"""
Check on the arrow keys and update the avatar.
"""
onScreenDebug.append("localToon pos = %s\n"%(toonbase.localToon.getPos().pPrintValues(),))
onScreenDebug.append("localToon hpr = %s\n"%(toonbase.localToon.getHpr().pPrintValues(),))
#assert(self.debugPrint("handleAvatarControls(task=%s)"%(task,)))
physObject=self.actorNode.getPhysicsObject()
rotAvatarToPhys=Mat3.rotateMatNormaxis(-self.avatarNodePath.getH(), Vec3.up())
#rotAvatarToPhys=Mat3.rotateMatNormaxis(-self.avatarNodePath.getH(), Vec3.up())
#rotPhysToAvatar=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
contact=self.actorNode.getContactVector()
@ -239,7 +305,7 @@ class PhysicsWalker(DirectObject.DirectObject):
# Determine what the speeds are based on the buttons:
self.__speed=(self.__forwardButton and self.avatarControlForwardSpeed or
self.__reverseButton and -self.avatarControlReverseSpeed)
self.__reverseButton and -self.avatarControlReverseSpeed)
self.__slideSpeed=self.__slideButton and (
(self.__leftButton and -self.avatarControlForwardSpeed) or
(self.__rightButton and self.avatarControlForwardSpeed))
@ -249,16 +315,98 @@ class PhysicsWalker(DirectObject.DirectObject):
# How far did we move based on the amount of time elapsed?
dt=min(ClockObject.getGlobalClock().getDt(), 0.1)
if self.needToDeltaPos:
self.setPriorParentVector()
self.needToDeltaPos = 0
#self.__oldPosDelta = render.getRelativeVector(
# self.avatarNodePath,
# self.avatarNodePath.getPosDelta(render))
#self.__oldPosDelta = self.avatarNodePath.getRelativeVector(
# render,
# self.avatarNodePath.getPosDelta(render))
self.__oldPosDelta = self.avatarNodePath.getPosDelta(render)
self.__oldDt = dt
#posDelta = self.avatarNodePath.getPosDelta(render)
#if posDelta==Vec3.zero():
# self.priorParent.setVector(self.__oldPosDelta)
#else:
# self.priorParent.setVector(Vec3.zero())
# # We must copy the vector to preserve it:
# self.__oldPosDelta=Vec3(posDelta)
if 1 and __debug__:
if self.wantAvatarPhysicsIndicator:
onScreenDebug.add("posDelta1",
self.avatarNodePath.getPosDelta(render).pPrintValues())
# is same as posDelta1:
#onScreenDebug.add("posDelta2",
# self.avatarNodePath.getPosDelta(self.priorParentNp).pPrintValues())
# is always zero:
#onScreenDebug.add("posDelta2.5",
# self.avatarNodePath.getPosDelta(self.avatarNodePath).pPrintValues())
if 0:
onScreenDebug.add("posDelta3",
render.getRelativeVector(
self.avatarNodePath,
self.avatarNodePath.getPosDelta(render)).pPrintValues())
if 0:
lines = LineStream.LineStream()
self.phys.write(lines)
phys = ""
while lines.isTextAvailable():
phys += lines.getLine()
onScreenDebug.add("phys", phys)
if 1:
onScreenDebug.add("gravity",
self.gravity.getLocalVector().pPrintValues())
onScreenDebug.add("priorParent",
self.priorParent.getLocalVector().pPrintValues())
onScreenDebug.add("avatarViscosity",
"% 10.4f"%(self.avatarViscosity.getCoef(),))
onScreenDebug.add("physObject pos",
physObject.getPosition().pPrintValues())
onScreenDebug.add("physObject hpr",
physObject.getOrientation().getHpr().pPrintValues())
onScreenDebug.add("physObject orien",
physObject.getOrientation().pPrintValues())
if 0:
onScreenDebug.add("posDelta4",
self.priorParentNp.getRelativeVector(
render,
self.avatarNodePath.getPosDelta(render)).pPrintValues())
if 0:
onScreenDebug.add("priorParent",
self.priorParent.getLocalVector().pPrintValues())
if 0:
onScreenDebug.add("priorParent po",
self.priorParent.getVector(physObject).pPrintValues())
if 0:
onScreenDebug.add("__posDelta",
self.__oldPosDelta.pPrintValues())
if 1:
onScreenDebug.add("airborneHeight", "% 10.4f"%(
self.getAirborneHeight(),))
airborneHeight=self.getAirborneHeight()
#if airborneHeight < 0.1: #contact!=Vec3.zero():
if contact!=Vec3.zero():
contactLength = contact.length()
contact.normalize()
angle=contact.dot(Vec3.up())
if angle>self.__standableGround:
# ...avatar is on standable ground.
if self.__old_contact==Vec3.zero():
jumpTime = 0.0
if self.__oldAirborneHeight > 0.1: #self.__oldContact==Vec3.zero():
# ...avatar was airborne.
if contactLength>self.__hardLandingForce:
# ...avatar was airborne.
messenger.send("jumpHardLand")
else:
messenger.send("jumpLand")
@ -270,9 +418,10 @@ class PhysicsWalker(DirectObject.DirectObject):
jump.normalize()
jump*=self.avatarControlJumpForce
physObject.addImpulse(Vec3(jump))
if contact!=self.__old_contact:
if contact!=self.__oldContact:
# We must copy the vector to preserve it:
self.__old_contact=Vec3(contact)
self.__oldContact=Vec3(contact)
self.__oldAirborneHeight=airborneHeight
self.phys.doPhysics(dt)
# Check to see if we're moving at all:
if self.__speed or self.__slideSpeed or self.__rotationSpeed:
@ -281,28 +430,52 @@ class PhysicsWalker(DirectObject.DirectObject):
rotation = dt * self.__rotationSpeed
#debugTempH=self.avatarNodePath.getH()
assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
if self.rotatePhysics:
assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
# update pos:
# Take a step in the direction of our previous heading.
self.__vel=Vec3(Vec3.forward() * distance +
Vec3.right() * slideDistance)
# rotMat is the rotation matrix corresponding to
# our previous heading.
rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
step=rotMat.xform(self.__vel)
physObject.setPosition(Point3(
physObject.getPosition()+step))
# update hpr:
o=physObject.getOrientation()
r=LOrientationf()
r.setHpr(Vec3(rotation, 0.0, 0.0))
physObject.setOrientation(o*r)
# sync the change:
self.actorNode.updateTransform()
self.__vel=Vec3(
Vec3.forward() * distance +
Vec3.right() * slideDistance)
if self.rotatePhysics:
# rotMat is the rotation matrix corresponding to
# our previous heading.
rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
step=rotMat.xform(self.__vel)
physObject.setPosition(Point3(
physObject.getPosition()+step))
# update hpr:
o=physObject.getOrientation()
r=LOrientationf()
r.setHpr(Vec3(rotation, 0.0, 0.0))
physObject.setOrientation(o*r)
assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
# sync the change:
self.actorNode.updateTransform()
else:
#physObject.setPosition(Point3(
# physObject.getPosition()+self.__vel))
# rotMat is the rotation matrix corresponding to
# our previous heading.
rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
step=rotMat.xform(self.__vel)
physObject.setPosition(Point3(
physObject.getPosition()+step))
# sync the change:
self.actorNode.updateTransform()
self.avatarNodePath.setHpr(
self.avatarNodePath.getHpr()+
Vec3(rotation, 0.0, 0.0))
if self.rotatePhysics:
assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
#assert self.avatarNodePath.getH()==debugTempH-rotation
messenger.send("avatarMoving")
@ -318,7 +491,7 @@ class PhysicsWalker(DirectObject.DirectObject):
"""
#assert(self.debugPrint("handleAvatarControls(task=%s)"%(task,)))
physObject=self.actorNode.getPhysicsObject()
rotAvatarToPhys=Mat3.rotateMatNormaxis(-self.avatarNodePath.getH(), Vec3.up())
#rotAvatarToPhys=Mat3.rotateMatNormaxis(-self.avatarNodePath.getH(), Vec3.up())
#rotPhysToAvatar=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
contact=self.actorNode.getContactVector()
@ -347,8 +520,7 @@ class PhysicsWalker(DirectObject.DirectObject):
if angle>self.__standableGround:
# ...avatar is on standable ground.
#print "standableGround"
if self.__old_contact==Vec3.zero():
jumpTime = 0.0
if self.__oldContact==Vec3.zero():
if contactLength>self.__hardLandingForce:
# ...avatar was airborne.
messenger.send("jumpHardLand")
@ -366,9 +538,9 @@ class PhysicsWalker(DirectObject.DirectObject):
physObject.setVelocity(Vec3(0.0))
self.__vel.set(0.0, 0.0, 0.0)
doPhysics=0
if contact!=self.__old_contact:
if contact!=self.__oldContact:
# We must copy the vector to preserve it:
self.__old_contact=Vec3(contact)
self.__oldContact=Vec3(contact)
#print "doPhysics", doPhysics
#print "contact", contact
if doPhysics:
@ -411,9 +583,29 @@ class PhysicsWalker(DirectObject.DirectObject):
self.actorNode.setContactVector(Vec3.zero())
return Task.cont
def doDeltaPos(self):
assert(self.debugPrint("doDeltaPos()"))
self.needToDeltaPos = 1
def setPriorParentVector(self):
assert(self.debugPrint("doDeltaPos()"))
if 0:
posDelta = self.avatarNodePath.getPosDelta(render)
assert(self.debugPrint(" posDelta=%s"%(posDelta,)))
self.priorParent.setVector(Vec3(posDelta))
onScreenDebug.append("posDelta = %s\n"%(posDelta,))
else:
print "self.__oldDt", self.__oldDt, "self.__oldPosDelta", self.__oldPosDelta
velocity = self.__oldPosDelta*(1/self.__oldDt)
assert(self.debugPrint(" __oldPosDelta=%s"%(self.__oldPosDelta,)))
assert(self.debugPrint(" velocity=%s"%(velocity,)))
self.priorParent.setVector(Vec3(velocity))
onScreenDebug.add("velocity", velocity.pPrintValues())
def resetPhys(self):
assert(self.debugPrint("resetPhys()"))
self.actorNode.getPhysicsObject().resetPosition(self.avatarNodePath.getPos())
self.priorParent.setVector(Vec3.zero())
self.actorNode.setContactVector(Vec3.zero())
def enableAvatarControls(self):
@ -441,14 +633,15 @@ class PhysicsWalker(DirectObject.DirectObject):
self.accept("arrow_down", self.moveInReverse, [1])
self.accept("arrow_down-up", self.moveInReverse, [0])
if 1:
if __debug__:
self.accept("control-f3", self.spawnTest) #*#
self.accept("f3", self.resetPhys) # for debugging only.
taskName = "AvatarControls%s"%(id(self),)
# remove any old
taskMgr.remove(taskName)
# spawn the new task
taskMgr.add(self.handleAvatarControls, taskName, 10)
taskMgr.add(self.handleAvatarControls, taskName, 25)
if self.physVelocityIndicator:
taskMgr.add(self.avatarPhysicsIndicator, "AvatarControlsIndicator%s"%(id(self),), 35)
@ -483,7 +676,10 @@ class PhysicsWalker(DirectObject.DirectObject):
self.ignore("arrow_down")
self.ignore("arrow_down-up")
self.ignore("f3")
if __debug__:
self.ignore("control-f3") #*#
self.ignore("f3")
# reset state
self.moveTurnLeft(0)