DirectX3D--正交矩阵、旋转、平移、DrawPrimitive 综合dome

在学习了 DIRECTX.9.0.3D游戏开发编程基础 一书 前4章后,终于写了一个简单dome,将前4章内容进行了整合。

此dome主要涉及坐标转换、正交投影矩阵、DrawPrimitive、SetRenderState 等知识点。现将主要代码进行讲解。

1、初始化DirectX3D组件

bool UIMain::InitD3d(HINSTANCE hInst, int width, int height)
{
	m_hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 01: CreateDevice", 
		WS_OVERLAPPEDWINDOW, 100, 100, width, height,
		NULL, NULL, m_wc.hInstance, NULL );
	
	if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
		return false;

	D3DPRESENT_PARAMETERS d3dpp; 
	ZeroMemory( &d3dpp, sizeof(d3dpp) );
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

	if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp, &g_pd3dDevice ) ) )
	{
		return false;
	}

	ShowWindow( m_hWnd, SW_SHOWDEFAULT );
	UpdateWindow( m_hWnd );
	return true;
}

2、顶点数据初始化

struct Vertex  //顶点数据
{
	Vertex() {};
	Vertex(float _x, float _y, float _z, D3DCOLOR _color) 
	{
		x = _x; 
		y = _y;
		z = _z;
		color = _color;
	}
	float x, y, z;
	DWORD color; 
	static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ |D3DFVF_DIFFUSE;

bool DrawPrimitiveDlg::InitData()
{
	if( FAILED( g_pd3dDevice->CreateVertexBuffer( PointNum * sizeof(Vertex),
		D3DUSAGE_WRITEONLY, Vertex::FVF,
		D3DPOOL_DEFAULT, &m_VB, NULL ) ) )
	{
		return false;
	}

	Vertex* vertices = NULL;
	m_VB->Lock(0,0,(void**) &vertices, 0);
	vertices[0] = Vertex(-1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,   0,   0));  //一个正方形
	vertices[1] = Vertex(-1.0f,  1.0f, 0.0f, D3DCOLOR_XRGB(  0, 255,   0));  
	vertices[2] = Vertex( 1.0f,  1.0f, 0.0f, D3DCOLOR_XRGB(  0,   0, 255));
	vertices[3] = Vertex(1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,   0,   0));
	vertices[4] = Vertex(0.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(  0, 255,   0));
	vertices[5] = Vertex(0.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(  0,   0, 255));
	m_VB->Unlock();

	return true;
}

3、绘制函数

利用D3DXMatrixTransformation函数获取了 平移+旋转的 转换矩阵。并用D3DXMatrixOrthoLH函数获取了正交投影矩阵。

分别绘制了直线(D3DPT_LINELIST)、折线(D3DPT_LINESTRIP)、孤立三角新(D3DPT_TRIANGLELIST)、三角形条带(D3DPT_TRIANGLESTRIP)、三角形扇形(D3DPT_TRIANGLEFAN)。

代码中的注释已经相当详细,不用过多解释。


void DrawPrimitiveDlg::Render()
{
    g_pd3dDevice->Clear( 0, NULL,  D3DCLEAR_TARGET , D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );

    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
	D3DXMATRIXA16 matWorld;
	UINT  iTime  = timeGetTime() % 1000;
	FLOAT fAngle = iTime * (2.0f * D3DX_PI) / 1000.0f; //旋转角度
	D3DXMatrixRotationY( &matWorld, fAngle );

	g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false); //关闭光照
	g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); //完全禁用背面消隐
	D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-10.0f ); //相机位置
	D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); //相机 观察中心点
	D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); //相机 向上视角点,一般都设此值
	D3DXMATRIXA16 matView;
	D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
	g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );  //设置相机坐标 及 视角

	D3DXMATRIXA16 matProj;
        //透视投影矩阵的计算,本dome不需要
/*	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/2, 1024.0f/768.0f, 2.0f, 100.0f );*/ 
	//正交投影 矩阵计算  14, 14, 我需要绘制的在世界坐标系中,x的取值范围(-6, 6)
	D3DXMatrixOrthoLH(&matProj, 14, 14, 0.1f, 1000.0f);  
	g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); //设置投影变化

	g_pd3dDevice->SetStreamSource( 0, m_VB, 0, sizeof(Vertex) ); //将顶点数据 注册
	g_pd3dDevice->SetFVF( Vertex::FVF ); //设置顶点数据格式
	D3DXMATRIXA16 m_worldMatrix;
/*	D3DXMatrixTranslation(&m_worldMatrix, -5.0f, 0.0f, 0.0f); */ //平移矩阵这里不需要用
//四元数 Q = [cos(O/2)  sin(O/2)N] = [ cos(O/2)     ( sin(O/2)Nx     sin(O/2)Ny      sin(O/2)Nz ) ]
	D3DXQUATERNION angle;
	angle.x = 0;
	angle.y = sin(fAngle/2.0);
	angle.z = 0;
	angle.w = cos(fAngle/2.0);

	//孤立 直线的绘制
	D3DXVECTOR3  pinyi(-5.0f, 0.0f, 0.0f);
//不能用 旋转矩阵(D3DXMatrixRotationY) * 平移矩阵(D3DXMatrixTranslation) 获取转换矩阵
// 这样算的矩阵会绕 y轴选择, 可以试试D3DXMatrixRotationAxis 函数
// D3DXMatrixTranslation(&m_worldMatrix, -2.5f, 0.0f, 0.0f);
// D3DXMatrixRotationY( &m_worldMatrix, fAngle );
	//根据平移向量 和 四元数(旋转) 计算转换矩阵
	D3DXMatrixTransformation(&m_worldMatrix, NULL, NULL, NULL, NULL, &angle, &pinyi); 
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &m_worldMatrix); //将物品坐标系映射到世界坐标系
	//D3DPT_LINELIST 将顶点作为孤立的直线段列表   绘制孤立直线  3(6个点 3条线)
	g_pd3dDevice->DrawPrimitive( D3DPT_LINELIST, 0, 3 ); //比如ABCDEF, 分别会画出:AB CD EF  三条线

	//折线 的绘制
	pinyi.x = -2.5f;
	D3DXMatrixTransformation(&m_worldMatrix, NULL, NULL, NULL, NULL, &angle, &pinyi);
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &m_worldMatrix);
	//D3DPT_TRIANGLELIST 将顶点作为单个折线呈现   将多个点连接成折线 5(6个点 依次连接成 5条线)
	g_pd3dDevice->DrawPrimitive( D3DPT_LINESTRIP, 0, 5 );  //比如ABCDEF, 分别会连接:AB BC CD DE EF  线段
	
	//孤立三角形的绘制
	pinyi.x = 0.0f;
	D3DXMatrixTransformation(&m_worldMatrix, NULL, NULL, NULL, NULL, &angle, &pinyi);
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &m_worldMatrix);
	g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //平面着色,即以第一个顶点颜色绘制
	//D3DPT_TRIANGLELIST 将指定顶点作为孤立三角形序列 每组三个顶点定义了一个独立的三角形 6个点 2个三角形
	g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);//比如ABCDEF, 分别会画出以下三角形:ABC DEF

	//三角形条带 的绘制
	pinyi.x = 2.5f;
	D3DXMatrixTransformation(&m_worldMatrix, NULL, NULL, NULL, NULL, &angle, &pinyi);
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &m_worldMatrix);
	g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); //渐变着色,根据顶点颜色渐变
	//D3DPT_TRIANGLESTRIP 将顶点作为三角形条带 6个点 4个 三角形
	g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 4); //比如ABCD, 分别会画出以下三角形:ABC BCD

	//三角形扇形 的绘制
	pinyi.x = 5.0f;
	D3DXMatrixTransformation(&m_worldMatrix, NULL, NULL, NULL, NULL, &angle, &pinyi);
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &m_worldMatrix);
	g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
	//D3DPT_TRIANGLEFAN 渲染顶点为三角形扇形 6个点 4个 三角形
	g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 4); //比如ABCD,分别会画出以下三角形:ABC ACD

	g_pd3dDevice->EndScene();
    }
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

4、展示

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值