- Main Page
- Related Pages
- Modules
- Classes
- Examples

# D3DGeometryItem.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,2008 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.
    // ==========================================================================
    //+

    #include <stdio.h>

    #include <D3DViewportRenderer.h>

    #include <maya/MGlobal.h>
    #include <maya/MString.h>
    #include <maya/MMatrix.h>
    #include <maya/MDagPath.h>
    #include <maya/MFnDagNode.h>
    #include <maya/MFnMesh.h>
    #include <maya/MItMeshPolygon.h>
    #include <maya/MBoundingBox.h>
    #include <maya/MImage.h>
    #include <maya/MDrawTraversal.h>
    #include <maya/MGeometryManager.h>
    #include <maya/MGeometry.h>
    #include <maya/MGeometryData.h>
    #include <maya/MGeometryPrimitive.h>
    #include <maya/MNodeMessage.h> // For monitor geometry list
    #include <maya/MPlug.h>
    #include <maya/MPlugArray.h>
    #include <maya/MFnSet.h>
    #include <maya/MFnNumericData.h>
    #include <maya/MItDependencyGraph.h>

    #include <stdio.h>

    #if defined(D3D9_SUPPORTED)

    //
    // Populate a D3DGeometry object from a Maya mesh
    //
    bool D3DGeometry::Populate( const MDagPath& dagPath, LPDIRECT3DDEVICE9 D3D)
    {
        Release();
        MFnMesh mesh( dagPath.node());

        // Figure out texturing
        //
        MString pn = dagPath.fullPathName();
        //printf("Convert shape %s\n", pn.asChar());
        bool haveTexture = false;
        int numUVsets = mesh.numUVSets();
        MString uvSetName;
        MObjectArray textures;
        if (numUVsets > 0)
        {
            mesh.getCurrentUVSetName( uvSetName );
            // Always send down uvs for now, since we don't dirty the populate
            // based on material texture connection.
            //
            //MStatus status = mesh.getAssociatedUVSetTextures(uvSetName, textures);
            //if (status == MS::kSuccess && textures.length())
            int numCoords = mesh.numUVs( uvSetName );
            if (numCoords > 0)
            {
                haveTexture = true;
            }
        }

        bool haveColors = false;
        int numColors = mesh.numColorSets();
        MString colorSetName;
        if (numColors > 0)
        {
            haveColors = true;
            mesh.getCurrentColorSetName(colorSetName);
        }

        bool useNormals = true;

        // Setup our requirements needs.
        MGeometryRequirements requirements;
        requirements.addPosition();
        if (useNormals)
            requirements.addNormal();
        if (haveTexture)
            requirements.addTexCoord( uvSetName );
        if (haveColors)
            requirements.addColor( colorSetName );

        // Test for tangents and binormals
        bool testBinormal = false;
        if (testBinormal)
            requirements.addBinormal( uvSetName );
        bool testTangent= false;
        if (testTangent)
            requirements.addTangent( uvSetName );

        MGeometry geom = MGeometryManager::getGeometry( dagPath, requirements, NULL );

        unsigned int numPrims = geom.primitiveArrayCount();
        if( numPrims)
        {
            const MGeometryPrimitive prim = geom.primitiveArray(0);

            NumIndices = prim.elementCount();
            if( NumIndices)
            {
                //MGeometryData::ElementType primType = prim.dataType();
                unsigned int *idx = (unsigned int *) prim.data();

                // Get the position data
                const MGeometryData pos = geom.position();
                float * posPtr = (float * )pos.data();
                if( !idx || !posPtr) return false;
                NumVertices = pos.elementCount();

                // Start building our vertex format. We always have position, so
                // start with that and add in all the elements we find along the way
                FVF = D3DFVF_XYZ;
                Stride = sizeof( float) * 3;

                // Get the normals data
                float * normPtr = NULL;
                if( useNormals)
                {
                    const MGeometryData norm = geom.normal();
                    normPtr = (float * )norm.data();
                    Stride += sizeof( float) * 3;
                    FVF |= D3DFVF_NORMAL;
                }

                // Get the texture coordinate data
                float *uvPtr = NULL;
                if( haveTexture)
                {
                    const MGeometryData uvs = geom.texCoord( uvSetName );
                    uvPtr = (float *)uvs.data();
                    Stride += sizeof( float) * 2;
                    FVF |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0);
                }

                unsigned int numColorComponents = 4;
                float *clrPtr = NULL;
                if (haveColors)
                {
                    const MGeometryData clrs = geom.color( colorSetName );
                    clrPtr = (float *)clrs.data();
                }
                else if (testBinormal)
                {
                    const MGeometryData binorm = geom.binormal( uvSetName );
                    clrPtr = (float *)binorm.data();
                    numColorComponents = 3;
                }
                else if (testTangent)
                {
                    const MGeometryData tang = geom.tangent( uvSetName );
                    clrPtr = (float *)tang.data();
                    numColorComponents = 3;
                }

                // Allocate our vertex buffer
                //
                if( D3D->CreateVertexBuffer( Stride * NumVertices, D3DUSAGE_WRITEONLY, FVF,
                                                D3DPOOL_DEFAULT, &VertexBuffer, NULL) != D3D_OK)
                {
                    MGlobal::displayWarning( "Direct3D renderer : Unable to allocate vertex buffer\n");
                    return false;
                }

                // Copy our vertex data into the buffer
                //
                float* VertexData = NULL;
                int FloatsPerVertex = Stride / sizeof( float);
                int StrideOffset = FloatsPerVertex - 3;
                //MGlobal::displayInfo( MString( "Allocating buffers for ") + NumVertices + MString( " verts and ") + NumIndices + MString( " indices\n"));
                VertexBuffer->Lock( 0, 0, (void**)&VertexData, D3DLOCK_DISCARD);
                for( unsigned int i = 0; i < NumVertices; i++)
                {
                    *VertexData++ = *posPtr++;
                    *VertexData++ = *posPtr++;
                    *VertexData++ = *posPtr++;
                    VertexData += StrideOffset;
                }
                VertexData -= NumVertices * FloatsPerVertex - 3;

                if( normPtr)
                {
                    for( unsigned int i = 0; i < NumVertices; i++)
                    {
                        *VertexData++ = *normPtr++;
                        *VertexData++ = *normPtr++;
                        *VertexData++ = *normPtr++;
                        VertexData += StrideOffset;
                    }
                    VertexData -= NumVertices * FloatsPerVertex - 3;
                }

                if( uvPtr)
                {
                    StrideOffset = FloatsPerVertex - 2;
                    for( unsigned int i = 0; i < NumVertices; i++)
                    {
                        *VertexData++ = *uvPtr++;
                        *VertexData++ = 1.0f - *uvPtr++;
                        VertexData += StrideOffset;
                    }
                    VertexData -= NumVertices * FloatsPerVertex - 2;
                }

                VertexBuffer->Unlock();

                // Allocate our index buffer
                //
                if( D3D->CreateIndexBuffer( NumIndices * sizeof( DWORD), 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &IndexBuffer, NULL) != D3D_OK)
                {
                    MGlobal::displayWarning( "Direct3D renderer : Unable to allocate index buffer\n");
                    return false;
                }

                // Copy our index data into the buffer
                //
                unsigned int* IndexData = NULL;
                IndexBuffer->Lock( 0, 0, (void**)&IndexData, D3DLOCK_DISCARD);
                memcpy( IndexData, idx, NumIndices * sizeof(DWORD));
                IndexBuffer->Unlock();
            }
        }
        return IndexBuffer && VertexBuffer;
    }

    #endif