Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/collada')
-rw-r--r--source/blender/collada/AnimationClipExporter.cpp55
-rw-r--r--source/blender/collada/AnimationClipExporter.h50
-rw-r--r--source/blender/collada/AnimationCurveCache.cpp391
-rw-r--r--source/blender/collada/AnimationCurveCache.h130
-rw-r--r--source/blender/collada/AnimationExporter.cpp2029
-rw-r--r--source/blender/collada/AnimationExporter.h195
-rw-r--r--source/blender/collada/AnimationImporter.cpp77
-rw-r--r--source/blender/collada/AnimationImporter.h30
-rw-r--r--source/blender/collada/ArmatureExporter.cpp59
-rw-r--r--source/blender/collada/ArmatureExporter.h31
-rw-r--r--source/blender/collada/ArmatureImporter.cpp19
-rw-r--r--source/blender/collada/ArmatureImporter.h4
-rw-r--r--source/blender/collada/BCAnimationCurve.cpp678
-rw-r--r--source/blender/collada/BCAnimationCurve.h156
-rw-r--r--source/blender/collada/BCAnimationSampler.cpp645
-rw-r--r--source/blender/collada/BCAnimationSampler.h205
-rw-r--r--source/blender/collada/BCSampleData.cpp186
-rw-r--r--source/blender/collada/BCSampleData.h102
-rw-r--r--source/blender/collada/BlenderContext.cpp61
-rw-r--r--source/blender/collada/BlenderContext.h56
-rw-r--r--source/blender/collada/CMakeLists.txt13
-rw-r--r--source/blender/collada/ControllerExporter.cpp61
-rw-r--r--source/blender/collada/ControllerExporter.h16
-rw-r--r--source/blender/collada/DocumentExporter.cpp52
-rw-r--r--source/blender/collada/DocumentExporter.h12
-rw-r--r--source/blender/collada/DocumentImporter.cpp347
-rw-r--r--source/blender/collada/DocumentImporter.h9
-rw-r--r--source/blender/collada/EffectExporter.cpp333
-rw-r--r--source/blender/collada/EffectExporter.h21
-rw-r--r--source/blender/collada/ErrorHandler.cpp46
-rw-r--r--source/blender/collada/ExportSettings.h22
-rw-r--r--source/blender/collada/GeometryExporter.cpp324
-rw-r--r--source/blender/collada/GeometryExporter.h51
-rw-r--r--source/blender/collada/ImageExporter.cpp244
-rw-r--r--source/blender/collada/ImageExporter.h14
-rw-r--r--source/blender/collada/InstanceWriter.cpp52
-rw-r--r--source/blender/collada/InstanceWriter.h3
-rw-r--r--source/blender/collada/LightExporter.cpp35
-rw-r--r--source/blender/collada/MaterialExporter.cpp46
-rw-r--r--source/blender/collada/MaterialExporter.h1
-rw-r--r--source/blender/collada/Materials.cpp329
-rw-r--r--source/blender/collada/Materials.h84
-rw-r--r--source/blender/collada/MeshImporter.cpp121
-rw-r--r--source/blender/collada/MeshImporter.h22
-rw-r--r--source/blender/collada/SceneExporter.cpp267
-rw-r--r--source/blender/collada/SceneExporter.h23
-rw-r--r--source/blender/collada/SkinInfo.cpp14
-rw-r--r--source/blender/collada/SkinInfo.h2
-rw-r--r--source/blender/collada/TransformReader.cpp4
-rw-r--r--source/blender/collada/TransformWriter.cpp7
-rw-r--r--source/blender/collada/TransformWriter.h3
-rw-r--r--source/blender/collada/collada.cpp45
-rw-r--r--source/blender/collada/collada.h7
-rw-r--r--source/blender/collada/collada_internal.cpp44
-rw-r--r--source/blender/collada/collada_internal.h15
-rw-r--r--source/blender/collada/collada_utils.cpp672
-rw-r--r--source/blender/collada/collada_utils.h134
57 files changed, 5207 insertions, 3447 deletions
diff --git a/source/blender/collada/AnimationClipExporter.cpp b/source/blender/collada/AnimationClipExporter.cpp
new file mode 100644
index 00000000000..a2c4b388b7e
--- /dev/null
+++ b/source/blender/collada/AnimationClipExporter.cpp
@@ -0,0 +1,55 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#include "GeometryExporter.h"
+#include "AnimationClipExporter.h"
+#include "MaterialExporter.h"
+
+void AnimationClipExporter::exportAnimationClips(Scene *sce)
+{
+ openLibrary();
+ std::map<std::string, COLLADASW::ColladaAnimationClip *> clips;
+
+ std::vector<std::vector<std::string>>::iterator anim_meta_entry;
+ for (anim_meta_entry = anim_meta.begin(); anim_meta_entry != anim_meta.end(); ++anim_meta_entry) {
+ std::vector<std::string> entry = *anim_meta_entry;
+ std::string action_id = entry[0];
+ std::string action_name = entry[1];
+
+ std::map<std::string, COLLADASW::ColladaAnimationClip *>::iterator it = clips.find(action_name);
+ if (it == clips.end())
+ {
+ COLLADASW::ColladaAnimationClip *clip = new COLLADASW::ColladaAnimationClip(action_name);
+ clips[action_name] = clip;
+ }
+ COLLADASW::ColladaAnimationClip *clip = clips[action_name];
+ clip->setInstancedAnimation(action_id);
+ }
+
+ std::map<std::string, COLLADASW::ColladaAnimationClip *>::iterator clips_it;
+ for (clips_it = clips.begin(); clips_it != clips.end(); clips_it++) {
+ COLLADASW::ColladaAnimationClip *clip = (COLLADASW::ColladaAnimationClip *)clips_it->second;
+ addAnimationClip(*clip);
+ }
+
+ closeLibrary();
+}
diff --git a/source/blender/collada/AnimationClipExporter.h b/source/blender/collada/AnimationClipExporter.h
new file mode 100644
index 00000000000..8a9394ce88a
--- /dev/null
+++ b/source/blender/collada/AnimationClipExporter.h
@@ -0,0 +1,50 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "COLLADASWLibraryAnimationClips.h"
+
+
+class AnimationClipExporter:COLLADASW::LibraryAnimationClips {
+private:
+ Depsgraph *depsgraph;
+ Scene *scene;
+ COLLADASW::StreamWriter *sw;
+ const ExportSettings *export_settings;
+ std::vector<std::vector<std::string>> anim_meta;
+
+public:
+
+ AnimationClipExporter(Depsgraph *depsgraph , COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, std::vector<std::vector<std::string>> anim_meta) :
+ COLLADASW::LibraryAnimationClips(sw),
+ depsgraph(depsgraph),
+ scene(nullptr),
+ sw(sw),
+ export_settings(export_settings),
+ anim_meta(anim_meta)
+ {}
+
+ void exportAnimationClips(Scene *sce);
+};
diff --git a/source/blender/collada/AnimationCurveCache.cpp b/source/blender/collada/AnimationCurveCache.cpp
new file mode 100644
index 00000000000..f580ffce7bb
--- /dev/null
+++ b/source/blender/collada/AnimationCurveCache.cpp
@@ -0,0 +1,391 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#include "AnimationCurveCache.h"
+
+extern "C" {
+#include "BKE_action.h"
+#include "BLI_listbase.h"
+}
+
+AnimationCurveCache::AnimationCurveCache(bContext *C):
+ mContext(C)
+{
+}
+
+AnimationCurveCache::~AnimationCurveCache()
+{
+ clear_cache();
+}
+
+void AnimationCurveCache::clear_cache()
+{
+
+}
+
+void AnimationCurveCache::clear_cache(Object *ob)
+{
+
+}
+
+void AnimationCurveCache::create_curves(Object *ob)
+{
+
+}
+
+void AnimationCurveCache::addObject(Object *ob)
+{
+ cached_objects.push_back(ob);
+}
+
+bool AnimationCurveCache::bone_matrix_local_get(Object *ob, Bone *bone, float(&mat)[4][4], bool for_opensim)
+{
+
+ /* Ok, lets be super cautious and check if the bone exists */
+ bPose *pose = ob->pose;
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
+ if (!pchan) {
+ return false;
+ }
+
+ bAction *action = bc_getSceneObjectAction(ob);
+ bPoseChannel *parchan = pchan->parent;
+ enable_fcurves(action, bone->name);
+ float ipar[4][4];
+
+ if (bone->parent) {
+ invert_m4_m4(ipar, parchan->pose_mat);
+ mul_m4_m4m4(mat, ipar, pchan->pose_mat);
+ }
+ else
+ copy_m4_m4(mat, pchan->pose_mat);
+
+ /* OPEN_SIM_COMPATIBILITY
+ * AFAIK animation to second life is via BVH, but no
+ * reason to not have the collada-animation be correct
+ */
+ if (for_opensim) {
+ float temp[4][4];
+ copy_m4_m4(temp, bone->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ invert_m4(temp);
+
+ mul_m4_m4m4(mat, mat, temp);
+
+ if (bone->parent) {
+ copy_m4_m4(temp, bone->parent->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+
+ mul_m4_m4m4(mat, temp, mat);
+ }
+ }
+
+ return true;
+}
+
+void AnimationCurveCache::sampleMain(Scene *scene, BC_export_transformation_type atm_type, bool for_opensim)
+{
+ std::map<int, std::vector<SamplePoint>>::iterator frame;
+ for (frame = sample_frames.begin(); frame != sample_frames.end(); frame++) {
+ int frame_index = frame->first;
+ std::vector<SamplePoint> sample_points = frame->second;
+
+ bc_update_scene(mContext, scene, frame_index);
+
+ for (int spi = 0; spi < sample_points.size(); spi++) {
+ SamplePoint &point = sample_points[spi];
+ Object *ob = point.get_object();
+ float mat[4][4];
+
+ if (ob->type == OB_ARMATURE) {
+ /* For Armatures we need to check if this maybe is a pose sample point*/
+ Bone *bone = point.get_bone();
+ if (bone) {
+ if (bone_matrix_local_get(ob, bone, mat, for_opensim)) {
+ point.set_matrix(mat);
+ }
+ continue;
+ }
+ }
+
+ /* When this SamplePoint is not for a Bone,
+ * then we just store the Object local matrix here
+ */
+
+ BKE_object_matrix_local_get(ob, mat);
+ point.set_matrix(mat);
+
+ }
+ }
+}
+
+/*
+* enable fcurves driving a specific bone, disable all the rest
+* if bone_name = NULL enable all fcurves
+*/
+void AnimationCurveCache::enable_fcurves(bAction *act, char *bone_name)
+{
+ FCurve *fcu;
+ char prefix[200];
+
+ if (bone_name)
+ BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
+
+ for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
+ if (bone_name) {
+ if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
+ fcu->flag &= ~FCURVE_DISABLED;
+ else
+ fcu->flag |= FCURVE_DISABLED;
+ }
+ else {
+ fcu->flag &= ~FCURVE_DISABLED;
+ }
+ }
+}
+/*
+* Sample the scene at frames where object fcurves
+* have defined keys.
+*/
+void AnimationCurveCache::sampleScene(Scene *scene, BC_export_transformation_type atm_type, bool for_opensim, bool keyframe_at_end)
+{
+ create_sample_frames_from_keyframes();
+ sampleMain(scene, atm_type, for_opensim);
+}
+
+void AnimationCurveCache::sampleScene(Scene *scene, BC_export_transformation_type atm_type, int sampling_rate, bool for_opensim, bool keyframe_at_end)
+{
+ create_sample_frames_generated(scene->r.sfra, scene->r.efra, sampling_rate, keyframe_at_end);
+ sampleMain(scene, atm_type, for_opensim);
+}
+
+std::vector<FCurve *> *AnimationCurveCache::getSampledCurves(Object *ob)
+{
+ std::map<Object *, std::vector<FCurve *>>::iterator fcurves;
+ fcurves = cached_curves.find(ob);
+ return (fcurves == cached_curves.end()) ? NULL : &fcurves->second;
+}
+
+std::vector<SamplePoint> &AnimationCurveCache::getFrameInfos(int frame_index)
+{
+ std::map<int, std::vector<SamplePoint>>::iterator frames = sample_frames.find(frame_index);
+ if (frames == sample_frames.end()) {
+ std::vector<SamplePoint> sample_points;
+ sample_frames[frame_index] = sample_points;
+ }
+ return sample_frames[frame_index];
+}
+
+
+void AnimationCurveCache::add_sample_point(SamplePoint &point)
+{
+ int frame_index = point.get_frame();
+ std::vector<SamplePoint> &frame_infos = getFrameInfos(frame_index);
+ frame_infos.push_back(point);
+}
+
+/*
+* loop over all cached objects
+* loop over all fcurves
+* record all keyframes
+*
+* The vector sample_frames finally contains a list of vectors
+* where each vector contains a list of SamplePoints which
+* need to be processed when evaluating the animation.
+*/
+void AnimationCurveCache::create_sample_frames_from_keyframes()
+{
+ sample_frames.clear();
+ for (int i = 0; i < cached_objects.size(); i++) {
+ Object *ob = cached_objects[i];
+ bAction *action = bc_getSceneObjectAction(ob);
+ FCurve *fcu = (FCurve *)action->curves.first;
+
+ for (; fcu; fcu = fcu->next) {
+ for (unsigned int i = 0; i < fcu->totvert; i++) {
+ float f = fcu->bezt[i].vec[1][0];
+ int frame_index = int(f);
+ SamplePoint sample_point(frame_index, ob, fcu, i);
+ add_sample_point(sample_point);
+ }
+ }
+ }
+}
+
+/*
+* loop over all cached objects
+* loop over active action using a stesize of sampling_rate
+* record all frames
+*
+* The vector sample_frames finally contains a list of vectors
+* where each vector contains a list of SamplePoints which
+* need to be processed when evaluating the animation.
+* Note: The FCurves of the objects will not be used here.
+*/
+void AnimationCurveCache::create_sample_frames_generated(float sfra, float efra, int sampling_rate, int keyframe_at_end)
+{
+ sample_frames.clear();
+
+ for (int i = 0; i < cached_objects.size(); i++) {
+
+ Object *ob = cached_objects[i];
+ float f = sfra;
+
+ do {
+ int frame_index = int(f);
+ SamplePoint sample_point(frame_index, ob);
+ add_sample_point(sample_point);
+
+ /* Depending on the Object type add more sample points here
+ */
+
+ if (ob && ob->type == OB_ARMATURE) {
+ LISTBASE_FOREACH(bPoseChannel *, pchan, &ob->pose->chanbase) {
+ SamplePoint point(frame_index, ob, pchan->bone);
+ add_sample_point(sample_point);
+ }
+ }
+
+ if (f == efra)
+ break;
+ f += sampling_rate;
+ if (f > efra)
+ if (keyframe_at_end)
+ f = efra; // make sure the last frame is always exported
+ else
+ break;
+ } while (true);
+ }
+}
+
+Matrix::Matrix()
+{
+ unit_m4(matrix);
+}
+
+Matrix::Matrix(float (&mat)[4][4])
+{
+ set_matrix(mat);
+}
+
+void Matrix::set_matrix(float(&mat)[4][4])
+{
+ copy_m4_m4(matrix, mat);
+}
+
+void Matrix::set_matrix(Matrix &mat)
+{
+ copy_m4_m4(matrix, mat.matrix);
+}
+
+void Matrix::get_matrix(float(&mat)[4][4])
+{
+ copy_m4_m4(mat, matrix);
+}
+
+SamplePoint::SamplePoint(int frame, Object *ob)
+{
+ this->frame = frame;
+ this->fcu = NULL;
+ this->ob = ob;
+ this->pose_bone = NULL;
+ this->index = -1;
+}
+
+SamplePoint::SamplePoint(int frame, Object *ob, FCurve *fcu, int index)
+{
+ this->frame = frame;
+ this->fcu = fcu;
+ this->ob = ob;
+ this->pose_bone = NULL;
+ this->index = index;
+ this->path = std::string(fcu->rna_path);
+
+ /* Further elaborate on what this Fcurve is doing by checking
+ * its rna_path
+ */
+
+ if (ob && ob->type == OB_ARMATURE) {
+ char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ bPose *pose = ob->pose;
+ if (boneName) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName);
+ this->pose_bone = pchan->bone;
+ }
+ }
+}
+
+
+SamplePoint::SamplePoint(int frame, Object *ob, Bone *bone)
+{
+ this->frame = frame;
+ this->fcu = NULL;
+ this->ob = ob;
+ this->pose_bone = bone;
+ this->index = -1;
+ this->path = "pose.bones[\"" + id_name(bone) + "\"].matrix";
+}
+
+Matrix &SamplePoint::get_matrix()
+{
+ return matrix;
+}
+
+void SamplePoint::set_matrix(Matrix &mat)
+{
+ this->matrix.set_matrix(mat);
+}
+
+void SamplePoint::set_matrix(float(&mat)[4][4])
+{
+
+}
+
+Object *SamplePoint::get_object()
+{
+ return this->ob;
+}
+
+Bone *SamplePoint::get_bone()
+{
+ return this->pose_bone;
+}
+
+FCurve *SamplePoint::get_fcurve()
+{
+ return this->fcu;
+}
+
+int SamplePoint::get_frame()
+{
+ return this->frame;
+}
+
+int SamplePoint::get_fcurve_index()
+{
+ return this->index;
+}
+
+std::string &SamplePoint::get_path()
+{
+ return path;
+}
diff --git a/source/blender/collada/AnimationCurveCache.h b/source/blender/collada/AnimationCurveCache.h
new file mode 100644
index 00000000000..3d74e93758e
--- /dev/null
+++ b/source/blender/collada/AnimationCurveCache.h
@@ -0,0 +1,130 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#ifndef __ANIMATION_CURVE_CACHE_H__
+#define __ANIMATION_CURVE_CACHE_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <vector>
+#include <map>
+#include <algorithm> // std::find
+
+#include "exportSettings.h"
+#include "collada_utils.h"
+
+extern "C"
+{
+#include "DNA_object_types.h"
+#include "DNA_anim_types.h"
+}
+
+class Matrix {
+private:
+ float matrix[4][4];
+public:
+ Matrix();
+ Matrix(float (&mat)[4][4]);
+ void set_matrix(float (&mat)[4][4]);
+ void set_matrix(Matrix &mat);
+ void get_matrix(float (&mat)[4][4]);
+};
+
+class SamplePoint {
+
+private:
+
+ Object * ob;
+ Bone *pose_bone;
+ FCurve *fcu;
+ int frame; /* frame in timeline (not sure if we actually should store a float here) */
+ int index; /* Keyframe index in fcurve (makes sense only when fcu is also set) */
+ std::string path; /* Do not mixup with rna_path. It is used for different purposes! */
+
+ Matrix matrix; /* Local matrix, by default unit matrix, will be set when sampling */
+
+public:
+
+ SamplePoint(int frame, Object *ob);
+ SamplePoint(int frame, Object *ob, FCurve *fcu, int index);
+ SamplePoint(int frame, Object *ob, Bone *bone);
+
+ Object *get_object();
+ Bone *get_bone();
+ FCurve *get_fcurve();
+ int get_frame();
+ int get_fcurve_index();
+ Matrix &get_matrix();
+ std::string &get_path();
+
+ void set_matrix(Matrix &matrix);
+ void set_matrix(float(&mat)[4][4]);
+};
+
+
+class AnimationCurveCache {
+private:
+ void clear_cache(); // remove all sampled FCurves
+ void clear_cache(Object *ob); //remove sampled FCurves for single object
+ void create_curves(Object *ob);
+
+ std::vector<Object *> cached_objects; // list of objects for caching
+ std::map<Object *, std::vector<FCurve *>> cached_curves; //map of cached FCurves
+ std::map<int, std::vector<SamplePoint>> sample_frames; // list of frames where objects need to be sampled
+
+ std::vector<SamplePoint> &getFrameInfos(int frame_index);
+ void add_sample_point(SamplePoint &point);
+ void enable_fcurves(bAction *act, char *bone_name);
+ bool bone_matrix_local_get(Object *ob, Bone *bone, float (&mat)[4][4], bool for_opensim);
+
+ bContext *mContext;
+
+public:
+
+ AnimationCurveCache(bContext *C);
+ ~AnimationCurveCache();
+
+ void addObject(Object *obj);
+
+ void sampleMain(Scene *scene,
+ BC_export_transformation_type atm_type,
+ bool for_opensim);
+
+ void sampleScene(Scene *scene,
+ BC_export_transformation_type atm_type,
+ bool for_opensim,
+ bool keyframe_at_end = true); // use keys from FCurves, use timeline boundaries
+
+ void sampleScene(Scene *scene,
+ BC_export_transformation_type atm_type,
+ int sampling_rate, bool for_opensim,
+ bool keyframe_at_end = true ); // generate keyframes for frames use timeline boundaries
+
+ std::vector<FCurve *> *getSampledCurves(Object *ob);
+
+ void create_sample_frames_from_keyframes();
+ void create_sample_frames_generated(float sfra, float efra, int sampling_rate, int keyframe_at_end);
+};
+
+
+#endif
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index e5c54fd9917..69a25ac7a82 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -20,658 +20,344 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file AnimationExporter.cpp
+ * \ingroup collada
+ */
+
#include "GeometryExporter.h"
#include "AnimationExporter.h"
+#include "AnimationClipExporter.h"
+#include "BCAnimationSampler.h"
#include "MaterialExporter.h"
+#include "collada_utils.h"
-template<class Functor>
-void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
-{
- LinkNode *node;
- for (node = export_set; node; node = node->next) {
- Object *ob = (Object *)node->link;
- f(ob);
- }
-}
+std::string EMPTY_STRING;
-bool AnimationExporter::exportAnimations(Main *bmain, Scene *sce)
+std::string AnimationExporter::get_axis_name(std::string channel, int id)
{
- bool has_animations = hasAnimations(sce);
- m_bmain = bmain;
- if (has_animations) {
- this->scene = sce;
+ static std::map<std::string, std::vector<std::string>> BC_COLLADA_AXIS_FROM_TYPE = {
+ { "color" ,{ "R", "G", "B" } },
+ { "specular_color",{ "R", "G", "B" } },
+ { "diffuse_color",{ "R", "G", "B" } },
+ { "alpha",{ "R", "G", "B" } },
+ { "scale",{ "X", "Y", "Z" } },
+ { "location",{ "X", "Y", "Z" } },
+ { "rotation_euler",{ "X", "Y", "Z" } }
+ };
- openLibrary();
+ std::map<std::string, std::vector<std::string>>::const_iterator it;
+ it = BC_COLLADA_AXIS_FROM_TYPE.find(channel);
+ if (it == BC_COLLADA_AXIS_FROM_TYPE.end())
+ return "";
- forEachObjectInExportSet(sce, *this, this->export_settings->export_set);
-
- closeLibrary();
- }
- return has_animations;
+ const std::vector<std::string> &subchannel = it->second;
+ if (id >= subchannel.size())
+ return "";
+ return subchannel[id];
}
-bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
+bool AnimationExporter::open_animation_container(bool has_container, Object *ob)
{
- for (int i = 0; i < values.size(); i += channel_count) {
- for (int j = 0; j < channel_count; j++) {
- if (!bc_in_range(values[j], values[i+j], 0.000001))
- return false;
- }
+ if (!has_container) {
+ char anim_id[200];
+ sprintf(anim_id, "action_container-%s", translate_id(id_name(ob)).c_str());
+ openAnimation(anim_id, encode_xml(id_name(ob)));
}
return true;
}
-/*
- * This function creates a complete LINEAR Collada <Animation> Entry with all needed
- * <source>, <sampler>, and <channel> entries.
- * This is is used for creating sampled Transformation Animations for either:
- *
- * 1-axis animation:
- * times contains the time points in seconds from within the timeline
- * values contains the data (list of single floats)
- * channel_count = 1
- * axis_name = ['X' | 'Y' | 'Z']
- * is_rot indicates if the animation is a rotation
- *
- * 3-axis animation:
- * times contains the time points in seconds from within the timeline
- * values contains the data (list of floats where each 3 entries are one vector)
- * channel_count = 3
- * axis_name = "" (actually not used)
- * is_rot = false (see xxx below)
- *
- * xxx:
- * I tried to create a 3 axis rotation animation
- * like for translation or scale. But i could not
- * figure out how to setup the channel for this case.
- * So for now rotations are exported as 3 separate 1-axis collada animations
- * See export_sampled_animation() further down.
- */
-void AnimationExporter::create_sampled_animation(int channel_count,
- std::vector<float> &times,
- std::vector<float> &values,
- std::string ob_name,
- std::string label,
- std::string axis_name,
- bool is_rot)
-{
- char anim_id[200];
-
- if (is_flat_line(values, channel_count))
- return;
-
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str());
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
- /* create input source */
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, "");
-
- /* create output source */
- std::string output_id;
- if (channel_count == 1)
- output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str());
- else if (channel_count == 3)
- output_id = create_xyz_source(&values[0], times.size(), anim_id);
- else if (channel_count == 16)
- output_id = create_4x4_source(times, values, anim_id);
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
- COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
-
- /* TODO create in/out tangents source (LINEAR) */
- std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, "");
-
- /* Create Sampler */
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
- addSampler(sampler);
-
- /* Create channel */
- std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : "");
- addChannel(COLLADABU::URI(empty, sampler_id), target);
-
- closeAnimation();
-
-}
-
-/*
- * Export all animation FCurves of an Object.
- *
- * Note: This uses the keyframes as sample points,
- * and exports "baked keyframes" while keeping the tangent information
- * of the FCurves intact. This works for simple cases, but breaks
- * especially when negative scales are involved in the animation.
- *
- * If it is necessary to conserve the Animation precisely then
- * use export_sampled_animation_set() instead.
- */
-void AnimationExporter::export_keyframed_animation_set(Object *ob)
+void AnimationExporter::openAnimationWithClip(std::string action_id, std::string action_name)
{
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
- if (!fcu) {
- return; /* object has no animation */
- }
-
- if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
+ std::vector<std::string> anim_meta_entry;
+ anim_meta_entry.push_back(translate_id(action_id));
+ anim_meta_entry.push_back(action_name);
+ anim_meta.push_back(anim_meta_entry);
- std::vector<float> ctimes;
- find_keyframes(ob, ctimes);
- if (ctimes.size() > 0)
- export_sampled_matrix_animation(ob, ctimes);
- }
- else {
- char *transformName;
- while (fcu) {
- //for armature animations as objects
- if (ob->type == OB_ARMATURE)
- transformName = fcu->rna_path;
- else
- transformName = extract_transform_name(fcu->rna_path);
-
- if (
- STREQ(transformName, "location") ||
- STREQ(transformName, "scale") ||
- (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
- STREQ(transformName, "rotation_quaternion"))
- {
- create_keyframed_animation(ob, fcu, transformName, false);
- }
- fcu = fcu->next;
- }
- }
+ openAnimation(translate_id(action_id), action_name);
}
-/*
- * Export the sampled animation of an Object.
- *
- * Note: This steps over all animation frames (step size is given in export_settings.sample_size)
- * and then evaluates the transformation,
- * and exports "baked samples" This works always, however currently the interpolation type is set
- * to LINEAR for now. (maybe later this can be changed to BEZIER)
- *
- * Note: If it is necessary to keep the FCurves intact, then use export_keyframed_animation_set() instead.
- * However be aware that exporting keyframed animation may modify the animation slightly.
- * Also keyframed animation exports tend to break when negative scales are involved.
- */
-void AnimationExporter::export_sampled_animation_set(Object *ob)
+void AnimationExporter::close_animation_container(bool has_container)
{
- std::vector<float>ctimes;
- find_sampleframes(ob, ctimes);
- if (ctimes.size() > 0) {
- if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX)
- export_sampled_matrix_animation(ob, ctimes);
- else
- export_sampled_transrotloc_animation(ob, ctimes);
- }
+ if (has_container)
+ closeAnimation();
}
-void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes)
+bool AnimationExporter::exportAnimations()
{
- UnitConverter converter;
+ Scene *sce = blender_context.get_scene();
- std::vector<float> values;
+ LinkNode &export_set = *this->export_settings->export_set;
+ bool has_anim_data = bc_has_animations(sce, export_set);
+ int animation_count = 0;
+ if (has_anim_data) {
- for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) {
- float fmat[4][4];
+ BCObjectSet animated_subset;
+ BCAnimationSampler::get_animated_from_export_set(animated_subset, export_set);
+ animation_count = animated_subset.size();
+ BCAnimationSampler animation_sampler(blender_context, animated_subset);
- bc_update_scene(m_bmain, scene, *ctime);
- BKE_object_matrix_local_get(ob, fmat);
- if (this->export_settings->limit_precision)
- bc_sanitize_mat(fmat, 6);
+ try {
+ animation_sampler.sample_scene(
+ export_settings->sampling_rate,
+ /*keyframe_at_end = */ true,
+ export_settings->open_sim,
+ export_settings->keep_keyframes,
+ export_settings->export_animation_type
+ );
- for (int i = 0; i < 4; i++)
- for (int j = 0; j < 4; j++)
- values.push_back(fmat[i][j]);
- }
-
- std::string ob_name = id_name(ob);
+ openLibrary();
- create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false);
-}
+ BCObjectSet::iterator it;
+ for (it = animated_subset.begin(); it != animated_subset.end(); ++it) {
+ Object *ob = *it;
+ exportAnimation(ob, animation_sampler);
+ }
+ }
+ catch (std::invalid_argument &iae)
+ {
+ fprintf(stderr, "Animation export interrupted");
+ fprintf(stderr, "Exception was: %s", iae.what());
+ }
-void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes)
-{
- static int LOC = 0;
- static int EULX = 1;
- static int EULY = 2;
- static int EULZ = 3;
- static int SCALE = 4;
-
- std::vector<float> baked_curves[5];
-
- for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) {
- float fmat[4][4];
- float floc[3];
- float fquat[4];
- float fsize[3];
- float feul[3];
-
- bc_update_scene(m_bmain, scene, *ctime);
- BKE_object_matrix_local_get(ob, fmat);
- mat4_decompose(floc, fquat, fsize, fmat);
- quat_to_eul(feul, fquat);
-
- baked_curves[LOC].push_back(floc[0]);
- baked_curves[LOC].push_back(floc[1]);
- baked_curves[LOC].push_back(floc[2]);
-
- baked_curves[EULX].push_back(feul[0]);
- baked_curves[EULY].push_back(feul[1]);
- baked_curves[EULZ].push_back(feul[2]);
-
- baked_curves[SCALE].push_back(fsize[0]);
- baked_curves[SCALE].push_back(fsize[1]);
- baked_curves[SCALE].push_back(fsize[2]);
+ closeLibrary();
+#if 0
+ /* TODO: If all actions shall be exported, we need to call the
+ * AnimationClipExporter which will figure out which actions
+ * need to be exported for which objects
+ */
+ if (this->export_settings->include_all_actions) {
+ AnimationClipExporter ace(eval_ctx, sw, export_settings, anim_meta);
+ ace.exportAnimationClips(sce);
+ }
+#endif
}
-
- std::string ob_name = id_name(ob);
-
- create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale", "", false);
- create_sampled_animation(3, ctimes, baked_curves[LOC], ob_name, "location", "", false);
-
- /* Not sure how to export rotation as a 3channel animation,
- * so separate into 3 single animations for now:
- */
-
- create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true);
- create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true);
- create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true);
-
- fprintf(stdout, "Animation Export: Baked %d frames for %s (sampling rate: %d)\n",
- (int)baked_curves[0].size(),
- ob->id.name,
- this->export_settings->sampling_rate);
+ return animation_count;
}
/* called for each exported object */
-void AnimationExporter::operator()(Object *ob)
+void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler)
{
- char *transformName;
+ bool container_is_open = false;
- /* bool isMatAnim = false; */ /* UNUSED */
+ //Transform animations (trans, rot, scale)
+ container_is_open = open_animation_container(container_is_open, ob);
- //Export transform animations
- if (ob->adt && ob->adt->action) {
+ /* Now take care of the Object Animations
+ * Note: For Armatures the skeletal animation has already been exported (see above)
+ * However Armatures also can have Object animation.
+ */
+ bool export_as_matrix = this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX;
+ if (export_as_matrix) {
+ export_matrix_animation(ob, sampler); // export all transform_curves as one single matrix animation
+ }
- if (ob->type == OB_ARMATURE) {
- /* Export skeletal animation (if any)*/
- bArmature *arm = (bArmature *)ob->data;
- for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
- write_bone_animation_matrix(ob, bone);
- }
+ export_curve_animation_set(ob, sampler, export_as_matrix);
- /* Armatures can have object animation and skeletal animation*/
- if (this->export_settings->sampling_rate < 1) {
- export_keyframed_animation_set(ob);
- }
- else {
- export_sampled_animation_set(ob);
- }
- }
+ if (ob->type == OB_ARMATURE) {
- export_object_constraint_animation(ob);
+#ifdef WITH_MORPH_ANIMATION
+ /* TODO: This needs to be handled by extra profiles, postponed for now */
+ export_morph_animation(ob);
+#endif
- //This needs to be handled by extra profiles, so postponed for now
- //export_morph_animation(ob);
+ /* Export skeletal animation (if any) */
+ bArmature *arm = (bArmature *)ob->data;
+ for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next)
+ export_bone_animations_recursive(ob, root_bone, sampler);
+ }
- //Export Lamp parameter animations
- if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
- FCurve *fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
- while (fcu) {
- transformName = extract_transform_name(fcu->rna_path);
+ close_animation_container(container_is_open);
+}
- if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
- (STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
- {
- create_keyframed_animation(ob, fcu, transformName, true);
- }
- fcu = fcu->next;
+/*
+ * Export all animation FCurves of an Object.
+ *
+ * Note: This uses the keyframes as sample points,
+ * and exports "baked keyframes" while keeping the tangent information
+ * of the FCurves intact. This works for simple cases, but breaks
+ * especially when negative scales are involved in the animation.
+ * And when parent inverse matrices are involved (when exporting
+ * object hierarchies)
+ *
+ */
+void AnimationExporter::export_curve_animation_set(Object *ob, BCAnimationSampler &sampler, bool export_as_matrix)
+{
+ BCAnimationCurveMap *curves = sampler.get_curves(ob);
+
+ BCAnimationCurveMap::iterator it;
+ for (it = curves->begin(); it != curves->end(); ++it) {
+ BCAnimationCurve &curve = *it->second;
+ if (curve.get_channel_target() == "rotation_quaternion") {
+ /*
+ Can not export Quaternion animation in Collada as far as i know)
+ Maybe automatically convert to euler rotation?
+ Discard for now.
+ */
+ continue;
+ }
+
+ if (export_as_matrix && curve.is_transform_curve()) {
+ /* All Transform curves will be exported within a single matrix animation,
+ * see export_matrix_animation()
+ * No need to export the curves here again.
+ */
+ continue;
}
- }
- //Export Camera parameter animations
- if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
- FCurve *fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
- while (fcu) {
- transformName = extract_transform_name(fcu->rna_path);
-
- if ((STREQ(transformName, "lens")) ||
- (STREQ(transformName, "ortho_scale")) ||
- (STREQ(transformName, "clip_end")) ||
- (STREQ(transformName, "clip_start")))
- {
- create_keyframed_animation(ob, fcu, transformName, true);
- }
- fcu = fcu->next;
+ if (!curve.is_animated()) {
+ continue;
}
- }
- //Export Material parameter animations.
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
- if (!ma) continue;
- if (ma->adt && ma->adt->action) {
- /* isMatAnim = true; */
- FCurve *fcu = (FCurve *)ma->adt->action->curves.first;
- while (fcu) {
- transformName = extract_transform_name(fcu->rna_path);
-
- if ((STREQ(transformName, "specular_hardness")) || (STREQ(transformName, "specular_color")) ||
- (STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
- (STREQ(transformName, "ior")))
- {
- create_keyframed_animation(ob, fcu, transformName, true, ma);
- }
- fcu = fcu->next;
- }
+ BCAnimationCurve *mcurve = get_modified_export_curve(ob, curve, *curves);
+ if (mcurve) {
+ export_curve_animation(ob, *mcurve);
+ delete mcurve;
+ }
+ else {
+ export_curve_animation(ob, curve);
}
}
}
-void AnimationExporter::export_object_constraint_animation(Object *ob)
+void AnimationExporter::export_matrix_animation(Object *ob, BCAnimationSampler &sampler)
{
- std::vector<float> fra;
- //Takes frames of target animations
- make_anim_frames_from_targets(ob, fra);
+ std::vector<float> frames;
+ sampler.get_object_frames(frames, ob);
+ if (frames.size() > 0) {
+ BCMatrixSampleMap samples;
+ bool is_animated = sampler.get_object_samples(samples, ob);
+ if (is_animated) {
+ bAction *action = bc_getSceneObjectAction(ob);
+ std::string name = encode_xml(id_name(ob));
+ std::string action_name = (action == NULL) ? name + "-action" : id_name(action);
+ std::string channel_type = "transform";
+ std::string axis = "";
+ std::string id = bc_get_action_id(action_name, name, channel_type, axis);
- if (fra.size())
- dae_baked_object_animation(fra, ob);
-}
+ std::string target = translate_id(name) + '/' + channel_type;
-void AnimationExporter::export_morph_animation(Object *ob)
-{
- FCurve *fcu;
- char *transformName;
- Key *key = BKE_key_from_object(ob);
- if (!key) return;
-
- if (key->adt && key->adt->action) {
- fcu = (FCurve *)key->adt->action->curves.first;
-
- while (fcu) {
- transformName = extract_transform_name(fcu->rna_path);
-
- create_keyframed_animation(ob, fcu, transformName, true);
-
- fcu = fcu->next;
+ export_collada_matrix_animation(id, name, target, frames, samples);
}
}
-
}
-void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames )
+//write bone animations in transform matrix sources
+void AnimationExporter::export_bone_animations_recursive(Object *ob, Bone *bone, BCAnimationSampler &sampler)
{
- ListBase *conlist = get_active_constraints(ob);
- if (conlist == NULL) return;
- bConstraint *con;
- for (con = (bConstraint *)conlist->first; con; con = con->next) {
- ListBase targets = {NULL, NULL};
-
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
-
- if (!validateConstraints(con)) continue;
-
- if (cti && cti->get_constraint_targets) {
- bConstraintTarget *ct;
- Object *obtar;
- /* get targets
- * - constraints should use ct->matrix, not directly accessing values
- * - ct->matrix members have not yet been calculated here!
- */
- cti->get_constraint_targets(con, &targets);
+ std::vector<float> frames;
+ sampler.get_bone_frames(frames, ob, bone);
- for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
- obtar = ct->tar;
-
- if (obtar)
- find_keyframes(obtar, frames);
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
+ if (frames.size()) {
+ BCMatrixSampleMap samples;
+ bool is_animated = sampler.get_bone_samples(samples, ob, bone);
+ if (is_animated) {
+ export_bone_animation(ob, bone, frames, samples);
}
}
+
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
+ export_bone_animations_recursive(ob, child, sampler);
}
-//euler sources from quternion sources
-float *AnimationExporter::get_eul_source_for_quat(Object *ob)
-{
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
- const int keys = fcu->totvert;
- float *quat = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");
- float *eul = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
- float temp_quat[4];
- float temp_eul[3];
- while (fcu) {
- char *transformName = extract_transform_name(fcu->rna_path);
-
- if (STREQ(transformName, "rotation_quaternion") ) {
- for (int i = 0; i < fcu->totvert; i++) {
- *(quat + (i * 4) + fcu->array_index) = fcu->bezt[i].vec[1][1];
+/*
+* In some special cases the exported Curve needs to be replaced
+* by a modified curve (for collada purposes)
+* This method checks if a conversion is necessary and if applicable
+* returns a pointer to the modified BCAnimationCurve.
+* IMPORTANT: the modified curve must be deleted by the caller when no longer needed
+* if no conversion is needed this method returns a NULL;
+*/
+BCAnimationCurve *AnimationExporter::get_modified_export_curve(Object *ob, BCAnimationCurve &curve, BCAnimationCurveMap &curves)
+{
+ std::string channel_target = curve.get_channel_target();
+ BCAnimationCurve *mcurve = NULL;
+ if (channel_target == "lens") {
+
+ /* Create an xfov curve */
+
+ BCCurveKey key(BC_ANIMATION_TYPE_CAMERA, "xfov", 0);
+ mcurve = new BCAnimationCurve(key, ob);
+
+ // now tricky part: transform the fcurve
+ BCValueMap lens_values;
+ curve.get_value_map(lens_values);
+
+ BCAnimationCurve *sensor_curve = NULL;
+ BCCurveKey sensor_key(BC_ANIMATION_TYPE_CAMERA, "sensor_width", 0);
+ BCAnimationCurveMap::iterator cit = curves.find(sensor_key);
+ if (cit != curves.end()) {
+ sensor_curve = cit->second;
+ }
+
+ BCValueMap::const_iterator vit;
+ for (vit = lens_values.begin(); vit != lens_values.end(); ++vit) {
+ int frame = vit->first;
+ float lens_value = vit->second;
+
+ float sensor_value;
+ if (sensor_curve) {
+ sensor_value = sensor_curve->get_value(frame);
+ }
+ else {
+ sensor_value = ((Camera *)ob->data)->sensor_x;
}
+ float value = RAD2DEGF(focallength_to_fov(lens_value, sensor_value));
+ mcurve->add_value(value, frame);
}
- fcu = fcu->next;
+ mcurve->clean_handles(); // to reset the handles
}
-
- for (int i = 0; i < keys; i++) {
- for (int j = 0; j < 4; j++)
- temp_quat[j] = quat[(i * 4) + j];
-
- quat_to_eul(temp_eul, temp_quat);
-
- for (int k = 0; k < 3; k++)
- eul[i * 3 + k] = temp_eul[k];
-
- }
- MEM_freeN(quat);
- return eul;
-
-}
-
-//Get proper name for bones
-std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu)
-{
- //hard-way to derive the bone name from rna_path. Must find more compact method
- std::string rna_path = std::string(fcu->rna_path);
-
- char *boneName = strtok((char *)rna_path.c_str(), "\"");
- boneName = strtok(NULL, "\"");
-
- if (boneName != NULL)
- return /*id_name(ob) + "_" +*/ std::string(boneName);
- else
- return id_name(ob);
+ return mcurve;
}
-std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
+void AnimationExporter::export_curve_animation(
+ Object *ob,
+ BCAnimationCurve &curve)
{
- std::string rna_path = std::string(fcu->rna_path);
- return translate_id(rna_path);
-}
-
-/* convert f-curves to animation curves and write */
-void AnimationExporter::create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
-{
- const char *axis_name = NULL;
- char anim_id[200];
-
- bool has_tangents = false;
- bool quatRotation = false;
-
- Object *obj = NULL;
-
- if (STREQ(transformName, "rotation_quaternion") ) {
- fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
- quatRotation = true;
- return;
- }
-
- //axis names for colors
- else if (STREQ(transformName, "color") ||
- STREQ(transformName, "specular_color") ||
- STREQ(transformName, "diffuse_color") ||
- STREQ(transformName, "alpha"))
- {
- const char *axis_names[] = {"R", "G", "B"};
- if (fcu->array_index < 3)
- axis_name = axis_names[fcu->array_index];
- }
+ std::string channel_target = curve.get_channel_target();
/*
- * Note: Handle transformation animations separately (to apply matrix inverse to fcurves)
- * We will use the object to evaluate the animation on all keyframes and calculate the
- * resulting object matrix. We need this to incorporate the
- * effects of the parent inverse matrix (when it contains a rotation component)
- *
- * TODO: try to combine exported fcurves into 3 channel animations like done
- * in export_sampled_animation(). For now each channel is exported as separate <Animation>.
+ * Some curves can not be exported as is and need some conversion
+ * For more information see implementation oif get_modified_export_curve()
+ * note: if mcurve is not NULL then it must be deleted at end of this method;
*/
- else if (
- STREQ(transformName, "scale") ||
- STREQ(transformName, "location") ||
- STREQ(transformName, "rotation_euler"))
- {
- const char *axis_names[] = {"X", "Y", "Z"};
- if (fcu->array_index < 3) {
- axis_name = axis_names[fcu->array_index];
- obj = ob;
- }
- }
- else {
- /* no axis name. single parameter */
- axis_name = "";
- }
+ int channel_index = curve.get_channel_index();
+ std::string axis = get_axis_name(channel_target, channel_index); // RGB or XYZ or ""
- std::string ob_name = std::string("null");
+ std::string action_name;
+ bAction *action = bc_getSceneObjectAction(ob);
+ action_name = (action) ? id_name(action) : "constraint_anim";
- /* Create anim Id */
- if (ob->type == OB_ARMATURE) {
- ob_name = getObjectBoneName(ob, fcu);
- BLI_snprintf(
- anim_id,
- sizeof(anim_id),
- "%s_%s.%s",
- (char *)translate_id(ob_name).c_str(),
- (char *)translate_id(transformName).c_str(),
- axis_name);
- }
- else {
- if (ma)
- ob_name = id_name(ob) + "_material";
- else
- ob_name = id_name(ob);
-
- BLI_snprintf(
- anim_id,
- sizeof(anim_id),
- "%s_%s_%s",
- (char *)translate_id(ob_name).c_str(),
- (char *)getAnimationPathId(fcu).c_str(),
- axis_name);
- }
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
-
- // create input source
- std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
+ const std::string curve_name = encode_xml(curve.get_animation_name(ob));
+ std::string id = bc_get_action_id(action_name, curve_name, channel_target, axis, ".");
- // create output source
- std::string output_id;
+ std::string collada_target = translate_id(curve_name);
- //quat rotations are skipped for now, because of complications with determining axis.
- if (quatRotation) {
- float *eul = get_eul_source_for_quat(ob);
- float *eul_axis = (float *)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
- for (int i = 0; i < fcu->totvert; i++) {
- eul_axis[i] = eul[i * 3 + fcu->array_index];
+ if (curve.is_of_animation_type(BC_ANIMATION_TYPE_MATERIAL)) {
+ int material_index = curve.get_subindex();
+ Material *ma = give_current_material(ob, material_index + 1);
+ if (ma) {
+ collada_target = translate_id(id_name(ma)) + "-effect/common/" + get_collada_sid(curve, axis);
}
- output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis, fcu->totvert, quatRotation, anim_id, axis_name);
- MEM_freeN(eul);
- MEM_freeN(eul_axis);
- }
- else if (STREQ(transformName, "lens") && (ob->type == OB_CAMERA)) {
- output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
}
else {
- output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name, obj);
+ collada_target += "/" + get_collada_sid(curve, axis);
}
- // create interpolations source
- std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
-
- // handle tangents (if required)
- std::string intangent_id;
- std::string outtangent_id;
+ export_collada_curve_animation(id, curve_name, collada_target, axis, curve);
- if (has_tangents) {
- // create in_tangent source
- intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name, obj);
-
- // create out_tangent source
- outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name, obj);
- }
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
- COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
-
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
-
- if (has_tangents) {
- sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
- sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
- }
-
- addSampler(sampler);
-
- std::string target;
-
- if (!is_param)
- target = translate_id(ob_name) +
- "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
- else {
- if (ob->type == OB_LAMP)
- target = get_light_id(ob) +
- "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
-
- if (ob->type == OB_CAMERA)
- target = get_camera_id(ob) +
- "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
-
- if (ma)
- target = translate_id(id_name(ma)) + "-effect" +
- "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
- //if shape key animation, this is the main problem, how to define the channel targets.
- /*target = get_morph_id(ob) +
- "/value" +*/
- }
- addChannel(COLLADABU::URI(empty, sampler_id), target);
-
- closeAnimation();
}
-
-
-//write bone animations in transform matrix sources
-void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
+void AnimationExporter::export_bone_animation(Object *ob, Bone *bone, BCFrames &frames, BCMatrixSampleMap &samples)
{
- if (!ob_arm->adt)
- return;
-
- //This will only export animations of bones in deform group.
- /* if (!is_bone_deform_group(bone)) return; */
+ bAction* action = bc_getSceneObjectAction(ob);
+ std::string bone_name(bone->name);
+ std::string name = encode_xml(id_name(ob));
+ std::string id = bc_get_action_id(id_name(action), name, bone_name, "pose_matrix");
+ std::string target = translate_id(id_name(ob) + "_" + bone_name) + "/transform";
- sample_and_write_bone_animation_matrix(ob_arm, bone);
-
- for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
- write_bone_animation_matrix(ob_arm, child);
+ export_collada_matrix_animation(id, name, target, frames, samples);
}
bool AnimationExporter::is_bone_deform_group(Bone *bone)
@@ -691,204 +377,86 @@ bool AnimationExporter::is_bone_deform_group(Bone *bone)
return false;
}
-void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
-{
- bArmature *arm = (bArmature *)ob_arm->data;
- int flag = arm->flag;
- std::vector<float> fra;
- //char prefix[256];
-
- //Check if there is a fcurve in the armature for the bone in param
- //when baking this check is not needed, solve every bone for every frame.
- /*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
-
- while (fcu) {
- std::string bone_name = getObjectBoneName(ob_arm, fcu);
- int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
- if (val == 0) break;
- fcu = fcu->next;
- }
- if (!(fcu)) return;*/
+void AnimationExporter::export_collada_curve_animation(
+ std::string id,
+ std::string name,
+ std::string collada_target,
+ std::string axis,
+ BCAnimationCurve &curve)
+{
+ BCFrames frames;
+ BCValues values;
+ curve.get_frames(frames);
+ curve.get_values(values);
+ std::string channel_target = curve.get_channel_target();
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
- if (!pchan)
- return;
+ fprintf(stdout, "Export animation curve %s (%d control points)\n", id.c_str(), int(frames.size()));
+ openAnimation(id, name);
+ BC_animation_source_type source_type = (curve.is_rotation_curve()) ? BC_SOURCE_TYPE_ANGLE : BC_SOURCE_TYPE_VALUE;
+ std::string input_id = collada_source_from_values(BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, axis);
+ std::string output_id = collada_source_from_values(source_type, COLLADASW::InputSemantic::OUTPUT, values, id, axis);
- if (this->export_settings->sampling_rate < 1)
- find_keyframes(ob_arm, fra);
+ bool has_tangents = false;
+ std::string interpolation_id;
+ if (this->export_settings->keep_smooth_curves)
+ interpolation_id = collada_interpolation_source(curve, id, axis, &has_tangents);
else
- find_sampleframes(ob_arm, fra);
+ interpolation_id = collada_linear_interpolation_source(frames.size(), id);
- if (flag & ARM_RESTPOS) {
- arm->flag &= ~ARM_RESTPOS;
- BKE_pose_where_is(scene, ob_arm);
- }
-
- if (fra.size()) {
- dae_baked_animation(fra, ob_arm, bone);
+ std::string intangent_id;
+ std::string outtangent_id;
+ if (has_tangents) {
+ intangent_id = collada_tangent_from_curve(COLLADASW::InputSemantic::IN_TANGENT, curve, id, axis);
+ outtangent_id = collada_tangent_from_curve(COLLADASW::InputSemantic::OUT_TANGENT, curve, id, axis);
}
- if (flag & ARM_RESTPOS)
- arm->flag = flag;
- BKE_pose_where_is(scene, ob_arm);
-}
-
-void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
-{
- std::string ob_name = id_name(ob_arm);
- std::string bone_name = bone->name;
- char anim_id[200];
-
- if (!fra.size())
- return;
-
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
- (char *)translate_id(bone_name).c_str(), "pose_matrix");
+ std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
-
- // create input source
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
-
- // create output source
- std::string output_id;
-
- output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
-
- // create interpolations source
- std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
- // TODO create in/out tangents source
+ sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id));
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(EMPTY_STRING, interpolation_id));
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+ if (has_tangents) {
+ sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(EMPTY_STRING, intangent_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(EMPTY_STRING, outtangent_id));
+ }
addSampler(sampler);
-
- std::string target = get_joint_id(ob_arm, bone) + "/transform";
- addChannel(COLLADABU::URI(empty, sampler_id), target);
+ addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), collada_target);
closeAnimation();
}
-void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob)
+void AnimationExporter::export_collada_matrix_animation(std::string id, std::string name, std::string target, BCFrames &frames, BCMatrixSampleMap &samples)
{
- std::string ob_name = id_name(ob);
- char anim_id[200];
-
- if (!fra.size())
- return;
+ fprintf(stdout, "Export animation matrix %s (%d control points)\n", id.c_str(), int(frames.size()));
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char *)translate_id(ob_name).c_str(),
- "object_matrix");
+ openAnimationWithClip(id, name);
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
+ std::string input_id = collada_source_from_values(BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, "");
+ std::string output_id = collada_source_from_values(samples, id);
+ std::string interpolation_id = collada_linear_interpolation_source(frames.size(), id);
- // create input source
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
-
- // create output source
- std::string output_id;
- output_id = create_4x4_source( fra, ob, NULL, anim_id);
-
- // create interpolations source
- std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
+ std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
- // TODO create in/out tangents source
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
-
- addSampler(sampler);
+ sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id));
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(EMPTY_STRING, interpolation_id));
- std::string target = translate_id(ob_name) + "/transform";
- addChannel(COLLADABU::URI(empty, sampler_id), target);
-
- closeAnimation();
-}
-
-// dae_bone_animation -> add_bone_animation
-// (blend this into dae_bone_animation)
-void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
-{
- const char *axis_names[] = {"X", "Y", "Z"};
- const char *axis_name = NULL;
- char anim_id[200];
- bool is_rot = tm_type == 0;
-
- if (!fra.size())
- return;
-
- char rna_path[200];
- BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
- tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
-
- if (axis > -1)
- axis_name = axis_names[axis];
-
- std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
-
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
- (char *)translate_id(bone_name).c_str(), (char *)transform_sid.c_str());
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
-
- // create input source
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
-
- // create output source
- std::string output_id;
- if (axis == -1)
- output_id = create_xyz_source(values, fra.size(), anim_id);
- else
- output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
-
- // create interpolations source
- std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
- COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
-
- // TODO create in/out tangents source
-
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+ // Matrix animation has no tangents
addSampler(sampler);
-
- std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
- addChannel(COLLADABU::URI(empty, sampler_id), target);
+ addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), target);
closeAnimation();
}
-float AnimationExporter::convert_time(float frame)
-{
- return FRA2TIME(frame);
-}
-
-float AnimationExporter::convert_angle(float angle)
-{
- return COLLADABU::Math::Utils::radToDegF(angle);
-}
-
std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
{
switch (semantic) {
@@ -909,7 +477,10 @@ std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Sem
}
void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
- COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
+ COLLADASW::InputSemantic::Semantics semantic,
+ bool is_rot,
+ const std::string axis,
+ bool transform)
{
switch (semantic) {
case COLLADASW::InputSemantic::INPUT:
@@ -920,7 +491,7 @@ void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNa
param.push_back("ANGLE");
}
else {
- if (axis) {
+ if (axis != "") {
param.push_back(axis);
}
else
@@ -944,262 +515,83 @@ void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNa
}
}
-void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values, int *length)
+std::string AnimationExporter::collada_tangent_from_curve(COLLADASW::InputSemantic::Semantics semantic, BCAnimationCurve &curve, const std::string& anim_id, std::string axis_name)
{
- switch (semantic) {
- case COLLADASW::InputSemantic::INPUT:
- *length = 1;
- values[0] = convert_time(bezt->vec[1][0]);
- break;
- case COLLADASW::InputSemantic::OUTPUT:
- *length = 1;
- if (is_angle) {
- values[0] = RAD2DEGF(bezt->vec[1][1]);
- }
- else {
- values[0] = bezt->vec[1][1];
- }
- break;
+ Scene *scene = blender_context.get_scene();
+ std::string channel = curve.get_channel_target();
- case COLLADASW::InputSemantic::IN_TANGENT:
- *length = 2;
- values[0] = convert_time(bezt->vec[0][0]);
- if (bezt->ipo != BEZT_IPO_BEZ) {
- // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
- values[0] = 0;
- values[1] = 0;
- }
- else if (is_angle) {
- values[1] = RAD2DEGF(bezt->vec[0][1]);
- }
- else {
- values[1] = bezt->vec[0][1];
- }
- break;
+ const std::string source_id = anim_id + get_semantic_suffix(semantic);
- case COLLADASW::InputSemantic::OUT_TANGENT:
- *length = 2;
- values[0] = convert_time(bezt->vec[2][0]);
- if (bezt->ipo != BEZT_IPO_BEZ) {
- // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
- values[0] = 0;
- values[1] = 0;
- }
- else if (is_angle) {
- values[1] = RAD2DEGF(bezt->vec[2][1]);
- }
- else {
- values[1] = bezt->vec[2][1];
- }
- break;
- default:
- *length = 0;
- break;
- }
-}
-
-// old function to keep compatibility for calls where offset and object are not needed
-std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
-{
- return create_source_from_fcurve(semantic, fcu, anim_id, axis_name, NULL);
-}
-
-void AnimationExporter::evaluate_anim_with_constraints(Object *ob, float ctime)
-{
- BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
- ListBase *conlist = get_active_constraints(ob);
- bConstraint *con;
- for (con = (bConstraint *)conlist->first; con; con = con->next) {
- ListBase targets = { NULL, NULL };
-
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
-
- if (cti && cti->get_constraint_targets) {
- bConstraintTarget *ct;
- Object *obtar;
- cti->get_constraint_targets(con, &targets);
- for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
- obtar = ct->tar;
-
- if (obtar) {
- BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
- BKE_object_where_is_calc_time(scene, obtar, ctime);
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- BKE_object_where_is_calc_time(scene, ob, ctime);
-}
-
-/*
- * ob is needed to aply parent inverse information to fcurve.
- * TODO: Here we have to step over all keyframes for each object and for each fcurve.
- * Instead of processing each fcurve one by one,
- * step over the animation from keyframe to keyframe,
- * then create adjusted fcurves (and entries) for all affected objects.
- * Then we would need to step through the scene only once.
- */
-std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob)
-{
- std::string source_id = anim_id + get_semantic_suffix(semantic);
-
- bool is_angle = (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path, "spot_size"));
- bool is_euler = strstr(fcu->rna_path, "rotation_euler");
- bool is_translation = strstr(fcu->rna_path, "location");
- bool is_scale = strstr(fcu->rna_path, "scale");
- bool is_tangent = false;
- int offset_index = 0;
+ bool is_angle = (bc_startswith(channel, "rotation") || channel == "spot_size");
COLLADASW::FloatSourceF source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fcu->totvert);
-
- switch (semantic) {
- case COLLADASW::InputSemantic::INPUT:
- case COLLADASW::InputSemantic::OUTPUT:
- source.setAccessorStride(1);
- offset_index = 0;
- break;
- case COLLADASW::InputSemantic::IN_TANGENT:
- case COLLADASW::InputSemantic::OUT_TANGENT:
- source.setAccessorStride(2);
- offset_index = 1;
- is_tangent = true;
- break;
- default:
- break;
- }
+ source.setAccessorCount(curve.sample_count());
+ source.setAccessorStride(2);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
add_source_parameters(param, semantic, is_angle, axis_name, false);
source.prepareToAppendValues();
- for (unsigned int frame_index = 0; frame_index < fcu->totvert; frame_index++) {
- float fixed_val = 0;
- if (ob) {
- float fmat[4][4];
- float frame = fcu->bezt[frame_index].vec[1][0];
- float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
-
- evaluate_anim_with_constraints(ob, ctime); // set object transforms to fcurve's i'th keyframe
-
- BKE_object_matrix_local_get(ob, fmat);
- float floc[3];
- float fquat[4];
- float fsize[3];
- mat4_decompose(floc, fquat, fsize, fmat);
-
- if (is_euler) {
- float eul[3];
- quat_to_eul(eul, fquat);
- fixed_val = RAD2DEGF(eul[fcu->array_index]);
- }
- else if (is_translation) {
- fixed_val = floc[fcu->array_index];
- }
- else if (is_scale) {
- fixed_val = fsize[fcu->array_index];
- }
- }
+ const FCurve *fcu = curve.get_fcurve();
+ int tangent = (semantic == COLLADASW::InputSemantic::IN_TANGENT) ? 0 : 2;
- float values[3]; // be careful!
- float offset = 0;
- int length = 0;
- get_source_values(&fcu->bezt[frame_index], semantic, is_angle, values, &length);
- if (is_tangent) {
- float bases[3];
- int len = 0;
- get_source_values(&fcu->bezt[frame_index], COLLADASW::InputSemantic::OUTPUT, is_angle, bases, &len);
- offset = values[offset_index] - bases[0];
- }
+ for (int i = 0; i < fcu->totvert; ++i) {
+ BezTriple &bezt = fcu->bezt[i];
- for (int j = 0; j < length; j++) {
- float val;
- if (j == offset_index) {
- if (ob) {
- val = fixed_val + offset;
- }
- else {
- val = values[j] + offset;
- }
- } else {
- val = values[j];
- }
- source.appendValues(val);
- }
- }
-
- source.finish();
+ float sampled_time = bezt.vec[tangent][0];
+ float sampled_val = bezt.vec[tangent][1];
- return source_id;
-}
-
-/*
- * Similar to create_source_from_fcurve, but adds conversion of lens
- * animation data from focal length to FOV.
- */
-std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id)
-{
- std::string source_id = anim_id + get_semantic_suffix(semantic);
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fcu->totvert);
-
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, false, "", false);
+ if (is_angle) {
+ sampled_val = RAD2DEGF(sampled_val);
+ }
- source.prepareToAppendValues();
+ source.appendValues(FRA2TIME(sampled_time));
+ source.appendValues(sampled_val);
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- float values[3]; // be careful!
- int length = 0;
- get_source_values(&fcu->bezt[i], semantic, false, values, &length);
- for (int j = 0; j < length; j++)
- {
- float val = RAD2DEGF(focallength_to_fov(values[j], cam->sensor_x));
- source.appendValues(val);
- }
}
-
source.finish();
-
return source_id;
}
-/*
- * only to get OUTPUT source values ( if rotation and hence the axis is also specified )
- */
-std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
+std::string AnimationExporter::collada_source_from_values(
+ BC_animation_source_type source_type,
+ COLLADASW::InputSemantic::Semantics semantic,
+ std::vector<float> &values,
+ const std::string& anim_id,
+ const std::string axis_name)
{
+ Scene *scene = blender_context.get_scene();
+ /* T can be float, int or double */
+
+ int stride = 1;
+ int entry_count = values.size() / stride;
std::string source_id = anim_id + get_semantic_suffix(semantic);
COLLADASW::FloatSourceF source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(tot);
- source.setAccessorStride(1);
+ source.setAccessorCount(entry_count);
+ source.setAccessorStride(stride);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, is_rot, axis_name, false);
+ add_source_parameters(param, semantic, source_type== BC_SOURCE_TYPE_ANGLE, axis_name, false);
source.prepareToAppendValues();
- for (int i = 0; i < tot; i++) {
- float val = v[i];
- ////if (semantic == COLLADASW::InputSemantic::INPUT)
- // val = convert_time(val);
- //else
- if (is_rot)
+ for (int i = 0; i < entry_count; i++) {
+ float val = values[i];
+ switch (source_type) {
+ case BC_SOURCE_TYPE_TIMEFRAME:
+ val = FRA2TIME(val);
+ break;
+ case BC_SOURCE_TYPE_ANGLE:
val = RAD2DEGF(val);
+ break;
+ default: break;
+ }
source.appendValues(val);
}
@@ -1209,39 +601,9 @@ std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic
}
/*
- * only used for sources with INPUT semantic
- */
-std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name)
-{
- std::string source_id = anim_id + get_semantic_suffix(semantic);
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fra.size());
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, is_rot, axis_name, false);
-
- source.prepareToAppendValues();
-
- std::vector<float>::iterator it;
- for (it = fra.begin(); it != fra.end(); it++) {
- float val = *it;
- //if (semantic == COLLADASW::InputSemantic::INPUT)
- val = convert_time(val);
- /*else if (is_rot)
- val = convert_angle(val);*/
- source.appendValues(val);
- }
-
- source.finish();
-
- return source_id;
-}
-
-std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id)
+ * Create a collada matrix source for a set of samples
+*/
+std::string AnimationExporter::collada_source_from_values(BCMatrixSampleMap &samples, const std::string &anim_id)
{
COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -1249,180 +611,38 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std
COLLADASW::Float4x4Source source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(ctimes.size());
+ source.setAccessorCount(samples.size());
source.setAccessorStride(16);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, false, NULL, true);
+ add_source_parameters(param, semantic, false, "", true);
source.prepareToAppendValues();
- std::vector<float>::iterator it;
-
- for (it = values.begin(); it != values.end(); it+=16) {
- float mat[4][4];
-
- bc_copy_m4_farray(mat, &*it);
-
- UnitConverter converter;
- double outmat[4][4];
- converter.mat4_to_dae_double(outmat, mat);
-
- if (this->export_settings->limit_precision)
- bc_sanitize_mat(outmat, 6);
-
- source.appendValues(outmat);
+ BCMatrixSampleMap::iterator it;
+ int precision = (this->export_settings->limit_precision) ? 6 : -1; // could be made configurable
+ for (it = samples.begin(); it != samples.end(); it++) {
+ const BCMatrix *sample = it->second;
+ double daemat[4][4];
+ sample->get_matrix(daemat, true, precision);
+ source.appendValues(daemat);
}
source.finish();
return source_id;
}
-std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
-{
- bool is_bone_animation = ob->type == OB_ARMATURE && bone;
-
- COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
- std::string source_id = anim_id + get_semantic_suffix(semantic);
-
- COLLADASW::Float4x4Source source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(frames.size());
- source.setAccessorStride(16);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, false, NULL, true);
-
- source.prepareToAppendValues();
-
- bPoseChannel *parchan = NULL;
- bPoseChannel *pchan = NULL;
-
- if (is_bone_animation) {
- bPose *pose = ob->pose;
- pchan = BKE_pose_channel_find_name(pose, bone->name);
- if (!pchan)
- return "";
-
- parchan = pchan->parent;
-
- enable_fcurves(ob->adt->action, bone->name);
- }
-
- std::vector<float>::iterator it;
- int j = 0;
- for (it = frames.begin(); it != frames.end(); it++) {
- float mat[4][4], ipar[4][4];
- float frame = *it;
-
- float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
- bc_update_scene(m_bmain, scene, ctime);
- if (is_bone_animation) {
- if (pchan->flag & POSE_CHAIN) {
- enable_fcurves(ob->adt->action, NULL);
- BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
- BKE_pose_where_is(scene, ob);
- }
- else {
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
- }
-
- // compute bone local mat
- if (bone->parent) {
- invert_m4_m4(ipar, parchan->pose_mat);
- mul_m4_m4m4(mat, ipar, pchan->pose_mat);
- }
- else
- copy_m4_m4(mat, pchan->pose_mat);
-
- /* OPEN_SIM_COMPATIBILITY
- * AFAIK animation to second life is via BVH, but no
- * reason to not have the collada-animation be correct
- */
- if (export_settings->open_sim) {
- float temp[4][4];
- copy_m4_m4(temp, bone->arm_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- invert_m4(temp);
-
- mul_m4_m4m4(mat, mat, temp);
-
- if (bone->parent) {
- copy_m4_m4(temp, bone->parent->arm_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
-
- mul_m4_m4m4(mat, temp, mat);
- }
- }
-
- }
- else {
- copy_m4_m4(mat, ob->obmat);
- }
-
- UnitConverter converter;
-
- double outmat[4][4];
- converter.mat4_to_dae_double(outmat, mat);
-
- if (this->export_settings->limit_precision)
- bc_sanitize_mat(outmat, 6);
-
- source.appendValues(outmat);
-
- j++;
-
- BIK_release_tree(scene, ob, ctime);
- }
-
- if (ob->adt) {
- enable_fcurves(ob->adt->action, NULL);
- }
-
- source.finish();
-
- return source_id;
-}
-
-
-/*
- * only used for sources with OUTPUT semantic ( locations and scale)
- */
-std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
-{
- COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
- std::string source_id = anim_id + get_semantic_suffix(semantic);
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(tot);
- source.setAccessorStride(3);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, false, NULL, false);
-
- source.prepareToAppendValues();
-
- for (int i = 0; i < tot; i++) {
- source.appendValues(*v, *(v + 1), *(v + 2));
- v += 3;
- }
-
- source.finish();
-
- return source_id;
-}
-
-std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
+std::string AnimationExporter::collada_interpolation_source(const BCAnimationCurve &curve,
+ const std::string& anim_id,
+ const std::string axis,
+ bool *has_tangents)
{
std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
COLLADASW::NameSource source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fcu->totvert);
+ source.setAccessorCount(curve.sample_count());
source.setAccessorStride(1);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
@@ -1432,12 +652,17 @@ std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const st
*has_tangents = false;
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- if (fcu->bezt[i].ipo == BEZT_IPO_BEZ) {
+ std::vector<float>frames;
+ curve.get_frames(frames);
+
+ for (unsigned int i = 0; i < curve.sample_count(); i++) {
+ float frame = frames[i];
+ int ipo = curve.get_interpolation_type(frame);
+ if (ipo == BEZT_IPO_BEZ) {
source.appendValues(BEZIER_NAME);
*has_tangents = true;
}
- else if (fcu->bezt[i].ipo == BEZT_IPO_CONST) {
+ else if (ipo == BEZT_IPO_CONST) {
source.appendValues(STEP_NAME);
}
else { // BEZT_IPO_LIN
@@ -1451,7 +676,7 @@ std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const st
return source_id;
}
-std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
+std::string AnimationExporter::collada_linear_interpolation_source(int tot, const std::string& anim_id)
{
std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
@@ -1475,474 +700,102 @@ std::string AnimationExporter::fake_interpolation_source(int tot, const std::str
return source_id;
}
-std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
-{
- std::string tm_name;
- // when given rna_path, determine tm_type from it
- if (rna_path) {
- char *name = extract_transform_name(rna_path);
-
- if (STREQ(name, "color"))
- tm_type = 1;
- else if (STREQ(name, "spot_size"))
- tm_type = 2;
- else if (STREQ(name, "spot_blend"))
- tm_type = 3;
- else if (STREQ(name, "distance"))
- tm_type = 4;
- else
- tm_type = -1;
- }
-
- switch (tm_type) {
- case 1:
- tm_name = "color";
- break;
- case 2:
- tm_name = "fall_off_angle";
- break;
- case 3:
- tm_name = "fall_off_exponent";
- break;
- case 4:
- tm_name = "blender/blender_dist";
- break;
-
- default:
- tm_name = "";
- break;
- }
-
- if (tm_name.size()) {
- if (axis_name[0])
- return tm_name + "." + std::string(axis_name);
- else
- return tm_name;
- }
-
- return std::string("");
-}
-
-std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
+const std::string AnimationExporter::get_collada_name(std::string channel_target) const
{
- std::string tm_name;
- // when given rna_path, determine tm_type from it
- if (rna_path) {
- char *name = extract_transform_name(rna_path);
-
- if (STREQ(name, "lens"))
- tm_type = 0;
- else if (STREQ(name, "ortho_scale"))
- tm_type = 1;
- else if (STREQ(name, "clip_end"))
- tm_type = 2;
- else if (STREQ(name, "clip_start"))
- tm_type = 3;
-
- else
- tm_type = -1;
- }
-
- switch (tm_type) {
- case 0:
- tm_name = "xfov";
- break;
- case 1:
- tm_name = "xmag";
- break;
- case 2:
- tm_name = "zfar";
- break;
- case 3:
- tm_name = "znear";
- break;
-
- default:
- tm_name = "";
- break;
- }
-
- if (tm_name.size()) {
- if (axis_name[0])
- return tm_name + "." + std::string(axis_name);
- else
- return tm_name;
- }
-
- return std::string("");
+ /*
+ * Translation table to map FCurve animation types to Collada animation.
+ * Todo: Maybe we can keep the names from the fcurves here instead of
+ * mapping. However this is what i found in the old code. So keep
+ * this map for now.
+ */
+ static std::map<std::string, std::string> BC_CHANNEL_BLENDER_TO_COLLADA = {
+ { "rotation", "rotation" },
+ { "rotation_euler", "rotation" },
+ { "rotation_quaternion", "rotation" },
+ { "scale", "scale" },
+ { "location", "location" },
+
+ /* Materials */
+ { "specular_color", "specular" },
+ { "diffuse_color", "diffuse" },
+ { "ior", "index_of_refraction" },
+ { "specular_hardness", "specular_hardness" },
+ { "alpha", "alpha" },
+
+ /* Lamps */
+ { "color", "color" },
+ { "fall_off_angle", "falloff_angle" },
+ { "spot_size", "falloff_angle" },
+ { "fall_off_exponent", "falloff_exponent" },
+ { "spot_blend", "falloff_exponent" },
+ { "blender/blender_dist", "blender/blender_dist" }, // special blender profile (todo: make this more elegant)
+ { "distance", "blender/blender_dist" }, // special blender profile (todo: make this more elegant)
+
+ /* Cameras */
+ { "lens", "xfov" },
+ { "xfov", "xfov" },
+ { "xmag", "xmag" },
+ { "zfar", "zfar" },
+ { "znear", "znear" },
+ { "ortho_scale", "xmag" },
+ { "clip_end", "zfar" },
+ { "clip_start", "znear" }
+ };
+
+ std::map<std::string, std::string>::iterator name_it = BC_CHANNEL_BLENDER_TO_COLLADA.find(channel_target);
+ if (name_it == BC_CHANNEL_BLENDER_TO_COLLADA.end())
+ return "";
+
+ std::string tm_name = name_it->second;
+ return tm_name;
}
/*
* Assign sid of the animated parameter or transform for rotation,
* axis name is always appended and the value of append_axis is ignored
*/
-std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
+std::string AnimationExporter::get_collada_sid(const BCAnimationCurve &curve, const std::string axis_name)
{
- std::string tm_name;
- bool is_angle = false;
- // when given rna_path, determine tm_type from it
- if (rna_path) {
- char *name = extract_transform_name(rna_path);
-
- if (STREQ(name, "rotation_euler"))
- tm_type = 0;
- else if (STREQ(name, "rotation_quaternion"))
- tm_type = 1;
- else if (STREQ(name, "scale"))
- tm_type = 2;
- else if (STREQ(name, "location"))
- tm_type = 3;
- else if (STREQ(name, "specular_hardness"))
- tm_type = 4;
- else if (STREQ(name, "specular_color"))
- tm_type = 5;
- else if (STREQ(name, "diffuse_color"))
- tm_type = 6;
- else if (STREQ(name, "alpha"))
- tm_type = 7;
- else if (STREQ(name, "ior"))
- tm_type = 8;
+ std::string channel_target = curve.get_channel_target();
+ std::string tm_name = get_collada_name(channel_target);
- else
- tm_type = -1;
- }
+ bool is_angle = curve.is_rotation_curve();
- switch (tm_type) {
- case 0:
- case 1:
- tm_name = "rotation";
- is_angle = true;
- break;
- case 2:
- tm_name = "scale";
- break;
- case 3:
- tm_name = "location";
- break;
- case 4:
- tm_name = "shininess";
- break;
- case 5:
- tm_name = "specular";
- break;
- case 6:
- tm_name = "diffuse";
- break;
- case 7:
- tm_name = "transparency";
- break;
- case 8:
- tm_name = "index_of_refraction";
- break;
-
- default:
- tm_name = "";
- break;
- }
if (tm_name.size()) {
if (is_angle)
return tm_name + std::string(axis_name) + ".ANGLE";
else
- if (axis_name[0])
- return tm_name + "." + std::string(axis_name);
- else
- return tm_name;
- }
-
- return std::string("");
-}
-
-char *AnimationExporter::extract_transform_name(char *rna_path)
-{
- char *dot = strrchr(rna_path, '.');
- return dot ? (dot + 1) : rna_path;
-}
-
-/*
- * enable fcurves driving a specific bone, disable all the rest
- * if bone_name = NULL enable all fcurves
- */
-void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
-{
- FCurve *fcu;
- char prefix[200];
-
- if (bone_name)
- BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
-
- for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
- if (bone_name) {
- if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
- fcu->flag &= ~FCURVE_DISABLED;
+ if (axis_name != "")
+ return tm_name + "." + std::string(axis_name);
else
- fcu->flag |= FCURVE_DISABLED;
- }
- else {
- fcu->flag &= ~FCURVE_DISABLED;
- }
+ return tm_name;
}
-}
-bool AnimationExporter::hasAnimations(Scene *sce)
-{
- LinkNode *node;
-
- for (node=this->export_settings->export_set; node; node=node->next) {
- Object *ob = (Object *)node->link;
-
- FCurve *fcu = 0;
- //Check for object transform animations
- if (ob->adt && ob->adt->action)
- fcu = (FCurve *)ob->adt->action->curves.first;
- //Check for Lamp parameter animations
- else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
- fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
- //Check for Camera parameter animations
- else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
- fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
-
- //Check Material Effect parameter animations.
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
- if (!ma) continue;
- if (ma->adt && ma->adt->action) {
- fcu = (FCurve *)ma->adt->action->curves.first;
- }
- }
-
- //check shape key animation
- if (!fcu) {
- Key *key = BKE_key_from_object(ob);
- if (key && key->adt && key->adt->action)
- fcu = (FCurve *)key->adt->action->curves.first;
- }
- if (fcu)
- return true;
- }
- return false;
-}
-
-//------------------------------- Not used in the new system.--------------------------------------------------------
-void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
-{
- if (rotmode > 0)
- find_keyframes(ob, fra, prefix, "rotation_euler");
- else if (rotmode == ROT_MODE_QUAT)
- find_keyframes(ob, fra, prefix, "rotation_quaternion");
- /*else if (rotmode == ROT_MODE_AXISANGLE)
- ;*/
+ return tm_name;
}
-/* Take care to always have the first frame and the last frame in the animation
- * regardless of the sampling_rate setting
- */
-void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra)
+#ifdef WITH_MORPH_ANIMATION
+/* TODO: This function needs to be implemented similar to the material animation export
+So we have to update BCSample for this to work.
+*/
+void AnimationExporter::export_morph_animation(Object *ob, BCAnimationSampler &sampler)
{
- int frame = scene->r.sfra;
- do {
- float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
- fra.push_back(ctime);
- if (frame == scene->r.efra)
- break;
- frame += this->export_settings->sampling_rate;
- if (frame > scene->r.efra)
- frame = scene->r.efra; // make sure the last frame is always exported
-
- } while (true);
-}
-
-/*
- * find keyframes of all the objects animations
- */
-void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra)
-{
- if (ob->adt && ob->adt->action) {
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
-
- for (; fcu; fcu = fcu->next) {
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- float f = fcu->bezt[i].vec[1][0];
- if (std::find(fra.begin(), fra.end(), f) == fra.end())
- fra.push_back(f);
- }
- }
-
- // keep the keys in ascending order
- std::sort(fra.begin(), fra.end());
- }
-}
-
-void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
-{
- if (ob->adt && ob->adt->action) {
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
-
- for (; fcu; fcu = fcu->next) {
- if (prefix && !STREQLEN(prefix, fcu->rna_path, strlen(prefix)))
- continue;
-
- char *name = extract_transform_name(fcu->rna_path);
- if (STREQ(name, tm_name)) {
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- float f = fcu->bezt[i].vec[1][0];
- if (std::find(fra.begin(), fra.end(), f) == fra.end())
- fra.push_back(f);
- }
- }
- }
-
- // keep the keys in ascending order
- std::sort(fra.begin(), fra.end());
- }
-}
-
-void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
-{
- if (!ob_arm->adt)
- return;
-
- //write bone animations for 3 transform types
- //i=0 --> rotations
- //i=1 --> scale
- //i=2 --> location
- for (int i = 0; i < 3; i++)
- sample_and_write_bone_animation(ob_arm, bone, i);
-
- for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
- write_bone_animation(ob_arm, child);
-}
-
-void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
-{
- bArmature *arm = (bArmature *)ob_arm->data;
- int flag = arm->flag;
- std::vector<float> fra;
- char prefix[256];
-
- BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
-
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
- if (!pchan)
- return;
- //Fill frame array with key frame values framed at \param:transform_type
- switch (transform_type) {
- case 0:
- find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
- break;
- case 1:
- find_keyframes(ob_arm, fra, prefix, "scale");
- break;
- case 2:
- find_keyframes(ob_arm, fra, prefix, "location");
- break;
- default:
- return;
- }
-
- // exit rest position
- if (flag & ARM_RESTPOS) {
- arm->flag &= ~ARM_RESTPOS;
- BKE_pose_where_is(scene, ob_arm);
- }
- //v array will hold all values which will be exported.
- if (fra.size()) {
- float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
- sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
-
- if (transform_type == 0) {
- // write x, y, z curves separately if it is rotation
- float *axisValues = (float *)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
-
- for (int i = 0; i < 3; i++) {
- for (unsigned int j = 0; j < fra.size(); j++)
- axisValues[j] = values[j * 3 + i];
-
- dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
- }
- MEM_freeN(axisValues);
- }
- else {
- // write xyz at once if it is location or scale
- dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
- }
-
- MEM_freeN(values);
- }
-
- // restore restpos
- if (flag & ARM_RESTPOS)
- arm->flag = flag;
- BKE_pose_where_is(scene, ob_arm);
-}
-
-void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
-{
- bPoseChannel *parchan = NULL;
- bPose *pose = ob_arm->pose;
-
- pchan = BKE_pose_channel_find_name(pose, bone->name);
-
- if (!pchan)
- return;
-
- parchan = pchan->parent;
-
- enable_fcurves(ob_arm->adt->action, bone->name);
-
- std::vector<float>::iterator it;
- for (it = frames.begin(); it != frames.end(); it++) {
- float mat[4][4], ipar[4][4];
+ FCurve *fcu;
+ Key *key = BKE_key_from_object(ob);
+ if (!key) return;
- float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
+ if (key->adt && key->adt->action) {
+ fcu = (FCurve *)key->adt->action->curves.first;
+ while (fcu) {
+ BC_animation_transform_type tm_type = get_transform_type(fcu->rna_path);
- BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
- BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
+ create_keyframed_animation(ob, fcu, tm_type, true, sampler);
- // compute bone local mat
- if (bone->parent) {
- invert_m4_m4(ipar, parchan->pose_mat);
- mul_m4_m4m4(mat, ipar, pchan->pose_mat);
- }
- else
- copy_m4_m4(mat, pchan->pose_mat);
-
- switch (type) {
- case 0:
- mat4_to_eul(v, mat);
- break;
- case 1:
- mat4_to_size(v, mat);
- break;
- case 2:
- copy_v3_v3(v, mat[3]);
- break;
+ fcu = fcu->next;
}
-
- v += 3;
}
- enable_fcurves(ob_arm->adt->action, NULL);
-}
-
-bool AnimationExporter::validateConstraints(bConstraint *con)
-{
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- /* these we can skip completely (invalid constraints...) */
- if (cti == NULL)
- return false;
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
- return false;
-
- /* these constraints can't be evaluated anyway */
- if (cti->evaluate_constraint == NULL)
- return false;
-
- /* influence == 0 should be ignored */
- if (con->enforce == 0.0f)
- return false;
-
- /* validation passed */
- return true;
}
+#endif
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
index b6b67847f4e..969669ef11d 100644
--- a/source/blender/collada/AnimationExporter.h
+++ b/source/blender/collada/AnimationExporter.h
@@ -20,9 +20,15 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#ifndef __BC_ANIMATION_EXPORTER_H__
+#define __BC_ANIMATION_EXPORTER_H__
+
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
+
+#include "BCAnimationCurve.h"
+
extern "C"
{
#include "DNA_scene_types.h"
@@ -42,7 +48,6 @@ extern "C"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_fcurve.h"
#include "BKE_animsys.h"
#include "BKE_scene.h"
@@ -71,40 +76,45 @@ extern "C"
#include "COLLADASWBaseInputElement.h"
#include "EffectExporter.h"
-
+#include "BCAnimationSampler.h"
#include "collada_internal.h"
#include "IK_solver.h"
#include <vector>
+#include <map>
#include <algorithm> // std::find
+struct Depsgraph;
+typedef enum BC_animation_source_type {
+ BC_SOURCE_TYPE_VALUE,
+ BC_SOURCE_TYPE_ANGLE,
+ BC_SOURCE_TYPE_TIMEFRAME
+} BC_animation_source_type;
class AnimationExporter: COLLADASW::LibraryAnimations
{
private:
- Main *m_bmain;
- Scene *scene;
+ BlenderContext &blender_context;
COLLADASW::StreamWriter *sw;
+ const ExportSettings *export_settings;
public:
- AnimationExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings):
+ AnimationExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings):
COLLADASW::LibraryAnimations(sw),
+ blender_context(blender_context),
+ sw(sw),
export_settings(export_settings)
- {
- this->sw = sw;
- }
+ {}
- bool exportAnimations(Main *bmain, Scene *sce);
+ bool exportAnimations();
// called for each exported object
void operator() (Object *ob);
protected:
- const ExportSettings *export_settings;
-
void export_object_constraint_animation(Object *ob);
@@ -116,8 +126,6 @@ protected:
void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type);
- bool is_bone_deform_group(Bone * bone);
-
void sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone);
void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pChan);
@@ -136,70 +144,123 @@ protected:
float convert_angle(float angle);
+ std::vector<std::vector<std::string>> anim_meta;
+
+ /* Main entry point into Animation export (called for each exported object) */
+ void exportAnimation(Object *ob, BCAnimationSampler &sampler);
+
+ /* export animation as separate trans/rot/scale curves */
+ void export_curve_animation_set(
+ Object *ob,
+ BCAnimationSampler &sampler,
+ bool export_tm_curves);
+
+ /* export one single curve */
+ void export_curve_animation(
+ Object *ob,
+ BCAnimationCurve &curve);
+
+ /* export animation as matrix data */
+ void export_matrix_animation(
+ Object *ob,
+ BCAnimationSampler &sampler);
+
+ /* step through the bone hierarchy */
+ void export_bone_animations_recursive(
+ Object *ob_arm,
+ Bone *bone,
+ BCAnimationSampler &sampler);
+
+ /* Export for one bone */
+ void export_bone_animation(
+ Object *ob,
+ Bone *bone,
+ BCFrames &frames,
+ BCMatrixSampleMap &outmats);
+
+ /* call to the low level collada exporter */
+ void export_collada_curve_animation(
+ std::string id,
+ std::string name,
+ std::string target,
+ std::string axis,
+ BCAnimationCurve &curve);
+
+ /* call to the low level collada exporter */
+ void export_collada_matrix_animation(
+ std::string id,
+ std::string name,
+ std::string target,
+ BCFrames &frames,
+ BCMatrixSampleMap &outmats);
+
+ BCAnimationCurve *get_modified_export_curve(Object *ob, BCAnimationCurve &curve, BCAnimationCurveMap &curves);
+
+ /* Helper functions */
+ void openAnimationWithClip(std::string id, std::string name);
+ bool open_animation_container(bool has_container, Object *ob);
+ void close_animation_container(bool has_container);
+
+ /* Input and Output sources (single valued) */
+ std::string collada_source_from_values(
+ BC_animation_source_type tm_channel,
+ COLLADASW::InputSemantic::Semantics semantic,
+ std::vector<float> &values,
+ const std::string& anim_id,
+ const std::string axis_name);
+
+ /* Output sources (matrix data) */
+ std::string collada_source_from_values(
+ BCMatrixSampleMap &samples,
+ const std::string& anim_id);
+
+ /* Interpolation sources */
+ std::string collada_linear_interpolation_source(
+ int tot,
+ const std::string& anim_id);
+
+ /* source ID = animation_name + semantic_suffix */
+
std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic);
void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
- COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform);
-
- void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values, int *length);
-
- float* get_eul_source_for_quat(Object *ob );
-
- bool is_flat_line(std::vector<float> &values, int channel_count);
- void export_keyframed_animation_set(Object *ob);
- void create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL);
- void export_sampled_animation_set(Object *ob);
- void export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes);
- void export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes);
- void create_sampled_animation(int channel_count, std::vector<float> &times, std::vector<float> &values, std::string, std::string label, std::string axis_name, bool is_rot);
-
- void evaluate_anim_with_constraints(Object *ob, float ctime);
+ COLLADASW::InputSemantic::Semantics semantic,
+ bool is_rot,
+ const std::string axis,
+ bool transform);
- std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name);
- std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob);
+ int get_point_in_curve(BCBezTriple &bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values);
+ int get_point_in_curve(const BCAnimationCurve &curve, float sample_frame, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values);
- std::string create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id);
+ std::string collada_tangent_from_curve(
+ COLLADASW::InputSemantic::Semantics semantic,
+ BCAnimationCurve &curve,
+ const std::string& anim_id,
+ const std::string axis_name);
- std::string create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name);
+ std::string collada_interpolation_source(const BCAnimationCurve &curve, const std::string& anim_id, std::string axis_name, bool *has_tangents);
- std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name);
+ std::string get_axis_name(std::string channel, int id);
+ const std::string get_collada_name(std::string channel_target) const;
+ std::string get_collada_sid(const BCAnimationCurve &curve, const std::string axis_name);
- std::string create_xyz_source(float *v, int tot, const std::string& anim_id);
- std::string create_4x4_source(std::vector<float> &times, std::vector<float> &values, const std::string& anim_id);
- std::string create_4x4_source(std::vector<float> &frames, Object * ob_arm, Bone *bone, const std::string& anim_id);
+ /* ===================================== */
+ /* Currently unused or not (yet?) needed */
+ /* ===================================== */
- std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents);
-
- std::string fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name);
-
- // for rotation, axis name is always appended and the value of append_axis is ignored
- std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
- std::string get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
- std::string get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
-
- void find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name);
- void find_keyframes(Object *ob, std::vector<float> &fra);
- void find_sampleframes(Object *ob, std::vector<float> &fra);
-
-
- void make_anim_frames_from_targets(Object *ob, std::vector<float> &frames );
-
- void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode);
-
- // enable fcurves driving a specific bone, disable all the rest
- // if bone_name = NULL enable all fcurves
- void enable_fcurves(bAction *act, char *bone_name);
-
- bool hasAnimations(Scene *sce);
-
- char *extract_transform_name(char *rna_path);
-
- std::string getObjectBoneName(Object *ob, const FCurve * fcu);
- std::string getAnimationPathId(const FCurve *fcu);
-
- void getBakedPoseData(Object *obarm, int startFrame, int endFrame, bool ActionBake, bool ActionBakeFirstFrame);
+ bool is_bone_deform_group(Bone * bone);
- bool validateConstraints(bConstraint *con);
+#if 0
+ BC_animation_transform_type _get_transform_type(const std::string path);
+ void get_eul_source_for_quat(std::vector<float> &cache, Object *ob);
+#endif
+#ifdef WITH_MORPH_ANIMATION
+ void export_morph_animation(
+ Object *ob,
+ BCAnimationSampler &sampler);
+#endif
};
+
+#endif
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 3dda67abbba..e3a8e517352 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -107,11 +107,9 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve");
fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
- // fcu->rna_path = BLI_strdupn(path, strlen(path));
fcu->array_index = 0;
- //fcu->totvert = curve->getKeyCount();
+ fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
- // create beztriple for each key
for (unsigned int j = 0; j < curve->getKeyCount(); j++) {
BezTriple bez;
memset(&bez, 0, sizeof(BezTriple));
@@ -120,7 +118,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
// input, output
bez.vec[1][0] = bc_get_float_value(input, j) * fps;
bez.vec[1][1] = bc_get_float_value(output, j * dim + i);
-
+ bez.h1 = bez.h2 = HD_AUTO;
if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ||
curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_STEP)
@@ -135,14 +133,15 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
// outtangent
bez.vec[2][0] = bc_get_float_value(outtan, (j * 2 * dim) + (2 * i)) * fps;
bez.vec[2][1] = bc_get_float_value(outtan, (j * 2 * dim) + (2 * i) + 1);
- if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER)
+ if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER) {
bez.ipo = BEZT_IPO_BEZ;
- else
+ bez.h1 = bez.h2 = HD_AUTO_ANIM;
+ }
+ else {
bez.ipo = BEZT_IPO_CONST;
- //bez.h1 = bez.h2 = HD_AUTO;
+ }
}
else {
- bez.h1 = bez.h2 = HD_AUTO;
bez.ipo = BEZT_IPO_LIN;
}
// bez.ipo = U.ipo_new; /* use default interpolation mode here... */
@@ -245,10 +244,6 @@ void AnimationImporter::add_fcurves_to_object(Main *bmain, Object *ob, std::vect
}
}
-AnimationImporter::AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene) :
- TransformReader(conv), armature_importer(arm), scene(scene) {
-}
-
AnimationImporter::~AnimationImporter()
{
// free unused FCurves
@@ -304,7 +299,6 @@ bool AnimationImporter::write_animation(const COLLADAFW::Animation *anim)
bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList *animlist)
{
const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId();
-
animlist_map[animlist_id] = animlist;
#if 0
@@ -725,7 +719,7 @@ void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId& listid
}
}
-void AnimationImporter::apply_matrix_curves(Main *bmain, Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node,
+void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node,
COLLADAFW::Transformation *tm)
{
bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
@@ -840,6 +834,7 @@ void AnimationImporter::apply_matrix_curves(Main *bmain, Object *ob, std::vector
add_bezt(newcu[i], fra, scale[i - 7]);
}
}
+ Main *bmain = CTX_data_main(mContext);
verify_adt_action(bmain, (ID *)&ob->id, 1);
ListBase *curves = &ob->adt->action->curves;
@@ -908,7 +903,7 @@ static ListBase &get_animation_curves(Main *bmain, Material *ma)
return act->curves;
}
-void AnimationImporter::translate_Animations(Main *bmain, COLLADAFW::Node *node,
+void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map,
std::multimap<COLLADAFW::UniqueId, Object *>& object_map,
std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map,
@@ -932,6 +927,7 @@ void AnimationImporter::translate_Animations(Main *bmain, COLLADAFW::Node *node,
AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map);
bAction *act;
+ Main *bmain = CTX_data_main(mContext);
if ( (animType->transform) != 0) {
/* const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; */ /* UNUSED */
@@ -940,9 +936,11 @@ void AnimationImporter::translate_Animations(Main *bmain, COLLADAFW::Node *node,
if (is_joint)
armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
+ if (!ob->adt || !ob->adt->action)
+ act = verify_adt_action(bmain, (ID *)&ob->id, 1);
- if (!ob->adt || !ob->adt->action) act = verify_adt_action(bmain, (ID *)&ob->id, 1);
- else act = ob->adt->action;
+ else
+ act = ob->adt->action;
//Get the list of animation curves of the object
ListBase *AnimCurves = &(act->curves);
@@ -972,11 +970,11 @@ void AnimationImporter::translate_Animations(Main *bmain, COLLADAFW::Node *node,
for (unsigned int j = 0; j < bindings.getCount(); j++) {
animcurves = curve_map[bindings[j].animation];
if (is_matrix) {
- apply_matrix_curves(bmain, ob, animcurves, root, node, transform);
+ apply_matrix_curves(ob, animcurves, root, node, transform);
}
else {
if (is_joint) {
- add_bone_animation_sampled(bmain, ob, animcurves, root, node, transform);
+ add_bone_animation_sampled(ob, animcurves, root, node, transform);
}
else {
//calculate rnapaths and array index of fcurves according to transformation and animation class
@@ -1003,9 +1001,10 @@ void AnimationImporter::translate_Animations(Main *bmain, COLLADAFW::Node *node,
if ((animType->light) != 0) {
Lamp *lamp = (Lamp *) ob->data;
-
- if (!lamp->adt || !lamp->adt->action) act = verify_adt_action(bmain, (ID *)&lamp->id, 1);
- else act = lamp->adt->action;
+ if (!lamp->adt || !lamp->adt->action)
+ act = verify_adt_action(bmain, (ID *)&lamp->id, 1);
+ else
+ act = lamp->adt->action;
ListBase *AnimCurves = &(act->curves);
const COLLADAFW::InstanceLightPointerArray& nodeLights = node->getInstanceLights();
@@ -1036,6 +1035,7 @@ void AnimationImporter::translate_Animations(Main *bmain, COLLADAFW::Node *node,
}
if (animType->camera != 0) {
+
Camera *cam = (Camera *) ob->data;
if (!cam->adt || !cam->adt->action)
act = verify_adt_action(bmain, (ID *)&cam->id, 1);
@@ -1090,6 +1090,12 @@ void AnimationImporter::translate_Animations(Main *bmain, COLLADAFW::Node *node,
}
if (animType->material != 0) {
+ Material *ma = give_current_material(ob, 1);
+ if (!ma->adt || !ma->adt->action)
+ act = verify_adt_action(bmain, (ID *)&ma->id, 1);
+ else
+ act = ma->adt->action;
+
const COLLADAFW::InstanceGeometryPointerArray& nodeGeoms = node->getInstanceGeometries();
for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) {
const COLLADAFW::MaterialBindingArray& matBinds = nodeGeoms[i]->getMaterialBindings();
@@ -1136,7 +1142,7 @@ void AnimationImporter::translate_Animations(Main *bmain, COLLADAFW::Node *node,
delete animType;
}
-void AnimationImporter::add_bone_animation_sampled(Main *bmain, Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, COLLADAFW::Transformation *tm)
+void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, COLLADAFW::Transformation *tm)
{
const char *bone_name = bc_get_joint_name(node);
char joint_path[200];
@@ -1259,6 +1265,7 @@ void AnimationImporter::add_bone_animation_sampled(Main *bmain, Object *ob, std:
add_bezt(newcu[i], fra, scale[i - 7]);
}
}
+ Main *bmain = CTX_data_main(mContext);
verify_adt_action(bmain, (ID *)&ob->id, 1);
// add curves
@@ -1291,7 +1298,7 @@ AnimationImporter::AnimMix *AnimationImporter::get_animation_type(const COLLADAF
continue;
}
else {
- types->transform = types->transform | NODE_TRANSFORM;
+ types->transform = types->transform | BC_NODE_TRANSFORM;
break;
}
}
@@ -1435,7 +1442,7 @@ void AnimationImporter::find_frames_old(std::vector<float> *frames, COLLADAFW::N
// prerequisites:
// animlist_map - map animlist id -> animlist
// curve_map - map anim id -> curve(s)
-Object *AnimationImporter::translate_animation_OLD(Main *bmain, COLLADAFW::Node *node,
+Object *AnimationImporter::translate_animation_OLD(COLLADAFW::Node *node,
std::map<COLLADAFW::UniqueId, Object *>& object_map,
std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map,
COLLADAFW::Transformation::TransformationType tm_type,
@@ -1657,7 +1664,7 @@ Object *AnimationImporter::translate_animation_OLD(Main *bmain, COLLADAFW::Node
}
#endif
}
-
+ Main *bmain = CTX_data_main(mContext);
verify_adt_action(bmain, (ID *)&ob->id, 1);
ListBase *curves = &ob->adt->action->curves;
@@ -1775,24 +1782,24 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float
else if (is_translate)
dae_translate_to_v3(tm, vec);
- for (unsigned int j = 0; j < bindings.getCount(); j++) {
- const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[j];
+ for (unsigned int index = 0; index < bindings.getCount(); index++) {
+ const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[index];
std::vector<FCurve *>& curves = curve_map[binding.animation];
COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass;
char path[100];
switch (type) {
case COLLADAFW::Transformation::ROTATE:
- BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, j);
+ BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, index);
break;
case COLLADAFW::Transformation::SCALE:
- BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, j);
+ BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, index);
break;
case COLLADAFW::Transformation::TRANSLATE:
- BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, j);
+ BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, index);
break;
case COLLADAFW::Transformation::MATRIX:
- BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, j);
+ BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, index);
break;
default:
break;
@@ -1938,7 +1945,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
job->lay = BKE_scene_base_find(scene, job)->lay = 2;
mul_v3_fl(job->size, 0.5f);
- DAG_id_tag_update(&job->id, OB_RECALC_OB);
+ DEG_id_tag_update(&job->id, OB_RECALC_OB);
verify_adt_action((ID *)&job->id, 1);
@@ -1959,14 +1966,14 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
if (par_job) {
job->parent = par_job;
- DAG_id_tag_update(&par_job->id, OB_RECALC_OB);
+ DEG_id_tag_update(&par_job->id, OB_RECALC_OB);
job->parsubstr[0] = 0;
}
BKE_object_where_is_calc(scene, job);
// after parenting and layer change
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
joint_objects[node->getUniqueId()] = job;
}
diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h
index ff49bc369cf..d6d5ad03a88 100644
--- a/source/blender/collada/AnimationImporter.h
+++ b/source/blender/collada/AnimationImporter.h
@@ -42,6 +42,7 @@
#include "COLLADAFWInstanceGeometry.h"
extern "C" {
+#include "BKE_context.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -65,7 +66,7 @@ public:
class AnimationImporter : private TransformReader, public AnimationImporterBase
{
private:
-
+ bContext *mContext;
ArmatureImporter *armature_importer;
Scene *scene;
@@ -124,8 +125,8 @@ private:
enum AnimationType
{
- INANIMATE = 0,
- NODE_TRANSFORM = 1,
+ BC_INANIMATE = 0,
+ BC_NODE_TRANSFORM = 1
};
struct AnimMix
@@ -138,7 +139,11 @@ private:
};
public:
- AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene);
+ AnimationImporter(bContext *C, UnitConverter *conv, ArmatureImporter *arm, Scene *scene) :
+ TransformReader(conv),
+ mContext(C),
+ armature_importer(arm),
+ scene(scene) {}
~AnimationImporter();
@@ -153,7 +158,7 @@ public:
virtual void change_eul_to_quat(Object *ob, bAction *act);
#endif
- void translate_Animations(Main *bmain, COLLADAFW::Node * Node,
+ void translate_Animations(COLLADAFW::Node * Node,
std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
std::multimap<COLLADAFW::UniqueId, Object*>& object_map,
std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map,
@@ -161,10 +166,10 @@ public:
AnimMix* get_animation_type( const COLLADAFW::Node * node, std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map );
- void apply_matrix_curves(Main *bmain, Object *ob, std::vector<FCurve*>& animcurves, COLLADAFW::Node* root, COLLADAFW::Node* node,
+ void apply_matrix_curves(Object *ob, std::vector<FCurve*>& animcurves, COLLADAFW::Node* root, COLLADAFW::Node* node,
COLLADAFW::Transformation * tm );
- void add_bone_animation_sampled(Main *bmain, Object *ob, std::vector<FCurve*>& animcurves, COLLADAFW::Node* root, COLLADAFW::Node* node, COLLADAFW::Transformation * tm);
+ void add_bone_animation_sampled(Object *ob, std::vector<FCurve*>& animcurves, COLLADAFW::Node* root, COLLADAFW::Node* node, COLLADAFW::Transformation * tm);
void Assign_transform_animations(COLLADAFW::Transformation* transform,
const COLLADAFW::AnimationList::AnimationBinding *binding,
@@ -181,12 +186,11 @@ public:
// prerequisites:
// animlist_map - map animlist id -> animlist
// curve_map - map anim id -> curve(s)
- Object *translate_animation_OLD(
- Main *bmain, COLLADAFW::Node *node,
- std::map<COLLADAFW::UniqueId, Object*>& object_map,
- std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
- COLLADAFW::Transformation::TransformationType tm_type,
- Object *par_job = NULL);
+ Object *translate_animation_OLD(COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Object *>& object_map,
+ std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map,
+ COLLADAFW::Transformation::TransformationType tm_type,
+ Object *par_job = NULL);
void find_frames( std::vector<float>* frames, std::vector<FCurve*>* curves );
void find_frames_old( std::vector<float>* frames, COLLADAFW::Node * node, COLLADAFW::Transformation::TransformationType tm_type );
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 432ce92b49d..2aa7b483110 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -39,10 +39,8 @@
#include "BKE_armature.h"
extern "C" {
-#include "BKE_main.h"
-#include "BKE_mesh.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_mesh.h"
}
#include "ED_armature.h"
@@ -55,42 +53,41 @@ extern "C" {
#include "collada_utils.h"
-// XXX exporter writes wrong data for shared armatures. A separate
-// controller should be written for each armature-mesh binding how do
-// we make controller ids then?
-ArmatureExporter::ArmatureExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryControllers(sw), export_settings(export_settings) {
-}
-
// write bone nodes
-void ArmatureExporter::add_armature_bones(bContext *C, Object *ob_arm, Scene *sce,
- SceneExporter *se,
- std::list<Object *>& child_objects)
+void ArmatureExporter::add_armature_bones(
+ Object *ob_arm,
+ ViewLayer *view_layer,
+ SceneExporter *se,
+ std::vector<Object *>& child_objects)
+
{
- Main *bmain = CTX_data_main(C);
// write bone nodes
bArmature *armature = (bArmature *)ob_arm->data;
bool is_edited = armature->edbo != NULL;
- if (!is_edited)
+ if (!is_edited) {
ED_armature_to_edit(armature);
+ }
for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) {
// start from root bones
- if (!bone->parent)
- add_bone_node(C, bone, ob_arm, sce, se, child_objects);
+ if (!bone->parent) {
+ add_bone_node(bone, ob_arm, se, child_objects);
+ }
}
if (!is_edited) {
- ED_armature_from_edit(bmain, armature);
ED_armature_edit_free(armature);
}
}
void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
{
- if (bc_is_root_bone(bone, this->export_settings->deform_bones_only))
- ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(ob_arm, bone)));
+ if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) {
+ std::string joint_id = translate_id(id_name(ob_arm) + "_" + bone->name);
+ ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, joint_id));
+ }
else {
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
write_bone_URLs(ins, ob_arm, child);
@@ -117,10 +114,7 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(),
- ob,
- this->export_settings->active_uv_only,
- this->export_settings->export_texture_type);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
ins.add();
return true;
@@ -161,12 +155,14 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
#endif
// parent_mat is armature-space
-void ArmatureExporter::add_bone_node(bContext *C, Bone *bone, Object *ob_arm, Scene *sce,
- SceneExporter *se,
- std::list<Object *>& child_objects)
+void ArmatureExporter::add_bone_node(
+ Bone *bone,
+ Object *ob_arm,
+ SceneExporter *se,
+ std::vector<Object *>& child_objects)
{
if (!(this->export_settings->deform_bones_only && bone->flag & BONE_NO_DEFORM)) {
- std::string node_id = get_joint_id(ob_arm, bone);
+ std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name);
std::string node_name = std::string(bone->name);
std::string node_sid = get_joint_sid(bone);
@@ -206,7 +202,7 @@ void ArmatureExporter::add_bone_node(bContext *C, Bone *bone, Object *ob_arm, Sc
add_bone_transform(ob_arm, bone, node);
// Write nodes of childobjects, remove written objects from list
- std::list<Object *>::iterator i = child_objects.begin();
+ std::vector<Object *>::iterator i = child_objects.begin();
while (i != child_objects.end()) {
if ((*i)->partype == PARBONE && STREQ((*i)->parsubstr, bone->name)) {
@@ -235,8 +231,7 @@ void ArmatureExporter::add_bone_node(bContext *C, Bone *bone, Object *ob_arm, Sc
mul_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
}
- se->writeNodes(C, *i, sce);
-
+ se->writeNodes(*i);
copy_m4_m4((*i)->parentinv, backup_parinv);
child_objects.erase(i++);
}
@@ -244,13 +239,13 @@ void ArmatureExporter::add_bone_node(bContext *C, Bone *bone, Object *ob_arm, Sc
}
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
- add_bone_node(C, child, ob_arm, sce, se, child_objects);
+ add_bone_node(child, ob_arm, se, child_objects);
}
node.end();
}
else {
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
- add_bone_node(C, child, ob_arm, sce, se, child_objects);
+ add_bone_node(child, ob_arm, se, child_objects);
}
}
}
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
index 3199703cb20..1a8080ad613 100644
--- a/source/blender/collada/ArmatureExporter.h
+++ b/source/blender/collada/ArmatureExporter.h
@@ -57,20 +57,26 @@ class SceneExporter;
class ArmatureExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
{
public:
- ArmatureExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
- // write bone nodes
- void add_armature_bones(bContext *C, Object *ob_arm, Scene *sce, SceneExporter *se,
- std::list<Object *>& child_objects);
+ // XXX exporter writes wrong data for shared armatures. A separate
+ // controller should be written for each armature-mesh binding how do
+ // we make controller ids then?
+ ArmatureExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) :
+ COLLADASW::LibraryControllers(sw),
+ blender_context(blender_context),
+ export_settings(export_settings)
+ {}
+
+ void add_armature_bones(
+ Object *ob_arm,
+ ViewLayer *view_layer,
+ SceneExporter *se,
+ std::vector<Object *>& child_objects);
bool add_instance_controller(Object *ob);
- //void export_controllers(Scene *sce);*/
-
- //void operator()(Object *ob);
-
private:
- UnitConverter converter;
+ BlenderContext &blender_context;
const ExportSettings *export_settings;
#if 0
@@ -85,8 +91,11 @@ private:
// Scene, SceneExporter and the list of child_objects
// are required for writing bone parented objects
- void add_bone_node(bContext *C, Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se,
- std::list<Object *>& child_objects);
+ void add_bone_node(
+ Bone *bone,
+ Object *ob_arm,
+ SceneExporter *se,
+ std::vector<Object *>& child_objects);
void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node);
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index a96d1e76a99..32c7363a994 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -34,7 +34,6 @@
extern "C" {
#include "BKE_action.h"
-#include "BKE_depsgraph.h"
#include "BKE_object.h"
#include "BKE_armature.h"
#include "BLI_string.h"
@@ -42,6 +41,8 @@ extern "C" {
#include "ED_armature.h"
}
+#include "DEG_depsgraph.h"
+
#include "collada_utils.h"
#include "ArmatureImporter.h"
@@ -54,10 +55,12 @@ static const char *bc_get_joint_name(T *node)
}
-ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Main *bmain, Scene *sce, const ImportSettings *import_settings) :
+ArmatureImporter::ArmatureImporter(
+ UnitConverter *conv, MeshImporterBase *mesh, Main *bmain, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings) :
TransformReader(conv),
m_bmain(bmain),
scene(sce),
+ view_layer(view_layer),
unit_converter(conv),
import_settings(import_settings),
empty(NULL),
@@ -410,7 +413,7 @@ Object *ArmatureImporter::get_empty_for_leaves()
{
if (empty) return empty;
- empty = bc_add_object(m_bmain, scene, OB_EMPTY, NULL);
+ empty = bc_add_object(m_bmain, scene, view_layer, OB_EMPTY, NULL);
empty->empty_drawtype = OB_EMPTY_SPHERE;
return empty;
@@ -496,7 +499,7 @@ void ArmatureImporter::create_armature_bones(Main *bmain, std::vector<Object *>
ob_arms.push_back(ob_arm);
}
- DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
}
}
@@ -585,7 +588,7 @@ Object *ArmatureImporter::create_armature_bones(Main *bmain, SkinInfo& skin)
ob_arm = skin.set_armature(shared);
}
else {
- ob_arm = skin.create_armature(m_bmain, scene); //once for every armature
+ ob_arm = skin.create_armature(m_bmain, scene, view_layer); //once for every armature
}
// enter armature edit mode
@@ -629,7 +632,7 @@ Object *ArmatureImporter::create_armature_bones(Main *bmain, SkinInfo& skin)
ED_armature_from_edit(bmain, armature);
ED_armature_edit_free(armature);
- DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
return ob_arm;
}
@@ -879,7 +882,7 @@ void ArmatureImporter::make_shape_keys(bContext *C)
//insert basis key
kb = BKE_keyblock_add_ctime(key, "Basis", false);
- BKE_keyblock_convert_from_mesh(source_me, kb);
+ BKE_keyblock_convert_from_mesh(source_me, key, kb);
//insert other shape keys
for (int i = 0 ; i < morphTargetIds.getCount() ; i++ ) {
@@ -893,7 +896,7 @@ void ArmatureImporter::make_shape_keys(bContext *C)
std::string morph_name = *this->mesh_importer->get_geometry_name(me->id.name);
kb = BKE_keyblock_add_ctime(key, morph_name.c_str(), false);
- BKE_keyblock_convert_from_mesh(me, kb);
+ BKE_keyblock_convert_from_mesh(me, key, kb);
//apply weights
weight = morphWeights.getFloatValues()->getData()[i];
diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h
index a215b186f75..419861554f4 100644
--- a/source/blender/collada/ArmatureImporter.h
+++ b/source/blender/collada/ArmatureImporter.h
@@ -64,6 +64,7 @@ class ArmatureImporter : private TransformReader
private:
Main *m_bmain;
Scene *scene;
+ ViewLayer *view_layer;
UnitConverter *unit_converter;
const ImportSettings *import_settings;
@@ -138,7 +139,8 @@ private:
TagsMap uid_tags_map;
public:
- ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Main *bmain, Scene *sce, const ImportSettings *import_settings);
+ ArmatureImporter(
+ UnitConverter *conv, MeshImporterBase *mesh, Main *bmain, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings);
~ArmatureImporter();
void add_root_joint(COLLADAFW::Node *node, Object *parent);
diff --git a/source/blender/collada/BCAnimationCurve.cpp b/source/blender/collada/BCAnimationCurve.cpp
new file mode 100644
index 00000000000..87cf07cc21c
--- /dev/null
+++ b/source/blender/collada/BCAnimationCurve.cpp
@@ -0,0 +1,678 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2008 Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Blender Foundation
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#include "BCAnimationCurve.h"
+
+BCAnimationCurve::BCAnimationCurve()
+{
+ this->curve_key.set_object_type(BC_ANIMATION_TYPE_OBJECT);
+ this->fcurve = NULL;
+ this->curve_is_local_copy = false;
+}
+
+BCAnimationCurve::BCAnimationCurve(const BCAnimationCurve &other)
+{
+ this->min = other.min;
+ this->max = other.max;
+ this->fcurve = other.fcurve;
+ this->curve_key = other.curve_key;
+ this->curve_is_local_copy = false;
+ this->id_ptr = other.id_ptr;
+
+ /* The fcurve of the new instance is a copy and can be modified */
+
+ get_edit_fcurve();
+}
+
+BCAnimationCurve::BCAnimationCurve(BCCurveKey key, Object *ob, FCurve *fcu)
+{
+ this->min = 0;
+ this->max = 0;
+ this->curve_key = key;
+ this->fcurve = fcu;
+ this->curve_is_local_copy = false;
+ init_pointer_rna(ob);
+}
+
+BCAnimationCurve::BCAnimationCurve(const BCCurveKey &key, Object *ob)
+{
+ this->curve_key = key;
+ this->fcurve = NULL;
+ this->curve_is_local_copy = false;
+ init_pointer_rna(ob);
+}
+
+void BCAnimationCurve::init_pointer_rna(Object *ob)
+{
+ switch (this->curve_key.get_animation_type()) {
+ case BC_ANIMATION_TYPE_BONE:
+ {
+ bArmature * arm = (bArmature *)ob->data;
+ RNA_id_pointer_create(&arm->id, &id_ptr);
+ }
+ break;
+ case BC_ANIMATION_TYPE_OBJECT:
+ {
+ RNA_id_pointer_create(&ob->id, &id_ptr);
+ }
+ break;
+ case BC_ANIMATION_TYPE_MATERIAL:
+ {
+ Material *ma = give_current_material(ob, curve_key.get_subindex() + 1);
+ RNA_id_pointer_create(&ma->id, &id_ptr);
+ }
+ break;
+ case BC_ANIMATION_TYPE_CAMERA:
+ {
+ Camera * camera = (Camera *)ob->data;
+ RNA_id_pointer_create(&camera->id, &id_ptr);
+ }
+ break;
+ case BC_ANIMATION_TYPE_LIGHT:
+ {
+ Lamp * lamp = (Lamp *)ob->data;
+ RNA_id_pointer_create(&lamp->id, &id_ptr);
+ }
+ break;
+ default:
+ fprintf(stderr, "BC_animation_curve_type %d not supported", this->curve_key.get_array_index());
+ break;
+ }
+}
+
+void BCAnimationCurve::delete_fcurve(FCurve *fcu)
+{
+ free_fcurve(fcu);
+}
+
+FCurve *BCAnimationCurve::create_fcurve(int array_index, const char *rna_path)
+{
+ FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve");
+ fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
+ fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
+ fcu->array_index = array_index;
+ return fcu;
+}
+
+void BCAnimationCurve::create_bezt(float frame, float output)
+{
+ FCurve *fcu = get_edit_fcurve();
+ BezTriple bez;
+ memset(&bez, 0, sizeof(BezTriple));
+ bez.vec[1][0] = frame;
+ bez.vec[1][1] = output;
+ bez.ipo = U.ipo_new; /* use default interpolation mode here... */
+ bez.f1 = bez.f2 = bez.f3 = SELECT;
+ bez.h1 = bez.h2 = HD_AUTO;
+ insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
+ calchandles_fcurve(fcu);
+}
+
+BCAnimationCurve::~BCAnimationCurve()
+{
+ if (curve_is_local_copy && fcurve) {
+ //fprintf(stderr, "removed fcurve %s\n", fcurve->rna_path);
+ delete_fcurve(fcurve);
+ this->fcurve = NULL;
+ }
+}
+
+const bool BCAnimationCurve::is_of_animation_type(BC_animation_type type) const
+{
+ return curve_key.get_animation_type() == type;
+}
+
+const std::string BCAnimationCurve::get_channel_target() const
+{
+ const std::string path = curve_key.get_path();
+ return bc_string_after(path, '.');
+}
+
+const std::string BCAnimationCurve::get_animation_name(Object *ob) const
+{
+ std::string name;
+
+ switch (curve_key.get_animation_type()) {
+ case BC_ANIMATION_TYPE_OBJECT:
+ {
+ name = id_name(ob);
+ }
+ break;
+
+ case BC_ANIMATION_TYPE_BONE:
+ {
+ if (fcurve == NULL || fcurve->rna_path == NULL)
+ name = "";
+ else {
+ const char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones[");
+ name = (boneName) ? std::string(boneName) : "";
+ }
+ }
+ break;
+
+ case BC_ANIMATION_TYPE_CAMERA:
+ {
+ Camera *camera = (Camera *)ob->data;
+ name = id_name(ob) + "-" + id_name(camera) + "-camera";
+ }
+ break;
+
+ case BC_ANIMATION_TYPE_LIGHT:
+ {
+ Lamp *lamp = (Lamp *)ob->data;
+ name = id_name(ob) + "-" + id_name(lamp) + "-light";
+ }
+ break;
+
+ case BC_ANIMATION_TYPE_MATERIAL:
+ {
+ Material * ma = give_current_material(ob, this->curve_key.get_subindex() + 1);
+ name = id_name(ob) + "-" + id_name(ma) + "-material";
+ }
+ break;
+
+ default:
+ {
+ name = "";
+ }
+ }
+
+ return name;
+}
+
+const int BCAnimationCurve::get_channel_index() const
+{
+ return curve_key.get_array_index();
+}
+
+const int BCAnimationCurve::get_subindex() const
+{
+ return curve_key.get_subindex();
+}
+
+const std::string BCAnimationCurve::get_rna_path() const
+{
+ return curve_key.get_path();
+}
+
+const int BCAnimationCurve::sample_count() const
+{
+ if (fcurve == NULL)
+ return 0;
+ return fcurve->totvert;
+}
+
+const int BCAnimationCurve::closest_index_above(const float sample_frame, const int start_at) const
+{
+ if (fcurve == NULL)
+ return -1;
+
+ const int cframe = fcurve->bezt[start_at].vec[1][0]; // inacurate!
+
+ if (fabs(cframe - sample_frame) < 0.00001)
+ return start_at;
+ return (fcurve->totvert > start_at + 1) ? start_at + 1 : start_at;
+}
+
+const int BCAnimationCurve::closest_index_below(const float sample_frame) const
+{
+ if (fcurve == NULL)
+ return -1;
+
+ float lower_frame = sample_frame;
+ float upper_frame = sample_frame;
+ int lower_index = 0;
+ int upper_index = 0;
+
+ for (int fcu_index = 0; fcu_index < fcurve->totvert; ++fcu_index) {
+ upper_index = fcu_index;
+
+ const int cframe = fcurve->bezt[fcu_index].vec[1][0]; // inacurate!
+ if (cframe <= sample_frame) {
+ lower_frame = cframe;
+ lower_index = fcu_index;
+ }
+ if (cframe >= sample_frame) {
+ upper_frame = cframe;
+ break;
+ }
+ }
+
+ if (lower_index == upper_index)
+ return lower_index;
+
+ const float fraction = float(sample_frame - lower_frame) / (upper_frame - lower_frame);
+ return (fraction < 0.5) ? lower_index : upper_index;
+}
+
+const int BCAnimationCurve::get_interpolation_type(float sample_frame) const
+{
+ const int index = closest_index_below(sample_frame);
+ if (index < 0)
+ return BEZT_IPO_BEZ;
+ return fcurve->bezt[index].ipo;
+}
+
+const FCurve *BCAnimationCurve::get_fcurve() const
+{
+ return fcurve;
+}
+
+FCurve *BCAnimationCurve::get_edit_fcurve()
+{
+ if (!curve_is_local_copy) {
+ const int index = curve_key.get_array_index();
+ const std::string &path = curve_key.get_path();
+ fcurve = create_fcurve(index, path.c_str());
+
+ /* Caution here:
+ Replacing the pointer here is OK only because the original value
+ of FCurve was a const pointer into Blender territory. We do not
+ touch that! We use the local copy to prepare data for export.
+ */
+
+ curve_is_local_copy = true;
+ }
+ return fcurve;
+}
+
+void BCAnimationCurve::clean_handles()
+{
+ if (fcurve == NULL)
+ fcurve = get_edit_fcurve();
+
+ /* Keep old bezt data for copy)*/
+ BezTriple *old_bezts = fcurve->bezt;
+ int totvert = fcurve->totvert;
+ fcurve->bezt = NULL;
+ fcurve->totvert = 0;
+
+ for (int i = 0; i < totvert; i++) {
+ BezTriple *bezt = &old_bezts[i];
+ float x = bezt->vec[1][0];
+ float y = bezt->vec[1][1];
+ insert_vert_fcurve(fcurve, x, y, (eBezTriple_KeyframeType)BEZKEYTYPE(bezt), INSERTKEY_NOFLAGS);
+ BezTriple *lastb = fcurve->bezt + (fcurve->totvert - 1);
+ lastb->f1 = lastb->f2 = lastb->f3 = 0;
+ }
+
+ /* now free the memory used by the old BezTriples */
+ if (old_bezts)
+ MEM_freeN(old_bezts);
+}
+
+const bool BCAnimationCurve::is_transform_curve() const
+{
+ std::string channel_target = this->get_channel_target();
+ return (
+ is_rotation_curve() ||
+ channel_target == "scale" ||
+ channel_target == "location"
+ );
+}
+
+const bool BCAnimationCurve::is_rotation_curve() const
+{
+ std::string channel_target = this->get_channel_target();
+ return (
+ channel_target == "rotation" ||
+ channel_target == "rotation_euler" ||
+ channel_target == "rotation_quaternion"
+ );
+}
+
+const float BCAnimationCurve::get_value(const float frame)
+{
+ if (fcurve) {
+ return evaluate_fcurve(fcurve, frame);
+ }
+ return 0; // TODO: handle case where neither sample nor fcu exist
+}
+
+void BCAnimationCurve::update_range(float val)
+{
+ if (val < min) {
+ min = val;
+ }
+ if (val > max) {
+ max = val;
+ }
+}
+
+void BCAnimationCurve::init_range(float val)
+{
+ min = max = val;
+}
+
+void BCAnimationCurve::adjust_range(const int frame_index)
+{
+ if (fcurve && fcurve->totvert > 1) {
+ const float eval = evaluate_fcurve(fcurve, frame_index);
+
+ int first_frame = fcurve->bezt[0].vec[1][0];
+ if (first_frame == frame_index) {
+ init_range(eval);
+ }
+ else {
+ update_range(eval);
+ }
+ }
+}
+
+void BCAnimationCurve::add_value(const float val, const int frame_index)
+{
+ FCurve *fcu = get_edit_fcurve();
+ fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ insert_vert_fcurve(
+ fcu,
+ frame_index, val,
+ BEZT_KEYTYPE_KEYFRAME,
+ INSERTKEY_NOFLAGS);
+
+ if (fcu->totvert == 1) {
+ init_range(val);
+ }
+ else {
+ update_range(val);
+ }
+}
+
+bool BCAnimationCurve::add_value_from_matrix(const BCSample &sample, const int frame_index)
+{
+ int array_index = curve_key.get_array_index();
+
+ /* transformation curves are feeded directly from the transformation matrix
+ * to resolve parent inverse matrix issues with object hierarchies.
+ * Maybe this can be unified with the
+ */
+ const std::string channel_target = get_channel_target();
+ float val = 0;
+ /* Pick the value from the sample according to the definition of the FCurve */
+ bool good = sample.get_value(channel_target, array_index, &val);
+ if (good) {
+ add_value(val, frame_index);
+ }
+ return good;
+}
+
+bool BCAnimationCurve::add_value_from_rna(const int frame_index)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ float value = 0.0f;
+ int array_index = curve_key.get_array_index();
+ const std::string full_path = curve_key.get_full_path();
+
+ /* get property to read from, and get value as appropriate */
+ bool path_resolved = RNA_path_resolve_full(&id_ptr, full_path.c_str(), &ptr, &prop, &array_index);
+ if (!path_resolved && array_index == 0) {
+ const std::string rna_path = curve_key.get_path();
+ path_resolved = RNA_path_resolve_full(&id_ptr, rna_path.c_str(), &ptr, &prop, &array_index);
+ }
+
+ if (path_resolved) {
+ bool is_array = RNA_property_array_check(prop);
+ if (is_array) {
+ /* array */
+ if ((array_index >= 0) && (array_index < RNA_property_array_length(&ptr, prop))) {
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ value = (float)RNA_property_boolean_get_index(&ptr, prop, array_index);
+ break;
+ case PROP_INT:
+ value = (float)RNA_property_int_get_index(&ptr, prop, array_index);
+ break;
+ case PROP_FLOAT:
+ value = RNA_property_float_get_index(&ptr, prop, array_index);
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ fprintf(stderr, "Out of Bounds while reading data for Curve %s\n", curve_key.get_full_path().c_str());
+ return false;
+ }
+ }
+ else {
+ /* not an array */
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ value = (float)RNA_property_boolean_get(&ptr, prop);
+ break;
+ case PROP_INT:
+ value = (float)RNA_property_int_get(&ptr, prop);
+ break;
+ case PROP_FLOAT:
+ value = RNA_property_float_get(&ptr, prop);
+ break;
+ case PROP_ENUM:
+ value = (float)RNA_property_enum_get(&ptr, prop);
+ break;
+ default:
+ fprintf(stderr, "property type %d not supported for Curve %s\n", RNA_property_type(prop), curve_key.get_full_path().c_str());
+ return false;
+ break;
+ }
+ }
+ }
+ else {
+ /* path couldn't be resolved */
+ fprintf(stderr, "Path not recognized for Curve %s\n", curve_key.get_full_path().c_str());
+ return false;
+ }
+
+ add_value(value, frame_index);
+ return true;
+}
+
+void BCAnimationCurve::get_value_map(BCValueMap &value_map)
+{
+ value_map.clear();
+ if (fcurve == NULL) {
+ return;
+ }
+
+ for (int i = 0; i < fcurve->totvert; i++) {
+ const float frame = fcurve->bezt[i].vec[1][0];
+ const float val = fcurve->bezt[i].vec[1][1];
+ value_map[frame] = val;
+ }
+}
+
+void BCAnimationCurve::get_frames(BCFrames &frames) const
+{
+ frames.clear();
+ if (fcurve) {
+ for (int i = 0; i < fcurve->totvert; i++) {
+ const float val = fcurve->bezt[i].vec[1][0];
+ frames.push_back(val);
+ }
+ }
+}
+
+void BCAnimationCurve::get_values(BCValues &values) const
+{
+ values.clear();
+ if (fcurve) {
+ for (int i = 0; i < fcurve->totvert; i++) {
+ const float val = fcurve->bezt[i].vec[1][1];
+ values.push_back(val);
+ }
+ }
+}
+
+bool BCAnimationCurve::is_animated()
+{
+ static float MIN_DISTANCE = 0.00001;
+ return fabs(max - min) > MIN_DISTANCE;
+}
+
+
+bool BCAnimationCurve::is_keyframe(int frame) {
+ if (this->fcurve == NULL)
+ return false;
+
+ for (int i = 0; i < fcurve->totvert; ++i) {
+ const int cframe = nearbyint(fcurve->bezt[i].vec[1][0]);
+ if (cframe == frame)
+ return true;
+ if (cframe > frame)
+ break;
+ }
+ return false;
+}
+
+/* Needed for adding a BCAnimationCurve into a BCAnimationCurveSet */
+inline bool operator< (const BCAnimationCurve& lhs, const BCAnimationCurve& rhs) {
+ std::string lhtgt = lhs.get_channel_target();
+ std::string rhtgt = rhs.get_channel_target();
+ if (lhtgt == rhtgt)
+ {
+ const int lha = lhs.get_channel_index();
+ const int rha = rhs.get_channel_index();
+ return lha < rha;
+ }
+ else
+ return lhtgt < rhtgt;
+}
+
+BCCurveKey::BCCurveKey()
+{
+ this->key_type = BC_ANIMATION_TYPE_OBJECT;
+ this->rna_path = "";
+ this->curve_array_index = 0;
+ this->curve_subindex = -1;
+}
+
+BCCurveKey::BCCurveKey(const BC_animation_type type, const std::string path, const int array_index, const int subindex)
+{
+ this->key_type = type;
+ this->rna_path = path;
+ this->curve_array_index = array_index;
+ this->curve_subindex = subindex;
+}
+
+void BCCurveKey::operator=(const BCCurveKey &other)
+{
+ this->key_type = other.key_type;
+ this->rna_path = other.rna_path;
+ this->curve_array_index = other.curve_array_index;
+ this->curve_subindex = other.curve_subindex;
+}
+
+const std::string BCCurveKey::get_full_path() const
+{
+ return this->rna_path + '[' + std::to_string(this->curve_array_index) + ']';
+}
+
+const std::string BCCurveKey::get_path() const
+{
+ return this->rna_path;
+}
+
+const int BCCurveKey::get_array_index() const
+{
+ return this->curve_array_index;
+}
+
+const int BCCurveKey::get_subindex() const
+{
+ return this->curve_subindex;
+}
+
+void BCCurveKey::set_object_type(BC_animation_type object_type)
+{
+ this->key_type = object_type;
+}
+
+const BC_animation_type BCCurveKey::get_animation_type() const
+{
+ return this->key_type;
+}
+
+const bool BCCurveKey::operator<(const BCCurveKey &other) const
+{
+ /* needed for using this class as key in maps and sets */
+ if (this->key_type != other.key_type)
+ return this->key_type < other.key_type;
+
+ if (this->curve_subindex != other.curve_subindex)
+ return this->curve_subindex < other.curve_subindex;
+
+ if (this->rna_path != other.rna_path)
+ return this->rna_path < other.rna_path;
+
+ return this->curve_array_index < other.curve_array_index;
+}
+
+BCBezTriple::BCBezTriple(BezTriple &bezt) :
+ bezt(bezt) {}
+
+const float BCBezTriple::get_frame() const
+{
+ return bezt.vec[1][0];
+}
+
+const float BCBezTriple::get_time(Scene *scene) const
+{
+ return FRA2TIME(bezt.vec[1][0]);
+}
+
+const float BCBezTriple::get_value() const
+{
+ return bezt.vec[1][1];
+}
+
+const float BCBezTriple::get_angle() const
+{
+ return RAD2DEGF(get_value());
+}
+
+void BCBezTriple::get_in_tangent(Scene *scene, float point[2], bool as_angle) const
+{
+ get_tangent(scene, point, as_angle, 0);
+}
+
+void BCBezTriple::get_out_tangent(Scene *scene, float point[2], bool as_angle) const
+{
+ get_tangent(scene, point, as_angle, 2);
+}
+
+void BCBezTriple::get_tangent(Scene *scene, float point[2], bool as_angle, int index) const
+{
+ point[0] = FRA2TIME(bezt.vec[index][0]);
+ if (bezt.ipo != BEZT_IPO_BEZ) {
+ /* We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data */
+ point[0] = 0;
+ point[1] = 0;
+ }
+ else if (as_angle) {
+ point[1] = RAD2DEGF(bezt.vec[index][1]);
+ }
+ else {
+ point[1] = bezt.vec[index][1];
+ }
+}
diff --git a/source/blender/collada/BCAnimationCurve.h b/source/blender/collada/BCAnimationCurve.h
new file mode 100644
index 00000000000..c575c969e0f
--- /dev/null
+++ b/source/blender/collada/BCAnimationCurve.h
@@ -0,0 +1,156 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2008 Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Blender Foundation
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#ifndef __BC_ANIMATION_CURVE_H__
+#define __BC_ANIMATION_CURVE_H__
+
+#include "collada_utils.h"
+#include "BCSampleData.h"
+
+extern "C"
+{
+#include "MEM_guardedalloc.h"
+#include "BKE_fcurve.h"
+#include "BKE_armature.h"
+#include "BKE_material.h"
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+}
+
+typedef float(TangentPoint)[2];
+
+typedef std::set<float> BCFrameSet;
+typedef std::vector<float> BCFrames;
+typedef std::vector<float> BCValues;
+typedef std::vector<float> BCTimes;
+typedef std::map<int, float> BCValueMap;
+
+typedef enum BC_animation_type {
+ BC_ANIMATION_TYPE_OBJECT,
+ BC_ANIMATION_TYPE_BONE,
+ BC_ANIMATION_TYPE_CAMERA,
+ BC_ANIMATION_TYPE_MATERIAL,
+ BC_ANIMATION_TYPE_LIGHT
+} BC_animation_type;
+
+class BCCurveKey {
+private:
+ BC_animation_type key_type;
+ std::string rna_path;
+ int curve_array_index;
+ int curve_subindex; /* only needed for materials */
+
+public:
+
+ BCCurveKey();
+ BCCurveKey(const BC_animation_type type, const std::string path, const int array_index, const int subindex = -1);
+ void operator=(const BCCurveKey &other);
+ const std::string get_full_path() const;
+ const std::string get_path() const;
+ const int get_array_index() const;
+ const int get_subindex() const;
+ void set_object_type(BC_animation_type object_type);
+ const BC_animation_type get_animation_type() const;
+ const bool operator<(const BCCurveKey &other) const;
+
+};
+
+class BCBezTriple {
+public:
+ BezTriple & bezt;
+
+ BCBezTriple(BezTriple &bezt);
+ const float get_frame() const;
+ const float get_time(Scene *scene) const;
+ const float get_value() const;
+ const float get_angle() const;
+ void get_in_tangent(Scene *scene, float point[2], bool as_angle) const;
+ void get_out_tangent(Scene *scene, float point[2], bool as_angle) const;
+ void get_tangent(Scene *scene, float point[2], bool as_angle, int index) const;
+
+};
+
+class BCAnimationCurve {
+private:
+ BCCurveKey curve_key;
+ float min = 0;
+ float max = 0;
+
+ bool curve_is_local_copy = false;
+ FCurve *fcurve;
+ PointerRNA id_ptr;
+ void init_pointer_rna(Object *ob);
+ void delete_fcurve(FCurve *fcu);
+ FCurve *create_fcurve(int array_index, const char *rna_path);
+ void create_bezt(float frame, float output);
+ void update_range(float val);
+ void init_range(float val);
+
+public:
+ BCAnimationCurve();
+ BCAnimationCurve(const BCAnimationCurve &other);
+ BCAnimationCurve(const BCCurveKey &key, Object *ob);
+ BCAnimationCurve(BCCurveKey key, Object *ob, FCurve *fcu);
+ ~BCAnimationCurve();
+
+ const bool is_of_animation_type(BC_animation_type type) const;
+ const int get_interpolation_type(float sample_frame) const;
+ bool is_animated();
+ const bool is_transform_curve() const;
+ const bool is_rotation_curve() const;
+ bool is_keyframe(int frame);
+ void adjust_range(int frame);
+
+ const std::string get_animation_name(Object *ob) const; /* xxx: this is collada specific */
+ const std::string get_channel_target() const;
+ const int get_channel_index() const;
+ const int get_subindex() const;
+ const std::string get_rna_path() const;
+ const FCurve *get_fcurve() const;
+ const int sample_count() const;
+
+ const float get_value(const float frame);
+ void get_values(BCValues &values) const;
+ void get_value_map(BCValueMap &value_map);
+
+ void get_frames(BCFrames &frames) const;
+
+ /* Curve edit functions create a copy of the underlaying FCurve */
+ FCurve *get_edit_fcurve();
+ bool add_value_from_rna(const int frame);
+ bool add_value_from_matrix(const BCSample &sample, const int frame);
+ void add_value(const float val, const int frame);
+ void clean_handles();
+
+ /* experimental stuff */
+ const int closest_index_above(const float sample_frame, const int start_at) const;
+ const int closest_index_below(const float sample_frame) const;
+
+};
+
+typedef std::map<BCCurveKey, BCAnimationCurve *> BCAnimationCurveMap;
+
+#endif
diff --git a/source/blender/collada/BCAnimationSampler.cpp b/source/blender/collada/BCAnimationSampler.cpp
new file mode 100644
index 00000000000..5c0c1b4316d
--- /dev/null
+++ b/source/blender/collada/BCAnimationSampler.cpp
@@ -0,0 +1,645 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2008 Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Blender Foundation
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#include <vector>
+#include <map>
+#include <algorithm> // std::find
+
+#include "ExportSettings.h"
+#include "BCAnimationCurve.h"
+#include "BCAnimationSampler.h"
+#include "collada_utils.h"
+
+extern "C" {
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_key.h"
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+#include "BLI_listbase.h"
+#include "DNA_anim_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_key_types.h"
+#include "DNA_constraint_types.h"
+#include "ED_object.h"
+}
+
+static std::string EMPTY_STRING;
+static BCAnimationCurveMap BCEmptyAnimationCurves;
+
+BCAnimationSampler::BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &object_set):
+ blender_context(blender_context)
+{
+ BCObjectSet::iterator it;
+ for (it = object_set.begin(); it != object_set.end(); ++it) {
+ Object *ob = *it;
+ add_object(ob);
+ }
+}
+
+BCAnimationSampler::~BCAnimationSampler()
+{
+ BCAnimationObjectMap::iterator it;
+ for (it = objects.begin(); it != objects.end(); ++it) {
+ BCAnimation *animation = it->second;
+ delete animation;
+ }
+}
+
+void BCAnimationSampler::add_object(Object *ob)
+{
+ BCAnimation *animation = new BCAnimation(blender_context.get_context(), ob);
+ objects[ob] = animation;
+
+ initialize_keyframes(animation->frame_set, ob);
+ initialize_curves(animation->curve_map, ob);
+}
+
+BCAnimationCurveMap *BCAnimationSampler::get_curves(Object *ob)
+{
+ BCAnimation &animation = *objects[ob];
+ if (animation.curve_map.size() == 0)
+ initialize_curves(animation.curve_map, ob);
+ return &animation.curve_map;
+}
+
+static void get_sample_frames(BCFrameSet &sample_frames, int sampling_rate, bool keyframe_at_end, Scene *scene)
+{
+ sample_frames.clear();
+
+ if (sampling_rate < 1)
+ return; // no sample frames in this case
+
+ float sfra = scene->r.sfra;
+ float efra = scene->r.efra;
+
+ int frame_index;
+ for (frame_index = nearbyint(sfra); frame_index < efra; frame_index += sampling_rate) {
+ sample_frames.insert(frame_index);
+ }
+
+ if (frame_index >= efra && keyframe_at_end)
+ {
+ sample_frames.insert(efra);
+ }
+}
+
+static bool is_object_keyframe(Object *ob, int frame_index)
+{
+ return false;
+}
+
+static void add_keyframes_from(bAction *action, BCFrameSet &frameset)
+{
+ if (action) {
+ FCurve *fcu = NULL;
+ for (fcu = (FCurve *)action->curves.first; fcu; fcu = fcu->next) {
+ BezTriple *bezt = fcu->bezt;
+ for (int i = 0; i < fcu->totvert; bezt++, i++) {
+ int frame_index = nearbyint(bezt->vec[1][0]);
+ frameset.insert(frame_index);
+ }
+ }
+ }
+}
+
+void BCAnimationSampler::check_property_is_animated(BCAnimation &animation, float *ref, float *val, std::string data_path, int length)
+{
+ for (int array_index =0; array_index < length; ++array_index) {
+ if (!bc_in_range(ref[length], val[length], 0.00001)) {
+ BCCurveKey key(BC_ANIMATION_TYPE_OBJECT, data_path, array_index);
+ BCAnimationCurveMap::iterator it = animation.curve_map.find(key);
+ if (it == animation.curve_map.end()) {
+ animation.curve_map[key] = new BCAnimationCurve(key, animation.get_reference());
+ }
+ }
+ }
+}
+
+void BCAnimationSampler::update_animation_curves(BCAnimation &animation, BCSample &sample, Object *ob, int frame)
+{
+ BCAnimationCurveMap::iterator it;
+ for (it = animation.curve_map.begin(); it != animation.curve_map.end(); ++it) {
+ BCAnimationCurve *curve = it->second;
+ if (curve->is_transform_curve()) {
+ curve->add_value_from_matrix(sample, frame);
+ }
+ else {
+ curve->add_value_from_rna(frame);
+ }
+ }
+}
+
+BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool for_opensim)
+{
+ BCSample &ob_sample = sample_data.add(ob, frame_index);
+
+ if (ob->type == OB_ARMATURE) {
+ bPoseChannel *pchan;
+ for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ Matrix bmat;
+ if (bc_bone_matrix_local_get(ob, bone, bmat, for_opensim)) {
+ ob_sample.add_bone_matrix(bone, bmat);
+ }
+ }
+ }
+ return ob_sample;
+}
+
+void BCAnimationSampler::sample_scene(
+ int sampling_rate,
+ int keyframe_at_end,
+ bool for_opensim,
+ bool keep_keyframes,
+ BC_export_animation_type export_animation_type)
+{
+ Scene *scene = blender_context.get_scene();
+ BCFrameSet scene_sample_frames;
+ get_sample_frames(scene_sample_frames, sampling_rate, keyframe_at_end, scene);
+ BCFrameSet::iterator it;
+
+ int startframe = scene->r.sfra;
+ int endframe = scene->r.efra;
+
+ for (int frame_index = startframe; frame_index <= endframe; ++frame_index) {
+ /* Loop over all frames and decide for each frame if sampling is necessary */
+ bool is_scene_sample_frame = false;
+ bool needs_update = true;
+ if (scene_sample_frames.find(frame_index) != scene_sample_frames.end()) {
+ bc_update_scene(blender_context, frame_index);
+ needs_update = false;
+ is_scene_sample_frame = true;
+ }
+
+ bool needs_sampling = is_scene_sample_frame || keep_keyframes || export_animation_type == BC_ANIMATION_EXPORT_KEYS;
+ if (!needs_sampling) {
+ continue;
+ }
+
+ BCAnimationObjectMap::iterator obit;
+ for (obit = objects.begin(); obit != objects.end(); ++obit) {
+ Object *ob = obit->first;
+ BCAnimation *animation = obit->second;
+ BCFrameSet &object_keyframes = animation->frame_set;
+ if (is_scene_sample_frame || object_keyframes.find(frame_index) != object_keyframes.end()) {
+
+ if (needs_update) {
+ bc_update_scene(blender_context, frame_index);
+ needs_update = false;
+ }
+
+ BCSample &sample = sample_object(ob, frame_index, for_opensim);
+ update_animation_curves(*animation, sample, ob, frame_index);
+ }
+ }
+ }
+}
+
+bool BCAnimationSampler::is_animated_by_constraint(Object *ob, ListBase *conlist, std::set<Object *> &animated_objects)
+{
+ bConstraint *con;
+ for (con = (bConstraint *)conlist->first; con; con = con->next) {
+ ListBase targets = { NULL, NULL };
+
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+
+ if (!bc_validateConstraints(con))
+ continue;
+
+ if (cti && cti->get_constraint_targets) {
+ bConstraintTarget *ct;
+ Object *obtar;
+ cti->get_constraint_targets(con, &targets);
+ for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
+ obtar = ct->tar;
+ if (obtar) {
+ if (animated_objects.find(obtar) != animated_objects.end())
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void BCAnimationSampler::find_depending_animated(std::set<Object *> &animated_objects, std::set<Object *> &candidates)
+{
+ bool found_more;
+ do {
+ found_more = false;
+ std::set<Object *>::iterator it;
+ for (it = candidates.begin(); it != candidates.end(); ++it) {
+ Object *cob = *it;
+ ListBase *conlist = get_active_constraints(cob);
+ if (is_animated_by_constraint(cob, conlist, animated_objects)) {
+ animated_objects.insert(cob);
+ candidates.erase(cob);
+ found_more = true;
+ break;
+ }
+ }
+ } while (found_more && candidates.size() > 0);
+}
+
+void BCAnimationSampler::get_animated_from_export_set(std::set<Object *> &animated_objects, LinkNode &export_set)
+{
+ /*
+ Check if this object is animated. That is: Check if it has its own action, or
+
+ - Check if it has constraints to other objects
+ - at least one of the other objects is animated as well
+ */
+
+ animated_objects.clear();
+ std::set<Object *> static_objects;
+ std::set<Object *> candidates;
+
+ LinkNode *node;
+ for (node = &export_set; node; node = node->next) {
+ Object *cob = (Object *)node->link;
+ if (bc_has_animations(cob)) {
+ animated_objects.insert(cob);
+ }
+ else {
+ ListBase conlist = cob->constraints;
+ if (conlist.first)
+ candidates.insert(cob);
+ }
+ }
+ find_depending_animated(animated_objects, candidates);
+}
+
+void BCAnimationSampler::get_object_frames(BCFrames &frames, Object *ob)
+{
+ sample_data.get_frames(ob, frames);
+}
+
+void BCAnimationSampler::get_bone_frames(BCFrames &frames, Object *ob, Bone *bone)
+{
+ sample_data.get_frames(ob, bone, frames);
+}
+
+bool BCAnimationSampler::get_bone_samples(BCMatrixSampleMap &samples, Object *ob, Bone *bone)
+{
+ sample_data.get_matrices(ob, bone, samples);
+ return bc_is_animated(samples);
+}
+
+bool BCAnimationSampler::get_object_samples(BCMatrixSampleMap &samples, Object *ob)
+{
+ sample_data.get_matrices(ob, samples);
+ return bc_is_animated(samples);
+}
+
+#if 0
+/*
+ Add sampled values to FCurve
+ If no FCurve exists, create a temporary FCurve;
+ Note: The temporary FCurve will later be removed when the
+ BCAnimationSampler is removed (by its destructor)
+
+ curve: The curve to whioch the data is added
+ matrices: The set of matrix values from where the data is taken
+ animation_type BC_ANIMATION_EXPORT_SAMPLES: Use all matrix data
+ animation_type BC_ANIMATION_EXPORT_KEYS: Only take data from matrices for keyframes
+*/
+
+void BCAnimationSampler::add_value_set(
+ BCAnimationCurve &curve,
+ BCFrameSampleMap &samples,
+ BC_export_animation_type animation_type)
+{
+ int array_index = curve.get_array_index();
+ const BC_animation_transform_type tm_type = curve.get_transform_type();
+
+ BCFrameSampleMap::iterator it;
+ for (it = samples.begin(); it != samples.end(); ++it) {
+ const int frame_index = nearbyint(it->first);
+ if (animation_type == BC_ANIMATION_EXPORT_SAMPLES || curve.is_keyframe(frame_index)) {
+
+ const BCSample *sample = it->second;
+ float val = 0;
+
+ int subindex = curve.get_subindex();
+ bool good;
+ if (subindex == -1) {
+ good = sample->get_value(tm_type, array_index, &val);
+ }
+ else {
+ good = sample->get_value(tm_type, array_index, &val, subindex);
+ }
+
+ if (good) {
+ curve.add_value(val, frame_index);
+ }
+ }
+ }
+ curve.remove_unused_keyframes();
+ curve.calchandles();
+}
+#endif
+
+void BCAnimationSampler::generate_transform(
+ Object *ob,
+ const BCCurveKey &key,
+ BCAnimationCurveMap &curves)
+{
+ BCAnimationCurveMap::const_iterator it = curves.find(key);
+ if (it == curves.end()) {
+ curves[key] = new BCAnimationCurve(key, ob);
+ }
+}
+
+void BCAnimationSampler::generate_transforms(
+ Object *ob,
+ const std::string prep,
+ const BC_animation_type type,
+ BCAnimationCurveMap &curves)
+{
+ generate_transform(ob, BCCurveKey(type, prep+"location", 0), curves);
+ generate_transform(ob, BCCurveKey(type, prep+"location", 1), curves);
+ generate_transform(ob, BCCurveKey(type, prep+"location", 2), curves);
+ generate_transform(ob, BCCurveKey(type, prep+"rotation_euler", 0), curves);
+ generate_transform(ob, BCCurveKey(type, prep+"rotation_euler", 1), curves);
+ generate_transform(ob, BCCurveKey(type, prep+"rotation_euler", 2), curves);
+ generate_transform(ob, BCCurveKey(type, prep+"scale", 0), curves);
+ generate_transform(ob, BCCurveKey(type, prep+"scale", 1), curves);
+ generate_transform(ob, BCCurveKey(type, prep+"scale", 2), curves);
+}
+
+void BCAnimationSampler::generate_transforms(Object *ob, Bone *bone, BCAnimationCurveMap &curves)
+{
+ std::string prep = "pose.bones[\"" + std::string(bone->name) + "\"].";
+ generate_transforms(ob, prep, BC_ANIMATION_TYPE_BONE, curves);
+
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
+ generate_transforms(ob, child, curves);
+}
+
+/*
+* Collect all keyframes from all animation curves related to the object
+* The bc_get... functions check for NULL and correct object type
+* The add_keyframes_from() function checks for NULL
+*/
+void BCAnimationSampler::initialize_keyframes(BCFrameSet &frameset, Object *ob)
+{
+ frameset.clear();
+ add_keyframes_from(bc_getSceneObjectAction(ob), frameset);
+ add_keyframes_from(bc_getSceneCameraAction(ob), frameset);
+ add_keyframes_from(bc_getSceneLampAction(ob), frameset);
+
+ for (int a = 0; a < ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a + 1);
+ add_keyframes_from(bc_getSceneMaterialAction(ma), frameset);
+ }
+}
+
+void BCAnimationSampler::initialize_curves(BCAnimationCurveMap &curves, Object *ob)
+{
+ BC_animation_type object_type = BC_ANIMATION_TYPE_OBJECT;
+
+ bAction *action = bc_getSceneObjectAction(ob);
+ if (action) {
+ FCurve *fcu = (FCurve *)action->curves.first;
+
+ for (; fcu; fcu = fcu->next) {
+ object_type = BC_ANIMATION_TYPE_OBJECT;
+ if (ob->type == OB_ARMATURE) {
+ char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ if (boneName) {
+ object_type = BC_ANIMATION_TYPE_BONE;
+ }
+ }
+
+ /* Adding action curves on object */
+ BCCurveKey key(object_type, fcu->rna_path, fcu->array_index);
+ curves[key] = new BCAnimationCurve(key, ob, fcu);
+ }
+ }
+
+ /* Add missing curves */
+ object_type = BC_ANIMATION_TYPE_OBJECT;
+ generate_transforms(ob, EMPTY_STRING, object_type, curves);
+ if (ob->type == OB_ARMATURE) {
+ bArmature *arm = (bArmature *)ob->data;
+ for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next)
+ generate_transforms(ob, root_bone, curves);
+ }
+
+ /* Add curves on Object->data actions */
+ action = NULL;
+ if (ob->type == OB_CAMERA) {
+ action = bc_getSceneCameraAction(ob);
+ object_type = BC_ANIMATION_TYPE_CAMERA;
+ }
+ else if (ob->type == OB_LAMP) {
+ action = bc_getSceneLampAction(ob);
+ object_type = BC_ANIMATION_TYPE_LIGHT;
+ }
+
+ if (action) {
+ /* Add lamp action or Camera action */
+ FCurve *fcu = (FCurve *)action->curves.first;
+ for (; fcu; fcu = fcu->next) {
+ BCCurveKey key(object_type, fcu->rna_path, fcu->array_index);
+ curves[key] = new BCAnimationCurve(key, ob, fcu);
+ }
+ }
+
+ /* Add curves on Object->material actions*/
+ object_type = BC_ANIMATION_TYPE_MATERIAL;
+ for (int a = 0; a < ob->totcol; a++) {
+ /* Export Material parameter animations. */
+ Material *ma = give_current_material(ob, a + 1);
+ if (ma) {
+ action = bc_getSceneMaterialAction(ma);
+ if (action) {
+ /* isMatAnim = true; */
+ FCurve *fcu = (FCurve *)action->curves.first;
+ for (; fcu; fcu = fcu->next) {
+ BCCurveKey key(object_type, fcu->rna_path, fcu->array_index, a);
+ curves[key] = new BCAnimationCurve(key, ob, fcu);
+ }
+ }
+ }
+ }
+}
+
+/* ==================================================================== */
+
+BCSample &BCSampleFrame::add(Object *ob)
+{
+ BCSample *sample = new BCSample(ob);
+ sampleMap[ob] = sample;
+ return *sample;
+}
+
+/* Get the matrix for the given key, returns Unity when the key does not exist */
+const BCSample *BCSampleFrame::get_sample(Object *ob) const
+{
+ BCSampleMap::const_iterator it = sampleMap.find(ob);
+ if (it == sampleMap.end()) {
+ return NULL;
+ }
+ return it->second;
+}
+
+const BCMatrix *BCSampleFrame::get_sample_matrix(Object *ob) const
+{
+ BCSampleMap::const_iterator it = sampleMap.find(ob);
+ if (it == sampleMap.end()) {
+ return NULL;
+ }
+ BCSample *sample = it->second;
+ return &sample->get_matrix();
+}
+
+/* Get the matrix for the given Bone, returns Unity when the Objewct is not sampled */
+const BCMatrix *BCSampleFrame::get_sample_matrix(Object *ob, Bone *bone) const
+{
+ BCSampleMap::const_iterator it = sampleMap.find(ob);
+ if (it == sampleMap.end()) {
+ return NULL;
+ }
+
+ BCSample *sample = it->second;
+ const BCMatrix *bc_bone = sample->get_matrix(bone);
+ return bc_bone;
+}
+
+/* Check if the key is in this BCSampleFrame */
+const bool BCSampleFrame::has_sample_for(Object *ob) const
+{
+ return sampleMap.find(ob) != sampleMap.end();
+}
+
+/* Check if the Bone is in this BCSampleFrame */
+const bool BCSampleFrame::has_sample_for(Object *ob, Bone *bone) const
+{
+ const BCMatrix *bc_bone = get_sample_matrix(ob, bone);
+ return (bc_bone);
+}
+
+/* ==================================================================== */
+
+BCSample &BCSampleFrameContainer::add(Object *ob, int frame_index)
+{
+ BCSampleFrame &frame = sample_frames[frame_index];
+ return frame.add(ob);
+}
+
+
+/* ====================================================== */
+/* Below are the getters which we need to export the data */
+/* ====================================================== */
+
+/* Return either the BCSampleFrame or NULL if frame does not exist*/
+BCSampleFrame * BCSampleFrameContainer::get_frame(int frame_index)
+{
+ BCSampleFrameMap::iterator it = sample_frames.find(frame_index);
+ BCSampleFrame *frame = (it == sample_frames.end()) ? NULL : &it->second;
+ return frame;
+}
+
+/* Return a list of all frames that need to be sampled */
+const int BCSampleFrameContainer::get_frames(std::vector<int> &frames) const
+{
+ frames.clear(); // safety;
+ BCSampleFrameMap::const_iterator it;
+ for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
+ frames.push_back(it->first);
+ }
+ return frames.size();
+}
+
+const int BCSampleFrameContainer::get_frames(Object *ob, BCFrames &frames) const
+{
+ frames.clear(); // safety;
+ BCSampleFrameMap::const_iterator it;
+ for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
+ const BCSampleFrame &frame = it->second;
+ if (frame.has_sample_for(ob)) {
+ frames.push_back(it->first);
+ }
+ }
+ return frames.size();
+}
+
+const int BCSampleFrameContainer::get_frames(Object *ob, Bone *bone, BCFrames &frames) const
+{
+ frames.clear(); // safety;
+ BCSampleFrameMap::const_iterator it;
+ for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
+ const BCSampleFrame &frame = it->second;
+ if (frame.has_sample_for(ob, bone)) {
+ frames.push_back(it->first);
+ }
+ }
+ return frames.size();
+}
+
+const int BCSampleFrameContainer::get_samples(Object *ob, BCFrameSampleMap &samples) const
+{
+ samples.clear(); // safety;
+ BCSampleFrameMap::const_iterator it;
+ for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
+ const BCSampleFrame &frame = it->second;
+ const BCSample *sample = frame.get_sample(ob);
+ if (sample) {
+ samples[it->first] = sample;
+ }
+ }
+ return samples.size();
+}
+
+const int BCSampleFrameContainer::get_matrices(Object *ob, BCMatrixSampleMap &samples) const
+{
+ samples.clear(); // safety;
+ BCSampleFrameMap::const_iterator it;
+ for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
+ const BCSampleFrame &frame = it->second;
+ const BCMatrix *matrix = frame.get_sample_matrix(ob);
+ if (matrix) {
+ samples[it->first] = matrix;
+ }
+ }
+ return samples.size();
+}
+
+const int BCSampleFrameContainer::get_matrices(Object *ob, Bone *bone, BCMatrixSampleMap &samples) const
+{
+ samples.clear(); // safety;
+ BCSampleFrameMap::const_iterator it;
+ for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
+ const BCSampleFrame &frame = it->second;
+ const BCMatrix *sample = frame.get_sample_matrix(ob, bone);
+ if (sample) {
+ samples[it->first] = sample;
+ }
+ }
+ return samples.size();
+}
diff --git a/source/blender/collada/BCAnimationSampler.h b/source/blender/collada/BCAnimationSampler.h
new file mode 100644
index 00000000000..8bf2967a44f
--- /dev/null
+++ b/source/blender/collada/BCAnimationSampler.h
@@ -0,0 +1,205 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2008 Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Blender Foundation
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#ifndef __BC_ANIMATION_CURVE_CONTAINER_H__
+#define __BC_ANIMATION_CURVE_CONTAINER_H__
+
+#include "BCAnimationCurve.h"
+#include "BCSampleData.h"
+#include "collada_utils.h"
+
+extern "C" {
+#include "BKE_action.h"
+#include "BKE_library.h"
+#include "BLI_math_rotation.h"
+#include "DNA_action_types.h"
+}
+
+/* Collection of animation curves */
+class BCAnimation {
+private:
+ Object *reference = NULL;
+ bContext *mContext;
+
+
+public:
+ BCFrameSet frame_set;
+ BCAnimationCurveMap curve_map;
+
+ BCAnimation(bContext *C, Object *ob):
+ mContext(C)
+ {
+ Main *bmain = CTX_data_main(mContext);
+ reference = BKE_object_copy(bmain, ob);
+ }
+
+ ~BCAnimation()
+ {
+ BCAnimationCurveMap::iterator it;
+ for (it = curve_map.begin(); it != curve_map.end(); ++it) {
+ delete it->second;
+ }
+
+ if (reference && reference->id.us == 0)
+ {
+ Main *bmain = CTX_data_main(mContext);
+ BKE_libblock_delete(bmain, &reference->id);
+ }
+ curve_map.clear();
+ }
+
+ Object *get_reference()
+ {
+ return reference;
+ }
+};
+
+typedef std::map<Object *, BCAnimation *> BCAnimationObjectMap;
+
+class BCSampleFrame {
+
+ /*
+ Each frame on the timeline that needs to be sampled will have
+ one BCSampleFrame where we collect sample information about all objects
+ that need to be sampled for that frame.
+ */
+
+private:
+ BCSampleMap sampleMap;
+
+public:
+
+ ~BCSampleFrame()
+ {
+ BCSampleMap::iterator it;
+ for (it = sampleMap.begin(); it != sampleMap.end(); ++it) {
+ BCSample *sample = it->second;
+ delete sample;
+ }
+ sampleMap.clear();
+ }
+
+ BCSample &add(Object *ob);
+
+ /* Following methods return NULL if object is not in the sampleMap*/
+ const BCSample *get_sample(Object *ob) const;
+ const BCMatrix *get_sample_matrix(Object *ob) const;
+ const BCMatrix *get_sample_matrix(Object *ob, Bone *bone) const;
+
+ const bool has_sample_for(Object *ob) const;
+ const bool has_sample_for(Object *ob, Bone *bone) const;
+};
+
+typedef std::map<int, BCSampleFrame> BCSampleFrameMap;
+
+class BCSampleFrameContainer {
+
+ /*
+ * The BCSampleFrameContainer stores a map of BCSampleFrame objects
+ * with the timeline frame as key.
+ *
+ * Some details on the purpose:
+ * An Animation is made of multiple FCurves where each FCurve can
+ * have multiple keyframes. When we want to export the animation we
+ * also can decide whether we want to export the keyframes or a set
+ * of sample frames at equidistant locations (sample period).
+ * In any case we must resample first need to resample it fully
+ * to resolve things like:
+ *
+ * - animations by constraints
+ * - animations by drivers
+ *
+ * For this purpose we need to step through the entire animation and
+ * then sample each frame that contains at least one keyFrame or
+ * sampleFrame. Then for each frame we have to store the transform
+ * information for all exported objects in a BCSampleframe
+ *
+ * The entire set of BCSampleframes is finally collected into
+ * a BCSampleframneContainer
+ */
+
+private:
+ BCSampleFrameMap sample_frames;
+
+public:
+
+ ~BCSampleFrameContainer()
+ {
+ }
+
+ BCSample &add(Object *ob, int frame_index);
+ BCSampleFrame * get_frame(int frame_index); // returns NULL if frame does not exist
+
+ const int get_frames(std::vector<int> &frames) const;
+ const int get_frames(Object *ob, BCFrames &frames) const;
+ const int get_frames(Object *ob, Bone *bone, BCFrames &frames) const;
+
+ const int get_samples(Object *ob, BCFrameSampleMap &samples) const;
+ const int get_matrices(Object *ob, BCMatrixSampleMap &matrices) const;
+ const int get_matrices(Object *ob, Bone *bone, BCMatrixSampleMap &bones) const;
+};
+
+class BCAnimationSampler {
+private:
+ BlenderContext &blender_context;
+ BCSampleFrameContainer sample_data;
+ BCAnimationObjectMap objects;
+
+ void generate_transform(Object *ob, const BCCurveKey &key, BCAnimationCurveMap &curves);
+ void generate_transforms(Object *ob, const std::string prep, const BC_animation_type type, BCAnimationCurveMap &curves);
+ void generate_transforms(Object *ob, Bone *bone, BCAnimationCurveMap &curves);
+
+ void initialize_curves(BCAnimationCurveMap &curves, Object *ob);
+ void initialize_keyframes(BCFrameSet &frameset, Object *ob);
+ BCSample &sample_object(Object *ob, int frame_index, bool for_opensim);
+ void update_animation_curves(BCAnimation &animation, BCSample &sample, Object *ob, int frame_index);
+ void check_property_is_animated(BCAnimation &animation, float *ref, float *val, std::string data_path, int length);
+
+public:
+ BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &animated_subset);
+ ~BCAnimationSampler();
+
+ void add_object(Object *ob);
+
+ void sample_scene(
+ int sampling_rate,
+ int keyframe_at_end,
+ bool for_opensim,
+ bool keep_keyframes,
+ BC_export_animation_type export_animation_type);
+
+ BCAnimationCurveMap *get_curves(Object *ob);
+ void get_object_frames(BCFrames &frames, Object *ob);
+ bool get_object_samples(BCMatrixSampleMap &samples, Object *ob);
+ void get_bone_frames(BCFrames &frames, Object *ob, Bone *bone);
+ bool get_bone_samples(BCMatrixSampleMap &samples, Object *ob, Bone *bone);
+
+ static void get_animated_from_export_set(std::set<Object *> &animated_objects, LinkNode &export_set);
+ static void find_depending_animated(std::set<Object *> &animated_objects, std::set<Object *> &candidates);
+ static bool is_animated_by_constraint(Object *ob, ListBase *conlist, std::set<Object *> &animated_objects);
+
+};
+
+#endif
diff --git a/source/blender/collada/BCSampleData.cpp b/source/blender/collada/BCSampleData.cpp
new file mode 100644
index 00000000000..95898bb5429
--- /dev/null
+++ b/source/blender/collada/BCSampleData.cpp
@@ -0,0 +1,186 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2008 Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Blender Foundation
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#include "BCSampleData.h"
+#include "collada_utils.h"
+
+BCSample::BCSample(Object *ob):
+ obmat(ob)
+{}
+
+BCSample::~BCSample()
+{
+ BCBoneMatrixMap::iterator it;
+ for (it = bonemats.begin(); it != bonemats.end(); ++it) {
+ delete it->second;
+ }
+}
+
+void BCSample::add_bone_matrix(Bone *bone, Matrix &mat)
+{
+ BCMatrix *matrix;
+ BCBoneMatrixMap::const_iterator it = bonemats.find(bone);
+ if (it != bonemats.end()) {
+ throw std::invalid_argument("bone " + std::string(bone->name) + " already defined before");
+ }
+ matrix = new BCMatrix(mat);
+ bonemats[bone] = matrix;
+}
+
+BCMatrix::BCMatrix(Matrix &mat)
+{
+ set_transform(mat);
+}
+
+BCMatrix::BCMatrix(Object *ob)
+{
+ set_transform(ob);
+}
+
+void BCMatrix::set_transform(Matrix &mat)
+{
+ copy_m4_m4(matrix, mat);
+ mat4_decompose(this->loc, this->q, this->size, mat);
+ quat_to_eul(this->rot, this->q);
+}
+
+void BCMatrix::set_transform(Object *ob)
+{
+ Matrix lmat;
+
+ BKE_object_matrix_local_get(ob, lmat);
+ copy_m4_m4(matrix, lmat);
+
+ mat4_decompose(this->loc, this->q, this->size, lmat);
+ quat_to_compatible_eul(this->rot, ob->rot, this->q);
+}
+
+const BCMatrix *BCSample::get_matrix(Bone *bone) const
+{
+ BCBoneMatrixMap::const_iterator it = bonemats.find(bone);
+ if (it == bonemats.end()) {
+ return NULL;
+ }
+ return it->second;
+}
+
+const BCMatrix &BCSample::get_matrix() const
+{
+ return obmat;
+}
+
+
+/* Get channel value */
+const bool BCSample::get_value(std::string channel_target, const int array_index, float *val) const
+{
+ if (channel_target == "location") {
+ *val = obmat.location()[array_index];
+ }
+ else if (channel_target == "scale") {
+ *val = obmat.scale()[array_index];
+ }
+ else if (
+ channel_target == "rotation" ||
+ channel_target == "rotation_euler") {
+ *val = obmat.rotation()[array_index];
+ }
+ else if (channel_target == "rotation_quat") {
+ *val = obmat.quat()[array_index];
+ }
+ else {
+ *val = 0;
+ return false;
+ }
+
+ return true;
+}
+
+void BCMatrix::copy(Matrix &out, Matrix &in)
+{
+ /* destination comes first: */
+ memcpy(out, in, sizeof(Matrix));
+}
+
+void BCMatrix::transpose(Matrix &mat)
+{
+ transpose_m4(mat);
+}
+
+void BCMatrix::sanitize(Matrix &mat, int precision)
+{
+ bc_sanitize_mat(mat, precision);
+}
+
+void BCMatrix::unit()
+{
+ unit_m4(matrix);
+}
+
+/*
+We need double here because the OpenCollada API needs it.
+precision = -1 indicates to not limit the precision
+*/
+void BCMatrix::get_matrix(double(&mat)[4][4], const bool transposed, const int precision) const
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++) {
+ float val = (transposed) ? matrix[j][i] : matrix[i][j];
+ if (precision >= 0)
+ val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision);
+ mat[i][j] = val;
+ }
+}
+
+const bool BCMatrix::in_range(const BCMatrix &other, float distance) const
+{
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ if (fabs(other.matrix[i][j] - matrix[i][j]) > distance) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+float(&BCMatrix::location() const)[3]
+{
+ return loc;
+}
+
+float(&BCMatrix::rotation() const)[3]
+{
+ return rot;
+}
+
+float(&BCMatrix::scale() const)[3]
+{
+ return size;
+}
+
+float(&BCMatrix::quat() const)[4]
+{
+ return q;
+}
diff --git a/source/blender/collada/BCSampleData.h b/source/blender/collada/BCSampleData.h
new file mode 100644
index 00000000000..a685cb30fa6
--- /dev/null
+++ b/source/blender/collada/BCSampleData.h
@@ -0,0 +1,102 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2008 Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Blender Foundation
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#ifndef __BC_SAMPLE_H__
+#define __BC_SAMPLE_H__
+
+#include <string>
+#include <map>
+#include <algorithm>
+
+extern "C"
+{
+#include "BKE_object.h"
+#include "BLI_math_rotation.h"
+#include "DNA_object_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_material_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_camera_types.h"
+}
+
+typedef float(Matrix)[4][4];
+
+class BCMatrix {
+
+private:
+ mutable float matrix[4][4];
+ mutable float size[3];
+ mutable float rot[3];
+ mutable float loc[3];
+ mutable float q[4];
+
+ void unit();
+ void copy(Matrix &r, Matrix &a);
+ void set_transform(Object *ob);
+ void set_transform(Matrix &mat);
+
+public:
+
+ float(&location() const)[3];
+ float(&rotation() const)[3];
+ float(&scale() const)[3];
+ float(&quat() const)[4];
+
+ BCMatrix(Matrix &mat);
+ BCMatrix(Object *ob);
+
+ void get_matrix(double(&mat)[4][4], const bool transposed = false, const int precision = -1) const;
+
+ const bool in_range(const BCMatrix &other, float distance) const;
+ static void sanitize(Matrix &matrix, int precision);
+ static void transpose(Matrix &matrix);
+
+};
+
+typedef std::map<Bone *, BCMatrix *> BCBoneMatrixMap;
+
+class BCSample{
+private:
+
+ BCMatrix obmat;
+ BCBoneMatrixMap bonemats; /* For Armature animation */
+
+public:
+ BCSample(Object *ob);
+ ~BCSample();
+
+ void add_bone_matrix(Bone *bone, Matrix &mat);
+
+ const bool get_value(std::string channel_target, const int array_index, float *val) const;
+ const BCMatrix &get_matrix() const;
+ const BCMatrix *get_matrix(Bone *bone) const; // returns NULL if bone is not animated
+
+};
+
+typedef std::map<Object *, BCSample *> BCSampleMap;
+typedef std::map<int, const BCSample *> BCFrameSampleMap;
+typedef std::map<int, const BCMatrix *> BCMatrixSampleMap;
+
+#endif
diff --git a/source/blender/collada/BlenderContext.cpp b/source/blender/collada/BlenderContext.cpp
new file mode 100644
index 00000000000..536d517bd6e
--- /dev/null
+++ b/source/blender/collada/BlenderContext.cpp
@@ -0,0 +1,61 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Gaia Clary,
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+ /** \file CameraExporter.h
+ * \ingroup collada
+ */
+
+#include "BlenderContext.h"
+
+BlenderContext::BlenderContext(bContext *C)
+{
+ context = C;
+ main = CTX_data_main(C);
+ depsgraph = CTX_data_depsgraph(C);
+ scene = CTX_data_scene(C);
+ view_layer = DEG_get_evaluated_view_layer(depsgraph);
+}
+
+bContext *BlenderContext::get_context()
+{
+ return context;
+}
+
+Depsgraph *BlenderContext::get_depsgraph()
+{
+ return depsgraph;
+}
+
+Scene *BlenderContext::get_scene()
+{
+ return scene;
+}
+
+ViewLayer *BlenderContext::get_view_layer()
+{
+ return view_layer;
+}
+
+Main *BlenderContext::get_main()
+{
+ return main;
+}
diff --git a/source/blender/collada/BlenderContext.h b/source/blender/collada/BlenderContext.h
new file mode 100644
index 00000000000..648d97a7e86
--- /dev/null
+++ b/source/blender/collada/BlenderContext.h
@@ -0,0 +1,56 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Gaia Clary,
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+ /** \file CameraExporter.h
+ * \ingroup collada
+ */
+
+#ifndef __BLENDERCONTEXT_H__
+#define __BLENDERCONTEXT_H__
+
+extern "C" {
+#include "DNA_object_types.h"
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+}
+
+class BlenderContext
+{
+private:
+ bContext *context;
+ Depsgraph *depsgraph;
+ Scene *scene;
+ ViewLayer *view_layer;
+ Main *main;
+
+public:
+ BlenderContext(bContext *C);
+ bContext *get_context();
+ Depsgraph *get_depsgraph();
+ Scene *get_scene();
+ ViewLayer *get_view_layer();
+ Main *get_main();
+};
+
+#endif
diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt
index 293049a1a05..f860dfac08b 100644
--- a/source/blender/collada/CMakeLists.txt
+++ b/source/blender/collada/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blenkernel
../blenlib
../blentranslation
+ ../depsgraph
../editors/include
../makesdna
../makesrna
@@ -48,8 +49,13 @@ set(INC_SYS
set(SRC
AnimationImporter.cpp
AnimationExporter.cpp
+ AnimationClipExporter.cpp
ArmatureExporter.cpp
ArmatureImporter.cpp
+ BlenderContext.cpp
+ BCAnimationCurve.cpp
+ BCAnimationSampler.cpp
+ BCSampleData.cpp
CameraExporter.cpp
ControllerExporter.cpp
DocumentExporter.cpp
@@ -67,6 +73,7 @@ set(SRC
MaterialExporter.cpp
MeshImporter.cpp
SkinInfo.cpp
+ Materials.cpp
SceneExporter.cpp
TransformReader.cpp
TransformWriter.cpp
@@ -76,8 +83,13 @@ set(SRC
AnimationImporter.h
AnimationExporter.h
+ AnimationClipExporter.h
ArmatureExporter.h
ArmatureImporter.h
+ BlenderContext.h
+ BCAnimationCurve.h
+ BCAnimationSampler.h
+ BCSampleData.h
CameraExporter.h
ControllerExporter.h
DocumentExporter.h
@@ -94,6 +106,7 @@ set(SRC
LightExporter.h
MaterialExporter.h
MeshImporter.h
+ Materials.h
SkinInfo.h
SceneExporter.h
TransformReader.h
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index a5f96123fd4..7685a2b09a0 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -38,11 +38,10 @@
#include "BKE_armature.h"
extern "C" {
-#include "BKE_main.h"
-#include "BKE_mesh.h"
#include "BKE_global.h"
-#include "BKE_library.h"
#include "BKE_idprop.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
}
#include "ED_armature.h"
@@ -56,22 +55,18 @@ extern "C" {
#include "collada_utils.h"
-// XXX exporter writes wrong data for shared armatures. A separate
-// controller should be written for each armature-mesh binding how do
-// we make controller ids then?
-ControllerExporter::ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryControllers(sw), export_settings(export_settings) {
-}
bool ControllerExporter::is_skinned_mesh(Object *ob)
{
return bc_get_assigned_armature(ob) != NULL;
}
-
void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
{
- if (bc_is_root_bone(bone, this->export_settings->deform_bones_only))
- ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(ob_arm, bone)));
+ if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) {
+ std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name);
+ ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, node_id));
+ }
else {
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
write_bone_URLs(ins, ob_arm, child);
@@ -98,20 +93,15 @@ bool ControllerExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(),
- ob,
- this->export_settings->active_uv_only,
- this->export_settings->export_texture_type);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
ins.add();
return true;
}
-void ControllerExporter::export_controllers(Main *bmain, Scene *sce)
+void ControllerExporter::export_controllers()
{
- m_bmain = bmain;
- scene = sce;
-
+ Scene *sce = blender_context.get_scene();
openLibrary();
GeometryFunctor gf;
@@ -201,16 +191,17 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
bool use_instantiation = this->export_settings->use_object_instantiation;
Mesh *me;
+ if (((Mesh *)ob->data)->dvert == NULL) {
+ return;
+ }
+
me = bc_get_mesh_copy(
- m_bmain,
- scene,
+ blender_context,
ob,
this->export_settings->export_mesh_type,
this->export_settings->apply_modifiers,
this->export_settings->triangulate);
- if (!me->dvert) return;
-
std::string controller_name = id_name(ob_arm);
std::string controller_id = get_controller_id(ob_arm, ob);
@@ -294,7 +285,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
- BKE_libblock_free_us(m_bmain, me);
+ BKE_id_free(NULL, me);
closeSkin();
closeController();
@@ -306,8 +297,7 @@ void ControllerExporter::export_morph_controller(Object *ob, Key *key)
Mesh *me;
me = bc_get_mesh_copy(
- m_bmain,
- scene,
+ blender_context,
ob,
this->export_settings->export_mesh_type,
this->export_settings->apply_modifiers,
@@ -332,8 +322,7 @@ void ControllerExporter::export_morph_controller(Object *ob, Key *key)
COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id)));
targets.add();
- BKE_libblock_free_us(m_bmain, me);
-
+ BKE_id_free(NULL, me);
//support for animations
//can also try the base element and param alternative
@@ -432,8 +421,7 @@ void ControllerExporter::add_joints_element(ListBase *defbase,
void ControllerExporter::add_bind_shape_mat(Object *ob)
{
double bind_mat[4][4];
-
- converter.mat4_to_dae_double(bind_mat, ob->obmat);
+ UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat);
addBindShapeTransform(bind_mat);
}
@@ -501,8 +489,11 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
// put armature in rest position
if (!(arm->flag & ARM_RESTPOS)) {
+ Depsgraph *depsgraph = blender_context.get_depsgraph();
+ Scene *scene = blender_context.get_scene();
+
arm->flag |= ARM_RESTPOS;
- BKE_pose_where_is(scene, ob_arm);
+ BKE_pose_where_is(depsgraph, scene, ob_arm);
}
for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
@@ -540,17 +531,19 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
mul_m4_m4m4(world, ob_arm->obmat, bind_mat);
invert_m4_m4(mat, world);
- converter.mat4_to_dae(inv_bind_mat, mat);
+ UnitConverter::mat4_to_dae(inv_bind_mat, mat);
if (this->export_settings->limit_precision)
bc_sanitize_mat(inv_bind_mat, 6);
source.appendValues(inv_bind_mat);
}
}
- // back from rest positon
+ // back from rest position
if (!(flag & ARM_RESTPOS)) {
+ Depsgraph *depsgraph = blender_context.get_depsgraph();
+ Scene *scene = blender_context.get_scene();
arm->flag = flag;
- BKE_pose_where_is(scene, ob_arm);
+ BKE_pose_where_is(depsgraph, scene, ob_arm);
}
source.finish();
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
index 2e258c63b6f..309bdbd37f0 100644
--- a/source/blender/collada/ControllerExporter.h
+++ b/source/blender/collada/ControllerExporter.h
@@ -54,25 +54,31 @@
#include "BKE_key.h"
+struct Depsgraph;
class SceneExporter;
class ControllerExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
{
public:
- ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
+ // XXX exporter writes wrong data for shared armatures. A separate
+ // controller should be written for each armature-mesh binding how do
+ // we make controller ids then?
+ ControllerExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) :
+ COLLADASW::LibraryControllers(sw),
+ blender_context(blender_context),
+ export_settings(export_settings) {
+ }
bool is_skinned_mesh(Object *ob);
bool add_instance_controller(Object *ob);
- void export_controllers(Main *bmain, Scene *sce);
+ void export_controllers();
void operator()(Object *ob);
private:
- Main *m_bmain;
- Scene *scene;
- UnitConverter converter;
+ BlenderContext &blender_context;
const ExportSettings *export_settings;
#if 0
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index bf29ec42c42..4d0dd7605f9 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -66,12 +66,11 @@ extern "C"
{
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_group_types.h"
+#include "DNA_collection_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_image_types.h"
#include "DNA_material_types.h"
-#include "DNA_texture_types.h"
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_curve_types.h"
@@ -86,11 +85,11 @@ extern "C"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_action.h" // pose functions
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_blender_version.h"
+#include "BKE_customdata.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -138,8 +137,7 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
{
int layer_index = CustomData_get_layer_index(data, type);
- if (layer_index < 0)
- return NULL;
+ if (layer_index < 0) return NULL;
return data->layers[layer_index + n].name;
}
@@ -148,13 +146,14 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
- if (layer_index < 1)
- return NULL;
+ if (layer_index < 0) return NULL;
- return bc_CustomData_get_layer_name(data, type, layer_index-1);
+ return data->layers[layer_index].name;
}
-DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {
+DocumentExporter::DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings) :
+ blender_context(blender_context),
+ export_settings(export_settings) {
}
static COLLADABU::NativeString make_temp_filepath(const char *name, const char *extension)
@@ -181,9 +180,11 @@ static COLLADABU::NativeString make_temp_filepath(const char *name, const char *
// COLLADA allows this through multiple <channel>s in <animation>.
// For this to work, we need to know objects that use a certain action.
-int DocumentExporter::exportCurrentScene(bContext *C, const EvaluationContext *eval_ctx, Scene *sce)
+int DocumentExporter::exportCurrentScene()
{
- Main *bmain = CTX_data_main(C);
+ Scene *sce = blender_context.get_scene();
+ bContext *C = blender_context.get_context();
+
PointerRNA sceneptr, unit_settings;
PropertyRNA *system; /* unused , *scale; */
@@ -273,42 +274,43 @@ int DocumentExporter::exportCurrentScene(bContext *C, const EvaluationContext *e
le.exportLights(sce);
}
+ // <library_effects>
+ EffectsExporter ee(writer, this->export_settings, key_image_map);
+ ee.exportEffects(C, sce);
+
// <library_images>
- ImagesExporter ie(writer, this->export_settings);
+ ImagesExporter ie(writer, this->export_settings, key_image_map);
ie.exportImages(sce);
- // <library_effects>
- EffectsExporter ee(writer, this->export_settings);
- ee.exportEffects(sce);
-
// <library_materials>
MaterialsExporter me(writer, this->export_settings);
me.exportMaterials(sce);
// <library_geometries>
if (bc_has_object_type(export_set, OB_MESH)) {
- GeometryExporter ge(writer, this->export_settings);
- ge.exportGeom(bmain, sce);
+ GeometryExporter ge(blender_context, writer, this->export_settings);
+ ge.exportGeom();
}
// <library_controllers>
- ArmatureExporter arm_exporter(writer, this->export_settings);
- ControllerExporter controller_exporter(writer, this->export_settings);
+ ArmatureExporter arm_exporter(blender_context, writer, this->export_settings);
+ ControllerExporter controller_exporter(blender_context, writer, this->export_settings);
if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys)
{
- controller_exporter.export_controllers(bmain, sce);
+ controller_exporter.export_controllers();
}
// <library_visual_scenes>
- SceneExporter se(writer, &arm_exporter, this->export_settings);
+ SceneExporter se(blender_context, writer, &arm_exporter, this->export_settings);
if (this->export_settings->include_animations) {
// <library_animations>
- AnimationExporter ae(writer, this->export_settings);
- ae.exportAnimations(bmain, sce);
+ AnimationExporter ae(blender_context, writer, this->export_settings);
+ ae.exportAnimations();
}
- se.exportScene(C, sce);
+
+ se.exportScene();
// <scene>
std::string scene_name(translate_id(id_name(sce)));
diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h
index 817df3735da..cb55dbc459e 100644
--- a/source/blender/collada/DocumentExporter.h
+++ b/source/blender/collada/DocumentExporter.h
@@ -28,22 +28,24 @@
#define __DOCUMENTEXPORTER_H__
#include "collada.h"
+#include "collada_utils.h"
+#include "BlenderContext.h"
extern "C" {
#include "DNA_customdata_types.h"
-#include "BKE_depsgraph.h"
-}
-struct Scene;
+}
class DocumentExporter
{
public:
- DocumentExporter(const ExportSettings *export_settings);
- int exportCurrentScene(bContext *C, const EvaluationContext *eval_ctx, Scene *sce);
+ DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings);
+ int exportCurrentScene();
void exportScenes(const char *filename);
private:
+ BlenderContext &blender_context;
const ExportSettings *export_settings;
+ KeyImageMap key_image_map;
};
#endif
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 67fd9d648c7..8eb9e5c969e 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -57,16 +57,15 @@ extern "C" {
#include "BLI_fileops.h"
#include "BKE_camera.h"
-#include "BKE_main.h"
-#include "BKE_lamp.h"
-#include "BKE_library.h"
-#include "BKE_texture.h"
+#include "BKE_collection.h"
#include "BKE_fcurve.h"
-#include "BKE_depsgraph.h"
-#include "BKE_scene.h"
#include "BKE_global.h"
-#include "BKE_material.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
+#include "BKE_lamp.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+#include "BKE_scene.h"
#include "BLI_path_util.h"
@@ -82,6 +81,9 @@ extern "C" {
}
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ExtraHandler.h"
#include "ErrorHandler.h"
#include "DocumentImporter.h"
@@ -89,7 +91,7 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
-
+#include "Materials.h"
/*
* COLLADA Importer limitations:
@@ -102,11 +104,12 @@ extern "C" {
DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) :
import_settings(import_settings),
- mImportStage(General),
+ mImportStage(Fetching_Scene_data),
mContext(C),
- armature_importer(&unit_converter, &mesh_importer, CTX_data_main(C), CTX_data_scene(C), import_settings),
- mesh_importer(&unit_converter, &armature_importer, CTX_data_main(C), CTX_data_scene(C)),
- anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
+ view_layer(CTX_data_view_layer(mContext)),
+ armature_importer(&unit_converter, &mesh_importer, CTX_data_main(C), CTX_data_scene(C), view_layer, import_settings),
+ mesh_importer(&unit_converter, &armature_importer, CTX_data_main(C), CTX_data_scene(C), view_layer),
+ anim_importer(C, &unit_converter, &armature_importer, CTX_data_scene(C))
{
}
@@ -130,7 +133,7 @@ bool DocumentImporter::import()
loader.registerExtraDataCallbackHandler(ehandler);
// deselect all to select new objects
- BKE_scene_base_deselect_all(CTX_data_scene(mContext));
+ BKE_view_layer_base_deselect_all(view_layer);
std::string mFilename = std::string(this->import_settings->filepath);
const std::string encodedFilename = bc_url_encode(mFilename);
@@ -146,9 +149,7 @@ bool DocumentImporter::import()
}
/** TODO set up scene graph and such here */
-
- mImportStage = Controller;
-
+ mImportStage = Fetching_Controller_data;
COLLADASaxFWL::Loader loader2;
COLLADAFW::Root root2(&loader2, this);
@@ -179,7 +180,7 @@ void DocumentImporter::start()
void DocumentImporter::finish()
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return;
Main *bmain = CTX_data_main(mContext);
@@ -222,6 +223,7 @@ void DocumentImporter::finish()
}
// Write nodes to scene
+ fprintf(stderr, "+-- Import Scene --------\n");
const COLLADAFW::NodePointerArray& roots = (*sit)->getRootNodes();
for (unsigned int i = 0; i < roots.getCount(); i++) {
std::vector<Object *> *objects_done = write_node(roots[i], NULL, sce, NULL, false);
@@ -229,10 +231,6 @@ void DocumentImporter::finish()
delete objects_done;
}
- // update scene
- DAG_relations_tag_update(bmain);
- WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL);
-
}
@@ -241,7 +239,6 @@ void DocumentImporter::finish()
armature_importer.set_tags_map(this->uid_tags_map);
armature_importer.make_armatures(mContext, *objects_to_scale);
armature_importer.make_shape_keys(mContext);
- DAG_relations_tag_update(bmain);
#if 0
armature_importer.fix_animation();
@@ -257,35 +254,29 @@ void DocumentImporter::finish()
if (libnode_ob.size()) {
- fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
+ fprintf(stderr, "| Cleanup: free %d library nodes\n", (int)libnode_ob.size());
// free all library_nodes
- std::vector<Object *>::iterator lit;
- for (lit = libnode_ob.begin(); lit != libnode_ob.end(); lit++) {
- Object *ob = *lit;
-
- Base *base = BKE_scene_base_find(sce, ob);
- if (base) {
- BLI_remlink(&sce->base, base);
- BKE_libblock_free_us(bmain, base->object);
- if (sce->basact == base)
- sce->basact = NULL;
- MEM_freeN(base);
- }
+ std::vector<Object *>::iterator it;
+ for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
+ Object *ob = *it;
+ BKE_scene_collections_object_remove(bmain, sce, ob, true);
}
libnode_ob.clear();
-
- DAG_relations_tag_update(bmain);
}
bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units);
delete objects_to_scale;
+
+ // update scene
+ DEG_id_tag_update(&sce->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL);
}
void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
{
- Main *bmain = CTX_data_main(mContext);
// The split in #29246, rootmap must point at actual root when
// calculating bones in apply_curves_as_matrix. - actual root is the root node.
// This has to do with inverse bind poses being world space
@@ -320,7 +311,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
translate_anim_recursive(node, node, parob);
}
else {
- anim_importer.translate_Animations(bmain, node, root_map, object_map, FW_object_map, uid_material_map);
+ anim_importer.translate_Animations(node, root_map, object_map, FW_object_map, uid_material_map);
COLLADAFW::NodePointerArray &children = node->getChildNodes();
for (i = 0; i < children.getCount(); i++) {
translate_anim_recursive(children[i], node, NULL);
@@ -384,7 +375,7 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera
}
Main *bmain = CTX_data_main(mContext);
- Object *ob = bc_add_object(bmain, sce, OB_CAMERA, NULL);
+ Object *ob = bc_add_object(bmain, sce, view_layer, OB_CAMERA, NULL);
Camera *cam = uid_camera_map[cam_uid];
Camera *old_cam = (Camera *)ob->data;
ob->data = cam;
@@ -396,12 +387,12 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce
{
const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {
- fprintf(stderr, "Couldn't find lamp by UID.\n");
+ fprintf(stderr, "Couldn't find light by UID.\n");
return NULL;
}
Main *bmain = CTX_data_main(mContext);
- Object *ob = bc_add_object(bmain, sce, OB_LAMP, NULL);
+ Object *ob = bc_add_object(bmain, sce, view_layer, OB_LAMP, NULL);
Lamp *la = uid_lamp_map[lamp_uid];
Lamp *old_lamp = (Lamp *)ob->data;
ob->data = la;
@@ -411,12 +402,12 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce
Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
{
- fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL);
+ //fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL);
Main *bmain = CTX_data_main(mContext);
Object *obn = BKE_object_copy(bmain, source_ob);
- DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_scene_base_add(sce, obn);
+ DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ BKE_collection_object_add_from(bmain, sce, source_ob, obn);
if (instance_node) {
anim_importer.read_node_transform(instance_node, obn);
@@ -511,15 +502,16 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
std::vector<Object *> *root_objects = new std::vector<Object *>();
fprintf(stderr,
- "Writing node id='%s', name='%s'\n",
- id.c_str(),
- name.c_str());
+ "| %s id='%s', name='%s'\n",
+ is_joint ? "JOINT" : "NODE ",
+ id.c_str(),
+ name.c_str() );
if (is_joint) {
if (parent_node == NULL && !is_library_node) {
// A Joint on root level is a skeleton without root node.
// Here we add the armature "on the fly":
- par = bc_add_object(bmain, sce, OB_ARMATURE, std::string("Armature").c_str());
+ par = bc_add_object(bmain, sce, view_layer, OB_ARMATURE, std::string("Armature").c_str());
objects_done->push_back(par);
root_objects->push_back(par);
object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par));
@@ -551,8 +543,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
// maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
// <instance_geometry>
while (geom_done < geom.getCount()) {
- ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
- material_texture_mapping_map);
+ ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map);
if (ob == NULL) {
report_unknown_reference(*node, "instance_mesh");
}
@@ -592,7 +583,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
}
while (controller_done < controller.getCount()) {
COLLADAFW::InstanceGeometry *geometry = (COLLADAFW::InstanceGeometry *)controller[controller_done];
- ob = mesh_importer.create_mesh_object(node, geometry, true, uid_material_map, material_texture_mapping_map);
+ ob = mesh_importer.create_mesh_object(node, geometry, true, uid_material_map);
if (ob == NULL) {
report_unknown_reference(*node, "instance_controller");
}
@@ -633,10 +624,10 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
//Check if Object is armature, by checking if immediate child is a JOINT node.
if (is_armature(node)) {
- ob = bc_add_object(bmain, sce, OB_ARMATURE, name.c_str());
+ ob = bc_add_object(bmain, sce, view_layer, OB_ARMATURE, name.c_str());
}
else {
- ob = bc_add_object(bmain, sce, OB_EMPTY, NULL);
+ ob = bc_add_object(bmain, sce, view_layer, OB_EMPTY, NULL);
}
objects_done->push_back(ob);
if (parent_node == NULL) {
@@ -709,7 +700,7 @@ finally:
*/
bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScene)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
// this method called on post process after writeGeometry, writeMaterial, etc.
@@ -732,19 +723,19 @@ bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScen
* \return The writer should return true, if writing succeeded, false otherwise.*/
bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
Scene *sce = CTX_data_scene(mContext);
const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
+ fprintf(stderr, "+-- Read Library nodes ----------\n");
for (unsigned int i = 0; i < nodes.getCount(); i++) {
std::vector<Object *> *child_objects;
child_objects = write_node(nodes[i], NULL, sce, NULL, true);
delete child_objects;
}
-
return true;
}
@@ -752,7 +743,7 @@ bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryN
* \return The writer should return true, if writing succeeded, false otherwise.*/
bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
return mesh_importer.write_geometry(geom);
@@ -762,7 +753,7 @@ bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom)
* \return The writer should return true, if writing succeeded, false otherwise.*/
bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
Main *bmain = CTX_data_main(mContext);
@@ -775,181 +766,18 @@ bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
return true;
}
-// create mtex, create texture, set texture image
-MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
- int i, TexIndexTextureArrayMap &texindex_texarray_map)
-{
- COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
- COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
-
- const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
-
- if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
- fprintf(stderr, "Couldn't find an image by UID.\n");
- return NULL;
- }
-
- Main *bmain = CTX_data_main(mContext);
- ma->mtex[i] = BKE_texture_mtex_add();
- ma->mtex[i]->texco = TEXCO_UV;
- ma->mtex[i]->tex = BKE_texture_add(bmain, "Texture");
- ma->mtex[i]->tex->type = TEX_IMAGE;
- ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
-
- texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
-
- return ma->mtex[i];
-}
void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
{
- COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
-
- // blinn
- if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
- ma->spec_shader = MA_SPEC_BLINN;
- ma->spec = ef->getShininess().getFloatValue();
- }
- // phong
- else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
- ma->spec_shader = MA_SPEC_PHONG;
- ma->har = ef->getShininess().getFloatValue();
- }
- // lambert
- else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
- ma->diff_shader = MA_DIFF_LAMBERT;
- }
- // default - lambert
- else {
- ma->diff_shader = MA_DIFF_LAMBERT;
- fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
- }
- // reflectivity
- ma->ray_mirror = ef->getReflectivity().getFloatValue();
- // index of refraction
- ma->ang = ef->getIndexOfRefraction().getFloatValue();
-
- int i = 0;
- COLLADAFW::Color col;
- MTex *mtex = NULL;
- TexIndexTextureArrayMap texindex_texarray_map;
-
- // DIFFUSE
- // color
- if (ef->getDiffuse().isColor()) {
- /* too high intensity can create artefacts (fireflies)
- So here we take care that intensity is set to 0.8 wherever possible
- */
- col = ef->getDiffuse().getColor();
- ma->ref = max_ffff(col.getRed(), col.getGreen(), col.getBlue(), 0.8);
- ma->r = col.getRed() / ma->ref;
- ma->g = col.getGreen() / ma->ref;
- ma->b = col.getBlue() / ma->ref;
- }
- // texture
- else if (ef->getDiffuse().isTexture()) {
- COLLADAFW::Texture ctex = ef->getDiffuse().getTexture();
- mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
- if (mtex != NULL) {
- mtex->mapto = MAP_COL;
- ma->texact = (int)i;
- i++;
- }
- }
- // AMBIENT
- // color
- if (ef->getAmbient().isColor()) {
- col = ef->getAmbient().getColor();
- ma->ambr = col.getRed();
- ma->ambg = col.getGreen();
- ma->ambb = col.getBlue();
- }
- // texture
- else if (ef->getAmbient().isTexture()) {
- COLLADAFW::Texture ctex = ef->getAmbient().getTexture();
- mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
- if (mtex != NULL) {
- mtex->mapto = MAP_AMB;
- i++;
- }
- }
- // SPECULAR
- // color
- if (ef->getSpecular().isColor()) {
- col = ef->getSpecular().getColor();
- ma->specr = col.getRed();
- ma->specg = col.getGreen();
- ma->specb = col.getBlue();
- }
- // texture
- else if (ef->getSpecular().isTexture()) {
- COLLADAFW::Texture ctex = ef->getSpecular().getTexture();
- mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
- if (mtex != NULL) {
- mtex->mapto = MAP_SPEC;
- i++;
- }
- }
- // REFLECTIVE
- // color
- if (ef->getReflective().isColor()) {
- col = ef->getReflective().getColor();
- ma->mirr = col.getRed();
- ma->mirg = col.getGreen();
- ma->mirb = col.getBlue();
- }
- // texture
- else if (ef->getReflective().isTexture()) {
- COLLADAFW::Texture ctex = ef->getReflective().getTexture();
- mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
- if (mtex != NULL) {
- mtex->mapto = MAP_REF;
- i++;
- }
- }
-
- // EMISSION
- // color
- if (ef->getEmission().isColor()) {
- // XXX there is no emission color in blender
- // but I am not sure
- }
- // texture
- else if (ef->getEmission().isTexture()) {
- COLLADAFW::Texture ctex = ef->getEmission().getTexture();
- mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
- if (mtex != NULL) {
- mtex->mapto = MAP_EMIT;
- i++;
- }
- }
-
- // TRANSPARENT
- // color
- if (ef->getOpacity().isColor()) {
- col = ef->getTransparent().getColor();
- float alpha = ef->getTransparency().getFloatValue();
- if (col.isValid()) {
- alpha *= col.getAlpha(); // Assuming A_ONE opaque mode
- }
- if (col.isValid() || alpha < 1.0) {
- ma->alpha = alpha;
- ma->mode |= MA_ZTRANSP | MA_TRANSP;
- }
- }
- // texture
- else if (ef->getOpacity().isTexture()) {
- COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
- mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
- if (mtex != NULL) {
- mtex->mapto = MAP_ALPHA;
- i++;
- ma->spectra = ma->alpha = 0;
- ma->mode |= MA_ZTRANSP | MA_TRANSP;
- }
- }
-
- material_texture_mapping_map[ma] = texindex_texarray_map;
+ MaterialNode matNode = MaterialNode(mContext, ef, ma, uid_image_map);
+ matNode.set_reflectivity(ef->getReflectivity().getFloatValue());
+ matNode.set_ior(ef->getIndexOfRefraction().getFloatValue());
+ matNode.set_diffuse(ef->getDiffuse(), "Diffuse");
+ matNode.set_ambient(ef->getAmbient(), "Ambient");
+ matNode.set_specular(ef->getSpecular(), "Specular");
+ matNode.set_reflective(ef->getReflective(), "Reflective");
+ matNode.set_emission(ef->getEmission(), "Emission");
+ matNode.set_opacity(ef->getOpacity(), "Opacity");
}
/** When this method is called, the writer must write the effect.
@@ -957,7 +785,7 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
const COLLADAFW::UniqueId& uid = effect->getUniqueId();
@@ -994,7 +822,7 @@ bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect)
* \return The writer should return true, if writing succeeded, false otherwise.*/
bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
Main *bmain = CTX_data_main(mContext);
@@ -1120,7 +948,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
* \return The writer should return true, if writing succeeded, false otherwise.*/
bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
const std::string& imagepath = image->getImageURI().toNativePath();
@@ -1137,7 +965,7 @@ bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
else {
// Maybe imagepath was already absolute ?
if (!BLI_exists(imagepath.c_str())) {
- fprintf(stderr, "Image not found: %s.\n", imagepath.c_str() );
+ fprintf(stderr, "|! Image not found: %s\n", imagepath.c_str() );
return true;
}
workpath = imagepath.c_str();
@@ -1145,11 +973,11 @@ bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
Image *ima = BKE_image_load_exists(CTX_data_main(mContext), workpath);
if (!ima) {
- fprintf(stderr, "Cannot create image: %s\n", workpath);
+ fprintf(stderr, "|! Cannot create image: %s\n", workpath);
return true;
}
this->uid_image_map[image->getUniqueId()] = ima;
-
+ fprintf(stderr, "| import Image: %s\n", workpath);
return true;
}
@@ -1157,7 +985,7 @@ bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
* \return The writer should return true, if writing succeeded, false otherwise.*/
bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
Main *bmain = CTX_data_main(mContext);
@@ -1177,7 +1005,7 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
else lamp = (Lamp *)BKE_lamp_add(bmain, (char *)la_id.c_str());
if (!lamp) {
- fprintf(stderr, "Cannot create lamp.\n");
+ fprintf(stderr, "Cannot create light.\n");
return true;
}
@@ -1198,7 +1026,6 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
et->setData("spotsize", &(lamp->spotsize));
lamp->spotsize = DEG2RADF(lamp->spotsize);
et->setData("spotblend", &(lamp->spotblend));
- et->setData("halo_intensity", &(lamp->haint));
et->setData("att1", &(lamp->att1));
et->setData("att2", &(lamp->att2));
et->setData("falloff_type", &(lamp->falloff_type));
@@ -1206,38 +1033,12 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
et->setData("clipend", &(lamp->clipend));
et->setData("bias", &(lamp->bias));
et->setData("soft", &(lamp->soft));
- et->setData("compressthresh", &(lamp->compressthresh));
et->setData("bufsize", &(lamp->bufsize));
- et->setData("samp", &(lamp->samp));
et->setData("buffers", &(lamp->buffers));
- et->setData("filtertype", &(lamp->filtertype));
- et->setData("bufflag", &(lamp->bufflag));
- et->setData("buftype", &(lamp->buftype));
- et->setData("ray_samp", &(lamp->ray_samp));
- et->setData("ray_sampy", &(lamp->ray_sampy));
- et->setData("ray_sampz", &(lamp->ray_sampz));
- et->setData("ray_samp_type", &(lamp->ray_samp_type));
et->setData("area_shape", &(lamp->area_shape));
et->setData("area_size", &(lamp->area_size));
et->setData("area_sizey", &(lamp->area_sizey));
et->setData("area_sizez", &(lamp->area_sizez));
- et->setData("adapt_thresh", &(lamp->adapt_thresh));
- et->setData("ray_samp_method", &(lamp->ray_samp_method));
- et->setData("shadhalostep", &(lamp->shadhalostep));
- et->setData("sun_effect_type", &(lamp->shadhalostep));
- et->setData("skyblendtype", &(lamp->skyblendtype));
- et->setData("horizon_brightness", &(lamp->horizon_brightness));
- et->setData("spread", &(lamp->spread));
- et->setData("sun_brightness", &(lamp->sun_brightness));
- et->setData("sun_size", &(lamp->sun_size));
- et->setData("backscattered_light", &(lamp->backscattered_light));
- et->setData("sun_intensity", &(lamp->sun_intensity));
- et->setData("atm_turbidity", &(lamp->atm_turbidity));
- et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
- et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
- et->setData("skyblendfac", &(lamp->skyblendfac));
- et->setData("sky_exposure", &(lamp->sky_exposure));
- et->setData("sky_colorspace", &(lamp->sky_colorspace));
}
else {
float constatt = light->getConstantAttenuation().getValue();
@@ -1277,11 +1078,10 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
lamp->energy = e;
lamp->dist = d;
- COLLADAFW::Light::LightType type = light->getLightType();
- switch (type) {
+ switch (light->getLightType()) {
case COLLADAFW::Light::AMBIENT_LIGHT:
{
- lamp->type = LA_HEMI;
+ lamp->type = LA_SUN; //TODO needs more thoughts
}
break;
case COLLADAFW::Light::SPOT_LIGHT:
@@ -1301,7 +1101,6 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
{
/* our sun is very strong, so pick a smaller energy level */
lamp->type = LA_SUN;
- lamp->mode |= LA_NO_SPEC;
}
break;
case COLLADAFW::Light::POINT_LIGHT:
@@ -1317,7 +1116,7 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
break;
case COLLADAFW::Light::UNDEFINED:
{
- fprintf(stderr, "Current lamp type is not supported.\n");
+ fprintf(stderr, "Current light type is not supported.\n");
lamp->type = LA_LOCAL;
}
break;
@@ -1332,7 +1131,7 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
// this function is called only for animations that pass COLLADAFW::validate
bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
// return true;
@@ -1342,7 +1141,7 @@ bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
// called on post-process stage after writeVisualScenes
bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animationList)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
// return true;
@@ -1359,7 +1158,7 @@ bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerDa
// this is called on postprocess, before writeVisualScenes
bool DocumentImporter::writeController(const COLLADAFW::Controller *controller)
{
- if (mImportStage != General)
+ if (mImportStage == Fetching_Controller_data)
return true;
return armature_importer.write_controller(controller);
diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h
index 17e61326032..26ded417aa6 100644
--- a/source/blender/collada/DocumentImporter.h
+++ b/source/blender/collada/DocumentImporter.h
@@ -59,8 +59,8 @@ class DocumentImporter : COLLADAFW::IWriter
public:
//! Enumeration to denote the stage of import
enum ImportStage {
- General, //!< First pass to collect all data except controller
- Controller, //!< Second pass to collect controller data
+ Fetching_Scene_data, /* First pass to collect all data except controller */
+ Fetching_Controller_data, /* Second pass to collect controller data */
};
/** Constructor */
DocumentImporter(bContext *C, const ImportSettings *import_settings);
@@ -77,7 +77,6 @@ public:
Object* create_instance_node(Object*, COLLADAFW::Node*, COLLADAFW::Node*, Scene*, bool);
void create_constraints(ExtraTags *et, Object *ob);
std::vector<Object *> *write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool);
- MTex* create_texture(COLLADAFW::EffectCommon*, COLLADAFW::Texture&, Material*, int, TexIndexTextureArrayMap&);
void write_profile_COMMON(COLLADAFW::EffectCommon*, Material*);
void translate_anim_recursive(COLLADAFW::Node*, COLLADAFW::Node*, Object*);
@@ -144,6 +143,7 @@ private:
ImportStage mImportStage;
bContext *mContext;
+ ViewLayer *view_layer;
UnitConverter unit_converter;
ArmatureImporter armature_importer;
@@ -155,7 +155,7 @@ private:
/** Tags map of unique id as a string and ExtraTags instance. */
TagsMap uid_tags_map;
- std::map<COLLADAFW::UniqueId, Image*> uid_image_map;
+ UidImageMap uid_image_map;
std::map<COLLADAFW::UniqueId, Material*> uid_material_map;
std::map<COLLADAFW::UniqueId, Material*> uid_effect_map;
std::map<COLLADAFW::UniqueId, Camera*> uid_camera_map;
@@ -172,6 +172,7 @@ private:
std::string import_from_version;
void report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type);
+
};
#endif
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index d33ce725e58..5c702304e27 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -27,6 +27,7 @@
#include <map>
+#include <set>
#include "COLLADASWEffectProfile.h"
#include "COLLADAFWColorOrTexture.h"
@@ -40,24 +41,36 @@
extern "C" {
#include "DNA_mesh_types.h"
- #include "DNA_texture_types.h"
#include "DNA_world_types.h"
+ #include "BKE_collection.h"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_material.h"
}
-EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
+static std::string getActiveUVLayerName(Object *ob)
+{
+ Mesh *me = (Mesh *)ob->data;
+
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers)
+ return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
+
+ return "";
}
+EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, KeyImageMap &key_image_map) :
+ COLLADASW::LibraryEffects(sw),
+ export_settings(export_settings),
+ key_image_map(key_image_map)
+{}
+
bool EffectsExporter::hasEffects(Scene *sce)
{
- Base *base = (Base *)sce->base.first;
-
- while (base) {
- Object *ob = base->object;
+ FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
+ {
int a;
for (a = 0; a < ob->totcol; a++) {
Material *ma = give_current_material(ob, a + 1);
@@ -67,234 +80,123 @@ bool EffectsExporter::hasEffects(Scene *sce)
return true;
}
- base = base->next;
}
+ FOREACH_SCENE_OBJECT_END;
return false;
}
-void EffectsExporter::exportEffects(Scene *sce)
+void EffectsExporter::exportEffects(bContext *C, Scene *sce)
{
- this->scene = sce;
-
- if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
- if (hasEffects(sce)) {
- MaterialFunctor mf;
- openLibrary();
- mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
- closeLibrary();
- }
- }
- else {
- std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only);
- std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
- if (uv_images.size() > 0) {
- openLibrary();
- std::set<Image *>::iterator uv_images_iter;
- for (uv_images_iter = uv_images.begin();
- uv_images_iter != uv_images.end();
- uv_images_iter++)
- {
-
- Image *ima = *uv_images_iter;
- std::string key(id_name(ima));
- key = translate_id(key);
- COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
- key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
- key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
- sampler.setImageId(key);
-
- openEffect(key + "-effect");
- COLLADASW::EffectProfile ep(mSW);
- ep.setProfileType(COLLADASW::EffectProfile::COMMON);
- ep.setShaderType(COLLADASW::EffectProfile::PHONG);
- ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse");
- COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f);
- ep.setSpecular(cot, false, "specular");
- ep.openProfile();
- ep.addProfileElements();
- ep.addExtraTechniques(mSW);
- ep.closeProfile();
- closeEffect();
- }
- closeLibrary();
- }
+ if (hasEffects(sce)) {
+ this->mContext = C;
+ this->scene = sce;
+ openLibrary();
+ MaterialFunctor mf;
+ mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
+
+ closeLibrary();
}
}
-void EffectsExporter::writeBlinn(COLLADASW::EffectProfile &ep, Material *ma)
+void EffectsExporter::set_shader_type(COLLADASW::EffectProfile &ep, Material *ma)
{
- COLLADASW::ColorOrTexture cot;
- ep.setShaderType(COLLADASW::EffectProfile::BLINN);
- // shininess
- ep.setShininess(ma->har, false, "shininess");
- // specular
- cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
- ep.setSpecular(cot, false, "specular");
+ ep.setShaderType(COLLADASW::EffectProfile::LAMBERT); //XXX check if BLINN and PHONG can be supported as well
}
-void EffectsExporter::writeLambert(COLLADASW::EffectProfile &ep, Material *ma)
+void EffectsExporter::set_transparency(COLLADASW::EffectProfile &ep, Material *ma)
{
- COLLADASW::ColorOrTexture cot;
- ep.setShaderType(COLLADASW::EffectProfile::LAMBERT);
+ if (ma->alpha == 1.0f) {
+ return; // have no transparency
+ }
+
+ // Tod: because we are in A_ONE mode transparency is calculated like this:
+ COLLADASW::ColorOrTexture cot = getcol(1.0f, 1.0f, 1.0f, ma->alpha);
+ ep.setTransparent(cot);
+ ep.setOpaque(COLLADASW::EffectProfile::A_ONE);
+}
+void EffectsExporter::set_diffuse_color(COLLADASW::EffectProfile &ep, Material *ma)
+{
+ // get diffuse color
+ COLLADASW::ColorOrTexture cot = bc_get_base_color(ma);
+ ep.setDiffuse(cot, false, "diffuse");
}
-void EffectsExporter::writePhong(COLLADASW::EffectProfile &ep, Material *ma)
+void EffectsExporter::set_specular_color(COLLADASW::EffectProfile &ep, Material *ma)
{
- COLLADASW::ColorOrTexture cot;
- ep.setShaderType(COLLADASW::EffectProfile::PHONG);
- // shininess
- ep.setShininess(ma->har, false, "shininess");
- // specular
- cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
+ bool use_fallback = ep.getShaderType() != COLLADASW::EffectProfile::LAMBERT;
+ COLLADASW::ColorOrTexture cot = bc_get_specular_color(ma, use_fallback);
ep.setSpecular(cot, false, "specular");
}
-void EffectsExporter::writeTextures(
- COLLADASW::EffectProfile &ep,
- std::string &key,
- COLLADASW::Sampler *sampler,
- MTex *t, Image *ima,
- std::string &uvname )
+void EffectsExporter::set_emission(COLLADASW::EffectProfile &ep, Material *ma)
{
- // Image not set for texture
- if (!ima) return;
+ // not yet supported (needs changes in principled shader
+}
- // color
- if (t->mapto & MAP_COL) {
- ep.setDiffuse(createTexture(ima, uvname, sampler), false, "diffuse");
- }
- // ambient
- if (t->mapto & MAP_AMB) {
- ep.setAmbient(createTexture(ima, uvname, sampler), false, "ambient");
- }
- // specular
- if (t->mapto & (MAP_SPEC | MAP_COLSPEC)) {
- ep.setSpecular(createTexture(ima, uvname, sampler), false, "specular");
- }
- // emission
- if (t->mapto & MAP_EMIT) {
- ep.setEmission(createTexture(ima, uvname, sampler), false, "emission");
- }
- // reflective
- if (t->mapto & MAP_REF) {
- ep.setReflective(createTexture(ima, uvname, sampler));
+void EffectsExporter::get_images(Material *ma, KeyImageMap &material_image_map)
+{
+ if (!ma->use_nodes) {
+ return;
}
- // alpha
- if (t->mapto & MAP_ALPHA) {
- ep.setTransparent(createTexture(ima, uvname, sampler));
+
+ MaterialNode material = MaterialNode(mContext, ma, key_image_map);
+ Image *image = material.get_diffuse_image();
+ if (image == nullptr) {
+ return;
}
- // extension:
- // Normal map --> Must be stored with <extra> tag as different technique,
- // since COLLADA doesn't support normal maps, even in current COLLADA 1.5.
- if (t->mapto & MAP_NORM) {
- COLLADASW::Texture texture(key);
- texture.setTexcoord(uvname);
- texture.setSampler(*sampler);
- // technique FCOLLADA, with the <bump> tag, is most likely the best understood,
- // most widespread de-facto standard.
- texture.setProfileName("FCOLLADA");
- texture.setChildElementName("bump");
- ep.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture));
+
+ std::string uid(id_name(image));
+ std::string key = translate_id(uid);
+
+ if (material_image_map.find(key) == material_image_map.end()) {
+ material_image_map[key] = image;
+ key_image_map[key] = image;
}
}
-void EffectsExporter::operator()(Material *ma, Object *ob)
+void EffectsExporter::create_image_samplers(COLLADASW::EffectProfile &ep, KeyImageMap &material_image_map, std::string &active_uv)
{
- // create a list of indices to textures of type TEX_IMAGE
- std::vector<int> tex_indices;
- createTextureIndices(ma, tex_indices);
+ KeyImageMap::iterator iter;
- openEffect(translate_id(id_name(ma)) + "-effect");
+ for (iter = material_image_map.begin(); iter != material_image_map.end(); iter++) {
- COLLADASW::EffectProfile ep(mSW);
- ep.setProfileType(COLLADASW::EffectProfile::COMMON);
- ep.openProfile();
- // set shader type - one of three blinn, phong or lambert
- if (ma->spec > 0.0f) {
- if (ma->spec_shader == MA_SPEC_BLINN) {
- writeBlinn(ep, ma);
- }
- else {
- // \todo figure out handling of all spec+diff shader combos blender has, for now write phong
- // for now set phong in case spec shader is not blinn
- writePhong(ep, ma);
- }
- }
- else {
- if (ma->diff_shader == MA_DIFF_LAMBERT) {
- writeLambert(ep, ma);
- }
- else {
- // \todo figure out handling of all spec+diff shader combos blender has, for now write phong
- writePhong(ep, ma);
- }
- }
+ Image *image = iter->second;
+ std::string uid(id_name(image));
+ std::string key = translate_id(uid);
- // index of refraction
- if (ma->mode & MA_RAYTRANSP) {
- ep.setIndexOfRefraction(ma->ang, false, "index_of_refraction");
- }
- else {
- ep.setIndexOfRefraction(1.0f, false, "index_of_refraction");
- }
+ COLLADASW::Sampler *sampler = new COLLADASW::Sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
+ key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
+ key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
- COLLADASW::ColorOrTexture cot;
+ sampler->setImageId(key);
- // transparency
- if (ma->mode & MA_TRANSP) {
- // Tod: because we are in A_ONE mode transparency is calculated like this:
- cot = getcol(1.0f, 1.0f, 1.0f, ma->alpha);
- ep.setTransparent(cot);
- ep.setOpaque(COLLADASW::EffectProfile::A_ONE);
+ ep.setDiffuse(createTexture(image, active_uv, sampler), false, "diffuse");
}
+}
- // emission
- cot = getcol(ma->emit, ma->emit, ma->emit, 1.0f);
- ep.setEmission(cot, false, "emission");
-
- // diffuse multiplied by diffuse intensity
- cot = getcol(ma->r * ma->ref, ma->g * ma->ref, ma->b * ma->ref, 1.0f);
- ep.setDiffuse(cot, false, "diffuse");
-
- // ambient
- /* ma->ambX is calculated only on render, so lets do it here manually and not rely on ma->ambX. */
- if (this->scene->world)
- cot = getcol(this->scene->world->ambr * ma->amb, this->scene->world->ambg * ma->amb, this->scene->world->ambb * ma->amb, 1.0f);
- else
- cot = getcol(ma->amb, ma->amb, ma->amb, 1.0f);
+void EffectsExporter::operator()(Material *ma, Object *ob)
+{
+ KeyImageMap material_image_map;
- ep.setAmbient(cot, false, "ambient");
+ openEffect(get_effect_id(ma));
- // reflective, reflectivity
- if (ma->mode & MA_RAYMIRROR) {
- cot = getcol(ma->mirr, ma->mirg, ma->mirb, 1.0f);
- ep.setReflective(cot);
- ep.setReflectivity(ma->ray_mirror);
- }
- // else {
- // cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
- // ep.setReflective(cot);
- // ep.setReflectivity(ma->spec);
- // }
-
- // specular
- if (ep.getShaderType() != COLLADASW::EffectProfile::LAMBERT) {
- cot = getcol(ma->specr * ma->spec, ma->specg * ma->spec, ma->specb * ma->spec, 1.0f);
- ep.setSpecular(cot, false, "specular");
- }
+ COLLADASW::EffectProfile ep(mSW);
+ ep.setProfileType(COLLADASW::EffectProfile::COMMON);
+ ep.openProfile();
+ set_shader_type(ep, ma);
- // XXX make this more readable if possible
+ COLLADASW::ColorOrTexture cot;
- // create <sampler> and <surface> for each image
- COLLADASW::Sampler samplers[MAX_MTEX];
- //COLLADASW::Surface surfaces[MAX_MTEX];
- //void *samp_surf[MAX_MTEX][2];
- void *samp_surf[MAX_MTEX];
+ set_transparency(ep, ma);
+ set_diffuse_color(ep, ma);
+ set_specular_color(ep, ma);
+ set_emission(ep, ma);
- // image to index to samp_surf map
- // samp_surf[index] stores 2 pointers, sampler and surface
- std::map<std::string, int> im_samp_map;
+ get_images(ma, material_image_map);
+ std::string active_uv(getActiveUVLayerName(ob));
+ create_image_samplers(ep, material_image_map, active_uv);
+#if 0
unsigned int a, b;
for (a = 0, b = 0; a < tex_indices.size(); a++) {
MTex *t = ma->mtex[tex_indices[a]];
@@ -308,24 +210,13 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
// create only one <sampler>/<surface> pair for each unique image
if (im_samp_map.find(key) == im_samp_map.end()) {
- // //<newparam> <surface> <init_from>
- // COLLADASW::Surface surface(COLLADASW::Surface::SURFACE_TYPE_2D,
- // key + COLLADASW::Surface::SURFACE_SID_SUFFIX);
- // COLLADASW::SurfaceInitOption sio(COLLADASW::SurfaceInitOption::INIT_FROM);
- // sio.setImageReference(key);
- // surface.setInitOption(sio);
-
- // COLLADASW::NewParamSurface surface(mSW);
- // surface->setParamType(COLLADASW::CSW_SURFACE_TYPE_2D);
-
//<newparam> <sampler> <source>
COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
- key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
- key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
+ key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
+ key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
sampler.setImageId(key);
// copy values to arrays since they will live longer
samplers[a] = sampler;
- //surfaces[a] = surface;
// store pointers so they can be used later when we create <texture>s
samp_surf[b] = &samplers[a];
@@ -336,12 +227,6 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
}
}
- // used as fallback when MTex->uvname is "" (this is pretty common)
- // it is indeed the correct value to use in that case
- std::string active_uv(bc_get_active_uvlayer_name(ob));
-
- // write textures
- // XXX very slow
for (a = 0; a < tex_indices.size(); a++) {
MTex *t = ma->mtex[tex_indices[a]];
Image *ima = t->tex->ima;
@@ -354,9 +239,10 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
key = translate_id(key);
int i = im_samp_map[key];
std::string uvname = strlen(t->uvname) ? t->uvname : active_uv;
- COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i];
+ COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i]; // possibly uninitialised memory ...
writeTextures(ep, key, sampler, t, ima, uvname);
}
+#endif
// performs the actual writing
ep.addProfileElements();
@@ -397,20 +283,3 @@ COLLADASW::ColorOrTexture EffectsExporter::getcol(float r, float g, float b, flo
COLLADASW::ColorOrTexture cot(color);
return cot;
}
-
-//returns the array of mtex indices which have image
-//need this for exporting textures
-void EffectsExporter::createTextureIndices(Material *ma, std::vector<int> &indices)
-{
- indices.clear();
-
- for (int a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a] &&
- ma->mtex[a]->tex &&
- ma->mtex[a]->tex->type == TEX_IMAGE &&
- ma->mtex[a]->texco == TEXCO_UV)
- {
- indices.push_back(a);
- }
- }
-}
diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h
index 278e1ebcfce..462f1548586 100644
--- a/source/blender/collada/EffectExporter.h
+++ b/source/blender/collada/EffectExporter.h
@@ -42,12 +42,14 @@
#include "DNA_scene_types.h"
#include "ExportSettings.h"
+#include "collada_utils.h"
class EffectsExporter: COLLADASW::LibraryEffects
{
public:
- EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
- void exportEffects(Scene *sce);
+ EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, KeyImageMap &key_image_map);
+ void exportEffects(bContext *C, Scene *sce);
+
void operator()(Material *ma, Object *ob);
COLLADASW::ColorOrTexture createTexture(Image *ima,
@@ -57,12 +59,14 @@ public:
COLLADASW::ColorOrTexture getcol(float r, float g, float b, float a);
private:
- /** Fills the array of mtex indices which have image. Used for exporting images. */
- void createTextureIndices(Material *ma, std::vector<int> &indices);
+ void set_shader_type(COLLADASW::EffectProfile &ep, Material *ma);
+ void set_transparency(COLLADASW::EffectProfile &ep, Material *ma);
+ void set_diffuse_color(COLLADASW::EffectProfile &ep, Material *ma);
+ void set_specular_color(COLLADASW::EffectProfile &ep, Material *ma);
+ void set_emission(COLLADASW::EffectProfile &ep, Material *ma);
+ void get_images(Material *ma, KeyImageMap &uid_image_map);
+ void create_image_samplers(COLLADASW::EffectProfile &ep, KeyImageMap &uid_image_map, std::string &active_uv);
- void writeBlinn(COLLADASW::EffectProfile &ep, Material *ma);
- void writeLambert(COLLADASW::EffectProfile &ep, Material *ma);
- void writePhong(COLLADASW::EffectProfile &ep, Material *ma);
void writeTextures(COLLADASW::EffectProfile &ep,
std::string &key,
COLLADASW::Sampler *sampler,
@@ -72,8 +76,9 @@ private:
bool hasEffects(Scene *sce);
const ExportSettings *export_settings;
-
+ KeyImageMap &key_image_map;
Scene *scene;
+ bContext *mContext;
};
#endif
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index caa73900632..e708cc9fc8c 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -49,47 +49,67 @@ ErrorHandler::~ErrorHandler()
//--------------------------------------------------------------------
bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
{
- /* This method must return true when Collada should continue.
+ /* This method must return false when Collada should continue.
* See https://github.com/KhronosGroup/OpenCOLLADA/issues/442
*/
- bool isWarning = false;
+ bool isError = true;
+ std::string error_context;
+ std::string error_message;
if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) {
+ error_context = "Schema validation";
+
COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error;
const GeneratedSaxParser::ParserError& parserError = saxParserError->getError();
+ error_message = parserError.getErrorMessage();
- // Workaround to avoid wrong error
if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_MIN_OCCURS_UNMATCHED) {
if (STREQ(parserError.getElement(), "effect")) {
- isWarning = true;
+ isError = false;
}
}
- if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_SEQUENCE_PREVIOUS_SIBLING_NOT_PRESENT) {
+
+ else if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_SEQUENCE_PREVIOUS_SIBLING_NOT_PRESENT) {
if (!(STREQ(parserError.getElement(), "extra") &&
STREQ(parserError.getAdditionalText().c_str(), "sibling: fx_profile_abstract")))
{
- isWarning = true;
+ isError = false;
}
}
- if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_COULD_NOT_OPEN_FILE) {
- std::cout << "Couldn't open file" << std::endl;
+ else if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_COULD_NOT_OPEN_FILE) {
+ isError = true;
+ error_context = "File access";
}
- std::cout << "Schema validation error: " << parserError.getErrorMessage() << std::endl;
+ else isError = (parserError.getSeverity() != GeneratedSaxParser::ParserError::Severity::SEVERITY_ERROR_NONCRITICAL);
+
}
else if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXFWL) {
+ error_context = "Sax FWL";
COLLADASaxFWL::SaxFWLError *saxFWLError = (COLLADASaxFWL::SaxFWLError *) error;
+ error_message = saxFWLError->getErrorMessage();
+
/*
* Accept non critical errors as warnings (i.e. texture not found)
* This makes the importer more graceful, so it now imports what makes sense.
*/
- isWarning = (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL);
- std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl;
+
+ isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL);
+
}
else {
- std::cout << "opencollada error: " << error->getFullErrorMessage() << std::endl;
+ error_context = "OpenCollada";
+ error_message = error->getFullErrorMessage();
+ isError = true;
}
- return isWarning;
+ std::string severity = (isError) ? "Error" : "Warning";
+ std::cout << error_context << " (" << severity << "): " << error_message << std::endl;
+ if (isError) {
+ std::cout << "The Collada import has been forced to stop." << std::endl;
+ std::cout << "Please fix the reported error and then try again.";
+ mError = true;
+ }
+ return isError;
}
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index fa6751bef60..3b4397a6093 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -43,10 +43,19 @@ typedef enum BC_export_transformation_type {
BC_TRANSFORMATION_TYPE_TRANSROTLOC
} BC_export_transformation_type;
-typedef enum BC_export_texture_type {
- BC_TEXTURE_TYPE_MAT,
- BC_TEXTURE_TYPE_UV
-} BC_export_texture_type;
+
+typedef enum BC_export_animation_type {
+ BC_ANIMATION_EXPORT_SAMPLES,
+ BC_ANIMATION_EXPORT_KEYS
+} BC_export_animation_type;
+
+typedef enum BC_ui_export_section {
+ BC_UI_SECTION_MAIN,
+ BC_UI_SECTION_GEOMETRY,
+ BC_UI_SECTION_ARMATURE,
+ BC_UI_SECTION_ANIMATION,
+ BC_UI_SECTION_COLLADA
+} BC_ui_export_section;
typedef struct ExportSettings {
bool apply_modifiers;
@@ -58,10 +67,13 @@ typedef struct ExportSettings {
bool include_shapekeys;
bool deform_bones_only;
bool include_animations;
+ bool include_all_actions;
int sampling_rate;
+ bool keep_smooth_curves;
+ bool keep_keyframes;
bool active_uv_only;
- BC_export_texture_type export_texture_type;
+ BC_export_animation_type export_animation_type;
bool use_texture_copies;
bool triangulate;
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index eb627b5c066..8b4302f3470 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -40,11 +40,9 @@
extern "C" {
#include "BLI_utildefines.h"
- #include "BKE_DerivedMesh.h"
- #include "BKE_main.h"
+ #include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_library.h"
- #include "BKE_customdata.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
}
@@ -53,17 +51,11 @@ extern "C" {
#include "collada_utils.h"
-// TODO: optimize UV sets by making indexed list with duplicates removed
-GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
-{
-}
-
-void GeometryExporter::exportGeom(Main *bmain, Scene *sce)
+void GeometryExporter::exportGeom()
{
+ Scene *sce = blender_context.get_scene();
openLibrary();
- m_bmain = bmain;
- mScene = sce;
GeometryFunctor gf;
gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set);
@@ -72,15 +64,9 @@ void GeometryExporter::exportGeom(Main *bmain, Scene *sce)
void GeometryExporter::operator()(Object *ob)
{
- // XXX don't use DerivedMesh, Mesh instead?
-#if 0
- DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH);
-#endif
-
bool use_instantiation = this->export_settings->use_object_instantiation;
Mesh *me = bc_get_mesh_copy(
- m_bmain,
- mScene,
+ blender_context,
ob,
this->export_settings->export_mesh_type,
this->export_settings->apply_modifiers,
@@ -98,6 +84,7 @@ void GeometryExporter::operator()(Object *ob)
}
std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob);
+ geom_name = encode_xml(geom_name);
exportedGeometry.insert(geom_id);
@@ -138,22 +125,13 @@ void GeometryExporter::operator()(Object *ob)
// Only create Polylists if number of faces > 0
if (me->totface > 0) {
// XXX slow
- std::set<Image *> uv_images = bc_getUVImages(ob, !this->export_settings->active_uv_only);
- if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT || uv_images.size() == 0) {
- if (ob->totcol) {
- for (int a = 0; a < ob->totcol; a++) {
- createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
- }
- }
- else {
- int i = 0;
- createPolylist(i, has_uvs, has_color, ob, me, geom_id, norind);
+ if (ob->totcol) {
+ for (int a = 0; a < ob->totcol; a++) {
+ createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- bool all_uv_layers = !this->export_settings->active_uv_only;
- std::set<Image *> uv_image_set = bc_getUVImages(ob, all_uv_layers);
- createPolylists(uv_image_set, has_uvs, has_color, ob, me, geom_id, norind);
+ createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
}
}
@@ -178,8 +156,7 @@ void GeometryExporter::operator()(Object *ob)
}
}
- BKE_libblock_free_us(m_bmain, me);
-
+ BKE_id_free(NULL, me);
}
void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
@@ -233,15 +210,13 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
//createLooseEdgeList(ob, me, geom_id, norind);
// XXX slow
- if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
+ if (ob->totcol) {
for (int a = 0; a < ob->totcol; a++) {
createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- bool all_uv_layers = !this->export_settings->active_uv_only;
- std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
- createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
+ createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
}
closeMesh();
@@ -310,44 +285,7 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char
return result;
}
-static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase *facelist, std::vector<unsigned long> &vcount_list)
-{
- // performs the actual writing
- if (is_triangulated) {
- ((COLLADASW::Triangles *)facelist)->prepareToAppendValues();
- }
- else {
- // sets <vcount>
- facelist->setVCountList(vcount_list);
- ((COLLADASW::Polylist *)facelist)-> prepareToAppendValues();
- }
-}
-
-static void finishList(bool is_triangulated, COLLADASW::PrimitivesBase *facelist)
-{
- if (is_triangulated) {
- ((COLLADASW::Triangles *)facelist)->finish();
- }
- else {
- ((COLLADASW::Polylist *)facelist)->finish();
- }
-}
-
-COLLADASW::PrimitivesBase *getFacelist(bool is_triangulated, COLLADASW::StreamWriter *mSW)
-{
- COLLADASW::PrimitivesBase *facelist;
-
- if (is_triangulated)
- {
- facelist = new COLLADASW::Triangles(mSW);
- }
- else {
- facelist = new COLLADASW::Polylist(mSW);
- }
- return facelist;
-}
-
-// Export meshes with Materials
+// powerful because it handles both cases when there is material and when there's not
void GeometryExporter::createPolylist(short material_index,
bool has_uvs,
bool has_color,
@@ -365,7 +303,7 @@ void GeometryExporter::createPolylist(short material_index,
int i;
int faces_in_polylist = 0;
std::vector<unsigned long> vcount_list;
- bool is_triangulated = true;
+
// count faces with this material
for (i = 0; i < totpolys; i++) {
MPoly *p = &mpolys[i];
@@ -373,9 +311,6 @@ void GeometryExporter::createPolylist(short material_index,
if (p->mat_nr == material_index) {
faces_in_polylist++;
vcount_list.push_back(p->totloop);
- if (p->totloop != 3) {
- is_triangulated = false;
- }
}
}
@@ -386,21 +321,20 @@ void GeometryExporter::createPolylist(short material_index,
}
Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
- COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
-
+ COLLADASW::Polylist polylist(mSW);
// sets count attribute in <polylist>
- facelist->setCount(faces_in_polylist);
+ polylist.setCount(faces_in_polylist);
// sets material name
if (ma) {
std::string material_id = get_material_id(ma);
std::ostringstream ostr;
ostr << translate_id(material_id);
- facelist->setMaterial(ostr.str());
+ polylist.setMaterial(ostr.str());
}
- COLLADASW::InputList &til = facelist->getInputList();
+ COLLADASW::InputList &til = polylist.getInputList();
// creates <input> in <polylist> for vertices
COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
@@ -417,20 +351,12 @@ void GeometryExporter::createPolylist(short material_index,
for (i = 0; i < num_layers; i++) {
if (!this->export_settings->active_uv_only || i == active_uv_index) {
- std::string uv_name(bc_get_uvlayer_name(me, i));
- std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
- std::string layer_id = makeTexcoordSourceId(
- effective_id,
- i, this->export_settings->active_uv_only);
-
- /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
- For now this is always 2 (This may change sometime/maybe)
- */
+ // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(layer_id),
- 2, // this is only until we have optimized UV sets
- (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
- );
+ makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
+ );
til.push_back(input3);
}
}
@@ -451,9 +377,11 @@ void GeometryExporter::createPolylist(short material_index,
}
}
+ // sets <vcount>
+ polylist.setVCountList(vcount_list);
// performs the actual writing
- prepareToAppendValues(is_triangulated, facelist, vcount_list);
+ polylist.prepareToAppendValues();
// <p>
int texindex = 0;
@@ -466,202 +394,20 @@ void GeometryExporter::createPolylist(short material_index,
BCPolygonNormalsIndices normal_indices = norind[i];
for (int j = 0; j < loop_count; j++) {
- facelist->appendValues(l[j].v);
- facelist->appendValues(normal_indices[j]);
- if (has_uvs)
- facelist->appendValues(texindex + j);
-
- if (has_color)
- facelist->appendValues(texindex + j);
- }
- }
-
- texindex += loop_count;
- }
-
- finishList(is_triangulated, facelist);
- delete facelist;
-}
-
-void GeometryExporter::createPolylists(std::set<Image *> uv_images,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind)
-{
- std::set<Image *>::iterator uv_images_iter;
- for (uv_images_iter = uv_images.begin();
- uv_images_iter != uv_images.end();
- uv_images_iter++)
- {
-
- Image *ima = *uv_images_iter;
- std::string imageid(id_name(ima));
- createPolylist(imageid, has_uvs,
- has_color,
- ob,
- me,
- geom_id,
- norind);
- }
-
- /* We msut add an additional collector for the case when
- * some parts of the object are not textured at all.
- * The next call creates a polylist for all untextured polygons
- */
-
- createPolylist("", has_uvs,
- has_color,
- ob,
- me,
- geom_id,
- norind);
-
-}
-
-/* ===========================================================================
- * Export Meshes with UV Textures (export as materials, see also in
- * effectExporter and MaterialExporter)
- *
- * If imageid is the empty string, then collect only untextured polygons
- * =========================================================================== */
-void GeometryExporter::createPolylist(std::string imageid,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind)
-{
-
- MPoly *mpolys = me->mpoly;
- MLoop *mloops = me->mloop;
- MTexPoly *mtpolys = me->mtpoly;
-
- int totpolys = me->totpoly;
-
- // <vcount>
- int i;
- int faces_in_polylist = 0;
- std::vector<unsigned long> vcount_list;
- bool is_triangulated = true;
- // count faces with this material
- for (i = 0; i < totpolys; i++) {
- MTexPoly *tp = &mtpolys[i];
- MPoly *p = &mpolys[i];
-
- std::string tpageid = (mtpolys && tp->tpage) ? id_name(tp->tpage) : "";
- if (tpageid == imageid) {
- faces_in_polylist++;
- vcount_list.push_back(p->totloop);
- if (p->totloop != 3) {
- is_triangulated = false;
- }
- }
- }
-
- // no faces using this imageid
- if (faces_in_polylist == 0) {
- if (imageid != "")
- fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid.c_str());
- return;
- }
-
- COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
-
- // sets count attribute in <polylist>
- facelist->setCount(faces_in_polylist);
-
- if (imageid != "") {
- // sets material name
- std::string material_id = get_material_id_from_id(imageid);
- std::ostringstream ostr;
- ostr << translate_id(material_id);
- facelist->setMaterial(ostr.str());
- }
- COLLADASW::InputList &til = facelist->getInputList();
-
- // creates <input> in <polylist> for vertices
- COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
-
- // creates <input> in <polylist> for normals
- COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
-
- til.push_back(input1);
- til.push_back(input2);
-
- // if mesh has uv coords writes <input> for TEXCOORD
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
- for (i = 0; i < num_layers; i++) {
- if (!this->export_settings->active_uv_only || i == active_uv_index) {
-
- std::string uv_name(bc_get_uvlayer_name(me, i));
- std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
- std::string layer_id = makeTexcoordSourceId(
- effective_id,
- i, this->export_settings->active_uv_only);
-
- /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
- For now this is always 2 (This may change sometime/maybe)
- */
- COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(layer_id),
- 2, // this is only until we have optimized UV sets
- (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
- );
- til.push_back(input3);
- }
- }
-
- int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
- if (totlayer_mcol > 0) {
- int map_index = 0;
-
- for (int a = 0; a < totlayer_mcol; a++) {
- char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
- COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
- makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
- (has_uvs) ? 3 : 2, // all color layers have same index order
- map_index // set number equals color map index
- );
- til.push_back(input4);
- map_index++;
- }
- }
-
- // performs the actual writing
- prepareToAppendValues(is_triangulated, facelist, vcount_list);
-
- // <p>
- int texindex = 0;
- for (i = 0; i < totpolys; i++) {
- MTexPoly *tp = &mtpolys[i];
- MPoly *p = &mpolys[i];
- int loop_count = p->totloop;
- std::string tpageid = (mtpolys && tp->tpage) ? id_name(tp->tpage) : "";
- if (tpageid == imageid) {
- MLoop *l = &mloops[p->loopstart];
- BCPolygonNormalsIndices normal_indices = norind[i];
-
- for (int j = 0; j < loop_count; j++) {
- facelist->appendValues(l[j].v);
- facelist->appendValues(normal_indices[j]);
+ polylist.appendValues(l[j].v);
+ polylist.appendValues(normal_indices[j]);
if (has_uvs)
- facelist->appendValues(texindex + j);
+ polylist.appendValues(texindex + j);
if (has_color)
- facelist->appendValues(texindex + j);
+ polylist.appendValues(texindex + j);
}
}
texindex += loop_count;
}
- finishList(is_triangulated, facelist);
- delete facelist;
+ polylist.finish();
}
// creates <source> for positions
@@ -782,13 +528,7 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
- std::string active_uv_name(bc_get_active_uvlayer_name(me));
- std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
- std::string layer_id = makeTexcoordSourceId(
- effective_id,
- a,
- this->export_settings->active_uv_only );
-
+ std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
source.setId(layer_id);
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index fd9db7b1fd2..bd629946d01 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -43,9 +43,11 @@
#include "ExportSettings.h"
#include "collada_utils.h"
-
+#include "BlenderContext.h"
#include "BKE_key.h"
+struct Depsgraph;
+
extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob);
class Normal
@@ -72,13 +74,16 @@ class GeometryExporter : COLLADASW::LibraryGeometries
Normal n;
- Main *m_bmain;
- Scene *mScene;
-
public:
- GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
- void exportGeom(Main *bmain, Scene *sce);
+ // TODO: optimize UV sets by making indexed list with duplicates removed
+ GeometryExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) :
+ COLLADASW::LibraryGeometries(sw),
+ blender_context(blender_context),
+ export_settings(export_settings)
+ {}
+
+ void exportGeom();
void operator()(Object *ob);
@@ -86,32 +91,14 @@ public:
Mesh *me,
std::string& geom_id);
- // Create polylists for meshes with Materials
+ // powerful because it handles both cases when there is material and when there's not
void createPolylist(short material_index,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
-
- // Create polylists for meshes with UV Textures
- void createPolylists(std::set<Image *> uv_images,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
-
- // Create polylists for meshes with UV Textures
- void createPolylist(std::string imageid,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
// creates <source> for positions
void createVertsSource(std::string geom_id, Mesh *me);
@@ -140,7 +127,7 @@ public:
private:
std::set<std::string> exportedGeometry;
-
+ BlenderContext &blender_context;
const ExportSettings *export_settings;
Mesh *get_mesh(Scene *sce, Object *ob, int apply_modifiers);
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index 87f1197e3af..d7ab16f81e7 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -39,9 +39,11 @@ extern "C" {
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+
#include "IMB_imbuf_types.h"
}
@@ -49,217 +51,121 @@ extern "C" {
#include "MaterialExporter.h"
-ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryImages(sw), export_settings(export_settings)
+ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, KeyImageMap &key_image_map) :
+ COLLADASW::LibraryImages(sw),
+ export_settings(export_settings),
+ key_image_map(key_image_map)
{
}
void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
{
- std::string id(id_name(image));
- std::string translated_id(translate_id(id));
- bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end();
+ std::string name(id_name(image));
+ std::string translated_name(translate_id(name));
- if (not_yet_exported) {
-
- ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL);
- if (!imbuf) {
- fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name);
- return;
- }
+ ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+ if (!imbuf) {
+ fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name);
+ return;
+ }
- bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0;
+ bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0;
- ImageFormatData imageFormat;
- BKE_imbuf_to_image_format(&imageFormat, imbuf);
+ ImageFormatData imageFormat;
+ BKE_imbuf_to_image_format(&imageFormat, imbuf);
- short image_source = image->source;
- bool is_generated = image_source == IMA_SRC_GENERATED;
- bool is_packed = BKE_image_has_packedfile(image);
+ short image_source = image->source;
+ bool is_generated = image_source == IMA_SRC_GENERATED;
+ bool is_packed = BKE_image_has_packedfile(image);
- char export_path[FILE_MAX];
- char source_path[FILE_MAX];
- char export_dir[FILE_MAX];
- char export_file[FILE_MAX];
+ char export_path[FILE_MAX];
+ char source_path[FILE_MAX];
+ char export_dir[FILE_MAX];
+ char export_file[FILE_MAX];
- // Destination folder for exported assets
- BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir));
+ // Destination folder for exported assets
+ BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir));
- if (is_generated || is_dirty || use_copies || is_packed) {
+ if (is_generated || is_dirty || use_copies || is_packed) {
- // make absolute destination path
+ // make absolute destination path
- BLI_strncpy(export_file, id.c_str(), sizeof(export_file));
- BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
+ BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
+ BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
- BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
+ BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
- // make dest directory if it doesn't exist
- BLI_make_existing_file(export_path);
- }
+ // make dest directory if it doesn't exist
+ BLI_make_existing_file(export_path);
+ }
- if (is_generated || is_dirty || is_packed) {
+ if (is_generated || is_dirty || is_packed) {
- // This image in its current state only exists in Blender memory.
- // So we have to export it. The export will keep the image state intact,
- // so the exported file will not be associated with the image.
+ // This image in its current state only exists in Blender memory.
+ // So we have to export it. The export will keep the image state intact,
+ // so the exported file will not be associated with the image.
- if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) {
- fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path);
- return;
- }
- BLI_strncpy(export_path, export_file, sizeof(export_path));
+ if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) {
+ fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path);
+ return;
}
- else {
+ BLI_strncpy(export_path, export_file, sizeof(export_path));
+ }
+ else {
- // make absolute source path
- BLI_strncpy(source_path, image->name, sizeof(source_path));
- BLI_path_abs(source_path, BKE_main_blendfile_path_from_global());
- BLI_cleanup_path(NULL, source_path);
+ // make absolute source path
+ BLI_strncpy(source_path, image->name, sizeof(source_path));
+ BLI_path_abs(source_path, BKE_main_blendfile_path_from_global());
+ BLI_cleanup_path(NULL, source_path);
- if (use_copies) {
+ if (use_copies) {
- // This image is already located on the file system.
- // But we want to create copies here.
- // To move images into the same export directory.
- // Note: If an image is already located in the export folder,
- // then skip the copy (as it would result in a file copy error).
+ // This image is already located on the file system.
+ // But we want to create copies here.
+ // To move images into the same export directory.
+ // Note: If an image is already located in the export folder,
+ // then skip the copy (as it would result in a file copy error).
- if (BLI_path_cmp(source_path, export_path) != 0) {
- if (BLI_copy(source_path, export_path) != 0) {
- fprintf(stderr, "Collada export: Cannot copy image:\n source:%s\ndest :%s\n", source_path, export_path);
- return;
- }
+ if (BLI_path_cmp(source_path, export_path) != 0) {
+ if (BLI_copy(source_path, export_path) != 0) {
+ fprintf(stderr, "Collada export: Cannot copy image:\n source:%s\ndest :%s\n", source_path, export_path);
+ return;
}
-
- BLI_strncpy(export_path, export_file, sizeof(export_path));
-
}
- else {
- // Do not make any copies, but use the source path directly as reference
- // to the original image
+ BLI_strncpy(export_path, export_file, sizeof(export_path));
- BLI_strncpy(export_path, source_path, sizeof(export_path));
- }
}
+ else {
- /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
- COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id);
- img.add(mSW);
- fprintf(stdout, "Collada export: Added image: %s\n", export_file);
- mImages.push_back(translated_id);
+ // Do not make any copies, but use the source path directly as reference
+ // to the original image
- BKE_image_release_ibuf(image, imbuf, NULL);
- }
-}
-
-void ImagesExporter::export_UV_Images()
-{
- std::set<Image *> uv_textures;
- LinkNode *node;
- bool use_texture_copies = this->export_settings->use_texture_copies;
- bool active_uv_only = this->export_settings->active_uv_only;
-
- for (node = this->export_settings->export_set; node; node = node->next) {
- Object *ob = (Object *)node->link;
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *) ob->data;
- BKE_mesh_tessface_ensure(me);
- int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
- for (int i = 0; i < me->pdata.totlayer; i++) {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- if (!active_uv_only || active_uv_layer == i)
- {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- for (int j = 0; j < me->totpoly; j++, txface++) {
-
- Image *ima = txface->tpage;
- if (ima == NULL)
- continue;
-
- bool not_in_list = uv_textures.find(ima) == uv_textures.end();
- if (not_in_list) {
- uv_textures.insert(ima);
- export_UV_Image(ima, use_texture_copies);
- }
- }
- }
- }
- }
+ BLI_strncpy(export_path, source_path, sizeof(export_path));
}
}
-}
-
-/* ============================================================
- * Check if there are any images to be exported
- * Returns true as soon as an object is detected that
- * either has an UV Texture assigned, or has a material
- * assigned that uses an Image Texture.
- * ============================================================
- */
-bool ImagesExporter::hasImages(Scene *sce)
-{
- LinkNode *node;
- for (node = this->export_settings->export_set; node; node = node->next) {
- Object *ob = (Object *)node->link;
-
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
-
- // no material, but check all of the slots
- if (!ma) continue;
- int b;
- for (b = 0; b < MAX_MTEX; b++) {
- MTex *mtex = ma->mtex[b];
- if (mtex && mtex->tex && mtex->tex->ima) return true;
- }
+ COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+ img.add(mSW);
+ fprintf(stdout, "Collada export: Added image: %s\n", export_file);
- }
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *) ob->data;
- BKE_mesh_tessface_ensure(me);
- bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
- if (has_uvs) {
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- for (int a = 0; a < num_layers; a++) {
- MTFace *tface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, a);
- Image *img = tface->tpage;
- if (img) return true;
- }
- }
- }
-
- }
- return false;
+ BKE_image_release_ibuf(image, imbuf, NULL);
}
void ImagesExporter::exportImages(Scene *sce)
{
+ bool use_texture_copies = this->export_settings->use_texture_copies;
openLibrary();
- MaterialFunctor mf;
- if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
- mf.forEachMaterialInExportSet<ImagesExporter>(sce, *this, this->export_settings->export_set);
- }
- else {
- export_UV_Images();
- }
-
- closeLibrary();
-}
+ KeyImageMap::iterator iter;
+ for (iter = key_image_map.begin(); iter != key_image_map.end(); iter++) {
+ Image *image = iter->second;
+ std::string uid(id_name(image));
+ std::string key = translate_id(uid);
-
-void ImagesExporter::operator()(Material *ma, Object *ob)
-{
- int a;
- bool use_texture_copies = this->export_settings->use_texture_copies;
- for (a = 0; a < MAX_MTEX; a++) {
- MTex *mtex = ma->mtex[a];
- if (mtex && mtex->tex && mtex->tex->ima) {
- Image *image = mtex->tex->ima;
- export_UV_Image(image, use_texture_copies);
- }
+ export_UV_Image(image, use_texture_copies);
}
+
+ closeLibrary();
}
diff --git a/source/blender/collada/ImageExporter.h b/source/blender/collada/ImageExporter.h
index 524260891ae..7ce312a52b1 100644
--- a/source/blender/collada/ImageExporter.h
+++ b/source/blender/collada/ImageExporter.h
@@ -40,21 +40,19 @@
#include "DNA_scene_types.h"
#include "ExportSettings.h"
+#include "collada_utils.h"
class ImagesExporter: COLLADASW::LibraryImages
{
public:
- ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
-
+ ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, KeyImageMap &key_image_map);
void exportImages(Scene *sce);
- void operator()(Material *ma, Object *ob);
-private:
- std::vector<std::string> mImages; // contains list of written images, to avoid duplicates
- void export_UV_Images();
- void export_UV_Image(Image *image, bool use_texture_copies);
- bool hasImages(Scene *sce);
+private:
const ExportSettings *export_settings;
+ KeyImageMap &key_image_map;
+ void export_UV_Image(Image *image, bool use_texture_copies);
+
};
#endif
diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp
index 4d846693e50..68842596550 100644
--- a/source/blender/collada/InstanceWriter.cpp
+++ b/source/blender/collada/InstanceWriter.cpp
@@ -41,22 +41,16 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
-void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
+void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only)
{
- bool all_uv_layers = !active_uv_only;
- COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
+ for (int a = 0; a < ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a + 1);
- if (export_texture_type == BC_TEXTURE_TYPE_UV)
- {
- std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
- std::set<Image *>::iterator uv_images_iter;
- for (uv_images_iter = uv_images.begin();
- uv_images_iter != uv_images.end();
- uv_images_iter++)
- {
- Image *ima = *uv_images_iter;
- std::string matid(id_name(ima));
- matid = get_material_id_from_id(matid);
+ COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
+
+ if (ma) {
+ std::string matid(get_material_id(ma));
+ matid = translate_id(matid);
std::ostringstream ostr;
ostr << matid;
COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
@@ -66,7 +60,7 @@ void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_materia
int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
int map_index = 0;
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) -1;
for (int b = 0; b < totlayer; b++) {
if (!active_uv_only || b == active_uv_index) {
char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
@@ -77,32 +71,4 @@ void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_materia
iml.push_back(im);
}
}
-
- else {
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
- if (ma) {
- std::string matid(get_material_id(ma));
- matid = translate_id(matid);
- std::ostringstream ostr;
- ostr << matid;
- COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
-
- // create <bind_vertex_input> for each uv map
- Mesh *me = (Mesh *)ob->data;
- int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-
- int map_index = 0;
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
- for (int b = 0; b < totlayer; b++) {
- if (!active_uv_only || b == active_uv_index) {
- char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
- im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
- }
- }
-
- iml.push_back(im);
- }
- }
- }
}
diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h
index a46027325a2..49ddf091b1c 100644
--- a/source/blender/collada/InstanceWriter.h
+++ b/source/blender/collada/InstanceWriter.h
@@ -31,12 +31,11 @@
#include "COLLADASWBindMaterial.h"
#include "DNA_object_types.h"
-#include "collada.h"
class InstanceWriter
{
protected:
- void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type);
+ void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only);
};
#endif
diff --git a/source/blender/collada/LightExporter.cpp b/source/blender/collada/LightExporter.cpp
index 02c5438ec47..b1f805bfb87 100644
--- a/source/blender/collada/LightExporter.cpp
+++ b/source/blender/collada/LightExporter.cpp
@@ -89,14 +89,7 @@ void LightsExporter::operator()(Object *ob)
exportBlenderProfile(cla, la);
addLight(cla);
}
- // hemi
- else if (la->type == LA_HEMI) {
- COLLADASW::AmbientLight cla(mSW, la_id, la_name);
- cla.setColor(col, false, "color");
- cla.setConstantAttenuation(constatt);
- exportBlenderProfile(cla, la);
- addLight(cla);
- }
+
// spot
else if (la->type == LA_SPOT) {
COLLADASW::SpotLight cla(mSW, la_id, la_name);
@@ -149,7 +142,6 @@ bool LightsExporter::exportBlenderProfile(COLLADASW::Light &cla, Lamp *la)
cla.addExtraTechniqueParameter("blender", "dist", la->dist, "blender_dist");
cla.addExtraTechniqueParameter("blender", "spotsize", RAD2DEGF(la->spotsize));
cla.addExtraTechniqueParameter("blender", "spotblend", la->spotblend);
- cla.addExtraTechniqueParameter("blender", "halo_intensity", la->haint, "blnder_halo_intensity");
cla.addExtraTechniqueParameter("blender", "att1", la->att1);
cla.addExtraTechniqueParameter("blender", "att2", la->att2);
// \todo figure out how we can have falloff curve supported here
@@ -158,38 +150,13 @@ bool LightsExporter::exportBlenderProfile(COLLADASW::Light &cla, Lamp *la)
cla.addExtraTechniqueParameter("blender", "clipend", la->clipend);
cla.addExtraTechniqueParameter("blender", "bias", la->bias);
cla.addExtraTechniqueParameter("blender", "soft", la->soft);
- cla.addExtraTechniqueParameter("blender", "compressthresh", la->compressthresh);
cla.addExtraTechniqueParameter("blender", "bufsize", la->bufsize);
cla.addExtraTechniqueParameter("blender", "samp", la->samp);
cla.addExtraTechniqueParameter("blender", "buffers", la->buffers);
- cla.addExtraTechniqueParameter("blender", "filtertype", la->filtertype);
- cla.addExtraTechniqueParameter("blender", "bufflag", la->bufflag);
- cla.addExtraTechniqueParameter("blender", "buftype", la->buftype);
- cla.addExtraTechniqueParameter("blender", "ray_samp", la->ray_samp);
- cla.addExtraTechniqueParameter("blender", "ray_sampy", la->ray_sampy);
- cla.addExtraTechniqueParameter("blender", "ray_sampz", la->ray_sampz);
- cla.addExtraTechniqueParameter("blender", "ray_samp_type", la->ray_samp_type);
cla.addExtraTechniqueParameter("blender", "area_shape", la->area_shape);
cla.addExtraTechniqueParameter("blender", "area_size", la->area_size);
cla.addExtraTechniqueParameter("blender", "area_sizey", la->area_sizey);
cla.addExtraTechniqueParameter("blender", "area_sizez", la->area_sizez);
- cla.addExtraTechniqueParameter("blender", "adapt_thresh", la->adapt_thresh);
- cla.addExtraTechniqueParameter("blender", "ray_samp_method", la->ray_samp_method);
- cla.addExtraTechniqueParameter("blender", "shadhalostep", la->shadhalostep);
- cla.addExtraTechniqueParameter("blender", "sun_effect_type", la->shadhalostep);
- cla.addExtraTechniqueParameter("blender", "skyblendtype", la->skyblendtype);
- cla.addExtraTechniqueParameter("blender", "horizon_brightness", la->horizon_brightness);
- cla.addExtraTechniqueParameter("blender", "spread", la->spread);
- cla.addExtraTechniqueParameter("blender", "sun_brightness", la->sun_brightness);
- cla.addExtraTechniqueParameter("blender", "sun_size", la->sun_size);
- cla.addExtraTechniqueParameter("blender", "backscattered_light", la->backscattered_light);
- cla.addExtraTechniqueParameter("blender", "sun_intensity", la->sun_intensity);
- cla.addExtraTechniqueParameter("blender", "atm_turbidity", la->atm_turbidity);
- cla.addExtraTechniqueParameter("blender", "atm_extinction_factor", la->atm_extinction_factor);
- cla.addExtraTechniqueParameter("blender", "atm_distance_factor", la->atm_distance_factor);
- cla.addExtraTechniqueParameter("blender", "skyblendfac", la->skyblendfac);
- cla.addExtraTechniqueParameter("blender", "sky_exposure", la->sky_exposure);
- cla.addExtraTechniqueParameter("blender", "sky_colorspace", la->sky_colorspace);
return true;
}
diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp
index 0c0395f2a21..2fa71817ac8 100644
--- a/source/blender/collada/MaterialExporter.cpp
+++ b/source/blender/collada/MaterialExporter.cpp
@@ -38,40 +38,14 @@ MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSe
void MaterialsExporter::exportMaterials(Scene *sce)
{
- if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT)
- {
- if (hasMaterials(sce)) {
- openLibrary();
+ if (hasMaterials(sce)) {
+ openLibrary();
- MaterialFunctor mf;
- mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
+ MaterialFunctor mf;
+ mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
- closeLibrary();
- }
- }
-
- else {
- std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
- if (uv_images.size() > 0) {
- openLibrary();
- std::set<Image *>::iterator uv_images_iter;
- for (uv_images_iter = uv_images.begin();
- uv_images_iter != uv_images.end();
- uv_images_iter++)
- {
-
- Image *ima = *uv_images_iter;
- std::string matid(id_name(ima));
-
- openMaterial(get_material_id_from_id(matid), translate_id(matid));
- std::string efid = translate_id(matid) + "-effect";
- addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid));
- closeMaterial();
- }
- closeLibrary();
- }
+ closeLibrary();
}
-
}
bool MaterialsExporter::hasMaterials(Scene *sce)
@@ -94,12 +68,12 @@ bool MaterialsExporter::hasMaterials(Scene *sce)
void MaterialsExporter::operator()(Material *ma, Object *ob)
{
- std::string name(id_name(ma));
-
- openMaterial(get_material_id(ma), translate_id(name));
+ std::string mat_name = encode_xml(id_name(ma));
+ std::string mat_id = get_material_id(ma);
+ std::string eff_id = get_effect_id(ma);
- std::string efid = translate_id(name) + "-effect";
- addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid));
+ openMaterial(mat_id, mat_name);
+ addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, eff_id));
closeMaterial();
}
diff --git a/source/blender/collada/MaterialExporter.h b/source/blender/collada/MaterialExporter.h
index e830a433432..171c05fcea7 100644
--- a/source/blender/collada/MaterialExporter.h
+++ b/source/blender/collada/MaterialExporter.h
@@ -44,6 +44,7 @@ extern "C" {
#include "GeometryExporter.h"
#include "collada_internal.h"
#include "ExportSettings.h"
+#include "Materials.h"
class MaterialsExporter: COLLADASW::LibraryMaterials
{
diff --git a/source/blender/collada/Materials.cpp b/source/blender/collada/Materials.cpp
new file mode 100644
index 00000000000..3173c2592c4
--- /dev/null
+++ b/source/blender/collada/Materials.cpp
@@ -0,0 +1,329 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* Contributor(s): Gaia Clary.
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#include "Materials.h"
+
+MaterialNode::MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map) :
+ mContext(C),
+ material(ma),
+ effect(nullptr),
+ key_image_map(&key_image_map)
+{
+ ntree = prepare_material_nodetree();
+ setShaderType();
+}
+
+MaterialNode::MaterialNode(bContext *C, COLLADAFW::EffectCommon *ef, Material *ma, UidImageMap &uid_image_map) :
+ mContext(C),
+ material(ma),
+ effect(ef),
+ uid_image_map(&uid_image_map)
+{
+ ntree = prepare_material_nodetree();
+ setShaderType();
+
+ std::map<std::string, bNode *> nmap;
+#if 0
+ nmap["main"] = add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300);
+ nmap["emission"] = add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission");
+ nmap["add"] = add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400);
+ nmap["transparent"] = add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200);
+ nmap["mix"] = add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency");
+ nmap["out"] = add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300);
+ nmap["out"]->flag &= ~NODE_SELECT;
+
+ add_link(ntree, nmap["emission"], 0, nmap["add"], 0);
+ add_link(ntree, nmap["main"], 0, nmap["add"], 1);
+ add_link(ntree, nmap["add"], 0, nmap["mix"], 1);
+ add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2);
+
+ add_link(ntree, nmap["mix"], 0, nmap["out"], 0);
+ // experimental, probably not used.
+ make_group(C, ntree, nmap);
+#else
+ shader_node = add_node(SH_NODE_BSDF_PRINCIPLED, 0, 300, "");
+ output_node = add_node(SH_NODE_OUTPUT_MATERIAL, 300, 300, "");
+ add_link(shader_node, 0, output_node, 0);
+#endif
+}
+
+void MaterialNode::setShaderType()
+{
+#if 0
+ COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
+ // Currently we only support PBR based shaders
+ // TODO: simulate the effects with PBR
+
+ // blinn
+ if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
+ ma->spec_shader = MA_SPEC_BLINN;
+ ma->spec = ef->getShininess().getFloatValue();
+ }
+ // phong
+ else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
+ ma->spec_shader = MA_SPEC_PHONG;
+ ma->har = ef->getShininess().getFloatValue();
+ }
+ // lambert
+ else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
+ ma->diff_shader = MA_DIFF_LAMBERT;
+ }
+ // default - lambert
+ else {
+ ma->diff_shader = MA_DIFF_LAMBERT;
+ fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
+ }
+#endif
+}
+
+bNodeTree *MaterialNode::prepare_material_nodetree()
+{
+ if (material->nodetree == NULL) {
+ material->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree");
+ material->use_nodes = true;
+ }
+ return material->nodetree;
+}
+
+bNode *MaterialNode::add_node(int node_type, int locx, int locy, std::string label)
+{
+ bNode *node = nodeAddStaticNode(mContext, ntree, node_type);
+ if (node) {
+ if (label.length() > 0) {
+ strcpy(node->label, label.c_str());
+ }
+ node->locx = locx;
+ node->locy = locy;
+ node->flag |= NODE_SELECT;
+ }
+ node_map[label] = node;
+ return node;
+}
+
+void MaterialNode::add_link(bNode *from_node, int from_index, bNode *to_node, int to_index)
+{
+ bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
+ bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
+
+ nodeAddLink(ntree, from_node, from_socket, to_node, to_socket);
+}
+
+void MaterialNode::set_reflectivity(float val)
+{
+ material->metallic = val;
+ bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_METALLIC);
+ *(float *)socket->default_value = val;
+}
+
+void MaterialNode::set_ior(float val)
+{
+ bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_IOR);
+ *(float *)socket->default_value = val;
+}
+
+void MaterialNode::set_diffuse(COLLADAFW::ColorOrTexture &cot, std::string label)
+{
+ int locy = -300 * (node_map.size()-2);
+ if (cot.isColor()) {
+ COLLADAFW::Color col = cot.getColor();
+ material->r = col.getRed();
+ material->g = col.getGreen();
+ material->b = col.getBlue();
+
+ bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_DIFFUSE);
+ float *fcol = (float *)socket->default_value;
+ fcol[0] = col.getRed();
+ fcol[1] = col.getGreen();
+ fcol[2] = col.getBlue();
+ }
+ else if (cot.isTexture()) {
+ bNode *texture_node = add_texture_node(cot, -300, locy, label);
+ if (texture_node != NULL) {
+ add_link(texture_node, 0, shader_node, 0);
+ }
+ }
+}
+
+Image *MaterialNode::get_diffuse_image()
+{
+ bNode *shader = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED);
+ if (shader == nullptr) {
+ return nullptr;
+ }
+
+ bNodeSocket *in_socket = (bNodeSocket *)BLI_findlink(&shader->inputs, BC_PBR_DIFFUSE);
+ if (in_socket == nullptr) {
+ return nullptr;
+ }
+
+ bNodeLink *link = in_socket->link;
+ if (link == nullptr) {
+ return nullptr;
+ }
+
+ bNode *texture = link->fromnode;
+ if (texture == nullptr) {
+ return nullptr;
+ }
+
+ if (texture->type != SH_NODE_TEX_IMAGE) {
+ return nullptr;
+ }
+
+ Image *image = (Image *)texture->id;
+ return image;
+
+}
+
+static bNodeSocket *set_color(bNode *node, COLLADAFW::Color col)
+{
+ bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->outputs, 0);
+ float *fcol = (float *)socket->default_value;
+ fcol[0] = col.getRed();
+ fcol[1] = col.getGreen();
+ fcol[2] = col.getBlue();
+
+ return socket;
+}
+
+void MaterialNode::set_ambient(COLLADAFW::ColorOrTexture &cot, std::string label)
+{
+ int locy = -300 * (node_map.size() - 2);
+ if (cot.isColor()) {
+ COLLADAFW::Color col = cot.getColor();
+ bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
+ set_color(node, col);
+ // TODO: Connect node
+ }
+ // texture
+ else if (cot.isTexture()) {
+ add_texture_node(cot, -300, locy, label);
+ // TODO: Connect node
+ }
+}
+void MaterialNode::set_reflective(COLLADAFW::ColorOrTexture &cot, std::string label)
+{
+ int locy = -300 * (node_map.size() - 2);
+ if (cot.isColor()) {
+ COLLADAFW::Color col = cot.getColor();
+ bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
+ set_color(node, col);
+ // TODO: Connect node
+ }
+ // texture
+ else if (cot.isTexture()) {
+ add_texture_node(cot, -300, locy, label);
+ // TODO: Connect node
+ }
+}
+
+void MaterialNode::set_emission(COLLADAFW::ColorOrTexture &cot, std::string label)
+{
+ int locy = -300 * (node_map.size() - 2);
+ if (cot.isColor()) {
+ COLLADAFW::Color col = cot.getColor();
+ bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
+ set_color(node, col);
+ // TODO: Connect node
+ }
+ // texture
+ else if (cot.isTexture()) {
+ add_texture_node(cot, -300, locy, label);
+ // TODO: Connect node
+ }
+}
+
+void MaterialNode::set_opacity(COLLADAFW::ColorOrTexture &cot, std::string label)
+{
+ if (effect == nullptr) {
+ return;
+ }
+
+ int locy = -300 * (node_map.size() - 2);
+ if (cot.isColor()) {
+ COLLADAFW::Color col = effect->getTransparent().getColor();
+ float alpha = effect->getTransparency().getFloatValue();
+
+ if (col.isValid()) {
+ alpha *= col.getAlpha(); // Assuming A_ONE opaque mode
+ }
+ if (col.isValid() || alpha < 1.0) {
+ // not sure what to do here
+ }
+
+ bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
+ set_color(node, col);
+ // TODO: Connect node
+ }
+ // texture
+ else if (cot.isTexture()) {
+ add_texture_node(cot, -300, locy, label);
+ // TODO: Connect node
+ }
+}
+
+void MaterialNode::set_specular(COLLADAFW::ColorOrTexture &cot, std::string label)
+{
+ int locy = -300 * (node_map.size() - 2);
+ if (cot.isColor()) {
+ COLLADAFW::Color col = cot.getColor();
+ material->specr = col.getRed();
+ material->specg = col.getGreen();
+ material->specb = col.getBlue();
+
+ bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
+ set_color(node, col);
+ // TODO: Connect node
+ }
+ // texture
+ else if (cot.isTexture()) {
+ add_texture_node(cot, -300, locy, label);
+ // TODO: Connect node
+ }
+}
+
+bNode *MaterialNode::add_texture_node(COLLADAFW::ColorOrTexture &cot, int locx, int locy, std::string label)
+{
+ if (effect == nullptr) {
+ return nullptr;
+ }
+
+ UidImageMap &image_map = *uid_image_map;
+
+ COLLADAFW::Texture ctex = cot.getTexture();
+
+ COLLADAFW::SamplerPointerArray& samp_array = effect->getSamplerPointerArray();
+ COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
+
+ const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
+
+ if (image_map.find(ima_uid) == image_map.end()) {
+ fprintf(stderr, "Couldn't find an image by UID.\n");
+ return NULL;
+ }
+
+ Image *ima = image_map[ima_uid];
+ bNode *texture_node = add_node(SH_NODE_TEX_IMAGE, locx, locy, label);
+ texture_node->id = &ima->id;
+ return texture_node;
+
+}
diff --git a/source/blender/collada/Materials.h b/source/blender/collada/Materials.h
new file mode 100644
index 00000000000..69f64a6280d
--- /dev/null
+++ b/source/blender/collada/Materials.h
@@ -0,0 +1,84 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __MATERIAL_H__
+#define __MATERIAL_H__
+
+#include <map>
+#include <string>
+
+extern "C" {
+#include "BKE_context.h"
+#include "BKE_node.h"
+#include "BLI_listbase.h"
+#include "DNA_material_types.h"
+#include "DNA_node_types.h"
+}
+
+#include "collada_utils.h"
+#include "COLLADAFWEffectCommon.h"
+
+typedef enum BC_pbr_inputs {
+ BC_PBR_DIFFUSE = 0,
+ BC_PBR_METALLIC = 4,
+ BC_PBR_IOR = 14
+} BC_pbr_inputs;
+
+typedef std::map<std::string, bNode *> NodeMap;
+
+class MaterialNode {
+
+private:
+ bContext *mContext;
+ Material *material;
+ COLLADAFW::EffectCommon *effect;
+ UidImageMap *uid_image_map = nullptr;
+ KeyImageMap *key_image_map = nullptr;
+
+ NodeMap node_map;
+ bNodeTree *ntree;
+
+ bNode *shader_node;
+ bNode *output_node;
+
+ bNodeTree *prepare_material_nodetree();
+ bNode *add_node(int node_type, int locx, int locy, std::string label);
+ void add_link(bNode *from_node, int from_index, bNode *to_node, int to_index);
+ bNode *add_texture_node(COLLADAFW::ColorOrTexture &cot, int locx, int locy, std::string label);
+ void setShaderType();
+
+public:
+ MaterialNode(bContext *C, COLLADAFW::EffectCommon *ef, Material *ma, UidImageMap &uid_image_map);
+ MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map);
+ void set_diffuse(COLLADAFW::ColorOrTexture &cot, std::string label);
+ Image *get_diffuse_image();
+ void set_specular(COLLADAFW::ColorOrTexture &cot, std::string label);
+ void set_ambient(COLLADAFW::ColorOrTexture &cot, std::string label);
+ void set_reflective(COLLADAFW::ColorOrTexture &cot, std::string label);
+ void set_emission(COLLADAFW::ColorOrTexture &cot, std::string label);
+ void set_opacity(COLLADAFW::ColorOrTexture &cot, std::string label);
+ void set_reflectivity(float val);
+ void set_ior(float val);
+
+};
+
+#endif
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 1f24010b04e..4dd3f1cc219 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -43,7 +43,6 @@ extern "C" {
#include "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_library.h"
- #include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
@@ -207,11 +206,12 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
}
-MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce) :
- unitconverter(unitconv),
- m_bmain(bmain),
- scene(sce),
- armature_importer(arm) {
+MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer):
+ unitconverter(unitconv),
+ m_bmain(bmain),
+ scene(sce),
+ view_layer(view_layer),
+ armature_importer(arm) {
}
bool MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count)
@@ -476,11 +476,9 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i];
COLLADAFW::String &uvname = info->mName;
// Allocate space for UV_data
- CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname.c_str());
CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str());
}
// activate the first uv map
- me->mtpoly = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0);
me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0);
}
@@ -601,9 +599,8 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me)
COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
- for (int i = 0; i < prim_arr.getCount(); i++) {
-
- COLLADAFW::MeshPrimitive *mp = prim_arr[i];
+ for (int index = 0; index < prim_arr.getCount(); index++) {
+ COLLADAFW::MeshPrimitive *mp = prim_arr[index];
int type = mp->getPrimitiveType();
if (type == COLLADAFW::MeshPrimitive::LINES) {
@@ -881,48 +878,6 @@ std::string *MeshImporter::get_geometry_name(const std::string &mesh_name)
return NULL;
}
-MTex *MeshImporter::assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
- Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
- MTex *color_texture)
-{
- const COLLADAFW::TextureMapId texture_index = ctexture.getTextureMapId();
- size_t setindex = ctexture.getSetIndex();
- std::string uvname = ctexture.getSemantic();
-
- if (setindex == -1) return NULL;
-
- const CustomData *data = &me->fdata;
- int layer_index = CustomData_get_layer_index(data, CD_MTFACE);
-
- if (layer_index == -1) return NULL;
-
- CustomDataLayer *cdl = &data->layers[layer_index + setindex];
-
- /* set uvname to bind_vertex_input semantic */
- BLI_strncpy(cdl->name, uvname.c_str(), sizeof(cdl->name));
-
- if (texindex_texarray_map.find(texture_index) == texindex_texarray_map.end()) {
-
- fprintf(stderr, "Cannot find texture array by texture index.\n");
- return color_texture;
- }
-
- std::vector<MTex *> textures = texindex_texarray_map[texture_index];
-
- std::vector<MTex *>::iterator it;
-
- for (it = textures.begin(); it != textures.end(); it++) {
-
- MTex *texture = *it;
-
- if (texture) {
- BLI_strncpy(texture->uvname, uvname.c_str(), sizeof(texture->uvname));
- if (texture->mapto == MAP_COL) color_texture = texture;
- }
- }
- return color_texture;
-}
-
/**
* this function checks if both objects have the same
* materials assigned to Object (in the same order)
@@ -1056,21 +1011,19 @@ void MeshImporter::optimize_material_assignements()
* which materials shall be moved to the created geometries. Also see
* optimize_material_assignements() above.
*/
-MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
- std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
- Object *ob, const COLLADAFW::UniqueId *geom_uid,
- char *layername, MTFace *texture_face,
- std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index)
+void MeshImporter::assign_material_to_geom(
+ COLLADAFW::MaterialBinding cmaterial,
+ std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
+ Object *ob, const COLLADAFW::UniqueId *geom_uid,
+ short mat_index)
{
- MTex *color_texture = NULL;
- Mesh *me = (Mesh *)ob->data;
const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial();
// do we know this material?
if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
fprintf(stderr, "Cannot find material by UID.\n");
- return NULL;
+ return;
}
// first time we get geom_uid, ma_uid pair. Save for later check.
@@ -1083,27 +1036,6 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri
ob->actcol=0;
assign_material(m_bmain, ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT);
- COLLADAFW::TextureCoordinateBindingArray& tex_array =
- cmaterial.getTextureCoordinateBindingArray();
- TexIndexTextureArrayMap texindex_texarray_map = material_texture_mapping_map[ma];
- unsigned int i;
- // loop through <bind_vertex_inputs>
- for (i = 0; i < tex_array.getCount(); i++) {
-
- color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map,
- color_texture);
- }
-
- // set texture face
- if (color_texture &&
- strlen((color_texture)->uvname) &&
- !STREQ(layername, color_texture->uvname))
- {
- texture_face = (MTFace *)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
- color_texture->uvname);
- strcpy(layername, color_texture->uvname);
- }
-
MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
@@ -1118,23 +1050,16 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri
Primitive& prim = *it;
MPoly *mpoly = prim.mpoly;
- for (i = 0; i < prim.totpoly; i++, mpoly++) {
+ for (int i = 0; i < prim.totpoly; i++, mpoly++) {
mpoly->mat_nr = mat_index;
- // bind texture images to faces
- if (texture_face && color_texture) {
- texture_face->tpage = (Image *)color_texture->tex->ima;
- texture_face++;
- }
}
}
}
- return texture_face;
}
Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
bool isController,
- std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
- std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map)
+ std::map<COLLADAFW::UniqueId, Material *>& uid_material_map)
{
const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
@@ -1164,8 +1089,8 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
const char *name = (id.length()) ? id.c_str() : NULL;
// add object
- Object *ob = bc_add_object(m_bmain, scene, OB_MESH, name);
- bc_set_mark(ob); // used later for material assignement optimization
+ Object *ob = bc_add_object(m_bmain, scene, view_layer, OB_MESH, name);
+ bc_set_mark(ob); // used later for material assignment optimization
// store object pointer for ArmatureImporter
@@ -1182,10 +1107,6 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */
BKE_libblock_free_us(m_bmain, old_mesh);
- char layername[100];
- layername[0] = '\0';
- MTFace *texture_face = NULL;
-
COLLADAFW::MaterialBindingArray& mat_array =
geom->getMaterialBindings();
@@ -1193,9 +1114,9 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
for (unsigned int i = 0; i < mat_array.getCount(); i++) {
if (mat_array[i].getReferencedMaterial().isValid()) {
- texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid,
- layername, texture_face,
- material_texture_mapping_map, i);
+ assign_material_to_geom(
+ mat_array[i], uid_material_map, ob, geom_uid,
+ i);
}
else {
fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str());
diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h
index 23926bf1ce5..4583242808b 100644
--- a/source/blender/collada/MeshImporter.h
+++ b/source/blender/collada/MeshImporter.h
@@ -51,7 +51,6 @@ extern "C" {
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
}
@@ -93,6 +92,8 @@ private:
Main *m_bmain;
Scene *scene;
+ ViewLayer *view_layer;
+
ArmatureImporter *armature_importer;
std::map<std::string, std::string> mesh_geom_map; // needed for correct shape key naming
@@ -160,29 +161,24 @@ private:
public:
- MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce);
+ MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer);
virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
- MTex *assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
- Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
- MTex *color_texture);
-
void optimize_material_assignements();
- MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
- std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
- Object *ob, const COLLADAFW::UniqueId *geom_uid,
- char *layername, MTFace *texture_face,
- std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index);
+ void assign_material_to_geom(
+ COLLADAFW::MaterialBinding cmaterial,
+ std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
+ Object *ob, const COLLADAFW::UniqueId *geom_uid,
+ short mat_index);
Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
bool isController,
- std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
- std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map);
+ std::map<COLLADAFW::UniqueId, Material*>& uid_material_map);
// create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
bool write_geometry(const COLLADAFW::Geometry* geom);
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index b571b7503d5..9a7a3aa673d 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -26,6 +26,7 @@
extern "C" {
#include "BLI_utildefines.h"
+ #include "BKE_collection.h"
#include "BKE_object.h"
#include "BLI_listbase.h"
}
@@ -33,22 +34,19 @@ extern "C" {
#include "SceneExporter.h"
#include "collada_utils.h"
-SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings)
- : COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings)
+void SceneExporter::exportScene()
{
-}
+ ViewLayer *view_layer = blender_context.get_view_layer();
-void SceneExporter::exportScene(bContext *C, Scene *sce)
-{
// <library_visual_scenes> <visual_scene>
- std::string id_naming = id_name(sce);
- openVisualScene(translate_id(id_naming), id_naming);
- exportHierarchy(C, sce);
+ std::string name = id_name(view_layer);
+ openVisualScene(translate_id(name), encode_xml(name));
+ exportHierarchy();
closeVisualScene();
closeLibrary();
}
-void SceneExporter::exportHierarchy(bContext *C, Scene *sce)
+void SceneExporter::exportHierarchy()
{
LinkNode *node;
std::vector<Object *> base_objects;
@@ -68,6 +66,7 @@ void SceneExporter::exportHierarchy(bContext *C, Scene *sce)
case OB_CAMERA:
case OB_LAMP:
case OB_EMPTY:
+ case OB_GPENCIL:
case OB_ARMATURE:
base_objects.push_back(ob);
break;
@@ -80,165 +79,157 @@ void SceneExporter::exportHierarchy(bContext *C, Scene *sce)
Object *ob = base_objects[index];
if (bc_is_marked(ob)) {
bc_remove_mark(ob);
- writeNodes(C, ob, sce);
+ writeNodes(ob);
}
}
}
+void SceneExporter::writeNodeList(std::vector<Object *> &child_objects, Object *parent)
+{
+ /* TODO: Handle the case where a parent is not exported
+ Actually i am not even sure if this can be done at all
+ in a good way.
+ I really prefer to enforce the export of hidden
+ elements in an object hierarchy. When the children of
+ the hidden elements are exported as well.
+ */
+ for (int i = 0; i < child_objects.size(); ++i) {
+ Object *child = child_objects[i];
+ if (bc_is_marked(child)) {
+ bc_remove_mark(child);
+ writeNodes(child);
+ }
+ }
+}
-void SceneExporter::writeNodes(bContext *C, Object *ob, Scene *sce)
+void SceneExporter::writeNodes(Object *ob)
{
+ ViewLayer *view_layer = blender_context.get_view_layer();
+
+ std::vector<Object *> child_objects;
+ bc_get_children(child_objects, ob, view_layer);
+ bool can_export = bc_is_in_Export_set(this->export_settings->export_set, ob, view_layer);
+
// Add associated armature first if available
bool armature_exported = false;
Object *ob_arm = bc_get_assigned_armature(ob);
+
if (ob_arm != NULL) {
- armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm);
+ armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm, view_layer);
if (armature_exported && bc_is_marked(ob_arm)) {
bc_remove_mark(ob_arm);
- writeNodes(C, ob_arm, sce);
+ writeNodes(ob_arm);
armature_exported = true;
}
}
- COLLADASW::Node colladaNode(mSW);
- colladaNode.setNodeId(translate_id(id_name(ob)));
- colladaNode.setNodeName(translate_id(id_name(ob)));
- colladaNode.setType(COLLADASW::Node::NODE);
+ if (can_export) {
+ COLLADASW::Node colladaNode(mSW);
+ colladaNode.setNodeId(translate_id(id_name(ob)));
+ colladaNode.setNodeName(encode_xml(id_name(ob)));
+ colladaNode.setType(COLLADASW::Node::NODE);
- colladaNode.start();
+ colladaNode.start();
- std::list<Object *> child_objects;
-
- // list child objects
- LinkNode *node;
- for (node=this->export_settings->export_set; node; node=node->next) {
- // cob - child object
- Object *cob = (Object *)node->link;
+ if (ob->type == OB_MESH && armature_exported) {
+ // for skinned mesh we write obmat in <bind_shape_matrix>
+ TransformWriter::add_node_transform_identity(colladaNode);
+ }
+ else {
+ TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings->export_transformation_type);
+ }
- if (cob->parent == ob) {
- switch (cob->type) {
- case OB_MESH:
- case OB_CAMERA:
- case OB_LAMP:
- case OB_EMPTY:
- case OB_ARMATURE:
- if (bc_is_marked(cob))
- child_objects.push_back(cob);
- break;
+ // <instance_geometry>
+ if (ob->type == OB_MESH) {
+ bool instance_controller_created = false;
+ if (armature_exported) {
+ instance_controller_created = arm_exporter->add_instance_controller(ob);
+ }
+ if (!instance_controller_created) {
+ COLLADASW::InstanceGeometry instGeom(mSW);
+ instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
+ instGeom.setName(encode_xml(id_name(ob)));
+ InstanceWriter::add_material_bindings(instGeom.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only);
+ instGeom.add();
}
}
- }
-
- if (ob->type == OB_MESH && armature_exported)
- // for skinned mesh we write obmat in <bind_shape_matrix>
- TransformWriter::add_node_transform_identity(colladaNode);
- else {
- TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings->export_transformation_type);
- }
- // <instance_geometry>
- if (ob->type == OB_MESH) {
- bool instance_controller_created = false;
- if (armature_exported) {
- instance_controller_created = arm_exporter->add_instance_controller(ob);
+ // <instance_controller>
+ else if (ob->type == OB_ARMATURE) {
+ arm_exporter->add_armature_bones(ob, view_layer, this, child_objects);
}
- if (!instance_controller_created) {
- COLLADASW::InstanceGeometry instGeom(mSW);
- instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
- instGeom.setName(translate_id(id_name(ob)));
- InstanceWriter::add_material_bindings(instGeom.getBindMaterial(),
- ob,
- this->export_settings->active_uv_only,
- this->export_settings->export_texture_type);
-
- instGeom.add();
- }
- }
-
- // <instance_controller>
- else if (ob->type == OB_ARMATURE) {
- arm_exporter->add_armature_bones(C, ob, sce, this, child_objects);
- }
-
- // <instance_camera>
- else if (ob->type == OB_CAMERA) {
- COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob)));
- instCam.add();
- }
- // <instance_light>
- else if (ob->type == OB_LAMP) {
- COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob)));
- instLa.add();
- }
-
- // empty object
- else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLIGROUP
- if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) {
- GroupObject *go = NULL;
- Group *gr = ob->dup_group;
- /* printf("group detected '%s'\n", gr->id.name + 2); */
- for (go = (GroupObject *)(gr->gobject.first); go; go = go->next) {
- printf("\t%s\n", go->ob->id.name);
- }
+ // <instance_camera>
+ else if (ob->type == OB_CAMERA) {
+ COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob)));
+ instCam.add();
}
- }
- if (ob->type == OB_ARMATURE) {
- colladaNode.end();
- }
+ // <instance_light>
+ else if (ob->type == OB_LAMP) {
+ COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob)));
+ instLa.add();
+ }
- if (BLI_listbase_is_empty(&ob->constraints) == false) {
- bConstraint *con = (bConstraint *) ob->constraints.first;
- while (con) {
- std::string con_name(translate_id(con->name));
- std::string con_tag = con_name + "_constraint";
- printf("%s\n", con_name.c_str());
- printf("%s\n\n", con_tag.c_str());
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"type",con->type);
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"enforce",con->enforce);
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"flag",con->flag);
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"headtail",con->headtail);
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error);
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"own_space",con->ownspace);
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"rot_error",con->rot_error);
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"tar_space",con->tarspace);
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error);
-
- //not ideal: add the target object name as another parameter.
- //No real mapping in the .dae
- //Need support for multiple target objects also.
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- if (cti && cti->get_constraint_targets) {
-
- bConstraintTarget *ct;
- Object *obtar;
-
- cti->get_constraint_targets(con, &targets);
-
- for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
- obtar = ct->tar;
- std::string tar_id((obtar) ? id_name(obtar) : "");
- colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"target_id",tar_id);
+ // empty object
+ else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLICOLLECTION
+ if ((ob->transflag & OB_DUPLICOLLECTION) == OB_DUPLICOLLECTION && ob->dup_group) {
+ Collection *collection = ob->dup_group;
+ /* printf("group detected '%s'\n", group->id.name + 2); */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
+ {
+ printf("\t%s\n", object->id.name);
}
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
-
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
- con = con->next;
- }
- }
-
- for (std::list<Object *>::iterator i = child_objects.begin(); i != child_objects.end(); ++i) {
- if (bc_is_marked(*i)) {
- bc_remove_mark(*i);
- writeNodes(C, *i, sce);
+ if (BLI_listbase_is_empty(&ob->constraints) == false) {
+ bConstraint *con = (bConstraint *)ob->constraints.first;
+ while (con) {
+ std::string con_name(encode_xml(con->name));
+ std::string con_tag = con_name + "_constraint";
+ printf("%s\n", con_name.c_str());
+ printf("%s\n\n", con_tag.c_str());
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "type", con->type);
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "enforce", con->enforce);
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "flag", con->flag);
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "headtail", con->headtail);
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "lin_error", con->lin_error);
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "own_space", con->ownspace);
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "rot_error", con->rot_error);
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "tar_space", con->tarspace);
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "lin_error", con->lin_error);
+
+ //not ideal: add the target object name as another parameter.
+ //No real mapping in the .dae
+ //Need support for multiple target objects also.
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = { NULL, NULL };
+ if (cti && cti->get_constraint_targets) {
+
+ bConstraintTarget *ct;
+ Object *obtar;
+
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
+ obtar = ct->tar;
+ std::string tar_id((obtar) ? id_name(obtar) : "");
+ colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "target_id", tar_id);
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+
+ }
+
+ con = con->next;
+ }
+ }
}
- }
-
- if (ob->type != OB_ARMATURE)
+ writeNodeList(child_objects, ob);
colladaNode.end();
+ }
}
diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h
index 6cf561749de..f6525d5438d 100644
--- a/source/blender/collada/SceneExporter.h
+++ b/source/blender/collada/SceneExporter.h
@@ -34,7 +34,7 @@
extern "C" {
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_group_types.h"
+#include "DNA_collection_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_image_types.h"
@@ -48,7 +48,6 @@ extern "C" {
#include "DNA_modifier_types.h"
#include "DNA_userdef_types.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_fcurve.h"
#include "BKE_animsys.h"
#include "BLI_path_util.h"
@@ -95,16 +94,26 @@ extern "C" {
class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, protected InstanceWriter
{
public:
- SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings);
- void exportScene(bContext *C, Scene *sce);
+
+ SceneExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings) :
+ COLLADASW::LibraryVisualScenes(sw),
+ blender_context(blender_context),
+ arm_exporter(arm),
+ export_settings(export_settings)
+ {}
+
+ void exportScene();
private:
+ BlenderContext &blender_context;
friend class ArmatureExporter;
- void exportHierarchy(bContext *C, Scene *sce);
- void writeNodes(bContext *C, Object *ob, Scene *sce);
-
ArmatureExporter *arm_exporter;
const ExportSettings *export_settings;
+
+ void exportHierarchy();
+ void writeNodeList(std::vector<Object *> &child_objects, Object *parent);
+ void writeNodes(Object *ob);
+
};
#endif
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index b270ac87976..c55aca7976f 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -159,9 +159,9 @@ void SkinInfo::set_controller(const COLLADAFW::SkinController *co)
}
// called from write_controller
-Object *SkinInfo::create_armature(Main *bmain, Scene *scene)
+Object *SkinInfo::create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
- ob_arm = bc_add_object(bmain, scene, OB_ARMATURE, NULL);
+ ob_arm = bc_add_object(bmain, scene, view_layer, OB_ARMATURE, NULL);
return ob_arm;
}
@@ -232,7 +232,10 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
amd->object = ob_arm;
#if 1
- bc_set_parent(ob, ob_arm, C);
+ /* XXX Why do we enforce objects to be children of Armatures if they weren't so before ?*/
+ if (!BKE_object_is_child_recursive(ob_arm, ob)) {
+ bc_set_parent(ob, ob_arm, C);
+ }
#else
Object workob;
ob->parent = ob_arm;
@@ -241,10 +244,7 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
BKE_object_workob_calc_parent(scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
- DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA);
-
- DAG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA);
#endif
copy_m4_m4(ob->obmat, bind_shape_matrix);
BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
diff --git a/source/blender/collada/SkinInfo.h b/source/blender/collada/SkinInfo.h
index 500ae3878a6..39808c546b1 100644
--- a/source/blender/collada/SkinInfo.h
+++ b/source/blender/collada/SkinInfo.h
@@ -99,7 +99,7 @@ public:
void set_controller(const COLLADAFW::SkinController* co);
// called from write_controller
- Object *create_armature(Main *bmain, Scene *scene);
+ Object *create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer);
Object* set_armature(Object *ob_arm);
diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp
index bf9c34153b7..0c2ea9cb7c4 100644
--- a/source/blender/collada/TransformReader.cpp
+++ b/source/blender/collada/TransformReader.cpp
@@ -80,8 +80,10 @@ void TransformReader::get_node_mat(
dae_scale_to_mat4(tm, cur);
break;
case COLLADAFW::Transformation::LOOKAT:
+ fprintf(stderr, "|! LOOKAT transformations are not supported yet.\n");
+ break;
case COLLADAFW::Transformation::SKEW:
- fprintf(stderr, "LOOKAT and SKEW transformations are not supported yet.\n");
+ fprintf(stderr, "|! SKEW transformations are not supported yet.\n");
break;
}
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index 89653c139f3..9f75a604f96 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -26,8 +26,10 @@
*/
-#include "BKE_object.h"
#include "BLI_math.h"
+#include "BLI_sys_types.h"
+
+#include "BKE_object.h"
#include "TransformWriter.h"
@@ -61,7 +63,8 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4],
}
}
-void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, BC_export_transformation_type transformation_type)
+void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob,
+ BC_export_transformation_type transformation_type)
{
#if 0
float rot[3], loc[3], scale[3];
diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h
index 5bb13d4aac9..580430911f7 100644
--- a/source/blender/collada/TransformWriter.h
+++ b/source/blender/collada/TransformWriter.h
@@ -41,7 +41,8 @@ class TransformWriter
protected:
void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]);
- void add_node_transform_ob(COLLADASW::Node& node, Object *ob, BC_export_transformation_type transformation_type);
+ void add_node_transform_ob(COLLADASW::Node& node, Object *ob,
+ BC_export_transformation_type transformation_type);
void add_node_transform_identity(COLLADASW::Node& node);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index ecaa7fba08c..c6321a4047e 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -32,34 +32,67 @@
#include "DocumentImporter.h"
#include "ExportSettings.h"
#include "ImportSettings.h"
+#include "collada.h"
extern "C"
{
#include "BKE_scene.h"
#include "BKE_context.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
/* make dummy file */
#include "BLI_fileops.h"
#include "BLI_linklist.h"
+
+static void print_import_header(ImportSettings &import_settings)
+{
+ fprintf(stderr, "+-- Collada Import parameters------\n");
+ fprintf(stderr, "| input file : %s\n", import_settings.filepath);
+ fprintf(stderr, "| use units : %s\n", (import_settings.import_units)?"yes":"no");
+ fprintf(stderr, "| autoconnect : %s\n", (import_settings.auto_connect) ? "yes" : "no");
+ fprintf(stderr, "+-- Armature Import parameters ----\n");
+ fprintf(stderr, "| find bone chains: %s\n", (import_settings.find_chains) ? "yes" : "no");
+ fprintf(stderr, "| min chain len : %d\n", import_settings.min_chain_length);
+ fprintf(stderr, "| fix orientation : %s\n", (import_settings.fix_orientation) ? "yes" : "no");
+ fprintf(stderr, "| keep bind info : %s\n", (import_settings.keep_bind_info) ? "yes" : "no");
+
+}
+
+static void print_import_footer(int status)
+{
+ fprintf(stderr, "+----------------------------------\n");
+ fprintf(stderr, "| Collada Import : %s\n", (status)? "OK":"FAIL");
+ fprintf(stderr, "+----------------------------------\n");
+}
+
int collada_import(bContext *C, ImportSettings *import_settings)
{
+ print_import_header(*import_settings);
DocumentImporter imp(C, import_settings);
- return (imp.import())? 1:0;
+ int status = imp.import()? 1:0;
+ print_import_footer(status);
+
+ return status;
}
int collada_export(bContext *C,
- EvaluationContext *eval_ctx,
- Scene *sce,
ExportSettings *export_settings)
{
+ BlenderContext blender_context(C);
+ ViewLayer *view_layer = blender_context.get_view_layer();
int includeFilter = OB_REL_NONE;
if (export_settings->include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
if (export_settings->include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
+ /* Fetch the complete set of exported objects
+ * ATTENTION: Invisible objects will not be exported
+ */
eObjectSet objectSet = (export_settings->selected) ? OB_SET_SELECTED : OB_SET_ALL;
- export_settings->export_set = BKE_object_relational_superset(sce, objectSet, (eObRelationTypes)includeFilter);
+ export_settings->export_set = BKE_object_relational_superset(view_layer, objectSet, (eObRelationTypes)includeFilter);
+
int export_count = BLI_linklist_count(export_settings->export_set);
if (export_count == 0) {
@@ -75,8 +108,8 @@ int collada_export(bContext *C,
bc_bubble_sort_by_Object_name(export_settings->export_set);
}
- DocumentExporter exporter(export_settings);
- int status = exporter.exportCurrentScene(C, eval_ctx, sce);
+ DocumentExporter exporter(blender_context, export_settings);
+ int status = exporter.exportCurrentScene();
BLI_linklist_free(export_settings->export_set, NULL);
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index 907c94855f7..7882542ca44 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -36,15 +36,14 @@
extern "C" {
#endif
-#include "BKE_depsgraph.h"
#include "BLI_linklist.h"
#include "BLI_path_util.h"
#include "RNA_types.h"
-
-struct EvaluationContext;
struct bContext;
+struct Depsgraph;
struct Scene;
+struct ViewLayer;
/*
* both return 1 on success, 0 on error
@@ -53,8 +52,6 @@ int collada_import(struct bContext *C,
ImportSettings *import_settings);
int collada_export(struct bContext *C,
- struct EvaluationContext *eval_ctx,
- struct Scene *sce,
ExportSettings *export_settings);
#ifdef __cplusplus
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index 14f3e811797..64de0596ac5 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -30,6 +30,7 @@
#include "collada_utils.h"
#include "BLI_linklist.h"
+#include "ED_armature.h"
UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP)
{
@@ -310,6 +311,33 @@ std::string id_name(void *id)
return ((ID *)id)->name + 2;
}
+std::string encode_xml(std::string xml)
+{
+ const std::map<char, std::string> escape {
+ {'<' , "&lt;" },
+ {'>' , "&gt;" },
+ {'"' , "&quot;"},
+ {'\'', "&apos;"},
+ {'&' , "&amp;" }
+ };
+
+ std::map<char, std::string>::const_iterator it;
+ std::string encoded_xml = "";
+
+ for (unsigned int i = 0; i < xml.size(); i++) {
+ char c = xml.at(i);
+ it = escape.find(c);
+
+ if (it == escape.end()) {
+ encoded_xml += c;
+ }
+ else {
+ encoded_xml += it->second;
+ }
+ }
+ return encoded_xml;
+}
+
std::string get_geometry_id(Object *ob)
{
return translate_id(id_name(ob->data)) + "-mesh";
@@ -327,12 +355,11 @@ std::string get_light_id(Object *ob)
return translate_id(id_name(ob)) + "-light";
}
-std::string get_joint_id(Object *ob, Bone *bone)
+std::string get_joint_sid(Bone *bone)
{
- return translate_id(id_name(ob) + "_" + bone->name);
+ return translate_id(bone->name);
}
-
-std::string get_joint_sid(Bone *bone)
+std::string get_joint_sid(EditBone *bone)
{
return translate_id(bone->name);
}
@@ -342,15 +369,14 @@ std::string get_camera_id(Object *ob)
return translate_id(id_name(ob)) + "-camera";
}
-std::string get_material_id(Material *mat)
+std::string get_effect_id(Material *mat)
{
- std::string id = id_name(mat);
- return get_material_id_from_id(id);
+ return translate_id(id_name(mat)) + "-effect";
}
-std::string get_material_id_from_id(std::string id)
+std::string get_material_id(Material *mat)
{
- return translate_id(id) + "-material";
+ return translate_id(id_name(mat)) + "-material";
}
std::string get_morph_id(Object *ob)
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index ff998a94685..f16e3a7cf4a 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -73,11 +73,9 @@ public:
// TODO need also for angle conversion, time conversion...
- void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4& in);
-
- void mat4_to_dae(float out[4][4], float in[4][4]);
-
- void mat4_to_dae_double(double out[4][4], float in[4][4]);
+ static void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4& in);
+ static void mat4_to_dae(float out[4][4], float in[4][4]);
+ static void mat4_to_dae_double(double out[4][4], float in[4][4]);
float(&get_rotation())[4][4];
float(&get_scale())[4][4];
@@ -91,20 +89,19 @@ extern std::string translate_id(const std::string &id);
extern std::string translate_id(const char *idString);
extern std::string id_name(void *id);
+extern std::string encode_xml(std::string xml);
extern std::string get_geometry_id(Object *ob);
extern std::string get_geometry_id(Object *ob, bool use_instantiation);
extern std::string get_light_id(Object *ob);
-extern std::string get_joint_id(Object *ob, Bone *bone);
extern std::string get_joint_sid(Bone *bone);
extern std::string get_camera_id(Object *ob);
+extern std::string get_morph_id(Object *ob);
+extern std::string get_effect_id(Material *mat);
extern std::string get_material_id(Material *mat);
-extern std::string get_material_id_from_id(std::string id);
-
-extern std::string get_morph_id(Object *ob);
#endif /* __COLLADA_INTERNAL_H__ */
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index b25a35a5452..41e661ffd40 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -33,39 +33,59 @@
#include "COLLADAFWMeshVertexData.h"
#include <set>
-
+#include <string>
extern "C" {
#include "DNA_modifier_types.h"
#include "DNA_customdata_types.h"
+#include "DNA_key_types.h"
#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
#include "DNA_armature_types.h"
#include "BLI_math.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h"
+#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
+#include "BKE_constraint.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
+#include "BKE_library.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_object.h"
#include "BKE_scene.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_main.h"
#include "ED_armature.h"
+#include "ED_screen.h"
+#include "ED_node.h"
+
+#include "MEM_guardedalloc.h"
#include "WM_api.h" // XXX hrm, see if we can do without this
#include "WM_types.h"
#include "bmesh.h"
#include "bmesh_tools.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+#if 0
+#include "NOD_common.h"
+#endif
}
#include "collada_utils.h"
#include "ExportSettings.h"
+#include "BlenderContext.h"
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
{
@@ -89,11 +109,53 @@ int bc_test_parent_loop(Object *par, Object *ob)
return bc_test_parent_loop(par->parent, ob);
}
+void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer)
+{
+ Base *base;
+ for (base = (Base *)view_layer->object_bases.first; base; base = base->next) {
+ Object *cob = base->object;
+ if (cob->parent == ob) {
+ switch (ob->type) {
+ case OB_MESH:
+ case OB_CAMERA:
+ case OB_LAMP:
+ case OB_EMPTY:
+ case OB_ARMATURE:
+ child_set.push_back(cob);
+ default: break;
+ }
+ }
+ }
+}
+
+bool bc_validateConstraints(bConstraint *con)
+{
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+
+ /* these we can skip completely (invalid constraints...) */
+ if (cti == NULL)
+ return false;
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
+ return false;
+
+ /* these constraints can't be evaluated anyway */
+ if (cti->evaluate_constraint == NULL)
+ return false;
+
+ /* influence == 0 should be ignored */
+ if (con->enforce == 0.0f)
+ return false;
+
+ /* validation passed */
+ return true;
+}
+
// a shortened version of parent_set_exec()
// if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting
int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
{
Object workob;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *sce = CTX_data_scene(C);
if (!par || bc_test_parent_loop(par, ob))
@@ -107,7 +169,7 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
if (is_parent_space) {
float mat[4][4];
// calc par->obmat
- BKE_object_where_is_calc(sce, par);
+ BKE_object_where_is_calc(depsgraph, sce, par);
// move child obmat into world space
mul_m4_m4m4(mat, par->obmat, ob->obmat);
@@ -118,74 +180,121 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
// compute parentinv
- BKE_object_workob_calc_parent(sce, ob, &workob);
+ BKE_object_workob_calc_parent(depsgraph, sce, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
- DAG_id_tag_update(&par->id, OB_RECALC_OB);
-
- /** done once after import */
-#if 0
- DAG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-#endif
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&par->id, OB_RECALC_OB);
return true;
}
-EvaluationContext *bc_get_evaluation_context(Main *bmain)
+std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions)
{
- return bmain->eval_ctx;
+ std::vector<bAction *> actions;
+ if (all_actions) {
+ Main *bmain = CTX_data_main(C);
+ ID *id;
+
+ for (id = (ID *)bmain->action.first; id; id = (ID *)(id->next)) {
+ bAction *act = (bAction *)id;
+ /* XXX This currently creates too many actions.
+ TODO Need to check if the action is compatible to the given object
+ */
+ actions.push_back(act);
+ }
+ }
+ else
+ {
+ bAction *action = bc_getSceneObjectAction(ob);
+ actions.push_back(action);
+ }
+
+ return actions;
}
-void bc_update_scene(Main *bmain, Scene *scene, float ctime)
+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)
{
+ std::string result = action_name + "_" + channel_type;
+ if (ob_name.length() > 0)
+ result = ob_name + "_" + result;
+ if (axis_name.length() > 0)
+ result += axis_separator + axis_name;
+ return translate_id(result);
+}
+
+void bc_update_scene(BlenderContext &blender_context, float ctime)
+{
+ Main *bmain = blender_context.get_main();
+ Scene *scene = blender_context.get_scene();
+ Depsgraph *depsgraph = blender_context.get_depsgraph();
+
+ /*
+ * See remark in physics_fluid.c lines 395...)
+ * BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
+ */
BKE_scene_frame_set(scene, ctime);
- EvaluationContext *ev_context = bc_get_evaluation_context(bmain);
- BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
+ ED_update_for_newframe(bmain, depsgraph);
}
-Object *bc_add_object(Main *bmain, Scene *scene, int type, const char *name)
+Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
{
Object *ob = BKE_object_add_only_object(bmain, type, name);
ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
ob->lay = scene->lay;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_scene_base_select(scene, BKE_scene_base_add(scene, ob));
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, ob);
+
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ /* TODO: is setting active needed? */
+ BKE_view_layer_base_select_and_set_active(view_layer, base);
return ob;
}
Mesh *bc_get_mesh_copy(
- Main *bmain, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
+ BlenderContext &blender_context,
+ Object *ob,
+ BC_export_mesh_type export_mesh_type,
+ bool apply_modifiers,
+ bool triangulate)
{
- Mesh *tmpmesh;
CustomDataMask mask = CD_MASK_MESH;
Mesh *mesh = (Mesh *)ob->data;
- DerivedMesh *dm = NULL;
+ Mesh *tmpmesh = NULL;
if (apply_modifiers) {
+#if 0 /* Not supported by new system currently... */
switch (export_mesh_type) {
case BC_MESH_TYPE_VIEW:
{
- dm = mesh_create_derived_view(scene, ob, mask);
+ dm = mesh_create_derived_view(depsgraph, scene, ob, mask);
break;
}
case BC_MESH_TYPE_RENDER:
{
- dm = mesh_create_derived_render(scene, ob, mask);
+ dm = mesh_create_derived_render(depsgraph, scene, ob, mask);
break;
}
}
+#else
+ Depsgraph *depsgraph = blender_context.get_depsgraph();
+ Scene *scene = blender_context.get_scene();
+ tmpmesh = mesh_get_eval_final(depsgraph, scene, ob, mask);
+#endif
}
else {
- dm = mesh_create_derived((Mesh *)ob->data, NULL);
+ tmpmesh = mesh;
}
- tmpmesh = BKE_mesh_add(bmain, "ColladaMesh"); // name is not important here
- DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true);
- tmpmesh->flag = mesh->flag;
+ BKE_id_copy_ex(NULL, &tmpmesh->id, (ID **)&tmpmesh,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
if (triangulate) {
bc_triangulate_mesh(tmpmesh);
@@ -213,12 +322,14 @@ Object *bc_get_assigned_armature(Object *ob)
return ob_arm;
}
-// Returns the highest selected ancestor
-// returns NULL if no ancestor is selected
-// IMPORTANT: This function expects that
-// all exported objects have set:
-// ob->id.tag & LIB_TAG_DOIT
+/*
+* Returns the highest selected ancestor
+* returns NULL if no ancestor is selected
+* IMPORTANT: This function expects that all exported objects have set:
+* ob->id.tag & LIB_TAG_DOIT
+*/
Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob)
+
{
Object *ancestor = ob;
while (ob->parent && bc_is_marked(ob->parent)) {
@@ -228,16 +339,31 @@ Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *o
return ancestor;
}
-
bool bc_is_base_node(LinkNode *export_set, Object *ob)
{
Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob);
return (root == ob);
}
-bool bc_is_in_Export_set(LinkNode *export_set, Object *ob)
+bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer)
{
- return (BLI_linklist_index(export_set, ob) != -1);
+ bool to_export = (BLI_linklist_index(export_set, ob) != -1);
+
+ if (!to_export)
+ {
+ /* Mark this object as to_export even if it is not in the
+ export list, but it contains children to export */
+
+ std::vector<Object *> children;
+ bc_get_children(children, ob, view_layer);
+ for (int i = 0; i < children.size(); i++) {
+ if (bc_is_in_Export_set(export_set, children[i], view_layer)) {
+ to_export = true;
+ break;
+ }
+ }
+ }
+ return to_export;
}
bool bc_has_object_type(LinkNode *export_set, short obtype)
@@ -811,6 +937,133 @@ static bool has_custom_props(Bone *bone, bool enabled, std::string key)
}
+void bc_enable_fcurves(bAction *act, char *bone_name)
+{
+ FCurve *fcu;
+ char prefix[200];
+
+ if (bone_name)
+ BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
+
+ for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
+ if (bone_name) {
+ if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
+ fcu->flag &= ~FCURVE_DISABLED;
+ else
+ fcu->flag |= FCURVE_DISABLED;
+ }
+ else {
+ fcu->flag &= ~FCURVE_DISABLED;
+ }
+ }
+}
+
+bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim)
+{
+
+ /* Ok, lets be super cautious and check if the bone exists */
+ bPose *pose = ob->pose;
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
+ if (!pchan) {
+ return false;
+ }
+
+ bAction *action = bc_getSceneObjectAction(ob);
+ bPoseChannel *parchan = pchan->parent;
+
+ bc_enable_fcurves(action, bone->name);
+ float ipar[4][4];
+
+ if (bone->parent) {
+ invert_m4_m4(ipar, parchan->pose_mat);
+ mul_m4_m4m4(mat, ipar, pchan->pose_mat);
+ }
+ else
+ copy_m4_m4(mat, pchan->pose_mat);
+
+ /* OPEN_SIM_COMPATIBILITY
+ * AFAIK animation to second life is via BVH, but no
+ * reason to not have the collada-animation be correct
+ */
+ if (for_opensim) {
+ float temp[4][4];
+ copy_m4_m4(temp, bone->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ invert_m4(temp);
+
+ mul_m4_m4m4(mat, mat, temp);
+
+ if (bone->parent) {
+ copy_m4_m4(temp, bone->parent->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+
+ mul_m4_m4m4(mat, temp, mat);
+ }
+ }
+ bc_enable_fcurves(action, NULL);
+ return true;
+}
+
+bool bc_is_animated(BCMatrixSampleMap &values)
+{
+ static float MIN_DISTANCE = 0.00001;
+
+ if (values.size() < 2)
+ return false; // need at least 2 entries to be not flat
+
+ BCMatrixSampleMap::iterator it;
+ const BCMatrix *refmat = NULL;
+ for (it = values.begin(); it != values.end(); ++it) {
+ const BCMatrix *matrix = it->second;
+
+ if (refmat == NULL) {
+ refmat = matrix;
+ continue;
+ }
+
+ if (!matrix->in_range(*refmat, MIN_DISTANCE))
+ return true;
+ }
+ return false;
+}
+
+bool bc_has_animations(Object *ob)
+{
+ /* Check for object,lamp and camera transform animations */
+ if ((bc_getSceneObjectAction(ob) && bc_getSceneObjectAction(ob)->curves.first) ||
+ (bc_getSceneLampAction(ob) && bc_getSceneLampAction(ob)->curves.first) ||
+ (bc_getSceneCameraAction(ob) && bc_getSceneCameraAction(ob)->curves.first))
+ return true;
+
+ //Check Material Effect parameter animations.
+ for (int a = 0; a < ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a + 1);
+ if (!ma) continue;
+ if (ma->adt && ma->adt->action && ma->adt->action->curves.first)
+ return true;
+ }
+
+ Key *key = BKE_key_from_object(ob);
+ if ((key && key->adt && key->adt->action) && key->adt->action->curves.first)
+ return true;
+
+ return false;
+}
+
+
+bool bc_has_animations(Scene *sce, LinkNode &export_set)
+{
+ LinkNode *node;
+
+ for (node = &export_set; node; node = node->next) {
+ Object *ob = (Object *)node->link;
+
+ if (bc_has_animations(ob))
+ return true;
+ }
+ return false;
+}
+
/**
* Check if custom information about bind matrix exists and modify the from_mat
* accordingly.
@@ -875,8 +1128,11 @@ void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, f
void bc_sanitize_mat(float mat[4][4], int precision)
{
for (int i = 0; i < 4; i++)
- for (int j = 0; j < 4; j++)
- mat[i][j] = double_round(mat[i][j], precision);
+ for (int j = 0; j < 4; j++) {
+ double val = (double)mat[i][j];
+ val = double_round(val, precision);
+ mat[i][j] = (float)val;
+ }
}
void bc_sanitize_mat(double mat[4][4], int precision)
@@ -898,17 +1154,31 @@ void bc_copy_farray_m4(float *r, float a[4][4])
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
*r++ = a[i][j];
+}
+void bc_copy_darray_m4d(double *r, double a[4][4])
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ *r++ = a[i][j];
}
-/*
-* Returns name of Active UV Layer or empty String if no active UV Layer defined.
-* Assuming the Object is of type MESH
-*/
-std::string bc_get_active_uvlayer_name(Object *ob)
+void bc_copy_v44_m4d(std::vector<std::vector<double>> &r, double(&a)[4][4])
{
- Mesh *me = (Mesh *)ob->data;
- return bc_get_active_uvlayer_name(me);
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ r[i][j] = a[i][j];
+ }
+ }
+}
+
+void bc_copy_m4d_v44(double (&r)[4][4], std::vector<std::vector<double>> &a)
+{
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ r[i][j] = a[i][j];
+ }
+ }
}
/**
@@ -926,7 +1196,17 @@ std::string bc_get_active_uvlayer_name(Mesh *me)
return "";
}
-/*
+/**
+ * Returns name of Active UV Layer or empty String if no active UV Layer defined.
+ * Assuming the Object is of type MESH
+ */
+std::string bc_get_active_uvlayer_name(Object *ob)
+{
+ Mesh *me = (Mesh *)ob->data;
+ return bc_get_active_uvlayer_name(me);
+}
+
+/**
* Returns UV Layer name or empty string if layer index is out of range
*/
std::string bc_get_uvlayer_name(Mesh *me, int layer)
@@ -941,124 +1221,202 @@ std::string bc_get_uvlayer_name(Mesh *me, int layer)
return "";
}
-/**********************************************************************
-*
-* Return the list of Mesh objects with assigned UVtextures and Images
-* Note: We need to create artificaial materials for each of them
-*
-***********************************************************************/
-std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
-{
- std::set <Object *> UVObjects;
- Base *base = (Base *)sce->base.first;
-
- while (base) {
- Object *ob = base->object;
- bool has_uvimage = false;
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *)ob->data;
- int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
-
- for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
- if (all_uv_layers || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Image *ima = txface->tpage;
- if (ima != NULL) {
- has_uvimage = true;
- break;
- }
- }
- }
- }
- }
+std::string bc_find_bonename_in_path(std::string path, std::string probe)
+{
+ std::string result;
+ char *boneName = BLI_str_quoted_substrN(path.c_str(), probe.c_str());
+ if (boneName) {
+ result = std::string(boneName);
+ MEM_freeN(boneName);
+ }
+ return result;
+}
- if (has_uvimage) {
- UVObjects.insert(ob);
- }
- }
- base = base->next;
+static bNodeTree *prepare_material_nodetree(Material *ma)
+{
+ if (ma->nodetree == NULL) {
+ ma->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree");
+ ma->use_nodes = true;
}
- return UVObjects;
-}
-
-/**********************************************************************
-*
-* Return the list of UV Texture images from all exported Mesh Items
-* Note: We need to create one artificial material for each Image.
-*
-***********************************************************************/
-std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
-{
- std::set <Image *> UVImages;
- Base *base = (Base *)sce->base.first;
-
- while (base) {
- Object *ob = base->object;
- bool has_uvimage = false;
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *)ob->data;
- int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
-
- for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
- if (all_uv_layers || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Image *ima = txface->tpage;
- if (ima != NULL) {
- if (UVImages.find(ima) == UVImages.end())
- UVImages.insert(ima);
- }
- }
- }
- }
- }
+ return ma->nodetree;
+}
+
+bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy, std::string label)
+{
+ bNode *node = nodeAddStaticNode(C, ntree, node_type);
+ if (node) {
+ if (label.length() > 0) {
+ strcpy(node->label, label.c_str());
}
- base = base->next;
+ node->locx = locx;
+ node->locy = locy;
+ node->flag |= NODE_SELECT;
}
- return UVImages;
+ return node;
}
-/**********************************************************************
-*
-* Return the list of UV Texture images for the given Object
-* Note: We need to create one artificial material for each Image.
-*
-***********************************************************************/
-std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
+
+bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy)
{
- std::set <Image *> UVImages;
+ return bc_add_node(C, ntree, node_type, locx, locy, "");
+}
- bool has_uvimage = false;
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *)ob->data;
- int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+#if 0
+// experimental, probably not used
+static bNodeSocket *bc_group_add_input_socket(bNodeTree *ntree, bNode *to_node, int to_index, std::string label)
+{
+ bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
- for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
- if (all_uv_layers || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Image *ima = txface->tpage;
- if (ima != NULL) {
- if (UVImages.find(ima) == UVImages.end())
- UVImages.insert(ima);
- }
- }
- }
+ //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
+ //return socket;
+
+ bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
+ bNode *inputGroup = ntreeFindType(ntree, NODE_GROUP_INPUT);
+ node_group_input_verify(ntree, inputGroup, (ID *)ntree);
+ bNodeSocket *newsock = node_group_input_find_socket(inputGroup, gsock->identifier);
+ nodeAddLink(ntree, inputGroup, newsock, to_node, to_socket);
+ strcpy(newsock->name, label.c_str());
+ return newsock;
+}
+
+static bNodeSocket *bc_group_add_output_socket(bNodeTree *ntree, bNode *from_node, int from_index, std::string label)
+{
+ bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
+
+ //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
+ //return socket;
+
+ bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, from_node, from_socket);
+ bNode *outputGroup = ntreeFindType(ntree, NODE_GROUP_OUTPUT);
+ node_group_output_verify(ntree, outputGroup, (ID *)ntree);
+ bNodeSocket *newsock = node_group_output_find_socket(outputGroup, gsock->identifier);
+ nodeAddLink(ntree, from_node, from_socket, outputGroup, newsock);
+ strcpy(newsock->name, label.c_str());
+ return newsock;
+}
+
+
+void bc_make_group(bContext *C, bNodeTree *ntree, std::map<std::string, bNode *> nmap)
+{
+ bNode * gnode = node_group_make_from_selected(C, ntree, "ShaderNodeGroup", "ShaderNodeTree");
+ bNodeTree *gtree = (bNodeTree *)gnode->id;
+
+ bc_group_add_input_socket(gtree, nmap["main"], 0, "Diffuse");
+ bc_group_add_input_socket(gtree, nmap["emission"], 0, "Emission");
+ bc_group_add_input_socket(gtree, nmap["mix"], 0, "Transparency");
+ bc_group_add_input_socket(gtree, nmap["emission"], 1, "Emission");
+ bc_group_add_input_socket(gtree, nmap["main"], 4, "Metallic");
+ bc_group_add_input_socket(gtree, nmap["main"], 5, "Specular");
+
+ bc_group_add_output_socket(gtree, nmap["mix"], 0, "Shader");
+}
+#endif
+
+static void bc_node_add_link(bNodeTree *ntree, bNode *from_node, int from_index, bNode *to_node, int to_index)
+{
+ bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
+ bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
+
+ nodeAddLink(ntree, from_node, from_socket, to_node, to_socket);
+}
+
+void bc_add_default_shader(bContext *C, Material *ma)
+{
+ bNodeTree *ntree = prepare_material_nodetree(ma);
+ std::map<std::string, bNode *> nmap;
+#if 0
+ nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300);
+ nmap["emission"] = bc_add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission");
+ nmap["add"] = bc_add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400);
+ nmap["transparent"] = bc_add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200);
+ nmap["mix"] = bc_add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency");
+ nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300);
+ nmap["out"]->flag &= ~NODE_SELECT;
+
+ bc_node_add_link(ntree, nmap["emission"], 0, nmap["add"], 0);
+ bc_node_add_link(ntree, nmap["main"], 0, nmap["add"], 1);
+ bc_node_add_link(ntree, nmap["add"], 0, nmap["mix"], 1);
+ bc_node_add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2);
+
+ bc_node_add_link(ntree, nmap["mix"], 0, nmap["out"], 0);
+ // experimental, probably not used.
+ bc_make_group(C, ntree, nmap);
+#else
+nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, 0, 300);
+nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 300, 300);
+bc_node_add_link(ntree, nmap["main"], 0, nmap["out"], 0);
+#endif
+}
+
+COLLADASW::ColorOrTexture bc_get_base_color(Material *ma)
+{
+ bNode *master_shader = bc_get_master_shader(ma);
+ if (master_shader) {
+ return bc_get_base_color(master_shader);
+ }
+ else {
+ return bc_get_cot(ma->r, ma->g, ma->b, ma->alpha);
+ }
+}
+
+COLLADASW::ColorOrTexture bc_get_specular_color(Material *ma, bool use_fallback)
+{
+ bNode *master_shader = bc_get_master_shader(ma);
+ if (master_shader) {
+ return bc_get_specular_color(master_shader);
+ }
+ else if (use_fallback) {
+ return bc_get_cot(ma->specr * ma->spec, ma->specg * ma->spec, ma->specb * ma->spec, 1.0f);
+ }
+ else {
+ return bc_get_cot(0.0, 0.0, 0.0, 1.0); // no specular
+ }
+}
+
+COLLADASW::ColorOrTexture bc_get_base_color(bNode *shader)
+{
+ bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, "Base Color");
+ if (socket)
+ {
+ bNodeSocketValueRGBA *dcol = (bNodeSocketValueRGBA *)socket->default_value;
+ float* col = dcol->value;
+ return bc_get_cot(col[0], col[1], col[2], col[3]);
+ }
+ else {
+ return bc_get_cot(0.8, 0.8, 0.8, 1.0); //default white
+ }
+}
+
+COLLADASW::ColorOrTexture bc_get_specular_color(bNode *shader)
+{
+ bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, "Specular");
+ if (socket)
+ {
+ bNodeSocketValueRGBA *dcol = (bNodeSocketValueRGBA *)socket->default_value;
+ float* col = dcol->value;
+ return bc_get_cot(col[0], col[1], col[2], col[3]);
+ }
+ else {
+ return bc_get_cot(0.8, 0.8, 0.8, 1.0); //default white
+ }
+}
+
+bNode *bc_get_master_shader(Material *ma)
+{
+ bNodeTree *nodetree = ma->nodetree;
+ if (nodetree) {
+ for (bNode *node = (bNode *)nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->type == SH_NODE_BSDF_PRINCIPLED) {
+ return node;
}
}
}
- return UVImages;
+ return NULL;
+}
+
+COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a)
+{
+ COLLADASW::Color color(r, g, b, a);
+ COLLADASW::ColorOrTexture cot(color);
+ return cot;
}
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index d1591a34cce..14d1948a42b 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -31,6 +31,9 @@
#include "COLLADAFWGeometry.h"
#include "COLLADAFWFloatOrDoubleArray.h"
#include "COLLADAFWTypes.h"
+#include "COLLADASWEffectProfile.h"
+#include "COLLADAFWColorOrTexture.h"
+
#include <vector>
#include <map>
@@ -39,7 +42,12 @@
extern "C" {
#include "DNA_object_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_camera_types.h"
+
#include "DNA_customdata_types.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
@@ -50,33 +58,95 @@ extern "C" {
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BKE_main.h"
#include "BKE_context.h"
#include "BKE_object.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_scene.h"
#include "BKE_idprop.h"
+#include "BKE_node.h"
}
+#include "DEG_depsgraph_query.h"
+
#include "ImportSettings.h"
#include "ExportSettings.h"
#include "collada_internal.h"
+#include "BCSampleData.h"
+#include "BlenderContext.h"
+struct Depsgraph;
+
+typedef std::map<COLLADAFW::UniqueId, Image*> UidImageMap;
+typedef std::map<std::string, Image*> KeyImageMap;
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureArrayMap;
+typedef std::set<Object *> BCObjectSet;
+
+extern void bc_update_scene(BlenderContext &blender_context, float ctime);
+
+/* Action helpers */
+
+std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions);
+
+/* Action helpers */
+
+inline bAction *bc_getSceneObjectAction(Object *ob)
+{
+ return (ob->adt && ob->adt->action) ? ob->adt->action : NULL;
+}
+
+/* Returns Lamp Action or NULL */
+inline bAction *bc_getSceneLampAction(Object *ob)
+{
+ if (ob->type != OB_LAMP)
+ return NULL;
+
+ Lamp *lamp = (Lamp *)ob->data;
+ return (lamp->adt && lamp->adt->action) ? lamp->adt->action : NULL;
+}
+
+/* Return Camera Action or NULL */
+inline bAction *bc_getSceneCameraAction(Object *ob)
+{
+ if (ob->type != OB_CAMERA)
+ return NULL;
+
+ Camera *camera = (Camera *)ob->data;
+ return (camera->adt && camera->adt->action) ? camera->adt->action : NULL;
+}
+
+/* returns material action or NULL */
+inline bAction *bc_getSceneMaterialAction(Material *ma)
+{
+ if (ma == NULL)
+ return NULL;
+
+ return (ma->adt && ma->adt->action) ? ma->adt->action : NULL;
+}
+
+inline void bc_setSceneObjectAction(bAction *action, Object *ob)
+{
+ if (ob->adt)
+ ob->adt->action = action;
+}
+
+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 = "_");
-extern EvaluationContext *bc_get_evaluation_context(Main *bmain);
-extern void bc_update_scene(Main *bmain, Scene *scene, float ctime);
extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index);
extern int bc_test_parent_loop(Object *par, Object *ob);
+
+extern void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer);
+extern bool bc_validateConstraints(bConstraint *con);
+
extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true);
-extern Object *bc_add_object(Main *bmain, Scene *scene, int type, const char *name);
+extern Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name);
extern Mesh *bc_get_mesh_copy(
- Main *bmain, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate);
+ BlenderContext &blender_context, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate);
extern Object *bc_get_assigned_armature(Object *ob);
extern Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob);
extern bool bc_is_base_node(LinkNode *export_set, Object *ob);
-extern bool bc_is_in_Export_set(LinkNode *export_set, Object *ob);
+extern bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer);
extern bool bc_has_object_type(LinkNode *export_set, short obtype);
extern int bc_is_marked(Object *ob);
@@ -90,6 +160,30 @@ extern void bc_bubble_sort_by_Object_name(LinkNode *export_set);
extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only);
extern int bc_get_active_UVLayer(Object *ob);
+std::string bc_find_bonename_in_path(std::string path, std::string probe);
+
+inline std::string bc_string_after(const std::string& s, const char c)
+{
+ size_t i = s.rfind(c, s.length());
+ if (i != std::string::npos) {
+ return(s.substr(i + 1, s.length() - i));
+ }
+ return(s);
+}
+
+inline bool bc_startswith(std::string const & value, std::string const & starting)
+{
+ if (starting.size() > value.size())
+ return false;
+ return (value.substr(0, starting.size()) == starting);
+}
+
+inline bool bc_endswith(std::string const & value, std::string const & ending)
+{
+ if (ending.size() > value.size()) return false;
+ return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
+}
+
extern std::string bc_replace_string(std::string data, const std::string& pattern, const std::string& replacement);
extern std::string bc_url_encode(std::string data);
extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene);
@@ -109,9 +203,12 @@ inline bool bc_in_range(float a, float b, float range) {
}
void bc_copy_m4_farray(float r[4][4], float *a);
void bc_copy_farray_m4(float *r, float a[4][4]);
+void bc_copy_darray_m4d(double *r, double a[4][4]);
+void bc_copy_m4d_v44(double(&r)[4][4], std::vector<std::vector<double>> &a);
+void bc_copy_v44_m4d(std::vector<std::vector<double>> &a, double(&r)[4][4]);
-extern void bc_sanitize_mat(float mat[4][4], int precision);
-extern void bc_sanitize_mat(double mat[4][4], int precision);
+void bc_sanitize_mat(float mat[4][4], int precision);
+void bc_sanitize_mat(double mat[4][4], int precision);
extern IDProperty *bc_get_IDProperty(Bone *bone, std::string key);
extern void bc_set_IDProperty(EditBone *ebone, const char *key, float value);
@@ -121,15 +218,14 @@ extern float bc_get_property(Bone *bone, std::string key, float def);
extern void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]);
extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]);
-extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space);
+extern void bc_enable_fcurves(bAction *act, char *bone_name);
+extern bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim);
+extern bool bc_is_animated(BCMatrixSampleMap &values);
+extern bool bc_has_animations(Scene *sce, LinkNode &node);
+extern bool bc_has_animations(Object *ob);
-extern std::string bc_get_active_uvlayer_name(Object *ob);
-extern std::string bc_get_active_uvlayer_name(Mesh *me);
-extern std::string bc_get_uvlayer_name(Mesh *me, int layer);
-extern std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers);
-extern std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers);
-extern std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers);
+extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space);
class BCPolygonNormalsIndices
{
@@ -210,4 +306,12 @@ public:
~BoneExtensionManager();
};
+void bc_add_default_shader(bContext *C, Material *ma);
+bNode *bc_get_master_shader(Material *ma);
+COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a);
+COLLADASW::ColorOrTexture bc_get_base_color(bNode *shader);
+COLLADASW::ColorOrTexture bc_get_base_color(Material *ma);
+COLLADASW::ColorOrTexture bc_get_specular_color(bNode *shader);
+COLLADASW::ColorOrTexture bc_get_specular_color(Material *ma, bool use_fallback);
+
#endif