Visual c++ 在direct3d中绘制屏幕角的坐标系轴

Visual c++ 在direct3d中绘制屏幕角的坐标系轴,visual-c++,mfc,direct3d,direct3d9,Visual C++,Mfc,Direct3d,Direct3d9,我在MFC窗口中有一个direct3d环境,我想像任何3d软件一样,在屏幕的角落绘制坐标系轴。我以为这不会有问题,但当我开始移动相机时,问题就出现了。无论我如何平移、缩放或旋转相机,我都需要对象显示在同一个点上 但似乎我做错了什么,我希望有人能给我指出正确的方向,因为我正在绘制的对象在缩放时没有相应的缩放,但在平移或旋转时效果很好 我还上传了一段youtube视频,向大家展示这些症状: 这是我绘制对象的代码: void CDEMView::DrawSomeBox() { // Defin

我在MFC窗口中有一个direct3d环境,我想像任何3d软件一样,在屏幕的角落绘制坐标系轴。我以为这不会有问题,但当我开始移动相机时,问题就出现了。无论我如何平移、缩放或旋转相机,我都需要对象显示在同一个点上

但似乎我做错了什么,我希望有人能给我指出正确的方向,因为我正在绘制的对象在缩放时没有相应的缩放,但在平移或旋转时效果很好

我还上传了一段youtube视频,向大家展示这些症状:

这是我绘制对象的代码:

    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();
}

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


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

您可以做一件事,尽管有点过火,首先绘制旋转对象,不进行平移,只正交旋转到纹理中。看


这样,无论物体有多远,它的大小都是一样的。获得纹理后,只需执行以下两项操作之一:在左上角的屏幕上渲染四边形,无需进行3d变换,或者使用DirectX提供的精灵界面渲染纹理。使用sprite界面基本上与使用2D quad做相同的事情,但可能会更简单一些,根据我的经验,速度相当快。祝你好运

嗨!谢谢你的回复。我对一般编程和directx都知之甚少。因此,我不明白什么是“虚拟场景”以及如何实现它。我也有一个想法,创建另一个较小的视口,并在那里绘制轴,但我有很多麻烦,放弃了这个想法。你能不能给我指一个地方,在那里我可以研究同一个窗口上多个视口的使用情况(我使用MFC)。再次感谢!虚拟场景不是一个官方术语,它只是我所描述的方法的术语。使用较小的视口没什么大不了的,只需使用要渲染到的坐标调用SetViewport,然后可能需要调用Clear在渲染之前清除z缓冲区。您现在所做的任何渲染都会发生在屏幕的子区域上。太好了!我要试一试。几天前我也试过,但我想现在我明白了哪里出了问题。我会通知你的。好的。。。我尝试过使用多个视口,但我无法让它只在较小的视口上应用旋转,而不应用平移和缩放。苏欧。。我想我会接受老派的做事方式(努力工作而不是聪明),我会向你展示我在上传的视频中取得的成就:这是通过使用视图矩阵的缩放和旋转来补偿对象的大小来实现的。不优雅,但很管用。:)谢谢你的帮助!