BGRABitmap tutorial 15/de

From Free Pascal wiki
Jump to navigationJump to search

Deutsch (de) English (en)


Home | Tutorial 1 | Tutorial 2 | Tutorial 3 | Tutorial 4 | Tutorial 5 | Tutorial 6 | Tutorial 7 | Tutorial 8 | Tutorial 9 | Tutorial 10 | Tutorial 11 | Tutorial 12 | Tutorial 13 | Tutorial 14 | Tutorial 15 | Tutorial 16 | Edit

Dieses Tutorial zeigt Ihnen, wie Sie 3D-Objekte mittels des TBGRAScene3D-Objekts darstellen.

Das Szenenobjekt

Das Szenenobjekt ist in der Unit "BGRAScene3D" enthalten. Hier ist ein einfaches Beispiel:

uses BGRAScene3D, BGRABitmap, BGRABitmapTypes; 

procedure TForm1.FormPaint(Sender: TObject);
var
  scene: TBGRAScene3D;
  bmp: TBGRABitmap;
  base: array of IBGRAVertex3D;
  topV: IBGRAVertex3D;
begin
  bmp := TBGRABitmap.Create(ClientWidth,ClientHeight,BGRABlack);

  scene := TBGRAScene3D.Create(bmp);
  //erzeugt eine Pyramide
  with scene.CreateObject(BGRA(255,240,128)) do
  begin
    //erzeugt die Kanten
    topV := MainPart.Add(0,-15,0);
    //die Basis der Pyramide ist im Uhrzeigersinn angeordnet, wenn wir von unten auf die Pyramide sehen
    base := MainPart.Add([-20,15,-20, 20,15,-20, 20,15,20, -20,15,20]);

    AddFace(base);
    //fügt vier Flächen hinzu, die drei Kanten sind im Uhrzeigersinn angeordnet
    AddFace([base[0],topV,base[1]]);
    AddFace([base[1],topV,base[2]]);
    AddFace([base[2],topV,base[3]]);
    AddFace([base[3],topV,base[0]]);
    topV := nil;
    base := nil;
  end;
  scene.Render;
  scene.Free;

  bmp.Draw(Canvas,0,0);
  bmp.Free;
end;

Das Szenenobjekt zeichnet sich selbst auf ein TBGRABitmap-Objekt. Sie können die Bitmap entweder als Parameter beim Erzeugen des Objekts übergeben, so wie hier, oder nachträglich der Eigenschaft "Surface" zuweisen. Die Szene wird automatisch in der Bitmap zentriert.

Das Szenenobjekt bietet die Funktion "CreateObject", welche eine Schnittstelle auf das erzeugte Objekt zurückgibt. Objekte innerhalb einer Szene werden automatisch freigegeben, wenn Sie die Szene freigeben.

Ein Objekt hat eine Eigenschaft "MainPart", die es erlaubt, Kanten zu erzeugen und auf diese zuzugreifen. Die Koordinaten können als drei einzelne Werte angegeben werden, als TPoint3D-Records, oder als Array von einzelnen Werten, dessen Länge ein Vielfaches von 3 ist. Wenn Sie eine Kante erzeugen, erhalten Sie eine IBGRAVertex3D-Schnittstelle, die Sie zum Erzeugen von Flächen verwenden können.

Die X-Achse zeigt nach rechts, die Y-Achse zeigt nach unten, und die Z-Achse zeigt vorwärts (hinter den Bildschirm). Das bedeutet, dass XY gleich liegt wie in einer Bitmap, und dass es einen Wert für die Tiefe gibt. Die Flächen müssen im Uhrzeigersinn geordnet sein, um sichtbar zu sein.

Hier wird die Farbe für das gesamte Objekt beim Erzeugen festgelegt, aber Sie können sie auch individuell für jede Fläche setzen, oder für jede Kante.

BGRATutorial15a.png

Wie Sie sehen, wird die Pyramide von der Seite gezeigt, wir können also nur eine Fläche sehen. Es gibt auch keine Beleuchtung.

Fügen Sie im 'with'-Block folgende Zeilen ein:

    MainPart.Scale(1.3);
    MainPart.RotateYDeg(30);
    MainPart.RotateXDeg(20);
    MainPart.Translate(0,-5,0);

Die erste Zeile macht das Objekt etwas größer. Zwei Drehungen werden angewendet. Die erste erfolgt um die Y-Achse und die zweite um die X-Achse. Um den Drehsinn festzulegen, schauen wir in Richtung einer Achse. Ein positiver Wert in Grad bedeutet eine Drehung im Uhrzeigersinn, ein positiver Wert in Radiant bedeutet eine Drehung im Gegenzeigersinn.

Zuletzt erfolgt eine vertikale Schiebung, um das Objekt zu zentrieren.

BGRATutorial15b.png

Jetzt fügen wir etwas Licht hinzu:

  //setzt die ambiente Helligkeit auf Dunkel (1 ist normale Helligkeit, 2 ist völliges Weiss)
  scene.AmbiantLightness := 0.5;
  //fügt eine direktionale Beleuchtung von links-oben hinzu, die maximale Helligkeit ist 0.5 + 1 = 1.5
  scene.AddDirectionalLight(Point3D(1,1,1), 1);

Das Beispiel verwendet Helligkeitswerte. 0 ist schwarz, 1 bedeutet unveränderte Farbe, und 2 ist weiss. Die direktionale Beleuchtung braucht einen Point3D-Parameter, um die Richtung des Lichtstrahls anzuzeigen. Dieser muss nicht normalisiert werden.

BGRATutorial15c.png

Ableiten von TBGRAScene3D

Der Szenencode kann in ein Objekt eingebettet werden. Hier ist das vorige Beispiel in einer einzelnen Unit:

unit ex1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, BGRAScene3D, BGRABitmapTypes;

type

  { TExample1 }

  TExample1 = class(TBGRAScene3D)
    SandColor: TBGRAPixel;
    constructor Create;
    procedure Render; override;
  end;

implementation

{ TExample1 }

constructor TExample1.Create;
var
  base: array of IBGRAVertex3D;
  top: IBGRAVertex3D;
begin
  inherited Create;

  SandColor := BGRA(255,240,128);

  //erzeugt eine Pyramide
  with CreateObject(SandColor) do
  begin
    top := MainPart.Add(0,-15,0);
    //die Basis der Pyramide ist im Uhrzeigersinn angeordnet, wenn wir von unten auf die Pyramide sehen
    base := MainPart.Add([-20,15,-20, 20,15,-20, 20,15,20, -20,15,20]);
    AddFace(base);
    //fügt vier Flächen hinzu, die drei Kanten sind im Uhrzeigersinn angeordnet
    AddFace([base[0],top,base[1]]);
    AddFace([base[1],top,base[2]]);
    AddFace([base[2],top,base[3]]);
    AddFace([base[3],top,base[0]]);

    MainPart.Scale(1.3);
    MainPart.RotateYDeg(30);
    MainPart.RotateXDeg(20);
    MainPart.Translate(0,-5,0);
  end;

  //setzt die ambiente Helligkeit auf Dunkel (1 ist normale Helligkeit, 2 ist völliges Weiss)
  AmbiantLightness := 0.5;
  //fügt eine direktionale Beleuchtung von links-oben hinzu, die maximale Helligkeit ist 0.5 + 1 = 1.5
  AddDirectionalLight(Point3D(1,1,1),1);

  //wir können Antialiasing eisetzen, weil es eine einfache Szene ist
  Antialiasing := True;
end;

procedure TExample1.Render;
begin
  //füllt den Hintergrund
  Surface.GradientFill(0,0,Surface.Width,Surface.Height,SandColor,MergeBGRA(SandColor,BGRABlack),gtRadial,PointF(0,0),PointF(Surface.Width,Surface.Height),dmSet);

  inherited Render;
end;

end.

Um die Szene jetzt zu zeichnen, geben wir ein:

uses BGRABitmap, BGRABitmapTypes, BGRAScene3D, ex1;

procedure TForm1.FormPaint(Sender: TObject);
var
  bmp: TBGRABitmap;
  scene: TBGRAScene3D;
begin
  bmp := TBGRABitmap.Create(ClientWidth,ClientHeight,BGRABlack);

  scene := TExample1.Create;
  scene.Surface := bmp;
  scene.Render;
  scene.Free;

  bmp.Draw(Canvas,0,0);
  bmp.Free;
end;

Nebenbei, es wurde Antialiasing und ein Hintergrund hinzugefügt. Beachten Sie, dass Antialiasing nur bei einfachen Szenen funktioniert. Komplexe Szenen mit Texturen und transparenten Farben werden nicht korrekt dargestellt.

BGRATutorial15d.png


Voriges Tutorial (Canvas 2D) | Nächstes Tutorial (Texturen mit 3D-Objekten)

Seite übersetzt von: --billyraybones 00:05, 21 October 2011 (CEST)