Compare commits
2 Commits
attribute-
...
geometry-t
Author | SHA1 | Date | |
---|---|---|---|
c79c0c3c9a | |||
f7af5f9933 |
58
source/blender/blenkernel/BKE_geometry.hh
Normal file
58
source/blender/blenkernel/BKE_geometry.hh
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
struct Mesh;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
class Geometry {
|
||||
private:
|
||||
/* Only contains a mesh for now. */
|
||||
Mesh *mesh_ = nullptr;
|
||||
|
||||
public:
|
||||
Geometry() = default;
|
||||
~Geometry();
|
||||
|
||||
/** Takes ownership of the mesh. */
|
||||
static Geometry *from_mesh(Mesh *mesh)
|
||||
{
|
||||
Geometry *geometry = new Geometry();
|
||||
geometry->mesh_ = mesh;
|
||||
return geometry;
|
||||
}
|
||||
|
||||
Mesh *mesh()
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
/* The caller takes ownership of the mesh and removes it from the geometry. */
|
||||
Mesh *extract_mesh()
|
||||
{
|
||||
Mesh *mesh = mesh_;
|
||||
mesh_ = nullptr;
|
||||
return mesh;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
@@ -112,6 +112,8 @@ namespace blender {
|
||||
namespace nodes {
|
||||
class SocketMFNetworkBuilder;
|
||||
class NodeMFNetworkBuilder;
|
||||
class GeoNodeInput;
|
||||
class GeoNodeOutput;
|
||||
} // namespace nodes
|
||||
namespace fn {
|
||||
class MFDataType;
|
||||
@@ -121,11 +123,15 @@ class MFDataType;
|
||||
using NodeExpandInMFNetworkFunction = void (*)(blender::nodes::NodeMFNetworkBuilder &builder);
|
||||
using SocketGetMFDataTypeFunction = blender::fn::MFDataType (*)();
|
||||
using SocketExpandInMFNetworkFunction = void (*)(blender::nodes::SocketMFNetworkBuilder &builder);
|
||||
using GeometryNodeExecFunction = void (*)(struct bNode *node,
|
||||
blender::nodes::GeoNodeInput input,
|
||||
blender::nodes::GeoNodeOutput output);
|
||||
|
||||
#else
|
||||
typedef void *NodeExpandInMFNetworkFunction;
|
||||
typedef void *SocketGetMFDataTypeFunction;
|
||||
typedef void *SocketExpandInMFNetworkFunction;
|
||||
typedef void *GeometryNodeExecFunction;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -302,6 +308,9 @@ typedef struct bNodeType {
|
||||
/* Expands the bNode into nodes in a multi-function network, which will be evaluated later on. */
|
||||
NodeExpandInMFNetworkFunction expand_in_mf_network;
|
||||
|
||||
/* Execute a geometry node. */
|
||||
GeometryNodeExecFunction geometry_node_execute;
|
||||
|
||||
/* RNA integration */
|
||||
ExtensionRNA rna_ext;
|
||||
} bNodeType;
|
||||
|
@@ -124,6 +124,7 @@ set(SRC
|
||||
intern/fmodifier.c
|
||||
intern/font.c
|
||||
intern/freestyle.c
|
||||
intern/geometry.cc
|
||||
intern/gpencil.c
|
||||
intern/gpencil_curve.c
|
||||
intern/gpencil_geom.c
|
||||
@@ -310,6 +311,7 @@ set(SRC
|
||||
BKE_fluid.h
|
||||
BKE_font.h
|
||||
BKE_freestyle.h
|
||||
BKE_geometry.hh
|
||||
BKE_global.h
|
||||
BKE_gpencil.h
|
||||
BKE_gpencil_curve.h
|
||||
|
32
source/blender/blenkernel/intern/geometry.cc
Normal file
32
source/blender/blenkernel/intern/geometry.cc
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "BKE_geometry.hh"
|
||||
#include "BKE_mesh.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
Geometry::~Geometry()
|
||||
{
|
||||
if (mesh_ != nullptr) {
|
||||
BKE_mesh_free(mesh_);
|
||||
MEM_freeN(mesh_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
@@ -38,6 +38,7 @@ set(SRC
|
||||
FN_array_spans.hh
|
||||
FN_attributes_ref.hh
|
||||
FN_cpp_type.hh
|
||||
FN_generic_pointer.hh
|
||||
FN_generic_vector_array.hh
|
||||
FN_multi_function.hh
|
||||
FN_multi_function_builder.hh
|
||||
|
70
source/blender/functions/FN_generic_pointer.hh
Normal file
70
source/blender/functions/FN_generic_pointer.hh
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FN_cpp_type.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
|
||||
/**
|
||||
* A generic pointer whose type is only known at runtime.
|
||||
*/
|
||||
class GMutablePointer {
|
||||
private:
|
||||
const CPPType *type_ = nullptr;
|
||||
void *data_ = nullptr;
|
||||
|
||||
public:
|
||||
GMutablePointer() = default;
|
||||
|
||||
GMutablePointer(const CPPType *type, void *data = nullptr) : type_(type), data_(data)
|
||||
{
|
||||
/* If there is data, there has to be a type. */
|
||||
BLI_assert(data_ == nullptr || type_ != nullptr);
|
||||
}
|
||||
|
||||
GMutablePointer(const CPPType &type, void *data = nullptr) : GMutablePointer(&type, data)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T> GMutablePointer(T *data) : GMutablePointer(&CPPType::get<T>(), data)
|
||||
{
|
||||
}
|
||||
|
||||
void *get() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
const CPPType *type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
template<typename T> T *get() const
|
||||
{
|
||||
BLI_assert(this->is_type<T>());
|
||||
return reinterpret_cast<T *>(data_);
|
||||
}
|
||||
|
||||
template<typename T> bool is_type() const
|
||||
{
|
||||
return type_ != nullptr && type_->is<T>();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::fn
|
@@ -29,8 +29,10 @@ set(INC
|
||||
../bmesh
|
||||
../depsgraph
|
||||
../editors/include
|
||||
../functions
|
||||
../makesdna
|
||||
../makesrna
|
||||
../nodes
|
||||
../render/extern/include
|
||||
../windowmanager
|
||||
../../../intern/eigen
|
||||
|
@@ -63,6 +63,9 @@
|
||||
#include "MOD_modifiertypes.h"
|
||||
#include "MOD_ui_common.h"
|
||||
|
||||
#include "NOD_derived_node_tree.hh"
|
||||
#include "NOD_geometry_exec.hh"
|
||||
|
||||
using blender::float3;
|
||||
|
||||
static void initData(ModifierData *md)
|
||||
@@ -107,12 +110,97 @@ static PointCloud *modifyPointCloud(ModifierData *md,
|
||||
return pointcloud;
|
||||
}
|
||||
|
||||
using namespace blender;
|
||||
using namespace blender::nodes;
|
||||
using namespace blender::fn;
|
||||
using namespace blender::bke;
|
||||
|
||||
static Geometry *compute_geometry(const DOutputSocket *group_input,
|
||||
Geometry *group_input_geometry,
|
||||
const DInputSocket &socket_to_compute)
|
||||
{
|
||||
Span<const DOutputSocket *> from_sockets = socket_to_compute.linked_sockets();
|
||||
Span<const DGroupInput *> from_group_inputs = socket_to_compute.linked_group_inputs();
|
||||
const int total_inputs = from_sockets.size() + from_group_inputs.size();
|
||||
if (total_inputs != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!from_group_inputs.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const DOutputSocket &from_socket = *from_sockets[0];
|
||||
if (&from_socket == group_input) {
|
||||
return group_input_geometry;
|
||||
}
|
||||
if (from_socket.idname() != "NodeSocketGeometry") {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const DNode &from_node = from_socket.node();
|
||||
if (from_node.inputs().size() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Geometry *input_geometry = compute_geometry(
|
||||
group_input, group_input_geometry, from_node.input(0));
|
||||
|
||||
bNode *bnode = from_node.node_ref().bnode();
|
||||
GeometryNodeExecFunction execute = bnode->typeinfo->geometry_node_execute;
|
||||
|
||||
LinearAllocator<> allocator;
|
||||
GeoNodeInputBuilder input_builder;
|
||||
GeometryP geometry_p{input_geometry};
|
||||
input_builder.add("Geometry", CPPType::get<GeometryP>(), &geometry_p);
|
||||
GeoNodeOutputCollector output_collector{allocator};
|
||||
execute(bnode, input_builder, output_collector);
|
||||
|
||||
Geometry *output_geometry =
|
||||
output_collector.get<GeometryP>(from_socket.socket_ref().bsocket()->identifier).p;
|
||||
return output_geometry;
|
||||
}
|
||||
|
||||
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh)
|
||||
{
|
||||
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
||||
UNUSED_VARS(nmd);
|
||||
std::cout << __func__ << "\n";
|
||||
return mesh;
|
||||
if (nmd->node_tree == nullptr) {
|
||||
return mesh;
|
||||
}
|
||||
|
||||
NodeTreeRefMap tree_refs;
|
||||
DerivedNodeTree tree{nmd->node_tree, tree_refs};
|
||||
|
||||
Span<const DNode *> input_nodes = tree.nodes_by_type("NodeGroupInput");
|
||||
Span<const DNode *> output_nodes = tree.nodes_by_type("NodeGroupOutput");
|
||||
|
||||
if (input_nodes.size() > 1) {
|
||||
return mesh;
|
||||
}
|
||||
if (output_nodes.size() != 1) {
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Span<const DOutputSocket *> group_inputs = (input_nodes.size() == 1) ?
|
||||
input_nodes[0]->outputs().drop_back(1) :
|
||||
Span<const DOutputSocket *>{};
|
||||
Span<const DInputSocket *> group_outputs = output_nodes[0]->inputs().drop_back(1);
|
||||
|
||||
if (group_outputs.size() != 1) {
|
||||
return mesh;
|
||||
}
|
||||
|
||||
const DInputSocket *group_output = group_outputs[0];
|
||||
if (group_output->idname() != "NodeSocketGeometry") {
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Geometry *input_geometry = Geometry::from_mesh(mesh);
|
||||
Geometry *new_geometry = compute_geometry(group_inputs[0], input_geometry, *group_outputs[0]);
|
||||
if (new_geometry == nullptr) {
|
||||
return mesh;
|
||||
}
|
||||
Mesh *new_mesh = new_geometry->extract_mesh();
|
||||
return new_mesh;
|
||||
}
|
||||
|
||||
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||
|
@@ -48,11 +48,17 @@
|
||||
#include "MOD_modifiertypes.h"
|
||||
#include "MOD_ui_common.h"
|
||||
|
||||
static Mesh *triangulate_mesh(Mesh *mesh,
|
||||
const int quad_method,
|
||||
const int ngon_method,
|
||||
const int min_vertices,
|
||||
const int flag)
|
||||
Mesh *triangulate_mesh(Mesh *mesh,
|
||||
const int quad_method,
|
||||
const int ngon_method,
|
||||
const int min_vertices,
|
||||
const int flag);
|
||||
|
||||
Mesh *triangulate_mesh(Mesh *mesh,
|
||||
const int quad_method,
|
||||
const int ngon_method,
|
||||
const int min_vertices,
|
||||
const int flag)
|
||||
{
|
||||
Mesh *result;
|
||||
BMesh *bm;
|
||||
|
@@ -139,6 +139,7 @@ set(SRC
|
||||
|
||||
geometry/nodes/node_geo_common.cc
|
||||
geometry/nodes/node_geo_triangulate.cc
|
||||
geometry/node_geometry_exec.cc
|
||||
geometry/node_geometry_tree.cc
|
||||
geometry/node_geometry_util.cc
|
||||
|
||||
@@ -273,7 +274,7 @@ set(SRC
|
||||
composite/node_composite_util.h
|
||||
function/node_function_util.hh
|
||||
shader/node_shader_util.h
|
||||
geometry/node_geometry_util.h
|
||||
geometry/node_geometry_util.hh
|
||||
texture/node_texture_util.h
|
||||
|
||||
NOD_common.h
|
||||
|
129
source/blender/nodes/NOD_geometry_exec.hh
Normal file
129
source/blender/nodes/NOD_geometry_exec.hh
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FN_generic_pointer.hh"
|
||||
|
||||
#include "BLI_linear_allocator.hh"
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include "BKE_geometry.hh"
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
using bke::Geometry;
|
||||
using fn::CPPType;
|
||||
using fn::GMutablePointer;
|
||||
|
||||
class GeoNodeInputBuilder {
|
||||
private:
|
||||
Map<StringRef, GMutablePointer> values_;
|
||||
|
||||
friend class GeoNodeInput;
|
||||
|
||||
public:
|
||||
void add(StringRef name, const CPPType &type, void *data)
|
||||
{
|
||||
values_.add_new(name, GMutablePointer{type, data});
|
||||
}
|
||||
};
|
||||
|
||||
class GeoNodeInput {
|
||||
private:
|
||||
const GeoNodeInputBuilder &builder_;
|
||||
|
||||
public:
|
||||
GeoNodeInput(const GeoNodeInputBuilder &builder) : builder_(builder)
|
||||
{
|
||||
}
|
||||
|
||||
GMutablePointer get(StringRef name)
|
||||
{
|
||||
return builder_.values_.lookup(name);
|
||||
}
|
||||
|
||||
template<typename T> T &get(StringRef name)
|
||||
{
|
||||
return *this->get(name).get<T>();
|
||||
}
|
||||
};
|
||||
|
||||
class GeoNodeOutputCollector {
|
||||
private:
|
||||
LinearAllocator<> &allocator_;
|
||||
Map<StringRef, GMutablePointer> values_;
|
||||
|
||||
friend class GeoNodeOutput;
|
||||
|
||||
public:
|
||||
GeoNodeOutputCollector(LinearAllocator<> &allocator) : allocator_(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
GMutablePointer get(StringRef name)
|
||||
{
|
||||
return values_.lookup(name);
|
||||
}
|
||||
|
||||
template<typename T> T &get(StringRef name)
|
||||
{
|
||||
return *this->get(name).get<T>();
|
||||
}
|
||||
};
|
||||
|
||||
class GeoNodeOutput {
|
||||
private:
|
||||
GeoNodeOutputCollector &collector_;
|
||||
|
||||
public:
|
||||
GeoNodeOutput(GeoNodeOutputCollector &collector) : collector_(collector)
|
||||
{
|
||||
}
|
||||
|
||||
void set(StringRef name, const CPPType &type, void *data)
|
||||
{
|
||||
collector_.values_.add(name, GMutablePointer{type, data});
|
||||
}
|
||||
|
||||
template<typename T> void set(StringRef name, T &&data)
|
||||
{
|
||||
T *copied_data = collector_.allocator_.construct<T>(std::forward<T>(data));
|
||||
collector_.values_.add_new(name, GMutablePointer{copied_data});
|
||||
}
|
||||
};
|
||||
|
||||
struct GeometryP {
|
||||
bke::Geometry *p = nullptr;
|
||||
|
||||
uint64_t hash() const
|
||||
{
|
||||
return DefaultHash<bke::Geometry *>{}(p);
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const GeometryP &geometry)
|
||||
{
|
||||
stream << geometry.p;
|
||||
return stream;
|
||||
}
|
||||
|
||||
friend bool operator==(const GeometryP &a, const GeometryP &b)
|
||||
{
|
||||
return a.p == b.p;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::nodes
|
23
source/blender/nodes/geometry/node_geometry_exec.cc
Normal file
23
source/blender/nodes/geometry/node_geometry_exec.cc
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NOD_geometry_exec.hh"
|
||||
|
||||
MAKE_CPP_TYPE(GeometryP, blender::nodes::GeometryP);
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "node_geometry_util.h"
|
||||
#include "node_geometry_util.hh"
|
||||
#include "node_util.h"
|
||||
|
||||
bool geo_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "NOD_geometry.h"
|
||||
#include "NOD_geometry_exec.hh"
|
||||
|
||||
#include "node_util.h"
|
||||
|
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "NOD_common.h"
|
||||
#include "node_common.h"
|
||||
#include "node_geometry_util.h"
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
void register_node_type_geo_group(void)
|
||||
{
|
||||
|
@@ -14,7 +14,15 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "node_geometry_util.h"
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
extern "C" {
|
||||
Mesh *triangulate_mesh(Mesh *mesh,
|
||||
const int quad_method,
|
||||
const int ngon_method,
|
||||
const int min_vertices,
|
||||
const int flag);
|
||||
}
|
||||
|
||||
static bNodeSocketTemplate geo_node_triangulate_in[] = {
|
||||
{SOCK_GEOMETRY, N_("Geometry")},
|
||||
@@ -26,11 +34,27 @@ static bNodeSocketTemplate geo_node_triangulate_out[] = {
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
namespace blender::nodes {
|
||||
static void geo_triangulate_exec(bNode *UNUSED(node), GeoNodeInput input, GeoNodeOutput output)
|
||||
{
|
||||
Geometry *geometry = input.get<GeometryP>("Geometry").p;
|
||||
if (geometry != nullptr) {
|
||||
Mesh *old_mesh = geometry->extract_mesh();
|
||||
if (old_mesh != nullptr) {
|
||||
Mesh *new_mesh = triangulate_mesh(old_mesh, 3, 0, 4, 0);
|
||||
geometry = Geometry::from_mesh(new_mesh);
|
||||
}
|
||||
}
|
||||
output.set("Geometry", GeometryP{geometry});
|
||||
}
|
||||
} // namespace blender::nodes
|
||||
|
||||
void register_node_type_geo_triangulate()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
geo_node_type_base(&ntype, GEO_NODE_TRIANGULATE, "Triangulate", 0, 0);
|
||||
node_type_socket_templates(&ntype, geo_node_triangulate_in, geo_node_triangulate_out);
|
||||
ntype.geometry_node_execute = blender::nodes::geo_triangulate_exec;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
Reference in New Issue
Block a user