Blender  V3.3
id_map.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #ifndef __BLENDER_ID_MAP_H__
5 #define __BLENDER_ID_MAP_H__
6 
7 #include <string.h>
8 
9 #include "scene/geometry.h"
10 #include "scene/scene.h"
11 
12 #include "util/map.h"
13 #include "util/set.h"
14 #include "util/vector.h"
15 
17 
18 /* ID Map
19  *
20  * Utility class to map between Blender datablocks and Cycles data structures,
21  * and keep track of recalc tags from the dependency graph. */
22 
23 template<typename K, typename T> class id_map {
24  public:
25  id_map(Scene *scene_) : scene(scene_)
26  {
27  }
28 
30  {
31  set<T *> nodes;
32 
33  typename map<K, T *>::iterator jt;
34  for (jt = b_map.begin(); jt != b_map.end(); jt++) {
35  nodes.insert(jt->second);
36  }
37 
38  scene->delete_nodes(nodes);
39  }
40 
41  T *find(const BL::ID &id)
42  {
43  return find(id.ptr.owner_id);
44  }
45 
46  T *find(const K &key)
47  {
48  if (b_map.find(key) != b_map.end()) {
49  T *data = b_map[key];
50  return data;
51  }
52 
53  return NULL;
54  }
55 
56  void set_recalc(const BL::ID &id)
57  {
58  b_recalc.insert(id.ptr.data);
59  }
60 
61  void set_recalc(void *id_ptr)
62  {
63  b_recalc.insert(id_ptr);
64  }
65 
66  bool has_recalc()
67  {
68  return !(b_recalc.empty());
69  }
70 
71  void pre_sync()
72  {
73  used_set.clear();
74  }
75 
76  /* Add new data. */
77  void add(const K &key, T *data)
78  {
79  assert(find(key) == NULL);
80  b_map[key] = data;
81  used(data);
82  }
83 
84  /* Update existing data. */
85  bool update(T *data, const BL::ID &id)
86  {
87  return update(data, id, id);
88  }
89  bool update(T *data, const BL::ID &id, const BL::ID &parent)
90  {
91  bool recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
92  if (parent.ptr.data && parent.ptr.data != id.ptr.data) {
93  recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
94  }
95  used(data);
96  return recalc;
97  }
98 
99  /* Combined add and update as needed. */
100  bool add_or_update(T **r_data, const BL::ID &id)
101  {
102  return add_or_update(r_data, id, id, id.ptr.owner_id);
103  }
104  bool add_or_update(T **r_data, const BL::ID &id, const K &key)
105  {
106  return add_or_update(r_data, id, id, key);
107  }
108  bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
109  {
110  T *data = find(key);
111  bool recalc;
112 
113  if (!data) {
114  /* Add data if it didn't exist yet. */
115  data = scene->create_node<T>();
116  add(key, data);
117  recalc = true;
118  }
119  else {
120  /* check if updated needed. */
121  recalc = update(data, id, parent);
122  }
123 
124  *r_data = data;
125  return recalc;
126  }
127 
128  /* Combined add or update for convenience. */
129 
130  bool is_used(const K &key)
131  {
132  T *data = find(key);
133  return (data) ? used_set.find(data) != used_set.end() : false;
134  }
135 
136  void used(T *data)
137  {
138  /* tag data as still in use */
139  used_set.insert(data);
140  }
141 
143  {
144  b_map[NULL] = data;
145  }
146 
147  void post_sync(bool do_delete = true)
148  {
149  map<K, T *> new_map;
150  typedef pair<const K, T *> TMapPair;
151  typename map<K, T *>::iterator jt;
152 
153  for (jt = b_map.begin(); jt != b_map.end(); jt++) {
154  TMapPair &pair = *jt;
155 
156  if (do_delete && used_set.find(pair.second) == used_set.end()) {
157  scene->delete_node(pair.second);
158  }
159  else {
160  new_map[pair.first] = pair.second;
161  }
162  }
163 
164  used_set.clear();
165  b_recalc.clear();
166  b_map = new_map;
167  }
168 
169  const map<K, T *> &key_to_scene_data()
170  {
171  return b_map;
172  }
173 
174  protected:
175  map<K, T *> b_map;
176  set<T *> used_set;
177  set<void *> b_recalc;
179 };
180 
181 /* Object Key
182  *
183  * To uniquely identify instances, we use the parent, object and persistent instance ID.
184  * We also export separate object for a mesh and its particle hair. */
185 
186 enum { OBJECT_PERSISTENT_ID_SIZE = 8 /* MAX_DUPLI_RECUR in Blender. */ };
187 
188 struct ObjectKey {
189  void *parent;
191  void *ob;
193 
194  ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_, bool use_particle_hair_)
195  : parent(parent_), ob(ob_), use_particle_hair(use_particle_hair_)
196  {
197  if (id_)
198  memcpy(id, id_, sizeof(id));
199  else
200  memset(id, 0, sizeof(id));
201  }
202 
203  bool operator<(const ObjectKey &k) const
204  {
205  if (ob < k.ob) {
206  return true;
207  }
208  else if (ob == k.ob) {
209  if (parent < k.parent) {
210  return true;
211  }
212  else if (parent == k.parent) {
214  return true;
215  }
216  else if (use_particle_hair == k.use_particle_hair) {
217  return memcmp(id, k.id, sizeof(id)) < 0;
218  }
219  }
220  }
221 
222  return false;
223  }
224 };
225 
226 /* Geometry Key
227  *
228  * We export separate geometry for a mesh and its particle hair, so key needs to
229  * distinguish between them. */
230 
231 struct GeometryKey {
232  void *id;
234 
236  {
237  }
238 
239  bool operator<(const GeometryKey &k) const
240  {
241  if (id < k.id) {
242  return true;
243  }
244  else if (id == k.id) {
245  if (geometry_type < k.geometry_type) {
246  return true;
247  }
248  }
249 
250  return false;
251  }
252 };
253 
254 /* Particle System Key */
255 
257  void *ob;
259 
260  ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_)
261  {
262  if (id_)
263  memcpy(id, id_, sizeof(id));
264  else
265  memset(id, 0, sizeof(id));
266  }
267 
268  bool operator<(const ParticleSystemKey &k) const
269  {
270  /* first id is particle index, we don't compare that */
271  if (ob < k.ob)
272  return true;
273  else if (ob == k.ob)
274  return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0;
275 
276  return false;
277  }
278 };
279 
281 
282 #endif /* __BLENDER_ID_MAP_H__ */
struct ID ID
#define K(key)
Definition: id_map.h:23
T * find(const K &key)
Definition: id_map.h:46
bool has_recalc()
Definition: id_map.h:66
set< void * > b_recalc
Definition: id_map.h:177
map< K, T * > b_map
Definition: id_map.h:175
set< T * > used_set
Definition: id_map.h:176
void add(const K &key, T *data)
Definition: id_map.h:77
void set_recalc(void *id_ptr)
Definition: id_map.h:61
bool add_or_update(T **r_data, const BL::ID &id)
Definition: id_map.h:100
bool update(T *data, const BL::ID &id, const BL::ID &parent)
Definition: id_map.h:89
const map< K, T * > & key_to_scene_data()
Definition: id_map.h:169
bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
Definition: id_map.h:108
void set_recalc(const BL::ID &id)
Definition: id_map.h:56
Scene * scene
Definition: id_map.h:178
void pre_sync()
Definition: id_map.h:71
bool update(T *data, const BL::ID &id)
Definition: id_map.h:85
id_map(Scene *scene_)
Definition: id_map.h:25
void used(T *data)
Definition: id_map.h:136
T * find(const BL::ID &id)
Definition: id_map.h:41
void set_default(T *data)
Definition: id_map.h:142
bool add_or_update(T **r_data, const BL::ID &id, const K &key)
Definition: id_map.h:104
bool is_used(const K &key)
Definition: id_map.h:130
~id_map()
Definition: id_map.h:29
void post_sync(bool do_delete=true)
Definition: id_map.h:147
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
@ OBJECT_PERSISTENT_ID_SIZE
Definition: id_map.h:186
#define T
void * id
Definition: id_map.h:232
GeometryKey(void *id, Geometry::Type geometry_type)
Definition: id_map.h:235
Geometry::Type geometry_type
Definition: id_map.h:233
bool operator<(const GeometryKey &k) const
Definition: id_map.h:239
bool use_particle_hair
Definition: id_map.h:192
ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_, bool use_particle_hair_)
Definition: id_map.h:194
void * parent
Definition: id_map.h:189
void * ob
Definition: id_map.h:191
bool operator<(const ObjectKey &k) const
Definition: id_map.h:203
int id[OBJECT_PERSISTENT_ID_SIZE]
Definition: id_map.h:190
ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE])
Definition: id_map.h:260
int id[OBJECT_PERSISTENT_ID_SIZE]
Definition: id_map.h:258
bool operator<(const ParticleSystemKey &k) const
Definition: id_map.h:268
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
T * create_node(Args &&...args)
Definition: scene.h:284
void delete_node(T *node)
Definition: scene.h:297
void delete_nodes(const set< T * > &nodes)
Definition: scene.h:315
PointerRNA * ptr
Definition: wm_files.c:3480