Коммит 7414ba61 создал по автору DolphinDream's avatar DolphinDream
Просмотр файлов

Add Scalar-Vector mode to quaternion IN/OUT nodes

Scalar-Vector is the same as WXYZ except that the input/output is provided as scalar W + vector (X,Y,Z). This is to help with the work-flow when quaternions are regarded as a (s,v) pair.

note: The Scalar-Vector is different thant Axis-Angle mode as for this mode the quaternion is Q = cos(a/2) + sin(a/2) * vector(x,y,z)
владелец 4a6e77b2
......@@ -7,28 +7,31 @@ Quaternion In node constructs quaternions based on various input components prov
Modes
=====
The available **Modes** are: WXYZ, EULER, AXIS-ANGLE & MATRIX.
+============+================================================================+
| Mode | Description |
+------------+----------------------------------------------------------------+
| WXYZ | Converts W, X, Y, Z components into a quaternion. [1] |
+------------+----------------------------------------------------------------+
| EULER | Converts X, Y, Z Euler angles and an order of rotation |
| | into a quaternion. [2,3] |
+------------+----------------------------------------------------------------+
| AXIS-ANGLE | Converts an Axis & an Angle of rotation into a quaternion. [2] |
+------------+----------------------------------------------------------------+
| MATRIX | Converts an orthogonal 4x4 rotation matrix into a quaternion. |
+============+================================================================+
The available **Modes** are: WXYZ, SCALAR-VECTOR, EULER, AXIS-ANGLE & MATRIX.
+===============+================================================================+
| Mode | Description |
+---------------+----------------------------------------------------------------+
| WXYZ | Converts W, X, Y, Z components into a quaternion. [1] |
+---------------+----------------------------------------------------------------+
| SCALAR-VECTOR | Converts Scalar & Vector components into a quaternion. [1] |
+---------------+----------------------------------------------------------------+
| EULER | Converts X, Y, Z Euler angles and an order of rotation |
| | into a quaternion. [2,3] |
+---------------+----------------------------------------------------------------+
| AXIS-ANGLE | Converts an Axis & an Angle of rotation into a quaternion. [2] |
+---------------+----------------------------------------------------------------+
| MATRIX | Converts an orthogonal 4x4 rotation matrix into a quaternion. |
+===============+================================================================+
Notes:
[1] : For WXYZ the node provides a "Normalize" option to generate a normalized quaternion.
[1] : For WXYZ and SCALAR-VECTOR modes the node provides a "Normalize" option to generate a normalized quaternion. All the other modes automatically generate a normalized quaternion.
[2] : For EULER and AXIS-ANGLE modes (which take angle input) the node provides an
angle unit conversion to let the angle values be converted to Radians, Degrees or Unities (0-1 range).
[3] : For EULER mode the node provides the option to select the Euler rotation order:
"XYZ", "XZY", "YXZ", "YZX", "ZXY" or "ZYX".
The modes WXYZ and SCALAR-VECTOR are the same except the WXYZ provides 4 floats (W, X, Y and Z) to generate the quaternion, while SCALAR-VECTOR provides a scalar (W) and a vector (X, Y, Z).
Inputs
======
......@@ -40,17 +43,19 @@ extend the length of the connected input lists to match the longest one before c
Based on the selected **Mode** the node makes available the corresponding input sockets:
+============+================================+
| Mode | Input Sockets (types) |
+------------+--------------------------------+
| WXYZ | W, X, Y, Z (floats) |
+------------+--------------------------------+
| EULER | X, Y, Z angles (floats) |
+------------+--------------------------------+
| AXIS-ANGLE | Axis (Vector) & Angle (float) |
+------------+--------------------------------+
| MATRIX | Matrix (4x4 matrix) |
+============+================================+
+===============+==================================+
| Mode | Input Sockets (types) |
+---------------+----------------------------------+
| WXYZ | W, X, Y, Z (floats) |
+---------------+----------------------------------+
| SCALAR-VECTOR | Scalar (float) & Vector (vector) |
+---------------+----------------------------------+
| EULER | X, Y, Z angles (floats) |
+---------------+----------------------------------+
| AXIS-ANGLE | Axis (vector) & Angle (float) |
+---------------+----------------------------------+
| MATRIX | Matrix (4x4 matrix) |
+===============+==================================+
Outputs
......
......@@ -8,22 +8,23 @@ Modes
The available **Modes** are: WXYZ, EULER, AXIS-ANGLE & MATRIX.
+============+==============================================================+
| Mode | Description |
+------------+--------------------------------------------------------------+
| WXYZ | Converts a quaternion into its W, X, Y, Z components. [1] |
+------------+--------------------------------------------------------------+
| EULER | Converts a quaternion into X, Y, Z angles corresponding |
| | to the Euler rotation given an Euler rotation order. [2,3] |
+------------+--------------------------------------------------------------+
| AXIS-ANGLE | Converts a quaternion into the Axis & Angle of rotation. [2] |
+------------+--------------------------------------------------------------+
| MATRIX | Converts a quaternion into an orthogonal 4x4 rotation matrix.|
+============+==============================================================+
+===============+================================================================+
| Mode | Description |
+---------------+----------------------------------------------------------------+
| WXYZ | Converts a quaternion into its W, X, Y, Z components. [1] |
+---------------+----------------------------------------------------------------+
| SCALAR-VECTOR | Converts a quaternion into its Scalar & Vector components. [1] |
+---------------+----------------------------------------------------------------+
| EULER | Converts a quaternion into X, Y, Z angles corresponding |
| | to the Euler rotation given an Euler rotation order. [2,3] |
+---------------+----------------------------------------------------------------+
| AXIS-ANGLE | Converts a quaternion into the Axis & Angle of rotation. [2] |
+---------------+----------------------------------------------------------------+
| MATRIX | Converts a quaternion into an orthogonal 4x4 rotation matrix...|
+===============+================================================================+
Notes:
[1] : For WXYZ the node provides a "Normalize" option to let the input quaternion
be normalized before outputting its components.
[1] : For WXYZ and SCALAR-VECTOR modes the node provides a "Normalize" option to normalize the input quaternion before outputting its components. All the other modes automatically normalize the quaternion.
[2] : For EULER and AXIS-ANGLE modes, which output angles, the node provides an
angle unit conversion to let the angle output values be converted to Radians,
Degrees or Unities (0-1 range).
......@@ -43,17 +44,21 @@ Outputs
Based on the selected **Mode** the node makes available the corresponding output sockets:
+============+================================+
| Mode | Output Sockets (types) |
+------------+--------------------------------+
| WXYZ | W, X, Y, Z (floats) |
+------------+--------------------------------+
| EULER | X, Y, Z angles (floats) |
+------------+--------------------------------+
| AXIS-ANGLE | Axis (Vector) & Angle (float) |
+------------+--------------------------------+
| MATRIX | Matrix (4x4 matrix) |
+============+================================+
+===============+==================================+
| Mode | Output Sockets (types) |
+---------------+----------------------------------+
| WXYZ | W, X, Y, Z (floats) |
+---------------+----------------------------------+
| SCALAR-VECTOR | Scalar (float) & Vector (vector) |
+---------------+----------------------------------+
| EULER | X, Y, Z angles (floats) |
+---------------+----------------------------------+
| AXIS-ANGLE | Axis (vector) & Angle (float) |
+---------------+----------------------------------+
| MATRIX | Matrix (4x4 matrix) |
+===============+==================================+
The modes WXYZ and SCALAR-VECTOR are the same except the WXYZ mode outputs the components as 4 floats (W, X, Y and Z), while the SCALAR-VECTOR mode outputs the components as a scalar (W) and a vector (XYZ).
The node only generates the conversion when the output sockets are connected.
......@@ -26,9 +26,10 @@ from math import pi
modeItems = [
("WXYZ", "WXYZ", "Convert components into quaternion", 0),
("EULER", "Euler Angles", "Convert Euler angles into quaternion", 1),
("AXISANGLE", "Axis Angle", "Convert Axis & Angle into quaternion", 2),
("MATRIX", "Matrix", "Convert Rotation Matrix into quaternion", 3),
("SCALARVECTOR", "Scalar Vector", "Convert Scalar & Vector into quaternion", 1),
("EULER", "Euler Angles", "Convert Euler angles into quaternion", 2),
("AXISANGLE", "Axis Angle", "Convert Axis & Angle into quaternion", 3),
("MATRIX", "Matrix", "Convert Rotation Matrix into quaternion", 4),
]
eulerOrderItems = [
......@@ -52,6 +53,7 @@ idMat = [[tuple(v) for v in Matrix()]] # identity matrix
input_sockets = {
"WXYZ": ["W", "X", "Y", "Z"],
"SCALARVECTOR": ["Scalar", "Vector"],
"EULER": ["Angle X", "Angle Y", "Angle Z"],
"AXISANGLE": ["Angle", "Axis"],
"MATRIX": ["Matrix"]
......@@ -81,7 +83,7 @@ class SvQuaternionInNode(bpy.types.Node, SverchCustomTreeNode):
updateNode(self, context)
mode = EnumProperty(
name='Mode', description='Input mode (wxyz, Euler, Axis-Angle, Matrix)',
name='Mode', description='The input component format of the quaternion',
items=modeItems, default="WXYZ", update=update_mode)
eulerOrder = EnumProperty(
......@@ -108,6 +110,14 @@ class SvQuaternionInNode(bpy.types.Node, SverchCustomTreeNode):
name='Z', description='Z component',
default=0.0, precision=3, update=updateNode)
scalar = FloatProperty(
name='Scalar', description='Scalar component of the quaternion',
default=0.0, update=updateNode)
vector = FloatVectorProperty(
name='Vector', description='Vector component of the quaternion',
size=3, default=(0.0, 0.0, 0.0), subtype="XYZ", update=updateNode)
angle_x = FloatProperty(
name='Angle X', description='Rotation angle about X axis',
default=0.0, precision=3, update=updateNode)
......@@ -137,6 +147,8 @@ class SvQuaternionInNode(bpy.types.Node, SverchCustomTreeNode):
self.inputs.new('StringsSocket', "X").prop_name = 'component_x'
self.inputs.new('StringsSocket', "Y").prop_name = 'component_y'
self.inputs.new('StringsSocket', "Z").prop_name = 'component_z'
self.inputs.new('StringsSocket', "Scalar").prop_name = 'scalar'
self.inputs.new('VerticesSocket', "Vector").prop_name = "vector"
self.inputs.new('StringsSocket', "Angle X").prop_name = 'angle_x'
self.inputs.new('StringsSocket', "Angle Y").prop_name = 'angle_y'
self.inputs.new('StringsSocket', "Angle Z").prop_name = 'angle_z'
......@@ -155,7 +167,7 @@ class SvQuaternionInNode(bpy.types.Node, SverchCustomTreeNode):
if self.mode in {"EULER", "AXISANGLE"}:
row = layout.row(align=True)
row.prop(self, "angleUnits", expand=True)
if self.mode == "WXYZ":
if self.mode in {"WXYZ", "SCALARVECTOR"}:
layout.prop(self, "normalize", toggle=True)
def process(self):
......@@ -175,6 +187,15 @@ class SvQuaternionInNode(bpy.types.Node, SverchCustomTreeNode):
q.normalize()
quaternionList.append(q)
elif self.mode == "SCALARVECTOR":
I = [inputs[n].sv_get()[0] for n in ["Scalar", "Vector"]]
params = match_long_repeat(I)
for scalar, vector in zip(*params):
q = Quaternion([scalar, *vector])
if self.normalize:
q.normalize()
quaternionList.append(q)
elif self.mode == "EULER":
I = [inputs["Angle " + n].sv_get()[0] for n in "XYZ"]
params = match_long_repeat(I)
......
......@@ -128,7 +128,7 @@ class SvQuaternionMathNode(bpy.types.Node, SverchCustomTreeNode):
inputs_AZ = list(filter(lambda s: s.name in ABC, inputs))
# last A-Z socket connected ? => add an empty A-Z socket at the end
if inputs_AZ[-1].links:
if inputs_AZ and inputs_AZ[-1].links:
name = ABC[len(inputs_AZ)] # pick the next letter A to Z
inputs.new("SvQuaternionSocket", name)
else: # last input disconnected ? => remove all but last unconnected
......
......@@ -26,9 +26,10 @@ from math import pi
modeItems = [
("WXYZ", "WXYZ", "Convert quaternion into components", 0),
("EULER", "Euler Angles", "Convert quaternion into Euler angles", 1),
("AXISANGLE", "Axis Angle", "Convert quaternion into Axis & Angle", 2),
("MATRIX", "Matrix", "Convert quaternion into Rotation Matrix", 3),
("SCALARVECTOR", "Scalar Vector", "Convert quaternion into Scalar & Vector", 1),
("EULER", "Euler Angles", "Convert quaternion into Euler angles", 2),
("AXISANGLE", "Axis Angle", "Convert quaternion into Axis & Angle", 3),
("MATRIX", "Matrix", "Convert quaternion into Rotation Matrix", 4),
]
eulerOrderItems = [
......@@ -50,6 +51,7 @@ angleConversion = {"RAD": 1.0, "DEG": 180.0 / pi, "UNI": 0.5 / pi}
output_sockets = {
"WXYZ": ["W", "X", "Y", "Z"],
"SCALARVECTOR": ["Scalar", "Vector"],
"EULER": ["Angle X", "Angle Y", "Angle Z"],
"AXISANGLE": ["Angle", "Axis"],
"MATRIX": ["Matrix"]
......@@ -79,7 +81,7 @@ class SvQuaternionOutNode(bpy.types.Node, SverchCustomTreeNode):
updateNode(self, context)
mode = EnumProperty(
name='Mode', description='Output mode (wxyz, Euler, Axis-Angle, Matrix)',
name='Mode', description='The output component format of the quaternion',
items=modeItems, default="WXYZ", update=update_mode)
eulerOrder = EnumProperty(
......@@ -106,6 +108,9 @@ class SvQuaternionOutNode(bpy.types.Node, SverchCustomTreeNode):
self.outputs.new('StringsSocket', "X")
self.outputs.new('StringsSocket', "Y")
self.outputs.new('StringsSocket', "Z")
# scalar-vector output
self.outputs.new('StringsSocket', "Scalar")
self.outputs.new('VerticesSocket', "Vector")
# euler angle ouputs
self.outputs.new('StringsSocket', "Angle X")
self.outputs.new('StringsSocket', "Angle Y")
......@@ -126,7 +131,7 @@ class SvQuaternionOutNode(bpy.types.Node, SverchCustomTreeNode):
if self.mode in {"EULER", "AXISANGLE"}:
row = layout.row(align=True)
row.prop(self, "angleUnits", expand=True)
if self.mode == "WXYZ":
if self.mode in {"WXYZ", "SCALARVECTOR"}:
layout.prop(self, "normalize", toggle=True)
def process(self):
......@@ -140,10 +145,23 @@ class SvQuaternionOutNode(bpy.types.Node, SverchCustomTreeNode):
if self.mode == "WXYZ":
if self.normalize:
quaternionList = [q.normalized() for q in quaternionList]
for i, name in enumerate("WXYZ"):
if outputs[name].is_linked:
outputs[name].sv_set([[q[i] for q in quaternionList]])
elif self.mode == "SCALARVECTOR":
if self.normalize:
quaternionList = [q.normalized() for q in quaternionList]
if outputs['Scalar'].is_linked:
scalarList = [q[0] for q in quaternionList]
outputs['Scalar'].sv_set([scalarList])
if outputs['Vector'].is_linked:
vectorList = [tuple(q[1:]) for q in quaternionList]
outputs['Vector'].sv_set([vectorList])
elif self.mode == "EULER":
au = angleConversion[self.angleUnits]
for i, name in enumerate("XYZ"):
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать