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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/collada/DocumentExporter.cpp')
-rw-r--r--source/blender/collada/DocumentExporter.cpp191
1 files changed, 156 insertions, 35 deletions
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index 3e1898a64d9..7a994d6b418 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -1,3 +1,26 @@
+/**
+ * $Id$
+ *
+ * ***** 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>
@@ -359,6 +382,8 @@ public:
std::vector<Normal> nor;
std::vector<Face> norind;
+ bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
+
create_normals(nor, norind, me);
// openMesh(geoId, geoName, meshId)
@@ -370,12 +395,15 @@ public:
// writes <source> for normal coords
createNormalsSource(geom_id, me, nor);
- int has_uvs = CustomData_has_layer(&me->fdata, CD_MTFACE);
+ bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
// writes <source> for uv coords if mesh has uv coords
- if (has_uvs) {
- createTexcoordsSource(geom_id, (Mesh*)ob->data);
- }
+ if (has_uvs)
+ createTexcoordsSource(geom_id, me);
+
+ if (has_color)
+ createVertexColorSource(geom_id, me);
+
// <vertices>
COLLADASW::Vertices verts(mSW);
verts.setId(getIdBySemantics(geom_id, COLLADASW::VERTEX));
@@ -389,11 +417,11 @@ public:
for(int a = 0; a < ob->totcol; a++) {
// account for NULL materials, this should not normally happen?
Material *ma = give_current_material(ob, a + 1);
- createPolylist(ma != NULL, a, has_uvs, ob, geom_id, norind);
+ createPolylist(ma != NULL, a, has_uvs, has_color, ob, geom_id, norind);
}
}
else {
- createPolylist(false, 0, has_uvs, ob, geom_id, norind);
+ createPolylist(false, 0, has_uvs, has_color, ob, geom_id, norind);
}
closeMesh();
@@ -408,14 +436,11 @@ public:
void createPolylist(bool has_material,
int material_index,
bool has_uvs,
+ bool has_color,
Object *ob,
std::string& geom_id,
std::vector<Face>& norind)
{
-#if 0
- MFace *mfaces = dm->getFaceArray(dm);
- int totfaces = dm->getNumFaces(dm);
-#endif
Mesh *me = (Mesh*)ob->data;
MFace *mfaces = me->mface;
int totfaces = me->totface;
@@ -479,6 +504,11 @@ public:
);
til.push_back(input3);
}
+
+ if (has_color) {
+ COLLADASW::Input input4(COLLADASW::COLOR, getUrlBySemantics(geom_id, COLLADASW::COLOR), has_uvs ? 3 : 2);
+ til.push_back(input4);
+ }
// sets <vcount>
polylist.setVCountList(vcount_list);
@@ -501,6 +531,9 @@ public:
if (has_uvs)
polylist.appendValues(texindex + j);
+
+ if (has_color)
+ polylist.appendValues(texindex + j);
}
}
@@ -545,6 +578,42 @@ public:
}
+ void createVertexColorSource(std::string geom_id, Mesh *me)
+ {
+ if (!CustomData_has_layer(&me->fdata, CD_MCOL))
+ return;
+
+ MFace *f;
+ int totcolor = 0, i, j;
+
+ for (i = 0, f = me->mface; i < me->totface; i++, f++)
+ totcolor += f->v4 ? 4 : 3;
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(getIdBySemantics(geom_id, COLLADASW::COLOR));
+ source.setArrayId(getIdBySemantics(geom_id, COLLADASW::COLOR) + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(totcolor);
+ source.setAccessorStride(3);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("R");
+ param.push_back("G");
+ param.push_back("B");
+
+ source.prepareToAppendValues();
+
+ int index = CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
+
+ MCol *mcol = (MCol*)me->fdata.layers[index].data;
+ MCol *c = mcol;
+
+ for (i = 0, f = me->mface; i < me->totface; i++, c += 4, f++)
+ for (j = 0; j < (f->v4 ? 4 : 3); j++)
+ source.appendValues(c[j].b / 255.0f, c[j].g / 255.0f, c[j].r / 255.0f);
+
+ source.finish();
+ }
+
std::string makeTexcoordSourceId(std::string& geom_id, int layer_index)
{
char suffix[20];
@@ -592,8 +661,8 @@ public:
source.setAccessorCount(totuv);
source.setAccessorStride(2);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- param.push_back("X");
- param.push_back("Y");
+ param.push_back("S");
+ param.push_back("T");
source.prepareToAppendValues();
@@ -862,7 +931,7 @@ public:
Object *ob_arm = get_assigned_armature(ob);
bArmature *arm = (bArmature*)ob_arm->data;
- const std::string& controller_id = get_controller_id(ob_arm);
+ const std::string& controller_id = get_controller_id(ob_arm, ob);
COLLADASW::InstanceController ins(mSW);
ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
@@ -1005,9 +1074,9 @@ private:
TransformWriter::add_node_transform(node, mat, NULL);
}
- std::string get_controller_id(Object *ob_arm)
+ std::string get_controller_id(Object *ob_arm, Object *ob)
{
- return translate_id(id_name(ob_arm)) + SKIN_CONTROLLER_ID_SUFFIX;
+ return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
}
// ob should be of type OB_MESH
@@ -1041,7 +1110,7 @@ private:
if (!me->dvert) return;
std::string controller_name = id_name(ob_arm);
- std::string controller_id = get_controller_id(ob_arm);
+ std::string controller_id = get_controller_id(ob_arm, ob);
openSkin(controller_id, controller_name,
COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob)));
@@ -1433,7 +1502,7 @@ public:
char src[FILE_MAX];
char dir[FILE_MAX];
- BLI_split_dirfile_basic(mfilename, dir, NULL);
+ BLI_split_dirfile(mfilename, dir, NULL);
BKE_rebase_path(abs, sizeof(abs), rel, sizeof(rel), G.sce, image->name, dir);
@@ -1441,7 +1510,7 @@ public:
// make absolute source path
BLI_strncpy(src, image->name, sizeof(src));
- BLI_convertstringcode(src, G.sce);
+ BLI_path_abs(src, G.sce);
// make dest directory if it doesn't exist
BLI_make_existing_file(abs);
@@ -1509,18 +1578,27 @@ public:
else {
ep.setIndexOfRefraction(1.0f);
}
+
+ COLLADASW::ColorOrTexture cot;
+
// transparency
- ep.setTransparency(ma->alpha);
+ // Tod: because we are in A_ONE mode transparency is calculated like this:
+ ep.setTransparency(1.0f);
+ cot = getcol(0.0f, 0.0f, 0.0f, ma->alpha);
+ ep.setTransparent(cot);
+
// emission
- COLLADASW::ColorOrTexture cot = getcol(0.0f, 0.0f, 0.0f, 1.0f);
+ cot=getcol(ma->emit, ma->emit, ma->emit, 1.0f);
ep.setEmission(cot);
- ep.setTransparent(cot);
+
// diffuse
cot = getcol(ma->r, ma->g, ma->b, 1.0f);
ep.setDiffuse(cot);
+
// ambient
cot = getcol(ma->ambr, ma->ambg, ma->ambb, 1.0f);
ep.setAmbient(cot);
+
// reflective, reflectivity
if (ma->mode & MA_RAYMIRROR) {
cot = getcol(ma->mirr, ma->mirg, ma->mirb, 1.0f);
@@ -1528,15 +1606,16 @@ public:
ep.setReflectivity(ma->ray_mirror);
}
else {
- cot = getcol(0.0f, 0.0f, 0.0f, 1.0f);
+ cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
ep.setReflective(cot);
- ep.setReflectivity(0.0f);
+ ep.setReflectivity(ma->spec);
}
+
// specular
if (ep.getShaderType() != COLLADASW::EffectProfile::LAMBERT) {
cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
ep.setSpecular(cot);
- }
+ }
// XXX make this more readable if possible
@@ -1640,12 +1719,28 @@ public:
// most widespread de-facto standard.
texture.setProfileName("FCOLLADA");
texture.setChildElementName("bump");
+#ifdef WIN32 // currently, Windows builds are using revision 746 of OpenCollada while Linux and Mac are using an older revision 721
+ ep.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture));
+#else
ep.setExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture));
+#endif
}
}
// performs the actual writing
ep.addProfileElements();
+ bool twoSided = false;
+ if (ob->type == OB_MESH && ob->data) {
+ Mesh *me = (Mesh*)ob->data;
+ if (me->flag & ME_TWOSIDED)
+ twoSided = true;
+ }
+ if (twoSided)
+ ep.addExtraTechniqueParameter("GOOGLEEARTH", "double_sided", 1);
+ ep.addExtraTechniques(mSW);
+
ep.closeProfile();
+ if (twoSided)
+ mSW->appendTextBlock("<extra><technique profile=\"MAX3D\"><double_sided>1</double_sided></technique></extra>");
closeEffect();
}
@@ -1902,7 +1997,7 @@ protected:
addSampler(sampler);
std::string target = translate_id(ob_name)
- + "/" + get_transform_sid(fcu->rna_path, -1, axis_name);
+ + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
addChannel(COLLADABU::URI(empty, sampler_id), target);
closeAnimation();
@@ -2050,7 +2145,7 @@ protected:
if (axis > -1)
axis_name = axis_names[axis];
- std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name);
+ std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
(char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str());
@@ -2321,24 +2416,47 @@ protected:
return source_id;
}
- std::string get_transform_sid(char *rna_path, int tm_type, 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 tm_name;
+
+ // when given rna_path, determine tm_type from it
if (rna_path) {
char *name = extract_transform_name(rna_path);
if (strstr(name, "rotation"))
- return std::string("rotation") + std::string(axis_name) + ".ANGLE";
- else if (!strcmp(name, "location") || !strcmp(name, "scale"))
- return std::string(name);
+ tm_type = 0;
+ else if (!strcmp(name, "scale"))
+ tm_type = 1;
+ else if (!strcmp(name, "location"))
+ tm_type = 2;
+ else
+ tm_type = -1;
}
- else {
- if (tm_type == 0)
- return std::string("rotation") + std::string(axis_name) + ".ANGLE";
+
+ switch (tm_type) {
+ case 0:
+ return std::string("rotation") + std::string(axis_name) + ".ANGLE";
+ case 1:
+ tm_name = "scale";
+ break;
+ case 2:
+ tm_name = "location";
+ break;
+ default:
+ tm_name = "";
+ break;
+ }
+
+ if (tm_name.size()) {
+ if (append_axis)
+ return tm_name + std::string(".") + std::string(axis_name);
else
- return tm_type == 1 ? "scale" : "location";
+ return tm_name;
}
- return NULL;
+ return std::string("");
}
char *extract_transform_name(char *rna_path)
@@ -2364,6 +2482,9 @@ protected:
}
}
}
+
+ // keep the keys in ascending order
+ std::sort(fra.begin(), fra.end());
}
void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)