Jump to content
  • Advertisement
Sign in to follow this  
kslam

skeletal animation problem

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

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

Recommended Posts

Hi, I got a problem, when I load a charecter model by using directx 9, the charecter model not load in the world origin, I have to zoom out the camera to : D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0.0f, 0.0f, -5000.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); D3DXMatrixPerspectiveFovLH(&proj, 0.2f, 1.33333f, 0.01f, 100000.0f); then I can see the model but I can't see the texture, but I draw this model in local origin at 3d animation software. I also try to load the Blender's sample model, but I totally can not see the model. I can see the model if I opened the .x file in Directx viewer. The original source code which I using is from the book, The author draw the model by using 3Ds Max, and can be loaded properly. Is it the problem from the Model's .x(3d software) file or from the source code ? Some of the source code are as below :
-----------------------------------------------------------------------
//Set camera
	D3DXMATRIX view, proj, world, r, s;

	D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0.0f, 0.0f, -5000.0f), 	&D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
	D3DXMatrixPerspectiveFovLH(&proj, 0.2f, 1.33333f, 0.01f, 	100000.0f);
	D3DXMatrixRotationYawPitchRoll(&r, m_angle, 0.0f, 0.0f);
	D3DXMatrixScaling(&s, 1.0f, 1.0f, 1.0f);
	world = s * r;
	

	m_pDevice->SetTransform(D3DTS_VIEW, &view);
	m_pDevice->SetTransform(D3DTS_PROJECTION, &proj);
	m_pDevice->SetTransform(D3DTS_WORLD, &world);

m_skinnedMesh.SetPose(world, NULL, m_unitTime);

-----------------------------------------------------------------------
void SKINNEDMESH::SetPose(D3DXMATRIX world, ID3DXAnimationController* animControl, float time)
{
	if(animControl != NULL)
		animControl->AdvanceTime(time, NULL);
	else m_pAnimControl->AdvanceTime(time, NULL);

	UpdateMatrices((BONE*)m_pRootBone, &world);

-----------------------------------------------------------------------void SKINNEDMESH::Render(BONE *bone)
{
	if(bone == NULL)bone = (BONE*)m_pRootBone;

	//If there is a mesh to render...
	if(bone->pMeshContainer != NULL)
	{
		BONEMESH *boneMesh = (BONEMESH*)bone->pMeshContainer;

		if (boneMesh->pSkinInfo != NULL)
		{		
			// set up bone transforms
			int numBones = boneMesh->pSkinInfo->GetNumBones();
			for(int i=0;i < numBones;i++)
				D3DXMatrixMultiply(&boneMesh->currentBoneMatrices,
								   &boneMesh->boneOffsetMatrices, 
								   boneMesh->boneMatrixPtrs);

			//Update the skinned mesh
			BYTE *src = NULL, *dest = NULL;
			boneMesh->OriginalMesh->LockVertexBuffer(D3DLOCK_READONLY, (VOID**)&src);
			boneMesh->MeshData.pMesh->LockVertexBuffer(0, (VOID**)&dest);

			boneMesh->pSkinInfo->UpdateSkinnedMesh(boneMesh->currentBoneMatrices, NULL, src, dest);

			boneMesh->MeshData.pMesh->UnlockVertexBuffer();
			boneMesh->OriginalMesh->UnlockVertexBuffer();

			//Render the mesh
			for(int i=0;i < boneMesh->NumAttributeGroups;i++)
			{
				int mtrlIndex = boneMesh->attributeTable.AttribId;
				m_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));
				//m_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);
				boneMesh->MeshData.pMesh->DrawSubset(mtrlIndex);
			}
		}
	}

	if(bone->pFrameSibling != NULL)Render((BONE*)bone->pFrameSibling);
	if(bone->pFrameFirstChild != NULL)Render((BONE*)bone->pFrameFirstChild);

-----------------------------------------------------------------------


Thank you Kslam

Share this post


Link to post
Share on other sites
Advertisement
If the mesh can be seen properly in the mesh viewer, then it is extremely likely that the problem is in your code.

Does your code load and display other .x files properly, like tiny.x, etc?

With regard to the texture, the code you posted has the SetTexture() line commented out.

Also, do you successfully load the texture when the .x file is loaded? If so, how do you know?

Share this post


Link to post
Share on other sites
The model create using 3ds max can load successfully( position and texture).
The tiny.x can be loaded but not in origin coordinate, I have to zoom out in order to see the model and can not see the texture. Do u know how to set the model to origin position in Directx 9.

The texture code as below :


HRESULT BONE_HIERARCHY::CreateMeshContainer(LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
//Create new Bone Mesh
BONEMESH *boneMesh = new BONEMESH;
memset(boneMesh, 0, sizeof(BONEMESH));

//Get mesh data
boneMesh->OriginalMesh = pMeshData->pMesh;
boneMesh->MeshData.pMesh = pMeshData->pMesh;
boneMesh->MeshData.Type = pMeshData->Type;
pMeshData->pMesh->AddRef(); //Add Reference so that the mesh isnt deallocated
IDirect3DDevice9 *m_pDevice = NULL;
pMeshData->pMesh->GetDevice(&m_pDevice); //Get Device ptr from mesh

//Copy materials and load textures (just like with a static mesh)
for(int i=0;i<NumMaterials;i++)
{
D3DXMATERIAL mtrl;
memcpy(&mtrl, &pMaterials, sizeof(D3DXMATERIAL));
boneMesh->materials.push_back(mtrl.MatD3D);

if(mtrl.pTextureFilename)
{
char textureFname[200];
strcpy(textureFname, "units/");
strcat(textureFname, mtrl.pTextureFilename);

//Load texture
IDirect3DTexture9* newTexture = NULL;
D3DXCreateTextureFromFile(m_pDevice, textureFname, &newTexture);
boneMesh->textures.push_back(newTexture);
}
}

if(pSkinInfo != NULL)
{
//Get Skin Info
boneMesh->pSkinInfo = pSkinInfo;
pSkinInfo->AddRef(); //Add reference so that the SkinInfo isnt deallocated

//Clone mesh and store in boneMesh->MeshData.pMesh
pMeshData->pMesh->CloneMeshFVF(D3DXMESH_MANAGED, pMeshData->pMesh->GetFVF(),
m_pDevice, &boneMesh->MeshData.pMesh);

//Get Attribute Table
boneMesh->MeshData.pMesh->GetAttributeTable(NULL, &boneMesh->NumAttributeGroups);
boneMesh->attributeTable = new D3DXATTRIBUTERANGE[boneMesh->NumAttributeGroups];
boneMesh->MeshData.pMesh->GetAttributeTable(boneMesh->attributeTable, NULL);

//Create bone offset and current matrices
int NumBones = pSkinInfo->GetNumBones();
boneMesh->boneOffsetMatrices = new D3DXMATRIX[NumBones];
boneMesh->currentBoneMatrices = new D3DXMATRIX[NumBones];

//Get bone offset matrices
for(int i=0;i < NumBones;i++)
boneMesh->boneOffsetMatrices = *(boneMesh->pSkinInfo->GetBoneOffsetMatrix(i));
}

//Set ppNewMeshContainer to the newly created boneMesh container
*ppNewMeshContainer = boneMesh;

return S_OK;
}



Share this post


Link to post
Share on other sites
Something I notice, you have a very small fov in your perspective matrix. Your view is in an extreme "zoom" mode. You're not zooming out, you're zooming in, which makes the model appear much larger than a more normal perspective. Try setting the fov in your perspective matrix call to something a little more "normal," such as D3DX_PI/4.0f.

Share this post


Link to post
Share on other sites
I can see the model, but I can't see the texture.

The settexture code as below :


void SKINNEDMESH::Render(BONE *bone)
{
if(bone == NULL)bone = (BONE*)m_pRootBone;

//If there is a mesh to render...
if(bone->pMeshContainer != NULL)
{
BONEMESH *boneMesh = (BONEMESH*)bone->pMeshContainer;

if (boneMesh->pSkinInfo != NULL)
{
// set up bone transforms
int numBones = boneMesh->pSkinInfo->GetNumBones();
for(int i=0;i < numBones;i++)
D3DXMatrixMultiply(&boneMesh->currentBoneMatrices,
&boneMesh->boneOffsetMatrices,
boneMesh->boneMatrixPtrs);

//Update the skinned mesh
BYTE *src = NULL, *dest = NULL;
boneMesh->OriginalMesh->LockVertexBuffer(D3DLOCK_READONLY, (VOID**)&src);
boneMesh->MeshData.pMesh->LockVertexBuffer(0, (VOID**)&dest);

boneMesh->pSkinInfo->UpdateSkinnedMesh(boneMesh->currentBoneMatrices, NULL, src, dest);

boneMesh->MeshData.pMesh->UnlockVertexBuffer();
boneMesh->OriginalMesh->UnlockVertexBuffer();

//Render the mesh
for(int i=0;i < boneMesh->NumAttributeGroups;i++)
{
int mtrlIndex = boneMesh->attributeTable.AttribId;
m_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));
m_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);
boneMesh->MeshData.pMesh->DrawSubset(mtrlIndex);
}
}
}

if(bone->pFrameSibling != NULL)Render((BONE*)bone->pFrameSibling);
if(bone->pFrameFirstChild != NULL)Render((BONE*)bone->pFrameFirstChild);
}

Share this post


Link to post
Share on other sites
this is main cpp file.


#include <windows.h>
#include <d3dx9.h>
#include "debug.h"
#include "skinnedmesh.h"
#include "shader.h"

class APPLICATION
{
public:

APPLICATION();
HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
HRESULT Update(float deltaTime);
HRESULT Render();
HRESULT Cleanup();
HRESULT Quit();
DWORD FtoDword(float f){return *((DWORD*)&f);}

private:
IDirect3DDevice9* m_pDevice;
SKINNEDMESH m_skinnedMesh;

DWORD m_time, m_pressTime;
int m_fps, m_lastFps, m_col;
float m_angle, m_unitTime, m_colFade;
D3DXVECTOR4 m_activeCol, m_lastCol, m_currentCol;
HWND m_mainWindow;
ID3DXFont *m_pFont;

//Shaders
SHADER m_unitVS, m_unitPS;
D3DXHANDLE m_worldHandle, m_viewProjHandle, m_sunHandle, m_teamColHandle;
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
APPLICATION app;

if(FAILED(app.Init(hInstance, 800, 600, true)))return 0;

MSG msg;
memset(&msg, 0, sizeof(MSG));
int startTime = timeGetTime();

while(msg.message != WM_QUIT)
{
if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
else
{
int t = timeGetTime();
float deltaTime = (t - startTime)*0.001f;

app.Update(deltaTime);
app.Render();

startTime = t;
}
}

app.Cleanup();

return msg.wParam;
}

APPLICATION::APPLICATION()
{
m_pDevice = NULL;
m_mainWindow = 0;
srand(GetTickCount());
m_fps = m_lastFps = m_col = 0;
m_angle = m_unitTime = m_colFade = 0.0f;
m_time = m_pressTime = GetTickCount();
m_currentCol = m_lastCol = m_activeCol = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);
}

HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
{
debug.Print("Application initiated");

//Create Window Class
WNDCLASS wc;
memset(&wc, 0, sizeof(WNDCLASS));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)::DefWindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = "D3DWND";

//Register Class and Create new Window
RegisterClass(&wc);
m_mainWindow = CreateWindow("D3DWND", "Example 8.1: Team Color", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0);
SetCursor(NULL);
ShowWindow(m_mainWindow, SW_SHOW);
UpdateWindow(m_mainWindow);

//Create IDirect3D9 Interface
IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

if(d3d9 == NULL)
{
debug.Print("Direct3DCreate9() - FAILED");
return E_FAIL;
}

//Check that the Device supports what we need from it
D3DCAPS9 caps;
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);

//Hardware Vertex Processing or not?
int vp = 0;
if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

//Check vertex & pixelshader versions
if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
{
debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
}

//Set D3DPRESENT_PARAMETERS
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = m_mainWindow;
d3dpp.Windowed = windowed;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

//Create the IDirect3DDevice9
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
vp, &d3dpp, &m_pDevice)))
{
debug.Print("Failed to create IDirect3DDevice9");
return E_FAIL;
}

//Release IDirect3D9 interface
d3d9->Release();

D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);

//m_skinnedMesh.Load("units/magician.x", m_pDevice);
m_skinnedMesh.Load("units/tiny1.x", m_pDevice);
m_skinnedMesh.SetAnimation("Run");

//Set sampler state
for(int i=0;i<4;i++)
{
m_pDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
m_pDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
m_pDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
}

//Setup shaders
m_unitVS.Init(m_pDevice, "shaders/lighting.vs", VERTEX_SHADER);
m_worldHandle = m_unitVS.GetConstant("matW");
m_viewProjHandle = m_unitVS.GetConstant("matVP");
m_sunHandle = m_unitVS.GetConstant("DirToSun");

m_unitPS.Init(m_pDevice, "shaders/teamCol.ps", PIXEL_SHADER);
m_teamColHandle = m_unitPS.GetConstant("tmCol");

return S_OK;
}

HRESULT APPLICATION::Update(float deltaTime)
{
//Rotate unit
m_angle += deltaTime * 0.2f;
m_unitTime = deltaTime * 0.5f;
if(m_angle > D3DX_PI * 2.0f)m_angle -= D3DX_PI * 2.0f;

//change color
m_colFade += deltaTime * 0.4f;
if(m_colFade > 1.0f)m_colFade = 1.0f;
m_currentCol = m_lastCol * (1.0f - m_colFade) + m_activeCol * m_colFade;

if(KEYDOWN(VK_SPACE) && GetTickCount() - m_pressTime > 300)
{
m_pressTime = GetTickCount();
m_col++;
if(m_col > 11)m_col = 0;

D3DXVECTOR4 tmColors[] = {D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f),
D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f),
D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f),
D3DXVECTOR4(1.0f, 1.0f, 0.0f, 1.0f),
D3DXVECTOR4(1.0f, 0.0f, 1.0f, 1.0f),
D3DXVECTOR4(0.0f, 1.0f, 1.0f, 1.0f),
D3DXVECTOR4(0.5f, 0.25f, 0.0f, 1.0f),
D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f),
D3DXVECTOR4(1.0f, 0.5f, 0.0f, 1.0f),
D3DXVECTOR4(0.0f, 0.25f, 0.0f, 1.0f),
D3DXVECTOR4(0.25f, 0.0f, 0.0f, 1.0f),
D3DXVECTOR4(0.0f, 0.0f, 0.25f, 1.0f)};
m_lastCol = m_currentCol;
m_activeCol = tmColors[m_col];
m_colFade = 0.0f;
}
else if(KEYDOWN(VK_ESCAPE))
{
Quit();
}

return S_OK;
}

HRESULT APPLICATION::Render()
{
// Clear the viewport
m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);

D3DVIEWPORT9 v,v2;
m_pDevice->GetViewport(&v);
v2 = v;

v.Y = 200;
v.Height = 200;
m_pDevice->SetViewport(&v);
m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DXCOLOR(m_currentCol.x, m_currentCol.y, m_currentCol.z, 1.0f), 1.0f, 0);
m_pDevice->SetViewport(&v2);

//FPS Calculation
m_fps++;
if(GetTickCount() - m_time > 1000)
{
m_lastFps = m_fps;
m_fps = 0;
m_time = GetTickCount();
}

//Set camera
D3DXMATRIX view, proj, world, r, s;
D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0.0f, 1000.0f, -5000.0f), &D3DXVECTOR3(0.0f, 4.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
D3DXMatrixPerspectiveFovLH(&proj, 0.2f, 1.33333f, 0.01f, 10000.0f);
D3DXMatrixRotationYawPitchRoll(&r, m_angle, 0.0f, 0.0f);
D3DXMatrixScaling(&s, 1.2f, 1.2f, 1.2f);
world = s * r;

m_pDevice->SetTransform(D3DTS_VIEW, &view);
m_pDevice->SetTransform(D3DTS_PROJECTION, &proj);
m_pDevice->SetTransform(D3DTS_WORLD, &world);

// Begin the scene
if(SUCCEEDED(m_pDevice->BeginScene()))
{
m_unitVS.SetMatrix(m_worldHandle, world);
m_unitVS.SetMatrix(m_viewProjHandle, view * proj);

D3DXVECTOR3 sun;
D3DXVec3Normalize(&sun, &D3DXVECTOR3(0.5f, 1.0f, -0.5));
m_unitVS.SetVector3(m_sunHandle, sun);

m_unitPS.SetVector4(m_teamColHandle, m_currentCol);

m_unitVS.Begin();
m_unitPS.Begin();
m_skinnedMesh.SetPose(world, NULL, m_unitTime);
m_skinnedMesh.Render(NULL);
m_unitPS.End();
m_unitVS.End();

RECT r[] = {{10, 10, 0, 0}, {720, 10, 0, 0}};
m_pFont->DrawText(NULL, "Space: Change Team Color", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);

//FPS
char number[50];
std::string text = "FPS: ";
text += _itoa(m_lastFps, number, 10);
m_pFont->DrawText(NULL, text.c_str(), -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);

// End the scene.
m_pDevice->EndScene();
m_pDevice->Present(0, 0, 0, 0);
}

return S_OK;
}

HRESULT APPLICATION::Cleanup()
{
try
{
m_pFont->Release();
m_pDevice->Release();

debug.Print("Application terminated");
}
catch(...){}

return S_OK;
}

HRESULT APPLICATION::Quit()
{
::DestroyWindow(m_mainWindow);
::PostQuitMessage(0);
return S_OK;
}




This is skinmesh cpp file.



#include "skinnedMesh.h"

class BONE_HIERARCHY: public ID3DXAllocateHierarchy
{
public:
STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame);
STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR Name, CONST D3DXMESHDATA * pMeshData, CONST D3DXMATERIAL * pMaterials, CONST D3DXEFFECTINSTANCE * pEffectInstances, DWORD NumMaterials, CONST DWORD * pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER * ppNewMeshContainer);
STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);
STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);
};

HRESULT BONE_HIERARCHY::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame)
{
BONE *newBone = new BONE;
memset(newBone, 0, sizeof(BONE));

//Copy name
if(Name != NULL)
{
newBone->Name = new char[strlen(Name)+1];
strcpy(newBone->Name, Name);
}

//Set the transformation matrices
D3DXMatrixIdentity(&newBone->TransformationMatrix);
D3DXMatrixIdentity(&newBone->CombinedTransformationMatrix);

//Return the new bone...
*ppNewFrame = (D3DXFRAME*)newBone;

return S_OK;
}

HRESULT BONE_HIERARCHY::CreateMeshContainer(LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
//Create new Bone Mesh
BONEMESH *boneMesh = new BONEMESH;
memset(boneMesh, 0, sizeof(BONEMESH));

//Get mesh data
boneMesh->OriginalMesh = pMeshData->pMesh;
boneMesh->MeshData.pMesh = pMeshData->pMesh;
boneMesh->MeshData.Type = pMeshData->Type;
pMeshData->pMesh->AddRef(); //Add Reference so that the mesh isnt deallocated
IDirect3DDevice9 *m_pDevice = NULL;
pMeshData->pMesh->GetDevice(&m_pDevice); //Get Device ptr from mesh

//Copy materials and load textures (just like with a static mesh)
for(int i=0;i<NumMaterials;i++)
{
D3DXMATERIAL mtrl;
memcpy(&mtrl, &pMaterials, sizeof(D3DXMATERIAL));
boneMesh->materials.push_back(mtrl.MatD3D);

if(mtrl.pTextureFilename)
{
char textureFname[200];
strcpy(textureFname, "units/");
strcat(textureFname, mtrl.pTextureFilename);

//Load texture
IDirect3DTexture9* newTexture = NULL;
D3DXCreateTextureFromFile(m_pDevice, textureFname, &newTexture);
boneMesh->textures.push_back(newTexture);
}
}

if(pSkinInfo != NULL)
{
//Get Skin Info
boneMesh->pSkinInfo = pSkinInfo;
pSkinInfo->AddRef(); //Add reference so that the SkinInfo isnt deallocated

//Clone mesh and store in boneMesh->MeshData.pMesh
pMeshData->pMesh->CloneMeshFVF(D3DXMESH_MANAGED, pMeshData->pMesh->GetFVF(),
m_pDevice, &boneMesh->MeshData.pMesh);

//Get Attribute Table
boneMesh->MeshData.pMesh->GetAttributeTable(NULL, &boneMesh->NumAttributeGroups);
boneMesh->attributeTable = new D3DXATTRIBUTERANGE[boneMesh->NumAttributeGroups];
boneMesh->MeshData.pMesh->GetAttributeTable(boneMesh->attributeTable, NULL);

//Create bone offset and current matrices
int NumBones = pSkinInfo->GetNumBones();
boneMesh->boneOffsetMatrices = new D3DXMATRIX[NumBones];
boneMesh->currentBoneMatrices = new D3DXMATRIX[NumBones];

//Get bone offset matrices
for(int i=0;i < NumBones;i++)
boneMesh->boneOffsetMatrices = *(boneMesh->pSkinInfo->GetBoneOffsetMatrix(i));
}

//Set ppNewMeshContainer to the newly created boneMesh container
*ppNewMeshContainer = boneMesh;

return S_OK;
}

HRESULT BONE_HIERARCHY::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
if(pFrameToFree)
{
//Free name
if(pFrameToFree->Name != NULL)
delete [] pFrameToFree->Name;

//Free bone
delete pFrameToFree;
}
pFrameToFree = NULL;

return S_OK;
}

HRESULT BONE_HIERARCHY::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
BONEMESH *boneMesh = (BONEMESH*)pMeshContainerBase;

//Release textures
for(int i=0;i < boneMesh->textures.size();i++)
if(boneMesh->textures != NULL)
boneMesh->textures->Release();

//Release mesh data
if(boneMesh->MeshData.pMesh)boneMesh->MeshData.pMesh->Release();
if(boneMesh->pSkinInfo)boneMesh->pSkinInfo->Release();
if(boneMesh->OriginalMesh)boneMesh->OriginalMesh->Release();
delete boneMesh;

return S_OK;
}


//////////////////////////////////////////////////////////////////////////////////////////////////
// SKINNED MESH //
//////////////////////////////////////////////////////////////////////////////////////////////////

struct VERTEX{
VERTEX();
VERTEX(D3DXVECTOR3 pos, D3DCOLOR col){position = pos; color = col;}
D3DXVECTOR3 position;
D3DCOLOR color;
static const DWORD FVF;
};

const DWORD VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;

SKINNEDMESH::SKINNEDMESH()
{
m_pRootBone = NULL;
m_pAnimControl = NULL;
}

SKINNEDMESH::~SKINNEDMESH()
{
BONE_HIERARCHY boneHierarchy;
boneHierarchy.DestroyFrame(m_pRootBone);
if(m_pAnimControl)m_pAnimControl->Release();
}

void SKINNEDMESH::Load(char fileName[], IDirect3DDevice9 *Dev)
{
m_pDevice = Dev;
BONE_HIERARCHY boneHierarchy;

D3DXLoadMeshHierarchyFromX(fileName, D3DXMESH_MANAGED,
m_pDevice, &boneHierarchy,
NULL, &m_pRootBone, &m_pAnimControl);

SetupBoneMatrixPointers((BONE*)m_pRootBone);
}

void SKINNEDMESH::UpdateMatrices(BONE* bone, D3DXMATRIX *parentMatrix)
{
if(bone == NULL)return;

D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,
&bone->TransformationMatrix,
parentMatrix);

if(bone->pFrameSibling)UpdateMatrices((BONE*)bone->pFrameSibling, parentMatrix);
if(bone->pFrameFirstChild)UpdateMatrices((BONE*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);
}

void SKINNEDMESH::Render(BONE *bone)
{
if(bone == NULL)bone = (BONE*)m_pRootBone;

//If there is a mesh to render...
if(bone->pMeshContainer != NULL)
{
BONEMESH *boneMesh = (BONEMESH*)bone->pMeshContainer;

if (boneMesh->pSkinInfo != NULL)
{
// set up bone transforms
int numBones = boneMesh->pSkinInfo->GetNumBones();
for(int i=0;i < numBones;i++)
D3DXMatrixMultiply(&boneMesh->currentBoneMatrices,
&boneMesh->boneOffsetMatrices,
boneMesh->boneMatrixPtrs);

//Update the skinned mesh
BYTE *src = NULL, *dest = NULL;
boneMesh->OriginalMesh->LockVertexBuffer(D3DLOCK_READONLY, (VOID**)&src);
boneMesh->MeshData.pMesh->LockVertexBuffer(0, (VOID**)&dest);

boneMesh->pSkinInfo->UpdateSkinnedMesh(boneMesh->currentBoneMatrices, NULL, src, dest);

boneMesh->MeshData.pMesh->UnlockVertexBuffer();
boneMesh->OriginalMesh->UnlockVertexBuffer();

//Render the mesh
for(int i=0;i < boneMesh->NumAttributeGroups;i++)
{
int mtrlIndex = boneMesh->attributeTable.AttribId;
m_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));
m_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);
boneMesh->MeshData.pMesh->DrawSubset(mtrlIndex);
}
}
}

if(bone->pFrameSibling != NULL)Render((BONE*)bone->pFrameSibling);
if(bone->pFrameFirstChild != NULL)Render((BONE*)bone->pFrameFirstChild);
}

ID3DXMesh* SKINNEDMESH::GetCurrentMesh(BONE *bone)
{
if(bone == NULL)
bone = (BONE*)m_pRootBone;

if(bone->pMeshContainer != NULL)
return bone->pMeshContainer->MeshData.pMesh;

ID3DXMesh* mesh = NULL;

if(bone->pFrameSibling != NULL)mesh = GetCurrentMesh((BONE*)bone->pFrameSibling);
if(mesh == NULL && bone->pFrameFirstChild != NULL)mesh = GetCurrentMesh((BONE*)bone->pFrameFirstChild);

return mesh;
}

void SKINNEDMESH::SetupBoneMatrixPointers(BONE *bone)
{
if(bone->pMeshContainer != NULL)
{
BONEMESH *boneMesh = (BONEMESH*)bone->pMeshContainer;

if(boneMesh->pSkinInfo != NULL)
{
int NumBones = boneMesh->pSkinInfo->GetNumBones();
boneMesh->boneMatrixPtrs = new D3DXMATRIX*[NumBones];

for(int i=0;i < NumBones;i++)
{
BONE *b = (BONE*)D3DXFrameFind(m_pRootBone, boneMesh->pSkinInfo->GetBoneName(i));
if(b != NULL)boneMesh->boneMatrixPtrs = &b->CombinedTransformationMatrix;
else boneMesh->boneMatrixPtrs = NULL;
}
}
}

if(bone->pFrameSibling != NULL)SetupBoneMatrixPointers((BONE*)bone->pFrameSibling);
if(bone->pFrameFirstChild != NULL)SetupBoneMatrixPointers((BONE*)bone->pFrameFirstChild);
}

BONE* SKINNEDMESH::FindBone(char name[])
{
return (BONE*) D3DXFrameFind(m_pRootBone, name);
}

void SKINNEDMESH::SetPose(D3DXMATRIX world, ID3DXAnimationController* animControl, float time)
{
if(animControl != NULL)
animControl->AdvanceTime(time, NULL);
else m_pAnimControl->AdvanceTime(time, NULL);

UpdateMatrices((BONE*)m_pRootBone, &world);
}

int SKINNEDMESH::SetAnimation(char name[])
{
ID3DXAnimationSet *anim = NULL;

for(int i=0;i<m_pAnimControl->GetMaxNumAnimationSets();i++)
{
anim = NULL;
m_pAnimControl->GetAnimationSet(i, &anim);

if(anim != NULL)
{
if(strcmp(name, anim->GetName()) == 0)
{
m_pAnimControl->SetTrackAnimationSet(0, anim);
anim->Release();
return i;
}
anim->Release();
}
}

return -1;
}

void SKINNEDMESH::SetAnimation(int index)
{
ID3DXAnimationSet *anim = NULL;
m_pAnimControl->GetAnimationSet(index, &anim);
if(anim != NULL)m_pAnimControl->SetTrackAnimationSet(0, anim);
anim->Release();
}

float SKINNEDMESH::GetAnimationDuration(int index)
{
float duration = 0.0f;
ID3DXAnimationSet *anim = NULL;
m_pAnimControl->GetAnimationSet(index, &anim);
if(anim != NULL)duration = anim->GetPeriod();
anim->Release();

return duration;
}

std::vector<std::string> SKINNEDMESH::GetAnimations()
{
ID3DXAnimationSet *anim = NULL;
std::vector<std::string> animations;

for(int i=0;i<m_pAnimControl->GetMaxNumAnimationSets();i++)
{
anim = NULL;
m_pAnimControl->GetAnimationSet(i, &anim);

if(anim != NULL)
{
animations.push_back(anim->GetName());
anim->Release();
}
}

return animations;
}







this is vs file.





uniform extern float4x4 matW;
uniform extern float4x4 matVP;
uniform extern float3 DirToSun;

struct VS_INPUT
{
float4 position : POSITION0;
float3 normal : NORMAL0;
float2 uv : TEXCOORD0;
};

struct VS_OUTPUT
{
float4 position : POSITION0;
float2 uv : TEXCOORD0;
float shade : TEXCOORD1;
};

VS_OUTPUT Main(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;

// Project position homogeneous clip space.
float4 temp = mul(input.position, matW);
output.position = mul(temp, matVP);

// Do basic diffuse lighting calculating to compute vertex shade.
output.shade = max(0.0f, dot(normalize(input.normal), DirToSun));
output.shade = 0.2f + output.shade * 0.8f;

output.uv = input.uv;

return output;
}







this is ps file.



sampler unitTexture;
uniform extern float4 tmCol;

float4 Main(float2 UV : TEXCOORD0, float shade : TEXCOORD1) : COLOR
{
float4 c0 = tex2D(unitTexture, UV);
float Inv = 1.0f - c0.a;

//Weigh pixel and team color using the alpha channel
float4 c1 = float4(c0.rgb * Inv + tmCol.rgb * c0.a, 1.0f);

//return Shaded pixel
return c1 * shade;
}

Share this post


Link to post
Share on other sites
A previous question:
Quote:
do you successfully load the texture when the .x file is loaded? If so, how do you know?


kslam: you do not test any return codes from any of your calls.
D3DXCreateTextureFromFile(m_pDevice, textureFname, &newTexture);

How do you know if the texture was loaded correctly?

If you don't test any return codes, then you may have many errors.

Share this post


Link to post
Share on other sites
I validate the code below, the program run without error but can't see texture. (The model is red color without texture)
If I disable the VS and PS code, the model become black color.
I think this code is custom made for the 3ds Max model.

HRESULT hResult = D3DXCreateTextureFromFile(m_pDevice, textureFname, &newTexture);
if (FAILED(hResult))
{
strcpy(emsg, "Error creating texture.");
PostQuitMessage(WM_QUIT);
break;
}

-------------------------------------------------------------

HRESULT hResult = m_pDevice->SetTexture(0, boneMesh- textures[mtrlIndex]);
if (FAILED(hResult))
{
strcpy(emsg, "Error settexture.");
PostQuitMessage(WM_QUIT);
break;
}

Share this post


Link to post
Share on other sites
In this loop:

for(int i=0;i < boneMesh->NumAttributeGroups;i++)
{
int mtrlIndex = boneMesh->attributeTable.AttribId;
m_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));
m_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);
boneMesh->MeshData.pMesh->DrawSubset(mtrlIndex);
}

you're drawing the subset with the mtrlIndex instead of the attribute group number.

That may not be the problem but you should be using:

boneMesh->MeshData.pMesh->DrawSubset(i);

Share this post


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

  • Advertisement
×

Important Information

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

We are the game development community.

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

Sign me up!