31 unsigned theOtherPoint;
35 static void ReleaseEdgeList(
37 unsigned numberOfVertexes,
39 for (
unsigned i = 0; i < numberOfVertexes; ++i) {
41 edge* e = theEdges[i]->nextEdge;
43 edge* nextE = e->nextEdge;
60 faceIndexes* nextFace;
67 QStringList(),
"ma", QStringList(),
68 QStringList{
"Maya ASCII mesh (*.ma)"},
Export}) {}
72 bool& exclusive)
const {
89 CVLog::Error(
"[MA] This filter can only save one mesh at a time!");
95 unsigned numberOfTriangles = theMesh->
size();
96 unsigned numberOfVertexes = theCloud->
size();
98 if (numberOfTriangles == 0 || numberOfVertexes == 0) {
103 bool hasColors =
false;
117 FILE* fp = fopen(qPrintable(
filename),
"wt");
122 QScopedPointer<ecvProgressDialog> pDlg(
nullptr);
123 const int coloursAdjustment = (hasColors ? 1 : 0);
127 pDlg->setMethodTitle(QObject::tr(
"Save MA file"));
128 pDlg->setInfo(QObject::tr(
"Triangles = %1").arg(numberOfTriangles));
132 pDlg.data(), ((2 + coloursAdjustment) * numberOfTriangles +
133 (3 + coloursAdjustment) * numberOfVertexes));
136 QString baseFilename = QFileInfo(
filename).fileName();
142 if (fprintf(fp,
"//Maya ASCII 7.0 scene\n") < 0) {
146 if (fprintf(fp,
"//Name: %s\n", qPrintable(baseFilename)) < 0) {
150 if (fprintf(fp,
"//Last modified: %s\n",
151 qPrintable(QDateTime::currentDateTime().
toString(
152 Qt::ISODateWithMs))) < 0) {
156 if (fprintf(fp,
"requires maya \"4.0\";\n") < 0) {
160 if (fprintf(fp,
"currentUnit -l %s -a degree -t film;\n",
"centimeter") <
167 if (fprintf(fp,
"fileInfo \"application\" \"%s\"\n",
173 if (fprintf(fp,
"fileInfo \"product\" \"%s\"\n",
179 if (fprintf(fp,
"fileInfo \"version\" \"%s\"\n",
186 unsigned char currentMesh = 0;
189 if (fprintf(fp,
"createNode transform -n \"Mesh%i\";\n", currentMesh + 1) <
196 if (fprintf(fp,
"createNode mesh -n \"MeshShape%i\" -p \"Mesh%i\";\n",
197 currentMesh + 1, currentMesh + 1) < 0) {
202 if (fprintf(fp,
"\tsetAttr -k off \".v\";\n") < 0) {
208 "\tsetAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n") <
213 if (fprintf(fp,
"\tsetAttr \".cuvs\" -type \"string\" \"map1\";\n") < 0) {
218 if (fprintf(fp,
"\tsetAttr \".dcol\" yes;\n") < 0) {
224 "\tsetAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n") <
229 if (fprintf(fp,
"\tsetAttr \".ccls\" -type \"string\" \"colorSet%i\";\n",
230 currentMesh + 1) < 0) {
235 "\tsetAttr \".clst[0].clsn\" -type \"string\" "
237 currentMesh + 1) < 0) {
242 if (fprintf(fp,
"\tsetAttr \".ndt\" 0;\n") < 0) {
246 if (fprintf(fp,
"\tsetAttr \".tgsp\" 1;\n") < 0) {
253 "createNode mesh -n \"polySurfaceShape%i\" -p "
255 currentMesh + 1, currentMesh + 1) < 0) {
260 if (fprintf(fp,
"\tsetAttr -k off \".v\";\n") < 0) {
264 if (fprintf(fp,
"\tsetAttr \".io\" yes;\n") < 0) {
269 "\tsetAttr \".uvst[0].uvsn\" -type \"string\" "
270 "\"map1\";\n") < 0) {
274 if (fprintf(fp,
"\tsetAttr \".cuvs\" -type \"string\" \"map1\";\n") <
279 if (fprintf(fp,
"\tsetAttr \".dcol\" yes;\n") < 0) {
284 "\tsetAttr \".dcc\" -type \"string\" "
285 "\"Ambient+Diffuse\";\n") < 0) {
290 "\tsetAttr \".ccls\" -type \"string\" \"colorSet%i\";\n",
291 currentMesh + 1) < 0) {
296 "\tsetAttr \".clst[0].clsn\" -type \"string\" "
298 currentMesh + 1) < 0) {
305 if (fprintf(fp,
"\tsetAttr -s %u \".vt[0:%u]\"\n", numberOfVertexes,
306 numberOfVertexes - 1) < 0) {
311 for (
unsigned i = 0; i < numberOfVertexes; ++i) {
315 (i + 1 == numberOfVertexes ?
"\t\t%f %f %f;\n"
317 Pglobal.
x, Pglobal.
y, Pglobal.
z) < 0) {
329 edge** theEdges =
new edge*[numberOfVertexes];
330 memset(theEdges, 0,
sizeof(edge*) * numberOfVertexes);
331 unsigned ind[3]{0, 0, 0};
334 int lastEdgeIndexPushed = -1;
339 for (
unsigned i = 0; i < numberOfTriangles; ++i) {
350 for (
unsigned char k = 0; k < 3; ++k) {
351 unsigned char l = (k < 2 ? k + 1 : 0);
352 a = (ind[k] < ind[l] ? ind[k] : ind[l]);
353 b = (a == ind[k] ? ind[l] : ind[k]);
355 int currentEdgeIndex = -1;
356 edge* e = theEdges[a];
358 if (e->theOtherPoint == b) {
359 currentEdgeIndex = e->edgeIndex;
365 if (currentEdgeIndex < 0)
367 edge* newEdge =
new edge;
368 newEdge->nextEdge =
nullptr;
369 newEdge->theOtherPoint = b;
370 newEdge->positif = (a == ind[k]);
373 newEdge->edgeIndex = 0;
374 ++lastEdgeIndexPushed;
380 while (e->nextEdge) e = e->nextEdge;
381 e->nextEdge = newEdge;
383 theEdges[a] = newEdge;
399 unsigned numberOfEdges =
static_cast<unsigned>(lastEdgeIndexPushed + 1);
400 if (fprintf(fp,
"\tsetAttr -s %u \".ed[0:%u]\"", numberOfEdges,
401 numberOfEdges - 1) < 0) {
403 ReleaseEdgeList(theEdges, numberOfVertexes);
407 lastEdgeIndexPushed = 0;
408 for (
unsigned i = 0; i < numberOfVertexes; ++i) {
409 edge* e = theEdges[i];
411 e->edgeIndex = lastEdgeIndexPushed++;
412 if (fprintf(fp,
"\n \t\t%u %u %i", i, e->theOtherPoint, hard) <
415 ReleaseEdgeList(theEdges, numberOfVertexes);
427 if (fprintf(fp,
";\n") < 0) {
429 ReleaseEdgeList(theEdges, numberOfVertexes);
434 if (fprintf(fp,
"\tsetAttr -s %u \".fc[0:%u]\" -type \"polyFaces\"\n",
435 numberOfTriangles, numberOfTriangles - 1) < 0) {
437 ReleaseEdgeList(theEdges, numberOfVertexes);
443 for (
unsigned i = 0; i < numberOfTriangles; ++i) {
444 if (fprintf(fp,
"\t\tf 3") < 0) {
446 ReleaseEdgeList(theEdges, numberOfVertexes);
459 for (
unsigned char k = 0; k < 3; ++k) {
460 unsigned char l = (k < 2 ? k + 1 : 0);
461 a = (ind[k] < ind[l] ? ind[k] : ind[l]);
462 b = (a == ind[k] ? ind[l] : ind[k]);
464 edge* e = theEdges[a];
465 while (e->theOtherPoint != b) e = e->nextEdge;
467 if (fprintf(fp,
" %i",
468 ((e->positif && a == ind[k]) ||
469 (!e->positif && a == ind[l])
471 : -(e->edgeIndex + 1))) < 0) {
473 ReleaseEdgeList(theEdges, numberOfVertexes);
478 if (fprintf(fp, (i + 1 == numberOfTriangles ?
";\n" :
"\n")) < 0) {
480 ReleaseEdgeList(theEdges, numberOfVertexes);
492 ReleaseEdgeList(theEdges, numberOfVertexes,
493 pDlg ? &nprogress :
nullptr);
498 "\tsetAttr \".cd\" -type \"dataPolyComponent\" Index_Data Edge "
500 fprintf(fp,
"\tsetAttr \".ndt\" 0;\n") < 0 ||
501 fprintf(fp,
"\tsetAttr \".tgsp\" 1;\n") < 0) {
512 "createNode polyColorPerVertex -n "
513 "\"polyColorPerVertex%i\";\n",
514 currentMesh + 1) < 0) {
519 if (fprintf(fp,
"\tsetAttr \".uopa\" yes;\n") < 0) {
524 if (fprintf(fp,
"\tsetAttr -s %u \".vclr\";\n", numberOfVertexes) < 0) {
530 faceIndexes** theFacesIndexes =
new faceIndexes*[numberOfVertexes];
531 memset(theFacesIndexes, 0,
sizeof(faceIndexes*) * numberOfVertexes);
534 for (
unsigned i = 0; i < numberOfTriangles; ++i) {
544 for (
unsigned char j = 0; j < 3; ++j) {
545 if (!theFacesIndexes[ind[j]]) {
546 faceIndexes* f =
new faceIndexes;
548 f->nextFace =
nullptr;
549 theFacesIndexes[ind[j]] = f;
551 faceIndexes* f = theFacesIndexes[ind[j]];
552 while (f->nextFace) f = f->nextFace;
553 f->nextFace =
new faceIndexes;
554 f->nextFace->faceIndex = i;
555 f->nextFace->nextFace =
nullptr;
567 for (
unsigned i = 0; i < numberOfVertexes; ++i) {
575 faceIndexes* f = theFacesIndexes[i];
582 if (fprintf(fp,
"\tsetAttr -s %i \".vclr[%u].vfcl\";\n", nf,
585 delete[] theFacesIndexes;
590 faceIndexes* f = theFacesIndexes[i];
593 "\tsetAttr \".vclr[%u].vfcl[%i].frgb\" "
594 "-type \"float3\" %f %f %f;\n",
595 i, f->faceIndex, col.
r, col.
g, col.
b) < 0) {
597 delete[] theFacesIndexes;
603 faceIndexes* oldf = f;
607 theFacesIndexes[i] =
nullptr;
615 delete[] theFacesIndexes;
616 theFacesIndexes =
nullptr;
618 if (fprintf(fp,
"\tsetAttr \".cn\" -type \"string\" \"colorSet%i\";\n",
619 currentMesh + 1) < 0) {
628 "connectAttr \"polyColorPerVertex%i.out\" "
629 "\"MeshShape%i.i\";\n",
630 currentMesh + 1, currentMesh + 1) < 0 ||
632 "connectAttr \"polySurfaceShape%i.o\" "
633 "\"polyColorPerVertex%i.ip\";\n",
634 currentMesh + 1, currentMesh + 1) < 0) {
641 "connectAttr \"MeshShape%i.iog\" \":initialShadingGroup.dsm\" "
643 currentMesh + 1) < 0) {
649 if (fprintf(fp,
"//End of %s\n", qPrintable(baseFilename)) < 0) {
float PointCoordinateType
Type of the coordinates of a (N-D) point.
int64_t CV_CLASS_ENUM
Type of object type flags (64 bits)
CC_FILE_ERROR
Typical I/O filter errors.
@ CC_FERR_BAD_ENTITY_TYPE
static bool Error(const char *format,...)
Display an error dialog with formatted message.
static constexpr float DEFAULT_PRIORITY
static QString writerInfo()
static QString applicationName()
virtual bool canSave(CV_CLASS_ENUM type, bool &multiple, bool &exclusive) const override
Returns whether this I/O filter can save the specified type of entity.
virtual CC_FILE_ERROR saveToFile(ccHObject *entity, const QString &filename, const SaveParameters ¶meters) override
Saves an entity (or a group of) to a file.
virtual ccGenericPointCloud * getAssociatedCloud() const =0
Returns the vertices cloud.
A 3D cloud interface with associated features (color, normals, octree, etc.)
static ccGenericMesh * ToGenericMesh(ccHObject *obj)
Converts current object to ccGenericMesh (if possible)
Hierarchical CLOUDVIEWER Object.
bool isA(CV_CLASS_ENUM type) const
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
const ecvColor::Rgb & getPointColor(unsigned pointIndex) const override
Returns color corresponding to a given point.
CCVector3d toGlobal3d(const Vector3Tpl< T > &Plocal) const
Returns the point back-projected into the original coordinates system.
virtual unsigned size() const =0
Returns the number of points.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
virtual VerticesIndexes * getNextTriangleVertIndexes()=0
virtual unsigned size() const =0
Returns the number of triangles.
virtual void placeIteratorAtBeginning()=0
Places the mesh iterator at the beginning.
bool oneStep()
Increments total progress value of a single unit.
Graphical progress indicator (thread-safe)
std::string toString(T x)
constexpr ColorCompType MAX
Max value of a single color component (default type)
Generic saving parameters.
QWidget * parentWidget
Parent widget (if any)
Triangle described by the indexes of its 3 vertices.