.x Model and duplicated vertices issue

I can see that in a .x template

template VertexDuplicationIndices {
<b8d65549-d7c9-4995-89cf-53a9a8b031e3>
DWORD nIndices;
DWORD nOriginalVertices;
array DWORD indices[nIndices];
}


There is a duplication of vertices. I believe this was done during the export when faces sharing a vertex duplicates that vertex. Am I right to say that

My main problem is how can I get pointers or references back to the original vertices

Can anyone help


Answer this question

.x Model and duplicated vertices issue

  • C#2006

    Sorry for the delay, I was out with my mates and when I got back I was in no fit condition to do anything.

    There is a difference between the actual mesh indices and “VertexDuplicationIndices”.

    “VertexDuplicationIndices” doesn’t actually make triangles or whatever type of ordering, its just saying these are the indices used with a few duplicates that have different properties. Also the template might be declared but it doesn’t mean it’s used.

    Looks like Etienne is onto something with D3DXWeldVertices, I haven’t used it either, will try later too.

    I’m not sure about Maya, I use trueSpace. In the utilities section of the SDK is the source code for the Maya exporter which might be worth checking out, well I’m using the December 2004 version of the SDK which has it, not sure about the latest.

    Here’s a small console app to extract the duplication data. Notice the way I’m linking the structures, things end up in a reversed order. I haven’t done any error checking to save space, you can add this.

     

    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <iostream>

    // xfile objects
    #include <d3dx9xof.h>

    // required header for VertexDuplicationIndices template and guid
    #include <d3dx9mesh.h>

    // Standard xfile templates and guids
    #include "rmxfguid.h"
    #include "rmxftmpl.h"

    #pragma comment (lib, "d3dx9.lib")      // D3DX lib

    // Declare the structure
    struct sDuplicateIndices
    {
        DWORD   nIndices;
        DWORD   nOriginalVertices;
        int *pIndices;

        sDuplicateIndices *pNext;

        sDuplicateIndices()
        {
            nIndices = 0;
            nOriginalVertices = 0;
            pIndices = NULL;
            pNext = NULL;
        }

        ~sDuplicateIndices()
        {
            if(pIndices) delete [] pIndices;
            if(pNext)    delete pNext;
        }
    };

    BOOL Load(const char *FileName, sDuplicateIndices **ppDupIndices);
    BOOL Parse(ID3DXFileData *pData, sDuplicateIndices **ppDupIndices);

    int main()
    {
        sDuplicateIndices *pDupIndices = NULL;

        // SDK sample, not to big
        Load("airplane 2.x", &pDupIndices);

        if(pDupIndices)
        {
            sDuplicateIndices* ptr = pDupIndices;
            while(ptr != NULL)
            {
                std::cout << "Number of indices: " << ptr->nIndices << std::endl;
                std::cout << "Original vertices: " << ptr->nOriginalVertices << std::endl;
                std::cout << "The indices : " << std::endl;
                for(DWORD i = 0; i < ptr->nIndices; ++i)
                {
                    std::cout << ptr->pIndices[ i ] << ",";
                }
                std::cout << std::endl << std::endl;

                ptr = ptr->pNext;
            }
            delete pDupIndices;
        }

     return 0;
    }

    BOOL Load(const char *FileName, sDuplicateIndices **ppDupIndices)
    {
        ID3DXFile           *pFile = NULL;
        ID3DXFileEnumObject *pEnum = NULL;
        ID3DXFileData       *pData = NULL;
        SIZE_T               nChildren;
        HRESULT              hr;

        // Create file object
        hr = D3DXFileCreate(&pFile);

        // Register standard templates
        hr = pFile->RegisterTemplates((LPCVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES);

        // Register skin extension templates where VertexDuplicationIndices is defined
        // Shouldn't be needed since these are usually defined in the XFiles
        //hr = pFile->RegisterTemplates((LPCVOID)XSKINEXP_TEMPLATES, strlen(XSKINEXP_TEMPLATES));
        //hr = pFile->RegisterTemplates((LPCVOID)XEXTENSIONS_TEMPLATES, strlen(XEXTENSIONS_TEMPLATES));

        // I think there are more templates spread around the place

        // Create enumeration object, you’ll get a pass error here for an invalid xfile
        hr = pFile->CreateEnumObject((LPCVOID)FileName, D3DXF_FILELOAD_FROMFILE, &pEnum);

        // Get the number of top-level objects
        hr = pEnum->GetChildren(&nChildren);

        // Loop through the top-level objects
        for(SIZE_T nChild = 0; nChild < nChildren; ++nChild)
        {
            // Get the child data
            hr = pEnum->GetChild(nChild, &pData);

            // Parse data
            Parse(pData, ppDupIndices);

            pData->Release();
        }
        pEnum->Release();
        pFile->Release();

        return TRUE;
    }

    BOOL Parse(ID3DXFileData *pData, sDuplicateIndices **ppDupIndices)
    {
        ID3DXFileData *pSubData = NULL;
        SIZE_T         Size;
        GUID           Type;
        BYTE         **Ptr = NULL;
        HRESULT        hr;

        // Get the template type
        hr = pData->GetType(&Type);

        // Check for a VertexDuplicationIndices type
        if(Type == DXFILEOBJ_VertexDuplicationIndices)
        {
            // Create a new structure
            sDuplicateIndices *pDI = new sDuplicateIndices;

            // Access the data buffer
            hr = pData->Lock(&Size, (LPCVOID*)&Ptr);

            // Load the information
            pDI->nIndices = ((DWORD*)Ptr)[0];
            pDI->nOriginalVertices = ((DWORD*)Ptr)[1];
            pDI->pIndices = new int[pDI->nIndices];
            memcpy(pDI->pIndices, &((DWORD*)Ptr)[2], sizeof(int) * pDI->nIndices);

            // Release the data buffer
            hr = pData->Unlock();

            // Link into list
            pDI->pNext = *ppDupIndices;
            *ppDupIndices = pDI;
        }

        // Scan for embedded templates
        hr = pData->GetChildren(&Size);
        for(SIZE_T nChild = 0; nChild < Size; ++nChild)
        {
            hr = pData->GetChild(nChild, &pSubData);
            Parse(pSubData, ppDupIndices);
            pSubData->Release();
        }

        return TRUE;
    }


    Check out a book like Jim Adams “Advanced Animation with DirectX” for more advanced stuff dealing with animation loading.


  • xeno18274

    For a small square in 2 triangles :
    the Vertex Buffer 0,1,2,3 so
    for the Index Buffer 2 faces/triangle 0,1,2 and 0,2,3 (clock wise)

    Your index use the order your vertex was entered...
    They are NOT the number of the vertex...just the ORDER they were entered...

    I have the same problem to solve...

    I have many square to add up and I want to remove their common vertex

    for 2 square I have
    0,1,2,3 and 3,2,4,5
    So I have twice the vertex 2 and 3...

    I found the function D3DXWeldvertice...that should merge all vertex that have
    the same position and material...it should word for static mesh, I didn't try it yet

    It's a mesh function...(not the exact word for the function but it has ''Weld'' in it)


  • kiwigriff

    I was looking on the net, but information on this subject is sparse, I found some good ebooks though.

    From what I’ve understood so far some 3D packages write the templates to the xfile so they don’t have to register them, the templates are essentially registered as the file is read. In some of the forums I came across, people were creating simple shapes by writing their own xfiles and trying to load them into their 3D software with little success, they then added the template declarations to their files and the thing would load without a problem.

    If you’re parsing the file yourself you can always check for the template’s GUID and extract the information to something separate, then you can play about with it. Maybe you can create a separate vertex buffer and put the vertices into that while ignoring any duplicates to see what will happen.

    You can also optimise your mesh using D3DXMESHOPT_ATTRSORT so the faces with the same properties a grouped together. Then you can extract the meshes attribute table and use the attribute’s ID to determine which material and/or texture is being used, also the faces and vertices used. This way you can draw the subsets you want.

    Basically we’re going to have to experiment, or maybe someone who knows what he’s talking might come a tell us.


  • TravelMan

    Sorry I think I misread your part on parsing the file. You are talking abt parsing the actual x-file I don't think that its possible as I wont be able to identify which is duplicates or the original vertices from the huge array of vertices id. So I guess maybe I will look into the Direct X SDK to see if I can recompile my own exporter with some more information into it.

    Please correct me or advise me if my understanding is wrong, as I am still pretty new to Direct X.

  • jefswy

  • Giedrius Banaitis

    From reading the description of "VertexDuplicationIndices" in the DX documentation this is what I understand.

    "nIndices" the number of vertices in the mesh.

    "nOriginalVertices" is the number of vertices before duplication, so the number of duplicate vertices must be:

    nIndices – nOriginalVertices = number of duplicates

    Any indices that are the same in "indices[nIndices]" are the duplicates, so you know where the duplicates are in the vertex buffer.

    The thing is the information’s there, but how do you put it together for what you want That’s the question.

    If you’ve never passed an xfile before let me know and I’ll put a little example for you.


  • nidionys

    Hi there,



    Thanks for the reply, I should have gone to the DirectX SDK files to compile my own exporter that exports the information I need.. how silly of me not to think of this.

    I will try out the
    D3DXMESHOPT_ATTRSORT later on too.. thanks!

  • Claudia K

    Hi again

    I think I am getting what you are driving at.

    In the .x file there is the array of indices
    eg.
    0
    1
    2
    3
    2
    ....

    So the second "2" is actually a duplicate right So now all I really need is to parse the .x file and get a handle to this array then remove the duplicates I am not that familar to parsing the .x file, do you have an example to show me

    This is another problem, I just realise that directx reads the vertices in a different order then that of Maya. It reads them by the triangle while Maya reads it from bottom up, ie. the DirectX ordering of vertices don't match the Maya one. Is there a way for the DirectX to order the vertices differently so that it tallies perfectly with the Maya one

    Thanks a million!

  • .x Model and duplicated vertices issue