home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2006 July & August
/
PCWorld_2006-07-08_cd.bin
/
temacd
/
planearcade
/
planearcade.exe
/
Tank3.bmp
/
octree.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2004-10-15
|
39KB
|
1,714 lines
#include "main.h"
//------------------------------------------------------------------
// Name: OCTREE()
// Desc: konstruktor
//------------------------------------------------------------------
OCTREE::OCTREE()
{
g_pVB = NULL;
Group = NULL;
Face = NULL;
Node = NULL;
FileScn = NULL;
FileGeo = NULL;
FileOct = NULL;
}
//------------------------------------------------------------------
// Name: CleanUp()
// Desc: Odstrani
//------------------------------------------------------------------
void OCTREE::CleanUp()
{
//
//vertex buffer
//
if (g_pVB != NULL)
g_pVB->Release();
g_pVB = NULL;
//
//skupina
//
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;
//
//Octree
//
if (Node != NULL)
delete [] Node;
//
//kolizia
//
IntPos = Get3D(0,0,0);
IntNormal = Get3D(0,0,0);
ColliseStatus = false;
}
//------------------------------------------------------------------
// Name: InitializeGroup()
// Desc: inicializuje textury group
//------------------------------------------------------------------
void OCTREE::InitializeGroupTextures(int Index)
{
int NumTextures = Group[Index].NumTextures;
Group[Index].g_pTexture = new LPDIRECT3DTEXTURE9[NumTextures];
for (int i=0;i<NumTextures;i++)
{
Group[Index].g_pTexture[i] = NULL;
}
}
//------------------------------------------------------------------
// Name: ClearGroup()
// Desc: Odtrani z pamati textury group
//------------------------------------------------------------------
void OCTREE::ClearGroupTextures(int Index)
{
if(Group[Index].g_pTexture != NULL)
{
for (int i=0;i<Group[Index].NumTextures;i++)
{
if (Group[Index].g_pTexture[i] != NULL)
Group[Index].g_pTexture[i]->Release();
Group[Index].g_pTexture[i] = NULL;
}
}
delete [] Group[Index].g_pTexture;
Group[Index].g_pTexture = NULL;
}
//------------------------------------------------------------------
// Name: Load()
// Desc: nahra scenu zo suboru GEO
//------------------------------------------------------------------
void OCTREE::Load(char *FileName)
{
char cBuf[80];
int i;
//Log
LogPrint("Vytvaram OCTree");
sprintf(cBuf," Subor: %s",FileName);
LogPrint(cBuf);
///////////////
//otvor subor//
///////////////
FileGeo = fopen(FileName,"r");
if (FileGeo == NULL)
LogPrint(" Subor sa nepodarilo otvrit");
///////////////
//hlavicka //
///////////////
fscanf(FileGeo,"%s %d",cBuf,&MinNodeSize);
fscanf(FileGeo,"%s %d",cBuf,&NumGroups);
fscanf(FileGeo,"%s %d",cBuf,&NumFaces);
sprintf(cBuf," MinPolygonsInNode: %d",MinNodeSize);
LogPrint(cBuf);
sprintf(cBuf," NumGroups: %d",NumGroups);
LogPrint(cBuf);
sprintf(cBuf," NumFaces: %d",NumFaces);
LogPrint(cBuf);
///////////////
//group //
///////////////
Group = new OCTGROUP[NumGroups];
for (i=0;i<NumGroups;i++)
{
ReadGroup();
}
///////////////
//faces //
///////////////
Face = new OCTFACE[NumFaces];
for (i=0;i<NumFaces;i++)
{
ReadFace();
}
/////////////////
//Vertex Buffer//
/////////////////
CreateVertexBuffer();
/////////////////
//SmoothShading//
/////////////////
for (i=0;i<NumGroups;i++)
{
if (Group[i].SmoothShading == 1)
{
CalcSmoothShading(i);
}
}
///////////
//OCTree //
///////////
//CreateOctTree();
//SaveOctTree("scene/terrain.oct");
//LoadOctTree("scene/terrain.oct");
////////////////
//zatvor subor//
////////////////
fclose(FileGeo);
}
//------------------------------------------------------------------
// Name: ReadGroup()
// Desc: Precita a nahraje group
//------------------------------------------------------------------
void OCTREE::ReadGroup()
{
char cBuf[80];
char TexFileName[80];
int Index;
int TexIndex;
fscanf(FileGeo,"%s",cBuf);
fscanf(FileGeo,"%s %d",cBuf,&Index);
fscanf(FileGeo,"%s %d",cBuf,&Group[Index].NumTextures);
fscanf(FileGeo,"%s %f",cBuf,&Group[Index].TextureTime);
//log
sprintf(cBuf," Material %d",Index);
LogPrint(cBuf);
//default vlastnosti
Group[Index].ActTexture = 0;
Group[Index].ActTime = 0.0f;
//inicializacia pola textur
InitializeGroupTextures(Index);
///////////////////
//Nahraje textury//
///////////////////
for (int i=0;i<Group[Index].NumTextures;i++)
{
fscanf(FileGeo,"%s %d %s",cBuf,&TexIndex,TexFileName);
sprintf(cBuf," Textura %s",TexFileName);
LogPrint(cBuf);
//load hlavnej terrain textury
if (Index == 0 && (i == 0 || i == 2))
{
if (SceneDetail == 0 && i==0)
strcpy(TexFileName,"scene/texturepole512.jpg");
if (SceneDetail == 0 && i==2)
strcpy(TexFileName,"scene/texturepust512.jpg");
if (SceneDetail == 1 && i==0)
strcpy(TexFileName,"scene/texturepole1024.jpg");
if (SceneDetail == 1 && i==2)
strcpy(TexFileName,"scene/texturepust1024.jpg");
if (FAILED(D3DXCreateTextureFromFileEx(g_pd3dDevice,
TexFileName,
0,
0,
0, //MipLevels
0,
D3DFMT_R5G6B5,
Engine.TextureCreatingFlag,
D3DX_DEFAULT, //Filter
D3DX_DEFAULT, //MipFilter
0, //Disable ColorKey
NULL,
NULL,
&Group[Index].g_pTexture[i])))
{
sprintf(cBuf," chyba pri vytvarani textury: %s",TexFileName);
LogPrint(cBuf);
}
}
//load ostatnych textur
else
{
if (FAILED(D3DXCreateTextureFromFileEx(g_pd3dDevice,
TexFileName,
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[i])))
{
sprintf(cBuf," chyba pri vytvarani textury: %s",TexFileName);
LogPrint(cBuf);
}
}
}
//nacitaj dalsie vlastnosti
fscanf(FileGeo,"%s %d",cBuf,&Group[Index].BlendType );
fscanf(FileGeo,"%s %d",cBuf,&Group[Index].GroupType );
fscanf(FileGeo,"%s %d",cBuf,&Group[Index].MaterialType );
fscanf(FileGeo,"%s %d",cBuf,&Group[Index].CollisionType );
fscanf(FileGeo,"%s %d",cBuf,&Group[Index].Specular );
fscanf(FileGeo,"%s %d",cBuf,&Group[Index].SmoothShading );
}
//------------------------------------------------------------------
// Name: ReadFace()
// Desc: Precita a nahraje face
//------------------------------------------------------------------
void OCTREE::ReadFace()
{
char cBuf[80];
int Index;
int GroupIndex;
float X,Y,Z,U,V;
fscanf(FileGeo,"%s",cBuf);
//nacitaj hlavicku
fscanf(FileGeo,"%s %d",cBuf,&Index);
fscanf(FileGeo,"%s %d",cBuf,&GroupIndex);
//nacitaj body
for(int i=2;i>-1;i--)
{
fscanf(FileGeo,"%f %f %f %f %f",&X,&Y,&Z,&U,&V);
Face[Index].P[i] = Get3D(X,Y,Z);
Face[Index].T1[i].X = U;
Face[Index].T1[i].Y = V;
}
//plane
Face[Index].Plane = CreatePlaneFace(Face[Index].P[0],
Face[Index].P[1],
Face[Index].P[2]);
//normaly
Face[Index].N[0] = Face[Index].Plane.Normal ;
Face[Index].N[1] = Face[Index].Plane.Normal ;
Face[Index].N[2] = Face[Index].Plane.Normal ;
//texcoord2
Face[Index].T2[0].X = Face[Index].P[0].X / 500.0f;
Face[Index].T2[0].Y = Face[Index].P[0].Z / 500.0f;
Face[Index].T2[1].X = Face[Index].P[1].X / 500.0f;
Face[Index].T2[1].Y = Face[Index].P[1].Z / 500.0f;
Face[Index].T2[2].X = Face[Index].P[2].X / 500.0f;
Face[Index].T2[2].Y = Face[Index].P[2].Z / 500.0f;
//vlastnosti
Face[Index].Group = GroupIndex;
Face[Index].Index = Index;
}
//------------------------------------------------------------------
// Name: CreateVertexBuffer()
// Desc: Vytvori Vertex Buffer
//------------------------------------------------------------------
void OCTREE::CreateVertexBuffer()
{
if (FAILED(g_pd3dDevice->CreateVertexBuffer(NumFaces*3*sizeof(CUSTOMVERTEXOCT),
D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC, D3DFVF_CUSTOMVERTEXOCT,
D3DPOOL_DEFAULT, &g_pVB, NULL )))
{
LogPrint(" Chyba pri vytvarani VB");
}
else
{
LogPrint(" Vertex Buffer vytvoreny");
}
}
//------------------------------------------------------------------
// Name: FillVertexBuffer()
// Desc: Naplni VB a ulozi hodnoty do Group
//------------------------------------------------------------------
void OCTREE::FillVertexBuffer()
{
//pomocne premenne
int ActVertex = 0;
int NumF = 0;
int i,u,j;
//reset pocitadla
NumVisibleFaces = 0;
//Vertex do ktoreho sa uklada
CUSTOMVERTEXOCT *Vertex;
//Otvor VB
g_pVB->Lock(0, 0, (void**)&Vertex, D3DLOCK_DISCARD|D3DLOCK_NOOVERWRITE) ;
/////////
//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].normal = D3DXVECTOR3(Face[u].N[j].X,
Face[u].N[j].Y,
Face[u].N[j].Z);
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;
//
// DebugDrawLine(Face[u].P[j],Get3D(Face[u].P[j].X+(2.0f*Face[u].N[j].X),
// Face[u].P[j].Y+(2.0f*Face[u].N[j].Y),
// Face[u].P[j].Z+(2.0f*Face[u].N[j].Z)));
ActVertex++;
}
NumF++;
}
}
}
Group[i].NumVisibleFaces = NumF;
}
//zatvor VB
g_pVB->Unlock();
}
//------------------------------------------------------------------
// Name: Render()
// Desc: Vyrenderuje celu scenu
//------------------------------------------------------------------
void OCTREE::Render()
{
int i;
///////////////
//Optimalize //
///////////////
Optimalize();
//vynuluje world maticu
D3DXMATRIXA16 NullMatrix;
D3DXMatrixIdentity(&NullMatrix);
g_pd3dDevice->SetTransform( D3DTS_WORLD, &NullMatrix);
//naplni Vertex Buffer
FillVertexBuffer();
//oznaci Vertex Buffer
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEXOCT));
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEXOCT);
///////////////
//Render //
///////////////
//priesvitne materialy nakoniec
//0
for (i = 0;i<NumGroups;i++)
{
Engine.SetLighting(false);
if (Group[i].GroupType == 2 && SceneDetail == 2)
Engine.SetMipMapping(0,false);
if (Group[i].BlendType == 0)
RenderGroup(i);
Engine.SetMipMapping(0,true);
}
//1
for (i = 0;i<NumGroups;i++)
{
Engine.SetAlphaTest(true);
Engine.SetLighting(false);
Engine.SetFilter(0,D3DTEXF_POINT);
if (Group[i].BlendType == 1)
RenderGroup(i);
Engine.SetFilter(0,D3DTEXF_LINEAR);
}
//2
for (i = 0;i<NumGroups;i++)
{
if (Group[i].BlendType == 2)
RenderGroup(i);
}
//zresetuj blending
Engine.SetBlendNone();
//debug
//RenderDebugNode(Node);
//reset to default
Engine.ResetToDefault();
}
//------------------------------------------------------------------
// Name: RenderGroup()
// Desc: Vyrenderuje skupinu
//------------------------------------------------------------------
void OCTREE::RenderGroup(int Index)
{
//nastavi material
SetMaterial(Group[Index].MaterialType );
//nastavi blending
SetBlendMode(Group[Index].BlendType);
//zapni specular ak je povoleny
if (Group[Index].Specular == 0)
Engine.SetSpecular(false);
else
Engine.SetSpecular(true);
//ak je iba pre krajinu pole nerenderuj
if (Group[Index].CollisionType == 1 && Mode == 1)
return;
//
//NORMAL TEXTURA
//
if(Group[Index].GroupType == 0)
{
g_pd3dDevice->SetTexture( 0, Group[Index].g_pTexture[0]);
}
//
//ANIMOVANA TEXTURA
//
if(Group[Index].GroupType == 1)
{
//vyber textury
Group[Index].ActTime += PowerTime(1.0f);
if (Group[Index].ActTime > Group[Index].TextureTime)
{
Group[Index].ActTexture++;
Group[Index].ActTime = 0.0f;
if (Group[Index].ActTexture == Group[Index].NumTextures)
Group[Index].ActTexture = 0;
}
int ActTexture = Group[Index].ActTexture;
g_pd3dDevice->SetTexture( 0, Group[Index].g_pTexture[ActTexture]);
}
//
//MULTITEXTURING
//
if(Group[Index].GroupType == 2)
{
//vyber indexu textury
int T1,T2;
if (Mode == 0) { T1 = 0; T2 = 1; }
if (Mode == 1) { T1 = 2; T2 = 3; }
//1 stage
g_pd3dDevice->SetTexture( 0, Group[Index].g_pTexture[T1]);
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);
//2 stage
g_pd3dDevice->SetTexture( 1, Group[Index].g_pTexture[T2]);
g_pd3dDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX,1);
g_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADDSIGNED);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
}
//
//ENVIROMENT MAPPING
//
if(Group[Index].GroupType == 3)
{
g_pd3dDevice->SetTexture( 0, Group[Index].g_pTexture[0]);
for (int i=0;i<NumFaces;i++)
{
if (Face[i].Group != Index)
continue;
for (int u=0;u<3;u++)
{
Face[i].T1[u] = EnvironmentMapping(Face[i].P[u],
Face[i].N[u],300.0f,matView);
}
}
}
//
//EMBOSS BUMB MAPPING
//
if(Group[Index].GroupType == 4)
{
g_pd3dDevice->SetTexture( 0, Group[Index].g_pTexture[0] );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
g_pd3dDevice->SetTexture( 1, Group[Index].g_pTexture[0] );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_ADDSIGNED );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
Engine.SetBlendCustom(D3DBLEND_SRCALPHA,D3DBLEND_ZERO);
for (int i=0;i<NumFaces;i++)
{
if (Face[i].Group != Index)
continue;
for (int u=0;u<3;u++)
{
Face[i].T2[u] = BumpMapping(Face[i].N[u],Face[i].T1[u],0.030f,matView);
}
}
}
//render
if (Group[Index].NumVisibleFaces > 0)
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, Group[Index].StartVertex , Group[Index].NumVisibleFaces );
//reset
Engine.ResetToDefault();
}
//------------------------------------------------------------------
// Name: SetMaterial()
// Desc: Nastavi material podla typu
//------------------------------------------------------------------
void OCTREE::SetMaterial(int MaterialType)
{
D3DMATERIAL9 Material;
ZeroMemory( &Material, sizeof(D3DMATERIAL9) );
switch (MaterialType)
{
case 0:
Material = GetMaterial(GetColor(0.2f,0.2f,0.2f,0.2f),
GetColor(1.0f,1.0f,1.0f,1.0f),
GetColor(0.0f,0.0f,0.0f,0.0f),
GetColor(0.0f,0.0f,0.0f,0.0f),0.0f);
break;
case 1:
Material = GetMaterial(GetColor(0.3f,0.3f,0.3f,0.3f),
GetColor(1.0f,1.0f,0.0f,0.0f),
GetColor(1.0f,1.0f,1.0f,1.0f),
GetColor(0.2f,0.2f,0.2f,0.2f),5.0f);
break;
case 2:
break;
}
//nastavi material
g_pd3dDevice->SetMaterial(&Material);
}
//------------------------------------------------------------------
// Name: SetBlendMode()
// Desc: nastavi priesvitnos¥ podla typu
//------------------------------------------------------------------
void OCTREE::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: CalcSmoothShading()
// Desc: Vypocita smooth shading pre urcitu skupinu
//------------------------------------------------------------------
void OCTREE::CalcSmoothShading(int Index)
{
VECTOR3D *Normal = NULL;
Normal = new VECTOR3D[NumFaces];
for (int i=0;i<NumFaces;i=i+1)
{
if (Face[i].Group == Index)
{
for (int u=0;u<3;u=u+1)
{
//bod
VECTOR3D B = Face[i].P[u];
VECTOR3D NormalVys = Get3D(0.0f,0.0f,0.0f);
int ActNormal = 0;
//ziskaj normaly
for (int j=0;j<NumFaces;j=j+1)
{
if (Face[i].Group == Index)
{
for (int k=0;k<3;k=k+1)
{
if((B.X == Face[j].P[k].X) &&
(B.Y == Face[j].P[k].Y) &&
(B.Z == Face[j].P[k].Z) )
{
Normal[ActNormal] = Face[j].Plane.Normal ;
ActNormal++;
}
}
}
}
//vypocitaj normalu
for (int a=0;a<ActNormal;a++)
{
Add(&NormalVys,NormalVys,Normal[a]);
}
//normalizuj vyslednu normalu
Normalize(&NormalVys);
//zapis nove normaly
for (j=0;j<NumFaces;j=j+1)
{
if (Face[i].Group == Index)
{
for (int k=0;k<3;k=k+1)
{
if((B.X == Face[j].P[k].X) &&
(B.Y == Face[j].P[k].Y) &&
(B.Z == Face[j].P[k].Z) )
{
Face[j].N[k] = NormalVys;
}
}
}
}
}
}
}
if (Normal != NULL)
delete [] Normal;
Normal = NULL;
}
//------------------------------------------------------------------
// Name: CreateOctTree()
// Desc: vytvori Octree strom
//------------------------------------------------------------------
void OCTREE::CreateOctTree()
{
int i,u;
//log
LogPrint(" Vytvaram strom");
//vytvori NODE
Node = new OCTNODE;
///////////
//MIN MAX//
///////////
VECTOR3D Min = Get3D(10000.0f,10000.0f,10000.0f);
VECTOR3D Max = Get3D(-10000.0f,-10000.0f,-10000.0f);
float a,b,c;
for ( i=0;i<NumFaces;i++)
{
for ( u=0;u<3;u++)
{
if (Face[i].P[u].X < Min.X)
Min.X = Face[i].P[u].X;
if (Face[i].P[u].Y < Min.Y)
Min.Y = Face[i].P[u].Y;
if (Face[i].P[u].Z < Min.Z)
Min.Z = Face[i].P[u].Z;
if (Face[i].P[u].X > Max.X)
Max.X = Face[i].P[u].X;
if (Face[i].P[u].Y > Max.Y)
Max.Y = Face[i].P[u].Y;
if (Face[i].P[u].Z > Max.Z)
Max.Z = Face[i].P[u].Z;
}
}
Node->Centre.X = (Min.X + Max.X) / 2.0f;
Node->Centre.Y = (Min.Y + Max.Y) / 2.0f;
Node->Centre.Z = (Min.Z + Max.Z) / 2.0f;
//upravi na kocku
a = Max.X - Node->Centre.X ;
b = Max.Y - Node->Centre.Y ;
c = Max.Z - Node->Centre.Z ;
if (a >= b && a >= c)
{
Add(&Node->Max,Node->Centre,Get3D(a,a,a));
Add(&Node->Min,Node->Centre,Get3D(-a,-a,-a));
}
if (b >= a && b >= c)
{
Add(&Node->Max,Node->Centre,Get3D(b,b,b));
Add(&Node->Min,Node->Centre,Get3D(-b,-b,-b));
}
if (c >= b && c >= a)
{
Add(&Node->Max,Node->Centre,Get3D(c,c,c));
Add(&Node->Min,Node->Centre,Get3D(-c,-c,-c));
}
Node->Polomer = CalcDistance(Node->Centre,Node->Min);
//reset info
NumEndNodes = 0;
//vytvori octree
CreateNode(Node);
}
//------------------------------------------------------------------
// Name: CreateNode()
// Desc: Funkcia sa vola rekrizivne - vytvara nody
//------------------------------------------------------------------
void OCTREE::CreateNode(OCTNODE *N)
{
int i;
//vypocita stred
N->Centre.X = (N->Min.X + N->Max.X) / 2.0f;
N->Centre.Y = (N->Min.Y + N->Max.Y) / 2.0f;
N->Centre.Z = (N->Min.Z + N->Max.Z) / 2.0f;
//vypocita polomer
N->Polomer = CalcDistance(N->Centre,N->Min);
//zresetuje vlastnosti
N->NumFaces = 0;
//zisti face ktore lezia v node
int *Index = NULL;
Index = new int[NumFaces];
for (i=0;i<NumFaces;i++)
{
if (ColliseNodeFace(N,Face[i]) == true)
{
Index[N->NumFaces] = i;
N->NumFaces++;
}
}
//skopiruje a vytvori pole
N->FaceList = new int [N->NumFaces];
for (i=0;i<N->NumFaces;i++)
{
N->FaceList[i] = Index[i];
}
//vymaze pomocne pole
if (Index != NULL)
delete [] Index;
//zisti ci ma pokracovat vo vytvarani dalsej nody
if(((N->Centre.X - N->Min.X) < MinNodeSize) || (N->NumFaces == 0 ))
{
N->EndNode = true;
if (N->NumFaces>0)
NumEndNodes++;
return ;
}
//vymaze pole nody pretoze nieje konecna
if (N->FaceList != NULL)
delete [] N->FaceList;
///////////////////////
//vytvori dalsie nody//
///////////////////////
N->EndNode = false;
N->Node[0] = new OCTNODE;
N->Node[1] = new OCTNODE;
N->Node[2] = new OCTNODE;
N->Node[3] = new OCTNODE;
N->Node[4] = new OCTNODE;
N->Node[5] = new OCTNODE;
N->Node[6] = new OCTNODE;
N->Node[7] = new OCTNODE;
///
///Dole
///
//0
N->Node[0]->Min.X = N->Min.X;
N->Node[0]->Min.Y = N->Min.Y;
N->Node[0]->Min.Z = N->Centre.Z;
N->Node[0]->Max.X = N->Centre.X;
N->Node[0]->Max.Y = N->Centre.Y;
N->Node[0]->Max.Z = N->Max.Z;
CreateNode(N->Node[0]);
//1
N->Node[1]->Min.X = N->Centre.X;
N->Node[1]->Min.Y = N->Min.Y;
N->Node[1]->Min.Z = N->Centre.Z;
N->Node[1]->Max.X = N->Max.X;
N->Node[1]->Max.Y = N->Centre.Y;
N->Node[1]->Max.Z = N->Max.Z;
CreateNode(N->Node[1]);
//2
N->Node[2]->Min.X = N->Min.X;
N->Node[2]->Min.Y = N->Min.Y;
N->Node[2]->Min.Z = N->Min.Z;
N->Node[2]->Max.X = N->Centre.X;
N->Node[2]->Max.Y = N->Centre.Y;
N->Node[2]->Max.Z = N->Centre.Z;
CreateNode(N->Node[2]);
//3
N->Node[3]->Min.X = N->Centre.X;
N->Node[3]->Min.Y = N->Min.Y;
N->Node[3]->Min.Z = N->Min.Z;
N->Node[3]->Max.X = N->Max.X;
N->Node[3]->Max.Y = N->Centre.Y;
N->Node[3]->Max.Z = N->Centre.Z;
CreateNode(N->Node[3]);
///
///Hore
///
//4
N->Node[4]->Min.X = N->Min.X;
N->Node[4]->Min.Y = N->Centre.Y;
N->Node[4]->Min.Z = N->Centre.Z;
N->Node[4]->Max.X = N->Centre.X;
N->Node[4]->Max.Y = N->Max.Y;
N->Node[4]->Max.Z = N->Max.Z;
CreateNode(N->Node[4]);
//5
N->Node[5]->Min.X = N->Centre.X;
N->Node[5]->Min.Y = N->Centre.Y;
N->Node[5]->Min.Z = N->Centre.Z;
N->Node[5]->Max.X = N->Max.X;
N->Node[5]->Max.Y = N->Max.Y;
N->Node[5]->Max.Z = N->Max.Z;
CreateNode(N->Node[5]);
//6
N->Node[6]->Min.X = N->Min.X;
N->Node[6]->Min.Y = N->Centre.Y;
N->Node[6]->Min.Z = N->Min.Z;
N->Node[6]->Max.X = N->Centre.X;
N->Node[6]->Max.Y = N->Max.Y;
N->Node[6]->Max.Z = N->Centre.Z;
CreateNode(N->Node[6]);
//7
N->Node[7]->Min.X = N->Centre.X;
N->Node[7]->Min.Y = N->Centre.Y;
N->Node[7]->Min.Z = N->Min.Z;
N->Node[7]->Max.X = N->Max.X;
N->Node[7]->Max.Y = N->Max.Y;
N->Node[7]->Max.Z = N->Centre.Z;
CreateNode(N->Node[7]);
}
//------------------------------------------------------------------
// Name: ColliseNodeLine()
// Desc: Zisti koliziu usecky a nody
//------------------------------------------------------------------
bool OCTREE::ColliseNodeLine(OCTNODE *N,VECTOR3D P1,VECTOR3D P2)
{
if (CollisionBoxEdge(P1,P2,N->Min,N->Max) == true)
return true;
else
return false;
}
//------------------------------------------------------------------
// Name: ColliseNodeFace()
// Desc: Zisti koliziu medzi Face a node - zisti ci sa face nachazda v node
//------------------------------------------------------------------
bool OCTREE::ColliseNodeFace(OCTNODE *N,OCTFACE F)
{
if (ColliseNodeLine(N,F.P[0],F.P[1]) == true)
return true;
if (ColliseNodeLine(N,F.P[1],F.P[2]) == true)
return true;
if (ColliseNodeLine(N,F.P[0],F.P[2]) == true)
return true;
return false;
}
//------------------------------------------------------------------
// Name: RenderDebugNode()
// Desc: graficky zobrazi octree
//------------------------------------------------------------------
void OCTREE::RenderDebugNode(OCTNODE *N)
{
if (N->EndNode == true)
{
//if (Camera.FrustrumSphere(N->Centre ,N->Polomer ) == false)
// return;
if (N->NumFaces > 0)
{
DebugDrawBox(N->Min,N->Max);
}
}
if (N->EndNode == false)
{
RenderDebugNode(N->Node[0]);
RenderDebugNode(N->Node[1]);
RenderDebugNode(N->Node[2]);
RenderDebugNode(N->Node[3]);
RenderDebugNode(N->Node[4]);
RenderDebugNode(N->Node[5]);
RenderDebugNode(N->Node[6]);
RenderDebugNode(N->Node[7]);
}
}
//------------------------------------------------------------------
// Name: Optimalize()
// Desc: Vyberie tie face ktore su vidie¥
//------------------------------------------------------------------
void OCTREE::Optimalize()
{
//oznaci vsetky face ako neviditelne
for (int i=0;i<NumFaces;i++)
{
Face[i].Visible = false;
}
//frustrum culling
FrustrumNode(Node);
//backface culing
BackFaceCulling();
}
//------------------------------------------------------------------
// Name: FrustumNode()
// Desc: Frustrum culling
//------------------------------------------------------------------
void OCTREE::FrustrumNode(OCTNODE *N)
{
//ako node neobsahuje ziadny face vyhod
if (N->NumFaces == 0)
return;
//ak nieje v dohlade
if (Camera.FrustrumSphere(N->Centre,N->Polomer) == false)
return;
//
if (N->EndNode == true)
{
// if (Camera.FrustrumSphere(N->Centre,N->Polomer) == false)
// return;
for (int i=0;i<N->NumFaces;i++)
{
Face[N->FaceList[i]].Visible = true;
}
}
else
{
FrustrumNode(N->Node[0]);
FrustrumNode(N->Node[1]);
FrustrumNode(N->Node[2]);
FrustrumNode(N->Node[3]);
FrustrumNode(N->Node[4]);
FrustrumNode(N->Node[5]);
FrustrumNode(N->Node[6]);
FrustrumNode(N->Node[7]);
}
}
//------------------------------------------------------------------
// Name: ColliseFace()
// Desc: Zisti koliziu s facom
//------------------------------------------------------------------
bool OCTREE::ColliseFace(OCTFACE F, VECTOR3D P1, VECTOR3D P2)
{
VECTOR3D Inter;
float U,U1,U2,U3;
if (CalcPriesEdge(&Inter,F.Plane,P1,P2) == true)
{
U1 = CalcAngleCentre(Inter,F.P[0],
F.P[1]);
U2 = CalcAngleCentre(Inter,F.P[1],
F.P[2]);
U3 = CalcAngleCentre(Inter,F.P[2],
F.P[0]);
U = U1+U2+U3;
if (U > 6.2f && U < 6.35f)
{
ColliseStatus = true;
IntPos = Inter;
IntNormal = F.Plane.Normal;
IntMaterialType = Group[F.Group ].MaterialType ;
IntBlendType = Group[F.Group ].BlendType ;
IntGroupType = Group[F.Group ].GroupType ;
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
//------------------------------------------------------------------
// Name: ColliseFaceDistance()
// Desc: Zisti koliziu s facom vyberie najblizsi priesecnik
//------------------------------------------------------------------
bool OCTREE::ColliseFaceDistance(OCTFACE F, VECTOR3D P1, VECTOR3D P2)
{
VECTOR3D Inter;
float U,U1,U2,U3;
if (CalcPriesEdge(&Inter,F.Plane,P1,P2) == true)
{
U1 = CalcAngleCentre(Inter,F.P[0],
F.P[1]);
U2 = CalcAngleCentre(Inter,F.P[1],
F.P[2]);
U3 = CalcAngleCentre(Inter,F.P[2],
F.P[0]);
U = U1+U2+U3;
if (U > 6.2f && U < 6.35f)
{
if (ColliseStatus ==false)
{
ColliseStatus = true;
IntPos = Inter;
IntNormal = F.Plane.Normal;
IntMaterialType = Group[F.Group ].MaterialType ;
IntBlendType = Group[F.Group ].BlendType ;
IntGroupType = Group[F.Group ].GroupType ;
}
else
{
float Dis1 = CalcDistance(P1,Inter);
float Dis2 = CalcDistance(P1,IntPos);
if(Dis1 < Dis2)
{
IntPos = Inter;
IntNormal = F.Plane.Normal;
IntMaterialType = Group[F.Group ].MaterialType ;
IntBlendType = Group[F.Group ].BlendType ;
IntGroupType = Group[F.Group ].GroupType ;
}
}
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
//------------------------------------------------------------------
// Name: ColliseNode()
// Desc: rekruziva na koliziu
//------------------------------------------------------------------
void OCTREE::ColliseNode(OCTNODE *N, VECTOR3D P1, VECTOR3D P2)
{
int GroupIndex;
int FaceIndex;
//
//ak uz je kolizia dalej koliziu neprevadzat
//
if (ColliseStatus == true)
return;
//
//ak luc prechadzat nodov
//
if (ColliseNodeLine(N,P1,P2) == true)
{
//ak to je konecna noda
if (N->EndNode == true)
{
for (int i=0;i<N->NumFaces;i++)
{
//zisti indexi
FaceIndex = N->FaceList[i];
GroupIndex = Face[FaceIndex].Group ;
//ak je zapnuta kolizia skupiny
if (!(Group[GroupIndex].CollisionType == 1 && Mode == 1))
{
if (ColliseFace(Face[FaceIndex],P1,P2) == true)
break;
}
}
}
//
//inak otestuj vsetky podnody
//
else
{
ColliseNode(N->Node[0],P1,P2);
ColliseNode(N->Node[1],P1,P2);
ColliseNode(N->Node[2],P1,P2);
ColliseNode(N->Node[3],P1,P2);
ColliseNode(N->Node[4],P1,P2);
ColliseNode(N->Node[5],P1,P2);
ColliseNode(N->Node[6],P1,P2);
ColliseNode(N->Node[7],P1,P2);
}
}
}
//------------------------------------------------------------------
// Name: ColliseNodeDistance()
// Desc: otestuje vsetky polygony a vybere najblizsi priesecnik k bodu P1
//------------------------------------------------------------------
void OCTREE::ColliseNodeDistance(OCTNODE *N, VECTOR3D P1, VECTOR3D P2)
{
int GroupIndex;
int FaceIndex;
//
//ak luc prechadzat nodov
//
if (ColliseNodeLine(N,P1,P2) == true)
{
//ak to je konecna noda
if (N->EndNode == true)
{
for (int i=0;i<N->NumFaces;i++)
{
//zisti indexi
FaceIndex = N->FaceList[i];
GroupIndex = Face[FaceIndex].Group ;
//ak je zapnuta kolizia skupiny
if (!(Group[GroupIndex].CollisionType == 1 && Mode == 1))
{
ColliseFaceDistance(Face[FaceIndex],P1,P2);
}
}
}
//
//inak otestuj vsetky podnody
//
else
{
ColliseNodeDistance(N->Node[0],P1,P2);
ColliseNodeDistance(N->Node[1],P1,P2);
ColliseNodeDistance(N->Node[2],P1,P2);
ColliseNodeDistance(N->Node[3],P1,P2);
ColliseNodeDistance(N->Node[4],P1,P2);
ColliseNodeDistance(N->Node[5],P1,P2);
ColliseNodeDistance(N->Node[6],P1,P2);
ColliseNodeDistance(N->Node[7],P1,P2);
}
}
}
//------------------------------------------------------------------
// Name: Collise()
// Desc: funkcia testuje koliziu s terenom
//------------------------------------------------------------------
bool OCTREE::Collise(VECTOR3D P1,VECTOR3D P2)
{
//zresetuje
ColliseStatus = false;
ColliseNode(Node,P1,P2);
return ColliseStatus;
}
//------------------------------------------------------------------
// Name: ColliseDistance()
// Desc: funkcia testuje koliziu s terenom vyberie najblizsi priesecnik
//------------------------------------------------------------------
bool OCTREE::ColliseDistance(VECTOR3D P1,VECTOR3D P2)
{
//zresetuje
ColliseStatus = false;
ColliseNodeDistance(Node,P1,P2);
return ColliseStatus;
}
//------------------------------------------------------------------
// Name: SaveScene()
// Desc: ulozi optimalizovanu scenu
//------------------------------------------------------------------
void OCTREE::SaveScene(char *FileName)
{
//otvori suber pre bynarny zapis
FileScn = fopen(FileName,"wb");
//zapise pocet facov
int NumF = NumFaces;
fwrite(&NumF,sizeof(int),1,FileScn);
//zapise faces
fwrite(Face,sizeof(OCTFACE),NumF,FileScn);
//zatvor subor
fclose(FileScn);
}
//------------------------------------------------------------------
// Name: LoadScene()
// Desc: Otvori optimalizovanu scenu
//------------------------------------------------------------------
void OCTREE::LoadScene(char *FileNameGeo,char *FileNameScn)
{
char cBuf[80];
int i;
int NumF;
//Log
LogPrint("Vytvaram OCTree");
sprintf(cBuf," Subor Geo: %s",FileNameGeo);
LogPrint(cBuf);
sprintf(cBuf," Subor Scn: %s",FileNameScn);
LogPrint(cBuf);
///////////////////
//otvor subor GEO//
///////////////////
FileGeo = fopen(FileNameGeo,"r");
if (FileGeo == NULL)
LogPrint(" Subor GEO sa nepodarilo otvorit");
///////////////////
//otvor subor SCN//
///////////////////
FileScn = fopen(FileNameScn,"rb");
if (FileScn == NULL)
LogPrint(" Subor SCN sa nepodarilo otvorit");
///////////////
//hlavicka //
///////////////
fscanf(FileGeo,"%s %d",cBuf,&MinNodeSize);
fscanf(FileGeo,"%s %d",cBuf,&NumGroups);
fscanf(FileGeo,"%s %d",cBuf,&NumFaces);
sprintf(cBuf," MinPolygonsInNode: %d",MinNodeSize);
LogPrint(cBuf);
sprintf(cBuf," NumGroups: %d",NumGroups);
LogPrint(cBuf);
sprintf(cBuf," NumFaces: %d",NumFaces);
LogPrint(cBuf);
///////////////
//group //
///////////////
Group = new OCTGROUP[NumGroups];
for (i=0;i<NumGroups;i++)
{
ReadGroup();
}
///////////////
//faces //
///////////////
Face = new OCTFACE[NumFaces];
fread(&NumF,sizeof(int),1,FileScn);
for(i = 0;i<NumF;i++)
fread(&Face[i],sizeof(OCTFACE),1,FileScn);
/////////////////
//Vertex Buffer//
/////////////////
CreateVertexBuffer();
////////////////
//zatvor subor//
////////////////
fclose(FileGeo);
fclose(FileScn);
///////////
//OCTree //
///////////
//CreateOctTree();
}
//------------------------------------------------------------------
// Name: BackFaceCulling()
// Desc: odstrani zadnΘ hrany
//------------------------------------------------------------------
void OCTREE::BackFaceCulling()
{
for (int i=0;i<NumFaces;i++)
{
if (Face[i].Visible == true)
{
if (PointPlane(Face[i].Plane,Camera.Pos) > 0.0f)
Face[i].Visible = false;
}
}
}
//------------------------------------------------------------------
// Name: SetTexture()
// Desc: nastavi externu texturu do skupiny
//------------------------------------------------------------------
void OCTREE::SetTexture(int ToGroup,int ToFrame,LPDIRECT3DTEXTURE9 Tex)
{
Group[ToGroup].g_pTexture[ToFrame] = Tex;
}
//------------------------------------------------------------------
// Name: LoadOctTree()
// Desc: nacita octree storm
//------------------------------------------------------------------
void OCTREE::LoadOctTree(char *FileName)
{
//subor
FileOct = fopen(FileName,"rb");
//zachytavanie chyb
if (FileOct == NULL)
{
char cBuf[80];
sprintf(cBuf,"Nemozem najst subor %s",FileName);
}
//loadne strom
Node = new OCTNODE;
LoadNode(Node);
//zatvor
fclose(FileOct);
FileOct = NULL;
}
//------------------------------------------------------------------
// Name: SaveOctTree()
// Desc: ulozi octree stom
//------------------------------------------------------------------
void OCTREE::SaveOctTree(char *FileName)
{
//subor
FileOct = fopen(FileName,"wb");
//ulozi strom
SaveNode(Node);
//zatvor
fclose(FileOct);
FileOct = NULL;
}
//------------------------------------------------------------------
// Name: SaveNone()
// Desc: ulozi nodu octtree
//------------------------------------------------------------------
void OCTREE::SaveNode(OCTNODE *N)
{
OCTRNODE RNode;
//rnode
RNode.Centre = N->Centre;
RNode.EndNode = N->EndNode ;
RNode.Max = N->Max;
RNode.Min = N->Min;
RNode.NumFaces = N->NumFaces;
RNode.Polomer = N->Polomer;
//zapis - node
fwrite(&RNode,sizeof(OCTRNODE),1,FileOct);
//zapis - facelist ak je konecna
if (RNode.EndNode == true)
fwrite(N->FaceList,sizeof(int),RNode.NumFaces,FileOct);
//ak je konecna node tak vyhod
if (RNode.EndNode == true)
return;
//inak uloz sub nody
SaveNode(N->Node[0]);
SaveNode(N->Node[1]);
SaveNode(N->Node[2]);
SaveNode(N->Node[3]);
SaveNode(N->Node[4]);
SaveNode(N->Node[5]);
SaveNode(N->Node[6]);
SaveNode(N->Node[7]);
}
//------------------------------------------------------------------
// Name: LoadNone()
// Desc: nacita nodu octree
//------------------------------------------------------------------
void OCTREE::LoadNode(OCTNODE *N)
{
OCTRNODE RNode;
//precita - node
fread(&RNode,sizeof(OCTRNODE),1,FileOct);
//precita - facelist ak je konecna
if (RNode.EndNode == true)
{
N->FaceList = new int[RNode.NumFaces];
fread(N->FaceList,sizeof(int),RNode.NumFaces,FileOct);
}
//rnode
N->Centre = RNode.Centre;
N->EndNode = RNode.EndNode ;
N->Max = RNode.Max;
N->Min = RNode.Min;
N->NumFaces = RNode.NumFaces;
N->Polomer = RNode.Polomer;
//ak je konecna node tak vyhod
if (RNode.EndNode == true)
return;
//vytvor sub nody
N->Node[0] = new OCTNODE;
N->Node[1] = new OCTNODE;
N->Node[2] = new OCTNODE;
N->Node[3] = new OCTNODE;
N->Node[4] = new OCTNODE;
N->Node[5] = new OCTNODE;
N->Node[6] = new OCTNODE;
N->Node[7] = new OCTNODE;
//uloz sub nody
LoadNode(N->Node[0]);
LoadNode(N->Node[1]);
LoadNode(N->Node[2]);
LoadNode(N->Node[3]);
LoadNode(N->Node[4]);
LoadNode(N->Node[5]);
LoadNode(N->Node[6]);
LoadNode(N->Node[7]);
}