Example #1
0
/**
 * \brief Called to render a mesh
 * \param device - the Direct3D device object
 * \param meshContainerBase - the mesh container
 * \param frameBase - frame containing the mesh
 * \author Keith Ditchburn \date 18 July 2005
*/
void CXFileEntity::DrawMeshContainer(LPD3DXMESHCONTAINER meshContainerBase, LPD3DXFRAME frameBase)
{
	DWORD attrSize = 0;
	// Cast to our extended frame type
	D3DXFRAME_EXTENDED *frame = (D3DXFRAME_EXTENDED*)frameBase;		

	// Cast to our extended mesh container
	D3DXMESHCONTAINER_EXTENDED *meshContainer = (D3DXMESHCONTAINER_EXTENDED*)meshContainerBase;
	
	// Set the world transform
    m_d3dDevice->SetTransform(D3DTS_WORLD, &frame->exCombinedTransformationMatrix);

	unsigned int pass;
	if (effect) {
		effect->SetMatrix("worldmat",&frame->exCombinedTransformationMatrix);

		effect->Begin(&pass,0);
		effect->BeginPass(0);
	}

	// Loop through all the materials in the mesh rendering each subset
    for (unsigned int iMaterial = 0; iMaterial < meshContainer->NumMaterials; iMaterial++)
    {
		// use the material in our extended data rather than the one in meshContainer->pMaterials[iMaterial].MatD3D
		//m_d3dDevice->SetMaterial( &meshContainer->exMaterials[iMaterial] );
		//m_d3dDevice->SetTexture( 0, meshContainer->exTextures[iMaterial] );

		// Select the mesh to draw, if there is skin then use the skinned mesh else the normal one
		LPD3DXMESH pDrawMesh = (meshContainer->pSkinInfo) ? meshContainer->exSkinMesh: meshContainer->MeshData.pMesh;

		// Finally Call the mesh draw function
        //pDrawMesh->DrawSubset(iMaterial);

		pDrawMesh->GetVertexBuffer(&vb.vb);
		pDrawMesh->GetIndexBuffer(&ib.ib);

		//D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE];
		//pDrawMesh->GetDeclaration(pDecl);
		//renderSystem->CreateVertexDeclaration(&pDecl[0],&vb.declaration);
		// Получение данных о количестве вершин, индексов и полигонов
		dwNumVerticies	= pDrawMesh->GetNumVertices();
		dwNumIndecies	= pDrawMesh->GetNumFaces()*3;
		dwNumFaces		= pDrawMesh->GetNumFaces();
		vb.vertexSize = (short)pDrawMesh->GetNumBytesPerVertex();

		renderSystem->DrawIndexedPrimitive(vb,0,dwNumVerticies,ib,0,dwNumFaces);
    }

	if (effect) {
		effect->EndPass();
		effect->End();
	}
}
Example #2
0
void cMyASELoader::LoadMesh(){
#ifdef _DEBUG
	_ASSERT(m_bLoaded && "Data Not Loaded");
#endif
	int check = 0;
	for (size_t i = 0; i < m_vecASENode.size(); i++){
		if (m_vecASENode[i].nRef != INT_MAX){
			m_vecsubSet.push_back(m_vecASENode[i].nRef);
			LPD3DXMESH pMesh = NULL;
			HRESULT hr = D3DXCreateMeshFVF(m_vecASENode[i].vecVertex.size() / 3,
				m_vecASENode[i].vecVertex.size(),
				D3DXMESH_MANAGED,
				ST_PNT_VERTEX::FVF,
				g_pD3DDevice,
				&pMesh);

			ST_PNT_VERTEX* pV = NULL;
			pMesh->LockVertexBuffer(0, (LPVOID*)&pV);
			memcpy(pV, &m_vecASENode[i].vecVertex[0], m_vecASENode[i].vecVertex.size() * sizeof(ST_PNT_VERTEX));
			pMesh->UnlockVertexBuffer();

			WORD* pI = NULL;
			pMesh->LockIndexBuffer(0, (LPVOID*)&pI);
			for (size_t j = 0; j < pMesh->GetNumVertices(); ++j)
			{
				pI[j] = j;
			}
			pMesh->UnlockIndexBuffer();

			DWORD* pA = NULL;
			pMesh->LockAttributeBuffer(0, &pA);
			for (size_t j = 0; j < pMesh->GetNumFaces(); j++){
				pA[j] = m_vecASENode[i].nRef;
			}
			pMesh->UnlockAttributeBuffer();

			std::vector<DWORD> vecAdjBuffer(m_vecASENode[i].vecVertex.size());
			pMesh->GenerateAdjacency(0.0f, &vecAdjBuffer[0]);

			pMesh->OptimizeInplace(
				D3DXMESHOPT_ATTRSORT |
				D3DXMESHOPT_COMPACT |
				D3DXMESHOPT_VERTEXCACHE,
				&vecAdjBuffer[0], 0, 0, 0);

			m_vecMeshs.push_back(pMesh);
		}
	}
	m_bMeshed = true;
}
Example #3
0
    /* ================================================================================ */
    bool init_ff (const sD3D9_XMSH* xmesh, DWORD idx, const map_acs<crh3d9_texr>* texpool)
    {
        int32u*         ptr;
        crh3d9_texr*    texr;
        D3DXMATERIAL*   mtrl;

        mtrl = (D3DXMATERIAL*)xmesh->xattr->GetBufferPointer();
        mtrl += idx;
        if (mtrl->pTextureFilename != NULL) {
            texr = texpool->get(mtrl->pTextureFilename);
            if (texr == NULL)
                return (false);
            m_map_kd = texr->get_texr();
        }
        else {
            m_map_kd = NULL;
        }
        m_idx = idx;
        m_msh = xmesh->xmesh;
        if (idx == 0) {
            m_nv = m_msh->GetNumVertices();
            m_nt = m_msh->GetNumFaces();
        }
        else {
            m_nv = m_nt = 0;
        }
        m_mtl = &mtrl->MatD3D;
        m_mtl->Ambient.r = m_mtl->Diffuse.r;
        m_mtl->Ambient.g = m_mtl->Diffuse.g;
        m_mtl->Ambient.b = m_mtl->Diffuse.b;
        m_mtl->Ambient.a = 0.0f;
        if (m_mtl->Diffuse.a < 1.0f)
            m_type |= ATTR_TYPE_ALPHAOP;
        if (m_map_kd != NULL)
            m_type |= ATTR_TYPE_TEXTURE;
        ptr = (int32u*)(&m_mtl->Specular);
        for (idx = 0; idx < 3; idx++) {
            if (*ptr != 0) {
                m_type |= ATTR_TYPE_SPECULAR;
                break;
            }
            ptr += 1;
        }
        return (true);
    }
Example #4
0
HRESULT KG3DMesh::_LoadBSPFileFromMemory(IKG_Buffer *piBSPFile)
{
	HRESULT hrResult  = E_FAIL;
    HRESULT hrRetCode = E_FAIL;
    DWORD dwBSPVertexCount = 0;
    DWORD dwBSPFaceCount = 0;
    DWORD dwMeshVerticesCount = 0;
    DWORD dwMeshFacesCount = 0;
    LPD3DXMESH piMesh = m_ppMeshes[SMBT_NORMAL];
    KG3DBsp *pBSP = NULL;
   
    ASSERT(piBSPFile);

    KGLOG_PROCESS_ERROR(piMesh);
    dwMeshFacesCount    = piMesh->GetNumFaces();
    dwMeshVerticesCount = piMesh->GetNumVertices();

    pBSP = new KG3DBsp;
    KGLOG_PROCESS_ERROR(pBSP);

	hrRetCode = pBSP->LoadFromMemory(piBSPFile);
	KGLOG_COM_PROCESS_ERROR(hrRetCode);

    hrRetCode = pBSP->GetMeshInfo(&dwBSPVertexCount, &dwBSPFaceCount);
    KGLOG_COM_PROCESS_ERROR(hrRetCode);

    if ((dwBSPVertexCount != dwMeshVerticesCount) || (dwBSPFaceCount != dwMeshFacesCount))
    {
        KGLogPrintf(KGLOG_ERR, "%s, BSP unmatch Mesh :(", m_scName.c_str());
        KG_PROCESS_ERROR(FALSE);
    }

    ASSERT(!m_lpBsp);
    m_lpBsp = pBSP;
    pBSP = NULL;
	hrResult = S_OK;
Exit0:
    KG_DELETE(pBSP);
	if(FAILED(hrResult))
	{
		KGLogPrintf(KGLOG_ERR, "%s BSP加载失败", m_scName.c_str());
	}
	return hrResult;
}
Example #5
0
HRESULT D3DXMeshCreateAttributeEnumer(LPD3DXMESH pMesh, D3DXMeshAttributeEnumer& enumer )
{
	_ASSERTE(! enumer.IsValid());
	ZeroMemory(&enumer, sizeof(D3DXMeshAttributeEnumer)); //因为外部传入的enumer是可能重用的,这里绝对要重新清空一次

	_ASSERTE(NULL != pMesh);
	KG_PROCESS_ERROR(NULL != pMesh);
	{
		HRESULT hr = pMesh->LockAttributeBuffer(0, reinterpret_cast<DWORD**>(&enumer.m_pBuffer));
		KG_COM_PROCESS_ERROR(hr);
		_ASSERTE(1 == sizeof(BYTE) && 2 == sizeof(WORD) && 4 == sizeof(DWORD));

		enumer.m_pMesh = pMesh;
		enumer.m_pMesh->AddRef();
		enumer.m_dwNumFaceCount = pMesh->GetNumFaces();

		return S_OK;
	}
Exit0:
	return E_FAIL;
}
Example #6
0
HRESULT D3DXMeshCreateIndexEnumer( LPD3DXMESH pMesh, D3DXMeshIndexEnumer& enumer )
{
	_ASSERTE(! enumer.IsValid());
	ZeroMemory(&enumer, sizeof(D3DXMeshIndexEnumer)); //因为外部传入的enumer是可能重用的,这里绝对要重新清空一次

	_ASSERTE(NULL != pMesh);
	KG_PROCESS_ERROR(NULL != pMesh);
	{
		HRESULT hr = pMesh->LockIndexBuffer(0, reinterpret_cast<LPVOID*>(&enumer.m_pBuffer));
		KG_COM_PROCESS_ERROR(hr);
		_ASSERTE(1 == sizeof(BYTE) && 2 == sizeof(WORD) && 4 == sizeof(DWORD));

		enumer.m_pMesh = pMesh;
		enumer.m_pMesh->AddRef();
		enumer.m_dwNumBytePerIndex = (pMesh->GetOptions() & D3DXMESH_32BIT) ? 4 : 2;
		enumer.m_dwNumIndexCount = pMesh->GetNumFaces() * 3;
	
		return S_OK;
	}
Exit0:
	return E_FAIL;
}
Example #7
0
HRESULT D3DXMeshCreateByVerticesPos( DWORD dwFVF, D3DVECTOR* pPosArray, DWORD dwVertexCount
									, DWORD* pIndexArray, DWORD dwNumIndexCount
									, LPDIRECT3DDEVICE9 pDevice, DWORD dwOption, LPD3DXMESH* pRet )
{
	HRESULT hr = E_FAIL;
	LPD3DXMESH pMesh = NULL;
	KG_PROCESS_ERROR((dwFVF & D3DFVF_XYZ));
	KG_PROCESS_ERROR(NULL != pPosArray && NULL != pIndexArray && NULL != pDevice && NULL != pRet);

	_ASSERTE(IsMeshValidToBeCreated(dwOption, dwVertexCount, dwNumIndexCount));

	{
		DWORD dwNumFaces = dwNumIndexCount / 3;
		
		hr = D3DXCreateMeshFVF(dwNumFaces, dwVertexCount, dwOption, dwFVF, pDevice, &pMesh);
		KG_COM_PROCESS_ERROR(hr);
		
#if defined(DEBUG) | defined(_DEBUG)
		ULONG uRefSave = KGGetRef(pMesh);
#endif

		{
			BOOL bValidity = pMesh->GetNumVertices() == dwVertexCount && pMesh->GetNumFaces() == dwNumFaces;
			KG_PROCESS_ERROR(bValidity);
		}
		
		_ASSERTE(sizeof(BYTE) == 1);
		{
			D3DXMeshVertexEnumer vertexEnumer;
			hr = D3DXMeshCreateVertexEnumer(pMesh, vertexEnumer);
			KG_COM_PROCESS_ERROR(hr);
			_ASSERTE(vertexEnumer.IsValid() && vertexEnumer.GetVertexCount() == dwVertexCount);
			for (UINT i = 0; i < vertexEnumer.GetVertexCount(); ++i)
			{
				vertexEnumer.SetPos(i, pPosArray[i]);
			}
		}

		{
			D3DXMeshIndexEnumer indexEnumer;
			hr = D3DXMeshCreateIndexEnumer(pMesh, indexEnumer);
			KG_COM_PROCESS_ERROR(hr);
			_ASSERTE(indexEnumer.IsValid() && indexEnumer.GetIndexCount() <= dwNumIndexCount);
			
			for (UINT i = 0; i < indexEnumer.GetIndexCount(); ++i)
			{
				indexEnumer.SetIndex(i, pIndexArray[i]);
			}
		}

		D3DXMeshZeroMeshAttributes(pMesh);

		_ASSERTE(uRefSave == KGGetRef(pMesh));
	}
	
	*pRet = pMesh;
	return S_OK;
Exit0:
	SAFE_RELEASE(pMesh);
	return E_FAIL;
}
Example #8
0
void CreateGeometry(const char* sourceFile)
{
    cout << endl << "Reading " << sourceFile << endl;
    wstring wideSourceFile(sourceFile, sourceFile + strlen(sourceFile));

    // Load the mesh from the specified file
    LPD3DXBUFFER pD3DXMtrlBuffer;
    LPD3DXBUFFER pD3DXEffectInstances;
    HRESULT hr = D3DXLoadMeshFromX(
        wideSourceFile.c_str(),
        D3DXMESH_SYSTEMMEM,
        g_pd3dDevice, 0,
        &pD3DXMtrlBuffer, &pD3DXEffectInstances, &g_dwNumMaterials,
        &g_pMesh);

    if (FAILED(hr))
    {
        MessageBox(0, (L"Could not find " + wideSourceFile).c_str(), L"X2CTM", MB_OK);
        exit(1);
    }

    DWORD* adjacencyIn = new DWORD[3 * g_pMesh->GetNumFaces()];
    g_pMesh->GenerateAdjacency(0.0001f, adjacencyIn);

    DWORD* adjacencyOut = new DWORD[3 * g_pMesh->GetNumFaces()];

    LPD3DXMESH newMesh = 0;
    //hr = g_pMesh->Optimize(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT, adjacencyIn, adjacencyOut, 0, 0, &newMesh);
    //hr = g_pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, adjacencyIn, adjacencyOut, 0, 0);
    if (FAILED(hr))
    {
        MessageBox(0, L"Unable to build attribute table", L"Whatever", MB_OK);
        exit(1);
    }
    //g_pMesh = newMesh;

    if (WeldVertices)
    {
        DWORD beforeVertCount = g_pMesh->GetNumVertices();
        DWORD beforeFaceCount = g_pMesh->GetNumFaces();
        hr = D3DXWeldVertices(g_pMesh, D3DXWELDEPSILONS_WELDALL, 0, 0, 0, 0, 0);
        DWORD afterVertCount = g_pMesh->GetNumVertices();
        DWORD afterFaceCount = g_pMesh->GetNumFaces();
    }

    D3DXATTRIBUTERANGE table[256];
    DWORD tableSize = sizeof(table) / sizeof(table[0]);
    g_pMesh->GetAttributeTable(&table[0], &tableSize);

    D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*) pD3DXMtrlBuffer->GetBufferPointer();
    D3DXEFFECTINSTANCE* d3dxEffects = (D3DXEFFECTINSTANCE*) pD3DXEffectInstances->GetBufferPointer();

    g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials];
    g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials];

    for (DWORD i = 0; i < g_dwNumMaterials; i++)
    {
        g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
        g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
        g_pMeshTextures[i] = 0;
        if (d3dxMaterials[i].pTextureFilename && lstrlenA(d3dxMaterials[i].pTextureFilename) > 0)
        {
            D3DXCreateTextureFromFileA(g_pd3dDevice, d3dxMaterials[i].pTextureFilename, &g_pMeshTextures[i]);
        }
    }
/*
    for (DWORD attrib = 0;  attrib < tableSize; ++attrib)
    {

        // I'm not so sure about material-to-attribute correlation
//        if (attrib < g_dwNumMaterials)
//        {
            LPSTR pTexture = d3dxMaterials[attrib].pTextureFilename;
            LPSTR pSlash = strchr(pTexture, '\\');
            if (pSlash)
            {
                pTexture = ++pSlash;
            }
            cout << "{Texture='" << pTexture << "',";
//        }

        string subMeshFilename = string("X_") + string("Armature.ctm"); // string(pTexture).substr(0, strlen(pTexture) - 4) + ".ctm";
        subMeshFilename[0] = attrib + 'A';

        ExportRangeCTM(table[attrib], g_pMesh, subMeshFilename.c_str());

        cout
            //<< table[attrib].AttribId << ' '
            << "FaceStart=" << table[attrib].FaceStart << ','
            << "FaceCount=" << table[attrib].FaceCount << ','
            << "VertexStart=" << table[attrib].VertexStart << ','
            << "VertexCount=" << table[attrib].VertexCount << '}' << endl;
    }
*/
    pD3DXMtrlBuffer->Release();


    // Convert the filename from .X to .CTM while preserving the full path.

   char destFile[_MAX_PATH];
   char drive[_MAX_DRIVE];
   char dir[_MAX_DIR];
   char fname[_MAX_FNAME];
   char ext[_MAX_EXT];
    
   _splitpath_s(sourceFile, drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT);
   _makepath_s(destFile, _MAX_PATH, drive, dir, fname, "ctm");

    ExportCTM(g_pMesh, destFile);
    cout << "Exported " << destFile << endl;
/*
    const WORD MISSING_ATTRIBUTE = 0xffff;
    WORD positionsOffset = MISSING_ATTRIBUTE;
    WORD normalsOffset = MISSING_ATTRIBUTE;
    WORD texCoordsOffset = MISSING_ATTRIBUTE;

    D3DVERTEXELEMENT9 vertexLayout[MAX_FVF_DECL_SIZE];
    D3DVERTEXELEMENT9 endMarker = D3DDECL_END();
    g_pMesh->GetDeclaration(vertexLayout);
    D3DVERTEXELEMENT9* pVertexLayout = &vertexLayout[0];
    for (int attrib = 0;  attrib < MAX_FVF_DECL_SIZE; ++attrib, pVertexLayout++)
    {
        if (0 == memcmp(&vertexLayout[attrib], &endMarker, sizeof(endMarker)))
        {
            break;
        }
        if (pVertexLayout->Stream != 0)
        {
            cout << "Nonzero stream: " << pVertexLayout->Stream << endl;
            continue;
        }
        if (pVertexLayout->Usage == D3DDECLUSAGE_POSITION && pVertexLayout->Type == D3DDECLTYPE_FLOAT3)
        {
            cout << "Contains positions " << (int) pVertexLayout->UsageIndex << endl;
            positionsOffset = pVertexLayout->Offset;
        }
        else if (pVertexLayout->Usage == D3DDECLUSAGE_NORMAL && pVertexLayout->Type == D3DDECLTYPE_FLOAT3)
        {
            cout << "Contains normals " << (int) pVertexLayout->UsageIndex << endl;
            normalsOffset = pVertexLayout->Offset;
        }
        else if (pVertexLayout->Usage == D3DDECLUSAGE_TEXCOORD && pVertexLayout->Type == D3DDECLTYPE_FLOAT2)
        {
            cout << "Contains texture coordinates " << (int) pVertexLayout->UsageIndex << endl;
            texCoordsOffset = pVertexLayout->Offset;
        }
        else
        {
            cout << "Mysterious attribute" << endl;
        }
    }

    // Check that we support the format of the data.

    if (positionsOffset == MISSING_ATTRIBUTE)
    {
        exit(1);
    }

    // Obtain vertex & index counts from the D3D mesh; allocate memory for the CTM mesh.
    DWORD dwVertexCount = g_pMesh->GetNumVertices();
    DWORD dwTriangleCount = g_pMesh->GetNumFaces();
    DWORD dwIndexCount = dwTriangleCount * 3;

    // Lock down the verts and pluck out the positions and normals.
    {
        void* pData = 0;
        if (S_OK != g_pMesh->LockVertexBuffer(0, &pData))
        {
            exit(1);
        }

        if (positionsOffset != MISSING_ATTRIBUTE)
        {
            unsigned char* pSource = ((unsigned char*) pData) + positionsOffset;
            DWORD dwSourceStride = g_pMesh->GetNumBytesPerVertex();
            DWORD dwDestStride = sizeof(CTMfloat) * 3;

            for (DWORD dwVertex = 0; dwVertex < dwVertexCount; ++dwVertex)
            {
                float* pFloat = (float*) pSource;
                *pFloat = -*pFloat;
                //*pFloat = -*pFloat;
                pSource += dwSourceStride;
            }
        }

        g_pMesh->UnlockVertexBuffer();
    }

    // Lock down the indices and convert them to unsigned 32-bit integers.
    {
        void* pData = 0;
        g_pMesh->LockIndexBuffer(0, &pData);

        DWORD dwOptions = g_pMesh->GetOptions();
        DWORD dwSourceStride = (dwOptions & D3DXMESH_32BIT) ? 4 : 2;

        unsigned char* pSource = (unsigned char*) pData;

        for (DWORD dwIndex = 0; dwIndex < dwIndexCount / 3; ++dwIndex)
        {
            unsigned short* inds = (unsigned short*) pSource;
            
            std::swap(inds[0], inds[1]);

            pSource += dwSourceStride * 3;
        }

        g_pMesh->UnlockIndexBuffer();
    }


    D3DXSaveMeshToX(L"new.x", g_pMesh, 0, d3dxMaterials, d3dxEffects, g_dwNumMaterials, D3DXF_FILEFORMAT_BINARY | D3DXF_FILEFORMAT_COMPRESSED);
    cout << "Saved." << endl;
*/   
}
//====================================================================================
// メッシュコンテナの作成(XFileの各パーツの集合)ようはスキンメッシュモデルをここで作る
//====================================================================================
HRESULT CInheritanceHierarchy::CreateMeshContainer(LPCSTR Name, CONST D3DXMESHDATA* pMeshData,
													CONST D3DXMATERIAL* pMaterials, CONST D3DXEFFECTINSTANCE* pEffectInstances,
													DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, 
													LPD3DXMESHCONTAINER *ppMeshContainer )
{
	//========================================================================
	// コンテナ作成に当たって必要な変数を用意
	//========================================================================
	MYMESHCONTAINER *pMeshContainer = NULL;
	int iFacesAmount;
	DWORD iMaterial;
	LPDIRECT3DDEVICE9 pDevice = NULL;
	LPD3DXMESH pMesh = NULL;
	*ppMeshContainer = NULL;
	DWORD dwBoneNum=0;

	//========================================================================
	// コンテナを動的確保して値を入れていく作業へ
	//========================================================================
	pMesh = pMeshData->pMesh;
	pMeshContainer = new MYMESHCONTAINER;

	//メモリ不足のときは終了
	if (pMeshContainer == NULL)
	{
		return E_OUTOFMEMORY;
	}

	//作成に成功したら中身を0で初期化しておく
	ZeroMemory(pMeshContainer, sizeof(MYMESHCONTAINER));

	//メッシュコンテナとしてXFileでつけられてる名前を拾う
	pMeshContainer->Name=new TCHAR[lstrlen(Name) + 1];	// \0分の+1

	//名前がなかったらおかしいので終了
	if (!pMeshContainer->Name)
	{
		return E_FAIL;
	}

	//名前があるならそれにする
	strcpy(pMeshContainer->Name,Name);

	// デバイスゲット
	pMesh->GetDevice(&pDevice);

	// 面の数ゲット
	iFacesAmount = pMesh->GetNumFaces();

	pMeshContainer->MeshData.pMesh = pMesh;
	pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

	//通常メッシュの場合はこれが必要。スキンの場合、これをするとメモリリークになる。
	if (pSkinInfo == NULL)
	{
		pMesh->AddRef();
	}

	//メッシュのマテリアル設定
	pMeshContainer->NumMaterials = max(1, NumMaterials);
	pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
	pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
	pMeshContainer->pAdjacency = new DWORD[iFacesAmount * NUM_POLYGON_CREATE_TRIANGLE];

	//隣接性情報またはマテリアルがなければ終了
	if( pMeshContainer->pAdjacency == NULL
	||	pMeshContainer->pMaterials == NULL )
	{
		return E_FAIL;
	}

	//情報をメッシュコンテナに流し込む
	memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * iFacesAmount * NUM_POLYGON_CREATE_TRIANGLE);
	memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);

	//========================================================================
	//該当メッシュがスキン情報を持っている場合
	//========================================================================
	if (pSkinInfo != NULL)
	{
		pMeshContainer->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();
		dwBoneNum = pSkinInfo->GetNumBones();
		pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[dwBoneNum];
		for (DWORD i = 0; i < dwBoneNum; i++)
		{
			memcpy(&pMeshContainer->pBoneOffsetMatrices[i], pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i), sizeof(D3DMATRIX));
		}

		// インデックスつきのものに変換   シェーダー使わないやつとは別なので注意
		if (FAILED(pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh(pMesh,
			NULL,
			dwBoneNum,
			pMeshContainer->pAdjacency,
			NULL,
			NULL,
			NULL,
			&pMeshContainer->dwWeight,
			&pMeshContainer->dwBoneNum,
			&pMeshContainer->pBoneBuffer,
			&pMeshContainer->MeshData.pMesh)))
		{
			return E_FAIL;
		}

		// コンバート
		ConvertMesh(&pMeshContainer->MeshData.pMesh);

		D3DVERTEXELEMENT9 elements[] =
		{
			// 頂点ストリーム(パイプライン)番号, オフセット(頂点の型の先頭からのバイト数), データ型, DEFAULTでOK, 使用用途, 使用用途が同じものを複数使うときに仕分ける番号
			{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
			{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0 },
			{ 0, 24, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0 },
			{ 0, 28, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
			{ 0, 40, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
			{ 0, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
			D3DDECL_END()																					// 定義終了 絶対必要
		};
		pMeshContainer->pSkinInfo->SetDeclaration(elements);
	}

	//========================================================================
	// モデルのマテリアル情報
	//========================================================================
	if (NumMaterials > 0)
	{
		memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);

		for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
		{
			// マテリアルのディフーズ色を強制的に変更
			pMeshContainer->pMaterials[iMaterial].MatD3D.Diffuse = DEFAULT_POLYGON_COLOR;

			if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
			{
				TCHAR strTexturePath[MAX_PATH];
				strcpy( strTexturePath,TEX_FOLDER_PATH);
				strcat_s( strTexturePath, sizeof( char ) * MAX_LENGTH_FILE_PATH, pMeshContainer->pMaterials[iMaterial].pTextureFilename );
				if (FAILED(D3DXCreateTextureFromFile(pDevice, strTexturePath,
					&pMeshContainer->ppTextures[iMaterial])))
				{
					pMeshContainer->ppTextures[iMaterial] = NULL;
					pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
				}
			}
		}
	}
	else
	{
		pMeshContainer->pMaterials[0].pTextureFilename = NULL;
		memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = COLOR_OF_NOT_EXIST_MATERIAL.r;
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = COLOR_OF_NOT_EXIST_MATERIAL.g;
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = COLOR_OF_NOT_EXIST_MATERIAL.b;
		pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
	}

	//ローカルに生成したメッシュコンテナーを呼び出し側にコピーする (コピーじゃないけど・・・)
	*ppMeshContainer = pMeshContainer;

	//参照カウンタを増やしたので減らす
	SAFE_RELEASE(pDevice);
	return S_OK;
}
void MeshParameterization::GenerateCache( LPD3DXMESH meshOut, LPD3DXBUFFER remapped )
{
	paramVertex * pNewVerts = NULL;
	IToolBox * tool = EngineGetToolBox();
			
	HRESULT hr;
	m_Cache.Clean();
	//have to now be able to map a face to a texture area, or, a face to a chart.
	int numVertices = m_CollapsedMesh->size();
	int numNewVertices = remapped->GetBufferSize() / sizeof( DWORD );

	if( numNewVertices != numVertices )
	{
		//Our cache is a remapping cache! New vertices were generated!!!!
		m_Cache.m_bRemapped = true;

		//First we remap our vertices
		int remapsize = remapped->GetBufferSize() / sizeof( DWORD );
		DWORD * remappedData = (DWORD*) remapped->GetBufferPointer();

		m_Cache.m_NumVertices = remapsize;
		m_Cache.ResizeRemappedData( remapsize );
		m_Cache.ResizeUVData(  remapsize*2 );
		memcpy( m_Cache.m_RemappedData, remappedData, sizeof( DWORD )*remapsize );

		vector< ParameterizationVertex > newVertBuffer;
		newVertBuffer.resize( remapsize );

		//loop through and assign new vertices
		hr = meshOut->LockVertexBuffer( 0, (LPVOID*)&pNewVerts );
		if( hr == D3D_OK &&
			pNewVerts)
		{
			for( int i = 0; i < remapsize; i++ )
			{
				int oldIndex = remappedData[ i ];
				newVertBuffer[ i ] = (*m_CollapsedMesh)[ oldIndex ];
				//UV for internal lightmap calcs
				NormalizeUV( pNewVerts[ i ].u );
				NormalizeUV( pNewVerts[ i ].v );
				newVertBuffer[ i ].generatedU = pNewVerts[ i ].u;
				newVertBuffer[ i ].generatedV = pNewVerts[ i ].v;
				//Duplicate uv to pass to render object as a stream
				m_Cache.m_UVData[ i*2 ]		= pNewVerts[ i ].u;
				m_Cache.m_UVData[ i*2 + 1 ] = pNewVerts[ i ].v;
			}
			meshOut->UnlockVertexBuffer();
			//assign new mesh
			m_CollapsedMesh->clear();
			(*m_CollapsedMesh) = newVertBuffer;
			newVertBuffer.clear();
		}else
		{
			tool->Log( LOGERROR, _T("Could not lock mesh param vertex buffer to remap vertices\n"));

		}
		//now do indices
		int numIndices = 3*meshOut->GetNumFaces();
		m_Cache.m_NumIndices = numIndices;
		m_Cache.ResizeRemappedIndices( numIndices );
		WORD * pIndices = NULL;
		hr = meshOut->LockIndexBuffer( 0, (LPVOID*)&pIndices );
		if( hr == D3D_OK &&
			pIndices)
		{
			for( int i = 0; i < numIndices; i++ )
			{
				m_Cache.m_RemappedIndices[ i ] = (DWORD)pIndices[ i ];
				//faces
				int faceIndex = i/3;
				int triIndex = i%3;
				(*m_Faces)[ faceIndex ].index[ triIndex ] = pIndices[ i ];
			}
		}else if( tool )
		{
			tool->Log( LOGERROR, _T("Could not lock mesh param index buffer to remap indices\n"));
		}
	}
	else //no remapping, just uvs needed
	{
		BYTE * pNewVerts = NULL;
		hr = meshOut->LockVertexBuffer( 0, (LPVOID*)&pNewVerts );
		
		m_Cache.m_NumVertices = m_CollapsedMesh->size();
		m_Cache.ResizeUVData( m_Cache.m_NumVertices*2 );
		if( hr == D3D_OK )
		{
			//copy new uvs
			paramVertex * pv = (paramVertex*)pNewVerts;
			for( int i = 0; i < (int)m_CollapsedMesh->size(); i++ )
			{
				NormalizeUV( pv[ i ].u );
				NormalizeUV( pv[ i ].v );
				(*m_CollapsedMesh)[i].generatedU = pv[ i ].u;
				(*m_CollapsedMesh)[i].generatedV = pv[ i ].v;
				//copy uvs for passing to render object as a stream
				m_Cache.m_UVData[ i*2 ] = pv[ i ].u;
				m_Cache.m_UVData[ i*2 + 1 ] = pv[ i ].v;
			}
			meshOut->UnlockVertexBuffer();
		}
	}
}
Example #11
0
int main(int argc, char* argv[])
{
	if (argc < 3)
	{
		puts("Usage: MeshConv meshfile rdffile");
		return 1;
	}

	// Initialize DirectDraw
	pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	if (pD3D == NULL)
	{
		puts("Cannot init D3D");
		return 1;
	}

	MeshMender mender;
	std::vector<MeshMender::Vertex> MendVerts;
	std::vector<unsigned int> MendIndices;
	std::vector<unsigned int> mappingNewToOld;

	HRESULT hr;
	D3DDISPLAYMODE dispMode;
	D3DPRESENT_PARAMETERS presentParams;

	pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode);

	ZeroMemory(&presentParams, sizeof(presentParams));
	presentParams.Windowed = TRUE;
	presentParams.hDeviceWindow = GetConsoleWindow();
	presentParams.SwapEffect = D3DSWAPEFFECT_COPY;
	presentParams.BackBufferWidth = 8;
	presentParams.BackBufferHeight = 8;
	presentParams.BackBufferFormat = dispMode.Format;

	hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &pD3DDevice);
	if (FAILED(hr))
	{
		printf("Cannot init D3D device: %08x\n", hr);
		pD3D->Release();
		return 1;
	}

	printf("Loading mesh %s: ", argv[1]);

	LPD3DXBUFFER pAdjacency, pMaterials, pEffects;
	DWORD n;
	LPD3DXMESH pLoadMesh;
	hr = D3DXLoadMeshFromX(argv[1], D3DXMESH_SYSTEMMEM, pD3DDevice, &pAdjacency, &pMaterials, &pEffects, &n, &pLoadMesh);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	pEffects->Release();
	pMaterials->Release();
	printf("%d faces, %d verts\n", pLoadMesh->GetNumFaces(), pLoadMesh->GetNumVertices());

	LPD3DXMESH pMesh;
	if (pLoadMesh->GetFVF() != MESHFVF)
	{
		hr = pLoadMesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, MESHFVF, pD3DDevice, &pMesh);
		pLoadMesh->Release();
		if (FAILED(hr))
		{
			printf("CloneMesh error: %08x\n", hr);
			goto mesherror;
		}
	}
	else
		pMesh = pLoadMesh;

	printf("Welding verts: ");

	DWORD* pAdj = new DWORD[pAdjacency->GetBufferSize() / 4];

	D3DXWELDEPSILONS Eps;
	memset(&Eps, 0, sizeof(Eps));
	hr = D3DXWeldVertices(pMesh, D3DXWELDEPSILONS_WELDPARTIALMATCHES, &Eps, (DWORD*)pAdjacency->GetBufferPointer(), pAdj, NULL, NULL);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	
	hr = pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, pAdj, (DWORD*)pAdjacency->GetBufferPointer(), NULL, NULL);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	
	pAdjacency->Release();
	delete [] pAdj;

	printf("%d faces, %d verts\n", pMesh->GetNumFaces(), pMesh->GetNumVertices());

	printf("Mending mesh: ");

	DWORD NumVerts = pMesh->GetNumVertices();
	DWORD NumFaces = pMesh->GetNumFaces();

	MESHVERT* MeshVert;
	pMesh->LockVertexBuffer(0, (LPVOID*)&MeshVert);

	//fill up Mend vectors with your mesh's data
	MendVerts.reserve(NumVerts);
	for(DWORD i = 0; i < NumVerts; ++i)
	{
		MeshMender::Vertex v;
		v.pos = MeshVert[i].pos;
		v.s = MeshVert[i].s;
		v.t = MeshVert[i].t;
		v.normal = MeshVert[i].norm;
		MendVerts.push_back(v);
	}
	pMesh->UnlockVertexBuffer();

	WORD* MeshIdx;
	pMesh->LockIndexBuffer(0, (LPVOID*)&MeshIdx);

	MendIndices.reserve(NumFaces * 3);
	for(DWORD i = 0; i < NumFaces * 3; ++i)
	{
		MendIndices.push_back(MeshIdx[i]);
	}
	pMesh->UnlockIndexBuffer();

	pMesh->Release();
	pMesh = 0;

	//pass it in to Mend mender to do it's stuff
	mender.Mend(MendVerts, MendIndices, mappingNewToOld, 0.9f, 0.9f, 0.9f, 1.0f, MeshMender::DONT_CALCULATE_NORMALS, MeshMender::RESPECT_SPLITS);
	
	mappingNewToOld.clear();

	printf("%d faces, %d verts\n", MendIndices.size() / 3, MendVerts.size());

	printf("Saving data: ");

	FILE* fp = fopen("meshdata.bin", "wb");
	n = MendIndices.size() / 3;
	fwrite(&n, 4, 1, fp);
	n = MendVerts.size();
	fwrite(&n, 4, 1, fp);
	fclose(fp);

	// Load existing file
	HANDLE hFile = CreateFile(argv[2], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("ERROR: %08x\n", GetLastError());
		goto mesherror;
	}
	DWORD Size = GetFileSize(hFile, 0);
	char* FileData = (char*)VirtualAlloc(0, 64*1024*1024, MEM_RESERVE, PAGE_NOACCESS);
	VirtualAlloc(FileData, Size, MEM_COMMIT, PAGE_READWRITE);
	ReadFile(hFile, FileData, Size, &n, 0);
	FileData[n] = 0;
	Size = n;

	char *p, *q;
	// Find vertex data
	p = strstr(FileData, "VertexBuffer");
	if (!p)
	{
		printf("ERROR: Invalid output file\n");
		goto mesherror;
	}
	p = strchr(p, '{');
	q = p+1;
	int depth = 1;
	do {
		if (*q == '}')
			--depth;
		else if (*q == '{')
			++depth;
		++q;
	} while (depth > 0);

	// move post-vertex data to temp buffer
	Size = (FileData + Size) - q;
	char* TempData = (char*)VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(TempData, q, Size);

	// write vertex data
	strcpy(p, "{\r\n    VertexFormat {D3DVSDT_FLOAT3 D3DVSDT_NORMPACKED3 D3DVSDT_FLOAT2 D3DVSDT_NORMPACKED3 D3DVSDT_NORMPACKED3}\r\n    VertexData\r\n    {\r\n");
	p += strlen(p);

	for (std::vector<MeshMender::Vertex>::iterator i = MendVerts.begin(); i != MendVerts.end(); ++i)
	{
		VirtualAlloc(p, 500, MEM_COMMIT, PAGE_READWRITE);
		p += sprintf(p, "        %12f %12f %12f  %12f %12f %12f  %12f %12f  %12f %12f %12f  %12f %12f %12f\r\n",
			i->pos.x, i->pos.y, i->pos.z, i->normal.x, i->normal.y, i->normal.z,
			i->s, i->t,
			i->tangent.x, i->tangent.y, i->tangent.z, i->binormal.x, i->binormal.y, i->binormal.z);
	}

	strcpy(p, "    }\r\n}");
	p += strlen(p);

	VirtualAlloc(p, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(p, TempData, Size);
	Size += p - FileData;
	VirtualFree(TempData, 0, MEM_RELEASE);

	// Find index data
	p = strstr(FileData, "IndexBuffer");
	if (!p)
	{
		printf("ERROR: Invalid output file\n");
		goto mesherror;
	}
	p = strchr(p, '{');
	q = p+1;
	depth = 1;
	do {
		if (*q == '}')
			--depth;
		else if (*q == '{')
			++depth;
		++q;
	} while (depth > 0);

	// move post-index data to temp buffer
	Size = (FileData + Size) - q;
	TempData = (char*)VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(TempData, q, Size);

	// write index data
	strcpy(p, "{\r\n    IndexData\r\n    {\r\n        ");
	p += strlen(p);

	n = 0;
	for (std::vector<unsigned>::iterator i = MendIndices.begin(); i != MendIndices.end(); ++i)
	{
		VirtualAlloc(p, 20, MEM_COMMIT, PAGE_READWRITE);
		p += sprintf(p, " %5hu", *i);
		if (n++ == 2)
		{
			p += sprintf(p, "\r\n       ");
			n = 0;
		}
	}

	strcpy(p-3, "}\r\n}");
	p += strlen(p);

	VirtualAlloc(p, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(p, TempData, Size);
	Size += p - FileData;
	VirtualFree(TempData, 0, MEM_RELEASE);

	SetFilePointer(hFile, 0, 0, FILE_BEGIN);
	WriteFile(hFile, FileData, Size, &n, 0);
	SetEndOfFile(hFile);

	CloseHandle(hFile);
	VirtualFree(FileData, 0, MEM_RELEASE);

	printf("Done\n");

	pD3D->Release();
	pD3DDevice->Release();

	return 0;

mesherror:
	pD3D->Release();
	pD3DDevice->Release();
	
	return 1;
}
Example #12
0
HRESULT AllocateHierarchy::CreateMeshContainer(
	LPCSTR Name,
	CONST D3DXMESHDATA *pMeshData,
	CONST D3DXMATERIAL *pMaterials,
	CONST D3DXEFFECTINSTANCE *pEffectInstances,
	DWORD NumMaterials,
	CONST DWORD *pAdjacency,
	LPD3DXSKININFO pSkinInfo,
	LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
    HRESULT hr;
    D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;
    UINT NumFaces;
    UINT iMaterial;
    UINT iBone, cBones;
    LPDIRECT3DDEVICE9 pd3dDevice = NULL;

    LPD3DXMESH pMesh = NULL;

    *ppNewMeshContainer = NULL;

    // this sample does not handle patch meshes, so fail when one is found
    if (pMeshData->Type != D3DXMESHTYPE_MESH)
    {
        hr = E_FAIL;
        goto e_Exit;
    }

    // get the pMesh interface pointer out of the mesh data structure
    pMesh = pMeshData->pMesh;

    // this sample does not FVF compatible meshes, so fail when one is found
    if (pMesh->GetFVF() == 0)
    {
        hr = E_FAIL;
        goto e_Exit;
    }

    // allocate the overloaded structure to return as a D3DXMESHCONTAINER
    pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
    if (pMeshContainer == NULL)
    {
        hr = E_OUTOFMEMORY;
        goto e_Exit;
    }
    memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_DERIVED));

    // make sure and copy the name.  All memory as input belongs to caller, interfaces can be addref'd though
    hr = AllocateName(Name, &pMeshContainer->Name);
    if (FAILED(hr))
        goto e_Exit;        

    pMesh->GetDevice(&pd3dDevice);
    NumFaces = pMesh->GetNumFaces();

    // if no normals are in the mesh, add them
    if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
    {
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

        // clone the mesh to make room for the normals
        hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
                                    pMesh->GetFVF() | D3DFVF_NORMAL, 
                                    pd3dDevice, &pMeshContainer->MeshData.pMesh );
        if (FAILED(hr))
            goto e_Exit;

        // get the new pMesh pointer back out of the mesh container to use
        // NOTE: we do not release pMesh because we do not have a reference to it yet
        pMesh = pMeshContainer->MeshData.pMesh;

        // now generate the normals for the pmesh
        D3DXComputeNormals( pMesh, NULL );
    }
    else  // if no normals, just add a reference to the mesh for the mesh container
    {
        pMeshContainer->MeshData.pMesh = pMesh;
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

        pMesh->AddRef();
    }
        
    // allocate memory to contain the material information.  This sample uses
    //   the D3D9 materials and texture names instead of the EffectInstance style materials
    pMeshContainer->NumMaterials = max(1, NumMaterials);
    pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
    pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
    pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
    if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
    {
        hr = E_OUTOFMEMORY;
        goto e_Exit;
    }

    memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);
    memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);

    // if materials provided, copy them
    if (NumMaterials > 0)            
    {
        memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);

        for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
        {
            if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
            {
                string strTexturePath;
				string strFilename = _pSkinmesh->GetMeshname();
				strFilename = strFilename + "\\" + pMeshContainer->pMaterials[iMaterial].pTextureFilename;
				strTexturePath = MODEL_DIR(strFilename.c_str());
				if( FAILED( Moon_CreateTexture( pd3dDevice, const_cast<char*>(strTexturePath.c_str()), 
                                                        &pMeshContainer->ppTextures[iMaterial] ) ) )
                    pMeshContainer->ppTextures[iMaterial] = NULL;


                // don't remember a pointer into the dynamic memory, just forget the name after loading
                pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
            }
        }
    }
    else // if no materials provided, use a default one
    {
        pMeshContainer->pMaterials[0].pTextureFilename = NULL;
        memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
    }

    // if there is skinning information, save off the required data and then setup for HW skinning
    if (pSkinInfo != NULL)
    {
        // first save off the SkinInfo and original mesh data
        pMeshContainer->pSkinInfo = pSkinInfo;
        pSkinInfo->AddRef();

        pMeshContainer->pOrigMesh = pMesh;
        pMesh->AddRef();

        // Will need an array of offset matrices to move the vertices from the figure space to the bone's space
        cBones = pSkinInfo->GetNumBones();
        pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
        if (pMeshContainer->pBoneOffsetMatrices == NULL)
        {
            hr = E_OUTOFMEMORY;
            goto e_Exit;
        }

        // get each of the bone offset matrices so that we don't need to get them later
        for (iBone = 0; iBone < cBones; iBone++)
        {
            pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
        }

        // GenerateSkinnedMesh will take the general skinning information and transform it to a HW friendly version
        hr = _pSkinmesh->GenerateSkinmesh(pMeshContainer);
        if (FAILED(hr))
            goto e_Exit;
    }

    *ppNewMeshContainer = pMeshContainer;
    pMeshContainer = NULL;
e_Exit:
    SAFE_RELEASE(pd3dDevice);

    // call Destroy function to properly clean up the memory allocated 
    if (pMeshContainer != NULL)
    {
        DestroyMeshContainer(pMeshContainer);
    }

    return hr;
}
Example #13
0
//======================================================================
// <<<メッシュ コンテナ オブジェクトの割り当て要求の実装>>>
//	Name			 : [in] メッシュの名前
//	pMeshData		 : [in] メッシュデータ構造体へのポインタ
//	pMaterials		 : [in] メッシュに使うマテリアルの配列
//	pEffectInstances : [in] メッシュに使うエフェクトインスタンスの配列
//	NumMaterials	 : [in] マテリアル配列内のマテリアルの数
//	pAdjacency		 : [in] メッシュの隣接性配列
//	pSkinInfo		 : [in] スキンデータが見つかった場合のスキンメッシュオブジェクトへのポインタ
//	ppNewMeshContainer : [out, retval] 作成されたメッシュコンテナを返す
//======================================================================
HRESULT CAllocateHierarchy::CreateMeshContainer( LPCSTR Name, 
        CONST D3DXMESHDATA *pMeshData,
        CONST D3DXMATERIAL *pMaterials, 
        CONST D3DXEFFECTINSTANCE *pEffectInstances, 
        DWORD NumMaterials, 
        CONST DWORD *pAdjacency, 
        LPD3DXSKININFO pSkinInfo, 
        LPD3DXMESHCONTAINER *ppNewMeshContainer) 
{
	HRESULT hr = S_OK;

	*ppNewMeshContainer = NULL;

	// patch meshes を扱う事はできない
	if( pMeshData->Type != D3DXMESHTYPE_MESH )
	{
		return E_FAIL;
	}

	LPD3DXMESH pMesh = pMeshData->pMesh;

	// FVF で記述されたメッシュ以外は読めぬ
	if( pMesh->GetFVF() == 0 )
	{
		return E_FAIL;
	}

	UINT NumFaces = pMesh->GetNumFaces();

	// メッシュ作成
	CXMesh *pCXMesh	= NULL;
	
	try
	{
		pCXMesh = new CXMesh;
	}
	
	catch ( std::bad_alloc& )
	{
		// メモリが足りない
		return E_OUTOFMEMORY;
	}

	// 名前設定
	pCXMesh->SetName( Name );

	// メッシュタイプ設定
	pCXMesh->MeshData.Type = D3DXMESHTYPE_MESH;

	LPDIRECT3DDEVICE9 pD3DDevice = NULL;

	// デバイスを取得
	if( FAILED( pMesh->GetDevice( &pD3DDevice ) ) )
	{
		hr = E_FAIL;
		goto e_Exit;
	}

	// Xファイルに法線が無かったら計算で求める
	if( !( pMesh->GetFVF() & D3DFVF_NORMAL ) )
	{
		////FVFに法線を追加した新しいメッシュにする////
        hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
                                  pMesh->GetFVF() | D3DFVF_NORMAL, 
                                  pD3DDevice, &pCXMesh->MeshData.pMesh );

        if( FAILED( hr ) )
		{
			goto e_Exit;
		}

		// 引数で渡されたメッシュへのポインタに新しいメッシュへのポインタをセット
		// pMeshへの参照はこの時点で存在しないので、ここではreleaseをかけない
		pMesh = pCXMesh->MeshData.pMesh;

		D3DXComputeNormals( pMesh, NULL );
	}
	
	// 法線があった
	else
	{
		// リファレンスを増やすだけ
		pCXMesh->MeshData.pMesh = pMesh;
		pMesh->AddRef();
	}

	// マテリアル用のメモリを確保
	pCXMesh->NumMaterials = max( 1, NumMaterials );

	try
	{
		pCXMesh->pMaterials		= new D3DXMATERIAL[pCXMesh->NumMaterials];
		pCXMesh->m_ppTextures	= new LPDIRECT3DTEXTURE9[pCXMesh->NumMaterials];
		pCXMesh->pAdjacency		= new DWORD[NumFaces * 3];
	}
	
	catch ( std::bad_alloc& )
	{
		// メモリが足りない
		goto e_Exit;
	}

	memcpy( pCXMesh->pAdjacency, pAdjacency, sizeof( DWORD ) * NumFaces * 3 );
	memset( pCXMesh->m_ppTextures, 0, sizeof( LPDIRECT3DTEXTURE9 ) * pCXMesh->NumMaterials );

	// マテリアルのコピー
	if( NumMaterials > 0 )
	{
		memcpy( pCXMesh->pMaterials, pMaterials, sizeof( D3DXMATERIAL ) * NumMaterials );

		for( UINT i=0; i<NumMaterials; i++ )
		{
			if( pCXMesh->pMaterials[i].pTextureFilename != NULL )
			{
				// テクスチャを読み込む
				if( FAILED( D3DXCreateTextureFromFileEx(
								pD3DDevice, pCXMesh->pMaterials[i].pTextureFilename, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_RENDERTARGET, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, m_KeyColor, NULL, NULL,
								&pCXMesh->m_ppTextures[i] ) ) )
				{
					
					// 読み込み失敗
					pCXMesh->m_ppTextures[i] = NULL;
				}
				
				pD3DDevice->SetTexture(0, pCXMesh->m_ppTextures[i]);
				pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
				pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
				pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
				
				pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
				pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, true);
				pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
				pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 8);
				
			}
		}
	}
	// マテリアルが無いので適当にセット
	else
	{
		pCXMesh->pMaterials[0].pTextureFilename = NULL;
		memset( &pCXMesh->pMaterials[0].MatD3D, 0, sizeof( D3DMATERIAL9 ) );
		pCXMesh->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
		pCXMesh->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
		pCXMesh->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
		pCXMesh->pMaterials[0].MatD3D.Specular = pCXMesh->pMaterials[0].MatD3D.Diffuse;
	}

	// ワンスキン形式のXファイルだった時の処理
	if( pSkinInfo != NULL )
	{
		/* スキンメッシュ用の処理*/

		/*pSkinInfo と pMesh をセット*/
		pCXMesh->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();
		
		pCXMesh->m_pOrigMesh = pMesh;
		pMesh->AddRef();

		/* Bone Offset Matrices 保存用のメモリを確保*/
		UINT NumBones = pSkinInfo->GetNumBones();

		try
		{
			pCXMesh->m_pBoneOffsetMatrices = new D3DXMATRIX[NumBones];
		}
		
		catch ( std::bad_alloc& )
		{
			// メモリが足りない
			goto e_Exit;
		}

		/*Bone Offset Matrices 読み込み*/
		for( UINT i = 0; i < NumBones; i++ )
		{
			//memcpy(&pCXMesh->m_pBoneOffsetMatrices[i], pCXMesh->pSkinInfo->GetBoneOffsetMatrix(i), sizeof(D3DMATRIX) );
			pCXMesh->m_pBoneOffsetMatrices[i] = *(pCXMesh->pSkinInfo->GetBoneOffsetMatrix( i ) );			
		}
		
		// ジェネレート処理
		hr = m_pModel->GenerateSkinnedMesh( m_pD3DX9, pCXMesh, m_MaxBlend );

		if( FAILED( hr ) )
		{
			goto e_Exit;
		}
		
	}

	// メッシュコンテナの割り当て。
	// CXMeshクラスは D3DXMESHCONTAINER を継承している
	*ppNewMeshContainer = pCXMesh;

	pCXMesh = NULL;

e_Exit:
	// 開放処理
	F_RELEASE( pD3DDevice );

	if( pCXMesh != NULL )
	{
		DestroyMeshContainer( pCXMesh );
	}

	return hr;
}
Example #14
0
void Sombra::ConstruirSombra(LPD3DXMESH pMesh, D3DXVECTOR3 vLight)
{
    // Note: the MeshVertex format depends on the FVF of the mesh
	struct MeshVertex { D3DXVECTOR3 p, n;
                            DWORD diffuse;
                         float tu,tv;   };

    MeshVertex *pVertices;
    WORD       *pIndices;

    // Lock the geometry buffers
    pMesh->LockVertexBuffer( 0L, (LPVOID*)&pVertices );
    pMesh->LockIndexBuffer( 0L, (LPVOID*)&pIndices );
    DWORD dwNumFaces    = pMesh->GetNumFaces();

    // Allocate a temporary edge list
    WORD *pEdges = new WORD[dwNumFaces*6];

    if( pEdges == NULL )
    {
        pMesh->UnlockVertexBuffer();
        pMesh->UnlockIndexBuffer();
        return ;
    }
	
    DWORD dwNumEdges = 0;

    // For each face
    for( DWORD i = 0; i < dwNumFaces; ++i )
    {
        WORD wFace0 = pIndices[3*i+0];
        WORD wFace1 = pIndices[3*i+1];
        WORD wFace2 = pIndices[3*i+2];

        D3DXVECTOR3 v0 = pVertices[wFace0].p;
        D3DXVECTOR3 v1 = pVertices[wFace1].p;
        D3DXVECTOR3 v2 = pVertices[wFace2].p;

        // Transform vertices or transform light?
        D3DXVECTOR3 vCross1(v2-v1);
        D3DXVECTOR3 vCross2(v1-v0);
        D3DXVECTOR3 vNormal;
        D3DXVec3Cross( &vNormal, &vCross1, &vCross2 );

        if( D3DXVec3Dot( &vNormal, &vLight ) >= 0.0f )
        {
            InsertarSegmento( pEdges, dwNumEdges, wFace0, wFace1 );
            InsertarSegmento( pEdges, dwNumEdges, wFace1, wFace2 );
            InsertarSegmento( pEdges, dwNumEdges, wFace2, wFace0 );
        }
    }

    // Se construyen las caras de la sombra extrudando los segmentos en la dirección
    // de la luz y una longitud 10 veces la del vector luz.
    for( i = 0; i < dwNumEdges; ++i )
    {
        D3DXVECTOR3 v1 = pVertices[pEdges[2*i+0]].p;
        D3DXVECTOR3 v2 = pVertices[pEdges[2*i+1]].p;
        D3DXVECTOR3 v3 = v1 - vLight/10;
        D3DXVECTOR3 v4 = v2 - vLight/10;

        // Add a quad (two triangles) to the vertex list
        m_pVertices[m_dwNumVertices++] = v1;
        m_pVertices[m_dwNumVertices++] = v2;
        m_pVertices[m_dwNumVertices++] = v3;

        m_pVertices[m_dwNumVertices++] = v2;
        m_pVertices[m_dwNumVertices++] = v4;
        m_pVertices[m_dwNumVertices++] = v3;
    }

    // Delete the temporary edge list
    delete[] pEdges;

    // Unlock the geometry buffers
    pMesh->UnlockVertexBuffer();
    pMesh->UnlockIndexBuffer();

   
    
}
Example #15
0
//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: Load the mesh and build the material and texture arrays
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
	LPD3DXBUFFER pD3DXMtrlBuffer;
	LPDIRECT3DVERTEXBUFFER9 pMeshSourceVB;
	LPDIRECT3DINDEXBUFFER9  pMeshSourceIB;
	D3DVERTEX*              pSrc;
	D3DVERTEX*              pDst;


	// load the textures we are going to be using
	if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"cartoonpallet-white-to-black.bmp", &g_pTexture ) ) )
		MessageBox(NULL, L"Texture Load Problem", NULL, NULL);

	if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"cartoonpallet-black-to-white.bmp", &g_pTexture2 ) ) )
		MessageBox(NULL, L"Texture Load Problem", NULL, NULL);

	if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"marble.bmp",	&marbleTexture ) ) )
		MessageBox(NULL, L"Texture Load Problem", NULL, NULL);

	if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"background.jpg",	&backgroundTexture ) ) )
		MessageBox(NULL, L"Texture Load Problem", NULL, NULL);



	// Load the mesh from the specified file
	if( FAILED( D3DXLoadMeshFromX( L"skull.x", D3DXMESH_SYSTEMMEM, 
		g_pd3dDevice, NULL, 
		&pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, 
		&g_pMesh ) ) )

		g_pd3dDevice->SetFVF(D3DFVF_D3DVERTEX );
	g_dwNumVertices  = g_pMesh->GetNumVertices();
	g_dwNumFaces     = g_pMesh->GetNumFaces();

	//Clone the mesh to set the FVF
	LPD3DXMESH pTempSysMemMesh = NULL;

	if( FAILED( g_pMesh->CloneMeshFVF( D3DXMESH_SYSTEMMEM, D3DFVF_D3DVERTEX,
		g_pd3dDevice, &pTempSysMemMesh ) ) )
		MessageBox(NULL,L"Mesh clone problem",NULL,NULL);
	g_pMesh->Release();


	g_pMesh = pTempSysMemMesh;

	//Compute normals in case the meshes have them
	if( g_pMesh )
		D3DXComputeNormals( g_pMesh, NULL );


	//Meshes cloned 

	if( FAILED(g_pd3dDevice->CreateVertexBuffer( g_dwNumVertices * sizeof(D3DVERTEX),
		D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED,
		&g_pMeshVB, NULL )))
		MessageBox(NULL,L"Vertex buffer create problem",NULL,NULL);

	if( FAILED(g_pd3dDevice->CreateIndexBuffer( g_dwNumFaces * 3 * sizeof(WORD),
		D3DUSAGE_WRITEONLY,
		D3DFMT_INDEX16, D3DPOOL_MANAGED,
		&g_pMeshIB, NULL )))
		MessageBox(NULL,L"Index buffer create problem",NULL,NULL);
	g_pMesh->GetVertexBuffer(&pMeshSourceVB);
	g_pMeshVB->Lock( 0, 0, (void**)&pDst, 0 );
	pMeshSourceVB->Lock( 0, 0, (void**)&pSrc, 0 );
	memcpy( pDst, pSrc, g_dwNumVertices * sizeof(D3DVERTEX) );
	g_pMeshVB->Unlock();
	pMeshSourceVB->Unlock();
	pMeshSourceVB->Release();

	g_pMesh->GetIndexBuffer(&pMeshSourceIB);
	g_pMeshIB->Lock( 0, 0, (void**)&pDst, 0 );
	pMeshSourceIB->Lock( 0, 0, (void**)&pSrc, 0 );
	memcpy( pDst, pSrc, g_dwNumFaces * 3 * sizeof(WORD));
	g_pMeshIB->Unlock();
	pMeshSourceIB->Unlock();
	pMeshSourceIB->Release();



	//// Done with the material buffer
	pD3DXMtrlBuffer->Release();

	return S_OK;
}
Example #16
0
//------------------------------------------------------------------------------------------------
// Name:  XMesh
// Desc:  Constructs the subset geometry for a D3DXMesh
//------------------------------------------------------------------------------------------------
bool XMesh::buildGeometryFromD3DXMesh(LPD3DXMESH d3dxMesh, SubsetGeometry* subsetGeometry, DWORD subsets)
{
    // Check parameters
    if (APP_ERROR(!d3dxMesh || !subsetGeometry)("Invalid parameter to XMesh::buildGeometryFromD3DXMesh"))
        return false;

    // Add a reference to the mesh to counteract freeing it at the end
    d3dxMesh->AddRef();

    // Get the device
    LPDIRECT3DDEVICE9 pd3dDevice = NULL;
    d3dxMesh->GetDevice(&pd3dDevice);

    // If this mesh isn't already in the correct format, have D3D do the grunt work of
    // converting it.
    bool generate_normals = false; // Whether or not normals need to be generated for this mesh
    if ((d3dxMesh->GetFVF() != D3DFVF_GEOMETRYVERTEX) ||
        (D3DFMT_GEOMETRYINDEX == D3DFMT_INDEX32) && ((d3dxMesh->GetOptions() & D3DXMESH_32BIT) == 0))
    {
        // Holds the mesh when its converted to the correct format
        LPD3DXMESH pTemd3dxMesh = NULL;

        // Duplicate the loaded mesh into the format
        if (APP_ERROR(d3dxMesh->CloneMeshFVF(
                            D3DXMESH_SYSTEMMEM | ((D3DFMT_GEOMETRYINDEX == D3DFMT_INDEX32) ? D3DXMESH_32BIT : 0),
                            D3DFVF_GEOMETRYVERTEX, pd3dDevice, &pTemd3dxMesh))
                     ("XMesh couldn't convert the source geometry format")) {
            d3dxMesh->Release();
            pd3dDevice->Release();
			      return false;
        }

        // Generate normals if they didn't exist
        generate_normals = ((d3dxMesh->GetFVF()&D3DFVF_NORMAL)!=D3DFVF_NORMAL &&
                            (D3DFMT_GEOMETRYINDEX&D3DFVF_NORMAL)!=D3DFVF_NORMAL);

        // Use this mesh instead
        d3dxMesh->Release();
        d3dxMesh = pTemd3dxMesh;
    }

    // The mesh must have its attributes sorted before it can be converted to single strips
    {
        // Allocate an adjacency buffer
        DWORD faces = d3dxMesh->GetNumFaces();
        DWORD* pAdjacency = new DWORD[faces * 3];
		    bool failed = false;

        if (APP_ERROR(FAILED(d3dxMesh->GenerateAdjacency(ADJACENCY_EPSILON, pAdjacency)))("Unable to generate the mesh adjacency"))
          failed = true;

        { // Clean up "bowties" in the mesh that prevent lighting from being calculated correctly
          LPD3DXMESH cleaned_mesh = NULL;
          DWORD* cleaned_adjacency = new DWORD[faces * 3];
          LPD3DXBUFFER errors_and_warnings = NULL;
          if (!failed && APP_ERROR(FAILED(D3DXCleanMesh(D3DXCLEAN_BOWTIES,
                                                        d3dxMesh,
                                                        pAdjacency,
                                                        &cleaned_mesh,
                                                        cleaned_adjacency,
                                                        &errors_and_warnings)))
                                  ("Failed to clean mesh")) {
            failed = true;
            if (errors_and_warnings) {
              DEBUG_ERROR("Mesh cleaning error:  %s", (const char*)errors_and_warnings->GetBufferPointer());
            }
          }

          SAFE_RELEASE(errors_and_warnings);

          // If we successfully cleaned the mesh, use the new mesh and new set of
          // adjacencies.  Otherwise, just delete anything that was allocated and
          // keep the original.
          if (failed) {
            SAFE_DELETE_ARRAY(cleaned_adjacency);
            SAFE_RELEASE(cleaned_mesh);
          } else {
            SAFE_DELETE_ARRAY(pAdjacency);
            SAFE_RELEASE(d3dxMesh)
            pAdjacency = cleaned_adjacency;
            d3dxMesh = cleaned_mesh;
          }
        }

        // Compute mesh normals, if necessary
        if (!failed && generate_normals && APP_ERROR(FAILED(D3DXComputeNormals(d3dxMesh, pAdjacency)))("Couldn't generate mesh normals")) {
          failed = true;
        }

        // Optimize the mesh
        if (!failed && APP_ERROR(FAILED(d3dxMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT,
                                                                  pAdjacency,
                                                                  NULL,
                                                                  NULL,
                                                                  NULL)))
                                 ("Couldn't optimize mesh attributes")) {
			    failed = true;
		    }

        // Get rid of the temporary adjacency buffer
        SAFE_DELETE_ARRAY(pAdjacency);

        // Return if there was an error
        if (failed) {
          SAFE_RELEASE(d3dxMesh);
          SAFE_RELEASE(pd3dDevice);
          return false;
        }
    }

    // Lock the vertex buffer
    GeometryVertex* pXVertices = NULL;
    if (APP_ERROR(d3dxMesh->LockVertexBuffer(D3DLOCK_READONLY, (VOID**)&pXVertices))("Couldn't lock source vertex buffer"))
    {
		// Erase this mesh
        d3dxMesh->Release();
        pd3dDevice->Release();

		// Failure
		return false;
    }

    // Iterate through all of the materials and copy vertex/index data, and assign material
    // information for the mesh.
    for (DWORD subset = 0; subset < subsets; subset++)
    {
        // Use D3DX to convert this subset into a nicely indexed form
        DWORD numStripIndices;
        LPDIRECT3DINDEXBUFFER9 pSubsetIB;
        if (APP_ERROR(D3DXConvertMeshSubsetToSingleStrip(d3dxMesh, subset, D3DXMESH_SYSTEMMEM, &pSubsetIB, &numStripIndices))("Couldn't convert mesh subset into indexable strip"))
        {
            // Erase any geometry we made
            DeallocateGeometry(subsetGeometry);

            // Get rid of the mesh
            d3dxMesh->UnlockVertexBuffer();
            d3dxMesh->Release();

            // Free our device
            pd3dDevice->Release();

            // Return the error
            return false;
        }

        D3DINDEXBUFFER_DESC desc;
        GeometryIndex* pXIndices = NULL;

        // Check the format of the indices and lock the strip index buffer
        if (APP_ERROR(pSubsetIB->GetDesc(&desc))("Couldn't get .X mesh IB desc") || (desc.Format != D3DFMT_GEOMETRYINDEX) ||
            APP_ERROR(pSubsetIB->Lock(0, 0, (VOID**)&pXIndices, D3DLOCK_READONLY))("Unable to lock the .X index buffer"))
        {
            // Erase any geometry we made
            DeallocateGeometry(subsetGeometry);

            // Get rid of the mesh
            pSubsetIB->Release();
            d3dxMesh->UnlockVertexBuffer();
            d3dxMesh->Release();

            // Free our device
            pd3dDevice->Release();

            // Error!
            return false;
        }

        // This table pairs an index from the .X file to an index in the buffer that
        // holds the vertices for this subset
        XIndicesTable xIndicesTable;

        // For each of the indices in the strip, puts its vertex ID into the indices
        // table.  Use the counter to determine which vertex this is.
        {
            GeometryIndex vertexCounter = 0;
            for (DWORD e = 0; e < numStripIndices; ++e)
            {
                // Insert the entry [x-mesh index, subset index] into the table
                XIndicesTableInsertResult result = xIndicesTable.insert(XIndicesEntry(pXIndices[e], vertexCounter));

                // If the result was successful (this isn't a duplicated X-mesh index) increment the vertex counter
                if (result.second)
                    vertexCounter++;
            }
        }

        // Grab the number of vertices this geometry uses
        DWORD numVertices = (DWORD)xIndicesTable.size();

        // This buffer holds all of the triangles in this subset
        TriangleList triangles;

        // This list keeps track of locations in the strip where the winding order changes.  This is necessary
        // because this next part will remove degenerate triangles from the list.
        std::set<size_t> windingChanges;

        // Generate the list of triangles from the strip provided
        for (DWORD t = 0; t < numStripIndices - 2; ++t)
        {
            // Build the triangle that will be added to the buffer
            // CHANGED July 25, 2008:  the winding order is wrong here
            //Triangle tri = { pXIndices[t + 0], pXIndices[t + 1], pXIndices[t + 2] };
            Triangle tri = { pXIndices[t + 0], pXIndices[t + 2], pXIndices[t + 1] };



            // Convert the triangle into subset-indices by using the lookup table
            // we generated before.
            tri.index[0] = xIndicesTable.find(tri.index[0])->second;
            tri.index[1] = xIndicesTable.find(tri.index[1])->second;
            tri.index[2] = xIndicesTable.find(tri.index[2])->second;

            // Check to make sure this triangle isn't degenerate.  If it is, we can just skip
            // this triangle entirely to simplify the geometry.
            if (tri.index[0] == tri.index[1] || tri.index[1] == tri.index[2] || tri.index[0] == tri.index[2])
            {
                // Try to find the winding in the list
                std::set<size_t>::iterator currentWinding = windingChanges.find(triangles.size());

                // Add this to the winding change list, or remove the change if it's already there
                if (currentWinding != windingChanges.end())
                    windingChanges.erase(currentWinding);
                else
                    windingChanges.insert(triangles.size());

                // Don't insert a triangle here
                continue;
            }

            // Add this triangle to the list
            triangles.push_back(tri);
        }

        // Calculate the number of indices we need for the buffer
        DWORD numGeometryIndices = (DWORD)(triangles.size() * 3);

        // Allocate the destination geometry
        Geometry* pGeometry = NULL;
        if (APP_ERROR(AllocateGeometry(numVertices, numGeometryIndices, &pGeometry))("Couldn't allocate geometry"))
        {
            // Erase any geometry we made
            DeallocateGeometry(subsetGeometry);

            // Get rid of the mesh
            pSubsetIB->Unlock();
            pSubsetIB->Release();
            d3dxMesh->UnlockVertexBuffer();
            d3dxMesh->Release();

            // Free our device
            pd3dDevice->Release();

            // Error!
            return false;
        }

        // Copy the vertices needed for this subset into the buffer
        GeometryVertex* pVertices = pGeometry->pVertices;
        for (XIndicesIterator i = xIndicesTable.begin(); i != xIndicesTable.end(); ++i)
        {
            GeometryVertex* pCurrentVertex = &pVertices[i->second];
            *pCurrentVertex = pXVertices[i->first];

            // Modify the vertex location to make this a unit mesh sitting on the X-Z plane
            pCurrentVertex->x = pCurrentVertex->x;
            pCurrentVertex->y = pCurrentVertex->y;
            pCurrentVertex->z = pCurrentVertex->z;

            //pVertices[i->second].color = D3DCOLOR_XRGB(255,255,255);
            // todo: enable color?
        }

        // Copy triangles into the indices buffer
        DWORD index = 0;
        GeometryIndex* pIndices = pGeometry->pIndices;
        DWORD windingOrder = 0;
        for (TriangleIterator t = triangles.begin(); t != triangles.end(); ++t)
        {
            // Find this index in the winding list
            if (windingChanges.find(index / 3) != windingChanges.end())
                windingOrder = 1 - windingOrder;

            // Alternate the winding order so that everything shows up correctly
            if ((index / 3) % 2 == windingOrder)
            {
                pIndices[index + 0] = t->index[0];
                pIndices[index + 1] = t->index[1];
                pIndices[index + 2] = t->index[2];
            }
            else
            {
                pIndices[index + 0] = t->index[1];
                pIndices[index + 1] = t->index[0];
                pIndices[index + 2] = t->index[2];
            }

            // Increment the index counter
            index += 3;
        }

        // Unlock and delete strip index buffer
        pSubsetIB->Unlock();
        pSubsetIB->Release();

        // Store the buffers in the main array
        std::pair<SubsetGeometry::iterator,bool> result =
            subsetGeometry->insert(SubsetGeometry::value_type(subset, pGeometry));

        if (APP_ERROR(!result.second)("Couldn't insert subset geometry into main array for .X mesh"))
        {
            // Get rid of this geometry
            DeallocateGeometry(pGeometry);
            DeallocateGeometry(subsetGeometry);

            // Erase the mesh
            d3dxMesh->UnlockVertexBuffer();
            d3dxMesh->Release();

            // Free our device
            pd3dDevice->Release();

            // Return error
            return false;
        }

        //DEBUG_MSG("Subset %i has %i vertices %i indices (%i polygons)\n", subset, numVertices, numGeometryIndices, numGeometryIndices / 3);
    }

    // Done with the DirectX mesh.  This will not erase the outside mesh.
    d3dxMesh->UnlockVertexBuffer();
    d3dxMesh->Release();

    // Free the device reference
    pd3dDevice->Release();

    // Success
    return true;
}
Example #17
0
	void CreateBox( const float &w, const float &h, const float &d, const bool &centerWidth, const bool &centerHeight, const bool &centerDepth, LPD3DXMESH &mesh )
	{
		float offsetX = 0, offsetY = 0, offsetZ = 0;
		if( centerWidth )
			offsetX = -w / 2.f;
		if( centerHeight )
			offsetY = -h / 2.f;
		if( centerDepth )
			offsetZ = -d / 2.f;

		std::vector<DWORD> vIB;
		std::vector<VERTEX3> vVB;
		std::vector<DWORD> vAB;
		DWORD offset = 0;

		// fill in the front face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the front face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 1.f, 1.f ) );

		vAB.push_back( 0 );
		vAB.push_back( 0 );

		offset += 4;

		// fill in the back face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the back face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 1.f, 1.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 1.f, 0.f ) );

		vAB.push_back( 1 );
		vAB.push_back( 1 );

		offset += 4;

		// fill in the top face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		//fill in the top face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 1.f, 0.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, 0.f, 1.f, 0.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 0.f, 1.f, 0.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 1.f, 0.f, 1.f, 1.f ) );

		vAB.push_back( 2 );
		vAB.push_back( 2 );

		offset += 4;

		// fill in the bottom face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the bottom face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, -1.f, 0.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, -1.f, 0.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 0.f, -1.f, 0.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, 0.f, -1.f, 0.f, 1.f, 1.f ) );

		vAB.push_back( 3 );
		vAB.push_back( 3 );

		offset += 4;

		// fill in the left face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the left face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, -1.f, 0.f, 0.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, -1.f, 0.f, 0.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, -1.f, 0.f, 0.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, -1.f, 0.f, 0.f, 1.f, 1.f ) );

		vAB.push_back( 4 );
		vAB.push_back( 4 );

		offset += 4;

		// fill in the right face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the right face vertex data
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 1.f, 0.f, 0.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 1.f, 0.f, 0.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 1.f, 0.f, 0.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 1.f, 0.f, 0.f, 1.f, 1.f ) );

		vAB.push_back( 5 );
		vAB.push_back( 5 );

		offset += 4;

		D3DXCreateMeshFVF( offset / 2, offset, D3DXMESH_MANAGED | D3DXMESH_32BIT, VERTEX3::FVF, g_pEngine->core->lpd3dd9, &mesh );

		VERTEX3 *pVB = nullptr;
		mesh->LockVertexBuffer( D3DLOCK_DISCARD, reinterpret_cast< void** >( &pVB ) );
		copy( vVB.begin(), vVB.end(), pVB );
		mesh->UnlockVertexBuffer();

		DWORD *pIB = nullptr;
		mesh->LockIndexBuffer( D3DLOCK_DISCARD, reinterpret_cast< void** >( &pIB ) );
		copy( vIB.begin(), vIB.end(), pIB );
		mesh->UnlockIndexBuffer();

		DWORD *pAB = nullptr;
		mesh->LockAttributeBuffer( D3DLOCK_DISCARD, &pAB );
		copy( vAB.begin(), vAB.end(), pAB );
		mesh->UnlockAttributeBuffer();

		std::vector<DWORD> adjacencyBuffer( mesh->GetNumFaces() * 3 );
		mesh->GenerateAdjacency( 0.f, &adjacencyBuffer[ 0 ] );
		mesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, &adjacencyBuffer[ 0 ], nullptr, nullptr, nullptr );
	}
Example #18
0
//-----------------------------------------------------------------------------
// Desc: 在这里是调用了成员函数 GenerateGameSkinMesh(pMeshContainer);
//       是在这里加载了蒙皮信息
//-----------------------------------------------------------------------------
HRESULT DexAllocateHierarchy::CreateMeshContainer(LPCSTR Name, 
	CONST D3DXMESHDATA *pMeshData,
	CONST D3DXMATERIAL *pMaterials, 
	CONST D3DXEFFECTINSTANCE *pEffectInstances, 
	DWORD NumMaterials, 
	CONST DWORD *pAdjacency, 
	LPD3DXSKININFO pSkinInfo, 
	LPD3DXMESHCONTAINER *ppNewMeshContainer) 
{
	HRESULT hr;
	stDexMeshContainerEx *pMeshContainer = NULL;
	LPDIRECT3DDEVICE9 device = NULL;
	UINT NumFaces;
	UINT iMaterial;
	UINT iBone, cBones;

	LPD3DXMESH pMesh = NULL;

	*ppNewMeshContainer = NULL;

	// this sample does not handle patch meshes, so fail when one is found
	if (pMeshData->Type != D3DXMESHTYPE_MESH)
	{
		hr = E_FAIL;
		return hr;
	}

	// get the pMesh interface pointer out of the mesh data structure
	pMesh = pMeshData->pMesh;
	pMesh->GetDevice( &device );

	// this sample does not FVF compatible meshes, so fail when one is found
	if (pMesh->GetFVF() == 0)
	{
		hr = E_FAIL;
		return hr;
	}

	// allocate the overloaded structure to return as a D3DXMESHCONTAINER
	pMeshContainer = new stDexMeshContainerEx;
	if (pMeshContainer == NULL)
	{
		hr = E_OUTOFMEMORY;
		return hr;
	}
	memset(pMeshContainer, 0, sizeof(stDexMeshContainerEx));

	// make sure and copy the name.  All memory as input belongs to caller, interfaces can be addref'd though
	hr = AllocateName(Name, &pMeshContainer->Name);
	if (FAILED(hr))
	{
		if (pMeshContainer != NULL)
		{
			DestroyMeshContainer(pMeshContainer);
		}
		return hr;
	}

	NumFaces = pMesh->GetNumFaces();

	// if no normals are in the mesh, add them
	if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
	{
		pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

		// clone the mesh to make room for the normals
		hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
			pMesh->GetFVF() | D3DFVF_NORMAL, 
			device, &pMeshContainer->MeshData.pMesh );
		if (FAILED(hr))
		{
			if (pMeshContainer != NULL)
			{
				DestroyMeshContainer(pMeshContainer);
			}
			return hr;
		}

		// get the new pMesh pointer back out of the mesh container to use
		// NOTE: we do not release pMesh because we do not have a reference to it yet
		pMesh = pMeshContainer->MeshData.pMesh;

		// now generate the normals for the pmesh
		D3DXComputeNormals( pMesh, NULL );
	}
	else  // if no normals, just add a reference to the mesh for the mesh container
	{
		pMeshContainer->MeshData.pMesh = pMesh;
		pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

		pMesh->AddRef();
	}

	// allocate memory to contain the material information.  This sample uses
	//   the D3D9 materials and texture names instead of the EffectInstance style materials
	pMeshContainer->NumMaterials = max(1, NumMaterials);
	pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
	pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
	pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
	if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
	{
		hr = E_OUTOFMEMORY;
		if (pMeshContainer != NULL)
		{
			DestroyMeshContainer(pMeshContainer);
		}
		return hr;
	}

	memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);
	memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);

	// if materials provided, copy them
	if (NumMaterials > 0)            
	{
		memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);

		for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
		{
			if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
			{
				//TCHAR file[1000];
				//FindMediaFile(file,pMeshContainer->pMaterials[iMaterial].pTextureFilename);
				
				// 根据纹理的文件名创建纹理资源,如果创建失败,纹理指针必须赋成NULL
				// MessageNULL(file);
				//D3DXCreateTextureFromFileEx(device, file, 
				//	D3DX_DEFAULT_NONPOW2, 
				//	D3DX_DEFAULT_NONPOW2, 
				//	D3DX_FROM_FILE, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, 
				//	D3DX_FILTER_NONE, D3DX_FILTER_NONE, D3DCOLOR_XRGB(0,0,0), NULL, NULL, 
				//	&pMeshContainer->ppTextures[iMaterial]);
				string texname = "model/";  //轉到model文件夾中去找紋理
				texname += pMeshContainer->pMaterials[iMaterial].pTextureFilename;
				if( FAILED( D3DXCreateTextureFromFile( device, texname.c_str(),
					&pMeshContainer->ppTextures[iMaterial] ) ) )
				{
					getLog()->BeginLog();
					getLog()->Log(log_allert, "load model texture %s failed! \n", texname.c_str());
					pMeshContainer->ppTextures[iMaterial] = NULL;
					getLog()->EndLog();
				}

				// don't remember a pointer into the dynamic memory, just forget the name after loading
				pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
			}
		}
	}
	else // if no materials provided, use a default one
	{
		pMeshContainer->pMaterials[0].pTextureFilename = NULL;
		memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
		pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
	}

	// if there is skinning information, save off the required data and then setup for HW skinning
	if (pSkinInfo != NULL)
	{
		// first save off the SkinInfo and original mesh data
		pMeshContainer->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();

		pMeshContainer->pOrigMesh = pMesh;
		pMesh->AddRef();

		// Will need an array of offset matrices to move the vertices from the figure space to the bone's space
		cBones = pSkinInfo->GetNumBones();
		pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
		if (pMeshContainer->pBoneOffsetMatrices == NULL)
		{
			hr = E_OUTOFMEMORY;
			if (pMeshContainer != NULL)
			{
				DestroyMeshContainer(pMeshContainer);
			}
			return hr;
		}

		// get each of the bone offset matrices so that we don't need to get them later
		for (iBone = 0; iBone < cBones; iBone++)
		{
			pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
		}

		// GenerateGameSkinMesh will take the general skinning information and transform it to a HW friendly version
		hr = GenerateGameSkinMesh(device, pMeshContainer );
		if (FAILED(hr))
		{       
			if (pMeshContainer != NULL)
			{
				DestroyMeshContainer(pMeshContainer);
			}
			return hr;
		}
	}

	*ppNewMeshContainer = pMeshContainer;
	pMeshContainer = NULL;

	// call Destroy function to properly clean up the memory allocated 
	if (pMeshContainer != NULL)
	{
		DestroyMeshContainer(pMeshContainer);
	}
	return hr;
}
Example #19
0
//*************************************************************************************************************
void GenerateEdges(edgeset& out, LPD3DXMESH mesh)
{
	D3DXVECTOR3	p1, p2, p3;
	D3DXVECTOR3	a, b, n;
	Edge		e;
	BYTE*		vdata		= 0;
	WORD*		idata		= 0;
	size_t		ind;
	DWORD		numindices	= mesh->GetNumFaces() * 3;
	DWORD		stride		= mesh->GetNumBytesPerVertex();
	WORD		i1, i2, i3;
	bool		is32bit		= (mesh->GetOptions() & D3DXMESH_32BIT);

	out.clear();

	if( is32bit )
	{
		MYERROR("GenerateEdges(): 4 byte indices not implemented yet");
		return;
	}

	// generate edge info
	mesh->LockIndexBuffer(D3DLOCK_READONLY, (LPVOID*)&idata);
	mesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&vdata);

	out.reserve(512);

	for( DWORD i = 0; i < numindices; i += 3 )
	{
		if( out.capacity() <= out.size() )
			out.reserve(out.size() + 1024);

		i1 = idata[i + 0];
		i2 = idata[i + 1];
		i3 = idata[i + 2];

		p1 = *((D3DXVECTOR3*)(vdata + i1 * stride));
		p2 = *((D3DXVECTOR3*)(vdata + i2 * stride));
		p3 = *((D3DXVECTOR3*)(vdata + i3 * stride));

		a = p2 - p1;
		b = p3 - p1;

		D3DXVec3Cross(&n, &a, &b);
		D3DXVec3Normalize(&n, &n);

		if( i1 < i2 )
		{
			e.i1 = i1;
			e.i2 = i2;
			e.v1 = p1;
			e.v2 = p2;
			e.n1 = n;

			if( !out.insert(e) )
				std::cout << "Crack in mesh (first triangle)\n";
		}

		if( i2 < i3 )
		{
			e.i1 = i2;
			e.i2 = i3;
			e.v1 = p2;
			e.v2 = p3;
			e.n1 = n;

			if( !out.insert(e) )
				std::cout << "Crack in mesh (first triangle)\n";
		}

		if( i3 < i1 )
		{
			e.i1 = i3;
			e.i2 = i1;
			e.v1 = p3;
			e.v2 = p1;
			e.n1 = n;

			if( !out.insert(e) )
				std::cout << "Crack in mesh (first triangle)\n";
		}
	}

	// find second triangle for each edge
	for( DWORD i = 0; i < numindices; i += 3 )
	{
		i1 = idata[i + 0];
		i2 = idata[i + 1];
		i3 = idata[i + 2];

		p1 = *((D3DXVECTOR3*)(vdata + i1 * stride));
		p2 = *((D3DXVECTOR3*)(vdata + i2 * stride));
		p3 = *((D3DXVECTOR3*)(vdata + i3 * stride));

		a = p2 - p1;
		b = p3 - p1;

		D3DXVec3Cross(&n, &a, &b);
		D3DXVec3Normalize(&n, &n);

		if( i1 > i2 )
		{
			e.i1 = i2;
			e.i2 = i1;

			ind = out.find(e);

			if( ind == edgeset::npos )
			{
				std::cout << "Lone triangle\n";
				continue;
			}

			if( out[ind].other == 0xffffffff )
			{
				out[ind].other = i / 3;
				out[ind].n2 = n;
			}
			else
				std::cout << "Crack in mesh (second triangle)\n";
		}

		if( i2 > i3 )
		{
			e.i1 = i3;
			e.i2 = i2;

			ind = out.find(e);

			if( ind == edgeset::npos )
			{
				std::cout << "Lone triangle\n";
				continue;
			}

			if( out[ind].other == 0xffffffff )
			{
				out[ind].other = i / 3;
				out[ind].n2 = n;
			}
			else
				std::cout << "Crack in mesh (second triangle)\n";
		}

		if( i3 > i1 )
		{
			e.i1 = i1;
			e.i2 = i3;

			ind = out.find(e);

			if( ind == edgeset::npos )
			{
				std::cout << "Lone triangle\n";
				continue;
			}

			if( out[ind].other == 0xffffffff )
			{
				out[ind].other = i / 3;
				out[ind].n2 = n;
			}
			else
				std::cout << "Crack in mesh (second triangle)\n";
		}
	}

	mesh->UnlockIndexBuffer();
	mesh->UnlockVertexBuffer();
}
Example #20
0
//メッシュコンテナの生成
HRESULT Dx_Hierarchy::CreateMeshContainer(
	LPCTSTR Name,
	CONST D3DXMESHDATA *pMeshData,
	CONST D3DXMATERIAL *pMaterials,
	CONST D3DXEFFECTINSTANCE *pEffectInstances,
	DWORD NumMaterials, 
	CONST DWORD *pAdjacency,
	LPD3DXSKININFO pSkinInfo, 
	LPD3DXMESHCONTAINER *ppMeshContainer )
{
	HRESULT hr = S_OK;
	//生成用オブジェクトの宣言
	DxMeshContainer *pMeshContainer = NULL;
	//生成したオブジェクトの登録先を初期化
	*ppMeshContainer = NULL;

	int iFacesAmount;
	unsigned iMaterial;
	LPDIRECT3DDEVICE9 pDevice = NULL;
	LPD3DXMESH pMesh = NULL;

	// patch meshes を扱う事はできない
	//if( pMeshData->Type != D3DXMESHTYPE_MESH ) return E_FAIL;

	// FVF で記述されたメッシュ以外は読めない
	//if( pMesh->GetFVF() == 0 ) return E_FAIL;

	//DWORD					dwBoneAmt=0;

	//メッシュデータの持つメッシュポインタを取得
	pMesh = pMeshData->pMesh;

	//オブジェクトの生成
	pMeshContainer = new DxMeshContainer;
	//変数がNULLだった場合
    if (pMeshContainer == NULL)
	{
		//エラーの意味 : Direct3D が呼び出しを完了するための十分なメモリを割り当てることができませんでした。
		return E_OUTOFMEMORY;
	}
	//
	ZeroMemory(pMeshContainer, sizeof(DxMeshContainer));

	//メッシュコンテナ名の領域確保
	pMeshContainer->Name=new TCHAR[lstrlen(Name) + 1];
	//領域が確保されなかった場合
    if (!pMeshContainer->Name)
	{
		//エラーの意味 : Direct3D サブシステム内で原因不明のエラーが発生しました。
		return E_FAIL;
	}
	//名前をコピーする
	strcpy(pMeshContainer->Name,Name);

	//メッシュに関連付けられているデバイスを取得
	if(FAILED(pMesh->GetDevice(&pDevice)))
	{
		/*hr = E_FAIL;
		SAFE_RELEASE( pDevice );
		if( pMeshContainer ) DestroyMeshContainer( pMeshContainer );
		return hr;*/
	}

	//メッシュに含まれる面の数を取得
	iFacesAmount = pMesh->GetNumFaces();

    // 当該メッシュが法線を持たない場合は法線を追加する
    if (!(pMesh->GetFVF() & D3DFVF_NORMAL)) {
		//メッシュデータの種類を「メッシュ」に変更
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
		//FVFコードを使ってメッシュのコピーを生成
        hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
                                    pMesh->GetFVF() | D3DFVF_NORMAL, 
                                    pDevice, &pMeshContainer->MeshData.pMesh );
		//処理が失敗した場合
        if (FAILED(hr))
		{
			//エラーの意味 : Direct3D サブシステム内で原因不明のエラーが発生しました。
			return E_FAIL;
		}

        pMesh = pMeshContainer->MeshData.pMesh;
		//pMeshに含まれる各頂点の法線を計算して出力
        D3DXComputeNormals( pMesh, NULL );

    } else{
		//メッシュコンテナ内のメッシュデータにメッシュポインタを設定
        pMeshContainer->MeshData.pMesh = pMesh;
		//メッシュデータの種類を「メッシュ」に設定
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
		//???
        pMesh->AddRef();
    }

	//メッシュのマテリアル設定
	//マテリアル数を設定
    pMeshContainer->NumMaterials	= max(1, NumMaterials);
	//マテリアルの数だけマテリアルの領域を確保
    pMeshContainer->pMaterials		= new D3DXMATERIAL[pMeshContainer->NumMaterials];
	//マテリアルの数だけテクスチャの領域確保
    pMeshContainer->ppTextures		= new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
	//面の数だけ領域を確保
    pMeshContainer->pAdjacency		= new DWORD[iFacesAmount*3];

	//それぞれの領域確保に失敗した場合
    if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
	{
		//エラーの意味 : Direct3D が呼び出しを完了するための十分なメモリを割り当てることができませんでした。
		return E_OUTOFMEMORY;
	}

	//配列に0を設定
    memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
	//配列にpAbjacencyを設定
    memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * iFacesAmount*3);

	//マテリアルが存在する時
    if (NumMaterials > 0)
	{
		//
		memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);

		//
        for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
		{
			//テクスチャのファイル名が存在する場合
            if( pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
			{
				//ファイルまでの相対パスを設定
				char path[256] ="res/x/";
				//ファイル名を取得
				LPSTR fName	= pMeshContainer->pMaterials[iMaterial].pTextureFilename;

				//テクスチャ情報の生成
				pMeshContainer->ppTextures[iMaterial] = 
					this->t_manager->LoadTextureFromFile(fName,path);
				//テクスチャ名の破棄
                pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
            }
        }
    }
	else
	{
		//テクスチャ名の破棄
        pMeshContainer->pMaterials[0].pTextureFilename = NULL;
		//マテリアルに0を設定
        memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));

		//
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Specular  = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
    }

	//スキニング情報が存在する場合、ボーンを生成
	if(pSkinInfo!=NULL)
	{
		//メッシュコンテナ内のスキニング情報を設定
		pMeshContainer->pSkinInfo = pSkinInfo;
		//???
		pSkinInfo->AddRef();

		//スキニング情報からボーンを生成
		this->CreateBone(pMeshContainer,pDevice);
	}

	//ローカルに生成したメッシュコンテナを呼び出し側にコピーする
	*ppMeshContainer = pMeshContainer;

	//処理が無事に終了
    return hr;
}
Example #21
0
HRESULT KG3DMesh::CreateBspFile()
{
    HRESULT hrResult = E_FAIL;
    HRESULT hrRetCode = E_FAIL;
    int nRetCode = false;
    TCHAR szBSPPathName[MAX_PATH];
    void *pvVerticesBuffer = NULL;
    WORD* pIndexBuffer    = NULL;
    D3DXVECTOR3 *pPos = NULL;
    DWORD *pdwFaceIndex = NULL;
    DWORD dwStride = 0;
    DWORD i = 0;
    DWORD dwNumFaces = 0;
    DWORD dwNumVertices = 0;
    DWORD dwStartTime = timeGetTime();
    LPD3DXMESH piMesh = m_ppMeshes[SMBT_NORMAL];
    KG3DBsp *pBSP = NULL;

    KGLOG_PROCESS_ERROR(piMesh);

    dwStride      = piMesh->GetNumBytesPerVertex();
    dwNumVertices = piMesh->GetNumVertices();
    dwNumFaces    = piMesh->GetNumFaces();

    KG_PROCESS_SUCCESS(dwNumFaces < 256);

    pPos = new D3DXVECTOR3[dwNumVertices];
    KG_ASSERT_EXIT(pPos);

    pdwFaceIndex = new DWORD[dwNumFaces * 3];
    KG_ASSERT_EXIT(pdwFaceIndex);

    hrRetCode = piMesh->LockVertexBuffer(D3DLOCK_READONLY, (void **)&pvVerticesBuffer);
    KGLOG_COM_PROCESS_ERROR(hrRetCode);

    hrRetCode = piMesh->LockIndexBuffer(D3DLOCK_READONLY, (void **)&pIndexBuffer);
    KGLOG_COM_PROCESS_ERROR(hrRetCode);

    for (i = 0; i < dwNumVertices; ++i)
    {
        pPos[i] = *(D3DXVECTOR3 *)(((BYTE *)pvVerticesBuffer) + dwStride * i);
    }
    for (i = 0; i < dwNumFaces * 3; ++i)
    {
        pdwFaceIndex[i] = pIndexBuffer[i];
    }

    // -------------------------- create BSP --------------------------

    hrRetCode = ChangePathExtName(m_scName.c_str(), "bsp", sizeof(szBSPPathName), szBSPPathName);
    KGLOG_COM_PROCESS_ERROR(hrRetCode);

    pBSP = new KG3DBsp;
    KGLOG_PROCESS_ERROR(pBSP);

    hrRetCode = pBSP->CreateFromMesh(dwNumVertices, dwNumFaces, pPos, pdwFaceIndex);
    KGLOG_COM_PROCESS_ERROR(hrRetCode);

    hrRetCode = pBSP->SaveToFile(szBSPPathName);
    KGLOG_COM_PROCESS_ERROR(hrRetCode);

    DWORD dwCost = timeGetTime() - dwStartTime;
    if(dwCost > 500)
    {
        KGLogPrintf(
            KGLOG_WARNING, "BSP %d %d Face %s",
            dwCost, dwNumFaces, szBSPPathName
        );
    }

    KG_DELETE(m_lpBsp); // recreate
    m_lpBsp = pBSP;
    pBSP = NULL;
Exit1:
    hrResult = S_OK;
Exit0:
    KG_DELETE(pBSP);
    if (pIndexBuffer)
    {
        piMesh->UnlockIndexBuffer();
        pIndexBuffer = NULL;
    }
    if (pvVerticesBuffer)
    {
        piMesh->UnlockVertexBuffer();
        pvVerticesBuffer = NULL;
    }
    KG_DELETE_ARRAY(pdwFaceIndex);
    KG_DELETE_ARRAY(pPos);

    if(FAILED(hrResult))
    {
        KGLogPrintf(KGLOG_ERR, "%s 创建失败", szBSPPathName);
    }
    return hrResult;
}
//-----------------------------------------------------------------------------
// Name: buildShadowVolume()
// Desc: Takes a mesh as input, and uses it to build a shadow volume. The
//       technique used considers each triangle of the mesh, and adds it's
//       edges to a temporary list. The edge list is maintained, such that
//       only silohuette edges are kept. Finally, the silohuette edges are
//       extruded to make the shadow volume vertex list.
//-----------------------------------------------------------------------------
HRESULT CShadowVolume::BuildShadowVolume(LPD3DXMESH pMesh, D3DXVECTOR3 vLight)
{
    // pMesh的顶点结构
    struct MeshVertex {
        D3DXVECTOR3 p;
        D3DXVECTOR3 n;
        float u, v;
    };

    MeshVertex *pVertices;
    WORD       *pIndices;

    // 锁缓存
    pMesh->LockVertexBuffer(0L, (LPVOID*)&pVertices);
    pMesh->LockIndexBuffer(0L, (LPVOID*)&pIndices);
    DWORD dwNumFaces = pMesh->GetNumFaces();

    // 分配一个临时的索引数组
    WORD *pEdges = new WORD[dwNumFaces * 6];

    if (pEdges == NULL)
    {
        pMesh->UnlockVertexBuffer();
        pMesh->UnlockIndexBuffer();
        return E_OUTOFMEMORY;
    }

    DWORD dwNumEdges = 0;

    // 对每个片面进行计算
    for (DWORD i = 0; i < dwNumFaces; ++i)
    {
        WORD wFace0 = pIndices[3 * i + 0];
        WORD wFace1 = pIndices[3 * i + 1];
        WORD wFace2 = pIndices[3 * i + 2];

        // 一个面的三个顶点坐标
        D3DXVECTOR3 v0 = pVertices[wFace0].p;
        D3DXVECTOR3 v1 = pVertices[wFace1].p;
        D3DXVECTOR3 v2 = pVertices[wFace2].p;

        // 计算法线是否向光
        D3DXVECTOR3 vCross1(v2 - v1);
        D3DXVECTOR3 vCross2(v1 - v0);
        D3DXVECTOR3 vNormal;
        D3DXVec3Cross(&vNormal, &vCross1, &vCross2);

        if (D3DXVec3Dot(&vNormal, &vLight) >= 0.0f)
        {
            AddEdge(pEdges, dwNumEdges, wFace0, wFace1);
            AddEdge(pEdges, dwNumEdges, wFace1, wFace2);
            AddEdge(pEdges, dwNumEdges, wFace2, wFace0);
        }
    }

    // pEdges中仅剩pMesh的边缘顶点,对每条边的两个顶点按光照的方向进行延伸
    // 最终构建一个完整的阴影体
    for (DWORD i = 0; i < dwNumEdges; ++i)
    {
        D3DXVECTOR3 v1 = pVertices[pEdges[2 * i + 0]].p;
        D3DXVECTOR3 v2 = pVertices[pEdges[2 * i + 1]].p;
        D3DXVECTOR3 v3 = v1 + vLight * 200;
        D3DXVECTOR3 v4 = v2 + vLight * 200;

        // 封边操作
        m_pVertices[m_dwNumVertices++] = v1;
        m_pVertices[m_dwNumVertices++] = v2;
        m_pVertices[m_dwNumVertices++] = v3;

        m_pVertices[m_dwNumVertices++] = v2;
        m_pVertices[m_dwNumVertices++] = v4;
        m_pVertices[m_dwNumVertices++] = v3;
    }

    // Delete the temporary edge list
    delete[] pEdges;

    // Unlock the geometry buffers
    pMesh->UnlockVertexBuffer();
    pMesh->UnlockIndexBuffer();

    return S_OK;
}
void optimizePhysXMesh(int flag, IDirect3DDevice9* D3DDevice, float epsilon, std::vector<physx::PxVec3>& pxVertices, oiram::IndexBuffer& indexBuffer)
{
	assert(D3DDevice);

	D3DVERTEXELEMENT9 szDecl[] = {
		{0,		0,		D3DDECLTYPE_FLOAT3,		D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_POSITION,	0},
		{0xFF,	0,		D3DDECLTYPE_UNUSED,		0,						0,						0}
	};

	// 创建D3D MESH
	LPD3DXMESH pMesh = 0;
	DWORD options = D3DXMESH_SYSTEMMEM | D3DXMESH_DYNAMIC;
	if (indexBuffer.use32BitIndices)
		options |= D3DXMESH_32BIT;
	DWORD numVertices = static_cast<DWORD>(pxVertices.size()), numFaces = numVertices / 3;
	HRESULT hr = D3DXCreateMesh(numFaces, numVertices, options, szDecl, D3DDevice, &pMesh);
	if (SUCCEEDED(hr))
	{
		LPVOID pData = nullptr;
		// 填充Index Buffer
		if (SUCCEEDED(pMesh->LockIndexBuffer(D3DLOCK_DISCARD, &pData)))
		{
			if (indexBuffer.use32BitIndices)
				memcpy(pData, indexBuffer.uiIndexBuffer.data(), indexBuffer.uiIndexBuffer.size() * sizeof(physx::PxU32));
			else
				memcpy(pData, indexBuffer.usIndexBuffer.data(), indexBuffer.usIndexBuffer.size() * sizeof(physx::PxU16));

			pMesh->UnlockIndexBuffer();
		}

		// 填充Vertex Buffer
		if (SUCCEEDED(pMesh->LockVertexBuffer(D3DLOCK_DISCARD, &pData)))
		{
			memcpy(pData, pxVertices.data(), pxVertices.size() * sizeof(physx::PxVec3));
			pMesh->UnlockVertexBuffer();
		}

		// 进行Mesh优化
		DWORD dwFaces = pMesh->GetNumFaces();
		std::vector<DWORD> szAdjacencies(dwFaces * 3);
		DWORD* pAdjacency = &szAdjacencies[0];
		pMesh->GenerateAdjacency(epsilon, pAdjacency);
		// 清理mesh
		hr = D3DXCleanMesh(D3DXCLEAN_SIMPLIFICATION, pMesh, pAdjacency, &pMesh, pAdjacency, NULL);
		if (SUCCEEDED(hr))
		{
			// 去除mesh中重复的顶点
			hr = D3DXWeldVertices(pMesh, D3DXWELDEPSILONS_WELDALL, NULL, pAdjacency, pAdjacency, NULL, NULL);
			if (SUCCEEDED(hr))
			{
				// 将优化后的数据写回mesh data
				DWORD numIndices = pMesh->GetNumFaces() * 3;
				indexBuffer.use32BitIndices = numIndices > 65535;
				if (indexBuffer.use32BitIndices)
					indexBuffer.uiIndexBuffer.resize(numIndices);
				else
					indexBuffer.usIndexBuffer.resize(numIndices);

				// 取出Index Buffer
				if (SUCCEEDED(pMesh->LockIndexBuffer(D3DLOCK_READONLY | D3DLOCK_DISCARD, &pData)))
				{
					if (indexBuffer.use32BitIndices)
						memcpy(indexBuffer.uiIndexBuffer.data(), pData, indexBuffer.uiIndexBuffer.size() * sizeof(physx::PxU32));
					else
						memcpy(indexBuffer.usIndexBuffer.data(), pData, indexBuffer.usIndexBuffer.size() * sizeof(physx::PxU16));

					pMesh->UnlockIndexBuffer();
				}

				// 取出Vertex Buffer
				DWORD dwVertices = pMesh->GetNumVertices();
				pxVertices.resize(dwVertices);

				if (SUCCEEDED(pMesh->LockVertexBuffer(D3DLOCK_READONLY | D3DLOCK_DISCARD, &pData)))
				{
					memcpy(pxVertices.data(), pData, pxVertices.size() * sizeof(physx::PxVec3));
					pMesh->UnlockVertexBuffer();
				}
			}
		}

		pMesh->Release();
	}
}
DWORD MeshParameterization::OnGenerateAtlas( DWORD size, void * params )
{
	VERIFY_MESSAGE_SIZE( size, sizeof( GENERATEATLASMESSAGE ) );
	GENERATEATLASMESSAGE * msg = (GENERATEATLASMESSAGE*)params;
	if( !msg )
	{
		return MSG_ERROR;
	}
	bool bUseIncomingTexCoords = msg->useIncomingTexCoords;
	GenerateBounds();
	HRESULT hr;
	//This should be changed to use a new mesh parameterization technique
	DWORD numFaces = (DWORD)m_Faces->size();
	DWORD numVertices = (DWORD)m_CollapsedMesh->size();
	DWORD curError = 0;
	if( !bUseIncomingTexCoords &&
		numFaces > 0 &&
		numVertices > 0 )
	{
		DWORD fvf = D3DFVF_XYZ |  D3DFVF_NORMAL | D3DFVF_TEX1 ;
		DWORD flags =  D3DXMESH_SYSTEMMEM ;//  | D3DXMESH_MANAGED ;// | D3DXMESH_SOFTWAREPROCESSING | D3DXMESH_SYSTEMMEM |;
		
		LPD3DXMESH mesh = NULL;
		hr = D3DXCreateMeshFVF( numFaces, numVertices, flags, fvf, m_pDevice, &mesh );
		if( FAILED( hr ) )
		{
			curError = GetLastError();
			EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in create mesh fvf\n"));
			return MSG_ERROR;
		}
		//now fill with data
		BYTE * vertexData;
		BYTE * indexData;
		hr = mesh->LockVertexBuffer( 0, (LPVOID*)&vertexData );
		hr = mesh->LockIndexBuffer( 0, (LPVOID*)&indexData );
		D3DVERTEXELEMENT9 Decl[ MAX_FVF_DECL_SIZE ];
		mesh->GetDeclaration( Decl );
		
		paramVertex * pVertOriginal = (paramVertex*)vertexData;
		for( int i = 0; i < (int)numVertices; i++ )
		{
			paramVertex * pVert = (paramVertex*)vertexData;
			pVert->x = (*m_CollapsedMesh)[i].originalPosition.x;
			pVert->y = (*m_CollapsedMesh)[i].originalPosition.y;
			pVert->z = (*m_CollapsedMesh)[i].originalPosition.z;
			pVert->nx = -(*m_CollapsedMesh)[i].normal.x;
			pVert->ny = -(*m_CollapsedMesh)[i].normal.y;
			pVert->nz = -(*m_CollapsedMesh)[i].normal.z;
			pVert->u = (*m_CollapsedMesh)[i].generatedU;
			pVert->v = (*m_CollapsedMesh)[i].generatedV;
			NormalizeUV( pVert->u );
			NormalizeUV( pVert->v );

			vertexData += sizeof( paramVertex );
		}
		for( int i = 0; i < (int)numFaces; i++ )
		{
			unsigned short * index = (unsigned short*)indexData;
			index[0] = ( unsigned short )(*m_Faces)[ i ].index[ 0 ];
			index[1] = ( unsigned short )(*m_Faces)[ i ].index[ 1 ];
			index[2] = ( unsigned short )(*m_Faces)[ i ].index[ 2 ];
			indexData += sizeof( unsigned short )*3;//32 bit indices triangles
		}

		LPD3DXBUFFER imt;
		hr = D3DXComputeIMTFromPerVertexSignal( mesh, (const float*)pVertOriginal + 3*sizeof(float), 3, sizeof(paramVertex),
											0L, 0, 0, &imt );		
		mesh->UnlockIndexBuffer();
		mesh->UnlockVertexBuffer();
		//tensors
   		float * tensors = new float[ 3*numFaces ];
   		for( int i = 0; i < 3*(int)numFaces; i += 3 )
   		{
   			tensors[ i ] = 4.f;
   			tensors[ i + 1 ] = 0.f;
   			tensors[ i + 2 ] = 4.f;
   		}
		
		//some checks 
		numVertices = mesh->GetNumVertices();
		numFaces = mesh->GetNumFaces();

		//create adjacency
		DWORD * adjacency = new DWORD[	3*numFaces ];
		memset( adjacency, 0, sizeof(DWORD)*3*numFaces );
		hr = mesh->GenerateAdjacency( 0.001f, adjacency );
		//hr = mesh->ConvertPointRepsToAdjacency( NULL, adjacency );
		if( FAILED( hr ) )
		{
			curError = GetLastError();
			EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in generate adjacency\n"));
			return MSG_ERROR;
		}
		/* save to mesh to check model uvs
		D3DXMATERIAL mat;
		mat.MatD3D.Ambient.r = mat.MatD3D.Ambient.a =mat.MatD3D.Ambient.b =mat.MatD3D.Ambient.g = 0;
		mat.MatD3D.Diffuse.r = mat.MatD3D.Diffuse.a =mat.MatD3D.Diffuse.b =mat.MatD3D.Diffuse.g = 1;
		mat.pTextureFilename = "tex.dds";
		D3DXSaveMeshToX( "mesh.x", mesh, adjacency, &mat, NULL, 0, D3DXF_FILEFORMAT_TEXT );
		*/

		float * imtTensor = tensors;//(float*)imt->GetBufferPointer();

		float stretchout;
		unsigned int charts;
		LPD3DXMESH meshOut = NULL;
		LPD3DXBUFFER remappedData = NULL;
		LPD3DXBUFFER faceData = NULL;

		D3DXATTRIBUTERANGE Attrib;
		memset(&Attrib, 0, sizeof(D3DXATTRIBUTERANGE));
		Attrib.FaceCount = numFaces;
		Attrib.VertexCount = numVertices;
		mesh->SetAttributeTable(&Attrib, 1);
		int gutter = m_TexSize / 32;
		gutter = min( gutter, 6 );
		hr = D3DXUVAtlasCreate( mesh, 0, .5, m_TexSize, m_TexSize, 
								6, //gutter
								0, adjacency, 0,
								imtTensor, (LPD3DXUVATLASCB)UVGenCallback, .0001f, 0,
								//D3DXUVATLAS_GEODESIC_QUALITY ,
								D3DXUVATLAS_GEODESIC_FAST,
								&meshOut, &faceData, &remappedData, 
								&stretchout, &charts );
		if( FAILED( hr ) )
		{
			curError = GetLastError();
			EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in uv atlas create\n"));
			return MSG_ERROR;
		}
		/* save to mesh to check model uvs
		hr = meshOut->ConvertPointRepsToAdjacency( NULL, adjacency );
		D3DXSaveMeshToX( "mesh2.x", meshOut, adjacency, &mat, NULL, 0, D3DXF_FILEFORMAT_TEXT );
		*/
		delete [] adjacency;
		delete [] tensors;

		//Generate our lightmap cache data for passing on and saving
		GenerateCache( meshOut, remappedData );
		GenerateTriangleTexelData();
		
		meshOut->Release();
		faceData->Release();
		remappedData->Release();
		mesh->Release();
	}    
	else 
	if( bUseIncomingTexCoords )
	{
		GenerateCache();
		GenerateTriangleTexelData();
	}
	return MSG_HANDLED_STOP;
}