以此纪念我的伯父,数学教育家钟载硕

  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  4 随笔 :: 0 文章 :: 1 评论 :: 0 Trackbacks

// Copyright (C) 2000 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
///////////////////////////////////////////////////////////////////////////////
// EXPORTER.CPP
//
// DESCR:
//     Main MAX Class Implementation
//
// CHANGE LOG:
//     12/99 : DY : Created
//  09/2001 : rjc : modifications to bring it up to 3ds max r4.2 spec
//
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "exporter.h"
#include <time.h>

///////////////////////////////////////////////////////////////////////////////
// MAX Class Descriptor
//
///////////////////////////////////////////////////////////////////////////////

class MyExporterClassDesc : public ClassDesc2
{
public:
    int             IsPublic()              { return TRUE; }
    void *          Create(BOOL loading)    { return new MyExporter; }
    const TCHAR *   ClassName()             { return GetString(IDS_CLASSNAME); }
    SClass_ID       SuperClassID()          { return SCENE_EXPORT_CLASS_ID; }
    Class_ID        ClassID()               { return MYEXP_CLASSID; }
    const TCHAR*    Category()              { return _T("");  }

    // Hardwired name, used by MAX Script as unique identifier (not localized)
    const TCHAR*    InternalName()          { return _T("MyExporter"); }
    HINSTANCE       HInstance()             { return g_hInstance; }
};

static MyExporterClassDesc g_ExportCD;

ClassDesc* GetSceneExportDesc()
{
    return &g_ExportCD;
}


///////////////////////////////////////////////////////////////////////////////
// Constructor/Destructor
//
///////////////////////////////////////////////////////////////////////////////

MyExporter::MyExporter()
: m_exportSelected(false)
, m_suppressPrompts(false)
, m_ip(NULL)
, m_expip(NULL)
, m_fileStream(NULL)
{
}

MyExporter::~MyExporter()
{
}


///////////////////////////////////////////////////////////////////////////////
// (SceneExport overrides)
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Returns the number of file name extensions supported by the plug-in.
///////////////////////////////////////////////////////////////////////////////

int MyExporter::ExtCount()
{
    return 1;
}

///////////////////////////////////////////////////////////////////////////////
// Returns the 'n-th' file name extension (i.e. "3DS").
///////////////////////////////////////////////////////////////////////////////

const TCHAR * MyExporter::Ext(int n)
{
    switch(n) {
    case 0:
        return (_T(MYEXP_EXT));
    }
    return _T("");
}


///////////////////////////////////////////////////////////////////////////////
// Returns a long ASCII description of the file type being exported
// (i.e. "Autodesk 3D Studio File").
///////////////////////////////////////////////////////////////////////////////

const TCHAR * MyExporter::LongDesc()
{
    // (NOTE: Unlike the extension, this, and various other subsequent
    // description strings can be localized, so we keep 'em in the string table)
    return GetString(IDS_LONGDESC);
}

///////////////////////////////////////////////////////////////////////////////
// Returns a short ASCII description of the file type being exported
// (i.e. "3D Studio").
///////////////////////////////////////////////////////////////////////////////

const TCHAR * MyExporter::ShortDesc()
{
    return GetString(IDS_SHORTDESC);
}

///////////////////////////////////////////////////////////////////////////////
// Returns the ASCII Author name.
///////////////////////////////////////////////////////////////////////////////

const TCHAR * MyExporter::AuthorName()
{
    return GetString(IDS_AUTHOR);
}

///////////////////////////////////////////////////////////////////////////////
// Returns the ASCII Copyright message for the plug-in.
///////////////////////////////////////////////////////////////////////////////

const TCHAR * MyExporter::CopyrightMessage()
{
    return GetString(IDS_COPYRIGHT);
}

///////////////////////////////////////////////////////////////////////////////
// Returns the first message string that is displayed.
///////////////////////////////////////////////////////////////////////////////

const TCHAR * MyExporter::OtherMessage1()
{
    return GetString(IDS_OTHER1);
}

///////////////////////////////////////////////////////////////////////////////
// Returns the second message string that is displayed.
///////////////////////////////////////////////////////////////////////////////

const TCHAR * MyExporter::OtherMessage2()
{
    return GetString(IDS_OTHER2);
}


///////////////////////////////////////////////////////////////////////////////
// Returns the version number of the export plug-in. 
// The format is the version number * 100 (i.e. v3.01 = 301).
///////////////////////////////////////////////////////////////////////////////

unsigned int MyExporter::Version()
{
    return MYEXP_VER;
}

 

///////////////////////////////////////////////////////////////////////////////
// About box Dialog handler
///////////////////////////////////////////////////////////////////////////////

static BOOL CALLBACK AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    MyExporter * myexp = (MyExporter*)GetWindowLong(hWnd,GWL_USERDATA);

    if (!myexp && msg != WM_INITDIALOG)
        return FALSE;

    switch (msg) {
    case WM_INITDIALOG:
        // Update class pointer
        myexp = (MyExporter*)lParam;
        SetWindowLong(hWnd,GWL_USERDATA,lParam);
        break;

    case WM_DESTROY:
        break;

    case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case IDOK:
            EndDialog(hWnd,1);
            break;
        }
        break;

    default:
        return FALSE;
    }  
    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// Show the aboutbox
///////////////////////////////////////////////////////////////////////////////

void MyExporter::ShowAbout(HWND hWnd)
{
    DialogBoxParam(g_hInstance,
                   MAKEINTRESOURCE(IDD_ABOUT),
                   hWnd,
                   AboutDlgProc,
                   (LPARAM)this);
}


///////////////////////////////////////////////////////////////////////////////
// This method is called for the plug-in to perform its file export.
///////////////////////////////////////////////////////////////////////////////

int MyExporter::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL suppressPrompts, DWORD options)
{
    TCHAR buf[256];

    // cache export session stuff for utility methods
    m_exportSelected = (options & SCENE_EXPORT_SELECTED);
    m_suppressPrompts = !!suppressPrompts;
    m_ip = i;
    m_expip = ei;

    // open file
    m_fileStream = ::_tfopen(name, _T("wt"));
    if (!m_fileStream) {
        ::sprintf(buf, GetString(IDS_OPENFILEERR), name);
        ::MessageBox(i->GetMAXHWnd(), buf, GetString(IDS_EXPCAPTION), MB_OK | MB_ICONSTOP);
        return FALSE; // fail
    }

    // get and write out "global" header information
    DoHeader();

    // get and write out scene information
    DoNodes();

    // get and write out tailer information (if any)
    DoTailer();

    // close file
    ::fclose(m_fileStream);

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// (utility fcns)
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
// This method is called by MAX to determine if one or more export options are
// supported by a plug-in for a given extension.
// It should return TRUE if all option bits set are supported for this
// extension; otherwise FALSE.
///////////////////////////////////////////////////////////////////////////////

BOOL MyExporter::SupportsOptions(int ext, DWORD options)
{
    // (from the SDK helpfile)
    // "This parameter [options] specifies which options are being queried,
    // and may have more than one option specified.  At present,
    // the only export option is SCENE_EXPORT_SELECTED, but this may
    // change in the future.  If more than one option is specified in
    // this field, the plugin should only return TRUE if all of the
    // options are supported.  If one or more of the options are not
    // supported, the plugin should return FALSE."

    if (options & SCENE_EXPORT_SELECTED)
        return TRUE;
    else
        return FALSE;

}

///////////////////////////////////////////////////////////////////////////////
// Utility fcn to enumerate over nodes
///////////////////////////////////////////////////////////////////////////////

void MyExporter::DoHeader()
{

    // write out a basic header line
    struct tm *newtime;
    time_t aclock;
    char buf[256];

    ::time(&aclock);
    newtime = ::localtime(&aclock);
    ::strcpy(buf, ::asctime(newtime));
    buf[strlen(buf) - 1] = '\0'; // remove extra newline
    ::fprintf(m_fileStream, "BEGIN MYEXPORTER Version:<%d> Date:<%s>\n",MYEXP_VER,buf);

    // write out basic header info here
    ::fprintf(m_fileStream, "BEGIN HEADER\n");


    // export material info used in scene
    MtlBaseLib * scenemats = m_ip->GetSceneMtls();
    int i,j; // for loops
    if (scenemats) {
        for (i = 0; i < scenemats->Count(); i++)  {
            // DoSomething(scenemats[i]);
            MtlBase * mtl = (*scenemats)[i];
            ::fprintf(m_fileStream, "BEGIN MTL Name:<%s> FullName:<%s>\n", mtl->GetName(), mtl->GetFullName());
            if (IsMtl(mtl) && mtl->IsMultiMtl()) {
                // multi-mtl
                Mtl * m = (Mtl *)mtl;
                ::fprintf(m_fileStream, "    multimtl -- submtls:\n");
                for (j = 0; j < m->NumSubMtls(); j++) {
                    Mtl *sm = m->GetSubMtl(j);
                    if (sm) {
                        // NOTE: For this tutorial, we only go one "level" deep
                        ::fprintf(m_fileStream, "        Name:<%s>\n", sm->GetName());
                    }
                }

            } else {

                // submtls or texmaps
                for (j = 0; j < mtl->NumSubTexmaps(); j++) {
                    Texmap * tmap = mtl->GetSubTexmap(j);
                    if (tmap) {
                        // NOTE: For this tutorial, we only go one subtex "level"
                        // deep, although in reality, we can go much deeper
                        // (e.g. mtl with checker diffuse, that in turn has another
                        // checker as a subtex, etc)
                        ::fprintf(m_fileStream, "    subtex -- Name:<%s> UVWSrc:<%d> MapChannel:<%d> \n", tmap->GetName(), tmap->GetUVWSource(), tmap->GetMapChannel());
                        // for this sample, if one of the first level subtex's is a
                        // bitmaptex, dump out some more info.  It should be clear
                        // that similar actions can be taken with other typical subtexs
                        // (RGBMult, etc)
                        if (tmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
                            BitmapTex *bmt = (BitmapTex*) tmap;
                            ::fprintf(m_fileStream, "        Bitmap Tex -- File:<%s>\n", bmt->GetMapName());
                            // (Sidenote: There are supposedly some cases where this
                            // might not return the full filename + path)
                        }

                    }
                }
            }
            ::fprintf(m_fileStream, "END MTL\n");
        }
    }

    // export ambient scene light
    Color ambLight = m_ip->GetAmbient(m_ip->GetTime(), FOREVER);
    COLORREF ambColor = (DWORD)ambLight;
    ::fprintf(m_fileStream,"AMBIENT LIGHT rgb:<%d,%d,%d>\n",
        GetRValue(ambColor), GetGValue(ambColor), GetBValue(ambColor));

    ::fprintf(m_fileStream, "END HEADER\n");

}

void MyExporter::DoNodes()
{
    // walk the scene or selected nodes and export the desired information

    int numChildren = m_ip->GetRootNode()->NumberOfChildren();

    // Call our node enumerator.
    // The nodeEnum function will recurse into itself and
    // export each object found in the scene.
    for (int idx = 0; idx < numChildren; idx++) {
        if (m_ip->GetCancel())
            break;
        nodeEnum(m_ip->GetRootNode()->GetChildNode(idx));
    }

}

void MyExporter::DoTailer()
{
    ::fprintf(m_fileStream, "END MYEXPORTER\n");
}


BOOL MyExporter::nodeEnum(INode* node)
{

    if (!node)
        return FALSE;

    // if we're only exporting selected nodes, and
    // the given node isn't selected, skip it
    if (m_exportSelected && node->Selected() == FALSE)
        return FALSE;

    // Stop recursing if the user pressed Cancel
    if (m_ip->GetCancel())
        return FALSE;


    // The ObjectState is a 'thing' that flows down the pipeline containing
    // all information about the object. By calling EvalWorldState() we tell
    // max to eveluate the object at end of the pipeline.
    ObjectState os = node->EvalWorldState(m_ip->GetTime());

    // The obj member of ObjectState is the actual object we will export.
    if (os.obj) {
        // We look at the super class ID to determine the type of the object.
        switch(os.obj->SuperClassID()) {
        case GEOMOBJECT_CLASS_ID:
            ExportGeomObject(node);
            break;

        case LIGHT_CLASS_ID:
            ExportLightObject(node);
            break;

        default:
            break;
        }
    }


    // For each child of this node, we recurse into ourselves
    // until no more children are found.
    for (int c = 0; c < node->NumberOfChildren(); c++) {
        if (!nodeEnum(node->GetChildNode(c)))
            return FALSE;
    }


    return TRUE;
}

void MyExporter::ExportGeomObject(INode * node)
{
    int i; // for loops
    Point3 vert;
    int numTVerts, chanloop;

    TimeValue currtime = m_ip->GetTime();
    ObjectState os = node->EvalWorldState(currtime);
    if (!os.obj)
        return;
   
    // Target camera "targets" are actually geomobjects, so we skip them here.
    if (os.obj->ClassID() == Class_ID(TARGET_CLASS_ID, 0))
        return;

    ::fprintf(m_fileStream, "BEGIN GEOMOBJECT Name:<%s>\n",node->GetName());

    ///////////////////////////////////
    // dump mtl info for this node
    Mtl * nodemtl = node->GetMtl();
    if (nodemtl) {
        ::fprintf(m_fileStream, "    mtl -- name:<%s>\n", nodemtl->GetName());
    } else {
        // no mat assigned to node, print out 0-255 RGB color
        DWORD col = node->GetWireColor();
        ::fprintf(m_fileStream,"    color -- rgb:<%d,%d,%d>\n",
            GetRValue(col), GetGValue(col), GetBValue(col));
    }

    ///////////////////////////////////
    // get and dump the node matrix, mainly for xform and rot info
    Matrix3 nodepivot = node->GetNodeTM(currtime);
    Point3 row;
    row = nodepivot.GetRow(0);
    ::fprintf(m_fileStream,"BEGIN TM\n    Row 0:<%f,%f,%f>\n", row.x, row.y, row.z);
    row = nodepivot.GetRow(1);
    ::fprintf(m_fileStream,"    Row 1:<%f,%f,%f>\n", row.x, row.y, row.z);
    row = nodepivot.GetRow(2);
    ::fprintf(m_fileStream,"    Row 2:<%f,%f,%f>\n", row.x, row.y, row.z);
    row = nodepivot.GetRow(3);
    ::fprintf(m_fileStream,"    Row 3:<%f,%f,%f>\nEND TM\n", row.x, row.y, row.z);

    ///////////////////////////////////
    // export geometric data
    Matrix3 tm = node->GetObjTMAfterWSM(currtime);

    if (os.obj->ClassID() == Class_ID(PATCHOBJ_CLASS_ID, 0) ||
        os.obj->ClassID() == Class_ID(PATCHGRID_CLASS_ID, 0)) {
        // Patches      
        bool delPatch = false;
        Object *obj = os.obj;
        if (obj && obj->CanConvertToType(Class_ID(PATCHOBJ_CLASS_ID, 0))) {
            PatchObject * patchobj = NULL;
            patchobj = (PatchObject *) obj->ConvertToType(0, Class_ID(PATCHOBJ_CLASS_ID, 0));
            if (obj != patchobj)
                delPatch = true; // we own the copy
            if (patchobj) {
                PatchMesh * patchmesh = &(patchobj->patch);
                ::fprintf(m_fileStream, "BEGIN PATCH NumVerts:<%d> NumVecs:<%d> NumPatches:<%d> NumEdges:<%d>\n",
                        patchmesh->getNumVerts(),
                        patchmesh->getNumVecs(),
                        patchmesh->getNumPatches(),
                        patchmesh->getNumEdges());

                // export vertices
                for (i = 0; i < patchmesh->getNumVerts(); i++) {
                    vert = tm * patchmesh->getVert(i).p;
                    ::fprintf(m_fileStream, "    vertex %d -- pos:<%f,%f,%f> veccount:<%d>\n", i, vert.x, vert.y, vert.z, patchmesh->getVert(i).vectors.Count());
                }

                // export vectors
                for (i = 0; i < patchmesh->getNumVecs(); i++) {
                    vert = patchmesh->getVec(i).p;
                    ::fprintf(m_fileStream, "    vector %d -- vec:<%f,%f,%f> vertind:<%d>\n", i, vert.x, vert.y, vert.z, patchmesh->getVec(i).vert);
                }

                // export edges
                for (i = 0; i < patchmesh->getNumEdges(); i++) {
                    PatchEdge * workedge = &(patchmesh->edges[i]);
                    if (workedge)
                        ::fprintf(m_fileStream, "    edge %d -- vertind:<%d,%d> vecind:<%d,%d> patchind:<%d,%d>\n", i, workedge->v1, workedge->v2, workedge->vec12, workedge->vec21, workedge->patches[0], workedge->patches[1]);
                }

                // export patches
                for (i = 0; i < patchmesh->getNumPatches(); i++) {
                    Patch * workpatch = &(patchmesh->patches[i]);
                    if (workpatch) {
                        if (workpatch->type == PATCH_TRI) {
                            ::fprintf(m_fileStream, "    tripatch %d -- ",i);
                            // get corner vert indices
                            ::fprintf(m_fileStream, " vertind:<%d,%d,%d>",
                                    workpatch->v[0], workpatch->v[1], workpatch->v[2]);
                            // get tangent vector indices
                            ::fprintf(m_fileStream, " vecind:<%d,%d,%d,%d,%d,%d>",
                                    workpatch->vec[0],
                                    workpatch->vec[1],
                                    workpatch->vec[2],
                                    workpatch->vec[3],
                                    workpatch->vec[4],
                                    workpatch->vec[5]);
                            // get interior vert indices
                            ::fprintf(m_fileStream, " internal vertind:<%d,%d,%d>",
                                    workpatch->interior[0], workpatch->interior[1], workpatch->interior[2]);
                            // get edge indices
                            ::fprintf(m_fileStream, " edge ind:<%d,%d,%d>",
                                    workpatch->edge[0], workpatch->edge[1], workpatch->edge[2]);
                            ::fprintf(m_fileStream, "\n");
                        } else if (workpatch->type == PATCH_QUAD) {
                            ::fprintf(m_fileStream, "    quadpatch %d -- ",i);
                            // get corner vert indices
                            ::fprintf(m_fileStream, " vertind:<%d,%d,%d,%d>", workpatch->v[0], workpatch->v[1], workpatch->v[2], workpatch->v[3]);
                            // get tangent vector indices
                            ::fprintf(m_fileStream, " vecind:<%d,%d,%d,%d,%d,%d,%d,%d>",
                                    workpatch->vec[0],
                                    workpatch->vec[1],
                                    workpatch->vec[2],
                                    workpatch->vec[3],
                                    workpatch->vec[4],
                                    workpatch->vec[5],
                                    workpatch->vec[6],
                                    workpatch->vec[7]);
                            // get interior vert indices
                            ::fprintf(m_fileStream, " internal vertind:<%d,%d,%d,%d>", workpatch->interior[0], workpatch->interior[1], workpatch->interior[2], workpatch->interior[3]);
                            // get edge indices
                            ::fprintf(m_fileStream, " edge ind:<%d,%d,%d,%d>", workpatch->edge[0], workpatch->edge[1], workpatch->edge[2], workpatch->edge[3]);
                            ::fprintf(m_fileStream, "\n");

                        } // (otherwise, unknown type, don't output)
                    }
                }

                // export patch texture vertices info
                // first, channel 1
                numTVerts = patchmesh->getNumTVerts();
                if (numTVerts) {
                    ::fprintf(m_fileStream, "    texture channel 1 -- numverts:<%d>\n", numTVerts);
                    for (i = 0; i < numTVerts; i++) {
                        UVVert tvert = patchmesh->getTVert(i);
                        ::fprintf(m_fileStream, "        UVW tvert %d:<%f,%f,%f>\n", i, tvert.x, tvert.y, tvert.z);
                    }
                    // now, print tvert indices used by tvpatches (always 4)
                    for (i = 0; i < patchmesh->getNumPatches(); i++) {
                        TVPatch tvpatch = patchmesh->getTVPatch(i);
                        ::fprintf(m_fileStream, "        TVPatch %d -- tvertind:<%d,%d,%d,%d>\n",
                            tvpatch.tv[0], tvpatch.tv[1], tvpatch.tv[2], tvpatch.tv[3]);
                    }
                }
                // now, rest of channels
                for (chanloop = 2; chanloop < MAX_MESHMAPS - 1; chanloop++) {
                    numTVerts = patchmesh->getNumMapVerts(chanloop);
                    if (numTVerts > 0) {
                        ::fprintf(m_fileStream, "    texture channel %d -- numverts:<%d>\n", chanloop, numTVerts);
                        for (i = 0; i < numTVerts; i++) {
                            UVVert tvert = patchmesh->getMapVert(chanloop, i);
                            ::fprintf(m_fileStream, "        UVW tvert %d:<%f,%f,%f>\n", i, tvert.x, tvert.y, tvert.z);
                        }
                        // now, print tvert indices used by tvpatches
                        for (i = 0; i < patchmesh->getNumPatches(); i++) {
                            TVPatch tvpatch = patchmesh->getTVPatchChannel(chanloop,i);
                            ::fprintf(m_fileStream, "        TVPatch %d -- tvertind:<%d,%d,%d,%d>\n",
                                tvpatch.tv[0], tvpatch.tv[1], tvpatch.tv[2], tvpatch.tv[3]);
                        }
                    }
                }

                ::fprintf(m_fileStream, "END PATCH\n");

                // del patchobject, if it was generated
                if (delPatch)
                    delete patchobj;

            }
        }      
    } else {
        // Treat everything else as trimeshes (geomobjects should all
        // be able to convert themselves at least.  If we just wanted
        // collapsed meshes, we could check for TRIOBJ_CLASS_ID)

        // first, get the triobject mesh
        bool delMesh = false;
        Object *obj = os.obj;
        if (obj && obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) {
            TriObject * tri = NULL;
            tri = (TriObject *) obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));
            if (obj != tri)
                delMesh = true; // we own the copy
            if (tri) {
                Mesh * mesh = &(tri->GetMesh());
                assert(mesh);
                mesh->buildNormals();
                ::fprintf(m_fileStream, "BEGIN MESH NumVerts:<%d> NumFaces:<%d>\n",mesh->getNumVerts(),mesh->getNumFaces());

                // Export the vertices
                for (i = 0; i < mesh->getNumVerts(); i++) {
                    vert = tm * mesh->verts[i];
                    ::fprintf(m_fileStream, "    vertex %d:<%f,%f,%f>\n", i, vert.x, vert.y, vert.z);
                }

                // export faces
                for (i = 0; i < mesh->getNumFaces(); i++) {
                    ::fprintf(m_fileStream, "    face %d -- verts:<%d,%d,%d> edgevis:<%d,%d,%d> smoothgrp:<0x%x> matid:<%d>\n", i,
                                mesh->faces[i].v[0],
                                mesh->faces[i].v[1],
                                mesh->faces[i].v[2],
                                mesh->faces[i].getEdgeVis(0) ? 1 : 0,
                                mesh->faces[i].getEdgeVis(1) ? 1 : 0,
                                mesh->faces[i].getEdgeVis(2) ? 1 : 0,
                                mesh->faces[i].getSmGroup(),
                                mesh->faces[i].getMatID());
                }

                // export texture vertices info (note: assumes not using face mapping)
                // (for MAX 3, we iterate over texture channels, but not color-per-vert
                // channel)
                // first, channel 1, the regular UV channel
                numTVerts = mesh->getNumTVerts();
                if (numTVerts) {
                    ::fprintf(m_fileStream, "    texture channel 1 -- numverts:<%d>\n", numTVerts);
                    for (i = 0; i < numTVerts; i++) {
                        UVVert tvert = mesh->tVerts[i];
                        ::fprintf(m_fileStream, "        UVW tvert %d:<%f,%f,%f>\n", i, tvert.x, tvert.y, tvert.z);
                    }
                    // now, print tvert indices used by tvfaces
                    for (i = 0; i < mesh->getNumFaces(); i++) {
                        TVFace tface = mesh->tvFace[i];
                        ::fprintf(m_fileStream, "        TVFace %d -- tvertind:<%d,%d,%d>\n",
                            i, tface.t[0], tface.t[1], tface.t[2]);
                    }                   
                }
                // now, rest of channels
                for (chanloop = 2; chanloop < MAX_MESHMAPS - 1; chanloop++) {
                    if (mesh->mapSupport(chanloop)) {
                        numTVerts = mesh->getNumMapVerts(chanloop);
                        ::fprintf(m_fileStream, "    texture channel %d -- numverts:<%d>\n", chanloop, numTVerts);
                        for (i = 0; i < numTVerts; i++) {
                            UVVert tvert = mesh->mapVerts(chanloop)[i];
                            ::fprintf(m_fileStream, "        UVW tvert %d:<%f,%f,%f>\n", i, tvert.x, tvert.y, tvert.z);
                        }
                        // now, print tvert indices used by tvfaces
                        for (i = 0; i < mesh->getNumFaces(); i++) {
                            TVFace tface = mesh->mapFaces(chanloop)[i];
                            ::fprintf(m_fileStream, "        TVFace %d -- tvertind:<%d,%d,%d>\n",
                                i, tface.t[0], tface.t[1], tface.t[2]);
                        }                     
                    }
                }

                ::fprintf(m_fileStream, "END MESH\n");

                // del triobject, if it was generated
                if (delMesh)
                    delete tri;
            }
        }
    }

    ::fprintf(m_fileStream, "END GEOMOBJECT\n");

}


void MyExporter::ExportLightObject(INode * node)
{

    TimeValue currtime = m_ip->GetTime();
    ObjectState os = node->EvalWorldState(currtime);
    if (!os.obj)
        return;

    GenLight* light = (GenLight*)os.obj;
    struct LightState ls;
    light->EvalLightState(currtime, FOREVER, &ls);

    if (! light->GetUseLight())
        return; // only export lights that are on for simplicity

    ::fprintf(m_fileStream, "BEGIN LIGHT Name:<%s> Type:<",node->GetName());

    // light type
    switch(light->Type()) {
    case OMNI_LIGHT: 
        fprintf(m_fileStream, "OMNI>\n");
        break;
    case TSPOT_LIGHT:
        fprintf(m_fileStream, "TARGET SPOT>\n");
        break;
    case DIR_LIGHT:  
        fprintf(m_fileStream, "DIRECTIONAL>\n");
        break;
    case FSPOT_LIGHT:
        fprintf(m_fileStream, "FREE SPOT>\n");
        break;
    case TDIR_LIGHT:
    default:
        fprintf(m_fileStream, "TARGETED DIRECTIONAL>\n");
        break;
    }

    ///////////////////////////////////
    // color, intensity info
    COLORREF lightcol = (DWORD)ls.color;
    ::fprintf(m_fileStream,"    light color -- rgb:<%d,%d,%d>\n",
        GetRValue(lightcol), GetGValue(lightcol), GetBValue(lightcol));
    ::fprintf(m_fileStream,"    light intensity -- mult:<%f>\n", ls.intens);

    ///////////////////////////////////
    // get and dump the node matrix, mainly for xform and rot info
    // also dump target TM, if the light has a target
    Matrix3 nodepivot = node->GetNodeTM(currtime);
    Point3 row;
    row = nodepivot.GetRow(0);
    ::fprintf(m_fileStream,"BEGIN TM\n    Row 0:<%f,%f,%f>\n", row.x, row.y, row.z);
    row = nodepivot.GetRow(1);
    ::fprintf(m_fileStream,"    Row 1:<%f,%f,%f>\n", row.x, row.y, row.z);
    row = nodepivot.GetRow(2);
    ::fprintf(m_fileStream,"    Row 2:<%f,%f,%f>\n", row.x, row.y, row.z);
    row = nodepivot.GetRow(3);
    ::fprintf(m_fileStream,"    Row 3:<%f,%f,%f>\nEND TM\n", row.x, row.y, row.z);
    INode* target = node->GetTarget();
    if (target) {
        nodepivot = target->GetNodeTM(currtime);
        row = nodepivot.GetRow(0);
        ::fprintf(m_fileStream,"BEGIN TARGET TM\n    Row 0:<%f,%f,%f>\n", row.x, row.y, row.z);
        row = nodepivot.GetRow(1);
        ::fprintf(m_fileStream,"    Row 1:<%f,%f,%f>\n", row.x, row.y, row.z);
        row = nodepivot.GetRow(2);
        ::fprintf(m_fileStream,"    Row 2:<%f,%f,%f>\n", row.x, row.y, row.z);
        row = nodepivot.GetRow(3);
        ::fprintf(m_fileStream,"    Row 3:<%f,%f,%f>\nEND TARGET TM\n", row.x, row.y, row.z);
    }

    ///////////////////////////////////
    // export shadow info, if applicable

    if (light->GetShadow()) {
        int shadtype = light->GetShadowType();
        ::fprintf(m_fileStream,"    shadow -- type:<");
        switch (shadtype) {
        case -1:
            ::fprintf(m_fileStream, "GENERATOR (null)>\n");
            break;
        case 0:
            ::fprintf(m_fileStream, "SHADOW MAPS>\n");
            break;
        case 1:
            ::fprintf(m_fileStream, "RAYTRACED>\n");
            break;
        default:
            ::fprintf(m_fileStream, "GENERATOR (0x%x)>\n", shadtype);
            break;
        }
    }

    ::fprintf(m_fileStream, "END LIGHT\n");

}

posted on 2007-08-12 18:11 昆达 阅读(674) 评论(0)  编辑 收藏 引用
只有注册用户登录后才能发表评论。