You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-10 13:00:37 +00:00
-Rasterizer supports meshes with both skeletons and blend shapes
-Collada exporter supports Blend Shapes (even on actions via set driven keys)
This commit is contained in:
@@ -555,6 +555,42 @@ String String::get_slice(String p_splitter, int p_slice) const {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Vector<String> String::split_spaces() const {
|
||||||
|
|
||||||
|
Vector<String> ret;
|
||||||
|
int from=0;
|
||||||
|
int i=0;
|
||||||
|
int len = length();
|
||||||
|
bool inside=false;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
|
||||||
|
bool empty=operator[](i)<33;
|
||||||
|
|
||||||
|
if (i==0)
|
||||||
|
inside=!empty;
|
||||||
|
|
||||||
|
if (!empty && !inside) {
|
||||||
|
inside=true;
|
||||||
|
from=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty && inside) {
|
||||||
|
|
||||||
|
ret.push_back(substr(from,i-from));
|
||||||
|
inside=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i==len)
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Vector<String> String::split(const String &p_splitter,bool p_allow_empty) const {
|
Vector<String> String::split(const String &p_splitter,bool p_allow_empty) const {
|
||||||
|
|
||||||
Vector<String> ret;
|
Vector<String> ret;
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ public:
|
|||||||
String get_slice(String p_splitter,int p_slice) const;
|
String get_slice(String p_splitter,int p_slice) const;
|
||||||
|
|
||||||
Vector<String> split(const String &p_splitter,bool p_allow_empty=true) const;
|
Vector<String> split(const String &p_splitter,bool p_allow_empty=true) const;
|
||||||
|
Vector<String> split_spaces() const;
|
||||||
Vector<float> split_floats(const String &p_splitter,bool p_allow_empty=true) const;
|
Vector<float> split_floats(const String &p_splitter,bool p_allow_empty=true) const;
|
||||||
Vector<float> split_floats_mk(const Vector<String> &p_splitters,bool p_allow_empty=true) const;
|
Vector<float> split_floats_mk(const Vector<String> &p_splitters,bool p_allow_empty=true) const;
|
||||||
Vector<int> split_ints(const String &p_splitter,bool p_allow_empty=true) const;
|
Vector<int> split_ints(const String &p_splitter,bool p_allow_empty=true) const;
|
||||||
|
|||||||
@@ -5011,7 +5011,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<bool USE_NORMAL, bool USE_TANGENT>
|
template<bool USE_NORMAL, bool USE_TANGENT,bool INPLACE>
|
||||||
void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms) {
|
void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms) {
|
||||||
|
|
||||||
uint32_t basesize = 3;
|
uint32_t basesize = 3;
|
||||||
@@ -5021,6 +5021,8 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str
|
|||||||
basesize+=4;
|
basesize+=4;
|
||||||
|
|
||||||
uint32_t extra=(p_dst_stride-basesize*4);
|
uint32_t extra=(p_dst_stride-basesize*4);
|
||||||
|
const int dstvec_size=3+(USE_NORMAL?3:0)+(USE_TANGENT?4:0);
|
||||||
|
float dstcopy[dstvec_size];
|
||||||
|
|
||||||
for(int i=0;i<p_elements;i++) {
|
for(int i=0;i<p_elements;i++) {
|
||||||
|
|
||||||
@@ -5029,7 +5031,11 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str
|
|||||||
const uint16_t *bi = (const uint16_t*)&p_src_bones[ss];
|
const uint16_t *bi = (const uint16_t*)&p_src_bones[ss];
|
||||||
const float *bw = (const float *)&p_src_weights[ss];
|
const float *bw = (const float *)&p_src_weights[ss];
|
||||||
const float *src_vec=(const float *)&p_src_array[ss];
|
const float *src_vec=(const float *)&p_src_array[ss];
|
||||||
float *dst_vec=(float*)&p_dst_array[ds];
|
float *dst_vec;
|
||||||
|
if (INPLACE)
|
||||||
|
dst_vec=dstcopy;
|
||||||
|
else
|
||||||
|
dst_vec=(float*)&p_dst_array[ds];
|
||||||
|
|
||||||
dst_vec[0]=0.0;
|
dst_vec[0]=0.0;
|
||||||
dst_vec[1]=0.0;
|
dst_vec[1]=0.0;
|
||||||
@@ -5082,6 +5088,18 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str
|
|||||||
|
|
||||||
end:
|
end:
|
||||||
|
|
||||||
|
if (INPLACE) {
|
||||||
|
|
||||||
|
const uint8_t *esp =(const uint8_t*) dstcopy;
|
||||||
|
uint8_t *edp =(uint8_t*)&p_dst_array[ds];
|
||||||
|
|
||||||
|
|
||||||
|
for(uint32_t j=0;j<dstvec_size*4;j++) {
|
||||||
|
|
||||||
|
edp[j]=esp[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
//copy extra stuff
|
//copy extra stuff
|
||||||
const uint8_t *esp =(const uint8_t*) &src_vec[basesize];
|
const uint8_t *esp =(const uint8_t*) &src_vec[basesize];
|
||||||
uint8_t *edp =(uint8_t*) &dst_vec[basesize];
|
uint8_t *edp =(uint8_t*) &dst_vec[basesize];
|
||||||
@@ -5091,7 +5109,7 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str
|
|||||||
|
|
||||||
edp[j]=esp[j];
|
edp[j]=esp[j];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5166,6 +5184,8 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t coeffp = CLAMP(coef*255,0,255);
|
||||||
|
|
||||||
|
|
||||||
for(int i=0;i<VS::ARRAY_MAX-1;i++) {
|
for(int i=0;i<VS::ARRAY_MAX-1;i++) {
|
||||||
|
|
||||||
@@ -5175,9 +5195,13 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
|
|||||||
|
|
||||||
int ofs = ad.ofs;
|
int ofs = ad.ofs;
|
||||||
int src_stride=surf->stride;
|
int src_stride=surf->stride;
|
||||||
int dst_stride=surf->local_stride;
|
int dst_stride=skeleton_valid?surf->stride:surf->local_stride;
|
||||||
int count = surf->array_len;
|
int count = surf->array_len;
|
||||||
|
|
||||||
|
if (!skeleton_valid && i>=VS::ARRAY_MAX-3)
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
switch(i) {
|
switch(i) {
|
||||||
|
|
||||||
case VS::ARRAY_VERTEX:
|
case VS::ARRAY_VERTEX:
|
||||||
@@ -5193,7 +5217,21 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
|
|||||||
dst[0]= src[0]*coef;
|
dst[0]= src[0]*coef;
|
||||||
dst[1]= src[1]*coef;
|
dst[1]= src[1]*coef;
|
||||||
dst[2]= src[2]*coef;
|
dst[2]= src[2]*coef;
|
||||||
|
};
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
case VS::ARRAY_COLOR: {
|
||||||
|
|
||||||
|
for(int k=0;k<count;k++) {
|
||||||
|
|
||||||
|
const uint8_t *src = (const uint8_t*)&surf->array_local[ofs+k*src_stride];
|
||||||
|
uint8_t *dst = (uint8_t*)&base[ofs+k*dst_stride];
|
||||||
|
|
||||||
|
dst[0]= (src[0]*coeffp)>>8;
|
||||||
|
dst[1]= (src[1]*coeffp)>>8;
|
||||||
|
dst[2]= (src[2]*coeffp)>>8;
|
||||||
|
dst[3]= (src[3]*coeffp)>>8;
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case VS::ARRAY_TEX_UV:
|
case VS::ARRAY_TEX_UV:
|
||||||
@@ -5206,16 +5244,32 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
|
|||||||
|
|
||||||
dst[0]= src[0]*coef;
|
dst[0]= src[0]*coef;
|
||||||
dst[1]= src[1]*coef;
|
dst[1]= src[1]*coef;
|
||||||
} break;
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
case VS::ARRAY_BONES:
|
||||||
|
case VS::ARRAY_WEIGHTS: {
|
||||||
|
|
||||||
|
for(int k=0;k<count;k++) {
|
||||||
|
|
||||||
|
const float *src = (const float*)&surf->array_local[ofs+k*src_stride];
|
||||||
|
float *dst = (float*)&base[ofs+k*dst_stride];
|
||||||
|
|
||||||
|
dst[0]= src[0];
|
||||||
|
dst[1]= src[1];
|
||||||
|
dst[2]= src[2];
|
||||||
|
dst[3]= src[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(int j=0;j<surf->morph_target_count;j++) {
|
for(int j=0;j<surf->morph_target_count;j++) {
|
||||||
|
|
||||||
for(int i=0;i<VS::ARRAY_MAX-1;i++) {
|
for(int i=0;i<VS::ARRAY_MAX-3;i++) {
|
||||||
|
|
||||||
const Surface::ArrayData& ad=surf->array[i];
|
const Surface::ArrayData& ad=surf->array[i];
|
||||||
if (ad.size==0)
|
if (ad.size==0)
|
||||||
@@ -5223,10 +5277,12 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
|
|||||||
|
|
||||||
|
|
||||||
int ofs = ad.ofs;
|
int ofs = ad.ofs;
|
||||||
int dst_stride=surf->local_stride;
|
int src_stride=surf->local_stride;
|
||||||
|
int dst_stride=skeleton_valid?surf->stride:surf->local_stride;
|
||||||
int count = surf->array_len;
|
int count = surf->array_len;
|
||||||
const uint8_t *morph=surf->morph_targets_local[j].array;
|
const uint8_t *morph=surf->morph_targets_local[j].array;
|
||||||
float w = p_morphs[j];
|
float w = p_morphs[j];
|
||||||
|
int16_t wfp = CLAMP(w*255,0,255);
|
||||||
|
|
||||||
switch(i) {
|
switch(i) {
|
||||||
|
|
||||||
@@ -5237,13 +5293,26 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
|
|||||||
|
|
||||||
for(int k=0;k<count;k++) {
|
for(int k=0;k<count;k++) {
|
||||||
|
|
||||||
const float *src_morph = (const float*)&morph[ofs+k*dst_stride];
|
const float *src_morph = (const float*)&morph[ofs+k*src_stride];
|
||||||
float *dst = (float*)&base[ofs+k*dst_stride];
|
float *dst = (float*)&base[ofs+k*dst_stride];
|
||||||
|
|
||||||
dst[0]+= src_morph[0]*w;
|
dst[0]+= src_morph[0]*w;
|
||||||
dst[1]+= src_morph[1]*w;
|
dst[1]+= src_morph[1]*w;
|
||||||
dst[2]+= src_morph[2]*w;
|
dst[2]+= src_morph[2]*w;
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
case VS::ARRAY_COLOR: {
|
||||||
|
for(int k=0;k<count;k++) {
|
||||||
|
|
||||||
|
const uint8_t *src = (const uint8_t*)&morph[ofs+k*src_stride];
|
||||||
|
uint8_t *dst = (uint8_t*)&base[ofs+k*dst_stride];
|
||||||
|
|
||||||
|
dst[0]= (src[0]*wfp)>>8;
|
||||||
|
dst[1]= (src[1]*wfp)>>8;
|
||||||
|
dst[2]= (src[2]*wfp)>>8;
|
||||||
|
dst[3]= (src[3]*wfp)>>8;
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case VS::ARRAY_TEX_UV:
|
case VS::ARRAY_TEX_UV:
|
||||||
@@ -5251,18 +5320,43 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
|
|||||||
|
|
||||||
for(int k=0;k<count;k++) {
|
for(int k=0;k<count;k++) {
|
||||||
|
|
||||||
const float *src_morph = (const float*)&morph[ofs+k*dst_stride];
|
const float *src_morph = (const float*)&morph[ofs+k*src_stride];
|
||||||
float *dst = (float*)&base[ofs+k*dst_stride];
|
float *dst = (float*)&base[ofs+k*dst_stride];
|
||||||
|
|
||||||
dst[0]+= src_morph[0]*w;
|
dst[0]+= src_morph[0]*w;
|
||||||
dst[1]+= src_morph[1]*w;
|
dst[1]+= src_morph[1]*w;
|
||||||
} break;
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (skeleton_valid) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t *src_weights=&surf->array_local[surf->array[VS::ARRAY_WEIGHTS].ofs];
|
||||||
|
const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs];
|
||||||
|
const Skeleton::Bone *skeleton = &p_skeleton->bones[0];
|
||||||
|
|
||||||
|
|
||||||
|
if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT)
|
||||||
|
_skeleton_xform<true,true,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton);
|
||||||
|
else if (surf->format&(VS::ARRAY_FORMAT_NORMAL))
|
||||||
|
_skeleton_xform<true,false,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton);
|
||||||
|
else if (surf->format&(VS::ARRAY_FORMAT_TANGENT))
|
||||||
|
_skeleton_xform<false,true,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton);
|
||||||
|
else
|
||||||
|
_skeleton_xform<false,false,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
stride=skeleton_valid?surf->stride:surf->local_stride;
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
//in-place skeleton tansformation, only used for morphs, slow.
|
//in-place skeleton tansformation, only used for morphs, slow.
|
||||||
@@ -5357,13 +5451,13 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
|
|||||||
const Skeleton::Bone *skeleton = &p_skeleton->bones[0];
|
const Skeleton::Bone *skeleton = &p_skeleton->bones[0];
|
||||||
|
|
||||||
if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT)
|
if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT)
|
||||||
_skeleton_xform<true,true>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
|
_skeleton_xform<true,true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
|
||||||
else if (surf->format&(VS::ARRAY_FORMAT_NORMAL))
|
else if (surf->format&(VS::ARRAY_FORMAT_NORMAL))
|
||||||
_skeleton_xform<true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
|
_skeleton_xform<true,false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
|
||||||
else if (surf->format&(VS::ARRAY_FORMAT_TANGENT))
|
else if (surf->format&(VS::ARRAY_FORMAT_TANGENT))
|
||||||
_skeleton_xform<false,true>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
|
_skeleton_xform<false,true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
|
||||||
else
|
else
|
||||||
_skeleton_xform<false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
|
_skeleton_xform<false,false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
|
||||||
|
|
||||||
|
|
||||||
stride=dst_stride;
|
stride=dst_stride;
|
||||||
|
|||||||
@@ -608,7 +608,7 @@ class RasterizerGLES2 : public Rasterizer {
|
|||||||
mutable SelfList<Skeleton>::List _skeleton_dirty_list;
|
mutable SelfList<Skeleton>::List _skeleton_dirty_list;
|
||||||
|
|
||||||
|
|
||||||
template<bool USE_NORMAL, bool USE_TANGENT>
|
template<bool USE_NORMAL, bool USE_TANGENT,bool INPLACE>
|
||||||
void _skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms);
|
void _skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms);
|
||||||
|
|
||||||
struct Light {
|
struct Light {
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ def get_flags():
|
|||||||
return [
|
return [
|
||||||
('freetype','builtin'), #use builtin freetype
|
('freetype','builtin'), #use builtin freetype
|
||||||
('openssl','builtin'), #use builtin openssl
|
('openssl','builtin'), #use builtin openssl
|
||||||
|
('theora','no'), #use builtin openssl
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -137,6 +138,8 @@ def configure(env):
|
|||||||
#build using mingw
|
#build using mingw
|
||||||
if (os.name=="nt"):
|
if (os.name=="nt"):
|
||||||
env['ENV']['TMP'] = os.environ['TMP'] #way to go scons, you can be so stupid sometimes
|
env['ENV']['TMP'] = os.environ['TMP'] #way to go scons, you can be so stupid sometimes
|
||||||
|
else:
|
||||||
|
env["PROGSUFFIX"]=env["PROGSUFFIX"]+".exe"
|
||||||
|
|
||||||
mingw_prefix=""
|
mingw_prefix=""
|
||||||
|
|
||||||
|
|||||||
@@ -443,7 +443,10 @@ Vector<String> Collada::_read_string_array(XMLParser& parser) {
|
|||||||
if (parser.get_node_type() == XMLParser::NODE_TEXT) {
|
if (parser.get_node_type() == XMLParser::NODE_TEXT) {
|
||||||
// parse String data
|
// parse String data
|
||||||
String str = parser.get_node_data();
|
String str = parser.get_node_data();
|
||||||
array=str.split(" ",false);
|
array=str.split_spaces();
|
||||||
|
for(int i=0;i<array.size();i++) {
|
||||||
|
print_line(itos(i)+": "+array[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
|
if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
|
||||||
@@ -2066,6 +2069,8 @@ void Collada::_parse_animation(XMLParser& parser) {
|
|||||||
track.target=target;
|
track.target=target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_line("TARGET: "+track.target);
|
||||||
|
|
||||||
state.animation_tracks.push_back(track);
|
state.animation_tracks.push_back(track);
|
||||||
|
|
||||||
if (!state.referenced_tracks.has(target))
|
if (!state.referenced_tracks.has(target))
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ public:
|
|||||||
Vector3 uv2;
|
Vector3 uv2;
|
||||||
Plane tangent;
|
Plane tangent;
|
||||||
Color color;
|
Color color;
|
||||||
|
int uid;
|
||||||
struct Weight {
|
struct Weight {
|
||||||
int bone_idx;
|
int bone_idx;
|
||||||
float weight;
|
float weight;
|
||||||
@@ -331,6 +332,7 @@ public:
|
|||||||
|
|
||||||
bool operator<(const Vertex& p_vert) const {
|
bool operator<(const Vertex& p_vert) const {
|
||||||
|
|
||||||
|
if (uid==p_vert.uid) {
|
||||||
if (vertex==p_vert.vertex) {
|
if (vertex==p_vert.vertex) {
|
||||||
if(normal==p_vert.normal) {
|
if(normal==p_vert.normal) {
|
||||||
if(uv==p_vert.uv) {
|
if(uv==p_vert.uv) {
|
||||||
@@ -344,8 +346,12 @@ public:
|
|||||||
return (normal<p_vert.normal);
|
return (normal<p_vert.normal);
|
||||||
} else
|
} else
|
||||||
return vertex<p_vert.vertex;
|
return vertex<p_vert.vertex;
|
||||||
|
} else
|
||||||
|
return uid < p_vert.uid;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vertex() { uid=0; idx=0; }
|
||||||
};
|
};
|
||||||
struct Node {
|
struct Node {
|
||||||
|
|
||||||
|
|||||||
@@ -694,6 +694,7 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co
|
|||||||
// Must convert to GL/DX format.
|
// Must convert to GL/DX format.
|
||||||
|
|
||||||
int _prim_ofs=0;
|
int _prim_ofs=0;
|
||||||
|
int vertidx=0;
|
||||||
for(int p_i=0;p_i<p.count;p_i++) {
|
for(int p_i=0;p_i<p.count;p_i++) {
|
||||||
|
|
||||||
|
|
||||||
@@ -718,6 +719,8 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co
|
|||||||
ERR_FAIL_INDEX_V(src,p.indices.size(),ERR_INVALID_DATA);
|
ERR_FAIL_INDEX_V(src,p.indices.size(),ERR_INVALID_DATA);
|
||||||
|
|
||||||
Collada::Vertex vertex;
|
Collada::Vertex vertex;
|
||||||
|
if (p_morph_data)
|
||||||
|
vertex.uid=vertidx++;
|
||||||
|
|
||||||
int vertex_index=p.indices[src+vertex_ofs]; //used for index field (later used by controllers)
|
int vertex_index=p.indices[src+vertex_ofs]; //used for index field (later used by controllers)
|
||||||
int vertex_pos = (vertex_src->stride?vertex_src->stride:3) * vertex_index;
|
int vertex_pos = (vertex_src->stride?vertex_src->stride:3) * vertex_index;
|
||||||
@@ -1670,15 +1673,20 @@ void ColladaImport::_fix_param_animation_tracks() {
|
|||||||
source=skin.base;
|
source=skin.base;
|
||||||
} else if (collada.state.morph_controller_data_map.has(source)) {
|
} else if (collada.state.morph_controller_data_map.has(source)) {
|
||||||
|
|
||||||
|
print_line("has morph");
|
||||||
const Collada::MorphControllerData& morph = collada.state.morph_controller_data_map[source];
|
const Collada::MorphControllerData& morph = collada.state.morph_controller_data_map[source];
|
||||||
|
|
||||||
if (morph.targets.has("MORPH_WEIGHT") && morph.targets.has("MORPH_TARGET")) {
|
if (morph.targets.has("MORPH_WEIGHT") && morph.targets.has("MORPH_TARGET")) {
|
||||||
|
print_line("weight and target");
|
||||||
|
|
||||||
String weights = morph.targets["MORPH_WEIGHT"];
|
String weights = morph.targets["MORPH_WEIGHT"];
|
||||||
String targets = morph.targets["MORPH_TARGET"];
|
String targets = morph.targets["MORPH_TARGET"];
|
||||||
|
//fails here
|
||||||
|
|
||||||
if (morph.sources.has(targets) && morph.sources.has(weights)) {
|
if (morph.sources.has(targets) && morph.sources.has(weights)) {
|
||||||
const Collada::MorphControllerData::Source &weight_src=morph.sources[weights];
|
const Collada::MorphControllerData::Source &weight_src=morph.sources[weights];
|
||||||
const Collada::MorphControllerData::Source &target_src=morph.sources[targets];
|
const Collada::MorphControllerData::Source &target_src=morph.sources[targets];
|
||||||
|
print_line("sources OK");
|
||||||
|
|
||||||
ERR_FAIL_COND(weight_src.array.size() != target_src.sarray.size());
|
ERR_FAIL_COND(weight_src.array.size() != target_src.sarray.size());
|
||||||
|
|
||||||
@@ -1687,6 +1695,8 @@ void ColladaImport::_fix_param_animation_tracks() {
|
|||||||
String track_name = weights+"("+itos(i)+")";
|
String track_name = weights+"("+itos(i)+")";
|
||||||
String mesh_name = target_src.sarray[i];
|
String mesh_name = target_src.sarray[i];
|
||||||
if (collada.state.mesh_name_map.has(mesh_name) && collada.state.referenced_tracks.has(track_name)) {
|
if (collada.state.mesh_name_map.has(mesh_name) && collada.state.referenced_tracks.has(track_name)) {
|
||||||
|
print_line("refe tracks");
|
||||||
|
|
||||||
|
|
||||||
const Vector<int>&rt = collada.state.referenced_tracks[track_name];
|
const Vector<int>&rt = collada.state.referenced_tracks[track_name];
|
||||||
|
|
||||||
@@ -1731,6 +1741,7 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) {
|
|||||||
for(int i=0;i<collada.state.animation_tracks.size();i++) {
|
for(int i=0;i<collada.state.animation_tracks.size();i++) {
|
||||||
|
|
||||||
Collada::AnimationTrack &at = collada.state.animation_tracks[i];
|
Collada::AnimationTrack &at = collada.state.animation_tracks[i];
|
||||||
|
print_line("CHANNEL: "+at.target+" PARAM: "+at.param);
|
||||||
if (!node_map.has(at.target)) {
|
if (!node_map.has(at.target)) {
|
||||||
print_line("Coudlnt find node: "+at.target);
|
print_line("Coudlnt find node: "+at.target);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -19,14 +19,14 @@
|
|||||||
# <pep8-80 compliant>
|
# <pep8-80 compliant>
|
||||||
|
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Khronos Collada format",
|
"name": "Better Collada Exporter",
|
||||||
"author": "Juan Linietsky",
|
"author": "Juan Linietsky",
|
||||||
"blender": (2, 5, 8),
|
"blender": (2, 5, 8),
|
||||||
"api": 38691,
|
"api": 38691,
|
||||||
"location": "File > Import-Export",
|
"location": "File > Import-Export",
|
||||||
"description": ("Export DAE Scenes"),
|
"description": ("Export DAE Scenes, This plugin actually works better! otherwise contact me."),
|
||||||
"warning": "",
|
"warning": "",
|
||||||
"wiki_url": ("None"),
|
"wiki_url": ("http://www.godotengine.org"),
|
||||||
"tracker_url": "",
|
"tracker_url": "",
|
||||||
"support": 'OFFICIAL',
|
"support": 'OFFICIAL',
|
||||||
"category": "Import-Export"}
|
"category": "Import-Export"}
|
||||||
@@ -171,7 +171,7 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
|
|||||||
|
|
||||||
|
|
||||||
def menu_func(self, context):
|
def menu_func(self, context):
|
||||||
self.layout.operator(ExportDAE.bl_idname, text="Khronos Collada (.dae)")
|
self.layout.operator(ExportDAE.bl_idname, text="Better Collada (.dae)")
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
|||||||
@@ -123,6 +123,11 @@ class DaeExporter:
|
|||||||
tup = (self.vertex.x,self.vertex.y,self.vertex.z,self.normal.x,self.normal.y,self.normal.z)
|
tup = (self.vertex.x,self.vertex.y,self.vertex.z,self.normal.x,self.normal.y,self.normal.z)
|
||||||
for t in self.uv:
|
for t in self.uv:
|
||||||
tup = tup + (t.x,t.y)
|
tup = tup + (t.x,t.y)
|
||||||
|
#for t in self.bones:
|
||||||
|
# tup = tup + (t)
|
||||||
|
#for t in self.weights:
|
||||||
|
# tup = tup + (t)
|
||||||
|
|
||||||
return tup
|
return tup
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -315,13 +320,127 @@ class DaeExporter:
|
|||||||
return matid
|
return matid
|
||||||
|
|
||||||
|
|
||||||
def export_mesh(self,node,armature=None,shapename=None):
|
def export_mesh(self,node,armature=None,skeyindex=-1,skel_source=None):
|
||||||
|
|
||||||
mesh = node.data
|
mesh = node.data
|
||||||
if (node.data in self.mesh_cache) and shapename==None:
|
|
||||||
|
|
||||||
|
if (node.data in self.mesh_cache):
|
||||||
return self.mesh_cache[mesh]
|
return self.mesh_cache[mesh]
|
||||||
|
|
||||||
if (len(node.modifiers) and self.config["use_mesh_modifiers"]) or shapename!=None:
|
if (skeyindex==-1 and mesh.shape_keys!=None and len(mesh.shape_keys.key_blocks)):
|
||||||
|
values=[]
|
||||||
|
morph_targets=[]
|
||||||
|
md=None
|
||||||
|
for k in range(0,len(mesh.shape_keys.key_blocks)):
|
||||||
|
shape = node.data.shape_keys.key_blocks[k]
|
||||||
|
values+=[shape.value] #save value
|
||||||
|
shape.value=0
|
||||||
|
|
||||||
|
mid = self.new_id("morph")
|
||||||
|
|
||||||
|
for k in range(0,len(mesh.shape_keys.key_blocks)):
|
||||||
|
|
||||||
|
shape = node.data.shape_keys.key_blocks[k]
|
||||||
|
node.show_only_shape_key=True
|
||||||
|
node.active_shape_key_index = k
|
||||||
|
shape.value = 1.0
|
||||||
|
mesh.update()
|
||||||
|
"""
|
||||||
|
oldval = shape.value
|
||||||
|
shape.value = 1.0
|
||||||
|
|
||||||
|
"""
|
||||||
|
p = node.data
|
||||||
|
v = node.to_mesh(bpy.context.scene, True, "RENDER")
|
||||||
|
node.data = v
|
||||||
|
# self.export_node(node,il,shape.name)
|
||||||
|
node.data.update()
|
||||||
|
if (armature and k==0):
|
||||||
|
md=self.export_mesh(node,armature,k,mid)
|
||||||
|
else:
|
||||||
|
md=self.export_mesh(node,None,k)
|
||||||
|
|
||||||
|
node.data = p
|
||||||
|
node.data.update()
|
||||||
|
shape.value = 0.0
|
||||||
|
morph_targets.append(md)
|
||||||
|
|
||||||
|
"""
|
||||||
|
shape.value = oldval
|
||||||
|
"""
|
||||||
|
node.show_only_shape_key=False
|
||||||
|
node.active_shape_key_index = 0
|
||||||
|
|
||||||
|
|
||||||
|
self.writel(S_CONT,1,'<controller id="'+mid+'" name="">')
|
||||||
|
#if ("skin_id" in morph_targets[0]):
|
||||||
|
# self.writel(S_CONT,2,'<morph source="#'+morph_targets[0]["skin_id"]+'" method="NORMALIZED">')
|
||||||
|
#else:
|
||||||
|
self.writel(S_CONT,2,'<morph source="#'+morph_targets[0]["id"]+'" method="NORMALIZED">')
|
||||||
|
|
||||||
|
self.writel(S_CONT,3,'<source id="'+mid+'-morph-targets">')
|
||||||
|
self.writel(S_CONT,4,'<IDREF_array id="'+mid+'-morph-targets-array" count="'+str(len(morph_targets)-1)+'">')
|
||||||
|
marr=""
|
||||||
|
warr=""
|
||||||
|
for i in range(len(morph_targets)):
|
||||||
|
if (i==0):
|
||||||
|
continue
|
||||||
|
elif (i>1):
|
||||||
|
marr+=" "
|
||||||
|
|
||||||
|
if ("skin_id" in morph_targets[i]):
|
||||||
|
marr+=morph_targets[i]["skin_id"]
|
||||||
|
else:
|
||||||
|
marr+=morph_targets[i]["id"]
|
||||||
|
|
||||||
|
warr+=" 0"
|
||||||
|
|
||||||
|
self.writel(S_CONT,5,marr)
|
||||||
|
self.writel(S_CONT,4,'</IDREF_array>')
|
||||||
|
self.writel(S_CONT,4,'<technique_common>')
|
||||||
|
self.writel(S_CONT,5,'<accessor source="#'+mid+'-morph-targets-array" count="'+str(len(morph_targets)-1)+'" stride="1">')
|
||||||
|
self.writel(S_CONT,6,'<param name="MORPH_TARGET" type="IDREF"/>')
|
||||||
|
self.writel(S_CONT,5,'</accessor>')
|
||||||
|
self.writel(S_CONT,4,'</technique_common>')
|
||||||
|
self.writel(S_CONT,3,'</source>')
|
||||||
|
|
||||||
|
self.writel(S_CONT,3,'<source id="'+mid+'-morph-weights">')
|
||||||
|
self.writel(S_CONT,4,'<float_array id="'+mid+'-morph-weights-array" count="'+str(len(morph_targets)-1)+'" >')
|
||||||
|
self.writel(S_CONT,5,warr)
|
||||||
|
self.writel(S_CONT,4,'</float_array>')
|
||||||
|
self.writel(S_CONT,4,'<technique_common>')
|
||||||
|
self.writel(S_CONT,5,'<accessor source="#'+mid+'-morph-weights-array" count="'+str(len(morph_targets)-1)+'" stride="1">')
|
||||||
|
self.writel(S_CONT,6,'<param name="MORPH_WEIGHT" type="float"/>')
|
||||||
|
self.writel(S_CONT,5,'</accessor>')
|
||||||
|
self.writel(S_CONT,4,'</technique_common>')
|
||||||
|
self.writel(S_CONT,3,'</source>')
|
||||||
|
|
||||||
|
self.writel(S_CONT,3,'<targets>')
|
||||||
|
self.writel(S_CONT,4,'<input semantic="MORPH_TARGET" source="#'+mid+'-morph-targets"/>')
|
||||||
|
self.writel(S_CONT,4,'<input semantic="MORPH_WEIGHT" source="#'+mid+'-morph-weights"/>')
|
||||||
|
self.writel(S_CONT,3,'</targets>')
|
||||||
|
self.writel(S_CONT,2,'</morph>')
|
||||||
|
self.writel(S_CONT,1,'</controller>')
|
||||||
|
if (armature!=None):
|
||||||
|
|
||||||
|
self.armature_for_morph[node]=armature
|
||||||
|
|
||||||
|
meshdata={}
|
||||||
|
if (armature):
|
||||||
|
meshdata = morph_targets[0]
|
||||||
|
meshdata["morph_id"]=mid
|
||||||
|
else:
|
||||||
|
meshdata["id"]=morph_targets[0]["id"]
|
||||||
|
meshdata["morph_id"]=mid
|
||||||
|
meshdata["material_assign"]=morph_targets[0]["material_assign"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.mesh_cache[node.data]=meshdata
|
||||||
|
return meshdata
|
||||||
|
|
||||||
|
if (len(node.modifiers) and self.config["use_mesh_modifiers"]):
|
||||||
mesh=node.to_mesh(self.scene,True,"RENDER") #is this allright?
|
mesh=node.to_mesh(self.scene,True,"RENDER") #is this allright?
|
||||||
else:
|
else:
|
||||||
mesh=node.data
|
mesh=node.data
|
||||||
@@ -349,7 +468,6 @@ class DaeExporter:
|
|||||||
for fi in range(len(mesh.tessfaces)):
|
for fi in range(len(mesh.tessfaces)):
|
||||||
f=mesh.tessfaces[fi]
|
f=mesh.tessfaces[fi]
|
||||||
|
|
||||||
|
|
||||||
if (not (f.material_index in surface_indices)):
|
if (not (f.material_index in surface_indices)):
|
||||||
surface_indices[f.material_index]=[]
|
surface_indices[f.material_index]=[]
|
||||||
print("Type: "+str(type(f.material_index)))
|
print("Type: "+str(type(f.material_index)))
|
||||||
@@ -419,7 +537,7 @@ class DaeExporter:
|
|||||||
|
|
||||||
tup = v.get_tup()
|
tup = v.get_tup()
|
||||||
idx = 0
|
idx = 0
|
||||||
if (tup in vertex_map):
|
if (skeyindex==-1 and tup in vertex_map): #do not optmize if using shapekeys
|
||||||
idx = vertex_map[tup]
|
idx = vertex_map[tup]
|
||||||
else:
|
else:
|
||||||
idx = len(vertices)
|
idx = len(vertices)
|
||||||
@@ -428,10 +546,7 @@ class DaeExporter:
|
|||||||
|
|
||||||
indices.append(idx)
|
indices.append(idx)
|
||||||
|
|
||||||
if shapename != None:
|
|
||||||
meshid = self.new_id("mesh_"+shapename)
|
|
||||||
self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'_'+shapename+'">')
|
|
||||||
else:
|
|
||||||
meshid = self.new_id("mesh")
|
meshid = self.new_id("mesh")
|
||||||
self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">')
|
self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">')
|
||||||
|
|
||||||
@@ -526,20 +641,26 @@ class DaeExporter:
|
|||||||
self.writel(S_GEOM,2,'</mesh>')
|
self.writel(S_GEOM,2,'</mesh>')
|
||||||
self.writel(S_GEOM,1,'</geometry>')
|
self.writel(S_GEOM,1,'</geometry>')
|
||||||
|
|
||||||
|
|
||||||
meshdata={}
|
meshdata={}
|
||||||
meshdata["id"]=meshid
|
meshdata["id"]=meshid
|
||||||
meshdata["material_assign"]=mat_assign
|
meshdata["material_assign"]=mat_assign
|
||||||
|
if (skeyindex==-1):
|
||||||
self.mesh_cache[node.data]=meshdata
|
self.mesh_cache[node.data]=meshdata
|
||||||
|
|
||||||
|
|
||||||
# Export armature data (if armature exists)
|
# Export armature data (if armature exists)
|
||||||
|
|
||||||
if (armature!=None):
|
if (armature!=None and (skel_source!=None or skeyindex==-1)):
|
||||||
|
|
||||||
contid = self.new_id("controller")
|
contid = self.new_id("controller")
|
||||||
|
|
||||||
self.writel(S_CONT,1,'<controller id="'+contid+'">')
|
self.writel(S_CONT,1,'<controller id="'+contid+'">')
|
||||||
|
if (skel_source!=None):
|
||||||
|
self.writel(S_CONT,2,'<skin source="'+skel_source+'">')
|
||||||
|
else:
|
||||||
self.writel(S_CONT,2,'<skin source="'+meshid+'">')
|
self.writel(S_CONT,2,'<skin source="'+meshid+'">')
|
||||||
|
|
||||||
self.writel(S_CONT,3,'<bind_shape_matrix>'+strmtx(node.matrix_world)+'</bind_shape_matrix>')
|
self.writel(S_CONT,3,'<bind_shape_matrix>'+strmtx(node.matrix_world)+'</bind_shape_matrix>')
|
||||||
#Joint Names
|
#Joint Names
|
||||||
self.writel(S_CONT,3,'<source id="'+contid+'-joints">')
|
self.writel(S_CONT,3,'<source id="'+contid+'-joints">')
|
||||||
@@ -614,7 +735,7 @@ class DaeExporter:
|
|||||||
return meshdata
|
return meshdata
|
||||||
|
|
||||||
|
|
||||||
def export_mesh_node(self,node,il,shapename=None):
|
def export_mesh_node(self,node,il):
|
||||||
|
|
||||||
if (node.data==None):
|
if (node.data==None):
|
||||||
return
|
return
|
||||||
@@ -624,14 +745,19 @@ class DaeExporter:
|
|||||||
if (node.parent.type=="ARMATURE"):
|
if (node.parent.type=="ARMATURE"):
|
||||||
armature=node.parent
|
armature=node.parent
|
||||||
|
|
||||||
meshdata = self.export_mesh(node,armature,shapename)
|
meshdata = self.export_mesh(node,armature)
|
||||||
|
close_controller=False
|
||||||
|
|
||||||
if (armature==None):
|
if ("skin_id" in meshdata):
|
||||||
self.writel(S_NODES,il,'<instance_geometry url="#'+meshdata["id"]+'">')
|
close_controller=True
|
||||||
else:
|
|
||||||
self.writel(S_NODES,il,'<instance_controller url="#'+meshdata["skin_id"]+'">')
|
self.writel(S_NODES,il,'<instance_controller url="#'+meshdata["skin_id"]+'">')
|
||||||
for sn in self.skeleton_info[armature]["skeleton_nodes"]:
|
for sn in self.skeleton_info[armature]["skeleton_nodes"]:
|
||||||
self.writel(S_NODES,il+1,'<skeleton>#'+sn+'</skeleton>')
|
self.writel(S_NODES,il+1,'<skeleton>#'+sn+'</skeleton>')
|
||||||
|
elif ("morph_id" in meshdata):
|
||||||
|
self.writel(S_NODES,il,'<instance_controller url="#'+meshdata["morph_id"]+'">')
|
||||||
|
close_controller=True
|
||||||
|
elif (armature==None):
|
||||||
|
self.writel(S_NODES,il,'<instance_geometry url="#'+meshdata["id"]+'">')
|
||||||
|
|
||||||
|
|
||||||
if (len(meshdata["material_assign"])>0):
|
if (len(meshdata["material_assign"])>0):
|
||||||
@@ -644,17 +770,17 @@ class DaeExporter:
|
|||||||
self.writel(S_NODES,il+2,'</technique_common>')
|
self.writel(S_NODES,il+2,'</technique_common>')
|
||||||
self.writel(S_NODES,il+1,'</bind_material>')
|
self.writel(S_NODES,il+1,'</bind_material>')
|
||||||
|
|
||||||
if (armature==None):
|
if (close_controller):
|
||||||
self.writel(S_NODES,il,'</instance_geometry>')
|
|
||||||
else:
|
|
||||||
self.writel(S_NODES,il,'</instance_controller>')
|
self.writel(S_NODES,il,'</instance_controller>')
|
||||||
|
else:
|
||||||
|
self.writel(S_NODES,il,'</instance_geometry>')
|
||||||
|
|
||||||
|
|
||||||
def export_armature_bone(self,bone,il,si):
|
def export_armature_bone(self,bone,il,si):
|
||||||
boneid = self.new_id("bone")
|
boneid = self.new_id("bone")
|
||||||
boneidx = si["bone_count"]
|
boneidx = si["bone_count"]
|
||||||
si["bone_count"]+=1
|
si["bone_count"]+=1
|
||||||
bonesid = si["name"]+"-"+str(boneidx)
|
bonesid = si["id"]+"-"+str(boneidx)
|
||||||
si["bone_index"][bone.name]=boneidx
|
si["bone_index"][bone.name]=boneidx
|
||||||
si["bone_ids"][bone]=boneid
|
si["bone_ids"][bone]=boneid
|
||||||
si["bone_names"].append(bonesid)
|
si["bone_names"].append(bonesid)
|
||||||
@@ -683,7 +809,7 @@ class DaeExporter:
|
|||||||
self.skeletons.append(node)
|
self.skeletons.append(node)
|
||||||
|
|
||||||
armature = node.data
|
armature = node.data
|
||||||
self.skeleton_info[node]={ "bone_count":0, "name":node.name, "bone_index":{},"bone_ids":{},"bone_names":[],"bone_bind_poses":[],"skeleton_nodes":[],"armature_xform":node.matrix_world }
|
self.skeleton_info[node]={ "bone_count":0, "id":self.new_id("skelbones"),"name":node.name, "bone_index":{},"bone_ids":{},"bone_names":[],"bone_bind_poses":[],"skeleton_nodes":[],"armature_xform":node.matrix_world }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -912,21 +1038,18 @@ class DaeExporter:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def export_node(self,node,il,shapename=None):
|
def export_node(self,node,il):
|
||||||
if (not self.is_node_valid(node)):
|
if (not self.is_node_valid(node)):
|
||||||
return
|
return
|
||||||
bpy.context.scene.objects.active = node
|
bpy.context.scene.objects.active = node
|
||||||
|
|
||||||
if shapename != None:
|
|
||||||
self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name + '_' + shapename)+'" name="'+node.name+'_'+shapename+'" type="NODE">')
|
|
||||||
else:
|
|
||||||
self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name)+'" name="'+node.name+'" type="NODE">')
|
self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name)+'" name="'+node.name+'" type="NODE">')
|
||||||
il+=1
|
il+=1
|
||||||
|
|
||||||
self.writel(S_NODES,il,'<matrix sid="transform">'+strmtx(node.matrix_local)+'</matrix>')
|
self.writel(S_NODES,il,'<matrix sid="transform">'+strmtx(node.matrix_local)+'</matrix>')
|
||||||
print("NODE TYPE: "+node.type+" NAME: "+node.name)
|
print("NODE TYPE: "+node.type+" NAME: "+node.name)
|
||||||
if (node.type=="MESH"):
|
if (node.type=="MESH"):
|
||||||
self.export_mesh_node(node,il,shapename)
|
self.export_mesh_node(node,il)
|
||||||
elif (node.type=="CURVE"):
|
elif (node.type=="CURVE"):
|
||||||
self.export_curve_node(node,il)
|
self.export_curve_node(node,il)
|
||||||
elif (node.type=="ARMATURE"):
|
elif (node.type=="ARMATURE"):
|
||||||
@@ -937,22 +1060,9 @@ class DaeExporter:
|
|||||||
self.export_lamp_node(node,il)
|
self.export_lamp_node(node,il)
|
||||||
|
|
||||||
self.valid_nodes.append(node)
|
self.valid_nodes.append(node)
|
||||||
if shapename==None:
|
|
||||||
for x in node.children:
|
for x in node.children:
|
||||||
self.export_node(x,il)
|
self.export_node(x,il)
|
||||||
if node.type=="MESH" and self.config["export_shapekeys"]:
|
|
||||||
for k in range(0,len(node.data.shape_keys.key_blocks)):
|
|
||||||
shape = node.data.shape_keys.key_blocks[k]
|
|
||||||
oldval = shape.value
|
|
||||||
shape.value = 1.0
|
|
||||||
node.active_shape_key_index = k
|
|
||||||
p = node.data
|
|
||||||
v = node.to_mesh(bpy.context.scene, True, "RENDER")
|
|
||||||
node.data = v
|
|
||||||
self.export_node(node,il,shape.name)
|
|
||||||
node.data = p
|
|
||||||
node.data.update()
|
|
||||||
shape.value = oldval
|
|
||||||
il-=1
|
il-=1
|
||||||
self.writel(S_NODES,il,'</node>')
|
self.writel(S_NODES,il,'</node>')
|
||||||
|
|
||||||
@@ -1003,18 +1113,22 @@ class DaeExporter:
|
|||||||
self.writel(S_ASSET,0,'</asset>')
|
self.writel(S_ASSET,0,'</asset>')
|
||||||
|
|
||||||
|
|
||||||
def export_animation_transform_channel(self,target,transform_keys):
|
def export_animation_transform_channel(self,target,keys,matrices=True):
|
||||||
|
|
||||||
frame_total=len(transform_keys)
|
frame_total=len(keys)
|
||||||
anim_id=self.new_id("anim")
|
anim_id=self.new_id("anim")
|
||||||
self.writel(S_ANIM,1,'<animation id="'+anim_id+'">')
|
self.writel(S_ANIM,1,'<animation id="'+anim_id+'">')
|
||||||
source_frames = ""
|
source_frames = ""
|
||||||
source_transforms = ""
|
source_transforms = ""
|
||||||
source_interps = ""
|
source_interps = ""
|
||||||
|
|
||||||
for k in transform_keys:
|
for k in keys:
|
||||||
source_frames += " "+str(k[0])
|
source_frames += " "+str(k[0])
|
||||||
|
if (matrices):
|
||||||
source_transforms += " "+strmtx(k[1])
|
source_transforms += " "+strmtx(k[1])
|
||||||
|
else:
|
||||||
|
source_transforms += " "+str(k[1])
|
||||||
|
|
||||||
source_interps +=" LINEAR"
|
source_interps +=" LINEAR"
|
||||||
|
|
||||||
|
|
||||||
@@ -1028,6 +1142,7 @@ class DaeExporter:
|
|||||||
self.writel(S_ANIM,3,'</technique_common>')
|
self.writel(S_ANIM,3,'</technique_common>')
|
||||||
self.writel(S_ANIM,2,'</source>')
|
self.writel(S_ANIM,2,'</source>')
|
||||||
|
|
||||||
|
if (matrices):
|
||||||
# Transform Source
|
# Transform Source
|
||||||
self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">')
|
self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">')
|
||||||
self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total*16)+'">'+source_transforms+'</float_array>')
|
self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total*16)+'">'+source_transforms+'</float_array>')
|
||||||
@@ -1037,6 +1152,16 @@ class DaeExporter:
|
|||||||
self.writel(S_ANIM,4,'</accessor>')
|
self.writel(S_ANIM,4,'</accessor>')
|
||||||
self.writel(S_ANIM,3,'</technique_common>')
|
self.writel(S_ANIM,3,'</technique_common>')
|
||||||
self.writel(S_ANIM,2,'</source>')
|
self.writel(S_ANIM,2,'</source>')
|
||||||
|
else:
|
||||||
|
# Value Source
|
||||||
|
self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">')
|
||||||
|
self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total)+'">'+source_transforms+'</float_array>')
|
||||||
|
self.writel(S_ANIM,3,'<technique_common>')
|
||||||
|
self.writel(S_ANIM,4,'<accessor source="'+anim_id+'-transform-output-array" count="'+str(frame_total)+'" stride="1">')
|
||||||
|
self.writel(S_ANIM,5,'<param name="X" type="float"/>')
|
||||||
|
self.writel(S_ANIM,4,'</accessor>')
|
||||||
|
self.writel(S_ANIM,3,'</technique_common>')
|
||||||
|
self.writel(S_ANIM,2,'</source>')
|
||||||
|
|
||||||
# Interpolation Source
|
# Interpolation Source
|
||||||
self.writel(S_ANIM,2,'<source id="'+anim_id+'-interpolation-output">')
|
self.writel(S_ANIM,2,'<source id="'+anim_id+'-interpolation-output">')
|
||||||
@@ -1053,7 +1178,10 @@ class DaeExporter:
|
|||||||
self.writel(S_ANIM,3,'<input semantic="OUTPUT" source="#'+anim_id+'-transform-output"/>')
|
self.writel(S_ANIM,3,'<input semantic="OUTPUT" source="#'+anim_id+'-transform-output"/>')
|
||||||
self.writel(S_ANIM,3,'<input semantic="INTERPOLATION" source="#'+anim_id+'-interpolation-output"/>')
|
self.writel(S_ANIM,3,'<input semantic="INTERPOLATION" source="#'+anim_id+'-interpolation-output"/>')
|
||||||
self.writel(S_ANIM,2,'</sampler>')
|
self.writel(S_ANIM,2,'</sampler>')
|
||||||
|
if (matrices):
|
||||||
self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'/transform"/>')
|
self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'/transform"/>')
|
||||||
|
else:
|
||||||
|
self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'"/>')
|
||||||
self.writel(S_ANIM,1,'</animation>')
|
self.writel(S_ANIM,1,'</animation>')
|
||||||
|
|
||||||
return [anim_id]
|
return [anim_id]
|
||||||
@@ -1075,6 +1203,7 @@ class DaeExporter:
|
|||||||
|
|
||||||
tcn = []
|
tcn = []
|
||||||
xform_cache={}
|
xform_cache={}
|
||||||
|
blend_cache={}
|
||||||
# Change frames first, export objects last
|
# Change frames first, export objects last
|
||||||
# This improves performance enormously
|
# This improves performance enormously
|
||||||
|
|
||||||
@@ -1089,9 +1218,26 @@ class DaeExporter:
|
|||||||
if (not node in self.valid_nodes):
|
if (not node in self.valid_nodes):
|
||||||
continue
|
continue
|
||||||
if (allowed!=None and not (node in allowed)):
|
if (allowed!=None and not (node in allowed)):
|
||||||
|
if (node.type=="MESH" and node.data!=None and (node in self.armature_for_morph) and (self.armature_for_morph[node] in allowed)):
|
||||||
|
pass #all good you pass with flying colors for morphs inside of action
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if (node.type=="MESH" and node.data!=None and node.data.shape_keys!=None and (node.data in self.mesh_cache) and len(node.data.shape_keys.key_blocks)):
|
||||||
|
target = self.mesh_cache[node.data]["morph_id"]
|
||||||
|
for i in range(len(node.data.shape_keys.key_blocks)):
|
||||||
|
|
||||||
|
if (i==0):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
name=target+"-morph-weights("+str(i-1)+")"
|
||||||
|
if (not (name in blend_cache)):
|
||||||
|
blend_cache[name]=[]
|
||||||
|
|
||||||
|
blend_cache[name].append( (key,node.data.shape_keys.key_blocks[i].value) )
|
||||||
|
|
||||||
|
|
||||||
if (node.type=="MESH" and node.parent and node.parent.type=="ARMATURE"):
|
if (node.type=="MESH" and node.parent and node.parent.type=="ARMATURE"):
|
||||||
|
|
||||||
continue #In Collada, nodes that have skin modifier must not export animation, animate the skin instead.
|
continue #In Collada, nodes that have skin modifier must not export animation, animate the skin instead.
|
||||||
|
|
||||||
if (len(node.constraints)>0 or node.animation_data!=None):
|
if (len(node.constraints)>0 or node.animation_data!=None):
|
||||||
@@ -1108,6 +1254,7 @@ class DaeExporter:
|
|||||||
|
|
||||||
if (node.type=="ARMATURE"):
|
if (node.type=="ARMATURE"):
|
||||||
#All bones exported for now
|
#All bones exported for now
|
||||||
|
|
||||||
for bone in node.data.bones:
|
for bone in node.data.bones:
|
||||||
|
|
||||||
bone_name=self.skeleton_info[node]["bone_ids"][bone]
|
bone_name=self.skeleton_info[node]["bone_ids"][bone]
|
||||||
@@ -1138,7 +1285,9 @@ class DaeExporter:
|
|||||||
|
|
||||||
#export animation xml
|
#export animation xml
|
||||||
for nid in xform_cache:
|
for nid in xform_cache:
|
||||||
tcn+=self.export_animation_transform_channel(nid,xform_cache[nid])
|
tcn+=self.export_animation_transform_channel(nid,xform_cache[nid],True)
|
||||||
|
for nid in blend_cache:
|
||||||
|
tcn+=self.export_animation_transform_channel(nid,blend_cache[nid],False)
|
||||||
|
|
||||||
return tcn
|
return tcn
|
||||||
|
|
||||||
@@ -1197,7 +1346,7 @@ class DaeExporter:
|
|||||||
print("Export anim: "+x.name)
|
print("Export anim: "+x.name)
|
||||||
self.writel(S_ANIM_CLIPS,1,'<animation_clip name="'+x.name+'" start="'+str(start)+'" end="'+str(end)+'">')
|
self.writel(S_ANIM_CLIPS,1,'<animation_clip name="'+x.name+'" start="'+str(start)+'" end="'+str(end)+'">')
|
||||||
for z in tcn:
|
for z in tcn:
|
||||||
self.writel(S_ANIM_CLIPS,2,'<instance_animation url="#'+z+'">')
|
self.writel(S_ANIM_CLIPS,2,'<instance_animation url="#'+z+'"/>')
|
||||||
self.writel(S_ANIM_CLIPS,1,'</animation_clip>')
|
self.writel(S_ANIM_CLIPS,1,'</animation_clip>')
|
||||||
|
|
||||||
|
|
||||||
@@ -1276,6 +1425,7 @@ class DaeExporter:
|
|||||||
self.skeleton_info={}
|
self.skeleton_info={}
|
||||||
self.config=kwargs
|
self.config=kwargs
|
||||||
self.valid_nodes=[]
|
self.valid_nodes=[]
|
||||||
|
self.armature_for_morph={}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user