- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Directories
- Examples

# STLExport/STLExporter.cpp

    //**************************************************************************/
    // Copyright (c) 2009 Autodesk, Inc.
    // All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk license
    // agreement provided at the time of installation or download, or which
    // otherwise accompanies this software in either electronic or hard copy form.
    //
    //**************************************************************************/
    // DESCRIPTION: Sample stereolithography (STL) file exporter.
    //
    //   Limitations
    //     - requires a single, closed mesh to work.
    //     - There will be no decimation done, so the mesh will be saved at full density,
    //         which might be too big for stereolithography shops.
    //     - Self-intersecting meshes
    //         are not corrected, which may cause problems with the resulting STL file.
    //
    // CREATED: February 2009
    //**************************************************************************/

    #include <stdio.h>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #include <fstream>
    #include <assert.h>
    #include <QtCore/QFile>

    #if defined(JAMBUILD)
    #include <Mudbox/mudbox.h>
    #else
    #include "../../include/Mudbox/mudbox.h"
    #endif

    #include "utility.hpp"

    namespace mudbox
    {

    // Creates a record in the memory to describe the plugin to Mudbox
    MB_PLUGIN( "STL Exporter", "STL file export plugin", "Autodesk", "http://www.mudbox3d.com", 0 );

    // Main plug-in declaration
    class STLExporter :
        public BaseExporter,
        public Singleton<STLExporter>
    {
    public:

        // The following line is used to expose RTTI information to Mudbox
        DECLARE_CLASS;

        // Default constructor, does nothing.
        STLExporter() {
        }

        // Return the supported file extension(s) by the plugin.
        virtual QString Extension() const { return "stl"; };

        virtual QString Description() const { return "Stereolithography File"; };

        virtual QVector<FileExtension> SupportedExtensions( void ) const
        {
            QVector<FileExtension> ret;
            ret.push_back(FileExtension("stl", "Stereolithography File"));
            return ret;
        }

        void Export( const QString &sFileName, const QString &sFormat = QString() )
        {
            if (GetNumMeshes() == 0)
                MB_ERROR("There are no meshes to export");
            if (GetNumMeshes() > 1)
                MB_ERROR("Multiple meshes can not be exported to this format");

            const Mesh* m = GetMesh(0);

            if (IsMeshOpen(m))
                MB_ERROR("Only continuous meshes can be exported");

            QFile ofile(sFileName);
            ofile.open(QFile::WriteOnly);

            const uint STL_HEADER_SIZE = 80;
            char header[STL_HEADER_SIZE] = "";
            std::fill(header, header + STL_HEADER_SIZE, 0);
            ofile.write(header, STL_HEADER_SIZE);

            // output the total number of faces
            uint32 cnt = m->FaceCount();
            if ( m->Type() == Mesh::typeQuadric )
                cnt *= 2;
            WriteUInt32(ofile, cnt);

            // Write each triangle face to file
            if ( m->Type() == Mesh::typeTriangular )
            {
                for ( uint i = 0; i < m->FaceCount(); ++i ) {
                    // Write the normal vector
                    const Vector& normal = m->FaceNormal(i);
                    WriteVectorFloat32(ofile, normal);

                    // three sets of three 32-bit floats specifying the position of each vertex
                    for (uint j = 0; j < 3; ++j) {
                        const Vector& v = m->TriangleVertexPosition( i, j );
                        WriteVectorFloat32(ofile, v);
                    }

                    // 2-byte padding
                    WriteUInt16(ofile, 0);
                }
            }
            // Write each quadric face as two triangles
            else if ( m->Type() == Mesh::typeQuadric )
            {
                for ( uint i = 0; i < m->FaceCount(); ++i ) {
                    // Write the normal vector
                    const Vector& normal = m->FaceNormal(i);
                    WriteVectorFloat32(ofile, normal);

                    // Get first sub-triangle using corners 0, 2, and 3 of quad
                    for (uint j = 0; j < 4; ++j) {
                        if (j != 1) {
                            const Vector& v = m->QuadVertexPosition( i, j );
                            WriteVectorFloat32(ofile, v);
                        }
                    }

                    // 2-byte padding
                    WriteUInt16(ofile, 0);

                    // Write the normal vector again (both triangles share the same normal)
                    WriteVectorFloat32(ofile, normal);

                    // Get second sub-triangle using corners 0, 1, and 2 of quad
                    for (uint j = 0; j < 4; ++j) {
                        if (j != 3) {
                            const Vector& v = m->QuadVertexPosition( i, j );
                            WriteVectorFloat32(ofile, v);
                        }
                    }

                    // 2-byte padding
                    WriteUInt16(ofile, 0);
                }
            }

            ofile.close();
        };
    };

    // RTTI information
    IMPLEMENT_CLASS( STLExporter, Exporter, "STL Exporter" );

    } // namespace mudbox