// make-games.ru
// Автор: Лебедев вячеслав Юрьевич
// Ник на сайте: Конструктор

unit objects;

interface uses dglOpenGL, vectors, unit3ds;

type color4f=record
  r,g,b,a : GlFloat;
end;

type TSkybox=class(TObject)
   FrontTex : glUint;
   BackTex : glUint;
   TopTex : glUint;
   BottomTex : glUint;
   LeftTex : glUint;
   RightTex : glUint;
  constructor create();virtual;
  procedure Draw(size: GlFloat);
  destructor destroy();virtual;
end;

type TBox=class(TObject)
 tex : glUint;
 a : GlFloat;
 candraw: boolean;
 x,y,z,w,v,h,rotx,roty: GlFloat;
  constructor create();virtual;
  procedure Draw();
  destructor destroy();virtual;
end;

type TSphere=class(TObject)
 tex : glUint;
 a : GLFloat;
 candraw: boolean;
 id: GLUint;
  constructor create(CX, CY, CZ, Radius : glFloat; N : Integer); virtual;
  procedure Draw();
  destructor destroy(); virtual;
end;

type TTorus=class(TObject)
 tex : glUint;
 a: GLFloat;
 candraw: boolean;
 id: GLUint;
  constructor create(TubeRadius, Radius : GLfloat; Sides, Rings : Integer); virtual;
  procedure Draw();
  destructor destroy(); virtual;
end;

type TFloor=class(TObject)
 tex : glUint;
 candraw: boolean;
 x,y,z,w,h,r,t,a: GlFloat;
  constructor create(); virtual;
  procedure Draw();
  destructor destroy(); virtual;
end;

type TWall=class(TObject)
 tex : glUint;
 candraw: boolean;
 x,y,z,w,h,r,t,a: GlFloat;
  constructor create(); virtual;
  procedure Draw();
  destructor destroy(); virtual;
end;

type TWallMe=class(TObject)
 tex : glUint;
 candraw: boolean;
 pos : TVector;
 s,a: GlFloat;
  constructor create(); virtual;
  procedure Draw();
  destructor destroy(); virtual;
end;

type TModel3ds=class(TObject)
 x,y,z : GLFloat;
 rotx,roty,rotz : GLFloat;
 sx,sy,sz : GlFloat;
 a : GlFloat;
 Model : T3DModel;
  constructor create; virtual;
  Procedure Load(Str: String);
  procedure Draw();
  destructor destroy(); virtual;
end;

type Model3dsProp=record
 mdl : T3DModel; x,y,z,rotx,roty,rotz,sx,sy,sz,alpha: GlFloat;
end;

// TBox , TSphere, TTorus, TFloor, tWall , TWallMe , Model3ds
type TGLPremitives=class(TObject)
 box_count : Integer;
 box_object : array [0..32000] of TBox;
 Sphere_count : Integer;
 Sphere_object : array [0..32000] of TSphere;
 Torus_count : Integer;
 Torus_object : array [0..32000] of TTorus;
 Floor_count : Integer;
 Floor_object : array [0..32000] of TFloor;
 Wall_count : Integer;
 Wall_object : array [0..32000] of TWall;
 WallMe_count : Integer;
 WallMe_object : array [0..32000] of TWallMe;
 Model3ds_count : Integer;
 Model3ds_object : array [0..32000] of TModel3ds;
 canDraw : Boolean;
 id : GLUint;
 myid : integer;
  constructor create;virtual;
  procedure Draw(x,y,z : GlFloat);
  function add_box(tex : glUint; x,y,z,w,v,h,rotx,roty: GlFloat; alpha: GlFloat) : integer;
  function add_sphere(tex : glUint; CX, CY, CZ, Radius : glFloat; N : Integer; alpha: GlFloat) : integer;
  function add_torus(tex : glUint; TubeRadius, Radius : GLfloat; Sides, Rings : Integer; alpha: GlFloat) : integer;
  function add_floor(tex : glUint; x,y,z,w,h,r,t: GlFloat; alpha: GlFloat) : integer;
  function add_wall(tex : glUint; x,y,z,w,h,r,t: GlFloat; alpha: GlFloat) : integer;
  function add_wallme(tex : glUint;  x,y,z,s: GlFloat; alpha: GlFloat) : integer;
  function add_Model3ds(path : String; x,y,z,rotx,roty,rotz,sx,sy,sz,alpha: GlFloat) : integer;
  function add_Model3ds_loaded(param : TModel3ds; x,y,z,rotx,roty,rotz,sx,sy,sz,alpha: GlFloat) : integer;
  function Get_Model3ds_loaded(param : integer) : TModel3ds;
  procedure Step;
  destructor destroy;virtual;
end;

procedure DrawBox(x,y,z,w,v,h,rotx,roty,a: GlFloat);
function CreateSphere(CX, CY, CZ, Radius : glFloat; N : Integer) : GluInt;
Function CreateTorus(TubeRadius, Radius : GLfloat; Sides, Rings : Integer) : GLUint;
Procedure DrawFloor(x,y,z,w,h,r,t:GlFloat);
Procedure DrawWall(x,y,z,w,h,r,t:GlFloat);
procedure DrawWallME(Position: TVector; Size: GlFloat);

Procedure Drawbumpwall(tex,bump,time: GLFloat);

Function GetColor4F(r,g,b,a: GlFloat) : Color4F;

implementation

Function GetColor4F(r,g,b,a: GlFloat) : Color4F;
begin
  Result.r:=r;
  Result.g:=g;
  Result.b:=b;
  Result.a:=a;
end;

{------------------------------------------------------------------}
{  TGLObjects                                                     }
{------------------------------------------------------------------}

constructor TGLPremitives.create();
begin
CanDraw:=true;
end;

procedure TGLPremitives.Step();
var i:Integer;
begin
id:=glGenLists(1);
glNewList(id, GL_COMPILE);
if CanDraw=false then Exit;
for i:=0 to box_count-1 do
 box_object[i].Draw;
for i:=0 to sphere_count-1 do
 sphere_object[i].Draw;
for i:=0 to Torus_count-1 do
 Torus_object[i].Draw;
for i:=0 to Floor_count-1 do
 Floor_object[i].Draw;
for i:=0 to Wall_count-1 do
 Wall_object[i].Draw;
for i:=0 to WallME_count-1 do
 WallME_object[i].Draw;
for i:=0 to Model3DS_count-1 do
 Model3DS_object[i].Draw;
glEndList();
end;

Procedure TGLPremitives.Draw(x,y,z : GlFloat);
begin
  gltranslatef(x,y,z);
  glCallList(id);
  gltranslatef(-x,-y,-z);
end;

function TGLPremitives.add_box(tex : glUint; x,y,z,w,v,h,rotx,roty: GlFloat; alpha: GlFloat) : integer;
begin
Result:=box_count;
box_object[box_count]:=TBox.create;
box_object[box_count].tex:=tex;
box_object[box_count].x:=x;
box_object[box_count].y:=y;
box_object[box_count].z:=z;
box_object[box_count].w:=w;
box_object[box_count].v:=v;
box_object[box_count].h:=h;
box_object[box_count].rotx:=rotx;
box_object[box_count].roty:=roty;
box_object[box_count].a:=alpha;
box_count:=box_count+1;
end;

function TGLPremitives.add_sphere(tex : glUint; CX, CY, CZ, Radius : glFloat; N : Integer; alpha: GlFloat) : integer;
begin
Result:=sphere_count;
sphere_object[sphere_count]:=Tsphere.create(cx,cy,cz,Radius,n);
sphere_object[sphere_count].tex:=tex;
sphere_object[sphere_count].a:=alpha;
sphere_count:=sphere_count+1;
end;

function TGLPremitives.add_torus(tex : glUint; TubeRadius, Radius : GLfloat; Sides, Rings : Integer; alpha: GlFloat) : integer;
begin
Result:=torus_count;
torus_object[torus_count]:=Ttorus.create(TubeRadius, Radius, Sides, Rings);
torus_object[torus_count].tex:=tex;
torus_object[torus_count].a:=alpha;
torus_count:=torus_count+1;
end;

function TGLPremitives.add_floor(tex : glUint; x,y,z,w,h,r,t: GlFloat; alpha: GlFloat) : integer;
begin
Result:=floor_count;
floor_object[floor_count]:=Tfloor.create();
floor_object[floor_count].tex:=tex;
floor_object[floor_count].x:=x;
floor_object[floor_count].y:=y;
floor_object[floor_count].z:=z;
floor_object[floor_count].w:=w;
floor_object[floor_count].h:=h;
floor_object[floor_count].r:=r;
floor_object[floor_count].t:=t;
floor_object[floor_count].a:=alpha;
floor_count:=floor_count+1;
end;

function TGLPremitives.add_wall(tex : glUint; x,y,z,w,h,r,t: GlFloat; alpha: GlFloat) : integer;
begin
Result:=wall_count;
wall_object[wall_count]:=Twall.create();
wall_object[wall_count].tex:=tex;
wall_object[wall_count].x:=x;
wall_object[wall_count].y:=y;
wall_object[wall_count].z:=z;
wall_object[wall_count].w:=w;
wall_object[wall_count].h:=h;
wall_object[wall_count].r:=r;
wall_object[wall_count].t:=t;
wall_object[wall_count].a:=alpha;
wall_count:=wall_count+1;
end;

function TGLPremitives.add_wallme(tex : glUint; x,y,z,s: GlFloat; alpha: GlFloat) : integer;
begin
Result:=wallme_count;
wallme_object[wallme_count]:=Twallme.create();
wallme_object[wallme_count].tex:=tex;
wallme_object[wallme_count].pos.X:=x;
wallme_object[wallme_count].pos.Y:=Y;
wallme_object[wallme_count].pos.Z:=Z;
wallme_object[wallme_count].s:=s;
wallme_object[wallme_count].a:=alpha;
wallme_count:=wallme_count+1;
end;

function TGLPremitives.add_Model3ds(path : String; x,y,z,rotx,roty,rotz,sx,sy,sz,alpha: GlFloat) : integer;
begin
Result:=Model3ds_count;
Model3ds_object[Model3ds_count]:=TModel3DS.Create();
Model3ds_object[Model3ds_count].Load(path);
Model3ds_object[Model3ds_count].rotx:=rotx;
Model3ds_object[Model3ds_count].roty:=roty;
Model3ds_object[Model3ds_count].rotz:=rotz;
Model3ds_object[Model3ds_count].sx:=sx;
Model3ds_object[Model3ds_count].sy:=sy;
Model3ds_object[Model3ds_count].sz:=sz;
Model3ds_object[Model3ds_count].x:=x;
Model3ds_object[Model3ds_count].y:=y;
Model3ds_object[Model3ds_count].z:=z;
Model3ds_object[Model3ds_count].a:=alpha;
Model3ds_count:=Model3ds_count+1;
end;

function TGLPremitives.add_Model3ds_loaded(param : TModel3ds; x,y,z,rotx,roty,rotz,sx,sy,sz,alpha: GlFloat) : integer;
begin
Result:=Model3ds_count;
Model3ds_object[Model3ds_count]:=param;
Model3ds_object[Model3ds_count].rotx:=rotx;
Model3ds_object[Model3ds_count].roty:=roty;
Model3ds_object[Model3ds_count].rotz:=rotz;
Model3ds_object[Model3ds_count].sx:=sx;
Model3ds_object[Model3ds_count].sy:=sy;
Model3ds_object[Model3ds_count].sz:=sz;
Model3ds_object[Model3ds_count].x:=x;
Model3ds_object[Model3ds_count].y:=y;
Model3ds_object[Model3ds_count].z:=z;
Model3ds_object[Model3ds_count].a:=alpha;
Model3ds_count:=Model3ds_count+1;
end;

function TGLPremitives.Get_Model3ds_loaded(param : integer) : TModel3ds;
begin
Result:=Model3ds_object[param];
end;

destructor TGLPremitives.destroy();
begin
Candraw:=false;
glDeleteLists(id,1);
end;

{------------------------------------------------------------------}
{  TModel3DS                                                        }
{------------------------------------------------------------------}
constructor TModel3DS.create();
begin
Model:=T3dModel.Create;
end;

Procedure TModel3DS.Load(Str: String);
begin
Model.LoadFromFile(STR);
end;

procedure TModel3DS.Draw();
begin
if a<1 then
begin
 glEnable( GL_BLEND );
 glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
 glColor4F(1,1,1,a);
end;

glpushmatrix();
glTranslatef(x,y,z);
glRotatef(rotx,1,0,0);
glRotatef(roty,0,1,0);
glRotatef(rotz,0,0,1);
glscaled(sx,sy,sz);

Model.Draw;

glpopmatrix;

if a<1 then glDisable(GL_BLEND );
end;


destructor TModel3DS.destroy();
begin
Model.Destroy;
end;



{------------------------------------------------------------------}
{  TWALLME                                                         }
{------------------------------------------------------------------}
constructor TWallMe.create();
begin
a:=1;
candraw:=true;
end;

procedure TWallMe.Draw();
begin
if canDraw=false then Exit;
glBindTexture(GL_TEXTURE_2D, tex);
if a<1 then
begin
 glEnable( GL_BLEND );
 glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
 glColor4F(1,1,1,a);
end;
DrawWallMe(pos,s);
if a<1 then glDisable(GL_BLEND );
end;

destructor TWallMe.destroy();
begin
inherited;
canDraw:=false;
end;

{------------------------------------------------------------------}
{  TWALL                                                           }
{------------------------------------------------------------------}
constructor TWall.create();
begin
a:=1;
candraw:=true;
end;

procedure TWall.Draw();
begin
if canDraw=false then Exit;
glBindTexture(GL_TEXTURE_2D, tex);
if a<1 then
begin
 glEnable( GL_BLEND );
 glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
 glColor4F(1,1,1,a);
end;
DrawWall(x,y,z,w,h,r,t);
if a<1 then glDisable(GL_BLEND );
end;

destructor TWall.destroy();
begin
inherited;
canDraw:=false;
end;

{------------------------------------------------------------------}
{  TFlor                                                           }
{------------------------------------------------------------------}
constructor TFloor.create();
begin
a:=1;
candraw:=true;
end;

procedure TFloor.Draw();
begin
if canDraw=false then Exit;
glBindTexture(GL_TEXTURE_2D, tex);
if a<1 then
begin
 glEnable( GL_BLEND );
 glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
 glColor4F(1,1,1,a);
end;


DrawFloor(x,y,z,w,h,r,t);


if a<1 then glDisable(GL_BLEND );
end;

destructor TFloor.destroy();
begin
inherited;
canDraw:=false;
end;

{------------------------------------------------------------------}
{  TTorus                                                          }
{------------------------------------------------------------------}
constructor TTorus.create(TubeRadius, Radius : GLfloat; Sides, Rings : Integer);
begin
a:=1;
candraw:=true;
id:=CreateTorus(TubeRadius, Radius, Sides, Rings);
end;

procedure TTorus.Draw();
begin
if canDraw=false then Exit;
glBindTexture(GL_TEXTURE_2D, tex);
if a<1 then
begin
 glEnable( GL_BLEND );
 glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
 glColor4F(1,1,1,a);
end;
glCallList(id);
if a<1 then glDisable(GL_BLEND );
end;

destructor TTorus.destroy();
begin
inherited;
canDraw:=false;
glDeleteLists(id,1);
end;

{------------------------------------------------------------------}
{  TSphere                                                         }
{------------------------------------------------------------------}
constructor TSphere.create(CX, CY, CZ, Radius : glFloat; N : Integer);
begin
a:=1;
candraw:=true;
id:=CreateSphere(CX, CY, CZ, Radius, N);
end;

procedure TSphere.Draw();
begin
if canDraw=false then Exit;
if a<1 then
begin
 glEnable( GL_BLEND );
 glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
 glColor4F(1,1,1,a);
end;
glCallList(id);
if a<1 then glDisable(GL_BLEND );
end;

destructor TSphere.destroy();
begin
inherited;
canDraw:=false;
glDeleteLists(id,1);
end;

{------------------------------------------------------------------}
{  TBox                                                            }
{------------------------------------------------------------------}
constructor TBox.create();
begin
inherited;a:=1;
candraw:=true;
end;

procedure TBox.Draw();
begin
if canDraw=false then Exit;
glBindTexture(GL_TEXTURE_2D, tex);
DrawBox(x,y,z,w,v,h,rotx,roty,a);
end;

destructor TBox.destroy();
begin
inherited;
canDraw:=false;
end;

{------------------------------------------------------------------}
{  TSkybox                                                         }
{------------------------------------------------------------------}
constructor TSkybox.create();
begin
inherited;
end;

destructor TSkybox.destroy();
begin
inherited;
end;

procedure TSkybox.Draw(size: GlFloat);
begin
glPushMatrix;
glscaled(size,size,size);
  glBindTexture(GL_TEXTURE_2D, FrontTex);
  glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.01, -1.01,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.01, -1.01,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.01,  1.01,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.01,  1.01,  1.0);
  glend;
  glBindTexture(GL_TEXTURE_2D, BackTex);
  glBegin(GL_QUADS);
    glNormal3f( 0.0, 0.0,-1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.01, -1.01, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.01,  1.01, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.01,  1.01, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.01, -1.01, -1.0);
  glEnd;
  glBindTexture(GL_TEXTURE_2D, TopTex);
  glBegin(GL_QUADS);
    glNormal3f( 0.0, 1.0, 0.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.01,  1.0, -1.01);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.01,  1.0,  1.01);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.01,  1.0,  1.01);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.01,  1.0, -1.01);
  glEnd;
  glBindTexture(GL_TEXTURE_2D, BottomTex);
  glBegin(GL_QUADS);
    glNormal3f( 0.0,-1.0, 0.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.01, -1.0, -1.01);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.01, -1.0, -1.01);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.01, -1.0,  1.01);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.01, -1.0,  1.01);
  glEnd;
  glBindTexture(GL_TEXTURE_2D, LeftTex);
  glBegin(GL_QUADS);
    glNormal3f( 1.0, 0.0, 0.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.01, -1.01);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.01, -1.01);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.01,  1.01);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.01,  1.01);
  glEnd;
  glBindTexture(GL_TEXTURE_2D, RightTex);
  glBegin(GL_QUADS);
    glNormal3f(-1.0, 0.0, 0.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.01, -1.01);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.01,  1.01);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.01,  1.01);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.01, -1.01);
  glEnd();
glPopMatrix;
end;


{------------------------------------------------------------------}
{  Draws objects Primitive                                         }
{------------------------------------------------------------------}
procedure DrawBox(x,y,z,w,v,h,rotx,roty,a: GlFloat);
begin
if a<1 then
begin
glEnable ( GL_BLEND );
glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
glColor4F(1,1,1,a);
end;
glPushMatrix;
glTranslateF(-x-w/2,y+v/2,-z-h/2);
glscaled(w/2,v/2,h/2);
glrotatef(rotx,1,0,0);
glRotatef(roty,0,1,0);
  glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0,  1.0);
  glend;
  glBegin(GL_QUADS);
    glNormal3f( 0.0, 0.0,-1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
  glEnd;
  glBegin(GL_QUADS);
    glNormal3f( 0.0, 1.0, 0.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0,  1.0, -1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0,  1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
  glEnd;
  glBegin(GL_QUADS);
    glNormal3f( 0.0,-1.0, 0.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0,  1.0);
  glEnd;
  glBegin(GL_QUADS);
    glNormal3f( 1.0, 0.0, 0.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
  glEnd;
  glBegin(GL_QUADS);
    glNormal3f(-1.0, 0.0, 0.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
  glEnd();
glPopMatrix;
if a<1 then glDisable(GL_BLEND );
end;

function CreateSphere(CX, CY, CZ, Radius : glFloat; N : Integer) : GluInt;
var I, J : Integer;
    theta1,theta2,theta3 : glFloat;
    X, Y, Z, px, py, pz : glFloat;
begin
  Result :=glGenLists(1);
  glNewList(Result, GL_COMPILE);
    if Radius < 0 then Radius :=-Radius;
    if n < 0 then n := -n;
    if (n < 4) OR (Radius <= 0) then
    begin
      glBegin(GL_POINTS);
        glVertex3f(CX, CY, CZ);
      glEnd();
      exit;
    end;
    for J :=0 to N DIV 2 -1 do
    begin
      theta1 := J*2*PI/N - PI/2;
      theta2 := (J+1)*2*PI/n - PI/2;
      glBegin(GL_QUAD_STRIP);
        For I :=0 to N do
        begin
          theta3 := i*2*PI/N;
          x := cos(theta2) * cos(theta3);
          y := sin(theta2);
          z := cos(theta2) * sin(theta3);
          px := CX + Radius*x;
          py := CY + Radius*y;
          pz := CZ + Radius*z;
          glTexCoord2f(1-I/n, 2*(J+1)/n);
          glVertex3f(px,py,pz);
          X := cos(theta1) * cos(theta3);
          Y := sin(theta1);
          Z := cos(theta1) * sin(theta3);
          px := CX + Radius*X;
          py := CY + Radius*Y;
          pz := CZ + Radius*Z;
          glTexCoord2f(1-i/n, 2*j/n);
          glVertex3f(px,py,pz);
        end;
      glEnd();
    end;
  glEndList();
end;

Function CreateTorus(TubeRadius, Radius : GLfloat; Sides, Rings : Integer) : GLUint;
var I, J : Integer;
    theta, phi, theta1 : GLfloat;
    cosTheta, sinTheta : GLfloat;
    cosTheta1, sinTheta1 : GLfloat;
    ringDelta, sideDelta : GLfloat;
    cosPhi, sinPhi, dist : GLfloat;
begin
  sideDelta := 2.0 * Pi / Sides;
  ringDelta := 2.0 * Pi / rings;
  theta := 0.0;
  cosTheta := 1.0;
  sinTheta := 0.0;
  Result :=glGenLists(1);
  glNewList(Result, GL_COMPILE);
    for i := rings - 1 downto 0 do
    begin
      theta1 := theta + ringDelta;
      cosTheta1 := cos(theta1);
      sinTheta1 := sin(theta1);
      glBegin(GL_QUAD_STRIP);
        phi := 0.0;
        for j := Sides downto 0 do
        begin
          phi := phi + sideDelta;
          cosPhi := cos(phi);
          sinPhi := sin(phi);
          dist := Radius + (TubeRadius * cosPhi);
          glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
          glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, TubeRadius * sinPhi);
          glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
          glVertex3f(cosTheta * dist, -sinTheta * dist, TubeRadius * sinPhi);
        end;
      glEnd();
      theta := theta1;
      cosTheta := cosTheta1;
      sinTheta := sinTheta1;
    end;
  glEndList();
end;

Procedure DrawFloor(x,y,z,w,h,r,t:GlFloat);
begin
z:=-z;
glPushMatrix();
glrotatef(r,1,0,0);
 glBegin(GL_QUADS);
  glTexCoord2f(0.0, 0.0); glVertex3f(0, y, 0);
  glTexCoord2f(0.0, t); glVertex3f(0, y, 0-h);
  glTexCoord2f(t, t); glVertex3f(0-w, y, 0-h);
  glTexCoord2f(t, 0.0); glVertex3f(0-w, y, 0);
 glEnd;
glPopMatrix();
end;

procedure DrawWallME(Position: TVector; Size: GlFloat);
var Cross1, Cross2,
    A, B, C, D: TVector;
    Matrix: array [0..15] of GlFloat;
begin
 glGetFloatv(GL_MODELVIEW_MATRIX, @Matrix);

 Cross1 := GetVector(Matrix[0], Matrix[4], Matrix[8]);
 Cross1 := MultVector(Cross1, Size);

 Cross2 := GetVector(Matrix[1], Matrix[5], Matrix[9]);
 Cross2 := MultVector(Cross2, Size);

 glDepthMask(False);
 glEnable(GL_BLEND);
 glBlendFunc(GL_ONE, GL_ONE);

 A := AddVector(Position, GetVector(- Cross1.X - Cross2.X, - Cross1.Y - Cross2.Y, - Cross1.Z - Cross2.Z));
 B := AddVector(Position, GetVector(Cross1.X - Cross2.X, Cross1.Y - Cross2.Y, Cross1.Z - Cross2.Z));
 C := AddVector(Position, GetVector(Cross1.X + Cross2.X, Cross1.Y + Cross2.Y, Cross1.Z + Cross2.Z));
 D := AddVector(Position, GetVector(- Cross1.X + Cross2.X, - Cross1.Y + Cross2.Y, - Cross1.Z + Cross2.Z));

 glBegin(GL_QUADS);
  glTexCoord2f(0.0, 0.0); glVertex3fv(@A);
  glTexCoord2f(1.0, 0.0); glVertex3fv(@B);
  glTexCoord2f(1.0, 1.0); glVertex3fv(@C);
  glTexCoord2f(0.0, 1.0); glVertex3fv(@D);
 glEnd;

 glDisable(GL_BLEND);
 glDepthMask(True);
end;

Procedure DrawWall(x,y,z,w,h,r,t:GlFloat);
begin
glPushMatrix();
glRotatef(90,0,1,0);
x:=(x-x)-x;
x:=x-8;
 glBegin(GL_QUADS);
  glTexCoord2f(0.0, 0.0); glVertex3f(x, z, y);
  glTexCoord2f(0.0, 1); glVertex3f(x, h, y);
  glTexCoord2f(1, 1); glVertex3f(x+w, h, y);
  glTexCoord2f(1, 0.0); glVertex3f(x+w, z, y);
 glEnd;
glPopMatrix();
end;

Procedure Drawbumpwall(tex,bump,time: GlFloat);
var x1,y1,z1 : GlFloat;
begin
glBegin(GL_QUADS);

   x1:=(1 + 0.954 * -cos(((Pi/180)*time)/100))/2;
   y1:=(1 + 0.954 * -sin(((Pi/180)*time)/100))/2;
   z1:=(1 + 0.3)/2;

   glColor3f(x1, y1, z1);

   glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0,0);
   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0,0);
   glVertex3f(-8.0, -0.0, 0);


   glMultiTexCoord2fARB(GL_TEXTURE0_ARB, bump,0);
   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, tex,0);
   glVertex3f(-8.0,  8.0, 0);

   glMultiTexCoord2fARB(GL_TEXTURE0_ARB, bump,bump);
   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, tex,tex);
   glVertex3f( 0.0,  8.0, 0);

   glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0,bump);
   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0,tex);
   glVertex3f( 0.0, -0.0, 0);

glEnd();
end;

end.
 