• 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;
    	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).
    ", 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;
    }
    


           下面我来介绍下这个库:CDXWindow是整个库的基础,负责整个DX程序的创建和结束,整个渲染与逻辑处理部分并不在主线程里面,而是在DrawThread这个线程里面,这样做的目的就是当你再操作窗体的时候并不会影响游戏的正常运行,值得注意的是设备丢失的话如果不在DX创建的那个主线程,那么设备恢复就会有问题,所以我在DrawThread里面使用消息通知的模式,当设备丢失时会通知主线程去恢复设备,恢复后通知DrawThread恢复完成。

           我们要注意CDXWindow的以下几个虚函数:

            virtual void DXDraw(bool bInputEnabled)=0;  //渲染函数
    virtual bool ExtInit(){return true;}    //初始化资源

    virtual void DXRelease(){}     //程序退出的释放资源函数

       virtual void DXOnLostDevice();        //设备丢失函数

      virtual void DXOnResetDevice();
    virtual void DXBeforeDraw(bool bInputEnabled){}
             
       //逻辑处理函数

               virtual void DXAfterDraw(bool bInputEnabled){} 

     

     

             其中 DXDraw是我们的程序必须要重载的虚函数,下面给出一个简单的例子:

     

    // DXUI.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "DXLib.h"
    #include <io.h>
    #include <fcntl.h>
    #pragma comment(linker, "/subsystem:"windows" /entry:"mainCRTStartup"" )
    class CDXMyButton:public CDXButton
    {
    public:
    	void OnMouseOver(int x,int y);
    	void OnMouseLeave(int x,int y);
    	void OnMouseMove(int x,int y);
    };
    
    void CDXMyButton::OnMouseOver(int x,int y)
    {
    	SetBKColor(D3DCOLOR_XRGB(110,110,10));
    }
    
    void CDXMyButton::OnMouseLeave(int x,int y)
    {
    	SetBKColor(D3DCOLOR_XRGB(255,255,255));
    }
    
    void CDXMyButton::OnMouseMove( int x,int y )
    {
    	WCHAR wzBuf[255]={0};
    	wsprintf(wzBuf,L"%d,%d",x,y);
    	SetText(wzBuf);
    }
    
    class MyWin:public CDXWindow
    {
    public:
    	MyWin(){}
    protected:
    	void DXDraw(bool bInputEnabled);
    	bool ExtInit();
    	ID3DXSprite *m_Spr;
    	CDXMyButton m_Button;
    	void DXBeforeDraw(bool bInputEnabled);
    	ID3DXFont *m_Font;
    	void DXOnLostDevice();
    	void DXOnResetDevice();
    	CDXListBox m_Listbox;
    	CDXEdit m_Edit;
    	CDXXFile m_XFile;
    };
    
    void MyWin::DXDraw(bool bInputEnabled)
    {
    //	m_XFile.Render();
    
    
    	RECT r={10,20,120,100};
    	DXDrawQuad(&r,D3DCOLOR_ARGB(255,1,11,0),true);
    	DXDrawQuad(&r,D3DCOLOR_ARGB(255,111,111,0),true);
    	
    
    }
    
    bool MyWin::ExtInit()
    {
    	SetBKColor(D3DCOLOR_XRGB(10,111,10));
    	m_Edit.Create(this,300,100,100,20);
    	m_Button.Create(this,200,200,300,200);
    	m_Button.SetFont(30,_T("微软雅黑"));
    	m_Button.SetText(_T("df5345"));
    	m_Button.SetForeColor(D3DCOLOR_XRGB(66,66,66));
    	//m_Button.SetBkImg(_T("c:\1.bmp"));
    	m_Button.SetBKColor(D3DCOLOR_XRGB(255,255,255));
    	m_Button.SetVertexAlpha(true);
    	m_Spr=DXCreateSprite();
     	//m_pd3dDevice->CreateTexture(500,500,1,D3DUSAGE_RENDERTARGET,D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT,&m_Tex,0);
    //	m_pd3dDevice->CreateRenderTarget(500,500,D3DFMT_X8R8G8B8,D3DMULTISAMPLE_NONE,1,0,&m_Sur,0);
    //	m_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&m_back);
    	m_Font=DXCreateFont();
    	m_Listbox.Create(this,400,400,100,100,30);
    	m_Listbox.AddItem(L"123");
    	m_Listbox.AddItem(L"ewrw");
    	m_Listbox.AddItem(L"12ds3");
    	m_Listbox.AddItem(L"r2");
    	m_Listbox.AddItem(L"dsgs");
    	m_Listbox.AddItem(L"fgf");
    	m_Listbox.AddItem(L"56");
    	m_Listbox.AddItem(L"123");
    	m_Listbox.AddItem(L"ewrw");
    	m_Listbox.AddItem(L"12ds3");
    	m_Listbox.AddItem(L"r2");
    	m_Listbox.AddItem(L"dsgs");
    	m_Listbox.AddItem(L"fgf");
    	m_Listbox.AddItem(L"56");
    // 	AllocConsole();
    // 
    // 	// 取得 STDOUT 的文件系统
    // 	HANDLE stdOutputHandle = GetStdHandle( STD_OUTPUT_HANDLE );
    // 
    // 	// Redirect STDOUT to the new console by associating STDOUT's file 
    // 	// descriptor with an existing operating-system file handle.
    // 	int hConsoleHandle = _open_osfhandle( (intptr_t)stdOutputHandle, _O_TEXT );
    // 	FILE *pFile = _fdopen( hConsoleHandle, "w" );
    // 	*stdout = *pFile;
    // 	setvbuf( stdout, NULL, _IONBF, 0 );
    // 
    // 	// 这个调用确保 iostream 和 C run-time library 的操作在源代码中有序。 
    // 	ios::sync_with_stdio();
    // 	cout<<1<<endl;
    //	m_XFile.LoadFile(L"C:\Users\sx\Desktop\12.x",m_pd3dDevice);
    	return true;
    }
    
    void MyWin::DXBeforeDraw( bool bInputEnabled )
    {
    // 	m_Tex->GetSurfaceLevel(0,&m_Sur);
    // 	IDirect3DSurface9 *curSurface;
    // 	m_pd3dDevice->GetRenderTarget(0,&curSurface);
    // 	m_pd3dDevice->SetRenderTarget(0,m_Sur);
    // 	//m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
    // 	m_pd3dDevice->BeginScene();
    // 	RECT r={10,10,400,400};
    // 	if(FAILED(m_Font->DrawTextW(0,L"123456789",9,&r,DT_TOP|DT_LEFT,D3DCOLOR_XRGB(155,15,155))))
    // 	{
    // 		return;
    // 	}
    // 	m_pd3dDevice->EndScene();
    // 	m_pd3dDevice->SetRenderTarget(0,curSurface);
    // 	curSurface->Release();
    // 	m_Sur->Release();
    }
    
    void MyWin::DXOnLostDevice()
    {
    	m_Spr->OnLostDevice();
    	m_Font->OnLostDevice();
    }
    
    void MyWin::DXOnResetDevice()
    {
    	m_Spr->OnResetDevice();
    	m_Font->OnResetDevice();
    }
    
    
    int main(int argc, _TCHAR* argv[])
    {
    	CoInitialize(0);
    	MyWin win;
    	win.Create(_T("sx"),0,20,30,800,600);
    	win.SetDrawDelay(20);
    	win.SetFps(true);
    	win.DoModal();
    	return 0;
    }
    


           在上面的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文件渲染类


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




         

  • 相关阅读:
    [20190401]跟踪dbms_lock.sleep调用.txt
    [20190401]隐含参数_mutex_spin_count.txt
    [20190401]关于semtimedop函数调用.txt
    [20190401]那个更快的疑问.txt
    [20190329]探究sql语句相关mutexes补充2.txt
    [20190328]简单探究sql语句相关mutexes.txt
    [20190324]奇怪的GV$FILESPACE_USAGE视图.txt
    [20190322]测试相同语句遇到导致cursor pin S的疑问.txt
    linux命令(8):cp 命令
    linux命令(7):mv命令
  • 原文地址:https://www.cnblogs.com/james1207/p/3358012.html
Copyright © 2020-2023  润新知