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/GeometryExporter.cpp')
-rw-r--r--source/blender/collada/GeometryExporter.cpp472
1 files changed, 472 insertions, 0 deletions
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
new file mode 100644
index 00000000000..1aef6e6489a
--- /dev/null
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -0,0 +1,472 @@
+/**
+ * $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,
+ * Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "COLLADASWPrimitves.h"
+#include "COLLADASWSource.h"
+#include "COLLADASWVertices.h"
+#include "COLLADABUUtils.h"
+
+#include "GeometryExporter.h"
+
+#include "DNA_meshdata_types.h"
+#include "BKE_customdata.h"
+#include "BKE_material.h"
+
+#include "collada_internal.h"
+
+// TODO: optimize UV sets by making indexed list with duplicates removed
+GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryGeometries(sw) {}
+
+
+void GeometryExporter::exportGeom(Scene *sce)
+{
+ openLibrary();
+
+ mScene = sce;
+ GeometryFunctor gf;
+ gf.forEachMeshObjectInScene<GeometryExporter>(sce, *this);
+
+ closeLibrary();
+}
+
+void GeometryExporter::operator()(Object *ob)
+{
+ // XXX don't use DerivedMesh, Mesh instead?
+
+#if 0
+ DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH);
+#endif
+ Mesh *me = (Mesh*)ob->data;
+ std::string geom_id = get_geometry_id(ob);
+ 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)
+ openMesh(geom_id);
+
+ // writes <source> for vertex coords
+ createVertsSource(geom_id, me);
+
+ // writes <source> for normal coords
+ createNormalsSource(geom_id, me, nor);
+
+ 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, me);
+
+ if (has_color)
+ createVertexColorSource(geom_id, me);
+
+ // <vertices>
+ COLLADASW::Vertices verts(mSW);
+ verts.setId(getIdBySemantics(geom_id, COLLADASW::VERTEX));
+ COLLADASW::InputList &input_list = verts.getInputList();
+ COLLADASW::Input input(COLLADASW::POSITION, getUrlBySemantics(geom_id, COLLADASW::POSITION));
+ input_list.push_back(input);
+ verts.add();
+
+ // XXX slow
+ if (ob->totcol) {
+ for(int a = 0; a < ob->totcol; a++) {
+ createPolylist(a, has_uvs, has_color, ob, geom_id, norind);
+ }
+ }
+ else {
+ createPolylist(0, has_uvs, has_color, ob, geom_id, norind);
+ }
+
+ closeMesh();
+ closeGeometry();
+
+#if 0
+ dm->release(dm);
+#endif
+}
+
+// powerful because it handles both cases when there is material and when there's not
+void GeometryExporter::createPolylist(int material_index,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ std::string& geom_id,
+ std::vector<Face>& norind)
+{
+ Mesh *me = (Mesh*)ob->data;
+ MFace *mfaces = me->mface;
+ int totfaces = me->totface;
+
+ // <vcount>
+ int i;
+ int faces_in_polylist = 0;
+ std::vector<unsigned long> vcount_list;
+
+ // count faces with this material
+ for (i = 0; i < totfaces; i++) {
+ MFace *f = &mfaces[i];
+
+ if (f->mat_nr == material_index) {
+ faces_in_polylist++;
+ if (f->v4 == 0) {
+ vcount_list.push_back(3);
+ }
+ else {
+ vcount_list.push_back(4);
+ }
+ }
+ }
+
+ // no faces using this material
+ if (faces_in_polylist == 0) {
+ fprintf(stderr, "%s: no faces use material %d\n", id_name(ob).c_str(), material_index);
+ return;
+ }
+
+ Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
+ COLLADASW::Polylist polylist(mSW);
+
+ // sets count attribute in <polylist>
+ polylist.setCount(faces_in_polylist);
+
+ // sets material name
+ if (ma) {
+ polylist.setMaterial(translate_id(id_name(ma)));
+ }
+
+ COLLADASW::InputList &til = polylist.getInputList();
+
+ // creates <input> in <polylist> for vertices
+ COLLADASW::Input input1(COLLADASW::VERTEX, getUrlBySemantics(geom_id, COLLADASW::VERTEX), 0);
+
+ // creates <input> in <polylist> for normals
+ COLLADASW::Input input2(COLLADASW::NORMAL, getUrlBySemantics(geom_id, COLLADASW::NORMAL), 1);
+
+ til.push_back(input1);
+ til.push_back(input2);
+
+ // if mesh has uv coords writes <input> for TEXCOORD
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+
+ for (i = 0; i < num_layers; i++) {
+ // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
+ COLLADASW::Input input3(COLLADASW::TEXCOORD,
+ makeUrl(makeTexcoordSourceId(geom_id, i)),
+ 2, // offset always 2, this is only until we have optimized UV sets
+ i // set number equals UV layer index
+ );
+ 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);
+
+ // performs the actual writing
+ polylist.prepareToAppendValues();
+
+ // <p>
+ int texindex = 0;
+ for (i = 0; i < totfaces; i++) {
+ MFace *f = &mfaces[i];
+
+ if (f->mat_nr == material_index) {
+
+ unsigned int *v = &f->v1;
+ unsigned int *n = &norind[i].v1;
+ for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
+ polylist.appendValues(v[j]);
+ polylist.appendValues(n[j]);
+
+ if (has_uvs)
+ polylist.appendValues(texindex + j);
+
+ if (has_color)
+ polylist.appendValues(texindex + j);
+ }
+ }
+
+ texindex += 3;
+ if (f->v4 != 0)
+ texindex++;
+ }
+
+ polylist.finish();
+}
+
+// creates <source> for positions
+void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
+{
+#if 0
+ int totverts = dm->getNumVerts(dm);
+ MVert *verts = dm->getVertArray(dm);
+#endif
+ int totverts = me->totvert;
+ MVert *verts = me->mvert;
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(getIdBySemantics(geom_id, COLLADASW::POSITION));
+ source.setArrayId(getIdBySemantics(geom_id, COLLADASW::POSITION) +
+ ARRAY_ID_SUFFIX);
+ source.setAccessorCount(totverts);
+ source.setAccessorStride(3);
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("X");
+ param.push_back("Y");
+ param.push_back("Z");
+ /*main function, it creates <source id = "">, <float_array id = ""
+ count = ""> */
+ source.prepareToAppendValues();
+ //appends data to <float_array>
+ int i = 0;
+ for (i = 0; i < totverts; i++) {
+ source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]);
+ }
+
+ source.finish();
+
+}
+
+void GeometryExporter::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 GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int layer_index)
+{
+ char suffix[20];
+ sprintf(suffix, "-%d", layer_index);
+ return getIdBySemantics(geom_id, COLLADASW::TEXCOORD) + suffix;
+}
+
+//creates <source> for texcoords
+void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
+{
+#if 0
+ int totfaces = dm->getNumFaces(dm);
+ MFace *mfaces = dm->getFaceArray(dm);
+#endif
+ int totfaces = me->totface;
+ MFace *mfaces = me->mface;
+
+ int totuv = 0;
+ int i;
+
+ // count totuv
+ for (i = 0; i < totfaces; i++) {
+ MFace *f = &mfaces[i];
+ if (f->v4 == 0) {
+ totuv+=3;
+ }
+ else {
+ totuv+=4;
+ }
+ }
+
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+
+ // write <source> for each layer
+ // each <source> will get id like meshName + "map-channel-1"
+ for (int a = 0; a < num_layers; a++) {
+ MTFace *tface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, a);
+ // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, a);
+
+ COLLADASW::FloatSourceF source(mSW);
+ std::string layer_id = makeTexcoordSourceId(geom_id, a);
+ source.setId(layer_id);
+ source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
+
+ source.setAccessorCount(totuv);
+ source.setAccessorStride(2);
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("S");
+ param.push_back("T");
+
+ source.prepareToAppendValues();
+
+ for (i = 0; i < totfaces; i++) {
+ MFace *f = &mfaces[i];
+
+ for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
+ source.appendValues(tface[i].uv[j][0],
+ tface[i].uv[j][1]);
+ }
+ }
+
+ source.finish();
+ }
+}
+
+
+//creates <source> for normals
+void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor)
+{
+#if 0
+ int totverts = dm->getNumVerts(dm);
+ MVert *verts = dm->getVertArray(dm);
+#endif
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(getIdBySemantics(geom_id, COLLADASW::NORMAL));
+ source.setArrayId(getIdBySemantics(geom_id, COLLADASW::NORMAL) +
+ ARRAY_ID_SUFFIX);
+ source.setAccessorCount((unsigned long)nor.size());
+ source.setAccessorStride(3);
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("X");
+ param.push_back("Y");
+ param.push_back("Z");
+
+ source.prepareToAppendValues();
+
+ std::vector<Normal>::iterator it;
+ for (it = nor.begin(); it != nor.end(); it++) {
+ Normal& n = *it;
+ source.appendValues(n.x, n.y, n.z);
+ }
+
+ source.finish();
+}
+
+void GeometryExporter::create_normals(std::vector<Normal> &nor, std::vector<Face> &ind, Mesh *me)
+{
+ int i, j, v;
+ MVert *vert = me->mvert;
+ std::map<unsigned int, unsigned int> nshar;
+
+ for (i = 0; i < me->totface; i++) {
+ MFace *fa = &me->mface[i];
+ Face f;
+ unsigned int *nn = &f.v1;
+ unsigned int *vv = &fa->v1;
+
+ memset(&f, 0, sizeof(f));
+ v = fa->v4 == 0 ? 3 : 4;
+
+ if (!(fa->flag & ME_SMOOTH)) {
+ Normal n;
+ if (v == 4)
+ normal_quad_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co, vert[fa->v4].co);
+ else
+ normal_tri_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co);
+ nor.push_back(n);
+ }
+
+ for (j = 0; j < v; j++) {
+ if (fa->flag & ME_SMOOTH) {
+ if (nshar.find(*vv) != nshar.end())
+ *nn = nshar[*vv];
+ else {
+ Normal n = {
+ vert[*vv].no[0]/32767.0,
+ vert[*vv].no[1]/32767.0,
+ vert[*vv].no[2]/32767.0
+ };
+ nor.push_back(n);
+ *nn = (unsigned int)nor.size() - 1;
+ nshar[*vv] = *nn;
+ }
+ vv++;
+ }
+ else {
+ *nn = (unsigned int)nor.size() - 1;
+ }
+ nn++;
+ }
+
+ ind.push_back(f);
+ }
+}
+
+std::string GeometryExporter::getIdBySemantics(std::string geom_id, COLLADASW::Semantics type, std::string other_suffix) {
+ return geom_id + getSuffixBySemantic(type) + other_suffix;
+}
+
+
+COLLADASW::URI GeometryExporter::getUrlBySemantics(std::string geom_id, COLLADASW::Semantics type, std::string other_suffix) {
+
+ std::string id(getIdBySemantics(geom_id, type, other_suffix));
+ return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
+
+}
+
+COLLADASW::URI GeometryExporter::makeUrl(std::string id)
+{
+ return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
+}
+
+
+/* int GeometryExporter::getTriCount(MFace *faces, int totface) {
+ int i;
+ int tris = 0;
+ for (i = 0; i < totface; i++) {
+ // if quad
+ if (faces[i].v4 != 0)
+ tris += 2;
+ else
+ tris++;
+ }
+
+ return tris;
+ }*/