⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mouseray.cpp

📁 一个关于在DX编程中的的鼠标拣选的DEMO。
💻 CPP
字号:
#include "d3dUtility.h"
 
HWND g_hwnd=0;
IDirect3DDevice9* Device = 0; 
const int Width  = 640;
const int Height = 480;

struct Ray														//	射线结构
{
	D3DXVECTOR3 _origin;							//	射线起点
	D3DXVECTOR3 _dirction;						//	射线方向
};

struct BoundSphere											//	绑定球
{
	D3DXVECTOR3 _center;							//	中心点
	float		radius;												//	半径
};

LPD3DXMESH Sphere[2];                    // 球mesh	Mesh object.

 
bool						m_bRotate[2];					//	2个旋转开关
float						m_fAngle[2];						//	2个角度
BoundSphere		m_boundSphere[2];			//	2个绑定球

 
Ray CalculateRay(int x, int y)// 计算拾取射线,传入鼠标的x和y,返回射线结构
{
	float px=0.0f;
	float py=0.0f;
	//获取视口大小
	D3DVIEWPORT9 vp;
	//////////////////////////////////////////////////////////////////////////
	//typedef struct _D3DVIEWPORT9 {
	//	DWORD       X;
	//	DWORD       Y;            /* Viewport Top left */
	//	DWORD       Width;
	//	DWORD       Height;       /* Viewport Dimensions */
	//	float       MinZ;         /* Min/max of clip Volume */
	//	float       MaxZ;
	//} D3DVIEWPORT9;
	//////////////////////////////////////////////////////////////////////////
	Device->GetViewport(&vp);
	D3DXMATRIX proj;
	Device->GetTransform(D3DTS_PROJECTION,&proj);//获取投影矩阵
	//计算拾取射线,以下为数学公式转换而来
	px=(((2.0f*x)/vp.Width)-1.0f)/proj._11;
	py=(((-2.0f*y)/vp.Height)+1.0f)/proj._22;
	Ray ray;
	ray._origin = D3DXVECTOR3(0.0f,0.0f,0.0f);				//	射线源点在中心
	ray._dirction = D3DXVECTOR3(px,py,1.0f);				//	方向指向通过xy转换的pxpy
	return ray;
}

Ray  TransformRay(Ray ray, D3DXMATRIX* T)		// 转换射线,将射线转换到世界空间中
{
	Ray transRay;
	D3DXVec3TransformCoord(&transRay._origin,&ray._origin,T);		//转换射线的起点,起点是按照点变换的w=1
	D3DXVec3TransformNormal(&transRay._dirction,&ray._dirction,T);//转换射线的方向,方向是按照向量变换的w=0
	D3DXVec3Normalize(&transRay._dirction,&transRay._dirction);//标准化向量
	return transRay;
}

BOOL CheckIntersection(Ray* ray, BoundSphere* sphere)	// 计算与球的相交
{
	//计算t0与t1的值
	D3DXVECTOR3 v = ray->_origin-sphere->_center;		//	建立从原点指向球中心的向量
	float b = 2.0f*D3DXVec3Dot(&ray->_dirction,&v);
	float c = D3DXVec3Dot(&v,&v)-(sphere->radius*sphere->radius);

	float n = (b*b)-(4.0f*c);
	if (n<0.0f)
	{
		return false;
	}
	n = sqrtf(n);
	float t0 = (-b+n)/2.0f;
	float t1 = (-b-n)/2.0f;
	//判断是否相交
	if (t0>=0||t1>=0)
	{
		return true;
	}
	return false;
}


bool Setup()
{
	D3DXMATRIX matRroj;
	D3DXMatrixPerspectiveFovLH( &matRroj, D3DX_PI/4, 4.f/3.f, 1.f, 500.0f );
	Device->SetTransform(D3DTS_PROJECTION, &matRroj);
	// 更新视矩阵
	D3DXMATRIX matView;
	D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3(13.0f, 13.0f, 13.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f) );
	Device->SetTransform(D3DTS_VIEW, &matView);
	Device->SetRenderState( D3DRS_LIGHTING, false );		//	关灯
	Device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);// 改为线框绘制


	// 创建球		To create the sphere we simple call D3DXCreateSphere and the rest is done for us.
	if(FAILED(D3DXCreateSphere(Device, 3.0f, 15, 15, &Sphere[0], NULL)))	//	参数3,4是经纬度线条数量
		return false;
	// 创建球		To create the sphere we simple call D3DXCreateSphere and the rest is done for us.
	if(FAILED(D3DXCreateSphere(Device, 3.0f, 25, 25, &Sphere[1], NULL)))
		return false;

	for(int i=0; i<2; ++i)
	{
		m_boundSphere[i]._center = D3DXVECTOR3(-5.0f + i*10.0f, 0.0f, 0.0f);			//	设置绑定球中心点,与绘制球mesh的位置相同
		m_boundSphere[i].radius = 3.0f;			//	设置绑定球半径,应与上面的球模型半径相同
		m_bRotate[i] = false;		//	关闭旋转
		m_fAngle[i] = 0.0f;			//	赋值旋转角度为0
	}

 	return true;
}

void Cleanup()
{
	SAFE_RELEASE(Sphere[0]);
	SAFE_RELEASE(Sphere[1]);
}

bool Display(float timeDelta)
{
	if( Device )
	{
	Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00888888, 1.0f, 0);
	Device->BeginScene();
	 

	D3DXMATRIX matWorld;
	for(int i=0; i<2; ++i)
	{
		if(m_bRotate[i])
			m_fAngle[i] += 1.5f * timeDelta;					//	更新角度

		D3DXMatrixRotationY(&matWorld, m_fAngle[i]);
		matWorld._41 = -5.0f + i*10.0f;			//	x		更新位置,也可使用平移矩阵只不过麻烦些,在这就直接改了
		matWorld._42 = 0.0f;							//	y
		matWorld._43 = 0.0f;							// z

		Device->SetTransform( D3DTS_WORLD, &matWorld );
		Sphere[i]->DrawSubset(0);
	}

	Device->EndScene();
	Device->Present(0, 0, 0, 0);
	}
	return true;
}

LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch( msg )
	{
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
		
	case WM_KEYDOWN:
		if( wParam == VK_ESCAPE )
			::DestroyWindow(hwnd);
		break;
	case WM_LBUTTONDOWN:
		{
			POINT pt;			//	定义点结构
			GetCursorPos(&pt);		//	获取当前鼠标位置
			ScreenToClient(g_hwnd, &pt);			//	屏幕位置转到窗口位置

			Ray ray = CalculateRay(pt.x, pt.y);	//	通过鼠标位置计算射线
			D3DXMATRIX mat;
			Device->GetTransform(D3DTS_VIEW, &mat);		//	获取摄像机矩阵
			D3DXMatrixInverse(&mat, NULL, &mat);					//	取得摄像机矩阵的逆矩阵
			ray = TransformRay(ray, &mat);								//	将射线转换到世界空间中

			for(int i=0; i<2; ++i)
			{
				if( CheckIntersection(&ray, &m_boundSphere[i]) )
					m_bRotate[i] = true;
				else
					m_bRotate[i] = false;
			}

		}
		break;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hinstance,
				   HINSTANCE prevInstance, 
				   PSTR cmdLine,
				   int showCmd)
{
	if(!d3d::InitD3D(hinstance,
		Width, Height, true, D3DDEVTYPE_HAL, &Device,g_hwnd))
	{
		::MessageBox(0, "InitD3D() - FAILED", 0, 0);
		return 0;
	}
	if(!Setup())
	{
		::MessageBox(0, "Setup() - FAILED", 0, 0);
		return 0;
	}
	d3d::EnterMsgLoop( Display );
	Cleanup();
	Device->Release();
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -