Einzelnen Beitrag anzeigen

Vitus

Registriert seit: 24. Apr 2003
Ort: Auckland, Neuseeland
38 Beiträge
 
Delphi XE2 Professional
 
#4

Re: Direct3D - Kapselung der Routinen

  Alt 19. Feb 2004, 14:53
Danke für die Antwort, ich hatte schon vermutet dass mich hier keiner mag und deshalb keiner antwortet *fg*


Inzwischen bin ich nach vieeeeeeeeeeeeeeelen Testläufen endlich mal zu einem Ergebnis gekommen - das Programm ist nun auch etwas anders strukturiert. Damit das hier mal up-to-date ist mal den Code für die neue Tlts2DObject Klasse.


Erstmal die Definitionen:
Delphi-Quellcode:
type

pIDIRECT3D9 = ^IDIRECT3D9;

pIDirect3DDevice9 = ^IDirect3DDevice9;

pIDirect3DVertexBuffer9 = ^IDirect3DVertexBuffer9;

pIDIRECT3DTEXTURE9 = ^IDIRECT3DTEXTURE9;

////////////////////////////////////////////////////////////////////////////////
// Vertexstruktur //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

TMyVertex = Record
  x,y,z : single; // Position des Vertex
  color : dword; // Farbe des Vertex
  tu,tv : single; // Die Koordinaten der Textur
end;

TltsSprite = array [0..5] of TMyVertex;

////////////////////////////////////////////////////////////////////////////////
// 2D Objekt: Grundgerüst für Dialogelemente uä. ///////////////////////////////
////////////////////////////////////////////////////////////////////////////////

Tlts2DObject = class(TObject)
  private
    D3DVertexBuffer: IDirect3DVertexBuffer9;
    D3DTexture: IDIRECT3DTEXTURE9;
    D3DVertex: TltsSprite;
  public
    Left: Real;
    Top: Real;
    Width: Real;
    Height: Real;

    Layer: Integer;

    Angle: Real;

    tuleft: Real;
    turight: Real;
    tvtop: Real;
    tvbottom: Real;

    Color: dword;
    Alpha: Integer;

    Graphic: String;

    constructor Create();
    procedure init(pD3DDevice: pIDirect3DDevice9);
    procedure render(pD3DDevice: pIDirect3DDevice9);
    procedure updateGeom(); virtual;
    procedure updateTexPos(tuleft,turight,tvtop,tvbottom: Real);
    function getVertexBuffer(): pIDirect3DVertexBuffer9;
    function getTexture(): pIDIRECT3DTEXTURE9;
end;
Implementation:
Delphi-Quellcode:
implementation

////////////////////////////////////////////////////////////////////////////////
// Routinen Tlts2DObject ///////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

constructor Tlts2DObject.Create();
begin
  inherited Create();
  tuleft := 0;
  turight := 1;
  tvtop := 0;
  tvbottom := 1;
end;

function Tlts2DObject.getTexture(): pIDIRECT3DTEXTURE9;
begin
  result := @D3DTexture;
end;

function Tlts2DObject.getVertexBuffer(): pIDirect3DVertexBuffer9;
begin
  result := @D3DVertexBuffer;
end;

procedure Tlts2DObject.init(pD3DDevice: pIDirect3DDevice9);
var
  vbVertices : pByte;
begin

  updateGeom();
  updateTexPos(tuleft,turight,tvtop,tvbottom);

  pD3DDevice^.CreateVertexBuffer (sizeof(TltsSprite), D3DUSAGE_WRITEONLY,
                            D3D9T_CUSTOMVERTEX, D3DPOOL_MANAGED,
                            D3DVertexBuffer, nil);

  D3DVertexBuffer.Lock(0,0,pointer(vbVertices),0);
  Move(D3DVertex,vbVertices^,SizeOf(TltsSprite));
  D3DVertexBuffer.Unlock;

  pD3DDevice^.SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW); //alle Seiten anzeigen
  pD3DDevice^.SetRenderState(D3DRS_LIGHTING,0);
  pD3DDevice^.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); //Z Buffer abgeschaltet

  pD3DDevice^.SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_CONSTANT, D3DTEXF_LINEAR);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_CONSTANT, D3DTEXF_LINEAR);

  D3DXCreateTextureFromFile(pD3DDevice^,pchar(Graphic),D3DTexture);
end;

procedure Tlts2DObject.render(pD3DDevice: pIDirect3DDevice9);
begin
  pD3DDevice^.SetTexture( 0, D3DTexture );
  pD3DDevice^.SetStreamSource(0,D3DVertexBuffer,0,sizeof(TMyVertex));
  pD3DDevice^.DrawPrimitive( D3DPT_TRIANGLELIST,0,2 );
end;

procedure Tlts2DObject.updateTexPos(tuleft,turight,tvtop,tvbottom: Real);
var
  i: Integer;
begin
  for i := 0 to 5 do
  begin
    if i = 0 then
    begin
      D3DVertex[i].tu := tuleft;
      D3DVertex[i].tv := tvbottom;
    end;
    if i = 1 then
    begin
      D3DVertex[i].tu := tuleft;
      D3DVertex[i].tv := tvtop;
    end;
    if i = 2 then
    begin
      D3DVertex[i].tu := turight;
      D3DVertex[i].tv := tvtop;
    end;
    if i = 3 then
    begin
      D3DVertex[i].tu := turight;
      D3DVertex[i].tv := tvtop;
    end;
    if i = 4 then
    begin
      D3DVertex[i].tu := turight;
      D3DVertex[i].tv := tvbottom;
    end;
    if i = 5 then
    begin
      D3DVertex[i].tu := tuleft;
      D3DVertex[i].tv := tvbottom;
    end;
  end;
end;

procedure Tlts2DObject.updateGeom();
var
  x,y: Real;
  i: Integer;
begin

   for i:=0 to 5 do
  begin
    if i = 0 then
    begin
      x := left;
         y := top;
    end
    else if i = 1 then
    begin
        x := left;
        y := top+height;
    end
    else if i = 2 then
    begin
         x := left+width;
         y := top+height;
    end
    else if i = 3 then
    begin
         x := left+width;
         y := top+height;
    end
    else if i = 4 then
    begin
         x := left+width;
         y := top;
    end
    else
    begin
        x := left;
        y := top;
    end;

      D3DVertex[i].x := x;
      D3DVertex[i].y := y;
    D3DVertex[i].z := (layer*(-1))/100;
      D3DVertex[i].color := Color;
  end;
end;
Nach der Initialisierung des D3DDevice (um die Frage zu beantworten: D3DDevice ist nat. vom Typ IDirect3DDevice9) wird das neue 2D Objekt so initialisiert:

Delphi-Quellcode:
var
  D2DObjekt: Tlts2DObject;
begin
  D2DObjekt:= Tlts2DObject.Create();
  D2DObjekt.Width := 4;
  D2DObjekt.Height := 3;
  D2DObjekt.Left := -2;
  D2DObjekt.Top := -1.5;
  D2DObjekt.Layer := 1;
  D2DObjekt.Color := $457890;
  D2DObjekt.Angle := 0;
  D2DObjekt.Alpha := 130;
  D2DObjekt.Graphic := 'pfadzumbild.bmp';

  if assigned(D3DDevice) then
  begin
    D3DObjekt.init(pD3DDevice);
  end;
und in der Render Funktion so gerendert:

Delphi-Quellcode:
  D3DDevice.Clear(0,nil,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1,0);

  if SUCCEEDED(D3DDevice.BeginScene) then
  begin

    D3DDevice.SetFVF(D3D9T_CUSTOMVERTEX);

    D3DObjekt.render(pD3DDevice);

    D3DDevice.EndScene;
  end;

 // Zeige Resultate auf dem Bildschirm
  D3DDevice.Present(nil,nil,0,nil);
Das funktioniert so eigentlich ganz gut auch wenn noch viel zu tun ist - bei der initialisierung des Objekts bin ich mir ziemlich unsicher aber die ganzen zusätzlichen Features Problembeseitigungen werden als nächstes "herausgetüftelt"
Eine Frage die sich mir zum Beispiel stellt ist die ob es wirklich sinnvoll ist die Position des 2D Objekts ausschliesslich über die Koordinaten der Dreiecke festzulegen, oder ob es nicht sinnvoller wäre das ganze über transformationen zu realisieren...

Um auf mein ursprüngliches Problem zurückzukommen:
Ich übergebe in der Render Methode (Jetzt heisst die nat. "init" Methode) eigentlich nur deshalb einen Zeiger weil ich Angst hatte dass die Methode sonst versucht ein ganz neues Objekt als eine Kopie des übergebenen anzulegen anstatt auf das vorhandene zuzugreifen. Das würde bedeuten dass dieses neue angelegte D3DDevice im Grunde nur in diesem einen Objekt existent wäre - damit kann man also nix anfangen

Dein Tip mit dem @ war gut - wie schon gesagt: ich habe mich bisher noch NULL (<- achtung: Wortspiel ) mit Zeigern beschäftigt deshalb wußte ich nicht wie man überhaupt den Zeiger auf ein Objekt rausfinden kann - das @ tuts *gg*






Soviel also zu meiner vörläufigen Lösung des Problems...

Was mich wirklich interessieren würde: Macht das was ich da getippselt habe Sinn oder geht das alles viel einfacher!?
Ausserdem: wenn ich mich in meinem Spiel für eine 3D "Engine" (*hüstel*) entscheide, muss dann wirklich ALLES 3D sein - oder ist es technisch auch möglich zB. Hauptmenü und das Interface als einfache 2D Grafiken zu zeichnen, ohne einen solchen Aufwand, wie da oben ersichtlich, zu treiben?

Danke für die nun folgenden, zahlreichen (!) Antworten

Gruß
Vitus
Gott segne diese Heiden! [Homer J. Simpson]
  Mit Zitat antworten Zitat