{$MODE OBJFPC}
uses tools,vipgfx,math;
const
v3dMaxVertex=8;
type
v3dVector = record
x,y,z,w:single;
end;
v3dPoly = record
v:array [0..v3dMaxVertex] of v3dVector;
numVertex:dword;
n:v3dVector;
matNum:dword;
end;
v3dObject = record
name:string;
position:v3dVector;
polys:array of v3dPoly;
translatedPolys:array of v3dPoly;
numPolys:dword;
end;
function aVector(x,y,z:single):v3dVector;
var v:v3dVector;
begin
v.x:=X;
v.Y:=Y;
v.z:=Z;
v.w:=1;
aVector:=v;
end;
procedure v3dRasterizeWire(poly:v3dPoly; color:dword);
var i,ii:longint;
x1,y1,x2,y2:longint;
begin
ii:=0;
for i:=0 to poly.numVertex-1 do begin
inc(ii);
if ii>=poly.numVertex then ii:=0;
x1:=ceil(poly.v[i].x);
y1:=ceil(poly.v[i].y);
x2:=ceil(poly.v[ii].x);
y2:=ceil(poly.v[ii].y);
drawline(vscreen,x1,y1,x2,y2,color);
end;
end;
function v3dCreatePoly(v1,v2,v3:v3dVector):v3dPoly;
var i:dword;
p:v3dPoly;
begin
p.numVertex:=3;
p.v[0]:=v1;
p.v[1]:=v2;
p.v[2]:=v3;
v3dCreatePoly:=p;
end;
function v3dCreateObject(name:string; x,y,z:single):v3dObject;
var o:v3dObject;
begin
o.name:=name;
setLength(o.polys,0);
setLength(o.translatedPolys,0);
o.numPolys:=0;
o.position:=aVector(0,0,0);
v3dCreateObject:=o;
end;
procedure v3dAddPolyToObject(var o:v3dObject; p:v3dPoly);
begin
inc(o.numPolys);
setLength(o.polys,o.numPolys);
setLength(o.translatedPolys,o.numPolys);
o.polys[o.numPolys-1]:=p;
end;
const
width=1366;
height=512;
fullscreen=false;
var
theObject:v3dObject;
operator + (a,b:v3dVector):v3dVector;
begin
result.x:=a.x + b.x;
result.y:=a.y + b.y;
result.z:=a.z + b.z;
result.w:=1;
end;
function v3dMakeProjection(v:v3dVector):v3dVector;
var outV:v3dVector;
centerX,centerY:longint;
fNear,fFar,fFov,fAspectRatio,fFovRad:single;
begin
fNear := 0.01;
fFar := 1000.0;
fFov := 90.0;
fAspectRatio := vScreen.height / vScreen.width;
fFovRad := 1.0 / tan(fFov * 0.5 / 180.0 * 3.14159);
outV:=v;
centerX:=vscreen.width div 2;
centerY:=vscreen.height div 2;
outV.x:=fAspectRatio*fFovRad*outV.x / outV.z * (vScreen.width / 2) + centerX;
outV.y:=-fFovRad * outV.y / outV.z * (vScreen.height / 2) + centerY;
// outV.z:=( (fFar/(fFar-fNear)) - ((fFar*fNear) / (fFar-fNear)) ) * outV.z;
v3dMakeProjection:=outV;
end;
procedure v3dRenderPoly(poly:v3dPoly);
var
i:dword;
p:v3dPoly;
begin
for i:=0 to poly.numVertex-1 do p.v[i]:=v3dMakeProjection(poly.v[i]);
p.numVertex:=poly.numVertex;
v3dRasterizeWire(p,$ffffffff);
end;
procedure v3dRenderObject(var o:v3dObject);
var i,ii:dword;
begin
for i:=0 to o.numPolys-1 do begin
o.translatedPolys[i].numVertex:=o.polys[i].numVertex;
for ii:=0 to o.polys[i].numVertex-1 do o.translatedPolys[i].v[ii]:=o.Polys[i].v[ii] + o.position;
v3dRenderPoly(o.translatedPolys[i]);
end;
end;
const
speed=0.1;
var
rx:single=0;
ry:single=0;
rz:single=0;
r:single=0;
mx:single=0;
my:single=0;
mz:single=10;
procedure move;
begin
if KEYBOARD[KEY_T] then mz:=mz-speed;
if KEYBOARD[KEY_G] then mz:=mz+speed;
if KEYBOARD[KEY_UP] then my:=my-speed;
if KEYBOARD[KEY_DOWN] then my:=my+speed;
if KEYBOARD[KEY_LEFT] then mx:=mx-speed;
if KEYBOARD[KEY_RIGHT] then mx:=mx+speed;
theObject.position:=aVector(mx,my,mz);
end;
function cube:v3dObject;
var
v1,v2,v3:v3dVector;
p:v3dPoly;
o:v3dObject;
begin
o:=v3dCreateObject('box',0,0,0);
v1:=aVector(-1.0,-1.0,-1.0);
v2:=aVector(-1.0,-1.0, 1.0);
v3:=aVector(-1.0, 1.0, 1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0, 1.0,-1.0);
v2:=aVector(-1.0,-1.0,-1.0);
v3:=aVector(-1.0, 1.0,-1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0,-1.0, 1.0);
v2:=aVector(-1.0,-1.0,-1.0);
v3:=aVector(1.0,-1.0,-1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0, 1.0,-1.0);
v2:=aVector(1.0,-1.0,-1.0);
v3:=aVector(-1.0,-1.0,-1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(-1.0,-1.0,-1.0);
v2:=aVector(-1.0, 1.0, 1.0);
v3:=aVector(-1.0, 1.0,-1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0,-1.0, 1.0);
v2:=aVector(-1.0,-1.0, 1.0);
v3:=aVector(-1.0,-1.0,-1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(-1.0, 1.0, 1.0);
v2:=aVector(-1.0,-1.0, 1.0);
v3:=aVector(1.0,-1.0, 1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0, 1.0, 1.0);
v2:=aVector(1.0,-1.0,-1.0);
v3:=aVector(1.0, 1.0,-1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0,-1.0,-1.0);
v2:=aVector(1.0, 1.0, 1.0);
v3:=aVector(1.0,-1.0, 1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0, 1.0, 1.0);
v2:=aVector(1.0, 1.0,-1.0);
v3:=aVector(-1.0, 1.0,-1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0, 1.0, 1.0);
v2:=aVector(-1.0, 1.0,-1.0);
v3:=aVector(-1.0, 1.0, 1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
v1:=aVector(1.0, 1.0, 1.0);
v2:=aVector(-1.0, 1.0, 1.0);
v3:=aVector(1.0,-1.0, 1.0);
p:=v3dCreatePoly(v1,v2,v3);
v3dAddPolyToObject(o,p);
cube:=o;
end;
begin
theObject:=cube;
initGFXsystem(width,height,fullscreen);
repeat
fastfill(vscreen.data,vscreen.width*vscreen.height,0);
move;
v3dRenderObject(theObject);
updateGFXsystem;
until gfxDone or keyboard[KEY_ESCAPE];
finishGFXsystem;
ReturnFPSstring;
end.