forked from LeenkxTeam/LNXSDK
Update leenkx/blender/lnx/logicnode/lnx_sockets.py
This commit is contained in:
parent
30e5acf9bf
commit
bdcf4c980b
@ -158,70 +158,90 @@ class LnxRotationSocket(LnxCustomSocket):
|
||||
self.do_update_raw(context)
|
||||
|
||||
@staticmethod
|
||||
def convert_to_quaternion(part1,part2,param1,param2,param3):
|
||||
"""converts a representation of rotation into a quaternion.
|
||||
``part1`` is a vector, ``part2`` is a scalar or None,
|
||||
``param1`` is in ('Quaternion', 'EulerAngles', 'AxisAngle'),
|
||||
``param2`` is in ('Rad','Deg') for both EulerAngles and AxisAngle,
|
||||
``param3`` is a len-3 string like "XYZ", for EulerAngles """
|
||||
if param1=='Quaternion':
|
||||
qx, qy, qz = part1[0], part1[1], part1[2]
|
||||
qw = part2
|
||||
# need to normalize the quaternion for a rotation (having it be 0 is not an option)
|
||||
ql = sqrt(qx**2+qy**2+qz**2+qw**2)
|
||||
if abs(ql)<1E-5:
|
||||
qx, qy, qz, qw = 0.0,0.0,0.0,1.0
|
||||
def convert_to_quaternion(vec3_val, scalar_val, mode, unit, order):
|
||||
'''Converts Euler or Axis-Angle representation to a Quaternion Vector'''
|
||||
|
||||
if mode == 'Quaternion':
|
||||
qx, qy, qz = vec3_val[0], vec3_val[1], vec3_val[2]
|
||||
qw = scalar_val
|
||||
|
||||
ql = sqrt(qx**2 + qy**2 + qz**2 + qw**2)
|
||||
if abs(ql) < 1E-5:
|
||||
qx, qy, qz, qw = 0.0, 0.0, 0.0, 1.0
|
||||
else:
|
||||
qx /= ql
|
||||
qy /= ql
|
||||
qz /= ql
|
||||
qw /= ql
|
||||
return mathutils.Vector((qx,qy,qz,qw))
|
||||
return mathutils.Vector((qx, qy, qz, qw))
|
||||
|
||||
elif param1 == 'AxisAngle':
|
||||
if param2 == 'Deg':
|
||||
angle = part2 * pi/180
|
||||
else:
|
||||
angle = part2
|
||||
cang, sang = cos(angle/2), sin(angle/2)
|
||||
x,y,z = part1[0], part1[1], part1[2]
|
||||
veclen = sqrt(x**2+y**2+z**2)
|
||||
if veclen<1E-5:
|
||||
return mathutils.Vector((0.0,0.0,0.0,1.0))
|
||||
else:
|
||||
return mathutils.Vector((
|
||||
x/veclen * sang,
|
||||
y/veclen * sang,
|
||||
z/veclen * sang,
|
||||
cang
|
||||
))
|
||||
else: # param1 == 'EulerAngles'
|
||||
x,y,z = part1[0], part1[1], part1[2]
|
||||
if param2 == 'Deg':
|
||||
x *= pi/180
|
||||
y *= pi/180
|
||||
z *= pi/180
|
||||
|
||||
euler = mathutils.Euler((x, y, z), param3)
|
||||
quat = euler.to_quaternion()
|
||||
elif mode == 'EulerAngles':
|
||||
x, y, z = vec3_val.to_tuple()
|
||||
|
||||
if unit == 'Deg':
|
||||
x, y, z = radians(x), radians(y), radians(z)
|
||||
|
||||
angles_ordered = [0.0, 0.0, 0.0]
|
||||
for i, axis in enumerate(order):
|
||||
if axis == 'X':
|
||||
angles_ordered[i] = x
|
||||
elif axis == 'Y':
|
||||
angles_ordered[i] = y
|
||||
elif axis == 'Z':
|
||||
angles_ordered[i] = z
|
||||
eul = mathutils.Euler(angles_ordered, order)
|
||||
quat = eul.to_quaternion()
|
||||
return mathutils.Vector((quat.x, quat.y, quat.z, quat.w))
|
||||
|
||||
|
||||
elif mode == 'AxisAngle':
|
||||
axis = vec3_val.normalized().to_tuple()
|
||||
angle = scalar_val
|
||||
if unit == 'Deg':
|
||||
angle = radians(angle)
|
||||
quat = mathutils.Quaternion(axis, angle)
|
||||
return mathutils.Vector((quat.x, quat.y, quat.z, quat.w))
|
||||
|
||||
print(f"Warning: Invalid mode '{mode}' in convert_to_quaternion")
|
||||
return mathutils.Vector((0.0, 0.0, 0.0, 1.0))
|
||||
|
||||
|
||||
|
||||
def do_update_raw(self, context):
|
||||
part1 = mathutils.Vector((
|
||||
self.default_value_s0,
|
||||
self.default_value_s1,
|
||||
self.default_value_s2, 1
|
||||
))
|
||||
part2 = self.default_value_s3
|
||||
if self.default_value_mode == 'Quaternion':
|
||||
# Directly construct the quaternion vector from s0, s1, s2, s3 (x, y, z, w)
|
||||
vec3_val = mathutils.Vector((
|
||||
self.default_value_s0, # X component or Euler X or Axis X
|
||||
self.default_value_s1, # Y component or Euler Y or Axis Y
|
||||
self.default_value_s2 # Z component or Euler Z or Axis Z
|
||||
))
|
||||
scalar_val = self.default_value_s3 # W component or Axis Angle
|
||||
|
||||
self.default_value_raw = self.convert_to_quaternion(
|
||||
part1,
|
||||
self.default_value_s3,
|
||||
self.default_value_mode,
|
||||
self.default_value_unit,
|
||||
self.default_value_order
|
||||
)
|
||||
# Always call the unified conversion function
|
||||
# The result will be in (x, y, z, w) order
|
||||
self.default_value_raw = self.convert_to_quaternion(
|
||||
vec3_val,
|
||||
scalar_val,
|
||||
self.default_value_mode,
|
||||
self.default_value_unit,
|
||||
self.default_value_order
|
||||
)
|
||||
else:
|
||||
# Handle EulerAngles and AxisAngle using the conversion helper
|
||||
vec3_val = mathutils.Vector((
|
||||
self.default_value_s0,
|
||||
self.default_value_s1,
|
||||
self.default_value_s2
|
||||
))
|
||||
# s3 is used for AxisAngle angle, irrelevant for Euler
|
||||
scalar_val = self.default_value_s3
|
||||
|
||||
self.default_value_raw = self.convert_to_quaternion(
|
||||
vec3_val, # Vector part (Euler angles X,Y,Z or Axis X,Y,Z)
|
||||
scalar_val, # Scalar part (Axis angle)
|
||||
self.default_value_mode, # Mode ('EulerAngles' or 'AxisAngle')
|
||||
self.default_value_unit, # Unit ('Rad' or 'Deg')
|
||||
self.default_value_order # Order ('XYZ', 'ZYX', etc. - used only for Euler)
|
||||
)
|
||||
|
||||
|
||||
def draw(self, context, layout, node, text):
|
||||
@ -275,9 +295,11 @@ class LnxRotationSocket(LnxCustomSocket):
|
||||
('YZX','YZX','YZX'),
|
||||
('ZXY','ZXY','ZXY'),
|
||||
('ZYX','ZYX','ZYX')],
|
||||
name='', default='XYZ'
|
||||
name='', default='XYZ',
|
||||
update=do_update_raw
|
||||
)
|
||||
|
||||
|
||||
default_value_s0: FloatProperty(update=do_update_raw)
|
||||
default_value_s1: FloatProperty(update=do_update_raw)
|
||||
default_value_s2: FloatProperty(update=do_update_raw)
|
||||
|
Loading…
x
Reference in New Issue
Block a user