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]