def GetSynchedAnimStartLocation(sourcePos, sourceRot, targetPos, targetRot, animInfo): relVec = geo2.Vec3Subtract(sourcePos, targetPos) curDist = geo2.Vec3Length(relVec) if curDist <= 0.01: sourcePos = geo2.Vec3Add(targetPos, (0, 0, -1)) relVec = geo2.Vec3Subtract(sourcePos, targetPos) entName = const.animation.ATTACKER_NAME if entName in animInfo and const.animation.METADATA_TURN_TO_FACE in animInfo[entName] and animInfo[entName][const.animation.METADATA_TURN_TO_FACE] == False: newSourceRot = sourceRot else: newSourceRot = GetQuatFromDirection(sourcePos, targetPos) entName = const.animation.VICTIM_NAME if entName in animInfo and const.animation.METADATA_TURN_TO_FACE in animInfo[entName] and animInfo[entName][const.animation.METADATA_TURN_TO_FACE] == False: newTargetRot = targetRot newTargetYaw, trash, trash = geo2.QuaternionRotationGetYawPitchRoll(targetRot) else: newTargetRot = GetQuatFromDirection(targetPos, sourcePos) if entName in animInfo and const.animation.METADATA_START_OFFSET_YAW in animInfo[entName]: degrees = animInfo[entName][const.animation.METADATA_START_OFFSET_YAW] offsetYaw = math.pi * -degrees / 180.0 offsetRot = geo2.QuaternionRotationSetYawPitchRoll(offsetYaw, 0.0, 0.0) newTargetRot = geo2.QuaternionMultiply(newTargetRot, offsetRot) distance = 0.5 if const.animation.METADATA_START_DISTANCE in animInfo: distance = animInfo[const.animation.METADATA_START_DISTANCE] entName = const.animation.VICTIM_NAME if entName in animInfo and const.animation.METADATA_START_OFFSET_YAW in animInfo[entName]: if '/righthanded' in blue.pyos.GetArg(): front = (0, 0, distance) else: front = (0, 0, -distance) degrees = animInfo[entName][const.animation.METADATA_START_OFFSET_YAW] radians = math.pi * degrees / 180.0 offsetRot = geo2.QuaternionRotationSetYawPitchRoll(radians, 0.0, 0.0) yawOffsetQuat = geo2.QuaternionMultiply(newTargetRot, offsetRot) radOffset = geo2.QuaternionTransformVector(yawOffsetQuat, front) newSourcePos = geo2.Vec3Add(targetPos, radOffset) newSourceRot = GetQuatFromDirection(newSourcePos, targetPos) else: direction = geo2.Vec3Normalize(relVec) newSourcePos = geo2.Vec3Add(targetPos, (distance * direction[0], distance * direction[1], distance * direction[2])) entName = const.animation.ATTACKER_NAME if entName in animInfo and const.animation.METADATA_START_OFFSET_YAW in animInfo[entName]: degrees = animInfo[entName][const.animation.METADATA_START_OFFSET_YAW] radians = math.pi * -degrees / 180.0 offsetRot = geo2.QuaternionRotationSetYawPitchRoll(radians, 0.0, 0.0) newSourceRot = geo2.QuaternionMultiply(newSourceRot, offsetRot) return (newSourcePos, newSourceRot, targetPos, newTargetRot)
def _TransformContext(self, q): scenarioSvc = sm.StartService('scenario') originalToolRotation = self.GetRotation() orgX, orgY, orgZ = scenarioSvc.GetDungeonOrigin() toolPositionX, toolPositionY, toolPositionZ = sm.GetService('scenario').GetSelectionCenter() toolOffset = geo2.Vector(toolPositionX - orgX, toolPositionY - orgY, toolPositionZ - orgZ) qout = geo2.QuaternionMultiply(originalToolRotation, q) qout = geo2.QuaternionNormalize(qout) inverse = geo2.QuaternionInverse(originalToolRotation) diff = geo2.QuaternionMultiply(qout, inverse) diff = geo2.QuaternionNormalize(diff) slimItems = scenarioSvc.GetSelObjects() for slimItem in slimItems: if slimItem.dunObjectID in scenarioSvc.GetLockedObjects(): if uicore.uilib.Key(uiconst.VK_CONTROL): scenarioSvc.UnlockObject(slimItem.itemID, slimItem.dunObjectID, force=True) else: continue targetBall = sm.StartService('michelle').GetBall(slimItem.itemID) targetModel = getattr(targetBall, 'model', None) if targetModel and slimItem.categoryID != const.categoryAsteroid and slimItem.groupID != const.groupHarvestableCloud: qout = geo2.QuaternionMultiply(targetModel.rotationCurve.value, diff) qout = geo2.QuaternionNormalize(qout) targetModel.rotationCurve.value = qout slimItem.dunDirection = geo2.QuaternionTransformVector(qout, geo2.Vector(0.0, 0.0, 1.0)) scenarioSvc.UpdateUnsavedObjectChanges(slimItem.itemID, CHANGE_ROTATION) if len(slimItems) > 1 and not uicore.uilib.Key(uiconst.VK_SHIFT): relativeObjectPosition = geo2.Vector(slimItem.dunX - toolOffset.x, slimItem.dunY - toolOffset.y, slimItem.dunZ - toolOffset.z) rotatedDirectionVector = geo2.QuaternionTransformVector(diff, relativeObjectPosition) if targetModel: targetModel.translationCurve.x = rotatedDirectionVector[0] + toolPositionX targetModel.translationCurve.y = rotatedDirectionVector[1] + toolPositionY targetModel.translationCurve.z = rotatedDirectionVector[2] + toolPositionZ elif slimItem.groupID in scenarioSvc.groupsWithNoModel: try: targetTransform = scenarioSvc.fakeTransforms[slimItem.itemID] targetTransform.translationCurve.x = rotatedDirectionVector[0] + toolPositionX targetTransform.translationCurve.y = rotatedDirectionVector[1] + toolPositionY targetTransform.translationCurve.z = rotatedDirectionVector[2] + toolPositionZ except KeyError: scenarioSvc.LogError('Unable to rotate any ball for dungeon object:', slimItem.dunObjectID) slimItem.dunX = rotatedDirectionVector[0] + toolOffset.x slimItem.dunY = rotatedDirectionVector[1] + toolOffset.y slimItem.dunZ = rotatedDirectionVector[2] + toolOffset.z scenarioSvc.UpdateUnsavedObjectChanges(slimItem.itemID, CHANGE_TRANSLATION) qout = geo2.QuaternionMultiply(q, originalToolRotation) qout = geo2.QuaternionNormalize(qout) self.Rotate(qout)
def _GetBonePosRot(self, ENTID, boneName, posProp, rotProp): entity = self.entityService.FindEntityByID(ENTID) if entity is None: self.LogError('GetBonePosRot: Entity with ID ', ENTID, ' not found!') return False animClient = entity.GetComponent('animation') posComp = entity.GetComponent('position') if animClient is not None and posComp is not None: if animClient.controller is not None: boneTransform = animClient.controller.animationNetwork.GetBoneTransform( boneName) if boneTransform: translation, orientation = boneTransform translation = geo2.QuaternionTransformVector( posComp.rotation, translation) translation = geo2.Vec3Add(posComp.position, translation) orientation = geo2.QuaternionMultiply( posComp.rotation, orientation) translation = list(translation) orientation = list(orientation) GameWorld.AddPropertyForCurrentPythonProc( {posProp: translation}) GameWorld.AddPropertyForCurrentPythonProc( {rotProp: orientation}) return True self.LogError('GetBonePosRot: Missing critical data in entity!') return False
def TransformAccumulatedAnimFromPos(curPos, curRot, offsetTranslation, offsetYaw): offsetYaw = offsetYaw * math.pi / 180.0 trajRot = geo2.QuaternionRotationSetYawPitchRoll(offsetYaw, 0.0, 0.0) offsetPosRotated = geo2.QuaternionTransformVector(curRot, offsetTranslation) newPos = geo2.Vec3Add(curPos, offsetPosRotated) newRot = geo2.QuaternionMultiply(trajRot, curRot) return (newPos, newRot)
def ProcessInput(self): if self.CanControl(): yaw, pitch = self.controls() else: yaw, pitch = (0, 0) currentYaw, currentPitch, _ = self.curve.GetQuaternionAt(blue.os.GetSimTime()).GetYawPitchRoll() currentPitch = max(-math.pi / 2.0, min(math.pi / 2.0, currentPitch + pitch)) current = geo2.QuaternionRotationSetYawPitchRoll(currentYaw, currentPitch, 0) rotation = geo2.QuaternionRotationSetYawPitchRoll(yaw, 0, 0) result = geo2.QuaternionMultiply(rotation, current) self.direction = geo2.QuaternionTransformVector(result, (0, 0, 1)) if not self.controlling: self.controlling = bool(yaw or pitch)
def GetSynchedAnimEndingDeltas(animInfo): atkPos = (0.0, 0.0, 0.0) atkRot = geo2.QuaternionIdentity() vicPos = (0.0, 0.0, -1.0) vicRot = geo2.QuaternionIdentity() atkPos, atkRot, vicPos, vicRot = GetSynchedAnimStartLocation(atkPos, atkRot, vicPos, vicRot, animInfo) offsetXZ = animInfo[const.animation.ATTACKER_NAME][const.animation.METADATA_END_OFFSET] offsetPos = (0.01 * offsetXZ[0], 0.0, 0.01 * offsetXZ[1]) atkPos, atkRot = TransformAccumulatedAnimFromPos(atkPos, atkRot, offsetPos, animInfo[const.animation.ATTACKER_NAME][const.animation.METADATA_YAW]) offsetXZ = animInfo[const.animation.VICTIM_NAME][const.animation.METADATA_END_OFFSET] offsetPos = (0.01 * offsetXZ[0], 0.0, 0.01 * offsetXZ[1]) vicPos, vicRot = TransformAccumulatedAnimFromPos(vicPos, vicRot, offsetPos, animInfo[const.animation.VICTIM_NAME][const.animation.METADATA_YAW]) deltaPos = geo2.Vec3Subtract(vicPos, atkPos) deltaPos = geo2.QuaternionTransformVector(atkRot, deltaPos) deltaRot = geo2.QuaternionMultiply(vicRot, atkRot) return (deltaPos, deltaRot)
def RotateSelected(self, yaw, pitch, roll): slimItems = self.GetSelObjects() if len(slimItems) == 0: return yawRad = yaw / 180.0 * math.pi pitchRad = pitch / 180.0 * math.pi rollRad = roll / 180.0 * math.pi rotationToAdd = geo2.QuaternionRotationSetYawPitchRoll( yawRad, pitchRad, rollRad) posCtr = geo2.VectorD(0, 0, 0) for slimItem in slimItems: posCtr += geo2.VectorD(slimItem.dunX, slimItem.dunY, slimItem.dunZ) geo2.Scale(posCtr, 1.0 / len(slimItems)) for slimItem in slimItems: rot = getattr(slimItem, 'dunRotation', None) slimItemRotation = geo2.QuaternionIdentity() if rot is not None: yaw, pitch, roll = rot slimItemRotation = geo2.QuaternionRotationSetYawPitchRoll( yaw / 180.0 * math.pi, pitch / 180.0 * math.pi, roll / 180.0 * math.pi) y, p, r = geo2.QuaternionRotationGetYawPitchRoll(slimItemRotation) slimItemRotation = geo2.QuaternionMultiply(rotationToAdd, slimItemRotation) y, p, r = geo2.QuaternionRotationGetYawPitchRoll(slimItemRotation) y = y / math.pi * 180.0 p = p / math.pi * 180.0 r = r / math.pi * 180.0 translation = geo2.VectorD(slimItem.dunX, slimItem.dunY, slimItem.dunZ) translation -= posCtr geo2.QuaternionTransformVector(rotationToAdd, translation) translation += posCtr dungeonHelper.SetObjectPosition(slimItem.dunObjectID, translation.x, translation.y, translation.z) dungeonHelper.SetObjectRotation(slimItem.dunObjectID, y, p, r)
def UpdateModelRotation(self, dx): if self.model: rotation = geo2.QuaternionRotationAxis((0, 1.0, 0), dx) self.model.modelRotationCurve.value = geo2.QuaternionMultiply( self.model.modelRotationCurve.value, rotation)
def RotateQuatByYaw(oldRot, yawAngle): """ Rotates a quaternion by a yaw rotation """ newRot = (0, math.sin(yawAngle / 2.0), 0, math.cos(yawAngle / 2.0)) return geo2.QuaternionMultiply(oldRot, newRot)
def RotateQuatByYaw(oldRot, yawAngle): newRot = (0, math.sin(yawAngle / 2.0), 0, math.cos(yawAngle / 2.0)) return geo2.QuaternionMultiply(oldRot, newRot)