home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Equalizer BBS
/
equalizer-bbs-collection_2004.zip
/
equalizer-bbs-collection
/
DEMOSCENE-STUFF
/
PHRO.ZIP
/
VECTOR.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1995-12-30
|
14KB
|
412 lines
{ Vector Engine Source File }
{ PHRO! }
{ Phred/OTM }
{ achalfin@uceng.uc.edu }
{ DO NOT DISTRIBUTE THIS SOURCE FILE }
Unit Vector;
Interface
Const
cGouraudPoly = 1;
cPhongPoly = 2;
Procedure InitVectorRoutines(NumtoSort : Integer);
Procedure CloseVectorRoutines;
Procedure SelectEnable(Num, Ena : Byte; EnMap : Pointer);
Procedure Location(Num, tx, ty, tz, ax, ay, az : Longint);
Procedure LoadVectorObject(Data : Pointer; NumVecObjects, Shading : Byte);
Procedure DisplayVectorObjects(VPage : Word);
Procedure FreeVectorObject(Num : Byte);
Implementation
Uses Polygons;
Type
SCoord = Record { Screen coordinate }
x, y : Integer;
End;
LCoord = Record { Vertex & Normal coordinate }
x, y, z : Longint;
End;
PolygonDef = Record
p1, p2, p3 : Integer;
End;
TPolygonList = Array[0..1000] of PolygonDef;
PPolygonList = ^TPolygonList;
TCoordList = Array[0..1000] of LCoord;
PCoordList = ^TCoordList;
TScreenCoord = Array[0..1000] of SCoord;
PScreenCoord = ^TScreenCoord;
PSortRec = ^PhongSortRec;
PhongSortRec = Record
ZMid : Integer;
PolyType : Byte;
OwnerIndex : Byte;
Next : PSortRec; { 4 Bytes }
Index : Integer; { 2 Bytes }
Theta1, Phi1 : Byte; { 2 Bytes }
Theta2, Phi2 : Byte; { 2 Bytes }
Theta3, Phi3 : Byte; { 2 Bytes }
{ Exactly 16 bytes. For faster indexing }
End;
GSortRec = ^GouraudSortRec;
GouraudSortRec = Record
ZMid : Integer;
PolyType : Byte;
OwnerIndex : Byte;
Next : PSortRec; { 4 Bytes }
Index : Integer; { 2 Bytes }
C1, C2, C3 : Byte; { 3 Bytes }
Base : Byte;
T1, T2 : Byte; { 3 Bytes }
{ Exactly 16 bytes. For faster indexing }
End;
TRotateList = Array[0..5000] of Byte;
PRotateList = ^TRotateList;
TSortList = Array[0..3000] of PhongSortRec;
PSortList = ^TSortList;
TByteList = Array[0..255] of PSortRec;
PByteList = ^TByteList;
DotRec = Record
Viewer, XAxis, YAxis : Longint;
End;
tVectorObject = Record
LocalVert : pCoordList;
WorldVert : pCoordList;
ScreenVert : pScreenCoord;
Normals : pCoordList;
VertNorms : pCoordList;
Polygons : pPolygonList;
RotateList : pRotateList;
NumVert : Integer;
NumFacet : Integer;
ShadeType : Byte;
Enabled : Byte;
EnvMap : Pointer;
xt, yt, zt : Longint;
xa, ya, za : Word;
DotList : Array[0..1000] of DotRec;
End;
Var
SortList : PSortList;
VectorObjects : Array[0..3] of tVectorObject;
ObjectViewer : LCoord;
XAxis, YAxis : LCoord;
MSBList : PByteList;
MaxSort : Integer;
Procedure Location(Num, tx, ty, tz, ax, ay, az : Longint);
Begin
VectorObjects[Num].xa := ax;
VectorObjects[Num].ya := ay;
VectorObjects[Num].za := az;
VectorObjects[Num].xt := tx;
VectorObjects[Num].yt := ty;
VectorObjects[Num].zt := tz;
End;
Procedure InitVectorRoutines(NumtoSort : Integer);
Begin
MaxSort := NumToSort;
Getmem(SortList, NumToSort*Sizeof(PhongSortRec));
FillChar(VectorObjects, Sizeof(VectorObjects), 0);
End;
Procedure CloseVectorRoutines;
Begin
Freemem(SortList, MaxSort*Sizeof(PhongSortRec));
FillChar(VectorObjects, Sizeof(VectorObjects), 0);
End;
Procedure SelectEnable(Num, Ena : Byte; EnMap : Pointer);
Begin
VectorObjects[Num].Enabled := Ena;
VectorObjects[Num].EnvMap := EnMap;
End;
Procedure FreeVectorObject(Num : Byte);
Begin
With VectorObjects[Num] do
Begin
Freemem(LocalVert, NumVert*Sizeof(LCoord));
Freemem(WorldVert, NumVert*Sizeof(LCoord));
Freemem(VertNorms, NumVert*Sizeof(LCoord));
Freemem(ScreenVert, NumVert*Sizeof(SCoord));
Freemem(RotateList, NumFacet*Sizeof(Byte));
Freemem(Normals, NumFacet*Sizeof(LCoord));
Freemem(Polygons, NumFacet*Sizeof(PolygonDef));
End;
End;
{$F+}
{$L Mat.OBJ}
Procedure InitRotationMatrix(x, y, z : Integer); External;
Procedure Rotate(Var Local, World, Screen, Mask; Num : Word; X, Y, Z : Longint); External;
Procedure SingleRotate(Var Vertex; X, Y, Z : Word); External;
{$L ByteSort.Obj}
Procedure ByteSort(Var PolyList; Num : Word; Var List : PByteList); External;
{$L Dot.Obj}
Function DotProduct(Var V1, V2) : Longint; External;
{$F-}
Procedure LoadVectorObject(Data : Pointer; NumVecObjects, Shading : Byte);
Var
VecSeg, VecOfs : Word;
Temp : Integer;
Count : Integer;
Begin
VecSeg := Seg(Data^);
VecOfs := Ofs(Data^);
Temp := MemW[VecSeg:VecOfs]; { Read Flag }
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].NumVert := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
With VectorObjects[NumVecObjects] do
Begin
Getmem(LocalVert, NumVert*Sizeof(LCoord));
Getmem(WorldVert, NumVert*Sizeof(LCoord));
Getmem(VertNorms, NumVert*Sizeof(LCoord));
Getmem(ScreenVert, NumVert*Sizeof(SCoord));
End;
For Count := 0 to (VectorObjects[NumVecObjects].Numvert-1) do
Begin
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].LocalVert^[Count].x := Temp;
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].LocalVert^[Count].y := Temp;
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].LocalVert^[Count].z := Temp;
End;
VectorObjects[NumVecObjects].NumFacet := MemW[VecSeg:VecOfs];
Inc(VecOfs, 3); { Read numpolys, and vif }
With VectorObjects[NumVecObjects] do
Begin
Getmem(Polygons, NumFacet*Sizeof(PolygonDef));
Getmem(Normals, NumFacet*Sizeof(LCoord));
Getmem(RotateList, NumFacet*Sizeof(Byte));
End;
For Count := 0 to (VectorObjects[NumVecObjects].NumFacet-1) do
Begin
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].Polygons^[Count].p1 := Temp;
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].Polygons^[Count].p2 := Temp;
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].Polygons^[Count].p3 := Temp;
End;
For Count := 0 to (VectorObjects[NumVecObjects].NumFacet-1) do
Begin
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].Normals^[Count].x := Temp*2;
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].Normals^[Count].y := Temp*2;
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].Normals^[Count].z := Temp*2;
End;
For Count := 0 to (VectorObjects[NumVecObjects].Numvert-1) do
Begin
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].VertNorms^[Count].x := Temp*2;
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].VertNorms^[Count].y := Temp*2;
Temp := MemW[VecSeg:VecOfs];
Inc(VecOfs, 2);
VectorObjects[NumVecObjects].VertNorms^[Count].z := Temp*2;
End;
VectorObjects[NumVecObjects].ShadeType := Shading;
End;
Procedure CreateRotateList(Var SortCount : Integer; NumUse : Integer);
{ Creates the vertex mask table and the sort list }
{ Returns the number of polygons in the sort list }
Var
Count : Integer;
Dot : Longint;
SortStart : Integer;
Begin
SortStart := SortCount;
With VectorObjects[NumUse] do
Begin
For Count := 0 to (NumFacet-1) do
Begin
Dot := DotProduct(ObjectViewer, Normals^[Count]);
If Dot >= 0
Then Begin
With SortList^[SortCount] do
Begin
Index := Count;
Next := Nil;
OwnerIndex := NumUse;
PolyType := ShadeType;
End;
RotateList^[Polygons^[Count].p1] := 1;
RotateList^[Polygons^[Count].p2] := 1;
RotateList^[Polygons^[Count].p3] := 1;
SortCount := SortCount + 1;
End;
End;
For Count := 0 to (NumVert - 1) do
Begin
If RotateList^[Count] = 1
Then Begin
DotList[Count].Viewer := DotProduct(ObjectViewer, VertNorms^[Count]);
DotList[Count].XAxis := DotProduct(XAxis, VertNorms^[Count]);
DotList[Count].YAxis := DotProduct(YAxis, VertNorms^[Count]);
End;
End;
If ShadeType = cGouraudPoly
Then Begin
For Count := SortStart to (SortCount-1) do
Begin
With GouraudSortRec(SortList^[Count]) do
Begin
If DotList[Polygons^[Index].p1].Viewer > 0
Then C1 := Word(DotList[Polygons^[Index].p1].Viewer)*63 Shr 9
Else C1 := 0;
If DotList[Polygons^[Index].p2].Viewer > 0
Then C2 := Word(DotList[Polygons^[Index].p2].Viewer)*63 Shr 9
Else C2 := 0;
If DotList[Polygons^[Index].p3].Viewer > 0
Then C3 := Word(DotList[Polygons^[Index].p3].Viewer)*63 Shr 9
Else C3 := 0;
Base := 64*(SortList^[Count].Index And 1);
End;
End;
End
Else Begin
For Count := SortStart to (SortCount-1) do
Begin
With SortList^[Count] do
Begin
Theta1 := 128 + Integer(DotList[Polygons^[Index].p1].XAxis) Shr 2;
Phi1 := 128 + Integer(DotList[Polygons^[Index].p1].YAxis) Shr 2;
Theta2 := 128 + Integer(DotList[Polygons^[Index].p2].XAxis) Shr 2;
Phi2 := 128 + Integer(DotList[Polygons^[Index].p2].YAxis) Shr 2;
Theta3 := 128 + Integer(DotList[Polygons^[Index].p3].XAxis) Shr 2;
Phi3 := 128 + Integer(DotList[Polygons^[Index].p3].YAxis) Shr 2;
End;
End;
End;
End;
End;
Procedure GetZMidValues(Num : Integer);
Var
Count : Integer;
T1, T2, T3 : Integer;
Begin
For Count := 0 to (Num-1) do
Begin
T1 := VectorObjects[SortList^[Count].OwnerIndex].Polygons^[SortList^[Count].Index].p1;
T2 := VectorObjects[SortList^[Count].OwnerIndex].Polygons^[SortList^[Count].Index].p2;
T3 := VectorObjects[SortList^[Count].OwnerIndex].Polygons^[SortList^[Count].Index].p3;
SortList^[Count].ZMid :=
Word(VectorObjects[SortList^[Count].OwnerIndex].WorldVert^[T1].z +
VectorObjects[SortList^[Count].OwnerIndex].WorldVert^[T2].z +
VectorObjects[SortList^[Count].OwnerIndex].WorldVert^[T3].z)
Div 3;
End;
End;
Procedure DisplayPolygons(PgSeg : Word);
Var
Radix : Word;
OI : Integer;
T1, T2, T3 : Integer;
Begin
For Radix := 255 downto 0 do
While MSBList^[Radix] <> Nil do
Begin
OI := MSBList^[Radix]^.OwnerIndex;
T1 := VectorObjects[OI].Polygons^[MSBList^[Radix]^.Index].p1;
T2 := VectorObjects[OI].Polygons^[MSBList^[Radix]^.Index].p2;
T3 := VectorObjects[OI].Polygons^[MSBList^[Radix]^.Index].p3;
If MSBList^[Radix]^.PolyType = cGouraudPoly
Then Begin
GouraudClipPolygon(VectorObjects[OI].ScreenVert^[T1].x, VectorObjects[OI].ScreenVert^[T1].y,
VectorObjects[OI].ScreenVert^[T2].x, VectorObjects[OI].ScreenVert^[T2].y,
VectorObjects[OI].ScreenVert^[T3].x, VectorObjects[OI].ScreenVert^[T3].y,
GouraudSortRec(MSBList^[Radix]^).Base+GouraudSortRec(MSBList^[Radix]^).C1,
GouraudSortRec(MSBList^[Radix]^).Base+GouraudSortRec(MSBList^[Radix]^).C2,
GouraudSortRec(MSBList^[Radix]^).Base+GouraudSortRec(MSBList^[Radix]^).C3,
PgSeg);
End
Else Begin
PhongClipPolygon(VectorObjects[OI].ScreenVert^[T1].x, VectorObjects[OI].ScreenVert^[T1].y,
VectorObjects[OI].ScreenVert^[T2].x, VectorObjects[OI].ScreenVert^[T2].y,
VectorObjects[OI].ScreenVert^[T3].x, VectorObjects[OI].ScreenVert^[T3].y,
(MSBList^[Radix]^).Theta1, (MSBList^[Radix]^).Phi1,
(MSBList^[Radix]^).Theta2, (MSBList^[Radix]^).Phi2,
(MSBList^[Radix]^).Theta3, (MSBList^[Radix]^).Phi3,
PgSeg, VectorObjects[OI].EnvMap);
End;
MSBList^[Radix] := MSBList^[Radix]^.Next;
End;
End;
Procedure DisplayVectorObjects(VPage : Word);
{ Displays all Vector Objects with the enabled bit on }
Var
Count : Integer;
SortCount : Integer;
Begin
SortCount := 0;
For Count := 0 to 3 do
Begin
If VectorObjects[Count].Enabled = 1
Then Begin
With VectorObjects[Count] do
Begin
ObjectViewer.x := 0; ObjectViewer.y := 0; ObjectViewer.z := -512;
XAxis.x := -512; XAxis.y := 0; XAxis.z := 0;
YAxis.x := 0; YAxis.y := -512; YAxis.z := 0;
SingleRotate(ObjectViewer, (511-xa), (511-ya), (511-za));
SingleRotate(XAxis, (511-xa), (511-ya), (511-za));
SingleRotate(YAxis, (511-xa), (511-ya), (511-za));
CreateRotateList(SortCount, Count);
InitRotationMatrix(xa, ya, za);
Rotate(LocalVert^, WorldVert^, ScreenVert^, RotateList^, NumVert, xt, yt, zt);
End;
End;
End;
GetZMidValues(SortCount);
ByteSort(SortList^, SortCount, MSBList);
DisplayPolygons(VPage);
End;
Begin
End.