-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEngine3D.p
1960 lines (1608 loc) · 43.7 KB
/
Engine3D.p
1
unit Engine3D;{ versione beta 1.82 del 13 dicembre 1996 }interfaceuses types, quickdraw, binio, dialoglord4, Dream3Display_Tipi, Engine3D_Globals; const E3D_DiffuseDarkness = 0; E3D_DiffuseEvening = 1; E3D_DiffuseCreep = 2; E3D_DiffuseDay = 3; E3D_SpeedWalk = 1; E3D_SpeedRun = 2; E3D_SpeedFastRun = 3; E3D_DetailVariable = 4; E3D_DetailMedium = 2; E3D_DetailHigh = 1; AnimateOnly = 1; RotateAll = 2; DonTCare = 3; doNothing = 4; procedure Engine3D_ActivateClouds ( Activate : boolean);procedure Engine3D_ActivateLensFlare ( Activate : boolean);procedure Engine3D_ActivateMipMap ( Activate : boolean);procedure Engine3D_ChangePalette ( TheClut : ctabhandle);procedure Engine3D_DisposeEnvironment;procedure Engine3D_DrawTheFloor ( DrawIt : boolean);procedure Engine3D_GetCurrentPrefs (var currentDetailLevel : integer; var currentPrefs : family);procedure Engine3D_GetViewInfos ( var ThePoint : DoublePoint; var Direction : integer);procedure Engine3D_Init;procedure Engine3D_LoadData ( TheId : integer);procedure Engine3D_LoadEvent ( Id : integer);procedure Engine3D_LoadPrefs ( theFile : myFile);procedure Engine3D_MakeAllWallsVisible;procedure Engine3D_NewEnvironment ( Id : integer; Direction : char);procedure Engine3D_OpenDoor ( Id : integer);procedure Engine3D_SaveData ( TheId : integer);procedure Engine3D_SavePrefs ( theFile : myFile);procedure Engine3D_ScanMap;procedure Engine3D_Set3DPtrAndRect (The3DRect : rect; ThePtr : cwindowptr);procedure Engine3D_SetDetail ( NewDetail : integer);procedure Engine3D_SetDiffuseLight (TheLight : integer);procedure Engine3D_SetDisplayRect ( TheRect : rect);procedure Engine3D_SetFadeType (NewFadeType : integer);procedure Engine3D_SetInertia ( NewInertia : integer);procedure Engine3D_SetLightIndexes (Index3 : integer; Index2 : integer; Index1 : integer);procedure Engine3D_SetLightSource ( Id : integer);procedure Engine3D_SetMapPtrAndRect ( The3DRect : rect; ThePtr : cwindowptr);procedure Engine3D_SetMapSize ( NewSize : integer);procedure Engine3D_SetSpeed ( NewSpeed : integer);procedure Engine3D_SetVariableDetail ( MinDetail, MaxDetail : integer); procedure Engine3D_SetViewAngle ( TheViewAngle : integer);procedure Engine3D_StartEvent;procedure Engine3D_UnloadEvent;FUNCTION Engine3D_GetAngleKey : char;function Engine3D_GetBestClut : ctabhandle;function Engine3D_Scan (Instruction : integer) : integer;function Engine3D_SetViewDirection ( var Direction : point) : integer;function Engine3D_SetViewPoint (var ThePoint : DoublePoint; Engine : boolean) : integer;implementation{$R-}uses fixmath, toolutils, windows, qdoffscreen, resources, icons, palettes, AppleEvents, AERegistry, segload, memory, events, binio, cilindro, dreamtypes, lowlevel, Engine3D_DrawProc, Engine3D_CIconArray, Dream3Display_Tools, Engine3D_Rotate, Engine3D_Roofs, Engine3D_Boxes, Engine3D_DrawXLine, Engine3D_DrawFloor, Engine3D_NPC, Engine3D_Weather, Engine3D_PlaySequence; var Inertia : integer; MaxInertia : integer; DeltaDetail : boolean; DettaglioMin, DettaglioMax : integer; DoorEvent : boolean; DisplayRect : rect; mipMapActive : boolean; lensFlareActive : boolean; oldDbPt : doublePoint; {$S Engine3D_Utils}function Engine3D_GetAngleKey : char;var deltaH, deltaV : integer; tmp : char; begin with environment.viewPoint do begin deltaH := h - oldDbPt.h; deltaV := v - oldDbPt.v; end; if (deltaH = 0) and (deltaV = 0) then begin Engine3D_GetAngleKey := '5'; exit (Engine3D_GetAngleKey); end; if deltaH = 0 then if deltaV > 0 then begin Engine3D_GetAngleKey := '8'; exit (Engine3D_GetAngleKey); end else begin Engine3D_GetAngleKey := '2'; exit (Engine3D_GetAngleKey); end; if deltaV = 0 then if deltaH > 0 then begin Engine3D_GetAngleKey := '6'; exit (Engine3D_GetAngleKey); end else begin Engine3D_GetAngleKey := '4'; exit (Engine3D_GetAngleKey); end; if deltaH > 0 then begin if deltaV > 0 then begin if deltaH > deltaV then begin tmp := '6'; end else begin tmp := '8'; end; end else begin if deltaH > -deltaV then begin tmp := '6'; end else begin tmp := '2'; end; end; end else begin if deltaV > 0 then begin if deltaH > deltaV then begin tmp := '4'; end else begin tmp := '8'; end; end else begin if deltaH > -deltaV then begin tmp := '4'; end else begin tmp := '2'; end; end; end; Engine3D_GetAngleKey := tmp;end;{$S Engine3D_Utils}procedure Engine3D_GetCurrentPrefs (var currentDetailLevel : integer; var currentPrefs : family);begin currentDetailLevel := dettaglio; currentPrefs [1] := cloudsActive; currentPrefs [2] := mipMapActive; currentPrefs [3] := lensFlareActive;end; {$S Engine3D_Utils}function Engine3D_GetBestClut : ctabhandle;begin Engine3D_GetBestClut := environment.displayPalette;end;{$S Engine3D_Utils}procedure Engine3D_SetVariableDetail ( MinDetail, MaxDetail : integer); begin DettaglioMin := MinDetail; DettaglioMax := MaxDetail;end;{$S Engine3D_Utils}procedure Engine3D_ActivateMipMap ( Activate : boolean);begin mipMapActive := Activate;end;{$S Engine3D_Utils}procedure Engine3D_ActivateLensFlare ( Activate : boolean);begin lensFlareActive := Activate; thisLensFlareActive := activate and placedata [4];end;{$S Engine3D_Utils}procedure Engine3D_ActivateClouds ( Activate : boolean);begin cloudsActive := Activate;end;{$S Engine3D_Utils}procedure Engine3D_SetInertia ( NewInertia : integer);begin if NewInertia > 0 then MaxInertia := NewInertia;end;{$S Engine3D_Utils}procedure Engine3D_DrawTheFloor ( DrawIt : boolean);begin Environment.DrawTheFloors := DrawIt;end;{$S Engine3D_Utils}procedure FillDiscreteSinAndCos;const Pi = 3.1415926;var I : integer; HalfAngles : integer; begin HalfAngles := NAngles div 2; for I := 0 to NAngles - 1 do begin DiscreteSin [I] := round (Coefficient40 * sin (I * Pi / HalfAngles)); DiscreteCos [I] := round (Coefficient40 * cos (I * Pi / HalfAngles)); end;end;{$S Engine3D}procedure HandleDoorEvent;var I : integer; begin DoorEvent := false; for I := DoorN downto 1 do begin with DoorArray^ [I]^ do if Open then begin if CurrentFrame < NFrames then begin CurrentFrame := CurrentFrame + 1; DoorEvent := true; end; end else if CurrentFrame > 0 then begin CurrentFrame := CurrentFrame - 1; DoorEvent := true; if CurrentFrame = 0 then begin Base^ [CloseTexture].MustIBeShown := true; Base^ [OpenTexture].MustIBeShown := false; Base^ [DoorTexture].MustIBeShown := false; end; end; OpenDoor (DoorArray^ [I]); end;end;{$S Engine3D}function Engine3D_Scan (Instruction : integer) : integer;label 200, 201; var TheHandle : gdhandle; TmpGWorld : cgrafptr; Depth : integer; StartAt : integer; ContaDettaglio : integer; RecX : integer; StoreLight1, StoreLight2, StoreLight3 : integer; LightChanged : boolean; LocalY : integer; AColor : rgbcolor; {$S Engine3D}procedure RecScan ( StartAt : integer);var ThePolyL : Poly3D; TheCiconXL : integer; begin Depth := Depth + 1; ScanForX (StartAt, RecX, TheCiconXL, ThePolyL); if (ThePolyL.CIcon <> 0) then begin if (Depth <= Environment.RayThroughDepth) and (not (ThePolyL.FullMask)) then begin LocalY := CurrentMaxY; RecScan (StartAt); CurrentMaxY := LocalY; end; DrawXLine (RecX, TheCiconXL, ThePolyL); end;end;procedure ShowEventFrame;var TheRect : rect; begin with EnvEvt do begin if Environment.ViewAngle <> ClutId then if Environment.ViewAngle > ClutId then if Environment.ViewAngle = 179 then ThePos := ThePos - Environment.AmplitudeOffSet else ThePos := ThePos + Environment.AmplitudeOffSet else if Environment.ViewAngle = 0 then ThePos := ThePos + Environment.AmplitudeOffSet else ThePos := ThePos - Environment.AmplitudeOffSet; with TheRect do begin left := ThePos; top := 0; bottom := Dimensions.bottom; right := Dimensions.right + ThePos; end; PlotMaskPICT (FramePICT [CurrentFrame], FramePICTMask [CurrentFrame], Dimensions, TheRect); CurrentFrame := CurrentFrame - 1; ClutId := Environment.ViewAngle; end;end;{$S Engine3D}procedure ScanCoreTr;label 100, 101; var I, J, K : integer; ThePoly : Poly3D; TheRect : rect; TheFace : integer; TheFrame : integer; TheNPCPtr : NPCPtr; TheBaseRect : rect; TheMin, TheMin2, TheMin3 : integer; TStart, TEnd : integer; TheZ : longint; thePt : point; begin setrect (TheBaseRect, 0, 0, 63, 63); for I := PolyNTr downto 1 do begin ThePoly := PolysTr^ [I]; TheMin := Min (ThePoly.ProjCorner1.X, WindowXCenter); setrect (TheRect, ThePoly.ProjCorner0.X + WindowXCenter, ThePoly.YStart0 + WindowYCenter, ThePoly.ProjCorner1.X + WindowXCenter, ThePoly.YEnd0 + WindowYCenter); TStart := Max (TheRect.left, 0); TheMin3 := Min (TheRect.right, 2 * WindowXCenter - 1); TheZ := ThePoly.MiddleZ; if TheZ < 0 then TheZ := 0 else TheZ := bsr (TheZ, 4); while TStart < TheMin3 do begin while (ZBuffer [TStart - WindowXCenter] < ThePoly.MiddleZ) and (TStart < TheMin3) do TStart := TStart + 1; if TStart >= TheRect.right then goto 101; for J := Max (TStart - WindowXCenter, -WindowXCenter) to TheMin do if ZBuffer [J] < ThePoly.MiddleZ then goto 100; 100: TEnd := J + WindowXCenter; case ThePoly.PoType of NPCType : begin TheNPCPtr := NPCList^ [ThePoly.BaseRef]; TheFace := GetNPCFace (TheNPCPtr^.Direction); TheFrame := TheNPCPtr^.MoveFrame; if not (TheNPCPtr^.IsGhost) then if (Environment.DiffuseLight > 1) or (TheNPCPtr^.LightSource) or (TheZ < Environment.LightIndex1) then PlotHMaskPICT (TheNPCPtr^.MovePICT [TheFace, TheFrame], TheNPCPtr^.MoveMask [TheFace, TheFrame], TheNPCPtr^.Dimensions, TheRect, TStart, TEnd) else PlotHMaskPICT (TheNPCPtr^.MoveMask [TheFace, TheFrame], TheNPCPtr^.MoveMask [TheFace, TheFrame], TheNPCPtr^.Dimensions, TheRect, TStart, TEnd) else if (Environment.DiffuseLight > 1) or (TheNPCPtr^.LightSource) or (TheZ < Environment.LightIndex1) then PlotGhostPICT (TheNPCPtr^.MovePICT [TheFace, TheFrame], TheNPCPtr^.MoveMask [TheFace, TheFrame], TheNPCPtr^.Dimensions, TheRect, TStart, TEnd) else PlotGhostPICT (TheNPCPtr^.MoveMask [TheFace, TheFrame], TheNPCPtr^.MoveMask [TheFace, TheFrame], TheNPCPtr^.Dimensions, TheRect, TStart, TEnd); end; -1, 6 : begin K := TStart; TheMin2 := Min (TEnd, 2 * WindowXCenter - 1); TheFrame := TheRect.right - TheRect.left + 1; if ThePoly.Dir = 0 then while K <= TheMin2 do begin CurrentMaxY := 200; DrawXLine (K - WindowXCenter, bsr (fixdiv (K - TheRect.left, TheFrame), 10), ThePoly); K := K + Dettaglio; end else while K <= TheMin2 do begin CurrentMaxY := 200; DrawXLine (K - WindowXCenter, 64 - bsr (fixdiv (K - TheRect.left, TheFrame), 10), ThePoly); K := K + Dettaglio; end end; 7 : begin DrawTheUpper (ThePoly.Levels, TStart, TEnd); end; 8 : begin end; otherwise begin Base^ [ThePoly.BaseRef].Seen := true; if (Base^ [ThePoly.BaseRef].Light <> 0) or (TheZ < Environment.LightIndex1) then begin if (TheZ < Environment.LightIndex3) or (Base^ [ThePoly.BaseRef].Light = 3) then PlotHMaskPICT (ptr (ThePoly.CIcon), ptr (ThePoly.CIcon), TheBaseRect, TheRect, TStart, TEnd) else if TheZ < Environment.LightIndex2 then PlotHMaskPICT (ptr (longint (ThePoly.CIcon) + 4096), ptr (ThePoly.CIcon), TheBaseRect, TheRect, TStart, TEnd) else PlotHMaskPICT (ptr (longint (ThePoly.CIcon) + 8192), ptr (ThePoly.CIcon), TheBaseRect, TheRect, TStart, TEnd); end else begin PlotHMMaskPICT (integerptr (ThePoly.CIcon), TheBaseRect, TheRect, TStart, TEnd); end; if thisLensFlareActive and ThePoly.LightSource then begin thePt.h := bsr (ThePoly.ProjCorner0.X + ThePoly.ProjCorner1.X, 1); if zBuffer [thePt.h] >= ThePoly.MiddleZ then begin thePt.h := thePt.h + 160; thePt.v := 100 + ThePoly.parameter; doLensFlare (thePt); end; end; end; end; TStart := TEnd + 2; while (ZBuffer [TStart - WindowXCenter] < ThePoly.MiddleZ) and (TStart < TheMin3) do TStart := TStart + 1; end;101: end;end;{$S Engine3D}procedure ScanCore;label 100, 101; var I : integer; TheCiconX : integer; ThePoly : Poly3D; begin Depth := 0; case Dettaglio of 1 : begin for I := - WindowXCenter to WindowXCenter - 1 do begin CurrentLevel := 0; CurrentMaxY := 200; SetVMin (100); StartAt := 1; while (CurrentLevel < MaxVWall) and (CurrentMaxY > 0) do begin ScanForX (StartAt, I, TheCIconX, ThePoly); if ThePoly.CIcon <> 0 then begin if ThePoly.FullMask then DrawXLine (I, TheCIconX, ThePoly); end else begin goto 100; end; end;100: SuperDrawFloor (I); if Environment.DrawTheCeilings then SuperDrawCeiling (I); end; end; 2 : begin ContaDettaglio := 0; for I := - WindowXCenter to WindowXCenter - 1 do begin CurrentLevel := 0; CurrentMaxY := 200; SetVMin (100); if ContaDettaglio = 0 then begin StartAt := 1; while (CurrentLevel < MaxVWall) and (CurrentMaxY > 0) do begin ScanForX (StartAt, I, TheCIconX, ThePoly); if ThePoly.CIcon <> 0 then begin if ThePoly.FullMask then DrawXLine (I, TheCIconX, ThePoly); end else begin goto 101; end; end;101: ContaDettaglio := ContaDettaglio + 1; if ContaDettaglio = 2 then ContaDettaglio := 0; SuperDrawFloor2 (I); if Environment.DrawTheCeilings then SuperDrawCeiling2 (I); end else begin ContaDettaglio := ContaDettaglio + 1; if ContaDettaglio = 2 then ContaDettaglio := 0; end; end; end; end;end;begin if instruction = doNothing then goto 200; LightChanged := false; if DoorEvent then HandleDoorEvent; MoveAllNPC; if (Instruction <> AnimateOnly) or (DoorEvent) then begin if Instruction <> AnimateOnly then begin LastSeed := qd.randseed; if Inertia < MaxInertia then Inertia := Inertia + 1; end; RotatePolys; RotateRoofs; SortPolys; end else begin Inertia := 1; RotatePolysTr; end; RotateBoxes; qd.randseed := LastSeed; RotateNPC; SortPolysTr; 200: if not lockpixels (Environment.OffScreenLab^.portpixmap) then deathalert (erroutofmemory, -1); if instruction = doNothing then goto 201; if (Environment.DrawTheFloors) then begin RotateFloor; SortFloor; end; CallMe4Ceiling; getgworld (TmpGWorld, TheHandle); if Environment.FloorPictId <> 0 then if not lockpixels (Environment.FloorGWorld^.portpixmap) then deathalert (erroutofmemory, -1); if Environment.CeilingPictId <> 0 then if not lockpixels (Environment.CeilingGWorld^.portpixmap) then deathalert (erroutofmemory, -1); setgworld (Environment.OffScreenLab, nil); OffScreenAddr := ptr (Environment.OffScreenLab^.portpixmap^^.baseaddr); case Environment.FadeKind of 4 : begin with AColor do begin red := Environment.FadeParameter * 256; green := Environment.FadeParameter * 256; blue := Environment.FadeParameter * 256; end; rgbforecolor (AColor); fillrect (Environment.CommonRect, qd.black); forecolor (blackcolor); end; 5 : begin forecolor (whitecolor); fillrect (Environment.CommonRect, qd.black); forecolor (blackcolor); end; otherwise fillrect (Environment.CommonRect, qd.black); end; if Environment.GroundPictId <> 0 then CopyTheBack; if EnvEvt.CurrentFrame <> 0 then begin ShowEventFrame; if EnvEvt.DiffuseLight then begin StoreLight1 := Environment.LightIndex1; StoreLight2 := Environment.LightIndex2; StoreLight3 := Environment.LightIndex3; Environment.LightIndex1 := $7FFF; Environment.LightIndex2 := $7FFF; Environment.LightIndex3 := $7FFF; LightChanged := true; end; end; Depth := 0; ContaDettaglio := 0; if (DeltaDetail) then if Instruction <> AnimateOnly then Dettaglio := DettaglioMin else Dettaglio := DettaglioMax; ScanCore; ScanCoreTr; if Environment.WeatherId <> 0 then ShowWeather; if LightChanged then begin Environment.LightIndex1 := StoreLight1; Environment.LightIndex2 := StoreLight2; Environment.LightIndex3 := StoreLight3; LightChanged := false; end; setgworld (TmpGWorld, TheHandle);201: if (placeData[6] & (artificialLight < 1)) then fillrect (DisplayRect, qd.black) else if Environment.OffScreenLab <> Environment.ScreenGWorld then copybits (bitmapptr (Environment.OffScreenLab^.portpixmap^)^, bitmapptr (Environment.ScreenGWorld^.portpixmap^)^, Environment.CommonRect, DisplayRect, srccopy, nil); unlockpixels (Environment.OffScreenLab^.portpixmap); if instruction = doNothing then Engine3D_Scan := 0 else begin if Environment.FloorPictId <> 0 then unlockpixels (Environment.FloorGWorld^.portpixmap); if Environment.CeilingPictId <> 0 then unlockpixels (Environment.CeilingGWorld^.portpixmap); TheTick := tickcount; if Instruction <> DonTCare then Engine3D_Scan := Engine3D_MeetSomeOne else Engine3D_Scan := 0; end;end;{$S Engine3D_Utils}procedure LoadGroundAndCeiling;label 100, 101, 102, 103; var ThePict : pichandle; TheRect : rect; TheOldWorld : cgrafptr; TheGDHandle : gdhandle; Err : oserr; begin getgworld (TheOldWorld, TheGDHandle); with Environment do begin if GroundPictId <> 0 then begin ThePict := pichandle (mygetresource ('PICT', GroundPictId, true, true)); if ThePict = nil then begin erroralert (errMissingScenRes, 0); GroundPictId := 0; goto 100; end; TheRect := ThePict^^.picframe; Err := (newgworld (GroundGWorld, 8, BackGroundRect, DisplayPalette, nil, 0)); if (Err <> noerr) or (GroundGWorld = nil) then begin erroralert (erroutofmemory, Err); GroundPictId := 0; goto 100; end; if not (lockpixels (GroundGWorld^.portpixmap)) then begin erroralert (erroutofmemory, -1); GroundPictId := 0; goto 100; end; setgworld (GroundGWorld, nil); drawpicture (ThePict, BackGroundRect); releaseresource (handle (ThePict)); unlockpixels (GroundGWorld^.portpixmap); end;100: if FloorPictId <> 0 then begin ThePict := pichandle (mygetresource ('PICT', FloorPictId, true, true)); if ThePict = nil then begin erroralert (errMissingScenRes, 0); FloorPictId := 0; goto 101; end; TheRect := ThePict^^.picframe; TheRect.right := 64; Err := (newgworld (FloorGWorld, 8, TheRect, DisplayPalette, nil, 0)); if (Err <> noerr) or (FloorGWorld = nil) then begin erroralert (erroutofmemory, Err); FloorPictId := 0; goto 101; end; if not (lockpixels (FloorGWorld^.portpixmap)) then begin erroralert (erroutofmemory, -1); FloorPictId := 0; goto 101; end; setgworld (FloorGWorld, nil); drawpicture (ThePict, TheRect); releaseresource (handle (ThePict)); unlockpixels (FloorGWorld^.portpixmap); end;101: if CeilingPictId <> 0 then begin ThePict := pichandle (mygetresource ('PICT', CeilingPictId, true, true)); if ThePict = nil then begin erroralert (errMissingScenRes, 0); CeilingPictId := 0; goto 102; end; TheRect := ThePict^^.picframe; TheRect.left := 0; TheRect.right := 64; Err := (newgworld (CeilingGWorld, 8, TheRect, DisplayPalette, nil, 0)); if (Err <> noerr) or (CeilingGWorld = nil) then begin erroralert (erroutofmemory, Err); CeilingPictId := 0; goto 102; end; if not (lockpixels (CeilingGWorld^.portpixmap)) then begin erroralert (erroutofmemory, -1); CeilingPictId := 0; goto 102; end; setgworld (CeilingGWorld, nil); drawpicture (ThePict, TheRect); releaseresource (handle (ThePict)); unlockpixels (CeilingGWorld^.portpixmap); end;102: if (MapRect.bottom <> 0) and (MapRect.right <> 0) then begin Err := (newgworld (MapGWorld, 1, MapRect, DisplayPalette, nil, 0)); if (Err <> noerr) or (MapGWorld = nil) then begin erroralert (erroutofmemory, Err);{ MapPictId := 0;} goto 103; end; if MapPictId <> 0 then begin ThePict := pichandle (mygetresource ('PICT', MapPictId, true, true)); if ThePict = nil then begin erroralert (errMissingScenRes, 0); MapPictId := 0; goto 103; end; if not (lockpixels (MapGWorld^.portpixmap)) then begin erroralert (erroutofmemory, -1); MapPictId := 0; goto 103; end; setgworld (MapGWorld, nil); drawpicture (ThePict, MapRect); releaseresource (handle (ThePict)); unlockpixels (MapGWorld^.portpixmap); end else mapPictId := -1; end;103: end; setgworld (TheOldWorld, TheGDHandle);end;{$S Engine3D_Utils}procedure Engine3D_DisposeEnvironment;begin if not Empty then begin with Environment do begin if OffScreenLab <> nil then disposegworld (OffScreenLab); if GroundPICTId <> 0 then disposegworld (GroundGWorld); if CeilingPICTId <> 0 then disposegworld (CeilingGWorld); if FloorPICTId <> 0 then disposegworld (FloorGWorld); if MapPICTId <> 0 then disposegworld (MapGWorld); disposehandle (handle (SquareMap)); if DisplayPalette <> nil then disposectable (DisplayPalette); if DrawTheFloors then DisposeFloors; if WeatherId <> 0 then DisposeWeather; end; DisposeAllNPCS; DisposeAllObjects; DisposeCIcons; DisposeAllRoofs; DisposeDoors; DisposeBoxes; if EnvEvt.Id <> 0 then Engine3D_UnloadEvent; end; SetUpPICTS; Empty := true;end;{$S Engine3D_Utils}procedure Engine3D_SetFadeType (NewFadeType : integer);var TheFade : integer; begin Environment.FadeKind := NewFadeType; DisposeCIcons; TheFade := SetUpFade; FillCIconArray;end;{$S Engine3D_Utils}procedure SetDstRowTop;var I : longint; LocalRow : longint; begin LocalRow := DstRow; for I := 0 to 199 do DstRowTop^ [I] := I * LocalRow;end;{$S Engine3D_Utils}procedure Engine3D_Set3DPtrAndRect (The3DRect : rect; ThePtr : cwindowptr); begin with Environment do begin DisplayRect := The3DRect; ScreenGWorld := ThePtr; with CommonRect do begin top := 0; left := 0; bottom := DisplayRect.bottom - DisplayRect.top; right := DisplayRect.right - DisplayRect.left; end; end;end;{$S Engine3D_Utils}procedure Engine3D_SetMapPtrAndRect ( The3DRect : rect; ThePtr : cwindowptr); var Err : oserr; Uguali : boolean;begin with Environment do begin Uguali := true; if The3DRect.left <> MapRect.left then Uguali := false; if The3DRect.right <> MapRect.right then Uguali := false; if The3DRect.top <> MapRect.top then Uguali := false; if The3DRect.bottom <> MapRect.bottom then Uguali := false; if not Uguali then begin disposegworld (MapGWorld); Err := (newgworld (MapGWorld, 1, The3DRect, DisplayPalette, nil, 0)); if (Err <> noerr) or (MapGWorld = nil) then erroralert (erroutofmemory, Err); end; MapRect := The3DRect; ScreenMapGWorld := ThePtr; end;end;{$S Engine3D_Utils}procedure Engine3D_NewEnvironment ( Id : integer; Direction : char);var TheW : WeatherResourceHandle; TheFade : longint; ThePos : point; TheLPos : DoublePoint; {$S Engine3D_Utils}procedure InitVars;begin LastIcon := 0; LastSeed := 26674; with FloorSpaceRect do begin top := 0; left := 0; Bottom := Environment.FloorGWorld^.portrect.bottom; end; with CeilingSpaceRect do begin Top := 0; Bottom := 2; Left := 0; end;end;{$S Engine3D_Utils}procedure SetUpPos;begin ThePos := GetPosSet (Id, Direction); if (ThePos.h <> 0) and (ThePos.v <> 0) then begin with TheLpos do begin h := ThePos.v; v := ThePos.h; end; ThePos.h := Engine3D_SetViewPoint (TheLPos, false); end; case Direction of '3' : Engine3D_SetViewAngle (113); '2' : Engine3D_SetViewAngle (90); '1' : Engine3D_SetViewAngle (67); '6' : Engine3D_SetViewAngle (135); '4' : Engine3D_SetViewAngle (45); '9' : Engine3D_SetViewAngle (157); '8' : Engine3D_SetViewAngle (0); '7' : Engine3D_SetViewAngle (23); otherwise; end;end;procedure loadDatas;var theData2 : envDataHandle; begin TheData2 := EnvDataHandle (mygetresource (EnvDataResType, id, false, false)); if TheData2 <> nil then begin hlock (handle (TheData2)); with TheData2^^ do begin Environment.ViewPoint := ViewPoint; Environment.ViewAngle := ViewAngle; end; releaseresource (handle (TheData2)); end; Environment.ViewAngle := Environment.ViewAngle + 90; while Environment.ViewAngle > 179 do Environment.ViewAngle := Environment.ViewAngle - 180; while Environment.ViewAngle < 0 do Environment.ViewAngle := Environment.ViewAngle + 180;end;begin if not Empty then begin Engine3D_DisposeEnvironment; end; Empty := false; cursoranimate; GetEnvironment3D (Id, mipMapActive); GetSquareMap (Environment.SquareMapId); GetSqElementList; GetObjectMap (Environment.ObjectMapId); TheFade := SetUpFade; cursoranimate; GetObjectList; GetBase; cursoranimate; FillCIconArray; disposehandle (handle (Environment.ObjectMap)); InitOffScreen (Environment.OffScreenLab); LoadGroundAndCeiling; cursoranimate; Engine3D_LoadAllNPC (Environment.SquareMapId); InitVars; if not (lockpixels (Environment.OffScreenLab^.portpixmap)) then deathalert (erroutofmemory, -1); DstRow := loword (bitand (Environment.OffScreenLab^.portpixmap^^.rowbytes, $7FFF)); SetDstRowTop; SrcRow := DstRow - Environment.CommonRect.right + 64; cursoranimate; LoadAllRoofs (Environment.SquareMapId); cursoranimate; GetBoxes (Environment.SquareMapId); unlockpixels (Environment.OffScreenLab^.portpixmap); if Environment.DrawTheFloors then begin SetFloor (Environment.FloorCicnID, Environment.CeilingCicnId); SetFloorXAndY (Environment.MapHor, Environment.MapVer); end; if Environment.WeatherId <> 0 then begin TheW := GetWeather (Environment.WeatherId); WeatherResource2Weather (TheW); end; cursoranimate; RotatePolys; RotateRoofs; SortPolys; case Environment.FadeKind of 4 : begin TheKBlack := TheFade; TheDKBlack := TheFade + 256 * TheFade; TheTKBlack := TheFade + 256 * TheFade + $FFFF * TheFade; end; 5 : begin TheKBlack := 0; TheDKBlack := 0; TheTKBlack := 0; end; otherwise begin TheKBlack := Black4Fade; TheDKBlack := DBlack4Fade; TheTKBlack := TBlack4Fade; end; end; SetUpPos; if Environment.DiffuseLight > 0 then Environment.LightIndex1 := $7FFF; if Environment.DiffuseLight > 1 then Environment.LightIndex2 := $7FFF; if Environment.DiffuseLight > 2 then Environment.LightIndex3 := $7FFF; Engine3D_NPCInit; thisLensFlareActive := lensFlareActive and placedata [4]; if direction <> '5' then loadDatas;end;{$S Engine3D_Utils}procedure InitDiv64;var I : integer; begin Div64 := Div64Ptr (newptr (sizeof (Div64Array))); if Div64 = nil then deathalert (erroutofmemory, MemError); for I := 1 to 1023 do begin Div64^ [I] := fixdiv (CiconMaxH + 1, I); end;end;{$S Engine3D_Utils}procedure InitDstRowTop; begin DstRowTop := DstRowTopPtr (newptr (sizeof (DstRowTopArray))); if DstRowTop = nil then deathalert (erroutofmemory, MemError);end;{$S Engine3D_Utils}procedure Engine3D_SmallInit;begin Empty := true; Dettaglio := 1; Inertia := 1; Environment.Speed := 1; EnvEvt.CurrentFrame := 0; EnvEvt.Id := 0; DettaglioMin := 2; DettaglioMax := 1; DoorEvent := false; mipMapActive := true; cloudsActive := true; lensFlareActive := true;end;{$S Engine3D_Utils}procedure Engine3D_SavePrefs ( theFile : myFile);begin writeint (theFile, dettaglio); writebyte (theFile, byte (mipMapActive)); writebyte (theFile, byte (lensFlareActive)); writebyte (theFile, byte (cloudsActive));end;{$S Engine3D_Utils}procedure Engine3D_LoadPrefs ( theFile : myFile);begin Engine3D_SmallInit; readint (theFile, dettaglio); readbyte (theFile, byte (mipMapActive)); readbyte (theFile, byte (lensFlareActive)); readbyte (theFile, byte (cloudsActive));end;{$S Engine3D_Utils}procedure Engine3D_Init;begin Polys := PolyArrayPtr (newptr (sizeof (PolyArray))); if Polys = nil then deathalert (erroutofmemory, MemError); PolysTr := PolyArrayPtr (newptr (sizeof (PolyArray))); if PolysTr = nil then deathalert (erroutofmemory, MemError); BaseLevels := PolyBaseLevelsPtr (newptr (sizeof (PolyBaseLevelsArray))); if BaseLevels = nil then begin deathalert (erroutofmemory, MemError); end; Base := PolyBaseArrayPtr (newptr (sizeof (PolyBaseArray))); if Base = nil then begin deathalert (erroutofmemory, MemError); end; CIconIdsArray := CIconIdsArrayPtr (newptr (sizeof (TCIconIdsArray))); if CIconIdsArray = nil then begin deathalert (erroutofmemory, MemError); end; TrCIconIdsArray := CIconIdsArrayPtr (newptr (sizeof (TCIconIdsArray))); if TrCIconIdsArray = nil then begin deathalert (erroutofmemory, MemError); end; InitTools; InitCIconArray; InitFloorPoint; InitRoofs; InitBox; InitDiv64; InitDstRowTop; FillDiscreteSinAndCos; DeltaDetail := false; with CIconSpaceRect do begin top := 0; bottom := CIconMaxH + 1; end; setrect (ZeroRect, 0, 0, 1, 1); Engine3D_SmallInit;end;{$S Engine3D}function Engine3D_SetViewPoint (var ThePoint : DoublePoint; Engine : boolean) : integer;label 100, 101, 102; var Dh, Dv : integer; TheResult : integer; TheBool : boolean; deltaH, deltaV : longint; procedure controlPoint;label 100; function iCan ( h, v : integer) : boolean;var theNum : integer; begin if (h < 0) or (h > environment.mapHor) or (v < 0) or (v > environment.mapVer)then begin iCan := false; exit (iCan); end; theNum := environment.squareMap^^ [h, v]; if theNum = 0 then iCan := true else iCan := getSqElementInList (theNum).passable;end;begin with environment do begin hlock (handle (squareMap)); with thePoint do begin if iCan (h, v) then goto 100; if iCan (h, v - 1) then begin v := v - 1; goto 100; end; if iCan (h, v + 1) then begin v := v + 1; goto 100; end; if iCan (h - 1, v) then begin h := h - 1; goto 100; end; if iCan (h + 1, v) then begin h := h + 1; goto 100; end; genericdreamalert (30); end;100: hunlock (handle (squareMap)); end;end;begin TheResult := 0; if not Engine then begin controlPoint; with ThePoint do begin h := (h - 1) * 20; v := Environment.MapVer - v + 1; v := v * 20; end; end; with Environment do begin if not Engine then begin ViewPoint := ThePoint; Engine3D_SetViewPoint := theResult; exit (Engine3D_SetViewPoint); end; if ThePoint.h > ViewPoint.h then begin deltaH := ThePoint.h - ViewPoint.h; Dh := 1; end else if ThePoint.h < ViewPoint.h then begin Dh := -1; deltaH := ViewPoint.h - ThePoint.h; end else begin Dh := 0; deltaH := 0; end; if ThePoint.v > ViewPoint.v then begin deltaV := ThePoint.v - ViewPoint.v; Dv := 1; end else if ThePoint.v < ViewPoint.v then begin Dv := -1; deltaV := ViewPoint.v - ThePoint.v; end else begin Dv := 0; deltaV := 0; end; if deltaH < deltaV then begin repeat ViewPoint.h := ViewPoint.h + Dh; TheBool := not (InMap (ViewPoint, TheResult, false)); until (ViewPoint.h = ThePoint.h) or TheBool or (theResult = -12); if TheBool then begin ViewPoint.h := ViewPoint.h - Dh; Engine3D_SetViewPoint := TheResult; if TheResult = -11 then goto 100; exit (Engine3D_SetViewPoint); end else if theResult = -12 then goto 102;100: repeat ViewPoint.v := ViewPoint.v + Dv; TheBool := not (InMap (ViewPoint, TheResult, false)); until (ViewPoint.v = ThePoint.v) or TheBool or (theResult = -12); if TheBool then begin ViewPoint.v := ViewPoint.v - Dv; end; end else begin repeat ViewPoint.v := ViewPoint.v + Dv; TheBool := not (InMap (ViewPoint, TheResult, false)); until (ViewPoint.v = ThePoint.v) or TheBool or (theResult = -12); if TheBool then begin ViewPoint.v := ViewPoint.v - Dv; Engine3D_SetViewPoint := TheResult; if TheResult = -11 then goto 101; exit (Engine3D_SetViewPoint); end else if theResult = -12 then goto 102;101: repeat ViewPoint.h := ViewPoint.h + Dh; TheBool := not (InMap (ViewPoint, TheResult, false)); until (ViewPoint.h = ThePoint.h) or TheBool or (theResult = -12); if TheBool then begin ViewPoint.h := ViewPoint.h - Dh; end; end; end;102: if theResult = -12 then theResult := -11; Engine3D_SetViewPoint := TheResult;end;{$S Engine3D}function Engine3D_SetViewDirection (var Direction : point) : integer;label 111; var I : integer; NewPoint : DoublePoint; TheResult : integer; LocalInertia : integer; begin TheResult := 0; oldDbPt := environment.viewPoint; with Environment do begin if (Direction.h in [7, 9]) then LocalInertia := bsl (environment.Speed * Inertia, 1) else if gGameRunning then LocalInertia := environment.Speed * Inertia else localInertia := 0; for I := 1 to LocalInertia do begin case Direction.h of 2 : begin NewPoint.v := Viewpoint.v - round (StepValue * DiscreteCos [ViewAngle] / Coefficient40); NewPoint.h := Viewpoint.h + round (StepValue * DiscreteSin [ViewAngle] / Coefficient40); end; 4 : begin NewPoint.v := Viewpoint.v - round (StepValue * DiscreteSin [ViewAngle] / Coefficient40); NewPoint.h := Viewpoint.h - round (StepValue * DiscreteCos [ViewAngle] / Coefficient40); end; 6 : begin NewPoint.v := Viewpoint.v + round (StepValue * DiscreteSin [ViewAngle] / Coefficient40); NewPoint.h := Viewpoint.h + round (StepValue * DiscreteCos [ViewAngle] / Coefficient40); end; 7 : begin ViewAngle := ViewAngle + 1; if ViewAngle = NAngles then ViewAngle := 0; end; 8 : begin NewPoint.v := Viewpoint.v + round (StepValue * DiscreteCos [ViewAngle] / Coefficient40); NewPoint.h := Viewpoint.h - round (StepValue * DiscreteSin [ViewAngle] / Coefficient40); end; 9 : begin ViewAngle := ViewAngle - 1; if ViewAngle = -1 then ViewAngle := NAngles - 1; end; otherwise; end; if Direction.h div 2 = Direction.h / 2 then begin TheResult := Engine3D_SetViewPoint (NewPoint, true); if TheResult <> 0 then begin if (TheResult = -11) or (TheResult = 111) then begin TheResult := 0; end; goto 111; end; end; end; end;111: Direction.h := (Environment.ViewPoint.h + 10) div 20 + 1; Direction.v := Environment.MapVer - (Environment.ViewPoint.v - 10) div 20; Engine3D_SetViewDirection := TheResult;end;{$S Engine3D_Utils}procedure Engine3D_GetViewInfos ( var ThePoint : DoublePoint; var Direction : integer);begin with Environment do begin ThePoint.h := (ViewPoint.h + 10) div 20 + 1; thePoint.v := MapVer - (ViewPoint.v - 10) div 20; Direction := ViewAngle; end;end;{$S Engine3D_Utils}procedure Engine3D_SetSpeed (NewSpeed : integer);begin if NewSpeed > 0 then Environment.Speed := NewSpeed;end;{$S Engine3D_Utils}procedure Engine3D_SetDiffuseLight (TheLight : integer);begin if TheLight in [0..3] then if TheLight <> Environment.DiffuseLight then begin Environment.DiffuseLight := TheLight; DisposeCIcons; GetObjectMap (Environment.ObjectMapId); GetObjectList; GetBase; disposehandle (handle (Environment.ObjectMap)); FillCIconArray; end; Limite1 := (10 * $10000) div (bsl (Environment.LightIndex1, 3) + Distance40); if TheLight = 3 then begin Limite1 := $7FFFFFFF; Limite2 := $7FFFFFFF; Limite3 := $7FFFFFFF; end; if TheLight = 2 then begin Limite1 := $7FFFFFFF; Limite2 := $7FFFFFFF; Limite3 := (10 * $10000) div (bsl (Environment.LightIndex3, 3) + Distance40); end; if TheLight = 1 then begin Limite1 := $7FFFFFFF; Limite2 := (10 * $10000) div (bsl (Environment.LightIndex2, 3) + Distance40); Limite3 := (10 * $10000) div (bsl (Environment.LightIndex3, 3) + Distance40); end;end;{$S Engine3D_Utils}procedure Engine3D_SetDetail ( NewDetail : integer);begin if NewDetail in [1..3] then begin Dettaglio := NewDetail; DeltaDetail := false; end else DeltaDetail := true;end;{$S Engine3D_Utils}procedure Engine3D_SetMapSize ( NewSize : integer);begin Environment.MapSize := NewSize;end;{$S Engine3D_Utils}procedure Engine3D_SetLightIndexes (Index3 : integer; Index2 : integer; Index1 : integer);begin with Environment do begin LightIndex3 := Index3; LightIndex2 := Index2; LightIndex1 := Index1; end; Limite1 := (10 * $10000) div (bsl (Environment.LightIndex1, 3) + Distance40); Limite2 := (10 * $10000) div (bsl (Environment.LightIndex2, 3) + Distance40); Limite3 := (10 * $10000) div (bsl (Environment.LightIndex3, 3) + Distance40); end;{$S Engine3D_Utils}procedure Engine3D_SetLightSource ( Id : integer);var Tmp : LightSource; begin Tmp := GetLightSource (Id); Engine3D_SetLightIndexes (Tmp.Light100, Tmp.Light66, Tmp.Light33);end;{$S Engine3D_Utils}procedure Engine3D_SaveData ( TheId : integer);var TheData : SaveDataHandle; TheData2 : EnvDataHandle; i : integer; begin TheData := SaveDataHandle (newHandle (sizeof (SaveData))); if TheData = nil then deathalert (erroutofmemory, MemError); hlock (handle (TheData)); TheData^^.EnvironmentId := TheId; TheData^^.BaseN := BaseN; for i := 1 to baseN do theData^^.baseOfPoly [i] := base^ [i].seen; writeres (currentsavegamefile, TheId, '3Dsv', '', handle (TheData)); releaseresource (handle (TheData)); Thedata2 := EnvDataHandle (newHandle (sizeof (envData))); if TheData2 = nil then deathalert (erroutofmemory, MemError); hlock (handle (TheData2)); with TheData2^^ do begin ViewPoint := Environment.ViewPoint; ViewAngle := Environment.ViewAngle; end; writeres (currentsavegamefile, TheId, EnvDataResType, '', handle (TheData2)); releaseresource (handle (TheData2));end;{$S Engine3D}procedure Engine3D_ScanMap;var I : integer; TmpGWorld : cgrafptr; TheHandle : gdhandle; TheRect : rect; LocalMapSize : integer; PersonalX, PersonalY : integer; LocalVP : DoublePoint; LocalBase : PolyBaseArrayPtr; begin getgworld (TmpGWorld, TheHandle); if not lockpixels (Environment.MapGWorld^.portpixmap) then deathalert (erroutofmemory, -1); setgworld (Environment.MapGWorld, nil); with Environment.MapRect do begin PersonalX := (left + right) div 2; PersonalY := (top + bottom) div 2; end;{ if Environment.MapPictId = 0 then fillrect (Environment.MapRect, qd.black) else with Environment do copybits (bitmapptr (MapGWorld^.portpixmap^)^, bitmapptr (OffScreenLab^.portpixmap^)^, MapRect, CommonRect, srccopy, nil);} fillrect (Environment.MapRect, qd.black); forecolor (whitecolor); LocalMapSize := Environment.MapSize; LocalVP := Environment.ViewPoint; LocalBase := Base; for I := 1 to BaseN do if LocalBase^ [I].Seen then if LocalBase^ [I].PoType = 0 then with Environment do begin moveto (bsr (((Base^ [I].RealCorner [0].h - LocalVP.h) * LocalMapSize), 4) + PersonalX, bsr (((-Base^ [I].RealCorner [0].v + LocalVP.v) * LocalMapSize), 4) + PersonalY); lineto (bsr (((Base^ [I].RealCorner [1].h - LocalVP.h) * LocalMapSize), 4) + PersonalX, bsr (((-Base^ [I].RealCorner [1].v + LocalVP.v) * LocalMapSize), 4) + PersonalY); end else if LocalBase^ [I].PoType = 2 then with Environment do begin setrect (TheRect, bsr (((Base^ [I].RealCorner [0].h - LocalVP.h - 5) * LocalMapSize), 4) + PersonalX, bsr (((-Base^ [I].RealCorner [0].v + LocalVP.v - 6) * LocalMapSize), 4) + PersonalY, bsr (((Base^ [I].RealCorner [0].h - LocalVP.h + 6) * LocalMapSize), 4) + PersonalX, bsr (((-Base^ [I].RealCorner [0].v + LocalVP.v + 5) * LocalMapSize), 4) + PersonalY);{ TheCIcon := getcicon (Base^ [I].CIcon); if TheCIcon <> nil then begin plotcicon (TheRect, TheCIcon); disposecicon (TheCIcon); end else deathalert (errmissingscenres, 0);} end; moveto (PersonalX, PersonalY); line (-DiscreteSin [Environment.ViewAngle] div $8, -DiscreteCos [Environment.ViewAngle] div $8); setrect (TheRect, PersonalX - 1, PersonalY - 1, PersonalX + 2, PersonalY + 2); framerect (TheRect); forecolor (blackcolor); setgworld (TmpGWorld, TheHandle); copybits (bitmapptr (Environment.MapGWorld^.portpixmap^)^, bitmapptr (Environment.ScreenMapGWorld^.portpixmap^)^, Environment.MapRect, Environment.MapRect, srccopy, nil); unlockpixels (Environment.MapGWorld^.portpixmap);end;{$S Engine3D}procedure Engine3D_StartEvent;begin if EnvEvt.Id <> 0 then begin EnvEvt.CurrentFrame := EnvEvt.AnimationFrames; if EnvEvt.PosAngle = 1000 then EnvEvt.ThePos := WindowXCenter - EnvEvt.Dimensions.right div 2 else if EnvEvt.PosAngle = 1001 then EnvEvt.ThePos := trunc (abs (random) / $7FFF * (320 - EnvEvt.Dimensions.right)) else EnvEvt.ThePos := EnvEvt.PosAngle; EnvEvt.ClutId := Environment.ViewAngle; end;end;{$S Engine3D_Utils}procedure Engine3D_LoadEvent ( Id : integer);var I : integer; begin Engine3D_UnloadEvent; EnvEvt := GetEnvironmentEvent (Id); with EnvEvt do begin for I := 1 to AnimationFrames do begin FramePICT [I] := GetPICTOnPtr (FramePICTId [I], Dimensions); FramePICTMask [I] := GetPICTOnPtr (FramePICTMaskId [I], Dimensions); end; end;end; {$S Engine3D_Utils}procedure Engine3D_UnloadEvent;var I : integer;begin if EnvEvt.Id = 0 then exit (Engine3D_UnloadEvent); with EnvEvt do begin for I := 1 to AnimationFrames do begin DisposePICTOnPtr (FramePict [I]); DisposePICTOnPtr (FramePictMask [I]); end; CurrentFrame := 0; end; EnvEvt.Id := 0;end;{$S Engine3D}procedure Engine3D_OpenDoor ( Id : integer); var I : integer; begin for I := DoorN downto 1 do if DoorArray^ [I]^.Id = Id then begin DoorEvent := true; with DoorArray^ [I]^ do begin if not (Open) then begin Open := true; Base^ [CloseTexture].MustIBeShown := false; Base^ [OpenTexture].MustIBeShown := true; Base^ [DoorTexture].MustIBeShown := true; end else begin Open := false; end; end; end; exit (Engine3D_OpenDoor);end;{$S Engine3D_Utils}procedure Engine3D_LoadData ( TheId : integer);var TheData : SaveDataHandle; i : integer; begin TheData := SaveDataHandle (mygetresource ('3Dsv', TheId, false, false)); if TheData <> nil then begin hlock (handle (TheData)); for i := 1 to baseN do base^ [i].seen := theData^^.baseOfPoly [i]; releaseresource (handle (TheData)); end;end;{$S Engine3D_Utils}procedure Engine3D_SetDisplayRect ( TheRect : rect);begin DisplayRect := TheRect;end;{$S Engine3D_Utils}procedure Engine3D_ChangePalette ( TheClut : ctabhandle);var TheFlags : gworldflags; begin with Environment do begin TheFlags := updategworld (OffScreenLab, 8, CommonRect, TheClut, nil, 0);{ disposectable (DisplayPalette);} DisplayPalette := TheClut; end;end;{$S Engine3D_Utils}procedure Engine3D_MakeAllWallsVisible;var I : integer; begin for I := 1 to BaseN do with Base^ [I] do Seen := true;end;{$S Engine3D_Utils}procedure Engine3D_SetViewAngle ( TheViewAngle : integer);begin Environment.ViewAngle := TheViewAngle;end;end.