Blender  V2.93
node_geo_point_instance.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
18 
19 #include "DNA_collection_types.h"
20 
21 #include "BLI_hash.h"
22 
23 #include "UI_interface.h"
24 #include "UI_resources.h"
25 
26 #include "node_geometry_util.hh"
27 
29  {SOCK_GEOMETRY, N_("Geometry")},
30  {SOCK_OBJECT, N_("Object")},
31  {SOCK_COLLECTION, N_("Collection")},
32  {SOCK_INT, N_("Seed"), 0, 0, 0, 0, -10000, 10000},
33  {-1, ""},
34 };
35 
37  {SOCK_GEOMETRY, N_("Geometry")},
38  {-1, ""},
39 };
40 
42 {
43  uiItemR(layout, ptr, "instance_type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
44  if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) {
45  uiItemR(layout, ptr, "use_whole_collection", 0, nullptr, ICON_NONE);
46  }
47 }
48 
49 namespace blender::nodes {
50 
52 {
53  bNodeSocket *object_socket = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
54  bNodeSocket *collection_socket = object_socket->next;
55  bNodeSocket *seed_socket = collection_socket->next;
56 
57  NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node->storage;
59  const bool use_whole_collection = (node_storage->flag &
61 
65  seed_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION && !use_whole_collection);
66 }
67 
69  MutableSpan<std::optional<InstancedData>> r_instances_data)
70 {
72  "Object");
73  Object *object = params.handle_map().lookup(object_handle);
74  if (object == params.self_object()) {
75  object = nullptr;
76  }
77  if (object != nullptr) {
78  InstancedData instance;
80  instance.data.object = object;
81  r_instances_data.fill(instance);
82  }
83 }
84 
88  MutableSpan<std::optional<InstancedData>> r_instances_data)
89 {
90  const bNode &node = params.node();
91  NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node.storage;
92 
93  bke::PersistentCollectionHandle collection_handle =
94  params.get_input<bke::PersistentCollectionHandle>("Collection");
95  Collection *collection = params.handle_map().lookup(collection_handle);
96  if (collection == nullptr) {
97  return;
98  }
99 
100  if (BLI_listbase_is_empty(&collection->children) &&
101  BLI_listbase_is_empty(&collection->gobject)) {
102  params.error_message_add(NodeWarningType::Info, TIP_("Collection is empty"));
103  return;
104  }
105 
106  const bool use_whole_collection = (node_storage->flag &
108  if (use_whole_collection) {
109  InstancedData instance;
111  instance.data.collection = collection;
112  r_instances_data.fill(instance);
113  }
114  else {
115  Vector<InstancedData> possible_instances;
116  /* Direct child objects are instanced as objects. */
117  LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
118  Object *object = cob->ob;
119  InstancedData instance;
120  instance.type = INSTANCE_DATA_TYPE_OBJECT;
121  instance.data.object = object;
122  possible_instances.append(instance);
123  }
124  /* Direct child collections are instanced as collections. */
125  LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
126  Collection *child_collection = child->collection;
127  InstancedData instance;
129  instance.data.collection = child_collection;
130  possible_instances.append(instance);
131  }
132 
133  if (!possible_instances.is_empty()) {
134  const int seed = params.get_input<int>("Seed");
136  for (const int i : r_instances_data.index_range()) {
137  const int index = BLI_hash_int_2d(ids[i], seed) % possible_instances.size();
138  r_instances_data[i] = possible_instances[index];
139  }
140  }
141  }
142 }
143 
146  const int amount)
147 {
148  const bNode &node = params.node();
149  NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node.storage;
151  node_storage->instance_type;
152  Array<std::optional<InstancedData>> instances_data(amount);
153 
154  switch (type) {
156  get_instanced_data__object(params, instances_data);
157  break;
158  }
161  break;
162  }
163  }
164  return instances_data;
165 }
166 
168  const GeometryComponent &src_geometry,
169  const GeoNodeExecParams &params)
170 {
171  const AttributeDomain domain = ATTR_DOMAIN_POINT;
172 
173  const int domain_size = src_geometry.attribute_domain_size(domain);
175  params, src_geometry, domain_size);
176 
177  Float3ReadAttribute positions = src_geometry.attribute_get_for_read<float3>(
178  "position", domain, {0, 0, 0});
179  Float3ReadAttribute rotations = src_geometry.attribute_get_for_read<float3>(
180  "rotation", domain, {0, 0, 0});
181  Float3ReadAttribute scales = src_geometry.attribute_get_for_read<float3>(
182  "scale", domain, {1, 1, 1});
183  Int32ReadAttribute ids = src_geometry.attribute_get_for_read<int>("id", domain, -1);
184 
185  for (const int i : IndexRange(domain_size)) {
186  if (instances_data[i].has_value()) {
187  const float4x4 matrix = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]);
188  instances.add_instance(*instances_data[i], matrix, ids[i]);
189  }
190  }
191 }
192 
194 {
195  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
196  GeometrySet geometry_set_out;
197 
198  /* TODO: This node should be able to instance on the input instances component
199  * rather than making the entire input geometry set real. */
200  geometry_set = geometry_set_realize_instances(geometry_set);
201 
202  InstancesComponent &instances = geometry_set_out.get_component_for_write<InstancesComponent>();
203  if (geometry_set.has<MeshComponent>()) {
205  instances, *geometry_set.get_component_for_read<MeshComponent>(), params);
206  }
207  if (geometry_set.has<PointCloudComponent>()) {
209  instances, *geometry_set.get_component_for_read<PointCloudComponent>(), params);
210  }
211 
212  params.set_output("Geometry", std::move(geometry_set_out));
213 }
214 
216 {
218  sizeof(NodeGeometryPointInstance), __func__);
219  data->instance_type = GEO_NODE_POINT_INSTANCE_TYPE_OBJECT;
221  node->storage = data;
222 }
223 
224 } // namespace blender::nodes
225 
227 {
228  static bNodeType ntype;
229 
230  geo_node_type_base(&ntype, GEO_NODE_POINT_INSTANCE, "Point Instance", NODE_CLASS_GEOMETRY, 0);
234  &ntype, "NodeGeometryPointInstance", node_free_standard_storage, node_copy_standard_storage);
238  nodeRegisterType(&ntype);
239 }
AttributeDomain
Definition: BKE_attribute.h:41
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:43
@ INSTANCE_DATA_TYPE_OBJECT
@ INSTANCE_DATA_TYPE_COLLECTION
void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available)
Definition: node.cc:3726
#define GEO_NODE_POINT_INSTANCE
Definition: BKE_node.h:1381
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
Definition: node.cc:4527
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4623
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4559
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
Definition: node.cc:4599
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1298
BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
Definition: BLI_hash.h:67
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define UNUSED(x)
#define TIP_(msgid)
#define N_(msgid)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:126
Object groups, one object can be in many groups at once.
@ GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION
GeometryNodePointInstanceType
@ GEO_NODE_POINT_INSTANCE_TYPE_OBJECT
@ GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION
@ SOCK_INT
@ SOCK_COLLECTION
@ SOCK_GEOMETRY
@ SOCK_OBJECT
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
#define C
Definition: RandGen.cpp:39
@ UI_ITEM_R_EXPAND
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
static unsigned long seed
Definition: btSoftBody.h:39
virtual int attribute_domain_size(const AttributeDomain domain) const
blender::bke::ReadAttributePtr attribute_get_for_read(const blender::StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type, const void *default_value) const
void add_instance(Object *object, blender::float4x4 transform, const int id=-1)
int64_t size() const
Definition: BLI_vector.hh:662
void append(const T &value)
Definition: BLI_vector.hh:438
bool is_empty() const
Definition: BLI_vector.hh:674
OperationNode * node
void * tree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
TypedReadAttribute< float3 > Float3ReadAttribute
TypedReadAttribute< int > Int32ReadAttribute
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
static void get_instanced_data__collection(const GeoNodeExecParams &params, const GeometryComponent &component, MutableSpan< std::optional< InstancedData >> r_instances_data)
static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node)
static void geo_node_point_instance_exec(GeoNodeExecParams params)
static void get_instanced_data__object(const GeoNodeExecParams &params, MutableSpan< std::optional< InstancedData >> r_instances_data)
static void add_instances_from_geometry_component(InstancesComponent &instances, const GeometryComponent &src_geometry, const GeoNodeExecParams &params)
static void geo_node_point_instance_init(bNodeTree *UNUSED(tree), bNode *node)
static Array< std::optional< InstancedData > > get_instanced_data(const GeoNodeExecParams &params, const GeometryComponent &component, const int amount)
Array< uint32_t > get_geometry_element_ids_as_uints(const GeometryComponent &component, const AttributeDomain domain)
static bNodeSocketTemplate geo_node_point_instance_out[]
static void geo_node_point_instance_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
void register_node_type_geo_point_instance()
static bNodeSocketTemplate geo_node_point_instance_in[]
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:67
void node_free_standard_storage(bNode *node)
Definition: node_util.c:55
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
bool has(const GeometryComponentType component_type) const
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
struct Object * object
InstancedDataType type
union InstancedData::@19 data
struct Collection * collection
Compact definition of a node socket.
Definition: BKE_node.h:95
struct bNodeSocket * next
Defines a node type.
Definition: BKE_node.h:221
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:327
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:253
static float4x4 from_loc_eul_scale(const float3 location, const float3 rotation, const float3 scale)
Definition: BLI_float4x4.hh:39
PointerRNA * ptr
Definition: wm_files.c:3157