def postBlend(self): _str_func = 'LiveRecord.postBlend' log.warning("Starting Post Blend") for recordable in self.recordableObjs: recordable.dataDict['startPosition'] = VALID.euclidVector3Arg( recordable.obj.p_position) currentFrame = mc.currentTime(q=True) if self.postBlendFrames > 0: for i in range(self.postBlendFrames + 1): easeVal = EASE.easeInOutQuad(i / (self.postBlendFrames * 1.0)) self._velocity = MATHUTILS.Vector3.Lerp( self._velocity, MATHUTILS.Vector3.zero(), easeVal) for recordable in self.recordableObjs: recordable.dataDict['startPosition'] = recordable.dataDict[ 'startPosition'] + self._velocity recordable.obj.p_position = MATHUTILS.Vector3.Lerp( recordable.dataDict['startPosition'], VALID.euclidVector3Arg(recordable.obj.p_position), easeVal) mc.setKeyframe(recordable.obj.mNode, at=self.keyableAttrs) try: if self.onUpdate != None: self.onUpdate(self.fixedDeltaTime) except Exception, err: log.error( "|{0}| >> onUpdate function failed: | err: {1}".format( _str_func, err)) currentFrame = currentFrame + 1 mc.currentTime(currentFrame)
def get_planeIntersect(planeSource=None, target=None, planeAxis='z+', objAxis='z+', mark=False): _str_func = 'get_planeIntersect' if target: mTarget = cgmMeta.asMeta(target) else: mTarget = cgmMeta.asMeta(mc.ls(sl=1)) if not mTarget: return log.error(cgmGEN.logString_msg(_str_func, 'No Target')) mTarget = mTarget[0] mObj = cgmMeta.asMeta(planeSource) planePoint = VALID.euclidVector3Arg(mObj.p_position) planeNormal = VALID.euclidVector3Arg(mObj.getAxisVector(planeAxis)) rayPoint = VALID.euclidVector3Arg(mTarget.p_position) rayDirection = VALID.euclidVector3Arg(mTarget.getAxisVector(objAxis)) plane = EUCLID.Plane( EUCLID.Point3(planePoint.x, planePoint.y, planePoint.z), EUCLID.Point3(planeNormal.x, planeNormal.y, planeNormal.z)) pos = plane.intersect( EUCLID.Line3( EUCLID.Point3(rayPoint.x, rayPoint.y, rayPoint.z), EUCLID.Vector3(rayDirection.x, rayDirection.y, rayDirection.z))) if mark: LOC.create(position=pos, name='pewpew_planeIntersect') return pos
def angleBetween(p1, p2, p3): p1 = VALID.euclidVector3Arg(p1) p2 = VALID.euclidVector3Arg(p2) p3 = VALID.euclidVector3Arg(p3) v1 = (p2 - p1).normalized() v2 = (p3 - p2).normalized() return math.degrees(v1.angle(v2))
def angleBetween(p1, p2, p3): try: p1 = VALID.euclidVector3Arg(p1) p2 = VALID.euclidVector3Arg(p2) p3 = VALID.euclidVector3Arg(p3) v1 = (p2 - p1).normalized() v2 = (p3 - p2).normalized() return math.degrees(v1.angle(v2)) except Exception, err: cgmGEN.cgmException(Exception, err)
def update(self, deltaTime=.04): #dir = self.obj.getTransformDirection(self.aimFwd.p_vector) self.dir = self._bakedLoc.getTransformDirection( self.aimFwd.p_vector) * self.objectScale if self.translate: self.obj.p_position = MATH.Vector3.Lerp( VALID.euclidVector3Arg(self.previousPosition), VALID.euclidVector3Arg(self._bakedLoc.p_position), deltaTime * self.damp) if self.rotate: wantedTargetPos = ( (VALID.euclidVector3Arg(self.obj.p_position) + self.dir) - self.obj.p_position ).normalized() * self.objectScale + self.obj.p_position self.lastUp = MATH.Vector3.Lerp( self.lastUp, self._bakedLoc.getTransformDirection(self.aimUp.p_vector), min(deltaTime * self.damp, 1.0)).normalized() self.aimTargetPos = ( MATH.Vector3.Lerp(self.aimTargetPos, wantedTargetPos, deltaTime * self.damp) - self.obj.p_position ).normalized() * self.objectScale + self.obj.p_position self.upTargetPos = ( MATH.Vector3.Lerp(self.aimTargetPos, wantedTargetPos, deltaTime * self.damp) - self.obj.p_position ).normalized() * self.objectScale + self.obj.p_position self.lastFwd = MATH.Vector3.Lerp( self.lastFwd, self._bakedLoc.getTransformDirection(self.aimFwd.p_vector), min(deltaTime * self.damp, 1.0)).normalized() SNAP.aim_atPoint(obj=self.obj.mNode, mode='matrix', position=self.aimTargetPos, aimAxis=self.aimFwd.p_string, upAxis=self.aimUp.p_string, vectorUp=self.lastUp) if self.debug: if not self._debugLoc: self._debugLoc = cgmMeta.asMeta(LOC.create(name='debug_loc')) self._debugLoc.p_position = self.aimTargetPos mc.setKeyframe(self._debugLoc.mNode, at='translate')
def __init__(self, obj=None, velocityDamp=30.0, showBake=False): self.obj = None self.velocityDamp = velocityDamp self.showBake = showBake self.velocity = MATH.Vector3.zero() self.previousPosition = MATH.Vector3.zero() self.startPosition = MATH.Vector3.zero() if obj is None: self.obj = cgmMeta.asMeta(mc.ls(sl=True)[0]) else: self.obj = cgmMeta.asMeta(obj) self.aimFwd = VALID.simpleAxis('z+') self.aimUp = VALID.simpleAxis('y+') self.velocity = MATH.Vector3.zero() self.startPosition = VALID.euclidVector3Arg(self.obj.p_position) self.previousPosition = self.startPosition self.keyableAttrs = ['translate', 'rotate', 'scale'] self._bakedLoc = None self.startTime = int(mc.playbackOptions(q=True, min=True)) self.endTime = int(mc.playbackOptions(q=True, max=True))
def constructPlaneInfo(self): self._currentPlaneObject = cgmMeta.asMeta(self.planeObject) if ( self.planeObject and self.plane == 'custom') else cgmMeta.asMeta( self.recordableObjs[0].obj) self._offsetUpVector = self.aimUp.p_vector if self.plane == 'planeX': self.planeNormal = MATHUTILS.Vector3.right() self.keyableAttrs = ['ty', 'tz'] elif self.plane == 'planeY': self.planeNormal = MATHUTILS.Vector3.up() self.keyableAttrs = ['tx', 'tz'] elif self.plane == 'planeZ': self.planeNormal = MATHUTILS.Vector3.forward() self.keyableAttrs = ['tx', 'ty'] elif self.plane == 'axisX': self.planeNormal = VALID.euclidVector3Arg( self.cam.getTransformDirection(MATHUTILS.Vector3.forward())) self.keyableAttrs = ['tx'] elif self.plane == 'axisY': self.planeNormal = VALID.euclidVector3Arg( self.cam.getTransformDirection(MATHUTILS.Vector3.forward())) self.keyableAttrs = ['ty'] elif self.plane == 'axisZ': self.planeNormal = VALID.euclidVector3Arg( self.cam.getTransformDirection(MATHUTILS.Vector3.forward())) self.keyableAttrs = ['tz'] elif self.plane == 'custom': if self.planeObject: self.planeNormal = MATHUTILS.Vector3.up() self._offsetUpVector = self.planeObject.getTransformInverseDirection( self.recordableObjs[0].obj.getTransformDirection( self.aimUp.p_vector)) self.keyableAttrs = ['tx', 'ty', 'tz'] else: log.error( "|{0}| >> Custom plane not found. Please input and try again" .format(_str_func)) return elif self.plane == 'object': self.planeNormal = VALID.euclidVector3Arg(self.aimUp.p_vector) self.keyableAttrs = ['tx', 'ty', 'tz'] else: self.planeNormal = VALID.euclidVector3Arg( self.cam.getTransformDirection(MATHUTILS.Vector3.forward())) self.keyableAttrs = ['tx', 'ty', 'tz']
def update(self, deltaTime=.04): #log.info("Updating") if self.translate: self.positionForce = self.positionForce + ((VALID.euclidVector3Arg(self._bakedLoc.p_position) - VALID.euclidVector3Arg(self.previousPosition)) * self.springForce) self.positionForce = self.positionForce * (1.0 - self.damp) self.obj.p_position = self.obj.p_position + (self.positionForce * deltaTime) if self.rotate: self.dir = self._bakedLoc.getTransformDirection(self.aimFwd.p_vector) * self.objectScale wantedTargetPos = ((VALID.euclidVector3Arg(self.obj.p_position) + self.dir) - self.obj.p_position).normalized() * self.objectScale + self.obj.p_position wantedUp = self._bakedLoc.getTransformDirection(self.aimUp.p_vector) * self.objectScale self.angularForce = self.angularForce + ((wantedTargetPos - self.aimTargetPos) * self.angularSpringForce) self.angularForce = self.angularForce * (1.0 - self.angularDamp) self.angularUpForce = self.angularUpForce + ((wantedUp - self.upTargetPos) * self.angularUpSpringForce) self.angularUpForce = self.angularUpForce * (1.0 - self.upDamp) self.aimTargetPos = self.aimTargetPos + (self.angularForce * deltaTime) self.upTargetPos = self.upTargetPos + (self.angularUpForce * deltaTime) SNAP.aim_atPoint(obj=self.obj.mNode, mode='matrix', position=self.aimTargetPos, aimAxis=self.aimFwd.p_string, upAxis=self.aimUp.p_string, vectorUp=self.upTargetPos.normalized() ) if self.debug: if not self._debugLoc: self._debugLoc = cgmMeta.asMeta(LOC.create(name='debug_loc')) self._debugLoc.p_position = self.aimTargetPos mc.setKeyframe(self._debugLoc.mNode, at='translate') if not self._wantedUpLoc: self._wantedUpLoc = cgmMeta.asMeta(LOC.create(name='wanted_up_loc')) self._wantedUpLoc.p_position = self.obj.p_position + self.upTargetPos mc.setKeyframe(self._wantedUpLoc.mNode, at='translate') if not self._wantedPosLoc: self._wantedPosLoc = cgmMeta.asMeta(LOC.create(name='wanted_pos_loc')) self._wantedPosLoc.p_position = wantedTargetPos mc.setKeyframe(self._wantedPosLoc.mNode, at='translate')
def get_planeIntersect(self, target=None, planeAxis='z+', objAxis='z+', mark=True): _short = self.mNode _str_func = '[{0}] get_planeIntersect'.format(_short) if target: mTarget = cgmMeta.asMeta(target) else: mTarget = cgmMeta.asMeta(mc.ls(sl=1)) if not mTarget: return log.error(cgmGEN.logString_msg(_str_func, 'No Target')) mTarget = mTarget[0] if not self.atUtils('is_rigged'): mObj = self else: mObj = self.moduleTarget.eyeLook planePoint = VALID.euclidVector3Arg(mObj.p_position) planeNormal = VALID.euclidVector3Arg(mObj.getAxisVector(planeAxis)) rayPoint = VALID.euclidVector3Arg(mTarget.p_position) rayDirection = VALID.euclidVector3Arg(mTarget.getAxisVector(objAxis)) plane = EUCLID.Plane( EUCLID.Point3(planePoint.x, planePoint.y, planePoint.z), EUCLID.Point3(planeNormal.x, planeNormal.y, planeNormal.z)) pos = plane.intersect( EUCLID.Line3( EUCLID.Point3(rayPoint.x, rayPoint.y, rayPoint.z), EUCLID.Vector3(rayDirection.x, rayDirection.y, rayDirection.z))) if mark: LOC.create(position=pos, name='pewpew') return pos
def projectOntoPlane(self, vector): _str_func = 'LiveRecord.projectOntoPlane' camPos = VALID.euclidVector3Arg(self.cam.p_position) planeNormal = self.planeNormal if self.plane in ['custom', 'object']: planeNormal = VALID.euclidVector3Arg( self._currentPlaneObject.getTransformDirection( self.planeNormal)) log.info('Current plane object : {0}'.format(self._currentPlaneObject)) self.planePoint = VALID.euclidVector3Arg( self._currentPlaneObject.p_position) rayPoint = VALID.euclidVector3Arg(self.cam.p_position) rayDirection = VALID.euclidVector3Arg(vector) plane = EUCLID.Plane( EUCLID.Point3(self.planePoint.x, self.planePoint.y, self.planePoint.z), EUCLID.Point3(planeNormal.x, planeNormal.y, planeNormal.z)) pos = plane.intersect( EUCLID.Line3( EUCLID.Point3(rayPoint.x, rayPoint.y, rayPoint.z), EUCLID.Vector3(rayDirection.x, rayDirection.y, rayDirection.z))) if self._debugPlane: self._debugPlane.p_position = self.planePoint SNAP.aim_atPoint(obj=self._debugPlane.mNode, mode='matrix', position=self.planePoint + planeNormal, aimAxis='y+', upAxis='z+', vectorUp=planeNormal.cross( EUCLID.Vector3(0, 1, .01))) return pos
def update(self, deltaTime=.04): mp = MOUSE.getMousePosition() pos, vec = cgmDrag.screenToWorld(mp['x'] + self.offset.x, mp['y'] + self.offset.y) startPos = VALID.euclidVector3Arg( self.recordableObjs[0].obj.p_position) currentFrame = int(mc.currentTime(q=True)) if self.mode == 'position': self.moveObjOnPlane(vec) elif self.mode == 'aim': self.aimObjToPlane(vec) self._velocity = VALID.euclidVector3Arg( self.recordableObjs[0].obj.p_position) - startPos if self.clickAction.modifier == 'ctrl': mc.refresh() else: currentFrame = currentFrame + 1 if self.loopTime: currentFrame = int(currentFrame % mc.playbackOptions(q=True, max=True)) if currentFrame == int(mc.playbackOptions(q=True, min=True)): self.recordableObjs[0].saveKeys(self.keyableAttrs, replace=True) mc.currentTime(currentFrame) if self.recordableObjs[0]._bakedLoc: if not self.recordableObjs[0].restoreBakedLocFromData( currentFrame): self.recordableObjs[ 0]._bakedLoc.p_position = self._currentPlaneObject.p_position LiveRecord.update(self, deltaTime)
def onPress(self, clickDict): LiveRecord.onPress(self, clickDict) self.validateData() if self._mb == 1: self.offset = MOUSE.Point() mp = MOUSE.getMousePosition() self.offset.x = int(clickDict['anchorPoint'][0]) - mp['x'] self.offset.y = int(clickDict['anchorPoint'][1]) - mp['y'] self._velocity = MATHUTILS.Vector3.zero() if not self._useCache: self.cacheData() if self.plane != 'custom': projectedPlanePos = self.projectOntoPlane(clickDict['vector']) for recordable in self.recordableObjs: recordable.dataDict['objOffset'] = VALID.euclidVector3Arg( recordable.obj.p_position) - projectedPlanePos else: for recordable in self.recordableObjs: recordable.dataDict['objOffset'] = MATHUTILS.Vector3.zero() if self.debug: self._debugLoc = cgmMeta.asMeta(LOC.create(name='Debug_Loc')) self._debugPlane = makePlaneCurve() if self.clickAction.modifier != 'ctrl': ct = mc.currentTime(q=True) for recordable in self.recordableObjs: mc.cutKey(recordable.obj.mNode, at=self.keyableAttrs, time=(ct, mc.findKeyframe(recordable.obj.mNode, which='last') + 1)) self.recordableObjs[0].restoreBakedLocFromData( mc.currentTime(q=True)) self.record() else: self.cacheData()
def cacheData(self): self.cam = cgmMeta.asMeta(CAM.getCurrentCamera()) self.planePoint = VALID.euclidVector3Arg( self.recordableObjs[0].obj.p_position) self.planeNormal = None self.keyableAttrs = [] fps = mel.eval('currentTimeUnitToFPS') self.fixedDeltaTime = 1.0 / fps #if self.mode == 'position': self.constructPlaneInfo() if self.clickAction.modifier != 'ctrl': for i, recordable in enumerate(self.recordableObjs): recordable.clearBakedLoc() recordable.bakeLoc() if self.recordMode == 'combine': if i == 0: recordable.storeTransformData(self._currentPlaneObject) else: recordable.storeTransformData() if self.recordableObjs[0]._bakedLoc and self.plane != 'custom': self._currentPlaneObject = self.recordableObjs[0]._bakedLoc if self.mode == 'aim': self.keyableAttrs = ['rx', 'ry', 'rz'] if self.clickAction.modifier == 'ctrl': for recordable in self.recordableObjs: mc.cutKey(recordable.obj.mNode, at=self.keyableAttrs, time=(mc.currentTime(q=True), ), clear=True) recordable.clearSaved() else: for recordable in self.recordableObjs: recordable.saveKeys(self.keyableAttrs, removeOld=False) self._useCache = True
def get_pos_by_vec_dist(startPos, vec, distance=1): """ Get a point along a ray given a point, ray and distance along that ray :parameters: point(list): [x,x,x] vector(list): [x,x,x] :returns distance(float) """ _str_func = 'get_pos_by_vec_dist' vec = VALID.euclidVector3Arg(vec) _startPos = MATHUTILS.Vector3(startPos[0], startPos[1], startPos[2]) _dir = MATHUTILS.Vector3(vec[0], vec[1], vec[2]) _new = _startPos + _dir * distance return _new.x, _new.y, _new.z
def moveObjOnPlane(self, vector): _str_func = 'LiveRecord.moveObjOnPlane' projectedPosition = self.projectOntoPlane(vector) for recordable in self.recordableObjs: wantedPos = projectedPosition + recordable.dataDict['objOffset'] currentPos = VALID.euclidVector3Arg(recordable.obj.p_position) if 'tx' not in self.keyableAttrs: wantedPos.x = currentPos.x if 'ty' not in self.keyableAttrs: wantedPos.y = currentPos.y if 'tz' not in self.keyableAttrs: wantedPos.z = currentPos.z recordable.obj.p_position = wantedPos #log.info('{0} wantedPos : {1}, projectedPos : {2}, objOffset : {3}'.format(recordable.obj.mNode, wantedPos, projectedPosition, recordable.dataDict['objOffset'])) mc.setKeyframe([x.obj.mNode for x in self.recordableObjs], at=self.keyableAttrs) if self._debugLoc: self._debugLoc.p_position = projectedPosition mc.setKeyframe(self._debugLoc.mNode, at='translate')
def aimObjToPlane(self, vector): _str_func = 'LiveRecord.aimObjToPlane' wantedPos = self.projectOntoPlane(vector) vectorUp = VALID.euclidVector3Arg( self._currentPlaneObject.getTransformDirection( self._offsetUpVector)) for recordable in self.recordableObjs: SNAP.aim_atPoint(obj=recordable.obj, mode='matrix', position=wantedPos, aimAxis=self.aimFwd.p_string, upAxis=self.aimUp.p_string, vectorUp=vectorUp) mc.setKeyframe([x.obj.mNode for x in self.recordableObjs], at=self.keyableAttrs) if self._debugLoc: self._debugLoc.p_position = wantedPos mc.setKeyframe(self._debugLoc.mNode, at='translate')
def bake(self, startTime=None, endTime=None): _str_func = 'PostBake.bake' self._cancelBake = False self.startTime = int(mc.playbackOptions( q=True, min=True)) if startTime is None else startTime self.endTime = int(mc.playbackOptions( q=True, max=True)) if endTime is None else endTime previousStart = mc.playbackOptions(q=True, min=True) previousEnd = mc.playbackOptions(q=True, max=True) previousCurrent = mc.currentTime(q=True) log.info('Baking from {0} to {1}'.format(self.startTime, self.endTime)) mc.currentTime(self.startTime) self.preBake() self.setAim(aimFwd=self.aimFwd, aimUp=self.aimUp) fps = mel.eval('currentTimeUnitToFPS') fixedDeltaTime = 1.0 / fps self.velocity = MATH.Vector3.zero() ak = mc.autoKeyframe(q=True, state=True) mc.autoKeyframe(state=False) mc.refresh(su=not self.showBake) _len = self.endTime - self.startTime _progressBar = cgmUI.doStartMayaProgressBar(_len, "Processing...") completed = True if self._cancelBake: mc.refresh(su=False) mc.autoKeyframe(state=ak) return for i in range(self.startTime, self.endTime + 1): mc.currentTime(i) try: self.update(fixedDeltaTime) except Exception, err: mc.refresh(su=False) mc.autoKeyframe(state=ak) log.warning('Error on update | {0}'.format(err)) cgmGEN.cgmException(Exception, err) return mc.setKeyframe(self.obj.mNode, at=self.keyableAttrs) self.velocity = MATH.Vector3.Lerp( self.velocity, VALID.euclidVector3Arg(self.obj.p_position) - self.previousPosition, min(fixedDeltaTime * self.velocityDamp, 1.0)) self.previousPosition = VALID.euclidVector3Arg(self.obj.p_position) if _progressBar: if mc.progressBar(_progressBar, query=True, isCancelled=True): log.warning('Bake cancelled!') completed = False break mc.progressBar(_progressBar, edit=True, status=("{0} On frame {1}".format(_str_func, i)), step=1, maxValue=_len)
def dotproduct(v1, v2): # https://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python v1 = VALID.euclidVector3Arg(v1) v2 = VALID.euclidVector3Arg(v2) return max(min(sum((a * b) for a, b in zip(v1, v2)), 1.0), -1.0) return sum((a * b) for a, b in zip(v1, v2))