在direct3d中绘制屏幕角落的坐标系轴

时间:2013-05-23 21:09:23

标签: visual-c++ mfc direct3d direct3d9

我在MFC窗口中有一个direct3d环境,我想在屏幕的一角绘制坐标系轴,就像任何三维软件一样。我认为这没问题,但是当我开始移动相机时会出现问题。无论我如何平移,缩放或旋转相机,我都需要物体看起来在同一个位置。

但似乎我做错了什么,我希望有人可以指出我正确的方向,因为当我缩放时我正在绘制的对象没有相应缩放,但它在平移或旋转时工作得很好

我还制作了一个YouTube视频,向您展示症状:http://www.youtube.com/watch?v=gwM0m8nbLts&feature=youtu.be

这是我绘制对象的代码:

    void CDEMView::DrawSomeBox()
{
// Define the needed matrices - object world, view and project 
D3DXMATRIX matObjectWorld;
    D3DXMatrixIdentity (&matObjectWorld);   // object world matrix
D3DXMATRIX matView;             
    D3DXMatrixIdentity (&matView);      // view matrix
D3DXMATRIX matProjection;   
    D3DXMatrixIdentity (&matProjection);    // projection matrix

// Get the needed matrices
_device->GetTransform(D3DTS_VIEW, &matView);
_device->GetTransform(D3DTS_PROJECTION, &matProjection);

// Get the viewport
D3DVIEWPORT9 viewport;
_device->GetViewport(&viewport);

// Get the center point of the object       
D3DXVECTOR3* p_centerPoint = BoxCenterVector; // this is from an external variable

// Get the point on the creen that is the screen projection of the object
D3DXVECTOR3 projectPoint;
D3DXVec3Project(&projectPoint, p_centerPoint ,&viewport, &matProjection, &matView, &matObjectWorld);

// choose the screen point where the object is to be drawn, relative to the Viewport's dimensions
D3DXVECTOR3 screenPoint;
screenPoint.x = 0.1*viewport.Width; // x position (horizontal) is 10% of the width of the screen (0% is left, 100% is right)
screenPoint.y = 0.9*viewport.Height;    // y position (vertical) is 90% of the height of the screen (0% is top, 100% is bottom)
screenPoint.z = projectPoint.z;     // 1-projectPoint.z*60/(-zoom);

//transform the screen position to a world position
D3DXVECTOR3 worldPoint;
D3DXVec3Unproject( &worldPoint, &screenPoint, &viewport, &matProjection, &matView, &matObjectWorld );

// now define how much to translate the box in order to get it to the point we want it to be (WorldPoint)
float transX, transY, transZ;
transX = worldPoint.x;
transY = worldPoint.y;
transZ = worldPoint.z;

// define a mesh to store the object into and create the object
ID3DXMesh* _SomeBox;
float boxSize = 2.0f;
D3DXCreateBox(_device,boxSize,boxSize,boxSize,&_SomeBox,NULL);

// define a material and set its color
D3DMATERIAL9 mat;

// Set the RGBA for diffuse reflection.
mat.Diffuse.r = 255;
mat.Diffuse.g = 0;
mat.Diffuse.b = 0;
mat.Diffuse.a = 0.5;

_device->SetMaterial(&mat);
_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); // D3DFILL_SOLID

// apply the translation matrix
D3DXMatrixTranslation(&matObjectWorld, transX, transY, transZ);
_device->SetTransform(D3DTS_WORLD, &matObjectWorld);

// draw the object
_SomeBox->DrawSubset(0);
// release the mesh
_SomeBox->Release();
}

2 个答案:

答案 0 :(得分:0)

我没有仔细查看您的代码以尝试找到问题,但我建议您可能需要采取稍微不同的方法,这样可以避免尝试补偿相机移动的需要。不要尝试将坐标轴定位为与场景位于同一世界空间中的对象,而是将视口更改为要显示坐标轴的区域,并使用固定摄像机和世界矩阵在虚拟场景中渲染它们那是没有翻译组件的主场景的摄像机视图矩阵。

这样您甚至不必担心相机的变焦,您只需直接显示视图矩阵旋转如何影响世界轴。此方法还具有以下优点:您可以避免轴与场景交互时出现任何问题。您可以在绘制轴之前清除视口的z缓冲区,它们将像一个不与主场景交互的单独图层。您还可以通过将轴渲染到屏幕外渲染目标纹理并在主场景中将其显示为四边形来实现相同的效果,但对于这种情况,这将是更多的工作,没有太多明显的好处。

答案 1 :(得分:0)

你可以做的一件事,虽然有点矫枉过正,但是首先绘制旋转物体而不进行平移但只能正交旋转到纹理中。请参阅this link

这种方式无论物体有多远,它的大小都是一样的。获得纹理后,只需执行以下两项操作之一:将四边形渲染到左上角的屏幕,不进行三维变换,或使用随DirectX提供的精灵界面渲染纹理。使用sprite接口基本上与使用2D quad相同,但它可能更容易一点,根据我的经验,它非常快。祝你好运!