Jump to content
  • Advertisement
Sign in to follow this  
lucky6969b

How to build a static mesh (ID3DXMesh) from a series of VBs?

This topic is 1037 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I am currently switching to asset importer to load files because of its flexibility.

I've got 2 questions. Firstly, If I load in various parts of a big scene in different entries (with unique vertex buffers and index buffers)?

If I want to build a physics system based on those little tiny buffers, I need to aggregate all the vertex buffers into one large vertex buffers,

or maybe more convenient to build a ID3DXMesh as a static mesh.

The question is how do I build a static mesh (ID3DXMesh) from many small pieces of Vertex buffers?

 

Second question is since I haven't yet created a ID3DXANIMATIONCONTROLLER,

I wonder how can I build such controllers with assimp? Do I have feed all animation keys,

times and transformations into the animation controller manually?

 

Thanks a lot

Jack

Edited by lucky6969b

Share this post


Link to post
Share on other sites
Advertisement


If I want to build a physics system based on those little tiny buffers

 

its often desirable to have geometry data for an object, and ALSO have a second simpler representation for the physics. IE a VB and IB for the mesh, and then also a BBox radius for checking collisions.

 

BBox, Bsphere, etc are popular choices for physics representations of objects. if you want pixel perfect 3d collisions, you use the BBox method as a first pass, then use the individual meshes for the complex intersection test. not sure if there's an algo for collision check of two arbitrary meshes. never got into pixel perfect collisions myself. they're seldom necessary.

 

to create a d3dx mesh, you new it and fill in the blanks. there's routines for copying the vb and ib and such. i originally used d3dx meshes, but now i just use them for loading from .x files. i load a .x into a d3dx mesh. copy the vb and ib to my mesh resource pool, then release the d3dx mesh.

 


Second question is since I haven't yet created a ID3DXANIMATIONCONTROLLER,
I wonder how can I build such controllers with assimp? Do I have feed all animation keys,
times and transformations into the animation controller manually?

 

if you're asking how to create a d3dx animation controller from scratch, instead of letting d3dx use a blank one when loading an animated .x file, then the answer is the same as for a d3dx mesh, you new it and fill in the blanks. again, there's routines for doing this.

 

the assimp page says it supports export now. guess its doesn't export .x yet, eh?

Share this post


Link to post
Share on other sites

Hello, I've been creating the mesh like this, but I can't generate adjacencies for the mesh.. It just continuously crashing on the generateAdjacency line... Anyways that I can fix that? Thanks Jack

bool CMesh::AggregateBuffers()
{
    std::vector<D3DVertex::VertexPositionNormal> vertexes;
    for (int i = 0; i < m_Entries.size(); i++) {
        IDirect3DVertexBuffer9* _vb = m_Entries[i].m_pVB;
        DWORD vertStride = m_Entries[i].m_vertStride;
        BYTE* pVert;
        _vb->Lock(0, m_Entries[i].m_numVerts * sizeof(D3DVertex::VertexPositionNormal), (VOID**)&pVert, 0);
        // read the vertices and copy them into one big buffer
        for (int i = 0; i < m_Entries[i].m_numVerts; i++) {
            D3DXVECTOR3 pos = *(D3DXVECTOR3*)(&pVert[vertStride * i + 0]);          
            D3DXVECTOR3 norm = *(D3DXVECTOR3*)(&pVert[vertStride * i + 3*sizeof(float)]);          
            //D3DXVECTOR3 uv = *(D3DXVECTOR3*)(&pVert[vertStride * i + 6*sizeof(float)]);          
            D3DVertex::VertexPositionNormal vertex;
            vertex.x = pos.x;
            vertex.y = pos.y;
            vertex.z = pos.z;
            vertex.nx = norm.x;
            vertex.ny = norm.y;
            vertex.nz = norm.z;
            //vertex.u = uv.x;
            //vertex.v = uv.y;
            
            vertexes.push_back(vertex);
        }
        _vb->Unlock();

        this->m_NumVerts += m_Entries[i].m_numVerts;

    }

    

    std::vector<DWORD> indexes32;
    std::vector<WORD> indexes16;
    for (int i = 0; i < m_Entries.size(); i++) {
        DWORD indStride =m_Entries[i].m_indStride;        
        IDirect3DIndexBuffer9* _ib = m_Entries[i].m_pIB;        
        BYTE* pInd;
        _ib->Lock(0, m_Entries[i].m_numIndices * indStride, (VOID**)&pInd, 0);
        // read the vertices and copy them into one big buffer
        for (int i = 0; i < m_Entries[i].m_numIndices; i++)
        {
            DWORD inx0, inx1, inx2 = 0;
            if (sizeof(DWORD) == indStride)
            {
                inx0 = *(int*)(&pInd[indStride * (i + 0)]);
                inx1 = *(int*)(&pInd[indStride * (i + 1)]);
                inx2 = *(int*)(&pInd[indStride * (i + 2)]);

                indexes32.push_back(inx0);
                indexes32.push_back(inx1);
                indexes32.push_back(inx2);
            }
            else
            {
                inx0 = *(WORD*)(&pInd[indStride * (i + 0)]);
                inx1 = *(WORD*)(&pInd[indStride * (i + 1)]);
                inx2 = *(WORD*)(&pInd[indStride * (i + 2)]);

                indexes16.push_back(inx0);
                indexes16.push_back(inx1);
                indexes16.push_back(inx2);
            }

            

            
        }
        
        _ib->Unlock();
        this->m_NumIndices += m_Entries[i].m_numIndices;
    }

    // Create a vertex buffer
    d3d::m_pDevice->CreateVertexBuffer(vertexes.size() * sizeof(D3DVertex::VertexPositionNormal),
            D3DUSAGE_WRITEONLY, D3DVertex::VertexPositionNormal::FVF, D3DPOOL_MANAGED,
            &m_pStaticVB, NULL);

    
    BYTE* pVerts;
    m_pStaticVB->Lock(0, vertexes.size() * sizeof(D3DVertex::VertexPositionNormal), (void**)&pVerts, 0);
    memcpy (pVerts, &vertexes[0], vertexes.size() * sizeof(D3DVertex::VertexPositionNormal));
    m_pStaticVB->Unlock();

    // use 32 bit
    if (!indexes16.empty()) {

        d3d::m_pDevice->CreateIndexBuffer(indexes16.size() * sizeof(WORD),
                D3DUSAGE_WRITEONLY,
                D3DFMT_INDEX16,
                D3DPOOL_MANAGED,
                &m_pStaticIB,
                0);
        VOID* pInds;
        m_pStaticIB->Lock(0, indexes16.size() * sizeof(WORD), (void**)&pInds, 0);
        memcpy(pInds, &indexes16[0], indexes16.size()*sizeof(WORD));
        m_pStaticIB->Unlock();
    }
    else
    {
        

        d3d::m_pDevice->CreateIndexBuffer(indexes32.size() * sizeof(DWORD),
                D3DUSAGE_WRITEONLY,
                D3DFMT_INDEX32,
                D3DPOOL_MANAGED,
                &m_pStaticIB,
                0);
        VOID* pInds;
        m_pStaticIB->Lock(0, indexes32.size() * sizeof(DWORD), (void**)&pInds, 0);
        memcpy(pInds, &indexes32[0], indexes32.size()*sizeof(DWORD));
        m_pStaticIB->Unlock();
    }
    

    // Create a LPD3DXMESH here
    if (!indexes16.empty()) {
        
        D3DXCreateMeshFVF(indexes16.size()/3, vertexes.size(), D3DXMESH_MANAGED,
                D3DVertex::VertexPositionNormal::FVF, d3d::m_pDevice, &m_pStaticMesh);
    }
    else
    {
        D3DXCreateMeshFVF(indexes32.size()/3, vertexes.size(), D3DXMESH_MANAGED,
                D3DVertex::VertexPositionNormal::FVF, d3d::m_pDevice, &m_pStaticMesh);
    }

    {
        BYTE* pVerts = 0;                 
        m_pStaticMesh->LockVertexBuffer(0, (VOID**)&pVerts);
        memcpy(pVerts, &vertexes[0], sizeof(D3DVertex::VertexPositionNormal)*vertexes.size());
        m_pStaticMesh->UnlockVertexBuffer();

        if (!indexes16.empty())
        {    
            BYTE* pInds;
            m_pStaticMesh->LockIndexBuffer(0, (VOID**)&pInds);
            memcpy(pInds, &indexes16[0], sizeof(WORD)*indexes16.size());
            m_pStaticMesh->UnlockIndexBuffer();
            
        }
        else
        {
            BYTE* pInds;
            m_pStaticMesh->LockIndexBuffer(0, (VOID**)&pInds);
            memcpy(pInds, &indexes32[0], sizeof(DWORD)*indexes32.size());
            m_pStaticMesh->UnlockIndexBuffer();
        }

        DWORD faceCount = 0;
        DWORD subSetNum = 0;
        SetSubsets(m_pStaticMesh, &faceCount, &subSetNum);
    }
    

        
    return true;
}


DWORD CMesh::SetSubsets(ID3DXMesh *pMesh,DWORD *pFaceCount,DWORD *pSubsetNum) {
   
    // Get face count, used to ensure we don't overrun attribute buffer
	DWORD numFaces=pMesh->GetNumFaces();
 
    // lock the attribute buffer
    DWORD *attribBuf;
    HRESULT hr;
    if (SUCCEEDED(hr=pMesh->LockAttributeBuffer(D3DLOCK_DISCARD,&attribBuf))) {

        // initialize face counter
        DWORD faceNum=0;

        // loop through the subsets
        for (int i=0;pFaceCount[i];i++) {

            // make sure there are enough faces for this subset
            if (faceNum+pFaceCount[i]>=numFaces) {
                // not enough faces, unlock the attribute buffer and return error code
                pMesh->UnlockAttributeBuffer();
                return E_INVALIDARG;
            }
 
            // loop through the faces for this range
            for (int j=0;jUnlockAttributeBuffer();

        // allocate storage and generate adjacency data
        /*DWORD *pAdj=new DWORD[numFaces*3];
		memset(pAdj, 0, sizeof(DWORD)*numFaces*3);
        if (!pAdj)
            return E_OUTOFMEMORY;
        if (FAILED(hr=pMesh->GenerateAdjacency(0.0f,pAdj))) {
            delete pAdj;
            return hr;
        }*/
		// Optimize the mesh for performance
		/*DWORD* pAdj = NULL;
		pAdj = new DWORD[pMesh->GetNumFaces() * 3];
		if( pAdj == NULL )
			return E_OUTOFMEMORY;
		pMesh->GenerateAdjacency( 1e-6f, pAdj );*/

        // optimize the mesh with attribute sorting
        // D3DXMESHOPT_ATTRSORT
		/*if (FAILED(hr=pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE,pAdj,NULL,NULL,NULL))) {
            delete pAdj;
            return hr;
        }

        // de-allocate adjacency data storage
        delete pAdj;

    } else

        // return error code on failure to lock attribute buffer
        return hr;*/
	}

	DWORD* rgdwAdjacency = NULL;

	// Make sure there are normals which are required for lighting
    if( !( pMesh->GetFVF() & D3DFVF_NORMAL ) )
    {
        LPD3DXMESH pTempMesh;
        hr = pMesh->CloneMeshFVF( pMesh->GetOptions(),
                                  pMesh->GetFVF() | D3DFVF_NORMAL,
								  d3d::m_pDevice, &pTempMesh );
        if( FAILED( hr ) )
            return hr;

        D3DXComputeNormals( pTempMesh, NULL );

        SAFE_RELEASE( pMesh );
        pMesh = pTempMesh;
    }

	// Optimze the mesh to make it fast for the user's graphics card
    rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3];
    if( rgdwAdjacency == NULL )
        return E_OUTOFMEMORY;
    V( pMesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ) );
    pMesh->OptimizeInplace( D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL );

    // return success
    return S_OK;
}
Edited by lucky6969b

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!