1
//##########################################################################
5
//# This program is free software; you can redistribute it and/or modify #
6
//# it under the terms of the GNU General Public License as published by #
7
//# the Free Software Foundation; version 2 or later of the License. #
9
//# This program is distributed in the hope that it will be useful, #
10
//# but WITHOUT ANY WARRANTY; without even the implied warranty of #
11
//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
12
//# GNU General Public License for more details. #
14
//# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) #
16
//##########################################################################
22
#include <ccPointCloud.h>
24
#include <ccProgressDialog.h>
33
bool MAFilter::canLoadExtension(QString upperCaseExt) const
35
//import not supported
39
bool MAFilter::canSave(CC_CLASS_ENUM type, bool& multiple, bool& exclusive) const
41
if (type == CC_TYPES::MESH)
54
unsigned theOtherPoint;
58
void ReleaseEdgeList(edge**& theEdges, unsigned numberOfVertexes, CCLib::NormalizedProgress* nprogress = 0)
60
for (unsigned i = 0; i < numberOfVertexes; ++i)
64
edge* e = theEdges[i]->nextEdge;
67
edge* nextE = e->nextEdge;
86
faceIndexes* nextFace;
89
CC_FILE_ERROR MAFilter::saveToFile(ccHObject* entity, QString filename, SaveParameters& parameters)
91
if (!entity || filename.isEmpty())
92
return CC_FERR_BAD_ARGUMENT;
95
ccGenericMesh* theMesh = ccHObjectCaster::ToGenericMesh(entity);
98
ccLog::Error("[MA] This filter can only save one mesh at a time!");
99
return CC_FERR_BAD_ENTITY_TYPE;
102
ccGenericPointCloud* theCloud = theMesh->getAssociatedCloud();
104
unsigned numberOfTriangles = theMesh->size();
105
unsigned numberOfVertexes = theCloud->size();
107
if (numberOfTriangles == 0 || numberOfVertexes == 0)
109
ccLog::Error("Mesh is empty!");
110
return CC_FERR_BAD_ENTITY_TYPE;
113
bool hasColors = false;
114
if (theCloud->isA(CC_TYPES::POINT_CLOUD))
115
static_cast<ccPointCloud*>(theCloud)->hasColors();
117
//and its scalar field
118
//ccScalarField* sf = 0;
119
//if (theCloud->isA(CC_TYPES::POINT_CLOUD))
120
// sf = static_cast<ccPointCloud*>(theCloud)->getCurrentDisplayedScalarField();
123
// ccLog::Warning("No displayed scalar field! Values will all be 0!\n");
125
//open ASCII file for writing
126
FILE* fp = fopen(qPrintable(filename) , "wt");
129
return CC_FERR_WRITING;
132
QScopedPointer<ccProgressDialog> pDlg(0);
133
const int coloursAdjustment = (hasColors ? 1 : 0);
134
if (parameters.parentWidget)
136
pDlg.reset(new ccProgressDialog(true, parameters.parentWidget)); //cancel available
137
pDlg->setMethodTitle(QObject::tr("Save MA file"));
138
pDlg->setInfo(QObject::tr("Triangles = %1").arg(numberOfTriangles));
141
CCLib::NormalizedProgress nprogress(pDlg.data(), ((2 + coloursAdjustment) * numberOfTriangles + (3 + coloursAdjustment) * numberOfVertexes));
143
//we extract the (short) filename from the whole path
144
QString baseFilename = QFileInfo(filename).fileName();
147
if (fprintf(fp,"//Maya ASCII 7.0 scene\n") < 0)
148
{fclose(fp);return CC_FERR_WRITING;}
149
if (fprintf(fp,"//Name: %s\n",qPrintable(baseFilename)) < 0)
150
{fclose(fp);return CC_FERR_WRITING;}
151
if (fprintf(fp,"//Last modified: Sat, Mai 10, 2008 00:00:00 PM\n") < 0)
152
{fclose(fp);return CC_FERR_WRITING;}
153
if (fprintf(fp,"requires maya \"4.0\";\n") < 0)
154
{fclose(fp);return CC_FERR_WRITING;}
155
if (fprintf(fp,"currentUnit -l %s -a degree -t film;\n","centimeter") < 0)
156
{fclose(fp);return CC_FERR_WRITING;}
158
//for multiple meshes handling (does not work yet)
159
unsigned char currentMesh = 0;
161
//transformation node
162
if (fprintf(fp,"createNode transform -n \"Mesh%i\";\n",currentMesh+1) < 0)
163
{fclose(fp);return CC_FERR_WRITING;}
166
if (fprintf(fp,"createNode mesh -n \"MeshShape%i\" -p \"Mesh%i\";\n",currentMesh+1,currentMesh+1) < 0)
167
{fclose(fp);return CC_FERR_WRITING;}
169
if (fprintf(fp,"\tsetAttr -k off \".v\";\n") < 0)
170
{fclose(fp);return CC_FERR_WRITING;}
172
if (fprintf(fp,"\tsetAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n") < 0)
173
{fclose(fp);return CC_FERR_WRITING;}
174
if (fprintf(fp,"\tsetAttr \".cuvs\" -type \"string\" \"map1\";\n") < 0)
175
{fclose(fp);return CC_FERR_WRITING;}
178
if (fprintf(fp,"\tsetAttr \".dcol\" yes;\n") < 0)
179
{fclose(fp);return CC_FERR_WRITING;}
181
if (fprintf(fp,"\tsetAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n") < 0)
182
{fclose(fp);return CC_FERR_WRITING;}
183
if (fprintf(fp,"\tsetAttr \".ccls\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
184
{fclose(fp);return CC_FERR_WRITING;}
185
if (fprintf(fp,"\tsetAttr \".clst[0].clsn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
186
{fclose(fp);return CC_FERR_WRITING;}
189
if (fprintf(fp,"\tsetAttr \".ndt\" 0;\n") < 0)
190
{fclose(fp);return CC_FERR_WRITING;}
191
if (fprintf(fp,"\tsetAttr \".tgsp\" 1;\n") < 0)
192
{fclose(fp);return CC_FERR_WRITING;}
194
//insert a secondary nodes
195
if (fprintf(fp,"createNode mesh -n \"polySurfaceShape%i\" -p \"Mesh%i\";\n",currentMesh+1,currentMesh+1) < 0)
196
{fclose(fp);return CC_FERR_WRITING;}
198
if (fprintf(fp,"\tsetAttr -k off \".v\";\n") < 0)
199
{fclose(fp);return CC_FERR_WRITING;}
200
if (fprintf(fp,"\tsetAttr \".io\" yes;\n") < 0)
201
{fclose(fp);return CC_FERR_WRITING;}
202
if (fprintf(fp,"\tsetAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n") < 0)
203
{fclose(fp);return CC_FERR_WRITING;}
204
if (fprintf(fp,"\tsetAttr \".cuvs\" -type \"string\" \"map1\";\n") < 0)
205
{fclose(fp);return CC_FERR_WRITING;}
206
if (fprintf(fp,"\tsetAttr \".dcol\" yes;\n") < 0)
207
{fclose(fp);return CC_FERR_WRITING;}
208
if (fprintf(fp,"\tsetAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n") < 0)
209
{fclose(fp);return CC_FERR_WRITING;}
210
if (fprintf(fp,"\tsetAttr \".ccls\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
211
{fclose(fp);return CC_FERR_WRITING;}
212
if (fprintf(fp,"\tsetAttr \".clst[0].clsn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
213
{fclose(fp);return CC_FERR_WRITING;}
217
if (fprintf(fp,"\tsetAttr -s %u \".vt[0:%u]\"\n",numberOfVertexes,numberOfVertexes-1) < 0)
220
return CC_FERR_WRITING;
223
for (unsigned i = 0; i < numberOfVertexes; ++i)
225
const CCVector3* P = theCloud->getPoint(i);
226
CCVector3d Pglobal = theCloud->toGlobal3d<PointCoordinateType>(*P);
227
if (fprintf(fp, (i + 1 == numberOfVertexes ? "\t\t%f %f %f;\n" : "\t\t%f %f %f\n"),
233
return CC_FERR_WRITING;
244
edge** theEdges = new edge*[numberOfVertexes];
245
memset(theEdges,0,sizeof(edge*)*numberOfVertexes);
246
unsigned ind[3], a, b;
247
int lastEdgeIndexPushed = -1;
249
int hard = 0; //Maya edges cab be "hard" or "soft" ...
252
theMesh->placeIteratorAtBegining();
253
for (unsigned i = 0; i < numberOfTriangles; ++i)
255
const CCLib::VerticesIndexes* tsi = theMesh->getNextTriangleVertIndexes(); //DGM: getNextTriangleVertIndexes is faster for mesh groups!
261
for (unsigned char k=0; k<3; ++k)
263
unsigned char l = (k<2 ? k+1 : 0);
264
a = (ind[k]<ind[l] ? ind[k] : ind[l]);
265
b = (a==ind[k] ? ind[l] : ind[k]);
267
int currentEdgeIndex = -1;
268
edge* e = theEdges[a];
271
if (e->theOtherPoint == b)
273
currentEdgeIndex = e->edgeIndex;
279
if (currentEdgeIndex < 0) //create a new edge
281
edge* newEdge = new edge;
282
newEdge->nextEdge = NULL;
283
newEdge->theOtherPoint = b;
284
newEdge->positif = (a == ind[k]);
285
//newEdge->edgeIndex = ++lastEdgeIndexPushed; //don't write the edge right now
286
newEdge->edgeIndex = 0;
287
++lastEdgeIndexPushed;
288
//currentEdgeIndex = lastEdgeIndexPushed;
290
//don't forget the node!
296
e->nextEdge = newEdge;
300
theEdges[a] = newEdge;
303
/*if (fprintf(fp,"\n \t\t%i %i %i",a,b,hard) < 0)
304
return CC_FERR_WRITING;*/
315
//now write the edges
317
unsigned numberOfEdges = static_cast<unsigned>(lastEdgeIndexPushed+1);
318
if (fprintf(fp,"\tsetAttr -s %u \".ed[0:%u]\"",numberOfEdges,numberOfEdges-1) < 0)
321
ReleaseEdgeList(theEdges, numberOfVertexes);
322
return CC_FERR_WRITING;
325
lastEdgeIndexPushed = 0;
326
for (unsigned i=0; i<numberOfVertexes; ++i)
328
edge* e = theEdges[i];
331
e->edgeIndex = lastEdgeIndexPushed++;
332
if (fprintf(fp,"\n \t\t%u %u %i",i,e->theOtherPoint,hard) < 0)
335
ReleaseEdgeList(theEdges, numberOfVertexes);
336
return CC_FERR_WRITING;
348
if (fprintf(fp,";\n") < 0)
351
ReleaseEdgeList(theEdges, numberOfVertexes);
352
return CC_FERR_WRITING;
356
if (fprintf(fp,"\tsetAttr -s %u \".fc[0:%u]\" -type \"polyFaces\"\n",numberOfTriangles,numberOfTriangles-1) < 0)
359
ReleaseEdgeList(theEdges, numberOfVertexes);
360
return CC_FERR_WRITING;
363
theMesh->placeIteratorAtBegining();
365
for (unsigned i=0; i<numberOfTriangles; ++i)
367
if (fprintf(fp,"\t\tf 3") < 0)
370
ReleaseEdgeList(theEdges, numberOfVertexes);
371
return CC_FERR_WRITING;
374
CCLib::VerticesIndexes* tsi = theMesh->getNextTriangleVertIndexes(); //DGM: getNextTriangleVertIndexes is faster for mesh groups!
379
for (unsigned char k=0; k<3; ++k)
381
unsigned char l = (k<2 ? k+1 : 0);
382
a = (ind[k]<ind[l] ? ind[k] : ind[l]);
383
b = (a==ind[k] ? ind[l] : ind[k]);
385
edge* e = theEdges[a];
386
while (e->theOtherPoint != b)
389
if (fprintf(fp," %i",((e->positif && a==ind[k]) || (!e->positif && a==ind[l]) ? e->edgeIndex : -(e->edgeIndex+1))) < 0)
392
ReleaseEdgeList(theEdges, numberOfVertexes);
393
return CC_FERR_WRITING;
397
if (fprintf(fp,(i+1==numberOfTriangles ? ";\n" : "\n")) < 0)
400
ReleaseEdgeList(theEdges, numberOfVertexes);
401
return CC_FERR_WRITING;
413
ReleaseEdgeList(theEdges, numberOfVertexes, pDlg ? &nprogress : 0);
417
if ( fprintf(fp,"\tsetAttr \".cd\" -type \"dataPolyComponent\" Index_Data Edge 0 ;\n") < 0
418
|| fprintf(fp,"\tsetAttr \".ndt\" 0;\n") < 0
419
|| fprintf(fp,"\tsetAttr \".tgsp\" 1;\n") < 0 )
422
return CC_FERR_WRITING;
428
assert(theCloud->isA(CC_TYPES::POINT_CLOUD));
429
ccPointCloud* pc = static_cast<ccPointCloud*>(theCloud);
431
if (fprintf(fp,"createNode polyColorPerVertex -n \"polyColorPerVertex%i\";\n",currentMesh+1) < 0)
432
{fclose(fp);return CC_FERR_WRITING;}
434
if (fprintf(fp,"\tsetAttr \".uopa\" yes;\n") < 0)
435
{fclose(fp);return CC_FERR_WRITING;}
437
if (fprintf(fp,"\tsetAttr -s %u \".vclr\";\n",numberOfVertexes) < 0)
438
{fclose(fp);return CC_FERR_WRITING;}
440
//association of each vertex with the faces it belongs to
441
faceIndexes** theFacesIndexes = new faceIndexes*[numberOfVertexes];
442
memset(theFacesIndexes,0,sizeof(faceIndexes*)*numberOfVertexes);
443
theMesh->placeIteratorAtBegining();
445
for (unsigned i=0; i<numberOfTriangles; ++i)
447
CCLib::VerticesIndexes* tsi = theMesh->getNextTriangleVertIndexes(); //DGM: getNextTriangleVertIndexes is faster for mesh groups!
452
for (unsigned char j=0; j<3; ++j)
454
if (!theFacesIndexes[ind[j]])
456
faceIndexes* f = new faceIndexes;
459
theFacesIndexes[ind[j]] = f;
463
faceIndexes* f = theFacesIndexes[ind[j]];
466
f->nextFace = new faceIndexes;
467
f->nextFace->faceIndex = i;
468
f->nextFace->nextFace = NULL;
481
for (unsigned i = 0; i < numberOfVertexes; ++i)
483
const ColorCompType* c = pc->getPointColor(i);
484
ccColor::Rgbf col( static_cast<float>(c[0])/ccColor::MAX,
485
static_cast<float>(c[1])/ccColor::MAX,
486
static_cast<float>(c[2])/ccColor::MAX);
488
//on compte le nombre de faces
490
faceIndexes* f = theFacesIndexes[i];
499
if (fprintf(fp,"\tsetAttr -s %i \".vclr[%u].vfcl\";\n",nf,i) < 0)
502
delete[] theFacesIndexes; //DGM: we are missing some faces here, aren't we?
503
return CC_FERR_WRITING;
506
faceIndexes* f = theFacesIndexes[i];
509
if (fprintf(fp,"\tsetAttr \".vclr[%u].vfcl[%i].frgb\" -type \"float3\" %f %f %f;\n",i,f->faceIndex,col.r,col.g,col.b) < 0)
512
delete[] theFacesIndexes; //DGM: we are missing some faces here, aren't we?
513
return CC_FERR_WRITING;
516
faceIndexes* oldf = f;
520
theFacesIndexes[i] = NULL;
529
delete[] theFacesIndexes;
532
if (fprintf(fp,"\tsetAttr \".cn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
535
return CC_FERR_WRITING;
542
if ( fprintf(fp,"connectAttr \"polyColorPerVertex%i.out\" \"MeshShape%i.i\";\n",currentMesh+1,currentMesh+1) < 0
543
|| fprintf(fp,"connectAttr \"polySurfaceShape%i.o\" \"polyColorPerVertex%i.ip\";\n",currentMesh+1,currentMesh+1) < 0 )
546
return CC_FERR_WRITING;
550
if (fprintf(fp,"connectAttr \"MeshShape%i.iog\" \":initialShadingGroup.dsm\" -na;\n",currentMesh+1) < 0)
553
return CC_FERR_WRITING;
557
if (fprintf(fp,"//End of %s\n",qPrintable(baseFilename)) < 0)
560
return CC_FERR_WRITING;
565
return CC_FERR_NO_ERROR;