def __init__(self, tKeyframe):
# Bit mask of elements present
self.mask = 0
# Time position in seconds: float
self.time = tKeyframe.time
# Position: Vector((0.0, 0.0, 0.0))
self.position = tKeyframe.position
if tKeyframe.position:
self.mask |= TRACK_POSITION
# Rotation: Quaternion()
self.rotation = tKeyframe.rotation
if tKeyframe.rotation:
self.mask |= TRACK_ROTATION
# Scale: Vector((0.0, 0.0, 0.0))
self.scale = tKeyframe.scale
if tKeyframe.scale:
self.mask |= TRACK_SCALE
python类Quaternion()的实例源码
def get_rotated_pt(piv_co, ang_diff_rad, rot_dat, mov_co):
axis_lk = rot_dat.axis_lk
mov_aligned = mov_co - piv_co
rot_val = []
if axis_lk == '': # arbitrary axis / spherical rotations
rot_val = Quaternion(rot_dat.piv_norm, ang_diff_rad)
elif axis_lk == 'X':
rot_val = Euler((ang_diff_rad, 0.0, 0.0), 'XYZ')
elif axis_lk == 'Y':
rot_val = Euler((0.0, ang_diff_rad, 0.0), 'XYZ')
elif axis_lk == 'Z':
rot_val = Euler((0.0, 0.0, ang_diff_rad), 'XYZ')
mov_aligned.rotate(rot_val)
return mov_aligned + piv_co
# Takes a ref_pts (ReferencePoints class) argument and modifies its member
# variable lp_ls (lock pt list). The lp_ls variable is assigned a modified list
# of 3D coordinates (if an axis lock was provided), the contents of the
# ref_pts' rp_ls var (if no axis lock was provided), or an empty list (if there
# wasn't enough ref_pts or there was a problem creating the modified list).
# todo : move inside ReferencePoints class ?
def RBenVe(Object, Dir):
ObjectV = Object.normalized()
DirV = Dir.normalized()
cosTheta = ObjectV.dot(DirV)
rotationAxis = mathutils.Vector((0.0, 0.0, 0.0))
if (cosTheta < -1 + 0.001):
v = mathutils.Vector((0.0, 1.0, 0.0))
rotationAxis = ObjectV.cross(v)
rotationAxis = rotationAxis.normalized()
q = mathutils.Quaternion()
q.w = 0.0
q.x = rotationAxis.x
q.y = rotationAxis.y
q.z = rotationAxis.z
return q
rotationAxis = ObjectV.cross(DirV)
s = math.sqrt((1.0 + cosTheta) * 2.0)
invs = 1 / s
q = mathutils.Quaternion()
q.w = s * 0.5
q.x = rotationAxis.x * invs
q.y = rotationAxis.y * invs
q.z = rotationAxis.z * invs
return q
def swap(vec):
if CONFIG['SWAP_AXIS'] == 'xyz': return vec
elif CONFIG['SWAP_AXIS'] == 'xzy':
if len(vec) == 3: return mathutils.Vector( [vec.x, vec.z, vec.y] )
elif len(vec) == 4: return mathutils.Quaternion( [ vec.w, vec.x, vec.z, vec.y] )
elif CONFIG['SWAP_AXIS'] == '-xzy':
if len(vec) == 3: return mathutils.Vector( [-vec.x, vec.z, vec.y] )
elif len(vec) == 4: return mathutils.Quaternion( [ vec.w, -vec.x, vec.z, vec.y] )
elif CONFIG['SWAP_AXIS'] == 'xz-y':
if len(vec) == 3: return mathutils.Vector( [vec.x, vec.z, -vec.y] )
elif len(vec) == 4: return mathutils.Quaternion( [ vec.w, vec.x, vec.z, -vec.y] )
elif CONFIG['SWAP_AXIS'] == 'aldeb':
if len(vec) == 3: return mathutils.Vector( [vec.x, -vec.z, vec.y] )
elif len(vec) == 4: return mathutils.Quaternion( [ vec.w, vec.x, -vec.z, vec.y] )
else:
print( 'unknown swap axis mode', CONFIG['SWAP_AXIS'] )
assert 0
## Config
def evaluate(self):
armature = self.get_parameter_value(self.armature)
bone_name = self.get_parameter_value(self.bone_name)
if armature is LogicNetworkCell.STATUS_WAITING: return
if bone_name is LogicNetworkCell.STATUS_WAITING: return
self._set_ready()
if none_or_invalid(armature): return
if not bone_name: return
channel = None
if (armature is self._prev_armature) and (bone_name == self._prev_bone):
channel = self._channel
else:
self._prev_armature = armature
self._prev_bone = bone_name
self._channel = armature.channels[bone_name]
channel = self._channel
if channel.rotation_mode is bge.logic.ROT_MODE_QUAT:
self._rot[:] = mathutils.Quaternion(channel.rotation_quaternion).to_euler()
else:
self._rot[:] = channel.rotation_euler
self._pos[:] = channel.location
self._sca[:] = channel.scale
def create_step(width, base_level, step_height, num_sides):
axis = [0,0,-1]
PI2 = pi * 2
rad = width / 2
quat_angles = [(cur_side/num_sides) * PI2
for cur_side in range(num_sides)]
quaternions = [Quaternion(axis, quat_angle)
for quat_angle in quat_angles]
init_vectors = [Vector([rad, 0, base_level])] * len(quaternions)
quat_vector_pairs = list(zip(quaternions, init_vectors))
vectors = [quaternion * vec for quaternion, vec in quat_vector_pairs]
bottom_list = [(vec.x, vec.y, vec.z) for vec in vectors]
top_list = [(vec.x, vec.y, vec.z+step_height) for vec in vectors]
full_list = bottom_list + top_list
return full_list
def onTrackerPosition(self,userdata,data):
sensor = data["sensor"]
# Position
name = "Location " + str(sensor)
socket = self.outputs.get(name)
if socket is None:
socket = self.outputs.new('NodeSocketVectorXYZ', name)
rawPosition = data["position"]
socket.default_value = Vector((rawPosition[0], -rawPosition[2], rawPosition[1]))
# Quaternion
name = "Rotation " + str(sensor)
socket = self.outputs.get(name)
if socket is None:
socket = self.outputs.new('NodeSocketQuaternion', name)
rawQuaternion = data["quaternion"]
socket.default_value = Quaternion((rawQuaternion[3], rawQuaternion[0], -rawQuaternion[2], rawQuaternion[1]))
QuaternionDeltaAccumulatorNode.py 文件源码
项目:InSituImmersiveAuthoring
作者: sat-metalab
项目源码
文件源码
阅读 15
收藏 0
点赞 0
评论 0
def run(self):
reset = self.getInputValue("Reset")
if reset:
self.lastValue = Quaternion((1.0, 0.0, 0.0, 0.0))
self.outputs["Quaternion"].default_value = Quaternion((1.0, 0.0, 0.0, 0.0))
accumulate = self.getInputValue("Accumulate")
if accumulate and not self.accumulate:
self.lastValue = self.getInputValue("Quaternion").inverted()
self.outputs["Accumulating"].default_value = True
self.accumulate = True
elif not accumulate and self.accumulate:
self.outputs["Accumulating"].default_value = False
self.accumulate = False
elif accumulate:
value = self.getInputValue("Quaternion") # No need to copy we're not using directly
self.outputs["Quaternion"].default_value *= self.lastValue * value
self.lastValue = value.inverted()
def getRotatedPoint(PivC,angleDiffRad,rotDat,movCo):
axisLk = rotDat.axisLk
vecTmp = movCo - PivC
rotVal = []
if axisLk == '': # arbitrary axis / spherical rotations
rotVal = Quaternion(rotDat.pivNorm, angleDiffRad)
elif axisLk == 'X':
rotVal = Euler((angleDiffRad,0.0,0.0), 'XYZ')
elif axisLk == 'Y':
rotVal = Euler((0.0,angleDiffRad,0.0), 'XYZ')
elif axisLk == 'Z':
rotVal = Euler((0.0,0.0,angleDiffRad), 'XYZ')
vecTmp.rotate(rotVal)
return vecTmp + PivC
# Finds out whether rotDat.newAngR or negative rotDat.newAngR will
# result in desired rotation angle.
# angleEq_0_180 for 0 and 180 degree starting rotations
def RBenVe(Object, Dir):
ObjectV = Object.normalized()
DirV = Dir.normalized()
cosTheta = ObjectV.dot(DirV)
rotationAxis = mathutils.Vector((0.0, 0.0, 0.0))
if (cosTheta < -1 + 0.001):
v = mathutils.Vector((0.0, 1.0, 0.0))
rotationAxis = ObjectV.cross(v)
rotationAxis = rotationAxis.normalized()
q = mathutils.Quaternion()
q.w = 0.0
q.x = rotationAxis.x
q.y = rotationAxis.y
q.z = rotationAxis.z
return q
rotationAxis = ObjectV.cross(DirV)
s = math.sqrt((1.0 + cosTheta) * 2.0)
invs = 1 / s
q = mathutils.Quaternion()
q.w = s * 0.5
q.x = rotationAxis.x * invs
q.y = rotationAxis.y * invs
q.z = rotationAxis.z * invs
return q
def getRotatedPoint(PivC,angleDiffRad,rotDat,movCo):
axisLk = rotDat.axisLk
vecTmp = movCo - PivC
rotVal = []
if axisLk == '': # arbitrary axis / spherical rotations
rotVal = Quaternion(rotDat.pivNorm, angleDiffRad)
elif axisLk == 'X':
rotVal = Euler((angleDiffRad,0.0,0.0), 'XYZ')
elif axisLk == 'Y':
rotVal = Euler((0.0,angleDiffRad,0.0), 'XYZ')
elif axisLk == 'Z':
rotVal = Euler((0.0,0.0,angleDiffRad), 'XYZ')
vecTmp.rotate(rotVal)
return vecTmp + PivC
# Finds out whether rotDat.newAngR or negative rotDat.newAngR will
# result in desired rotation angle.
# angleEq_0_180 for 0 and 180 degree starting rotations
def RBenVe(Object, Dir):
ObjectV = Object.normalized()
DirV = Dir.normalized()
cosTheta = ObjectV.dot(DirV)
rotationAxis = mathutils.Vector((0.0, 0.0, 0.0))
if (cosTheta < -1 + 0.001):
v = mathutils.Vector((0.0, 1.0, 0.0))
rotationAxis = ObjectV.cross(v)
rotationAxis = rotationAxis.normalized()
q = mathutils.Quaternion()
q.w = 0.0
q.x = rotationAxis.x
q.y = rotationAxis.y
q.z = rotationAxis.z
return q
rotationAxis = ObjectV.cross(DirV)
s = math.sqrt((1.0 + cosTheta) * 2.0)
invs = 1 / s
q = mathutils.Quaternion()
q.w = s * 0.5
q.x = rotationAxis.x * invs
q.y = rotationAxis.y * invs
q.z = rotationAxis.z * invs
return q
def relocation_taper_and_bevel(main_ob, sub_ob, is_taper):
# ????
if len(main_ob.data.splines):
if len(main_ob.data.splines[0].points):
end_co = main_ob.matrix_world * mathutils.Vector(main_ob.data.splines[0].points[-1].co[:3])
sub_ob.location = end_co.copy()
# ????
if len(main_ob.data.splines):
spline = main_ob.data.splines[0]
if 2 <= len(spline.points):
# ?????????
sub_ob.rotation_mode = 'QUATERNION'
last_direction = main_ob.matrix_world * mathutils.Vector(spline.points[-2].co[:3]) - main_ob.matrix_world * mathutils.Vector(spline.points[-1].co[:3])
up_direction = mathutils.Vector((0, 0, 1))
sub_ob.rotation_quaternion = up_direction.rotation_difference(last_direction)
# Z??
diff_co = main_ob.matrix_world * mathutils.Vector(spline.points[-1].co[:3]) - main_ob.matrix_world * mathutils.Vector(spline.points[0].co[:3])
rotation_z = math.atan2(diff_co.y, diff_co.x) - spline.points[-1].tilt
if is_taper: sub_ob.rotation_quaternion *= mathutils.Quaternion((0, 0, 1), rotation_z)
else : sub_ob.rotation_quaternion *= mathutils.Quaternion((0, 0, 1), rotation_z - math.radians(90))
def set_view_front(self,context):
for area in context.screen.areas:
if area.type == "VIEW_3D":
for space in area.spaces:
if space.type == "VIEW_3D":
region = space.region_3d
region.view_rotation = Quaternion((0.7071,0.7071,-0.0,-0.0))
def lock_view(screen,lock):
for area in screen.areas:
if area.type == "VIEW_3D":
for space in area.spaces:
if space.type == "VIEW_3D":
region = space.region_3d
if lock:
region.view_rotation = Quaternion((0.7071,0.7071,-0.0,-0.0))
region.lock_rotation = True
else:
region.lock_rotation = False
def get_mesh(self, bend, base_shape, index):
"""produce leaf mesh at position of this leaf given base mesh as input"""
# calculate angles to transform mesh to align with desired direction
trf = self.direction.to_track_quat('Z', 'Y')
right_t = self.right.rotated(trf.inverted())
spin_ang = pi - right_t.angle(Vector([1, 0, 0]))
# calculate bend transform if needed
if bend > 0:
bend_trf_1, bend_trf_2 = self.calc_bend_trf(bend)
else:
bend_trf_1 = bend_trf_2 = None
vertices = []
for vertex in base_shape[0]:
# rotate to correct direction
vertex = vertex.copy()
vertex.rotate(Quaternion(Vector([0, 0, 1]), spin_ang))
vertex.rotate(trf)
# apply bend if needed
if bend > 0:
vertex.rotate(bend_trf_1)
vertex.rotate(bend_trf_2)
# move to right position
vertex += self.position
# add to vertex array
vertices.append(vertex)
# set face to refer to vertices at correct offset in big vertex list
index *= len(vertices)
faces = deepcopy(base_shape[1])
for face in faces:
for ind, elem in enumerate(face):
face[ind] = elem + index
return vertices, faces
def calc_bend_trf(self, bend):
"""calculate the transformations required to 'bend' the leaf out/up from WP"""
normal = self.direction.cross(self.right)
theta_pos = atan2(self.position.y, self.position.x)
theta_bend = theta_pos - atan2(normal.y, normal.x)
bend_trf_1 = Quaternion(Vector([0, 0, 1]), theta_bend * bend)
self.direction.rotate(bend_trf_1)
self.right.rotate(bend_trf_1)
normal = self.direction.cross(self.right)
phi_bend = normal.declination()
if phi_bend > pi / 2:
phi_bend = phi_bend - pi
bend_trf_2 = Quaternion(self.right, phi_bend * bend)
return bend_trf_1, bend_trf_2
def turn_right(self, angle):
"""Turn the turtle right about the axis perpendicular to the direction
it is facing"""
axis = (self.dir.cross(self.right))
axis.normalize()
self.dir.rotate(Quaternion(axis, math.radians(angle)))
self.dir.normalize()
self.right.rotate(Quaternion(axis, math.radians(angle)))
self.right.normalize()
def pitch_up(self, angle):
"""Pitch the turtle up about the right axis"""
self.dir.rotate(Quaternion(self.right, math.radians(angle)))
self.dir.normalize()
def roll_right(self, angle):
"""Roll the turtle right about the direction it is facing"""
self.right.rotate(Quaternion(self.dir, math.radians(angle)))
self.right.normalize()
def apply_tropism(turtle, tropism_vector):
"""Apply tropism_vector to turtle direction"""
h_cross_t = turtle.dir.cross(tropism_vector)
# calc angle to rotate by (from ABoP) multiply to achieve accurate results from WP attractionUp param
alpha = 10 * h_cross_t.magnitude
h_cross_t.normalize()
# rotate by angle about axis perpendicular to turtle direction and tropism vector
turtle.dir.rotate(Quaternion(h_cross_t, radians(alpha)))
turtle.dir.normalize()
turtle.right.rotate(Quaternion(h_cross_t, radians(alpha)))
turtle.right.normalize()
def add_points_to_bez(self, line, point1, point2, width, trunk=False):
"""add point to specific bezier spline"""
direction = (point2 - point1)
handle_f = 0.3
# if exists get middle point in branch
if len(line.bezier_points) > 1:
start_point = line.bezier_points[-1]
# linearly interpolate branch width between start and end of branch
start_point.radius = line.bezier_points[-2].radius * 0.5 + width * 0.5
# add bendiness to branch by rotating direction about random axis by random angle
if self.bendiness > 0:
acc_dir = direction.rotated(Quaternion(Vector.random(), radians(self.bendiness * (random() * 35 - 20))))
else:
acc_dir = direction
start_point.handle_right = point1 + handle_f * acc_dir
start_point.handle_left = point1 - handle_f * acc_dir
else:
# scale initial handle to match branch length
start_point = line.bezier_points[-1]
if trunk:
# if trunk we also need to set the start width
start_point.radius = width
start_point.handle_right = start_point.co + Vector([0, 0, direction.magnitude * handle_f])
else:
start_point.handle_right = start_point.co + (start_point.handle_right -
start_point.co) * direction.magnitude * handle_f
start_point.handle_left = start_point.co + (start_point.handle_left -
start_point.co) * direction.magnitude * handle_f
# add new point to line and set position, direction and width
line.bezier_points.add()
end_point = line.bezier_points[-1]
end_point.co = point2
end_point.handle_right = point2 + handle_f * direction
end_point.handle_left = point2 - handle_f * direction
end_point.radius = width
def read_quaternion(self):
return mathutils.Quaternion((self.read_single(), self.read_single(), self.read_single(), self.read_single()))
def get_view_rotational_matrix(reverse=False):
qt = mathutils.Quaternion(bpy.context.scene.ne_view_orientation)
if reverse:
qt.conjugate()
return qt.to_matrix()
def get_rotation(self):
return Quaternion()
def angle_axis_to_quat(angle, axis):
w = math.cos(angle / 2.0)
xyz = axis.normalized() * math.sin(angle / 2.0)
return Quaternion((w, xyz.x, xyz.y, xyz.z))
def rot(point, axis, angle):
q = Quaternion(axis, angle)
P = point.copy()
P.rotate(q)
#print(point, P)
return P
def extend(p0, p1, p2, loopa, verts):
# will extend this with a tri centered at p0
#print('extend')
#print(p0,p1,p2,[verts[i] for i in loopa])
# both difference point upward, we extend to the second
d1 = p1 - p0
d2 = p0 - p2
p = (verts[loopa[0]] + verts[loopa[1]] + verts[loopa[2]] + verts[loopa[3]]) / 4
a = d1.angle(d2, 0)
if abs(a) < 0.05:
#print('small angle')
loopb = vertcopy(loopa, verts, p0 - d2 / 2 - p)
# all verts in loopb are displaced the same amount so no need to find the minimum distance
n = 4
return ([(loopa[(i) % n], loopa[(i + 1) % n], loopb[(i + 1) % n], loopb[(i) % n]) for i in range(n)], loopa, loopb)
r = d2.cross(d1)
q = Quaternion(r, -a)
dverts = [verts[i] - p for i in loopa]
#print('large angle',dverts,'axis',r)
for dv in dverts:
dv.rotate(q)
#print('rotated',dverts)
for dv in dverts:
dv += (p0 - d2 / 2)
#print('moved',dverts)
loopb = vertextend(verts, dverts)
# none of the verts in loopb are rotated so no need to find the minimum distance
n = 4
return ([(loopa[(i) % n], loopa[(i + 1) % n], loopb[(i + 1) % n], loopb[(i) % n]) for i in range(n)], loopa, loopb)
def console_math_data():
from mathutils import Matrix, Vector, Quaternion, Euler
data_matrix = {}
data_quat = {}
data_euler = {}
data_vector = {}
data_vector_array = {}
for key, var in console_namespace().items():
if key[0] == "_":
continue
state_prop = bpy.context.window_manager.MathVisStatePropList.get(key)
if state_prop:
disp, lock = state_prop.state
if not disp:
continue
var_type = type(var)
if var_type is Matrix:
if len(var.col) != 4 or len(var.row) != 4:
if len(var.col) == len(var.row):
var = var.to_4x4()
else: # todo, support 4x3 matrix
continue
data_matrix[key] = var
elif var_type is Vector:
if len(var) < 3:
var = var.to_3d()
data_vector[key] = var
elif var_type is Quaternion:
data_quat[key] = var
elif var_type is Euler:
data_euler[key] = var
elif var_type in {list, tuple} and is_display_list(var):
data_vector_array[key] = var
return data_matrix, data_quat, data_euler, data_vector, data_vector_array
def _rotate(self, ch, xyzrot):
orientation = self._convert_orientation(ch, xyzrot)
if ch.rotation_mode is bge.logic.ROT_MODE_QUAT:
ch.rotation_quaternion = mathutils.Quaternion(ch.rotation_quaternion) * orientation
else:
ch.rotation_euler = ch.rotation_euler.rotate(orientation)