home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2006 July & August
/
PCWorld_2006-07-08_cd.bin
/
temacd
/
planearcade
/
planearcade.exe
/
Tank3.bmp
/
q3bsp.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2004-10-03
|
38KB
|
950 lines
#include "main.h"
//------------------------------------------------------------------
// Name: QBSP()
// Desc: konÜtruktor
//------------------------------------------------------------------
QBSP::QBSP()
{
//DirectX
g_pVB = NULL;
Texture = NULL;
LightMap = NULL;
// Here we simply initialize our member variables to 0
// Nastav jednoduchΘ prom∞nnΘ
m_iNumOfVerts = 0; // PoΦet vrchol∙ scΘny nastav na 0
m_iNumOfFaces = 0; // PoΦet ploÜek scΘny nastav na 0
m_iNumOfTextures = 0; // PoΦet textur nastav na 0
m_iNumOfLightmaps = 0; // PoΦet lightmap nastav na 0
m_iNumOfNodes = 0; // PoΦet uzl∙ nastav na 0
m_iNumOfLeafs = 0; // PoΦe list∙ nastav na 0
m_iNumOfLeafFaces = 0; // PoΦet ploÜek v listu nastav na 0
m_iNumOfPlanes = 0; // PoΦet d∞licφch ploch nastav na 0
m_iVisibleFaces = 0; // Kontrolnφ prom∞nnou, kterß uklßdß, kolik ploÜek se renderuje nastav na 0
// Initialize all the dynamic BSP data pointers to NULL
m_ptBspVertex = NULL; // Vrcholy scΘny
m_ptBspFace = NULL; // PloÜky scΘny
m_ptBspNode = NULL; // Uzly BSP scΘny
m_ptBspLeaf = NULL; // Listy BSP scΘny
m_ptBspPlane = NULL; // D∞licφ plochy BSP scΘny
m_piLeafFaces = NULL; // PloÜky list∙ BSP scΘny
m_piLeafBrushes = NULL; //
memset(&m_tBspVisData, 0, sizeof(TBspVisData)); // Alokuj pam∞¥ pro data detekce viditelnosti portßl∙
}
//------------------------------------------------------------------
// Name: QBSP
// Desc: deÜtruktor
//------------------------------------------------------------------
QBSP::~QBSP()
{
int i=0;
/////////////
//DirectX
/////////////
//zmaz textury
if (Texture != NULL)
{
for ( i=0;i<m_iNumOfTextures;i++)
{
if(Texture[i] != NULL)
{
Texture[i]->Release();
}
}
delete[] Texture ;
}
//zmaz lightmapy
if (LightMap != NULL)
{
for ( i=0;i<m_iNumOfLightmaps;i++)
{
if(LightMap[i] != NULL)
{
LightMap[i]->Release();
}
}
delete[] LightMap ;
}
//vertex buffer
if (g_pVB != NULL)
g_pVB->Release();
g_pVB = NULL;
}
//------------------------------------------------------------------
// Name: LoadBSP()
// Desc: Loadni Quake 3 BSP scenu
//------------------------------------------------------------------
bool QBSP::LoadBSP(const char *pc_filename,float Gamma)
{
FILE *pfile = NULL; // Soubor nastav na NULL
int i = 0; // Prom∞nnou pro cyklovßnφ nastav na 0
char cBuf[80] ; // Premennß na chybovΘ hlaÜky
//Informacie pre Log
LogPrint("Nahravam Quake3 BSP mapu");
sprintf(cBuf," S·bor: %s",pc_filename);
LogPrint(cBuf);
// Check if the .bsp file could be opened
// Pokud se napoda°φ otev°φt soubor BSP, tak
if((pfile = fopen(pc_filename, "rb")) == NULL)
{
// Display an error message and quit if the file can't be found.
// Vyho∩ chybovou hlßÜku
sprintf(" Nenasiel som s·bor %s",pc_filename);
LogPrint(cBuf);
return false; // Vra¥ funkci false
}
// Initialize the header and lump structures
TBspHeader t_bsp_header = {0}; // Vyma₧ hodnoty BSP hlaviΦky
TBspLump t_bsp_lump[LUMPS_MAX_LUMPS] = {0}; // Vyma₧ hodnoty BSP identifikaΦnφch polo₧ek
// Read in the header and lump data
// NaΦti hodnoty hlaviΦky a identifikaΦnφ polo₧ky
fread(&t_bsp_header, 1, sizeof(TBspHeader), pfile);
fread(&t_bsp_lump, LUMPS_MAX_LUMPS, sizeof(TBspLump), pfile);
//VypφÜe informßcie pre Log
LogPrint(" Informacie o QBSP:");
sprintf(cBuf," verzia: %d",t_bsp_header.i_version);
LogPrint(cBuf);
sprintf(cBuf," pc_id: %s",t_bsp_header.pc_id );
LogPrint(cBuf);
// Now we know all the information about our file. We can
// then allocate the needed memory
//
// Nynφ znßme vÜechny informace o souboru.
// Dßle budeme alokovat pot°ebnou pam∞¥ pro vÜechny pot°ebnΘ prom∞nnΘ
// Allocate the vertex memory
// Alokuj pam∞¥ pro vrcholy
m_iNumOfVerts = t_bsp_lump[LUMPS_VERTICES].i_length / sizeof(TBspVertex);
m_ptBspVertex = new TBspVertex [m_iNumOfVerts];
sprintf(cBuf," pocet vertexov: %d",m_iNumOfVerts);
LogPrint(cBuf);
// Allocate the face memory
// Alokuj pam∞¥ pro ploÜky
m_iNumOfFaces = t_bsp_lump[LUMPS_FACES].i_length / sizeof(TBspFace);
m_ptBspFace = new TBspFace [m_iNumOfFaces];
sprintf(cBuf," pocet facov: %d",m_iNumOfFaces);
LogPrint(cBuf);
// Allocate memory to read in the texture information.
// Alokuj pam∞¥ pro texturovΘ informace
m_iNumOfTextures = t_bsp_lump[LUMPS_TEXTURES].i_length / sizeof(TBspTexture);
TBspTexture *pt_bsp_textures = new TBspTexture [m_iNumOfTextures];
sprintf(cBuf," pocet textur: %d",m_iNumOfTextures);
LogPrint(cBuf);
// Allocate memory to read in the lightmap data.
// Alokuj pam∞¥ pro lightmap data
m_iNumOfLightmaps = t_bsp_lump[LUMPS_LIGHTMAPS].i_length / sizeof(TBspLightmap);
TBspLightmap *pt_bsp_lightmaps = new TBspLightmap [m_iNumOfLightmaps ];
sprintf(cBuf," pocet lightmap: %d",m_iNumOfLightmaps);
LogPrint(cBuf);
// Seek to the position in the file that stores the vertex information
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty vrchol∙
fseek(pfile, t_bsp_lump[LUMPS_VERTICES].i_offset, SEEK_SET);
// Go through all of the vertices that need to be read and swap axises
// Projdi vÜechny vrcholy
for(i = 0; i < m_iNumOfVerts; i++)
{
// Read in the current vertex
// ╚ti ze souboru BSP hodnoty vrchol∙
fread(&m_ptBspVertex[i], 1, sizeof(TBspVertex), pfile);
// Swap the y and z values, and negate the new z so Y is up.
// Proho∩ hodnoty Y a Z, a nastav opaΦnΘ znamΘnko u novΘ hodnoty Z
float f_temp = m_ptBspVertex[i].pf_position[1];
m_ptBspVertex[i].pf_position[1] = m_ptBspVertex[i].pf_position[2];
m_ptBspVertex[i].pf_position[2] = -f_temp;
}
// Seek to the position in the file that stores the face information
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty ploÜek
fseek(pfile, t_bsp_lump[LUMPS_FACES].i_offset, SEEK_SET);
// Read in all the face information
// ╚ti ze souboru BSP vÜechny hodnoty ploÜek
fread(m_ptBspFace, m_iNumOfFaces, sizeof(TBspFace), pfile);
// Seek to the position in the file that stores the texture information
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty textur
fseek(pfile, t_bsp_lump[LUMPS_TEXTURES].i_offset, SEEK_SET);
// Read in all the texture information
// ╚ti ze souboru BSP vÜechny hodnoty textur
fread(pt_bsp_textures, m_iNumOfTextures, sizeof(TBspTexture), pfile);
//Alokuj pama¥ pre textury
Texture = new LPDIRECT3DTEXTURE9[m_iNumOfTextures];
// Go through all of the textures
// Projdi vÜechny textury
for(i = 0; i < m_iNumOfTextures; i++)
{
// Create a texture from the image
// NaΦti texturu
char TexFN1[80];
char TexFN2[80];
sprintf(TexFN1,"%s.jpg",pt_bsp_textures[i].pc_filename);
sprintf(TexFN2,"%s.tga",pt_bsp_textures[i].pc_filename);
sprintf(cBuf," nahravam texturu: %d %s",i,TexFN1);
LogPrint(cBuf);
Texture[i] = NULL;
if (FAILED(D3DXCreateTextureFromFileEx(g_pd3dDevice, //Our D3D Device
TexFN1, //Filename of our texture
D3DX_DEFAULT, //Width:D3DX_DEFAULT = Take from file
D3DX_DEFAULT, //Height:D3DX_DEFAULT = Take from file
Engine.MipMapLevels, //MipLevels
0, //Usage, Is this to be used as a Render Target? 0 == No
Engine.TextureFormat, //32-bit with Alpha, everything should support this
Engine.TextureCreatingFlag,//Pool, let D3D Manage our memory
D3DX_DEFAULT, //Filter:Default filtering
D3DX_DEFAULT, //MipFilter, used for filtering mipmaps
0, //Disable ColourKey
NULL, //SourceInfo, returns extra info if we want it (we don't)
NULL, //Palette:We're not using one
&Texture[i])))
{
sprintf(cBuf," nahravam texturu: %d %s",i,TexFN2);
LogPrint(cBuf);
if (FAILED(D3DXCreateTextureFromFileEx(g_pd3dDevice, //Our D3D Device
TexFN2, //Filename of our texture
D3DX_DEFAULT, //Width:D3DX_DEFAULT = Take from file
D3DX_DEFAULT, //Height:D3DX_DEFAULT = Take from file
Engine.MipMapLevels, //MipLevels
0, //Usage, Is this to be used as a Render Target? 0 == No
D3DFMT_UNKNOWN, //32-bit with Alpha, everything should support this
Engine.TextureCreatingFlag,//Pool, let D3D Manage our memory
D3DX_DEFAULT, //Filter:Default filtering
D3DX_DEFAULT, //MipFilter, used for filtering mipmaps
0, //Disable ColourKey
NULL, //SourceInfo, returns extra info if we want it (we don't)
NULL, //Palette:We're not using one
&Texture[i])))
{
LogPrint(" chyba");
}
else
{
LogPrint(" OK");
}
}
else
{
LogPrint(" OK");
}
}
// We can now free all the texture information since we already loaded them
// Vyma₧ vÜechny texturovΘ hodnoty z pam∞ti
delete [] pt_bsp_textures;
// Seek to the position in the file that stores the lightmap information
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty lightmap
fseek(pfile, t_bsp_lump[LUMPS_LIGHTMAPS].i_offset, SEEK_SET);
//inicializuj lightmapy
LightMap = new LPDIRECT3DTEXTURE9[m_iNumOfLightmaps];
// Go through all of the lightmaps and read them in
// Projdi vÜechny lightmapy
for(i = 0; i < m_iNumOfLightmaps; i++)
{
// Read in the RGB data for each lightmap
// NaΦti RGB data vÜech lightmap
fread(&pt_bsp_lightmaps[i], 1, sizeof(TBspLightmap), pfile);
// Create a texture map for each lightmap that is read in. The lightmaps
// are always 128 by 128.
// Vytvo° lightmap texturu kterß mß velikost v₧dy 128x128
sprintf(cBuf," Vytvaram LightMapu ID: %d",i);
LogPrint(cBuf);
LightMap[i] = NULL;
if (FAILED(D3DXCreateTexture(g_pd3dDevice,128,128,0,0,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,&LightMap[i])))
{
LogPrint(" chyba");
}
else
{
LogPrint(" OK");
}
//skopiruj do lightmapy
D3DSURFACE_DESC pDesc;
D3DLOCKED_RECT d3dlr;
LightMap[i]->GetLevelDesc(0, &pDesc );
LogPrint(" Otvaram lightmapu");
LightMap[i]->LockRect( 0, &d3dlr, 0, 0 );
DWORD *pDst = (DWORD *)d3dlr.pBits;
for (int x=0;x<128;x++)
{
for (int y=0;y<128;y++)
{
//gamma
float f_scale = 1.0f; // M∞°φtko nastav na 1
float f_temp = 0.0f; // Odkßdacφ zßsobnφk nastav na 0
float f_r = 0, f_g = 0, f_b = 0; // BarevnΘ kanßly nastav na 0
f_r = (float) pt_bsp_lightmaps[i].pppby_image_bits[y][x][0];
f_g = (float) pt_bsp_lightmaps[i].pppby_image_bits[y][x][1];
f_b = (float) pt_bsp_lightmaps[i].pppby_image_bits[y][x][2];
f_r = f_r * Gamma / 255.0f;
f_g = f_g * Gamma / 255.0f;
f_b = f_b * Gamma / 255.0f;
if(f_r > 1.0f && (f_temp = (1.0f / f_r)) < f_scale) f_scale = f_temp;
if(f_g > 1.0f && (f_temp = (1.0f / f_g)) < f_scale) f_scale = f_temp;
if(f_b > 1.0f && (f_temp = (1.0f / f_b)) < f_scale) f_scale = f_temp;
f_scale *= 255.0f;
f_r *= f_scale;
f_g *= f_scale;
f_b *= f_scale;
pt_bsp_lightmaps[i].pppby_image_bits[y][x][0] = (BYTE) f_r;
pt_bsp_lightmaps[i].pppby_image_bits[y][x][1] = (BYTE) f_g;
pt_bsp_lightmaps[i].pppby_image_bits[y][x][2] = (BYTE) f_b;
pDst[y*128+x] = (255 << 24 | pt_bsp_lightmaps[i].pppby_image_bits[y][x][0] << 16 |
pt_bsp_lightmaps[i].pppby_image_bits[y][x][1] << 8 |
pt_bsp_lightmaps[i].pppby_image_bits[y][x][2] );
}
}
LogPrint(" Zatvaram lightmapu");
LightMap[i]->UnlockRect (0);
}
// Delete the image bits because we are already done with them
// Vyma₧ vÜechny lightmap hodnoty z pam∞ti
delete [] pt_bsp_lightmaps;
// Store the number of nodes and allocate the memory to hold them
// NaΦti poΦet uzl∙ a alokuj pro n∞ pam∞¥
m_iNumOfNodes = t_bsp_lump[LUMPS_NODES].i_length / sizeof(TBspNode);
m_ptBspNode = new TBspNode [m_iNumOfNodes];
// Seek to the position in the file that hold the nodes and store them in m_ptBspNode
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty uzl∙ a tyto hodnoty naΦti
fseek(pfile, t_bsp_lump[LUMPS_NODES].i_offset, SEEK_SET);
fread(m_ptBspNode, m_iNumOfNodes, sizeof(TBspNode), pfile);
// Store the number of leafs and allocate the memory to hold them
// NaΦti poΦet list∙ a alokuj pro n∞ pam∞¥
m_iNumOfLeafs = t_bsp_lump[LUMPS_LEAFS].i_length / sizeof(TBspLeaf);
m_ptBspLeaf = new TBspLeaf [m_iNumOfLeafs];
// Seek to the position in the file that holds the leafs and store them in m_ptBspLeaf
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty list∙ a tyto hodnoty naΦti
fseek(pfile, t_bsp_lump[LUMPS_LEAFS].i_offset, SEEK_SET);
fread(m_ptBspLeaf, m_iNumOfLeafs, sizeof(TBspLeaf), pfile);
// Now we need to go through and convert all the leaf bounding boxes
// to the normal OpenGL Y up axis.
// Projdi vÜechny listy a proho∩ hodnoty Y na Z vÜech obßlek list∙.
// OpenGL mß toti₧ Y a Z hodnoty prohozeny oproti
// ostatnφm grafick²m program∙m (nap°. 3dsMax)
for(i = 0; i < m_iNumOfLeafs; i++)
{
// Swap the min y and z values, then negate the new Z
// Proho∩ minimßlnφ hodnoty obßlky Y na Z.
// U Z hodnoty nastav opaΦnΘ znamΘnko
float f_temp = (float) m_ptBspLeaf[i].pi_min_box[1];
m_ptBspLeaf[i].pi_min_box[1] = (int) m_ptBspLeaf[i].pi_min_box[2];
m_ptBspLeaf[i].pi_min_box[2] = (int)-f_temp;
// Swap the max y and z values, then negate the new Z
// Proho∩ maximßlnφ hodnoty obßlky Y na Z.
// U Z hodnoty nastav opaΦnΘ znamΘnko
f_temp = (float) m_ptBspLeaf[i].pi_max_box[1];
m_ptBspLeaf[i].pi_max_box[1] = (int)m_ptBspLeaf[i].pi_max_box[2];
m_ptBspLeaf[i].pi_max_box[2] = (int)-f_temp;
}
// Store the number of leaf faces and allocate the memory for them
// NaΦti poΦet ploÜek list∙ a alokuj pro n∞ pam∞¥
m_iNumOfLeafFaces = t_bsp_lump[LUMPS_LEAF_FACES].i_length / sizeof(int);
m_piLeafFaces = new int [m_iNumOfLeafFaces];
// Seek to the leaf faces lump, then read it's data
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty ploÜky lis∙ a tyto hodnoty naΦti
fseek(pfile, t_bsp_lump[LUMPS_LEAF_FACES].i_offset, SEEK_SET);
fread(m_piLeafFaces, m_iNumOfLeafFaces, sizeof(int), pfile);
// Store the number of planes, then allocate memory to hold them
// NaΦti poΦet d∞licφch ploch a alokuj pro n∞ pam∞¥
m_iNumOfPlanes = t_bsp_lump[LUMPS_PLANES].i_length / sizeof(TBspPlane);
m_ptBspPlane = new TBspPlane [m_iNumOfPlanes];
// Seek to the planes lump in the file, then read them into m_ptBspPlane
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty d∞licφch ploch a tyto hodnoty naΦti
fseek(pfile, t_bsp_lump[LUMPS_PLANES].i_offset, SEEK_SET);
fread(m_ptBspPlane, m_iNumOfPlanes, sizeof(TBspPlane), pfile);
// Go through every plane and convert it's normal to the Y-axis being up
// Projdi vÜechny d∞licφ plochy a proho∩ hodnoty Y na Z vÜech obßlek list∙.
// U Z hodnoty proho∩ znamΘnko
for(i = 0; i < m_iNumOfPlanes; i++)
{
float f_temp = m_ptBspPlane[i].pf_normal[1];
m_ptBspPlane[i].pf_normal[1] = m_ptBspPlane[i].pf_normal[2];
m_ptBspPlane[i].pf_normal[2] = -f_temp;
}
// Seek to the position in the file that holds the visibility lump
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty bitov²ch informacφ viditelnosti a tyto hodnoty naΦti
fseek(pfile, t_bsp_lump[LUMPS_VIS_DATA].i_offset, SEEK_SET);
// Check if there is any visibility information first
// Pokud existuje n∞jakß bitovß informace viditelnosti
if(t_bsp_lump[LUMPS_VIS_DATA].i_length)
{
// Read in the number of vectors and each vector's size
// NaΦti poΦet klastr∙ a jejich bytovou(1byte = 8bit∙) velikosti
fread(&(m_tBspVisData.i_num_of_clusters), 1, sizeof(int), pfile);
fread(&(m_tBspVisData.i_bytes_per_cluster), 1, sizeof(int), pfile);
// Allocate the memory for the cluster bitsets
// Alokuj pam∞¥ pro bitovΘ hodnoty klastr∙
int i_size = m_tBspVisData.i_num_of_clusters * m_tBspVisData.i_bytes_per_cluster;
m_tBspVisData.pby_cluster_bitsets = new byte [i_size];
// Read in the all the visibility bitsets for each cluster
// NaΦti vÜechny bitovΘ hodnoty klastr∙ pro detekci viditelnosti
fread(m_tBspVisData.pby_cluster_bitsets, 1, sizeof(byte) * i_size, pfile);
}
// Otherwise, we don't have any visibility data (prevents a crash)
else // Pokud neexistujφ ₧ßdnΘ bitovΘ informace viditelnosti, tak
m_tBspVisData.pby_cluster_bitsets = NULL; // Nastav bitovΘ hodnoty klastr∙ na NULL
// NaΦti poΦet koliznφch srß₧ek v listu a alokuj pro n∞ pam∞¥
m_iNumOfLeafBrushes = t_bsp_lump[LUMPS_LEAF_BRUSHES].i_length / sizeof(int);
m_piLeafBrushes = new int[m_iNumOfLeafBrushes];
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty koliznφch srß₧ek v listu
fseek(pfile, t_bsp_lump[LUMPS_LEAF_BRUSHES].i_offset, SEEK_SET);
fread(m_piLeafBrushes, m_iNumOfLeafBrushes, sizeof(int), pfile);
// NaΦti poΦet koliznφch srß₧ek a alokuj pro n∞ pam∞¥
m_iNumOfBrushes = t_bsp_lump[LUMPS_BRUSHES].i_length / sizeof(TBspBrush);
m_ptBspBrush = new TBspBrush[m_iNumOfBrushes];
sprintf(cBuf," Kolizne zrazky: %d",m_iNumOfLeafBrushes);
LogPrint(cBuf);
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty koliznφch srß₧ek
fseek(pfile, t_bsp_lump[LUMPS_BRUSHES].i_offset, SEEK_SET);
fread(m_ptBspBrush, m_iNumOfBrushes, sizeof(TBspBrush), pfile);
// NaΦti poΦet koliznφch stran srß₧ek a alokuj pro n∞ pam∞¥
m_iNumOfBrushSides = t_bsp_lump[LUMPS_BRUSH_SIDES].i_length / sizeof(TBspBrushSides);
m_ptBspBrushSides = new TBspBrushSides[m_iNumOfBrushSides];
sprintf(cBuf," Kolizne strany: %d",m_iNumOfBrushSides);
LogPrint(cBuf);
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty koliznφch stran srß₧ek
fseek(pfile, t_bsp_lump[LUMPS_BRUSH_SIDES].i_offset, SEEK_SET);
fread(m_ptBspBrushSides, m_iNumOfBrushSides, sizeof(TBspBrushSides), pfile);
// NaΦti poΦet efekt∙ a alokuj pro n∞ pam∞¥
m_iNumOfShaders = t_bsp_lump[LUMPS_SHADERS].i_length / sizeof(TBspShader);
m_ptBspShader = new TBspShader[m_iNumOfShaders];
sprintf(cBuf," Pocet efektov: %d",m_iNumOfShaders);
LogPrint(cBuf);
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty koliznφch stran srß₧ek
fseek(pfile, t_bsp_lump[LUMPS_SHADERS].i_offset, SEEK_SET);
fread(m_ptBspShader, m_iNumOfShaders, sizeof(TBspShader), pfile);
// NaΦti indexy braÜφ efekt∙.
// Index nßm bude slou₧it pro zamezenφ kolize
// kamery s efektem. Kolize nap°. s mlhou je nesmysl, ₧e.
m_piShaderBrushIndex = new int[m_iNumOfShaders]; // Alokuj pot°ebnou pam∞¥ pro index
for(i=0; i<m_iNumOfShaders; i++)
{
m_piShaderBrushIndex[i] = m_ptBspShader[i].i_brush_index; // NaΦti index
}
// NaΦti poΦet model∙ a alokuj pro n∞ pam∞¥
m_iNumOfModels = t_bsp_lump[LUMPS_MODELS].i_length / sizeof(TBspModel);
m_ptBspModel = new TBspModel[m_iNumOfModels];
sprintf(cBuf," Pocet modelov: %d",m_iNumOfModels);
LogPrint(cBuf);
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty koliznφch stran srß₧ek
fseek(pfile, t_bsp_lump[LUMPS_MODELS].i_offset, SEEK_SET);
fread(m_ptBspModel, m_iNumOfModels, sizeof(TBspModel), pfile);
// NaΦti indexy braÜφ efekt∙.
// Index nßm bude slou₧it pro zamezenφ kolize
// kamery s modelem
m_piModelBrushIndex = new int[m_iNumOfModels]; // Alokuj pot°ebnou pam∞¥ pro index
for(i=0; i<m_iNumOfModels; i++)
{
m_piModelBrushIndex[i] = m_ptBspModel[i].i_brush_index; // NaΦti index
}
// Store the number of mesh vertices and allocate the memory for them
// NaΦti poΦet vrchol∙ meÜφ a alokuj pro n∞ pam∞¥
m_iNumOfMeshVertices = t_bsp_lump[LUMPS_MESH_VERTS].i_length / sizeof(int);
m_piMeshVertices = new int [m_iNumOfMeshVertices];
sprintf(cBuf," Pocet mesh vertex: %d",m_iNumOfMeshVertices);
LogPrint(cBuf);
// Seek to the mesh vertices lump, then read it's data
// Najdi podle poΦtu byt∙ (t_bsp_lump[]) od 0 pozice (SEEK_SET(zaΦßtek souboru)) v BSP souboru
// ulo₧enΘ hodnoty vrchol∙ meÜφ a tyto hodnoty naΦti
fseek(pfile, t_bsp_lump[LUMPS_MESH_VERTS].i_offset, SEEK_SET);
fread(m_piMeshVertices, m_iNumOfMeshVertices, sizeof(int), pfile);
// Close the file
// Zav°i soubor
fclose(pfile);
//Fill Vertex Buffer
//Napln Vertex Buffer
FillVertexBuffer();
// Here we allocate enough bits to store all the faces for our bitset
// Alokuj dostateΦnΘ mno₧stvφ bit∙ pro vÜechny ploÜky, bitovΘ nastavenφ klastr∙
m_BitsetFacesDrawn.Resize(m_iNumOfFaces);
// Return a success
// Pokud jsi doÜel a₧ sem, tak vra¥ funkci true
return true;
}
//------------------------------------------------------------------
// Name: RenderFace()
// Desc: Render jedneho Facu
//------------------------------------------------------------------
void QBSP::RenderFace(int i_face_index)
{
TBspFace *p_bsp_face = &m_ptBspFace[i_face_index];
g_pd3dDevice->SetTexture( 0, Texture[p_bsp_face->i_texture_id] );
//ak je pouzita lightmapa
if(p_bsp_face->i_lightmap_id >= 0)
g_pd3dDevice->SetTexture( 1, LightMap[p_bsp_face->i_lightmap_id] );
//nastav texture stage pre LightMapping
g_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pd3dDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX,1);
g_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE );
g_pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
//ak je stena
if(p_bsp_face->i_type == 1)
{
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEXQBSP));
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEXQBSP);
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, p_bsp_face->i_start_vert_index
, p_bsp_face->i_num_of_verts-2);
}
g_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
if(p_bsp_face->i_type == 3)
{
//vytvori pole vertexov
CUSTOMVERTEXQBSP *MeshVertex = NULL;
MeshVertex = new CUSTOMVERTEXQBSP[p_bsp_face->i_num_mesh_verts];
for(int i=0; i<p_bsp_face->i_num_mesh_verts; i++) // Proje∩ vÜechny vrcholy meÜφ
{
// Zφskej index aktußlnφho vrcholu
int i_vert_index = m_piMeshVertices[p_bsp_face->i_mesh_vert_index + i];
// Nastav texturovΘ koordinace
MeshVertex[i].pos.x = m_ptBspVertex[p_bsp_face->i_start_vert_index + i_vert_index].pf_position[0];
MeshVertex[i].pos.y = m_ptBspVertex[p_bsp_face->i_start_vert_index + i_vert_index].pf_position[1];
MeshVertex[i].pos.z = m_ptBspVertex[p_bsp_face->i_start_vert_index + i_vert_index].pf_position[2];
MeshVertex[i].color = 0xffffffff;
MeshVertex[i].tu = m_ptBspVertex[p_bsp_face->i_start_vert_index + i_vert_index].pf_texture_coord[0];
MeshVertex[i].tv = m_ptBspVertex[p_bsp_face->i_start_vert_index + i_vert_index].pf_texture_coord[1];
}
//Vykresli Pole
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEXQBSP );
g_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST,p_bsp_face->i_num_mesh_verts/3,(BYTE**)&MeshVertex[0], sizeof(CUSTOMVERTEXQBSP));
if (MeshVertex != NULL)
delete MeshVertex;
}
}
//------------------------------------------------------------------
// Name:
// Desc:
//------------------------------------------------------------------
void QBSP::RenderBSP()
{
//vypni svetla
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,false );
// Reset our bitset so all the slots are zero.
// VyΦisti pam∞¥ ve kterΘ jsou ulo₧ena bitovß data vykreslen²ch ploÜek
m_BitsetFacesDrawn.ClearAll();
// Grab the leaf index that our camera is in
// Zφskej index listu, ve kterΘm se nachßzφ kamera
int i_leaf_index = FindLeaf(Camera.Pos);
// Grab the cluster that is assigned to the leaf
// Zφskej podle indexu klastr listu, ve kterΘm se nachßzφ kamera
int i_camera_in_cluster = m_ptBspLeaf[i_leaf_index].i_cluster;
// Initialize our counter variables (start at the last leaf and work down)
int i = m_iNumOfLeafs; // PoΦet list∙ p°edej hodnot∞ i
m_iVisibleFaces = 0; // Vyma₧ vyditelnΘ ploÜky
// Since we are using frustum culling to only draw the visible BSP leafs,
// we need to calculate the frustum every frame. This needs to happen
// right after we position our camera. Now the frustum planes can be defined.
// Zφskej hodnoty zornΘho pole kamery z projekΦnφ a modelovΘ matice scΘny.
// Podle hodnot zornΘho pole pak budeme urΦovat, kterΘ BSP listy jsou viditelnΘ
// a kterΘ ne. Tento v²poΦet musφme provßd∞t v ka₧dΘm cyklu p°ekreslovßnφ scΘny.
//m_Frustum.CalculateFrustum();
// Go through all the leafs and check their visibility
// Projdφ vÜechny listy a zjisti jejich viditelnost
while(i--)
{
// Get the current leaf that is to be tested for visibility from our camera's leaf
// Zφskej aktußlnφ list, kter² budeme pou₧φvat k detekci viditelnosti
TBspLeaf *p_bsp_leaf = &(m_ptBspLeaf[i]);
//
//PVS
//
// If the current leaf can't be seen from our cluster, go to the next leaf
// Jestli₧e aktußlnφ klastr listu neni viditeln² z klastru, ve kterΘm je kamera, tak
if(!IsClusterVisible(i_camera_in_cluster, p_bsp_leaf->i_cluster))
continue; // Se vra¥ na zaΦßtek cyklu na dalÜφ list
//
//FRUSTRUM CULLING
//
// If the current leaf is not in the camera's frustum, go to the next leaf
// Jestli₧e aktußlnφ list nenφ v zornΘm ·hlu kamery, tak
if(!Camera.FrustrumBox(Get3D((float)p_bsp_leaf->pi_min_box[0], (float)p_bsp_leaf->pi_min_box[1], (float)p_bsp_leaf->pi_min_box[2]),
Get3D((float)p_bsp_leaf->pi_max_box[0], (float)p_bsp_leaf->pi_max_box[1], (float)p_bsp_leaf->pi_max_box[2])))
continue; // Se vra¥ na zaΦßtek cyklu na dalÜφ list
// If we get here, the leaf we are testing must be visible in our camera's view.
// Get the number of faces that this leaf is in charge of.
// Zφskej poΦet ploÜek v listu
int i_num_of_leaf_faces = p_bsp_leaf->i_num_of_leaf_faces;
// Loop through and render all of the faces in this leaf
// Projdi vÜechny ploÜky listu
while(i_num_of_leaf_faces--)
{
// Grab the current face index from our leaf faces array
// Zφskej index ploÜky
int i_face_index = m_piLeafFaces[p_bsp_leaf->i_leaf_face + i_num_of_leaf_faces];
// Since many faces are duplicated in other leafs, we need to
// make sure this face already hasn't been drawn.
// Jestli₧e ploÜka, kterß mß b²t vykreslena, nebyla ji₧ vykreslena, tak
if(!m_BitsetFacesDrawn.On(i_face_index))
{
// Increase the rendered face count to display for fun
// P°idej 1 k poΦtu viditeln²ch ploÜek
m_iVisibleFaces++;
// Set this face as drawn and render it
// Nastav, ploÜku jako vykreslenou
m_BitsetFacesDrawn.Set(i_face_index);
// Vykresli ploÜku podle hodnoty indexu
RenderFace(i_face_index);
}
}
}
}
//------------------------------------------------------------------
// Name: FillVertexBuffer
// Desc: vytvori a nalpni vertex buffer
//------------------------------------------------------------------
void QBSP::FillVertexBuffer()
{
LogPrint(" Vytvaram Vertex Buffer");
//vytvaranie vertex buffera
if (FAILED(g_pd3dDevice->CreateVertexBuffer(m_iNumOfVerts*sizeof(CUSTOMVERTEXQBSP),
D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEXQBSP,
D3DPOOL_DEFAULT, &g_pVB, NULL )))
{
LogPrint(" chyba");
}
else
{
LogPrint(" OK");
}
//naplnanie VB
//Vertex do ktoreho sa uklada
CUSTOMVERTEXQBSP *Vertex;
//Otvor VB
LogPrint(" Otvaram Vertex Buffer");
g_pVB->Lock(0, 0, (void**)&Vertex, 0 ) ;
//zobrazi model do pola vertexov
for (int i = 0;i<m_iNumOfVerts;i++)
{
Vertex[i].pos.x = m_ptBspVertex[i].pf_position[0];
Vertex[i].pos.y = m_ptBspVertex[i].pf_position[1];
Vertex[i].pos.z = m_ptBspVertex[i].pf_position[2];
Vertex[i].tu = m_ptBspVertex[i].pf_texture_coord[0];
Vertex[i].tv = m_ptBspVertex[i].pf_texture_coord[1];
Vertex[i].tu2 = m_ptBspVertex[i].pf_lightmap_coord[0];
Vertex[i].tv2 = m_ptBspVertex[i].pf_lightmap_coord[1];
Vertex[i].color = D3DXCOLOR(255,255,255,255);
}
//zatvorVB
LogPrint(" Zatvaram Vertex Buffer");
g_pVB->Unlock();
}
//------------------------------------------------------------------
// Name: FindLeaf()
// Desc: Vrßti ID listu v ktorom sa nachßdza kamera
//------------------------------------------------------------------
int QBSP::FindLeaf(VECTOR3D CamPos)
{
int i = 0; // Nßvratovß hodnota indexu listu
float f_distance = 0.0f; // Vzdßlenost od plochy, kdy dochßzφ k detekci
// Continue looping until we find a negative index
// Cykluj, dokud nebude nßvratovß hodnota indexu listu zßpornß
while(i >= 0)
{
// Get the current node, then find the slitter plane from that
// node's plane index. Notice that we use a constant reference
// to store the plane and node so we get some optimization.
// Zφskej aktußlnφ uzek a d∞licφ plochu s indexem tohoto uzlu.
const TBspNode& node = m_ptBspNode[i]; // Zφskej uzel
const TBspPlane& plane = m_ptBspPlane[node.i_plane]; // Zφskej d∞licφ plochu tohoto uzlu
// Use the Plane Equation (Ax + By + Cz + D = 0) to find if the
// camera is in front of or behind the current splitter plane.
// Pou₧ij obecnou rovnici roviny (Ax + By + Cz + D = 0) pro v²poΦet,
// zda je kamera p°ed, nebo za d∞licφ plochou.
f_distance = plane.pf_normal[0] * CamPos.X +
plane.pf_normal[1] * CamPos.Y +
plane.pf_normal[2] * CamPos.Z - plane.f_distance;
// If the camera is in front of the plane
// Pokud je v²sledek rovnice v∞tÜφ nebo rovno 0,
// tak je kamera p°ed d∞licφ rovinou, je tedy v p°ednφm listu
if(f_distance >= 0)
{
// Assign the current node to the node in front of itself
// Ulo₧ p°ednφ hodnotu uzlu do indexu listu
i = node.i_front;
}
// Else if the camera is behind the plane
// Pokud je v²sledek rovnice menÜφ ne₧ 0,
// tak je kamera za d∞licφ rovinou, je tedy v zadnφm listu
else
{
// Assign the current node to the node behind itself
// Ulo₧ zadnφ hodnotu uzlu do indexu listu
i = node.i_back;
}
}
return ~i; //vrßti i
}
//------------------------------------------------------------------
// Name: IsClusterVisible()
// Desc: Zisti ci je Cluster viditelny z daneho clustra
//------------------------------------------------------------------
int QBSP::IsClusterVisible(int i_camera_in_cluster, int i_test_cluster)
{
// Make sure we have valid memory and that the current cluster is > 0.
// If we don't have any memory or a negative cluster, return a visibility (1).
// Ujisti se jestli jsou klastrovß data v pam∞¥i a ₧e klastr ve kterΘm je kamera je > 0
// Jestli₧e neexistujφ klastrovß data, nebo klastr ve kterΘm je kamera je < 0,
// tak vra¥ funkci 1. Tφm tento klastr oznaΦφme jako viditeln².
// Pokud by se oznaΦil jako neviditeln², mohlo by se stßt, ₧e by
// ve scΘn∞ mohly vzniknout dφry.
if(!m_tBspVisData.pby_cluster_bitsets || i_camera_in_cluster < 0) return 1;
// Use binary math to get the 8 bit visibility set for the current cluster
// Pou₧ij binßrnφ operaci pro zφskßnφ 8 bitovΘ informace o viditelnosti klastru ve kterΘm je kamera
// Bitovß operace (test >> 3) posune bity v "test" o 3 pozice doprava,
// Φφm₧ provede to samΘ (avÜak rychleji), jako (test / 8)
byte by_vis_set = m_tBspVisData.pby_cluster_bitsets[(i_camera_in_cluster * m_tBspVisData.i_bytes_per_cluster) + (i_test_cluster >> 3)];
// Now that we have our vector (bitset), do some bit shifting to find if
// the "test" cluster is visible from the "current" cluster, according to the bitset.
// Porovnej pomocφ bitovΘho souΦinu "&" bitovΘ hodnoty klastru ve kterΘm je kamera a testovanΘho klastru.
// Bitov² souΦin "&" nßm vracφ 1, pokud jsou ob∞ hodnoty stejnΘ, a 0 pokud jsou rozdφlnΘ
// Bitov² posun doleva "1 <<" vynßsobφ jedniΦkou v²slednou hodnotu bitovΘho souΦinu ((test) & 7))
// Pokud bude hodnota nap°. 1, vynßsobφ se (1 * 2), pokud bude hodnota nap°. 4, vynßsobφ (1 * 16) atd..
int result = by_vis_set & (1 << ((i_test_cluster) & 7));
// Return the result ( either 1 (visible) or 0 (not visible) )
// Vra¥ funkci v²sledek bitov²ch operacφ (v²sledek 1 = viditeln² klastr, v²sledek 0 = neviditeln² klastr)
return ( result );
}
//------------------------------------------------------------------
// Name: CheckBrushCollision()
// Desc: Zisti koliziu s listom
//------------------------------------------------------------------
bool QBSP::CheckBrushCollision(int i_leaf_index)
{
TBspLeaf *pt_bsp_leaf = &(m_ptBspLeaf[i_leaf_index]); // Zφskej hodnoty aktußlnφho listu
int i_num_leaf_brushes = pt_bsp_leaf->i_num_of_leaf_brushes; // Zφskej poΦet kolizφ
// Jestli₧e list obsahuje kolize
if(i_num_leaf_brushes)
{
return true;
}
else // Pokud nedochßzφ k detekci kolize
{
return false;
}
}
//------------------------------------------------------------------
// Name: ColliseBSP()
// Desc: Zisti koliziu
//------------------------------------------------------------------
bool QBSP::ColliseBSP(VECTOR3D Point)
{
int i_ray_leaf_index = FindLeaf(Point);
if(CheckBrushCollision(i_ray_leaf_index))
{
return true;
}
else
{
return false;
}
}