my .x file

Started by
0 comments, last by moeron 18 years, 11 months ago

///////////////////////////////////////////////////////////////////////////////
// 
// File: mlSkinnedmesh.cpp
// 
// Author: Frank Luna (C) All Rights Reserved
//
// System: Athlon 1800+ XP, 512 DDR, Radeon 9500 Pro, Windows XP, MSVC++ 7.0 
//
// Desc: Contains the implementation of SkinnedMesh.
// 
///////////////////////////////////////////////////////////////////////////////

#include "mlSkinnedmesh.h"
#include <iostream>
#include <cassert>

using namespace dx_err;

SkinnedMesh::SkinnedMesh()
:_device(0), _skinnedMesh(0), _tex(0), _effect(0), _root(0), 
_maxVertInfluences(0), _numBones(0), _skinInfo(0), _animCtrl(0), _hTech(0), 
_hWorldViewProj(0), _hFinalTransforms(0), _hTex(0)
{
}

SkinnedMesh::~SkinnedMesh()
{
	deleteDeviceObjects();
}

void SkinnedMesh::initDeviceObjects(IDirect3DDevice9* device,
									const std::string& inputFilename)
{
	_device = device;

	AllocMeshHierarchy allocMeshHierarchy;
	THROW_DXERR(D3DXLoadMeshHierarchyFromX(inputFilename.c_str(), D3DXMESH_MANAGED,
		_device, &allocMeshHierarchy, 0, /* ignore user data */ 
		
&_root,	&_animCtrl))


	D3DXFRAME* f = findNodeWithMesh(_root);
	if( f == 0 ) THROW_DXERR(E_FAIL);
	D3DXMESHCONTAINER* meshContainer = f->pMeshContainer;
	_skinInfo = meshContainer->pSkinInfo;
	_skinInfo->AddRef();


	_numBones = meshContainer->pSkinInfo->GetNumBones();
	_finalTransforms.resize(_numBones);
	_combinedTransforms.resize(_numBones, 0);
	

	buildSkinnedMesh(meshContainer->MeshData.pMesh);
	buildCombinedTransforms();
	buildEffect();
	buildMaterials(meshContainer);
}

void SkinnedMesh::restoreDeviceObjects()
{
	// Call after a reset to restore the effect.
    if ( _effect )
        THROW_DXERR( _effect->OnResetDevice() )
}

void SkinnedMesh::deleteDeviceObjects()
{
	if( _root )
	{
		AllocMeshHierarchy allocMeshHierarchy;
		THROW_DXERR( D3DXFrameDestroy(_root, &allocMeshHierarchy) )
		_root = 0;
	}

	ReleaseCOM(_skinnedMesh);
	ReleaseCOM(_skinInfo);
	ReleaseCOM(_animCtrl);
	ReleaseCOM(_effect);
}

void SkinnedMesh::invalidateDeviceObjects()
{
	// Call before a reset device.
    if ( _effect )
        THROW_DXERR( _effect->OnLostDevice() );
}

HRESULT SkinnedMesh::confirmDevice(D3DCAPS9* pCaps)
{
	////////////////////////////////////////////////////////////////////////
	// User needs a graphics device that supports vertex shader version 2.0.

	if( pCaps->VertexShaderVersion < D3DVS_VERSION(2, 0) )
		return E_FAIL;

	return D3D_OK;
}

//
//
//
//
//
//äÖȾ×î¼òµ¥,Ò»¸ö¸³Öµ,´«µÝ
//¾ÍÊǸöº¯Êýµ÷ÓÃ
//
//³ÌÐò¾ÍÊÇ×·Ñ°µÄäÖȾ½Ó¿Ú
//
//
//
//
//
//
//
//½¨Á¢-ºÍ×°Ôغ¯Êý
//
//
//¶¯»­Ò²ÊǹؼüÖ¡Êý¾Ý½¨Á¢ÐÂÊý¾Ý
//
//
//È»ºóÊÇÐÞ¸ÄÊý¾Ý,ÐÞÕý
//
//
//ÌÞ³ö
//
//
//
//ÓÎÏ·µÄÕæÕý¹ý³Ì,ÄÚÄ»
//
//
//
//
//ÌÞ³ö-Åöײ/ÎïÀí
//
//
//±Ø¶¨ÏÈÌÞ³ö,È»ºó
void SkinnedMesh::frameMove(float deltaTime, D3DXMATRIX& worldViewProj)
{
	//////////////////////////////////////////////////////////////////////
	// Animate the mesh.  The AnimationController has pointers to the 
	// hierarchy frame transform matrices.  The AnimationController updates
	// these matrices to reflect the given pose at the current time by 
	// interpolating between animation keyframes.

	_animCtrl->AdvanceTime(deltaTime, 0);

	
	//////////////////////////////////////////////////////////////////
	// Now that the frames are updated to the current pose, recurse
	// down the tree and generate a frame's combined-transform.

	D3DXMATRIX identity;
	D3DXMatrixIdentity(&identity);
	combineTransforms(static_cast<FrameEx*>(_root), identity);


	////////////////////////////////////////////////////////////
	// Add the offset-transform, note that this premultiplies 
	// the combined-transform.

	D3DXMATRIX offsetTemp, combinedTemp;
	for(UINT i = 0; i < _numBones; ++i)
	{
		offsetTemp   = *_skinInfo->GetBoneOffsetMatrix(i);
		combinedTemp = *_combinedTransforms;
		_finalTransforms = offsetTemp * combinedTemp;
	}


	///////////////////////////////////////////////////////////////
	// Finally, set the final-transform matrix array to the effect.

	_effect->SetMatrix(_hWorldViewProj, &worldViewProj);
	_effect->SetMatrixArray(_hFinalTransforms, 
		&_finalTransforms[0], _finalTransforms.size());
}

void SkinnedMesh::render()
{
	_effect->SetTechnique(_hTech);
	UINT numPasses = 0;
	_effect->Begin(&numPasses, 0);

	for(UINT i = 0; i < numPasses; ++i)
	{
		_effect->BeginPass(i);

		// Draw the one and only subset.
		_skinnedMesh->DrawSubset(0);

		_effect->EndPass();
	}
	_effect->End();
}

D3DXFRAME* SkinnedMesh::findNodeWithMesh(D3DXFRAME* frame)
{
	// In this demo we stipulate that the input .X file contains only one
	// mesh.  So search for that one and only mesh.

	
    frame = D3DXFrameFind(_root, "d_d");
	std::cout<<frame->Name<<" "<<frame->pMeshContainer->Name;
	return frame;

	/*if( frame->pMeshContainer )
		if( frame->pMeshContainer->MeshData.pMesh != 0)
			return frame;

	D3DXFRAME* f = 0;
	if(frame->pFrameSibling)
		if( f = findNodeWithMesh(frame->pFrameSibling) )	
			return f;

	if(frame->pFrameFirstChild)
		if( f = findNodeWithMesh(frame->pFrameFirstChild) )
			return f;

	return 0;*/
}

void SkinnedMesh::buildSkinnedMesh(ID3DXMesh* mesh)
{
	// The vertex format of the source mesh does not include vertex weights 
	// nor bone index data, both of which are needed for vertex blending.
	// Therefore, we must convert the source mesh to an "indexed-blended-mesh,"
	// which does have the necessary data.

	DWORD        numBoneComboEntries = 0;
	ID3DXBuffer* boneComboTable      = 0;

	THROW_DXERR( _skinInfo->ConvertToIndexedBlendedMesh(
		mesh, 
		D3DXMESH_MANAGED | D3DXMESH_WRITEONLY,  
		SkinnedMesh::MAX_NUM_BONES_SUPPORTED, 
		0, // ignore adjacency in
		0, // ignore adjacency out
		0, // ignore face remap
		0, // ignore vertex remap
		&_maxVertInfluences,
		&numBoneComboEntries, 
		&boneComboTable,
		&_skinnedMesh) )

	// We do not need the bone table, so just release it.
	ReleaseCOM(boneComboTable);
}

void SkinnedMesh::buildEffect()
{
	ID3DXBuffer* errorBuffer = 0;
	D3DXCreateEffectFromFile(_device, "vertBlendDynamic.txt", 0, 0,                
		D3DXSHADER_DEBUG, 0, &_effect, &errorBuffer);    

	if( errorBuffer )
	{
		::MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);
		ReleaseCOM(errorBuffer);
		ReleaseCOM(_effect);
		THROW_DXERR(E_FAIL);
	}
	else
	{
		_hTech            = _effect->GetTechniqueByName("VertexBlendingTech");
		_hWorldViewProj   = _effect->GetParameterByName(0, "WorldViewProj");
		_hFinalTransforms = _effect->GetParameterByName(0, "FinalTransforms");
		_hTex             = _effect->GetParameterByName(0, "Tex");
	}
}

void SkinnedMesh::buildMaterials(D3DXMESHCONTAINER* meshContainer)
{
	// In this demo we assume the skinned mesh has exactly one texture.
	// So load and set that texture with the effect interface.

	D3DXMATERIAL* mtrls = meshContainer->pMaterials;
	DWORD numMtrls = meshContainer->NumMaterials;
	assert(numMtrls == 1);

	if( mtrls[0].pTextureFilename )
	{
		IDirect3DTexture9* tex = 0;
		THROW_DXERR(
			D3DXCreateTextureFromFile(_device, mtrls[0].pTextureFilename, &tex))
		
		THROW_DXERR(_effect->SetTexture(_hTex, tex))
		ReleaseCOM(tex);
	}
}

void SkinnedMesh::buildCombinedTransforms()
{
	// Get an array of pointers to the combined frame transformations.  We 
	// store the pointers such that the ith pointer corresponds with the 
	// ith offset-matrix.  Thus, given the ith bone, we can obtain its ith 
	// offset matrix and ith transform.  
	//     We note that the skinInfo object converted the source mesh to a 
	// indexed-blended-mesh.  It follows then that the  bone indices for 
	// the vertices are relative to the skinInfo bone array.  Therefore
	// we base everything relative to the offset-matrix array since that
	// is the array the bone indices of the vertices are relative to.

	for(UINT i = 0; i < _numBones; ++i)
	{
		// Find the frame that corresponds with the ith bone offset matrix.
		const char* boneName = _skinInfo->GetBoneName(i);
		D3DXFRAME* frame = D3DXFrameFind(_root, boneName);
		if( frame )
		{
			FrameEx* frameEx = static_cast<FrameEx*>( frame );
			_combinedTransforms = &frameEx->combinedTransform;
		}
	}
}

void SkinnedMesh::combineTransforms(FrameEx* frame, 
									D3DXMATRIX& P) // parent's combined transform
{
	// Recurse down the tree, combining transforms as we go along.  
	// Any node N's combined transform C is determined by its local 
	// transform L, and the combined transform P of its parent.
	// Thus C = L * P.

	// Save some references to economize line space.
    D3DXMATRIX& L = frame->TransformationMatrix;
    D3DXMATRIX& C = frame->combinedTransform;

    C = L * P;

    FrameEx* sibling    = (FrameEx*)frame->pFrameSibling;
    FrameEx* firstChild = (FrameEx*)frame->pFrameFirstChild;

	// Recurse down siblings.
	if( sibling )
		combineTransforms(sibling, P);

	// Recurse to first child.
	if( firstChild )
		combineTransforms(firstChild, C);
}



it load tiny.x file it work,but I use these code load my .x file so no display .but program can run. but I could use dx sdk tool mesh view to watch my .x file . so what happen?
Advertisement
Do you have a camera set up looking in the correct direction? Its possible that it is renderering, but behind where your camera is looking.

Have you ran it through your debugger to make sure that all the initialization has worked correctly?
moe.ron

This topic is closed to new replies.

Advertisement