Original Post
Hey, I have been learning DirectX lately, so I have been writting a DirectX wrapper also. I have one going for the window. That was really simple. Anyway, I decided to go ahead and take my hand at trying to write a Vertex Buffer wrapper, so that way it will be a little bit easier for me to draw some simple shapes before I get into .X loading. Anyway...before I added the Vertex Buffer, my window worked just fine. Now that I did...it seems like it freezes or something. I am actually not really sure what is going on. All I know is that it's not even getting to the render loop. It won't even clear my screen like it used to. That reason alone has led me to believe that it is the Vertex Buffer. I will also include the window loading code, the demo I am using the wrapper in, and my vertex buffer class information. Let's begin. :) VertexBuffer.h VertexBuffer.cpp (Where I think where the problem could lie...) EGLWindow.h EGLWindow.cpp EGL.h (The main file for the EGL Library I am far aware of some of the bad coding techniques being used, though some more helpful hints would ALWAYS be appreciated. Do any of y'all know what is wrong? Any help is AMAZING and of course appreciated. Oh yikes. Almost forgot the runtime error that Visual C++ Express Edition is throwing at me.
/*VertexBuffer.h
*this file is here for the class declaration of the VertexBuffer
*This will lie in the EGLGraphics namespace TODO: Add the EGLGraphics Namespace!!!!
*help us get a vertex buffer up fast, and set an index buffer if we need it
*/
//inclusion guards
#ifndef VERTEXBUFFER_H
#define VERTEXBUFFER_H
//include the needed directX header files
#include <d3d9.h>
#include <d3dx9.h>
//start the vertex buffer class
class VertexBuffer
{
//public mode
public:
//constructor
VertexBuffer();
//destructor
~VertexBuffer() {Release();}
//create a vertex buffer
bool CreateVertexBuffer(LPDIRECT3DDEVICE9 theDevice, UINT numVertices, DWORD FVF, UINT vertexSize, bool dynamic=false);
//release the buffer
void Release();
//set the data
bool SetData(UINT numVertices, void* vertices, DWORD flags=D3DLOCK_DISCARD);
//render the vertex buffer
void Render(LPDIRECT3DDEVICE9 theDevice, UINT numPrimitives, D3DPRIMITIVETYPE primitiveType);
//private mode
private:
//vertex buffer
LPDIRECT3DVERTEXBUFFER9 VB;
//number of verticies to use
UINT numberVertices;
//vertex size
UINT vertexSize;
//the vertex FVF
DWORD FVF;
};
#endif
/*Vertexbuffer.cpp
*used for the class definition of the VertexBuffer
*/
//includes
//include the VertexBuffer.h
#include "VertexBuffer.h"
//the default constructor
VertexBuffer::VertexBuffer()
{
this->VB=NULL;
this->numberVertices=0;
this->FVF=0;
this->vertexSize=0;
}
//create a vertex buffer
//return true if it works, and false if not
bool VertexBuffer::CreateVertexBuffer(LPDIRECT3DDEVICE9 theDevice, UINT numVertices, DWORD FVF, UINT vertexSize, bool dynamic)
{
//release any other vertex buffer
Release();
this->numberVertices=numVertices;
this->FVF=FVF;
this->vertexSize=vertexSize;
//check to make sure we do not have a dynamic buffer, as they can not be used in D3DPOOL_MANAGED
D3DPOOL pool=dynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
DWORD usage=dynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : D3DUSAGE_WRITEONLY;
//check to makes ure the vertex buffer was created
if(FAILED(theDevice->CreateVertexBuffer(this->numberVertices*this->vertexSize, usage, this->FVF, pool, &VB, NULL)))
{
//if we are in here, then the vertex buffer was not created, and we need to exit
return false;
}
return true;
}
//clean up all the resources we created
void VertexBuffer::Release()
{
VB->Release();
this->numberVertices=0;
this->FVF=0;
this->vertexSize=0;
}
//now fill the vertex buffer with data
bool VertexBuffer::SetData(UINT numVertices, void *vertices, DWORD flags)
{
//if there is no vertexbuffer, we need to go ahead and exit
if(this->VB==NULL)
{
return false;
}
char* data;
//lock the vertex buffer, so we can wright stuff to it
if(FAILED(this->VB->Lock(0, 0, (void**)&data, flags)))
{
//if we are in here, then we could not lock the vertex buffer. exit
return false;
}
//now copy the vertices to the vertex buffer
memcpy(data, vertices, numVertices*vertexSize);
//unlock the vertex buffer
if(FAILED(VB->Unlock()))
{
//if we are in here, we could not unlock the vertex buffer
//so get out
return false;
}
return true;
}
//render the buffer
void VertexBuffer::Render(LPDIRECT3DDEVICE9 theDevice, UINT numPrimitives, D3DPRIMITIVETYPE primitiveType)
{
//if we have a null device, then get out of this function
if(theDevice==NULL)
{
return;
}
//set the stream source for the vertex buffer
theDevice->SetStreamSource(0, this->VB, 0, this->vertexSize);
//the FVF to use
theDevice->SetFVF(this->FVF);
theDevice->DrawPrimitive(primitiveType, 0, numPrimitives);
}
/*EGLWindow.h
*this file is uses for the window class for the EGL Library
*the window class will lie in the EGL namespace
*/
//inclusion guards
#ifndef EGLWINDOW_H_
#define EGLWINDOW_H_
//now include all of the usefull header files that we will need.
//iostream
#include <iostream>
//windows
#include <windows.h>
//DirectX header files
#include <d3d9.h>
#include <d3dx9.h>
//SDL header file
#include <SDL/sdl.h>
//start the EGL namespace
namespace EGL
{
//the EGL windows class
class EGLWindow
{
//first is public mode
public:
//the constructor
EGLWindow(int width, int height);
//the destructor
~EGLWindow();
//init the window
bool InitWindow();
//getters
//get the window width
int GetWidth() {return eglWidth;}
//get the windows height
int GetHeight() {return eglHeight;}
//get the windows Direct3D Device
IDirect3DDevice9* GetDevice() {return d3dDevice;}
//private mode
private:
//the very important variables that we will need
//first a Direct3D9 object
IDirect3D9* d3dObject;
//the Direct3D9Device
IDirect3DDevice9* d3dDevice;
//the present parameters, for device properties
D3DPRESENT_PARAMETERS presentParameters;
//hold the windows width
int eglWidth;
//height
int eglHeight;
};
//end class
//end namespace for this header file
}
#endif
/*EGLWindow.cpp
*used for the class and/or namespace definitions for the EGLWindow.h file
*/
//the includes
//I only need to include the EGLWindow.h file
#include "EGLWindow.h"
//use the std namespace
using namespace std;
//start the defintions now
//the constructor
EGL::EGLWindow::EGLWindow(int width, int height)
{
//first we need to set all variables/pointers to something
eglWidth=width;
eglHeight=height;
d3dObject=NULL;
d3dDevice=NULL;
//first, we need to Init SDL
//init all the subsystems
SDL_Init(SDL_INIT_EVERYTHING);
}
//the destructor
EGL::EGLWindow::~EGLWindow()
{
}
bool EGL::EGLWindow::InitWindow()
{
//set the video info
SDL_SetVideoMode(eglWidth, eglHeight, 32, NULL);
//now we init the Direct3D stuff
//the Direct3DObject
d3dObject=Direct3DCreate9(D3D_SDK_VERSION);
if(d3dObject==NULL)
{
MessageBox(GetActiveWindow(), L"Error-Could not create a Direct3D Object", L"Direct3D Error", MB_OK);
return false;
}
cout<<"The object was created"<<endl;
//set the device parameters
//clear out the structer
ZeroMemory(&presentParameters, sizeof(presentParameters));
presentParameters.Windowed=true;
presentParameters.SwapEffect=D3DSWAPEFFECT_DISCARD;
presentParameters.EnableAutoDepthStencil=true;
presentParameters.AutoDepthStencilFormat=D3DFMT_D24S8;
presentParameters.hDeviceWindow=::GetActiveWindow();
presentParameters.BackBufferWidth=eglWidth;
presentParameters.BackBufferHeight=eglHeight;
presentParameters.BackBufferFormat=D3DFMT_A8R8G8B8;
presentParameters.MultiSampleType=D3DMULTISAMPLE_NONE;
presentParameters.BackBufferCount=1;
presentParameters.PresentationInterval=D3DPRESENT_INTERVAL_IMMEDIATE;
//create the Direct3DDevice
if(FAILED(d3dObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetActiveWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&presentParameters, &d3dDevice)))
{
MessageBox(GetActiveWindow(), L"Error-Could not create the Direct3D Device", L"Direct3D Error", MB_OK);
return false;
}
cout<<"The device was created..."<<endl;
//we are done with the direct3D object now
d3dObject->Release();
cout<<"Object Released..."<<endl;
return true;
}
/*EGL.h
*this is the main header file
*this is where general functions are defined
*for the EGL Namespace
*/
//inclusion guards
#ifndef EGL_H_
#define EGL_H_
//include DirectX stuff
#include <d3d9.h>
//include the eglwindow stuff
#include "EGLWindow.h"
//start the EGL namespace
namespace EGL
{
//make a IDirect3DDevicee also be a EGLDevice
typedef IDirect3DDevice9* EGLDevice;
//a Direct3DDevice to use instead of the real one
EGLDevice referenceDevice;
//start a window for us automatically
bool InitEGLWindow(int width, int height)
{
EGLWindow appWindow(800, 600);
if(appWindow.InitWindow()==false)
{
return false;
}
//now set the reference device to a device
referenceDevice=appWindow.GetDevice();
std::cout<<appWindow.GetDevice()<<std::endl;
std::cout<<referenceDevice<<std::endl;
return true;
}
//clear the whole screen function
void ClearScreen(IDirect3DDevice9* theDevice, D3DCOLOR theColor)
{
theDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, theColor, 1.0f, 0);
}
//begin rendering the whole screen function
void BeginRender(IDirect3DDevice9* theDevice)
{
theDevice->BeginScene();
}
//end all the rendering stuff
void EndRender(IDirect3DDevice9* theDevice)
{
theDevice->EndScene();
}
//present the details to the user
void Present(IDirect3DDevice9* theDevice)
{
theDevice->Present(NULL, NULL, NULL, NULL);
}
//clear to a RGB color
inline D3DCOLOR ClearRGBColor(int r, int g, int b)
{
return D3DCOLOR_XRGB(r,g, b);
}
//templated release function, to release certain stuff
template<class T> void Release(T t)
{
if(t)
{
t->Release();
t=0;
}
}
}
#endif
The Demo file
//this is the demo for the EGL library
//include iostream
#include <iostream>
//first include the EGL.h file, as that is the main file
#include "EGL.h"
//the vertex and index buffer information
#include "VertexBuffer.h"
#include "IndexBuffer.h"
//struct for the custom vertex
struct Vertex
{
Vertex() {}
Vertex(float _x, float _y, float _z)
{
x=_x; y=_y; z=_z;
}
float x, y, z;
};
//CONSTANT TO HOLD THE FVF FOR THE CUSTOM VERTEX
const DWORD FVF=D3DFVF_XYZ;
//start main
int main(int argc, char* argv[])
{
//create a SDL_Event, so we can poll for events and handle input
SDL_Event evnt;
//CONSTANTS TO HOLD THE WINDOWS WIDTH AND HEIGHT AND ASPECT RATIO
const int WIDTH=800;
const int HEIGHT=600;
const float ASPECTRATIO=(float)WIDTH/(float)HEIGHT;
//init the window using the built in InitWindow from EGL's namespace
EGL::InitEGLWindow(800, 600);
if(EGL::referenceDevice==NULL)
{
std::cout<<"the device is null...we need out..."<<std::endl;
return 1;
}
//create a triangle
Vertex triangle[3];
triangle[0]=Vertex(-2.0f, -2.0f, 5.0f);
triangle[1]=Vertex(0.0f, 2.0f, 5.0f);
triangle[2]=Vertex(-2.0f, 2.0f, 5.0f);
//setup the Vertex and Index Buffers
VertexBuffer vertexBuffer;
vertexBuffer.CreateVertexBuffer(EGL::referenceDevice, 6, FVF, sizeof(Vertex));
vertexBuffer.SetData(3, triangle);
std::cout<<"Just created the index/vertex buffer(s)"<<std::endl;
//now position and aim the camera
//the position vector
//move it further back, so we can see the whole scene
D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
//aim the camera at the orgin (0, 0, 0)
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
//the y-axis is up
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
//view matrix
D3DXMATRIX view;
//define where the camera should look at
D3DXMatrixLookAtLH(&view, &position, ⌖, &up);
//set to transform to the view matrix now
EGL::referenceDevice->SetTransform(D3DTS_VIEW, &view);
//projection matrix
D3DXMATRIX projection;
D3DXMatrixPerspectiveFovLH(&projection, D3DXToRadian(90), ASPECTRATIO, 1.0f, 1000.0f);
//projection transform
EGL::referenceDevice->SetTransform(D3DTS_PROJECTION, &projection);
EGL::referenceDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
std::cout<<"window is now inited, and about to enter game loop"<<std::endl;
//before we loop, make sure are device is not null
if(EGL::referenceDevice==NULL)
{
std::cout<<"device is null...QUIT..."<<std::endl;
return 1;
}
//now loop while we are not done
while(1)
{
//while there is a event the check
while(SDL_PollEvent(&evnt))
{
if(evnt.type==SDL_QUIT)
{
return 0;
}
break;
}
D3DXMATRIX rotationX, rotationY;
//rotate 45 degrees along the x-axis
static float x=0.0f;
D3DXMatrixRotationX(&rotationX, x);
x+=0.05f;
//increatment the y-rotation angle
static float y=0.0f;
D3DXMatrixRotationY(&rotationY, y);
y+=0.05f;
if(y>=6.28f)
{
y=0.0f;
}
//combine rotations
D3DXMATRIX combined=rotationX*rotationY;
EGL::referenceDevice->SetTransform(D3DTS_WORLD, &combined);
EGL::ClearScreen(EGL::referenceDevice, EGL::ClearRGBColor(0, 255, 0));
EGL::BeginRender(EGL::referenceDevice);
vertexBuffer.Render(EGL::referenceDevice, 12, D3DPT_TRIANGLELIST);
EGL::EndRender(EGL::referenceDevice);
EGL::Present(EGL::referenceDevice);
}
vertexBuffer.Release();
//release the device with a homemade templated release function
EGL::Release<EGL::EGLDevice>(EGL::referenceDevice);
return 0;
}
Unhandled exception at 0x0041341d in EGL.exe: 0xC0000005: Access violation reading location 0x00000000.
From what that is saying...it does seem like there is a NULL pointer somewhere. My first thought was the reference device I was using. But where I output both of the addresses of the devices (reference, and real one) to make sure they are the same, it dosen't output it as a NULL pointer, and both addressse are the same. The output my program throws out in the console window is:
Object Created
Device Created
Object Released
*address here
*address here (same as the first)
I tried debugging this...but I am not really sure/good on debugging this kind of stuff. I'm still really learning the debugging ways, but getting a little better. Again...any help is appreciated. Chad.