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