Ok, first post. Ive tried to avoid asking for help when i've had problems before and usually managed to solve things on my own but on this, i'm just going round in circles.
I'm trying to teach myself basic directx9 and so far I made a program that takes a .3ds file, extracts only the info I need, stores it in binary to a .sd0 file (my own making but similiar to the .3ds format), and then i made this program, which just tries to extract the info from the .sd0 and load it into a vertex and index buffer for display. I'm not dealing with textures just yet, just the vertex/face data.
The first exception hits on the DrawIndexedPrimitive line, but from what Ive been able to learn i'm overflowing much earlier than that. I just can't find out where. I've tried to do it as a simple DrawPrimitive without indices so i'm assuming it's the vertex data but even so. I did notice that the memcpy was having programs when a vertex in the binary file was of value 0.00f. It was copying across that way in the original converter. I still havent been able to find out why but did put in a really lame hack to get around it (not asking for help on that one, i'll figure it out on my own.
Anyway, i'll post all the code, and yes, i'm a new learner so total apologises if my code makes you want to reach through the screen and throttle me.
sdImport.h
#ifndef _SDIMPORT_H_
#define _SDIMPORT_H_
#define _CRT_SECURE_NO_DEPRECATE_
#include <string>
#include <iostream>
#include <fstream>
#include <Windows.h>
typedef struct chunk
{
unsigned short ID;
long size;
} chunk;
typedef struct vertex
{
float x, y, z;
DWORD color;
} vertex;
typedef struct face
{
unsigned short p1, p2, p3;
} face;
typedef struct uvcoord
{
float u, v;
} uvcoord;
typedef struct texTri
{
float x, y, z;
float u, v;
}texTri;
class sdObj
{
public:
sdObj();
~sdObj();
unsigned char load(std::string const &filename);
chunk getChunkInfo(int offset, unsigned char *data);
void testvert();
bool scan(unsigned char *data);
int nVerts;
int nFace;
long filesize;
std::string gObjName;
int objNameSize;
unsigned char *objData;
vertex *vert;
face *facelist;
short *faceload;
vertex *vertconv;
protected:
enum
{
CHUNK_MAIN = 0x4D4D,
CHUNK_OBJ = 0x4D4D,
CHUNK_TRI = 0x3d3d,
CHUNK_VERTEX = 0x4110,
CHUNK_FACELIST = 0x4120,
CHUNK_FACEDESC = 0x4130,
CHUNK_UVCOORDLIST = 0x4140,
CHUNK_SMOOTHGROUP = 0x4150,
CHUNK_MAT = 0xAFFF,
CHUNK_MATNAME = 0xA000,
CHUNK_MATFILENAME = 0xA300
};
};
#endif
sdImport.cpp
#include <string>
#include <fstream>
#include <vector>
#include <d3d9.h>
#include <d3dx9.h>
#include <sstream>
#include "sdImport.h"
using namespace std;
sdObj::sdObj()
{
objData = NULL;
filesize = 0;
vert = NULL;
//face = NULL;
facelist = NULL;
faceload = NULL;
}
sdObj::~sdObj()
{
if(objData != NULL)
{
delete[] objData;
objData = NULL;
}
}
unsigned char sdObj::load(string const &filename)
{
unsigned char *funcObjData = NULL;
ifstream infile(filename.c_str(), ios::binary | ios::in);
if(infile.is_open())
{
infile.seekg(0, ios::end);
filesize = (long)infile.tellg();
infile.seekg(0, ios::beg);
if(funcObjData != NULL)
{
delete[] funcObjData;
funcObjData = NULL;
}
funcObjData = new unsigned char[filesize];
infile.read((char*)funcObjData, filesize);
infile.close();
if(infile.is_open())
return false;
}
scan(funcObjData);
return *funcObjData;
}
chunk sdObj::getChunkInfo(int offset, unsigned char *data)
{
chunk tc;
memcpy(&tc.ID, &data[offset], 2);
memcpy(&tc.size, &data[offset+2], 4);
return tc;
}
bool sdObj::scan(unsigned char *data)
{
chunk info;
int offset = 0;
memcpy(&info.ID, &data[offset], 2);
memcpy(&info.size, &data[offset+2], 4);
if(info.ID != CHUNK_OBJ)
return false;
if(info.size != filesize)
return false;
//offset = 6;
while (offset < filesize)
{
info = getChunkInfo(offset, data);
switch(info.ID)
{
case CHUNK_OBJ:
{
unsigned char* objname;
objname = new unsigned char;
int nameoff = offset + 6;
char c = 0;
string name;
do
{
memcpy (&c, &data[nameoff] , 1);
name += c;
nameoff++;
}
while(c != 0x00);
offset += nameoff;
break;
}
case CHUNK_TRI:
{
offset += 6;
break;
}
case CHUNK_VERTEX:
{
short nVert;
int vertoff = offset + 6;
memcpy (&nVert, &data[vertoff], 2);
vertoff += 2;
int vertplus = sizeof(float);
vert = new vertex[nVert];
for(int i = 0; i < nVert; i++)
{
memcpy(&vert[i].x,
&data[vertoff],
sizeof(float));
vertoff += vertplus;
memcpy(&vert[i].y,
&data[vertoff],
sizeof(float));
vertoff += vertplus;
memcpy(&vert[i].z,
&data[vertoff],
sizeof(float));
vertoff += vertplus;
vert[i].color = D3DCOLOR_XRGB(0, 255, 0);
}
nVerts = nVert;
testvert();
offset = vertoff;
break;
}
case CHUNK_FACELIST:
{
short nFaces;
int faceoff = offset + 6;
short faceinfo = 0;
int faceplus = sizeof(unsigned short);
memcpy(&nFaces, &data[faceoff], 2);
faceoff += 2;
facelist = new face[nFaces];
nFace = nFaces;
unsigned short facecheck = 0;
faceload = new short[nFaces];
for(int i = 0; i < nFaces; i++)
{
memcpy(&facelist[i].p1,
&data[faceoff],
sizeof(unsigned short));
faceload[facecheck] = facelist[i].p1;
faceoff += sizeof(unsigned short);
facecheck++;
memcpy(&facelist[i].p2,
&data[faceoff],
sizeof(unsigned short));
faceload[facecheck] = facelist[i].p2;
faceoff += sizeof(unsigned short);
facecheck++;
memcpy(&facelist[i].p3,
&data[faceoff],
sizeof(unsigned short));
faceload[facecheck] = facelist[i].p3;
faceoff += sizeof(unsigned short);
facecheck++;
faceoff += sizeof(short);
}
offset = faceoff;
break;
}
case CHUNK_FACEDESC:
{
offset += info.size;
break;
}
case CHUNK_UVCOORDLIST:
{
offset += info.size;
break;
}
case CHUNK_MAT:
{
offset += 6;
break;
}
case CHUNK_MATNAME:
{
offset += info.size;
break;
}
case CHUNK_MATFILENAME:
{
offset += info.size;
break;
}
default:
{
offset += info.size;
break;
}
}
}
return true;
}
void sdObj::testvert()
{
stringstream ss (stringstream::in | stringstream::out);
string check;
for(int i=0; i < nVerts; i++)
{
ss << vert[i].x;
check = ss.str();
string::size_type pos = check.find("e");
if (string::npos != pos)
{
vert[i].x = 0.00f;
}
ss << vert[i].y;
check = ss.str();
pos = check.find("e");
if (string::npos != pos)
{
vert[i].y = 0.00f;
}
ss << vert[i].z;
check = ss.str();
pos = check.find("e");
if (string::npos != pos)
{
vert[i].z = 0.00f;
}
}
}
dxInit.h
#ifndef _DX_INIT_H_
#define _DX_INIT_H_
#include <d3d9.h>
#include <d3dx9.h>
#include "sdImport.h"
#define CUSTOM_FVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
class dxInit
{
public:
dxInit();
~dxInit();
bool setDev(int width, int height, HWND hwnd, bool bFullscreen);
bool render();
bool setVBuffer();
bool setIBuffer();
bool setViewMatrix();
bool setProjectionMatrix();
bool setWorldMatrix();
sdObj sd;
private:
LPDIRECT3D9 pD3D;
LPDIRECT3DDEVICE9 pDevice;
LPDIRECT3DVERTEXBUFFER9 pVBuffer;
LPDIRECT3DINDEXBUFFER9 pIBuffer;
int dxScreenW, dxScreenH;
};
#endif
dxImport.cpp
#include <d3d9.h>
#include <d3dx9.h>
#include <string>
#include "dxInit.h"
#include "sdImport.h"
using namespace std;
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
dxInit::dxInit()
{
pD3D = NULL;
pDevice = NULL;
pVBuffer = NULL;
pIBuffer = NULL;
}
dxInit::~dxInit()
{
pIBuffer->Release();
pVBuffer->Release();
pDevice->Release();
pD3D->Release();
}
bool dxInit::setDev(int width, int height, HWND hwnd, bool bFullscreen)
{
dxScreenW = width;
dxScreenH = height;
pD3D = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS pD3Dpp;
ZeroMemory(&pD3Dpp, sizeof(pD3Dpp));
pD3Dpp.Windowed = !bFullscreen;
pD3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
pD3Dpp.hDeviceWindow = hwnd;
pD3Dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
pD3Dpp.BackBufferWidth = dxScreenW;
pD3Dpp.BackBufferHeight = dxScreenH;
pD3Dpp.EnableAutoDepthStencil = TRUE;
pD3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&pD3Dpp,
&pDevice)))
{
return false;
}
setVBuffer();
setIBuffer();
pDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
return true;
}
bool dxInit::render()
{
if(FAILED(pDevice->Clear(0,
NULL,
D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0, 0, 0),
1.0f,
0)))
return false;
if(FAILED(pDevice->Clear(0,
NULL,
D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0, 0, 0),
1.0f,
0)))
return false;
pDevice->SetFVF(CUSTOM_FVF);
setViewMatrix();
setProjectionMatrix();
setWorldMatrix();
if(FAILED(pDevice->SetStreamSource(0, pVBuffer, 0, sizeof(vertex))))
return false;
if(FAILED(pDevice->SetIndices(pIBuffer)))
return false;
if(FAILED(pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, sd.nVerts, 0, sd.nFace)))
return false;
pDevice->BeginScene();
pDevice->EndScene();
pDevice->Present(NULL, NULL, NULL, NULL);
return true;
}
bool dxInit::setVBuffer()
{
if(FAILED(pDevice->CreateVertexBuffer(sd.nVerts * sizeof(vertex),
D3DUSAGE_WRITEONLY,
CUSTOM_FVF,
D3DPOOL_MANAGED,
&pVBuffer,
NULL)))
return false;
void *pvoid;
if(FAILED(pVBuffer->Lock(0,0, (void**)&pvoid, 0)))
return false;
memcpy(pvoid, sd.vert, sizeof(sd.vert));
if(FAILED(pVBuffer->Unlock()))
return false;
return true;
}
bool dxInit::setIBuffer()
{
if(FAILED(pDevice->CreateIndexBuffer(sd.nFace * sizeof(short),
0,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&pIBuffer,
NULL)))
return false;
void *pvoid;
if(FAILED(pIBuffer->Lock(0,0, (void**)&pvoid, 0)))
return false;
memcpy(pvoid, sd.faceload, sizeof(sd.faceload));
if(FAILED(pIBuffer->Unlock()))
return false;
return true;
}
bool dxInit::setViewMatrix()
{
D3DXMATRIX matView;
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3(0.0f, 8.0f, 60.0f), //camera
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), // look at
&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); // up direction
if(FAILED(pDevice->SetTransform(D3DTS_VIEW, &matView)))
return false;
return true;
}
bool dxInit::setProjectionMatrix()
{
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45),
(float)dxScreenW / (float)dxScreenH,
1.0f,
100.0f);
if(FAILED(pDevice->SetTransform(D3DTS_PROJECTION, &matProjection)))
return false;
return true;
}
bool dxInit::setWorldMatrix()
{
static float index = 0.0f;
D3DXMATRIX matRotateY;
D3DXMatrixRotationY(&matRotateY, index);
if(FAILED(pDevice->SetTransform(D3DTS_WORLD, &(matRotateY))))
return false;
return true;
}
I didn't post the winclude.h/cpp files, as I can't see how they're relevant, but if you need them let me know.
Also, the .sd0 format i made is kinda lame, very similar to the .3ds format.
Works in chunks. 2 bytes for chunk code, 4 for size of chunk. Then any data within that chunk.
4D4D is the main obj chunk (one obj per file), followed by size of file and the object name (null terminated string)
3D3D is the trimesh subchunk of obj. only contains subchunks.
Then 4110, 4120, 4130 and 4140 are the vertex, face, face description and uv coordinate subchunks of tri.
AFFF is a material subchunk of obj, contains only subchunks.
A000, and A300 are the material name and material filename subchunks of mat.
The errors produced are:
First-chance exception at 0x7c812afb in DX3DImport.exe: Microsoft C++ exception: long at memory location 0x0012faa0
HEAP[DragDrapTest.exe]: Invalid Address specified to RtlValidateHeap( 00360000, 00366BC0 )
Finally and I can't iterate this enough, my code is so sloppy i'm a little embarressed to be presenting it, but to learn, I must accept that I am crap and move on from there.
Any help you can provide will be gratefully accepted.
edit - Just uploaded the .sd0 file incase you need it. - http://www.yunaco.com/dawnstar.sd0