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

s

Hey guys, I was crying for help a few months ago on here while I was developing my game engine in DirectX 9. I got everything I wanted working; Then realized why the hell am I developing a game engine on a very deprecated API. As a beginner at DirectX in general, I learned little by little, stemming from a tutorial that reads BSP maps in DX9 and learned all about DirectX 9, Audio, physics, HLSL, but I had no idea going from DX9 to DX11 would be like jumping across the grand canyon.

So I'm starting small trying to learn DX11, using https://www.braynzarsoft.net/viewtutorial/q16390-simple-lighting

as my tutorial to render things. At first glance it's a simple tutorial, so I figured, hey, why not take my BSP-tree map header, have it read the data, and fill in the vertex/index buffers to render at least one plane from a bsp file? I've been trying all day and have smacked my face into a brick wall.

So I'm back here calling in the big guns, you guys. And I really need some help because I am not going to figure this one out on my own.

Here is my main.cpp(the only other file is bspread.h which is Ken Wright's BSP header I've modified for this exact attempt)

//Include and link appropriate libraries and headers//
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3dx10.lib")

#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <xnamath.h>
#include "bspread.h"
//Global Declarations - Interfaces//
IDXGISwapChain* SwapChain;
ID3D11Device* d3d11Device;
ID3D11DeviceContext* d3d11DevCon;
ID3D11RenderTargetView* renderTargetView;
ID3D11Buffer* squareIndexBuffer;
ID3D11DepthStencilView* depthStencilView;
ID3D11Texture2D* depthStencilBuffer;
ID3D11Buffer* squareVertBuffer;
ID3D11VertexShader* VS;
ID3D11PixelShader* PS;
ID3D10Blob* VS_Buffer;
ID3D10Blob* PS_Buffer;
ID3D11InputLayout* vertLayout;
ID3D11Buffer* cbPerObjectBuffer;
///////////////**************new**************////////////////////
ID3D11ShaderResourceView* CubesTexture;
ID3D11SamplerState* CubesTexSamplerState;
///////////////**************new**************////////////////////




////////////////
//BSP
////////////////
CBSP::stBSPVertex *pVB = NULL;





//Global Declarations - Others//
LPCTSTR WndClassName = L"firstwindow";
HWND hwnd = NULL;
HRESULT hr;

const int Width  = 300;
const int Height = 300;

XMMATRIX WVP;
XMMATRIX cube1World;
XMMATRIX cube2World;
XMMATRIX camView;
XMMATRIX camProjection;

XMVECTOR camPosition;
XMVECTOR camTarget;
XMVECTOR camUp;

XMMATRIX Rotation;
XMMATRIX Scale;
XMMATRIX Translation;
float rot = 0.01f;

//Function Prototypes//
bool InitializeDirect3d11App(HINSTANCE hInstance);
void CleanUp();
bool InitScene();
void UpdateScene();
void DrawScene();

bool InitializeWindow(HINSTANCE hInstance,
int ShowWnd,
int width, int height,
bool windowed);
int messageloop();

LRESULT CALLBACK WndProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);

//Create effects constant buffer's structure//
struct cbPerObject
{
XMMATRIX  WVP;
};

cbPerObject cbPerObj;

///////////////**************new**************////////////////////
//Vertex Structure and Vertex Layout (Input Layout)//
/*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;
};*/

//Above was the original Vertex struct that the tutorial used to draw two cubes, I'm using stBSPVertex to read the BSP map

D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },  
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },  
};
UINT numElements = ARRAYSIZE(layout);
///////////////**************new**************////////////////////
CBSP bsp("maze5.bsp");
int WINAPI WinMain(HINSTANCE hInstance, //Main windows function
HINSTANCE hPrevInstance,  
LPSTR lpCmdLine,
int nShowCmd)
{
 
if(!InitializeWindow(hInstance, nShowCmd, Width, Height, true))
{
 MessageBox(0, L"Window Initialization - Failed",
  L"Error", MB_OK);
 return 0;
}

if(!InitializeDirect3d11App(hInstance)) //Initialize Direct3D
{
 MessageBox(0, L"Direct3D Initialization - Failed",
  L"Error", MB_OK);
 return 0;
}

if(!InitScene()) //Initialize our scene
{
 MessageBox(0, L"Scene Initialization - Failed",
  L"Error", MB_OK);
 return 0;
}

messageloop();

CleanUp();    

return 0;
}

bool InitializeWindow(HINSTANCE hInstance,
int ShowWnd,
int width, int height,
bool windowed)
{
typedef struct _WNDCLASS {
 UINT cbSize;
 UINT style;
 WNDPROC lpfnWndProc;
 int cbClsExtra;
 int cbWndExtra;
 HANDLE hInstance;
 HICON hIcon;
 HCURSOR hCursor;
 HBRUSH hbrBackground;
 LPCTSTR lpszMenuName;
 LPCTSTR lpszClassName;
} WNDCLASS;

WNDCLASSEX wc;

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
wc.lpszMenuName = NULL;
wc.lpszClassName = WndClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

if (!RegisterClassEx(&amp;wc))
{
 MessageBox(NULL, L"Error registering class",  
  L"Error", MB_OK | MB_ICONERROR);
 return 1;
}

hwnd = CreateWindowEx(
 NULL,
 WndClassName,
 L"Lesson 4 - Begin Drawing",
 WS_OVERLAPPEDWINDOW,
 CW_USEDEFAULT, CW_USEDEFAULT,
 width, height,
 NULL,
 NULL,
 hInstance,
 NULL
 );

if (!hwnd)
{
 MessageBox(NULL, L"Error creating window",
  L"Error", MB_OK | MB_ICONERROR);
 return 1;
}

ShowWindow(hwnd, ShowWnd);
UpdateWindow(hwnd);

return true;
}

bool InitializeDirect3d11App(HINSTANCE hInstance)
{
//Describe our SwapChain Buffer
DXGI_MODE_DESC bufferDesc;

ZeroMemory(&amp;bufferDesc, sizeof(DXGI_MODE_DESC));

bufferDesc.Width = Width;
bufferDesc.Height = Height;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

//Describe our SwapChain
DXGI_SWAP_CHAIN_DESC swapChainDesc;  

ZeroMemory(&amp;swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));

swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = hwnd;  
swapChainDesc.Windowed = TRUE;  
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;


//Create our SwapChain
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
 D3D11_SDK_VERSION, &amp;swapChainDesc, &amp;SwapChain, &amp;d3d11Device, NULL, &amp;d3d11DevCon);

//Create our BackBuffer
ID3D11Texture2D* BackBuffer;
hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&amp;BackBuffer );

//Create our Render Target
hr = d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &amp;renderTargetView );
BackBuffer->Release();

//Describe our Depth/Stencil Buffer
D3D11_TEXTURE2D_DESC depthStencilDesc;

depthStencilDesc.Width     = Width;
depthStencilDesc.Height    = Height;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format    = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilDesc.SampleDesc.Count   = 1;
depthStencilDesc.SampleDesc.Quality = 0;
depthStencilDesc.Usage          = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags      = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;  
depthStencilDesc.MiscFlags      = 0;

//Create the Depth/Stencil View
d3d11Device->CreateTexture2D(&amp;depthStencilDesc, NULL, &amp;depthStencilBuffer);
d3d11Device->CreateDepthStencilView(depthStencilBuffer, NULL, &amp;depthStencilView);

//Set our Render Target
d3d11DevCon->OMSetRenderTargets( 1, &amp;renderTargetView, depthStencilView );

return true;
}

void CleanUp()
{
//Release the COM Objects we created
SwapChain->Release();
d3d11Device->Release();
d3d11DevCon->Release();
renderTargetView->Release();
squareVertBuffer->Release();
squareIndexBuffer->Release();
VS->Release();
PS->Release();
VS_Buffer->Release();
PS_Buffer->Release();
vertLayout->Release();
depthStencilView->Release();
depthStencilBuffer->Release();
cbPerObjectBuffer->Release();
}

bool InitScene()
{
//Compile Shaders from shader file
hr = D3DX11CompileFromFile(L"Effects.fx", 0, 0, "VS", "vs_4_0", 0, 0, 0, &amp;VS_Buffer, 0, 0);
hr = D3DX11CompileFromFile(L"Effects.fx", 0, 0, "PS", "ps_4_0", 0, 0, 0, &amp;PS_Buffer, 0, 0);

//Create the Shader Objects
hr = d3d11Device->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &amp;VS);
hr = d3d11Device->CreatePixelShader(PS_Buffer->GetBufferPointer(), PS_Buffer->GetBufferSize(), NULL, &amp;PS);

//Set Vertex and Pixel Shaders
d3d11DevCon->VSSetShader(VS, 0, 0);
d3d11DevCon->PSSetShader(PS, 0, 0);

///////////////**************new**************////////////////////
//Create the vertex buffer




pVB = new CBSP::stBSPVertex;

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

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

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

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


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

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

D3D11_SUBRESOURCE_DATA iinitData;

iinitData.pSysMem = (const void*)10; //Was bsp.m_pMeshIndices
d3d11Device->CreateBuffer(&amp;indexBufferDesc, &amp;iinitData, &amp;squareIndexBuffer); //I AM HAVING TROUBLE AT THIS POINT

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


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

vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(CBSP::stBSPVertex) * bsp.m_nNumVerts;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
///////////////**************new**************////////////////////

D3D11_SUBRESOURCE_DATA vertexBufferData;  
 
ZeroMemory( &amp;vertexBufferData, sizeof(vertexBufferData) );
vertexBufferData.pSysMem = pVB;
//hr = d3d11Device->CreateBuffer( &amp;vertexBufferDesc, &amp;vertexBufferData, &amp;squareVertBuffer);
hr = d3d11Device->CreateBuffer(&amp;vertexBufferDesc, &amp;vertexBufferData, &amp;squareVertBuffer);
//Set the vertex buffer
UINT stride = sizeof(CBSP::stBSPVertex);
UINT offset = 0;
d3d11DevCon->IASetVertexBuffers( 0, 1, &amp;squareVertBuffer, &amp;stride, &amp;offset );

//Create the Input Layout
hr = d3d11Device->CreateInputLayout( layout, numElements, VS_Buffer->GetBufferPointer(),  
 VS_Buffer->GetBufferSize(), &amp;vertLayout );

//Set the Input Layout
d3d11DevCon->IASetInputLayout( vertLayout );

//Set Primitive Topology
d3d11DevCon->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

//Create the Viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&amp;viewport, sizeof(D3D11_VIEWPORT));

viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = Width;
viewport.Height = Height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;

//Set the Viewport
d3d11DevCon->RSSetViewports(1, &amp;viewport);

//Create the buffer to send to the cbuffer in effect file
D3D11_BUFFER_DESC cbbd;  
ZeroMemory(&amp;cbbd, sizeof(D3D11_BUFFER_DESC));

cbbd.Usage = D3D11_USAGE_DEFAULT;
cbbd.ByteWidth = sizeof(cbPerObject);
cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbbd.CPUAccessFlags = 0;
cbbd.MiscFlags = 0;

hr = d3d11Device->CreateBuffer(&amp;cbbd, NULL, &amp;cbPerObjectBuffer);

//Camera information
camPosition = XMVectorSet( 0.0f, 3.0f, -8.0f, 0.0f );
camTarget = XMVectorSet( 0.0f, 0.0f, 0.0f, 0.0f );
camUp = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );

//Set the View matrix
camView = XMMatrixLookAtLH( camPosition, camTarget, camUp );

//Set the Projection matrix
camProjection = XMMatrixPerspectiveFovLH( 0.4f*3.14f, Width/Height, 1.0f, 1000.0f);

///////////////**************new**************////////////////////
hr = D3DX11CreateShaderResourceViewFromFile( d3d11Device, (LPCWSTR)bsp.m_pTextures[1].Name,
 NULL, NULL, &amp;CubesTexture, NULL );
if (hr != S_OK)
 MessageBoxA(NULL, "Something went wrong reading the texture", "Fuck!", MB_OK);
// Describe the Sample State
D3D11_SAMPLER_DESC sampDesc;
ZeroMemory( &amp;sampDesc, sizeof(sampDesc) );
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
   sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
   sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
   sampDesc.MinLOD = 0;
   sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
   
//Create the Sample State
hr = d3d11Device->CreateSamplerState( &amp;sampDesc, &amp;CubesTexSamplerState );
///////////////**************new**************////////////////////

return true;
}

void UpdateScene()
{
//Keep the cubes rotating
rot += .0005f;
if(rot > 6.26f)
 rot = 0.0f;

//Reset cube1World
cube1World = XMMatrixIdentity();

//Define cube1's world space matrix
XMVECTOR rotaxis = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
Rotation = XMMatrixRotationAxis( rotaxis, rot);
Translation = XMMatrixTranslation( 0.0f, 0.0f, 4.0f );

//Set cube1's world space using the transformations
cube1World = Translation * Rotation;

//Reset cube2World
cube2World = XMMatrixIdentity();

//Define cube2's world space matrix
Rotation = XMMatrixRotationAxis( rotaxis, -rot);
Scale = XMMatrixScaling( 1.3f, 1.3f, 1.3f );

//Set cube2's world space matrix
cube2World = Rotation * Scale;
}

void DrawScene()
{
//Clear our backbuffer
float bgColor[4] = {(0.0f, 0.0f, 0.0f, 0.0f)};
d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);

//Refresh the Depth/Stencil view
d3d11DevCon->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);

//Set the WVP matrix and send it to the constant buffer in effect file
WVP = cube1World * camView * camProjection;
cbPerObj.WVP = XMMatrixTranspose(WVP);  
d3d11DevCon->UpdateSubresource( cbPerObjectBuffer, 0, NULL, &amp;cbPerObj, 0, 0 );
d3d11DevCon->VSSetConstantBuffers( 0, 1, &amp;cbPerObjectBuffer );
///////////////**************new**************////////////////////
d3d11DevCon->PSSetShaderResources( 0, 1, &amp;CubesTexture );
d3d11DevCon->PSSetSamplers( 0, 1, &amp;CubesTexSamplerState );
///////////////**************new**************////////////////////

//Draw the first cube
d3d11DevCon->DrawIndexed( 0, 0, 0 );

WVP = cube2World * camView * camProjection;
cbPerObj.WVP = XMMatrixTranspose(WVP);  
d3d11DevCon->UpdateSubresource( cbPerObjectBuffer, 0, NULL, &amp;cbPerObj, 0, 0 );
d3d11DevCon->VSSetConstantBuffers( 0, 1, &amp;cbPerObjectBuffer );
///////////////**************new**************////////////////////
d3d11DevCon->PSSetShaderResources( 0, 1, &amp;CubesTexture );
d3d11DevCon->PSSetSamplers( 0, 1, &amp;CubesTexSamplerState );
///////////////**************new**************////////////////////

//Draw the second cube
d3d11DevCon->DrawIndexed( 36, 0, 0 );

//Present the backbuffer to the screen
SwapChain->Present(0, 0);
}

int messageloop(){
MSG msg;
ZeroMemory(&amp;msg, sizeof(MSG));
while(true)
{
 BOOL PeekMessageL(  
  LPMSG lpMsg,
  HWND hWnd,
  UINT wMsgFilterMin,
  UINT wMsgFilterMax,
  UINT wRemoveMsg
  );

 if (PeekMessage(&amp;msg, NULL, 0, 0, PM_REMOVE))
 {
  if (msg.message == WM_QUIT)
   break;
  TranslateMessage(&amp;msg);  
  DispatchMessage(&amp;msg);
 }
 else{
  // run game code            
  UpdateScene();
  DrawScene();
 }
}
return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch( msg )
{
case WM_KEYDOWN:
 if( wParam == VK_ESCAPE ){
  DestroyWindow(hwnd);
 }
 return 0;

case WM_DESTROY:
 PostQuitMessage(0);
 return 0;
}
return DefWindowProc(hwnd,
 msg,
 wParam,
 lParam);
}

If you look at the tutorial, I've simply replaced the Vertex struct with stBSPVertex, which is from bspread.h. I'm getting memory errors like crazy, breakpoints I haven't set are being triggered, I am in over my neck here and I need someone who can talk to me like a kindergartner in terms of DirectX to tell me what I'm doing wrong. pVB is just a pointer and I don't know how to do what was done in DX9 in DX11, at all. I am not using bspread.h to render whatsoever, I'm only using functions that fill in members that I can read, but could someone please show me code on how exactly to do this? On executiong, it says I've triggered a breakpoint, and VS2013 goes straight to “wntdll.pdb not loaded”. I am no good with debuggers, I'm not exactly brilliant with memory, I just want to be able to have the vertex/index buffer filled with the proper information. I have all the data from the header,

The struct is as follows(I'm not putting in a codeblock it's crashing my browser at this point…yeah):
struct stBSPVertex

{

D3DXVECTOR3 p; // Position Vertice

D3DXVECTOR3 n; // Vertice Normal

DWORD colour; // ARGB

float tu1, tv1; // Texture Coordinates

float lu2, lv2; // Light Tex Coords

};

and am able to obtain the following data from the BSP map:
CBSP::CBSP()

{}

stHeader m_Header;

stVertex *m_pVerts;

int m_nNumVerts;

stFace *m_pFaces;

int m_nNumFaces;

int *m_pMeshIndices;

int m_nNumMeshIndices;

stTexture *m_pTextures;

int m_nNumTextures;

stNode *m_pNodes;

int m_nNumNodes;

stLeaf *m_pLeafs;

int m_nNumLeafs;

stPlane *m_pPlanes;

int m_nNumPlanes;

int *m_pLeafFaces;

int m_nNumLeafFaces;

stVisData m_VisData;

int m_nNumVisData;

stBrush *m_pBrushes;

int m_nNumBrushes;

stBrushSide *m_pBrushSides;

int m_nNumBrushSides;

int *m_pLeafBrushes;

int m_nNumLeafBrushes;


It's not even getting to the drawing phase of the program, it crashes right around the vertex buffer declaration. I don't think I have to actually include my bsp header file in this post, I'm sure to you seasons veterans that I am massively screwing up with the filling of the buffers. May one of you fine gentlemen please offer a bit of code to show how to do this properly? Even if it were done for me, I'd learn from it and 100% of my other problems would be worked out, just like I did with DX9.

This is what I've been able to accomplish myself in DX9(after receiving tremendous help and running into brick walls for months, screencapture is causing lag, the game engine runs very smoothly at run-time):

So I please ask for your help. Again, treat me like a child in this; I need to see code, how this would be done properly, I'm a “monkey see monkey do” and “dive in the deep end and learn to sink or swim” type person when it comes to learning, so I really need to see some code to illustrate how I should accomplish this properly.

To be 100% honest, I am actually willing to pay a few hundred dollars if someone is willing to say “hey, fine, I'll upgrade your DX9 header to DX11 for you so you can learn from it”. Dead serious, if you don't believe me, then show me that you've solved it first with screenshare/screenshots and I'll ZELLE you the cash(I can't use paypal, they banned my SSN when I was a teenager 15 years ago for writing botnets and adclicking :P)

Thank you all so much. I really need some help here.

Tom_W said:
It's not even getting to the drawing phase of the program, it crashes right around the vertex buffer declaration.

But a crash is good. You get error message about the reason, and the debugger brings you to the line of code where the crash happened, and you can use call stack to go back in time to see what happened before.

Tom_W said:
On executiong, it says I've triggered a breakpoint, and VS2013 goes straight to “wntdll.pdb not loaded”. I am no good with debuggers

https://docs.microsoft.com/en-us/visualstudio/debugger/specify-symbol-dot-pdb-and-source-files-in-the-visual-studio-debugger?view=vs-2019

Now i guess you use some library (like DX driver stuff), but this library can't be debugged. (There are often debug and release versions of libraries which you could link individually for debug / release build). But not sure… something like that.

Is there some more info, like “read / write access violation"? This would hint you forgot to allocate data for a pointer, or the data is smaller than some function expects.

Be sure to follow the call stack to see what happened before. You may stumble over the bug if you're lucky. It should bring you back to your own code lines, calling something with bad data, causing the crash.

Debugger is your friend, and very easy to learn and use. Learn how to set your own break points, how to execute code line by line to follow what happens (F10, F11), using callstack and variable windows (Locals, Autos, Watch) to see their values and how they change. You could set a breakpoint very early in your main file and step through until the crash happens.

The atmosphere of your game is great! Oh, how do i miss games like this…

Advertisement

Thank you Joe. Before you even replied, I've been doing exactly what you've been saying, but to no avail. This does not seem to be a DirectX issue afterall(at least I'm not sure) – when I try to simply retrieve the data from public members of the bsp class, it causes a breakpoint.

  void GetBSPData(void)
{
CBSP bsp("dxtest.bsp");
pVB = new stBSPVertex;
m_nNumVerts = bsp.verts();
//m_nNumFaces = bsp.m_nNumFaces;
m_nNumMeshIndices = bsp.indices();
m_nNumTextures = 0;
m_nNumNodes = 0;
m_nNumLeafs = 0;
m_nNumPlanes = 0;
m_nNumLeafFaces = 0;
m_nNumVisData = 0;
m_nNumTrisDraw = 0;
m_nNumBrushes = 0;
m_nNumBrushSides = 0;
m_nNumLeafBrushes = 0;

// Always initialise pointers to NULL
m_pFaces = NULL;
stVertex* m_pVerts = bsp.pVerts();
m_pMeshIndices = bsp.pIndices();
/*m_pTextures = NULL;
m_pNodes = NULL;
m_pLeafs = NULL;
m_pPlanes = NULL;
m_pLeafFaces = NULL;
m_VisData.pBits = NULL;
m_pBrushes = NULL;
m_pBrushSides = NULL;
m_pLeafBrushes = NULL;*/
for (static int i = 0; i < 3; 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 &amp;amp; bsp.m_pVerts->RGBA; // ARGB
}
//bsp.~bsp();

Simply calling this function will immediately crash and cause the debugger to ask to abort/retry/ignore. Even right after WINAPI WinMain. All the bsp class is a bunch of integers and certain structs that contain info, why would me retrieving their info and filling them into a global cause this?? It's real upsetting. I've been able to get DX11 to read the map, and draw up the three vertices before going completely haywire(not to mention the releasing of all API vars causes a breakpoint after the draw, once the user end the program).

What in the hell is going on? I've been programming C++ since I've been 11, and although I'm not keen on debuggers like you are Joe, nor am I good with memory, this is alien to me.

Edit: Thank you for the praise with my game, you've earned yourself yourself another heart <3
Edit upon edit: I wrote yourself twice. Why aren't I just correcting that in this edit? Why is there a memory leak? What is the meaning of life? Are we alone in the universe? Did the quick brown fox really jump over the lazy dog? Perhaps questions like these can only be answered by a higher power, such as Joe.

pVB = new CBSP::stBSPVertex;

for (int i = 0; i<bsp.m_nNumVerts; i++)

{

pVB[i].p.x = bsp.m_pVerts[i].vPoint[0]; /// ←

pVB is a pointer to a single object, but you assume it an array of size bsp.m_nNumVerts when filoling the data?

Is it just that, or do i miss something?

If so, we'll talk about how the debugger would have told you this very precisely…

You're correct. That is the exact problem.

Joe. I love you.

It reads the map, but only shows parts of it.

I'm simply trying to create the vertex buffer and index buffer like was done in DirectX9.

In DirectX9, the code for that was:

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

I'm able to use pVB for the vertex buffer, but for the index buffer,
D3D11_SUBRESOURCE_DATA iinitData;

iinitData.pSysMem = (SOME VARIABLE OF THE TYPE CONST VOID*);

How do I achieve what you see in the code block, but in DX11? Making vertex/index buffers are so different in DX9/11 that I'm in over my head, what would you do to make the index/vertex buffer with the above info at hand?

Thanks for your help so far!!

Advertisement

Hehe, falling in love with random strangers from internet is almost as dangerous as falling in love with real woman : )

Now i guess crash message and debugger are not as helpful here as i thought at first.
If you were lucky, there would be a memory access violation message and the debugger jumps right to the line of code where it happens, in this case after the loop counter becomes 1.

But if you're out of luck, it is not detected and some random memory becomes corrupted, causing any kind of wired behavior.

I fixed a bug like this some days ago, and it was in since 4 years or so, causing periods of frequent random crashes, which is annoying, but then no issues for months until it pops up again.
Whenever problems appear, i try to find it by disabling stuff. But any code change can randomly turn the memory corruption harmless again, so those bugs are really hard to find.
I have also released a game with such bug.

I don't know any debugging tools to be of help here, but we could prevent this in the first place with bounds checking in debug mode.
But this requires we implement our own array or vector containers, including the bounds checking.

Or we use built in stl stuff like std::array or std::vector.

So if you would use std::vector<CBSP::stBSPVertex> pVB instead a pointer and allocation, you would have got a useful error message and instant knowledge of the cause.
Same is true for std::array, e.g.:

int x[3]; x[3] = 1; Causes a memory corruption but going unnoticed.

std::array<int,3> x; x[3] = 1; Gives you a proper bad access message in debug mode, and same performance as the above in release mode (they say).

It's more typing and looks ugly, but you also can do this later: x = {3,4,5}; which is comfortable in comparison to setting each element individually using regular array.

Now, the same is true for std::vector, but old school gamedevs like me are resistant using it, because ‘it's slow because of dynamic allocation’.
But this can be avoided, e.g.

{

int *x = new int [3];

x[0] = 1; x[1] = 2; x[2] = 3;

delete[] x;

}

should give the same performance as using:

{

std::vector<int> x (3);

x[0] = 1; x[1] = 2; x[2] = 3;

}

Because in both cases it's only one allocation. (And notice it frees stuff automatically when going out of scope, so no risk of memory leaks.)

You can also do this, again same performance:

{

std::vector<int> x;

x.reserve(3); // allocate space for 3 elements

for (int i=0; i<3; i++) x.push_back(i+1);

x.push_back(4); // …but adding one more, which still works

}

So here you allocate space for 3 elements with the reserve. But if you add a 4th element it still works. It will just do a reallocation, copy and free old stuff under the hood - no risk for bugs at all.

You see stl can save a lot of work, and it also helps to avoid bugs. It's very slow in debug builds, but i don't see a real reason to not using it even for game runtimes nowadays.
Would be worth it's own thread to see what other people think, though.

Wait Joe, don't log off before answering my question please!! I need you!

On my last post there were two functions, for creating the index and vertex buffer.

Could you please show me some code that would do the same in DX11? Please?? Pretty please?? I'm begging you!
As you can see, pIB is a WORD pointer, and pVB is a pointer of that of the vertex. Can you show the DX11 equivalent for these functions?? You'd be helping me tremendously!

(Oh, and I hate vectors, I was raised on C)

Please Joe, I need your help!

Vectors are nothing to hate. You can think of them as a thin wrapper on top of malloc() and realloc(), that calls constructors/destructors if the objects inside them have them, and don't, if they don't.

The Microsoft documentation for Direct3D 11 has good samples for putting data into vertex buffers:

https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-buffers-vertex-how-to

For example:

ID3D11Buffer*      g_pVertexBuffer;

// Define the data-type that
// describes a vertex.
struct SimpleVertexCombined
{
    XMFLOAT3 Pos;  
    XMFLOAT3 Col;  
};

// Supply the actual vertex data.
SimpleVertexCombined verticesCombo[] =
{
    XMFLOAT3( 0.0f, 0.5f, 0.5f ),
    XMFLOAT3( 0.0f, 0.0f, 0.5f ),
    XMFLOAT3( 0.5f, -0.5f, 0.5f ),
    XMFLOAT3( 0.5f, 0.0f, 0.0f ),
    XMFLOAT3( -0.5f, -0.5f, 0.5f ),
    XMFLOAT3( 0.0f, 0.5f, 0.0f ),
};

// Fill in a buffer description.
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.Usage            = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth        = sizeof( SimpleVertexCombined ) * 3;
bufferDesc.BindFlags        = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags   = 0;
bufferDesc.MiscFlags        = 0;

// Fill in the subresource data.
D3D11_SUBRESOURCE_DATA InitData;
InitData.pSysMem = verticesCombo;
InitData.SysMemPitch = 0;
InitData.SysMemSlicePitch = 0;

// Create the vertex buffer.
hr = g_pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &g_pVertexBuffer );
enum Bool { True, False, FileNotFound };

Tom_W said:
Could you please show me some code that would do the same in DX11? Please?? Pretty please?? I'm begging you!

Offering money or love, or begging… nothing helps, because i have not really used DX. :D

Tom_W said:
(Oh, and I hate vectors, I was raised on C)

Me too. I started using C++11 stuff only recently for example. But it's always the same pattern: As soon as you discover a real application and benefit, there is no turning back. New tool in the bag is always good.

This topic is closed to new replies.

Advertisement