BaseGraph.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:13k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  @Abstract(Base Graphics Unit)
  3.  (C) 2006 George "Mirage" Bakhtadze. <a href="http://www.casteng.com">www.casteng.com</a> <br>
  4.  The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
  5.  Unit contains abstract classes for drawing 2D graphics
  6. *)
  7. {$Include GDefines.inc}
  8. unit BaseGraph;
  9. interface
  10. uses
  11.   TextFile, 
  12.   BaseTypes, Basics, BaseClasses, Base3D, BaseMsg;
  13. const
  14.   // Initial Z value for 2D primitives
  15.   ClearingZ = 1.0;
  16. type
  17.   // Font style flags
  18.   TFontStyleFlags = (fsBold, fsItalic, fsUnderline, fsStrikeOut);
  19.   // Font style
  20.   TFontStyle = set of TFontStyleFlags;
  21.   // Graphics-related messages base class
  22.   TGraphMessage = class(TMessage)
  23.   end;
  24.   // 2D transformations class
  25.   T2DTransform = Base3D.TMatrix4s;                       // ToDo: Reduce to 3x3 or 2x2?
  26.   // Rectangular viewport
  27.   TViewport = record
  28.     Left, Top, Right, Bottom: Single;
  29.   end;
  30.   // Base font class
  31.   TFont = class(BaseClasses.TItem)
  32.     // Font face name
  33.     FaceName: string;
  34.     // Font style
  35.     Style: TFontStyle;
  36.     // Font size
  37.     Size: Single;
  38.     // Fills <b>Width</b> and <b>Height</b> with width and height of the given string printed with the font
  39.     procedure GetTextExtent(const Text: string; out Width, Height: Single); virtual; abstract;
  40.   end;
  41.   // Base class for bitmap (texture) based font
  42.   TBaseBitmapFont = class(TFont)
  43.     // UV map which points to character images on the texture
  44.     UVMap: BaseTypes.TUVMap;
  45.     // Number of entries in the UV map
  46.     TotalUVs: Longword;
  47.     // Code to character map
  48.     CharMap: BaseTypes.TCharMap;
  49.     // Total characters
  50.     TotalCharacters: Longword;
  51.     // Format of the bitmap (texture)
  52.     BitmapFormat: Integer;
  53.     // Bitmap data pointer
  54.     Bitmap: Pointer;
  55.     // Scale of the font by X
  56.     XScale: Single;
  57.     // Scale of the font by Y
  58.     YScale: Single;
  59.     constructor Create(AManager: BaseClasses.TItemsManager); override;
  60.     // Sets UV and character maps
  61.     procedure SetMapResources(const AUVMap: BaseTypes.TUVMap; ATotalUVs: Integer; const ACharMap: BaseTypes.TCharMap; ATotalCharacters: Integer); virtual;
  62.     // Sets scale
  63.     procedure SetScale(AXScale, AYScale: Single); virtual;
  64.     procedure GetTextExtent(const Text: string; out Width, Height: Single); override;
  65.   end;
  66.   // True type font class
  67.   TTrueTypeFont = class(TFont)
  68.     Charset: Integer;
  69.     Monospaced: Boolean;
  70.   end;
  71.   // Bitmap class
  72.   TBitmap = class
  73.     // Bitmap width
  74.     Width: Integer;
  75.     // Bitmap height
  76.     Height: Integer;
  77.     // Bitmap data pointer
  78.     Data: Pointer;
  79.   end;
  80.   // Base class to handle 2D output
  81.   TScreen = class(TSubsystem)
  82.   private
  83.     // Screen width
  84.     FWidth: Single;
  85.     // Screen height
  86.     FHeight: Single;
  87.   public
  88.     // Current drawing color
  89.     Color: BaseTypes.TColor;
  90.     // Current drawing font
  91.     Font: TFont;
  92.     // Current drawing UV map
  93.     UV: BaseTypes.TUV;
  94.     // Current drawing bitmap
  95.     Bitmap: TBitmap;
  96.     // Current position by X
  97.     CurrentX,
  98.     // Current position by Y
  99.     CurrentY,
  100.     // Current position by X in local corrdinate system
  101.     LocalX,
  102.     // Current position by Y in local corrdinate system
  103.     LocalY: Single;
  104.     // Current position by Z (depth) (used for correct primitive order imitation via zbuffer)
  105.     CurrentZ: Single;
  106.     // Current transform. Point of origin, rotation, scaling
  107.     Transform: T2DTransform;
  108.     // Current clipping viewport in local coordinates
  109.     Viewport: TViewport;
  110.     constructor Create;
  111.     // Resets the screen
  112.     procedure Reset; virtual;
  113.     // Message handler
  114.     procedure HandleMessage(const Msg: TMessage); override;
  115.     // Set current viewport
  116.     procedure SetViewport(ALeft, ATop, ARight, ABottom: Single);
  117.     // Transforms a point with current transform
  118.     procedure TransformPoint(var X, Y: Single);
  119.     // Transforms a point without translation
  120.     procedure RotateScalePoint(var X, Y: Single);
  121.     // Transforms a point with the given transform
  122.     procedure TransformPointWith(const ATransform: T2DTransform; var X, Y: Single);
  123.     // Transforms a point with the given transform without translation
  124.     procedure RotateScalePointWith(const ATransform: T2DTransform; var X, Y: Single);
  125.     // Set current drawing color
  126.     procedure SetColor(const AColor: BaseTypes.TColor);
  127.     // Set current font
  128.     procedure SetFont(const AFont: TFont); virtual;
  129.     // Set current UV frame
  130.     procedure SetUV(const AUV: BaseTypes.TUV);
  131.     // Set current bitmap
  132.     procedure SetBitmap(const ABitmap: TBitmap);
  133.     // Moves current position
  134.     procedure MoveTo(const X, Y: Single); virtual;
  135.     // Draws a line from current position to the given point and moves current position to the given point
  136.     procedure LineTo(const X, Y: Single); virtual; abstract;
  137.     // Moves current position
  138.     procedure MoveToVec(const Vec: TVector3s);
  139.     // Draws a line from current position to the given point and moves current position to the given point
  140.     procedure LineToVec(const Vec: TVector3s); 
  141.     // Draws a line between the given points
  142.     procedure Line(X1, Y1, X2, Y2: Single); virtual;
  143.     // Draws a rectangle with the given coordinates
  144.     procedure Rectangle(X1, Y1, X2, Y2: Single); virtual;
  145.     // Draws a filled rectangle with the given coordinates
  146.     procedure Bar(X1, Y1, X2, Y2: Single); virtual; abstract;
  147.     // Draw the given text string at current position
  148.     procedure PutText(const Str: string); virtual; abstract;
  149.     // Draw the given text string at the specified position
  150.     procedure PutTextXY(const X, Y: Single; const Str: string); virtual; abstract;
  151.     // Resets current viewport and transform
  152.     procedure ResetViewport; virtual;
  153.     // Clears and resets the screen
  154.     procedure Clear; virtual;
  155.     // Screen width
  156.     property Width: Single read FWidth;
  157.     // Screen height
  158.     property Height: Single read FHeight;
  159.   end;
  160.   // Returns list of classes introduced by the unit
  161.   function GetUnitClassList: TClassArray;
  162.   // Clips the given line with Cohen-Sutherland algorithm and returns True if at least some part of the line is visible
  163.   function ClipLine(var X1, Y1: Single; var X2, Y2: Single; VPLeft, VPTop, VPRight, VPBottom: Single): Boolean;
  164.   // Clips the given colored and textured line with Cohen-Sutherland algorithm and returns True if at least some part of the line is visible
  165.   function ClipLineColorTex(var X1, Y1, U1, V1: Single; var Color1: BaseTypes.TColor; var X2, Y2, U2, V2: Single; var Color2: BaseTypes.TColor; VPLeft, VPTop, VPRight, VPBottom: Single): Boolean;
  166. var
  167.   // Screen reference which should be used for 2D output
  168.   Screen: TScreen;
  169. implementation
  170. function GetUnitClassList: TClassArray;
  171. begin
  172.   Result := GetClassList([TFont]);
  173. end;
  174. function ClipLineColorTex(var X1, Y1, U1, V1: Single; var Color1: BaseTypes.TColor; var X2, Y2, U2, V2: Single; var Color2: BaseTypes.TColor; VPLeft, VPTop, VPRight, VPBottom: Single): Boolean;
  175. begin
  176.   Result := ClipLine(X1, Y1, X2, Y2, VPLeft, VPTop, VPRight, VPBottom);
  177. end;
  178. function ClipLine(var X1, Y1: Single; var X2, Y2: Single; VPLeft, VPTop, VPRight, VPBottom: Single): Boolean;
  179.   function GetCode(X, Y: Single): Integer;
  180.   begin
  181.     Result := Ord(X < VPLeft)       or Ord(X > VPRight)  shl 1 or
  182.               Ord(Y < VPTop)  shl 2 or Ord(Y > VPBottom) shl 3;
  183.   end;
  184. var i, t, Code1, Code2, SwCount: Integer; DX, DY, DXDY, DYDX, ts: Single;
  185. begin
  186.   Code1 := GetCode(X1, Y1);
  187.   Code2 := GetCode(X2, Y2);
  188.   Result := True;
  189.   if Code1 or Code2 = 0 then Exit;                                      // Completely visible
  190.   Result := False;
  191.   if Code1 and Code2 <> 0 then Exit;                                    // Completely invisible
  192.   DX := X2 - X1;
  193.   DY := Y2 - Y1;
  194.   DYDX := 0;
  195.   DXDY := 0;
  196.   if DX <> 0 then DYDX := DY / DX else if dy = 0 then Exit;
  197.   if DY <> 0 then DXDY := DX / DY;
  198.   SwCount := 0;
  199.   i := 4;
  200.   repeat
  201.     if Code1 and Code2 <> 0 then begin Result := False; Break; end;     // Invisible
  202.     if Code1 or Code2 = 0 then begin Result := True; Break; end;        // Visible
  203.     if Code1 = 0 then begin
  204.       t := Code1; Code1 := Code2; Code2 := t;                           // Swap Code1 and Code2
  205.       ts := X1; X1 := X2; X2 := ts;
  206.       ts := Y1; Y1 := Y2; Y2 := ts;
  207.       Inc(SwCount);
  208.     end;
  209.     if Code1 and 1 > 0 then begin                                       // Check intersection with the left side
  210.        Y1 := Y1 + DYDX * (VPLeft - X1);
  211.        X1 := VPLeft;
  212.     end else if Code1 and 2 > 0 then begin                              // Check intersection with the right side
  213.        Y1 := Y1 + DYDX * (VPRight - X1);
  214.        X1 := VPRight;
  215.     end else if Code1 and 4 > 0 then begin                              // Check intersection with the top side
  216.        X1 := X1 + DXDY * (VPTop - Y1);
  217.        Y1 := VPTop;
  218.     end else if Code1 and 8 > 0 then begin                              // Check intersection with the bottom side
  219.        X1 := X1 + DXDY * (VPBottom - Y1);
  220.        Y1 := VPBottom;
  221.     end;
  222.     Code1 := GetCode(X1, Y1);                                           // Recalculate the code
  223.     Dec(i);
  224.   until i = 0;
  225.   if Odd(SwCount) then begin
  226.     ts := X1; X1 := X2; X2 := ts;
  227.     ts := Y1; Y1 := Y2; Y2 := ts;
  228.   end;
  229. end;
  230. { TBitmapFont }
  231. constructor TBaseBitmapFont.Create(AManager: BaseClasses.TItemsManager);
  232. begin
  233.   inherited;
  234.   TotalUVs := 0; TotalCharacters := 0;
  235.   UVMap := nil; CharMap := nil;
  236.   SetScale(128, 128);
  237. end;
  238. procedure TBaseBitmapFont.SetMapResources(const AUVMap: BaseTypes.TUVMap; ATotalUVs: Integer; const ACharMap: BaseTypes.TCharMap; ATotalCharacters: Integer);
  239. begin
  240.   TotalUVs := ATotalUVs;
  241.   UVMap := AUVMap;
  242.   TotalCharacters := ATotalCharacters;
  243.   CharMap := ACharMap;
  244. end;
  245. procedure TBaseBitmapFont.SetScale(AXScale, AYScale: Single);
  246. begin
  247.   XScale := AXscale; YScale := AYScale;
  248. end;
  249. procedure TBaseBitmapFont.GetTextExtent(const Text: string; out Width, Height: Single);
  250. var i: Integer; UV: BaseTypes.TUV;
  251. begin
  252.   Width := 0; Height := 0;
  253.   if (UVMap = nil) or (CharMap = nil) then begin
  254.     {$IFDEF LOGGING} Log.Log(ClassName + '.GetTextExtent: UV map or character map resource is invalid', lkError); {$ENDIF}
  255.     Exit;
  256.   end;
  257.   for i := 0 to Length(Text)-1 do begin
  258.     UV := UVMap^[CharMap^[Ord(Text[i+1])]];
  259.     Width := Width + UV.W;
  260.     if Height < UV.H then Height := UV.H;
  261.   end;
  262.   Width  := Width  * XScale;
  263.   Height := Height * YScale;
  264. end;
  265. { TScreen }
  266. constructor TScreen.Create;
  267. begin
  268.   inherited;
  269.   Reset;
  270. end;
  271. procedure TScreen.Reset;
  272. begin
  273.   ResetViewport;
  274.   Font     := nil;
  275.   Color.C  := $FFFFFFFF;
  276.   CurrentX := 0;
  277.   CurrentY := 0;
  278.   LocalX   := 0;
  279.   LocalY   := 0;
  280.   CurrentZ := ClearingZ;
  281.   UV       := DefaultUV;
  282. end;
  283. procedure TScreen.HandleMessage(const Msg: TMessage);
  284. begin
  285.   if Msg.ClassType = TWindowResizeMsg then with TWindowResizeMsg(Msg) do begin
  286.     FWidth  := NewWidth;
  287.     FHeight := NewHeight;
  288.   end;
  289. end;
  290. procedure TScreen.SetViewport(ALeft, ATop, ARight, ABottom: Single);
  291. begin
  292.   Viewport.Left      := ALeft;
  293.   Viewport.Top       := ATop;
  294.   Viewport.Right     := ARight;
  295.   Viewport.Bottom    := ABottom;
  296. end;
  297. procedure TScreen.TransformPoint(var X, Y: Single);
  298. var V: TVector4s;                       // ToDo: Optimize (eliminate) it.
  299. begin
  300.   V := GetVector4s(X, Y, 0, 1);
  301.   V := Transform4Vector4s(Transform, V);
  302.   X := V.X; Y := V.Y;
  303. end;
  304. procedure TScreen.RotateScalePoint(var X, Y: Single);
  305. var V: TVector3s;                       // ToDo: Optimize (eliminate) it.
  306. begin
  307.   V := GetVector3s(X, Y, 0);
  308.   V := Transform3Vector3s(CutMatrix3s(Transform), V);
  309.   X := V.X; Y := V.Y;
  310. end;
  311. procedure TScreen.TransformPointWith(const ATransform: T2DTransform; var X, Y: Single);
  312. var V: TVector4s;                       // ToDo: Optimize (eliminate) it.
  313. begin
  314.   V := GetVector4s(X, Y, 0, 1);
  315.   V := Transform4Vector4s(ATransform, V);
  316.   X := V.X; Y := V.Y;
  317. end;
  318. procedure TScreen.RotateScalePointWith(const ATransform: T2DTransform; var X, Y: Single);
  319. var V: TVector3s;                       // ToDo: Optimize (eliminate) it.
  320. begin
  321.   V := GetVector3s(X, Y, 0);
  322.   V := Transform3Vector3s(CutMatrix3s(ATransform), V);
  323.   X := V.X; Y := V.Y;
  324. end;
  325. procedure TScreen.SetColor(const AColor: BaseTypes.TColor);
  326. begin
  327.   Color := AColor;
  328. end;
  329. procedure TScreen.SetFont(const AFont: TFont);
  330. begin
  331.   Font := AFont;
  332. end;
  333. procedure TScreen.SetUV(const AUV: BaseTypes.TUV);
  334. begin
  335.   UV := AUV;
  336. end;
  337. procedure TScreen.SetBitmap(const ABitmap: TBitmap);
  338. begin
  339.   Bitmap := ABitmap;
  340. end;
  341. procedure TScreen.MoveTo(const X, Y: Single);
  342. begin
  343.   LocalX := X; LocalY := Y;
  344.   CurrentX := X; CurrentY := Y;
  345. //  TransformPoint(CurrentX, CurrentY);
  346. end;
  347. procedure TScreen.Line(X1, Y1, X2, Y2: Single);
  348. begin
  349.   MoveTo(X1, Y1);
  350.   LineTo(X2, Y2);
  351. end;
  352. procedure TScreen.Rectangle(X1, Y1, X2, Y2: Single);
  353. begin
  354.   MoveTo(X1, Y1);
  355.   LineTo(X2, Y1);
  356.   LineTo(X2, Y2);
  357.   LineTo(X1, Y2);
  358.   LineTo(X1, Y1);
  359. end;
  360. procedure TScreen.ResetViewport;
  361. begin
  362.   Transform := IdentityMatrix4s;
  363.   SetViewport(0, 0, Width, Height);
  364. end;
  365. procedure TScreen.Clear;
  366. begin
  367.   ResetViewport;
  368. end;
  369. procedure TScreen.LineToVec(const Vec: TVector3s);
  370. begin
  371.   LineTo(Vec.X, Vec.Y);
  372. end;
  373. procedure TScreen.MoveToVec(const Vec: TVector3s);
  374. begin
  375.   MoveTo(Vec.X, Vec.Y);
  376. end;
  377. begin
  378.   GlobalClassList.Add('BaseGraph', GetUnitClassList);
  379. end.