Blender  V2.93
collada_utils.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 /* COLLADABU_ASSERT, may be able to remove later */
22 #include "COLLADABUPlatform.h"
23 
24 #include "COLLADAFWGeometry.h"
25 #include "COLLADAFWMeshPrimitive.h"
26 #include "COLLADAFWMeshVertexData.h"
27 
28 #include <set>
29 #include <string>
30 
31 #include "MEM_guardedalloc.h"
32 
33 #include "DNA_armature_types.h"
34 #include "DNA_constraint_types.h"
35 #include "DNA_customdata_types.h"
36 #include "DNA_key_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41 
42 #include "BLI_linklist.h"
43 #include "BLI_listbase.h"
44 #include "BLI_math.h"
45 
46 #include "BKE_action.h"
47 #include "BKE_armature.h"
48 #include "BKE_constraint.h"
49 #include "BKE_context.h"
50 #include "BKE_customdata.h"
51 #include "BKE_global.h"
52 #include "BKE_key.h"
53 #include "BKE_layer.h"
54 #include "BKE_lib_id.h"
55 #include "BKE_material.h"
56 #include "BKE_mesh.h"
57 #include "BKE_mesh_runtime.h"
58 #include "BKE_node.h"
59 #include "BKE_object.h"
60 #include "BKE_scene.h"
61 
62 #include "ED_node.h"
63 #include "ED_object.h"
64 #include "ED_screen.h"
65 
66 #include "WM_api.h" /* XXX hrm, see if we can do without this */
67 #include "WM_types.h"
68 
69 #include "bmesh.h"
70 #include "bmesh_tools.h"
71 
72 #include "DEG_depsgraph.h"
73 #include "DEG_depsgraph_query.h"
74 #if 0
75 # include "NOD_common.h"
76 #endif
77 
78 #include "BlenderContext.h"
79 #include "ExportSettings.h"
80 #include "collada_utils.h"
81 
82 float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index)
83 {
84  if (index >= array.getValuesCount()) {
85  return 0.0f;
86  }
87 
88  if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT) {
89  return array.getFloatValues()->getData()[index];
90  }
91 
92  return array.getDoubleValues()->getData()[index];
93 }
94 
95 /* copied from /editors/object/object_relations.c */
97 {
98  /* test if 'ob' is a parent somewhere in par's parents */
99 
100  if (par == nullptr) {
101  return 0;
102  }
103  if (ob == par) {
104  return 1;
105  }
106 
107  return bc_test_parent_loop(par->parent, ob);
108 }
109 
111 {
113 
114  /* these we can skip completely (invalid constraints...) */
115  if (cti == nullptr) {
116  return false;
117  }
118  if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
119  return false;
120  }
121 
122  /* these constraints can't be evaluated anyway */
123  if (cti->evaluate_constraint == nullptr) {
124  return false;
125  }
126 
127  /* influence == 0 should be ignored */
128  if (con->enforce == 0.0f) {
129  return false;
130  }
131 
132  /* validation passed */
133  return true;
134 }
135 
136 bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
137 {
139  int partype = PAR_OBJECT;
140  const bool xmirror = false;
141  const bool keep_transform = false;
142 
143  if (par && is_parent_space) {
144  mul_m4_m4m4(ob->obmat, par->obmat, ob->obmat);
145  }
146 
147  bool ok = ED_object_parent_set(
148  nullptr, C, scene, ob, par, partype, xmirror, keep_transform, nullptr);
149  return ok;
150 }
151 
152 std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions)
153 {
154  std::vector<bAction *> actions;
155  if (all_actions) {
156  Main *bmain = CTX_data_main(C);
157  ID *id;
158 
159  for (id = (ID *)bmain->actions.first; id; id = (ID *)(id->next)) {
160  bAction *act = (bAction *)id;
161  /* XXX This currently creates too many actions.
162  * TODO Need to check if the action is compatible to the given object. */
163  actions.push_back(act);
164  }
165  }
166  else {
167  bAction *action = bc_getSceneObjectAction(ob);
168  actions.push_back(action);
169  }
170 
171  return actions;
172 }
173 
174 std::string bc_get_action_id(std::string action_name,
175  std::string ob_name,
176  std::string channel_type,
177  std::string axis_name,
178  std::string axis_separator)
179 {
180  std::string result = action_name + "_" + channel_type;
181  if (ob_name.length() > 0) {
182  result = ob_name + "_" + result;
183  }
184  if (axis_name.length() > 0) {
185  result += axis_separator + axis_name;
186  }
187  return translate_id(result);
188 }
189 
190 void bc_update_scene(BlenderContext &blender_context, float ctime)
191 {
192  Main *bmain = blender_context.get_main();
193  Scene *scene = blender_context.get_scene();
194  Depsgraph *depsgraph = blender_context.get_depsgraph();
195 
196  /* See remark in physics_fluid.c lines 395...) */
197  // BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
198  BKE_scene_frame_set(scene, ctime);
200 }
201 
202 Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
203 {
204  Object *ob = BKE_object_add_only_object(bmain, type, name);
205 
206  ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
208 
209  LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
210  BKE_collection_object_add(bmain, layer_collection->collection, ob);
211 
212  Base *base = BKE_view_layer_base_find(view_layer, ob);
213  /* TODO: is setting active needed? */
215 
216  return ob;
217 }
218 
219 Mesh *bc_get_mesh_copy(BlenderContext &blender_context,
220  Object *ob,
221  BC_export_mesh_type export_mesh_type,
222  bool apply_modifiers,
223  bool triangulate)
224 {
226  Mesh *tmpmesh = nullptr;
227  if (apply_modifiers) {
228 #if 0 /* Not supported by new system currently... */
229  switch (export_mesh_type) {
230  case BC_MESH_TYPE_VIEW: {
231  dm = mesh_create_derived_view(depsgraph, scene, ob, &mask);
232  break;
233  }
234  case BC_MESH_TYPE_RENDER: {
235  dm = mesh_create_derived_render(depsgraph, scene, ob, &mask);
236  break;
237  }
238  }
239 #else
240  Depsgraph *depsgraph = blender_context.get_depsgraph();
241  Scene *scene_eval = blender_context.get_evaluated_scene();
242  Object *ob_eval = blender_context.get_evaluated_object(ob);
243  tmpmesh = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &mask);
244 #endif
245  }
246  else {
247  tmpmesh = (Mesh *)ob->data;
248  }
249 
250  tmpmesh = (Mesh *)BKE_id_copy_ex(nullptr, &tmpmesh->id, nullptr, LIB_ID_COPY_LOCALIZE);
251 
252  if (triangulate) {
253  bc_triangulate_mesh(tmpmesh);
254  }
255  BKE_mesh_tessface_ensure(tmpmesh);
256  return tmpmesh;
257 }
258 
260 {
261  Object *ob_arm = nullptr;
262 
263  if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
264  ob_arm = ob->parent;
265  }
266  else {
267  ModifierData *mod;
268  for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
269  if (mod->type == eModifierType_Armature) {
270  ob_arm = ((ArmatureModifierData *)mod)->object;
271  }
272  }
273  }
274 
275  return ob_arm;
276 }
277 
278 bool bc_has_object_type(LinkNode *export_set, short obtype)
279 {
280  LinkNode *node;
281 
282  for (node = export_set; node; node = node->next) {
283  Object *ob = (Object *)node->link;
284  /* XXX - why is this checking for ob->data? - we could be looking for empties */
285  if (ob->type == obtype && ob->data) {
286  return true;
287  }
288  }
289  return false;
290 }
291 
292 /* Use bubble sort algorithm for sorting the export set */
294 {
295  bool sorted = false;
296  LinkNode *node;
297  for (node = export_set; node->next && !sorted; node = node->next) {
298 
299  sorted = true;
300 
301  LinkNode *current;
302  for (current = export_set; current->next; current = current->next) {
303  Object *a = (Object *)current->link;
304  Object *b = (Object *)current->next->link;
305 
306  if (strcmp(a->id.name, b->id.name) > 0) {
307  current->link = b;
308  current->next->link = a;
309  sorted = false;
310  }
311  }
312  }
313 }
314 
315 /* Check if a bone is the top most exportable bone in the bone hierarchy.
316  * When deform_bones_only == false, then only bones with NO parent
317  * can be root bones. Otherwise the top most deform bones in the hierarchy
318  * are root bones.
319  */
320 bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
321 {
322  if (deform_bones_only) {
323  Bone *root = nullptr;
324  Bone *bone = aBone;
325  while (bone) {
326  if (!(bone->flag & BONE_NO_DEFORM)) {
327  root = bone;
328  }
329  bone = bone->parent;
330  }
331  return (aBone == root);
332  }
333 
334  return !(aBone->parent);
335 }
336 
338 {
339  Mesh *me = (Mesh *)ob->data;
341 }
342 
343 std::string bc_url_encode(std::string data)
344 {
345  /* XXX We probably do not need to do a full encoding.
346  * But in case that is necessary,then it can be added here.
347  */
348  return bc_replace_string(data, "#", "%23");
349 }
350 
351 std::string bc_replace_string(std::string data,
352  const std::string &pattern,
353  const std::string &replacement)
354 {
355  size_t pos = 0;
356  while ((pos = data.find(pattern, pos)) != std::string::npos) {
357  data.replace(pos, pattern.length(), replacement);
358  pos += replacement.length();
359  }
360  return data;
361 }
362 
369 void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
370 {
371  if (scale_to_scene) {
372  mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat);
373  }
374  mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
375  BKE_object_apply_mat4(ob, ob->obmat, false, false);
376 }
377 
378 void bc_match_scale(std::vector<Object *> *objects_done,
379  UnitConverter &bc_unit,
380  bool scale_to_scene)
381 {
382  for (Object *ob : *objects_done) {
383  if (ob->parent == nullptr) {
384  bc_match_scale(ob, bc_unit, scale_to_scene);
385  }
386  }
387 }
388 
389 /*
390  * Convenience function to get only the needed components of a matrix
391  */
392 void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
393 {
394  if (size) {
395  mat4_to_size(size, mat);
396  }
397 
398  if (eul) {
399  mat4_to_eul(eul, mat);
400  }
401 
402  if (quat) {
403  mat4_to_quat(quat, mat);
404  }
405 
406  if (loc) {
407  copy_v3_v3(loc, mat[3]);
408  }
409 }
410 
411 /*
412  * Create rotation_quaternion from a delta rotation and a reference quat
413  *
414  * Input:
415  * mat_from: The rotation matrix before rotation
416  * mat_to : The rotation matrix after rotation
417  * qref : the quat corresponding to mat_from
418  *
419  * Output:
420  * rot : the calculated result (quaternion)
421  */
422 void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
423 {
424  float qd[4];
425  float matd[4][4];
426  float mati[4][4];
427  float mat_from[4][4];
428  quat_to_mat4(mat_from, quat_from);
429 
430  /* Calculate the difference matrix matd between mat_from and mat_to */
431  invert_m4_m4(mati, mat_from);
432  mul_m4_m4m4(matd, mati, mat_to);
433 
434  mat4_to_quat(qd, matd);
435 
436  mul_qt_qtqt(quat_to, qd, quat_from); /* rot is the final rotation corresponding to mat_to */
437 }
438 
440 {
441  bool use_beauty = false;
442  bool tag_only = false;
443 
444  /* XXX: The triangulation method selection could be offered in the UI. */
445  int quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE;
446 
447  const struct BMeshCreateParams bm_create_params = {0};
448  BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_create_params);
449  BMeshFromMeshParams bm_from_me_params = {0};
450  bm_from_me_params.calc_face_normal = true;
451  BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
452  BM_mesh_triangulate(bm, quad_method, use_beauty, 4, tag_only, nullptr, nullptr, nullptr);
453 
454  BMeshToMeshParams bm_to_me_params = {0};
455  bm_to_me_params.calc_object_remap = false;
456  BM_mesh_bm_to_me(nullptr, bm, me, &bm_to_me_params);
457  BM_mesh_free(bm);
458 }
459 
460 /*
461  * A bone is a leaf when it has no children or all children are not connected.
462  */
464 {
465  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
466  if (child->flag & BONE_CONNECTED) {
467  return false;
468  }
469  }
470  return true;
471 }
472 
473 EditBone *bc_get_edit_bone(bArmature *armature, char *name)
474 {
475  EditBone *eBone;
476 
477  for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
478  if (STREQ(name, eBone->name)) {
479  return eBone;
480  }
481  }
482 
483  return nullptr;
484 }
485 int bc_set_layer(int bitfield, int layer)
486 {
487  return bc_set_layer(bitfield, layer, true); /* enable */
488 }
489 
490 int bc_set_layer(int bitfield, int layer, bool enable)
491 {
492  int bit = 1u << layer;
493 
494  if (enable) {
495  bitfield |= bit;
496  }
497  else {
498  bitfield &= ~bit;
499  }
500 
501  return bitfield;
502 }
503 
510 {
511  std::string key = armature->id.name;
512  BoneExtensionMap *result = extended_bone_maps[key];
513  if (result == nullptr) {
514  result = new BoneExtensionMap();
515  extended_bone_maps[key] = result;
516  }
517  return *result;
518 }
519 
521 {
522  std::map<std::string, BoneExtensionMap *>::iterator map_it;
523  for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it) {
524  BoneExtensionMap *extended_bones = map_it->second;
525  for (auto &extended_bone : *extended_bones) {
526  delete extended_bone.second;
527  }
528  extended_bones->clear();
529  delete extended_bones;
530  }
531 }
532 
540 {
541  this->set_name(aBone->name);
542  this->chain_length = 0;
543  this->is_leaf = false;
544  this->tail[0] = 0.0f;
545  this->tail[1] = 0.5f;
546  this->tail[2] = 0.0f;
547  this->use_connect = -1;
548  this->roll = 0;
549  this->bone_layers = 0;
550 
551  this->has_custom_tail = false;
552  this->has_custom_roll = false;
553 }
554 
556 {
557  return name;
558 }
559 
560 void BoneExtended::set_name(char *aName)
561 {
562  BLI_strncpy(name, aName, MAXBONENAME);
563 }
564 
566 {
567  return chain_length;
568 }
569 
570 void BoneExtended::set_chain_length(const int aLength)
571 {
572  chain_length = aLength;
573 }
574 
576 {
577  is_leaf = state;
578 }
579 
581 {
582  return is_leaf;
583 }
584 
585 void BoneExtended::set_roll(float roll)
586 {
587  this->roll = roll;
588  this->has_custom_roll = true;
589 }
590 
592 {
593  return this->has_custom_roll;
594 }
595 
597 {
598  return this->roll;
599 }
600 
601 void BoneExtended::set_tail(const float vec[])
602 {
603  this->tail[0] = vec[0];
604  this->tail[1] = vec[1];
605  this->tail[2] = vec[2];
606  this->has_custom_tail = true;
607 }
608 
610 {
611  return this->has_custom_tail;
612 }
613 
615 {
616  return this->tail;
617 }
618 
619 inline bool isInteger(const std::string &s)
620 {
621  if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) {
622  return false;
623  }
624 
625  char *p;
626  strtol(s.c_str(), &p, 10);
627 
628  return (*p == 0);
629 }
630 
631 void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels)
632 {
633  std::stringstream ss(layerString);
634  std::string layer;
635  int pos;
636 
637  while (ss >> layer) {
638 
639  /* Blender uses numbers to specify layers*/
640  if (isInteger(layer)) {
641  pos = atoi(layer.c_str());
642  if (pos >= 0 && pos < 32) {
643  this->bone_layers = bc_set_layer(this->bone_layers, pos);
644  continue;
645  }
646  }
647 
648  /* layer uses labels (not supported by blender). Map to layer numbers:*/
649  pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin();
650  if (pos >= layer_labels.size()) {
651  layer_labels.push_back(layer); /* remember layer number for future usage*/
652  }
653 
654  if (pos > 31) {
655  fprintf(stderr,
656  "Too many layers in Import. Layer %s mapped to Blender layer 31\n",
657  layer.c_str());
658  pos = 31;
659  }
660 
661  /* If numeric layers and labeled layers are used in parallel (unlikely),
662  * we get a potential mixup. Just leave as is for now.
663  */
664  this->bone_layers = bc_set_layer(this->bone_layers, pos);
665  }
666 }
667 
668 std::string BoneExtended::get_bone_layers(int bitfield)
669 {
670  std::string sep;
671  int bit = 1u;
672 
673  std::ostringstream ss;
674  for (int i = 0; i < 32; i++) {
675  if (bit & bitfield) {
676  ss << sep << i;
677  sep = " ";
678  }
679  bit = bit << 1;
680  }
681  return ss.str();
682 }
683 
685 {
686  /* ensure that the bone is in at least one bone layer! */
687  return (bone_layers == 0) ? 1 : bone_layers;
688 }
689 
690 void BoneExtended::set_use_connect(int use_connect)
691 {
692  this->use_connect = use_connect;
693 }
694 
696 {
697  return this->use_connect;
698 }
699 
703 void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
704 {
705  IDProperty *idgroup = (IDProperty *)ebone->prop;
706  if (idgroup == nullptr) {
707  IDPropertyTemplate val = {0};
708  idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
709  ebone->prop = idgroup;
710  }
711 
712  IDPropertyTemplate val = {0};
713  val.array.len = 16;
714  val.array.type = IDP_FLOAT;
715 
716  IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
717  float *array = (float *)IDP_Array(data);
718  for (int i = 0; i < 4; i++) {
719  for (int j = 0; j < 4; j++) {
720  array[4 * i + j] = mat[i][j];
721  }
722  }
723 
724  IDP_AddToGroup(idgroup, data);
725 }
726 
727 #if 0
733 static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
734 {
735  if (ebone->prop == NULL) {
736  IDPropertyTemplate val = {0};
737  ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
738  }
739 
740  IDProperty *pgroup = (IDProperty *)ebone->prop;
741  IDPropertyTemplate val = {0};
742  IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
743  IDP_Float(prop) = value;
744  IDP_AddToGroup(pgroup, prop);
745 }
746 #endif
747 
752 IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
753 {
754  return (bone->prop == nullptr) ? nullptr : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
755 }
756 
761 float bc_get_property(Bone *bone, std::string key, float def)
762 {
763  float result = def;
764  IDProperty *property = bc_get_IDProperty(bone, key);
765  if (property) {
766  switch (property->type) {
767  case IDP_INT:
768  result = (float)(IDP_Int(property));
769  break;
770  case IDP_FLOAT:
771  result = (float)(IDP_Float(property));
772  break;
773  case IDP_DOUBLE:
774  result = (float)(IDP_Double(property));
775  break;
776  default:
777  result = def;
778  }
779  }
780  return result;
781 }
782 
791 bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
792 {
793  IDProperty *property = bc_get_IDProperty(bone, key);
794  if (property && property->type == IDP_ARRAY && property->len == 16) {
795  float *array = (float *)IDP_Array(property);
796  for (int i = 0; i < 4; i++) {
797  for (int j = 0; j < 4; j++) {
798  mat[i][j] = array[4 * i + j];
799  }
800  }
801  return true;
802  }
803  return false;
804 }
805 
809 void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
810 {
811  val[0] = bc_get_property(bone, key + "_x", def[0]);
812  val[1] = bc_get_property(bone, key + "_y", def[1]);
813  val[2] = bc_get_property(bone, key + "_z", def[2]);
814 }
815 
819 static bool has_custom_props(Bone *bone, bool enabled, std::string key)
820 {
821  if (!enabled) {
822  return false;
823  }
824 
825  return (bc_get_IDProperty(bone, key + "_x") || bc_get_IDProperty(bone, key + "_y") ||
826  bc_get_IDProperty(bone, key + "_z"));
827 }
828 
829 void bc_enable_fcurves(bAction *act, char *bone_name)
830 {
831  FCurve *fcu;
832  char prefix[200];
833 
834  if (bone_name) {
835  char bone_name_esc[sizeof(((Bone *)nullptr)->name) * 2];
836  BLI_str_escape(bone_name_esc, bone_name, sizeof(bone_name_esc));
837  BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name_esc);
838  }
839 
840  for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
841  if (bone_name) {
842  if (STREQLEN(fcu->rna_path, prefix, strlen(prefix))) {
843  fcu->flag &= ~FCURVE_DISABLED;
844  }
845  else {
846  fcu->flag |= FCURVE_DISABLED;
847  }
848  }
849  else {
850  fcu->flag &= ~FCURVE_DISABLED;
851  }
852  }
853 }
854 
855 bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim)
856 {
857 
858  /* Ok, lets be super cautious and check if the bone exists */
859  bPose *pose = ob->pose;
860  bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
861  if (!pchan) {
862  return false;
863  }
864 
865  bAction *action = bc_getSceneObjectAction(ob);
866  bPoseChannel *parchan = pchan->parent;
867 
868  bc_enable_fcurves(action, bone->name);
869  float ipar[4][4];
870 
871  if (bone->parent) {
872  invert_m4_m4(ipar, parchan->pose_mat);
873  mul_m4_m4m4(mat, ipar, pchan->pose_mat);
874  }
875  else {
876  copy_m4_m4(mat, pchan->pose_mat);
877  }
878 
879  /* OPEN_SIM_COMPATIBILITY
880  * AFAIK animation to second life is via BVH, but no
881  * reason to not have the collada-animation be correct */
882  if (for_opensim) {
883  float temp[4][4];
884  copy_m4_m4(temp, bone->arm_mat);
885  temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
886  invert_m4(temp);
887 
888  mul_m4_m4m4(mat, mat, temp);
889 
890  if (bone->parent) {
891  copy_m4_m4(temp, bone->parent->arm_mat);
892  temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
893 
894  mul_m4_m4m4(mat, temp, mat);
895  }
896  }
897  bc_enable_fcurves(action, nullptr);
898  return true;
899 }
900 
902 {
903  static float MIN_DISTANCE = 0.00001;
904 
905  if (values.size() < 2) {
906  return false; /* need at least 2 entries to be not flat */
907  }
908 
909  BCMatrixSampleMap::iterator it;
910  const BCMatrix *refmat = nullptr;
911  for (it = values.begin(); it != values.end(); ++it) {
912  const BCMatrix *matrix = it->second;
913 
914  if (refmat == nullptr) {
915  refmat = matrix;
916  continue;
917  }
918 
919  if (!matrix->in_range(*refmat, MIN_DISTANCE)) {
920  return true;
921  }
922  }
923  return false;
924 }
925 
927 {
928  /* Check for object, light and camera transform animations */
929  if ((bc_getSceneObjectAction(ob) && bc_getSceneObjectAction(ob)->curves.first) ||
930  (bc_getSceneLightAction(ob) && bc_getSceneLightAction(ob)->curves.first) ||
931  (bc_getSceneCameraAction(ob) && bc_getSceneCameraAction(ob)->curves.first)) {
932  return true;
933  }
934 
935  /* Check Material Effect parameter animations. */
936  for (int a = 0; a < ob->totcol; a++) {
937  Material *ma = BKE_object_material_get(ob, a + 1);
938  if (!ma) {
939  continue;
940  }
941  if (ma->adt && ma->adt->action && ma->adt->action->curves.first) {
942  return true;
943  }
944  }
945 
946  Key *key = BKE_key_from_object(ob);
947  if ((key && key->adt && key->adt->action) && key->adt->action->curves.first) {
948  return true;
949  }
950 
951  return false;
952 }
953 
954 bool bc_has_animations(Scene *sce, LinkNode *export_set)
955 {
956  LinkNode *node;
957  if (export_set) {
958  for (node = export_set; node; node = node->next) {
959  Object *ob = (Object *)node->link;
960 
961  if (bc_has_animations(ob)) {
962  return true;
963  }
964  }
965  }
966  return false;
967 }
968 
969 void bc_add_global_transform(Matrix &to_mat,
970  const Matrix &from_mat,
971  const BCMatrix &global_transform,
972  const bool invert)
973 {
974  copy_m4_m4(to_mat, from_mat);
975  bc_add_global_transform(to_mat, global_transform, invert);
976 }
977 
978 void bc_add_global_transform(Vector &to_vec,
979  const Vector &from_vec,
980  const BCMatrix &global_transform,
981  const bool invert)
982 {
983  copy_v3_v3(to_vec, from_vec);
984  bc_add_global_transform(to_vec, global_transform, invert);
985 }
986 
987 void bc_add_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
988 {
989  BCMatrix mat(to_mat);
990  mat.add_transform(global_transform, invert);
991  mat.get_matrix(to_mat);
992 }
993 
994 void bc_add_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert)
995 {
996  Matrix mat;
997  Vector from_vec;
998  copy_v3_v3(from_vec, to_vec);
999  global_transform.get_matrix(mat, false, 6, invert);
1000  mul_v3_m4v3(to_vec, mat, from_vec);
1001 }
1002 
1003 void bc_apply_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
1004 {
1005  BCMatrix mat(to_mat);
1006  mat.apply_transform(global_transform, invert);
1007  mat.get_matrix(to_mat);
1008 }
1009 
1010 void bc_apply_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert)
1011 {
1012  Matrix transform;
1013  global_transform.get_matrix(transform);
1014  mul_v3_m4v3(to_vec, transform, to_vec);
1015 }
1016 
1023 void bc_create_restpose_mat(BCExportSettings &export_settings,
1024  Bone *bone,
1025  float to_mat[4][4],
1026  float from_mat[4][4],
1027  bool use_local_space)
1028 {
1029  float loc[3];
1030  float rot[3];
1031  float scale[3];
1032  static const float V0[3] = {0, 0, 0};
1033 
1034  if (!has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_loc") &&
1035  !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_rot") &&
1036  !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_scale")) {
1037  /* No need */
1038  copy_m4_m4(to_mat, from_mat);
1039  return;
1040  }
1041 
1042  bc_decompose(from_mat, loc, rot, nullptr, scale);
1043  loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
1044 
1045  if (export_settings.get_keep_bind_info()) {
1046  bc_get_property_vector(bone, "restpose_loc", loc, loc);
1047 
1048  if (use_local_space && bone->parent) {
1049  Bone *b = bone;
1050  while (b->parent) {
1051  b = b->parent;
1052  float ploc[3];
1053  bc_get_property_vector(b, "restpose_loc", ploc, V0);
1054  loc[0] += ploc[0];
1055  loc[1] += ploc[1];
1056  loc[2] += ploc[2];
1057  }
1058  }
1059  }
1060 
1061  if (export_settings.get_keep_bind_info()) {
1062  if (bc_get_IDProperty(bone, "restpose_rot_x")) {
1063  rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
1064  }
1065  if (bc_get_IDProperty(bone, "restpose_rot_y")) {
1066  rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
1067  }
1068  if (bc_get_IDProperty(bone, "restpose_rot_z")) {
1069  rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
1070  }
1071  }
1072 
1073  if (export_settings.get_keep_bind_info()) {
1074  bc_get_property_vector(bone, "restpose_scale", scale, scale);
1075  }
1076 
1077  loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
1078 }
1079 
1080 void bc_sanitize_v3(float v[3], int precision)
1081 {
1082  for (int i = 0; i < 3; i++) {
1083  double val = (double)v[i];
1084  val = double_round(val, precision);
1085  v[i] = (float)val;
1086  }
1087 }
1088 
1089 void bc_sanitize_v3(double v[3], int precision)
1090 {
1091  for (int i = 0; i < 3; i++) {
1092  v[i] = double_round(v[i], precision);
1093  }
1094 }
1095 
1096 void bc_copy_m4_farray(float r[4][4], float *a)
1097 {
1098  for (int i = 0; i < 4; i++) {
1099  for (int j = 0; j < 4; j++) {
1100  r[i][j] = *a++;
1101  }
1102  }
1103 }
1104 
1105 void bc_copy_farray_m4(float *r, float a[4][4])
1106 {
1107  for (int i = 0; i < 4; i++) {
1108  for (int j = 0; j < 4; j++) {
1109  *r++ = a[i][j];
1110  }
1111  }
1112 }
1113 
1114 void bc_copy_darray_m4d(double *r, double a[4][4])
1115 {
1116  for (int i = 0; i < 4; i++) {
1117  for (int j = 0; j < 4; j++) {
1118  *r++ = a[i][j];
1119  }
1120  }
1121 }
1122 
1123 void bc_copy_v44_m4d(std::vector<std::vector<double>> &r, double (&a)[4][4])
1124 {
1125  for (int i = 0; i < 4; i++) {
1126  for (int j = 0; j < 4; j++) {
1127  r[i][j] = a[i][j];
1128  }
1129  }
1130 }
1131 
1132 void bc_copy_m4d_v44(double (&r)[4][4], std::vector<std::vector<double>> &a)
1133 {
1134  for (int i = 0; i < 4; i++) {
1135  for (int j = 0; j < 4; j++) {
1136  r[i][j] = a[i][j];
1137  }
1138  }
1139 }
1140 
1144 static std::string bc_get_active_uvlayer_name(Mesh *me)
1145 {
1146  int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
1147  if (num_layers) {
1148  char *layer_name = bc_CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV);
1149  if (layer_name) {
1150  return std::string(layer_name);
1151  }
1152  }
1153  return "";
1154 }
1155 
1160 static std::string bc_get_active_uvlayer_name(Object *ob)
1161 {
1162  Mesh *me = (Mesh *)ob->data;
1163  return bc_get_active_uvlayer_name(me);
1164 }
1165 
1169 static std::string bc_get_uvlayer_name(Mesh *me, int layer)
1170 {
1171  int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
1172  if (num_layers && layer < num_layers) {
1173  char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, layer);
1174  if (layer_name) {
1175  return std::string(layer_name);
1176  }
1177  }
1178  return "";
1179 }
1180 
1182 {
1183  if (ma->nodetree == nullptr) {
1184  ma->nodetree = ntreeAddTree(nullptr, "Shader Nodetree", "ShaderNodeTree");
1185  ma->use_nodes = true;
1186  }
1187  return ma->nodetree;
1188 }
1189 
1191  bContext *C, bNodeTree *ntree, int node_type, int locx, int locy, std::string label)
1192 {
1193  bNode *node = nodeAddStaticNode(C, ntree, node_type);
1194  if (node) {
1195  if (label.length() > 0) {
1196  strcpy(node->label, label.c_str());
1197  }
1198  node->locx = locx;
1199  node->locy = locy;
1200  node->flag |= NODE_SELECT;
1201  }
1202  return node;
1203 }
1204 
1205 static bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy)
1206 {
1207  return bc_add_node(C, ntree, node_type, locx, locy, "");
1208 }
1209 
1210 #if 0
1211 /* experimental, probably not used */
1212 static bNodeSocket *bc_group_add_input_socket(bNodeTree *ntree,
1213  bNode *to_node,
1214  int to_index,
1215  std::string label)
1216 {
1217  bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
1218 
1219  //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1220  //return socket;
1221 
1222  bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1223  bNode *inputGroup = ntreeFindType(ntree, NODE_GROUP_INPUT);
1224  node_group_input_verify(ntree, inputGroup, (ID *)ntree);
1225  bNodeSocket *newsock = node_group_input_find_socket(inputGroup, gsock->identifier);
1226  nodeAddLink(ntree, inputGroup, newsock, to_node, to_socket);
1227  strcpy(newsock->name, label.c_str());
1228  return newsock;
1229 }
1230 
1231 static bNodeSocket *bc_group_add_output_socket(bNodeTree *ntree,
1232  bNode *from_node,
1233  int from_index,
1234  std::string label)
1235 {
1236  bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
1237 
1238  //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1239  //return socket;
1240 
1241  bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, from_node, from_socket);
1242  bNode *outputGroup = ntreeFindType(ntree, NODE_GROUP_OUTPUT);
1243  node_group_output_verify(ntree, outputGroup, (ID *)ntree);
1244  bNodeSocket *newsock = node_group_output_find_socket(outputGroup, gsock->identifier);
1245  nodeAddLink(ntree, from_node, from_socket, outputGroup, newsock);
1246  strcpy(newsock->name, label.c_str());
1247  return newsock;
1248 }
1249 
1250 void bc_make_group(bContext *C, bNodeTree *ntree, std::map<std::string, bNode *> nmap)
1251 {
1252  bNode *gnode = node_group_make_from_selected(C, ntree, "ShaderNodeGroup", "ShaderNodeTree");
1253  bNodeTree *gtree = (bNodeTree *)gnode->id;
1254 
1255  bc_group_add_input_socket(gtree, nmap["main"], 0, "Diffuse");
1256  bc_group_add_input_socket(gtree, nmap["emission"], 0, "Emission");
1257  bc_group_add_input_socket(gtree, nmap["mix"], 0, "Transparency");
1258  bc_group_add_input_socket(gtree, nmap["emission"], 1, "Emission");
1259  bc_group_add_input_socket(gtree, nmap["main"], 4, "Metallic");
1260  bc_group_add_input_socket(gtree, nmap["main"], 5, "Specular");
1261 
1262  bc_group_add_output_socket(gtree, nmap["mix"], 0, "Shader");
1263 }
1264 #endif
1265 
1266 static void bc_node_add_link(
1267  bNodeTree *ntree, bNode *from_node, int from_index, bNode *to_node, int to_index)
1268 {
1269  bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
1270  bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
1271 
1272  nodeAddLink(ntree, from_node, from_socket, to_node, to_socket);
1273 }
1274 
1276 {
1278  std::map<std::string, bNode *> nmap;
1279 #if 0
1280  nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300);
1281  nmap["emission"] = bc_add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission");
1282  nmap["add"] = bc_add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400);
1283  nmap["transparent"] = bc_add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200);
1284  nmap["mix"] = bc_add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency");
1285  nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300);
1286  nmap["out"]->flag &= ~NODE_SELECT;
1287 
1288  bc_node_add_link(ntree, nmap["emission"], 0, nmap["add"], 0);
1289  bc_node_add_link(ntree, nmap["main"], 0, nmap["add"], 1);
1290  bc_node_add_link(ntree, nmap["add"], 0, nmap["mix"], 1);
1291  bc_node_add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2);
1292 
1293  bc_node_add_link(ntree, nmap["mix"], 0, nmap["out"], 0);
1294  /* experimental, probably not used. */
1295  bc_make_group(C, ntree, nmap);
1296 #else
1297  nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, 0, 300);
1298  nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 300, 300);
1299  bc_node_add_link(ntree, nmap["main"], 0, nmap["out"], 0);
1300 #endif
1301 }
1302 
1303 COLLADASW::ColorOrTexture bc_get_base_color(Material *ma)
1304 {
1305  /* for alpha see bc_get_alpha() */
1306  Color default_color = {ma->r, ma->g, ma->b, 1.0};
1308  if (ma->use_nodes && shader) {
1309  return bc_get_cot_from_shader(shader, "Base Color", default_color, false);
1310  }
1311 
1312  return bc_get_cot(default_color);
1313 }
1314 
1315 COLLADASW::ColorOrTexture bc_get_emission(Material *ma)
1316 {
1317  Color default_color = {0, 0, 0, 1}; /* default black */
1319  if (!(ma->use_nodes && shader)) {
1320  return bc_get_cot(default_color);
1321  }
1322 
1323  double emission_strength = 0.0;
1324  bc_get_float_from_shader(shader, emission_strength, "Emission Strength");
1325  if (emission_strength == 0.0) {
1326  return bc_get_cot(default_color);
1327  }
1328 
1329  COLLADASW::ColorOrTexture cot = bc_get_cot_from_shader(shader, "Emission", default_color);
1330 
1331  /* If using texture, emission strength is not supported. */
1332  COLLADASW::Color col = cot.getColor();
1333  double final_color[3] = {col.getRed(), col.getGreen(), col.getBlue()};
1334  mul_v3db_db(final_color, emission_strength);
1335 
1336  /* Collada does not support HDR colors, so clamp to 1 keeping channels proportional. */
1337  double max_color = fmax(fmax(final_color[0], final_color[1]), final_color[2]);
1338  if (max_color > 1.0) {
1339  mul_v3db_db(final_color, 1.0 / max_color);
1340  }
1341 
1342  cot.getColor().set(final_color[0], final_color[1], final_color[2], col.getAlpha());
1343 
1344  return cot;
1345 }
1346 
1347 COLLADASW::ColorOrTexture bc_get_ambient(Material *ma)
1348 {
1349  Color default_color = {0, 0, 0, 1.0};
1350  return bc_get_cot(default_color);
1351 }
1352 
1353 COLLADASW::ColorOrTexture bc_get_specular(Material *ma)
1354 {
1355  Color default_color = {0, 0, 0, 1.0};
1356  return bc_get_cot(default_color);
1357 }
1358 
1359 COLLADASW::ColorOrTexture bc_get_reflective(Material *ma)
1360 {
1361  Color default_color = {0, 0, 0, 1.0};
1362  return bc_get_cot(default_color);
1363 }
1364 
1366 {
1367  double alpha = ma->a; /* fallback if no socket found */
1368  bNode *master_shader = bc_get_master_shader(ma);
1369  if (ma->use_nodes && master_shader) {
1370  bc_get_float_from_shader(master_shader, alpha, "Alpha");
1371  }
1372  return alpha;
1373 }
1374 
1376 {
1377  double ior = -1; /* fallback if no socket found */
1378  bNode *master_shader = bc_get_master_shader(ma);
1379  if (ma->use_nodes && master_shader) {
1380  bc_get_float_from_shader(master_shader, ior, "IOR");
1381  }
1382  return ior;
1383 }
1384 
1386 {
1387  double ior = -1; /* fallback if no socket found */
1388  bNode *master_shader = bc_get_master_shader(ma);
1389  if (ma->use_nodes && master_shader) {
1390  bc_get_float_from_shader(master_shader, ior, "Roughness");
1391  }
1392  return ior;
1393 }
1394 
1396 {
1397  double reflectivity = ma->spec; /* fallback if no socket found */
1398  bNode *master_shader = bc_get_master_shader(ma);
1399  if (ma->use_nodes && master_shader) {
1400  bc_get_float_from_shader(master_shader, reflectivity, "Metallic");
1401  }
1402  return reflectivity;
1403 }
1404 
1405 bool bc_get_float_from_shader(bNode *shader, double &val, std::string nodeid)
1406 {
1407  bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, nodeid.c_str());
1408  if (socket) {
1410  val = (double)ref->value;
1411  return true;
1412  }
1413  return false;
1414 }
1415 
1416 COLLADASW::ColorOrTexture bc_get_cot_from_shader(bNode *shader,
1417  std::string nodeid,
1418  Color &default_color,
1419  bool with_alpha)
1420 {
1421  bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, nodeid.c_str());
1422  if (socket) {
1424  float *col = dcol->value;
1425  return bc_get_cot(col, with_alpha);
1426  }
1427 
1428  return bc_get_cot(default_color, with_alpha);
1429 }
1430 
1432 {
1433  bNodeTree *nodetree = ma->nodetree;
1434  if (nodetree) {
1435  for (bNode *node = (bNode *)nodetree->nodes.first; node; node = node->next) {
1436  if (node->typeinfo->type == SH_NODE_BSDF_PRINCIPLED) {
1437  return node;
1438  }
1439  }
1440  }
1441  return nullptr;
1442 }
1443 
1444 COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a)
1445 {
1446  COLLADASW::Color color(r, g, b, a);
1447  COLLADASW::ColorOrTexture cot(color);
1448  return cot;
1449 }
1450 
1451 COLLADASW::ColorOrTexture bc_get_cot(Color col, bool with_alpha)
1452 {
1453  COLLADASW::Color color(col[0], col[1], col[2], (with_alpha) ? col[3] : 1.0);
1454  COLLADASW::ColorOrTexture cot(color);
1455  return cot;
1456 }
typedef float(TangentPoint)[2]
std::map< int, const BCMatrix * > BCMatrixSampleMap
Definition: BCSampleData.h:63
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:1134
const bConstraintTypeInfo * BKE_constraint_typeinfo_get(struct bConstraint *con)
Definition: constraint.c:5435
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
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.c:1933
#define IDP_Float(prop)
Definition: BKE_idprop.h:179
#define IDP_Int(prop)
Definition: BKE_idprop.h:154
#define IDP_Double(prop)
Definition: BKE_idprop.h:180
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL()
Definition: idprop.c:643
struct IDProperty * IDP_GetPropertyFromGroup(const struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct IDProperty * IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:907
#define IDP_Array(prop)
Definition: BKE_idprop.h:155
struct Key * BKE_key_from_object(const struct Object *ob)
struct LayerCollection * BKE_layer_collection_get_active(struct ViewLayer *view_layer)
Definition: layer.c:630
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:394
void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, struct Base *selbase)
Definition: layer.c:412
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:145
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:697
void BKE_mesh_tessface_ensure(struct Mesh *mesh)
Definition: mesh.c:1560
struct Mesh * mesh_get_eval_final(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
#define SH_NODE_MIX_SHADER
Definition: BKE_node.h:999
struct bNode * ntreeFindType(const struct bNodeTree *ntree, int type)
#define SH_NODE_BSDF_PRINCIPLED
Definition: BKE_node.h:1058
#define SH_NODE_EMISSION
Definition: BKE_node.h:1009
struct bNodeSocket * ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNode *from_node, struct bNodeSocket *from_sock)
Definition: node.cc:3337
struct bNodeLink * nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock)
Definition: node.cc:2189
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:2529
struct bNode * nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type)
Definition: node.cc:2004
#define NODE_GROUP_INPUT
Definition: BKE_node.h:874
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_add_only_object(struct Main *bmain, int type, const char *name) ATTR_NONNULL(1) ATTR_RETURNS_NONNULL
Definition: object.c:2193
void * BKE_object_obdata_add_from_type(struct Main *bmain, int type, const char *name) ATTR_NONNULL(1)
Definition: object.c:2107
void BKE_object_apply_mat4(struct Object *ob, const float mat[4][4], const bool use_compat, const bool use_parent)
Definition: object.c:3754
void BKE_scene_frame_set(struct Scene *scene, double cfra)
Definition: scene.c:2475
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:47
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1187
void loc_eulO_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3], const short order)
Definition: math_matrix.c:2681
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
void mat4_to_size(float size[3], const float M[4][4])
Definition: math_matrix.c:2145
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:65
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])
size_t size_t char size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) ATTR_NONNULL()
Definition: string.c:333
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define STREQLEN(a, b, n)
#define STREQ(a, b)
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:614
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ IDP_DOUBLE
Definition: DNA_ID.h:103
@ IDP_FLOAT
Definition: DNA_ID.h:99
@ IDP_INT
Definition: DNA_ID.h:98
@ IDP_GROUP
Definition: DNA_ID.h:101
@ IDP_ARRAY
Definition: DNA_ID.h:100
@ FCURVE_DISABLED
#define MAXBONENAME
@ BONE_NO_DEFORM
@ BONE_CONNECTED
@ CONSTRAINT_OFF
@ CONSTRAINT_DISABLE
@ CD_MLOOPUV
@ MOD_TRIANGULATE_QUAD_SHORTEDGE
@ eModifierType_Armature
@ SOCK_IN
#define NODE_SELECT
Object is a sort of wrapper for general info.
@ PARSKEL
@ OB_ARMATURE
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, const bool xmirror, const bool keep_transform, const int vert_par[3])
@ PAR_OBJECT
Definition: ED_object.h:130
void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph)
Definition: screen_edit.c:1617
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.
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer SH_NODE_ADD_SHADER
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction SH_NODE_BSDF_TRANSPARENT
NODE_GROUP_OUTPUT
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave Voronoi Brick Texture Vector Combine Vertex Color
Group RGB to Bright Vector Camera Vector Combine SH_NODE_OUTPUT_MATERIAL
#define C
Definition: RandGen.cpp:39
ATTR_WARN_UNUSED_RESULT BMesh * bm
const BMAllocTemplate bm_mesh_allocsize_default
Definition: bmesh_mesh.c:46
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.c:307
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
BMesh Make Mesh.
Definition: bmesh_mesh.c:157
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
Mesh -> BMesh.
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 apply_transform(Matrix &to, const Matrix &transform, const Matrix &from, const bool inverse=false)
Definition: BCMath.cpp:106
void get_matrix(DMatrix &matrix, const bool transposed=false, const int precision=-1) const
Definition: BCMath.cpp:187
void add_transform(Matrix &to, const Matrix &transform, const Matrix &from, const bool inverted=false)
Definition: BCMath.cpp:91
bool in_range(const BCMatrix &other, float distance) const
Definition: BCMath.cpp:220
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_chain_length(const int aLength)
void set_bone_layers(std::string layers, std::vector< std::string > &layer_labels)
float * get_tail()
BoneExtended(EditBone *aBone)
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:82
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:88
char * bc_CustomData_get_layer_name(const CustomData *data, int type, int n)
bAction * bc_getSceneCameraAction(Object *ob)
Definition: collada_utils.h:99
std::map< std::string, BoneExtended * > BoneExtensionMap
OperationNode * node
const char * label
Scene scene
const Depsgraph * depsgraph
static CCL_NAMESPACE_BEGIN const double alpha
bNodeTree * ntree
#define rot(x, k)
uint pos
uint col
bool enabled
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
static ulong state[N]
static unsigned a[3]
Definition: RandGen.cpp:92
std::vector< ElementType, Eigen::aligned_allocator< ElementType > > vector
Definition: vector.h:39
bNodeSocket * node_group_output_find_socket(bNode *node, const char *identifier)
Definition: node_common.c:530
bNodeSocket * node_group_input_find_socket(bNode *node, const char *identifier)
Definition: node_common.c:433
static bNode * node_group_make_from_selected(const bContext *C, bNodeTree *ntree, const char *ntype, const char *ntreetype)
Definition: node_group.c:990
bAction * action
struct Bone * parent
char name[64]
IDProperty * prop
float arm_mat[4][4]
ListBase childbase
char name[64]
Definition: BKE_armature.h:57
struct EditBone * next
Definition: BKE_armature.h:49
struct IDProperty * prop
Definition: BKE_armature.h:51
struct FCurve * next
char * rna_path
short flag
Definition: DNA_ID.h:273
void * next
Definition: DNA_ID.h:274
char name[66]
Definition: DNA_ID.h:283
struct AnimData * adt
Definition: DNA_key_types.h:81
struct Collection * collection
void * link
Definition: BLI_linklist.h:40
struct LinkNode * next
Definition: BLI_linklist.h:39
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase actions
Definition: BKE_main.h:169
struct bNodeTree * nodetree
struct AnimData * adt
struct CustomData pdata 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]
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition: svm_invert.h:19
struct IDPropertyTemplate::@28 array
ccl_device_inline int mod(int x, int m)
Definition: util_math.h:405
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)