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