e4e94207d5
* golf: Address missing imports
* spellbook: Golf related magic words for easier debugging
* Revert "spellbook: Golf related magic words for easier debugging"
This reverts commit c0de7f6713
.
558 lines
24 KiB
Python
558 lines
24 KiB
Python
from direct.distributed import DistributedObjectAI
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from toontown.toonbase import ToontownGlobals
|
|
from panda3d.core import *
|
|
from panda3d.ode import OdeTriMeshData, OdeTriMeshGeom, OdeBody, OdeRayGeom
|
|
from . import DistributedPhysicsWorldAI
|
|
from direct.fsm.FSM import FSM
|
|
from toontown.ai.ToonBarrier import *
|
|
from toontown.golf import GolfGlobals
|
|
import random
|
|
import math
|
|
|
|
class GolfHoleBase:
|
|
|
|
def __init__(self, canRender = 0):
|
|
self.canRender = canRender
|
|
self.recording = []
|
|
self.aVRecording = []
|
|
self.holePositions = []
|
|
self.grayCount = 0
|
|
self.skyContact = None
|
|
self.lastSkyContactPoint = None
|
|
self.doingRecording = 0
|
|
self.backAmount = 270
|
|
self.ballRocket = 0
|
|
self.inCount = 0
|
|
self.frame = 0
|
|
self.onSlick = 0
|
|
self.didHoleBreak = 0
|
|
return
|
|
|
|
def loadLevel(self):
|
|
tm = self.holeInfo['terrainModel']
|
|
self.terrainModel = loader.loadModel(tm)
|
|
td = self.holeInfo['physicsData']
|
|
if self.canRender:
|
|
self.terrainModel.reparentTo(render)
|
|
if self.canRender:
|
|
self.terrainModel.find('**/softSurface').setBin('ground', 0)
|
|
terrainData = self.terrainModel.find('**/softSurface')
|
|
grassData = terrainData.findAllMatches('**/grass*')
|
|
self.terrainData = []
|
|
for index in range(grassData.getNumPaths()):
|
|
someTerrainData = grassData[index]
|
|
terrainDataOde = OdeTriMeshData(someTerrainData)
|
|
self.meshDataList.append(terrainDataOde)
|
|
terrainGeomOde = OdeTriMeshGeom(self.space, terrainDataOde)
|
|
self.geomDataList.append(terrainGeomOde)
|
|
terrainGeomOde.setCollideBits(BitMask32(4026531840))
|
|
terrainGeomOde.setCategoryBits(BitMask32(240))
|
|
self.space.setSurfaceType(terrainGeomOde, GolfGlobals.GRASS_SURFACE)
|
|
self.space.setCollideId(terrainGeomOde, 2)
|
|
|
|
slickData = terrainData.findAllMatches('**/slick*')
|
|
self.terrainData = []
|
|
for index in range(slickData.getNumPaths()):
|
|
someTerrainData = slickData[index]
|
|
terrainDataOde = OdeTriMeshData(someTerrainData)
|
|
self.meshDataList.append(terrainDataOde)
|
|
terrainGeomOde = OdeTriMeshGeom(self.space, terrainDataOde)
|
|
self.geomDataList.append(terrainGeomOde)
|
|
terrainGeomOde.setCollideBits(BitMask32(4026531840))
|
|
terrainGeomOde.setCategoryBits(BitMask32(240))
|
|
self.space.setSurfaceType(terrainGeomOde, GolfGlobals.SLICK_SURFACE)
|
|
self.space.setCollideId(terrainGeomOde, GolfGlobals.SLICK_COLLIDE_ID)
|
|
|
|
cupData = terrainData.find('**/hole*')
|
|
cupData = OdeTriMeshData(cupData)
|
|
self.meshDataList.append(cupData)
|
|
cupGeom = OdeTriMeshGeom(self.space, cupData)
|
|
self.geomDataList.append(cupGeom)
|
|
cupGeom.setCollideBits(BitMask32(4026531840))
|
|
cupGeom.setCategoryBits(BitMask32(240))
|
|
self.space.setSurfaceType(cupGeom, GolfGlobals.HOLE_SURFACE)
|
|
self.space.setCollideId(cupGeom, GolfGlobals.HOLE_CUP_COLLIDE_ID)
|
|
if self.canRender:
|
|
self.golfBarrier = self.terrainModel.find('**/collision1')
|
|
if not self.golfBarrier.isEmpty():
|
|
golfBarrierCollection = self.terrainModel.findAllMatches('**/collision?')
|
|
for i in range(golfBarrierCollection.getNumPaths()):
|
|
oneBarrier = golfBarrierCollection.getPath(i)
|
|
if oneBarrier != self.golfBarrier:
|
|
oneBarrier.wrtReparentTo(self.golfBarrier)
|
|
|
|
self.golfBarrier.hide()
|
|
else:
|
|
self.notify.warning('Could not find collision1 node ---------')
|
|
self.hardSurfaceNodePath = self.terrainModel.find('**/hardSurface')
|
|
if self.canRender:
|
|
self.terrainModel.find('**/hardSurface').setBin('ground', 0)
|
|
self.loadBlockers()
|
|
hardData = OdeTriMeshData(self.hardSurfaceNodePath)
|
|
self.meshDataList.append(hardData)
|
|
hardGeom = OdeTriMeshGeom(self.space, hardData)
|
|
self.geomDataList.append(hardGeom)
|
|
hardGeom.setCollideBits(BitMask32(4026531840))
|
|
hardGeom.setCategoryBits(BitMask32(240))
|
|
self.space.setCollideId(hardGeom, 3)
|
|
hardSurface = self.space.getSurfaceType(hardGeom)
|
|
self.notify.debug('hardSurface = %s' % hardSurface)
|
|
if self.notify.getDebug():
|
|
self.notify.debug('self.hardGeom')
|
|
hardGeom.write()
|
|
self.notify.debug(' -')
|
|
self.holeBottomNodePath = self.terrainModel.find('**/holebottom0')
|
|
if self.holeBottomNodePath.isEmpty():
|
|
self.holeBottomPos = Vec3(*self.holeInfo['holePos'][0])
|
|
else:
|
|
self.holeBottomPos = self.holeBottomNodePath.getPos()
|
|
self.holePositions.append(self.holeBottomPos)
|
|
|
|
def isBallInHole(self, ball):
|
|
retval = False
|
|
for holePos in self.holePositions:
|
|
displacement = ball.getPosition() - holePos
|
|
length = displacement.length()
|
|
self.notify.debug('hole %s length=%s' % (holePos, length))
|
|
if length <= GolfGlobals.DistanceToBeInHole * 0.5:
|
|
retval = True
|
|
break
|
|
|
|
return retval
|
|
|
|
def createRays(self):
|
|
self.notify.debug('createRays')
|
|
body = OdeBody(self.world)
|
|
self.ballRay = OdeRayGeom(self.space, 50.0)
|
|
self.ballRay.setBody(body)
|
|
self.ballRay.setOffsetRotation(Mat3(1, 0, 0, 0, -1, 0, 0, 0, -1))
|
|
self.ballRay.setOffsetPosition(0, 0, 0.0)
|
|
self.ballRay.setCollideBits(BitMask32(16773375))
|
|
self.ballRay.setCategoryBits(BitMask32(4278190080))
|
|
self.ballRayBody = body
|
|
self.space.setCollideId(self.ballRay, GolfGlobals.OOB_RAY_COLLIDE_ID)
|
|
self.rayList.append(self.ballRay)
|
|
self.rayList.append(self.ballRayBody)
|
|
self.skyRay = OdeRayGeom(self.space, 100.0)
|
|
self.skyRay.setCollideBits(BitMask32(240))
|
|
self.skyRay.setCategoryBits(BitMask32(0))
|
|
self.skyRay.setRotation(Mat3(1, 0, 0, 0, -1, 0, 0, 0, -1))
|
|
self.space.setCollideId(self.skyRay, GolfGlobals.SKY_RAY_COLLIDE_ID)
|
|
self.rayList.append(self.skyRay)
|
|
|
|
def delete(self):
|
|
self.ballRay = None
|
|
self.skyRay = None
|
|
self.recording = None
|
|
self.avRecording = None
|
|
self.llv = None
|
|
return
|
|
|
|
def initRecord(self):
|
|
del self.recording
|
|
self.recording = []
|
|
del self.aVRecording
|
|
self.aVRecording = []
|
|
self.skipFrame = 0.0
|
|
self.frame = 0
|
|
self.tXYMax = 1.0
|
|
self.tZMax = 1.0
|
|
self.tXYMin = 0.1
|
|
self.tZMin = 0.1
|
|
self.skyContact = 1
|
|
self.doingRecording = 1
|
|
self.ballRocket = 0
|
|
self.inCount = 0
|
|
self.ballInHoleFrame = 0
|
|
self.ballTouchedHoleFrame = 0
|
|
self.ballFirstTouchedHoleFrame = 0
|
|
self.ballLastTouchedGrass = 0
|
|
self.hasReset = 0
|
|
self.resetAt = 100000
|
|
self.greenIn = 0
|
|
for key in self.commonObjectDict:
|
|
self.commonObjectDict[key][2].enable()
|
|
|
|
def checkCommonObjectsNeedPass(self):
|
|
for index in self.commonObjectDict:
|
|
if self.commonObjectDict[index][1] in [4]:
|
|
return 1
|
|
|
|
return 0
|
|
|
|
def checkInRadius(self, ball):
|
|
smallestDist = None
|
|
for index in self.commonObjectDict:
|
|
if self.commonObjectDict[index][1] in [4]:
|
|
radius = self.commonObjectDict[index][8]
|
|
mover = self.commonObjectDict[index][2]
|
|
diffX = ball.getPosition()[0] - mover.getPosition()[0]
|
|
diffY = ball.getPosition()[1] - mover.getPosition()[1]
|
|
diffZ = ball.getPosition()[2] - mover.getPosition()[2]
|
|
dist = math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ)
|
|
if dist < radius:
|
|
if not smallestDist or smallestDist[1] > dist:
|
|
smallestDist = [radius, dist]
|
|
self.notify.debug('Ball Pos %s\nMover Pos %s' % (ball.getPosition(), mover.getPosition()))
|
|
|
|
return smallestDist
|
|
|
|
def trackRecordBodyFlight(self, ball, cycleTime, power, startPos, dirX, dirY):
|
|
self.notify.debug('trackRecordBodyFlight')
|
|
self.ballInHoleFrame = 0
|
|
self.ballTouchedHoleFrame = 0
|
|
self.ballFirstTouchedHoleFrame = 0
|
|
self.ballLastTouchedGrass = 0
|
|
startTime = globalClock.getRealTime()
|
|
self.notify.debug('start position %s' % startPos)
|
|
self.swingTime = cycleTime
|
|
frameCount = 0
|
|
lift = 0
|
|
startTime = GolfGlobals.BALL_CONTACT_FRAME / 24
|
|
startFrame = int(startTime * self.FPS)
|
|
for frame in range(startFrame):
|
|
self.simulate()
|
|
self.setTimeIntoCycle(self.swingTime + float(frameCount) * self.DTAStep)
|
|
frameCount += 1
|
|
|
|
forceMove = 1500
|
|
if power > 50:
|
|
lift = 0
|
|
self.didHoleBreak = 0
|
|
ball.setPosition(startPos)
|
|
ball.setLinearVel(0.0, 0.0, 0.0)
|
|
ball.setAngularVel(0.0, 0.0, 0.0)
|
|
ball.enable()
|
|
self.preStep()
|
|
self.simulate()
|
|
self.postStep()
|
|
ball.enable()
|
|
ball.addForce(Vec3(dirX * forceMove * power / 100.0, dirY * forceMove * power / 100.0, lift))
|
|
self.initRecord()
|
|
self.llv = None
|
|
self.lastSkyContactPoint = None
|
|
ran = 0
|
|
self.record(ball)
|
|
self.comObjNeedPass = self.checkCommonObjectsNeedPass()
|
|
self.notify.debug('self.comObjNeedPass %s' % self.comObjNeedPass)
|
|
firstDisabled = -1
|
|
reEnabled = 0
|
|
lastFrameEnabled = 0
|
|
checkFrames = self.FPS * (self.timingCycleLength + 1.0)
|
|
hasPrinted = 0
|
|
while ball.isEnabled() and len(self.recording) < 2100 or self.comObjNeedPass or len(self.recording) < 10:
|
|
ran = 1
|
|
if len(self.recording) > 2100 and not hasPrinted:
|
|
self.notify.debug('recording too long %s' % len(self.recording))
|
|
hasPrinted = 1
|
|
ball.disable()
|
|
self.preStep()
|
|
self.simulate()
|
|
self.setTimeIntoCycle(self.swingTime + float(frameCount) * self.DTAStep)
|
|
frameCount += 1
|
|
self.postStep()
|
|
self.record(ball)
|
|
if self.comObjNeedPass:
|
|
if firstDisabled == -1 and not ball.isEnabled():
|
|
firstDisabled = self.frame
|
|
self.notify.debug('firstDisabled %s' % firstDisabled)
|
|
check = self.checkInRadius(ball)
|
|
if check == None:
|
|
self.comObjNeedPass = 0
|
|
self.notify.debug('out radius')
|
|
else:
|
|
self.notify.debug('in radius %s dist %s' % (check[0], check[1]))
|
|
elif ball.isEnabled() and firstDisabled != -1 and not reEnabled:
|
|
reEnabled = self.frame
|
|
self.notify.debug('reEnabled %s' % reEnabled)
|
|
if reEnabled:
|
|
if self.frame > reEnabled + checkFrames:
|
|
self.comObjNeedPass = 0
|
|
self.notify.debug('renable limit passed')
|
|
elif self.frame > 2100 + checkFrames:
|
|
self.comObjNeedPass = 0
|
|
print('recording limit passed comObj')
|
|
if ball.isEnabled():
|
|
lastFrameEnabled = self.frame
|
|
|
|
self.notify.debug('lastFrameEnabled %s' % lastFrameEnabled)
|
|
if lastFrameEnabled < 3:
|
|
lastFrameEnabled = 3
|
|
self.record(ball)
|
|
self.notify.debug('Frames %s' % self.frame)
|
|
midTime = globalClock.getRealTime()
|
|
self.recording = self.recording[:lastFrameEnabled]
|
|
self.aVRecording = self.aVRecording[:lastFrameEnabled]
|
|
self.frame = lastFrameEnabled
|
|
self.processRecording()
|
|
self.processAVRecording()
|
|
self.notify.debug('Recording End time %s cycle %s len %s avLen %s' % (self.timingSimTime,
|
|
self.getCycleTime(),
|
|
len(self.recording),
|
|
len(self.aVRecording)))
|
|
length = len(self.recording) - 1
|
|
x = self.recording[length][1]
|
|
y = self.recording[length][2]
|
|
z = self.recording[length][3]
|
|
endTime = globalClock.getRealTime()
|
|
diffTime = endTime - startTime
|
|
self.doingRecording = 0
|
|
fpsTime = self.frame / diffTime
|
|
self.notify.debug('Time Start %s Mid %s End %s Diff %s Fps %s frames %s' % (startTime,
|
|
midTime,
|
|
endTime,
|
|
diffTime,
|
|
fpsTime,
|
|
self.frame))
|
|
return Vec3(x, y, z)
|
|
|
|
def record(self, ball):
|
|
self.recording.append((self.frame,
|
|
ball.getPosition()[0],
|
|
ball.getPosition()[1],
|
|
ball.getPosition()[2]))
|
|
self.aVRecording.append((self.frame,
|
|
ball.getAngularVel()[0],
|
|
ball.getAngularVel()[1],
|
|
ball.getAngularVel()[2]))
|
|
if self.frame > 50 and not self.frame % 13:
|
|
curFrame = self.recording[self.frame]
|
|
pastFrame5 = self.recording[self.frame - 11]
|
|
pastFrame10 = self.recording[self.frame - 34]
|
|
currPosA = Vec3(curFrame[1], curFrame[2], curFrame[3])
|
|
past5PosA = Vec3(pastFrame5[1], pastFrame5[2], pastFrame5[3])
|
|
past10PosA = Vec3(pastFrame10[1], pastFrame10[2], pastFrame10[3])
|
|
displacement1 = currPosA - past5PosA
|
|
displacement2 = currPosA - past10PosA
|
|
if displacement1.lengthSquared() < 0.002 and displacement2.lengthSquared() < 0.002 and not self.grayCount and not self.onSlick:
|
|
ball.disable()
|
|
self.frame += 1
|
|
|
|
def preStep(self):
|
|
if hasattr(self, 'ballRay'):
|
|
bp = self.curGolfBall().getPosition()
|
|
self.ballRayBody.setPosition(bp[0], bp[1], bp[2])
|
|
self.skyRay.setPosition(bp[0], bp[1], 50.0)
|
|
|
|
def getOrderedContacts(self, entry):
|
|
c0 = self.space.getCollideId(entry.getGeom1())
|
|
c1 = self.space.getCollideId(entry.getGeom2())
|
|
if c0 > c1:
|
|
return c1, c0
|
|
else:
|
|
return c0, c1
|
|
|
|
def postStep(self):
|
|
if self.canRender:
|
|
self.translucentLastFrame = self.translucentCurFrame[:]
|
|
self.translucentCurFrame = []
|
|
self.onSlick = 0
|
|
rayCount = 0
|
|
skyRayHitPos = None
|
|
ballRayHitPos = None
|
|
bp = self.curGolfBall().getPosition()
|
|
for entry in self.colEntries:
|
|
c0, c1 = self.getOrderedContacts(entry)
|
|
x, y, z = entry.getContactPoint(0)
|
|
if c0 == GolfGlobals.OOB_RAY_COLLIDE_ID or c1 == GolfGlobals.OOB_RAY_COLLIDE_ID:
|
|
rayCount += 1
|
|
if self.canRender:
|
|
if self.currentGolfer:
|
|
self.ballShadowDict[self.currentGolfer].setPos(x, y, z + 0.1)
|
|
if c1 == GolfGlobals.GRASS_COLLIDE_ID or c1 == GolfGlobals.HARD_COLLIDE_ID:
|
|
if self.curGolfBall().getPosition()[2] < z + 0.2:
|
|
ballRayHitPos = Vec3(x, y, z)
|
|
if c0 == GolfGlobals.OOB_RAY_COLLIDE_ID and c1 == GolfGlobals.SLICK_COLLIDE_ID:
|
|
self.onSlick = 1
|
|
elif c0 == GolfGlobals.OOB_RAY_COLLIDE_ID and c1 == GolfGlobals.HARD_COLLIDE_ID:
|
|
self.onSlick = 1
|
|
if c0 == GolfGlobals.GRASS_COLLIDE_ID and c1 == GolfGlobals.SKY_RAY_COLLIDE_ID:
|
|
self.lastSkyContactPoint = (x, y, z)
|
|
if self.curGolfBall().getPosition()[2] < z + 0.2 and rayCount == 0:
|
|
if self.skyContact in [1, 2]:
|
|
skyRayHitPos = Vec3(x, y, z)
|
|
self.skyContact += 1
|
|
if self.doingRecording:
|
|
if c0 == GolfGlobals.OOB_RAY_COLLIDE_ID or c1 == GolfGlobals.OOB_RAY_COLLIDE_ID:
|
|
rayCount += 1
|
|
if c1 == GolfGlobals.GRASS_COLLIDE_ID:
|
|
self.greenIn = self.frame
|
|
self.llv = self.curGolfBall().getLinearVel()
|
|
elif GolfGlobals.BALL_COLLIDE_ID in [c0, c1] and GolfGlobals.HOLE_CUP_COLLIDE_ID in [c0, c1]:
|
|
self.ballTouchedHoleFrame = self.frame
|
|
ballUndersideZ = self.curGolfBall().getPosition()[2] - 0.05
|
|
if z < ballUndersideZ:
|
|
if not self.ballInHoleFrame:
|
|
self.ballInHoleFrame = self.frame
|
|
if self.ballFirstTouchedHoleFrame < self.ballLastTouchedGrass:
|
|
self.ballFirstTouchedHoleFrame = self.frame
|
|
if self.isBallInHole(self.curGolfBall()) and self.didHoleBreak == 0:
|
|
self.comObjNeedPass = 0
|
|
ballLV = self.curGolfBall().getLinearVel()
|
|
ballAV = self.curGolfBall().getAngularVel()
|
|
self.curGolfBall().setLinearVel(0.5 * ballLV[0], 0.5 * ballLV[1], 0.5 * ballLV[2])
|
|
self.curGolfBall().setAngularVel(0.5 * ballAV[0], 0.5 * ballAV[1], 0.5 * ballAV[2])
|
|
self.notify.debug('BALL IN THE HOLE!!! FOO!')
|
|
self.didHoleBreak = 1
|
|
return
|
|
elif GolfGlobals.BALL_COLLIDE_ID in [c0, c1] and GolfGlobals.GRASS_COLLIDE_ID in [c0, c1]:
|
|
if self.ballInHoleFrame:
|
|
self.ballInHoleFrame = 0
|
|
self.notify.debug('setting ballInHoleFrame=0')
|
|
self.ballLastTouchedGrass = self.frame
|
|
elif self.canRender:
|
|
if c0 == GolfGlobals.TOON_RAY_COLLIDE_ID or c1 == GolfGlobals.TOON_RAY_COLLIDE_ID:
|
|
self.toonRayCollisionCallback(x, y, z)
|
|
if GolfGlobals.CAMERA_RAY_COLLIDE_ID in [c0, c1] and GolfGlobals.WINDMILL_BASE_COLLIDE_ID in [c0, c1]:
|
|
self.translucentCurFrame.append(self.windmillFanNodePath)
|
|
self.translucentCurFrame.append(self.windmillBaseNodePath)
|
|
if GolfGlobals.BALL_COLLIDE_ID in [c0, c1] and GolfGlobals.GRASS_COLLIDE_ID not in [c0, c1]:
|
|
self.handleBallHitNonGrass(c0, c1)
|
|
|
|
if not self.curGolfBall().isEnabled():
|
|
return
|
|
if rayCount == 0:
|
|
self.notify.debug('out of bounds detected!')
|
|
self.grayCount += 1
|
|
self.outCommon = self.getCommonObjectData()
|
|
self.inCount = 0
|
|
if skyRayHitPos:
|
|
self.curGolfBall().setPosition(skyRayHitPos[0], skyRayHitPos[1], skyRayHitPos[2] + 0.27)
|
|
self.notify.debug('SKY RAY ADJUST?')
|
|
else:
|
|
if self.grayCount > 1:
|
|
self.notify.debug('Back in bounds')
|
|
self.grayCount = 0
|
|
self.inCount += 1
|
|
if ballRayHitPos:
|
|
self.curGolfBall().setPosition(ballRayHitPos[0], ballRayHitPos[1], ballRayHitPos[2] + 0.245)
|
|
ballRayHitPos = None
|
|
if self.doingRecording:
|
|
self.notify.debug('BALL RAY ADJUST!')
|
|
self.notify.debug('%s' % self.curGolfBall().getLinearVel())
|
|
if self.ballRocket > 0 and self.inCount > 1:
|
|
self.ballRocket -= 1
|
|
rocketVel = self.curGolfBall().getLinearVel()
|
|
self.curGolfBall().setLinearVel(2.0 * rocketVel[0], 2.0 * rocketVel[1], 2.0 * rocketVel[2])
|
|
self.notify.debug('ROCKET!!!!')
|
|
if self.grayCount > self.backAmount and self.doingRecording:
|
|
if self.greenIn > 2:
|
|
self.greenIn -= 2
|
|
if self.greenIn > self.resetAt:
|
|
self.greenIn = self.resetAt - 10
|
|
if self.greenIn < 0 or self.hasReset > 3:
|
|
self.greenIn = 0
|
|
self.hasReset += 1
|
|
self.notify.debug('BALL RESET frame %s greenIn %s resetAt %s' % (self.frame, self.greenIn, self.resetAt))
|
|
self.useCommonObjectData(self.outCommon)
|
|
self.curGolfBall().setPosition(self.recording[self.greenIn][1], self.recording[self.greenIn][2], self.recording[self.greenIn][3] + 0.27)
|
|
self.curGolfBall().setAngularVel(0, 0, 0)
|
|
if self.hasReset < 3 and self.llv:
|
|
self.ballRocket += 1
|
|
self.notify.debug(' BRAKE!!!!')
|
|
self.curGolfBall().setLinearVel(0.5 * self.llv[0], 0.5 * self.llv[1], 0.5 * self.llv[2])
|
|
else:
|
|
self.notify.debug('back disable %s' % self.frame)
|
|
if self.lastSkyContactPoint:
|
|
self.curGolfBall().setPosition(self.lastSkyContactPoint[0], self.lastSkyContactPoint[1], self.lastSkyContactPoint[2] + 0.27)
|
|
self.curGolfBall().setLinearVel(0, 0, 0)
|
|
self.curGolfBall().disable()
|
|
self.recording = self.recording[:self.greenIn]
|
|
self.aVRecording = self.aVRecording[:self.greenIn]
|
|
self.frame = self.greenIn
|
|
self.resetAt = self.greenIn
|
|
self.grayCount = 0
|
|
if self.ballFirstTouchedHoleFrame > self.frame:
|
|
self.notify.debug('reseting first touched hole, self.frame=%d self.ballFirstTouchedHoleFrame=%d' % (self.frame, self.ballFirstTouchedHoleFrame))
|
|
self.ballFirstTouchedHoleFrame = 0
|
|
if self.ballLastTouchedGrass > self.frame:
|
|
self.ballLastTouchedGrass = 0
|
|
return
|
|
|
|
def processRecording(self, errorMult = 1.0):
|
|
self.notify.debug('processRecording')
|
|
lastFrame = self.recording[len(self.recording) - 1][0]
|
|
countRemovals = 0
|
|
for frame in self.recording:
|
|
if frame[0] == 0 or frame[0] == lastFrame:
|
|
pass
|
|
else:
|
|
index = self.recording.index(frame)
|
|
prevFrame = self.recording[index - 1]
|
|
nextFrame = self.recording[index + 1]
|
|
if self.predict(frame, prevFrame, nextFrame, errorMult):
|
|
self.recording.remove(frame)
|
|
countRemovals += 1
|
|
|
|
if countRemovals > 5:
|
|
self.processRecording()
|
|
elif len(self.recording) > 120:
|
|
self.processRecording(errorMult * 1.25)
|
|
else:
|
|
for frame in self.recording:
|
|
pass
|
|
|
|
def processAVRecording(self, errorMult = 1.0, trials = 0):
|
|
self.notify.debug('processAVRecording')
|
|
lastFrame = self.recording[len(self.recording) - 1][0]
|
|
countRemovals = 0
|
|
countTrials = trials
|
|
for frame in self.aVRecording:
|
|
if frame[0] == 0 or frame[0] == lastFrame:
|
|
pass
|
|
else:
|
|
index = self.aVRecording.index(frame)
|
|
prevFrame = self.aVRecording[index - 1]
|
|
nextFrame = self.aVRecording[index + 1]
|
|
if self.predictAV(frame, prevFrame, nextFrame, errorMult):
|
|
self.aVRecording.remove(frame)
|
|
countRemovals += 1
|
|
else:
|
|
countTrials += 1
|
|
|
|
if countRemovals > 5:
|
|
self.processAVRecording(errorMult, countTrials)
|
|
elif len(self.aVRecording) > 80:
|
|
self.processAVRecording(errorMult * 1.25, countTrials)
|
|
else:
|
|
for frame in self.aVRecording:
|
|
pass
|
|
|
|
def predict(self, frame, sourceFrame, destFrame, errorMult = 1.0):
|
|
tXY = 0.05 * errorMult
|
|
tZ = 0.05 * errorMult
|
|
projLength = destFrame[0] - sourceFrame[0]
|
|
projPen = destFrame[0] - frame[0]
|
|
propSource = float(projPen) / float(projLength)
|
|
propDest = 1.0 - propSource
|
|
projX = sourceFrame[1] * propSource + destFrame[1] * propDest
|
|
projY = sourceFrame[2] * propSource + destFrame[2] * propDest
|
|
projZ = sourceFrame[3] * propSource + destFrame[3] * propDest
|
|
varX = abs(projX - frame[1])
|
|
varY = abs(projY - frame[2])
|
|
varZ = abs(projZ - frame[3])
|
|
if varX > tXY or varY > tXY or varZ > tZ:
|
|
return 0
|
|
else:
|
|
return 1
|
|
|
|
def predictAV(self, frame, sourceFrame, destFrame, errorMult = 1.0):
|
|
tXYZ = 1.5 * errorMult
|
|
projLength = destFrame[0] - sourceFrame[0]
|
|
projPen = destFrame[0] - frame[0]
|
|
propSource = float(projPen) / float(projLength)
|
|
propDest = 1.0 - propSource
|
|
projX = sourceFrame[1] * propSource + destFrame[1] * propDest
|
|
projY = sourceFrame[2] * propSource + destFrame[2] * propDest
|
|
projZ = sourceFrame[3] * propSource + destFrame[3] * propDest
|
|
varX = abs(projX - frame[1])
|
|
varY = abs(projY - frame[2])
|
|
varZ = abs(projZ - frame[3])
|
|
if varX > tXYZ or varY > tXYZ or varZ > tXYZ:
|
|
return 0
|
|
else:
|
|
return 1
|
|
|
|
def handleBallHitNonGrass(self, c0, c1):
|
|
pass
|