Blender  V3.3
SceneExporter.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BKE_collection.h"
8 #include "BKE_lib_id.h"
9 #include "BKE_object.h"
10 #include "BLI_listbase.h"
11 #include "BLI_utildefines.h"
12 
13 #include "BCSampleData.h"
14 #include "SceneExporter.h"
15 #include "collada_utils.h"
16 
18 {
19  Scene *scene = blender_context.get_scene();
20 
21  /* <library_visual_scenes> <visual_scene> */
22  std::string name = id_name(scene);
23  openVisualScene(translate_id(name), encode_xml(name));
24  exportHierarchy();
25  closeVisualScene();
26  closeLibrary();
27 }
28 
29 void SceneExporter::exportHierarchy()
30 {
31  LinkNode *node;
32  ColladaBaseNodes base_objects;
33 
34  /* Ensure all objects in the export_set are marked */
35  for (node = this->export_settings.get_export_set(); node; node = node->next) {
36  Object *ob = (Object *)node->link;
37  ob->id.tag |= LIB_TAG_DOIT;
38  }
39 
40  /* Now find all exportable base objects (highest in export hierarchy) */
41  for (node = this->export_settings.get_export_set(); node; node = node->next) {
42  Object *ob = (Object *)node->link;
43  if (this->export_settings.is_export_root(ob)) {
44  switch (ob->type) {
45  case OB_MESH:
46  case OB_CAMERA:
47  case OB_LAMP:
48  case OB_EMPTY:
49  case OB_GPENCIL:
50  case OB_ARMATURE:
51  base_objects.add(ob);
52  break;
53  }
54  }
55  }
56 
57  /* And now export the base objects: */
58  for (int index = 0; index < base_objects.size(); index++) {
59  Object *ob = base_objects.get(index);
60  writeNode(ob);
61  if (bc_is_marked(ob)) {
62  bc_remove_mark(ob);
63  }
64  }
65 }
66 
67 void SceneExporter::writeNodeList(std::vector<Object *> &child_objects, Object *parent)
68 {
69  /* TODO: Handle the case where a parent is not exported
70  * Actually i am not even sure if this can be done at all
71  * in a good way.
72  * I really prefer to enforce the export of hidden
73  * elements in an object hierarchy. When the children of
74  * the hidden elements are exported as well. */
75  for (auto *child : child_objects) {
76  writeNode(child);
77  if (bc_is_marked(child)) {
78  bc_remove_mark(child);
79  }
80  }
81 }
82 
83 void SceneExporter::writeNode(Object *ob)
84 {
85  ViewLayer *view_layer = blender_context.get_view_layer();
86 
87  std::vector<Object *> child_objects;
88  bc_get_children(child_objects, ob, view_layer);
89  bool can_export = bc_is_in_Export_set(this->export_settings.get_export_set(), ob, view_layer);
90 
91  /* Add associated armature first if available */
92  bool armature_exported = false;
93  Object *ob_arm = bc_get_assigned_armature(ob);
94 
95  if (ob_arm != nullptr) {
96  armature_exported = bc_is_in_Export_set(
97  this->export_settings.get_export_set(), ob_arm, view_layer);
98  if (armature_exported && bc_is_marked(ob_arm)) {
99  writeNode(ob_arm);
100  bc_remove_mark(ob_arm);
101  armature_exported = true;
102  }
103  }
104 
105  if (can_export) {
106  COLLADASW::Node colladaNode(mSW);
107  colladaNode.setNodeId(translate_id(id_name(ob)));
108  colladaNode.setNodeName(encode_xml(id_name(ob)));
109  colladaNode.setType(COLLADASW::Node::NODE);
110 
111  colladaNode.start();
112  if (ob->type == OB_MESH && armature_exported) {
113  /* for skinned mesh we write obmat in <bind_shape_matrix> */
114  TransformWriter::add_node_transform_identity(colladaNode, this->export_settings);
115  }
116  else {
117  TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings);
118  }
119 
120  /* <instance_geometry> */
121  if (ob->type == OB_MESH) {
122  bool instance_controller_created = false;
123  if (armature_exported) {
124  instance_controller_created = arm_exporter->add_instance_controller(ob);
125  }
126  if (!instance_controller_created) {
127  COLLADASW::InstanceGeometry instGeom(mSW);
128  instGeom.setUrl(COLLADASW::URI(
130  get_geometry_id(ob, this->export_settings.get_use_object_instantiation())));
131  instGeom.setName(encode_xml(id_name(ob)));
133  instGeom.getBindMaterial(), ob, this->export_settings.get_active_uv_only());
134  instGeom.add();
135  }
136  }
137 
138  /* <instance_controller> */
139  else if (ob->type == OB_ARMATURE) {
140  arm_exporter->add_armature_bones(ob, view_layer, this, child_objects);
141  }
142 
143  /* <instance_camera> */
144  else if (ob->type == OB_CAMERA) {
145  COLLADASW::InstanceCamera instCam(
146  mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob)));
147  instCam.add();
148  }
149 
150  /* <instance_light> */
151  else if (ob->type == OB_LAMP) {
152  COLLADASW::InstanceLight instLa(
153  mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob)));
154  instLa.add();
155  }
156 
157  /* empty object */
158  else if (ob->type == OB_EMPTY) { /* TODO: handle groups (OB_DUPLICOLLECTION */
160  Collection *collection = ob->instance_collection;
161  // printf("group detected '%s'\n", group->id.name + 2);
162  FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, object) {
163  printf("\t%s\n", object->id.name);
164  }
166  }
167 
168  if (BLI_listbase_is_empty(&ob->constraints) == false) {
170  while (con) {
171  std::string con_name(encode_xml(con->name));
172  std::string con_tag = con_name + "_constraint";
173  printf("%s\n", con_name.c_str());
174  printf("%s\n\n", con_tag.c_str());
175  colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "type", con->type);
176  colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "enforce", con->enforce);
177  colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "flag", con->flag);
178  colladaNode.addExtraTechniqueChildParameter(
179  "blender", con_tag, "headtail", con->headtail);
180  colladaNode.addExtraTechniqueChildParameter(
181  "blender", con_tag, "lin_error", con->lin_error);
182  colladaNode.addExtraTechniqueChildParameter(
183  "blender", con_tag, "own_space", con->ownspace);
184  colladaNode.addExtraTechniqueChildParameter(
185  "blender", con_tag, "rot_error", con->rot_error);
186  colladaNode.addExtraTechniqueChildParameter(
187  "blender", con_tag, "tar_space", con->tarspace);
188  colladaNode.addExtraTechniqueChildParameter(
189  "blender", con_tag, "lin_error", con->lin_error);
190 
191  /* not ideal: add the target object name as another parameter.
192  * No real mapping in the `.dae`.
193  * Need support for multiple target objects also. */
194 
195  ListBase targets = {nullptr, nullptr};
196  if (BKE_constraint_targets_get(con, &targets)) {
197  bConstraintTarget *ct;
198  Object *obtar;
199 
200  for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
201  obtar = ct->tar;
202  std::string tar_id((obtar) ? id_name(obtar) : "");
203  colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "target_id", tar_id);
204  }
205 
206  BKE_constraint_targets_flush(con, &targets, true);
207  }
208 
209  con = con->next;
210  }
211  }
212  }
213  bc_remove_mark(ob);
214  writeNodeList(child_objects, ob);
215  colladaNode.end();
216  }
217  else {
218  writeNodeList(child_objects, ob);
219  }
220 }
std::string EMPTY_STRING
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targets, bool no_copy)
Definition: constraint.c:6186
int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targets)
Definition: constraint.c:6157
General operations, lookup, etc. for blender objects.
#define NODE(offset)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void bc_remove_mark(Object *ob)
int bc_is_marked(Object *ob)
bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer)
void bc_get_children(std::vector< Object * > &child_set, Object *ob, ViewLayer *view_layer)
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ OB_EMPTY
@ OB_CAMERA
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_GPENCIL
@ OB_DUPLICOLLECTION
bool add_instance_controller(Object *ob)
void add_armature_bones(Object *ob_arm, ViewLayer *view_layer, SceneExporter *se, std::vector< Object * > &child_objects)
void add(Object *ob)
Object * get(int index)
void add_material_bindings(COLLADASW::BindMaterial &bind_material, Object *ob, bool active_uv_only)
void add_node_transform_ob(COLLADASW::Node &node, Object *ob, BCExportSettings &export_settings)
void add_node_transform_identity(COLLADASW::Node &node, BCExportSettings &export_settings)
std::string get_camera_id(Object *ob)
std::string translate_id(const char *idString)
std::string get_geometry_id(Object *ob)
std::string encode_xml(std::string xml)
std::string get_light_id(Object *ob)
std::string id_name(void *id)
Object * bc_get_assigned_armature(Object *ob)
OperationNode * node
Scene scene
int tag
Definition: DNA_ID.h:387
void * first
Definition: DNA_listBase.h:31
short transflag
ListBase constraints
struct Collection * instance_collection
struct bConstraintTarget * next
struct bConstraint * next