rendered paste body//Filush :DDDDDDDDDDD//
//Prezentuje :PP //
//~~~~OCTREE !!~~~~~~//
unit octree;
interface
uses OpenGL, GL, glaux;
const
MAX_TRIANGLES_IN_NODE = 1024;
type
PVertex=^TVertex;
TVertex = Record
x,y,z: glFloat;
end;
PVertex3d=^TVertex3d;
TVertex3d=record
x,y,z: glDouble;
end;
PFullVertex=^TFullVertex;
TFullVertex = record
u,v: glFloat;
n,ver:TVertex;
end;
PPolygonPointer = ^TPolygonPointer;
TPolygonPointer = record
v:array[0..2] of PFullVertex;
end;
PPolygon = ^TPolygon;
TPolygon = record
v:array[0..2] of TFullVertex;
end;
PPolygonPointerArray = ^TPolygonPointerArray;
TPolygonPointerArray = array of TPolygonPointer;
PPolygonArray = ^TPolygonArray;
TPolygonArray = array of TPolygon;
//Poczatek Octree ;]
//Główny Węzeł
PNode = ^TNode;
TNode = object
polygons : array of TPolygonPointer;
pos : TVertex3d;
size : TVertex3d;
numPoly : integer;
numChildren : Byte;
polyID : glUint;
Mother : PNode;
children : array of PNode;
smallest : boolean;
Function HowManyPolygons : Integer;
procedure CreateVBO;
Procedure Divide;
Procedure DrawPolygons;
Procedure Check;
Procedure Draw;
Procedure Clear;
end;
//Główna Klasa Octree ;]
TOctree = class
public
mainNode : PNode;
Procedure DrawOctree(const drawPol, DrawNodes:Boolean; const Lighted:Boolean=TRUE; const Textured:Boolean=TRUE);
Constructor Create(polygons:PPolygonArray);
Destructor Destroy;
end;
var
MaxPol : integer;
AssignedPol : Integer;
implementation
uses Main;
//Konstruktor Klasy Octree
Constructor TOctree.Create(polygons : PPolygonArray);
var
i,j : Integer;
maxSize,minSize : TVertex;
begin
maxSize := polygons^[0].v[0].ver;
minSize := polygons^[0].v[0].ver;
for i:=0 to High(polygons^) do
for j:=0 to 2 do
with polygons^[i].v[j].ver do
begin
if x > maxSize.x then maxSize.x :=x;
if y > maxSize.x then maxSize.x :=y;
if z > maxSize.x then maxSize.x :=z;
if x < minSize.x then minSize.x :=x;
if y < minSize.x then minSize.x :=y;
if z < minSize.x then minSize.x :=z;
end;
New(MainNode);
MainNode.pos.x :=(maxSize.x + minSize.x)/2;
MainNode.pos.y :=(maxSize.x + minSize.x)/2;
MainNode.pos.z :=(maxSize.x + minSize.x)/2;
MainNode.size.x :=(maxSize.x - minSize.x)/2;
MainNode.size.y :=(maxSize.x - minSize.x)/2;
MainNode.size.z :=(maxSize.x - minSize.x)/2;
MainNode.smallest := FALSE;
SetLength(MainNode.polygons,Length(polygons^));
for i:=0 to Length(polygons^)-1 do
for j:=0 to 2 do
MainNode.polygons[i].v[j] :=@polygons^[i].v[j];
MaxPol:=Length(polygons^);
MainNode.Divide;
end;
//Ile wielokątów
Function TNode.HowManyPolygons: Integer;
var
i,j : Integer;
Inside : boolean;
begin
if Length(mother^.polygons) = 0 then Exit;
numPoly := 0;
for i:=0 to Length(Mother^.polygons)-1 do
begin
Inside := FALSE;
for j:=0 to 2 do
with mother^.polygons[i].v[j].ver do
begin
if Mother^.polygons[i].v[0] <> nil then //jezeli przynalezy do innego "liscia" ;]
if (not Inside) and
(x >= pos.x - size.x) and
(y >= pos.y - size.y) and
(z >= pos.z - size.z) and
(x <= pos.x + size.x) and
(y <= pos.y + size.y) and
(z <= pos.z + size.z) then Inside := TRUE;
end;
if Inside then
begin
Inc(numPoly);
SetLength(polygons,numPoly);
polygons[numPoly-1] :=Mother^.polygons[i];
Mother^.polygons[i].v[0] := nil;
end;
end;
Result := numPoly;
end;
//TWORZENIE VBO
Procedure TNode.CreateVBO;
var
i,k: Integer;
VBOPointer: Pointer;
VBOVertex: PFullVertex;
begin
glGenBuffersARB(1, @polyID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, polyID);
glEnableClientState(GL_VERTEX_ARRAY);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,numPoly*3*SizeOf(TFullVertex),nil,GL_STATIC_DRAW_ARB);
VBOPointer := glMapBufferARB(GL_ARRAY_BUFFER_ARB,GL_WRITE_ONLY_ARB);
for i:=0 to numPoly-1 do
for k:=0 to 2 do
begin
VBOVertex :=VBOPointer;
VBOVertex^ :=polygons[i].v[k]^;
Inc(Integer(VBOPointer),SizeOf(TFullVertex));
end;
glUnMapBufferARB(GL_ARRAY_BUFFER_ARB);
end;
//Dzielenie Drzewa ;-)
Procedure TNode.Divide;
var
TempNodes: array[0..7] of PNode;
i: integer;
begin
for i:=0 to 7 do New(TempNodes[i]);
numChildren:=0;
TempNodes[0].pos.x :=pos.x - size.x/2; //Przeliczanie osmiu wezłów (dzieci)
TempNodes[0].pos.y :=pos.y + size.y/2;
TempNodes[0].pos.z :=pos.z - size.z/2;
TempNodes[1].pos.x :=pos.x - size.x/2;
TempNodes[1].pos.y :=pos.y + size.y/2;
TempNodes[1].pos.z :=pos.z - size.z/2;
TempNodes[2].pos.x :=pos.x - size.x/2;
TempNodes[2].pos.y :=pos.y + size.y/2;
TempNodes[2].pos.z :=pos.z - size.z/2;
TempNodes[3].pos.x :=pos.x - size.x/2;
TempNodes[3].pos.y :=pos.y + size.y/2;
TempNodes[3].pos.z :=pos.z - size.z/2;
TempNodes[4].pos.x :=pos.x - size.x/2;
TempNodes[4].pos.y :=pos.y + size.y/2;
TempNodes[4].pos.z :=pos.z - size.z/2;
TempNodes[5].pos.x :=pos.x - size.x/2;
TempNodes[5].pos.y :=pos.y + size.y/2;
TempNodes[5].pos.z :=pos.z - size.z/2;
TempNodes[6].pos.x :=pos.x - size.x/2;
TempNodes[6].pos.y :=pos.y + size.y/2;
TempNodes[6].pos.z :=pos.z - size.z/2;
TempNodes[7].pos.x :=pos.x - size.x/2;
TempNodes[7].pos.y :=pos.y + size.y/2;
TempNodes[7].pos.z :=pos.z - size.z/2;
for i:=0 to 7 do
begin
TempNodes[i].size.x :=size.x/2;
TempNodes[i].size.y :=size.y/2;
TempNodes[i].size.z :=size.z/2;
TempNodes[i].smallest :=FALSE;
TempNodes[i].Mother :=@Self;
end;
for i:=0 to 7 do
begin
if TempNodes[i].HowManyPOlygons > 0 then
begin
inc(numChildren);
SetLength(Children,numCildren);
Children[numChildren-1] :=TempNodes[i];
if Children[numChildren-1].numPoly < MAX_TRIANGLES_IN_NODE then
begin
Children[numChildren-1].smallest :=TRUE;
Children[numChildren-1].CreateVBO;
Inc(AssignedPol,children[numChildren-1].numPoly);
end;
end else Dispose(TempNodes[i]);
end;
for i:=0 to numChildren-1 do
if not children[i].smallest then children[i].Divide; //Podziel Wezly ktore sa za duze
end;
//Rysowanie Noda ;]
Procedure TNode.Draw;
var
i: Integer;
begin
if Frunstum.IsBoxWithin(pos.x,pos.y,pos.z,size.x,size.y,size.z) = FALSE then Exit;
with pos do
begin
glBegin(GL_LINES);
glVertex3f(x-size.x,y-size.y,z-size.z);
glVertex3f(x+size.x,y-size.y,z-size.z);
glVertex3f(x-size.x,y+size.y,z-size.z);
glVertex3f(x+size.x,y+size.y,z-size.z);
glVertex3f(x-size.x,y-size.y,z+size.z);
glVertex3f(x+size.x,y-size.y,z+size.z);
glVertex3f(x-size.x,y+size.y,z+size.z);
glVertex3f(x+size.x,y+size.y,z+size.z);
glVertex3f(x+size.x,y+size.y,z+size.z);
glVertex3f(x+size.x,y+size.y,z+size.z);
glVertex3f(x+size.x,y+size.y,z-size.z);
glVertex3f(x+size.x,y+size.y,z-size.z);
glVertex3f(x-size.x,y+size.y,z+size.z);
glVertex3f(x-size.x,y-size.y,z+size.z);
glVertex3f(x-size.x,y+size.y,z-size.z);
glVertex3f(x-size.x,y-size.y,z-size.z);
glVertex3f(x+size.x,y+size.y,z+size.z);
glVertex3f(x+size.x,y+size.y,z-size.z);
glVertex3f(x+size.x,y-size.y,z+size.z);
glVertex3f(x+size.x,y-size.y,z-size.z);
glVertex3f(x-size.x,y-size.y,z+size.z);
glVertex3f(x-size.x,y-size.y,z-size.z);
glVertex3f(x-size.x,y+size.y,z+size.z);
glVertex3f(x-size.x,y+size.y,z-size.z);
glEnd;
end;
if Length(children) > 0 then Exit;
glBindBufferARB(GL_ARRAY_BUFFER_ARB,polyID);
glInterleavedArrays(GL_T2F_N3F_V3F,SizeOf(TFullVertex),nil);
glDrawArrays(GL_TRIANGLES,0,numPoly*3);
end;
end.