-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEngine3D_DrawFloor.p
1175 lines (1004 loc) · 29.4 KB
/
Engine3D_DrawFloor.p
1
unit Engine3D_DrawFloor;{ Dimensione delle variabili globali: 18 }interfaceuses types, quickdraw; const DBlack4Fade = $FFFF; TBlack4Fade = $FFFFFFFF; var cloudsActive : boolean;procedure SetFloorXAndY ( X, Y : integer);procedure SetFloor (FloorId, CeilingId : integer);procedure SetDstPtr ( DstPtr : ptr);procedure SetVMin ( VMin : integer); procedure RotateFloor;procedure SortFloor;function Max ( A, B : integer) : integer;function Min ( A, B : integer) : integer;procedure DrawFloorXLine ( TheX : longint);procedure SetFloorPoint;procedure InitFloorPoint;procedure DisposeFloors;procedure SuperDrawFloor ( TheX : longint);procedure SuperDrawFloor2 ( TheX : longint);procedure SuperDrawCeiling ( TheX : longint);procedure SuperDrawCeiling2 ( TheX : longint);procedure CallMe4Ceiling;var TheFloorWorld : cgrafptr; FloorX, FloorY : integer; Dettaglio : integer; TheKBlack : byte; TheDKBlack : integer; TheTKBlack : longint; Limite1, Limite2, Limite3 : longint;implementation{$R-}uses fixmath, toolutils, windows, qdoffscreen, icons, memory, resources, segload, AppleEvents, AERegistry, cilindro, dreamtypes, lowlevel, Dream3Display_Tipi, Dream3Display_Tools, Engine3D_Globals, Engine3D_CIconArray, Engine3D_Rotate, Engine3D_Roofs;const FloorDim = 20; FloorNum = 101; ScreenLastY = 199; LDistanceNeg = -Distance40 + 1; Middle1 = 50; Middle2 = 100; Middle3 = 150; D = 10; Y = 1000; mipMapD = 50; type FloorPointArray = array [1..FloorNum, 1..FloorNum] of DoublePoint; FloorPointPtr = ^FloorPointArray; FloorZArray = array [1..FloorNum, 1..FloorNum] of longint; FloorZArrayPtr = ^FloorZArray; TPFloor = record PStart, PEnd : DoublePoint; MiddleZ : longint; XDist, DeltaZ : longint; DeltaY : fixed; Side : integer; Dir : integer; AmINeg : boolean; end; PFloorArray = array [1..51 * 51] of TPFloor; PFloorPtr = ^PFloorArray; var FloorPoint : FloorPointPtr; FloorPoint2 : FloorPointPtr; FloorZ : FloorZArrayPtr; PFloor : PFloorPtr; NPFloor : integer; TheDstPtr : ptr; UpperDstPtr : ptr; TheVMIn : integer; TheFloorPtr1, TheFloorPtr2, TheFloorPtr3 : ptr; TheCeilingPtr1, TheCeilingPtr2, TheCeilingPtr3 : ptr; TheIndex1 : integer; TheFixDiv : ptr; WaterShift : integer; HorPtr : ptr; SHAmount, SVAmount : longint; ShiftCount : integer; {$S Engine3D}procedure SetVMin ( VMin : integer);begin TheVMin := VMin;end;{$S Engine3D}procedure SetDstPtr ( DstPtr : ptr);begin TheDstPtr := DstPtr;end;{$S Engine3D_FloorUtils}procedure SetFloorXAndY ( X, Y : integer);begin FloorX := X; FloorY := Y;end;{procedure InitFixDiv;var I, J : integer; SPtr : longintptr; begin TheFixDiv := newptr (64 * 128 * 4); if TheFixDiv = nil then deathalert (erroutofmemory, MemError); SPtr := longintptr (TheFixDiv); for J := 0 to 127 do for I := 0 to 63 do begin SPtr^ := fixdiv (I, J); SPtr := longintptr (longint (SPtr) + 4); end;end;}{$S Engine3D_FloorUtils}procedure InitFloorPoint;begin FloorPoint := FloorPointPtr (newptr (sizeof (FloorPointArray))); if FloorPoint = nil then deathalert (erroutofmemory, MemError); FloorPoint2 := FloorPointPtr (newptr (sizeof (FloorPointArray))); if FloorPoint2 = nil then deathalert (erroutofmemory, MemError); PFloor := PFloorPtr (newptr (sizeof (PFloorArray))); if PFloor = nil then deathalert (erroutofmemory, MemError); FloorZ := FloorZArrayPtr (newptr (sizeof (FloorZArray))); if FloorZ = nil then deathalert (erroutofmemory, MemError); SHAmount := 0; SVAmount := 0; if (Environment.ShiftH <> 0) or (Environment.ShiftH <> 0) then Environment.Clouds := true else Environment.Clouds := falseend;{$S Engine3D_FloorUtils}procedure SetFloorPoint; begin{ tmp := 1; WaterShift := Environment.WaterChaos; DoublePlaceDim := Environment.PlaceDim * 2; Fractal := Environment.FractalIntensity; for K := 255 downto 0 do SomeRandom [K] := random; K := 255; with Environment do for I := 1 to FloorX + 1 do for J := 1 to FloorY + 1 do begin with FloorPoint^ [I, J] do begin h := I * DoublePlaceDim - DoublePlaceDim - PlaceDim; v := MapVer * DoublePlaceDim - J * DoublePlaceDim + DoublePlaceDim + PlaceDim; end; end; if (Environment.FloorMapId = 0) or (WaterShift = 0) then for I := 1 to FloorX + 1 do for J := 1 to FloorY + 1 do begin Tmp := SomeRandom [K]; FloorZ^ [I, J] := Tmp * Fractal; K := K - 1; if K = -1 then K := 255; end else begin Tmp := Tmp * 128; hlock (handle (Environment.FloorMap)); TheMap := Environment.FloorMap^; for I := 1 to FloorX + 1 do for J := 1 to FloorY + 1 do FloorZ^ [I, J] := Tmp * TheMap^ [I, J]; hunlock (handle (Environment.FloorMap)); end;}end;{$S Engine3D_FastRotate}procedure RotateFloor;label 101, 102;const OutDist = 30000;var I, J : integer; Tmp, Tmp2, TmpA : DoublePoint; TheSin, TheCos : integer; Z1, Z2 : longint; WallHeight16 : longint; LocalPFloor : PFloorPtr; LocalFloor1, LocalFloor2 : FloorPointPtr; LocalNPFloor : integer; VPointH, VPointV : longint; TmpZ1, TmpZ2 : integer; begin if OddOrEven then begin WaterShift := WaterShift + 1; OddOrEven := false; end else OddOrEven := true; HorPtr := ptr (longint (OffScreenAddr) + WindowXCenter + Environment.HorizonLine * DstRow); TheVMin := 199; TheSin := DiscreteSin [Environment.ViewAngle]; TheCos := DiscreteCos [Environment.ViewAngle]; LocalPFloor := PFloor; LocalFloor1 := FloorPoint; LocalFloor2 := FloorPoint2; VPointH := Environment.ViewPoint.h; VPointV := Environment.ViewPoint.v; for I := FloorX + 1 downto 1 do for J := FloorY + 1 downto 1 do begin Tmp := LocalFloor1^ [I, J]; Tmp.h := Tmp.h - VPointH; Tmp.v := Tmp.v - VPointV; Tmp2.v := Tmp.v * TheCos - Tmp.h * TheSin; LocalFloor2^ [I, J].v := Tmp2.v; if Tmp2.v >= LDistanceNeg then begin Tmp2.h := Tmp.h * TheCos + Tmp.v * TheSin; LocalFloor2^ [I, J].h := (bsl (Tmp2.h, 9)) div (Tmp2.v + Distance40); end; end; LocalNPFloor := 0; WallHeight16 := bsl (Environment.StdWallHeight, 16); for I := FloorX downto 1 do begin for J := FloorY downto 1 do begin TmpA := LocalFloor2^ [I, J]; if (TmpA.v < LDistanceNeg) or (TmpA.v > OutDist) or (TmpA.h < -500) or (TmpA.h > 500) then goto 102; Z1 := TmpA.v; TmpZ1 := FloorZ^ [I, J]; TmpA.v := (WallHeight16 + TmpZ1) div (TmpA.v + Distance40) + WindowYCenter; LocalNPFloor := LocalNPFloor + 1; with LocalPFloor^ [LocalNPFloor] do begin PStart := TmpA; Tmp := LocalFloor2^ [I + 1, J]; if (Tmp.v < LDistanceNeg) or (Tmp.v > OutDist) or (abs (Tmp.h) > 500) then begin LocalNPFloor := LocalNPFloor - 1; goto 101; end; PEnd.h := Tmp.h; Z2 := Tmp.v; TmpZ2 := FloorZ^ [I + 1, J]; PEnd.v := (WallHeight16 + TmpZ2) div (Tmp.v + Distance40) + WindowYCenter; if PStart.h > PEnd.h then begin Tmp := PStart; PStart := PEnd; PEnd := Tmp; Dir := -1; end else Dir := 0; if (PStart.h > WindowXCenter) or (PEnd.h < -WindowXCenter) then begin LocalNPFloor := LocalNPFloor - 1; goto 101; end; Side := 0; MiddleZ := Z1 + Z2; XDist := PEnd.h - PStart.h; DeltaY := fixdiv (PEnd.v - PStart.v, XDist); if (TmpZ1 < 0) and (TmpZ2 < 0) then AmINeg := true else AmINeg := false; end;101: LocalNPFloor := LocalNPFloor + 1; with LocalPFloor^ [LocalNPFloor] do begin PStart := TmpA; Tmp := LocalFloor2^ [I, J + 1]; if (Tmp.v < LDistanceNeg) or (Tmp.v > OutDist) or (abs (Tmp.h) > 500) then begin LocalNPFloor := LocalNPFloor - 1; goto 102; end; PEnd.h := Tmp.h; Z2 := Tmp.v; TmpZ2 := FloorZ^ [I, J + 1]; PEnd.v := (WallHeight16 + TmpZ2) div (Tmp.v + Distance40) + WindowYCenter; if PStart.h > PEnd.h then begin Tmp := PStart; PStart := PEnd; PEnd := Tmp; Dir := -1; end else Dir := 0; if (PStart.h > WindowXCenter) or (PEnd.h < -WindowXCenter) then begin LocalNPFloor := LocalNPFloor - 1; goto 102; end; Side := 3; MiddleZ := Z1 + Z2; XDist := PEnd.h - PStart.h; DeltaY := fixdiv (PEnd.v - PStart.v, XDist); if (TmpZ1 < 0) and (TmpZ2 < 0) then AmINeg := true else AmINeg := false; end;102: end; end; NPFloor := LocalNPFloor;end;{$S Engine3D_FastRotate}procedure SortFloor;var LocalPFloor : PFloorPtr; {$S Engine3D_FastRotate}procedure QuickSortFloor ( S, D : integer);var I, J : integer; X, W, Z : TPFloor; XZ : longint; begin if S + 1 = D then begin if LocalPFloor^ [S].MiddleZ > LocalPFloor^ [D].MiddleZ then begin W := LocalPFloor^ [S]; LocalPFloor^ [S] := LocalPFloor^ [D]; LocalPFloor^ [D] := W; end; exit (QuickSortFloor); end else if S + 1 = D - 1 then begin X := LocalPFloor^ [S]; W := LocalPFloor^ [S + 1]; Z := LocalPFloor^ [D]; if X.MiddleZ < W.MiddleZ then if X.MiddleZ < Z.MiddleZ then if W.MiddleZ < Z.MiddleZ then exit (QuickSortFloor) else begin LocalPFloor^ [S + 1] := Z; LocalPFloor^ [D] := W; exit (QuickSortFloor) end else begin LocalPFloor^ [S] := Z; LocalPFloor^ [S + 1] := X; LocalPFloor^ [D] := W; exit (QuickSortFloor) end else if X.MiddleZ < Z.MiddleZ then begin LocalPFloor^ [S] := W; LocalPFloor^ [S + 1] := X; exit (QuickSortFloor) end else if W.MiddleZ < Z.MiddleZ then begin LocalPFloor^ [S] := W; LocalPFloor^ [S + 1] := Z; LocalPFloor^ [D] := X; exit (QuickSortFloor) end else begin LocalPFloor^ [S] := Z; LocalPFloor^ [D] := X; exit (QuickSortFloor) end; end; I := S; J := D; XZ := LocalPFloor^ [bsr (S + D, 1)].MIddleZ; repeat while LocalPFloor^ [I].MiddleZ < XZ do I := I + 1; while XZ < LocalPFloor^ [J].MiddleZ do J := J - 1; if I <= J then begin if I < J then begin W := LocalPFloor^ [I]; LocalPFloor^ [I] := LocalPFloor^ [J]; LocalPFloor^ [J] := W; end; I := I + 1; J := J - 1; end; until I > J; if S < J then QuickSortFloor (S, J); if I < D then QuickSortFloor (I, D);end;begin if NPFloor > 1 then begin LocalPFloor := PFloor; QuickSortFloor (1, NPFloor); end;end;{$S Engine3D}function Max ( A, B : integer) : integer;begin if A > B then Max := A else Max := B;end;{$S Engine3D}function Min ( A, B : integer) : integer;begin if A < B then Min := A else Min := B;end;{$S Engine3D_FloorUtils}procedure SetFloor (FloorId, CeilingId : integer);var OldWorld : cgrafptr; OldGD : gdhandle; TheCIcon : ciconhandle; ThePict : pichandle; I, J : integer; ShiftPtr : longintptr; SrcPtr : longintptr; TheRow : integer; err: OSErr; Tmp, Tmp0, Tmp1, Tmp2, Tmp3 : longint; IsCIcon : boolean; TheRect : rect; begin getgworld (OldWorld, OldGD); setrect (TheRect, 0, 0, 64, 64); IsCIcon := true; TheCIcon := getcicon (FloorId); if TheCIcon = nil then begin IsCIcon := false; ThePict := pichandle (mygetresource ('PICT', floorId, true, true)); if ThePict = nil then deathalert (errmissingscenres, FloorId); end; err := newgworld (TheFloorWorld, 8, TheRect, Environment.DisplayPalette, nil, 0); if (err <> noerr) or (TheFloorWorld = nil) then begin deathalert (erroutofmemory, err); end; if not (lockpixels (TheFloorWorld^.portpixmap)) then begin deathalert (erroutofmemory, -1); end; setgworld (TheFloorWorld, nil); if IsCIcon then begin plotcicon (TheRect, TheCIcon); disposecicon (TheCIcon); end else begin drawpicture (ThePict, TheRect); releaseresource (handle (ThePict)); end; setgworld (OldWorld, OldGD); TheRow := loword (bitand (TheFloorWorld^.portpixmap^^.rowbytes, $7FFF)) - 64; TheFloorPtr3 := newptr (4096); if TheFloorPtr3 = nil then deathalert (erroutofmemory, MemError); SrcPtr := longintptr (TheFloorWorld^.portpixmap^^.baseaddr); ShiftPtr := longintptr (TheFloorPtr3); for I := 0 to 63 do begin for J := 0 to 15 do begin ShiftPtr^ := SrcPtr^; ShiftPtr := longintptr (longint (ShiftPtr) + 4); SrcPtr := longintptr (longint (SrcPtr) + 4); end; SrcPtr := longintptr (longint (SrcPtr) + TheRow); end; TheFloorPtr1 := newptr (4096); if TheFloorPtr1 = nil then deathalert (erroutofmemory, MemError); ShiftPtr := LongintPtr (TheFloorPtr1); SrcPtr := LongintPtr (TheFloorPtr3); for I := 63 downto 0 do for J := 15 downto 0 do begin Tmp := SrcPtr^; Tmp0 := Array33^ [band (Tmp, $000000FF)]; Tmp1 := bsl (Array33^ [bsr (band (Tmp, $0000FF00), 8)], 8); Tmp2 := bsl (Array33^ [bsr (band (Tmp, $00FF0000), 16)], 16); Tmp3 := bsl (Array33^ [bsr (band (Tmp, $FF000000), 24)], 24); ShiftPtr^ := bor (bor (Tmp0, Tmp1), bor (Tmp2, Tmp3)); ShiftPtr := LongintPtr (longint (ShiftPtr) + 4); SrcPtr := LongintPtr (longint (SrcPtr) + 4); end; TheFloorPtr2 := newptr (4096); if TheFloorPtr2 = nil then deathalert (erroutofmemory, MemError); ShiftPtr := LongintPtr (TheFloorPtr2); SrcPtr := LongintPtr (TheFloorPtr3); for I := 63 downto 0 do for J := 15 downto 0 do begin Tmp := SrcPtr^; Tmp0 := Array66^ [band (Tmp, $000000FF)]; Tmp1 := bsl (Array66^ [bsr (band (Tmp, $0000FF00), 8)], 8); Tmp2 := bsl (Array66^ [bsr (band (Tmp, $00FF0000), 16)], 16); Tmp3 := bsl (Array66^ [bsr (band (Tmp, $FF000000), 24)], 24); ShiftPtr^ := bor (bor (Tmp0, Tmp1), bor (Tmp2, Tmp3)); ShiftPtr := LongintPtr (longint (ShiftPtr) + 4); SrcPtr := LongintPtr (longint (SrcPtr) + 4); end; if environment.mipMap then begin mipMap64 (TheFloorPtr2); mipMap64_2 (TheFloorPtr1); end; if Environment.DrawTheCeilings then begin getgworld (OldWorld, OldGD); IsCIcon := true; TheCIcon := getcicon (CeilingId); if TheCIcon = nil then begin IsCIcon := false; ThePict := pichandle (mygetresource ('PICT', ceilingId, true, true)); if ThePict = nil then deathalert (errmissingscenres, CeilingId); end; err := newgworld (TheFloorWorld, 8, TheRect, Environment.DisplayPalette, nil, 0); if (err <> noerr) or (TheFloorWorld = nil) then begin deathalert (erroutofmemory, err); end; if not (lockpixels (TheFloorWorld^.portpixmap)) then begin deathalert (erroutofmemory, -1); end; setgworld (TheFloorWorld, nil); if IsCIcon then begin plotcicon (TheRect, TheCIcon); disposecicon (TheCIcon); end else begin drawpicture (ThePict, TheRect); releaseresource (handle (ThePict)); end; setgworld (OldWorld, OldGD); TheRow := loword (bitand (TheFloorWorld^.portpixmap^^.rowbytes, $7FFF)) - 64; TheCeilingPtr3 := newptr (4096); if TheCeilingPtr3 = nil then deathalert (erroutofmemory, MemError); SrcPtr := longintptr (TheFloorWorld^.portpixmap^^.baseaddr); ShiftPtr := longintptr (TheCeilingPtr3); for I := 0 to 63 do begin for J := 0 to 15 do begin ShiftPtr^ := SrcPtr^; ShiftPtr := longintptr (longint (ShiftPtr) + 4); SrcPtr := longintptr (longint (SrcPtr) + 4); end; SrcPtr := longintptr (longint (SrcPtr) + TheRow); end; TheCeilingPtr1 := newptr (4096); if TheCeilingPtr1 = nil then deathalert (erroutofmemory, MemError); ShiftPtr := LongintPtr (TheCeilingPtr1); SrcPtr := LongintPtr (TheCeilingPtr3); for I := 63 downto 0 do for J := 15 downto 0 do begin Tmp := SrcPtr^; Tmp0 := Array33^ [band (Tmp, $000000FF)]; Tmp1 := bsl (Array33^ [bsr (band (Tmp, $0000FF00), 8)], 8); Tmp2 := bsl (Array33^ [bsr (band (Tmp, $00FF0000), 16)], 16); Tmp3 := bsl (Array33^ [bsr (band (Tmp, $FF000000), 24)], 24); ShiftPtr^ := bor (bor (Tmp0, Tmp1), bor (Tmp2, Tmp3)); ShiftPtr := LongintPtr (longint (ShiftPtr) + 4); SrcPtr := LongintPtr (longint (SrcPtr) + 4); end; TheCeilingPtr2 := newptr (4096); if TheCeilingPtr2 = nil then deathalert (erroutofmemory, MemError); ShiftPtr := LongintPtr (TheCeilingPtr2); SrcPtr := LongintPtr (TheCeilingPtr3); for I := 63 downto 0 do for J := 15 downto 0 do begin Tmp := SrcPtr^; Tmp0 := Array66^ [band (Tmp, $000000FF)]; Tmp1 := bsl (Array66^ [bsr (band (Tmp, $0000FF00), 8)], 8); Tmp2 := bsl (Array66^ [bsr (band (Tmp, $00FF0000), 16)], 16); Tmp3 := bsl (Array66^ [bsr (band (Tmp, $FF000000), 24)], 24); ShiftPtr^ := bor (bor (Tmp0, Tmp1), bor (Tmp2, Tmp3)); ShiftPtr := LongintPtr (longint (ShiftPtr) + 4); SrcPtr := LongintPtr (longint (SrcPtr) + 4); end; if environment.mipMap then begin mipMap64 (TheCeilingPtr2); mipMap64_2 (TheCeilingPtr1); end; end; disposegworld (TheFloorWorld); if Environment.DiffuseLight > 0 then TheIndex1 := Environment.LightIndex1 {$7FFF} else TheIndex1 := Environment.LightIndex1; if Environment.DiffuseLight = 0 then Limite1 := (10 * $10000) div (bsl (Environment.LightIndex1, 3) + Distance40) else Limite1 := 1; if Environment.DiffuseLight <= 1 then Limite2 := (10 * $10000) div (bsl (Environment.LightIndex2, 3) + Distance40) else Limite2 := 1; if Environment.DiffuseLight <= 2 then Limite3 := (10 * $10000) div (bsl (Environment.LightIndex3, 3) + Distance40) else Limite3 := 1;end;{$S Engine3D_FloorUtils}procedure DisposeFloors;begin disposeptr (TheFloorPtr1); disposeptr (TheFloorPtr2); disposeptr (TheFloorPtr3); if Environment.DrawTheCeilings then begin disposeptr (TheCeilingPtr1); disposeptr (TheCeilingPtr2); disposeptr (TheCeilingPtr3); end;end;{$S Engine3D}procedure SuperDrawFloor ( TheX : longint);var TheSin, TheCos : longint; ThePtr : ptr; I : longint; DstPtr : ptr; LocalRow : longint; LocalX, LocalZ : longint; X1, X, Z1, Z : longint; Index, Index2, IndexF : longint; LocalD40 : longint; begin LocalD40 := Distance40; ThePtr := TheFloorPtr3; LocalRow := DstRow; LocalX := bsl (band (Environment.ViewPoint.h, $0000003F), 1); LocalZ := bsl (band (Environment.ViewPoint.v, $0000003F), 1); DstPtr := ptr (longint (OffScreenAddr) + TheX + 199 * LocalRow + 160); TheSin := DiscreteSin [Environment.ViewAngle]; TheCos := DiscreteCos [Environment.ViewAngle]; IndexF := Max (TheVMin - 100, Limite1); Index := Max (IndexF, Limite3); I := 99; if I >= Index then while I <> Index do begin Z1 := (10 * $10000) div I - LocalD40; X1 := TheX * (Z1 + LocalD40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); DstPtr^ := ptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr := ptr (longint (DstPtr) - LocalRow); I := I - 1; end; if Index > IndexF then begin ThePtr := TheFloorPtr2; Index2 := Max (IndexF, Limite2); I := Index; if I > Index2 then while I <> Index2 do begin Z1 := (10 * $10000) div I - LocalD40; X1 := TheX * (Z1 + LocalD40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); DstPtr^ := ptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr := ptr (longint (DstPtr) - LocalRow); I := I - 1; end; if Index2 > IndexF then begin ThePtr := TheFloorPtr1; I := Index2; while I <> IndexF do begin Z1 := (10 * $10000) div I - LocalD40; X1 := TheX * (Z1 + LocalD40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); DstPtr^ := ptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr := ptr (longint (DstPtr) - LocalRow); I := I - 1; end; end; end;end;{$S Engine3D}procedure SuperDrawFloor2 ( TheX : longint);const Fill63 = $0000003F; Upper256 = $FF00; HowShift = 13; var TheSin, TheCos : longint; ThePtr : ptr; I : longint; DstPtr : integerptr; LocalRow : longint; LocalX, LocalZ : longint; X1, X, Z1, Z : longint; Tmp : integer; Index, Index2, IndexF : longint; LocalD40 : longint; begin LocalD40 := Distance40; ThePtr := TheFloorPtr3; LocalRow := DstRow; LocalX := bsl (band (Environment.ViewPoint.h, Fill63), 1); LocalZ := bsl (band (Environment.ViewPoint.v, Fill63), 1); DstPtr := integerptr (longint (OffScreenAddr) + TheX + 199 * LocalRow + 160); TheSin := DiscreteSin [Environment.ViewAngle]; TheCos := DiscreteCos [Environment.ViewAngle]; IndexF := Max (TheVMin - 100, Limite1); Index := Max (IndexF, Limite3); I := 99; if I >= Index then while I <> Index do begin Z1 := (10 * $10000) div I - LocalD40; X1 := TheX * (Z1 + LocalD40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); Tmp := integerptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr^ := bor (bsr (Tmp, 8), band (Tmp, $FF00)); DstPtr := integerptr (longint (DstPtr) - LocalRow); I := I - 1; end; if Index > IndexF then begin ThePtr := TheFloorPtr2; Index2 := Max (IndexF, Limite2); I := Index; if I > Index2 then while I <> Index2 do begin Z1 := (10 * $10000) div I - LocalD40; X1 := TheX * (Z1 + LocalD40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); Tmp := integerptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr^ := bor (bsr (Tmp, 8), band (Tmp, $FF00)); DstPtr := integerptr (longint (DstPtr) - LocalRow); I := I - 1; end; if Index2 > IndexF then begin ThePtr := TheFloorPtr1; I := Index2; while I <> IndexF do begin Z1 := (10 * $10000) div I - LocalD40; X1 := TheX * (Z1 + LocalD40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); Tmp := integerptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr^ := bor (bsr (Tmp, 8), band (Tmp, $FF00)); DstPtr := integerptr (longint (DstPtr) - LocalRow); I := I - 1; end; end; end;end;{$S Engine3D}procedure SuperDrawCeiling ( TheX : longint);var TheSin, TheCos : longint; ThePtr : ptr; I : longint; DstPtr : ptr; LocalRow : longint; LocalX, LocalZ, LocalX2, LocalZ2 : longint; X1, X, Z1, Z : longint; Index, Index2, IndexF : longint; H, H2 : longint; KBlack : byte; Tmp : byte; theMax : integer; begin ThePtr := TheCeilingPtr3; LocalRow := DstRow; DstPtr := ptr (longint (OffScreenAddr) + TheX + 160); TheSin := DiscreteSin [Environment.ViewAngle]; TheCos := DiscreteCos [Environment.ViewAngle]; IndexF := Max (100 - CurrentMaxY, Limite1); Index := Max (IndexF, Limite3); if not Environment.Clouds then begin H := (20 * Environment.MaxLevels - 10) * $10000; LocalX := bsl (band (Environment.ViewPoint.h, $0000003F), 1); LocalZ := bsl (band (Environment.ViewPoint.v, $0000003F), 1); for I := 99 downto Index do begin Z1 := H div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); DstPtr^ := ptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr := ptr (longint (DstPtr) + LocalRow); end; if Index > IndexF then begin Index2 := Max (IndexF, Limite2); ThePtr := TheCeilingPtr2; for I := Index - 1 downto Index2 do begin Z1 := H div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); DstPtr^ := ptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr := ptr (longint (DstPtr) + LocalRow); end; if Index2 > IndexF then begin ThePtr := TheCeilingPtr1; for I := Index2 - 1 downto IndexF do begin Z1 := H div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); Tmp := ptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr^ := ptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr := ptr (longint (DstPtr) + LocalRow); end; end; end; KBlack := TheKBlack; theMax := max (100 - CurrentMaxY, 0); for I := IndexF - 1 downto theMax do begin DstPtr^ := KBlack; DstPtr := ptr (longint (DstPtr) + LocalRow); end; end else if cloudsActive then begin H2 := (20 * Environment.MaxLevels + 30) * $10000; H := (20 * Environment.MaxLevels - 10) * $10000; LocalX := band (SHAmount, $0000003F); LocalZ := band (SVAmount, $0000003F); LocalX2 := band (SHAmount + 32, $0000003F); LocalZ2 := band (SVAmount + 32, $0000003F); IndexF := Max (100 - CurrentMaxY, 0); if IndexF < 99 then begin I := 99; while I <> IndexF do begin Z1 := H div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 16) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 16) + LocalZ, $0000003F); Tmp := ptr (longint (ThePtr) + X + bsl (Z, 6))^; if Tmp <> 0 then DstPtr^ := Tmp else begin Z1 := H2 div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 16) + LocalX2, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 16) + LocalZ2, $0000003F); Tmp := ptr (longint (ThePtr) + X + bsl (Z, 6))^; if Tmp <> 0 then DstPtr^ := Tmp; end; DstPtr := ptr (longint (DstPtr) + LocalRow); I := I - 1; end; end; end;end;{$S Engine3D}procedure SuperDrawCeiling2 ( TheX : longint);var TheSin, TheCos : longint; ThePtr : ptr; I : longint; DstPtr : integerptr; LocalRow : longint; LocalX, LocalZ, LocalX2, LocalZ2 : longint; X1, X, Z1, Z : longint; Tmp : integer; Index, Index2, IndexF : longint; H, H2 : longint; KBlack : integer; Tmp2 : byte; TmpP : ptr; theMax : integer; begin ThePtr := TheCeilingPtr3; LocalRow := DstRow; DstPtr := integerptr (longint (OffScreenAddr) + TheX + 160); TheSin := DiscreteSin [Environment.ViewAngle]; TheCos := DiscreteCos [Environment.ViewAngle]; IndexF := Max (100 - CurrentMaxY, Limite1); Index := Max (IndexF, Limite3); if not Environment.Clouds then begin H := (20 * Environment.MaxLevels - 10) * $10000; LocalX := bsl (band (Environment.ViewPoint.h, $0000003F), 1); LocalZ := bsl (band (Environment.ViewPoint.v, $0000003F), 1); for I := 99 downto Index do begin Z1 := H div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); Tmp := integerptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr^ := bor (bsr (Tmp, 8), band (Tmp, $FF00)); DstPtr := integerptr (longint (DstPtr) + LocalRow); end; if Index > IndexF then begin Index2 := Max (IndexF, Limite2); ThePtr := TheCeilingPtr2; for I := Index - 1 downto Index2 do begin Z1 := H div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); Tmp := integerptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr^ := bor (bsr (Tmp, 8), band (Tmp, $FF00)); DstPtr := integerptr (longint (DstPtr) + LocalRow); end; if Index2 > IndexF then begin ThePtr := TheCeilingPtr1; for I := Index2 - 1 downto IndexF do begin Z1 := H div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 13) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 13) + LocalZ, $0000003F); Tmp := integerptr (longint (ThePtr) + X + bsl (Z, 6))^; DstPtr^ := bor (bsr (Tmp, 8), band (Tmp, $FF00)); DstPtr := integerptr (longint (DstPtr) + LocalRow); end; end; end; KBlack := TheDKBlack; theMax := max (100 - CurrentMaxY, 0); for I := IndexF - 1 downto theMax do begin DstPtr^ := KBlack; DstPtr := integerptr (longint (DstPtr) + LocalRow); end; end else if cloudsActive then begin H2 := (20 * Environment.MaxLevels + 30) * $10000; H := (20 * Environment.MaxLevels - 10) * $10000; LocalX := band (SHAmount, $0000003F); LocalZ := band (SVAmount, $0000003F); LocalX2 := band (SHAmount + 32, $0000003F); LocalZ2 := band (SVAmount + 32, $0000003F); IndexF := Max (100 - CurrentMaxY, 0); if IndexF < 99 then begin I := 99; while I <> IndexF do begin Z1 := H div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 16) + LocalX, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 16) + LocalZ, $0000003F); TmpP := ptr (longint (ThePtr) + X + bsl (Z, 6)); if TmpP^ <> 0 then begin Tmp2 := integerptr (TmpP)^; DstPtr^ := bor (bsr (Tmp2, 8), band (Tmp2, $FF00)); end else begin Z1 := H2 div I - Distance40; X1 := TheX * (Z1 + Distance40) div ($200); Z := band (bsr (TheCos * X1 - TheSin * Z1, 16) + LocalX2, $0000003F); X := band (bsr (TheSin * X1 + TheCos * Z1, 16) + LocalZ2, $0000003F); TmpP := ptr (longint (ThePtr) + X + bsl (Z, 6)); if TmpP^ <> 0 then begin Tmp2 := integerptr (TmpP)^; DstPtr^ := bor (bsr (Tmp2, 8), band (Tmp2, $FF00)); end; end; DstPtr := integerptr (longint (DstPtr) + LocalRow); I := I - 1; end; end; end;end;procedure CallMe4Ceiling;begin SHAmount := SHAmount + Environment.ShiftH; SVAmount := SVAmount + Environment.ShiftV;end;end.