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_node.h"
46 #include "BKE_object.h"
47 #include "BKE_scene.h"
48 
49 #include "ED_node.h"
50 #include "ED_object.h"
51 #include "ED_screen.h"
52 
53 #include "WM_api.h" /* XXX hrm, see if we can do without this */
54 #include "WM_types.h"
55 
56 #include "bmesh.h"
57 #include "bmesh_tools.h"
58 
59 #include "DEG_depsgraph.h"
60 #include "DEG_depsgraph_query.h"
61 #if 0
62 # include "NOD_common.h"
63 #endif
64 
65 #include "BlenderContext.h"
66 #include "ExportSettings.h"
67 #include "collada_utils.h"
68 
69 float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index)
70 {
71  if (index >= array.getValuesCount()) {
72  return 0.0f;
73  }
74 
75  if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT) {
76  return array.getFloatValues()->getData()[index];
77  }
78 
79  return array.getDoubleValues()->getData()[index];
80 }
81 
83 {
84  /* Copied from /editors/object/object_relations.c */
85 
86  /* test if 'ob' is a parent somewhere in par's parents */
87 
88  if (par == nullptr) {
89  return 0;
90  }
91  if (ob == par) {
92  return 1;
93  }
94 
95  return bc_test_parent_loop(par->parent, ob);
96 }
97 
99 {
101 
102  /* these we can skip completely (invalid constraints...) */
103  if (cti == nullptr) {
104  return false;
105  }
106  if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
107  return false;
108  }
109 
110  /* these constraints can't be evaluated anyway */
111  if (cti->evaluate_constraint == nullptr) {
112  return false;
113  }
114 
115  /* influence == 0 should be ignored */
116  if (con->enforce == 0.0f) {
117  return false;
118  }
119 
120  /* validation passed */
121  return true;
122 }
123 
124 bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
125 {
127  int partype = PAR_OBJECT;
128  const bool xmirror = false;
129  const bool keep_transform = false;
130 
131  if (par && is_parent_space) {
132  mul_m4_m4m4(ob->obmat, par->obmat, ob->obmat);
133  }
134 
135  bool ok = ED_object_parent_set(
136  nullptr, C, scene, ob, par, partype, xmirror, keep_transform, nullptr);
137  return ok;
138 }
139 
140 std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions)
141 {
142  std::vector<bAction *> actions;
143  if (all_actions) {
144  Main *bmain = CTX_data_main(C);
145  ID *id;
146 
147  for (id = (ID *)bmain->actions.first; id; id = (ID *)(id->next)) {
148  bAction *act = (bAction *)id;
149  /* XXX This currently creates too many actions.
150  * TODO: Need to check if the action is compatible to the given object. */
151  actions.push_back(act);
152  }
153  }
154  else {
155  bAction *action = bc_getSceneObjectAction(ob);
156  actions.push_back(action);
157  }
158 
159  return actions;
160 }
161 
162 std::string bc_get_action_id(std::string action_name,
163  std::string ob_name,
164  std::string channel_type,
165  std::string axis_name,
166  std::string axis_separator)
167 {
168  std::string result = action_name + "_" + channel_type;
169  if (ob_name.length() > 0) {
170  result = ob_name + "_" + result;
171  }
172  if (axis_name.length() > 0) {
173  result += axis_separator + axis_name;
174  }
175  return translate_id(result);
176 }
177 
178 void bc_update_scene(BlenderContext &blender_context, float ctime)
179 {
180  Main *bmain = blender_context.get_main();
181  Scene *scene = blender_context.get_scene();
182  Depsgraph *depsgraph = blender_context.get_depsgraph();
183 
184  /* See remark in physics_fluid.c lines 395...) */
185  // BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
186  BKE_scene_frame_set(scene, ctime);
188 }
189 
190 Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
191 {
192  Object *ob = BKE_object_add_only_object(bmain, type, name);
193 
194  ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
196 
197  LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
198  BKE_collection_object_add(bmain, layer_collection->collection, ob);
199 
200  Base *base = BKE_view_layer_base_find(view_layer, ob);
201  /* TODO: is setting active needed? */
203 
204  return ob;
205 }
206 
207 Mesh *bc_get_mesh_copy(BlenderContext &blender_context,
208  Object *ob,
209  BC_export_mesh_type export_mesh_type,
210  bool apply_modifiers,
211  bool triangulate)
212 {
214  Mesh *tmpmesh = nullptr;
215  if (apply_modifiers) {
216 #if 0 /* Not supported by new system currently... */
217  switch (export_mesh_type) {
218  case BC_MESH_TYPE_VIEW: {
219  dm = mesh_create_derived_view(depsgraph, scene, ob, &mask);
220  break;
221  }
222  case BC_MESH_TYPE_RENDER: {
223  dm = mesh_create_derived_render(depsgraph, scene, ob, &mask);
224  break;
225  }
226  }
227 #else
228  Depsgraph *depsgraph = blender_context.get_depsgraph();
229  Scene *scene_eval = blender_context.get_evaluated_scene();
230  Object *ob_eval = blender_context.get_evaluated_object(ob);
231  tmpmesh = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &mask);
232 #endif
233  }
234  else {
235  tmpmesh = (Mesh *)ob->data;
236  }
237 
238  tmpmesh = (Mesh *)BKE_id_copy_ex(nullptr, &tmpmesh->id, nullptr, LIB_ID_COPY_LOCALIZE);
239 
240  if (triangulate) {
241  bc_triangulate_mesh(tmpmesh);
242  }
243  BKE_mesh_tessface_ensure(tmpmesh);
244  return tmpmesh;
245 }
246 
248 {
249  Object *ob_arm = nullptr;
250 
251  if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
252  ob_arm = ob->parent;
253  }
254  else {
255  ModifierData *mod;
256  for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
257  if (mod->type == eModifierType_Armature) {
258  ob_arm = ((ArmatureModifierData *)mod)->object;
259  }
260  }
261  }
262 
263  return ob_arm;
264 }
265 
266 bool bc_has_object_type(LinkNode *export_set, short obtype)
267 {
268  LinkNode *node;
269 
270  for (node = export_set; node; node = node->next) {
271  Object *ob = (Object *)node->link;
272  /* XXX: why is this checking for ob->data? - we could be looking for empties. */
273  if (ob->type == obtype && ob->data) {
274  return true;
275  }
276  }
277  return false;
278 }
279 
281 {
282  /* Use bubble sort algorithm for sorting the export set. */
283 
284  bool sorted = false;
285  LinkNode *node;
286  for (node = export_set; node->next && !sorted; node = node->next) {
287 
288  sorted = true;
289 
290  LinkNode *current;
291  for (current = export_set; current->next; current = current->next) {
292  Object *a = (Object *)current->link;
293  Object *b = (Object *)current->next->link;
294 
295  if (strcmp(a->id.name, b->id.name) > 0) {
296  current->link = b;
297  current->next->link = a;
298  sorted = false;
299  }
300  }
301  }
302 }
303 
304 bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
305 {
306  if (deform_bones_only) {
307  Bone *root = nullptr;
308  Bone *bone = aBone;
309  while (bone) {
310  if (!(bone->flag & BONE_NO_DEFORM)) {
311  root = bone;
312  }
313  bone = bone->parent;
314  }
315  return (aBone == root);
316  }
317 
318  return !(aBone->parent);
319 }
320 
322 {
323  Mesh *me = (Mesh *)ob->data;
325 }
326 
327 std::string bc_url_encode(std::string data)
328 {
329  /* XXX We probably do not need to do a full encoding.
330  * But in case that is necessary,then it can be added here.
331  */
332  return bc_replace_string(data, "#", "%23");
333 }
334 
335 std::string bc_replace_string(std::string data,
336  const std::string &pattern,
337  const std::string &replacement)
338 {
339  size_t pos = 0;
340  while ((pos = data.find(pattern, pos)) != std::string::npos) {
341  data.replace(pos, pattern.length(), replacement);
342  pos += replacement.length();
343  }
344  return data;
345 }
346 
347 void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
348 {
349  if (scale_to_scene) {
350  mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat);
351  }
352  mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
353  BKE_object_apply_mat4(ob, ob->obmat, false, false);
354 }
355 
356 void bc_match_scale(std::vector<Object *> *objects_done,
357  UnitConverter &bc_unit,
358  bool scale_to_scene)
359 {
360  for (Object *ob : *objects_done) {
361  if (ob->parent == nullptr) {
362  bc_match_scale(ob, bc_unit, scale_to_scene);
363  }
364  }
365 }
366 
367 void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
368 {
369  if (size) {
370  mat4_to_size(size, mat);
371  }
372 
373  if (eul) {
374  mat4_to_eul(eul, mat);
375  }
376 
377  if (quat) {
378  mat4_to_quat(quat, mat);
379  }
380 
381  if (loc) {
382  copy_v3_v3(loc, mat[3]);
383  }
384 }
385 
386 void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
387 {
388  float qd[4];
389  float matd[4][4];
390  float mati[4][4];
391  float mat_from[4][4];
392  quat_to_mat4(mat_from, quat_from);
393 
394  /* Calculate the difference matrix matd between mat_from and mat_to */
395  invert_m4_m4(mati, mat_from);
396  mul_m4_m4m4(matd, mati, mat_to);
397 
398  mat4_to_quat(qd, matd);
399 
400  mul_qt_qtqt(quat_to, qd, quat_from); /* rot is the final rotation corresponding to mat_to */
401 }
402 
404 {
405  bool use_beauty = false;
406  bool tag_only = false;
407 
408  /* XXX: The triangulation method selection could be offered in the UI. */
409  int quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE;
410 
411  const BMeshCreateParams bm_create_params{};
412  BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_create_params);
413  BMeshFromMeshParams bm_from_me_params{};
414  bm_from_me_params.calc_face_normal = true;
415  bm_from_me_params.calc_vert_normal = true;
416  BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
417  BM_mesh_triangulate(bm, quad_method, use_beauty, 4, tag_only, nullptr, nullptr, nullptr);
418 
419  BMeshToMeshParams bm_to_me_params{};
420  bm_to_me_params.calc_object_remap = false;
421  BM_mesh_bm_to_me(nullptr, bm, me, &bm_to_me_params);
422  BM_mesh_free(bm);
423 }
424 
426 {
427  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
428  if (child->flag & BONE_CONNECTED) {
429  return false;
430  }
431  }
432  return true;
433 }
434 
435 EditBone *bc_get_edit_bone(bArmature *armature, char *name)
436 {
437  EditBone *eBone;
438 
439  for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
440  if (STREQ(name, eBone->name)) {
441  return eBone;
442  }
443  }
444 
445  return nullptr;
446 }
447 int bc_set_layer(int bitfield, int layer)
448 {
449  return bc_set_layer(bitfield, layer, true); /* enable */
450 }
451 
452 int bc_set_layer(int bitfield, int layer, bool enable)
453 {
454  int bit = 1u << layer;
455 
456  if (enable) {
457  bitfield |= bit;
458  }
459  else {
460  bitfield &= ~bit;
461  }
462 
463  return bitfield;
464 }
465 
467 {
468  std::string key = armature->id.name;
469  BoneExtensionMap *result = extended_bone_maps[key];
470  if (result == nullptr) {
471  result = new BoneExtensionMap();
472  extended_bone_maps[key] = result;
473  }
474  return *result;
475 }
476 
478 {
479  std::map<std::string, BoneExtensionMap *>::iterator map_it;
480  for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it) {
481  BoneExtensionMap *extended_bones = map_it->second;
482  for (auto &extended_bone : *extended_bones) {
483  delete extended_bone.second;
484  }
485  extended_bones->clear();
486  delete extended_bones;
487  }
488 }
489 
496 {
497  this->set_name(aBone->name);
498  this->chain_length = 0;
499  this->is_leaf = false;
500  this->tail[0] = 0.0f;
501  this->tail[1] = 0.5f;
502  this->tail[2] = 0.0f;
503  this->use_connect = -1;
504  this->roll = 0;
505  this->bone_layers = 0;
506 
507  this->has_custom_tail = false;
508  this->has_custom_roll = false;
509 }
510 
512 {
513  return name;
514 }
515 
516 void BoneExtended::set_name(char *aName)
517 {
518  BLI_strncpy(name, aName, MAXBONENAME);
519 }
520 
522 {
523  return chain_length;
524 }
525 
526 void BoneExtended::set_chain_length(const int aLength)
527 {
528  chain_length = aLength;
529 }
530 
532 {
533  is_leaf = state;
534 }
535 
537 {
538  return is_leaf;
539 }
540 
541 void BoneExtended::set_roll(float roll)
542 {
543  this->roll = roll;
544  this->has_custom_roll = true;
545 }
546 
548 {
549  return this->has_custom_roll;
550 }
551 
553 {
554  return this->roll;
555 }
556 
557 void BoneExtended::set_tail(const float vec[])
558 {
559  this->tail[0] = vec[0];
560  this->tail[1] = vec[1];
561  this->tail[2] = vec[2];
562  this->has_custom_tail = true;
563 }
564 
566 {
567  return this->has_custom_tail;
568 }
569 
571 {
572  return this->tail;
573 }
574 
575 inline bool isInteger(const std::string &s)
576 {
577  if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) {
578  return false;
579  }
580 
581  char *p;
582  strtol(s.c_str(), &p, 10);
583 
584  return (*p == 0);
585 }
586 
587 void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels)
588 {
589  std::stringstream ss(layerString);
590  std::string layer;
591  int pos;
592 
593  while (ss >> layer) {
594 
595  /* Blender uses numbers to specify layers. */
596  if (isInteger(layer)) {
597  pos = atoi(layer.c_str());
598  if (pos >= 0 && pos < 32) {
599  this->bone_layers = bc_set_layer(this->bone_layers, pos);
600  continue;
601  }
602  }
603 
604  /* Layer uses labels (not supported by blender). Map to layer numbers: */
605  pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin();
606  if (pos >= layer_labels.size()) {
607  layer_labels.push_back(layer); /* Remember layer number for future usage. */
608  }
609 
610  if (pos > 31) {
611  fprintf(stderr,
612  "Too many layers in Import. Layer %s mapped to Blender layer 31\n",
613  layer.c_str());
614  pos = 31;
615  }
616 
617  /* If numeric layers and labeled layers are used in parallel (unlikely),
618  * we get a potential mix-up. Just leave as is for now. */
619  this->bone_layers = bc_set_layer(this->bone_layers, pos);
620  }
621 }
622 
623 std::string BoneExtended::get_bone_layers(int bitfield)
624 {
625  std::string sep;
626  int bit = 1u;
627 
628  std::ostringstream ss;
629  for (int i = 0; i < 32; i++) {
630  if (bit & bitfield) {
631  ss << sep << i;
632  sep = " ";
633  }
634  bit = bit << 1;
635  }
636  return ss.str();
637 }
638 
640 {
641  /* ensure that the bone is in at least one bone layer! */
642  return (bone_layers == 0) ? 1 : bone_layers;
643 }
644 
645 void BoneExtended::set_use_connect(int use_connect)
646 {
647  this->use_connect = use_connect;
648 }
649 
651 {
652  return this->use_connect;
653 }
654 
655 void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
656 {
657  IDProperty *idgroup = (IDProperty *)ebone->prop;
658  if (idgroup == nullptr) {
659  IDPropertyTemplate val = {0};
660  idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
661  ebone->prop = idgroup;
662  }
663 
664  IDPropertyTemplate val = {0};
665  val.array.len = 16;
666  val.array.type = IDP_FLOAT;
667 
668  IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
669  float *array = (float *)IDP_Array(data);
670  for (int i = 0; i < 4; i++) {
671  for (int j = 0; j < 4; j++) {
672  array[4 * i + j] = mat[i][j];
673  }
674  }
675 
676  IDP_AddToGroup(idgroup, data);
677 }
678 
679 #if 0
685 static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
686 {
687  if (ebone->prop == NULL) {
688  IDPropertyTemplate val = {0};
689  ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
690  }
691 
692  IDProperty *pgroup = (IDProperty *)ebone->prop;
693  IDPropertyTemplate val = {0};
694  IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
695  IDP_Float(prop) = value;
696  IDP_AddToGroup(pgroup, prop);
697 }
698 #endif
699 
700 IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
701 {
702  return (bone->prop == nullptr) ? nullptr : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
703 }
704 
705 float bc_get_property(Bone *bone, std::string key, float def)
706 {
707  float result = def;
708  IDProperty *property = bc_get_IDProperty(bone, key);
709  if (property) {
710  switch (property->type) {
711  case IDP_INT:
712  result = (float)(IDP_Int(property));
713  break;
714  case IDP_FLOAT:
715  result = (float)(IDP_Float(property));
716  break;
717  case IDP_DOUBLE:
718  result = (float)(IDP_Double(property));
719  break;
720  default:
721  result = def;
722  }
723  }
724  return result;
725 }
726 
727 bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
728 {
729  IDProperty *property = bc_get_IDProperty(bone, key);
730  if (property && property->type == IDP_ARRAY && property->len == 16) {
731  float *array = (float *)IDP_Array(property);
732  for (int i = 0; i < 4; i++) {
733  for (int j = 0; j < 4; j++) {
734  mat[i][j] = array[4 * i + j];
735  }
736  }
737  return true;
738  }
739  return false;
740 }
741 
742 void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
743 {
744  val[0] = bc_get_property(bone, key + "_x", def[0]);
745  val[1] = bc_get_property(bone, key + "_y", def[1]);
746  val[2] = bc_get_property(bone, key + "_z", def[2]);
747 }
748 
752 static bool has_custom_props(Bone *bone, bool enabled, std::string key)
753 {
754  if (!enabled) {
755  return false;
756  }
757 
758  return (bc_get_IDProperty(bone, key + "_x") || bc_get_IDProperty(bone, key + "_y") ||
759  bc_get_IDProperty(bone, key + "_z"));
760 }
761 
762 void bc_enable_fcurves(bAction *act, char *bone_name)
763 {
764  FCurve *fcu;
765  char prefix[200];
766 
767  if (bone_name) {
768  char bone_name_esc[sizeof(((Bone *)nullptr)->name) * 2];
769  BLI_str_escape(bone_name_esc, bone_name, sizeof(bone_name_esc));
770  BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name_esc);
771  }
772 
773  for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
774  if (bone_name) {
775  if (STREQLEN(fcu->rna_path, prefix, strlen(prefix))) {
776  fcu->flag &= ~FCURVE_DISABLED;
777  }
778  else {
779  fcu->flag |= FCURVE_DISABLED;
780  }
781  }
782  else {
783  fcu->flag &= ~FCURVE_DISABLED;
784  }
785  }
786 }
787 
788 bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim)
789 {
790 
791  /* Ok, lets be super cautious and check if the bone exists */
792  bPose *pose = ob->pose;
793  bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
794  if (!pchan) {
795  return false;
796  }
797 
798  bAction *action = bc_getSceneObjectAction(ob);
799  bPoseChannel *parchan = pchan->parent;
800 
801  bc_enable_fcurves(action, bone->name);
802  float ipar[4][4];
803 
804  if (bone->parent) {
805  invert_m4_m4(ipar, parchan->pose_mat);
806  mul_m4_m4m4(mat, ipar, pchan->pose_mat);
807  }
808  else {
809  copy_m4_m4(mat, pchan->pose_mat);
810  }
811 
812  /* OPEN_SIM_COMPATIBILITY
813  * AFAIK animation to second life is via BVH, but no
814  * reason to not have the collada-animation be correct */
815  if (for_opensim) {
816  float temp[4][4];
817  copy_m4_m4(temp, bone->arm_mat);
818  temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
819  invert_m4(temp);
820 
821  mul_m4_m4m4(mat, mat, temp);
822 
823  if (bone->parent) {
824  copy_m4_m4(temp, bone->parent->arm_mat);
825  temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
826 
827  mul_m4_m4m4(mat, temp, mat);
828  }
829  }
830  bc_enable_fcurves(action, nullptr);
831  return true;
832 }
833 
835 {
836  static float MIN_DISTANCE = 0.00001;
837 
838  if (values.size() < 2) {
839  return false; /* need at least 2 entries to be not flat */
840  }
841 
842  BCMatrixSampleMap::iterator it;
843  const BCMatrix *refmat = nullptr;
844  for (it = values.begin(); it != values.end(); ++it) {
845  const BCMatrix *matrix = it->second;
846 
847  if (refmat == nullptr) {
848  refmat = matrix;
849  continue;
850  }
851 
852  if (!matrix->in_range(*refmat, MIN_DISTANCE)) {
853  return true;
854  }
855  }
856  return false;
857 }
858 
860 {
861  /* Check for object, light and camera transform animations */
862  if ((bc_getSceneObjectAction(ob) && bc_getSceneObjectAction(ob)->curves.first) ||
865  return true;
866  }
867 
868  /* Check Material Effect parameter animations. */
869  for (int a = 0; a < ob->totcol; a++) {
870  Material *ma = BKE_object_material_get(ob, a + 1);
871  if (!ma) {
872  continue;
873  }
874  if (ma->adt && ma->adt->action && ma->adt->action->curves.first) {
875  return true;
876  }
877  }
878 
879  Key *key = BKE_key_from_object(ob);
880  if ((key && key->adt && key->adt->action) && key->adt->action->curves.first) {
881  return true;
882  }
883 
884  return false;
885 }
886 
887 bool bc_has_animations(Scene *sce, LinkNode *export_set)
888 {
889  LinkNode *node;
890  if (export_set) {
891  for (node = export_set; node; node = node->next) {
892  Object *ob = (Object *)node->link;
893 
894  if (bc_has_animations(ob)) {
895  return true;
896  }
897  }
898  }
899  return false;
900 }
901 
902 void bc_add_global_transform(Matrix &to_mat,
903  const Matrix &from_mat,
904  const BCMatrix &global_transform,
905  const bool invert)
906 {
907  copy_m4_m4(to_mat, from_mat);
908  bc_add_global_transform(to_mat, global_transform, invert);
909 }
910 
911 void bc_add_global_transform(Vector &to_vec,
912  const Vector &from_vec,
913  const BCMatrix &global_transform,
914  const bool invert)
915 {
916  copy_v3_v3(to_vec, from_vec);
917  bc_add_global_transform(to_vec, global_transform, invert);
918 }
919 
920 void bc_add_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
921 {
922  BCMatrix mat(to_mat);
923  mat.add_transform(global_transform, invert);
924  mat.get_matrix(to_mat);
925 }
926 
927 void bc_add_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert)
928 {
929  Matrix mat;
930  Vector from_vec;
931  copy_v3_v3(from_vec, to_vec);
932  global_transform.get_matrix(mat, false, 6, invert);
933  mul_v3_m4v3(to_vec, mat, from_vec);
934 }
935 
936 void bc_apply_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
937 {
938  BCMatrix mat(to_mat);
939  mat.apply_transform(global_transform, invert);
940  mat.get_matrix(to_mat);
941 }
942 
943 void bc_apply_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert)
944 {
945  Matrix transform;
946  global_transform.get_matrix(transform);
947  mul_v3_m4v3(to_vec, transform, to_vec);
948 }
949 
950 void bc_create_restpose_mat(BCExportSettings &export_settings,
951  Bone *bone,
952  float to_mat[4][4],
953  float from_mat[4][4],
954  bool use_local_space)
955 {
956  float loc[3];
957  float rot[3];
958  float scale[3];
959  static const float V0[3] = {0, 0, 0};
960 
961  if (!has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_loc") &&
962  !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_rot") &&
963  !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_scale")) {
964  /* No need */
965  copy_m4_m4(to_mat, from_mat);
966  return;
967  }
968 
969  bc_decompose(from_mat, loc, rot, nullptr, scale);
970  loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
971 
972  if (export_settings.get_keep_bind_info()) {
973  bc_get_property_vector(bone, "restpose_loc", loc, loc);
974 
975  if (use_local_space && bone->parent) {
976  Bone *b = bone;
977  while (b->parent) {
978  b = b->parent;
979  float ploc[3];
980  bc_get_property_vector(b, "restpose_loc", ploc, V0);
981  loc[0] += ploc[0];
982  loc[1] += ploc[1];
983  loc[2] += ploc[2];
984  }
985  }
986  }
987 
988  if (export_settings.get_keep_bind_info()) {
989  if (bc_get_IDProperty(bone, "restpose_rot_x")) {
990  rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
991  }
992  if (bc_get_IDProperty(bone, "restpose_rot_y")) {
993  rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
994  }
995  if (bc_get_IDProperty(bone, "restpose_rot_z")) {
996  rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
997  }
998  }
999 
1000  if (export_settings.get_keep_bind_info()) {
1001  bc_get_property_vector(bone, "restpose_scale", scale, scale);
1002  }
1003 
1004  loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
1005 }
1006 
1007 void bc_sanitize_v3(float v[3], int precision)
1008 {
1009  for (int i = 0; i < 3; i++) {
1010  double val = (double)v[i];
1011  val = double_round(val, precision);
1012  v[i] = (float)val;
1013  }
1014 }
1015 
1016 void bc_sanitize_v3(double v[3], int precision)
1017 {
1018  for (int i = 0; i < 3; i++) {
1019  v[i] = double_round(v[i], precision);
1020  }
1021 }
1022 
1023 void bc_copy_m4_farray(float r[4][4], float *a)
1024 {
1025  for (int i = 0; i < 4; i++) {
1026  for (int j = 0; j < 4; j++) {
1027  r[i][j] = *a++;
1028  }
1029  }
1030 }
1031 
1032 void bc_copy_farray_m4(float *r, float a[4][4])
1033 {
1034  for (int i = 0; i < 4; i++) {
1035  for (int j = 0; j < 4; j++) {
1036  *r++ = a[i][j];
1037  }
1038  }
1039 }
1040 
1041 void bc_copy_darray_m4d(double *r, double a[4][4])
1042 {
1043  for (int i = 0; i < 4; i++) {
1044  for (int j = 0; j < 4; j++) {
1045  *r++ = a[i][j];
1046  }
1047  }
1048 }
1049 
1050 void bc_copy_v44_m4d(std::vector<std::vector<double>> &r, double (&a)[4][4])
1051 {
1052  for (int i = 0; i < 4; i++) {
1053  for (int j = 0; j < 4; j++) {
1054  r[i][j] = a[i][j];
1055  }
1056  }
1057 }
1058 
1059 void bc_copy_m4d_v44(double (&r)[4][4], std::vector<std::vector<double>> &a)
1060 {
1061  for (int i = 0; i < 4; i++) {
1062  for (int j = 0; j < 4; j++) {
1063  r[i][j] = a[i][j];
1064  }
1065  }
1066 }
1067 
1071 static std::string bc_get_active_uvlayer_name(Mesh *me)
1072 {
1073  int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
1074  if (num_layers) {
1075  char *layer_name = bc_CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV);
1076  if (layer_name) {
1077  return std::string(layer_name);
1078  }
1079  }
1080  return "";
1081 }
1082 
1087 static std::string bc_get_active_uvlayer_name(Object *ob)
1088 {
1089  Mesh *me = (Mesh *)ob->data;
1090  return bc_get_active_uvlayer_name(me);
1091 }
1092 
1096 static std::string bc_get_uvlayer_name(Mesh *me, int layer)
1097 {
1098  int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
1099  if (num_layers && layer < num_layers) {
1100  char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, layer);
1101  if (layer_name) {
1102  return std::string(layer_name);
1103  }
1104  }
1105  return "";
1106 }
1107 
1109 {
1110  if (ma->nodetree == nullptr) {
1111  ma->nodetree = ntreeAddTree(nullptr, "Shader Nodetree", "ShaderNodeTree");
1112  ma->use_nodes = true;
1113  }
1114  return ma->nodetree;
1115 }
1116 
1118  bContext *C, bNodeTree *ntree, int node_type, int locx, int locy, std::string label)
1119 {
1120  bNode *node = nodeAddStaticNode(C, ntree, node_type);
1121  if (node) {
1122  if (label.length() > 0) {
1123  strcpy(node->label, label.c_str());
1124  }
1125  node->locx = locx;
1126  node->locy = locy;
1127  node->flag |= NODE_SELECT;
1128  }
1129  return node;
1130 }
1131 
1132 static bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy)
1133 {
1134  return bc_add_node(C, ntree, node_type, locx, locy, "");
1135 }
1136 
1137 #if 0
1138 /* experimental, probably not used */
1139 static bNodeSocket *bc_group_add_input_socket(bNodeTree *ntree,
1140  bNode *to_node,
1141  int to_index,
1142  std::string label)
1143 {
1144  bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
1145 
1146 # if 0
1147  bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1148  return socket;
1149 # endif
1150 
1151  bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1152  bNode *inputGroup = ntreeFindType(ntree, NODE_GROUP_INPUT);
1153  node_group_input_verify(ntree, inputGroup, (ID *)ntree);
1154  bNodeSocket *newsock = node_group_input_find_socket(inputGroup, gsock->identifier);
1155  nodeAddLink(ntree, inputGroup, newsock, to_node, to_socket);
1156  strcpy(newsock->name, label.c_str());
1157  return newsock;
1158 }
1159 
1160 static bNodeSocket *bc_group_add_output_socket(bNodeTree *ntree,
1161  bNode *from_node,
1162  int from_index,
1163  std::string label)
1164 {
1165  bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
1166 
1167 # if 0
1168  bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1169  return socket;
1170 # endif
1171 
1172  bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, from_node, from_socket);
1173  bNode *outputGroup = ntreeFindType(ntree, NODE_GROUP_OUTPUT);
1174  node_group_output_verify(ntree, outputGroup, (ID *)ntree);
1175  bNodeSocket *newsock = node_group_output_find_socket(outputGroup, gsock->identifier);
1176  nodeAddLink(ntree, from_node, from_socket, outputGroup, newsock);
1177  strcpy(newsock->name, label.c_str());
1178  return newsock;
1179 }
1180 
1181 void bc_make_group(bContext *C, bNodeTree *ntree, std::map<std::string, bNode *> nmap)
1182 {
1183  bNode *gnode = node_group_make_from_selected(C, ntree, "ShaderNodeGroup", "ShaderNodeTree");
1184  bNodeTree *gtree = (bNodeTree *)gnode->id;
1185 
1186  bc_group_add_input_socket(gtree, nmap["main"], 0, "Diffuse");
1187  bc_group_add_input_socket(gtree, nmap["emission"], 0, "Emission");
1188  bc_group_add_input_socket(gtree, nmap["mix"], 0, "Transparency");
1189  bc_group_add_input_socket(gtree, nmap["emission"], 1, "Emission");
1190  bc_group_add_input_socket(gtree, nmap["main"], 4, "Metallic");
1191  bc_group_add_input_socket(gtree, nmap["main"], 5, "Specular");
1192 
1193  bc_group_add_output_socket(gtree, nmap["mix"], 0, "Shader");
1194 }
1195 #endif
1196 
1197 static void bc_node_add_link(
1198  bNodeTree *ntree, bNode *from_node, int from_index, bNode *to_node, int to_index)
1199 {
1200  bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
1201  bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
1202 
1203  nodeAddLink(ntree, from_node, from_socket, to_node, to_socket);
1204 }
1205 
1207 {
1209  std::map<std::string, bNode *> nmap;
1210 #if 0
1211  nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300);
1212  nmap["emission"] = bc_add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission");
1213  nmap["add"] = bc_add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400);
1214  nmap["transparent"] = bc_add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200);
1215  nmap["mix"] = bc_add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency");
1216  nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300);
1217  nmap["out"]->flag &= ~NODE_SELECT;
1218 
1219  bc_node_add_link(ntree, nmap["emission"], 0, nmap["add"], 0);
1220  bc_node_add_link(ntree, nmap["main"], 0, nmap["add"], 1);
1221  bc_node_add_link(ntree, nmap["add"], 0, nmap["mix"], 1);
1222  bc_node_add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2);
1223 
1224  bc_node_add_link(ntree, nmap["mix"], 0, nmap["out"], 0);
1225  /* experimental, probably not used. */
1226  bc_make_group(C, ntree, nmap);
1227 #else
1228  nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, 0, 300);
1229  nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 300, 300);
1230  bc_node_add_link(ntree, nmap["main"], 0, nmap["out"], 0);
1231 #endif
1232 }
1233 
1234 COLLADASW::ColorOrTexture bc_get_base_color(Material *ma)
1235 {
1236  /* for alpha see bc_get_alpha() */
1237  Color default_color = {ma->r, ma->g, ma->b, 1.0};
1238  bNode *shader = bc_get_master_shader(ma);
1239  if (ma->use_nodes && shader) {
1240  return bc_get_cot_from_shader(shader, "Base Color", default_color, false);
1241  }
1242 
1243  return bc_get_cot(default_color);
1244 }
1245 
1246 COLLADASW::ColorOrTexture bc_get_emission(Material *ma)
1247 {
1248  Color default_color = {0, 0, 0, 1}; /* default black */
1249  bNode *shader = bc_get_master_shader(ma);
1250  if (!(ma->use_nodes && shader)) {
1251  return bc_get_cot(default_color);
1252  }
1253 
1254  double emission_strength = 0.0;
1255  bc_get_float_from_shader(shader, emission_strength, "Emission Strength");
1256  if (emission_strength == 0.0) {
1257  return bc_get_cot(default_color);
1258  }
1259 
1260  COLLADASW::ColorOrTexture cot = bc_get_cot_from_shader(shader, "Emission", default_color);
1261 
1262  /* If using texture, emission strength is not supported. */
1263  COLLADASW::Color col = cot.getColor();
1264  double final_color[3] = {col.getRed(), col.getGreen(), col.getBlue()};
1265  mul_v3db_db(final_color, emission_strength);
1266 
1267  /* Collada does not support HDR colors, so clamp to 1 keeping channels proportional. */
1268  double max_color = fmax(fmax(final_color[0], final_color[1]), final_color[2]);
1269  if (max_color > 1.0) {
1270  mul_v3db_db(final_color, 1.0 / max_color);
1271  }
1272 
1273  cot.getColor().set(final_color[0], final_color[1], final_color[2], col.getAlpha());
1274 
1275  return cot;
1276 }
1277 
1278 COLLADASW::ColorOrTexture bc_get_ambient(Material *ma)
1279 {
1280  Color default_color = {0, 0, 0, 1.0};
1281  return bc_get_cot(default_color);
1282 }
1283 
1284 COLLADASW::ColorOrTexture bc_get_specular(Material *ma)
1285 {
1286  Color default_color = {0, 0, 0, 1.0};
1287  return bc_get_cot(default_color);
1288 }
1289 
1290 COLLADASW::ColorOrTexture bc_get_reflective(Material *ma)
1291 {
1292  Color default_color = {0, 0, 0, 1.0};
1293  return bc_get_cot(default_color);
1294 }
1295 
1297 {
1298  double alpha = ma->a; /* fallback if no socket found */
1299  bNode *master_shader = bc_get_master_shader(ma);
1300  if (ma->use_nodes && master_shader) {
1301  bc_get_float_from_shader(master_shader, alpha, "Alpha");
1302  }
1303  return alpha;
1304 }
1305 
1307 {
1308  double ior = -1; /* fallback if no socket found */
1309  bNode *master_shader = bc_get_master_shader(ma);
1310  if (ma->use_nodes && master_shader) {
1311  bc_get_float_from_shader(master_shader, ior, "IOR");
1312  }
1313  return ior;
1314 }
1315 
1317 {
1318  double ior = -1; /* fallback if no socket found */
1319  bNode *master_shader = bc_get_master_shader(ma);
1320  if (ma->use_nodes && master_shader) {
1321  bc_get_float_from_shader(master_shader, ior, "Roughness");
1322  }
1323  return ior;
1324 }
1325 
1327 {
1328  double reflectivity = ma->spec; /* fallback if no socket found */
1329  bNode *master_shader = bc_get_master_shader(ma);
1330  if (ma->use_nodes && master_shader) {
1331  bc_get_float_from_shader(master_shader, reflectivity, "Metallic");
1332  }
1333  return reflectivity;
1334 }
1335 
1336 bool bc_get_float_from_shader(bNode *shader, double &val, std::string nodeid)
1337 {
1338  bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, nodeid.c_str());
1339  if (socket) {
1341  val = (double)ref->value;
1342  return true;
1343  }
1344  return false;
1345 }
1346 
1347 COLLADASW::ColorOrTexture bc_get_cot_from_shader(bNode *shader,
1348  std::string nodeid,
1349  Color &default_color,
1350  bool with_alpha)
1351 {
1352  bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, nodeid.c_str());
1353  if (socket) {
1355  float *col = dcol->value;
1356  return bc_get_cot(col, with_alpha);
1357  }
1358 
1359  return bc_get_cot(default_color, with_alpha);
1360 }
1361 
1363 {
1364  bNodeTree *nodetree = ma->nodetree;
1365  if (nodetree) {
1366  for (bNode *node = (bNode *)nodetree->nodes.first; node; node = node->next) {
1367  if (node->typeinfo->type == SH_NODE_BSDF_PRINCIPLED) {
1368  return node;
1369  }
1370  }
1371  }
1372  return nullptr;
1373 }
1374 
1375 COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a)
1376 {
1377  COLLADASW::Color color(r, g, b, a);
1378  COLLADASW::ColorOrTexture cot(color);
1379  return cot;
1380 }
1381 
1382 COLLADASW::ColorOrTexture bc_get_cot(Color col, bool with_alpha)
1383 {
1384  COLLADASW::Color color(col[0], col[1], col[2], (with_alpha) ? col[3] : 1.0);
1385  COLLADASW::ColorOrTexture cot(color);
1386  return cot;
1387 }
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)
#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