D3D游戏编程系列(一):DXLib的介绍

       这篇文章里我准备向大家介绍下我封装的一个基础D3D库:DXLib。有了这样一个类库,可以减少很多无用功以及繁琐的工作,使我们的效率大大提高。

DXLib.h

#define DIRECTINPUT_VERSION 0x0800
#pragma  warning(disable:4786)
#pragma  warning(disable:4244)
#pragma  warning(disable:4995)
#pragma  warning(disable:4996)
#include <Windows.h>
#include <iostream>
#include <tchar.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dinput.h>
#include <dsound.h>
#include <atlconv.h>
#include <DShow.h>
#include <MMSYSTEM.H>
#include <list>
#include <algorithm>
#include <atlstr.h>
#include <vector>
#include <map>
#include <set>
#include <ctime>
#include "AllocateHierarchyClass.h"
extern "C" 
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
};
#include "lua_tinker.h"
using namespace std;
#pragma  comment(lib,"d3d9")
#pragma  comment(lib,"d3dx9")
#if _MSC_VER>1200
#pragma  comment(lib,"dinput8")
#else
#pragma  comment(lib,"dinput")
#endif
#pragma  comment(lib,"dsound")
#pragma  comment(lib,"dxguid")
#pragma comment(lib, "winmm.lib ")
#pragma  comment(lib,"strmiids")
#pragma  comment(lib,"lua51")
#define  WM_DXDRAWEND WM_USER+1
#define  WM_DXDEVICENOTRESET WM_USER+2
#define  WM_DXDEVICENOTRESETRESPONDOK WM_USER+3
class CDXWindow;
typedef int (CDXWindow::*MessageFunc)(WPARAM,LPARAM);
struct MsgFuncStruct{
	UINT message;
	MessageFunc func;
};
#define  MESSAGE_MAP()   \
	static MsgFuncStruct m_sMsgFunc[];\
	virtual MsgFuncStruct* GetMsgFuncStruct(){return m_sMsgFunc;}
#define  BEGIN_MESSAGE(cls,basecls) \
	MsgFuncStruct cls::m_sMsgFunc[]={{(UINT)basecls::m_sMsgFunc,0},
#define  ONMESSAGE(message,func) \
{message,(MessageFunc)func},
#define  END_MESSAGE()  \
{0,0}};
class CDXControl;
class CDXWindow
{
public:
	friend CDXControl;
	CDXWindow();
	~CDXWindow();
	bool Create(LPCTSTR strTitle,bool bFullScreen=false,int nX=CW_USEDEFAULT,int nY=CW_USEDEFAULT,int nWidth=CW_USEDEFAULT,int nHeight=CW_USEDEFAULT);
	void SetDrawDelay(float iDelay){m_iDrawDelay=iDelay/1000;}
	void DoModal();
	int GetStyle();
	int GetStyleEx();
	int SetStyle();
	int SetStyleEx();
	ID3DXFont* DXCreateFont(int height=30,LPCTSTR font=_T("宋体"));
	LPD3DXSPRITE DXCreateSprite();
	LPDIRECT3DTEXTURE9 DXLoadTextureFromFile(LPCTSTR,bool bRenderTarget=false,D3DCOLOR transcolor=D3DCOLOR_XRGB(255,0,255));
	LPDIRECTSOUNDBUFFER DXLoadSound(LPCTSTR);
	D3DMATERIAL9 DXCreateMtrl(D3DCOLORVALUE ambient,D3DCOLORVALUE diffuse,D3DCOLORVALUE specular,D3DCOLORVALUE emissive,float power);
	D3DLIGHT9 DXCreateDirectionLight(D3DXVECTOR3 *dir,D3DCOLORVALUE ambient,D3DCOLORVALUE diffuse, D3DCOLORVALUE specular);
	D3DLIGHT9 DXCreatePointLight(D3DXVECTOR3 *pos,float range,D3DCOLORVALUE ambient,D3DCOLORVALUE diffuse, D3DCOLORVALUE specular,float att0=1);
	LPDIRECT3DDEVICE9 GetD3dDevice();
	HWND GetHwnd(){return m_hWnd;}
	CDXControl* GetFocusControl(){return m_pFocusControl;}
	void SetBKColor(D3DCOLOR color);
	void SetFps(bool bFps);
	void DXDrawQuad(RECT *rect,D3DCOLOR bkColor=D3DCOLOR_XRGB(0,0,0),bool bFill=true,float fLineWidth=0,IDirect3DTexture9 *pTex=0);
	bool GetFullScreen();
protected:
	typedef struct 
	{
		HWND hwnd;
		UINT message;
		WPARAM wparam;
		LPARAM lparam;
	}DXMSG;
	static DWORD WINAPI DrawThread(LPVOID);
	HWND m_hWnd;
	D3DCOLOR m_BKColor;
	DWORD m_dThread;
	bool m_bFullScreen;
	int m_iDXWndWidth;
	float m_iDrawDelay;
	char m_KeyBoard[256];
	DIMOUSESTATE m_MouseState;
	int m_iDXWndHeight;
	LPDIRECT3DDEVICE9 m_pd3dDevice;
	D3DPRESENT_PARAMETERS m_d3dpp;
	LPDIRECTINPUTDEVICE m_pInputKbd;
	LPDIRECTINPUTDEVICE m_pInputMouse;
	ID3DXLine *m_Line;
	float m_fDeltaTime;
	IMediaControl *DXLoadMusic(LPCTSTR);
	virtual void DXDraw(bool bInputEnabled)=0;
	virtual bool ExtInit(){return true;}
	bool DXInit();
	bool DXKeyDown(int key){if(m_KeyBoard[key] & 0x80){return true;}else{return false;}}
	bool DXLButtonDown();
	bool DXRButtonDown();
	int DXMouseMickeyX();
	int DXMouseMickeyY();
	int DXMouseMickeyZ();
	bool DXInputUpdate();
	void DXBaseRelease();
	void DXBaseOnLostDevice();
	void DXBaseOnResetDevice();
	void DXDrawControl(bool bInputEnabled);
	ID3DXFont* GetFpsFont();
	virtual void DXRelease(){}
	virtual void DXOnLostDevice();
	virtual void DXOnResetDevice();
	virtual void DXBeforeDraw(bool bInputEnabled){}
	virtual void DXAfterDraw(bool bInputEnabled){}
	virtual void DXProcessEvent(bool bInputEnabled);
	LPDIRECTSOUND m_pDirectSound; 
	static LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam);
	MESSAGE_MAP()
private:
	float GetFps();
	list<CDXControl*> m_pControlList;
	int OnDestroy(WPARAM,LPARAM){PostQuitMessage(0);return -1;}
	CDXControl *m_pFocusControl;
	bool m_bFps;
	ID3DXFont *m_FpsFont;
};

class CDXHelper
{
protected:
	static void GetRayInfo(LPDIRECT3DDEVICE9 pDevice,POINT p,D3DXVECTOR3* origin,D3DXVECTOR3 *direction,D3DXMATRIX *WorldMat=0);
public:
	struct sBoundingSphere
	{
		D3DXVECTOR3 pos;
		float radius;
	};
	struct sRect
	{
		float left,top,right,bottom;
	};
public:
	static void GetBoundingSphere(D3DXVECTOR3* pFirstPosition,DWORD NumVertices,DWORD dwStride,sBoundingSphere *pSphere);
	static bool MouseInSphere(LPDIRECT3DDEVICE9 pDevice,POINT p,sBoundingSphere* pSphere,D3DXVECTOR2 *pHit);  
	static bool MouseInTriangle(LPDIRECT3DDEVICE9 pDevice,POINT p,D3DXVECTOR3* p1,D3DXVECTOR3* p2,D3DXVECTOR3* p3);
	static bool MouseInMesh(LPDIRECT3DDEVICE9 pDevice,POINT p,LPD3DXMESH pMesh,D3DXMATRIX *WorldMat=0);
	static bool MouseInPlane(LPDIRECT3DDEVICE9 pDevice,POINT p,LPD3DXPLANE pPlane,D3DXVECTOR3 *pHitVec);
	static void ComputerNormal(D3DXVECTOR3 *p1,D3DXVECTOR3 *p2,D3DXVECTOR3 *p3,D3DXVECTOR3 *out);
	static void FillVertexNormal(void *p1,void *p2,void *p3,DWORD offset);
	template<typename FVFTYPE>
	static void FillFullVertexNormal(FVFTYPE *Vex,WORD *Index,DWORD dNumIndex,DWORD offset);
	static bool CheckBoxCollide(D3DXVECTOR3 min1,D3DXVECTOR3 max1,D3DXVECTOR3 min2,D3DXVECTOR3 max2);
	static float GetNormalAngle(D3DXVECTOR2 v1,D3DXVECTOR2 v2);
};

template<typename FVFTYPE>
void CDXHelper::FillFullVertexNormal( FVFTYPE *Vex,WORD *Index,DWORD dNumIndex,DWORD offset )
{
	map<DWORD,D3DXVECTOR3> VertexNormalList;
	static D3DXVECTOR3 VecNormal;
	for(int i=0;i<dNumIndex;i++)
	{
		if(i%3==0)
		{
			ComputerNormal((D3DXVECTOR3*)(Vex+Index[i]),(D3DXVECTOR3*)(Vex+Index[i+1]),(D3DXVECTOR3*)(Vex+Index[i+2]),&VecNormal);
		}
		if(VertexNormalList.find(Index[i])==VertexNormalList.end())
		{
			VertexNormalList[Index[i]]=VecNormal;
		}else
		{
			VertexNormalList[Index[i]]+=VecNormal;
		}
	}
	map<DWORD,D3DXVECTOR3>::iterator it;
	for(it=VertexNormalList.begin();it!=VertexNormalList.end();it++)
	{
		D3DXVECTOR3 normal=it->second;
		D3DXVec3Normalize(&normal,&normal);
		*(D3DXVECTOR3*)((char*)(Vex+it->first)+offset)=normal;
	}
}

class CDXCamera
{
public:
	void Go(float fLen);
	void Back(float fLen);
	void Up(float fLen);
	void Down(float fLen);
	void Left(float fLen);
	void Right(float fLen);
	void TurnLeft(float fAngle);
	void TurnRight(float fAngle);
	void TurnUp(float fAngle);
	void TurnDown(float fAngle);
	void Reset(CDXWindow *pWin,D3DXVECTOR3 vEye,D3DXVECTOR3 vAt);
	void SetTransForm();
	D3DXVECTOR3 GetEye();
	D3DXVECTOR3 GetAt();
	float GetX();
	float GetY();
	float GetZ();
	float GetRightAngle();
	float GetUpAngle();
protected:
	LPDIRECT3DDEVICE9 m_pDevice;
	D3DXVECTOR3 m_vEye; 
	D3DXVECTOR3 m_vAt; 
	D3DXVECTOR3 m_vUp;
	float m_fRightAngle;
	float m_fUpAngle;
	float m_fRad;
};

class CDXParticle
{
public:
	class sParticle;
	void Reset(CDXWindow *pWin,bool bSpriteEnable=true,bool bScaleEnable=true);
	void AddParticle();
	virtual void OnAdd(sParticle* pParticle){}
	virtual void Update(){}
	virtual void Render();
	void SetParticleSize(float iLen);
protected:
	struct sParticle
	{
		D3DXVECTOR3 pos;
		D3DXVECTOR3 normal;
		D3DCOLOR col;
		float x,y;
		static const DWORD FVF=D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1;
	};
	DWORD FToD(float f){
		return *((DWORD*)&f);
	}
	vector<sParticle> m_ParVector;
	LPDIRECT3DDEVICE9 m_pDevice;
};

class CDXBaseMesh
{
public:
	virtual void Render()=0;
	virtual ID3DXMesh* GetMeshObj()=0;
	virtual void Release()=0;
	virtual LPDIRECT3DDEVICE9 GetDevice()=0;
	virtual ~CDXBaseMesh(){}
};

class CDXXFile:public CDXBaseMesh
{
public:
	bool LoadFile(LPCTSTR szPath,LPDIRECT3DDEVICE9 pDevice,DWORD option=D3DXMESH_MANAGED);
	void Render();
	ID3DXMesh* GetMeshObj();
	void Release();
	LPDIRECT3DDEVICE9 GetDevice();
	CDXXFile();
	~CDXXFile();
protected:
	LPDIRECT3DDEVICE9 m_pDevice;
	LPD3DXMESH m_pMesh;
	vector<D3DMATERIAL9> m_VecMtrl;
	vector<LPDIRECT3DTEXTURE9> m_VecTex;
	DWORD m_dNumMtrl;
	DWORD m_dSubSize;
};

class CDXLand
{
public:
	CDXLand();
	~CDXLand();
	bool Create(LPDIRECT3DDEVICE9 pDevice,DWORD dWidthNumVertex,DWORD dHeightNumVertex,DWORD dCellLen,int dStartX,int dStartZ,LPCTSTR tcsRawPath,LPCTSTR tcsTexPath,float fScaleHeight=1 );
	void Render();
	float GetHeight(float x,float z);
	float GetStartX();
	float GetStartZ();
	float GetLandWidth();
	float GetLandHeight();
protected:
	struct sVertex
	{
		sVertex(){}
		sVertex(float x1,float y1,float z1,float u1,float v1)
		{
			x=x1,y=y1,z=z1;u=u1,v=v1;
		}
		float x,y,z;
		float nx,ny,nz;
		float u,v;
	};
	static const DWORD dVertexFVF=D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1;
	LPDIRECT3DDEVICE9 m_pDevice;
	LPDIRECT3DTEXTURE9 m_pTex;
	LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer ;  
	LPDIRECT3DINDEXBUFFER9  m_pIndexBuffer  ;  
	DWORD m_dWidthNumVertex;
	DWORD m_dHeightNumVertex;
	DWORD m_dCellLen;
	vector<float> m_HeightMap;
	float GetHeightFromXZ(int iRow,int iCol);
	int m_dStartX;
	int m_dStartZ;
};

class CDXSky
{
public:
	CDXSky();
	~CDXSky();
	bool Create(LPDIRECT3DDEVICE9 pDevice,int dStartX,int dStartZ,DWORD dWidth,DWORD dHeight,int dY,LPCTSTR *tcsTexPath);
	void Render();
	void SetPos(float x,float z);
protected:
	struct sVertex
	{
		sVertex(){}
		sVertex(float x1,float y1,float z1,float u1,float v1)
		{
			x=x1,y=y1,z=z1;u=u1,v=v1;
			col=D3DCOLOR_XRGB(255,255,255);
		}
		float x,y,z;
		D3DCOLOR col;
		float u,v;
	};
	static const DWORD dVertexFVF=D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1;
	LPDIRECT3DDEVICE9 m_pDevice;
	map<CString,LPDIRECT3DTEXTURE9> m_pTexList;
	LPDIRECT3DTEXTURE9 m_pTex[6];
	LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer ;  
	int m_dStartX;
	int m_dStartZ;
	int m_dWidth;
	int m_dHeight;
	int m_dY;
	float m_fCenterX;
	float m_fCenterZ;
	D3DXMATRIX m_TransMat;
};

template<typename FVFTYPE>
class CDXMesh:public CDXBaseMesh
{
public:
	CDXMesh();
	~CDXMesh();
	bool Create(DWORD dNumFace,DWORD dNumVert,DWORD dFVF,LPDIRECT3DDEVICE9 pDevice);
	void BeginVertex();
	void EndVertex();
	void BeginIndex();
	void EndIndex();
	void BeginAttr(int iNumSub);
	void EndAttr();
	void BeginTex();
	void EndTex();
	void BeginMtrl();
	void EndMtrl();
	void Release();
	CDXMesh<FVFTYPE>& operator [](int i);
	FVFTYPE& operator =(const FVFTYPE& vertex);
	int& operator=(int val);
	LPCTSTR& operator=(LPCTSTR strTex);
	LPDIRECT3DTEXTURE9& operator=( LPDIRECT3DTEXTURE9 pTex );
	D3DMATERIAL9& operator=(D3DMATERIAL9& mtrl);
	void ComputerNormal();
	void Optimize(DWORD option=D3DXMESHOPT_ATTRSORT|D3DXMESHOPT_COMPACT|D3DXMESHOPT_VERTEXCACHE);
	ID3DXMesh* GetMeshObj();
	void Render();
	void Clone(DWORD FVF,LPD3DXMESH *pMesh);
	LPDIRECT3DDEVICE9 GetDevice();
protected:
	static const  int VERTEX=1;
	static const  int INDEX=2;
	static const  int ATTR=3;
	static const  int TEX=4;
	static const int  MTRL=5;
	ID3DXMesh *m_pMesh;
	LPDIRECT3DDEVICE9 m_pDevice;
	int m_iType;
	map<CString,LPDIRECT3DTEXTURE9> m_TexPathMap;
	map<int,LPDIRECT3DTEXTURE9> m_TexList;
	map<int,D3DMATERIAL9> m_MtrlList;
	int m_iIndex;
	FVFTYPE* m_v;
	WORD *m_i;
	DWORD *m_a;
	int m_iNumSub;
};

template<typename FVFTYPE>
LPDIRECT3DTEXTURE9& CDXMesh<FVFTYPE>::operator=( LPDIRECT3DTEXTURE9 pTex )
{
	if(m_iType==TEX)
	{
		if(pTex!=0)
		{
			m_TexList[m_iIndex]=pTex;
		}		
		return pTex;
	}
}

template<typename FVFTYPE>
LPDIRECT3DDEVICE9 CDXMesh<FVFTYPE>::GetDevice()
{
	return m_pDevice;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::Release()
{
	this->~CDXMesh();
	delete this;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::Clone( DWORD FVF,LPD3DXMESH *pMesh )
{
	m_pMesh->CloneMeshFVF(m_pMesh->GetOptions(),FVF,m_pDevice,pMesh);
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::EndMtrl()
{
	m_iType=0;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::BeginMtrl()
{
	m_iType=MTRL;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::EndTex()
{
	m_iType=0;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::BeginTex()
{
	m_iType=TEX;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::Render()
{
	D3DMATERIAL9 mtrl;
	m_pDevice->GetMaterial(&mtrl);
	IDirect3DTexture9 *pTex;
	m_pDevice->GetTexture(0,(IDirect3DBaseTexture9**)&pTex);
	for(int i=0;i<m_iNumSub;i++)
	{
		if(i<m_TexList.size())
		{
			m_pDevice->SetTexture(0,m_TexList[i]);
		}
		if(i<m_MtrlList.size())
		{
			m_pDevice->SetMaterial(&m_MtrlList[i]);
		}
		m_pMesh->DrawSubset(i);
		m_pDevice->SetTexture(0,0);
	}	
	m_pDevice->SetMaterial(&mtrl);
	m_pDevice->SetTexture(0,pTex);
}

template<typename FVFTYPE>
CDXMesh<FVFTYPE>::~CDXMesh()
{
	if(m_pMesh)
	{
		m_pMesh->Release();
	}
	map<CString,LPDIRECT3DTEXTURE9>::iterator it;
	for(it=m_TexPathMap.begin();it!=m_TexPathMap.end();it++)
	{
		if(it->second)
		{
			it->second->Release();
		}

	}
}

template<typename FVFTYPE>
CDXMesh<FVFTYPE>::CDXMesh()
{
	m_pMesh=0;
	m_iType=0;
	m_iIndex=0;
	m_v=0;
	m_i=0;
	m_a=0;
	m_iNumSub=0;
}

template<typename FVFTYPE>
bool CDXMesh<FVFTYPE>::Create( DWORD dNumFace,DWORD dNumVert,DWORD dFVF,LPDIRECT3DDEVICE9 pDevice )
{
	HRESULT hr=D3DXCreateMeshFVF(dNumFace,dNumVert,D3DXMESH_MANAGED,dFVF,pDevice,&m_pMesh);
	if(FAILED(hr))
	{
		return false;
	}
	m_pDevice=pDevice;
	return true;
}


template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::BeginVertex()
{
	if(!m_pMesh)
	{
		return;
	}
	m_pMesh->LockVertexBuffer(0,(void**)&m_v);
	m_iType=VERTEX;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::EndVertex()
{
	if(!m_pMesh)
	{
		return;
	}
	m_pMesh->UnlockVertexBuffer();
	m_iType=0;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::EndAttr()
{
	if(!m_pMesh)
	{
		return;
	}
	m_pMesh->UnlockAttributeBuffer();
	m_iType=0;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::BeginAttr(int iNumSub)
{
	if(!m_pMesh)
	{
		return;
	}
	m_iNumSub=iNumSub;
	m_pMesh->LockAttributeBuffer(0,&m_a);
	m_iType=ATTR;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::EndIndex()
{
	if(!m_pMesh)
	{
		return;
	}
	m_pMesh->UnlockIndexBuffer();
	m_iType=0;
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::BeginIndex()
{
	if(!m_pMesh)
	{
		return;
	}
	m_pMesh->LockIndexBuffer(0,(void**)&m_i);
	m_iType=INDEX;
}

template<typename FVFTYPE>
CDXMesh<FVFTYPE>& CDXMesh<FVFTYPE>::operator[]( int i )
{
	m_iIndex=i;
	return *this;
}

template<typename FVFTYPE>
FVFTYPE& CDXMesh<FVFTYPE>::operator=( const FVFTYPE& vertex )
{
	if(m_iType==VERTEX)
	{
		m_v[m_iIndex]=vertex;
		return *(FVFTYPE*)&vertex;
	}

}


template<typename FVFTYPE>
int& CDXMesh<FVFTYPE>::operator=( int val )
{
	if(m_iType==INDEX)
	{
		m_i[m_iIndex]=val;
		return val;
	}else if(m_iType==ATTR)
	{
		if(val<m_iNumSub)
		{
			m_a[m_iIndex]=val;
			return val;
		}
	}
}


template<typename FVFTYPE>
LPCTSTR& CDXMesh<FVFTYPE>::operator=( LPCTSTR strTex )
{
	if(m_iType==TEX)
	{
		if(!m_TexPathMap.find(strTex))
		{
			IDirect3DTexture9 *pTex=0;
			D3DXCreateTextureFromFile(m_pDevice,strTex,&pTex);
			m_TexPathMap[strTex]=pTex;
		}
		m_TexList[m_iIndex]=m_TexPathMap[strTex];
		return strTex;
	}

}

template<typename FVFTYPE>
D3DMATERIAL9& CDXMesh<FVFTYPE>::operator=( D3DMATERIAL9& mtrl )
{
	if(m_iType==MTRL)
	{
		m_MtrlList[m_iIndex]=mtrl;
		return mtrl;
	}
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::Optimize( DWORD option/*=D3DXMESHOPT_ATTRSORT|D3DXMESHOPT_COMPACT|D3DXMESHOPT_VERTEXCACHE*/ )
{
	vector<DWORD> adj(m_pMesh->GetNumFaces()*3);
	m_pMesh->GenerateAdjacency(0.0f,&adj[0]);
	m_pMesh->OptimizeInplace(option,&adj[0],0,0,0);
}

template<typename FVFTYPE>
void CDXMesh<FVFTYPE>::ComputerNormal()
{
	D3DXComputeNormals(m_pMesh,0);
}

template<typename FVFTYPE>
ID3DXMesh* CDXMesh<FVFTYPE>::GetMeshObj()
{
	return m_pMesh;
}


class CDXControl
{
public:
	friend CDXWindow;
	CDXControl();
	~CDXControl();
	virtual bool Create(CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,bool bShow=true);
	virtual void ShowWindow(bool bShow);
	virtual bool IsWindowVisible();
	virtual void MoveWindow(int iLeft,int iTop,int iWidth,int iHeight);
	virtual void SetTopWindow();
	virtual void EnableWindow(bool bEnabled);
	virtual bool IsWindowEnabled();
	virtual void DestoryWindow();
	virtual void DXOnLostDevice(){}
	virtual void DXOnResetDevice(){}
	virtual void OnLButtonDown(int x,int y){}
	virtual void OnLButtonUp(int x,int y){}
	virtual void OnRButtonDown(int x,int y){}
	virtual void OnRButtonUp(int x,int y){}
	virtual void OnMouseOver(int x,int y){}
	virtual void OnMouseLeave(int x,int y){}
	virtual void OnMouseMove(int x,int y){}
	virtual void OnChar(UINT ch){}
	virtual void SetCheck(bool bCheck);
	virtual bool GetCheck();
	virtual void Draw()=0;
	virtual RECT GetRect()=0;
	void SetVertexAlpha(bool bAlpha);
	void SetMouseOver(bool bMouseOver);
	bool GetMouseOver();
	void SetMouseOverPoint(int x,int y);
	POINT GetMouseOverPoint();
protected:
	struct sVertex
	{
		sVertex(){}
		sVertex(float x1,float y1,float z1,float h1,D3DCOLOR color1,float tu1,float tv1)
		{
			x=x1,y=y1,z=z1,h=h1,color=color1,tu=tu1,tv=tv1;
		}
		float x, y, z, h;
		D3DCOLOR color;
		float tu, tv;
		static DWORD FVF;
	};
	sVertex *m_ControlRect;
	bool m_bShow;
	bool m_bEnabled;
	CDXWindow *m_pD3dWindow;
	bool m_bCheck;
	bool m_bAlpha;
	bool m_bMouseOver;
	int m_iOverX;
	int m_iOverY;
};

class CDXStatic:public CDXControl
{
public:
	bool Create(CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,bool bShow=true);
	void DestoryWindow();
	void Draw();
	void SetBKColor(D3DCOLOR color);
	void SetText(LPCTSTR strText);
	LPCTSTR GetText();
	void SetFont(int iHeight,LPCTSTR strFont);
	void SetForeColor(D3DCOLOR color);
	void SetStyle(int iStyle);
	void DXOnLostDevice();
	void DXOnResetDevice();
	RECT GetRect();
protected:
	D3DCOLOR m_BkColor;
	D3DCOLOR m_ForeColor;
	TCHAR   *m_strText; 
	ID3DXFont* m_Font;
	int m_iStyle;
};

class CDXButton:public CDXControl
{
public:
	bool Create(CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,bool bShow=true);
	void DestoryWindow();
	void Draw();
	void SetBKColor(D3DCOLOR color);
	void SetText(LPCTSTR strText);
	LPCTSTR GetText();
	void SetFont(int iHeight,LPCTSTR strFont);
	void SetForeColor(D3DCOLOR color);
	void DXOnLostDevice();
	void DXOnResetDevice();
	bool SetBkImg(LPCTSTR path);
	RECT GetRect();
	void OnLButtonDown(int x,int y);
	void OnLButtonUp(int x,int y);
	void OnRButtonDown(int x,int y);
	void OnRButtonUp(int x,int y);
protected:
	D3DCOLOR m_ForeColor;
	TCHAR   *m_strText; 
	ID3DXFont* m_Font;
	LPDIRECT3DTEXTURE9 m_pTexture;
};
class CDXEdit:public CDXStatic
{
public:
	bool Create(CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,bool bShow=true);
	void Draw();
	void OnChar(UINT ch);
	void OnLButtonDown(int x,int y);
	void SetText(LPCTSTR strText);
	LPCTSTR GetText();
	void DestoryWindow();
protected:
	TCHAR m_strText[1024];
	int m_iCount;
	int m_iBlinkLeft;
	int m_iBlinkHeight;
	int m_iCurPos;
	int m_iCurBegin;
};

class CDXListBox:public CDXControl
{
public:
	void DestoryWindow();
	bool Create(CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,int iItemHeight,bool bShow=true);
	void Draw();
	void OnLButtonDown(int x,int y);
	void OnLButtonUp(int x,int y);
	void OnMouseLeave(int x,int y);
	void OnMouseMove(int x,int y);
	int GetSelectedItem();
	LPCTSTR GetItemText(int iIndex);
	int GetItemCount();
	bool SetItemText(int iIndex,LPCTSTR strItem);
	void AddItem(LPCTSTR strItem);
	bool DeleteItem(int iIndex);
	RECT GetRect();
	void SetBKColor(D3DCOLOR color);
	void SetForeColor(D3DCOLOR color);
	void SetFont(int iHeight,LPCTSTR strFont);
	void DXOnLostDevice();
	void DXOnResetDevice();
protected:
	void CalcData();
	ID3DXFont *m_Font;
	IDirect3DTexture9 *m_Tex;
	IDirect3DSurface9 *m_Sur;
	ID3DXSprite *m_Spr;
	list<LPCTSTR> m_ItemTextList;
	RECT m_ClientRect;
	RECT m_UpRect;
	RECT m_SliderRect;
	RECT m_DownRect;
	int m_iSelectedIndex;
	int m_iItemHeight;
	int m_iMaxPageCount;
	float m_fRate;
	int m_iSliderSize;
	bool m_bDrag;
	int m_iOffsetY;
	int m_iDrawY;
	int m_iDrawPos;
	D3DCOLOR m_BkColor;
	D3DCOLOR m_ForeColor;
	static const int m_iMinSliderHeight=15;
	static const int m_iEdgeSize=20;
};
class CDXMutiplyStatic:public CDXStatic
{
public:
	bool Create(CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,bool bShow=true);
	void Draw();
	void SetText( LPCTSTR strText );
	void MoveWindow(int iLeft,int iTop,int iWidth,int iHeight);
protected:
	int m_iWidth;
	list<CString> m_strList;
};


class CDXEntity;
class CDXOctNode
{
public:
	friend CDXEntity;
	CDXOctNode();
	~CDXOctNode();
	void AddEntity(CDXEntity* pEntity,CString strId);
	int GetEntityNum();
	void SortNode(D3DXVECTOR3 min=D3DXVECTOR3(0,0,0),D3DXVECTOR3 max=D3DXVECTOR3(0,0,0));
	void Release();
	CDXOctNode*GetRoot();
	CDXEntity* GetEntityById(CString strId);
	bool CheckCollide(CDXEntity *pEntity,vector<CDXOctNode*>& NodeList);
	void Render(LPDIRECT3DDEVICE9 pDevice);
	bool CheckCollideEntity(D3DXVECTOR3 Min,D3DXVECTOR3 Max,set<CDXEntity*>& EntitySet);
protected:
	list<CDXEntity*> m_EntityList;
	CDXOctNode* m_pChildNode[8];
	CDXOctNode* m_pParNode;
	D3DXVECTOR3 m_MinVec;
	D3DXVECTOR3 m_MaxVec;
	void _Sort(CDXOctNode* pNode,int iDepth);
	bool m_bSort;
	void _Release(CDXOctNode* pNode);
	CString m_strId;
	static list<CDXEntity*> RenderList;
	void _CheckCollide(CDXOctNode *pNode,CDXEntity* pEntity,bool &bCollide,vector<CDXOctNode*>& NodeList);
	void _CheckCollideEntity(CDXOctNode *pNode,D3DXVECTOR3 Min,D3DXVECTOR3 Max,bool &bCollide,set<CDXEntity*>& EntitySet);
	bool _CheckInFrustum(D3DXVECTOR3 &min,D3DXVECTOR3 &max,D3DXPLANE *Planes,bool *bFullContained);
	void _Render(CDXOctNode* pNode,D3DXPLANE* Planes,bool bCheck=true);
	void _SortEntity(CDXOctNode* pNode);
	static int ref;
	static CDXOctNode* root;
	static map<CString,CDXEntity*> EntityIdList;
	static int iDepthNum;
	static bool bCreate;
};

class CDXEntity
{
public:
	friend CDXOctNode;
	CDXEntity(CDXBaseMesh *pMesh,D3DXMATRIX *mat=0);
	void Render();
	void Release(CDXOctNode *pNode);
	void Remove();
	void Move(float dx=0,float dy=0,float dz=0);
	void Scale(float nx=0,float ny=0,float nz=0);
	void Rotate(float ax=0,float ay=0,float az=0 ,float axis=0,D3DXVECTOR3 va=D3DXVECTOR3(0,0,0));
	void SetPos(D3DXVECTOR3 min);
	void GetPos(D3DXVECTOR3& min,D3DXVECTOR3& max);
	D3DXVECTOR3 GetBoundMin();
	D3DXVECTOR3 GetBoundMax();
	void SetBoundMin(D3DXVECTOR3 min);
	void SetBoundMax(D3DXVECTOR3 max);
	D3DXMATRIX GetMatrix();
	void SetExtMatrix(D3DXMATRIX *mat);
	CString GetID();
protected:
	CDXBaseMesh *m_pMesh;
	set<CDXOctNode*> m_NodeList;
	bool m_bDrawed;
	D3DXVECTOR3 m_BoundMin;
	D3DXVECTOR3 m_BoundMax;
	CString m_StrId;
	D3DXMATRIX m_Mat;
	D3DXMATRIX m_ExtMat;
	bool m_bNormalCompute;
	void _UpdatePos();
};

class CDXSkinMesh
{
public:
	CDXSkinMesh();
	~CDXSkinMesh();
	void LoadFromFile(LPDIRECT3DDEVICE9 pDevice,LPCTSTR tcsPath);
	void Update(float fDeltaTime,D3DXMATRIX *mat);
	void Render();
	void SetAnimation(LPCSTR szAnimName);
	void SetAnimation(int  iAnimIndex);
	LPD3DXFRAME GetRoot()
	{
		return m_pFrameRoot;
	}
protected:
	LPD3DXFRAME                 m_pFrameRoot ;
	D3DXMATRIX*                 m_pBoneMatrices;
	CAllocateHierarchy*         m_pAllocateHier;
	LPD3DXANIMATIONCONTROLLER   m_pAnimController;
	LPDIRECT3DDEVICE9 m_pDevice;
};

class CDXShader
{
public:
	CDXShader();
	~CDXShader();
	void Create(LPDIRECT3DDEVICE9 pDevice);
	bool AddEffect(LPCTSTR tcsPath,LPCTSTR tcsName);
	void SetEffect(LPCTSTR tcsName);
	ID3DXEffect* operator ->();
private:
	map<CString,ID3DXEffect*> m_EffectList;
	ID3DXEffect* m_pCurEffect;
	LPDIRECT3DDEVICE9 m_pDevice;
};

class CDXThirdCamera
{
public:
	void Create(D3DXVECTOR3 vEye,D3DXVECTOR3 vAt);
	void RorateY(float fAngle);
	void RorateAxis(float fAngle);
	void Scale(float fParam);
	void GetTransform(D3DXMATRIX *Matrix);
	void Walk(float fWalk);
	void Left(float fLeft);
	D3DXVECTOR3 GetEye();
	D3DXVECTOR3 GetAt();
	void SetEyeHeight(float iY);
	void SetAtHeight(float iY);
	void SetEye(D3DXVECTOR3 Eye);
	void SetAt(D3DXVECTOR3 At);
private:
	D3DXVECTOR3 m_vEye;
	D3DXVECTOR3 m_vAt;
};

class CDXLua
{
public:
	CDXLua();
	~CDXLua();
	bool Execute(LPCSTR szPath);
	float GetNum(LPCSTR szName);
	LPCSTR GetString(LPCSTR szName);
	float GetTableNum(LPCSTR szTable,LPCSTR szKey);
	LPCSTR GetTableString(LPCSTR szTable,LPCSTR szKey);
	void CallFunc(LPCSTR szFunc);
	lua_State *GetLua();
private:
	lua_State *m_pLua;
};

DXLib.cpp

// dx.cpp : 定义控制台应用程序的入口点。
//


// test.cpp : Defines the entry point for the console application.


//
#include "stdafx.h"
#include "DXLib.h"
DWORD CDXControl::sVertex::FVF=D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1;
MsgFuncStruct CDXWindow::m_sMsgFunc[]={{0,0},{WM_DESTROY,&CDXWindow::OnDestroy},{0,0}};
CDXWindow::CDXWindow()
{
	m_iDrawDelay=0;
	m_hWnd=0;
	m_pd3dDevice=0;
	m_pFocusControl=0;
	m_BKColor=D3DCOLOR_XRGB(0,0,0);
	m_bFps=false;
	m_fDeltaTime=0;
	CoInitialize(0);
}
CDXWindow::~CDXWindow()
{
	CoUninitialize();
}
bool CDXWindow::Create(LPCTSTR strTitle,bool bFullScreen,int nX/* =CW_USEDEFAULT */,int nY/* =CW_USEDEFAULT */,int nWidth/* =CW_USEDEFAULT */,int nHeight/* =CW_USEDEFAULT */)
{
	m_bFullScreen=bFullScreen;
	m_iDXWndWidth=nWidth;
	m_iDXWndHeight=nHeight;
	HINSTANCE hInstance=GetModuleHandle(0);
	WNDCLASS WindowClass; 
	TCHAR className[100]={0}; 
	_stprintf(className,_T("CDXWindow%d"),GetTickCount());
	//not first run, to set the windows class 
	WindowClass.style=NULL; 
	WindowClass.cbClsExtra=0; 
	WindowClass.cbWndExtra=0; 
	WindowClass.hbrBackground=WHITE_BRUSH; 
	WindowClass.hCursor=LoadCursor(hInstance,IDC_ARROW); 
	WindowClass.hIcon=LoadIcon(hInstance,IDI_APPLICATION); 
	WindowClass.hInstance=hInstance; 
	WindowClass.lpfnWndProc=WndProc; 
	WindowClass.lpszClassName=className; 
	WindowClass.lpszMenuName=NULL; 
	RegisterClass(&WindowClass); 
	RECT r={0,0,nWidth,nHeight};
	AdjustWindowRect(&r,(((WS_OVERLAPPEDWINDOW&~WS_THICKFRAME) & ~WS_MAXIMIZEBOX) & ~WS_SIZEBOX),false);
	// start to create the window when registed the window class 
	m_hWnd=CreateWindowEx(0,className,strTitle,(((WS_OVERLAPPEDWINDOW&~WS_THICKFRAME) & ~WS_MAXIMIZEBOX) & ~WS_SIZEBOX), 
		nX, 
		nY, 
		r.right-r.left, 
		r.bottom-r.top,NULL,NULL,hInstance,this); 
	DWORD e=GetLastError();
	if(m_hWnd)
	{
		SetWindowLong(m_hWnd,GWL_USERDATA,(long)this);
		if(DXInit() && ExtInit())
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}


bool CDXWindow::DXInit()
{
	LPDIRECT3D9  pD3D = NULL; //Direct3D接口对象的创建
	if( NULL == ( pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) //初始化Direct3D接口对象,并进行DirectX版本协商


		return false;
	D3DCAPS9 caps; int vp = 0;
	if( FAILED( pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps ) ) )
	{
		return false;
	}
	if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;   //支持硬件顶点运算,我们就采用硬件顶点运算,妥妥的
	else
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //不支持硬件顶点运算,无奈只好采用软件顶点运算
	ZeroMemory(&m_d3dpp, sizeof(m_d3dpp));
	m_d3dpp.BackBufferWidth            = /*m_bFullScreen?GetSystemMetrics(SM_CXSCREEN):*/m_iDXWndWidth;
	m_d3dpp.BackBufferHeight           = /*m_bFullScreen?GetSystemMetrics(SM_CYSCREEN):*/m_iDXWndHeight;
	m_d3dpp.BackBufferFormat           = D3DFMT_X8R8G8B8;
	m_d3dpp.BackBufferCount            = 1;
	m_d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
	m_d3dpp.MultiSampleQuality         = 0;
	m_d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
	m_d3dpp.hDeviceWindow              = m_hWnd;
	m_d3dpp.Windowed                   = !m_bFullScreen;
	m_d3dpp.EnableAutoDepthStencil     = true;
	m_d3dpp.AutoDepthStencilFormat     = D3DFMT_D16;
	m_d3dpp.Flags                      = 0;
	m_d3dpp.FullScreen_RefreshRateInHz = m_bFullScreen?D3DPRESENT_RATE_DEFAULT:0;
	m_d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
	//pD3D->EnumAdapterModes()
	if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,


		m_hWnd, vp|D3DCREATE_MULTITHREADED, &m_d3dpp, &m_pd3dDevice)))
		return false; 
	if(pD3D)
	{
		pD3D->Release();
	}
	LPDIRECTINPUT input;
#if _MSC_VER>1200
	DirectInput8Create(GetModuleHandle(0),DIRECTINPUT_VERSION,IID_IDirectInput8,(LPVOID*)&input,0);
#else
	DirectInputCreate(GetModuleHandle(0),DIRECTINPUT_VERSION,&input,0);
#endif
	input->CreateDevice(GUID_SysKeyboard,&m_pInputKbd,0);
	m_pInputKbd->SetDataFormat(&c_dfDIKeyboard);
	m_pInputKbd->SetCooperativeLevel(m_hWnd,DISCL_NONEXCLUSIVE|DISCL_FOREGROUND);
	m_pInputKbd->Acquire();
	input->CreateDevice(GUID_SysMouse,&m_pInputMouse,0);
	m_pInputMouse->SetDataFormat(&c_dfDIMouse);
	m_pInputMouse->SetCooperativeLevel(m_hWnd,DISCL_NONEXCLUSIVE|DISCL_FOREGROUND);
	m_pInputMouse->Acquire();
	if(input)
	{
		input->Release();
	}
	if(FAILED(DirectSoundCreate(0, &m_pDirectSound, 0)))
	{
		return false;
	}
	m_pDirectSound-> SetCooperativeLevel(m_hWnd, DSSCL_NORMAL); 
	m_FpsFont=DXCreateFont();
	D3DXCreateLine(m_pd3dDevice,&m_Line);
	m_Line->SetAntialias(true);
	return true;
}


DWORD WINAPI CDXWindow::DrawThread(LPVOID l)
{
	LARGE_INTEGER litmp; 
	LONGLONG QPart1=0,QPart2=0;
	double dfMinus, dfFreq, dfTim; 
	bool bDeviceLost=false;
	MSG msg;
	QueryPerformanceFrequency(&litmp);
	dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率 
	QueryPerformanceCounter(&litmp);
	QPart2 = litmp.QuadPart;//获得中止值 
	PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
	CDXWindow *dxWin=(CDXWindow*)l;
	while(1)
	{
		//Sleep(1);
		if(PeekMessage(&msg,0,0,0,PM_REMOVE))
		{
			if(msg.message==WM_DXDRAWEND)
			{
				break;
			}else if(msg.message==WM_DXDEVICENOTRESETRESPONDOK)
			{
				bDeviceLost=false;
			}else if(msg.message==WM_CHAR)
			{
				if(dxWin->m_pFocusControl)
				{
					dxWin->m_pFocusControl->OnChar((UINT)(msg.wParam));
				}
 			}//else if(msg.message==WM_KEYDOWN)
// 			{
// 				if(dxWin->m_pFocusControl)
// 				{
// 					dxWin->m_pFocusControl->OnKeyDown((UINT)(msg.wParam));
// 				}
// 			}
		}
		if(bDeviceLost)
		{   
			Sleep(1);
			continue;
		}
		QueryPerformanceCounter(&litmp);
		QPart1 = litmp.QuadPart;// 获得初始值 
		dfMinus = (double)(QPart1-QPart2);
		dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒 
		dxWin->m_fDeltaTime=dfTim;
		if(dfTim>=dxWin->m_iDrawDelay)
		{
			QueryPerformanceCounter(&litmp);
			QPart2 = litmp.QuadPart;//获得中止值 
			bool bInputEnabled=dxWin->DXInputUpdate();
			dxWin->DXProcessEvent(bInputEnabled);
			dxWin->DXBeforeDraw(bInputEnabled);
			dxWin->m_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, dxWin->m_BKColor, 1.0f, 0);
			dxWin->m_pd3dDevice->BeginScene();    
			dxWin->DXDraw(bInputEnabled);
			dxWin->DXDrawControl(bInputEnabled);
			if(dxWin->m_bFps)
			{
				
				float fFps=dxWin->GetFps();
				WCHAR wzBuf[255]={0};
				wsprintf(wzBuf,L"FPS:%d",(int)fFps);
				RECT r={0,0,200,100};
				dxWin->m_FpsFont->DrawTextW(0,wzBuf,-1,&r,DT_TOP|DT_LEFT,D3DCOLOR_XRGB(255,1,255));
			}
			dxWin->m_pd3dDevice->EndScene();     
			HRESULT hr=dxWin->m_pd3dDevice->Present(0, 0, NULL, NULL); 
			dxWin->DXAfterDraw(bInputEnabled);
			if(FAILED(hr))
			{
				bDeviceLost=true;
				PostMessage(dxWin->m_hWnd,WM_DXDEVICENOTRESET,0,0);
			}


		}


	}
	dxWin->DXBaseRelease();
	return 1;
}


void CDXWindow::DoModal()
{
	CreateThread(0,0,DrawThread,this,0,&m_dThread);
	ShowWindow(m_hWnd,1);  
	UpdateWindow(m_hWnd);  
	SetCursor(LoadCursor(NULL,IDC_ARROW));
	MSG msg;
	while(1)  
	{
		static bool bDeviceLost=false;
		Sleep(1);
		if(PeekMessage(&msg,0,0,0,PM_REMOVE))
		{
			if(msg.message==WM_QUIT)
			{
				break;
			}else if(msg.message==WM_DXDEVICENOTRESET)
			{
				bDeviceLost=true;
			}else if(msg.message==WM_CHAR)
			{
				PostThreadMessage(m_dThread,WM_CHAR,msg.wParam,msg.lParam);
			}else if(msg.message==WM_KEYDOWN)
 			{
				UINT uKey=0;
				switch(msg.wParam)
				{
				case VK_DELETE:
					{
						uKey=VK_DELETE;
						break;
					}
				case VK_LEFT:
					{
						uKey=VK_LEFT;
						break;
					}
				case VK_RIGHT:
					{
						uKey=VK_RIGHT;
						break;
					}
				}
				if(uKey)
				{
 					PostThreadMessage(m_dThread,WM_CHAR,uKey,msg.lParam);
				}
			}
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		if(bDeviceLost)
		{
			if(m_pd3dDevice->TestCooperativeLevel()==D3DERR_DEVICENOTRESET)
			{
				DXBaseOnLostDevice();
				m_pd3dDevice->Reset(&(m_d3dpp));
				DXBaseOnResetDevice();
				bDeviceLost=false;
				PostThreadMessage(m_dThread,WM_DXDEVICENOTRESETRESPONDOK,0,0);
			}
		}
	}
	typedef HANDLE  (WINAPI  *OPENTHREAD) (DWORD , BOOL , DWORD );   
	OPENTHREAD lpfnOpenThread = (OPENTHREAD)GetProcAddress(LoadLibrary(_T("kernel32.dll")),"OpenThread");   
	HANDLE hThread = lpfnOpenThread(THREAD_ALL_ACCESS, FALSE, m_dThread);
	PostThreadMessage(m_dThread,WM_DXDRAWEND,0,0);
	WaitForSingleObject(hThread,-1);
	CloseHandle(hThread);
}


LRESULT CALLBACK CDXWindow::WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
	CDXWindow *dxWin=(CDXWindow*)GetWindowLong(hwnd,GWL_USERDATA);
	if(dxWin)
	{
		MsgFuncStruct *msgStruct=dxWin->GetMsgFuncStruct();
		while(1)
		{	
			if(msgStruct==0)
			{
				break;
			}
			for (int i=1;msgStruct[i].func;i++)
			{
				if(msgStruct[i].message==message)
				{
					if((dxWin->*(msgStruct[i].func))(wparam,lparam)==-1)
					{
						return 0;
					}
				}
			}
			msgStruct=(MsgFuncStruct*)msgStruct[0].message;
		}
	}
	return DefWindowProc(hwnd,message,wparam,lparam);
}


float CDXWindow::GetFps()
{
	static float  fps = 0; //我们需要计算的FPS值
	static int    frameCount = 0;//帧数
	static float  currentTime =0.0f;//当前时间
	static float  lastTime = 0.0f;//持续时间
	frameCount++;//每调用一次Get_FPS()函数,帧数自增1
	currentTime = timeGetTime()*0.001f;//获取系统时间,其中timeGetTime函数返回的是以毫秒为单位的系统时间,所以需要乘以0.001,得到单位为秒的时间


	//如果当前时间减去持续时间大于了1秒钟,就进行一次FPS的计算和持续时间的更新,并将帧数值清零
	if(currentTime - lastTime > 1.0f) //将时间控制在1秒钟
	{
		fps = (float)frameCount /(currentTime - lastTime);//计算这1秒钟的FPS值
		lastTime = currentTime; //将当前时间currentTime赋给持续时间lastTime,作为下一秒的基准时间
		frameCount    = 0;//将本次帧数frameCount值清零
	}
	return fps;
}


ID3DXFont* CDXWindow::DXCreateFont( int height/*=30*/,LPCTSTR font/*=_T("宋体")*/ )
{
	ID3DXFont * pFont=0;
	if(SUCCEEDED(D3DXCreateFont(m_pd3dDevice, height, 0, 0, 1, FALSE, DEFAULT_CHARSET,


		OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, font, &pFont)))
	{
		return pFont;
	}
	else
	{
		return 0;
	}
}


bool CDXWindow::DXInputUpdate()
{
	m_pInputKbd->Acquire();
	ZeroMemory(&m_MouseState,sizeof(m_MouseState));
	m_pInputMouse->Acquire();
	if(SUCCEEDED(m_pInputKbd->GetDeviceState(sizeof(m_KeyBoard),(LPVOID)&m_KeyBoard)) && SUCCEEDED(m_pInputMouse->GetDeviceState(sizeof(m_MouseState),(LPVOID)&m_MouseState)))
	{
		return true;
	}
	return false;
}
void CDXWindow::DXBaseRelease()
{
	DXRelease();
	list<CDXControl*>::iterator it=m_pControlList.begin();
	while(it!=m_pControlList.end())
	{
		(*it)->DestoryWindow();
		it=m_pControlList.begin();
	}
	m_pd3dDevice->Release();
	m_pInputKbd->Unacquire();
	m_pInputKbd->Release();
	m_pDirectSound->Release();
	m_FpsFont->Release();
	m_Line->Release();
}


void CDXWindow::DXBaseOnLostDevice()
{
	list<CDXControl*>::iterator it;
	for (it=m_pControlList.begin();it!=m_pControlList.end();it++)
	{
		if((*it)->IsWindowVisible())
		{
			(*it)->DXOnLostDevice();
		}


	}
	m_FpsFont->OnLostDevice();
	m_Line->OnLostDevice();
	DXOnLostDevice();
}


void CDXWindow::DXBaseOnResetDevice()
{
	list<CDXControl*>::iterator it;
	for (it=m_pControlList.begin();it!=m_pControlList.end();it++)
	{
		if((*it)->IsWindowVisible())
		{
			(*it)->DXOnResetDevice();
		}


	}
	m_Line->OnResetDevice();
	m_FpsFont->OnResetDevice();
	m_pInputKbd->Acquire();
	DXOnResetDevice();
	
}


LPD3DXSPRITE CDXWindow::DXCreateSprite()
{
	LPD3DXSPRITE pSprite=NULL;
	D3DXCreateSprite(m_pd3dDevice,&pSprite);
	return pSprite;
}


LPDIRECT3DTEXTURE9 CDXWindow::DXLoadTextureFromFile( LPCTSTR strPath,bool bRenderTarget,D3DCOLOR transcolor/*=D3DCOLOR_XRGB(255,0,255)*/ )
{
	LPDIRECT3DTEXTURE9 pTexture=NULL;
	D3DXIMAGE_INFO info;
	if(FAILED(D3DXGetImageInfoFromFile(strPath,&info)))
	{
		return 0;
	}
	if(FAILED(D3DXCreateTextureFromFileEx(m_pd3dDevice,strPath,info.Width,info.Height,1,bRenderTarget?D3DUSAGE_RENDERTARGET:0,D3DFMT_UNKNOWN,bRenderTarget?D3DPOOL_DEFAULT:D3DPOOL_MANAGED,D3DX_DEFAULT,D3DX_DEFAULT,transcolor,&info,0,&pTexture)))
	{
		return 0;
	}
	
	return pTexture;
}


LPDIRECTSOUNDBUFFER CDXWindow::DXLoadSound(LPCTSTR path)
{
	LPVOID lpPtr1;//指针1; 
	LPVOID lpPtr2;//指针2; 
	HRESULT hResult; 
	DWORD dwLen1,dwLen2; 
	LPVOID m_pMemory;//内存指针; 
	LPWAVEFORMATEX m_pFormat;//LPWAVEFORMATEX变量; 
	LPVOID m_pData;//指向语音数据块的指针; 
	DWORD m_dwSize;//WAVE文件中语音数据块的长度; 
	FILE* File=0;//Cfile对象; 
	DWORD dwSize;//存放WAV文件长度; 
	//打开sound.wav文件; 
#if _UNICODE
	USES_CONVERSION;
	File=fopen(W2A(path) , "rb");
#else	
	File=fopen(path , "rb");
#endif
	if (!File) 
		return 0; 
	fseek (File,0, SEEK_END);
	dwSize =ftell(File); //获取WAVE文件长度; 
	fseek (File,0, SEEK_SET);//定位到打开的WAVE文件头; 
	//为m_pMemory分配内存,类型为LPVOID,用来存放WAVE文件中的数据; 
	m_pMemory = GlobalAlloc (GMEM_FIXED, dwSize); 
	if (fread(m_pMemory,1,dwSize, File) != dwSize)//读取文件中的数据; 
			fclose(File);
		return 0; 
		fclose(File);
	LPDWORD pdw,pdwEnd; 
	DWORD dwRiff,dwType,dwLength; 


	//	if (m_pFormat) //格式块指针 
	m_pFormat = NULL; 
	//	if (m_pData) //数据块指针,类型:LPBYTE 
	m_pData = NULL; 
	//	if (m_dwSize) //数据长度,类型:DWORD 
	m_dwSize = 0; 
	pdw = (DWORD *) m_pMemory; 
	dwRiff = *pdw++; 
	dwLength = *pdw++; 
	dwType = *pdw++; 
	if (dwRiff != mmioFOURCC ( 'R', 'I', 'F', 'F')) 
		return 0;//判断文件头是否为 "RIFF "字符; 
	if (dwType != mmioFOURCC ( 'W', 'A', 'V', 'E')) 
		return 0;//判断文件格式是否为 "WAVE "; 
	//寻找格式块,数据块位置及数据长度 
	pdwEnd = (DWORD *)((BYTE *) m_pMemory+dwLength -4); 
	bool m_bend=false; 
	while ((pdw < pdwEnd)&&(!m_bend)) 
		//pdw文件没有指到文件末尾并且没有获取到声音数据时继续; 
			dwType = *pdw++; 
		dwLength = *pdw++; 
		switch (dwType) 
				case mmioFOURCC( 'f', 'm', 't', ' ')://如果为 "fmt "标志; 
			{
				if (!m_pFormat)//获取LPWAVEFORMATEX结构数据; 
									if (dwLength < sizeof (WAVEFORMAT)) 
						return 0; 
					m_pFormat = (LPWAVEFORMATEX) pdw; 
								break; 
			}
		case mmioFOURCC( 'd', 'a', 't', 'a')://如果为 "data "标志; 
			{
				if (!m_pData || !m_dwSize) 
									m_pData = (LPBYTE) pdw;//得到指向声音数据块的指针; 
					m_dwSize = dwLength;//获取声音数据块的长度; 
					if (m_pFormat) 
						m_bend=TRUE; 
								break; 
			}


				pdw = (DWORD *)((BYTE *) pdw + ((dwLength + 1)&~1));//修改pdw指针,继续循环; 
		DSBUFFERDESC BufferDesc;//定义DSUBUFFERDESC结构对象; 
	memset (&BufferDesc, 0, sizeof (BufferDesc)); 
	BufferDesc.lpwfxFormat = (LPWAVEFORMATEX)m_pFormat; 
	BufferDesc.dwSize = sizeof (DSBUFFERDESC); 
	BufferDesc.dwBufferBytes = m_dwSize; 
	BufferDesc.dwFlags = 0; 
	LPDIRECTSOUNDBUFFER m_pDSoundBuffer; 
	if (FAILED(m_pDirectSound-> CreateSoundBuffer (&BufferDesc, &m_pDSoundBuffer, 0) ))
	{
		return 0;
	}
	m_pDSoundBuffer-> Lock(0,m_dwSize,&lpPtr1,&dwLen1,&lpPtr2,&dwLen2,0); 
	memcpy (lpPtr1, m_pData, dwLen1); 
	if(dwLen2> 0) 
			BYTE *m_pData1=(BYTE*)m_pData+dwLen1; 
		m_pData=(void *)m_pData1; 
		memcpy(lpPtr2,m_pData, dwLen2); 
	}
	m_pDSoundBuffer-> Unlock (lpPtr1, dwLen1, lpPtr2, dwLen2); 
	return m_pDSoundBuffer;
}


IMediaControl * CDXWindow::DXLoadMusic(LPCTSTR path)
{
	IGraphBuilder *pGraphBuilder=0;
	IMediaControl *pMedia=0;
	if(FAILED(CoCreateInstance(CLSID_FilterGraph,0,CLSCTX_INPROC,IID_IGraphBuilder,(void**)&pGraphBuilder)))
	{
		return 0;
	}
	pGraphBuilder->QueryInterface(IID_IMediaControl,(void**)&pMedia);
	if(pMedia==NULL)
	{
		return 0;
	}
	WCHAR *wszPath;
#ifndef  _UNICODE
	USES_CONVERSION;
	wszPath=A2W(path);
#else
	wszPath=(LPTSTR)path;
#endif
	if(FAILED(pGraphBuilder->RenderFile(wszPath,0)))
	{
		return 0;
	}
	if(pGraphBuilder)
	{
		pGraphBuilder->Release();
	}
	return pMedia;
}


void CDXWindow::DXDrawControl(bool bInputEnabled)
{
	list<CDXControl*>::iterator it;
	for (it=m_pControlList.begin();it!=m_pControlList.end();it++)
	{
		if((*it)->IsWindowVisible())
		{
			(*it)->Draw();
		}


	}
	
}


LPDIRECT3DDEVICE9 CDXWindow::GetD3dDevice()
{
	return m_pd3dDevice;
}


bool CDXWindow::DXLButtonDown()
{
	if(m_MouseState.rgbButtons[0] & 0x80)
	{	
		return true;	
	}
	return false;
}




bool CDXWindow::DXRButtonDown()
{
	if(m_MouseState.rgbButtons[1] & 0x80)
	{	
		return true;	
	}
	return false;
}


void CDXWindow::DXProcessEvent(bool bInputEnabled)
{
	static bool bLDown=false,bRDown=false;
	int iX=0,iY=0;
	if(bInputEnabled)
	{
		if(DXLButtonDown() && !bLDown)
		{
			bLDown=true;
			list<CDXControl*>::reverse_iterator it;
			for(it=m_pControlList.rbegin();it!=m_pControlList.rend();it++)
			{
				if(!((*it)->IsWindowVisible()))
				{
					continue;
				}
				RECT rect=(*it)->GetRect();
				POINT p;
				GetCursorPos(&p);
				if(!m_bFullScreen)
				{
					ScreenToClient(m_hWnd,&p);
				}	
				iX=p.x-rect.left;
				iY=p.y-rect.top;
				if(PtInRect(&rect,p) && (*it)->IsWindowEnabled())
				{
					m_pFocusControl=*it;
					(*it)->SetCheck(true);
					(*it)->OnLButtonDown(iX,iY);
					break;
				}
			}
		}else if(!DXLButtonDown() && bLDown)
		{
			bLDown=false;
			list<CDXControl*>::reverse_iterator it;
			for(it=m_pControlList.rbegin();it!=m_pControlList.rend();it++)
			{
				if(!((*it)->IsWindowVisible()))
				{
					continue;
				}
				RECT rect=(*it)->GetRect();
				POINT p;
				GetCursorPos(&p);
				if(!m_bFullScreen)
				{
					ScreenToClient(m_hWnd,&p);
				}	
				iX=p.x-rect.left;
				iY=p.y-rect.top;
				if(PtInRect(&rect,p) && (*it)->IsWindowEnabled())
				{
					m_pFocusControl=*it;
					(*it)->SetCheck(false);
					(*it)->OnLButtonUp(iX,iY);
					break;
				}
			}
		}else if(DXRButtonDown() && !bRDown)
		{
			bRDown=true;
			list<CDXControl*>::reverse_iterator it;
			for(it=m_pControlList.rbegin();it!=m_pControlList.rend();it++)
			{
				if(!((*it)->IsWindowVisible()))
				{
					continue;
				}
				RECT rect=(*it)->GetRect();
				POINT p;
				GetCursorPos(&p);
				if(!m_bFullScreen)
				{
					ScreenToClient(m_hWnd,&p);
				}	
				iX=p.x-rect.left;
				iY=p.y-rect.top;
				if(PtInRect(&rect,p) && (*it)->IsWindowEnabled())
				{
					m_pFocusControl=*it;
					(*it)->SetCheck(true);
					(*it)->OnRButtonDown(iX,iY);
					break;
				}
			}
		}else if(!DXRButtonDown() && bRDown)
		{
			bRDown=false;
			list<CDXControl*>::reverse_iterator it;
			for(it=m_pControlList.rbegin();it!=m_pControlList.rend();it++)
			{
				if(!((*it)->IsWindowVisible()))
				{
					continue;
				}
				RECT rect=(*it)->GetRect();
				POINT p;
				GetCursorPos(&p);
				if(!m_bFullScreen)
				{
					ScreenToClient(m_hWnd,&p);
				}	
				iX=p.x-rect.left;
				iY=p.y-rect.top;
				if(PtInRect(&rect,p) && (*it)->IsWindowEnabled())
				{
					m_pFocusControl=*it;
					(*it)->SetCheck(false);
					(*it)->OnRButtonUp(iX,iY);
					break;
				}
			}
		}else
		{
			list<CDXControl*>::reverse_iterator it;
			bool bOver=false,bLeave=false,bMove=false;
			for(it=m_pControlList.rbegin();it!=m_pControlList.rend();it++)
			{
				if(!((*it)->IsWindowVisible()))
				{
					continue;
				}
				RECT rect=(*it)->GetRect();
				POINT p;
				GetCursorPos(&p);
				if(!m_bFullScreen)
				{
					ScreenToClient(m_hWnd,&p);
				}	
				iX=p.x-rect.left;
				iY=p.y-rect.top;
				if(PtInRect(&rect,p) && (*it)->IsWindowEnabled())
				{
					if(!(*it)->GetMouseOver())
					{
						if(!bOver)
						{
							(*it)->SetMouseOver(true);
							(*it)->SetMouseOverPoint(iX,iY);
							(*it)->OnMouseOver(iX,iY);
							bOver=true;
						}
					}else
					{
						POINT p=(*it)->GetMouseOverPoint();
						if(p.x!=iX || p.y!=iY)
						{
							if(!bMove)
							{
								(*it)->SetMouseOverPoint(iX,iY);
								(*it)->OnMouseMove(iX,iY);
								bMove=true;
							}
						}		
					}
				}else if(!PtInRect(&rect,p) && (*it)->IsWindowEnabled() && (*it)->GetMouseOver())
				{
					if(!bLeave)
					{
						(*it)->SetMouseOver(false);
						(*it)->SetMouseOverPoint(-1,-1);
						(*it)->OnMouseLeave(iX,iY);
						bLeave=true;
					}
					
				}
				if(bOver && bLeave && bMove)
				{
					break;
				}
			}
		}
	}
}


void CDXWindow::SetBKColor(D3DCOLOR color)
{
	m_BKColor=color;
}


void CDXWindow::SetFps( bool bFps )
{
	m_bFps=bFps;
}


void CDXWindow::DXOnLostDevice()
{
	
}


void CDXWindow::DXOnResetDevice()
{
	
}


void CDXWindow::DXDrawQuad(RECT *rect,D3DCOLOR bkColor/*=D3DCOLOR_XRGB(0,0,0)*/,bool bFill/*=true*/,float fLineWidth/*=0*/,IDirect3DTexture9 *pTex/*=0*/ )
{
	if(bFill)
	{
		CDXControl::sVertex vRect[4];
		vRect[0]=CDXControl::sVertex(rect->left,rect->top,0,1,bkColor,0,0);
		vRect[1]=CDXControl::sVertex(rect->right,rect->top,0,1,bkColor,1,0);
		vRect[2]=CDXControl::sVertex(rect->right,rect->bottom,0,1,bkColor,1,1);
		vRect[3]=CDXControl::sVertex(rect->left,rect->bottom,0,1,bkColor,0,1);
		IDirect3DVertexDeclaration9* pDecl = NULL;
		m_pd3dDevice->GetVertexDeclaration(&pDecl);
		m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
		m_pd3dDevice->SetVertexShader( NULL );
		m_pd3dDevice->SetPixelShader( NULL );
// 		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
// 		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
		m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 
		m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 
		m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 
		m_pd3dDevice->SetFVF(CDXControl::sVertex::FVF);
		if(pTex)
		{
			m_pd3dDevice->SetTexture(0,pTex);
		}
		m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vRect, sizeof( CDXControl::sVertex ) );
		m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
		m_pd3dDevice->SetVertexDeclaration(pDecl);
	}else
	{
		float fOldWidth=m_Line->GetWidth();
		if(fLineWidth>0.00001)
		{
			m_Line->SetWidth(fLineWidth);
		}
		D3DXVECTOR2 v[5];
		v[0].x=rect->left;
		v[0].y=rect->top;
		v[1].x=rect->right;
		v[1].y=rect->top;
		v[2].x=rect->right;
		v[2].y=rect->bottom;
		v[3].x=rect->left;
		v[3].y=rect->bottom;
		v[4].x=rect->left;
		v[4].y=rect->top;
		m_Line->Begin();
		m_Line->Draw(v,5,bkColor);
		m_Line->End();
		m_Line->SetWidth(fOldWidth);
	}
	
}


bool CDXWindow::GetFullScreen()
{
	return m_bFullScreen;
}


D3DMATERIAL9 CDXWindow::DXCreateMtrl( D3DCOLORVALUE ambient,D3DCOLORVALUE diffuse,D3DCOLORVALUE specular,D3DCOLORVALUE emissive,float power )
{
	D3DMATERIAL9 mtrl;
	mtrl.Ambient=ambient;
	mtrl.Diffuse=diffuse;
	mtrl.Emissive=emissive;
	mtrl.Specular=specular;
	mtrl.Power=power;
	return mtrl;
}


D3DLIGHT9 CDXWindow::DXCreateDirectionLight( D3DXVECTOR3 *dir,D3DCOLORVALUE ambient,D3DCOLORVALUE diffuse, D3DCOLORVALUE specular)
{
	D3DLIGHT9 light;
	ZeroMemory(&light,sizeof(light));
	light.Type=D3DLIGHT_DIRECTIONAL;
	light.Ambient=ambient;
	light.Diffuse=diffuse;
	light.Specular=specular;
	light.Direction=*dir;
	return light;
}


D3DLIGHT9 CDXWindow::DXCreatePointLight( D3DXVECTOR3 *pos,float range,D3DCOLORVALUE ambient,D3DCOLORVALUE diffuse, D3DCOLORVALUE specular, float att0)
{
	D3DLIGHT9 light;
	ZeroMemory(&light,sizeof(light));
	light.Type=D3DLIGHT_POINT;
	light.Ambient=ambient;
	light.Diffuse=diffuse;
	light.Specular=specular;
	light.Position=*pos;
	light.Range=range;
	light.Attenuation0=att0;light.Attenuation1=0;light.Attenuation2=0;   
	return light;
}


int CDXWindow::DXMouseMickeyX()
{
	return m_MouseState.lX;
}


int CDXWindow::DXMouseMickeyY()
{
	return m_MouseState.lY;
}


int CDXWindow::DXMouseMickeyZ()
{
	return m_MouseState.lZ;
}


ID3DXFont* CDXWindow::GetFpsFont()
{
	return m_FpsFont;
}








bool CDXControl::Create( CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,bool bShow/*=true*/ )
{
	m_pD3dWindow=pDxWin;
	m_bShow=bShow;
	m_bEnabled=true;
	m_bCheck=false;
	m_bAlpha=false;
	m_bMouseOver=false;
	m_iOverX=-1;
	m_iOverY=-1;
	m_pD3dWindow->m_pControlList.push_back(this);
	return true;
}


void CDXControl::ShowWindow( bool bShow )
{
	m_bShow=bShow;
}


bool CDXControl::IsWindowVisible()
{
	return m_bShow;
}


void CDXControl::MoveWindow( int iLeft,int iTop,int iWidth,int iHeight )
{
	m_ControlRect[0].x=iLeft;
	m_ControlRect[0].y=iTop;
	m_ControlRect[1].x=iLeft+iWidth-1;
	m_ControlRect[1].y=iTop;
	m_ControlRect[2].x=iLeft+iWidth-1;
	m_ControlRect[2].y=iTop+iHeight-1;
	m_ControlRect[3].x=iLeft;
	m_ControlRect[3].y=iTop+iHeight-1;
}


void CDXControl::SetTopWindow()
{
	remove(m_pD3dWindow->m_pControlList.begin(),m_pD3dWindow->m_pControlList.end(),this);
	m_pD3dWindow->m_pControlList.push_back(this);
}


void CDXControl::EnableWindow( bool bEnabled )
{
	m_bEnabled=bEnabled;
}


bool CDXControl::IsWindowEnabled()
{
	return m_bEnabled;
}


void CDXControl::DestoryWindow()
{
	m_pD3dWindow->m_pControlList.remove(this);
}


CDXControl::CDXControl()
{
	memset(this,0,sizeof(*this));
}


CDXControl::~CDXControl()
{


}


void CDXControl::SetCheck( bool bCheck )
{
	m_bCheck=bCheck;
}


bool CDXControl::GetCheck()
{
	return m_bCheck;
}


void CDXControl::SetVertexAlpha( bool bAlpha )
{
	m_bAlpha=bAlpha;
}


void CDXControl::SetMouseOver( bool bMouseOver )
{
	m_bMouseOver=bMouseOver;
}


bool CDXControl::GetMouseOver()
{
	return m_bMouseOver;
}


void CDXControl::SetMouseOverPoint( int x,int y )
{
	m_iOverX=x;
	m_iOverY=y;
}


POINT CDXControl::GetMouseOverPoint()
{
	POINT p={m_iOverX,m_iOverY};
	return p;
}






bool CDXStatic::Create( CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,bool bShow/*=true*/ )
{
	if(!CDXControl::Create(pDxWin,iLeft,iTop,iWidth,iHeight,bShow))
	{
		return false;
	}
	m_ControlRect=new sVertex[4];
	m_ControlRect[0]=sVertex(iLeft,iTop,0,1,D3DCOLOR_XRGB(0,0,0),0,0);
	m_ControlRect[1]=sVertex(iLeft+iWidth-1,iTop,0,1,D3DCOLOR_XRGB(0,0,0),0,0);
	m_ControlRect[2]=sVertex(iLeft+iWidth-1,iTop+iHeight-1,0,1,D3DCOLOR_XRGB(0,0,0),0,0);
	m_ControlRect[3]=sVertex(iLeft,iTop+iHeight-1,0,1,D3DCOLOR_XRGB(0,0,0),0,0);
	m_iStyle=DT_LEFT|DT_TOP;
	m_BkColor=0;
	m_strText=0;
	m_Font=0;
	m_Font=m_pD3dWindow->DXCreateFont();
	if(m_Font)
	{
		return true;
	}else
	{
		return false;
	}
	
}


void CDXStatic::DestoryWindow()
{
	if(m_strText)
	{
		delete[] m_strText;
	}
	if(m_Font)
	{
		m_Font->Release();
	}
	delete[] m_ControlRect;
	CDXControl::DestoryWindow();
}


void CDXStatic::Draw()
{
	if(m_BkColor)
	{
		IDirect3DVertexDeclaration9* pDecl = NULL;
		m_pD3dWindow->GetD3dDevice()->GetVertexDeclaration(&pDecl);
		if(m_bAlpha)
		{
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, true); 
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 
		}
		m_pD3dWindow->GetD3dDevice()->SetVertexShader( NULL );
		m_pD3dWindow->GetD3dDevice()->SetPixelShader( NULL );
		//m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
		//m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
		m_pD3dWindow->GetD3dDevice()->SetFVF(sVertex::FVF);
		m_pD3dWindow->GetD3dDevice()->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, m_ControlRect, sizeof( sVertex ) );
		if(m_bAlpha)
		{
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, false); 
		}
		m_pD3dWindow->GetD3dDevice()->SetVertexDeclaration(pDecl);
	}


	RECT r={m_ControlRect[0].x,m_ControlRect[0].y,m_ControlRect[2].x+1,m_ControlRect[2].y+1};
	m_Font->DrawTextW(0,m_strText,-1,&r,m_iStyle,m_ForeColor);
}


void CDXStatic::SetBKColor( D3DCOLOR color )
{
	m_BkColor=color;
	for(int i=0;i<4;i++)
	{
		m_ControlRect[i].color=color;
	}
}


void CDXStatic::SetText( LPCTSTR strText )
{
	if(m_strText)
	{
		delete[] m_strText;
	}
	m_strText=new TCHAR[_tcslen(strText)+sizeof(TCHAR)];
	_tcscpy(m_strText,strText);
}


LPCTSTR CDXStatic::GetText()
{
	return m_strText;
}


void CDXStatic::SetFont( int iHeight,LPCTSTR strFont )
{
	if(m_Font)
	{
		m_Font->Release();
		m_Font=0;
	}
	m_Font=m_pD3dWindow->DXCreateFont(iHeight,strFont);
}


void CDXStatic::SetForeColor( D3DCOLOR color )
{
	m_ForeColor=color;
}


void CDXStatic::SetStyle( int iStyle )
{
	m_iStyle=iStyle;
}


void CDXStatic::DXOnLostDevice()
{
	m_Font->OnLostDevice();
}


void CDXStatic::DXOnResetDevice()
{
	m_Font->OnResetDevice();
}


RECT CDXStatic::GetRect()
{
	RECT r;
	r.left=m_ControlRect[0].x;
	r.top=m_ControlRect[0].y;
	r.right=m_ControlRect[2].x+1;
	r.bottom=m_ControlRect[2].y+1;
	return r;
}


bool CDXButton::Create( CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,bool bShow/*=true*/ )
{
	if(!CDXControl::Create(pDxWin,iLeft,iTop,iWidth,iHeight,bShow))
	{
		return false;
	}
	m_ControlRect=new sVertex[10];
	m_ControlRect[0]=sVertex(iLeft+iWidth/2,iTop+iHeight/2,0,1,D3DCOLOR_ARGB(255,200,200,200),0.5,0.5);
	m_ControlRect[1]=sVertex(iLeft,iTop,0,1,D3DCOLOR_ARGB(0,10,10,10),0,0);
	m_ControlRect[2]=sVertex(iLeft+iWidth/2,iTop,0,1,D3DCOLOR_ARGB(0,10,10,10),0.5,0);
	m_ControlRect[3]=sVertex(iLeft+iWidth-1,iTop,0,1,D3DCOLOR_ARGB(0,10,10,10),1,0);
	m_ControlRect[4]=sVertex(iLeft+iWidth-1,iTop+iHeight/2,0,1,D3DCOLOR_ARGB(0,10,10,10),1,0.5);
	m_ControlRect[5]=sVertex(iLeft+iWidth-1,iTop+iHeight-1,0,1,D3DCOLOR_ARGB(0,10,10,10),1,1);
	m_ControlRect[6]=sVertex(iLeft+iWidth/2,iTop+iHeight-1,0,1,D3DCOLOR_ARGB(0,10,10,10),0.5,1);
	m_ControlRect[7]=sVertex(iLeft,iTop+iHeight-1,0,1,D3DCOLOR_ARGB(0,10,10,10),0,1);
	m_ControlRect[8]=sVertex(iLeft,iTop+iHeight/2,0,1,D3DCOLOR_ARGB(0,10,10,10),0,0.5);
	m_ControlRect[9]=sVertex(iLeft,iTop,0,1,D3DCOLOR_ARGB(0,10,10,10),0,0);
	m_pTexture=0;
	m_strText=0;
	m_Font=0;
	m_Font=m_pD3dWindow->DXCreateFont();
	if(m_Font)
	{
		return true;
	}else
	{
		return false;
	}


}


void CDXButton::DestoryWindow()
{
	if(m_strText)
	{
		delete[] m_strText;
	}
	if(m_Font)
	{
		m_Font->Release();
	}
	delete[] m_ControlRect;
	CDXControl::DestoryWindow();
}


void CDXButton::Draw()
{


		IDirect3DVertexDeclaration9* pDecl = NULL;
		m_pD3dWindow->GetD3dDevice()->GetVertexDeclaration(&pDecl);
		if(m_bAlpha)
		{
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, true); 
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 
		}
		m_pD3dWindow->GetD3dDevice()->SetVertexShader( NULL );
		m_pD3dWindow->GetD3dDevice()->SetPixelShader( NULL );
		m_pD3dWindow->GetD3dDevice()->SetFVF(sVertex::FVF);
		if(m_pTexture)
		{
			m_pD3dWindow->GetD3dDevice()->SetTexture(0,m_pTexture);
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_ADD );
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );


			m_pD3dWindow->GetD3dDevice()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 
			m_pD3dWindow->GetD3dDevice()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		}	
		sVertex Vertes[10];
		if(GetCheck())
		{
			
			for(int i=0;i<10;i++)
			{
				Vertes[i]=m_ControlRect[i];
				Vertes[i].x+=2;
				Vertes[i].y+=2;
			}
			m_pD3dWindow->GetD3dDevice()->DrawPrimitiveUP( D3DPT_TRIANGLEFAN,8, Vertes, sizeof( sVertex ) );
			for(int i=0;i<10;i++)
			{
				Vertes[i].color=D3DCOLOR_XRGB(122,122,122);
			}
			m_pD3dWindow->GetD3dDevice()->SetTexture(0,0);
			m_pD3dWindow->GetD3dDevice()->DrawPrimitiveUP( D3DPT_LINESTRIP, 8, Vertes+1, sizeof( sVertex ) );
			RECT r={Vertes[1].x,Vertes[1].y,Vertes[5].x+1,Vertes[5].y+1};
			if(m_strText)
			{
				m_Font->DrawTextW(0,m_strText,-1,&r,DT_CENTER|DT_VCENTER,m_ForeColor);
			}
			


		}else
		{
			m_pD3dWindow->GetD3dDevice()->DrawPrimitiveUP( D3DPT_TRIANGLEFAN,8, m_ControlRect, sizeof( sVertex ) );
			D3DCOLOR color[10];
			for(int i=0;i<10;i++)
			{
				color[i]=m_ControlRect[i].color;
				m_ControlRect[i].color=D3DCOLOR_XRGB(122,122,122);
			}
			m_pD3dWindow->GetD3dDevice()->SetTexture(0,0);
			m_pD3dWindow->GetD3dDevice()->DrawPrimitiveUP( D3DPT_LINESTRIP, 8, m_ControlRect+1, sizeof( sVertex ) );
			for(int i=0;i<10;i++)
			{
				m_ControlRect[i].color=color[i];
			}
			RECT r={m_ControlRect[1].x,m_ControlRect[1].y,m_ControlRect[5].x+1,m_ControlRect[5].y+1};
			if(m_strText)
			{
				m_Font->DrawTextW(0,m_strText,-1,&r,DT_CENTER|DT_VCENTER,m_ForeColor);
			}
			
		}	
		if(m_bAlpha)
		{
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, false); 
		}
		m_pD3dWindow->GetD3dDevice()->SetVertexDeclaration(pDecl);
		
}


void CDXButton::SetBKColor( D3DCOLOR color )
{
	color=color & 0x00ffffff;
	m_ControlRect[0].color=D3DCOLOR_ARGB(255,200,200,200);
	for(int i=1;i<10;i++)
	{
		m_ControlRect[i].color=m_ControlRect[i].color & 0xff000000;	


		m_ControlRect[i].color|=color;
 	}


}


void CDXButton::SetText( LPCTSTR strText )
{
	if(m_strText)
	{
		delete[] m_strText;
	}
	m_strText=new TCHAR[_tcslen(strText)+sizeof(TCHAR)];
	_tcscpy(m_strText,strText);
}


LPCTSTR CDXButton::GetText()
{
	return m_strText;
}


void CDXButton::SetFont( int iHeight,LPCTSTR strFont )
{
	if(m_Font)
	{
		m_Font->Release();
		m_Font=0;
	}
	m_Font=m_pD3dWindow->DXCreateFont(iHeight,strFont);
}


void CDXButton::SetForeColor( D3DCOLOR color )
{
	m_ForeColor=color;
}


void CDXButton::DXOnLostDevice()
{
	m_Font->OnLostDevice();
}


void CDXButton::DXOnResetDevice()
{
	m_Font->OnResetDevice();
}


bool CDXButton::SetBkImg( LPCTSTR path )
{
	if(m_pTexture)
	{
		m_pTexture->Release();
		m_pTexture=0;
	}
	if(path==0)
	{
		return true;
	}
	m_pTexture=m_pD3dWindow->DXLoadTextureFromFile(path);
	if(m_pTexture)
	{
		return true;
	}
	return false;
}


RECT CDXButton::GetRect()
{
	RECT r;
	r.left=m_ControlRect[1].x;
	r.top=m_ControlRect[1].y;
	r.right=m_ControlRect[5].x+1;
	r.bottom=m_ControlRect[5].y+1;
	return r;
}


void CDXButton::OnLButtonDown(int x,int y)
{
	//MessageBox(0,0,0,0);
}


void CDXButton::OnLButtonUp(int x,int y)
{


}


void CDXButton::OnRButtonDown(int x,int y)
{


}


void CDXButton::OnRButtonUp(int x,int y)
{


}




bool CDXEdit::Create( CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,bool bShow/*=true*/ )
{
	if(!CDXStatic::Create(pDxWin,iLeft,iTop,iWidth,iHeight,bShow))
	{
		return false;
	}
	SetBKColor(D3DCOLOR_XRGB(225,225,225));
	memset(m_strText,0,sizeof(m_strText));
	m_iCount=0;
	m_iCurBegin=0;
	m_iCurPos=0;
	m_ForeColor=D3DCOLOR_XRGB(10,10,10);
	SetFont(iHeight,_T("宋体"));
	return true;
}


void CDXEdit::Draw()
{
	static DWORD dPreTime=GetTickCount(),dDelay=20;
	if(m_BkColor)
	{
		IDirect3DVertexDeclaration9* pDecl = NULL;
		m_pD3dWindow->GetD3dDevice()->GetVertexDeclaration(&pDecl);
		m_pD3dWindow->GetD3dDevice()->SetVertexShader( NULL );
		m_pD3dWindow->GetD3dDevice()->SetPixelShader( NULL );
		m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
		m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
		m_pD3dWindow->GetD3dDevice()->SetFVF(sVertex::FVF);
		m_pD3dWindow->GetD3dDevice()->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, m_ControlRect, sizeof( sVertex ) );
		m_pD3dWindow->GetD3dDevice()->SetVertexDeclaration(pDecl);
	}


	RECT r={m_ControlRect[0].x,m_ControlRect[0].y,m_ControlRect[2].x+1,m_ControlRect[2].y+1};
	m_Font->DrawTextW(0,m_strText+m_iCurBegin,m_iCount,&r,DT_TOP|DT_LEFT,m_ForeColor);
	if(m_pD3dWindow->GetFocusControl()==(CDXControl*)this)
	{
		if(GetTickCount()-dPreTime>1000)
		{
			if(dDelay)
			{
				sVertex Vert[2];
				Vert[0]=sVertex(m_iBlinkLeft,GetRect().top+1,0,1,D3DCOLOR_XRGB(0,0,255),0,0);
				Vert[1]=sVertex(m_iBlinkLeft,GetRect().top+m_iBlinkHeight,0,1,D3DCOLOR_XRGB(0,0,255),0,0);
				IDirect3DVertexDeclaration9* pDecl = NULL;
				m_pD3dWindow->GetD3dDevice()->GetVertexDeclaration(&pDecl);
				m_pD3dWindow->GetD3dDevice()->SetVertexShader( NULL );
				m_pD3dWindow->GetD3dDevice()->SetPixelShader( NULL );
				m_pD3dWindow->GetD3dDevice()->SetFVF(sVertex::FVF);
				m_pD3dWindow->GetD3dDevice()->DrawPrimitiveUP( D3DPT_LINELIST, 1, Vert, sizeof( sVertex ) );
				m_pD3dWindow->GetD3dDevice()->SetVertexDeclaration(pDecl);
				dDelay--;
			}
			else
			{
				dDelay=20;
				dPreTime=GetTickCount();
			}
			
			
		}
	}
}


void CDXEdit::OnChar( UINT ch )
{
	if(ch==VK_BACK)
	{
		if(m_iCurPos==0)
		{
			return;
		}
		memmove(m_strText+m_iCurPos-1,m_strText+m_iCurPos,(m_iCount-m_iCurPos)*sizeof(TCHAR));
		m_strText[m_iCount-1]=0;
		m_iCount--;
		m_iCurPos--;
		if(m_iCurPos<m_iCurBegin && m_iCurBegin>0)
		{
			m_iCurBegin--;
		}
		RECT r={0,0,0,0};
		m_Font->DrawTextW(0,m_strText+m_iCurBegin,m_iCurPos-m_iCurBegin,&r,DT_CALCRECT|DT_LEFT|DT_TOP,m_ForeColor);
		m_iBlinkLeft=GetRect().left+(r.right-r.left);
	}else if(ch==VK_DELETE)
	{
		if(m_iCurPos==m_iCount)
		{
			return;
		}
		memmove(m_strText+m_iCurPos,m_strText+m_iCurPos+1,(m_iCount-m_iCurPos)*sizeof(TCHAR));
		m_strText[m_iCount-1]=0;
		m_iCount--;
	}else if(ch==VK_LEFT)
	{
		if(m_iCurPos==0)
		{
			return;
		}
		m_iCurPos--;
		if(m_iCurPos<m_iCurBegin && m_iCurBegin>0)
		{
			m_iCurBegin--;
			m_iBlinkLeft=GetRect().left+1;
		}else
		{
			RECT r={0,0,0,0};
			m_Font->DrawTextW(0,m_strText+m_iCurBegin,m_iCurPos-m_iCurBegin,&r,DT_CALCRECT|DT_LEFT|DT_TOP,m_ForeColor);
			m_iBlinkLeft=GetRect().left+(r.right-r.left);
		}
		
		
	}else if(ch==VK_RIGHT)
	{
		if(m_iCurPos==m_iCount)
		{
			return;
		}
		m_iCurPos++;
		RECT r={0,0,0,0};
		m_Font->DrawTextW(0,m_strText+m_iCurBegin,m_iCurPos-m_iCurBegin,&r,DT_CALCRECT|DT_LEFT|DT_TOP,m_ForeColor);
		while(r.right-r.left>=GetRect().right-GetRect().left)
		{
			m_iCurBegin++;
			m_Font->DrawTextW(0,m_strText+m_iCurBegin,m_iCurPos-m_iCurBegin,&r,DT_CALCRECT|DT_LEFT|DT_TOP,m_ForeColor);


		}
		m_iBlinkLeft=GetRect().left+(r.right-r.left);
	}
	else
	{
		if(m_iCount==1024)
		{
			return;
		}
		memmove(m_strText+m_iCurPos+1,m_strText+m_iCurPos,(m_iCount-m_iCurPos)*sizeof(TCHAR));
		m_strText[m_iCurPos]=ch;
		m_iCurPos++;
		m_iCount++;
		RECT r={0,0,0,0};
		m_Font->DrawTextW(0,m_strText+m_iCurBegin,m_iCurPos-m_iCurBegin,&r,DT_CALCRECT|DT_LEFT|DT_TOP,m_ForeColor);
		while(r.right-r.left>=GetRect().right-GetRect().left)
		{
			m_iCurBegin++;
			memset(&r,0,sizeof(r));
			m_Font->DrawTextW(0,m_strText+m_iCurBegin,m_iCurPos-m_iCurBegin,&r,DT_CALCRECT|DT_LEFT|DT_TOP,m_ForeColor);


		}
		m_iBlinkLeft=GetRect().left+(r.right-r.left);
	}	
	




}


void CDXEdit::OnLButtonDown(int x,int y)
{
	POINT pi;
	GetCursorPos(&pi);
	ScreenToClient(m_pD3dWindow->GetHwnd(),&pi);
	int iLeft=pi.x-GetRect().left;
	TEXTMETRICW tm;
	m_Font->GetTextMetricsW(&tm);
	if(m_iCount==0)
	{
		m_iBlinkLeft=GetRect().left+1;
		m_iCurPos=0;
	}else
	{
		int iTextPreLeft=1;
		for(int i=1;i<=m_iCount;i++)
		{
			RECT r={0,0,0,0};
			m_Font->DrawTextW(0,m_strText+m_iCurBegin,i,&r,DT_CALCRECT|DT_LEFT|DT_TOP,m_ForeColor);
			int iTextLeft=r.right-r.left;
			if(iLeft>=iTextPreLeft && iLeft<iTextLeft)
			{
				m_iBlinkLeft=GetRect().left+iTextPreLeft;
				m_iCurPos=i-1+m_iCurBegin;
				break;
			}
			iTextPreLeft=iTextLeft;
		}
		RECT r={0,0,0,0};
		m_Font->DrawTextW(0,m_strText,m_iCount,&r,DT_CALCRECT|DT_LEFT|DT_TOP,m_ForeColor);
		if(iLeft>=r.right-r.left)
		{
			m_iBlinkLeft=GetRect().left+iTextPreLeft;
			m_iCurPos=m_iCount;
		}
	}
	int iHeight=m_ControlRect[3].y-m_ControlRect[0].y;
	m_iBlinkHeight=tm.tmHeight>iHeight?iHeight:tm.tmHeight;
}


void CDXEdit::SetText( LPCTSTR strText )
{
	if(_tcslen(strText)>1024)
	{
		return;
	}
	_tcscpy(m_strText,strText);
	m_iCount=_tcslen(strText);
	m_iCurPos=0;
	m_iCurBegin=0;
	m_iBlinkLeft=GetRect().left+1;
}


LPCTSTR CDXEdit::GetText()
{
	return m_strText;
}


void CDXEdit::DestoryWindow()
{


}




bool CDXListBox::Create( CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,int iHeight,int iItemHeight,bool bShow/*=true*/ )
{
	if(!CDXControl::Create(pDxWin,iLeft,iTop,iWidth,iHeight,bShow))
	{
		return false;
	}
	m_ControlRect=new sVertex[4];
	m_ControlRect[0]=sVertex(iLeft,iTop,0,1,D3DCOLOR_XRGB(200,200,200),0,0);
	m_ControlRect[1]=sVertex(iLeft+iWidth-1,iTop,0,1,D3DCOLOR_XRGB(200,200,200),0,0);
	m_ControlRect[2]=sVertex(iLeft+iWidth-1,iTop+iHeight-1,0,1,D3DCOLOR_XRGB(200,200,200),0,0);
	m_ControlRect[3]=sVertex(iLeft,iTop+iHeight-1,0,1,D3DCOLOR_XRGB(200,200,200),0,0);
	m_iItemHeight=iItemHeight;
	m_iSelectedIndex=-1;
	m_Tex=0;
	m_Sur=0;
	m_Spr=0;
	m_fRate=0;
	m_bDrag=false;
	m_iDrawPos=0;
	m_ForeColor=D3DCOLOR_XRGB(0,0,0);
	m_iDrawY=0;
	m_iOffsetY=0;
	m_BkColor=D3DCOLOR_XRGB(255,255,255);
	m_Font=m_pD3dWindow->DXCreateFont(iItemHeight/2);
	SetRect(&m_ClientRect,0,0,iWidth-m_iEdgeSize-1,iHeight-1);
	SetRect(&m_UpRect,iWidth-m_iEdgeSize-1,0,iWidth-1,m_iEdgeSize-1);
	SetRect(&m_DownRect,iWidth-m_iEdgeSize-1,iHeight-m_iEdgeSize-1,iWidth-1,iHeight-1);
	SetRect(&m_SliderRect,iWidth-m_iEdgeSize-1,0,iWidth-1,0);
	m_iMaxPageCount=(iHeight%iItemHeight==0)?(iHeight/iItemHeight+1):(iHeight/iItemHeight+2);
	if(FAILED(m_pD3dWindow->GetD3dDevice()->CreateTexture(iWidth-m_iEdgeSize,iItemHeight*m_iMaxPageCount,1,D3DUSAGE_RENDERTARGET,D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT,&m_Tex,0)))
	{
		return false;
	}
	m_Tex->GetSurfaceLevel(0,&m_Sur);
	m_Spr=m_pD3dWindow->DXCreateSprite();
	return true;
}


void CDXListBox::Draw()
{
	if(m_ItemTextList.size()==0)
	{
		return;
	}
	IDirect3DSurface9 *pCurSurface=0;
	m_pD3dWindow->GetD3dDevice()->GetRenderTarget(0,&pCurSurface);
	m_pD3dWindow->GetD3dDevice()->SetRenderTarget(0,m_Sur);
	m_pD3dWindow->GetD3dDevice()->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, m_BkColor, 1.0f, 0);
	m_pD3dWindow->GetD3dDevice()->BeginScene();
	list<LPCTSTR>::iterator it=m_ItemTextList.begin();
	int i=0;
	while(i!=m_iDrawPos)
	{
		it++;
		i++;
	}
	for (int n=0;n<m_iMaxPageCount;n++)
	{
		if(i+n>=m_ItemTextList.size())
		{
			break;
		}
		RECT r={0,n*m_iItemHeight,m_ClientRect.right,(n+1)*m_iItemHeight-1};
		if(i+n==m_iSelectedIndex)
		{
			m_pD3dWindow->DXDrawQuad(&r,D3DCOLOR_XRGB(0,0,255));
		}
		m_Font->DrawTextW(0,(*it),_tcslen((*it)),&r,DT_CENTER|DT_VCENTER,m_ForeColor);
		SetRect(&r,0,(n+1)*m_iItemHeight-1,m_ClientRect.right,(n+1)*m_iItemHeight);
		m_pD3dWindow->DXDrawQuad(&r,D3DCOLOR_XRGB(111,11,11));
		it++;
	}
	m_pD3dWindow->GetD3dDevice()->EndScene();
	m_pD3dWindow->GetD3dDevice()->SetRenderTarget(0,pCurSurface);
	pCurSurface->Release();
	m_Spr->Begin(D3DXSPRITE_ALPHABLEND);
	RECT r={0,m_iDrawY,m_ClientRect.right-m_ClientRect.left,m_iDrawY+m_ClientRect.bottom-m_ClientRect.top};
	D3DXVECTOR3 v(m_ControlRect[0].x,m_ControlRect[0].y,0);
	m_Spr->Draw(m_Tex,&r,0,&v,D3DCOLOR_XRGB(255,255,255));
	m_Spr->End();
	r=m_UpRect;
	OffsetRect(&r,m_ControlRect[0].x,m_ControlRect[0].y);
	m_pD3dWindow->DXDrawQuad(&r,D3DCOLOR_XRGB(111,111,111));
	r=m_DownRect;
	OffsetRect(&r,m_ControlRect[0].x,m_ControlRect[0].y);
	m_pD3dWindow->DXDrawQuad(&r,D3DCOLOR_XRGB(111,111,111));
	if(m_SliderRect.bottom!=0)
	{
		r=m_SliderRect;
		OffsetRect(&r,m_ControlRect[0].x,m_ControlRect[0].y);
		m_pD3dWindow->DXDrawQuad(&r,D3DCOLOR_XRGB(211,211,211));
	}
}




int CDXListBox::GetSelectedItem()
{
	return m_iSelectedIndex;
}


LPCTSTR CDXListBox::GetItemText( int iIndex )
{
	int iItemCount=m_ItemTextList.size();
	if(iIndex>=iItemCount)
		return 0;
	list<LPCTSTR>::iterator it=m_ItemTextList.begin();
	for(int i=0;i<iItemCount;i++)
	{
		if(i==iIndex)
		{
			return (*it);
		}
		it++;
	}
	return 0;
}


int CDXListBox::GetItemCount()
{
	return m_ItemTextList.size();
}


bool CDXListBox::SetItemText( int iIndex,LPCTSTR strItem )
{
	int iItemCount=m_ItemTextList.size();
	if(iIndex>=iItemCount)
		return false;
	list<LPCTSTR>::iterator it=m_ItemTextList.begin();
	for(int i=0;i<iItemCount;i++)
	{
		if(i==iIndex)
		{
			if((*it))
			{
				delete[] (*it);
				(*it)=new TCHAR[_tcslen(strItem)+1];
				_tcscpy((TCHAR*)(*it),strItem);
			}
			break;
		}
		it++;
	}
	return true;
}


void CDXListBox::AddItem( LPCTSTR strItem )
{
	LPTSTR strNewItem=new TCHAR[_tcslen(strItem)+1];
	_tcscpy(strNewItem,strItem);
	m_ItemTextList.push_back(strNewItem);
	CalcData();
}


bool CDXListBox::DeleteItem( int iIndex )
{
	int iItemCount=m_ItemTextList.size();
	if(iIndex>=iItemCount)
		return false;
	list<LPCTSTR>::iterator it=m_ItemTextList.begin();
	for(int i=0;i<iItemCount;i++)
	{
		if(i==iIndex)
		{
			if((*it))
			{
				delete[] (*it);
			}
			m_ItemTextList.erase(it);
			break;
		}
		it++;
	}
	CalcData();
	return true;
}








void CDXListBox::DestoryWindow()
{
	list<LPCTSTR>::iterator it=m_ItemTextList.begin();
	for(;it!=m_ItemTextList.end();it++)
	{
		if((*it))
		{
			delete[] (*it);
		}
	}
	if(m_Tex)
	{
		m_Tex->Release();
	}
	if(m_Sur)
	{
		m_Sur->Release();
	}
	if(m_Spr)
	{
		m_Spr->Release();
	}
	if(m_Font)
	{
		m_Font->Release();
	}
	CDXControl::DestoryWindow();
}


RECT CDXListBox::GetRect()
{
	RECT r;
	r.left=m_ControlRect[0].x;
	r.top=m_ControlRect[0].y;
	r.right=m_ControlRect[2].x+1;
	r.bottom=m_ControlRect[2].y+1;
	return r;
}


void CDXListBox::OnLButtonDown( int x,int y )
{
	POINT p={x,y};
	if(PtInRect(&m_SliderRect,p))
	{
		m_bDrag=true;
		m_iOffsetY=y-m_SliderRect.top;
	}else if(PtInRect(&m_UpRect,p))
	{
		m_bDrag=true;
		OnMouseMove(m_SliderRect.left,m_SliderRect.top+m_iOffsetY-2);
		m_bDrag=false;
	}else if(PtInRect(&m_DownRect,p))
	{
		m_bDrag=true;
		OnMouseMove(m_SliderRect.left,m_SliderRect.top+m_iOffsetY+2);
		m_bDrag=false;
	}else if(PtInRect(&m_ClientRect,p))
	{
		m_iSelectedIndex=m_iDrawPos+(y+m_iDrawY)/m_iItemHeight;
	}
}


void CDXListBox::OnMouseMove( int x,int y )
{
	POINT p={x,y};
	if(m_SliderRect.top>0  && m_bDrag)
	{
		int iHeight=m_SliderRect.bottom-m_SliderRect.top;
		m_SliderRect.top=y-m_iOffsetY;
		if(m_SliderRect.top<m_iEdgeSize)
		{
			m_SliderRect.top=m_iEdgeSize;


		}else if(m_SliderRect.top+iHeight>m_DownRect.top)
		{
			m_SliderRect.top=m_DownRect.top-iHeight;
		}
		m_SliderRect.bottom=m_SliderRect.top+iHeight;
		int iMoveY=m_SliderRect.top-m_UpRect.bottom-1;
		if(iMoveY>0)
		{
			int iY=iMoveY/m_fRate;
			m_iDrawPos=iY/m_iItemHeight;
			m_iDrawY=iY%m_iItemHeight;
		}else
		{
			m_iDrawPos=0;
			m_iDrawY=0;
		}
	}
}


void CDXListBox::OnLButtonUp( int x,int y )
{
	m_bDrag=false;
}


void CDXListBox::OnMouseLeave( int x,int y )
{
	m_bDrag=false;
}


void CDXListBox::CalcData()
{
	m_SliderRect.top=m_UpRect.bottom+1;
	int iTotleHeight=m_iItemHeight*m_ItemTextList.size();
	int iDrawHeight=m_ClientRect.bottom-m_ClientRect.top+1;
	int iMaxSliderLen=m_DownRect.top-m_UpRect.bottom-m_iMinSliderHeight;
	int iExtHeight=0;
	if(iTotleHeight>iDrawHeight)
	{
		iExtHeight=iTotleHeight-iDrawHeight;
		if(iExtHeight>iMaxSliderLen)
		{
			m_fRate=iMaxSliderLen*1.0/iExtHeight;
			m_SliderRect.bottom=m_SliderRect.top+m_iMinSliderHeight-1;
		}
		else
		{
			m_fRate=0;
			m_SliderRect.bottom=m_SliderRect.top+((m_DownRect.top-m_UpRect.bottom)-iExtHeight)-1;
		}
		
	}


}


void CDXListBox::SetBKColor( D3DCOLOR color )
{
	m_BkColor=color;
	for(int i=0;i<4;i++)
	{
		m_ControlRect[i].color=color;
	}
}


void CDXListBox::SetForeColor( D3DCOLOR color )
{
	m_ForeColor=color;
}


void CDXListBox::SetFont( int iHeight,LPCTSTR strFont )
{
	if(m_Font)
	{
		m_Font->Release();
		m_Font=0;
	}
	m_Font=m_pD3dWindow->DXCreateFont(iHeight,strFont);
}


void CDXListBox::DXOnLostDevice()
{
	if(m_Font)
	{
		m_Font->OnLostDevice();
	}
	if(m_Spr)
	{
		m_Spr->OnLostDevice();
	}
	if(m_Sur)
	{
		m_Sur->Release();
	}
	if(m_Tex)
	{
		m_Tex->Release();
	}
}


void CDXListBox::DXOnResetDevice()
{
	if(m_Font)
	{
		m_Font->OnResetDevice();
	}
	if(m_Spr)
	{
		m_Spr->OnResetDevice();
	}
	if(m_Tex)
	{
		m_pD3dWindow->GetD3dDevice()->CreateTexture(m_ClientRect.right-m_ClientRect.left,m_iItemHeight*m_iMaxPageCount,1,D3DUSAGE_RENDERTARGET,D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT,&m_Tex,0);		
	}
	if(m_Sur)
	{
		m_Tex->GetSurfaceLevel(0,&m_Sur);
	}
	
}


bool CDXMutiplyStatic::Create( CDXWindow* pDxWin,int iLeft,int iTop,int iWidth,bool bShow/*=true*/ )
{
	if(!CDXControl::Create(pDxWin,iLeft,iTop,iWidth,1,bShow))
	{
		return false;
	}
	m_ControlRect=new sVertex[4];
	m_ControlRect[0]=sVertex(iLeft,iTop,0,1,D3DCOLOR_XRGB(0,0,0),0,0);
	m_ControlRect[1]=sVertex(iLeft+iWidth-1,iTop,0,1,D3DCOLOR_XRGB(0,0,0),0,0);
	m_ControlRect[2]=sVertex(iLeft+iWidth-1,iTop+1-1,0,1,D3DCOLOR_XRGB(0,0,0),0,0);
	m_ControlRect[3]=sVertex(iLeft,iTop+1-1,0,1,D3DCOLOR_XRGB(0,0,0),0,0);
	m_iStyle=DT_LEFT|DT_TOP;
	m_BkColor=0;
	m_strText=0;
	m_Font=0;
	m_Font=m_pD3dWindow->DXCreateFont();
	m_iWidth=iWidth;
	if(m_Font)
	{
		return true;
	}else
	{
		return false;
	}
}


void CDXMutiplyStatic::Draw()
{
	if(m_BkColor)
	{
		IDirect3DVertexDeclaration9* pDecl = NULL;
		m_pD3dWindow->GetD3dDevice()->GetVertexDeclaration(&pDecl);
		if(m_bAlpha)
		{
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, true); 
			m_pD3dWindow->GetD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 
		}
		m_pD3dWindow->GetD3dDevice()->SetVertexShader( NULL );
		m_pD3dWindow->GetD3dDevice()->SetPixelShader( NULL );
	//	m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
	//	m_pD3dWindow->GetD3dDevice()->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
		m_pD3dWindow->GetD3dDevice()->SetFVF(sVertex::FVF);
		m_pD3dWindow->GetD3dDevice()->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, m_ControlRect, sizeof( sVertex ) );
		if(m_bAlpha)
		{
			m_pD3dWindow->GetD3dDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, false); 
		}
		m_pD3dWindow->GetD3dDevice()->SetVertexDeclaration(pDecl);
	}
	RECT r={0,0,0,0};
	m_Font->DrawTextW(0,m_strText,-1,&r,DT_CALCRECT|m_iStyle,m_ForeColor);
	int iHeight=(r.bottom-r.top)+2;
	list<CString>::iterator it;
	int i=0;
	for (it=m_strList.begin();it!=m_strList.end();it++)
	{
		RECT r={m_ControlRect[0].x,m_ControlRect[0].y+iHeight*i++,m_ControlRect[2].x+1,m_ControlRect[0].y+iHeight*i+iHeight+1};
		m_Font->DrawTextW(0,it->GetBuffer(0),-1,&r,m_iStyle,m_ForeColor);
	}


}


void CDXMutiplyStatic::SetText( LPCTSTR strText )
{
	m_strList.clear();
	if(m_strText)
	{
		delete[] m_strText;
	}
	m_strText=new TCHAR[_tcslen(strText)+sizeof(TCHAR)];
	_tcscpy(m_strText,strText);
	int iPos=0,iHeight=0;
	while(m_strText[iPos])
	{
		TCHAR wzTemp[1024]={0};
		RECT r={0,0,0,0};
		while(m_strText[iPos])
		{
			_tcsncat(wzTemp,m_strText+iPos,1);
			m_Font->DrawTextW(0,wzTemp,-1,&r,DT_CALCRECT|m_iStyle,m_ForeColor);
			if(r.right-r.left>=m_iWidth)
			{
				wzTemp[_tcslen(wzTemp)-1]=0;
				m_strList.push_back(wzTemp);
				iHeight+=(r.bottom-r.top)+2;
				break;
			}
			iPos++;
		}
		if(m_strText[iPos]==0)
		{
			m_strList.push_back(wzTemp);
			iHeight+=(r.bottom-r.top)+2;
		}
	}
	m_ControlRect[2].y=m_ControlRect[0].y+iHeight-1;
	m_ControlRect[3].y=m_ControlRect[0].y+iHeight-1;
}
void CDXMutiplyStatic::MoveWindow( int iLeft,int iTop,int iWidth,int iHeight )
{
	int Height=m_ControlRect[3].y-m_ControlRect[0].y;
	m_iWidth=iWidth;
	m_ControlRect[0].x=iLeft;
	m_ControlRect[0].y=iTop;
	m_ControlRect[1].x=iLeft+iWidth-1;
	m_ControlRect[1].y=iTop;
	m_ControlRect[2].x=iLeft+iWidth-1;
	m_ControlRect[2].y=iTop+Height-1;
	m_ControlRect[3].x=iLeft;
	m_ControlRect[3].y=iTop+Height-1;
}




void CDXCamera::Go( float fLen )
{
	float x,z;
	x=fLen*sin(m_fRightAngle*(D3DX_PI/180.0f));
	z=fLen*cos(m_fRightAngle*(D3DX_PI/180.0f));
	m_vEye.x+=x;
	m_vEye.z+=z;
}


void CDXCamera::Back( float fLen )
{
	float x,z;
	x=fLen*sin(m_fRightAngle*(D3DX_PI/180.0f));
	z=fLen*cos(m_fRightAngle*(D3DX_PI/180.0f));
	m_vEye.x-=x;
	m_vEye.z-=z;
}


void CDXCamera::Up( float fLen )
{
	m_vEye.y+=fLen;
	m_vAt.y+=fLen;
}


void CDXCamera::Down( float fLen )
{
	m_vEye.y-=fLen;
	m_vAt.y-=fLen;
}


void CDXCamera::Left( float fLen )
{
	float x,z;
	z=fLen*sin(m_fRightAngle*(D3DX_PI/180.0f));
	x=fLen*cos(m_fRightAngle*(D3DX_PI/180.0f));
	m_vEye.x-=x;
	m_vEye.z+=z;
	m_vAt.x-=x;
	m_vAt.z+=z;
}


void CDXCamera::Right( float fLen )
{
	float x,z;
	z=fLen*sin(m_fRightAngle*(D3DX_PI/180.0f));
	x=fLen*cos(m_fRightAngle*(D3DX_PI/180.0f));
	m_vEye.x+=x;
	m_vEye.z-=z;
	m_vAt.x+=x;
	m_vAt.z-=z;
}


void CDXCamera::TurnLeft( float fAngle )
{
	float x,z;
	float fTempAngle=m_fRightAngle;
	m_fRightAngle-=fAngle;
	if(m_fRightAngle<0)
	{
		m_fRightAngle=360+fTempAngle-fAngle;
	}


	x=m_fRad*sin(m_fRightAngle*(D3DX_PI/180.0f));
	z=m_fRad*cos(m_fRightAngle*(D3DX_PI/180.0f));
	m_vAt.x=m_vEye.x+x;
	m_vAt.z=z+m_vEye.z;
}


void CDXCamera::TurnRight( float fAngle )
{
	float x,z;
	float fTempAngle=m_fRightAngle;
	m_fRightAngle+=fAngle;
	if(m_fRightAngle>=360)
	{
		m_fRightAngle=fTempAngle+fAngle-360;
	}
	x=m_fRad*sin(m_fRightAngle*(D3DX_PI/180.0f));
	z=m_fRad*cos(m_fRightAngle*(D3DX_PI/180.0f));
	m_vAt.x=x+m_vEye.x;
	m_vAt.z=z+m_vEye.z;
}


void CDXCamera::TurnUp( float fAngle )
{
	float x,y,z;
	float fTempAngle=m_fUpAngle;
	m_fUpAngle+=fAngle;
	if(m_fUpAngle>=360)
	{
		m_fUpAngle=fTempAngle+fAngle-360;
	}
	y=m_fRad*tan(m_fUpAngle*(D3DX_PI/180.0f));
	m_vAt.y=y+m_vEye.y;
}


void CDXCamera::TurnDown( float fAngle )
{
	float x,y,z;
	float fTempAngle=m_fUpAngle;
	m_fUpAngle-=fAngle;
	if(m_fUpAngle<0)
	{
		m_fUpAngle=360+fTempAngle-fAngle;
	}
	y=m_fRad*tan(m_fUpAngle*(D3DX_PI/180.0f));
	m_vAt.y=y+m_vEye.y;
}


void CDXCamera::Reset(CDXWindow *pWin,D3DXVECTOR3 vEye,D3DXVECTOR3 vAt)
{
	m_pDevice=pWin->GetD3dDevice();
	D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);
	m_vUp=vUp;
	m_vEye=vEye;
	m_vAt=vAt;
	m_fRad=sqrtf(powf(m_vAt.x-m_vEye.x,2)+powf(m_vAt.z-m_vEye.z,2));
	m_fRightAngle=acos((m_vAt.z-m_vEye.z)/m_fRad)*180/D3DX_PI;
	if((m_vAt.x-m_vEye.x)/m_fRad<0)
	{
		m_fRightAngle=360-m_fRightAngle;
	}
	m_fUpAngle=atan((m_vAt.y-m_vEye.y)/m_fRad)*180/D3DX_PI;
}


void CDXCamera::SetTransForm()
{
	D3DXMATRIX matView; 
	D3DXMatrixLookAtLH(&matView, &m_vEye, &m_vAt, &m_vUp); 
	m_pDevice->SetTransform(D3DTS_VIEW, &matView); 
}


D3DXVECTOR3 CDXCamera::GetEye()
{
	return m_vEye;
}


D3DXVECTOR3 CDXCamera::GetAt()
{
	return m_vAt;
}


float CDXCamera::GetX()
{
	return m_vEye.x;
}


float CDXCamera::GetY()
{
	return m_vEye.y;
}


float CDXCamera::GetZ()
{
	return m_vEye.z;
}


float CDXCamera::GetRightAngle()
{
	return m_fRightAngle;
}


float CDXCamera::GetUpAngle()
{
	return m_fUpAngle;
}


void CDXParticle::Reset( CDXWindow *pWin,bool bSpriteEnable/*=true*/,bool bScaleEnable/*=true*/ )
{
	m_pDevice=pWin->GetD3dDevice();
	m_ParVector.clear();
	m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE,bSpriteEnable);
	m_pDevice->SetRenderState(D3DRS_POINTSCALEENABLE,bScaleEnable);
	m_pDevice->SetRenderState(D3DRS_POINTSCALE_A,FToD(0));
	m_pDevice->SetRenderState(D3DRS_POINTSCALE_B,FToD(0));
	m_pDevice->SetRenderState(D3DRS_POINTSCALE_C,FToD(1));
}


void CDXParticle::AddParticle()
{
	sParticle p;
	OnAdd(&p);
	m_ParVector.push_back(p);
}


void CDXParticle::SetParticleSize( float iLen )
{
	m_pDevice->SetRenderState(D3DRS_POINTSIZE,FToD(iLen));
}


void CDXParticle::Render()
{
	if(m_ParVector.size()>0)
	{
		m_pDevice->DrawPrimitiveUP(D3DPT_POINTLIST,m_ParVector.size(),&m_ParVector[0],sizeof(sParticle));
	}
}
	


void CDXHelper::GetBoundingSphere( D3DXVECTOR3* pFirstPosition,DWORD NumVertices,DWORD dFVF,sBoundingSphere *pSphere )
{
	D3DXComputeBoundingSphere(pFirstPosition,NumVertices,D3DXGetFVFVertexSize(dFVF),&(pSphere->pos),&(pSphere->radius));
}


bool CDXHelper::MouseInSphere(LPDIRECT3DDEVICE9 pDevice, POINT p,sBoundingSphere* pSphere,D3DXVECTOR2 *pHit )
{
	D3DXVECTOR3 origin,direction;
	GetRayInfo(pDevice,p,&origin,&direction);
	D3DXVECTOR3 v=origin-pSphere->pos;
	float b=2.0f*D3DXVec3Dot(&direction,&v);
	float c=D3DXVec3Dot(&v,&v)-(pSphere->radius*pSphere->radius);
	float discriminant=(b*b)-(4.0f*c);
	if(discriminant<0.0f)
		return false;
	discriminant=sqrtf(discriminant);
	float s0=(-b+discriminant)/2.0f;
	float s1=(-b-discriminant)/2.0f;
	if(s0>=0.0f || s1>=0.0f)
	{
		float dis;
		if(s0>=0.0f)
		{
			dis=s0;
		}else
		{
			dis=s1;
		}
		if(pHit)
		{
			pHit->x=origin.x+dis*direction.x;
			pHit->y=origin.z+dis*direction.z;
		}
		return true;
	}	
	return false;
}


void CDXHelper::GetRayInfo( LPDIRECT3DDEVICE9 pDevice,POINT p,D3DXVECTOR3* origin,D3DXVECTOR3 *direction,D3DXMATRIX *WorldMat/*=0 */)
{
	int x=p.x,y=p.y;
	float px=0.0f,py=0.0f;
	D3DVIEWPORT9 vp;
	pDevice->GetViewport(&vp);
	D3DXMATRIX proj;
	pDevice->GetTransform(D3DTS_PROJECTION,&proj);
	px=(((2.0f*x)/vp.Width)-1.0f)/proj(0,0);
	py=(((-2.0f*y)/vp.Height)+1.0f)/proj(1,1);
	*origin=D3DXVECTOR3(0,0,0);
	*direction=D3DXVECTOR3(px,py,1.0f);
	D3DXMATRIX view;
	pDevice->GetTransform(D3DTS_VIEW,&view);
	D3DXMATRIX viewInverse;
	D3DXMatrixInverse(&viewInverse,0,&view);
	if(WorldMat)
	{
		D3DXMATRIX WorldInverse;
		D3DXMatrixInverse(&WorldInverse,0,WorldMat);
		viewInverse*=WorldInverse;
	}
	D3DXVec3TransformCoord(origin,origin,&viewInverse);
	D3DXVec3TransformNormal(direction,direction,&viewInverse);
	D3DXVec3Normalize(direction,direction);
}


bool CDXHelper::MouseInTriangle( LPDIRECT3DDEVICE9 pDevice,POINT p,D3DXVECTOR3* p1,D3DXVECTOR3* p2,D3DXVECTOR3* p3 )
{
	D3DXVECTOR3 origin,direction;
	GetRayInfo(pDevice,p,&origin,&direction);
	float u,v,dist;
	bool bRet=D3DXIntersectTri(p1,p2,p3,&origin,&direction,&u,&v,&dist);
	return bRet;
}


void CDXHelper::ComputerNormal( D3DXVECTOR3 *p1,D3DXVECTOR3 *p2,D3DXVECTOR3 *p3,D3DXVECTOR3 *out )
{
	D3DXVec3Cross(out,&(*p2-*p1),&(*p3-*p1));
	D3DXVec3Normalize(out,out);
}


void CDXHelper::FillVertexNormal( void *p1,void *p2,void *p3,DWORD offset )
{
	D3DXVECTOR3 v1=*(D3DXVECTOR3*)p1,v2=*(D3DXVECTOR3*)p2,v3=*(D3DXVECTOR3*)p3;
	D3DXVECTOR3 *f1=(D3DXVECTOR3*)((char*)p1+offset);
	D3DXVECTOR3 *f2=(D3DXVECTOR3*)((char*)p2+offset);
	D3DXVECTOR3 *f3=(D3DXVECTOR3*)((char*)p3+offset);
	D3DXVECTOR3 out;
	ComputerNormal(&v1,&v2,&v3,&out);
	*f1=*f2=*f3=out;
}


bool CDXHelper::CheckBoxCollide( D3DXVECTOR3 min1,D3DXVECTOR3 max1,D3DXVECTOR3 min2,D3DXVECTOR3 max2 )
{
	if(min1.y>max2.y || max1.y<min2.y)
	{
		return false;
	}
	sRect rect1={min1.x,min1.z,max1.x,max1.z},rect2={min2.x,min2.z,max2.x,max2.z};
	if(rect1.right < rect2.left) return FALSE;
	if(rect1.left > rect2.right ) return FALSE;


	if(rect1.bottom < rect2.top ) return FALSE;
	if(rect1.top > rect2.bottom ) return FALSE;


	return TRUE;


}


bool CDXHelper::MouseInMesh( LPDIRECT3DDEVICE9 pDevice,POINT p,LPD3DXMESH pMesh,D3DXMATRIX *WorldMat/*=0*/ )
{
	D3DXVECTOR3 origin,direction;
	GetRayInfo(pDevice,p,&origin,&direction,WorldMat);
	BOOL bHit;
	D3DXIntersect(pMesh,&origin,&direction,&bHit,0,0,0,0,0,0);
	return bHit;
}


bool CDXHelper::MouseInPlane( LPDIRECT3DDEVICE9 pDevice,POINT p,LPD3DXPLANE pPlane,D3DXVECTOR3 *pHitVec )
{
	D3DXVECTOR3 origin,direction;
	GetRayInfo(pDevice,p,&origin,&direction);
	if(D3DXPlaneIntersectLine(pHitVec,pPlane,&origin,&direction))
	{
		return true;
	}
	return false;
}


float CDXHelper::GetNormalAngle( D3DXVECTOR2 v1,D3DXVECTOR2 v2 )
{
	D3DXVec2Normalize(&v1,&v1);
	D3DXVec2Normalize(&v2,&v2);
	float fCos=D3DXVec2Dot(&v1,&v2)/(D3DXVec2Length(&v1)*D3DXVec2Length(&v2));
	float fSin=v1.y*v2.x-v2.y*v1.x;
	if(fSin>=0)
	{
		return acos(fCos)*180/D3DX_PI;
	}else
	{
		return 360-acos(fCos)*180/D3DX_PI;
	}
}


CDXXFile::CDXXFile()
{
	m_pMesh=0;
	m_dNumMtrl=0;
	m_dSubSize=0;
}


CDXXFile::~CDXXFile()
{
	if(m_pMesh)
	{
		m_pMesh->Release();
	}
	for (int i=0;i<m_VecTex.size();i++)
	{
		if(m_VecTex[i])
		{
			m_VecTex[i]->Release();
		}
	}
}


bool CDXXFile::LoadFile( LPCTSTR szPath,LPDIRECT3DDEVICE9 pDevice,DWORD option/*=D3DXMESH_MANAGED*/ )
{
	ID3DXBuffer *adjBuffer=0,*mtrlBuffer=0;
	DWORD numMtrl=0;
	HRESULT hr=D3DXLoadMeshFromX(szPath,option,pDevice,&adjBuffer,&mtrlBuffer,0,&numMtrl,&m_pMesh);
	if(FAILED(hr))
	{
		return false;
	}
	m_pDevice=pDevice;
	vector<DWORD> adj(m_pMesh->GetNumFaces()*3);
	m_pMesh->GenerateAdjacency(0.0f,&adj[0]);
	m_pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT|D3DXMESHOPT_COMPACT|D3DXMESHOPT_VERTEXCACHE,&adj[0],0,0,0);
	if(numMtrl>0)
	{
		TCHAR szDir[255];
		_tcscpy(szDir,szPath);
		PathRemoveFileSpec(szDir);
		USES_CONVERSION;
		m_dNumMtrl=numMtrl;
		D3DXMATERIAL *mtrl=(D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
		for(int i=0;i<numMtrl;i++)
		{
			mtrl[i].MatD3D.Ambient=mtrl[i].MatD3D.Diffuse;
			m_VecMtrl.push_back(mtrl[i].MatD3D);
			if(mtrl[i].pTextureFilename)
			{
				CString strTex=szDir;
				strTex+="\\";
				strTex+=A2W(mtrl[i].pTextureFilename);
				IDirect3DTexture9 *tex=0;
				D3DXCreateTextureFromFileA(pDevice,W2A(strTex),&tex);
				if(tex)
				{
					m_VecTex.push_back(tex);
				}
				else
				{
					m_VecTex.push_back(0);
				}
			}
			else
			{
				m_VecTex.push_back(0);
			}
		}
	}
	else
	{
		m_pMesh->GetAttributeTable(0,&m_dSubSize);
	}
	if(mtrlBuffer)
	{
		mtrlBuffer->Release();
	}
	if(adjBuffer)
	{
		adjBuffer->Release();
	}
	return true;
}


void CDXXFile::Render()
{
	if(m_pMesh)
	{
		D3DMATERIAL9 mtrl;
		m_pDevice->GetMaterial(&mtrl);
		if(m_dNumMtrl>0)
		{
			for(int i=0;i<m_dNumMtrl;i++)
			{
				m_pDevice->SetMaterial(&m_VecMtrl[i]);
				m_pDevice->SetTexture(0,m_VecTex[i]);
				m_pMesh->DrawSubset(i);
			}
		}
		else
		{
			for(int i=0;i<m_dSubSize;i++)
			{
				m_pMesh->DrawSubset(i);
			}
		}
	m_pDevice->SetMaterial(&mtrl);
	m_pDevice->SetTexture(0,0);
	}
	
}


ID3DXMesh* CDXXFile::GetMeshObj()
{
	return m_pMesh;
}


void CDXXFile::Release()
{
	this->~CDXXFile();
	delete this;
}


LPDIRECT3DDEVICE9 CDXXFile::GetDevice()
{
	return m_pDevice;
}


CDXLand::CDXLand()
{
	m_pDevice=0;
	m_pTex=0;
	m_pVertexBuffer=0;
	m_pIndexBuffer=0;
	m_dWidthNumVertex=0;
	m_dHeightNumVertex=0;
	m_dCellLen=0;
}


CDXLand::~CDXLand()
{
	if(m_pTex)
	{
		m_pTex->Release();
	}
	if(m_pVertexBuffer)
	{
		m_pVertexBuffer->Release();
	}
	if(m_pIndexBuffer)
	{
		m_pIndexBuffer->Release();
	}
}


bool CDXLand::Create( LPDIRECT3DDEVICE9 pDevice,DWORD dWidthNumVertex,DWORD dHeightNumVertex,DWORD dCellLen,int dStartX,int dStartZ,LPCTSTR tcsRawPath,LPCTSTR tcsTexPath,float fScaleHeight/*=1*/ )
{
	if(pDevice==0)
	{
		return false;
	}
	m_pDevice=pDevice;
	USES_CONVERSION;
	FILE *file=_tfopen(tcsRawPath,_T("rb"));
	if(file==0)
	{
		return false;
	}
	fseek(file,0,SEEK_END);
	DWORD dLen=ftell(file);
	fseek(file,0,SEEK_SET);
	m_HeightMap.resize(dLen);
	byte *cRawBytes=new byte[dLen];
	fread(cRawBytes,1,dLen,file);
	fclose(file);
	for(int i=0;i<dLen;i++)
	{
		m_HeightMap[i]=cRawBytes[i]*fScaleHeight;
	}
	delete[] cRawBytes;
	D3DXCreateTextureFromFile(m_pDevice,tcsTexPath,&m_pTex);
	if(m_pTex==0)
	{
		return false;
	}
	D3DSURFACE_DESC Desc;


	m_pTex->GetLevelDesc(0,&Desc);
	m_dWidthNumVertex=dWidthNumVertex;
	m_dHeightNumVertex=dHeightNumVertex;
	m_dCellLen=dCellLen;
	m_dStartX=dStartX;
	m_dStartZ=dStartZ;
	sVertex *Vertex=new sVertex[m_dWidthNumVertex*m_dHeightNumVertex];
	int x,z;
	z=m_dStartZ;
	for(int i=0;i<m_dHeightNumVertex;i++)
	{
		x=m_dStartX;
		for(int j=0;j<m_dWidthNumVertex;j++)
		{			
			Vertex[i*m_dWidthNumVertex+j]=sVertex(x,GetHeightFromXZ(i,j),z,/*j*1.0/(m_dWidthNumVertex-1),i*1.0/(m_dHeightNumVertex-1)*/x*1.0/50,(z-m_dStartZ)*1.0/50);
			x+=dCellLen;
		}
		z-=dCellLen;
	}
	DWORD dIndexLen=(m_dWidthNumVertex-1)*(m_dHeightNumVertex-1)*6;
	WORD *wIndex=new WORD[dIndexLen];
	int iIndex=0;
	for(int i=0;i<m_dWidthNumVertex-1;i++)
	{
		for(int j=0;j<m_dHeightNumVertex-1;j++)
		{	
			wIndex[iIndex++]=i*m_dWidthNumVertex+j;
			wIndex[iIndex++]=i*m_dWidthNumVertex+j+1;
			wIndex[iIndex++]=(i+1)*m_dWidthNumVertex+j;
			wIndex[iIndex++]=i*m_dWidthNumVertex+j+1;
			wIndex[iIndex++]=(i+1)*m_dWidthNumVertex+j+1;
			wIndex[iIndex++]=(i+1)*m_dWidthNumVertex+j;
		}
	}
	int iOffset=(int)&(((sVertex*)0)->nx);
	CDXHelper::FillFullVertexNormal<sVertex>(Vertex,wIndex,dIndexLen,iOffset);
	m_pDevice->CreateVertexBuffer(m_dWidthNumVertex*m_dHeightNumVertex*sizeof(sVertex),0,dVertexFVF,D3DPOOL_MANAGED,&m_pVertexBuffer,0);
	sVertex *Vert;
	m_pVertexBuffer->Lock(0,0,(void**)&Vert,0);
	memcpy(Vert,Vertex,m_dWidthNumVertex*m_dHeightNumVertex*sizeof(sVertex));
	m_pVertexBuffer->Unlock();
	m_pDevice->CreateIndexBuffer(dIndexLen*sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&m_pIndexBuffer,0);
	WORD *pIndex;
	m_pIndexBuffer->Lock(0,0,(void**)&pIndex,0);
	memcpy(pIndex,wIndex,dIndexLen*sizeof(WORD));
	m_pIndexBuffer->Unlock();
	delete[] Vertex;
	delete[] wIndex;
	return true;
}


void CDXLand::Render()
{
	IDirect3DTexture9 *pTex;
	m_pDevice->GetTexture(0,(IDirect3DBaseTexture9**)&pTex);
 	m_pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
 	m_pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
	m_pDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 4);
	m_pDevice->SetStreamSource(0,m_pVertexBuffer,0,sizeof(sVertex));
	m_pDevice->SetFVF(dVertexFVF);
	m_pDevice->SetIndices(m_pIndexBuffer);
	m_pDevice->SetTexture(0,m_pTex);
	m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,m_dWidthNumVertex*m_dHeightNumVertex,0,(m_dWidthNumVertex-1)*(m_dHeightNumVertex-1)*2);
	m_pDevice->SetTexture(0,pTex);
	m_pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
 	m_pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
}


float CDXLand::GetHeightFromXZ( int iRow,int iCol )
{
	return m_HeightMap[iRow*m_dWidthNumVertex+iCol];
}


float CDXLand::GetHeight( float x,float z )
{
	z=m_dStartZ-z;
	x=x-m_dStartX;
	int row=floor(z/m_dCellLen);
	int col=floor(x/m_dCellLen);
	float A=GetHeightFromXZ(row,col);
	float B=GetHeightFromXZ(row,col+1);
	float C=GetHeightFromXZ(row+1,col);
	float D=GetHeightFromXZ(row+1,col+1);
	float dx=x-col*m_dCellLen;
	float dz=z-row*m_dCellLen;
	float fHeight;
	if(dx+dz<(float)m_dCellLen)
	{
		float fABHeight=B-A;
		float fACHeight=C-A;
		fHeight=A+dx/m_dCellLen*fABHeight+dz/m_dCellLen*fACHeight;
	}else
	{
		float fBDHeight=B-D;
		float fCDHeight=C-D;
		fHeight=D+(m_dCellLen-dx)/m_dCellLen*fCDHeight+(m_dCellLen-dz)/m_dCellLen*fBDHeight;
	}
	return fHeight;
}


float CDXLand::GetStartX()
{
	return m_dStartX;
}


float CDXLand::GetStartZ()
{
	return m_dStartZ;
}


float CDXLand::GetLandWidth()
{
	return (m_dWidthNumVertex-1)*m_dCellLen;
}


float CDXLand::GetLandHeight()
{
	return (m_dHeightNumVertex-1)*m_dCellLen;
}


CDXSky::CDXSky()
{
	m_pDevice=0;
	m_pVertexBuffer=0 ;  
	D3DXMatrixIdentity(&m_TransMat);
}


CDXSky::~CDXSky()
{
	map<CString,LPDIRECT3DTEXTURE9>::iterator it;
	for(it=m_pTexList.begin();it!=m_pTexList.end();it++)
	{
		if(it->second)
		{
			it->second->Release();
		}
	}
	if(m_pVertexBuffer)
	{
		m_pVertexBuffer->Release();
	}
}


bool CDXSky::Create( LPDIRECT3DDEVICE9 pDevice,int dStartX,int dStartZ,DWORD dWidth,DWORD dHeight,int dY,LPCTSTR *tcsTexPath )
{
	if(pDevice==0)
	{
		return false;
	}
	m_pDevice=pDevice;
	m_dStartX=dStartX;
	m_dStartZ=dStartZ;
	m_dWidth=dWidth;
	m_dHeight=dHeight;
	m_dY=dY;
	for(int i=0;i<6;i++)
	{
		if(m_pTexList.find(tcsTexPath[i])==m_pTexList.end())
		{
			LPDIRECT3DTEXTURE9 pTex;
			D3DXCreateTextureFromFile(m_pDevice,tcsTexPath[i],&pTex);
			m_pTexList[tcsTexPath[i]]=pTex;
			m_pTex[i]=pTex;
		}else
		{
			m_pTex[i]=m_pTexList[tcsTexPath[i]];
		}
		
	}
	sVertex Vertex[36];
	Vertex[0]=sVertex(m_dStartX,m_dY,m_dStartZ,0,0);
	Vertex[1]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ,1,0);
	Vertex[2]=sVertex(m_dStartX,0,m_dStartZ,0,1);
	Vertex[3]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ,1,0);
	Vertex[4]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ,1,1);
	Vertex[5]=sVertex(m_dStartX,0,m_dStartZ,0,1);
	Vertex[6]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ-m_dHeight,0,0);
	Vertex[7]=sVertex(m_dStartX,m_dY,m_dStartZ-m_dHeight,1,0);
	Vertex[8]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ-m_dHeight,0,1);
	Vertex[9]=sVertex(m_dStartX,m_dY,m_dStartZ-m_dHeight,1,0);
	Vertex[10]=sVertex(m_dStartX,0,m_dStartZ-m_dHeight,1,1);
	Vertex[11]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ-m_dHeight,0,1);
	Vertex[12]=sVertex(m_dStartX,m_dY,m_dStartZ-m_dHeight,0,0);
	Vertex[13]=sVertex(m_dStartX,m_dY,m_dStartZ,1,0);
	Vertex[14]=sVertex(m_dStartX,0,m_dStartZ-m_dHeight,0,1);
	Vertex[15]=sVertex(m_dStartX,m_dY,m_dStartZ,1,0);
	Vertex[16]=sVertex(m_dStartX,0,m_dStartZ,1,1);
	Vertex[17]=sVertex(m_dStartX,0,m_dStartZ-m_dHeight,0,1);
	Vertex[18]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ,0,0);
	Vertex[19]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ-m_dHeight,1,0);
	Vertex[20]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ,0,1);
	Vertex[21]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ-m_dHeight,1,0);
	Vertex[22]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ-m_dHeight,1,1);
	Vertex[23]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ,0,1);
	Vertex[24]=sVertex(m_dStartX,m_dY,m_dStartZ-m_dHeight,0,0);
	Vertex[25]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ-m_dHeight,1,0);
	Vertex[26]=sVertex(m_dStartX,m_dY,m_dStartZ,0,1);
	Vertex[27]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ-m_dHeight,1,0);
	Vertex[28]=sVertex(m_dStartX+m_dWidth,m_dY,m_dStartZ,1,1);
	Vertex[29]=sVertex(m_dStartX,m_dY,m_dStartZ,0,1);
	Vertex[30]=sVertex(m_dStartX,0,m_dStartZ,0,0);
	Vertex[31]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ,1,0);
	Vertex[32]=sVertex(m_dStartX,0,m_dStartZ-m_dHeight,0,1);
	Vertex[33]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ,1,0);
	Vertex[34]=sVertex(m_dStartX+m_dWidth,0,m_dStartZ-m_dHeight,1,1);
	Vertex[35]=sVertex(m_dStartX,0,m_dStartZ-m_dHeight,0,1);
	m_fCenterX=m_dStartX+m_dWidth*0.5f;
	m_fCenterZ=m_dStartZ-m_dHeight*0.5f;
	m_pDevice->CreateVertexBuffer(36*sizeof(sVertex),0,dVertexFVF,D3DPOOL_MANAGED,&m_pVertexBuffer,0);
	sVertex *Vert;
	m_pVertexBuffer->Lock(0,0,(void**)&Vert,0);
	memcpy(Vert,Vertex,sizeof(Vertex));
	m_pVertexBuffer->Unlock();
	return true;
}


void CDXSky::Render()
{
	if(m_pDevice)
	{
		D3DXMATRIX mat;
		m_pDevice->GetTransform(D3DTS_WORLD,&mat);
		m_pDevice->SetTransform(D3DTS_WORLD,&m_TransMat);
		DWORD val;
		m_pDevice->GetRenderState(D3DRS_LIGHTING,&val);
		m_pDevice->SetRenderState(D3DRS_LIGHTING,false);
		m_pDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
		LPDIRECT3DBASETEXTURE9 pTex;
		m_pDevice->GetTexture(0,&pTex);
		m_pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
		m_pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
		m_pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		m_pDevice->SetStreamSource(0,m_pVertexBuffer,0,sizeof(sVertex));
		m_pDevice->SetFVF(dVertexFVF);
		int iNum=0;
		for(int i=0;i<36;i+=6)
		{
			m_pDevice->SetTexture(0,m_pTex[iNum++]);
			m_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST,i,2);
		}
		m_pDevice->SetTexture(0,pTex);
		m_pDevice->SetRenderState(D3DRS_LIGHTING,val);
		m_pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		m_pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
		m_pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
		m_pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
		m_pDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
		m_pDevice->SetTransform(D3DTS_WORLD,&mat);
	}
	
}


void CDXSky::SetPos( float x,float z )
{
	float dx=x-m_fCenterX;
	float dz=z-m_fCenterZ;
	D3DXMatrixTranslation(&m_TransMat,dx,0,dz);
}


void CDXEntity::Render()
{
	if(!m_bDrawed && m_pMesh)
	{
		if(m_bNormalCompute)
		{
			D3DXMATRIX mat;
			D3DXMatrixInverse(&mat,0,&(m_Mat*m_ExtMat));
			D3DXMatrixTranspose(&mat,&mat);
			int iOffset=3*sizeof(float);
			int iVertexNum=m_pMesh->GetMeshObj()->GetNumVertices();
			int iVertexSize=m_pMesh->GetMeshObj()->GetNumBytesPerVertex();
			char *v=0;
			m_pMesh->GetMeshObj()->LockVertexBuffer(0,(void**)&v);
			for(int i=0;i<iVertexNum;i++)
			{
				D3DXVECTOR3 *pNormal=(D3DXVECTOR3*)((char*)v+iOffset);
				D3DXVec3TransformNormal(pNormal,pNormal,&mat);
				v+=iVertexSize;
			}
			m_pMesh->GetMeshObj()->UnlockVertexBuffer();
			m_bNormalCompute=false;
		}
// 		m_pMesh->GetDevice()->SetTransform(D3DTS_WORLD,&m_Mat);
// 		m_pMesh->Render();
		m_bDrawed=true;
		CDXOctNode::RenderList.push_back(this);
	}
	
}


CDXEntity::CDXEntity( CDXBaseMesh *pMesh,D3DXMATRIX *mat )
{
	if(pMesh)
	{
		m_pMesh=pMesh;
	}
	m_bDrawed=false;
	m_bNormalCompute=false;
	ID3DXMesh *mesh=pMesh->GetMeshObj();
	byte *v=0;
	mesh->LockVertexBuffer(0,(void**)&v);
	D3DXComputeBoundingBox((D3DXVECTOR3*)v,mesh->GetNumVertices(),D3DXGetFVFVertexSize(mesh->GetFVF()),&m_BoundMin,&m_BoundMax);
	mesh->UnlockVertexBuffer();
	D3DXMatrixIdentity(&m_Mat);
	D3DXMatrixIdentity(&m_ExtMat);
	if(mat)
	{
		m_Mat=*mat;
		D3DXVECTOR3 min=m_BoundMin,max=m_BoundMax;
		D3DXVECTOR3 v[8];
		v[0]=D3DXVECTOR3(min.x,max.y,max.z);
		v[1]=D3DXVECTOR3(max.x,max.y,max.z);
		v[2]=D3DXVECTOR3(max.x,max.y,min.z);
		v[3]=D3DXVECTOR3(min.x,max.y,min.z);
		v[4]=D3DXVECTOR3(min.x,min.y,max.z);
		v[5]=D3DXVECTOR3(max.x,min.y,max.z);
		v[6]=D3DXVECTOR3(max.x,min.y,min.z);
		v[7]=D3DXVECTOR3(min.x,min.y,min.z);
		for(int i=0;i<8;i++)
		{
			D3DXVec3TransformCoord(&v[i],&v[i],&m_Mat);
		}
		min=v[0];
		max=v[0];
		for(int i=1;i<8;i++)
		{
			if(v[i].x>max.x)
			{
				max.x=v[i].x;
			}
			if(v[i].y>max.y)
			{
				max.y=v[i].y;
			}
			if(v[i].z>max.z)
			{
				max.z=v[i].z;
			}
			if(v[i].x<min.x)
			{
				min.x=v[i].x;
			}
			if(v[i].y<min.y)
			{
				min.y=v[i].y;
			}
			if(v[i].z<min.z)
			{
				min.z=v[i].z;
			}
		}
		m_BoundMin=min;
		m_BoundMax=max;
	}
}


void CDXEntity::Release(CDXOctNode *pNode)
{
	m_NodeList.erase(pNode);
	if(m_NodeList.size()==0)
	{
		CDXOctNode::EntityIdList.erase(m_StrId);
		//m_pMesh->Release();
		m_pMesh=0;
		delete this;
	}
	
}


void CDXEntity::Remove()
{
	set<CDXOctNode*>::iterator it=m_NodeList.begin();
	for(;it!=m_NodeList.end();)
	{
		CDXOctNode *pNode=*it;
		pNode->m_EntityList.remove(this);
		CDXOctNode *pParNode=pNode->m_pParNode;
		bool bDel=true;
		for(int i=0;i<8;i++)
		{
			if(pParNode->m_pChildNode[i]->m_EntityList.size()>0)
			{
				bDel=false;
				break;
			}
		}
		if(bDel)
		{
			pParNode->Release();
		}
		it=m_NodeList.erase(it);
	}
	CDXOctNode::EntityIdList.erase(m_StrId);
}


void CDXEntity::Move( float dx,float dy,float dz )
{
	D3DXMATRIX mat;
	D3DXMatrixTranslation(&mat,dx,dy,dz);
	D3DXVec3TransformCoord(&m_BoundMin,&m_BoundMin,&mat);
	D3DXVec3TransformCoord(&m_BoundMax,&m_BoundMax,&mat);
	m_Mat*=mat;
	_UpdatePos();
}


void CDXEntity::Scale( float nx,float ny,float nz )
{
	D3DXMATRIX mat,mat1;
	D3DXMatrixScaling(&mat,nx,ny,nz);
	D3DXVECTOR3 min=m_BoundMin,max=m_BoundMax;
	D3DXVECTOR3 v[8];
	v[0]=D3DXVECTOR3(min.x,max.y,max.z);
	v[1]=D3DXVECTOR3(max.x,max.y,max.z);
	v[2]=D3DXVECTOR3(max.x,max.y,min.z);
	v[3]=D3DXVECTOR3(min.x,max.y,min.z);
	v[4]=D3DXVECTOR3(min.x,min.y,max.z);
	v[5]=D3DXVECTOR3(max.x,min.y,max.z);
	v[6]=D3DXVECTOR3(max.x,min.y,min.z);
	v[7]=D3DXVECTOR3(min.x,min.y,min.z);
	for(int i=0;i<8;i++)
	{
		D3DXVec3TransformCoord(&v[i],&v[i],&mat);
	}
	min=v[0];
	max=v[0];
	for(int i=1;i<8;i++)
	{
		if(v[i].x>max.x)
		{
			max.x=v[i].x;
		}
		if(v[i].y>max.y)
		{
			max.y=v[i].y;
		}
		if(v[i].z>max.z)
		{
			max.z=v[i].z;
		}
		if(v[i].x<min.x)
		{
			min.x=v[i].x;
		}
		if(v[i].y<min.y)
		{
			min.y=v[i].y;
		}
		if(v[i].z<min.z)
		{
			min.z=v[i].z;
		}
	}
	m_BoundMin=min;
	m_BoundMax=max;
	m_Mat*=mat;
	_UpdatePos();
	if(m_pMesh->GetMeshObj()->GetFVF() & D3DFVF_NORMAL)
	{
		if(nx!=ny || nx!=nz || ny!=nz)
		{
			m_bNormalCompute=true;
		}
	}
}


void CDXEntity::Rotate( float ax,float ay,float az,float axis,D3DXVECTOR3 va )
{
	D3DXMATRIX mat,mat1,mat2,mat3,mat4;
	D3DXMatrixRotationX(&mat1,ax*D3DX_PI/180);
	D3DXMatrixRotationY(&mat2,ay*D3DX_PI/180);
	D3DXMatrixRotationZ(&mat3,az*D3DX_PI/180);
	D3DXMatrixRotationAxis(&mat4,&va,axis*D3DX_PI/180);
	mat=mat1*mat2*mat3*mat4;
	D3DXVECTOR3 min=m_BoundMin,max=m_BoundMax;
	D3DXVECTOR3 v[8];
	v[0]=D3DXVECTOR3(min.x,max.y,max.z);
	v[1]=D3DXVECTOR3(max.x,max.y,max.z);
	v[2]=D3DXVECTOR3(max.x,max.y,min.z);
	v[3]=D3DXVECTOR3(min.x,max.y,min.z);
	v[4]=D3DXVECTOR3(min.x,min.y,max.z);
	v[5]=D3DXVECTOR3(max.x,min.y,max.z);
	v[6]=D3DXVECTOR3(max.x,min.y,min.z);
	v[7]=D3DXVECTOR3(min.x,min.y,min.z);
	for(int i=0;i<8;i++)
	{
		D3DXVec3TransformCoord(&v[i],&v[i],&mat);
	}
	min=v[0];
	max=v[0];
	for(int i=1;i<8;i++)
	{
		if(v[i].x>max.x)
		{
			max.x=v[i].x;
		}
		if(v[i].y>max.y)
		{
			max.y=v[i].y;
		}
		if(v[i].z>max.z)
		{
			max.z=v[i].z;
		}
		if(v[i].x<min.x)
		{
			min.x=v[i].x;
		}
		if(v[i].y<min.y)
		{
			min.y=v[i].y;
		}
		if(v[i].z<min.z)
		{
			min.z=v[i].z;
		}
	}
	m_BoundMin=min;
	m_BoundMax=max;
	m_Mat*=mat;
	_UpdatePos();
	if(m_pMesh->GetMeshObj()->GetFVF() & D3DFVF_NORMAL)
	{
		m_bNormalCompute=true;
	}
}


void CDXEntity::SetPos( D3DXVECTOR3 min )
{
	D3DXMATRIX mat;
	D3DXVECTOR3 v(min.x-m_BoundMin.x,min.y-m_BoundMin.y,min.z-m_BoundMin.z);
	D3DXMatrixTranslation(&mat,v.x,v.y,v.z);
	m_Mat*=mat;
	_UpdatePos();
}


void CDXEntity::GetPos( D3DXVECTOR3& min,D3DXVECTOR3& max )
{
	min=m_BoundMin;
	max=m_BoundMax;
}


void CDXEntity::_UpdatePos()
{
	if(m_NodeList.size()>0)
	{
		Remove();
		CDXOctNode::root->AddEntity(this,m_StrId);
	}
	
}


D3DXVECTOR3 CDXEntity::GetBoundMin()
{
	return m_BoundMin;
}


D3DXVECTOR3 CDXEntity::GetBoundMax()
{
	return m_BoundMax;
}


void CDXEntity::SetBoundMin( D3DXVECTOR3 min )
{
	m_BoundMin=min;
}


void CDXEntity::SetBoundMax( D3DXVECTOR3 max )
{
	m_BoundMax=max;
}


D3DXMATRIX CDXEntity::GetMatrix()
{
	return m_Mat;
}


void CDXEntity::SetExtMatrix( D3DXMATRIX *mat )
{
	m_ExtMat=*mat;
}


CString CDXEntity::GetID()
{
	return m_StrId;
}


CDXOctNode::CDXOctNode()
{
	memset(m_pChildNode,0,sizeof(m_pChildNode));
	m_pParNode=0;
	m_bSort=false;
	if(ref==0)
	{
		root=this;
		InterlockedIncrement((long*)&ref);
	}
}


void CDXOctNode::AddEntity( CDXEntity* pEntity,CString strId )
{
	if(pEntity==NULL)
	{
		return;
	}
	pEntity->m_StrId=strId;
	EntityIdList[strId]=pEntity;
	if(bCreate)
	{
		vector<CDXOctNode*> NodeList;
		GetRoot()->CheckCollide(pEntity,NodeList);
		for(int i=0;i<NodeList.size();i++)
		{
			list<CDXEntity*>::iterator it;
			for(it=NodeList[i]->m_EntityList.begin();it!=NodeList[i]->m_EntityList.end();it++)
			{
				(*it)->m_NodeList.erase(NodeList[i]);
			}
			NodeList[i]->m_EntityList.push_back(pEntity);
			NodeList[i]->SortNode();
		}
	}else
	{
		m_EntityList.push_back(pEntity);
	}
	
}


int CDXOctNode::GetEntityNum()
{
	return m_EntityList.size();
}


void CDXOctNode::SortNode(D3DXVECTOR3 min,D3DXVECTOR3 max)
{
	if(!bCreate)
	{
		m_MinVec=min;
		m_MaxVec=max;
		m_strId=_T("0");
		_Sort(this,1);
		bCreate=true;
	}else
	{
		CString strId=m_strId[0];
		int iDepth=iDepthNum-_ttoi(strId.GetBuffer(0));
		_Sort(this,iDepth);
	}
	_SortEntity(this);
}


void CDXOctNode::_Sort( CDXOctNode*  pNode,int iDepth)
{
	if(pNode->m_EntityList.size()<=1 || iDepth==iDepthNum)
	{
		return;
	}
	pNode->m_bSort=true;
	float x1=pNode->m_MinVec.x,y1=pNode->m_MinVec.y,z1=pNode->m_MinVec.z;
	float x2=pNode->m_MaxVec.x,y2=pNode->m_MaxVec.y,z2=pNode->m_MaxVec.z;
	pNode->m_pChildNode[0]=new CDXOctNode();
	pNode->m_pChildNode[0]->m_pParNode=pNode;
	pNode->m_pChildNode[0]->m_MinVec=D3DXVECTOR3(x1,y1+(y2-y1)/2,z1+(z2-z1)/2);
	pNode->m_pChildNode[0]->m_MaxVec=D3DXVECTOR3(x1+(x2-x1)/2,y2,z2);
	pNode->m_pChildNode[0]->m_strId.Format(_T("%d0"),iDepth);
	pNode->m_pChildNode[1]=new CDXOctNode();
	pNode->m_pChildNode[1]->m_pParNode=pNode;
	pNode->m_pChildNode[1]->m_MinVec=D3DXVECTOR3(x1+(x2-x1)/2,y1+(y2-y1)/2,z1+(z2-z1)/2);
	pNode->m_pChildNode[1]->m_MaxVec=D3DXVECTOR3(x2,y2,z2);
	pNode->m_pChildNode[1]->m_strId.Format(_T("%d1"),iDepth);
	pNode->m_pChildNode[2]=new CDXOctNode();
	pNode->m_pChildNode[2]->m_pParNode=pNode;
	pNode->m_pChildNode[2]->m_MinVec=D3DXVECTOR3(x1,y1+(y2-y1)/2,z1);
	pNode->m_pChildNode[2]->m_MaxVec=D3DXVECTOR3(x1+(x2-x1)/2,y2,z1+(z2-z1)/2);
	pNode->m_pChildNode[2]->m_strId.Format(_T("%d2"),iDepth);
	pNode->m_pChildNode[3]=new CDXOctNode();
	pNode->m_pChildNode[3]->m_pParNode=pNode;
	pNode->m_pChildNode[3]->m_MinVec=D3DXVECTOR3(x1+(x2-x1)/2,y1+(y2-y1)/2,z1);
	pNode->m_pChildNode[3]->m_MaxVec=D3DXVECTOR3(x2,y2,z1+(z2-z1)/2);
	pNode->m_pChildNode[3]->m_strId.Format(_T("%d3"),iDepth);
	pNode->m_pChildNode[4]=new CDXOctNode();
	pNode->m_pChildNode[4]->m_pParNode=pNode;
	pNode->m_pChildNode[4]->m_MinVec=D3DXVECTOR3(x1,y1,z1+(z2-z1)/2);
	pNode->m_pChildNode[4]->m_MaxVec=D3DXVECTOR3(x1+(x2-x1)/2,y1+(y2-y1)/2,z2);
	pNode->m_pChildNode[4]->m_strId.Format(_T("%d4"),iDepth);
	pNode->m_pChildNode[5]=new CDXOctNode();
	pNode->m_pChildNode[5]->m_pParNode=pNode;
	pNode->m_pChildNode[5]->m_MinVec=D3DXVECTOR3(x1+(x2-x1)/2,y1,z1+(z2-z1)/2);
	pNode->m_pChildNode[5]->m_MaxVec=D3DXVECTOR3(x2,y1+(y2-y1)/2,z2);
	pNode->m_pChildNode[5]->m_strId.Format(_T("%d5"),iDepth);
	pNode->m_pChildNode[6]=new CDXOctNode();
	pNode->m_pChildNode[6]->m_pParNode=pNode;
	pNode->m_pChildNode[6]->m_MinVec=D3DXVECTOR3(x1,y1,z1);
	pNode->m_pChildNode[6]->m_MaxVec=D3DXVECTOR3(x1+(x2-x1)/2,y1+(y2-y1)/2,z1+(z2-z1)/2);
	pNode->m_pChildNode[6]->m_strId.Format(_T("%d6"),iDepth);
	pNode->m_pChildNode[7]=new CDXOctNode();
	pNode->m_pChildNode[7]->m_pParNode=pNode;
	pNode->m_pChildNode[7]->m_MinVec=D3DXVECTOR3(x1+(x2-x1)/2,y1,z1);
	pNode->m_pChildNode[7]->m_MaxVec=D3DXVECTOR3(x2,y1+(y2-y1)/2,z1+(z2-z1)/2);
	pNode->m_pChildNode[7]->m_strId.Format(_T("%d7"),iDepth);
	list<CDXEntity*>::iterator it;
	for(it=pNode->m_EntityList.begin();it!=pNode->m_EntityList.end();)
	{
		for(int i=0;i<8;i++)
		{
			D3DXVECTOR3 min=pNode->m_pChildNode[i]->m_MinVec,max=pNode->m_pChildNode[i]->m_MaxVec;
			if(CDXHelper::CheckBoxCollide(min,max,(*it)->m_BoundMin,(*it)->m_BoundMax))
			{
				pNode->m_pChildNode[i]->m_EntityList.push_back((*it));
				//(*it)->m_NodeList.insert(pNode->m_pChildNode[i]);
			}
		}
		it=pNode->m_EntityList.erase(it);
	}
	iDepth++;
	for(int i=0;i<8;i++)
	{
		_Sort(pNode->m_pChildNode[i],iDepth);
	}
}


CDXOctNode::~CDXOctNode()
{
	if(m_pParNode==0)
	{
		_Release(this);
	}
	InterlockedDecrement((long*)&ref);
}


void CDXOctNode::_Release( CDXOctNode* pNode )
{
	if(pNode)
	{
		for(int i=0;i<8;i++)
		{
			_Release(pNode->m_pChildNode[i]);
		}


		list<CDXEntity*>::iterator it;
		for(it=pNode->m_EntityList.begin();it!=pNode->m_EntityList.end();it++)
		{
			(*it)->Release(pNode);
		}
		if(pNode->m_pParNode)
		{
			delete pNode;
		}	
	}
}


void CDXOctNode::Release()
{
	CDXOctNode *pParentNode=m_pParNode;
	m_pParNode=0;
	_Release(this);
	m_bSort=false;
	memset(m_pChildNode,0,sizeof(m_pChildNode));
	m_pParNode=pParentNode;
}


CDXOctNode* CDXOctNode::GetRoot()
{
	return root;
}


CDXEntity* CDXOctNode::GetEntityById( CString strId )
{
	map<CString,CDXEntity*>::iterator it=EntityIdList.find(strId);
	if(it==EntityIdList.end())
	{
		return 0;
	}else
	{
		return it->second;
	}
}


bool CDXOctNode::CheckCollide( CDXEntity *pEntity,vector<CDXOctNode*>& NodeList )
{
	bool bCollide=false;
	if(pEntity==0)
	{
		return bCollide;
	}
	_CheckCollide(this,pEntity,bCollide,NodeList);
	return bCollide;
}


void CDXOctNode::_CheckCollide(CDXOctNode *pNode, CDXEntity* pEntity,bool &bCollide,vector<CDXOctNode*>& NodeList )
{
	if(pNode)
	{
		if(CDXHelper::CheckBoxCollide(pNode->m_MinVec,pNode->m_MaxVec,pEntity->m_BoundMin,pEntity->m_BoundMax))
		{
			bCollide=true;
			if(pNode->m_bSort==false)
			{
				NodeList.push_back(pNode);
			}else
			{
				for(int i=0;i<8;i++)
				{
					_CheckCollide(pNode->m_pChildNode[i],pEntity,bCollide,NodeList);
				}
			}
		}
	}
}


void CDXOctNode::Render( LPDIRECT3DDEVICE9 pDevice )
{
	D3DXPLANE Planes[6];
	D3DXMATRIX Matrix,matView,matProj;
	pDevice->GetTransform(D3DTS_PROJECTION,&matProj);
	pDevice->GetTransform(D3DTS_VIEW,&matView);
	Matrix=matView*matProj;
	Planes[0].a=Matrix._14+Matrix._13;
	Planes[0].b=Matrix._24+Matrix._23;
	Planes[0].c=Matrix._34+Matrix._33;
	Planes[0].d=Matrix._44+Matrix._43;
	D3DXPlaneNormalize(&Planes[0],&Planes[0]);
	Planes[1].a=Matrix._14-Matrix._13;
	Planes[1].b=Matrix._24-Matrix._23;
	Planes[1].c=Matrix._34-Matrix._33;
	Planes[1].d=Matrix._44-Matrix._43;
	D3DXPlaneNormalize(&Planes[1],&Planes[1]);
	Planes[2].a=Matrix._14+Matrix._11;
	Planes[2].b=Matrix._24+Matrix._21;
	Planes[2].c=Matrix._34+Matrix._31;
	Planes[2].d=Matrix._44+Matrix._41;
	D3DXPlaneNormalize(&Planes[2],&Planes[2]);
	Planes[3].a=Matrix._14-Matrix._11;
	Planes[3].b=Matrix._24-Matrix._21;
	Planes[3].c=Matrix._34-Matrix._31;
	Planes[3].d=Matrix._44-Matrix._41;
	D3DXPlaneNormalize(&Planes[3],&Planes[3]);
	Planes[4].a=Matrix._14-Matrix._12;
	Planes[4].b=Matrix._24-Matrix._22;
	Planes[4].c=Matrix._34-Matrix._32;
	Planes[4].d=Matrix._44-Matrix._42;
	D3DXPlaneNormalize(&Planes[4],&Planes[4]);
	Planes[5].a=Matrix._14+Matrix._12;
	Planes[5].b=Matrix._24+Matrix._22;
	Planes[5].c=Matrix._34+Matrix._32;
	Planes[5].d=Matrix._44+Matrix._42;
	D3DXPlaneNormalize(&Planes[5],&Planes[5]);
	_Render(this,Planes);
	list<CDXEntity*>::iterator it;
	for(it=RenderList.begin();it!=RenderList.end();it++)
	{
		CDXEntity *pEntity=*it;
		pEntity->m_bDrawed=false;
		pEntity->m_pMesh->GetDevice()->SetTransform(D3DTS_WORLD,&(pEntity->m_Mat*pEntity->m_ExtMat));
		pEntity->m_pMesh->Render();
	}
	RenderList.clear();
}


bool CDXOctNode::_CheckInFrustum( D3DXVECTOR3 &min,D3DXVECTOR3 &max,D3DXPLANE *Planes,bool *bFullContained )
{
	D3DXVECTOR3 v[8];
	v[0]=D3DXVECTOR3(min.x,max.y,max.z);
	v[1]=D3DXVECTOR3(max.x,max.y,max.z);
	v[2]=D3DXVECTOR3(max.x,max.y,min.z);
	v[3]=D3DXVECTOR3(min.x,max.y,min.z);
	v[4]=D3DXVECTOR3(min.x,min.y,max.z);
	v[5]=D3DXVECTOR3(max.x,min.y,max.z);
	v[6]=D3DXVECTOR3(max.x,min.y,min.z);
	v[7]=D3DXVECTOR3(min.x,min.y,min.z);
	int iFullPoint=0;
	for(int i=0;i<6;i++)
	{
		int iCount=8;
		for(int j=0;j<8;j++)
		{
			if(Planes[i].a * v[j].x +Planes[i].b * v[j].y +Planes[i].c * v[j].z+ Planes[i].d<0.0f)
			{
				iCount--;
			}
		}
		if(iCount==0)
		{
			return false;
		}else if(iCount==8)
		{
			iFullPoint++;
		}
	}
	if(iFullPoint==6)
	{
		*bFullContained=true;
	}else
	{
		*bFullContained=false;
	}
	return true;
}


void CDXOctNode::_Render( CDXOctNode* pNode,D3DXPLANE* Planes,bool bCheck )
{
	if(bCheck)
	{
		bool bFullContained;
		if(_CheckInFrustum(pNode->m_MinVec,pNode->m_MaxVec,Planes,&bFullContained))
		{
				if(pNode->m_bSort==true)
				{
					for(int i=0;i<8;i++)
					{
						_Render(pNode->m_pChildNode[i],Planes,!bFullContained);
					}
				}else
				{
					if(pNode->m_EntityList.size()>0)
					{
						list<CDXEntity*>::iterator it;
						for(it=pNode->m_EntityList.begin();it!=pNode->m_EntityList.end();it++)
						{
							CDXEntity *pEntity=*it;
							bool bFull;
							if(_CheckInFrustum(pEntity->m_BoundMin,pEntity->m_BoundMax,Planes,&bFull))
							{
								pEntity->Render();
							}
						}
					}
				}


		}
	}else
	{
		if(pNode->m_bSort==true)
		{
			for(int i=0;i<8;i++)
			{
				_Render(pNode->m_pChildNode[i],Planes,false);
			}
		}else
		{
			if(pNode->m_EntityList.size()>0)
			{
				list<CDXEntity*>::iterator it;
				for(it=pNode->m_EntityList.begin();it!=pNode->m_EntityList.end();it++)
				{
					CDXEntity *pEntity=*it;
					pEntity->Render();
				}
			}
		}
	}
	
	
}


bool CDXOctNode::CheckCollideEntity( D3DXVECTOR3 Min,D3DXVECTOR3 Max,set<CDXEntity*>& EntitySet )
{
	bool bCollide=false;
	_CheckCollideEntity(this,Min,Max,bCollide,EntitySet);
	return bCollide;
}


void CDXOctNode::_CheckCollideEntity( CDXOctNode *pNode,D3DXVECTOR3 Min,D3DXVECTOR3 Max,bool &bCollide,set<CDXEntity*>& EntitySet )
{
	if(pNode)
	{
		if(CDXHelper::CheckBoxCollide(pNode->m_MinVec,pNode->m_MaxVec,Min,Max))
		{
			if(pNode->m_bSort==false)
			{
				list<CDXEntity*>::iterator it;
				for(it=pNode->m_EntityList.begin();it!=pNode->m_EntityList.end();it++)
				{
					if(CDXHelper::CheckBoxCollide((*it)->m_BoundMin,(*it)->m_BoundMax,Min,Max) && EntitySet.find(*it)==EntitySet.end())
					{
						bCollide=true;
						EntitySet.insert(*it);
					}
				}
			}else
			{
				for(int i=0;i<8;i++)
				{
					_CheckCollideEntity(pNode->m_pChildNode[i],Min,Max,bCollide,EntitySet);
				}
			}
		}
	}
}


void CDXOctNode::_SortEntity( CDXOctNode* pNode )
{
	if(pNode)
	{
			if(pNode->m_bSort==false)
			{
				list<CDXEntity*>::iterator it;
				for(it=pNode->m_EntityList.begin();it!=pNode->m_EntityList.end();it++)
				{
					(*it)->m_NodeList.insert(pNode);
				}
			}else
			{
				for(int i=0;i<8;i++)
				{
					_SortEntity(pNode->m_pChildNode[i]);
				}
			}
	}
}


list<CDXEntity*> CDXOctNode::RenderList;


bool CDXOctNode::bCreate=false;


int CDXOctNode::iDepthNum=4;


map<CString,CDXEntity*> CDXOctNode::EntityIdList;


CDXOctNode* CDXOctNode::root=0;
int CDXOctNode::ref=0;


CDXSkinMesh::CDXSkinMesh()
{
	m_pFrameRoot=0 ;
	m_pBoneMatrices=0;
	m_pAllocateHier=0;
	m_pAnimController=0;
	m_pDevice=0;
}


CDXSkinMesh::~CDXSkinMesh()
{
	if(m_pAllocateHier)
	{
		delete m_pAllocateHier;
		m_pAllocateHier=0;
	}
}


void CDXSkinMesh::LoadFromFile( LPDIRECT3DDEVICE9 pDevice,LPCTSTR tcsPath )
{
	if(pDevice)
	{
		m_pDevice=pDevice;
		m_pAllocateHier = new CAllocateHierarchy();
		TCHAR szDir[255];
		_tcscpy(szDir,tcsPath);
		PathRemoveFileSpec(szDir);
		_tcscat(szDir,_T("\\"));
#ifdef _UNICODE
		USES_CONVERSION;
		m_pAllocateHier->SetDir(W2A(szDir));
#else
		m_pAllocateHier->SetDir(szDir);
#endif
		D3DXLoadMeshHierarchyFromX(tcsPath, D3DXMESH_MANAGED, m_pDevice, 
			m_pAllocateHier, NULL, &m_pFrameRoot, &m_pAnimController);
		SetupBoneMatrixPointers(m_pFrameRoot, m_pFrameRoot);
	}


}


void CDXSkinMesh::Update( float fDeltaTime ,D3DXMATRIX *mat)
{
	if(m_pDevice)
	{
		// 更新骨骼动画
		m_pAnimController->AdvanceTime(fDeltaTime, NULL);  //设置骨骼动画的时间
		UpdateFrameMatrices(m_pFrameRoot, mat);   //更新框架中的变换矩阵
	}
	
}


void CDXSkinMesh::Render()
{
	if(m_pDevice)
	{
		DrawFrame(m_pDevice, m_pFrameRoot);
	}
}


void CDXSkinMesh::SetAnimation( LPCSTR szAnimName )
{
	 LPD3DXANIMATIONSET pAnimationSet = NULL;
	 m_pAnimController->GetAnimationSetByName(szAnimName, &pAnimationSet);
	 m_pAnimController->SetTrackAnimationSet((UINT)0, pAnimationSet);
	 if(pAnimationSet)
	 {
		pAnimationSet->Release();
	 }
}


void CDXSkinMesh::SetAnimation( int iAnimIndex )
{
	LPD3DXANIMATIONSET pAnimationSet = NULL;
	m_pAnimController->GetAnimationSet(iAnimIndex, &pAnimationSet);
	m_pAnimController->SetTrackAnimationSet((UINT)0, pAnimationSet);
	if(pAnimationSet)
	{
		pAnimationSet->Release();
	}
}






CDXShader::CDXShader()
{
	m_pDevice=0;
	m_pCurEffect=0;
}


CDXShader::~CDXShader()
{
	map<CString,ID3DXEffect*>::iterator it;
	for(it=m_EffectList.begin();it!=m_EffectList.end();it++)
	{
		if(it->second)
		{
			it->second->Release();
		}
	}
}


bool CDXShader::AddEffect( LPCTSTR tcsPath,LPCTSTR tcsName )
{
	if(m_EffectList.find(tcsName)!=m_EffectList.end() || !m_pDevice)
	{
		return false;
	}
	ID3DXEffect *pEffect=0;
	ID3DXBuffer *pErrorEffect=0;
	D3DXCreateEffectFromFile(m_pDevice,tcsPath,0,0,0,0,&pEffect,&pErrorEffect);
	if(pErrorEffect || !pEffect)
	{
		return false;
	}
	m_EffectList[tcsName]=pEffect;
	return true;
}


void CDXShader::Create( LPDIRECT3DDEVICE9 pDevice )
{
	if(pDevice)
	{
		m_pDevice=pDevice;
	}
}


void CDXShader::SetEffect( LPCTSTR tcsName )
{
	if(m_EffectList.find(tcsName)!=m_EffectList.end())
	{
		m_pCurEffect=m_EffectList[tcsName];
	}
}


ID3DXEffect* CDXShader::operator->()
{
	return m_pCurEffect;
}


void CDXThirdCamera::Create( D3DXVECTOR3 vEye,D3DXVECTOR3 vAt )
{
	m_vEye=vEye;
	m_vAt=vAt;


}


void CDXThirdCamera::RorateY( float fAngle )
{
	D3DXMATRIX mat,matY,matTrans;
	D3DXMatrixTranslation(&mat,-m_vAt.x,-m_vAt.y,-m_vAt.z);
	D3DXMatrixRotationY(&matY,fAngle*D3DX_PI/180);
	D3DXMatrixTranslation(&matTrans,m_vAt.x,m_vAt.y,m_vAt.z);
	mat=mat*matY*matTrans;
	D3DXVec3TransformCoord(&m_vEye,&m_vEye,&mat);
}


void CDXThirdCamera::RorateAxis( float fAngle )
{
	D3DXVECTOR3 u=m_vEye-m_vAt;
	D3DXVECTOR3 v=D3DXVECTOR3(m_vAt.x,0,m_vAt.z)-m_vAt;
	D3DXVECTOR3 out;
	D3DXVec3Cross(&out,&u,&v);
	D3DXVec3Normalize(&out,&out);
	D3DXMATRIX mat,matAxis,matTrans;
	D3DXMatrixTranslation(&mat,-m_vAt.x,-m_vAt.y,-m_vAt.z);
	D3DXMatrixRotationAxis(&matAxis,&out,fAngle*D3DX_PI/180);
	D3DXMatrixTranslation(&matTrans,m_vAt.x,m_vAt.y,m_vAt.z);
	mat=mat*matAxis*matTrans;
	D3DXVec3TransformCoord(&m_vEye,&m_vEye,&mat);
}


void CDXThirdCamera::Scale( float fParam )
{
	D3DXVECTOR3 vScale=m_vAt-m_vEye;
	m_vEye+=vScale*(1-fParam);
}


void CDXThirdCamera::GetTransform( D3DXMATRIX *Matrix )
{
	D3DXMatrixLookAtLH(Matrix,&m_vEye,&m_vAt,&D3DXVECTOR3(0,1,0));
}


void CDXThirdCamera::Walk( float fWalk )
{
	D3DXVECTOR2 Normal=D3DXVECTOR2(m_vAt.x,m_vAt.z)-D3DXVECTOR2(m_vEye.x,m_vEye.z);
	D3DXVec2Normalize(&Normal,&Normal);
	m_vAt+=D3DXVECTOR3(fWalk*Normal.x,0,fWalk*Normal.y);
	m_vEye+=D3DXVECTOR3(fWalk*Normal.x,0,fWalk*Normal.y);
}


D3DXVECTOR3 CDXThirdCamera::GetEye()
{
	return m_vEye;
}


D3DXVECTOR3 CDXThirdCamera::GetAt()
{
	return m_vAt;
}


void CDXThirdCamera::SetEyeHeight( float iY )
{
	m_vEye.y=iY;
}


void CDXThirdCamera::SetAtHeight( float iY )
{
	m_vAt.y=iY;
}


void CDXThirdCamera::SetEye( D3DXVECTOR3 Eye )
{
	m_vEye=Eye;
}


void CDXThirdCamera::SetAt( D3DXVECTOR3 At )
{
	m_vAt=At;
}


void CDXThirdCamera::Left( float fLeft )
{
	D3DXVECTOR3 u=m_vEye-m_vAt;
	D3DXVECTOR3 v=D3DXVECTOR3(m_vAt.x,0,m_vAt.z)-m_vAt;
	D3DXVECTOR3 out;
	D3DXVec3Cross(&out,&u,&v);
	D3DXVec3Normalize(&out,&out);
	m_vAt+=D3DXVECTOR3(fLeft*out.x,0,fLeft*out.z);
	m_vEye+=D3DXVECTOR3(fLeft*out.x,0,fLeft*out.z);
}




CDXLua::CDXLua()
{
	m_pLua =lua_open();
	luaL_openlibs(m_pLua);
}


CDXLua::~CDXLua()
{
	lua_close(m_pLua);
}


bool CDXLua::Execute( LPCSTR szPath )
{
	int iTop=lua_gettop(m_pLua);
	int ret=luaL_dofile(m_pLua,szPath);
	if(ret!=0)
	{
		 printf("[CLuaFn:: LoadLuaFile]luaL_loadfile(%s) is file(%d)(%s).\n", szPath, ret, lua_tostring(m_pLua, -1));
		 lua_settop(m_pLua,iTop);
		 return false;
	}
	lua_settop(m_pLua,iTop);
	return true;
}


float CDXLua::GetNum( LPCSTR szName )
{
	int iTop=lua_gettop(m_pLua);
	lua_getglobal(m_pLua,szName);
	if(!lua_isnumber(m_pLua,-1))
	{
		cout<<"GetNum error,Name:"<<szName<<endl;
		lua_settop(m_pLua,iTop);
		return 0;
	}
	float iRet=lua_tonumber(m_pLua,-1);
	lua_settop(m_pLua,iTop);
	return iRet;
}


LPCSTR CDXLua::GetString( LPCSTR szName )
{
	int iTop=lua_gettop(m_pLua);
	lua_getglobal(m_pLua,szName);
	if(!lua_isstring(m_pLua,-1))
	{
		cout<<"GetString error,Name:"<<szName<<endl;
		lua_settop(m_pLua,iTop);
		return 0;
	}
	LPCSTR szRet=lua_tostring(m_pLua,-1);
	lua_settop(m_pLua,iTop);
	return szRet;
}


float CDXLua::GetTableNum( LPCSTR szTable,LPCSTR szKey )
{
	int iTop=lua_gettop(m_pLua);
	lua_getglobal(m_pLua,szTable);
	if(!lua_istable(m_pLua,-1))
	{
		cout<<"GetTableNum error,TableName:"<<szTable<<"  KeyName:"<<szKey<<endl;
		lua_settop(m_pLua,iTop);
		return 0;
	}
	lua_pushstring(m_pLua,szKey);
	lua_gettable(m_pLua,-2);
	if(!lua_isnumber(m_pLua,-1))
	{
		cout<<"GetTableNum error,TableName:"<<szTable<<"  KeyName:"<<szKey<<endl;
		lua_settop(m_pLua,iTop);
		return 0;
	}
	float iRet=lua_tonumber(m_pLua,-1);
	lua_settop(m_pLua,iTop);
	return iRet;
}


LPCSTR CDXLua::GetTableString( LPCSTR szTable,LPCSTR szKey )
{
	int iTop=lua_gettop(m_pLua);
	lua_getglobal(m_pLua,szTable);
	if(!lua_istable(m_pLua,-1))
	{
		cout<<"GetTableString error,TableName:"<<szTable<<"  KeyName:"<<szKey<<endl;
		lua_settop(m_pLua,iTop);
		return 0;
	}
	lua_pushstring(m_pLua,szKey);
	lua_gettable(m_pLua,-2);
	if(!lua_isstring(m_pLua,-1))
	{
		cout<<"GetTableString error,TableName:"<<szTable<<"  KeyName:"<<szKey<<endl;
		lua_settop(m_pLua,iTop);
		return 0;
	}
	LPCSTR szRet=lua_tostring(m_pLua,-1);
	lua_settop(m_pLua,iTop);
	return szRet;
}


void CDXLua::CallFunc( LPCSTR szFunc )
{
	int iTop=lua_gettop(m_pLua);
	lua_getglobal(m_pLua,szFunc);
	if(lua_pcall(m_pLua,0,0,0)!=0)
	{
		cout<<"CallFunc error,Name:"<<szFunc<<endl;
	}
	lua_settop(m_pLua,iTop);
}


lua_State * CDXLua::GetLua()
{
	return m_pLua;
}

       在上面的demo里面,我们使用了CDXListBox,CDXEdit这两个DXLib内部的控件,以及CDXMyButton这个控件,该控件也是继承DXLib内部的CDXButton控件。有兴趣的朋友可以试试这些控件,有什么建议也可以跟我提出来,我会不断改善的。

       还有一点SetDrawDelay函数是设置DX程序的fps值,这里设置的是1000/20,也就是50。SetFps函数是设置fps的值是否显示在程序的左上角。下面我列出所有的DXLib的类,让大家一目了然:

CDXBaseMesh:网格的基类,是CDXEntity里的Mesh存储对象

CDXButton:Button控件

CDXCamera:第一人称Camera视角

CDXControl:控件的基类

CDXEdit:Edit控件

CDXEntity:实体类,主要作用于八叉树,用于存放每个Mesh对象

CDXHelper:Help帮助函数,可以做一些快速检测等操作

CDXLand:基于灰度图的地形渲染类

CDXListBox:Listbox控件

CDXLua:Lua脚本操作类

CDXMesh:网格操作类

CDXMutiplyStatic: 多行Static控件

CDXOctNode:八叉树渲染

CDXParticle:粒子渲染

CDXShader: Shader渲染

CDXSkinMesh: 骨骼动画操作类

CDXSky: 天空盒

CDXStatic:  Static控件

CDXThirdCamera: 第三人称Camera视角

CDXWindow: DX窗体类,DX的创建,渲染,释放等

CDXXFile: 静态X文件渲染类


      文章有不足之处,还望大家多多指正。




     

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值