DirectX 11:如何勾勒出边界框?

时间:2014-02-21 13:25:25

标签: c++ visual-c++ visual-studio-2012 directx directx-11

在2D平台游戏中,我想要可视化我创建的边界框以帮助调试。如何在Visual C ++ 2012中完成此操作?

2 个答案:

答案 0 :(得分:2)

首先定义一个简单的顶点结构:

struct Vertex
{
    D3DXVECTOR3 position; //a 3D point even in 2D rendering
};

现在您可以创建顶点和索引数组:

Vertex *vertices;
unsigned long *indices = new unsigned long[5];
D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
D3D11_SUBRESOURCE_DATA vertexData, indexData;

//create the vertex array
vertices = new Vertex[5];
if(!vertices)
{
    //handle error
}
//load the vertex array with data
vertices[0].position = D3DXVECTOR3(left, top, 0.0f);
vertices[1].position = D3DXVECTOR3(right, top, 0.0f);
vertices[2].position = D3DXVECTOR3(right, bottom, 0.0f);
vertices[3].position = D3DXVECTOR3(left, bottom, 0.0f);
vertices[4].position = D3DXVECTOR3(left, top, 0.0f);
//create the index array
indices = new unsigned long[5];
if(!indices)
{
    //handle error
}
//load the index array with data
for(i=0; i<5; i++)
    indices[i] = i;

将它们加载到缓冲区中:

ID3D11Buffer *vertexBuffer, *indexBuffer;
HRESULT result;

//set up the description of the dynamic vertex buffer
vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; //enables recreation and movement of vertices
vertexBufferDesc.ByteWidth = sizeof(Vertex) * 5;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; //couples with dynamic
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
//give the subresource structure a pointer to the vertex data
vertexData.pSysMem = vertices;
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0;

//now create the vertex buffer
result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &vertexBuffer);
if(FAILED(result))
{
    //handle error
}

//set up the description of the static index buffer
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(unsigned long) * 5;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;
//give the subresource structure a pointer to the index data
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;

//create the index buffer
result = device->CreateBuffer(&indexBufferDesc, &indexData, &indexBuffer);
if(FAILED(result))
{
    //handle error
}

设置要渲染的矩形:

unsigned int stride = sizeof(Vertex);
unsigned int offset = 0;

deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
deviceContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP);

现在使用您选择的着色器进行渲染,记住将orthographic matrix传递给着色器而不是透视矩阵。瞧!长方形。但是你还不能移动它......你必须定义另一个函数来做到这一点:

bool UpdateRectBuffers(ID3D11Buffer *vertexBuffer, ID3D11DeviceContext *deviceContext, float top, float left, float bottom, float right)
{
    Vertex *vertices;
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    VertexType *verticesPtr;
    HRESULT result;

    //create a temporary vertex array to fill with the updated data
    vertices = new Vertex[5];
    if(!vertices)
    {
        return false;
    }
    vertices[0].position = D3DXVECTOR3(left, top, 0.0f);
    vertices[1].position = D3DXVECTOR3(right, top, 0.0f);
    vertices[2].position = D3DXVECTOR3(right, bottom, 0.0f);
    vertices[3].position = D3DXVECTOR3(left, bottom, 0.0f);
    vertices[4].position = D3DXVECTOR3(left, top, 0.0f);

    //lock the vertex buffer so it can be written to
    result = deviceContext->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if(FAILED(result))
    {
        return false;
    }

    verticesPtr = (Vertex*)mappedResource.pData;

    //copy the data into the vertex buffer
    memcpy(verticesPtr, (void*)vertices, (sizeof(Vertex) * 5));

    deviceContext->Unmap(vertexBuffer, 0);
    delete [] vertices;
    vertices = 0;

    return true;
}

此代码的依赖项为float topfloat leftfloat rightfloat leftID3D11DeviceContext *deviceContextID3D11Device *device

答案 1 :(得分:0)

由于你没有很好地描述你已经能够做到的事情,我的回答是基于一些假设。

假设

所以,我假设

  • 您可以绘制sprite(即彩色/纹理矩形,即四边形顶点/二重奏三角形)
  • 您已经拥有定义边界体积的数据(以多种方式中的任何一种)

并且不会解释如何做到这一点。

可能的解决方案

  • 变体1: 绘制边缘不需要任何特殊的东西。 “边缘”(直线)只是长而细的矩形。因此,您需要在边缘应该放置4个薄矩形。

    这样你就可以选择粗细,线条的颜色,甚至可以使用纹理(虚线,虚线,粉红色小猫的线条等)或着色效果,如程序着色,平滑,模糊等。无论如何,你可能需要你的游戏线。

  • 变体2: 您可以绘制线条而不是三角形。使用“行列表”基元拓扑,而不是“三角形列表”。 (参见:ID3D11DeviceContext::IASetPrimitiveTopology()D3D11_PRIMITIVE_TOPOLOGY_LINELIST)。

    这样你无法自定义东西。但这更容易。

  • 变体3: 在线框模式下绘制矩形。只需设置光栅化器状态的填充模式。请参阅:ID3D11DeviceContext::RSSetStateD3D11_RASTERIZER_DESC::FillModeD3D11_FILL_MODE::D3D11_FILL_WIREFRAME

    你会得到三角形的边,甚至是那些是矩形对角线的三角形。这样,您既不能设置厚度,也不能设置颜色。但这种方式非常非常简单。

  • 变体4: 使用任何将为您执行变体1的2D绘图库。作为D3DX is obsolete,不建议再使用D3DXLine。您可以尝试DirectX toolkit或网上提供的任何库。 显然你会得到额外的依赖。

P.S。

如果我的初步假设不正确,那么你不会在这里得到答案。 StackOverflow上没有人会向你解释这些基本的东西。纠正一种情况:

  • 绘制矩形有很多种方法。在线选择任何教程(例如:rastertekbraynzarsoft),以便了解此答案中“可能的解决方案”中发生的事情。
  • 有很多方法可以为每种定义方法计算边界矩形。注意,要在2D空间中定义矩形,您至少需要2个点。要定义2D点,您需要2个坐标值。因此每个矩形有4个值。谷歌或选择一本数学书来获取更多信息。

希望它有所帮助!