Geometry Nodes: support Vector Rotate node

Differential Revision: https://developer.blender.org/D10410
This commit is contained in:
Leon Leno 2021-03-08 11:37:37 +01:00 committed by Jacques Lucke
parent 2b9eea17cc
commit e12ad2bce0
3 changed files with 182 additions and 1 deletions

View File

@ -543,6 +543,7 @@ geometry_node_categories = [
NodeItem("ShaderNodeSeparateXYZ"),
NodeItem("ShaderNodeCombineXYZ"),
NodeItem("ShaderNodeVectorMath"),
NodeItem("ShaderNodeVectorRotate"),
]),
GeometryNodeCategory("GEO_GROUP", "Group", items=node_group_items),
GeometryNodeCategory("GEO_LAYOUT", "Layout", items=[

View File

@ -168,6 +168,63 @@ class CustomMF_SI_SI_SI_SO : public MultiFunction {
}
};
/**
* Generates a multi-function with the following parameters:
* 1. single input (SI) of type In1
* 2. single input (SI) of type In2
* 3. single input (SI) of type In3
* 4. single input (SI) of type In4
* 5. single output (SO) of type Out1
*/
template<typename In1, typename In2, typename In3, typename In4, typename Out1>
class CustomMF_SI_SI_SI_SI_SO : public MultiFunction {
private:
using FunctionT = std::function<void(
IndexMask, VSpan<In1>, VSpan<In2>, VSpan<In3>, VSpan<In4>, MutableSpan<Out1>)>;
FunctionT function_;
public:
CustomMF_SI_SI_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature = this->get_builder(name);
signature.single_input<In1>("In1");
signature.single_input<In2>("In2");
signature.single_input<In3>("In3");
signature.single_input<In4>("In4");
signature.single_output<Out1>("Out1");
}
template<typename ElementFuncT>
CustomMF_SI_SI_SI_SI_SO(StringRef name, ElementFuncT element_fn)
: CustomMF_SI_SI_SI_SI_SO(name, CustomMF_SI_SI_SI_SI_SO::create_function(element_fn))
{
}
template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn)
{
return [=](IndexMask mask,
VSpan<In1> in1,
VSpan<In2> in2,
VSpan<In3> in3,
VSpan<In4> in4,
MutableSpan<Out1> out1) {
mask.foreach_index([&](int i) {
new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i], in3[i], in4[i]));
});
};
}
void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override
{
VSpan<In1> in1 = params.readonly_single_input<In1>(0);
VSpan<In2> in2 = params.readonly_single_input<In2>(1);
VSpan<In3> in3 = params.readonly_single_input<In3>(2);
VSpan<In4> in4 = params.readonly_single_input<In4>(3);
MutableSpan<Out1> out1 = params.uninitialized_single_output<Out1>(4);
function_(mask, in1, in2, in3, in4, out1);
}
};
/**
* Generates a multi-function with the following parameters:
* 1. single mutable (SM) of type Mut1

View File

@ -71,6 +71,128 @@ static int gpu_shader_vector_rotate(GPUMaterial *mat,
return 0;
}
using blender::float3;
static float3 sh_node_vector_rotate_around_axis(const float3 vector,
const float3 center,
const float3 axis,
const float angle)
{
float3 result = vector - center;
float mat[3][3];
axis_angle_to_mat3(mat, axis, angle);
mul_m3_v3(mat, result);
return result + center;
}
static float3 sh_node_vector_rotate_euler(const float3 vector,
const float3 center,
const float3 rotation,
const bool invert)
{
float mat[3][3];
float3 result = vector - center;
eul_to_mat3(mat, rotation);
if (invert) {
invert_m3(mat);
}
mul_m3_v3(mat, result);
return result + center;
}
static const blender::fn::MultiFunction &get_multi_function(
blender::nodes::NodeMFNetworkBuilder &builder)
{
bool invert = builder.bnode().custom2;
const int mode = builder.bnode().custom1;
switch (mode) {
case NODE_VECTOR_ROTATE_TYPE_AXIS: {
if (invert) {
static blender::fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float3, float, float3> fn{
"Rotate Axis", [](float3 in, float3 center, float3 axis, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
}};
return fn;
}
static blender::fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float3, float, float3> fn{
"Rotate Axis", [](float3 in, float3 center, float3 axis, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, angle);
}};
return fn;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_X: {
float3 axis = float3(1.0f, 0.0f, 0.0f);
if (invert) {
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
"Rotate X-Axis", [=](float3 in, float3 center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
}};
return fn;
}
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
"Rotate X-Axis", [=](float3 in, float3 center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, angle);
}};
return fn;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: {
float3 axis = float3(0.0f, 1.0f, 0.0f);
if (invert) {
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
"Rotate Y-Axis", [=](float3 in, float3 center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
}};
return fn;
}
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
"Rotate Y-Axis", [=](float3 in, float3 center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, angle);
}};
return fn;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: {
float3 axis = float3(0.0f, 0.0f, 1.0f);
if (invert) {
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
"Rotate Z-Axis", [=](float3 in, float3 center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
}};
return fn;
}
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
"Rotate Z-Axis", [=](float3 in, float3 center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, angle);
}};
return fn;
}
case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: {
if (invert) {
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
"Rotate Euler", [](float3 in, float3 center, float3 rotation) {
return sh_node_vector_rotate_euler(in, center, rotation, true);
}};
return fn;
}
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
"Rotate Euler", [](float3 in, float3 center, float3 rotation) {
return sh_node_vector_rotate_euler(in, center, rotation, false);
}};
return fn;
}
default:
BLI_assert(false);
return builder.get_not_implemented_fn();
}
}
static void sh_node_vector_rotate_expand_in_mf_network(
blender::nodes::NodeMFNetworkBuilder &builder)
{
const blender::fn::MultiFunction &fn = get_multi_function(builder);
builder.set_matching_fn(fn);
}
static void node_shader_update_vector_rotate(bNodeTree *UNUSED(ntree), bNode *node)
{
bNodeSocket *sock_rotation = nodeFindSocket(node, SOCK_IN, "Rotation");
@ -85,10 +207,11 @@ 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);
sh_fn_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);
ntype.expand_in_mf_network = sh_node_vector_rotate_expand_in_mf_network;
nodeRegisterType(&ntype);
}