diff options
author | Charlie Jolly <charlie> | 2020-02-17 18:15:46 +0300 |
---|---|---|
committer | Charlie Jolly <mistajolly@gmail.com> | 2020-02-17 18:43:18 +0300 |
commit | 20a4cdfd700d3722fdcaa3b3952ccea1b0e6ee47 (patch) | |
tree | 16eee69e8e1d3bdfb902e05df15b055f7141fd4d | |
parent | ab3a6e050c856345d10f8e36155913288559e4dc (diff) |
Cycles: Vector Rotate Node using Axis and Angle method
This node provides the ability to rotate a vector around a `center` point using either `Axis Angle` , `Single Axis` or `Euler` methods.
Reviewed By: #cycles, brecht
Differential Revision: https://developer.blender.org/D3789
23 files changed, 546 insertions, 1 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 12009d6160c..5a70126e012 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -323,6 +323,12 @@ static ShaderNode *add_node(Scene *scene, vector_math_node->type = (NodeVectorMathType)b_vector_math_node.operation(); node = vector_math_node; } + else if (b_node.is_a(&RNA_ShaderNodeVectorRotate)) { + BL::ShaderNodeVectorRotate b_vector_rotate_node(b_node); + VectorRotateNode *vector_rotate_node = new VectorRotateNode(); + vector_rotate_node->type = (NodeVectorRotateType)b_vector_rotate_node.rotation_type(); + node = vector_rotate_node; + } else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) { BL::ShaderNodeVectorTransform b_vector_transform_node(b_node); VectorTransformNode *vtransform = new VectorTransformNode(); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 99172f30b8b..566b6e3d191 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -228,6 +228,7 @@ set(SRC_SVM_HEADERS svm/svm_fractal_noise.h svm/svm_types.h svm/svm_value.h + svm/svm_vector_rotate.h svm/svm_vector_transform.h svm/svm_voronoi.h svm/svm_voxel.h diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 1c9445107ad..958ebe2f04e 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -78,6 +78,7 @@ set(SRC_OSL node_value.osl node_vector_curves.osl node_vector_math.osl + node_vector_rotate.osl node_vector_transform.osl node_velvet_bsdf.osl node_vertex_color.osl diff --git a/intern/cycles/kernel/shaders/node_math.h b/intern/cycles/kernel/shaders/node_math.h index 7d8478672af..4b1a6c5bc16 100644 --- a/intern/cycles/kernel/shaders/node_math.h +++ b/intern/cycles/kernel/shaders/node_math.h @@ -87,3 +87,24 @@ point wrap(point value, point max, point min) wrap(value[1], max[1], min[1]), wrap(value[2], max[2], min[2])); } + +matrix euler_to_mat(point euler) +{ + float cx = cos(euler[0]); + float cy = cos(euler[1]); + float cz = cos(euler[2]); + float sx = sin(euler[0]); + float sy = sin(euler[1]); + float sz = sin(euler[2]); + matrix mat = matrix(1.0); + mat[0][0] = cy * cz; + mat[0][1] = cy * sz; + mat[0][2] = -sy; + mat[1][0] = sy * sx * cz - cx * sz; + mat[1][1] = sy * sx * sz + cx * cz; + mat[1][2] = cy * sx; + +mat[2][0] = sy * cx * cz + sx * sz; + mat[2][1] = sy * cx * sz - sx * cz; + mat[2][2] = cy * cx; + return mat; +} diff --git a/intern/cycles/kernel/shaders/node_vector_rotate.osl b/intern/cycles/kernel/shaders/node_vector_rotate.osl new file mode 100644 index 00000000000..a049ee92dbc --- /dev/null +++ b/intern/cycles/kernel/shaders/node_vector_rotate.osl @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stdcycles.h" +#include "node_math.h" + +shader node_vector_rotate(string type = "axis", + vector VectorIn = vector(0.0, 0.0, 0.0), + point Center = point(0.0, 0.0, 0.0), + point Rotation = point(0.0, 0.0, 0.0), + vector Axis = vector(0.0, 0.0, 1.0), + float Angle = 0.0, + output vector VectorOut = vector(0.0, 0.0, 0.0)) +{ + if (type == "euler_xyz") { + VectorOut = transform(euler_to_mat(Rotation), VectorIn - Center) + Center; + } + else if (type == "euler_xzy") { + VectorOut = transform(euler_to_mat(point(-Rotation[0], -Rotation[2], -Rotation[1])), + VectorIn - Center) + + Center; + } + else if (type == "euler_yxz") { + VectorOut = transform(euler_to_mat(point(-Rotation[1], -Rotation[0], -Rotation[2])), + VectorIn - Center) + + Center; + } + else if (type == "euler_yzx") { + VectorOut = transform(euler_to_mat(point(Rotation[1], Rotation[2], Rotation[0])), + VectorIn - Center) + + Center; + } + else if (type == "euler_zxy") { + VectorOut = transform(euler_to_mat(point(Rotation[2], Rotation[0], Rotation[1])), + VectorIn - Center) + + Center; + } + else if (type == "euler_zyx") { + VectorOut = transform(euler_to_mat(point(-Rotation[2], -Rotation[1], -Rotation[0])), + VectorIn - Center) + + Center; + } + else if (type == "x_axis") { + VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(1.0, 0.0, 0.0)) + Center; + } + else if (type == "y_axis") { + VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(0.0, 1.0, 0.0)) + Center; + } + else if (type == "z_axis") { + VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(0.0, 0.0, 1.0)) + Center; + } + else { // axis + VectorOut = (length(Axis) != 0.0) ? + rotate(VectorIn - Center, Angle, point(0.0), Axis) + Center : + VectorIn; + } +} diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index fd2833ee687..88c9dbf5838 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -200,6 +200,7 @@ CCL_NAMESPACE_END #include "kernel/svm/svm_voronoi.h" #include "kernel/svm/svm_checker.h" #include "kernel/svm/svm_brick.h" +#include "kernel/svm/svm_vector_rotate.h" #include "kernel/svm/svm_vector_transform.h" #include "kernel/svm/svm_voxel.h" #include "kernel/svm/svm_bump.h" @@ -513,6 +514,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, case NODE_COMBINE_HSV: svm_node_combine_hsv(kg, sd, stack, node.y, node.z, node.w, &offset); break; + case NODE_VECTOR_ROTATE: + svm_node_vector_rotate(sd, stack, node.y, node.z, node.w); + break; case NODE_VECTOR_TRANSFORM: svm_node_vector_transform(kg, sd, stack, node); break; diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 45c299e0acb..cff2b964c51 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -153,6 +153,7 @@ typedef enum ShaderNodeType { NODE_AOV_START, NODE_AOV_VALUE, NODE_AOV_COLOR, + NODE_VECTOR_ROTATE, } ShaderNodeType; typedef enum NodeAttributeType { @@ -351,6 +352,19 @@ typedef enum NodeMappingType { NODE_MAPPING_TYPE_NORMAL } NodeMappingType; +typedef enum NodeVectorRotateType { + NODE_VECTOR_ROTATE_TYPE_AXIS, + NODE_VECTOR_ROTATE_TYPE_AXIS_X, + NODE_VECTOR_ROTATE_TYPE_AXIS_Y, + NODE_VECTOR_ROTATE_TYPE_AXIS_Z, + NODE_VECTOR_ROTATE_TYPE_EULER_XYZ, + NODE_VECTOR_ROTATE_TYPE_EULER_XZY, + NODE_VECTOR_ROTATE_TYPE_EULER_YXZ, + NODE_VECTOR_ROTATE_TYPE_EULER_YZX, + NODE_VECTOR_ROTATE_TYPE_EULER_ZXY, + NODE_VECTOR_ROTATE_TYPE_EULER_ZYX, +} NodeVectorRotateType; + typedef enum NodeVectorTransformType { NODE_VECTOR_TRANSFORM_TYPE_VECTOR, NODE_VECTOR_TRANSFORM_TYPE_POINT, diff --git a/intern/cycles/kernel/svm/svm_vector_rotate.h b/intern/cycles/kernel/svm/svm_vector_rotate.h new file mode 100644 index 00000000000..c7923e10c53 --- /dev/null +++ b/intern/cycles/kernel/svm/svm_vector_rotate.h @@ -0,0 +1,87 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + +/* Vector Rotate */ + +ccl_device void svm_node_vector_rotate(ShaderData *sd, + float *stack, + uint input_stack_offsets, + uint axis_stack_offsets, + uint result_stack_offset) +{ + uint type, vector_stack_offset, rotation_stack_offset, center_stack_offset, axis_stack_offset, + angle_stack_offset; + + svm_unpack_node_uchar3(input_stack_offsets, &type, &vector_stack_offset, &rotation_stack_offset); + svm_unpack_node_uchar3( + axis_stack_offsets, ¢er_stack_offset, &axis_stack_offset, &angle_stack_offset); + + float3 vector = stack_load_float3(stack, vector_stack_offset); + float3 center = stack_load_float3(stack, center_stack_offset); + float3 result = make_float3(0.0f, 0.0f, 0.0f); + + if (type != NODE_VECTOR_ROTATE_TYPE_AXIS && type != NODE_VECTOR_ROTATE_TYPE_AXIS_X && + type != NODE_VECTOR_ROTATE_TYPE_AXIS_Y && type != NODE_VECTOR_ROTATE_TYPE_AXIS_Z) { + float3 rotation = stack_load_float3(stack, rotation_stack_offset); // Default XYZ. + switch (type) { + case NODE_VECTOR_ROTATE_TYPE_EULER_XZY: + rotation = make_float3(-rotation.x, -rotation.z, -rotation.y); + break; + case NODE_VECTOR_ROTATE_TYPE_EULER_YXZ: + rotation = make_float3(-rotation.y, -rotation.x, -rotation.z); + break; + case NODE_VECTOR_ROTATE_TYPE_EULER_YZX: + rotation = make_float3(rotation.y, rotation.z, rotation.x); + break; + case NODE_VECTOR_ROTATE_TYPE_EULER_ZXY: + rotation = make_float3(rotation.z, rotation.x, rotation.y); + break; + case NODE_VECTOR_ROTATE_TYPE_EULER_ZYX: + rotation = make_float3(-rotation.z, -rotation.y, -rotation.x); + break; + } + Transform rotationTransform = euler_to_transform(rotation); + result = transform_direction(&rotationTransform, vector - center) + center; + } + else { + float3 axis; + switch (type) { + case NODE_VECTOR_ROTATE_TYPE_AXIS_X: + axis = make_float3(1.0f, 0.0f, 0.0f); + break; + case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: + axis = make_float3(0.0f, 1.0f, 0.0f); + break; + case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: + axis = make_float3(0.0f, 0.0f, 1.0f); + break; + default: + axis = normalize(stack_load_float3(stack, axis_stack_offset)); + break; + } + float angle = stack_load_float(stack, angle_stack_offset); + result = is_zero(axis) ? vector : rotate_around_axis(vector - center, axis, angle) + center; + } + + /* Output */ + if (stack_valid(result_stack_offset)) { + stack_store_float3(stack, result_stack_offset, result); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 83b973011a1..41b4b05ba19 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -6131,6 +6131,64 @@ void VectorMathNode::compile(OSLCompiler &compiler) compiler.add(this, "node_vector_math"); } +/* Vector Rotate */ + +NODE_DEFINE(VectorRotateNode) +{ + NodeType *type = NodeType::add("vector_rotate", create, NodeType::SHADER); + + static NodeEnum type_enum; + type_enum.insert("axis", NODE_VECTOR_ROTATE_TYPE_AXIS); + type_enum.insert("x_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_X); + type_enum.insert("y_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Y); + type_enum.insert("z_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Z); + type_enum.insert("euler_xyz", NODE_VECTOR_ROTATE_TYPE_EULER_XYZ); + type_enum.insert("euler_xzy", NODE_VECTOR_ROTATE_TYPE_EULER_XZY); + type_enum.insert("euler_yxz", NODE_VECTOR_ROTATE_TYPE_EULER_YXZ); + type_enum.insert("euler_yzx", NODE_VECTOR_ROTATE_TYPE_EULER_YZX); + type_enum.insert("euler_zxy", NODE_VECTOR_ROTATE_TYPE_EULER_ZXY); + type_enum.insert("euler_zyx", NODE_VECTOR_ROTATE_TYPE_EULER_ZYX); + SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS); + + SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_POINT(rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_POINT(center, "Center", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_VECTOR(axis, "Axis", make_float3(0.0f, 0.0f, 1.0f)); + SOCKET_IN_FLOAT(angle, "Angle", 0.0f); + SOCKET_OUT_VECTOR(vector, "Vector"); + + return type; +} + +VectorRotateNode::VectorRotateNode() : ShaderNode(node_type) +{ +} + +void VectorRotateNode::compile(SVMCompiler &compiler) +{ + ShaderInput *vector_in = input("Vector"); + ShaderInput *rotation_in = input("Rotation"); + ShaderInput *center_in = input("Center"); + ShaderInput *axis_in = input("Axis"); + ShaderInput *angle_in = input("Angle"); + ShaderOutput *vector_out = output("Vector"); + + compiler.add_node(NODE_VECTOR_ROTATE, + compiler.encode_uchar4(type, + compiler.stack_assign(vector_in), + compiler.stack_assign(rotation_in)), + compiler.encode_uchar4(compiler.stack_assign(center_in), + compiler.stack_assign(axis_in), + compiler.stack_assign(angle_in)), + compiler.stack_assign(vector_out)); +} + +void VectorRotateNode::compile(OSLCompiler &compiler) +{ + compiler.parameter(this, "type"); + compiler.add(this, "node_vector_rotate"); +} + /* VectorTransform */ NODE_DEFINE(VectorTransformNode) diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 8346ac77ae6..3cf1c56feb0 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -1384,6 +1384,22 @@ class VectorMathNode : public ShaderNode { NodeVectorMathType type; }; +class VectorRotateNode : public ShaderNode { + public: + SHADER_NODE_CLASS(VectorRotateNode) + + virtual int get_group() + { + return NODE_GROUP_LEVEL_3; + } + NodeVectorRotateType type; + float3 vector; + float3 center; + float3 axis; + float angle; + float3 rotation; +}; + class VectorTransformNode : public ShaderNode { public: SHADER_NODE_CLASS(VectorTransformNode) diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index d9a374503b3..969a1ca1bd7 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -264,6 +264,7 @@ shader_node_categories = [ NodeItem("ShaderNodeNormalMap"), NodeItem("ShaderNodeNormal"), NodeItem("ShaderNodeVectorCurve"), + NodeItem("ShaderNodeVectorRotate"), NodeItem("ShaderNodeVectorTransform"), ]), ShaderNodeCategory("SH_NEW_CONVERTOR", "Converter", items=[ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index a8305862d89..712e97a77f0 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -994,6 +994,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, #define SH_NODE_VOLUME_INFO 705 #define SH_NODE_VERTEX_COLOR 706 #define SH_NODE_OUTPUT_AOV 707 +#define SH_NODE_VECTOR_ROTATE 708 /* custom defines options for Material node */ // #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 2a8c9f2a40b..3d413b8fd62 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3975,6 +3975,7 @@ static void registerShaderNodes(void) register_node_type_sh_clamp(); register_node_type_sh_math(); register_node_type_sh_vect_math(); + register_node_type_sh_vector_rotate(); register_node_type_sh_vect_transform(); register_node_type_sh_squeeze(); register_node_type_sh_invert(); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index a00006f7025..8633ebca8d6 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -745,6 +745,11 @@ static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), Poin uiItemR(layout, ptr, "vector_type", 0, NULL, ICON_NONE); } +static void node_shader_buts_vector_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "rotation_type", 0, NULL, ICON_NONE); +} + static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); @@ -1207,6 +1212,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_VECTOR_MATH: ntype->draw_buttons = node_shader_buts_vect_math; break; + case SH_NODE_VECTOR_ROTATE: + ntype->draw_buttons = node_shader_buts_vector_rotate; + break; case SH_NODE_VECT_TRANSFORM: ntype->draw_buttons = node_shader_buts_vect_transform; break; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 0ab3e775566..8a900938d2a 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -303,6 +303,7 @@ data_to_c_simple(shaders/material/gpu_shader_material_uv_map.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_vector_curves.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_vector_displacement.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_vector_math.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_vector_rotate.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_velvet.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_vertex_color.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_volume_absorption.glsl SRC) diff --git a/source/blender/gpu/intern/gpu_material_library.c b/source/blender/gpu/intern/gpu_material_library.c index e7ec1bb12a2..959e5ef7440 100644 --- a/source/blender/gpu/intern/gpu_material_library.c +++ b/source/blender/gpu/intern/gpu_material_library.c @@ -119,6 +119,7 @@ extern char datatoc_gpu_shader_material_uv_map_glsl[]; extern char datatoc_gpu_shader_material_vector_curves_glsl[]; extern char datatoc_gpu_shader_material_vector_displacement_glsl[]; extern char datatoc_gpu_shader_material_vector_math_glsl[]; +extern char datatoc_gpu_shader_material_vector_rotate_glsl[]; extern char datatoc_gpu_shader_material_velvet_glsl[]; extern char datatoc_gpu_shader_material_vertex_color_glsl[]; extern char datatoc_gpu_shader_material_volume_absorption_glsl[]; @@ -527,6 +528,11 @@ static GPUMaterialLibrary gpu_shader_material_vector_math_library = { .dependencies = {&gpu_shader_material_math_util_library, NULL}, }; +static GPUMaterialLibrary gpu_shader_material_vector_rotate_library = { + .code = datatoc_gpu_shader_material_vector_rotate_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + static GPUMaterialLibrary gpu_shader_material_velvet_library = { .code = datatoc_gpu_shader_material_velvet_glsl, .dependencies = {&gpu_shader_material_diffuse_library, NULL}, @@ -647,6 +653,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = { &gpu_shader_material_vector_curves_library, &gpu_shader_material_vector_displacement_library, &gpu_shader_material_vector_math_library, + &gpu_shader_material_vector_rotate_library, &gpu_shader_material_velvet_library, &gpu_shader_material_vertex_color_library, &gpu_shader_material_volume_absorption_library, @@ -879,4 +886,3 @@ char *gpu_material_library_generate_code(GSet *used_libraries, const char *frag_ return result; } - diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl new file mode 100644 index 00000000000..7d707706a03 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl @@ -0,0 +1,82 @@ +vec3 rotate_around_axis(vec3 p, vec3 axis, float angle) +{ + float costheta = cos(angle); + float sintheta = sin(angle); + vec3 r; + + r.x = ((costheta + (1.0 - costheta) * axis.x * axis.x) * p.x) + + (((1.0 - costheta) * axis.x * axis.y - axis.z * sintheta) * p.y) + + (((1.0 - costheta) * axis.x * axis.z + axis.y * sintheta) * p.z); + + r.y = (((1.0 - costheta) * axis.x * axis.y + axis.z * sintheta) * p.x) + + ((costheta + (1.0 - costheta) * axis.y * axis.y) * p.y) + + (((1.0 - costheta) * axis.y * axis.z - axis.x * sintheta) * p.z); + + r.z = (((1.0 - costheta) * axis.x * axis.z - axis.y * sintheta) * p.x) + + (((1.0 - costheta) * axis.y * axis.z + axis.x * sintheta) * p.y) + + ((costheta + (1.0 - costheta) * axis.z * axis.z) * p.z); + + return r; +} + +void node_vector_rotate_axis_angle( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = (length(axis) != 0.0) ? + rotate_around_axis(vector_in - center, normalize(axis), angle) + center : + vector_in; +} + +void node_vector_rotate_axis_x( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = rotate_around_axis(vector_in - center, vec3(1.0, 0.0, 0.0), angle) + center; +} + +void node_vector_rotate_axis_y( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = rotate_around_axis(vector_in - center, vec3(0.0, 1.0, 0.0), angle) + center; +} + +void node_vector_rotate_axis_z( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = rotate_around_axis(vector_in - center, vec3(0.0, 0.0, 1.0), angle) + center; +} + +void node_vector_rotate_euler_xyz( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = euler_to_mat3(rotation) * (vector_in - center) + center; +} + +void node_vector_rotate_euler_xzy( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = euler_to_mat3(-rotation.xzy) * (vector_in - center) + center; +} + +void node_vector_rotate_euler_yxz( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = euler_to_mat3(-rotation.yxz) * (vector_in - center) + center; +} + +void node_vector_rotate_euler_yzx( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = euler_to_mat3(rotation.yzx) * (vector_in - center) + center; +} + +void node_vector_rotate_euler_zxy( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = euler_to_mat3(rotation.zxy) * (vector_in - center) + center; +} + +void node_vector_rotate_euler_zyx( + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) +{ + vec = euler_to_mat3(-rotation.zyx) * (vector_in - center) + center; +} diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index a8f33072915..071dc70af55 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1212,6 +1212,20 @@ enum { NODE_MAPPING_TYPE_NORMAL = 3, }; +/* Rotation node vector types */ +enum { + NODE_VECTOR_ROTATE_TYPE_AXIS = 0, + NODE_VECTOR_ROTATE_TYPE_AXIS_X = 1, + NODE_VECTOR_ROTATE_TYPE_AXIS_Y = 2, + NODE_VECTOR_ROTATE_TYPE_AXIS_Z = 3, + NODE_VECTOR_ROTATE_TYPE_EULER_XYZ = 4, + NODE_VECTOR_ROTATE_TYPE_EULER_XZY = 5, + NODE_VECTOR_ROTATE_TYPE_EULER_YXZ = 6, + NODE_VECTOR_ROTATE_TYPE_EULER_YZX = 7, + NODE_VECTOR_ROTATE_TYPE_EULER_ZXY = 8, + NODE_VECTOR_ROTATE_TYPE_EULER_ZYX = 9, +}; + /* math node clamp */ #define SHD_MATH_CLAMP 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index e17fdb5359d..36bb65294fb 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -122,6 +122,49 @@ const EnumPropertyItem rna_enum_mapping_type_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_vector_rotate_type_items[] = { + {NODE_VECTOR_ROTATE_TYPE_AXIS, + "AXIS_ANGLE", + 0, + "Axis Angle", + "Rotate a point using axis angle"}, + {NODE_VECTOR_ROTATE_TYPE_AXIS_X, "X_AXIS", 0, "X Axis", "Rotate a point using X axis"}, + {NODE_VECTOR_ROTATE_TYPE_AXIS_Y, "Y_AXIS", 0, "Y Axis", "Rotate a point using Y axis"}, + {NODE_VECTOR_ROTATE_TYPE_AXIS_Z, "Z_AXIS", 0, "Z Axis", "Rotate a point using Z axis"}, + {NODE_VECTOR_ROTATE_TYPE_EULER_XYZ, + "EULER_XYZ", + 0, + "XYZ Euler", + "Rotate a point using XYZ order"}, + + {NODE_VECTOR_ROTATE_TYPE_EULER_XZY, + "EULER_XZY", + 0, + "XZY Euler", + "Rotate a point using XZY order"}, + {NODE_VECTOR_ROTATE_TYPE_EULER_YXZ, + "EULER_YXZ", + 0, + "YXZ Euler", + "Rotate a point using YXZ order"}, + {NODE_VECTOR_ROTATE_TYPE_EULER_YZX, + "EULER_YZX", + 0, + "YZX Euler", + "Rotate a point using YZX order"}, + {NODE_VECTOR_ROTATE_TYPE_EULER_ZXY, + "EULER_ZXY", + 0, + "ZXY Euler", + "Rotate a point using ZXY order"}, + {NODE_VECTOR_ROTATE_TYPE_EULER_ZYX, + "EULER_ZYX", + 0, + "XZY Euler", + "Rotate a point using ZYX order"}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_node_math_items[] = { {0, "", 0, N_("Functions"), ""}, {NODE_MATH_ADD, "ADD", 0, "Add", "A + B"}, @@ -4141,6 +4184,17 @@ static void def_sh_mapping(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); } +static void def_sh_vector_rotate(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "rotation_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_vector_rotate_type_items); + RNA_def_property_ui_text(prop, "Type", "Type of rotation"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); +} + static void def_sh_attribute(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index e15eb5af2c4..41227a14fb3 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -206,6 +206,7 @@ set(SRC shader/nodes/node_shader_uvmap.c shader/nodes/node_shader_valToRgb.c shader/nodes/node_shader_value.c + shader/nodes/node_shader_vector_rotate.c shader/nodes/node_shader_vectTransform.c shader/nodes/node_shader_vector_displacement.c shader/nodes/node_shader_vector_math.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 69d779c9b7f..a89a9e927b9 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -85,6 +85,7 @@ void register_node_type_sh_volume_info(void); void register_node_type_sh_script(void); void register_node_type_sh_normal_map(void); void register_node_type_sh_tangent(void); +void register_node_type_sh_vector_rotate(void); void register_node_type_sh_vect_transform(void); void register_node_type_sh_vertex_color(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 2b141e1a639..7fec3324aab 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -117,6 +117,7 @@ DefNode(ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX DefNode(ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" ) DefNode(ShaderNode, SH_NODE_TEX_POINTDENSITY, def_sh_tex_pointdensity,"TEX_POINTDENSITY", TexPointDensity, "Point Density", "" ) DefNode(ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" ) +DefNode(ShaderNode, SH_NODE_VECTOR_ROTATE, def_sh_vector_rotate, "VECTOR_ROTATE", VectorRotate, "Vector Rotate", "" ) DefNode(ShaderNode, SH_NODE_VECT_TRANSFORM, def_sh_vect_transform, "VECT_TRANSFORM", VectorTransform, "Vector Transform", "" ) DefNode(ShaderNode, SH_NODE_SEPHSV, 0, "SEPHSV", SeparateHSV, "Separate HSV", "" ) DefNode(ShaderNode, SH_NODE_COMBHSV, 0, "COMBHSV", CombineHSV, "Combine HSV", "" ) diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c new file mode 100644 index 00000000000..3fd627cd886 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c @@ -0,0 +1,96 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "../node_shader_util.h" + +/* **************** Vector Rotate ******************** */ +static bNodeSocketTemplate sh_node_vector_rotate_in[] = { + {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + {SOCK_VECTOR, 1, N_("Center"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_NONE}, + {SOCK_VECTOR, 1, N_("Axis"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_NONE, PROP_NONE}, + {SOCK_FLOAT, 1, N_("Angle"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_ANGLE, PROP_NONE}, + {SOCK_VECTOR, 1, N_("Rotation"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_EULER}, + {-1, 0, ""}}; + +static bNodeSocketTemplate sh_node_vector_rotate_out[] = {{SOCK_VECTOR, 0, N_("Vector")}, + {-1, 0, ""}}; + +static int gpu_shader_vector_rotate(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + + static const char *names[] = { + [NODE_VECTOR_ROTATE_TYPE_AXIS] = "node_vector_rotate_axis_angle", + [NODE_VECTOR_ROTATE_TYPE_AXIS_X] = "node_vector_rotate_axis_x", + [NODE_VECTOR_ROTATE_TYPE_AXIS_Y] = "node_vector_rotate_axis_y", + [NODE_VECTOR_ROTATE_TYPE_AXIS_Z] = "node_vector_rotate_axis_z", + [NODE_VECTOR_ROTATE_TYPE_EULER_XYZ] = "node_vector_rotate_euler_xyz", + [NODE_VECTOR_ROTATE_TYPE_EULER_XZY] = "node_vector_rotate_euler_xzy", + [NODE_VECTOR_ROTATE_TYPE_EULER_YXZ] = "node_vector_rotate_euler_yxz", + [NODE_VECTOR_ROTATE_TYPE_EULER_YZX] = "node_vector_rotate_euler_yzx", + [NODE_VECTOR_ROTATE_TYPE_EULER_ZXY] = "node_vector_rotate_euler_zxy", + [NODE_VECTOR_ROTATE_TYPE_EULER_ZYX] = "node_vector_rotate_euler_zyx", + }; + + if (node->custom1 < ARRAY_SIZE(names) && names[node->custom1]) { + return GPU_stack_link(mat, node, names[node->custom1], in, out); + } + else { + return 0; + } +} + +static void node_shader_update_vector_rotate(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock_rotation = nodeFindSocket(node, SOCK_IN, "Rotation"); + nodeSetSocketAvailability(sock_rotation, + !ELEM(node->custom1, + NODE_VECTOR_ROTATE_TYPE_AXIS, + NODE_VECTOR_ROTATE_TYPE_AXIS_X, + NODE_VECTOR_ROTATE_TYPE_AXIS_Y, + NODE_VECTOR_ROTATE_TYPE_AXIS_Z)); + bNodeSocket *sock_axis = nodeFindSocket(node, SOCK_IN, "Axis"); + nodeSetSocketAvailability(sock_axis, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_AXIS)); + bNodeSocket *sock_angle = nodeFindSocket(node, SOCK_IN, "Angle"); + nodeSetSocketAvailability(sock_angle, + ELEM(node->custom1, + NODE_VECTOR_ROTATE_TYPE_AXIS, + NODE_VECTOR_ROTATE_TYPE_AXIS_X, + NODE_VECTOR_ROTATE_TYPE_AXIS_Y, + NODE_VECTOR_ROTATE_TYPE_AXIS_Z)); +} + +void register_node_type_sh_vector_rotate(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_VECTOR_ROTATE, "Vector Rotate", NODE_CLASS_OP_VECTOR, 0); + node_type_socket_templates(&ntype, sh_node_vector_rotate_in, sh_node_vector_rotate_out); + node_type_gpu(&ntype, gpu_shader_vector_rotate); + node_type_update(&ntype, node_shader_update_vector_rotate); + + nodeRegisterType(&ntype); +} |