[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]
{ NOTE : Units needed are included at the end of this code }
program		the_4d_experiment;
{version	1.1}
{ Kiszely Laszlo 1995
kiszely@bmeik.eik.bme.hu}
{--------------------------------------------------------------------------}
uses    crt,mygraf;
const   end_seq:real=237;       {the end of a data-stream,
				 it is a 'í' sign, indicates
				 the end of a kind of stream}
{---------------------------------------------------------------------------}
var	data:file of real;	{the file of the generated object}
	j:integer;		{indexes}
        a:real;                 {for temporary storage}
        chrt:char;              {readkey at the end}
        vertex: array[1..100,1..4] of real;
                                {let's store the vertex-values!}
        vertex_number:integer;  {the number of vertexes}
	edges: array[1..200,1..3] of byte;
				{let's store the edges' start-
				and end-points plus the color of the edge}
	edge_number:integer;	{yes, the number of edges}
        xy,xz,xw,yz,yw,zw:integer;
	sine: array[0..359] of real; {sine-table}
	cosine: array[0..359] of real; {cosine-table}
        FileName:string;  {the name of the 4d-object file}
{---------------------------------------------------------------------------}
{Input/Output procedures}
procedure Open_And_Check;       {Checks whether the requested file is
                                 in the directory or not}
begin
{$I-}
     reset(data);
{$I+}
     if IOResult<>0 then
                    begin
                         writeln(FileName,' not found!');
                         halt;
                    end;
end;
function CheckFlag(flag:real): Boolean;
begin
        read(data,a);
        if a=flag then CheckFlag:=true else CheckFlag:=False;
end;
procedure GetVertex_And_Write;  {Reads the vertexes and puts them
                                 into an an array}
begin
     for j:=1 to 4 do
         read(data,vertex[vertex_number,j]);
end;
procedure GetEdge_And_Write;	{Reads the edge-data-stream and
				puts them into an array}
var real_edge:real;
begin
     for j:=1 to 3 do
        begin
	read(data,real_edge);
        edges[edge_number,j]:=round(real_edge);
        end;
end;
{--------------------------------------------------------------------------}
procedure CmdLineFileName;
begin
     if ParamCount<>1 then begin
                          writeln('No Parameter/Too much Parameters Found!');
                          writeln('Usage: 4dexp object.4d');
                          halt(1);
                          end;
     FileName:=ParamStr(1);
end;
procedure MainScreenOut;
begin
	writeln;writeln;writeln;
	writeln('                          THE       4D      EXPERIMENT');
	writeln;writeln;writeln;
	writeln('                A little program to rotate a 4 dimensional cube');
	writeln;writeln;
	writeln('                           programmed by Kiszely L�szl¢');
	writeln;writeln;writeln;
	writeln('                                  Control Keys');
	writeln('                4 - 6       Rotation around the YW-plane');
	writeln('                8 - 2       Rotation around the XW-plane');
	writeln('                1 - 9       Rotation around the ZW-plane');
	writeln('                3 - 7       Rotation around the XY-plane');
	writeln('                a - s       Rotation around the XZ-plane');
	writeln('                z - x       Rotation around the YZ-plane');
	writeln('                  q         Quit');
	writeln;
	writeln('                                  Hit any key!');
	writeln;writeln;
	asm
@again:
	in	AL,60h
	and	AL,128
	jnz	@again
	end;
end;
procedure BuildSineTable;
var	index:integer;
begin
	for index:=0 to 359 do
		sine[index]:=sin(index*3.14/180);
end;
procedure BuildCosineTable;
var	index:integer;
begin
	for index:=0 to 359 do
		cosine[index]:=cos(index*3.14/180);
end;
{--------------------------------------------------------------------------}
{Graphical procedures}
procedure ShowThePixel(x1:real;y1:real);{Transform the relative coords}
var	x1tmp,y1tmp:integer;
begin
	x1tmp:=160+round(x1);	{160 - origin-translation}
	y1tmp:=100+round(y1);
	point(x1tmp,y1tmp,10);
end;
procedure ShowTheLine(startpoint:integer;endpoint:integer;color:byte);
var	x1tmp,y1tmp,x2tmp,y2tmp,colour:integer;
begin
	x1tmp:=160+round(vertex[startpoint,1]);
	y1tmp:=100+round(vertex[startpoint,2]);
	x2tmp:=160+round(vertex[endpoint,1]);
	y2tmp:=100+round(vertex[endpoint,2]);
	colour:=round(color);
	myline(x1tmp,y1tmp,x2tmp,y2tmp,colour);
end;
procedure ShowTheObject;
var       o:integer;
begin
	cls;
	for o:=1 to vertex_number do 
		ShowThePixel(vertex[o,1],vertex[o,2]);
        for o:=1 to edge_number do 
		ShowTheLine(edges[o,1],edges[o,2],edges[o,3]);
end;
{--------------------------------------------------------------------------}
{The functions of rotation}
procedure RotateAroundXW(alfa:integer);		{alfa - angle of rotating}
						{in degrees, of course}
var	ytmp,ztmp:real;
        i:integer;
begin
	for i:=1 to vertex_number do
	begin
	ytmp:=vertex[i,2]*cosine[alfa]+vertex[i,3]*sine[alfa];
	ztmp:=-vertex[i,2]*sine[alfa]+vertex[i,3]*cosine[alfa];
	vertex[i,2]:=ytmp;
	vertex[i,3]:=ztmp;
	end;
end;
procedure RotateAroundZW(alfa:integer);
var       xtmp,ytmp:real;
          index:integer;
begin
         for index:=1 to vertex_number do
 	 begin
          xtmp:=vertex[index,1]*cosine[alfa]+vertex[index,2]*sine[alfa];
	  ytmp:=-(vertex[index,1]*sine[alfa])+vertex[index,2]*cosine[alfa];
	  vertex[index,1]:=xtmp;
	  vertex[index,2]:=ytmp;
	 end;
end;
procedure RotateAroundYW(alfa:integer);
var       xtmp,ztmp:real;
          index:integer;
begin
         for index:=1 to vertex_number do
	begin
         xtmp:=vertex[index,1]*cosine[alfa]+vertex[index,3]*sine[alfa];
	 ztmp:=-(vertex[index,1]*sine[alfa])+vertex[index,3]*cosine[alfa];
	 vertex[index,1]:=xtmp;
	 vertex[index,3]:=ztmp;
	end;
end;
procedure RotateAroundXY(alfa:integer);
var       ztmp,wtmp:real;
          index:integer;
begin
         for index:=1 to vertex_number do
	begin
         ztmp:=vertex[index,3]*cosine[alfa]+vertex[index,4]*sine[alfa];
	 wtmp:=-(vertex[index,3]*sine[alfa])+vertex[index,4]*cosine[alfa];
	 vertex[index,3]:=ztmp;
	 vertex[index,4]:=wtmp;
	end;
end;
procedure RotateAroundXZ(alfa:integer);
var       ytmp,wtmp:real;
          index:integer;
begin
         for index:=1 to vertex_number do
	begin
         ytmp:=vertex[index,2]*cosine[alfa]+vertex[index,4]*sine[alfa];
	 wtmp:=-(vertex[index,2]*sine[alfa])+vertex[index,4]*cosine[alfa];
	 vertex[index,2]:=ytmp;
	 vertex[index,4]:=wtmp;
	end;
end;
procedure RotateAroundYZ(alfa:integer);
var       ytmp,ztmp:real;
          index:integer;
begin
         for index:=1 to vertex_number do
	begin
         ytmp:=vertex[index,2]*cosine[alfa]+vertex[index,3]*sine[alfa];
 	 ztmp:=-(vertex[index,2]*sine[alfa])+vertex[index,3]*cosine[alfa];
	 vertex[index,2]:=ytmp;
	 vertex[index,3]:=ztmp;
	end;
end;
{---------------------------------------------------------------------------}
begin
     CmdLineFileName;
     MainScreenOut;
     assign(data,FileName);
     Open_And_Check;
     vertex_number:=0;
     edge_number:=0;
     while CheckFlag(47) do
          begin
          vertex_number:=vertex_number+1;
          GetVertex_And_Write;
          end;
     while CheckFlag(92) do
	  begin
	  edge_number:=edge_number+1;
	  GetEdge_And_Write;
	  end;
	if a<>237 then begin
			writeln('This 4d file is not a valid one!');
			halt(2);
		       end;
     close(data);
vga320;
BuildSineTable;
BuildCosineTable;
ShowTheObject;
repeat
repeat
        RotateAroundYW(yw);
        RotateAroundZW(zw);
        RotateAroundXW(xw);
        RotateAroundXY(xy);
        RotateAroundXZ(xz);
        RotateAroundYZ(yz);
        ShowTheObject;
until keypressed;
chrt:=readkey;
case chrt of
     '4': begin;inc(yw);if yw>359 then yw:=yw-360;end;
     '6': begin;dec(yw);if yw<0 then yw:=yw+360;end;
     '1': begin;inc(zw);if zw>359 then zw:=zw-360;end;
     '9': begin;dec(zw);if zw<0 then zw:=zw+360;end;
     '8': begin;inc(xw);if xw>359 then xw:=xw-360;end;
     '2': begin;dec(xw);if xw<0 then xw:=xw+360;end;
     '7': begin;inc(xy);if xy>359 then xy:=xy-360;end;
     '3': begin;dec(xy);if xy<0 then xy:=xy+360;end;
     'a': begin;inc(xz);if xz>359 then xz:=xz-360;end;
     's': begin;dec(xz);if xz<0 then xz:=xz+360;end;
     'z': begin;inc(yz);if yz>359 then yz:=yz-360;end;
     'x': begin;dec(yz);if yz<0 then yz:=yz+360;end;
     'q': break;
end;
until j=0;
vga_out;
end.
{ -----------------------    CUT HERE ---------------------}
unit mygraf;
{Author: Kiszely Laszlo 1995
kiszely@bmeik.eik.bme.hu
Credits: Thanx to Bas van Gaalen for his 3dpas package}
interface
  const vidseg: word=$a000;
  procedure vga320;
  procedure retrace;
  procedure point(x,y:word;color:byte);
  procedure vga_out;
  procedure cls;
  procedure myline(xk,yk,xv,yv:word; color:byte);
implementation
 procedure vga320; assembler;
   asm
   mov ax,13h;
   int 10h;
   end;
procedure retrace; assembler; asm
  mov dx,03dah; @vert1: in al,dx; test al,8; jnz @vert1
  @vert2: in al,dx; test al,8; jz @vert2; end;
procedure point(x,y:word;color:byte);
   begin
  {if (y<200) and (x<320) then}
	   mem[vidseg:y*320+x]:=color;
   end;
procedure vga_out; assembler;
   asm
   mov  ax,03h
   int  10h
   end;
procedure cls; assembler;
      asm
      mov es,[vidseg];xor di,di;xor ax,ax;mov cx,320*100;
      rep stosw;
      end;
procedure myline(xk,yk,xv,yv:word; color:byte);
var
  sgnx,sgny:byte;
  eltx,elty,x,y,pp,qq,count,nn:word;
begin
  asm
  mov ax,xv
  mov bx,xk
  sub ax,bx
  js @h1
  mov cl,1
  mov  sgnx,cl
  mov  eltx,ax
  jmp @h3
@h1:
  mov cl,0
  mov  sgnx,cl
  mov  eltx,ax
  neg  eltx
@h3:
  mov ax,yv
  mov bx,yk
  sub ax,bx
  js @h4
  mov cl,1
  mov  sgny,cl
  mov  elty,ax
  jmp @h5
@h4:
  mov cl,0
  mov  sgny,cl
  mov  elty,ax
  neg  elty
@h5:
  mov ax, eltx
  mov bx, elty
  cmp ax,bx
  ja @j1
  mov ax, elty
  mov  nn,ax
  jmp @j2
@j1:
  mov ax, eltx
  mov  nn,ax
@j2:
  mov ax, nn
  mov dx,0
  mov bx,2
  div bx
  cmp ax,0
  je @gy1
  mov ax,0
  mov  pp,ax
  mov  qq,ax
  inc  pp
  inc  qq
  jmp @gy2
@gy1:
  mov  pp,ax
  mov  qq,ax
@gy2:
  mov ax,xk
  mov x,ax
  mov ax,yk
  mov y,ax
  mov ax,1
  mov  count,ax
@next :
  push x
  push y
  mov al,color
  push ax
  call point
  mov ax, pp
  add ax, eltx
  mov  pp,ax
  mov bx, nn
  cmp ax,bx
  jb @t1
  mov ax, pp
  sub ax, nn
  mov  pp,ax
  mov al, sgnx
  cmp al,1
  je @nn1
  dec x
  jmp @t1
@nn1:
   inc x
@t1:
  mov ax, qq
  add ax, elty
  mov  qq,ax
  mov bx, nn
  cmp ax,bx
  jb @t2
  mov ax, qq
  sub ax, nn
  mov  qq,ax
  mov al, sgny
  cmp al,1
  je @nn3
  dec y
  jmp @t2
@nn3:
  inc y
@t2:
  inc  count
  mov ax, count
  cmp  nn,ax
  jae @next
  end;
end;
end.
{ -----------------------    CUT HERE ---------------------}
{ CODE TO GENERATE THE CUBE FILE }
program		generate_the_4d_cube;
{this little util generates a 4d_object}
{Author:Kiszely Laszlo 1995
kiszely@bmeik.eik.bme.hu}
const   end_seq:real=237;        {the end of a data-stream,
				  it is a 'í' sign, indicates
				  the end of a kind of stream}
        vertex_number:integer=16;  {the number of the vertexes}
     the_object: array[1..16,1..5] of real=((47,40,40,40,40),(47,40,40,40,-40),
    (47,40,40,-40,40),(47,40,40,-40,-40),(47,40,-40,40,40),(47,40,-40,40,-40),
    (47,40,-40,-40,40),(47,40,-40,-40,-40),(47,-40,40,40,40),(47,-40,40,40,-40),
    (47,-40,40,-40,40),(47,-40,40,-40,-40),(47,-40,-40,40,40),
    (47,-40,-40,40,-40),(47,-40,-40,-40,40),(47,-40,-40,-40,-40));
                                {an array of vertexes,where:
				47 - a flag, here starts 4 data members
                                     of the vertex-stream
				of course, it can be anything else,too}
        edge_number:integer=32;    {the number of edges in the object}
        the_edges: array[1..32,1..4] of real=( (92,1,3,10),(92,3,7,10),
		      (92,7,5,10),(92,5,1,10),(92,9,11,10),(92,11,15,10),
		      (92,15,13,10),(92,13,9,10),(92,11,3,10),(92,15,7,10),
		      (92,13,5,10),(92,9,1,10),
		      (92,2,10,3),(92,10,14,3),(92,14,6,3),(92,6,2,3),
		      (92,12,4,3),(92,4,8,3),(92,8,16,3),(92,16,12,3),
		      (92,10,12,3),(92,14,16,3),(92,6,8,3),(92,2,4,3),
		      (92,9,10,5),(92,13,14,5),(92,5,6,5),(92,1,2,5),
		      (92,11,12,5),(92,3,4,5),(92,7,8,5),(92,15,16,5));
                                {an array of edges,where:
                                92 - a flag to separate the 2 data members
                                first value - starting point of the edge
                                second value - endpoint of the edge
				third value - the color of the edge}
var	data:file of real;	{the file of the generated object}
	i,j:integer;		{indexes}
begin
     assign(data,'cube.4d');
     rewrite(data);
        for i:=1 to vertex_number do
                 begin
                 for j:=1 to 5 do
                     begin
                     write(data,the_object[i,j]);
                     end;
                 end;                           {the vertexes' coords}
        write(data,end_seq);
        for i:=1 to edge_number do
                 begin
                 for j:=1 to 4 do
                     begin
                     write(data,the_edges[i,j]);
                     end;
                 end;                           {which v-s are on one edge}
        write(data,end_seq);
{Right now, the file of the 4d_object is ready. Be careful at the reading!}
     close(data);
end.
[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]