diff --git a/docs/nodes/quaternion/quaternion_index.rst b/docs/nodes/quaternion/quaternion_index.rst index 7a55fce4c272dbdb2b196d25270c7798061612fd..7edd798ca9b8e7a4300dbfe1f0301d70a2f4beaf 100644 --- a/docs/nodes/quaternion/quaternion_index.rst +++ b/docs/nodes/quaternion/quaternion_index.rst @@ -8,3 +8,4 @@ Quaternion quaternion_in quaternion_out quaternion_math + rotation_difference diff --git a/docs/nodes/quaternion/rotation_difference.rst b/docs/nodes/quaternion/rotation_difference.rst new file mode 100644 index 0000000000000000000000000000000000000000..46be13d934ffdd3289ceba456e6633b01f2b2298 --- /dev/null +++ b/docs/nodes/quaternion/rotation_difference.rst @@ -0,0 +1,49 @@ +Rotation difference +=================== + +.. image:: https://user-images.githubusercontent.com/28003269/72435157-ded07380-37b6-11ea-9ec3-7f8e0b20afda.png + +Functionality +------------- + +Creates quaternion which produce rotation from first to second given points. +It can be alternative of `normal matrix` node. Meanwhile last one can work only with limited number of axis +the `rotation difference` node can work with arbitrary axises. + +Category +-------- + +Quaternions -> Rotation difference + +Inputs +------ + +- **Verts_A** - vertices (start of rotation) +- **Verts_B** - vertices (end of rotation) + +Outputs +------- + +- **Quaternions** - rotation difference between given points + +Parameters +---------- + ++--------------------------+-------+--------------------------------------------------------------------------------+ +| Parameters | Type | Description | ++==========================+=======+================================================================================+ +| Flat output | bool | Put all quaternions into flat list | ++--------------------------+-------+--------------------------------------------------------------------------------+ + +Usage +----- + +First vector of the node is initial direction of monkey head, second one is direction of empty object: + +.. image:: https://user-images.githubusercontent.com/28003269/72435614-ecd2c400-37b7-11ea-80f2-176a0d1df5ee.png +.. image:: https://user-images.githubusercontent.com/28003269/72435623-f52aff00-37b7-11ea-984a-e0d0d4b14013.gif + +Also it is possible to make movements of monkey head more natural by applying Z component separately: + +.. image:: https://user-images.githubusercontent.com/28003269/72444577-b7cf6d00-37c9-11ea-8052-0be2fa3de938.png +.. image:: https://user-images.githubusercontent.com/28003269/72444896-43e19480-37ca-11ea-87c8-326b5c63e6b5.gif \ No newline at end of file diff --git a/index.md b/index.md index 9eb2c783d89b3d59d2dd474c108e7faf8a466324..f45d89f1d771f0b61c28cf469a4c6d4ef661e693 100644 --- a/index.md +++ b/index.md @@ -278,6 +278,7 @@ SvQuaternionInNode SvQuaternionOutNode SvQuaternionMathNode + SvRotationDifference ## Logic SvLogicNode diff --git a/nodes/quaternion/rotation_difference.py b/nodes/quaternion/rotation_difference.py new file mode 100644 index 0000000000000000000000000000000000000000..ff7e529852d2765a660e5411712416f88415a732 --- /dev/null +++ b/nodes/quaternion/rotation_difference.py @@ -0,0 +1,69 @@ +# This file is part of project Sverchok. It's copyrighted by the contributors +# recorded in the version control history of the file, available from +# its original location https://github.com/nortikin/sverchok/commit/master +# +# SPDX-License-Identifier: GPL3 +# License-Filename: LICENSE + + +from itertools import chain, cycle + +import bpy +from mathutils import Vector + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode + + +def get_quaternion(verts_a, verts_b): + """ + returns quaternion which represent rotation from vertices A to vertices B + :param verts_a: list of tuple(float, float, float) + :param verts_b: list of tuple(float, float, float) + :return: list of quaternions + """ + max_len = max([len(verts_a), len(verts_b)]) + verts_a = iter_last(verts_a) + verts_b = iter_last(verts_b) + return [Vector(va).rotation_difference(vb) for i, va, vb in zip(range(max_len), verts_a, verts_b)] + + +def iter_last(l): + return chain(l, cycle([l[-1]])) + + +class SvRotationDifference(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: Quaternion + + creates quaternion which represent rotation from vertices A to vertices B + """ + bl_idname = 'SvRotationDifference' + bl_label = 'Rotation difference' + bl_icon = 'TRACKING_REFINE_BACKWARDS' + + vec1: bpy.props.FloatVectorProperty(default=(1, 0, 0), update=updateNode) + vec2: bpy.props.FloatVectorProperty(default=(0, 1, 0), update=updateNode) + is_flatten: bpy.props.BoolProperty(name="Flat output", update=updateNode, default=True) + + def draw_buttons_ext(self, context, layout): + layout.prop(self, 'is_flatten') + + def sv_init(self, context): + self.inputs.new('SvVerticesSocket', 'Verts_A').prop_name = 'vec1' + self.inputs.new('SvVerticesSocket', "Verts_B").prop_name = 'vec2' + self.outputs.new('SvQuaternionSocket', 'Quaternions') + + def process(self): + max_len = max([len(sock.sv_get(deepcopy=False)) for sock in self.inputs]) + inputs = [iter_last(sock.sv_get(default=False)) for sock in self.inputs] + out = [get_quaternion(v1, v2) for i, v1, v2 in zip(range(max_len), *inputs)] + self.outputs['Quaternions'].sv_set([q for l in out for q in l] if self.is_flatten else out) + + +def register(): + bpy.utils.register_class(SvRotationDifference) + + +def unregister(): + bpy.utils.unregister_class(SvRotationDifference)