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