home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2006 July & August
/
PCWorld_2006-07-08_cd.bin
/
temacd
/
planearcade
/
planearcade.exe
/
Tank3.bmp
/
bsp.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2004-10-03
|
19KB
|
888 lines
#include "main.h"
//------------------------------------------------------------------
// Name: BSP()
// Desc: konstruktor
//------------------------------------------------------------------
BSP::BSP()
{
g_pVB = NULL;
Face = NULL;
Group = NULL;
Plane = NULL;
Node = NULL;
Leaf = NULL;
Light = NULL;
g_pLightMap = NULL;
FileBsp = NULL;
NumFaces = 0;
NumGroups = 0;
NumPlanes = 0;
NumNodes = 0;
NumLeafs = 0;
NumLights = 0;
NumLightMaps = 0;
}
//------------------------------------------------------------------
// Name: CleanUp()
// Desc: destruktor
//------------------------------------------------------------------
void BSP::CleanUp()
{
//
//vertex buffer
//
if (g_pVB != NULL)
g_pVB->Release();
g_pVB = NULL;
//
//group
//
if (Group != NULL)
{
//znic textury
for (int i=0;i<NumGroups;i++)
{
ClearGroupTextures(i);
}
delete [] Group;
}
Group = NULL;
//
//face
//
if (Face != NULL)
delete [] Face;
Face = NULL;
//
//plane
//
if (Plane != NULL)
delete [] Plane;
Plane = NULL;
//
//Node
//
if (Node != NULL)
delete [] Node;
Node = NULL;
//
//Leaf
//
if (Leaf != NULL)
delete [] Leaf;
Leaf = NULL;
//
//Lights
//
if (Light != NULL)
delete [] Light;
Light = NULL;
//
//LightMap
//
if (g_pLightMap != NULL)
{
for (int i=0;i<NumLightMaps;i++)
{
if (g_pLightMap[i] != NULL)
g_pLightMap[i]->Release();
g_pLightMap[i] = NULL;
}
delete [] g_pLightMap;
g_pLightMap = NULL;
}
}
//------------------------------------------------------------------
// Name: InitializeGroupTextures()
// Desc: Inicializuje textury skupiny
//------------------------------------------------------------------
void BSP::InitializeGroupTextures(int Index)
{
Group[Index].g_pTexture = NULL;
}
//------------------------------------------------------------------
// Name: ClearGroupTextures()
// Desc: zmaze textury skupiny
//------------------------------------------------------------------
void BSP::ClearGroupTextures(int Index)
{
if(Group[Index].g_pTexture != NULL)
Group[Index].g_pTexture->Release();
Group[Index].g_pTexture = NULL;
}
//------------------------------------------------------------------
// Name: Load()
// Desc: loadne BSP strom
//------------------------------------------------------------------
void BSP::Load(char *FileName)
{
char cBuf[80];
int i;
///////
//LOG//
///////
LogPrint("Loading BSP tree...");
sprintf(cBuf," File: %s",FileName);
LogPrint(cBuf);
////////
//FILE//
////////
FileBsp = fopen(FileName,"rb");
if (FileBsp == NULL)
{
sprintf(cBuf," Missing File: %s",FileName);
LogPrint(cBuf);
}
/////////
//Group//
/////////
fread(&NumGroups,sizeof(int),1,FileBsp);
sprintf(cBuf," NumGroups: %d",NumGroups);
LogPrint(cBuf);
Group = new BSPGROUP[NumGroups];
for (i=0;i<NumGroups;i++)
{
ReadGroup();
}
////////
//Face//
////////
fread(&NumFaces,sizeof(int),1,FileBsp);
sprintf(cBuf," NumFaces: %d",NumFaces);
LogPrint(cBuf);
Face = new BSPFACE[NumFaces];
for (i=0;i<NumFaces;i++)
{
ReadFace();
}
/////////
//Plane//
/////////
fread(&NumPlanes,sizeof(int),1,FileBsp);
sprintf(cBuf," NumPlanes: %d",NumPlanes);
LogPrint(cBuf);
Plane = new PLANE[NumPlanes];
for (i=0;i<NumPlanes;i++)
{
ReadPlane();
}
/////////
//Node //
/////////
fread(&NumNodes,sizeof(int),1,FileBsp);
sprintf(cBuf," NumNodes: %d",NumNodes);
LogPrint(cBuf);
Node = new BSPNODE[NumNodes];
for (i=0;i<NumNodes;i++)
{
ReadNode();
}
/////////
//Leaf //
/////////
fread(&NumLeafs,sizeof(int),1,FileBsp);
sprintf(cBuf," NumLeaf: %d",NumLeafs);
LogPrint(cBuf);
Leaf = new BSPLEAF[NumNodes];
for (i=0;i<NumLeafs;i++)
{
ReadLeaf();
}
/////////
//Light//
/////////
fread(&NumLights,sizeof(int),1,FileBsp);
sprintf(cBuf," NumLights: %d",NumLights);
LogPrint(cBuf);
Light = new BSPLIGHT[NumLights];
for (i=0;i<NumLights;i++)
{
ReadLight();
}
///////////
//LighMap//
///////////
fread(&NumLightMaps,sizeof(int),1,FileBsp);
sprintf(cBuf," NumLightMaps: %d",NumLightMaps);
LogPrint(cBuf);
g_pLightMap = new LPDIRECT3DTEXTURE9[NumLightMaps];
for (i=0;i<NumLightMaps;i++)
{
ReadLightMap();
}
////////////////
//VertexBuffer//
////////////////
CreateVertexBuffer();
fclose(FileBsp);
}
//------------------------------------------------------------------
// Name: ReadFace()
// Desc: precita face
//------------------------------------------------------------------
void BSP::ReadFace()
{
RBSPFACE F;
int Index;
fread(&F,sizeof(RBSPFACE),1,FileBsp);
Index = F.Index ;
Face[Index].Group = F.Group;
Face[Index].Plane = F.Plane;
for(int i=0;i<3;i++)
{
Face[Index].P[i] = F.P[i];
Face[Index].T1[i] = F.T1[i];
Face[Index].T2[i] = F.T2[i];
}
}
//------------------------------------------------------------------
// Name: ReadGroup()
// Desc: nacita skupinu
//------------------------------------------------------------------
void BSP::ReadGroup()
{
RBSPGROUP G;
char cBuf[80];
int Index;
fread(&G,sizeof(RBSPGROUP),1,FileBsp);
Index = G.Index ;
LogPrint(" Creating GROUP");
sprintf(cBuf," Texture: %s",G.Texture);
LogPrint(cBuf);
Group[Index].BlendType = G.BlendType;
Group[Index].CollisionType = G.CollisionType;
Group[Index].Type = G.Type ;
//loadne texturu
if (FAILED(D3DXCreateTextureFromFileEx(g_pd3dDevice,
G.Texture ,
D3DX_DEFAULT,
D3DX_DEFAULT,
Engine.MipMapLevels, //MipLevels
0,
Engine.TextureFormat,
Engine.TextureCreatingFlag,
D3DX_DEFAULT, //Filter
D3DX_DEFAULT, //MipFilter
0xffff00ff, //ColorKey
NULL,
NULL,
&Group[Index].g_pTexture)))
{
LogPrint(" FAILED");
}
}
//------------------------------------------------------------------
// Name: ReadPlane()
// Desc: nacita roviny
//------------------------------------------------------------------
void BSP::ReadPlane()
{
int Index;
RBSPPLANE P;
fread(&P,sizeof(RBSPPLANE),1,FileBsp);
Index = P.Index ;
Plane[Index].D = P.D;
Plane[Index].Normal = P.Normal;
}
//------------------------------------------------------------------
// Name: ReadLight()
// Desc: nacita svetlo
//------------------------------------------------------------------
void BSP::ReadLight()
{
int Index;
RBSPLIGHT L;
fread(&L,sizeof(RBSPLIGHT),1,FileBsp);
Index = L.Index ;
Light[Index].Color = L.Color;
Light[Index].Intensity = L.Intensity;
Light[Index].Pos = L.Pos;
Light[Index].Range = L.Range;
}
//------------------------------------------------------------------
// Name: ReadLight()
// Desc: nacita lightmapu
//------------------------------------------------------------------
void BSP::ReadLightMap()
{
int Index;
RBSPLIGHTMAP L;
fread(&L,sizeof(RBSPLIGHTMAP),1,FileBsp);
Index = L.Index;
//log
char cBuf[80];
sprintf(cBuf," Vytvaram LightMapu ID: %d",Index);
LogPrint(cBuf);
//vynuluje
g_pLightMap[Index] = NULL;
//vytvori lightmapu
if (FAILED(D3DXCreateTexture(g_pd3dDevice,
256,
256,0,0,
D3DFMT_A8R8G8B8,
Engine.TextureCreatingFlag,
&g_pLightMap[Index])))
{
LogPrint(" chyba");
}
else
{
LogPrint(" OK");
}
//skopiruj do lightmapy
D3DSURFACE_DESC pDesc;
D3DLOCKED_RECT d3dlr;
g_pLightMap[Index]->GetLevelDesc(0, &pDesc );
LogPrint(" Otvaram lightmapu");
g_pLightMap[Index]->LockRect( 0, &d3dlr, 0, 0 );
DWORD *pDst = (DWORD *)d3dlr.pBits;
for (int x=0;x<256;x++)
{
for (int y=0;y<256;y++)
{
pDst[x*256+y] = (255 << 24 | L.Texel[y][x][0] << 16 |
L.Texel[y][x][1] << 8 |
L.Texel[y][x][2] );
}
}
LogPrint(" Zatvaram lightmapu");
g_pLightMap[Index]->UnlockRect (0);
sprintf(cBuf,"media/light%d.bmp",Index);
D3DXSaveTextureToFile(cBuf,D3DXIFF_BMP,g_pLightMap[Index],NULL);
}
//------------------------------------------------------------------
// Name: CreateVertexBuffer()
// Desc: Vytvori Vertex Buffer
//------------------------------------------------------------------
void BSP::CreateVertexBuffer()
{
if (FAILED(g_pd3dDevice->CreateVertexBuffer(NumFaces*3*sizeof(CUSTOMVERTEXBSP),
D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEXBSP,
D3DPOOL_DEFAULT, &g_pVB, NULL )))
{
LogPrint(" VertexBuffer: FAILED");
}
else
{
LogPrint(" VertexBuffer: OK");
}
}
//------------------------------------------------------------------
// Name: FillVertexBuffer()
// Desc: naplni vertex buffer
//------------------------------------------------------------------
void BSP::FillVertexBuffer()
{
//pomocne premenne
int ActVertex = 0;
int NumF = 0;
int i,u,j;
//reset pocitadla
NumVisibleFaces = 0;
//Vertex do ktoreho sa uklada
CUSTOMVERTEXBSP *Vertex;
//Otvor VB
g_pVB->Lock(0, 0, (void**)&Vertex, 0 ) ;
/////////
//GROUP//
/////////
for (i=0;i<NumGroups;i++)
{
//nastavi pociatocnu hodnotu
Group[i].StartVertex = ActVertex;
NumF = 0;
for (u=0;u<NumFaces;u++)
{
if (Face[u].Visible == true)
{
if (Face[u].Group == i)
{
//pocitadlo
NumVisibleFaces++;
for (j=0;j<3;j++)
{
//prida vertex do VB
Vertex[ActVertex].pos = D3DXVECTOR3(Face[u].P[j].X,
Face[u].P[j].Y,
Face[u].P[j].Z);
Vertex[ActVertex].tu1 = Face[u].T1[j].X;
Vertex[ActVertex].tv1 = Face[u].T1[j].Y;
Vertex[ActVertex].tu2 = Face[u].T2[j].X;
Vertex[ActVertex].tv2 = Face[u].T2[j].Y;
Vertex[ActVertex].color = 0xffffffff;
ActVertex++;
}
NumF++;
}
}
}
Group[i].NumVisibleFaces = NumF;
}
//zatvor VB
g_pVB->Unlock();
}
//------------------------------------------------------------------
// Name: Render()
// Desc: vyrenderuje
//------------------------------------------------------------------
void BSP::Render()
{
int i;
//
//Optimalizacia
//
Optimalize();
//
//vynuluje world maticu
//
D3DXMATRIXA16 NullMatrix;
D3DXMatrixIdentity(&NullMatrix);
g_pd3dDevice->SetTransform( D3DTS_WORLD, &NullMatrix);
//
//Napσnie VB
//
FillVertexBuffer();
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEXBSP));
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEXBSP);
//
//redenruje podla materialov
//
//0
for (i = 0;i<NumGroups;i++)
{
if (Group[i].BlendType == 0)
RenderGroup(i);
}
//1
for (i = 0;i<NumGroups;i++)
{
if (Group[i].BlendType == 1)
RenderGroup(i);
}
//2
for (i = 0;i<NumGroups;i++)
{
if (Group[i].BlendType == 2)
RenderGroup(i);
}
//
//Render debug BSP NODES
//
/*
for (i=0;i<NumNodes;i++)
{
if (Node[i].Leaf == true)
DebugDrawBox(Node[i].Min,Node[i].Max);
}*/
//
//Render debug BSP LEAFS
/*
for (i=0;i<NumLeafs;i++)
{
DebugDrawBox(Leaf[i].Min,Leaf[i].Max);
}*/
//
//Reset
//
Engine.ResetToDefault();
}
//------------------------------------------------------------------
// Name: RenderGroup()
// Desc: Vybrederuje skupinu
//------------------------------------------------------------------
void BSP::RenderGroup(int Index)
{
//nastavi priesvitnos¥
SetBlendMode(Group[Index].BlendType);
//vyber textury
g_pd3dDevice->SetTexture( 0, Group[Index].g_pTexture);
//vyber LightMapy
g_pd3dDevice->SetTexture( 1, g_pLightMap[Index]);
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_ADDSIGNED );
g_pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
//render
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, Group[Index].StartVertex , Group[Index].NumVisibleFaces );
}
//------------------------------------------------------------------
// Name: OptimalizePVS()
// Desc: Vyberie viditelne faces
//------------------------------------------------------------------
void BSP::OptimalizePVS()
{
int i,u;
//oznaci vsetky ako neviditelne
for( i=0;i<NumFaces;i++)
Face[i].Visible = false;
//zisti v ktorom liste sa nachadza kamera
int LeafIndex = GetLeafIndex(Camera.Pos);
//ak je kamera v solid vyjdi z funckie
if (LeafIndex == -1)
return;
//kde sa nachadza kamera vsetko vidno
for(u=0;u<Leaf[LeafIndex].NumFaces ;u++)
Face[Leaf[LeafIndex].FaceList[u]].Visible = true;
//pre vsetky vidite╛ne leafy
///////
//PVS//
///////
for (i=0;i<Leaf[LeafIndex].NumVisibleLeafs;i++)
{
int LIndex = Leaf[LeafIndex].VisibleLeafs[i];
////////////////////
//Frustrum culling//
////////////////////
if (Camera.FrustrumSphere(Leaf[LIndex].Centre,Leaf[LIndex].Radius) == true)
{
for(u=0;u<Leaf[LIndex].NumFaces ;u++)
Face[Leaf[LIndex].FaceList[u]].Visible = true;
}
}
///////////////////
//backface culing//
///////////////////
for(i=0;i<NumFaces;i++)
{
if (Face[i].Visible == true)
{
if (PointPlane(Plane[Face[i].Plane ],Camera.Pos) < 0.0f)
Face[i].Visible = false;
}
}
}
//------------------------------------------------------------------
// Name: Optimalize()
// Desc: Vyberie viditelne faces
//------------------------------------------------------------------
void BSP::Optimalize()
{
int i,u;
//oznaci vsetky ako neviditelne
for( i=0;i<NumFaces;i++)
Face[i].Visible = false;
///////
for (i=0;i<NumLeafs;i++)
{
////////////////////
//Frustrum culling//
////////////////////
if (Camera.FrustrumSphere(Leaf[i].Centre,Leaf[i].Radius) == true)
{
for(u=0;u<Leaf[i].NumFaces ;u++)
Face[Leaf[i].FaceList[u]].Visible = true;
}
}
///////////////////
//backface culing//
///////////////////
for(i=0;i<NumFaces;i++)
{
if (Face[i].Visible == true)
{
if (PointPlane(Plane[Face[i].Plane ],Camera.Pos) < 0.0f)
Face[i].Visible = false;
}
}
}
//------------------------------------------------------------------
// Name: NoOptimalize()
// Desc: neoptimalizuje
//------------------------------------------------------------------
void BSP::NoOptimalize()
{
//oznaci vsetky ako neviditelne
for(int i=0;i<NumFaces;i++)
Face[i].Visible = true;
}
//------------------------------------------------------------------
// Name: SetBlendMode()
// Desc: Nastavi priesvitnos¥ podla Indexu
//------------------------------------------------------------------
void BSP::SetBlendMode(int BlendType)
{
switch (BlendType)
{
case 0: //bez priesvitnosti
Engine.SetBlendNone();
break;
case 1: //transparent
Engine.SetBlendTrans();
break;
case 2: //one
Engine.SetBlendOne();
break;
}
}
//------------------------------------------------------------------
// Name: ReadNode()
// Desc: precita nodu
//------------------------------------------------------------------
void BSP::ReadNode()
{
RBSPNODE N;
int Index;
fread(&N,sizeof(RBSPNODE),1,FileBsp);
Index = N.Index;
Node[Index].BackIndex = N.BackIndex ;
Node[Index].FrontIndex = N.FrontIndex ;
Node[Index].Leaf = N.Leaf ;
Node[Index].LeafIndex = N.LeafIndex ;
Node[Index].Solid = N.Solid;
Node[Index].Radius = N.Radius ;
Node[Index].Min = N.Min ;
Node[Index].Max = N.Max ;
Node[Index].Centre = N.Centre ;
Node[Index].Root = N.Root ;
}
//------------------------------------------------------------------
// Name: ReadLeaf()
// Desc: precita list
//------------------------------------------------------------------
void BSP::ReadLeaf()
{
RBSPLEAF L;
int Index;
//nacita leaf
fread(&L,sizeof(RBSPLEAF),1,FileBsp);
Index = L.Index;
Leaf[Index].FaceList = L.FaceList ;
Leaf[Index].NumFaces = L.NumFaces ;
Leaf[Index].VisibleLeafs = L.VisibleLeafs ;
Leaf[Index].NumVisibleLeafs = L.NumVisibleLeafs ;
Leaf[Index].Centre = L.Centre ;
Leaf[Index].Max = L.Max ;
Leaf[Index].Min = L.Min ;
Leaf[Index].Radius = L.Radius ;
//nacita face list leafu
Leaf[Index].FaceList = new int [Leaf[Index].NumFaces];
fread(&Leaf[Index].FaceList[0],sizeof(int),Leaf[Index].NumFaces,FileBsp);
//nacita PVS
Leaf[Index].VisibleLeafs = new int [Leaf[Index].NumVisibleLeafs ];
fread(&Leaf[Index].VisibleLeafs[0],sizeof(int),Leaf[Index].NumVisibleLeafs,FileBsp);
}
//------------------------------------------------------------------
// Name: GetLeafIndex()
// Desc: zisti v akom liste sa nachadza bod
//------------------------------------------------------------------
int BSP::GetLeafIndex(VECTOR3D P)
{
int NIndex = 0; //index nody
int PlaneIndex;
float D; //vzdialenos¥ od roviny
while(1==1)
{
PlaneIndex = Node[NIndex].Root;
//solid
if (Node[NIndex].Solid == true)
return -1;
//leaf
if (Node[NIndex].Leaf == true)
return Node[NIndex].LeafIndex ;
D = PointPlane(Plane[PlaneIndex],P);
//posle do front nody
if (D>0.0f)
{
NIndex = Node[NIndex].FrontIndex ;
continue;
}
//posle do back nody
if (D<0.0f)
{
NIndex = Node[NIndex].BackIndex ;
continue;
}
if (D == 0.0f)
break ;
}
return -1;
}
//------------------------------------------------------------------
// Name: SetTexture()
// Desc: nastavi texturu
//------------------------------------------------------------------
void BSP::SetTexture(int ToGroup,LPDIRECT3DTEXTURE9 Tex)
{
Group[ToGroup].g_pTexture = Tex;
}