Blender  V3.3
collada_utils.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 /* COLLADABU_ASSERT, may be able to remove later */
8 #include "COLLADABUPlatform.h"
9 
10 #include "COLLADAFWGeometry.h"
11 #include "COLLADAFWMeshPrimitive.h"
12 #include "COLLADAFWMeshVertexData.h"
13 
14 #include <set>
15 #include <string>
16 
17 #include "MEM_guardedalloc.h"
18 
19 #include "DNA_armature_types.h"
20 #include "DNA_constraint_types.h"
21 #include "DNA_customdata_types.h"
22 #include "DNA_key_types.h"
23 #include "DNA_mesh_types.h"
24 #include "DNA_modifier_types.h"
25 #include "DNA_object_types.h"
26 #include "DNA_scene_types.h"
27 
28 #include "BLI_linklist.h"
29 #include "BLI_listbase.h"
30 #include "BLI_math.h"
31 
32 #include "BKE_action.h"
33 #include "BKE_armature.h"
34 #include "BKE_constraint.h"
35 #include "BKE_context.h"
36 #include "BKE_customdata.h"
37 #include "BKE_global.h"
38 #include "BKE_key.h"
39 #include "BKE_layer.h"
40 #include "BKE_lib_id.h"
41 #include "BKE_material.h"
42 #include "BKE_mesh.h"
44 #include "BKE_mesh_runtime.h"
45 #include "BKE_mesh_wrapper.h"
46 #include "BKE_node.h"
47 #include "BKE_object.h"
48 #include "BKE_scene.h"
49 
50 #include "ED_node.h"
51 #include "ED_object.h"
52 #include "ED_screen.h"
53 
54 #include "WM_api.h" /* XXX hrm, see if we can do without this */
55 #include "WM_types.h"
56 
57 #include "bmesh.h"
58 #include "bmesh_tools.h"
59 
60 #include "DEG_depsgraph.h"
61 #include "DEG_depsgraph_query.h"
62 #if 0
63 # include "NOD_common.h"
64 #endif
65 
66 #include "BlenderContext.h"
67 #include "ExportSettings.h"
68 #include "collada_utils.h"
69 
70 float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index)
71 {
72  if (index >= array.getValuesCount()) {
73  return 0.0f;
74  }
75 
76  if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT) {
77  return array.getFloatValues()->getData()[index];
78  }
79 
80  return array.getDoubleValues()->getData()[index];
81 }
82 
84 {
85  /* Copied from /editors/object/object_relations.c */
86 
87  /* test if 'ob' is a parent somewhere in par's parents */
88 
89  if (par == nullptr) {
90  return 0;
91  }
92  if (ob == par) {
93  return 1;
94  }
95 
96  return bc_test_parent_loop(par->parent, ob);
97 }
98 
100 {
102 
103  /* these we can skip completely (invalid constraints...) */
104  if (cti == nullptr) {
105  return false;
106  }
107  if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
108  return false;
109  }
110 
111  /* these constraints can't be evaluated anyway */
112  if (cti->evaluate_constraint == nullptr) {
113  return false;
114  }
115 
116  /* influence == 0 should be ignored */
117  if (con->enforce == 0.0f) {
118  return false;
119  }
120 
121  /* validation passed */
122  return true;
123 }
124 
125 bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
126 {
128  int partype = PAR_OBJECT;
129  const bool xmirror = false;
130  const bool keep_transform = false;
131 
132  if (par && is_parent_space) {
133  mul_m4_m4m4(ob->obmat, par->obmat, ob->obmat);
134  }
135 
136  bool ok = ED_object_parent_set(
137  nullptr, C, scene, ob, par, partype, xmirror, keep_transform, nullptr);
138  return ok;
139 }
140 
141 std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions)
142 {
143  std::vector<bAction *> actions;
144  if (all_actions) {
145  Main *bmain = CTX_data_main(C);
146  ID *id;
147 
148  for (id = (ID *)bmain->actions.first; id; id = (ID *)(id->next)) {
149  bAction *act = (bAction *)id;
150  /* XXX This currently creates too many actions.
151  * TODO: Need to check if the action is compatible to the given object. */
152  actions.push_back(act);
153  }
154  }
155  else {
156  bAction *action = bc_getSceneObjectAction(ob);
157  actions.push_back(action);
158  }
159 
160  return actions;
161 }
162 
163 std::string bc_get_action_id(std::string action_name,
164  std::string ob_name,
165  std::string channel_type,
166  std::string axis_name,
167  std::string axis_separator)
168 {
169  std::string result = action_name + "_" + channel_type;
170  if (ob_name.length() > 0) {
171  result = ob_name + "_" + result;
172  }
173  if (axis_name.length() > 0) {
174  result += axis_separator + axis_name;
175  }
176  return translate_id(result);
177 }
178 
179 void bc_update_scene(BlenderContext &blender_context, float ctime)
180 {
181  Main *bmain = blender_context.get_main();
182  Scene *scene = blender_context.get_scene();
183  Depsgraph *depsgraph = blender_context.get_depsgraph();
184 
185  /* See remark in physics_fluid.c lines 395...) */
186  // BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
187  BKE_scene_frame_set(scene, ctime);
189 }
190 
191 Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
192 {
193  Object *ob = BKE_object_add_only_object(bmain, type, name);
194 
195  ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
197 
198  LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
199  BKE_collection_object_add(bmain, layer_collection->collection, ob);
200 
201  Base *base = BKE_view_layer_base_find(view_layer, ob);
202  /* TODO: is setting active needed? */
204 
205  return ob;
206 }
207 
208 Mesh *bc_get_mesh_copy(BlenderContext &blender_context,
209  Object *ob,
210  BC_export_mesh_type export_mesh_type,
211  bool apply_modifiers,
212  bool triangulate)
213 {
215  Mesh *tmpmesh = nullptr;
216  if (apply_modifiers) {
217 #if 0 /* Not supported by new system currently... */
218  switch (export_mesh_type) {
219  case BC_MESH_TYPE_VIEW: {
220  dm = mesh_create_derived_view(depsgraph, scene, ob, &mask);
221  break;
222  }
223  case BC_MESH_TYPE_RENDER: {
224  dm = mesh_create_derived_render(depsgraph, scene, ob, &mask);
225  break;
226  }
227  }
228 #else
229  Depsgraph *depsgraph = blender_context.get_depsgraph();
230  Scene *scene_eval = blender_context.get_evaluated_scene();
231  Object *ob_eval = blender_context.get_evaluated_object(ob);
232  tmpmesh = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &mask);
233 #endif
234  }
235  else {
236  tmpmesh = (Mesh *)ob->data;
237  }
238 
239  tmpmesh = (Mesh *)BKE_id_copy_ex(nullptr, &tmpmesh->id, nullptr, LIB_ID_COPY_LOCALIZE);
240 
241  if (triangulate) {
242  bc_triangulate_mesh(tmpmesh);
243  }
244  BKE_mesh_tessface_ensure(tmpmesh);
245 
246  /* Ensure data exists if currently in edit mode. */
248 
249  return tmpmesh;
250 }
251 
253 {
254  Object *ob_arm = nullptr;
255 
256  if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
257  ob_arm = ob->parent;
258  }
259  else {
260  ModifierData *mod;
261  for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
262  if (mod->type == eModifierType_Armature) {
263  ob_arm = ((ArmatureModifierData *)mod)->object;
264  }
265  }
266  }
267 
268  return ob_arm;
269 }
270 
271 bool bc_has_object_type(LinkNode *export_set, short obtype)
272 {
273  LinkNode *node;
274 
275  for (node = export_set; node; node = node->next) {
276  Object *ob = (Object *)node->link;
277  /* XXX: why is this checking for ob->data? - we could be looking for empties. */
278  if (ob->type == obtype && ob->data) {
279  return true;
280  }
281  }
282  return false;
283 }
284 
286 {
287  /* Use bubble sort algorithm for sorting the export set. */
288 
289  bool sorted = false;
290  LinkNode *node;
291  for (node = export_set; node->next && !sorted; node = node->next) {
292 
293  sorted = true;
294 
295  LinkNode *current;
296  for (current = export_set; current->next; current = current->next) {
297  Object *a = (Object *)current->link;
298  Object *b = (Object *)current->next->link;
299 
300  if (strcmp(a->id.name, b->id.name) > 0) {
301  current->link = b;
302  current->next->link = a;
303  sorted = false;
304  }
305  }
306  }
307 }
308 
309 bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
310 {
311  if (deform_bones_only) {
312  Bone *root = nullptr;
313  Bone *bone = aBone;
314  while (bone) {
315  if (!(bone->flag & BONE_NO_DEFORM)) {
316  root = bone;
317  }
318  bone = bone->parent;
319  }
320  return (aBone == root);
321  }
322 
323  return !(aBone->parent);
324 }
325 
327 {
328  Mesh *me = (Mesh *)ob->data;
330 }
331 
332 std::string bc_url_encode(std::string data)
333 {
334  /* XXX We probably do not need to do a full encoding.
335  * But in case that is necessary,then it can be added here.
336  */
337  return bc_replace_string(data, "#", "%23");
338 }
339 
340 std::string bc_replace_string(std::string data,
341  const std::string &pattern,
342  const std::string &replacement)
343 {
344  size_t pos = 0;
345  while ((pos = data.find(pattern, pos)) != std::string::npos) {
346  data.replace(pos, pattern.length(), replacement);
347  pos += replacement.length();
348  }
349  return data;
350 }
351 
352 void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
353 {
354  if (scale_to_scene) {
355  mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat);
356  }
357  mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
358  BKE_object_apply_mat4(ob, ob->obmat, false, false);
359 }
360 
361 void bc_match_scale(std::vector<Object *> *objects_done,
362  UnitConverter &bc_unit,
363  bool scale_to_scene)
364 {
365  for (Object *ob : *objects_done) {
366  if (ob->parent == nullptr) {
367  bc_match_scale(ob, bc_unit, scale_to_scene);
368  }
369  }
370 }
371 
372 void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
373 {
374  if (size) {
375  mat4_to_size(size, mat);
376  }
377 
378  if (eul) {
379  mat4_to_eul(eul, mat);
380  }
381 
382  if (quat) {
383  mat4_to_quat(quat, mat);
384  }
385 
386  if (loc) {
387  copy_v3_v3(loc, mat[3]);
388  }
389 }
390 
391 void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
392 {
393  float qd[4];
394  float matd[4][4];
395  float mati[4][4];
396  float mat_from[4][4];
397  quat_to_mat4(mat_from, quat_from);
398 
399  /* Calculate the difference matrix matd between mat_from and mat_to */
400  invert_m4_m4(mati, mat_from);
401  mul_m4_m4m4(matd, mati, mat_to);
402 
403  mat4_to_quat(qd, matd);
404 
405  mul_qt_qtqt(quat_to, qd, quat_from); /* rot is the final rotation corresponding to mat_to */
406 }
407 
409 {
410  bool use_beauty = false;
411  bool tag_only = false;
412 
413  /* XXX: The triangulation method selection could be offered in the UI. */
414  int quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE;
415 
416  const BMeshCreateParams bm_create_params{};
417  BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_create_params);
418  BMeshFromMeshParams bm_from_me_params{};
419  bm_from_me_params.calc_face_normal = true;
420  bm_from_me_params.calc_vert_normal = true;
421  BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
422  BM_mesh_triangulate(bm, quad_method, use_beauty, 4, tag_only, nullptr, nullptr, nullptr);
423 
424  BMeshToMeshParams bm_to_me_params{};
425  bm_to_me_params.calc_object_remap = false;
426  BM_mesh_bm_to_me(nullptr, bm, me, &bm_to_me_params);
427  BM_mesh_free(bm);
428 }
429 
431 {
432  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
433  if (child->flag & BONE_CONNECTED) {
434  return false;
435  }
436  }
437  return true;
438 }
439 
440 EditBone *bc_get_edit_bone(bArmature *armature, char *name)
441 {
442  EditBone *eBone;
443 
444  for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
445  if (STREQ(name, eBone->name)) {
446  return eBone;
447  }
448  }
449 
450  return nullptr;
451 }
452 int bc_set_layer(int bitfield, int layer)
453 {
454  return bc_set_layer(bitfield, layer, true); /* enable */
455 }
456 
457 int bc_set_layer(int bitfield, int layer, bool enable)
458 {
459  int bit = 1u << layer;
460 
461  if (enable) {
462  bitfield |= bit;
463  }
464  else {
465  bitfield &= ~bit;
466  }
467 
468  return bitfield;
469 }
470 
472 {
473  std::string key = armature->id.name;
474  BoneExtensionMap *result = extended_bone_maps[key];
475  if (result == nullptr) {
476  result = new BoneExtensionMap();
477  extended_bone_maps[key] = result;
478  }
479  return *result;
480 }
481 
483 {
484  std::map<std::string, BoneExtensionMap *>::iterator map_it;
485  for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it) {
486  BoneExtensionMap *extended_bones = map_it->second;
487  for (auto &extended_bone : *extended_bones) {
488  delete extended_bone.second;
489  }
490  extended_bones->clear();
491  delete extended_bones;
492  }
493 }
494 
501 {
502  this->set_name(aBone->name);
503  this->chain_length = 0;
504  this->is_leaf = false;
505  this->tail[0] = 0.0f;
506  this->tail[1] = 0.5f;
507  this->tail[2] = 0.0f;
508  this->use_connect = -1;
509  this->roll = 0;
510  this->bone_layers = 0;
511 
512  this->has_custom_tail = false;
513  this->has_custom_roll = false;
514 }
515 
517 {
518  return name;
519 }
520 
521 void BoneExtended::set_name(char *aName)
522 {
523  BLI_strncpy(name, aName, MAXBONENAME);
524 }
525 
527 {
528  return chain_length;
529 }
530 
531 void BoneExtended::set_chain_length(const int aLength)
532 {
533  chain_length = aLength;
534 }
535 
537 {
538  is_leaf = state;
539 }
540 
542 {
543  return is_leaf;
544 }
545 
546 void BoneExtended::set_roll(float roll)
547 {
548  this->roll = roll;
549  this->has_custom_roll = true;
550 }
551 
553 {
554  return this->has_custom_roll;
555 }
556 
558 {
559  return this->roll;
560 }
561 
562 void BoneExtended::set_tail(const float vec[])
563 {
564  this->tail[0] = vec[0];
565  this->tail[1] = vec[1];
566  this->tail[2] = vec[2];
567  this->has_custom_tail = true;
568 }
569 
571 {
572  return this->has_custom_tail;
573 }
574 
576 {
577  return this->tail;
578 }
579 
580 inline bool isInteger(const std::string &s)
581 {
582  if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) {
583  return false;
584  }
585 
586  char *p;
587  strtol(s.c_str(), &p, 10);
588 
589  return (*p == 0);
590 }
591 
592 void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels)
593 {
594  std::stringstream ss(layerString);
595  std::string layer;
596  int pos;
597 
598  while (ss >> layer) {
599 
600  /* Blender uses numbers to specify layers. */
601  if (isInteger(layer)) {
602  pos = atoi(layer.c_str());
603  if (pos >= 0 && pos < 32) {
604  this->bone_layers = bc_set_layer(this->bone_layers, pos);
605  continue;
606  }
607  }
608 
609  /* Layer uses labels (not supported by blender). Map to layer numbers: */
610  pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin();
611  if (pos >= layer_labels.size()) {
612  layer_labels.push_back(layer); /* Remember layer number for future usage. */
613  }
614 
615  if (pos > 31) {
616  fprintf(stderr,
617  "Too many layers in Import. Layer %s mapped to Blender layer 31\n",
618  layer.c_str());
619  pos = 31;
620  }
621 
622  /* If numeric layers and labeled layers are used in parallel (unlikely),
623  * we get a potential mix-up. Just leave as is for now. */
624  this->bone_layers = bc_set_layer(this->bone_layers, pos);
625  }
626 }
627 
628 std::string BoneExtended::get_bone_layers(int bitfield)
629 {
630  std::string sep;
631  int bit = 1u;
632 
633  std::ostringstream ss;
634  for (int i = 0; i < 32; i++) {
635  if (bit & bitfield) {
636  ss << sep << i;
637  sep = " ";
638  }
639  bit = bit << 1;
640  }
641  return ss.str();
642 }
643 
645 {
646  /* ensure that the bone is in at least one bone layer! */
647  return (bone_layers == 0) ? 1 : bone_layers;
648 }
649 
650 void BoneExtended::set_use_connect(int use_connect)
651 {
652  this->use_connect = use_connect;
653 }
654 
656 {
657  return this->use_connect;
658 }
659 
660 void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
661 {
662  IDProperty *idgroup = (IDProperty *)ebone->prop;
663  if (idgroup == nullptr) {
664  IDPropertyTemplate val = {0};
665  idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
666  ebone->prop = idgroup;
667  }
668 
669  IDPropertyTemplate val = {0};
670  val.array.len = 16;
671  val.array.type = IDP_FLOAT;
672 
673  IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
674  float *array = (float *)IDP_Array(data);
675  for (int i = 0; i < 4; i++) {
676  for (int j = 0; j < 4; j++) {
677  array[4 * i + j] = mat[i][j];
678  }
679  }
680 
681  IDP_AddToGroup(idgroup, data);
682 }
683 
684 #if 0
690 static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
691 {
692  if (ebone->prop == NULL) {
693  IDPropertyTemplate val = {0};
694  ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
695  }
696 
697  IDProperty *pgroup = (IDProperty *)ebone->prop;
698  IDPropertyTemplate val = {0};
699  IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
700  IDP_Float(prop) = value;
701  IDP_AddToGroup(pgroup, prop);
702 }
703 #endif
704 
705 IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
706 {
707  return (bone->prop == nullptr) ? nullptr : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
708 }
709 
710 float bc_get_property(Bone *bone, std::string key, float def)
711 {
712  float result = def;
713  IDProperty *property = bc_get_IDProperty(bone, key);
714  if (property) {
715  switch (property->type) {
716  case IDP_INT:
717  result = (float)(IDP_Int(property));
718  break;
719  case IDP_FLOAT:
720  result = (float)(IDP_Float(property));
721  break;
722  case IDP_DOUBLE:
723  result = (float)(IDP_Double(property));
724  break;
725  default:
726  result = def;
727  }
728  }
729  return result;
730 }
731 
732 bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
733 {
734  IDProperty *property = bc_get_IDProperty(bone, key);
735  if (property && property->type == IDP_ARRAY && property->len == 16) {
736  float *array = (float *)IDP_Array(property);
737  for (int i = 0; i < 4; i++) {
738  for (int j = 0; j < 4; j++) {
739  mat[i][j] = array[4 * i + j];
740  }
741  }
742  return true;
743  }
744  return false;
745 }
746 
747 void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
748 {
749  val[0] = bc_get_property(bone, key + "_x", def[0]);
750  val[1] = bc_get_property(bone, key + "_y", def[1]);
751  val[2] = bc_get_property(bone, key + "_z", def[2]);
752 }
753 
757 static bool has_custom_props(Bone *bone, bool enabled, std::string key)
758 {
759  if (!enabled) {
760  return false;
761  }
762 
763  return (bc_get_IDProperty(bone, key + "_x") || bc_get_IDProperty(bone, key + "_y") ||
764  bc_get_IDProperty(bone, key + "_z"));
765 }
766 
767 void bc_enable_fcurves(bAction *act, char *bone_name)
768 {
769  FCurve *fcu;
770  char prefix[200];
771 
772  if (bone_name) {
773  char bone_name_esc[sizeof(((Bone *)nullptr)->name) * 2];
774  BLI_str_escape(bone_name_esc, bone_name, sizeof(bone_name_esc));
775  BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name_esc);
776  }
777 
778  for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
779  if (bone_name) {
780  if (STREQLEN(fcu->rna_path, prefix, strlen(prefix))) {
781  fcu->flag &= ~FCURVE_DISABLED;
782  }
783  else {
784  fcu->flag |= FCURVE_DISABLED;
785  }
786  }
787  else {
788  fcu->flag &= ~FCURVE_DISABLED;
789  }
790  }
791 }
792 
793 bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim)
794 {
795 
796  /* Ok, lets be super cautious and check if the bone exists */
797  bPose *pose = ob->pose;
798  bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
799  if (!pchan) {
800  return false;
801  }
802 
803  bAction *action = bc_getSceneObjectAction(ob);
804  bPoseChannel *parchan = pchan->parent;
805 
806  bc_enable_fcurves(action, bone->name);
807  float ipar[4][4];
808 
809  if (bone->parent) {
810  invert_m4_m4(ipar, parchan->pose_mat);
811  mul_m4_m4m4(mat, ipar, pchan->pose_mat);
812  }
813  else {
814  copy_m4_m4(mat, pchan->pose_mat);
815  }
816 
817  /* OPEN_SIM_COMPATIBILITY
818  * AFAIK animation to second life is via BVH, but no
819  * reason to not have the collada-animation be correct */
820  if (for_opensim) {
821  float temp[4][4];
822  copy_m4_m4(temp, bone->arm_mat);
823  temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
824  invert_m4(temp);
825 
826  mul_m4_m4m4(mat, mat, temp);
827 
828  if (bone->parent) {
829  copy_m4_m4(temp, bone->parent->arm_mat);
830  temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
831 
832  mul_m4_m4m4(mat, temp, mat);
833  }
834  }
835  bc_enable_fcurves(action, nullptr);
836  return true;
837 }
838 
840 {
841  static float MIN_DISTANCE = 0.00001;
842 
843  if (values.size() < 2) {
844  return false; /* need at least 2 entries to be not flat */
845  }
846 
847  BCMatrixSampleMap::iterator it;
848  const BCMatrix *refmat = nullptr;
849  for (it = values.begin(); it != values.end(); ++it) {
850  const BCMatrix *matrix = it->second;
851 
852  if (refmat == nullptr) {
853  refmat = matrix;
854  continue;
855  }
856 
857  if (!matrix->in_range(*refmat, MIN_DISTANCE)) {
858  return true;
859  }
860  }
861  return false;
862 }
863 
865 {
866  /* Check for object, light and camera transform animations */
867  if ((bc_getSceneObjectAction(ob) && bc_getSceneObjectAction(ob)->curves.first) ||
870  return true;
871  }
872 
873  /* Check Material Effect parameter animations. */
874  for (int a = 0; a < ob->totcol; a++) {
875  Material *ma = BKE_object_material_get(ob, a + 1);
876  if (!ma) {
877  continue;
878  }
879  if (ma->adt && ma->adt->action && ma->adt->action->curves.first) {
880  return true;
881  }
882  }
883 
884  Key *key = BKE_key_from_object(ob);
885  if ((key && key->adt && key->adt->action) && key->adt->action->curves.first) {
886  return true;
887  }
888 
889  return false;
890 }
891 
892 bool bc_has_animations(Scene *sce, LinkNode *export_set)
893 {
894  LinkNode *node;
895  if (export_set) {
896  for (node = export_set; node; node = node->next) {
897  Object *ob = (Object *)node->link;
898 
899  if (bc_has_animations(ob)) {
900  return true;
901  }
902  }
903  }
904  return false;
905 }
906 
907 void bc_add_global_transform(Matrix &to_mat,
908  const Matrix &from_mat,
909  const BCMatrix &global_transform,
910  const bool invert)
911 {
912  copy_m4_m4(to_mat, from_mat);
913  bc_add_global_transform(to_mat, global_transform, invert);
914 }
915 
916 void bc_add_global_transform(Vector &to_vec,
917  const Vector &from_vec,
918  const BCMatrix &global_transform,
919  const bool invert)
920 {
921  copy_v3_v3(to_vec, from_vec);
922  bc_add_global_transform(to_vec, global_transform, invert);
923 }
924 
925 void bc_add_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
926 {
927  BCMatrix mat(to_mat);
928  mat.add_transform(global_transform, invert);
929  mat.get_matrix(to_mat);
930 }
931 
932 void bc_add_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert)
933 {
934  Matrix mat;
935  Vector from_vec;
936  copy_v3_v3(from_vec, to_vec);
937  global_transform.get_matrix(mat, false, 6, invert);
938  mul_v3_m4v3(to_vec, mat, from_vec);
939 }
940 
941 void bc_apply_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
942 {
943  BCMatrix mat(to_mat);
944  mat.apply_transform(global_transform, invert);
945  mat.get_matrix(to_mat);
946 }
947 
948 void bc_apply_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert)
949 {
950  Matrix transform;
951  global_transform.get_matrix(transform);
952  mul_v3_m4v3(to_vec, transform, to_vec);
953 }
954 
955 void bc_create_restpose_mat(BCExportSettings &export_settings,
956  Bone *bone,
957  float to_mat[4][4],
958  float from_mat[4][4],
959  bool use_local_space)
960 {
961  float loc[3];
962  float rot[3];
963  float scale[3];
964  static const float V0[3] = {0, 0, 0};
965 
966  if (!has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_loc") &&
967  !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_rot") &&
968  !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_scale")) {
969  /* No need */
970  copy_m4_m4(to_mat, from_mat);
971  return;
972  }
973 
974  bc_decompose(from_mat, loc, rot, nullptr, scale);
975  loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
976 
977  if (export_settings.get_keep_bind_info()) {
978  bc_get_property_vector(bone, "restpose_loc", loc, loc);
979 
980  if (use_local_space && bone->parent) {
981  Bone *b = bone;
982  while (b->parent) {
983  b = b->parent;
984  float ploc[3];
985  bc_get_property_vector(b, "restpose_loc", ploc, V0);
986  loc[0] += ploc[0];
987  loc[1] += ploc[1];
988  loc[2] += ploc[2];
989  }
990  }
991  }
992 
993  if (export_settings.get_keep_bind_info()) {
994  if (bc_get_IDProperty(bone, "restpose_rot_x")) {
995  rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
996  }
997  if (bc_get_IDProperty(bone, "restpose_rot_y")) {
998  rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
999  }
1000  if (bc_get_IDProperty(bone, "restpose_rot_z")) {
1001  rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
1002  }
1003  }
1004 
1005  if (export_settings.get_keep_bind_info()) {
1006  bc_get_property_vector(bone, "restpose_scale", scale, scale);
1007  }
1008 
1009  loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
1010 }
1011 
1012 void bc_sanitize_v3(float v[3], int precision)
1013 {
1014  for (int i = 0; i < 3; i++) {
1015  double val = (double)v[i];
1016  val = double_round(val, precision);
1017  v[i] = (float)val;
1018  }
1019 }
1020 
1021 void bc_sanitize_v3(double v[3], int precision)
1022 {
1023  for (int i = 0; i < 3; i++) {
1024  v[i] = double_round(v[i], precision);
1025  }
1026 }
1027 
1028 void bc_copy_m4_farray(float r[4][4], float *a)
1029 {
1030  for (int i = 0; i < 4; i++) {
1031  for (int j = 0; j < 4; j++) {
1032  r[i][j] = *a++;
1033  }
1034  }
1035 }
1036 
1037 void bc_copy_farray_m4(float *r, float a[4][4])
1038 {
1039  for (int i = 0; i < 4; i++) {
1040  for (int j = 0; j < 4; j++) {
1041  *r++ = a[i][j];
1042  }
1043  }
1044 }
1045 
1046 void bc_copy_darray_m4d(double *r, double a[4][4])
1047 {
1048  for (int i = 0; i < 4; i++) {
1049  for (int j = 0; j < 4; j++) {
1050  *r++ = a[i][j];
1051  }
1052  }
1053 }
1054 
1055 void bc_copy_v44_m4d(std::vector<std::vector<double>> &r, double (&a)[4][4])
1056 {
1057  for (int i = 0; i < 4; i++) {
1058  for (int j = 0; j < 4; j++) {
1059  r[i][j] = a[i][j];
1060  }
1061  }
1062 }
1063 
1064 void bc_copy_m4d_v44(double (&r)[4][4], std::vector<std::vector<double>> &a)
1065 {
1066  for (int i = 0; i < 4; i++) {
1067  for (int j = 0; j < 4; j++) {
1068  r[i][j] = a[i][j];
1069  }
1070  }
1071 }
1072 
1076 static std::string bc_get_active_uvlayer_name(Mesh *me)
1077 {
1078  int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
1079  if (num_layers) {
1080  char *layer_name = bc_CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV);
1081  if (layer_name) {
1082  return std::string(layer_name);
1083  }
1084  }
1085  return "";
1086 }
1087 
1092 static std::string bc_get_active_uvlayer_name(Object *ob)
1093 {
1094  Mesh *me = (Mesh *)ob->data;
1095  return bc_get_active_uvlayer_name(me);
1096 }
1097 
1101 static std::string bc_get_uvlayer_name(Mesh *me, int layer)
1102 {
1103  int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
1104  if (num_layers && layer < num_layers) {
1105  char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, layer);
1106  if (layer_name) {
1107  return std::string(layer_name);
1108  }
1109  }
1110  return "";
1111 }
1112 
1114 {
1115  if (ma->nodetree == nullptr) {
1116  ma->nodetree = ntreeAddTree(nullptr, "Shader Nodetree", "ShaderNodeTree");
1117  ma->use_nodes = true;
1118  }
1119  return ma->nodetree;
1120 }
1121 
1123  bContext *C, bNodeTree *ntree, int node_type, int locx, int locy, std::string label)
1124 {
1125  bNode *node = nodeAddStaticNode(C, ntree, node_type);
1126  if (node) {
1127  if (label.length() > 0) {
1128  strcpy(node->label, label.c_str());
1129  }
1130  node->locx = locx;
1131  node->locy = locy;
1132  node->flag |= NODE_SELECT;
1133  }
1134  return node;
1135 }
1136 
1137 static bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy)
1138 {
1139  return bc_add_node(C, ntree, node_type, locx, locy, "");
1140 }
1141 
1142 #if 0
1143 /* experimental, probably not used */
1144 static bNodeSocket *bc_group_add_input_socket(bNodeTree *ntree,
1145  bNode *to_node,
1146  int to_index,
1147  std::string label)
1148 {
1149  bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
1150 
1151 # if 0
1152  bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1153  return socket;
1154 # endif
1155 
1156  bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1157  bNode *inputGroup = ntreeFindType(ntree, NODE_GROUP_INPUT);
1158  node_group_input_verify(ntree, inputGroup, (ID *)ntree);
1159  bNodeSocket *newsock = node_group_input_find_socket(inputGroup, gsock->identifier);
1160  nodeAddLink(ntree, inputGroup, newsock, to_node, to_socket);
1161  strcpy(newsock->name, label.c_str());
1162  return newsock;
1163 }
1164 
1165 static bNodeSocket *bc_group_add_output_socket(bNodeTree *ntree,
1166  bNode *from_node,
1167  int from_index,
1168  std::string label)
1169 {
1170  bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
1171 
1172 # if 0
1173  bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1174  return socket;
1175 # endif
1176 
1177  bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, from_node, from_socket);
1178  bNode *outputGroup = ntreeFindType(ntree, NODE_GROUP_OUTPUT);
1179  node_group_output_verify(ntree, outputGroup, (ID *)ntree);
1180  bNodeSocket *newsock = node_group_output_find_socket(outputGroup, gsock->identifier);
1181  nodeAddLink(ntree, from_node, from_socket, outputGroup, newsock);
1182  strcpy(newsock->name, label.c_str());
1183  return newsock;
1184 }
1185 
1186 void bc_make_group(bContext *C, bNodeTree *ntree, std::map<std::string, bNode *> nmap)
1187 {
1188  bNode *gnode = node_group_make_from_selected(C, ntree, "ShaderNodeGroup", "ShaderNodeTree");
1189  bNodeTree *gtree = (bNodeTree *)gnode->id;
1190 
1191  bc_group_add_input_socket(gtree, nmap["main"], 0, "Diffuse");
1192  bc_group_add_input_socket(gtree, nmap["emission"], 0, "Emission");
1193  bc_group_add_input_socket(gtree, nmap["mix"], 0, "Transparency");
1194  bc_group_add_input_socket(gtree, nmap["emission"], 1, "Emission");
1195  bc_group_add_input_socket(gtree, nmap["main"], 4, "Metallic");
1196  bc_group_add_input_socket(gtree, nmap["main"], 5, "Specular");
1197 
1198  bc_group_add_output_socket(gtree, nmap["mix"], 0, "Shader");
1199 }
1200 #endif
1201 
1202 static void bc_node_add_link(
1203  bNodeTree *ntree, bNode *from_node, int from_index, bNode *to_node, int to_index)
1204 {
1205  bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
1206  bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
1207 
1208  nodeAddLink(ntree, from_node, from_socket, to_node, to_socket);
1209 }
1210 
1212 {
1214  std::map<std::string, bNode *> nmap;
1215 #if 0
1216  nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300);
1217  nmap["emission"] = bc_add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission");
1218  nmap["add"] = bc_add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400);
1219  nmap["transparent"] = bc_add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200);
1220  nmap["mix"] = bc_add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency");
1221  nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300);
1222  nmap["out"]->flag &= ~NODE_SELECT;
1223 
1224  bc_node_add_link(ntree, nmap["emission"], 0, nmap["add"], 0);
1225  bc_node_add_link(ntree, nmap["main"], 0, nmap["add"], 1);
1226  bc_node_add_link(ntree, nmap["add"], 0, nmap["mix"], 1);
1227  bc_node_add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2);
1228 
1229  bc_node_add_link(ntree, nmap["mix"], 0, nmap["out"], 0);
1230  /* experimental, probably not used. */
1231  bc_make_group(C, ntree, nmap);
1232 #else
1233  nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, 0, 300);
1234  nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 300, 300);
1235  bc_node_add_link(ntree, nmap["main"], 0, nmap["out"], 0);
1236 #endif
1237 }
1238 
1239 COLLADASW::ColorOrTexture bc_get_base_color(Material *ma)
1240 {
1241  /* for alpha see bc_get_alpha() */
1242  Color default_color = {ma->r, ma->g, ma->b, 1.0};
1243  bNode *shader = bc_get_master_shader(ma);
1244  if (ma->use_nodes && shader) {
1245  return bc_get_cot_from_shader(shader, "Base Color", default_color, false);
1246  }
1247 
1248  return bc_get_cot(default_color);
1249 }
1250 
1251 COLLADASW::ColorOrTexture bc_get_emission(Material *ma)
1252 {
1253  Color default_color = {0, 0, 0, 1}; /* default black */
1254  bNode *shader = bc_get_master_shader(ma);
1255  if (!(ma->use_nodes && shader)) {
1256  return bc_get_cot(default_color);
1257  }
1258 
1259  double emission_strength = 0.0;
1260  bc_get_float_from_shader(shader, emission_strength, "Emission Strength");
1261  if (emission_strength == 0.0) {
1262  return bc_get_cot(default_color);
1263  }
1264 
1265  COLLADASW::ColorOrTexture cot = bc_get_cot_from_shader(shader, "Emission", default_color);
1266 
1267  /* If using texture, emission strength is not supported. */
1268  COLLADASW::Color col = cot.getColor();
1269  double final_color[3] = {col.getRed(), col.getGreen(), col.getBlue()};
1270  mul_v3db_db(final_color, emission_strength);
1271 
1272  /* Collada does not support HDR colors, so clamp to 1 keeping channels proportional. */
1273  double max_color = fmax(fmax(final_color[0], final_color[1]), final_color[2]);
1274  if (max_color > 1.0) {
1275  mul_v3db_db(final_color, 1.0 / max_color);
1276  }
1277 
1278  cot.getColor().set(final_color[0], final_color[1], final_color[2], col.getAlpha());
1279 
1280  return cot;
1281 }
1282 
1283 COLLADASW::ColorOrTexture bc_get_ambient(Material *ma)
1284 {
1285  Color default_color = {0, 0, 0, 1.0};
1286  return bc_get_cot(default_color);
1287 }
1288 
1289 COLLADASW::ColorOrTexture bc_get_specular(Material *ma)
1290 {
1291  Color default_color = {0, 0, 0, 1.0};
1292  return bc_get_cot(default_color);
1293 }
1294 
1295 COLLADASW::ColorOrTexture bc_get_reflective(Material *ma)
1296 {
1297  Color default_color = {0, 0, 0, 1.0};
1298  return bc_get_cot(default_color);
1299 }
1300 
1302 {
1303  double alpha = ma->a; /* fallback if no socket found */
1304  bNode *master_shader = bc_get_master_shader(ma);
1305  if (ma->use_nodes && master_shader) {
1306  bc_get_float_from_shader(master_shader, alpha, "Alpha");
1307  }
1308  return alpha;
1309 }
1310 
1312 {
1313  double ior = -1; /* fallback if no socket found */
1314  bNode *master_shader = bc_get_master_shader(ma);
1315  if (ma->use_nodes && master_shader) {
1316  bc_get_float_from_shader(master_shader, ior, "IOR");
1317  }
1318  return ior;
1319 }
1320 
1322 {
1323  double ior = -1; /* fallback if no socket found */
1324  bNode *master_shader = bc_get_master_shader(ma);
1325  if (ma->use_nodes && master_shader) {
1326  bc_get_float_from_shader(master_shader, ior, "Roughness");
1327  }
1328  return ior;
1329 }
1330 
1332 {
1333  double reflectivity = ma->spec; /* fallback if no socket found */
1334  bNode *master_shader = bc_get_master_shader(ma);
1335  if (ma->use_nodes && master_shader) {
1336  bc_get_float_from_shader(master_shader, reflectivity, "Metallic");
1337  }
1338  return reflectivity;
1339 }
1340 
1341 bool bc_get_float_from_shader(bNode *shader, double &val, std::string nodeid)
1342 {
1343  bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, nodeid.c_str());
1344  if (socket) {
1346  val = (double)ref->value;
1347  return true;
1348  }
1349  return false;
1350 }
1351 
1352 COLLADASW::ColorOrTexture bc_get_cot_from_shader(bNode *shader,
1353  std::string nodeid,
1354  Color &default_color,
1355  bool with_alpha)
1356 {
1357  bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, nodeid.c_str());
1358  if (socket) {
1360  float *col = dcol->value;
1361  return bc_get_cot(col, with_alpha);
1362  }
1363 
1364  return bc_get_cot(default_color, with_alpha);
1365 }
1366 
1368 {
1369  bNodeTree *nodetree = ma->nodetree;
1370  if (nodetree) {
1371  for (bNode *node = (bNode *)nodetree->nodes.first; node; node = node->next) {
1372  if (node->typeinfo->type == SH_NODE_BSDF_PRINCIPLED) {
1373  return node;
1374  }
1375  }
1376  }
1377  return nullptr;
1378 }
1379 
1380 COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a)
1381 {
1382  COLLADASW::Color color(r, g, b, a);
1383  COLLADASW::ColorOrTexture cot(color);
1384  return cot;
1385 }
1386 
1387 COLLADASW::ColorOrTexture bc_get_cot(Color col, bool with_alpha)
1388 {
1389  COLLADASW::Color color(col[0], col[1], col[2], (with_alpha) ? col[3] : 1.0);
1390  COLLADASW::ColorOrTexture cot(color);
1391  return cot;
1392 }
typedef float(TangentPoint)[2]
std::map< int, const BCMatrix * > BCMatrixSampleMap
Definition: BCSampleData.h:48
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
bool BKE_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *ob)
Definition: collection.c:1125
const bConstraintTypeInfo * BKE_constraint_typeinfo_get(struct bConstraint *con)
Definition: constraint.c:5506
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_active_layer_index(const struct CustomData *data, int type)
int CustomData_number_of_layers(const struct CustomData *data, int type)
const CustomData_MeshMasks CD_MASK_MESH
Definition: customdata.cc:2065
#define IDP_Float(prop)
Definition: BKE_idprop.h:269
#define IDP_Int(prop)
Definition: BKE_idprop.h:244
struct IDProperty * IDP_New(char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:887
#define IDP_Double(prop)
Definition: BKE_idprop.h:270
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL()
Definition: idprop.c:631
struct IDProperty * IDP_GetPropertyFromGroup(const struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define IDP_Array(prop)
Definition: BKE_idprop.h:245
struct Key * BKE_key_from_object(struct Object *ob)
Definition: key.c:1803
struct LayerCollection * BKE_layer_collection_get_active(struct ViewLayer *view_layer)
Definition: layer.c:636
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, struct Base *selbase)
Definition: layer.c:397
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:187
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
void BKE_mesh_tessface_ensure(struct Mesh *mesh)
struct Mesh * mesh_get_eval_final(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.cc:94
#define SH_NODE_MIX_SHADER
Definition: BKE_node.h:1105
struct bNode * ntreeFindType(const struct bNodeTree *ntree, int type)
#define SH_NODE_BSDF_PRINCIPLED
Definition: BKE_node.h:1164
#define SH_NODE_EMISSION
Definition: BKE_node.h:1115
#define SH_NODE_ADD_SHADER
Definition: BKE_node.h:1127
struct bNodeSocket * ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNode *from_node, struct bNodeSocket *from_sock)
Definition: node.cc:3382
#define SH_NODE_BSDF_TRANSPARENT
Definition: BKE_node.h:1113
#define SH_NODE_OUTPUT_MATERIAL
Definition: BKE_node.h:1101
struct bNodeLink * nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock)
Definition: node.cc:2296
struct bNodeSocket * nodeFindSocket(const struct bNode *node, eNodeSocketInOut in_out, const char *identifier)
struct bNodeTree * ntreeAddTree(struct Main *bmain, const char *name, const char *idname)
Definition: node.cc:2674
struct bNode * nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type)
Definition: node.cc:2151
#define NODE_GROUP_INPUT
Definition: BKE_node.h:987
General operations, lookup, etc. for blender objects.
void * BKE_object_obdata_add_from_type(struct Main *bmain, int type, const char *name) ATTR_NONNULL(1)
Definition: object.cc:2161
void BKE_object_apply_mat4(struct Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Definition: object.cc:3575
struct Object * BKE_object_add_only_object(struct Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
Definition: object.cc:2241
void BKE_scene_frame_set(struct Scene *scene, float frame)
Definition: scene.cc:2420
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
double double_round(double x, int ndigits)
Definition: math_base.c:27
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1206
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void loc_eulO_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3], short order)
Definition: math_matrix.c:2571
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void mat4_to_size(float size[3], const float M[4][4])
Definition: math_matrix.c:2138
void mat4_to_eul(float eul[3], const float mat[4][4])
#define DEG2RADF(_deg)
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
Definition: math_rotation.c:46
void mat4_to_quat(float q[4], const float mat[4][4])
void quat_to_mat4(float mat[4][4], const float q[4])
MINLINE void mul_v3db_db(double r[3], double f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
size_t size_t char size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL()
Definition: string.c:250
#define STREQLEN(a, b, n)
#define STREQ(a, b)
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
@ IDP_DOUBLE
Definition: DNA_ID.h:143
@ IDP_FLOAT
Definition: DNA_ID.h:138
@ IDP_INT
Definition: DNA_ID.h:137
@ IDP_GROUP
Definition: DNA_ID.h:141
@ IDP_ARRAY
Definition: DNA_ID.h:140
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:794
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ FCURVE_DISABLED
#define MAXBONENAME
@ BONE_NO_DEFORM
@ BONE_CONNECTED
@ CONSTRAINT_OFF
@ CONSTRAINT_DISABLE
@ CD_MLOOPUV
@ eModifierType_Armature
@ MOD_TRIANGULATE_QUAD_SHORTEDGE
@ SOCK_IN
#define NODE_SELECT
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ PARSKEL
@ PAR_OBJECT
Definition: ED_object.h:138
bool ED_object_parent_set(struct ReportList *reports, const struct bContext *C, struct Scene *scene, struct Object *const ob, struct Object *const par, int partype, bool xmirror, bool keep_transform, const int vert_par[3])
void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph)
Definition: screen_edit.c:1694
BC_export_mesh_type
@ BC_MESH_TYPE_RENDER
@ BC_MESH_TYPE_VIEW
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_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
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its and Z components Generates normals with round corners and may slow down renders Vector Displace the surface along an arbitrary direction White Return a random value or color based on an input seed Float Map an input float to a curve and outputs a float value Separate Color
NODE_GROUP_OUTPUT
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a vector
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
#define C
Definition: RandGen.cpp:25
ATTR_WARN_UNUSED_RESULT BMesh * bm
const BMAllocTemplate bm_mesh_allocsize_default
Definition: bmesh_mesh.cc:23
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
Definition: bmesh_mesh.cc:125
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const int min_vertices, const bool tag_only, BMOperator *op, BMOpSlot *slot_facemap_out, BMOpSlot *slot_facemap_double_out)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void add_transform(Matrix &to, const Matrix &transform, const Matrix &from, bool inverted=false)
Definition: BCMath.cpp:72
void get_matrix(DMatrix &matrix, bool transposed=false, int precision=-1) const
Definition: BCMath.cpp:166
void apply_transform(Matrix &to, const Matrix &transform, const Matrix &from, bool inverse=false)
Definition: BCMath.cpp:87
bool in_range(const BCMatrix &other, float distance) const
Definition: BCMath.cpp:199
void set_use_connect(int use_connect)
int get_chain_length()
void set_roll(float roll)
void set_name(char *aName)
char * get_name()
void set_tail(const float vec[])
void set_leaf_bone(bool state)
void set_bone_layers(std::string layers, std::vector< std::string > &layer_labels)
float * get_tail()
BoneExtended(EditBone *aBone)
void set_chain_length(int aLength)
BoneExtensionMap & getExtensionMap(bArmature *armature)
float(& get_scale())[4]
float(& get_rotation())[4]
std::string translate_id(const char *idString)
COLLADASW::ColorOrTexture bc_get_specular(Material *ma)
COLLADASW::ColorOrTexture bc_get_ambient(Material *ma)
bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
void bc_copy_farray_m4(float *r, float a[4][4])
bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
Mesh * bc_get_mesh_copy(BlenderContext &blender_context, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
double bc_get_alpha(Material *ma)
void bc_triangulate_mesh(Mesh *me)
COLLADASW::ColorOrTexture bc_get_cot_from_shader(bNode *shader, std::string nodeid, Color &default_color, bool with_alpha)
float bc_get_property(Bone *bone, std::string key, float def)
void bc_add_global_transform(Matrix &to_mat, const Matrix &from_mat, const BCMatrix &global_transform, const bool invert)
void bc_copy_v44_m4d(std::vector< std::vector< double >> &r, double(&a)[4][4])
void bc_sanitize_v3(float v[3], int precision)
IDProperty * bc_get_IDProperty(Bone *bone, std::string key)
COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a)
bool bc_has_animations(Object *ob)
void bc_apply_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
COLLADASW::ColorOrTexture bc_get_emission(Material *ma)
COLLADASW::ColorOrTexture bc_get_reflective(Material *ma)
static bool has_custom_props(Bone *bone, bool enabled, std::string key)
bNode * bc_get_master_shader(Material *ma)
static std::string bc_get_uvlayer_name(Mesh *me, int layer)
bool isInteger(const std::string &s)
void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
double bc_get_reflectivity(Material *ma)
EditBone * bc_get_edit_bone(bArmature *armature, char *name)
std::vector< bAction * > bc_getSceneActions(const bContext *C, Object *ob, bool all_actions)
void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
void bc_add_default_shader(bContext *C, Material *ma)
static bNodeTree * prepare_material_nodetree(Material *ma)
static void bc_node_add_link(bNodeTree *ntree, bNode *from_node, int from_index, bNode *to_node, int to_index)
void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
bool bc_is_animated(BCMatrixSampleMap &values)
void bc_create_restpose_mat(BCExportSettings &export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space)
bool bc_get_float_from_shader(bNode *shader, double &val, std::string nodeid)
int bc_get_active_UVLayer(Object *ob)
void bc_bubble_sort_by_Object_name(LinkNode *export_set)
bool bc_validateConstraints(bConstraint *con)
std::string bc_url_encode(std::string data)
Object * bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
double bc_get_shininess(Material *ma)
bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
COLLADASW::ColorOrTexture bc_get_base_color(Material *ma)
Object * bc_get_assigned_armature(Object *ob)
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index)
double bc_get_ior(Material *ma)
static std::string bc_get_active_uvlayer_name(Mesh *me)
int bc_set_layer(int bitfield, int layer)
void bc_update_scene(BlenderContext &blender_context, float ctime)
static bNode * bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy, std::string label)
std::string bc_replace_string(std::string data, const std::string &pattern, const std::string &replacement)
bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim)
void bc_copy_darray_m4d(double *r, double a[4][4])
void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
void bc_copy_m4_farray(float r[4][4], float *a)
bool bc_has_object_type(LinkNode *export_set, short obtype)
void bc_enable_fcurves(bAction *act, char *bone_name)
std::string bc_get_action_id(std::string action_name, std::string ob_name, std::string channel_type, std::string axis_name, std::string axis_separator)
bool bc_is_leaf_bone(Bone *bone)
void bc_copy_m4d_v44(double(&r)[4][4], std::vector< std::vector< double >> &a)
int bc_test_parent_loop(Object *par, Object *ob)
bAction * bc_getSceneObjectAction(Object *ob)
Definition: collada_utils.h:68
char * bc_CustomData_get_active_layer_name(const CustomData *data, int type)
void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
bAction * bc_getSceneLightAction(Object *ob)
Definition: collada_utils.h:74
char * bc_CustomData_get_layer_name(const CustomData *data, int type, int n)
bAction * bc_getSceneCameraAction(Object *ob)
Definition: collada_utils.h:85
std::map< std::string, BoneExtended * > BoneExtensionMap
OperationNode * node
const char * label
Scene scene
const Depsgraph * depsgraph
bNodeTree * ntree
#define rot(x, k)
uint pos
uint col
bool enabled
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition: invert.h:8
const int state
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static unsigned a[3]
Definition: RandGen.cpp:78
static bNode * node_group_make_from_selected(const bContext &C, bNodeTree &ntree, const char *ntype, const char *ntreetype)
Definition: node_group.cc:990
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken ior("ior", pxr::TfToken::Immortal)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
bNodeSocket * node_group_output_find_socket(bNode *node, const char *identifier)
Definition: node_common.cc:536
bNodeSocket * node_group_input_find_socket(bNode *node, const char *identifier)
Definition: node_common.cc:444
bAction * action
struct Bone * parent
char name[64]
IDProperty * prop
float arm_mat[4][4]
ListBase childbase
char name[64]
Definition: BKE_armature.h:43
struct EditBone * next
Definition: BKE_armature.h:33
struct IDProperty * prop
Definition: BKE_armature.h:35
struct FCurve * next
char * rna_path
short flag
Definition: DNA_ID.h:368
void * next
Definition: DNA_ID.h:369
char name[66]
Definition: DNA_ID.h:378
struct AnimData * adt
Definition: DNA_key_types.h:65
struct Collection * collection
void * link
Definition: BLI_linklist.h:24
struct LinkNode * next
Definition: BLI_linklist.h:23
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase actions
Definition: BKE_main.h:191
struct bNodeTree * nodetree
struct AnimData * adt
CustomData ldata
short partype
struct bPose * pose
ListBase modifiers
float obmat[4][4]
struct Object * parent
void * data
ListBase curves
ListBase * edbo
void(* evaluate_constraint)(struct bConstraint *con, struct bConstraintOb *cob, struct ListBase *targets)
char name[64]
void * default_value
char identifier[64]
ListBase nodes
ListBase inputs
struct ID * id
ListBase outputs
struct bPoseChannel * parent
float pose_mat[4][4]
struct IDPropertyTemplate::@27 array
ccl_device_inline int mod(int x, int m)
Definition: util/math.h:490