rendered paste body{$I maindef.pas}
unit vip3d;
interface
uses io,tools,vipgfx,math3d;
const
maxArr=400;
z_max=-1000;
xscale=640;
yscale=480;
{
shiftconst=8; for 320x200
shiftconst=9; for 640x480
}
shiftconst=9;
var clear_translation:Longint=0;
FOCALDISTANCE : single = 256;
var Zbuffer : dword;
zAddValue : Longint;
type
tV3Dvertex=record
x,y,z:single;
nx,ny,nz:single;
u,v:single;
r,g,b,a:byte;
end;
tV3Dpoly=record
A,B,C:tV3Dvertex;
nx,ny,nz:single;
matNum:dword;
end;
tV3Dobject=record
posX,posY,posZ:single;
numPolys:dword;
Poly: array [0..maxArr] of tV3dpoly;
end;
procedure ClearZBuffer;
Procedure SwapB(Var A : byte; Var B : byte);
Procedure SwapL(Var A : Longint; Var B : Longint);
Procedure SwapD(Var A : dword; Var B : dword);
Procedure SwapS(Var A : Single; Var B : Single);
Procedure SwapV(var a : tV3DVertex; var b : tV3Dvertex);
function CreateV3DVertex(x,y,z,nx,ny,nz,u,v:single;r,g,b,a:byte):tV3DVertex;
Function CreateV3DPoly(A,B,C:tV3Dvertex;nx,ny,nz:single;matNum:dword):tV3Dpoly;
procedure AddPoly(thePoly:tV3Dpoly;var theObject:tV3Dobject);
function ExtractPoly(theObject:tV3Dobject;polyNum:dword):tV3Dpoly;
procedure PackPoly(var theObject:tV3Dobject;thePoly:tV3Dpoly;polynum:dword);
procedure RenderObject(theObject:tV3Dobject);
procedure MoveObject(var theObject:tV3Dobject; x,y,z:single);
procedure RotateObject(var theObject:tV3Dobject; x,y,z:single);
procedure move_Vertex(var Vrtx:tV3DVertex;MoveX,MoveY,MoveZ:Single);
function Rotate_Vertex(var Vctr:tV3DVertex;CenterX,CenterY,CenterZ,AngleX,AngleY,AngleZ:Single):tV3DVertex; {Angle=0..360}
function Rotate_Vertex_X(vctr:tV3DVertex;angle:single):tV3Dvertex;
function Rotate_Vertex_Y(vctr:tV3Dvertex;angle:single):tV3Dvertex;
function Rotate_Vertex_Z(vctr:tV3Dvertex;angle:single):tV3Dvertex;
function TriangleBackface(vA,vB,vC:tV3DVertex):boolean;
procedure makeProjection(V:tV3Dvertex;var X,Y,Z:single);
{LOADERS\txttools.pas}
const
obj_V:byte=1;
obj_VT:byte=2;
obj_VN:byte=3;
obj_F:byte=4;
obj_S:byte=5;
type obj_tVector3f=packed record
x,y,z:single;
end;
obj_tVector2f=packed record
u,v:single;
end;
obj_tFaceInfo=packed record
AvListNum:dword;
AtListNum:dword;
AnListNum:dword;
BvListNum:dword;
BtListNum:dword;
BnListNum:dword;
CvListNum:dword;
CtListNum:dword;
CnListNum:dword;
SmothingGroup:dword;
end;
function obj_GetFirstSign(s:String):byte;
function obj_GetVector3f(s:string):obj_tVector3f;
function obj_GetVector2f(s:string):obj_tVector2f;
function obj_GetFaceInfo(s:String):obj_tFaceInfo;
function obj_GetSmothingGroup(s:string):dword;
{LOADERS\objlib.pas}
procedure Load3DOBJ(filename:string;var theObject:tV3Dobject);
implementation
uses math;
{$I 3Dinc\loaders\txttools.pas}
{$I 3Dinc\loaders\objlib.pas}
{$I 3Dinc\shader\flat.inc}
procedure ClearZBuffer;
var x,y:dword;
begin
for y:=0 to yscale-1 do
for x:=0 to xscale-1 do begin
//putL(Zbuffer+ ((y*xscale+x) shl 2),z_max shl 4);
asm
mov eax,y
imul eax,xscale
add eax,x
shl eax,2
add eax,zBuffer
mov edx,z_max
shl edx,4
mov [eax],edx
end;
end;
end;
Procedure SwapB(Var A : byte; Var B : byte);
var t:byte;
Begin
t:=A;
a:=B;
b:=t;
End;
Procedure SwapL(Var A : Longint; Var B : Longint);
var t:Longint;
Begin
t:=A;
a:=B;
b:=t;
End;
Procedure SwapD(Var A : dword; Var B : dword);
var t:dword;
Begin
t:=A;
a:=B;
b:=t;
End;
Procedure SwapS(Var A : Single; Var B : Single);
var t:Single;
Begin
t:=A;
a:=B;
b:=t;
End;
Procedure SwapV(var a:tV3Dvertex; var b:tV3Dvertex);
var t:tV3Dvertex;
Begin
t:=A;
a:=B;
b:=t;
End;
function TriangleBackface(vA,vB,vC:tV3Dvertex):boolean;
var
x1,x2,x3:single;
y1,y2,y3:single;
z1,z2,z3:single;
a,b,c,d:single;
begin
x1:=vA.x;
x2:=vB.x;
x3:=vC.x;
y1:=vA.y;
y2:=vB.y;
y3:=vC.y;
z1:=vA.z;
z2:=vB.z;
z3:=vC.z;
A:=y1*(z2-z3)+y2*(z3-z1)+y3*(z1-z2);
B:=z1*(x2-x3)+z2*(x3-x1)+z3*(x1-x2);
C:=x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2);
D:=-x1*(y2*z3-y3*z2)-x2*(y3*z1-y1*z3)-x3*(y1*z2-y2*z1);
if D<0 then trianglebackface:=true else trianglebackface:=false;
end;
procedure makeProjection(V:tV3Dvertex;var X,Y,Z:single);
begin
z:=V.z;
if z=0 then begin
x:=0;
y:=0;
exit;
end;
x:=FOCALDISTANCE * V.x / z + xscale / 2 + 0.5;
y:=FOCALDISTANCE * V.y / z * -1 + yscale / 2 + 0.5;
end;
function CreateV3DVertex(x,y,z,nx,ny,nz,u,v:single;r,g,b,a:byte):tV3DVertex;
var myVertex:tV3DVertex;
begin
myVertex.x:=x;
myVertex.y:=y;
myVertex.z:=z;
myVertex.nx:=nx;
myVertex.ny:=ny;
myVertex.nz:=nz;
myVertex.u:=u;
myVertex.v:=v;
myVertex.r:=r;
myVertex.g:=g;
myVertex.b:=b;
myVertex.a:=a;
CreateV3DVertex:=myVertex;
end;
Function CreateV3DPoly(A,B,C:tV3Dvertex;nx,ny,nz:single;matNum:dword):tV3Dpoly;
Var TempPoly : tV3Dpoly;
Begin
TempPoly.A:=A;
TempPoly.B:=B;
TempPoly.C:=C;
TempPoly.nx:=nx;
TempPoly.ny:=ny;
TempPoly.nz:=nz;
TempPoly.matNum:=matNum;
CreateV3DPoly:=TempPoly;
End;
procedure MoveObject(var theObject:tV3Dobject; x,y,z:single);
var i:dword;
myPoly:tV3Dpoly;
A,B,C:tV3Dvertex;
begin
for i:=0 to theObject.numPolys-1 do begin
myPoly:=extractPoly(theObject,i);
A:=myPoly.A;
move_Vertex(A,x,y,z);
myPoly.A:=A;
B:=myPoly.B;
move_Vertex(B,x,y,z);
myPoly.B:=B;
C:=myPoly.C;
move_Vertex(C,x,y,z);
myPoly.C:=C;
packPoly(theObject,myPoly,i);
end;
end;
procedure RotateObject(var theObject:tV3Dobject; x,y,z:single);
var i:dword;
myPoly:tV3Dpoly;
A,B,C:tV3DVertex;
begin
for i:=0 to theObject.numPolys-1 do begin
myPoly:=extractPoly(theObject,i);
A:=myPoly.A;
myPoly.A:=rotate_Vertex_x(A,x);
A:=myPoly.A;
myPoly.A:=rotate_Vertex_y(A,y);
A:=myPoly.A;
myPoly.A:=rotate_Vertex_z(A,z);
B:=myPoly.B;
myPoly.B:=rotate_Vertex_x(B,x);
B:=myPoly.B;
myPoly.B:=rotate_Vertex_y(B,y);
B:=myPoly.B;
myPoly.B:=rotate_Vertex_z(B,z);
C:=myPoly.C;
myPoly.C:=rotate_Vertex_x(C,x);
C:=myPoly.C;
myPoly.C:=rotate_Vertex_y(C,y);
C:=myPoly.C;
myPoly.C:=rotate_Vertex_z(C,z);
packPoly(theObject,myPoly,i);
end;
end;
procedure RenderObject(theObject:tV3Dobject);
var i:longint;
myPoly:tV3DPoly;
begin
for i:=0 to theObject.numPolys-1 do begin
lognum(i);
myPoly:=theObject.Poly[i];
// if not TriangleBackface(myPoly.A,myPoly.B,myPoly.C) then
Triangle(myPoly.A,myPoly.B,myPoly.C,vscreen);
end;
end;
procedure AddPoly(thePoly:tV3DPoly;var theObject:tV3Dobject);
var p,pp,ppp:pointer;
i,d,dd,ddd:dword;
x:dword;
myPoly:tV3DPoly;
Begin
// getmem(theObject.polyEntriesList[theObject.numPolys],sizeof(tV3DPoly));
myPoly:=thePoly;
myPoly.A.r:=random(255);
myPoly.A.g:=random(255);
myPoly.A.b:=random(255);
// move(myPoly,theObject.polyEntriesList[theObject.numPolys]^,sizeof(tV3DPoly));
theObject.poly[theObject.numPolys]:=myPoly;
inc(theObject.numPolys);
End;
procedure PackPoly(var theObject:tV3Dobject;thePoly:tV3Dpoly;polynum:dword);
begin
// move(thePoly,theObject.polyEntriesList[polynum]^,sizeof(tV3DPoly));
theObject.poly[polynum]:=thePoly;
end;
function ExtractPoly(theObject:tV3Dobject;polyNum:dword):tV3Dpoly;
var poly:tV3Dpoly;
begin
poly:=theObject.poly[polynum];
ExtractPoly:=poly;
end;
procedure move_vertex(var Vrtx:tV3Dvertex;MoveX,MoveY,MoveZ:Single);
Begin
Vrtx.X:=Vrtx.X+MoveX;
Vrtx.Y:=Vrtx.Y+MoveY;
Vrtx.Z:=Vrtx.Z+MoveZ;
End;
function Rotate_Vertex(var Vctr:tV3Dvertex;CenterX,CenterY,CenterZ,AngleX,AngleY,AngleZ:Single):tV3Dvertex; {Angle=0..360}
Var RadX,RadY,RadZ,
SinX,SinY,SinZ,
CosX,CosY,CosZ,
TempX,TempY,TempZ,
Holder :Single;
aVctr:tV3Dvertex;
Begin
With Vctr do
Begin
TempX:=X-CenterX;
TempY:=Y-CenterY;
TempZ:=Z-CenterZ;
RadX:=AngleX*Theta;
RadY:=AngleY*Theta;
RadZ:=AngleZ*Theta;
SinX:=Sin (RadX);
CosX:=Cos (RadX);
SinY:=Sin (RadY);
CosY:=Cos (RadY);
SinZ:=Sin (RadZ);
CosZ:=Cos (RadZ);
Holder := TempY * CosY - TempZ * SinX;
TempZ := TempY * SinX + TempZ * CosX;
TempY := Holder;
Holder := TempX * CosY - TempZ * SinY;
TempZ := TempX * SinY + TempZ * CosY;
TempX := Holder;
Holder := TempX * CosZ - TempY * SinZ;
TempY := TempX * SinZ + TempY * CosZ;
TempX := Holder;
aVctr.X:=TempX+CenterX;
aVctr.Y:=TempY+CenterY;
aVctr.Z:=TempZ+CenterZ;
End;
Rotate_Vertex:=aVctr;
End;
function Rotate_Vertex_X(vctr:tV3Dvertex;angle:single):tV3Dvertex;
var v:tV3Dvertex;
begin
v:=vctr;
v.x:=vctr.x;
v.y:=cos(angle)*vctr.y - Sin(angle)*vctr.z;
v.z:=sin(angle)*vctr.y + Cos(angle)*vctr.z;
rotate_Vertex_X:=v;
end;
function Rotate_Vertex_Y(vctr:tV3Dvertex;angle:single):tV3Dvertex;
var v:tV3Dvertex;
begin
v:=vctr;
v.x:=cos(angle)*vctr.x - Sin(angle)*vctr.z;
v.y:=vctr.y;
v.z:=sin(angle)*vctr.x + Cos(angle)*vctr.z;
rotate_vertex_y:=v;
end;
function Rotate_Vertex_Z(vctr:tV3Dvertex;angle:single):tV3Dvertex;
var v:tV3Dvertex;
begin
v:=vctr;
v.x:=cos(angle)*vctr.x - Sin(angle)*vctr.y;
v.y:=sin(angle)*vctr.x + Cos(angle)*vctr.y;
v.z:=vctr.z;
rotate_Vertex_Z:=v;
end;
begin
end.