Haalef
Haalef

Reputation: 378

How can I draw 2D geometry benind 3D objects in DirectX? (D3D9)

I'm using the D3DXVec3Project function to get screen coordinates of 3D points and draw 2D lines that appear to be 3D. The obvious result is that the lines drawn will always be on top of any 3D object even if the object is supposed to be in front of the lines.

This is the code I use to draw lines:

 void DrawLine(float Xa, float Ya, float Xb, float Yb, float dwWidth, D3DCOLOR Color)
 {
    if (!g_pLine)
        D3DXCreateLine(d3ddev, &g_pLine);

    D3DXVECTOR2 vLine[2]; // Two points
    g_pLine->SetAntialias(0); // To smooth edges


    g_pLine->SetWidth(dwWidth); // Width of the line
    g_pLine->Begin();

    vLine[0][0] = Xa; // Set points into array
    vLine[0][1] = Ya;
    vLine[1][0] = Xb;
    vLine[1][1] = Yb;

    g_pLine->Draw(vLine, 2, Color); // Draw with Line, number of lines, and color
    g_pLine->End(); // finish
 }

As an example I have the earth as a 3D sphere and the ecliptic plane as a grid of 2D lines, half of the earth is on top of the ecliptic, so half of the earth should be drawn on top of the ecliptic grid, with the code I'm using the whole grid is always on top of the earth so it looks like the entire planet is under the grid.

Here is a screenshot: http://s13.postimg.org/3wok97q7r/screenshot.png

How can I draw the lines behind 3D objects?

Ok, I got it working now, this is the code that rocks for drawing 3D lines in D3D9:

LPD3DXLINE      g_pLine;

void Draw3DLine(float Xa, float Ya, float Za,
                float Xb, float Yb, float Zb,
                float dwWidth, D3DCOLOR Color)
{
    D3DXVECTOR3 vertexList[2];
    vertexList[0].x = Xa;
    vertexList[0].y = Ya;
    vertexList[0].z = Za;

    vertexList[1].x = Xb;
    vertexList[1].y = Yb;
    vertexList[1].z = Zb;

    static D3DXMATRIX   m_mxProjection, m_mxView;

    d3ddev->GetTransform(D3DTS_VIEW, &m_mxView);
    d3ddev->GetTransform(D3DTS_PROJECTION, &m_mxProjection);

    // Draw the line.
    if (!g_pLine)
    D3DXCreateLine(d3ddev, &g_pLine);
    D3DXMATRIX tempFinal = m_mxView * m_mxProjection;
    g_pLine->SetWidth(dwWidth);
    g_pLine->Begin();
    g_pLine->DrawTransform(vertexList, 2, &tempFinal, Color);
    g_pLine->End();
}

Upvotes: 0

Views: 1732

Answers (1)

Chuck Walbourn
Chuck Walbourn

Reputation: 41057

With legacy Direct3D 9, you just use the standard IDirect3DDevice9::DrawPrimitive methods with a D3DPRIMITIVETYPE of D3DPT_LINELIST or D3DPT_LINESTRIP. You will likely use DrawPrimitiveUP or DrawIndexedPrimitiveUP, although using the non-UP versions with a DYNAMIC Vertex Buffer is much more efficient.

D3DXCreateLine in the legacy D3DX9 utility library is intended for styled lines for CAD-like scenarios. In modern DirectX 11 parlance, D3DXCreateLine is basically like Direct2D which is for 2D rendering.

With Direct3D 11, you'd use ID3D11DeviceContext::Draw or ID3D11DeviceContext::DrawIndexed, after having used ID3D11DeviceContext::IASetPrimitiveTopology to set it to D3D11_PRIMITIVE_TOPOLOGY_LINELIST or 11_PRIMITIVE_TOPOLOGY_LINESTRIP mode. For "UP" style drawing, see PrimitiveBatch in the DirectX Tool Kit. I in fact use PrimitiveBatch to draw a 3D grid of lines into a 3D scene in the Simple Sample for DirectX Tool Kit.

Upvotes: 2

Related Questions