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