Beispiel #1
0
//-----------------------------------------------------------------------------
// Name: CMultiAnimAllocateHierarchy::CreateMeshContainer()
// Desc: Called by D3DX during the loading of a mesh hierarchy. At a minumum,
//       the app should allocate a D3DXMESHCONTAINER or a child of it and fill
//       in the members based on the parameters here.  The app can further
//       customize the allocation behavior here.  In our case, we initialize
//       m_amxBoneOffsets from the skin info for convenience reason.
//       Then we call ConvertToIndexedBlendedMesh to obtain a new mesh object
//       that's compatible with the palette size we have to work with.
//-----------------------------------------------------------------------------
HRESULT CMultiAnimAllocateHierarchy::CreateMeshContainer( THIS_
    LPCSTR Name,
    CONST D3DXMESHDATA *pMeshData,
    CONST D3DXMATERIAL *pMaterials,
    CONST D3DXEFFECTINSTANCE *pEffectInstances,
    DWORD NumMaterials,
    CONST DWORD *pAdjacency,
    LPD3DXSKININFO pSkinInfo, 
    LPD3DXMESHCONTAINER *ppNewMeshContainer )
{
    assert( m_pMA );

    * ppNewMeshContainer = NULL;

    HRESULT hr = S_OK;

    MultiAnimMC * pMC = new MultiAnimMC;
    if( pMC == NULL )
    { hr = E_OUTOFMEMORY; goto e_Exit; }

    ZeroMemory( pMC, sizeof( MultiAnimMC ) );

    // if this is a static mesh, exit early; we're only interested in skinned meshes
    if( pSkinInfo == NULL )
    {
        hr = S_OK;
        goto e_Exit;
    }

    // only support mesh type
    if( pMeshData->Type != D3DXMESHTYPE_MESH )
    { hr = E_FAIL; goto e_Exit; }

    if( Name )
        pMC->Name = (CHAR *) HeapCopy( (CHAR *) Name );
    else
        pMC->Name = (CHAR *) HeapCopy( "<no_name>" );

    // copy the mesh over
    pMC->MeshData.Type = pMeshData->Type;
    pMC->MeshData.pMesh = pMeshData->pMesh;
    pMC->MeshData.pMesh->AddRef();

    // copy adjacency over
    {
        DWORD dwNumFaces = pMC->MeshData.pMesh->GetNumFaces();
        pMC->pAdjacency = new DWORD[ 3 * dwNumFaces ];
        if( pMC->pAdjacency == NULL )
        { hr = E_OUTOFMEMORY; goto e_Exit; }

        CopyMemory( pMC->pAdjacency, pAdjacency, 3 * sizeof( DWORD ) * dwNumFaces );
    }

    // ignore effects instances
    pMC->pEffects = NULL;

    // alloc and copy materials
    pMC->NumMaterials = max( 1, NumMaterials );
    pMC->pMaterials = new D3DXMATERIAL           [ pMC->NumMaterials ];
    pMC->m_apTextures = new LPDIRECT3DTEXTURE9   [ pMC->NumMaterials ];
    if( pMC->pMaterials == NULL || pMC->m_apTextures == NULL )
    { hr = E_OUTOFMEMORY; goto e_Exit; }

    if( NumMaterials > 0 )
    {
        CopyMemory( pMC->pMaterials, pMaterials, NumMaterials * sizeof( D3DXMATERIAL ) );
        for( DWORD i = 0; i < NumMaterials; ++ i )
        {
            if( pMC->pMaterials[ i ].pTextureFilename )
            {
                // CALLBACK to get valid filename
                TCHAR sNewPath[ MAX_PATH ];
                TCHAR tszTexName[ MAX_PATH ];
                if( FAILED( DXUtil_ConvertAnsiStringToGenericCch( tszTexName,
                    pMC->pMaterials[ i ].pTextureFilename,
                    MAX_PATH ) ) )
                    pMC->m_apTextures[ i ] = NULL;
                else
                    if( SUCCEEDED( DXUtil_FindMediaFileCch( sNewPath, MAX_PATH, tszTexName ) ) )
                    {
                        // create the D3D texture
                        if( FAILED( D3DXCreateTextureFromFile( m_pMA->m_pDevice,
                            sNewPath,
                            &pMC->m_apTextures[ i ] ) ) )
                            pMC->m_apTextures[ i ] = NULL;
                    }
                    else
                        pMC->m_apTextures[ i ] = NULL;
            }
            else
                pMC->m_apTextures[ i ] = NULL;
        }
    }
    else    // mock up a default material and set it
    {
        ZeroMemory( & pMC->pMaterials[ 0 ].MatD3D, sizeof( ParaMaterial ) );
        pMC->pMaterials[ 0 ].MatD3D.Diffuse.r = 0.5f;
        pMC->pMaterials[ 0 ].MatD3D.Diffuse.g = 0.5f;
        pMC->pMaterials[ 0 ].MatD3D.Diffuse.b = 0.5f;
        pMC->pMaterials[ 0 ].MatD3D.Specular = pMC->pMaterials[ 0 ].MatD3D.Diffuse;
        pMC->pMaterials[ 0 ].pTextureFilename = NULL;
    }

    // save the skininfo object
    pMC->pSkinInfo = pSkinInfo;
    pSkinInfo->AddRef();

    // Get the bone offset matrices from the skin info
    pMC->m_amxBoneOffsets = new Matrix4[ pSkinInfo->GetNumBones() ];
    if( pMC->m_amxBoneOffsets == NULL )
    { hr = E_OUTOFMEMORY; goto e_Exit; }
    {
        for( DWORD i = 0; i < pSkinInfo->GetNumBones(); ++ i )
            pMC->m_amxBoneOffsets[ i ] = * (Matrix4 *) pSkinInfo->GetBoneOffsetMatrix( i );
    }

    //
    // Determine the palette size we need to work with, then call ConvertToIndexedBlendedMesh
    // to set up a new mesh that is compatible with the palette size.
    //
    {
        UINT iPaletteSize = 0;
        m_pMA->m_pEffect->GetInt( "MATRIX_PALETTE_SIZE", (INT *) & iPaletteSize );
        pMC->m_dwNumPaletteEntries = min( iPaletteSize, pMC->pSkinInfo->GetNumBones() );
    }

    // generate the skinned mesh - creates a mesh with blend weights and indices
    hr = pMC->pSkinInfo->ConvertToIndexedBlendedMesh( pMC->MeshData.pMesh,
        D3DXMESH_MANAGED | D3DXMESHOPT_VERTEXCACHE,
        pMC->m_dwNumPaletteEntries,
        pMC->pAdjacency,
        NULL,
        NULL,
        NULL,
        &pMC->m_dwMaxNumFaceInfls,
        &pMC->m_dwNumAttrGroups,
        &pMC->m_pBufBoneCombos,
        &pMC->m_pWorkingMesh );
    if( FAILED( hr ) )
        goto e_Exit;

    // Make sure the working set is large enough for this mesh.
    // This is a bone array used for all mesh containers as a working
    // set during drawing.  If one was created previously that isn't 
    // large enough for this mesh, we have to reallocate.
    if( m_pMA->m_dwWorkingPaletteSize < pMC->m_dwNumPaletteEntries )
    {
        if( m_pMA->m_amxWorkingPalette )
            delete [] m_pMA->m_amxWorkingPalette;

        m_pMA->m_dwWorkingPaletteSize = pMC->m_dwNumPaletteEntries;
        m_pMA->m_amxWorkingPalette = new Matrix4[ m_pMA->m_dwWorkingPaletteSize ];
        if( m_pMA->m_amxWorkingPalette == NULL )
        {
            m_pMA->m_dwWorkingPaletteSize = 0;
            hr = E_OUTOFMEMORY;
            goto e_Exit;
        }
    }

    // ensure the proper vertex format for the mesh
    {
        DWORD dwOldFVF = pMC->m_pWorkingMesh->GetFVF();
        DWORD dwNewFVF = ( dwOldFVF & D3DFVF_POSITION_MASK ) | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_LASTBETA_UBYTE4;
        if( dwNewFVF != dwOldFVF )
        {
            LPD3DXMESH pMesh;
            hr = pMC->m_pWorkingMesh->CloneMeshFVF( pMC->m_pWorkingMesh->GetOptions(),
                dwNewFVF,
                m_pMA->m_pDevice,
                &pMesh );
            if( FAILED( hr ) )
                goto e_Exit;

            pMC->m_pWorkingMesh->Release();
            pMC->m_pWorkingMesh = pMesh;

            // if the loaded mesh didn't contain normals, compute them here
            if( ! ( dwOldFVF & D3DFVF_NORMAL ) )
            {
                hr = D3DXComputeNormals( pMC->m_pWorkingMesh, NULL );
                if( FAILED( hr ) )
                    goto e_Exit;
            }
        }
    }

    // Interpret the UBYTE4 as a Color.
    // The GeForce3 doesn't support the UBYTE4 decl type.  So, we convert any
    // blend indices to a Color semantic, and later in the shader convert
    // it back using the D3DCOLORtoUBYTE4() intrinsic.  Note that we don't
    // convert any data, just the declaration.
    D3DVERTEXELEMENT9 pDecl[ MAX_FVF_DECL_SIZE ];
    D3DVERTEXELEMENT9 * pDeclCur;
    hr = pMC->m_pWorkingMesh->GetDeclaration( pDecl );
    if( FAILED( hr ) )
        goto e_Exit;

    pDeclCur = pDecl;
    while( pDeclCur->Stream != 0xff )
    {
        if( ( pDeclCur->Usage == D3DDECLUSAGE_BLENDINDICES ) && ( pDeclCur->UsageIndex == 0 ) )
            pDeclCur->Type = D3DDECLTYPE_D3DCOLOR;
        pDeclCur++;
    }

    hr = pMC->m_pWorkingMesh->UpdateSemantics( pDecl );
    if( FAILED( hr ) )
        goto e_Exit;

e_Exit:

    if( FAILED( hr ) )
    {
        if( pMC )
            DestroyMeshContainer( pMC );
    }
    else
        * ppNewMeshContainer = pMC;

    return hr;
}
Beispiel #2
0
//---------------------------------
HRESULT CAllocateHierarchy::CreateMeshContainer (LPCSTR Name, const D3DXMESHDATA *pMeshData, \
		const D3DXMATERIAL *pMaterials,const D3DXEFFECTINSTANCE *pEffectInstances, \
		DWORD NumMaterials, const DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, \
		LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
	DWORD i, j;
	D3DXMESHCONTAINER_DERIVED *pMeshContainer;
	LPD3DXMESH pMesh, pTempMesh;
	HRESULT hr = E_FAIL;

	*ppNewMeshContainer = NULL;

	//podporované su iba bezne meshe
	if (pMeshData->Type != D3DXMESHTYPE_MESH)
		return E_FAIL;

	//alokácia derivovanej štruktúry kvôli návratovej hodnote - LPD3DXMESHCONTAINER
	pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
	if (pMeshContainer == NULL)
		return E_OUTOFMEMORY;

	pMesh = pMeshData->pMesh;
	pMesh->AddRef();

	pMeshContainer->NumMaterials = max (1, NumMaterials);
	pMeshContainer->dwNumPaintings = 1;
	pMeshContainer->dwNumCoords = 1;
	if (m_localData.xmlTextures)
	{
		const char *szTemp;
		if (szTemp = g_pXML->Attr (m_localData.xmlTextures, "paint_num"))
			pMeshContainer->dwNumPaintings = (DWORD)atoi (szTemp);
		if (szTemp = g_pXML->Attr (m_localData.xmlTextures, "coord_num"))
			pMeshContainer->dwNumCoords = (DWORD)atoi (szTemp);
	}
	pMeshContainer->dwNumPaintings = max (1, pMeshContainer->dwNumPaintings);
	pMeshContainer->dwNumCoords = max (1, pMeshContainer->dwNumCoords);
	if (pMeshContainer->dwNumPaintings <= m_localData.dwUseThisPainting)
		m_localData.dwUseThisPainting = 0;		// chyba, pozadovana painting-verzia nie je v xml definovana

	//////////////////////////////////////////////////////////////////////////
	// mesh cloning - tangent, binormal, tex. koordinaty - pocitaju sa len pre modely s viac ako jednou texturovou vrstvou
	if (pMeshContainer->dwNumCoords > 1)
	{
		const DWORD dwRealNumCoords = (pMesh->GetFVF() & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
		const int intTexCoordsToAdd = pMeshContainer->dwNumCoords - dwRealNumCoords;
		DWORD dwVertexStride = pMesh->GetNumBytesPerVertex ();

		D3DVERTEXELEMENT9 meshDeclaration[MAX_FVF_DECL_SIZE];
		if (SUCCEEDED (pMesh->GetDeclaration (meshDeclaration)))
		{
			DWORD dwNumDeclarations = 0;
			for (i=0; (i < MAX_FVF_DECL_SIZE) && (meshDeclaration[i].Stream != 0xFF); i++)
				dwNumDeclarations++;
			// pridanie deklaracie pre tangent
			meshDeclaration[dwNumDeclarations].Stream = 0;
			meshDeclaration[dwNumDeclarations].Offset = (WORD)dwVertexStride;
			meshDeclaration[dwNumDeclarations].Type = D3DDECLTYPE_FLOAT3;
			meshDeclaration[dwNumDeclarations].Method = D3DDECLMETHOD_DEFAULT;
			meshDeclaration[dwNumDeclarations].Usage = D3DDECLUSAGE_TANGENT;
			meshDeclaration[dwNumDeclarations].UsageIndex = 0;
			dwNumDeclarations++;
			// pridanie deklaracie pre binormal
			meshDeclaration[dwNumDeclarations].Stream = 0;
			meshDeclaration[dwNumDeclarations].Offset = (WORD)(dwVertexStride + 3*sizeof(float));
			meshDeclaration[dwNumDeclarations].Type = D3DDECLTYPE_FLOAT3;
			meshDeclaration[dwNumDeclarations].Method = D3DDECLMETHOD_DEFAULT;
			meshDeclaration[dwNumDeclarations].Usage = D3DDECLUSAGE_BINORMAL;
			meshDeclaration[dwNumDeclarations].UsageIndex = 0;
			dwNumDeclarations++;
			// pridanie texturovych koordinatov
			for (int k=0; k<intTexCoordsToAdd; k++)
			{
				meshDeclaration[dwNumDeclarations].Stream = 0;
				meshDeclaration[dwNumDeclarations].Offset = (WORD)(dwVertexStride + 6*sizeof(float) + k*2*sizeof(float));
				meshDeclaration[dwNumDeclarations].Type = D3DDECLTYPE_FLOAT2;
				meshDeclaration[dwNumDeclarations].Method = D3DDECLMETHOD_DEFAULT;
				meshDeclaration[dwNumDeclarations].Usage = D3DDECLUSAGE_TEXCOORD;
				meshDeclaration[dwNumDeclarations].UsageIndex = BYTE(k + dwRealNumCoords);
				dwNumDeclarations++;
			}
			// ukoncovaci element
			memset (&meshDeclaration[dwNumDeclarations], 0, sizeof(D3DVERTEXELEMENT9));
			meshDeclaration[dwNumDeclarations].Stream = 0xFF;
			meshDeclaration[dwNumDeclarations].Type = D3DDECLTYPE_UNUSED;

			if (FAILED (pMesh->CloneMesh (pMesh->GetOptions(), meshDeclaration, g_pD3DDevice, &pTempMesh)))
				goto e_Exit;

			pMesh->Release ();
			pMesh = pTempMesh;
		}

		//////////////////////////////////////////////////////////////////////////
		const DWORD	dwVertexCount = pMesh->GetNumVertices ();
		dwVertexStride = pMesh->GetNumBytesPerVertex ();

		// uprava koordinatov, ak je to potrebne
		for (i=dwRealNumCoords; i < pMeshContainer->dwNumCoords; i++)
		{
			LPVOID	pData;
			DWORD	dwUseThisCoords = 0xFFFFFFFF,dwTexCoordOffsetSrc = 0xFFFFFFFF, dwTexCoordOffsetDst = 0xFFFFFFFF;
			if (m_localData.xmlTextures)
			{
				ezxml_t pTextureTag, pCoordsTag;
				const char *szTemp;
				char szCoordsTag[16];
				if (pTextureTag = g_pXML->Child (m_localData.xmlTextures, "texture0"))
				{
					sprintf (szCoordsTag, "coords%u", i);
					if (pCoordsTag = g_pXML->Child (pTextureTag, szCoordsTag))
						if (szTemp = g_pXML->Attr (pCoordsTag, "usecoords"))
						{
							dwUseThisCoords = (DWORD) atoi (szTemp);
							if (dwUseThisCoords >= i) dwUseThisCoords = 0;
						}
				}
			}
			if ((i > dwRealNumCoords) && (dwUseThisCoords == 0xFFFFFFFF))
				dwUseThisCoords = 0;

			// ak je v xml definovany usecoords, tak kopirovat koordinaty
			if (dwUseThisCoords != 0xFFFFFFFF)
			{
				for (j=0; (j < MAX_FVF_DECL_SIZE) && (meshDeclaration[j].Stream != 0xFF); j++)
					if (meshDeclaration[j].Usage == D3DDECLUSAGE_TEXCOORD)
						if (meshDeclaration[j].UsageIndex == dwUseThisCoords)
							dwTexCoordOffsetSrc = meshDeclaration[j].Offset;
						else if (meshDeclaration[j].UsageIndex == i)
							dwTexCoordOffsetDst = meshDeclaration[j].Offset;
				if ((dwTexCoordOffsetSrc == 0xFFFFFFFF) || (dwTexCoordOffsetDst == 0xFFFFFFFF))
					continue;	// chyba

				if (SUCCEEDED (pMesh->LockVertexBuffer (0, &pData)))
				{
					LPBYTE pVertexData = (LPBYTE)pData;
					// kopirovanie koordinatov z vrstvy dwUseThisCoords
					for (j=0; j<dwVertexCount; j++)
					{
						memcpy ((pVertexData + dwTexCoordOffsetDst), (pVertexData + dwTexCoordOffsetSrc), 2*sizeof(float));
						pVertexData += dwVertexStride;
					}
					pMesh->UnlockVertexBuffer ();
				}
			}
		}
		// vypocet tangent a binormal
		if (!CalculateMeshTangents (pMesh, 1))
			g_pConsole->Message(MSG_CON_ERR, "MeshLoader: CalculateMeshTangents() function failed");
	}

	//////////////////////////////////////////////////////////////////////////
	// nacitanie informacii o materialoch a texturach z x suboru
	pMeshContainer->pMaterials	= new D3DXMATERIAL[pMeshContainer->NumMaterials];
	pMeshContainer->pTextures	= new LPDIRECT3DTEXTURE9 [pMeshContainer->NumMaterials * pMeshContainer->dwNumCoords * pMeshContainer->dwNumPaintings];
	pMeshContainer->p7MTmaterials = new DWORD [pMeshContainer->NumMaterials];

	if ((pMeshContainer->pMaterials == NULL) || (pMeshContainer->pTextures == NULL) || \
														(pMeshContainer->p7MTmaterials == NULL))
		{hr = E_OUTOFMEMORY; goto e_Exit;}
	memset (pMeshContainer->pMaterials, 0, sizeof(D3DXMATERIAL) * pMeshContainer->NumMaterials);
	memset (pMeshContainer->pTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials * pMeshContainer->dwNumCoords * pMeshContainer->dwNumPaintings);
	memset (pMeshContainer->p7MTmaterials, 0xFF, sizeof(DWORD) * pMeshContainer->NumMaterials);

	// nacitanie materialov
	if (NumMaterials > 0)
	{
		for (i=0; i<NumMaterials; i++)
		{
			pMeshContainer->pMaterials[i].MatD3D = pMaterials[i].MatD3D;
			// do x suboru sa neexportuje udaj o ambient zlozke materialov, upravit podla potreby
			pMeshContainer->pMaterials[i].MatD3D.Ambient = D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f);
			// vypnut Power ak nie je zadana Specular zlozka
			D3DCOLORVALUE &colorSpec = pMeshContainer->pMaterials[i].MatD3D.Specular;
			if ((colorSpec.r == 0) && (colorSpec.g == 0) && (colorSpec.b == 0))
				pMeshContainer->pMaterials[i].MatD3D.Power = 0.0f;

			// nacitanie 7mt materialu, ak je k danemu povrchu priradeny
			#define MATERIAL_FLOAT_TOLERANCE		0.001f
			for (j=0; j < m_localData.dw7mtMaterialsNum; j++)
				if (m_localData.Mesh7mtMaterials[j].sz7mtMaterialName != NULL)
				{
					// porovnanie textur ak su dostupne
					if ((m_localData.Mesh7mtMaterials[j].szTextureName != NULL) && (pMaterials[i].pTextureFilename != NULL))
						if (stricmp (m_localData.Mesh7mtMaterials[j].szTextureName, pMaterials[i].pTextureFilename) != 0)
							continue;
					// porovnanie materialov
					if (fabs (m_localData.Mesh7mtMaterials[j].material.rDif - pMaterials[i].MatD3D.Diffuse.r) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.gDif - pMaterials[i].MatD3D.Diffuse.g) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.bDif - pMaterials[i].MatD3D.Diffuse.b) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.aDif - pMaterials[i].MatD3D.Diffuse.a) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.rSpec - pMaterials[i].MatD3D.Specular.r) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.gSpec - pMaterials[i].MatD3D.Specular.g) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.bSpec - pMaterials[i].MatD3D.Specular.b) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.rEm - pMaterials[i].MatD3D.Emissive.r) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.gEm - pMaterials[i].MatD3D.Emissive.g) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.bEm - pMaterials[i].MatD3D.Emissive.b) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.specPower - pMaterials[i].MatD3D.Power) > MATERIAL_FLOAT_TOLERANCE) continue;

					// materialy su zhodne
					char szBuf[MAX_PATH] = "materials\\models\\";
					strcat (szBuf, m_localData.Mesh7mtMaterials[j].sz7mtMaterialName);
					// 7mt material loading
					pMeshContainer->p7MTmaterials[i] = g_pMaterialManager->LoadMaterial (szBuf);
					break;
				}
			// #######################################################
			// naèítanie textúr
			if ((pMaterials[i].pTextureFilename != NULL) && (pMaterials[i].pTextureFilename[0] != 0))
			{
				char szTag[16];
				ezxml_t	pTextureTag = NULL;
				DWORD dwTextureIdx = 0xFFFFFFFF;

				pMeshContainer->pMaterials[i].pTextureFilename = new char [strlen (pMaterials[i].pTextureFilename) + 1];
				strcpy (pMeshContainer->pMaterials[i].pTextureFilename, pMaterials[i].pTextureFilename);

				if (FindTextureIndexTagByName (m_localData.xmlTextures, pMaterials[i].pTextureFilename, dwTextureIdx))
				{
					sprintf (szTag, "texture%u", dwTextureIdx);
					pTextureTag = g_pXML->Child (m_localData.xmlTextures, szTag);
				}

				for (j=0; j < pMeshContainer->dwNumCoords; j++)		// pre jednotlive koordinaty
				{
					char szBuf[MAX_PATH] = "textures\\models\\";
					if (pTextureTag == NULL)		// pouzit texturu z x-suboru
					{
						strcat (szBuf, pMaterials[i].pTextureFilename);
						pMeshContainer->pTextures[ i * pMeshContainer->dwNumCoords * pMeshContainer->dwNumPaintings + j*pMeshContainer->dwNumPaintings + m_localData.dwUseThisPainting] = g_TextureLoader.CreateTexture (szBuf);
					}
					else
					{
						// ziskanie nazvu textury z xml suboru
						ezxml_t	pCoordsTag, pPaintingTag;
						sprintf (szTag, "coords%u", j);
						if (pCoordsTag = g_pXML->Child (pTextureTag, szTag))
						{
							sprintf (szTag, "painting%u", m_localData.dwUseThisPainting);
							if (pPaintingTag = g_pXML->Child (pCoordsTag, szTag))
								if (pPaintingTag->txt)
								{
									strcat (szBuf, pPaintingTag->txt);
									pMeshContainer->pTextures[ i * pMeshContainer->dwNumCoords * pMeshContainer->dwNumPaintings + j*pMeshContainer->dwNumPaintings + m_localData.dwUseThisPainting] = g_TextureLoader.CreateTexture (szBuf);
								}
						}
					}
				}
			}
		}
	}
	else	// nastavenie defaultneho materialu - Diffuse = 0.8, Specular = Emissive = 0.0, Ambient = 1.0
	{
		pMeshContainer->pMaterials[0].pTextureFilename = NULL;
		pMeshContainer->pMaterials[0].MatD3D.Ambient = D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f);
		pMeshContainer->pMaterials[0].MatD3D.Diffuse = D3DXCOLOR (0.8f, 0.8f, 0.8f, 1.0f);
		pMeshContainer->pMaterials[0].MatD3D.Emissive = D3DXCOLOR (0.0f, 0.0f, 0.0f, 1.0f);
		pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Emissive;
		pMeshContainer->pMaterials[0].MatD3D.Power = 0.0f;
	}

/*
		// alokovanie pamäte pre materiály, textúry
		pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
		pMeshContainer->pTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
		if ((pMeshContainer->pMaterials == NULL) || (pMeshContainer->pTextures == NULL))
			{hr = E_OUTOFMEMORY; goto e_Exit;}
	
		//inicializácia textúr a materiálov
		memset(pMeshContainer->pTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
		memset(pMeshContainer->pMaterials, 0, sizeof(D3DXMATERIAL) * pMeshContainer->NumMaterials);
	
		//ak sú dostupné materiály, tak sa kopírujú
		if (NumMaterials > 0)
		{
			for (UINT iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
			{
				pMeshContainer->pMaterials[iMaterial].MatD3D = pMaterials[iMaterial].MatD3D;
				pMeshContainer->pMaterials[iMaterial].MatD3D.Ambient = D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f);
				D3DCOLORVALUE &colorSpec = pMeshContainer->pMaterials[iMaterial].MatD3D.Specular;
				if ((colorSpec.r == 0) && (colorSpec.g == 0) && (colorSpec.b == 0))
					pMeshContainer->pMaterials[iMaterial].MatD3D.Power = 0.0f;
				if (pMaterials[iMaterial].pTextureFilename != NULL)
				{
					wsprintf (szBuf, "textures\\models\\%s", pMaterials[iMaterial].pTextureFilename);
					pMeshContainer->pTextures[iMaterial] = g_TextureLoader.CreateTexture (szBuf);
				}
			}
		}
		else		// ak nie je definovany žiaden materiál, potom sa nastavý defaultný
		{
			//Diffuse = Specular = 0.8, Ambient = 1.0
			pMeshContainer->pMaterials[0].pTextureFilename = NULL;
			pMeshContainer->pMaterials[0].MatD3D.Ambient = D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f);
			pMeshContainer->pMaterials[0].MatD3D.Diffuse = D3DXCOLOR (0.8f, 0.8f, 0.8f, 1.0f);
			pMeshContainer->pMaterials[0].MatD3D.Emissive = D3DXCOLOR (0.0f, 0.0f, 0.0f, 1.0f);
			pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
			pMeshContainer->pMaterials[0].MatD3D.Power = 5.0f;
		}
*/
	

	//////////////////////////////////////////////////////////////////////////
	// nacitanie skin infa
	if (m_localData.bLoadSkinInfo && (pSkinInfo != NULL))
	{
		DWORD	dwNumBones;
		pMeshContainer->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();
		// alokovanie pamate pre skin-info matice
		dwNumBones = pSkinInfo->GetNumBones();
		if (dwNumBones > 0)
		{
			pMeshContainer->pBoneInverseMatrices = new D3DXMATRIX[dwNumBones];
			pMeshContainer->ppBoneTransformMatrices = new D3DXMATRIX*[dwNumBones];
			if ((pMeshContainer->pBoneInverseMatrices == NULL) || \
						(pMeshContainer->ppBoneTransformMatrices == NULL))
				{hr = E_OUTOFMEMORY; goto e_Exit;}
			// nacitanie bone-offset matic
			for (DWORD iBone=0; iBone < dwNumBones; iBone++)
				pMeshContainer->pBoneInverseMatrices[iBone] = *(pSkinInfo->GetBoneOffsetMatrix(iBone));

			memset (pMeshContainer->ppBoneTransformMatrices, 0, sizeof(LPD3DXMATRIX) * dwNumBones);
		}

		//////////////////////////////////////////////////////////////////////////
		// upravy pre shader skinning
		pMeshContainer->NumPaletteEntries = min(MAX_SKIN_BONES, pMeshContainer->pSkinInfo->GetNumBones());

		if (FAILED (pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh (
												pMesh,
												D3DXMESH_MANAGED | D3DXMESHOPT_VERTEXCACHE,
												pMeshContainer->NumPaletteEntries,
												pAdjacency,
												NULL, NULL, NULL,
												&pMeshContainer->NumInfl,
												&pMeshContainer->NumAttributeGroups,
												&pMeshContainer->pBoneCombinationBuf,
												&pTempMesh)))
			goto e_Exit;

		pMesh->Release ();
		pMesh = pTempMesh;
		pTempMesh = NULL;
	}

	//////////////////////////////////////////////////////////////////////////
	// optimalizacia
#ifdef MAKE_MESH_OPTIMIZATION
	if (pAdjacency)
	{
//		pMesh->GenerateAdjacency ()	 // ???
		pMesh->OptimizeInplace ( \
			D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, \
			pAdjacency, NULL, NULL, NULL);
	}
#endif

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

	*ppNewMeshContainer = pMeshContainer;
	return S_OK;

e_Exit:
	pMesh->Release ();
	SAFE_DELETE (pMeshContainer)
	return hr;
}