AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia OpenGL - Prüfen ob Textur angeklickt
Thema durchsuchen
Ansicht
Themen-Optionen

OpenGL - Prüfen ob Textur angeklickt

Ein Thema von Destroxi · begonnen am 6. Nov 2011 · letzter Beitrag vom 6. Nov 2011
Antwort Antwort
Destroxi

Registriert seit: 29. Okt 2011
55 Beiträge
 
Delphi 7 Enterprise
 
#1

OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 13:03
Hi,
ich will genau das herausfinden, wie der Name schon sagt:
Ob eine Textur angeklickt wurde, und zwar nur die Textur, die mit Alphatest rausgelesen wurde.

Wie bewerkstelle ich das?

Mfg, Destroxi

Geändert von Destroxi ( 6. Nov 2011 um 13:06 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#2

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 14:15
Stichworte: Picking, Selecting
hier
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#3

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 15:11
Der OpenGL Selection Mode ist furchtbar langsam. Ich würde davon abraten, ihn zu verwenden, ausser für das Prototyping, aber niemals für eine echte Applikation.
Besser ist es, mit Z-Sortierung, eigener Objekthiarchie und Raycasting zu arbeiten, auch wenn man damit nicht "so schnell" zu Ergebnissen kommt wie mit dem Selection Mode.

Einfach mal nach "OpenGL Picking Raycast" oder ähnlichem googlen, gibt sehr viele gute Ansätze dafür.

Oder du schaust dir von GLScene mal die "RayCastIntersect"-Funktionen an, sie sind zwar nicht optimal, dennoch ein guter Ansatzpunkt und schon mal 100-1000x
schneller als der OpenGL Selection Mode.

P.S.

Für OpenGL-Fragen bist du denke ich in einem direkten OpenGL-Forum oder beim GameDEV besser aufgehoben als hier.

Generell würde ich dir aber immer noch empfehlen, lade dir mal GLScene runter und gehe die Beispiele durch...dort sind für fast jeden Anwendungsfall Beispiele vorhanden. Und wenn du dann tiefer im Code gräbst, also nicht nur die GLScene-Wrapper anschaust und die Engine als "Klicki-Bunti" OpenGL-Engine benutzt, sondern den Code, der dahinter steckt analysierst, wirst du auf viele OpenGL-Funktionen und -Lösungen stossen und sehr viel von selbst lernen, ohne bei jedem Problem fragen zu müssen

Geändert von blackfin ( 6. Nov 2011 um 15:35 Uhr)
  Mit Zitat antworten Zitat
Destroxi

Registriert seit: 29. Okt 2011
55 Beiträge
 
Delphi 7 Enterprise
 
#4

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 15:33
Danke für die Tipps, werde mich für zukünftige fragen in einem OpenGL Forum umsehn
... aber erstma nach
Code:
OpenGL Picking Raycast
googeln

€dit: Ehrlich gesagt... ich versteh das total nicht
Wie, was, muss ich tun?
Ich will - einfach - nur prüfen ob meine Textur angeklickt wurde...
Geht das nicht irgendwie einfacher?
Bei TImage geht es so einfach xD
Gibts nicht vielleicht einfach so eine "OnClick" Methode für GL Objekte? *hoff*

Mfg...

Geändert von Destroxi ( 6. Nov 2011 um 15:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#5

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 15:50
Was blackfin gesagt hat, stimmt größtenteils aber in deinem Fall reicht es vollkommen aus und ist anfängerfreundlich. Kucks dir an.

Eine weitere Alternative, die mir gerade einfällt, ist "Color Picking"
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Destroxi

Registriert seit: 29. Okt 2011
55 Beiträge
 
Delphi 7 Enterprise
 
#6

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 15:57
Color Picking hab ich auch schon gesehn...
Und: was du mit "Anfängerfreundlich" meinst kommt bei jedem anders an
Ich stell ma ganz konkret die Frage zu meinem Quelltext:
Wie schaffe ich es das ich rauskriege ob das Flugzeug angeklickt ist (PlaneTex):
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, dglOpenGL, glText, Textures, StdCtrls, ExtCtrls;

type
  TMainForm = class(TForm)
    Timer1: TTimer;
    Timer2: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Timer2Timer(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Timer3Timer(Sender: TObject);
  private
    { Private declarations }
    procedure Render(Sender: TObject; var Done: Boolean);
    function Selection : integer;
  public
    { Public declarations }
    DC: HDC;
    RC: HGLRC;
    myPalette: HPALETTE;
  end;
  TRecBorder = Record
    RLeft, RRight, RBot, RTop: Integer;
  end;

procedure ErrorMsg
            (Msg: String; MsgTitle: String = 'Error!');

const
  RecBorder: TRecBorder = (RLeft: 10; RRight: 0;
                           RBot : 10; RTop : 10);
  SizeX = 640;
  SizeY = 480;
  ObjWidth = 100;
  ObjHeight = 100;
  dir_LEFT = 0;
  dir_RIGHT = 1;
  dir_Max = 1;
  ManWidth = 100;
  ManHeight = 100;

var
  MainForm: TMainForm;
  PlaneTex, ManTex: glUInt;
  SelPlane: Record
    pX, pY: Single;
    Direction: 0..1;
  end;
  Player: Record
    pX, pY: Single;
  end;
  Options: Record
    Speed: Integer;
    CanClick: Boolean;
    clicksHitted, clicksMissed, clicksTotal: Integer;
  end;
  xs, ys: Integer;

implementation

{$R *.dfm}

procedure SetupPixelFormat;
var hHeap: THandle;
  nColors, i: Integer;
  lpPalette : PLogPalette;
  byRedMask, byGreenMask, byBlueMask: Byte;
  nPixelFormat: Integer;
  pfd: TPixelFormatDescriptor;
begin
  FillChar(pfd, SizeOf(pfd), 0);
  with pfd do begin
    nSize := sizeof(pfd); // Länge der pfd-Struktur
    nVersion := 1; // Version
    dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or
                 PFD_DOUBLEBUFFER; // Flags
    iPixelType:= PFD_TYPE_RGBA; // RGBA Pixel Type
    cColorBits:= 24; // 24-bit color
    cDepthBits:= 32; // 32-bit depth buffer
    iLayerType:= PFD_MAIN_PLANE; // Layer Type
  end;
  nPixelFormat:= ChoosePixelFormat(MainForm.DC, @pfd);
  SetPixelFormat(MainForm.DC, nPixelFormat, @pfd);
                                            // Farbpalettenoptimierung wenn erforderlich
  DescribePixelFormat(MainForm.DC, nPixelFormat,
                      sizeof(TPixelFormatDescriptor),pfd);
  if ((pfd.dwFlags and PFD_NEED_PALETTE) <> 0) then begin
    nColors := 1 shl pfd.cColorBits;
    hHeap := GetProcessHeap;
    lpPalette:= HeapAlloc
       (hHeap,0,sizeof(TLogPalette)+(nColors*sizeof(TPaletteEntry)));
    lpPalette^.palVersion := $300;
    lpPalette^.palNumEntries := nColors;
    byRedMask := (1 shl pfd.cRedBits) - 1;
    byGreenMask:= (1 shl pfd.cGreenBits) - 1;
    byBlueMask := (1 shl pfd.cBlueBits) - 1;
    for i := 0 to nColors - 1 do begin
      lpPalette^.palPalEntry[i].peRed :=
        (((i shr pfd.cRedShift) and byRedMask) *255)DIV byRedMask;
      lpPalette^.palPalEntry[i].peGreen:=
        (((i shr pfd.cGreenShift)and byGreenMask)*255)DIV byGreenMask;
      lpPalette^.palPalEntry[i].peBlue :=
        (((i shr pfd.cBlueShift) and byBlueMask) *255)DIV byBlueMask;
      lpPalette^.palPalEntry[i].peFlags:= 0;
    end;
    MainForm.myPalette := CreatePalette(lpPalette^);
    HeapFree(hHeap, 0, lpPalette);
    if (MainForm.myPalette <> 0) then begin
      SelectPalette(MainForm.DC, MainForm.myPalette, False);
      RealizePalette(MainForm.DC);
    end;
  end;
end;

function TMainForm.Selection : integer;
var
Puffer : array[0..256] of GLUInt;
Viewport : {array[0..3] of Integer}TVector4i;
Treffer,i : Integer;
Z_Wert : GLUInt;
Getroffen : GLUInt;
tmpBool: Boolean;
begin
glGetIntegerv(GL_VIEWPORT, @viewport); //Die Sicht speichern
glSelectBuffer(256, @Puffer); //Den Puffer zuordnen
glRenderMode(GL_SELECT); //In den Selectionsmodus schalten
glmatrixmode(gl_projection); //In den Projektionsmodus
glPushMatrix; //Um unsere Matrix zu sichern
glLoadIdentity; //Und dieselbige wieder zurückzusetzen

gluPickMatrix(xs, viewport[3]-ys, 1.0, 1.0, viewport);
gluPerspective(45.0, ClientWidth/ClientHeight, 1, 100);

render(Self, tmpBool); //Die Szene zeichnen
glmatrixmode(gl_projection); //Wieder in den Projektionsmodus
glPopMatrix; //um unsere alte Matrix wiederherzustellen

treffer := glRenderMode(GL_RENDER); //Anzahl der Treffer auslesen

Getroffen := High(GLUInt); //Höchsten möglichen Wert annehmen
Z_Wert := High(GLUInt); //Höchsten Z - Wert
for i := 0 to Treffer-1 do
if Puffer[(i*4)+1] < Z_Wert then
 begin
 getroffen := Puffer[(i*4)+3];
 Z_Wert := Puffer[(i*4)+1];
 end;

 Result := getroffen;
end;
// Procedure to send an error message
procedure ErrorMsg
          (Msg: String; MsgTitle: String = 'Error!');
begin
 Application.MessageBox(PChar(Msg), PChar(MsgTitle),
                        MB_OK or MB_ICONERROR);
end;
// Procedure to create a texture quad
procedure DrawQuad(pX, pY: Single; pWidth, pHeight: Integer);
begin
 glBegin(GL_QUADS);
  glTexCoord2f(0, 0); glVertex2f(pX, pY);
  glTexCoord2f(1, 0); glVertex2f(pX+pWidth, pY);
  glTexCoord2f(1, 1); glVertex2f(pX+pWidth, pY+pHeight);
  glTexCoord2f(0, 1); glVertex2f(pX, pY+pHeight);
 glEnd;
end;
// Procedure to set the opengl sizes
procedure SetSizes;
begin
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity;
 glViewPort(0, 0, MainForm.ClientWidth, MainForm.ClientHeight);
 glOrtho(0, SizeX, 0, SizeY, -128, 128);

 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity;
end;
// Procedure to create a new plane
procedure NewPlane;
begin
 If (SelPlane.Direction <> 0) and (SelPlane.Direction <> 1) then
  SelPlane.Direction := Random(dir_MAX+1)
 else
  SelPlane.Direction := Integer(not Bool(SelPlane.Direction));
 Case SelPlane.Direction of
  dir_LEFT: SelPlane.pX := SizeX;
  dir_RIGHT: SelPlane.pX := 0;
 end;
 SelPlane.pY := Random(SizeY-ObjHeight*2-ManHeight)+ObjHeight+ManHeight;
end;

// ==========================================================
// TMainForm
// ==========================================================

procedure TMainForm.FormCreate(Sender: TObject);
begin
 DC:= GetDC(Handle);
 //SetupPixelFormat;
 RC:= CreateRenderingContext(DC, [opDoubleBuffered],
                             32, 24, 0, 0, 0, 0);
 ActivateRenderingContext(DC, RC);
 glEnable(GL_DEPTH_TEST);
 glLoadIdentity;

 SetSizes;

 glClearColor(1, 1, 1, 0);
 glEnable(GL_CULL_FACE);
 glEnable(GL_TEXTURE_2D);
 glEnable(GL_ALPHA_TEST);
 glAlphaFunc(GL_GREATER, 0.1);

 Application.OnIdle := Render;

 LoadTexture('Raumschiff.tga', PlaneTex, False);
 LoadTexture('Schütze.tga', ManTex, False);

 NewPlane;

 Options.Speed := 20;
 Options.CanClick := True;
 Options.clicksHitted := 0;
 Options.clicksMissed := 0;
 Options.clicksTotal := 0;

 Player.pX := 0;
 Player.pY := 0;
end;

// Procedure to render all things
procedure TMainForm.Render(Sender: TObject; var Done: Boolean);
var
 CanClickText: String;
begin
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

 SetSizes;

 glPrint(10, SizeY-15, 'Speed : '+IntToStr(Options.Speed), 0, 0, 0);
 glPrint(10, SizeY-35, 'Hits : '+IntToStr(Options.clicksHitted), 0.3, 1, 0.3);
 glPrint(10, SizeY-55, 'Missed : '+IntToStr(Options.clicksMissed), 1, 0.3, 0.3);
 glPrint(10, SizeY-75, 'Total : '+IntToStr(Options.clicksTotal), 0, 0, 0);
 CanClickText := 'You can'#10't hit it now!';
 If not Options.CanClick then
  glPrint(SizeX div 2 - Canvas.TextWidth(CanClickText) div 2, SizeY-95, CanClickText, 1, 0, 0);

 glPushMatrix;
  glLoadName(1);
  glTranslatef(SelPlane.pX, SelPlane.pY, 0);
  Case SelPlane.Direction of
   dir_LEFT: glRotatef(90*1, 0, 0, 1);
   dir_RIGHT: glRotatef(90*3, 0, 0, 1);
  end;
  glBindTexture(GL_TEXTURE_2D, PlaneTex);
  DrawQuad(0,0,ObjWidth,ObjHeight);
 glPopMatrix;
 glPushMatrix;
  glLoadName(2);
  glTranslatef(Player.pX, Player.pY, 0);
  glBindTexture(GL_TEXTURE_2D, ManTex);
  DrawQuad(0,0,ManWidth,ManHeight);
 glPopMatrix;

 SwapBuffers(DC);

 Done := False;
end;

procedure TMainForm.FormResize(Sender: TObject);
begin
 SetSizes;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
 DeactivateRenderingContext;
 DestroyRenderingContext(RC);
 ReleaseDC(Handle, DC);
end;

procedure TMainForm.Timer1Timer(Sender: TObject);
begin
 Case SelPlane.Direction of
  dir_LEFT: SelPlane.pX := SelPlane.pX - Options.Speed;
  dir_RIGHT: SelPlane.pX := SelPlane.pX + Options.Speed;
 end;
 If ((SelPlane.Direction = dir_LEFT) and
     (SelPlane.pX <= 0-ObjWidth)) or
    ((SelPlane.Direction = dir_RIGHT) and
     (SelPlane.pX >= SizeX+ObjWidth)) then NewPlane;
end;

procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 If Key = VK_F1 then
  Timer1.Enabled := not Timer1.Enabled;
 If Timer1.Enabled then
 begin
  Options.CanClick := False;
  Timer2.Enabled := False;
  Timer2.Enabled := True;
 end;
end;

procedure TMainForm.Timer2Timer(Sender: TObject);
begin
 Options.CanClick := True;
 Timer2.Enabled := False;
end;

procedure TMainForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 If not Options.CanClick then Exit;
 xs := x;
 ys := y;
 If Selection<>-1 then
 begin
  ShowMessage(IntToStr(Selection));
  Inc(Options.clicksHitted);
 end
 else
  Inc(Options.clicksMissed);
 Inc(Options.clicksTotal);
 If Options.clicksTotal mod 20 = 0 then
  Inc(Options.Speed, 5);
end;

procedure TMainForm.Timer3Timer(Sender: TObject);
begin
 BorderStyle := bsNone;
 WindowState := wsMaximized;
end;

end.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#7

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 16:05
Du gestehst OpenGL zu viel "Intelligenz" zu. Es gitb keine "Objekte" in OGL, OGL ist quasi nur ein Pinsel, und der Pinsel für sich ist erstmal doof. Der weiss nicht was er zeichnet, was davon zu einem "Objekt" gehört, nix. Du brauchst also eine ganz und gar eigene Datenstruktur im Hintergrund, die mit OGL überhaupt nichts zu tun hat (zunächst), in der du all deine Logik unterbringst. OGL ist nur zum Zeichnen da. NUR!

Eine Textur ist auch nicht, so wie du es ausdrückst, anklickbar. Das Fenster, in dem OGL was rendert, ist es. Dann bekomst du Fensterkoordinaten, die du (du!) erstmal in Weltkoordinaten deiner grade dargestellten Szene umrechnest. Zunächst mal in der Eye-Plane. Von dort aus musst du (du!) unter Zuhilfenahme von etwas linearer Algebra einen Strahl in deine Szene "schicken", und mit Geraden/Flächen-Schnitt gucken, ob und welches deiner(!) logischen Objekte getroffen wurde, die du idealerweise in einer Liste irgendwo im Sppeicher hast (OGL hat die nämlich nicht, bzw. nicht in auf diese Weise verwertbarer Form). Dann weisst du, welches deiner logischen "Objekte" geklickt wurde, und da du hoffentlich in den Klassen zu deinen Objekten auch die Referenz auf die zu verwendende Textur hast, darüber auch die Textur, des Objektes, das gerade dort zuvorderst dargestellt wird, wo der User auf das Fenster geklickt hat. Verglichen mit einem rosa plüschigen VCL-OnClick() Handler geht dabei natürlich eine ganze Ecke mehr ab, aber so ist das in der "echten" Welt
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Destroxi

Registriert seit: 29. Okt 2011
55 Beiträge
 
Delphi 7 Enterprise
 
#8

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 16:59
Du willst damit sagen, es ist sehr viel Arbeit etwas anklickbar zu machen?
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#9

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 17:07
Ja, denn du verlässt bei Benutzung von OpenGL die VCL komplett, was wiederum bedeutet, dass du die gesamte Objekthiearchie, -Verwaltung und Event Handler (wie z.B. ein onClick) deiner gezeichneten Dinge selbst schreiben musst, von Grund auf, angefangen bei (fast) 0.
Beispiel: Eine gezeichnete Textur hat keinerlei Objekt-Referenz in OpenGL, es wird halt einfach gezeichnet. Die Objekt-Struktur musst du dir (vorher) selbst überlegen und dir die Objekte / Klassen selbst ausdenken.
(z.B. eine Klasse, die einen texturierten Quad mit den übergebenen Parametern Breite, Höhe, Position zeichnet, die Koordinaten, Verschiebung etc. aber intern sebst verwaltet und eigentlich nur als Draw-Routine eben OpenGL verwendet).

Bei OpenGL gibt es eben so etwas Feines wie die VCL nicht, wie Medium bereits gesagt hat, ist OpenGL erstmal nichts andereres als eine Schnittstelle, mit der zu zeichnen kannst, mehr nicht.
Als Vorteil der Schnittstelle hast du eben Hardware-Zugriff beim Zeichnen und ein paar nette Funktionen für das Zeichnen und der Transformation der Zeichenfläche selbst, das wars aber schon.
(Das ganze Shader-Zeug mal ausgenommen, das würde jetzt aber den Rahmen sprengen...)

Willst du aber "ready to use" OnClick, Objekte, etc, musst du eine Game-Engine verwenden, die ein Objekt-System inkl. Eventhandlern usw. bereits implementiert hat und dir diese Arbeit bereits abgenommen hat.
Wenn du aber alles von Grund auf lernen willst, also OpenGL nativ verwenden willst, musst du aber auch von Grund auf selbst ran
Nicht verzagen, es ist am Anfang sehr hart, aber Stück für Stück lichtet sich das Dunkel und es macht Spass.
Auch wenn die Lernkurve echt steil ist und man erstmal Seitenweise lesen muss

Ich lege dir nochmal nahe, nimm dir erstmal eine OpenSource Game Engine wie z.B. GLScene und sieh dir den Code und die Objekthiearchie dort an, davon kann man viel lernen.

Geändert von blackfin ( 6. Nov 2011 um 17:32 Uhr)
  Mit Zitat antworten Zitat
Destroxi

Registriert seit: 29. Okt 2011
55 Beiträge
 
Delphi 7 Enterprise
 
#10

AW: OpenGL - Prüfen ob Textur angeklickt

  Alt 6. Nov 2011, 17:57
Dann werde ich mir mal GLScene an sehen^^

Danke für alle Antworten!

Mfg, Destroxi
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:00 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz