Compare commits
123 Commits
temp-cocoa
...
collada2.8
Author | SHA1 | Date | |
---|---|---|---|
cd1319d095 | |||
c5f14a3eec | |||
7bd7848374 | |||
5df55e184e | |||
76a18d555c | |||
06862486d4 | |||
6a311402db | |||
445b60270f | |||
0833084fd6 | |||
14d4c5477d | |||
5fa08d1ff0 | |||
cf43f4ed2f | |||
7d908f87b4 | |||
8073d672ab | |||
2e16905480 | |||
2aab0e85cf | |||
7d2bb2c9d9 | |||
4290c938e5 | |||
3749eac075 | |||
7254e92ba2 | |||
f0759a413e | |||
199017ac14 | |||
fd31a63a5c | |||
6e5f271a00 | |||
af6585cc9c | |||
d3ca5f8395 | |||
569ad49a01 | |||
58dfe293cb | |||
9f2b380b41 | |||
eac9021c62 | |||
c1b507f733 | |||
087e086ef9 | |||
9dcd4f9fcd | |||
9f298e2c81 | |||
e7e5930efb | |||
c437c017e3 | |||
14bb6a964a | |||
c103a3903f | |||
2271b79114 | |||
30dc14875f | |||
5b845ea104 | |||
d79c5ec2e2 | |||
a0350c0cb1 | |||
8daa543a2a | |||
d0a9b0c9dd | |||
aca6f9e0c4 | |||
3927aef22e | |||
5b9d70a85a | |||
756ef553d8 | |||
0698c194d2 | |||
eac73e504c | |||
ce3942a5b0 | |||
1e8dca814b | |||
281df836b0 | |||
ae3e320438 | |||
4d554543c2 | |||
5b63d4c1f6 | |||
b156b8b022 | |||
7793d5daec | |||
3c68ed62aa | |||
82e143cdb2 | |||
ca20df51dc | |||
bfc34b2248 | |||
a906c74f73 | |||
86c205ef00 | |||
d5455e4232 | |||
22d6cb36b4 | |||
ee67f50f25 | |||
fb8ea90a46 | |||
b32de8880e | |||
327f79cfb4 | |||
cfbebe7aaa | |||
51103eeebe | |||
16141f43bc | |||
3d6c191191 | |||
ceb4a44d0b | |||
f0d2dc61d9 | |||
9bd7d7027d | |||
635eff37de | |||
3df470fc62 | |||
3c0a7cca00 | |||
74e94a7ed4 | |||
7ca84b6418 | |||
4573540929 | |||
e77a3c2f27 | |||
51a76657de | |||
fda3a09f11 | |||
5d4c1f0242 | |||
e04a73c993 | |||
b773c5ce52 | |||
d0055996a7 | |||
30127c406a | |||
237da1869a | |||
ec1ed2a9f9 | |||
3ce6ff90b7 | |||
4c3a6fb3f9 | |||
d299f9d423 | |||
279e517770 | |||
bcbcc292f3 | |||
26f6e3a977 | |||
02f0b09329 | |||
9e4929b72d | |||
9dab15d3a1 | |||
b6ecf66894 | |||
f9bca158bb | |||
2183879216 | |||
839702080e | |||
12e28b4930 | |||
9a2771c1fa | |||
8cbfe8785e | |||
c2e1bfa3af | |||
90349bec6a | |||
1bf404dbd3 | |||
2e8391ee09 | |||
7ed18dc511 | |||
4dd14b7f38 | |||
6cae345de8 | |||
18bab65abb | |||
7bdde043a8 | |||
0fa59db066 | |||
83c3359100 | |||
2e82cdf318 | |||
ffd1893ba9 |
@@ -10,7 +10,6 @@ op.include_armatures = True
|
||||
op.include_shapekeys = False
|
||||
op.deform_bones_only = True
|
||||
op.active_uv_only = True
|
||||
op.include_uv_textures = True
|
||||
op.use_texture_copies = True
|
||||
op.triangulate = True
|
||||
op.use_object_instantiation = False
|
||||
|
55
source/blender/collada/AnimationClipExporter.cpp
Normal file
55
source/blender/collada/AnimationClipExporter.cpp
Normal file
@@ -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();
|
||||
}
|
50
source/blender/collada/AnimationClipExporter.h
Normal file
50
source/blender/collada/AnimationClipExporter.h
Normal file
@@ -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) :
|
||||
depsgraph(depsgraph),
|
||||
COLLADASW::LibraryAnimationClips(sw),
|
||||
export_settings(export_settings),
|
||||
anim_meta(anim_meta)
|
||||
{
|
||||
this->sw = sw;
|
||||
}
|
||||
|
||||
void exportAnimationClips(Scene *sce);
|
||||
};
|
391
source/blender/collada/AnimationCurveCache.cpp
Normal file
391
source/blender/collada/AnimationCurveCache.cpp
Normal file
@@ -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;
|
||||
}
|
130
source/blender/collada/AnimationCurveCache.h
Normal file
130
source/blender/collada/AnimationCurveCache.h
Normal file
@@ -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
|
File diff suppressed because it is too large
Load Diff
@@ -20,13 +20,15 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file AnimationExporter.h
|
||||
* \ingroup collada
|
||||
*/
|
||||
#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"
|
||||
@@ -74,35 +76,40 @@ 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;
|
||||
Depsgraph *depsgraph;
|
||||
BlenderContext &blender_context;
|
||||
COLLADASW::StreamWriter *sw;
|
||||
|
||||
public:
|
||||
|
||||
AnimationExporter(Depsgraph *depsgraph, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings):
|
||||
AnimationExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings):
|
||||
blender_context(blender_context),
|
||||
COLLADASW::LibraryAnimations(sw),
|
||||
depsgraph(depsgraph),
|
||||
export_settings(export_settings)
|
||||
{
|
||||
this->sw = sw;
|
||||
}
|
||||
|
||||
bool exportAnimations(Main *bmain, Scene *sce);
|
||||
bool exportAnimations();
|
||||
|
||||
// called for each exported object
|
||||
void operator() (Object *ob);
|
||||
@@ -110,7 +117,6 @@ public:
|
||||
protected:
|
||||
const ExportSettings *export_settings;
|
||||
|
||||
|
||||
void export_object_constraint_animation(Object *ob);
|
||||
|
||||
void export_morph_animation(Object *ob);
|
||||
@@ -121,8 +127,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);
|
||||
@@ -141,70 +145,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);
|
||||
COLLADASW::InputSemantic::Semantics semantic,
|
||||
bool is_rot,
|
||||
const std::string axis,
|
||||
bool transform);
|
||||
|
||||
void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values, int *length);
|
||||
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);
|
||||
|
||||
float* get_eul_source_for_quat(Object *ob );
|
||||
std::string collada_tangent_from_curve(
|
||||
COLLADASW::InputSemantic::Semantics semantic,
|
||||
BCAnimationCurve &curve,
|
||||
const std::string& anim_id,
|
||||
const std::string axis_name);
|
||||
|
||||
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> ×, std::vector<float> &values, std::string, std::string label, std::string axis_name, bool is_rot);
|
||||
std::string collada_interpolation_source(const BCAnimationCurve &curve, const std::string& anim_id, std::string axis_name, bool *has_tangents);
|
||||
|
||||
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);
|
||||
|
||||
void evaluate_anim_with_constraints(Object *ob, float ctime);
|
||||
/* ===================================== */
|
||||
/* Currently unused or not (yet?) needed */
|
||||
/* ===================================== */
|
||||
|
||||
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);
|
||||
bool is_bone_deform_group(Bone * bone);
|
||||
|
||||
std::string create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id);
|
||||
|
||||
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 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 create_xyz_source(float *v, int tot, const std::string& anim_id);
|
||||
std::string create_4x4_source(std::vector<float> ×, 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);
|
||||
|
||||
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 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
|
||||
|
@@ -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,7 +244,8 @@ void AnimationImporter::add_fcurves_to_object(Main *bmain, Object *ob, std::vect
|
||||
}
|
||||
}
|
||||
|
||||
AnimationImporter::AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene) :
|
||||
AnimationImporter::AnimationImporter(bContext *C, UnitConverter *conv, ArmatureImporter *arm, Scene *scene) :
|
||||
mContext(C),
|
||||
TransformReader(conv), armature_importer(arm), scene(scene) {
|
||||
}
|
||||
|
||||
@@ -304,7 +304,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 +724,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 +839,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 +908,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 +932,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 +941,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 +975,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 +1006,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 +1040,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 +1095,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 +1147,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 +1270,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 +1303,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 +1447,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 +1669,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 +1787,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;
|
||||
|
@@ -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,7 @@ private:
|
||||
};
|
||||
public:
|
||||
|
||||
AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene);
|
||||
AnimationImporter(bContext *C, UnitConverter *conv, ArmatureImporter *arm, Scene *scene);
|
||||
|
||||
~AnimationImporter();
|
||||
|
||||
@@ -153,7 +154,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 +162,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 +182,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 *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,
|
||||
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 );
|
||||
|
@@ -56,39 +56,47 @@ extern "C" {
|
||||
// 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) {
|
||||
ArmatureExporter::ArmatureExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) :
|
||||
blender_context(blender_context),
|
||||
COLLADASW::LibraryControllers(sw), export_settings(export_settings)
|
||||
{
|
||||
}
|
||||
|
||||
// write bone nodes
|
||||
void ArmatureExporter::add_armature_bones(bContext *C, Depsgraph *depsgraph, 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, depsgraph, 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);
|
||||
@@ -156,12 +164,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, Depsgraph *depsgraph, 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);
|
||||
|
||||
@@ -201,7 +211,7 @@ void ArmatureExporter::add_bone_node(bContext *C, Depsgraph *depsgraph, Bone *bo
|
||||
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)) {
|
||||
@@ -230,8 +240,7 @@ void ArmatureExporter::add_bone_node(bContext *C, Depsgraph *depsgraph, Bone *bo
|
||||
mul_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
|
||||
}
|
||||
|
||||
se->writeNodes(C, depsgraph, *i, sce);
|
||||
|
||||
se->writeNodes(*i);
|
||||
copy_m4_m4((*i)->parentinv, backup_parinv);
|
||||
child_objects.erase(i++);
|
||||
}
|
||||
@@ -239,13 +248,13 @@ void ArmatureExporter::add_bone_node(bContext *C, Depsgraph *depsgraph, Bone *bo
|
||||
}
|
||||
|
||||
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
|
||||
add_bone_node(C, depsgraph, 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, depsgraph, child, ob_arm, sce, se, child_objects);
|
||||
add_bone_node(child, ob_arm, se, child_objects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -57,21 +57,20 @@ class SceneExporter;
|
||||
class ArmatureExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
|
||||
{
|
||||
public:
|
||||
ArmatureExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
|
||||
ArmatureExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
|
||||
|
||||
// write bone nodes
|
||||
void add_armature_bones(bContext *C, struct Depsgraph *depsgraph, Object *ob_arm, Scene *sce, SceneExporter *se,
|
||||
std::list<Object *>& child_objects);
|
||||
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;
|
||||
const ExportSettings *export_settings;
|
||||
BlenderContext &blender_context;
|
||||
|
||||
#if 0
|
||||
std::vector<Object *> written_armatures;
|
||||
@@ -85,8 +84,11 @@ private:
|
||||
|
||||
// Scene, SceneExporter and the list of child_objects
|
||||
// are required for writing bone parented objects
|
||||
void add_bone_node(bContext *C, struct Depsgraph *depsgraph, 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);
|
||||
|
||||
|
679
source/blender/collada/BCAnimationCurve.cpp
Normal file
679
source/blender/collada/BCAnimationCurve.cpp
Normal file
@@ -0,0 +1,679 @@
|
||||
/*
|
||||
* ***** 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];
|
||||
}
|
||||
}
|
||||
|
156
source/blender/collada/BCAnimationCurve.h
Normal file
156
source/blender/collada/BCAnimationCurve.h
Normal file
@@ -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
|
645
source/blender/collada/BCAnimationSampler.cpp
Normal file
645
source/blender/collada/BCAnimationSampler.cpp
Normal file
@@ -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();
|
||||
}
|
205
source/blender/collada/BCAnimationSampler.h
Normal file
205
source/blender/collada/BCAnimationSampler.h
Normal file
@@ -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
|
188
source/blender/collada/BCSampleData.cpp
Normal file
188
source/blender/collada/BCSampleData.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* ***** 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;
|
||||
}
|
||||
|
||||
|
102
source/blender/collada/BCSampleData.h
Normal file
102
source/blender/collada/BCSampleData.h
Normal file
@@ -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
|
61
source/blender/collada/BlenderContext.cpp
Normal file
61
source/blender/collada/BlenderContext.cpp
Normal file
@@ -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;
|
||||
}
|
56
source/blender/collada/BlenderContext.h
Normal file
56
source/blender/collada/BlenderContext.h
Normal file
@@ -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
|
@@ -49,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
|
||||
@@ -68,6 +73,7 @@ set(SRC
|
||||
MaterialExporter.cpp
|
||||
MeshImporter.cpp
|
||||
SkinInfo.cpp
|
||||
Materials.cpp
|
||||
SceneExporter.cpp
|
||||
TransformReader.cpp
|
||||
TransformWriter.cpp
|
||||
@@ -77,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
|
||||
@@ -95,6 +106,7 @@ set(SRC
|
||||
LightExporter.h
|
||||
MaterialExporter.h
|
||||
MeshImporter.h
|
||||
Materials.h
|
||||
SkinInfo.h
|
||||
SceneExporter.h
|
||||
TransformReader.h
|
||||
|
@@ -58,7 +58,9 @@ extern "C" {
|
||||
// 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) {
|
||||
ControllerExporter::ControllerExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) :
|
||||
blender_context(blender_context),
|
||||
COLLADASW::LibraryControllers(sw), export_settings(export_settings) {
|
||||
}
|
||||
|
||||
bool ControllerExporter::is_skinned_mesh(Object *ob)
|
||||
@@ -66,11 +68,12 @@ 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);
|
||||
@@ -103,12 +106,9 @@ bool ControllerExporter::add_instance_controller(Object *ob)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControllerExporter::export_controllers(Main *bmain, Depsgraph *depsgraph, Scene *sce)
|
||||
void ControllerExporter::export_controllers()
|
||||
{
|
||||
this->depsgraph = depsgraph;
|
||||
m_bmain = bmain;
|
||||
scene = sce;
|
||||
|
||||
Scene *sce = blender_context.get_scene();
|
||||
openLibrary();
|
||||
|
||||
GeometryFunctor gf;
|
||||
@@ -203,8 +203,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
|
||||
}
|
||||
|
||||
me = bc_get_mesh_copy(
|
||||
depsgraph,
|
||||
scene,
|
||||
blender_context,
|
||||
ob,
|
||||
this->export_settings->export_mesh_type,
|
||||
this->export_settings->apply_modifiers,
|
||||
@@ -305,8 +304,7 @@ void ControllerExporter::export_morph_controller(Object *ob, Key *key)
|
||||
Mesh *me;
|
||||
|
||||
me = bc_get_mesh_copy(
|
||||
depsgraph,
|
||||
scene,
|
||||
blender_context,
|
||||
ob,
|
||||
this->export_settings->export_mesh_type,
|
||||
this->export_settings->apply_modifiers,
|
||||
@@ -499,6 +497,9 @@ 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(depsgraph, scene, ob_arm);
|
||||
}
|
||||
@@ -547,6 +548,8 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
|
||||
|
||||
// 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(depsgraph, scene, ob_arm);
|
||||
}
|
||||
|
@@ -60,20 +60,18 @@ class SceneExporter;
|
||||
class ControllerExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
|
||||
{
|
||||
public:
|
||||
ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
|
||||
ControllerExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
|
||||
|
||||
bool is_skinned_mesh(Object *ob);
|
||||
|
||||
bool add_instance_controller(Object *ob);
|
||||
|
||||
void export_controllers(Main *bmain, Depsgraph *depsgraph, Scene *sce);
|
||||
void export_controllers();
|
||||
|
||||
void operator()(Object *ob);
|
||||
|
||||
private:
|
||||
Depsgraph *depsgraph;
|
||||
Main *m_bmain;
|
||||
Scene *scene;
|
||||
BlenderContext &blender_context;
|
||||
UnitConverter converter;
|
||||
const ExportSettings *export_settings;
|
||||
|
||||
|
@@ -151,8 +151,8 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
|
||||
return data->layers[layer_index].name;
|
||||
}
|
||||
|
||||
DocumentExporter::DocumentExporter(Depsgraph *depsgraph, const ExportSettings *export_settings) :
|
||||
depsgraph(depsgraph),
|
||||
DocumentExporter::DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings) :
|
||||
blender_context(blender_context),
|
||||
export_settings(export_settings) {
|
||||
}
|
||||
|
||||
@@ -180,9 +180,13 @@ 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, Scene *sce)
|
||||
int DocumentExporter::exportCurrentScene()
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Main *bmain = blender_context.get_main();
|
||||
Scene *sce = blender_context.get_scene();
|
||||
bContext *C = blender_context.get_context();
|
||||
Depsgraph *depsgraph = blender_context.get_depsgraph(); \
|
||||
|
||||
PointerRNA sceneptr, unit_settings;
|
||||
PropertyRNA *system; /* unused , *scale; */
|
||||
|
||||
@@ -272,13 +276,13 @@ int DocumentExporter::exportCurrentScene(bContext *C, Scene *sce)
|
||||
le.exportLights(sce);
|
||||
}
|
||||
|
||||
// <library_images>
|
||||
ImagesExporter ie(writer, this->export_settings);
|
||||
ie.exportImages(sce);
|
||||
|
||||
// <library_effects>
|
||||
EffectsExporter ee(writer, this->export_settings);
|
||||
ee.exportEffects(sce);
|
||||
EffectsExporter ee(writer, this->export_settings, key_image_map);
|
||||
ee.exportEffects(C, sce);
|
||||
|
||||
// <library_images>
|
||||
ImagesExporter ie(writer, this->export_settings, key_image_map);
|
||||
ie.exportImages(sce);
|
||||
|
||||
// <library_materials>
|
||||
MaterialsExporter me(writer, this->export_settings);
|
||||
@@ -286,28 +290,29 @@ int DocumentExporter::exportCurrentScene(bContext *C, Scene *sce)
|
||||
|
||||
// <library_geometries>
|
||||
if (bc_has_object_type(export_set, OB_MESH)) {
|
||||
GeometryExporter ge(writer, this->export_settings);
|
||||
ge.exportGeom(bmain, depsgraph, 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, depsgraph, 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(depsgraph, writer, this->export_settings);
|
||||
ae.exportAnimations(bmain, sce);
|
||||
AnimationExporter ae(blender_context, writer, this->export_settings);
|
||||
ae.exportAnimations();
|
||||
}
|
||||
se.exportScene(C, depsgraph, sce);
|
||||
|
||||
se.exportScene();
|
||||
|
||||
// <scene>
|
||||
std::string scene_name(translate_id(id_name(sce)));
|
||||
|
@@ -28,24 +28,24 @@
|
||||
#define __DOCUMENTEXPORTER_H__
|
||||
|
||||
#include "collada.h"
|
||||
#include "collada_utils.h"
|
||||
#include "BlenderContext.h"
|
||||
|
||||
extern "C" {
|
||||
#include "DNA_customdata_types.h"
|
||||
|
||||
}
|
||||
|
||||
struct Scene;
|
||||
|
||||
class DocumentExporter
|
||||
{
|
||||
public:
|
||||
DocumentExporter(Depsgraph *depsgraph, const ExportSettings *export_settings);
|
||||
int exportCurrentScene(bContext *C, Scene *sce);
|
||||
|
||||
DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings);
|
||||
int exportCurrentScene();
|
||||
void exportScenes(const char *filename);
|
||||
private:
|
||||
Depsgraph *depsgraph;
|
||||
BlenderContext &blender_context;
|
||||
const ExportSettings *export_settings;
|
||||
KeyImageMap key_image_map;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -91,7 +91,7 @@ extern "C" {
|
||||
|
||||
#include "collada_internal.h"
|
||||
#include "collada_utils.h"
|
||||
|
||||
#include "materials.h"
|
||||
|
||||
/*
|
||||
* COLLADA Importer limitations:
|
||||
@@ -104,12 +104,12 @@ extern "C" {
|
||||
|
||||
DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) :
|
||||
import_settings(import_settings),
|
||||
mImportStage(General),
|
||||
mImportStage(Fetching_Scene_data),
|
||||
mContext(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(&unit_converter, &armature_importer, CTX_data_scene(C))
|
||||
anim_importer(C, &unit_converter, &armature_importer, CTX_data_scene(C))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -149,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);
|
||||
|
||||
@@ -182,7 +180,7 @@ void DocumentImporter::start()
|
||||
|
||||
void DocumentImporter::finish()
|
||||
{
|
||||
if (mImportStage != General)
|
||||
if (mImportStage == Fetching_Controller_data)
|
||||
return;
|
||||
|
||||
Main *bmain = CTX_data_main(mContext);
|
||||
@@ -225,12 +223,14 @@ 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);
|
||||
objects_to_scale->insert(objects_to_scale->end(), objects_done->begin(), objects_done->end());
|
||||
delete objects_done;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ 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 it;
|
||||
for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
|
||||
@@ -277,7 +277,6 @@ void DocumentImporter::finish()
|
||||
|
||||
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
|
||||
@@ -312,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);
|
||||
@@ -403,7 +402,7 @@ 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);
|
||||
@@ -503,9 +502,10 @@ 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) {
|
||||
@@ -700,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.
|
||||
@@ -723,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;
|
||||
}
|
||||
|
||||
@@ -743,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);
|
||||
@@ -753,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);
|
||||
@@ -766,136 +766,18 @@ bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
|
||||
{
|
||||
COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
|
||||
|
||||
// TODO: add back texture and extended material parameter support
|
||||
|
||||
// blinn
|
||||
if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
|
||||
#if 0
|
||||
ma->spec_shader = MA_SPEC_BLINN;
|
||||
ma->spec = ef->getShininess().getFloatValue();
|
||||
#endif
|
||||
}
|
||||
// phong
|
||||
else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
|
||||
#if 0
|
||||
ma->spec_shader = MA_SPEC_PHONG;
|
||||
ma->har = ef->getShininess().getFloatValue();
|
||||
#endif
|
||||
}
|
||||
// lambert
|
||||
else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
|
||||
#if 0
|
||||
ma->diff_shader = MA_DIFF_LAMBERT;
|
||||
#endif
|
||||
}
|
||||
// default - lambert
|
||||
else {
|
||||
#if 0
|
||||
ma->diff_shader = MA_DIFF_LAMBERT;
|
||||
fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
|
||||
#endif
|
||||
}
|
||||
// reflectivity
|
||||
ma->metallic = ef->getReflectivity().getFloatValue();
|
||||
// index of refraction
|
||||
#if 0
|
||||
ma->ang = ef->getIndexOfRefraction().getFloatValue();
|
||||
#endif
|
||||
|
||||
COLLADAFW::Color col;
|
||||
|
||||
// DIFFUSE
|
||||
// color
|
||||
if (ef->getDiffuse().isColor()) {
|
||||
col = ef->getDiffuse().getColor();
|
||||
ma->r = col.getRed();
|
||||
ma->g = col.getGreen();
|
||||
ma->b = col.getBlue();
|
||||
}
|
||||
// texture
|
||||
else if (ef->getDiffuse().isTexture()) {
|
||||
#if 0
|
||||
COLLADAFW::Texture ctex = ef->getDiffuse().getTexture();
|
||||
#endif
|
||||
}
|
||||
// AMBIENT
|
||||
// color
|
||||
if (ef->getAmbient().isColor()) {
|
||||
#if 0
|
||||
col = ef->getAmbient().getColor();
|
||||
#endif
|
||||
}
|
||||
// texture
|
||||
else if (ef->getAmbient().isTexture()) {
|
||||
#if 0
|
||||
COLLADAFW::Texture ctex = ef->getAmbient().getTexture();
|
||||
#endif
|
||||
}
|
||||
// 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()) {
|
||||
#if 0
|
||||
COLLADAFW::Texture ctex = ef->getSpecular().getTexture();
|
||||
#endif
|
||||
}
|
||||
// REFLECTIVE
|
||||
// color
|
||||
if (ef->getReflective().isColor()) {
|
||||
#if 0
|
||||
col = ef->getReflective().getColor();
|
||||
#endif
|
||||
}
|
||||
// texture
|
||||
else if (ef->getReflective().isTexture()) {
|
||||
#if 0
|
||||
COLLADAFW::Texture ctex = ef->getReflective().getTexture();
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
#if 0
|
||||
COLLADAFW::Texture ctex = ef->getEmission().getTexture();
|
||||
#endif
|
||||
}
|
||||
|
||||
// TRANSPARENT
|
||||
// color
|
||||
if (ef->getOpacity().isColor()) {
|
||||
#if 0
|
||||
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) {
|
||||
...
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// texture
|
||||
else if (ef->getOpacity().isTexture()) {
|
||||
#if 0
|
||||
COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
|
||||
#endif
|
||||
}
|
||||
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.
|
||||
@@ -903,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();
|
||||
@@ -940,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);
|
||||
@@ -1066,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();
|
||||
@@ -1083,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();
|
||||
@@ -1091,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;
|
||||
}
|
||||
|
||||
@@ -1103,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);
|
||||
@@ -1196,12 +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:
|
||||
{
|
||||
/* TODO Fix */
|
||||
// lamp->type = LA_HEMI;
|
||||
lamp->type = LA_SUN; //TODO needs more thoughts
|
||||
}
|
||||
break;
|
||||
case COLLADAFW::Light::SPOT_LIGHT:
|
||||
@@ -1251,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;
|
||||
@@ -1261,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;
|
||||
@@ -1278,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);
|
||||
|
@@ -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);
|
||||
@@ -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
|
||||
|
@@ -49,7 +49,6 @@ extern "C" {
|
||||
#include "BKE_material.h"
|
||||
}
|
||||
|
||||
// OB_MESH is assumed
|
||||
static std::string getActiveUVLayerName(Object *ob)
|
||||
{
|
||||
Mesh *me = (Mesh *)ob->data;
|
||||
@@ -61,8 +60,12 @@ static std::string getActiveUVLayerName(Object *ob)
|
||||
return "";
|
||||
}
|
||||
|
||||
EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -82,9 +85,10 @@ bool EffectsExporter::hasEffects(Scene *sce)
|
||||
return false;
|
||||
}
|
||||
|
||||
void EffectsExporter::exportEffects(Scene *sce)
|
||||
void EffectsExporter::exportEffects(bContext *C, Scene *sce)
|
||||
{
|
||||
if (hasEffects(sce)) {
|
||||
this->mContext = C;
|
||||
this->scene = sce;
|
||||
openLibrary();
|
||||
MaterialFunctor mf;
|
||||
@@ -94,61 +98,105 @@ void EffectsExporter::exportEffects(Scene *sce)
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsExporter::writeLambert(COLLADASW::EffectProfile &ep, Material *ma)
|
||||
void EffectsExporter::set_shader_type(COLLADASW::EffectProfile &ep, Material *ma)
|
||||
{
|
||||
COLLADASW::ColorOrTexture cot;
|
||||
ep.setShaderType(COLLADASW::EffectProfile::LAMBERT);
|
||||
ep.setShaderType(COLLADASW::EffectProfile::LAMBERT); //XXX check if BLINN and PHONG can be supported as well
|
||||
}
|
||||
|
||||
void EffectsExporter::set_transparency(COLLADASW::EffectProfile &ep, Material *ma)
|
||||
{
|
||||
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::set_specular_color(COLLADASW::EffectProfile &ep, Material *ma)
|
||||
{
|
||||
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::set_emission(COLLADASW::EffectProfile &ep, Material *ma)
|
||||
{
|
||||
// not yet supported (needs changes in principled shader
|
||||
}
|
||||
|
||||
void EffectsExporter::get_images(Material *ma, KeyImageMap &material_image_map)
|
||||
{
|
||||
if (!ma->use_nodes) {
|
||||
return;
|
||||
}
|
||||
|
||||
MaterialNode material = MaterialNode(mContext, ma, key_image_map);
|
||||
Image *image = material.get_diffuse_image();
|
||||
if (image == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
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::create_image_samplers(COLLADASW::EffectProfile &ep, KeyImageMap &material_image_map, std::string &active_uv)
|
||||
{
|
||||
KeyImageMap::iterator iter;
|
||||
|
||||
for (iter = material_image_map.begin(); iter != material_image_map.end(); iter++) {
|
||||
|
||||
Image *image = iter->second;
|
||||
std::string uid(id_name(image));
|
||||
std::string key = translate_id(uid);
|
||||
|
||||
COLLADASW::Sampler *sampler = new COLLADASW::Sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
|
||||
key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
|
||||
key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
|
||||
|
||||
sampler->setImageId(key);
|
||||
|
||||
ep.setDiffuse(createTexture(image, active_uv, sampler), false, "diffuse");
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsExporter::operator()(Material *ma, Object *ob)
|
||||
{
|
||||
// TODO: add back texture and extended material parameter support
|
||||
KeyImageMap material_image_map;
|
||||
|
||||
openEffect(translate_id(id_name(ma)) + "-effect");
|
||||
openEffect(get_effect_id(ma));
|
||||
|
||||
COLLADASW::EffectProfile ep(mSW);
|
||||
ep.setProfileType(COLLADASW::EffectProfile::COMMON);
|
||||
ep.openProfile();
|
||||
writeLambert(ep, ma);
|
||||
set_shader_type(ep, ma);
|
||||
|
||||
COLLADASW::ColorOrTexture cot;
|
||||
|
||||
// transparency
|
||||
if (ma->alpha != 1.0f) {
|
||||
// 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);
|
||||
}
|
||||
set_transparency(ep, ma);
|
||||
set_diffuse_color(ep, ma);
|
||||
set_specular_color(ep, ma);
|
||||
set_emission(ep, ma);
|
||||
|
||||
// emission
|
||||
#if 0
|
||||
cot = getcol(ma->emit, ma->emit, ma->emit, 1.0f);
|
||||
#endif
|
||||
|
||||
// diffuse
|
||||
cot = getcol(ma->r, ma->g, ma->b, 1.0f);
|
||||
ep.setDiffuse(cot, false, "diffuse");
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
// XXX make this more readable if possible
|
||||
get_images(ma, material_image_map);
|
||||
std::string active_uv(getActiveUVLayerName(ob));
|
||||
create_image_samplers(ep, material_image_map, active_uv);
|
||||
|
||||
#if 0
|
||||
// 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];
|
||||
|
||||
// image to index to samp_surf map
|
||||
// samp_surf[index] stores 2 pointers, sampler and surface
|
||||
std::map<std::string, int> im_samp_map;
|
||||
|
||||
unsigned int a, b;
|
||||
for (a = 0, b = 0; a < tex_indices.size(); a++) {
|
||||
MTex *t = ma->mtex[tex_indices[a]];
|
||||
@@ -162,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];
|
||||
@@ -189,15 +226,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
|
||||
b++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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(getActiveUVLayerName(ob));
|
||||
|
||||
// write textures
|
||||
// XXX very slow
|
||||
#if 0
|
||||
for (a = 0; a < tex_indices.size(); a++) {
|
||||
MTex *t = ma->mtex[tex_indices[a]];
|
||||
Image *ima = t->tex->ima;
|
||||
@@ -210,7 +239,7 @@ 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
|
||||
|
@@ -42,12 +42,13 @@
|
||||
#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);
|
||||
|
||||
@@ -58,7 +59,14 @@ public:
|
||||
|
||||
COLLADASW::ColorOrTexture getcol(float r, float g, float b, float a);
|
||||
private:
|
||||
void writeLambert(COLLADASW::EffectProfile &ep, Material *ma);
|
||||
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 writeTextures(COLLADASW::EffectProfile &ep,
|
||||
std::string &key,
|
||||
COLLADASW::Sampler *sampler,
|
||||
@@ -68,8 +76,9 @@ private:
|
||||
bool hasEffects(Scene *sce);
|
||||
|
||||
const ExportSettings *export_settings;
|
||||
|
||||
KeyImageMap &key_image_map;
|
||||
Scene *scene;
|
||||
bContext *mContext;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -49,47 +49,66 @@ 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() != COLLADASaxFWL::IError::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;
|
||||
}
|
||||
|
@@ -44,6 +44,19 @@ typedef enum BC_export_transformation_type {
|
||||
} BC_export_transformation_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;
|
||||
BC_export_mesh_type export_mesh_type;
|
||||
@@ -54,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;
|
||||
bool include_material_textures;
|
||||
BC_export_animation_type export_animation_type;
|
||||
bool use_texture_copies;
|
||||
|
||||
bool triangulate;
|
||||
|
@@ -51,17 +51,17 @@ 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)
|
||||
GeometryExporter::GeometryExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) :
|
||||
blender_context(blender_context),
|
||||
COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
|
||||
{
|
||||
}
|
||||
|
||||
void GeometryExporter::exportGeom(Main *bmain, struct Depsgraph *depsgraph, Scene *sce)
|
||||
void GeometryExporter::exportGeom()
|
||||
{
|
||||
Scene *sce = blender_context.get_scene();
|
||||
openLibrary();
|
||||
|
||||
mDepsgraph = depsgraph;
|
||||
m_bmain = bmain;
|
||||
mScene = sce;
|
||||
GeometryFunctor gf;
|
||||
gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set);
|
||||
|
||||
@@ -72,8 +72,7 @@ void GeometryExporter::operator()(Object *ob)
|
||||
{
|
||||
bool use_instantiation = this->export_settings->use_object_instantiation;
|
||||
Mesh *me = bc_get_mesh_copy(
|
||||
mDepsgraph,
|
||||
mScene,
|
||||
blender_context,
|
||||
ob,
|
||||
this->export_settings->export_mesh_type,
|
||||
this->export_settings->apply_modifiers,
|
||||
@@ -91,6 +90,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);
|
||||
|
||||
|
@@ -43,7 +43,7 @@
|
||||
|
||||
#include "ExportSettings.h"
|
||||
#include "collada_utils.h"
|
||||
|
||||
#include "BlenderContext.h"
|
||||
#include "BKE_key.h"
|
||||
|
||||
struct Depsgraph;
|
||||
@@ -74,14 +74,10 @@ class GeometryExporter : COLLADASW::LibraryGeometries
|
||||
|
||||
Normal n;
|
||||
|
||||
struct Depsgraph *mDepsgraph;
|
||||
Main *m_bmain;
|
||||
Scene *mScene;
|
||||
|
||||
public:
|
||||
GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
|
||||
GeometryExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
|
||||
|
||||
void exportGeom(Main *bmain, Depsgraph *depsgraph, Scene *sce);
|
||||
void exportGeom();
|
||||
|
||||
void operator()(Object *ob);
|
||||
|
||||
@@ -125,7 +121,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);
|
||||
|
@@ -51,7 +51,10 @@ 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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -59,135 +62,110 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
|
||||
{
|
||||
std::string name(id_name(image));
|
||||
std::string translated_name(translate_id(name));
|
||||
bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end();
|
||||
|
||||
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);
|
||||
bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0;
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
|
||||
if (is_generated || is_dirty || use_copies || is_packed) {
|
||||
|
||||
// make absolute destination path
|
||||
|
||||
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);
|
||||
|
||||
// make dest directory if it doesn't exist
|
||||
BLI_make_existing_file(export_path);
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
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));
|
||||
}
|
||||
else {
|
||||
|
||||
bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0;
|
||||
// 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);
|
||||
|
||||
ImageFormatData imageFormat;
|
||||
BKE_imbuf_to_image_format(&imageFormat, imbuf);
|
||||
if (use_copies) {
|
||||
|
||||
short image_source = image->source;
|
||||
bool is_generated = image_source == IMA_SRC_GENERATED;
|
||||
bool is_packed = BKE_image_has_packedfile(image);
|
||||
// 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).
|
||||
|
||||
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));
|
||||
|
||||
if (is_generated || is_dirty || use_copies || is_packed) {
|
||||
|
||||
// make absolute destination path
|
||||
|
||||
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);
|
||||
|
||||
// make dest directory if it doesn't exist
|
||||
BLI_make_existing_file(export_path);
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
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;
|
||||
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 {
|
||||
|
||||
// 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);
|
||||
// Do not make any copies, but use the source path directly as reference
|
||||
// to the original image
|
||||
|
||||
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).
|
||||
|
||||
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, source_path, sizeof(export_path));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
mImages.push_back(translated_name);
|
||||
|
||||
BKE_image_release_ibuf(image, imbuf, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
// TODO: find image textures in shader nodes
|
||||
BLI_strncpy(export_path, source_path, sizeof(export_path));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
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);
|
||||
|
||||
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->include_material_textures) {
|
||||
mf.forEachMaterialInExportSet<ImagesExporter>(sce, *this, this->export_settings->export_set);
|
||||
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);
|
||||
|
||||
export_UV_Image(image, use_texture_copies);
|
||||
}
|
||||
|
||||
closeLibrary();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ImagesExporter::operator()(Material *ma, Object *ob)
|
||||
{
|
||||
// bool use_texture_copies = this->export_settings->use_texture_copies;
|
||||
// TODO call export_UV_Image for every image in shader nodes
|
||||
}
|
||||
|
@@ -40,20 +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_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
|
||||
|
@@ -89,15 +89,7 @@ void LightsExporter::operator()(Object *ob)
|
||||
exportBlenderProfile(cla, la);
|
||||
addLight(cla);
|
||||
}
|
||||
// hemi
|
||||
/* Hemi were removed from 2.8 */
|
||||
// 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);
|
||||
|
@@ -68,12 +68,12 @@ bool MaterialsExporter::hasMaterials(Scene *sce)
|
||||
|
||||
void MaterialsExporter::operator()(Material *ma, Object *ob)
|
||||
{
|
||||
std::string name(id_name(ma));
|
||||
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);
|
||||
|
||||
openMaterial(get_material_id(ma), translate_id(name));
|
||||
|
||||
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();
|
||||
}
|
||||
|
@@ -44,6 +44,7 @@ extern "C" {
|
||||
#include "GeometryExporter.h"
|
||||
#include "collada_internal.h"
|
||||
#include "ExportSettings.h"
|
||||
#include "materials.h"
|
||||
|
||||
class MaterialsExporter: COLLADASW::LibraryMaterials
|
||||
{
|
||||
|
329
source/blender/collada/Materials.cpp
Normal file
329
source/blender/collada/Materials.cpp
Normal file
@@ -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),
|
||||
effect(nullptr),
|
||||
material(ma),
|
||||
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),
|
||||
effect(ef),
|
||||
material(ma),
|
||||
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;
|
||||
|
||||
}
|
83
source/blender/collada/Materials.h
Normal file
83
source/blender/collada/Materials.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* ***** 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
|
@@ -599,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) {
|
||||
|
@@ -34,22 +34,25 @@ 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)
|
||||
SceneExporter::SceneExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings):
|
||||
blender_context(blender_context),
|
||||
COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings)
|
||||
{
|
||||
}
|
||||
|
||||
void SceneExporter::exportScene(bContext *C, Depsgraph *depsgraph, Scene *sce)
|
||||
void SceneExporter::exportScene()
|
||||
{
|
||||
ViewLayer *view_layer = blender_context.get_view_layer();
|
||||
|
||||
// <library_visual_scenes> <visual_scene>
|
||||
std::string id_naming = id_name(sce);
|
||||
openVisualScene(translate_id(id_naming), id_naming);
|
||||
exportHierarchy(C, depsgraph, sce);
|
||||
std::string name = id_name(view_layer);
|
||||
openVisualScene(translate_id(name), encode_xml(name));
|
||||
exportHierarchy();
|
||||
closeVisualScene();
|
||||
closeLibrary();
|
||||
}
|
||||
|
||||
void SceneExporter::exportHierarchy(bContext *C, Depsgraph *depsgraph, Scene *sce)
|
||||
void SceneExporter::exportHierarchy()
|
||||
{
|
||||
LinkNode *node;
|
||||
std::vector<Object *> base_objects;
|
||||
@@ -82,164 +85,157 @@ void SceneExporter::exportHierarchy(bContext *C, Depsgraph *depsgraph, Scene *sc
|
||||
Object *ob = base_objects[index];
|
||||
if (bc_is_marked(ob)) {
|
||||
bc_remove_mark(ob);
|
||||
writeNodes(C, depsgraph, ob, sce);
|
||||
writeNodes(ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SceneExporter::writeNodes(bContext *C, Depsgraph *depsgraph, Object *ob, Scene *sce)
|
||||
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(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, depsgraph, 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;
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 (cob->parent == ob) {
|
||||
switch (cob->type) {
|
||||
case OB_MESH:
|
||||
case OB_CAMERA:
|
||||
case OB_LAMP:
|
||||
case OB_EMPTY:
|
||||
case OB_GPENCIL:
|
||||
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);
|
||||
|
||||
instGeom.add();
|
||||
// <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_controller>
|
||||
else if (ob->type == OB_ARMATURE) {
|
||||
arm_exporter->add_armature_bones(C, depsgraph, 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_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);
|
||||
}
|
||||
FOREACH_COLLECTION_OBJECT_RECURSIVE_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 (ob->type == OB_ARMATURE) {
|
||||
colladaNode.end();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
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, depsgraph, *i, sce);
|
||||
}
|
||||
}
|
||||
//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) {
|
||||
|
||||
if (ob->type != OB_ARMATURE)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
writeNodeList(child_objects, ob);
|
||||
colladaNode.end();
|
||||
}
|
||||
}
|
||||
|
@@ -94,13 +94,15 @@ 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, Depsgraph *depsgraph, Scene *sce);
|
||||
SceneExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings);
|
||||
void exportScene();
|
||||
|
||||
private:
|
||||
friend class ArmatureExporter;
|
||||
void exportHierarchy(bContext *C, struct Depsgraph *depsgraph, Scene *sce);
|
||||
void writeNodes(bContext *C, struct Depsgraph *depsgraph, Object *ob, Scene *sce);
|
||||
BlenderContext &blender_context;
|
||||
void exportHierarchy();
|
||||
void writeNodeList(std::vector<Object *> &child_objects, Object *parent);
|
||||
void writeNodes(Object *ob);
|
||||
|
||||
ArmatureExporter *arm_exporter;
|
||||
const ExportSettings *export_settings;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -45,23 +45,51 @@ extern "C"
|
||||
#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,
|
||||
Depsgraph *depsgraph,
|
||||
Scene *sce,
|
||||
ExportSettings *export_settings)
|
||||
{
|
||||
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
||||
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(view_layer, objectSet, (eObRelationTypes)includeFilter);
|
||||
|
||||
@@ -80,8 +108,8 @@ int collada_export(bContext *C,
|
||||
bc_bubble_sort_by_Object_name(export_settings->export_set);
|
||||
}
|
||||
|
||||
DocumentExporter exporter(depsgraph, export_settings);
|
||||
int status = exporter.exportCurrentScene(C, sce);
|
||||
DocumentExporter exporter(blender_context, export_settings);
|
||||
int status = exporter.exportCurrentScene();
|
||||
|
||||
BLI_linklist_free(export_settings->export_set, NULL);
|
||||
|
||||
|
@@ -52,8 +52,6 @@ int collada_import(struct bContext *C,
|
||||
ImportSettings *import_settings);
|
||||
|
||||
int collada_export(struct bContext *C,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *sce,
|
||||
ExportSettings *export_settings);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -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 {
|
||||
{'<' , "<" },
|
||||
{'>' , ">" },
|
||||
{'"' , """},
|
||||
{'\'', "'"},
|
||||
{'&' , "&" }
|
||||
};
|
||||
|
||||
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,21 +355,25 @@ std::string get_light_id(Object *ob)
|
||||
return translate_id(id_name(ob)) + "-light";
|
||||
}
|
||||
|
||||
std::string get_joint_id(Object *ob, Bone *bone)
|
||||
{
|
||||
return translate_id(id_name(ob) + "_" + bone->name);
|
||||
}
|
||||
|
||||
std::string get_joint_sid(Bone *bone)
|
||||
{
|
||||
return translate_id(bone->name);
|
||||
}
|
||||
std::string get_joint_sid(EditBone *bone)
|
||||
{
|
||||
return translate_id(bone->name);
|
||||
}
|
||||
|
||||
std::string get_camera_id(Object *ob)
|
||||
{
|
||||
return translate_id(id_name(ob)) + "-camera";
|
||||
}
|
||||
|
||||
std::string get_effect_id(Material *mat)
|
||||
{
|
||||
return translate_id(id_name(mat)) + "-effect";
|
||||
}
|
||||
|
||||
std::string get_material_id(Material *mat)
|
||||
{
|
||||
return translate_id(id_name(mat)) + "-material";
|
||||
|
@@ -91,19 +91,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_material_id(Material *mat);
|
||||
|
||||
extern std::string get_morph_id(Object *ob);
|
||||
|
||||
extern std::string get_effect_id(Material *mat);
|
||||
extern std::string get_material_id(Material *mat);
|
||||
|
||||
#endif /* __COLLADA_INTERNAL_H__ */
|
||||
|
@@ -33,20 +33,29 @@
|
||||
#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_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"
|
||||
@@ -56,19 +65,27 @@ extern "C" {
|
||||
#include "BKE_scene.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)
|
||||
{
|
||||
@@ -92,6 +109,47 @@ 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)
|
||||
@@ -131,15 +189,52 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
|
||||
return true;
|
||||
}
|
||||
|
||||
Scene *bc_get_scene(bContext *C)
|
||||
std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions)
|
||||
{
|
||||
return CTX_data_scene(C);
|
||||
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, Depsgraph *depsgraph, 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);
|
||||
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
|
||||
ED_update_for_newframe(bmain, depsgraph);
|
||||
}
|
||||
|
||||
Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
|
||||
@@ -161,7 +256,11 @@ Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type
|
||||
}
|
||||
|
||||
Mesh *bc_get_mesh_copy(
|
||||
Depsgraph *depsgraph, 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)
|
||||
{
|
||||
CustomDataMask mask = CD_MASK_MESH;
|
||||
Mesh *mesh = (Mesh *)ob->data;
|
||||
@@ -181,6 +280,8 @@ Mesh *bc_get_mesh_copy(
|
||||
}
|
||||
}
|
||||
#else
|
||||
Depsgraph *depsgraph = blender_context.get_depsgraph();
|
||||
Scene *scene = blender_context.get_scene();
|
||||
tmpmesh = mesh_get_eval_final(depsgraph, scene, ob, mask);
|
||||
#endif
|
||||
}
|
||||
@@ -221,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)) {
|
||||
@@ -236,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)
|
||||
@@ -819,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.
|
||||
@@ -883,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)
|
||||
@@ -906,7 +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];
|
||||
}
|
||||
|
||||
void bc_copy_v44_m4d(std::vector<std::vector<double>> &r, double(&a)[4][4])
|
||||
{
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -948,3 +1220,203 @@ std::string bc_get_uvlayer_name(Mesh *me, int layer)
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static bNodeTree *prepare_material_nodetree(Material *ma)
|
||||
{
|
||||
if (ma->nodetree == NULL) {
|
||||
ma->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree");
|
||||
ma->use_nodes = true;
|
||||
}
|
||||
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());
|
||||
}
|
||||
node->locx = locx;
|
||||
node->locy = locy;
|
||||
node->flag |= NODE_SELECT;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy)
|
||||
{
|
||||
return bc_add_node(C, ntree, node_type, locx, locy, "");
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
//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 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;
|
||||
}
|
||||
|
@@ -31,14 +31,23 @@
|
||||
#include "COLLADAFWGeometry.h"
|
||||
#include "COLLADAFWFloatOrDoubleArray.h"
|
||||
#include "COLLADAFWTypes.h"
|
||||
#include "COLLADASWEffectProfile.h"
|
||||
#include "COLLADAFWColorOrTexture.h"
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
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"
|
||||
@@ -49,35 +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_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 Scene *bc_get_scene(bContext *C);
|
||||
extern Depsgraph *bc_get_depsgraph();
|
||||
extern void bc_update_scene(Main *bmain, Depsgraph *depsgraph, 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, ViewLayer *view_layer, int type, const char *name);
|
||||
extern Mesh *bc_get_mesh_copy(
|
||||
Depsgraph *depsgraph, 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);
|
||||
@@ -91,8 +160,32 @@ 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);
|
||||
|
||||
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);
|
||||
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);
|
||||
extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene);
|
||||
|
||||
@@ -110,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);
|
||||
@@ -122,6 +218,13 @@ 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_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 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
|
||||
@@ -203,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
|
||||
|
@@ -94,10 +94,13 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
||||
int deform_bones_only;
|
||||
|
||||
int include_animations;
|
||||
int sample_animations;
|
||||
int include_all_actions;
|
||||
int sampling_rate;
|
||||
int keep_smooth_curves;
|
||||
int keep_keyframes;
|
||||
|
||||
int include_material_textures;
|
||||
int export_animation_type;
|
||||
int use_texture_copies;
|
||||
int active_uv_only;
|
||||
|
||||
@@ -112,6 +115,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
||||
int keep_bind_info;
|
||||
|
||||
int export_count;
|
||||
int sample_animations;
|
||||
|
||||
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No filename given");
|
||||
@@ -148,8 +152,12 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
||||
include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
|
||||
|
||||
include_animations = RNA_boolean_get(op->ptr, "include_animations");
|
||||
sample_animations = RNA_boolean_get(op->ptr, "sample_animations");
|
||||
sampling_rate = (sample_animations) ? RNA_int_get(op->ptr, "sampling_rate") : 0;
|
||||
include_all_actions = RNA_boolean_get(op->ptr, "include_all_actions");
|
||||
export_animation_type = RNA_enum_get(op->ptr, "export_animation_type_selection");
|
||||
sample_animations = (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES);
|
||||
sampling_rate = (sample_animations)? RNA_int_get(op->ptr, "sampling_rate") : 0;
|
||||
keep_smooth_curves = RNA_boolean_get(op->ptr, "keep_smooth_curves");
|
||||
keep_keyframes = RNA_boolean_get(op->ptr, "keep_keyframes");
|
||||
|
||||
deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
|
||||
|
||||
@@ -172,7 +180,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
||||
/* get editmode results */
|
||||
ED_object_editmode_load(bmain, CTX_data_edit_object(C));
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
//Scene *scene = CTX_data_scene(C);
|
||||
|
||||
ExportSettings export_settings;
|
||||
|
||||
@@ -185,18 +193,36 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
||||
export_settings.include_armatures = include_armatures != 0;
|
||||
export_settings.include_shapekeys = include_shapekeys != 0;
|
||||
export_settings.deform_bones_only = deform_bones_only != 0;
|
||||
export_settings.include_animations = include_animations;
|
||||
export_settings.include_animations = include_animations != 0;
|
||||
export_settings.include_all_actions = include_all_actions != 0;
|
||||
export_settings.sampling_rate = sampling_rate;
|
||||
export_settings.keep_keyframes = keep_keyframes != 0 || sampling_rate < 1;
|
||||
|
||||
export_settings.active_uv_only = active_uv_only != 0;
|
||||
export_settings.include_material_textures = include_material_textures != 0;
|
||||
export_settings.export_animation_type = export_animation_type;
|
||||
export_settings.use_texture_copies = use_texture_copies != 0;
|
||||
|
||||
export_settings.triangulate = triangulate != 0;
|
||||
export_settings.use_object_instantiation = use_object_instantiation != 0;
|
||||
export_settings.use_blender_profile = use_blender_profile != 0;
|
||||
export_settings.sort_by_name = sort_by_name != 0;
|
||||
export_settings.export_transformation_type = export_transformation_type;
|
||||
|
||||
if (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES) {
|
||||
export_settings.export_transformation_type = export_transformation_type;
|
||||
}
|
||||
else {
|
||||
// When curves are exported then we can not export as matrix
|
||||
export_settings.export_transformation_type = BC_TRANSFORMATION_TYPE_TRANSROTLOC;
|
||||
}
|
||||
|
||||
if (export_settings.export_transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC) {
|
||||
export_settings.keep_smooth_curves = keep_smooth_curves != 0;
|
||||
}
|
||||
else {
|
||||
// Can not export smooth curves when Matrix export is enabled.
|
||||
export_settings.keep_smooth_curves = false;
|
||||
}
|
||||
|
||||
export_settings.open_sim = open_sim != 0;
|
||||
export_settings.limit_precision = limit_precision != 0;
|
||||
export_settings.keep_bind_info = keep_bind_info != 0;
|
||||
@@ -207,8 +233,6 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
||||
|
||||
export_count = collada_export(
|
||||
C,
|
||||
CTX_data_depsgraph(C),
|
||||
scene,
|
||||
&export_settings
|
||||
);
|
||||
|
||||
@@ -232,96 +256,134 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
|
||||
{
|
||||
uiLayout *box, *row, *col, *split;
|
||||
bool include_animations = RNA_boolean_get(imfptr, "include_animations");
|
||||
int ui_section = RNA_enum_get(imfptr, "prop_bc_export_ui_section");
|
||||
|
||||
BC_export_animation_type animation_type = RNA_enum_get(imfptr, "export_animation_type_selection");
|
||||
BC_export_transformation_type transformation_type = RNA_enum_get(imfptr, "export_transformation_type_selection");
|
||||
|
||||
bool sampling = animation_type == BC_ANIMATION_EXPORT_SAMPLES;
|
||||
|
||||
/* Export Options: */
|
||||
box = uiLayoutBox(layout);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemL(row, IFACE_("Export Data Options:"), ICON_MESH_DATA);
|
||||
uiItemR(row, imfptr, "prop_bc_export_ui_section", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
|
||||
col = uiLayoutColumn(split, false);
|
||||
uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE);
|
||||
col = uiLayoutColumn(split, false);
|
||||
uiItemR(col, imfptr, "export_mesh_type_selection", 0, "", ICON_NONE);
|
||||
uiLayoutSetEnabled(col, RNA_boolean_get(imfptr, "apply_modifiers"));
|
||||
if (ui_section == BC_UI_SECTION_MAIN) {
|
||||
/* =================== */
|
||||
/* Export Data options */
|
||||
/* =================== */
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
|
||||
|
||||
/* Texture options */
|
||||
box = uiLayoutBox(layout);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemL(row, IFACE_("Texture Options:"), ICON_TEXTURE_DATA);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
|
||||
|
||||
}
|
||||
else if (ui_section == BC_UI_SECTION_GEOMETRY) {
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemL(row, IFACE_("Export Data Options:"), ICON_MESH_DATA);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
|
||||
col = uiLayoutColumn(split, false);
|
||||
uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE);
|
||||
col = uiLayoutColumn(split, false);
|
||||
uiItemR(col, imfptr, "export_mesh_type_selection", 0, "", ICON_NONE);
|
||||
uiLayoutSetEnabled(col, RNA_boolean_get(imfptr, "apply_modifiers"));
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE);
|
||||
}
|
||||
else if (ui_section == BC_UI_SECTION_ARMATURE) {
|
||||
/* Armature options */
|
||||
box = uiLayoutBox(layout);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemL(row, IFACE_("Armature Options:"), ICON_ARMATURE_DATA);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
|
||||
}
|
||||
else if (ui_section == BC_UI_SECTION_ANIMATION) {
|
||||
|
||||
/* ====================== */
|
||||
/* Animation Data options */
|
||||
/* ====================== */
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_animations", 0, NULL, ICON_NONE);
|
||||
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "export_animation_type_selection", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
|
||||
uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
|
||||
uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
|
||||
uiLayoutSetEnabled(row, animation_type == BC_ANIMATION_EXPORT_SAMPLES);
|
||||
|
||||
row = uiLayoutColumn(box, false);
|
||||
uiItemR(row, imfptr, "keep_smooth_curves", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, include_animations &&
|
||||
(transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC || animation_type == BC_ANIMATION_EXPORT_KEYS));
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_animations", 0, NULL, ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
if (include_animations) {
|
||||
uiItemR(row, imfptr, "sample_animations", 0, NULL, ICON_NONE);
|
||||
row = uiLayoutColumn(box, false);
|
||||
uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "sample_animations"));
|
||||
uiLayoutSetEnabled(row, sampling && include_animations);
|
||||
|
||||
row = uiLayoutColumn(box, false);
|
||||
uiItemR(row, imfptr, "keep_keyframes", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, sampling && include_animations);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_all_actions", 0, NULL, ICON_NONE);
|
||||
uiLayoutSetEnabled(row, include_animations);
|
||||
|
||||
}
|
||||
else if (ui_section == BC_UI_SECTION_COLLADA) {
|
||||
/* Collada options: */
|
||||
box = uiLayoutBox(layout);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER);
|
||||
|
||||
/* Texture options */
|
||||
box = uiLayoutBox(layout);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemL(row, IFACE_("Texture Options:"), ICON_TEXTURE_DATA);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "use_object_instantiation", 1, NULL, ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "use_blender_profile", 1, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "include_material_textures", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
|
||||
|
||||
|
||||
/* Armature options */
|
||||
box = uiLayoutBox(layout);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemL(row, IFACE_("Armature Options:"), ICON_ARMATURE_DATA);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
|
||||
|
||||
/* Collada options: */
|
||||
box = uiLayoutBox(layout);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "use_object_instantiation", 1, NULL, ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "use_blender_profile", 1, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
|
||||
uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
|
||||
uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "limit_precision", 0, NULL, ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "limit_precision", 0, NULL, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_collada_export_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
@@ -357,11 +419,27 @@ void WM_OT_collada_export(wmOperatorType *ot)
|
||||
};
|
||||
|
||||
static const EnumPropertyItem prop_bc_export_transformation_type[] = {
|
||||
{BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"},
|
||||
{BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
{ BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" },
|
||||
{ BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" },
|
||||
{ 0, NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const EnumPropertyItem prop_bc_export_animation_type[] = {
|
||||
{ BC_ANIMATION_EXPORT_SAMPLES, "sample", 0, "Samples", "Export Sampled points guided by sampling rate" },
|
||||
{ BC_ANIMATION_EXPORT_KEYS, "keys", 0, "Curves", "Export Curves\n Note: guided by curve keys" },
|
||||
{ 0, NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const EnumPropertyItem prop_bc_export_ui_section[] = {
|
||||
{ BC_UI_SECTION_MAIN, "main", 0, "Main", "Data Export Section" },
|
||||
{ BC_UI_SECTION_GEOMETRY, "geometry", 0, "Geom", "Geometry Export Section" },
|
||||
{ BC_UI_SECTION_ARMATURE, "armature", 0, "Arm", "Armature Export Section" },
|
||||
{ BC_UI_SECTION_ANIMATION, "animation", 0, "Anim", "Animation Export Section" },
|
||||
{ BC_UI_SECTION_COLLADA, "collada", 0, "Extra", "Collada Export Section" },
|
||||
{ 0, NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
ot->name = "Export COLLADA";
|
||||
ot->description = "Save a Collada file";
|
||||
ot->idname = "WM_OT_collada_export";
|
||||
@@ -379,6 +457,9 @@ void WM_OT_collada_export(wmOperatorType *ot)
|
||||
ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_SAVE,
|
||||
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
|
||||
|
||||
RNA_def_enum(func, "prop_bc_export_ui_section", prop_bc_export_ui_section, 0,
|
||||
"Export Section", "Only for User Interface Organisation");
|
||||
|
||||
RNA_def_boolean(func,
|
||||
"apply_modifiers", 0, "Apply Modifiers",
|
||||
"Apply modifiers to exported mesh (non destructive))");
|
||||
@@ -404,15 +485,25 @@ void WM_OT_collada_export(wmOperatorType *ot)
|
||||
RNA_def_boolean(func, "deform_bones_only", false, "Deform Bones only",
|
||||
"Only export deforming bones with armatures");
|
||||
|
||||
|
||||
|
||||
RNA_def_boolean(func, "include_animations", true,
|
||||
"Include Animations", "Export Animations if available.\nExporting Animations will enforce the decomposition of node transforms\ninto <translation> <rotation> and <scale> components");
|
||||
|
||||
RNA_def_boolean(func, "sample_animations", 0,
|
||||
"Sample Animations", "Auto-generate keyframes with a frame distance set by 'Sampling Rate'.\nWhen disabled, export only the keyframes defined in the animation f-curves (may be less accurate)");
|
||||
RNA_def_boolean(func, "include_all_actions", true,
|
||||
"Include all Actions", "Export also unassigned actions.\nThis allows you to export entire animation libraries for your charater(s)");
|
||||
|
||||
RNA_def_enum(func, "export_animation_type_selection", prop_bc_export_animation_type, 0,
|
||||
"Key Type", "Type for exported animations (use sample keys or Curve keys)");
|
||||
|
||||
RNA_def_int(func, "sampling_rate", 1, 1, INT_MAX,
|
||||
"Sampling Rate", "The distance between 2 keyframes. 1 means: Every frame is keyed", 1, INT_MAX);
|
||||
|
||||
RNA_def_boolean(func, "keep_smooth_curves", 0,
|
||||
"Keep Smooth curves", "Export also the curve handles (if available).\nThis does only work when the inverse parent matrix is the Unity matrix\nOtherwise you may end up with odd results\n");
|
||||
|
||||
RNA_def_boolean(func, "keep_keyframes", 0,
|
||||
"Keep Keyframes", "Use existing keyframes as additional sample points.\nThis helps when you want to keep manual tweeks");
|
||||
|
||||
RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
|
||||
"Export only the selected UV Map");
|
||||
@@ -497,7 +588,7 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports, RPT_ERROR, "Errors found during parsing COLLADA document (see console for details)");
|
||||
BKE_report(op->reports, RPT_ERROR, "Parsing errors in Document (see Blender Console)");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user