一般的3D图形软件都有坐标轴提示的功能,比如3DMax,当旋转物体时,坐标轴也跟着旋转,这样就能实时跟踪物体的角度了,今天我们自己手动做一个,以前一直觉得挺难,今天做起来忽然发现,其实也很简单,说白了,就是画线而已,下面是3DMAX中的坐标轴提示图。
![](https://images.cnblogs.com/cnblogs_com/graphics/219772/o_3dmaxaxis.JPG)
坐标轴是由线段组成的,但由于DirectX中的ID3DXLine接口只能用来绘制2D直线,所以我们这里使用DrawPrimitive函数并传递D3DPT_LINELIST来绘制3D直线,旋转使用的是ArcBall技术,先上个图吧,做成以后效果如下,比起上面那个来,比较丑陋,但是功能一样
![](https://images.cnblogs.com/cnblogs_com/graphics/219772/o_myaxis.bmp)
好了,下面介绍详细步骤,首先我们来定义顶点格式,因为绘制直线首先要确定顶点,比如要绘制X轴的话,要给出原点O以及X轴的端点X,我们使用的顶点格式如下
1 struct CUSTOMVERTEX
2 {
3 FLOAT x, y, z; // position
4 DWORD color; // color
5 };
6
7 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
这个顶点包含两个信息,位置和颜色,这里我们自己指定顶点的颜色,就不用额外设置光照了,光照不是本篇的主题,所以简化掉
1.确定三个坐标轴的端点,每个轴的长度都设置为0.5,颜色三个轴分别是红,绿,蓝。这样三个轴的端点就确定了,要注意到是,原点不只是一个,而是三个,位置都是(0, 0, 0),颜色分别是红,绿,蓝。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1 // X axis-red
2 CUSTOMVERTEX OX = { 0.0f, 0.0f, 0.0f, 0xffff0000 };
3 CUSTOMVERTEX X = { 0.5f, 0.0f, 0.0f, 0xffff0000 };
4
5 // Y axis-green
6 CUSTOMVERTEX OY = { 0.0f, 0.0f, 0.0f, 0xff00ff00 };
7 CUSTOMVERTEX Y = { 0.0f, 0.5f, 0.0f, 0xff00ff00 };
8
9 // Z axis-blue
10 CUSTOMVERTEX OZ = { 0.0f, 0.0f, 0.0f, 0xff0000ff };
11 CUSTOMVERTEX Z = { 0.0f, 0.0f, 0.5f, 0xff0000ff };
12
2. 确定三个箭头的端点
箭头可以看作是两条线段拼接而成的,而它们的交点就是上面的坐标轴端点,所以每个箭头实际上只需要两个顶点,如下,关于坐标位置我就不细说了,很简单
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1 // arrow x
2 CUSTOMVERTEX X1 = { 0.45f, 0.05f, 0.0f, 0xffff0000 };
3 CUSTOMVERTEX X2 = { 0.45f, -0.05f, 0.0f, 0xffff0000 };
4
5 // arrow x
6 CUSTOMVERTEX Y1 = { -0.05f, 0.45f, 0.0f, 0xff00ff00 };
7 CUSTOMVERTEX Y2 = { 0.05f, 0.45f, 0.0f, 0xff00ff00 };
8
9 // arrow z
10 CUSTOMVERTEX Z1 = { -0.05f, 0.0f, 0.45f, 0xff0000ff };
11 CUSTOMVERTEX Z2 = { 0.05f, 0.0f, 0.45f, 0xff0000ff };
12
3. 确定字母X, Y, Z的顶点
除了绘制箭头以外,我们还需要用字母标出三个坐标轴的名称,这里我没有使用绘制文本的函数,而是直接用线段拼出这三个字母,也是为了简化程序,好在这三个字母的笔画都比较直,拼起来也很容易,更加巧合的是,每个字母都恰好需要四个顶点,同样,坐标的位置不细说了,大家看看下面的图就都明白了
![](https://images.cnblogs.com/cnblogs_com/graphics/219772/o_letter.JPG)
代码
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1 // letter X
2 CUSTOMVERTEX XA = { 0.65f, 0.05f, 0.0f, 0xffff0000 };
3 CUSTOMVERTEX XB = { 0.75f, -0.05f, 0.0f, 0xffff0000 };
4 CUSTOMVERTEX XC = { 0.65f, -0.05f, 0.0f, 0xffff0000 };
5 CUSTOMVERTEX XD = { 0.75f, 0.05f, 0.0f, 0xffff0000 };
6
7 // letter Y
8 CUSTOMVERTEX YA = { -0.05f, 0.75f, 0.0f, 0xff00ff00 };
9 CUSTOMVERTEX YB = { 0.05f, 0.75f, 0.0f, 0xff00ff00 };
10 CUSTOMVERTEX YC = { 0.0f, 0.7f, 0.0f, 0xff00ff00 };
11 CUSTOMVERTEX YD = { 0.0f, 0.65f, 0.0f, 0xff00ff00 };
12
13 // letter Z
14 CUSTOMVERTEX ZA = { -0.05f, 0.0f, 0.65f, 0xff0000ff };
15 CUSTOMVERTEX ZB = { -0.05f, 0.0f, 0.7f, 0xff0000ff };
16 CUSTOMVERTEX ZC = { 0.05f, 0.0f, 0.65f, 0xff0000ff };
17 CUSTOMVERTEX ZD = { 0.05f, 0.0f, 0.7f, 0xff0000ff };
18
有了上面的顶点以后,就可以创建顶点buffer,然后copy data,最后绘制,这些都是比较基本的东西,不说了,大家可以从文章末尾下载完整的代码
准备顶点数据
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1 // Create vertex buffer
2 if( FAILED( m_pDirect3DDevice->CreateVertexBuffer( 34 * sizeof(CUSTOMVERTEX),
3 0, D3DFVF_CUSTOMVERTEX,
4 D3DPOOL_DEFAULT, &m_pVertexBuffer, NULL ) ) )
5 {
6 return E_FAIL;
7 }
8
9 // copy vertex data
10 VOID* pVertices;
11 if( FAILED( m_pVertexBuffer->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
12 return E_FAIL;
13 memcpy( pVertices, vertices, sizeof(vertices) );
14 m_pVertexBuffer->Unlock();
15
绘制
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1 m_pDirect3DDevice->SetStreamSource( 0, m_pVertexBuffer, 0, sizeof(CUSTOMVERTEX) );
2 m_pDirect3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
3
4 //draw line
5 m_pDirect3DDevice->DrawPrimitive( D3DPT_LINELIST, 0, 17 );
6
拖动鼠标,体会旋转的乐趣吧!
完整代码 here
happy coding!
==THE END==