Advertisement

Reading BSP map data into DX11 Buffers

Started by February 21, 2020 04:56 PM
50 comments, last by Tom_W 4 years, 10 months ago

Tom_W said:
I got much more cohesive boxes, I just have to find out the right Draw call with the right parameters…

Yeah, i think so too. Are you aware about differnt options like Fans, Strips, Lists? https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dprimitivetype

Because i think i remember some of those have been deprecated from OpenGL. Likely the same happened with DX. And IIRC Quake used fans.

So are you sure your DX9 version worked with D3DPT_TRIANGLELIST? Because this one is for sure still supported. Maybe it's about the start index then… something like that.

https://cdn.discordapp.com/attachments/642116703114887201/681992847569977354/unknown.png

This is one step closer than the previous box that Joe very politely outlined. The code for it is as such:

void DrawFace(ID3D11Device* pDevice, ID3D11DeviceContext* pDevCon,
 int nFace)
{
 struct Vertex //Overloaded Vertex Structure
 {
  Vertex(){}
  Vertex(float x, float y, float z,
   float u, float v)
   : pos(x, y, z), texCoord(u, v){}

  XMFLOAT3 pos;
  XMFLOAT2 texCoord;
 };
 ID3D11Buffer* squareIndexBuffer;
 ID3D11DepthStencilView* depthStencilView;
 ID3D11Texture2D* depthStencilBuffer;
 ID3D11Buffer* squareVertBuffer;
 
 
 /* 
 	OLD DX9 CODE ---
 pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
  pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
  pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);

  pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
  pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);*/

 // pDevice->SetIndices(m_pIB);

 // pDevice->SetStreamSource(0, m_pVB, 0, sizeof(stBSPVertex));

 // pDevice->SetFVF(m_FVF_Format);

 // If its not a tri mesh
 /* if (m_pFaces[nFace].nFaceType != 1)return;

  int nFirstF = m_pFaces[nFace].nFirstMeshVerts;
  int nNumF = m_pFaces[nFace].NumMeshVerts;

  int nFirstV = m_pFaces[nFace].FirstVert;
  int nNumV = m_pFaces[nFace].NumVerts;

  int nTexIndex = m_pFaces[nFace].nTexture;*/

 // pDevice->SetTexture(0, m_pT[nTexIndex]);

 


  /*
  pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,  // Type
  nFirstV,    // BaseVertexIndex
  0,      // MinIndex
  nNumV,     // NumVertices
  nFirstF,    // StartIndex
  nNumTris );    // PrimitiveCount
  */

  m_nNumTrisDraw += (m_pFaces[nFace].NumMeshVerts / 3);
  stBSPVertex pVB[10000];
  /* pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
    m_pFaces[nFace].FirstVert,
    0,
    m_pFaces[nFace].NumVerts,
    m_pFaces[nFace].nFirstMeshVerts,
    (m_pFaces[nFace].NumMeshVerts / 3));
    
    --END OF OLD DX9 CODE--
    
    */
  Vertex v2[10000];
  for (int i = 0; i < m_nNumVerts; i++)
  {
   // The put the y ans z the wrong way around!
   pVB[i].p.x = m_pVerts[i].vPoint[0];
   pVB[i].p.y = m_pVerts[i].vPoint[1];
   pVB[i].p.z = m_pVerts[i].vPoint[2];

   // tv is inverted!
   pVB[i].tu1 = m_pVerts[i].Tex[0];
   pVB[i].tv1 = m_pVerts[i].Tex[1];
   pVB[i].lu2 = m_pVerts[i].LightTexCoord[0];
   pVB[i].lv2 = m_pVerts[i].LightTexCoord[1];

   pVB[i].n.x = m_pVerts[i].vNormal[0];
   pVB[i].n.y = m_pVerts[i].vNormal[1];
   pVB[i].n.z = m_pVerts[i].vNormal[2];

   // Alpha hack - so our alpha value isn't 100% anymore
   pVB[i].colour = 0x10ffffff & m_pVerts->RGBA; // ARGB*/

  }
  for (int i = 0; i < m_nNumVerts; i++)
  {
   // The put the y ans z the wrong way around!
   v2[i] = Vertex(pVB[i].p.x, pVB[i].p.y, pVB[i].p.z, pVB[i].tu1, pVB[i].tv1);
  }
 
  WORD pIB[10000];
  /*m_pIB->Lock(0,
  m_nNumMeshIndices*sizeof(WORD),
  (void**)&pIB,
  0);*/ //THIS IS OLD DX9 CODE FOR INDEX BUFFER
  
  //below is me filling the new buffer in
  for (int i = 0; i < m_nNumMeshIndices; i++)
   pIB[i] = m_pMeshIndices[i];

  D3D11_BUFFER_DESC indexBufferDesc;
  ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));

  indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
  indexBufferDesc.ByteWidth = sizeof(WORD)* m_nNumMeshIndices;
  indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
  indexBufferDesc.CPUAccessFlags = 0;
  indexBufferDesc.MiscFlags = 0;

  D3D11_SUBRESOURCE_DATA iinitData;

  iinitData.pSysMem = pIB;
  pDevice->CreateBuffer(&indexBufferDesc, &iinitData, &squareIndexBuffer);

  pDevCon->IASetIndexBuffer(squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);


  D3D11_BUFFER_DESC vertexBufferDesc;
  ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));

  vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
  vertexBufferDesc.ByteWidth = sizeof(Vertex)* m_nNumVerts;
  vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  vertexBufferDesc.CPUAccessFlags = 0;
  vertexBufferDesc.MiscFlags = 0;
  D3D11_SUBRESOURCE_DATA vertexBufferData;

  ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
  vertexBufferData.pSysMem = v2;
  pDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &squareVertBuffer);

  //Set the vertex buffer
  UINT stride = sizeof(Vertex);
  UINT offset = 0;
  pDevCon->IASetVertexBuffers(0, 1, &squareVertBuffer, &stride, &offset);
  pDevCon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  for (int i = 0; i<m_nNumFaces; i++)
  {
   // If its not a tri mesh
   if (m_pFaces[i].nFaceType != 1) continue;

   int nFirstF = m_pFaces[i].nFirstMeshVerts;
   int nNumF = m_pFaces[i].NumMeshVerts;

   int nFirstV = m_pFaces[i].FirstVert;
   int nNumV = m_pFaces[i].NumVerts;

   int nTexIndex = m_pFaces[i].nTexture;
#if(0)
   pDevice->SetTexture(0,
    m_pT[nTexIndex]);
#endif

   int nNumTris = nNumF / 3;

   m_nNumTrisDraw += nNumTris;

  /* pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,  // Type
    nFirstV,    // BaseVertexIndex
    0,      // MinIndex
    nNumV,     // NumVertices
    nFirstF,    // StartIndex
    nNumTris);    // PrimitiveCount*/

   pDevCon->Draw(m_nNumTrisDraw, m_pFaces[i].FirstVert); //THIS is what draws the “improved” cube

  }
 
}

This is as close as I can get it – There are one of two issues going on here, either:

a) The index buffer is not being filled properly( I am literally doing it in the same manner it was done in DX9, that for loop was also used)

b) I am using Draw calls incorrectly.

I have, however, found a BSP parses in DX11, and it uses the Draw function:

m_pD3D->GetDeviceContext()->Draw(visibleFaces[i]->numVertices, 0);

Which is in a loop just like my Draw call is.

The old code in this header for the index/vertex buffers in D3D9 are as follows:

bool CreateDXIndexBuffer(IDirect3DDevice * pDevice)
{
 HRESULT hr = S_OK;

 hr =
  pDevice->CreateIndexBuffer(m_nNumMeshIndices * sizeof(WORD),
  D3DUSAGE_WRITEONLY,
  D3DFMT_INDEX16,
  D3DPOOL_DEFAULT,
  &m_pIB,
  NULL);
 if (hr != S_OK)
 {
  ErrLog("<!>Error Creating Index Buffer/n");
  return false;
 }

 // We need to copy the data one at a time, as the data is loaded
 // in as int, but directx uses a word for each indices
 WORD * pIB;
 m_pIB->Lock(0,
  m_nNumMeshIndices*sizeof(WORD),
  (void**)&pIB,
  0);
 for (int i = 0; i<m_nNumMeshIndices; i++)
  pIB[i] = m_pMeshIndices[i];
 m_pIB->Unlock();

 return true;
}

bool CreateDXVertexBuffer(IDirect3DDevice * pDevice)
{
 HRESULT hr = S_OK;

 m_FVF_Format = D3DFVF_XYZ |
  D3DFVF_NORMAL |
  D3DFVF_DIFFUSE |
  D3DFVF_TEX2 |
  D3DFVF_TEXCOORDSIZE2(0) |
  D3DFVF_TEXCOORDSIZE2(1);
 hr =
  pDevice->CreateVertexBuffer(m_nNumVerts * sizeof(stBSPVertex),
  0,
  m_FVF_Format,
  D3DPOOL_MANAGED,
  &m_pVB,
  NULL);
 if (hr != S_OK)
 {
  ErrLog("<!>Error Creating Vertex Buffer/n");
  return false;
 }

 // Copy data into our dx buffer
 stBSPVertex *pVB;
 m_pVB->Lock(0, 0, (void**)&pVB, 0);

 for (int i = 0; i<m_nNumVerts; i++)
 {
  // The put the y ans z the wrong way around!
  pVB[i].p.x = m_pVerts[i].vPoint[0];
  pVB[i].p.y = m_pVerts[i].vPoint[1];
  pVB[i].p.z = m_pVerts[i].vPoint[2];

  // tv is inverted!
  pVB[i].tu1 = m_pVerts[i].Tex[0];
  pVB[i].tv1 = m_pVerts[i].Tex[1];
  pVB[i].lu2 = m_pVerts[i].LightTexCoord[0];
  pVB[i].lv2 = m_pVerts[i].LightTexCoord[1];

  pVB[i].n.x = m_pVerts[i].vNormal[0];
  pVB[i].n.y = m_pVerts[i].vNormal[1];
  pVB[i].n.z = m_pVerts[i].vNormal[2];

  // Alpha hack - so our alpha value isn't 100% anymore
  pVB[i].colour = 0x10ffffff & m_pVerts->RGBA; // ARGB
 }
 m_pVB->Unlock();


 return true;
}

So which is it? Is the index buffer screwed up, filled with the wrong indices as Joe suggests? Or am I drawing incorrectly?

Thank you ALL for your help and support up to this point. The employee from Microsoft and the DirectX dev's from DX12's team said for me not to worry and that I could continue with D3D9, but I refuse to continue unless I under 100% of the code I use, otherwise I'm a hypocrite.

Again, thanks for all your help!

Advertisement

And yes Joe, it used D3DPT_TRIANGLELIST, as you can see in the code above.

Thanks for sticking with me through my journey of insanity, Joe. You're a hero in my eyes; You're getting up there with Steve Ballmer and John Carmack in terms of legend status.

Edit: I fixed it!! EVERYTHING IS WORKING PERFECLTY NOW! The code was right there the whole time…

#include “JoeJ.h”
/*
  ..misc code, init..
  
*/

int DrawFace(int face)
{
	JOEJ Joe;
     Joe→FillIndexBuffer();
     Joe→FillVertexBuffer();
     Joe→DrawEntireBSPMap();
  	return 0;
}

I knew DirectX11 would be easy, I'm glad I switched. D3D9 is so deprecated, now I see why!

pDevice->DrawIndexedPrimitive(

D3DPT_TRIANGLELIST,

m_pFaces[nFace].FirstVert, ?

0, ?

m_pFaces[nFace].NumVerts, ?

m_pFaces[nFace].nFirstMeshVerts, ?

(m_pFaces[nFace].NumMeshVerts / 3));

It seems at least some of those parameters or not used in DX11 versions?

Maybe, some base / first / offset crap has been removed for DX11?

If so, it can not work. Then you might need to compute new offsets, or in the worst case rearrange the data so it becomes compatible with simplified DX11.

So it's hopeless? In DX11, even though I'm able to read in the proper indices, I can't draw properly?

This is the original D3D9 code for DrawFace():

void DrawFace(IDirect3DDevice9 * pDevice,
 int nFace)
{

 pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
 pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
 pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
 pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);

 pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
 pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

 pDevice->SetIndices(m_pIB);

 pDevice->SetStreamSource(0, m_pVB, 0, sizeof(stBSPVertex));

 pDevice->SetFVF(m_FVF_Format);

 // If its not a tri mesh
 if (m_pFaces[nFace].nFaceType != 1)return;

 int nFirstF = m_pFaces[nFace].nFirstMeshVerts;
 int nNumF = m_pFaces[nFace].NumMeshVerts;

 int nFirstV = m_pFaces[nFace].FirstVert;
 int nNumV = m_pFaces[nFace].NumVerts;

 int nTexIndex = m_pFaces[nFace].nTexture;

 pDevice->SetTexture(0, m_pT[nTexIndex]);

 int nNumTris = nNumF / 3;

 /*
 pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,  // Type
 nFirstV,    // BaseVertexIndex
 0,      // MinIndex
 nNumV,     // NumVertices
 nFirstF,    // StartIndex
 nNumTris );    // PrimitiveCount
 */

 m_nNumTrisDraw += (m_pFaces[nFace].NumMeshVerts / 3);

 pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
  m_pFaces[nFace].FirstVert,
  0,
  m_pFaces[nFace].NumVerts,
  m_pFaces[nFace].nFirstMeshVerts,
  (m_pFaces[nFace].NumMeshVerts / 3));

}

There's no way to take those variables and use them as parameters in a DX11 Draw call? Draw, DrawIndexed, etc?

Advertisement

I'm just guessing, but it's not hopeless. It is guaranteed to be fixable, in any case.

If i am right, you would only need to figure out your data so you can transform it to a compatible format. Changing a single base or start index, or both might be enough if you're lucky.

But i could be wrong - i did render quake level with Vulkan without such issues. I also remember the data was somewhat confusing at first, as always with data i did not generate myself. I do not know if the level loader code i took from internet did changes to the original data already or not.

However, what is the answer to my question?:

JoeJ said:
It seems at least some of those parameters or not used in DX11 versions?

Are there unused params or not? And can you find a DX11 draw mwthod that supports all of them?

I have no idea! You have much more experience than I do in all of this, I'm asking questions in Microsoft's DirectX's Discord chatroom and they had me enable D3D11_CREATE_DEVICE_DEBUG and I've gotten the following output:


D3D11 WARNING: ID3D11DeviceContext::Draw: Vertex Buffer at the input vertex slot 0 is not big enough for what the Draw*() call expects to traverse. This is OK, as reading off the end of the Buffer is defined to return 0. However the developer probably did not intend to make use of this behavior. [ EXECUTION WARNING #356: DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL]

thousands of times. Then I was told to make my vertex buffer dynamic, which made everything disappear, so I made it so the vertex buffer was created and filled only once so I didn't have to make it dynamic, but still no effect or indicator as to why it's not drawing the way it should.

I FRICKING DID IT!!!!!!!!!!!!!!!!
https://cdn.discordapp.com/attachments/596046911010504754/682035853551468584/unknown.png

pDevCon->DrawIndexed(m_nNumMeshIndices, nFirstF, nFirstV);

This topic is closed to new replies.

Advertisement