XMLExporter.cpp

#include "StdAfx.h"
#include "XmlExporter.h"
#include "GeomUtilities.h"
#include "LocalizedStrings.h"

//Include the resource header on windows so that
//we have our string constants from the strings table
//#ifdef WINDOWS
#include "../win32/resource.h"
//#endif

//A set to help count the textures that we export
static std::set<long> textureHandles;

//Initialize the stats struct
CXMLExportStats::CXMLExportStats()
{
    m_nTextures = 0;
    m_nCameras = 0;
    m_nFaces = 0;
    m_nEdges = 0;
    m_nLayers = 0;
    m_nOptions = 0;
}

CXMLExporter::CXMLExporter(CXMLOptions* pOptions)
{
    m_pOptions = pOptions;

    //Initialize the inheritance manager - pass in the option to materials by layer so that
    //the class can offer up the appropriate material for the faces later on
    m_InheritanceManager = CInheritanceManager(m_pOptions->GetExportMaterialsByLayer());
}

CXMLExporter::~CXMLExporter(void)
{
}

HRESULT CXMLExporter::WriteModel()
{
    try
    {
        if (m_pProgressBar)
        {
            m_pProgressBar->SetPercentDone(0.0);
            m_pProgressBar->SetProgressMessage(LoadLocalizedString(IDS_WRITING_TEXTURE_FILES));
        }
  WriteTextureFiles();

  Write("<SkpToXML xmlversion=\"1.0\" skpversion=\"5.0\" units=\"inches\">\n");

            if (m_pProgressBar)
            {
                m_pProgressBar->SetPercentDone(10.0);
                m_pProgressBar->SetProgressMessage(LoadLocalizedString(IDS_WRITING_LAYERS));
            }
            WriteLayers();

            if (m_pProgressBar)
            {
                m_pProgressBar->SetPercentDone(20.0);
                m_pProgressBar->SetProgressMessage(LoadLocalizedString(IDS_WRITING_MATERIALS));
            }
            WriteMaterials();

            if (m_pProgressBar)
            {
                m_pProgressBar->SetPercentDone(30.0);
                m_pProgressBar->SetProgressMessage(LoadLocalizedString(IDS_WRITING_OPTIONS));
            }
            WriteOptions();

            if (m_pProgressBar)
            {
                m_pProgressBar->SetPercentDone(40.0);
                m_pProgressBar->SetProgressMessage(LoadLocalizedString(IDS_WRITING_GEOMETRY));
            }
            WriteGeometry();

        Write("</SkpToXML>");

        if (m_pProgressBar)
        {
            m_pProgressBar->SetPercentDone(100.0);
            m_pProgressBar->SetProgressMessage(LoadLocalizedString(IDS_EXPORT_COMPLETE));
        }

        return S_OK;
    }
    catch(HRESULT hr)
    {
        return hr;
    }
}

void CXMLExporter::WriteTextureFiles()
{
    if (m_pOptions->GetExportMaterials())
    {
        HResult hr;

        // Get the ISkpApplication from the ISkpDocument
        CComPtr<ISkpApplication> pApp;
        hr = m_pDocument->get_Application(&pApp);

        // Get the ISkpTextureWriter2 interface from ISkpApplication.  You
        // first have to get the ISkpTextureWriter, then get the ISkpTextureWriter2
        // extension from that.
        CComPtr<ISkpTextureWriter> pTW;
        hr = pApp->CreateTextureWriter(&pTW);
        hr = pTW->QueryInterface(IID_ISkpTextureWriter2, (void**)&m_pTextureWriter);

        if (m_pOptions->GetExportMaterialsByLayer())
        {
            LoadTexturesFromLayers();
        }
        else
        {
            // Get the top-level ISkpEntityProvider interface from the ISkpDocument,
            // which is the root component in the model
            CComPtr<ISkpEntityProvider> pEntProvider;
            hr = m_pDocument->QueryInterface(IID_ISkpEntityProvider, (void**) &pEntProvider);

            // Start recursing down the component hierarchy, loading the textures into
            // the ISkpTextureWriter2 along the way
            LoadTexturesFromEntities(pEntProvider);
        }
  
        // Get the number of textures for the statisics output
        long textureCount;
        m_pTextureWriter->get_Count(&textureCount);
        m_Stats.m_nTextures = textureCount;

        // Write out all the textures to a folder
        std::string btextureDir = GetExportFolder();
      _bstr_t textDirBstr(btextureDir.c_str());
        hr = m_pTextureWriter->WriteAllTextures(textDirBstr, FALSE);
    }
}

void CXMLExporter::LoadTexturesFromLayers()
{
    CComPtr<ISkpLayers> pLayers;
    HResult hr = m_pDocument->get_Layers(&pLayers);

    long count;
    hr = pLayers->get_Count(&count);

    for(long i=0; i<count; i++)
    {
        CComPtr<ISkpLayer> pLayer;
        hr = pLayers->get_Item(i, &pLayer);

        long handle;
        hr = m_pTextureWriter->LoadLayer(pLayer, &handle);

        if (hr == S_OK)
        {
            if (handle > 0)
            {
                textureHandles.insert(handle);
            }
        }
    }
}

void CXMLExporter::LoadTexturesFromEntities(CComPtr<ISkpEntityProvider> pEntProvider)
{
    HResult hr;
    long nElements, i;

    // Load all the textures applied to component instances
    CComPtr<ISkpComponentInstances> pInstances = NULL;
    hr = pEntProvider->get_ComponentInstances(&pInstances);
    hr = pInstances->get_Count(&nElements);

    for(i=0; i<nElements; i++)
    {
        // Get the ISkpComponentInstance from the ISkpComponentInstances
        CComPtr<ISkpComponentInstance> pInstance;
        hr = pInstances->get_Item(i, &pInstance);

        // Get the ISkpEntity interface for this ISkpComponentInstance
        CComPtr<ISkpEntity> pEnt;
        hr = pInstance->QueryInterface(IID_ISkpEntity, (void**) &pEnt);

        // Load the component instance into the texture writer
        long handle;
        hr = m_pTextureWriter->LoadComponentInstance(pInstance, &handle);

        if (hr == S_OK)
        {
            if (handle > 0)
            {
                // Record the resulting texture handle into our static std::set<long> of handles.
                textureHandles.insert(handle);
            }
        }

        // Get the instance's component definition (ISkpComponentDefinition)
        CComPtr<ISkpComponentDefinition> pDef;
        hr = pInstance->get_ComponentDefinition(&pDef);

        // Get the ISkpEntityProvider interface from the ISkpComponentDefinition
        CComPtr<ISkpEntityProvider> pEntProvider;
        hr = pDef->QueryInterface(IID_ISkpEntityProvider, (void**) &pEntProvider);

        // Recursively call this function
        LoadTexturesFromEntities(pEntProvider);
    }

    // Load all the textures applied to groups
    CComPtr<ISkpGroups> pGroups = NULL;
    hr = pEntProvider->get_Groups(&pGroups);
    hr = pGroups->get_Count(&nElements);

    for(i=0; i<nElements; i++)
    {
        // Get the ISkpGroup from the ISkpGroups
        CComPtr<ISkpGroup> pGroup;
        hr = pGroups->get_Item(i, &pGroup);
       
        // Load the group instance into the texture writer
        long handle;
        hr = m_pTextureWriter->LoadGroup(pGroup, &handle);

        if (hr == S_OK)
        {
            if (handle > 0)
            {
                // Record the resulting texture handle into our static std::set<long> of handles.
                textureHandles.insert(handle);
            }
        }

        // Get the ISkpEntityProvider interface from the ISkpGroup
        CComPtr<ISkpEntityProvider> pEntProvider;
        hr = pGroup->QueryInterface(IID_ISkpEntityProvider, (void**) &pEntProvider);

        // Recursively call this function
        LoadTexturesFromEntities(pEntProvider);
    }

    //Load all the textures applied to images
    CComPtr<ISkpImages> pImages = NULL;
    hr = pEntProvider->get_Images(&pImages);
    hr = pImages->get_Count(&nElements);

    for(i=0; i<nElements; i++)
    {
        // Get the ISkpImage from the ISkpImages
        CComPtr<ISkpImage> pImage;
        hr = pImages->get_Item(i, &pImage);

        // Load the image into the texture writer
        long handle;
        hr = m_pTextureWriter->LoadImage(pImage, &handle);

        if (hr == S_OK)
        {
            if (handle > 0)
            {
                // Record the resulting texture handle into our static std::set<long> of handles.
                textureHandles.insert(handle);
            }
        }

        // Get the ISkpEntityProvider interface from the ISkpImage
        CComPtr<ISkpEntityProvider> pEntProvider;
        hr = pImage->QueryInterface(IID_ISkpEntityProvider, (void**) &pEntProvider);

        // Recursively call this function
        LoadTexturesFromEntities(pEntProvider);
    }

    //Load all the textures applied to faces
    CComPtr<ISkpFaces> pFaces = NULL;
    hr = pEntProvider->get_Faces(&pFaces);
    hr = pFaces->get_Count(&nElements);

    for(i=0; i<nElements; i++)
    {
        // Get the ISkpFace from the ISkpFaces
        CComPtr<ISkpFace> pFace;
        hr = pFaces->get_Item(i, &pFace);

        // Load the texture on the FRONT side of the face into the texture writer
        long handle = 0;
        hr = m_pTextureWriter->LoadFace(pFace, /*bFront*/ true, &handle);

        if (hr == S_OK)
        {
            if (handle > 0)
            {
                // Record the resulting texture handle into our static std::set<long> of handles.
                textureHandles.insert(handle);
            }
        }

        // Load the texture on the BACK side of the face into the texture writer
        handle=0;
        hr = m_pTextureWriter->LoadFace(pFace, /*bFront*/ false, &handle);

        if (hr == S_OK)
        {
            if (handle > 0)
            {
                // Record the resulting texture handle into our static std::set<long> of handles.
                textureHandles.insert(handle);
            }
        }
    }
}

void CXMLExporter::WriteOptions()
{
    if (m_pOptions->GetExportOptions())
    {
        HResult hr;

        CComPtr<ISkpOptionsManager> pOptManager;
        hr = m_pDocument->get_OptionsManager(&pOptManager);

        long count;
        hr = pOptManager->get_Count(&count);

        if (count>0)
        {
            IncreaseIndent();
            Write("<Options>\n");

            VARIANT vNum;
            ::VariantInit(&vNum);
            vNum.vt = VT_I4;
            for(long i=0; i<count; i++)
            {
                CComPtr<ISkpOptionsProvider> pProvider;

                vNum.lVal = i;
                hr = pOptManager->get_Item(vNum, &pProvider);
               
                // write the option provider
                CComPtr<ISkpNamedValues> pNamedOptions;
                hr = pProvider->QueryInterface(IID_ISkpNamedValues, (void**)&pNamedOptions);

                BSTR bProviderName;
                hr = pProvider->get_Name(&bProviderName);
                _bstr_t szProviderName(bProviderName, true);

                WriteOptionsProvider((const char*)szProviderName, pNamedOptions);

                SysFreeString(bProviderName);
            }
            Write("</Options>\n");
            DecreaseIndent();
        }
    }
}

void CXMLExporter::WriteOptionsProvider(const char* title, CComPtr<ISkpNamedValues> pNVs)
{
    if(pNVs == NULL)
    {
        return;
    }

    long count;
    HResult hr;

    hr = pNVs->get_Count(&count);

    if (count>0)
    {
        IncreaseIndent();
        Write("<OptionsProvider name=\"%s\">\n", title);
        IncreaseIndent();
        for(long i=0; i<count; i++)
        {
   CComPtr<ISkpNamedValue> pNV;
            hr = pNVs->get_Item(i, &pNV);
            BSTR bName;
            VARIANT vValue;
            VariantInit(&vValue);

            hr = pNV->get_Name(&bName);
            hr = pNV->get_Value(&vValue);

            m_Stats.m_nOptions += 1;
            CXMLExporterBase::WriteOption(bName, vValue);

            SysFreeString(bName);
            VariantClear(&vValue);
        }
        DecreaseIndent();
        Write("</OptionsProvider>\n");
        DecreaseIndent();
    }
}

void CXMLExporter::WriteLayers()
{
    if (m_pOptions->GetExportLayers())
    {
        HResult hr;

        CComPtr<ISkpLayers> pLayers;
        hr = m_pDocument->get_Layers(&pLayers);
       
        long count;
        hr = pLayers->get_Count(&count);

        if (count>0)
        {
            IncreaseIndent();
            Write("<Layers>\n", count);
            IncreaseIndent();
            for(long i=0; i<count; i++)
            {
                CComPtr<ISkpLayer> pLayer;
                hr = pLayers->get_Item(i, &pLayer);
                WriteLayer(pLayer);
            }
            DecreaseIndent();
            Write("</Layers>\n");
            DecreaseIndent();
        }
    }
}

void CXMLExporter::WriteLayer(CComPtr<ISkpLayer> pLayer)
{
    HResult hr;

    m_Stats.m_nLayers += 1;

    long entityId = GetEntityId(pLayer);

    BSTR layerName;
    hr = pLayer->get_Name(&layerName);
    _bstr_t szLayerName(layerName, true);

    OLE_COLOR color;
    hr = pLayer->get_Color(&color);

    BOOL isVisible = TRUE;
    hr = pLayer->get_IsVisible(&isVisible);

    Write("<Layer id=\"%d\" name=\"%s\" color=\"#%06x\" visible=\"%s\" />\n", entityId, (const char*)szLayerName, color, BoolToText(isVisible));
    SysFreeString(layerName);
}

void CXMLExporter::WriteMaterials()
{
    if (m_pOptions->GetExportMaterials())
    {
        if (m_pOptions->GetExportMaterialsByLayer())
        {
            HResult hr;

            CComPtr<ISkpLayers> pLayers;
            hr = m_pDocument->get_Layers(&pLayers);

            long count;
            hr = pLayers->get_Count(&count);

            if (count>0)
            {
                for(long i=0; i<count; i++)
                {
                    CComPtr<ISkpLayer> pLayer;
                    hr = pLayers->get_Item(i, &pLayer);

                    CComPtr<ISkpMaterial> pMaterial;
                    hr = pLayer->get_Material(&pMaterial);
                    WriteMaterial(pMaterial);
                }
            }
        }
        else
        {
            HResult hr;
            CComPtr<ISkpMaterials> pMats;

            hr = m_pDocument->get_Materials(&pMats);
            long count = 0L;
            hr = pMats->get_Count(&count);
           
            if (count>0)
            {
                IncreaseIndent();
                Write("<Materials count=\"%ld\">\n", count);
                IncreaseIndent();
                for(long i=0; i<count; i++)
                {
                    CComPtr<ISkpMaterial> pMat;
                    hr = pMats->get_Item(i, &pMat);
                    WriteMaterial(pMat);
                }
                DecreaseIndent();
                Write("</Materials>\n");
                DecreaseIndent();
            }
        }
    }
}

void CXMLExporter::WriteMaterial(CComPtr<ISkpMaterial> pMaterial)
{
    if(pMaterial == NULL)
    {
        return;
    }

    HResult hr;
    BSTR materialName;

    hr = pMaterial->get_Name(&materialName);
    _bstr_t szMaterialName(materialName, true);

    Write("<Material id=\"%d\" name=\"%s\">\n", GetEntityId(pMaterial), (const char*)szMaterialName);
    SysFreeString(materialName);

    IncreaseIndent();

    //Color
    BOOL isColor;
    hr = pMaterial->get_IsColor(&isColor);
    if ( isColor )
    {
        OLE_COLOR color;
        hr = pMaterial->get_Color(&color);
        Write("<Color> #%06x </Color>\n", color);
    }

    // Alpha
    BOOL usesAlpha;
    hr = pMaterial->get_UsesAlpha(&usesAlpha);
    if ( usesAlpha )
    {
        double alpha = 0;
        hr = pMaterial->get_Alpha(&alpha);
        Write("<Alpha>%lf</Alpha>\n", alpha);
    }

    // See if it has a texture
    BOOL isTexture = FALSE;
    hr = pMaterial->get_IsTexture(&isTexture);
    if( isTexture )
    {
        CComPtr<ISkpTexture> pTexture = NULL;
        hr = pMaterial->get_Texture(&pTexture);
        if(pTexture != NULL)
        {
            BSTR texturePath = NULL;
            hr = pTexture->get_Filename(&texturePath);
            std::string bstrFilename = GetFileName(texturePath);
            _bstr_t szTexturePath(bstrFilename.c_str());
           
            double width = 0;
            double height = 0;
            hr = pTexture->get_XScale(&width);
            hr = pTexture->get_YScale(&height);
           
            Write("<Texture path=\"%s\" xscale=\"%8.4lf\" yscale=\"%8.4lf\" />\n", bstrFilename.c_str(), width, height);
            SysFreeString(texturePath);
        }
    }

    DecreaseIndent();
    Write("</Material>\n");
}

void CXMLExporter::WriteGeometry()
{
    HResult hr;

    CComPtr<ISkpEntityProvider> pEntProvider;
    hr = m_pDocument->QueryInterface(IID_ISkpEntityProvider, (void**) &pEntProvider);

    IncreaseIndent();
    Write("<Geometry>\n");
        IncreaseIndent();
        WriteFacesAndEdges(pEntProvider);
        DecreaseIndent();
    Write("</Geometry>\n");
    DecreaseIndent();
}

void CXMLExporter::WriteFacesAndEdges(CComPtr<ISkpEntityProvider> pEntProvider)
{
    HResult hr;
    long nElements, i;

    //Recurse all the instances
    CComPtr<ISkpComponentInstances> pInstances = NULL;
    hr = pEntProvider->get_ComponentInstances(&pInstances);
    hr = pInstances->get_Count(&nElements);

    for(i=0; i<nElements; i++)
    {
        CComPtr<ISkpComponentInstance> pInstance;
        hr = pInstances->get_Item(i, &pInstance);

        CComPtr<ISkpComponentDefinition> pDef;
        hr = pInstance->get_ComponentDefinition(&pDef);

        CComPtr<ISkpEntityProvider> pEntProvider;
        hr = pDef->QueryInterface(IID_ISkpEntityProvider, (void**) &pEntProvider);

        //Push Transform, Material and Layer
        m_InheritanceManager.PushElement(pInstance);

        WriteFacesAndEdges(pEntProvider);

        //Pop Transform, Material and Layer
        m_InheritanceManager.PopElement();
    }

    //Recurse all the groups
    CComPtr<ISkpGroups> pGroups = NULL;
    hr = pEntProvider->get_Groups(&pGroups);
    hr = pGroups->get_Count(&nElements);

    for(i=0; i<nElements; i++)
    {
        CComPtr<ISkpGroup> pGroup;
        hr = pGroups->get_Item(i, &pGroup);

        CComPtr<ISkpEntityProvider> pEntProvider;
        hr = pGroup->QueryInterface(IID_ISkpEntityProvider, (void**) &pEntProvider);

        //Push Transform, Material and Layer
        m_InheritanceManager.PushElement(pGroup);

        WriteFacesAndEdges(pEntProvider);

        //Pop Transform, Material and Layer
        m_InheritanceManager.PopElement();
    }

    //Recurse all the images
    CComPtr<ISkpImages> pImages = NULL;
    hr = pEntProvider->get_Images(&pImages);
    hr = pImages->get_Count(&nElements);

    for(i=0; i<nElements; i++)
    {
        CComPtr<ISkpImage> pImage;
        hr = pImages->get_Item(i, &pImage);

        CComPtr<ISkpEntityProvider> pEntProvider;
        hr = pImage->QueryInterface(IID_ISkpEntityProvider, (void**) &pEntProvider);

        //Push Transform, Material and Layer
        m_InheritanceManager.PushElement(pImage);

        WriteFacesAndEdges(pEntProvider);

        //Pop Transform, Material and Layer
        m_InheritanceManager.PopElement();
    }

    if (m_pOptions->GetExportFaces())
    {
        //Write all the faces
        CComPtr<ISkpFaces> pFaces = NULL;
        hr = pEntProvider->get_Faces(&pFaces);
        hr = pFaces->get_Count(&nElements);

        for(i=0; i<nElements; i++)
        {
            CComPtr<ISkpFace> pFace;
            hr = pFaces->get_Item(i, &pFace);

            if (hr==S_OK)
            {
                //Push Transform, Material and Layer
                m_InheritanceManager.PushElement(pFace);

                WriteFace(pFace);

                //Pop Transform, Material and Layer
                m_InheritanceManager.PopElement();
            }
        }
    }

    if (m_pOptions->GetExportFaces())
    {
        //Write all the edges
        CComPtr<ISkpEdges> pEdges = NULL;
        hr = pEntProvider->get_Edges(&pEdges);
        hr = pEdges->get_Count(&nElements);

        for(i=0; i<nElements; i++)
        {
            CComPtr<ISkpEdge> pEdge;
            hr = pEdges->get_Item(i, &pEdge);

            if (hr==S_OK)
            {
                //Push Transform, Material and Layer
                m_InheritanceManager.PushElement(pEdge);

                WriteEdge(pEdge);

                //Pop Transform, Material and Layer
                m_InheritanceManager.PopElement();
            }
        }
    }
}

void CXMLExporter::WriteFaceStart(long frontId, long backId, long layerId)
{
    m_Stats.m_nFaces += 1;

    Write("<Face");
    if (frontId!=-1) {Write(" frontMaterial=\"%d\"", frontId);}
    if (backId!=-1) {Write(" backMaterial=\"%d\"", backId);}
    if (layerId!=-1) {Write(" layer=\"%d\"", layerId);}
    Write(">\n");
}

void CXMLExporter::WriteFace(CComPtr<ISkpFace> pFace)
{
    HResult hr;

    BOOL bHasFrontTexture = false;
    BOOL bHasBackTexture = false;
    long frontId=-1;
    long backId=-1;
    long layerId=-1;

    if (m_pOptions->GetExportMaterials())
    {
        CComPtr<ISkpMaterial> pFrontMaterial = m_InheritanceManager.GetCurrentFrontMaterial();
        if (pFrontMaterial)
        {
            hr = pFrontMaterial->get_IsTexture(&bHasFrontTexture);
            frontId = GetEntityId(pFrontMaterial);
        }

        CComPtr<ISkpMaterial> pBackMaterial = m_InheritanceManager.GetCurrentBackMaterial();

        if (pBackMaterial)
        {
            hr = pBackMaterial->get_IsTexture(&bHasBackTexture);
            backId = GetEntityId(pBackMaterial);
        }
    }

    if (m_pOptions->GetExportLayers())
    {
        CComPtr<ISkpDrawingElement> pDE;
        hr = pFace->QueryInterface(IID_ISkpDrawingElement, (void**) &pDE);

        CComPtr<ISkpLayer> pLayer;
        hr = pDE->get_Layer(&pLayer);

        layerId = GetEntityId(pLayer);
    }

    BOOL bHasTexture = bHasFrontTexture | bHasBackTexture;
    CComPtr<ISkpUVHelper> pUVHelper = NULL;

    //If the face has a texture(s) applied to it, then create a UVHelper class so we can output the uv
    //coordinance at each vertex.
    if (bHasTexture)
    {
        CComPtr<ISkpCorrectPerspective> pCorrectPerspective;
        hr = m_pTextureWriter->QueryInterface(IID_ISkpCorrectPerspective, (void**)&pCorrectPerspective);

        hr = pFace->GetUVHelper(bHasFrontTexture, bHasBackTexture, pCorrectPerspective, &pUVHelper);
    }

    //Find out how many loops the face has
    CComPtr<ISkpLoops> pLoops;
    hr = pFace->get_Loops(&pLoops);

    long nLoops;
    hr = pLoops->get_Count(&nLoops);

    //If this is a simple face (no loops)
    if (nLoops==1)
    {
        WriteFaceStart(frontId, backId, layerId);

        IncreaseIndent();

        CComPtr<ISkpLoop> pLoop;
        hr = pFace->get_OuterLoop(&pLoop);

        CComPtr<ISkpVertices> pVerts;
        hr = pLoop->get_Vertices(&pVerts);

        long nVerts;
        hr = pVerts->get_Count(&nVerts);

        for (long i=0;i<nVerts;i++)
        {
            CComPtr<ISkpVertex> pVert;
            hr = pVerts->get_Item(i, &pVert);

            CComPtr<ISkpPoint3d> pSkpPoint;
            hr = pVert->get_Position(&pSkpPoint);

            CPoint3d point(pSkpPoint);
            CPoint3d worldPoint = m_InheritanceManager.GetCurrentTransform() * point;

            if (bHasTexture)
            {
                Write("<Vertex x=\"%f\" y=\"%f\" z=\"%f\">\n", worldPoint.X(), worldPoint.Y(), worldPoint.Z());
            }
            else
            {
                //This one closes the tag as well because we don't have child (UV) nodes
                Write("<Vertex x=\"%f\" y=\"%f\" z=\"%f\" />\n", worldPoint.X(), worldPoint.Y(), worldPoint.Z());
            }

            if (bHasFrontTexture)
            {
                IncreaseIndent();
                double u, v, q;
                pUVHelper->GetFrontUVQ(worldPoint.X(), worldPoint.Y(), worldPoint.Z(), &u, &v, &q);
                Write("<TextureCood front=\"true\" u=\"%f\" v=\"%f\" />\n", u, v);
                DecreaseIndent();
            }

            if (bHasBackTexture)
            {
                IncreaseIndent();
                double u, v, q;
                pUVHelper->GetBackUVQ(worldPoint.X(), worldPoint.Y(), worldPoint.Z(), &u, &v, &q);
                Write("<TextureCood front=\"false\" u=\"%f\" v=\"%f\" />\n", u, v);
                DecreaseIndent();
            }

            if (bHasTexture)
            {
                Write("</Vertex>\n");
            }

        }
        DecreaseIndent();
        Write("</Face>\n");
    }
    else
    {
        //If this is a complex face with one or more holes in it
        //we tesselate it into triangles using the polygon mesh class, then
        //export each triangle as a face.

        CComPtr<ISkpPolygonMesh> pMesh;

        if (bHasTexture)
        {
            pFace->CreateMeshWithUVHelper(3, pUVHelper, &pMesh);
        }
        else
        {
            pFace->CreateMesh(0, NULL, &pMesh);
        }

        long nPolys;
        hr = pMesh->get_NumPolygons(&nPolys);

        for (long i=0;i<nPolys;i++)
        {
            long nPoints;

            //The mesh is 1 based
            hr = pMesh->CountPolygonPoints(i+1, &nPoints);

            WriteFaceStart(frontId, backId, layerId);

            IncreaseIndent();
            for (long j=0;j<nPoints;j++)
            {
                CComPtr<ISkpPoint3d> skpPoint;
                hr = pMesh->get_PolygonPoint(i+1, j+1, &skpPoint);

                CPoint3d point(skpPoint);
                CPoint3d worldPoint = m_InheritanceManager.GetCurrentTransform() * point;

                if (bHasTexture)
                {
                    Write("<Vertex x=\"%f\" y=\"%f\" z=\"%f\">\n", worldPoint.X(), worldPoint.Y(), worldPoint.Z());
                }
                else
                {
                    //This one closes the tag as well because we don't have child (UV) nodes
                   Write("<Vertex x=\"%f\" y=\"%f\" z=\"%f\" />\n", worldPoint.X(), worldPoint.Y(), worldPoint.Z());
                }

                if (bHasFrontTexture)
                {
                    IncreaseIndent();
                    double u, v, q;
                    pUVHelper->GetFrontUVQ(worldPoint.X(), worldPoint.Y(), worldPoint.Z(), &u, &v, &q);
                    Write("<TextureCood front=\"true\" u=\"%f\" v=\"%f\" />\n", u, v);
                    DecreaseIndent();
                }

                if (bHasBackTexture)
                {
                    IncreaseIndent();
                    double u, v, q;
                    pUVHelper->GetBackUVQ(worldPoint.X(), worldPoint.Y(), worldPoint.Z(), &u, &v, &q);
                    Write("<TextureCood front=\"false\" u=\"%f\" v=\"%f\" />\n", u, v);
                    DecreaseIndent();
                }

                if (bHasTexture)
                {
                    Write("</Vertex>\n");
                }
            }
            DecreaseIndent();
            Write("</Face>\n");
        }
    }
}

void CXMLExporter::WriteEdge(CComPtr<ISkpEdge> pEdge)
{
    HResult hr;

    m_Stats.m_nEdges += 1;

    if (m_pOptions->GetExportLayers())
    {
        CComPtr<ISkpDrawingElement> pDE;
        hr = pEdge->QueryInterface(IID_ISkpDrawingElement, (void**) &pDE);

        CComPtr<ISkpLayer> pLayer;
        hr = pDE->get_Layer(&pLayer);

        long layerId = GetEntityId(pLayer);

        Write("<Edge layer=\"%d\">\n", layerId);
    }
    else
    {
        Write("<Edge>\n");
    }

    IncreaseIndent();

    CComPtr<ISkpPoint3d> pStartPoint;
    hr = pEdge->get_StartPoint(&pStartPoint);
    CPoint3d startPt(pStartPoint);
    CPoint3d startPoint = m_InheritanceManager.GetCurrentTransform() * startPt;
    Write("<Start x=\"%f\" y=\"%f\" z=\"%f\" />\n", startPoint.X(), startPoint.Y(), startPoint.Z());

    CComPtr<ISkpPoint3d> pEndPoint;
    hr = pEdge->get_EndPoint(&pEndPoint);
    CPoint3d endPt(pEndPoint);
    CPoint3d endPoint = m_InheritanceManager.GetCurrentTransform() * endPt;
    Write("<End x=\"%f\" y=\"%f\" z=\"%f\" />\n", endPoint.X(), endPoint.Y(), endPoint.Z());

    DecreaseIndent();

    Write("</Edge>\n");
}

posted @ 2011-07-28 14:21  贰百舞  阅读(437)  评论(0编辑  收藏  举报