OpenGL unter OSX

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Key-Real
Beiträge: 10
Registriert: Sa 28. Sep 2013, 23:36

OpenGL unter OSX

Beitrag von Key-Real »

Hi,
ich möchte unter OSX OpenGL (kein GLUT) so initialisieren, dass ich folgende Struktur habe:

....
InitOpenGLWindow();

repeat

glDRAWStuff;

glFlashBuffers;

until event.keypressed;

außerdem brauche ich auch eine Eventbechandlung.




Ein Vorschlag war:

Code: Alles auswählen

program MinimalPlusMenuPlusGL;
{$mode objfpc}
{$modeswitch objectivec1}
 
uses
	ctypes, MacOSAll, CocoaAll, GL, GLUT;
 
// -------------------- Window, view and OpenGL context
 
var
	m_context: NSOpenGLContext;
	a, b: Real;
 
type TestView = objcclass(NSView)
	public
	procedure drawRect (rect: NSRect); override;
	procedure windowWillClose (note: NSNotification); message 'windowWillClose:';
  end;
 
var
	NSApp: NSApplication;
	view: NSView;
 
procedure TestView.drawRect (rect: NSRect);
begin
		m_context.clearDrawable;
		glViewport(0, 0, Trunc(self.frame.size.width),
Trunc(self.frame.size.height));
 
		m_context.setView(self);
		m_context.makeCurrentContext;
 
		glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 
		glPushMatrix;
		glTranslatef(0, 0, -2);
		glRotatef(a, 0, 1, 0);
		glRotatef(b, 1, 0, 0);
		glScalef(-1, 1, 1);
	      glutSolidTeapot(0.75);
		glPopMatrix;
 
		m_context.flushBuffer;
end;
 
procedure TestView.windowWillClose (note: NSNotification);
begin
	NSApp.terminate(NSApp);
end;
 
procedure MakeWindow;
var
	window: NSWindow;
	fmt: NSOpenGLPixelFormat;
 
	attrs: array [0..3] of NSOpenGLPixelFormatAttribute =
		(
			NSOpenGLPFADoubleBuffer,
			NSOpenGLPFADepthSize, 32,
			0
		);
	frame: NSRect = (origin:(x: 10; y: 1200); size:(width: 400; height: 400));
begin
	a := 0;
	b := 0;
 
	// Create the window and get its view.
	window := NSWindow.alloc;
	window.initWithContentRect_styleMask_backing_defer(frame,
		NSTitledWindowMask or NSClosableWindowMask or NSMiniaturizableWindowMask
or NSResizableWindowMask,
		NSBackingStoreBuffered, LongBool(0));
	window.setTitle(NSString(CFSTR('Minimal + MiniMenu + GLView')));
 
	// Init GL context
	fmt := NSOpenGLPixelFormat.alloc.initWithAttributes(@attrs);
 
   m_context := NSOpenGLContext.alloc.initWithFormat_shareContext(fmt, nil);
	fmt.release;
	m_context.makeCurrentContext;
 
	// GL inits
	glClearColor(0.2,0.2,0.5,0);
	glMatrixMode(GL_PROJECTION);   glLoadIdentity();
	glFrustum(-0.1, 0.1, -0.1, 0.1, 0.1, 100); // left, right, bottom, top, near, far
	glMatrixMode(GL_MODELVIEW);    glLoadIdentity();
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);
 
	view := TestView.alloc;
	view.initWithFrame(frame);
	window.setContentView(view);
	window.setDelegate(NSWindowDelegateProtocol(view));
	window.makeKeyAndOrderFront(nil);
end;
 
// -------------------- Timer ------------------------
 
// Mini-mini class for the timer
type
	TimerController = objcclass(NSObject)
	public
		procedure TimerAction(t: NSTimer); message 'timerFireMethod:';
	end;
 
var
	gTimer: NSTimer;
	myTimerController: TimerController;
 
// Timer!
procedure TimerController.TimerAction(t: NSTimer);
var
	theText: AnsiString;
	CFText: CFStringRef;
begin
	a += 1;
	b += 1;
	view.setNeedsDisplay_(true);
end;
 
// -------------------- Menu ------------------------
 
// Mini-mini class for collecting events
type
	TMenuController = objcclass(NSObject)
	public
		procedure selectMenuItem (sender: id); message 'selectMenuItem:';
	end;
 
procedure TMenuController.selectMenuItem (sender: id);
begin
	WriteLn('Menu selection detected');
end;
 
var
	myController: TMenuController;
 
procedure SetupMenu;
var
	mainMenu, theMiniMenu: NSMenu;
	menuItem1, menuItem2: NSMenuItem;
	dummyItem: NSMenuItem;
begin
	// Allocate controller
	myController := TMenuController.alloc; // Create();
 
	// Create main menu = menu bar
	mainMenu := NSMenu.alloc;
	mainMenu.initWithTitle(NSString(CFSTR('')));
	NSApp.setMainMenu(mainMenu);
 
	// Create the custom menu
	theMiniMenu := NSMenu.alloc;
	theMiniMenu.initWithTitle(NSString(CFSTR('The MiniMenu')));
 
	// Create a menu item
	menuItem1 := NSMenuItem.alloc;
	menuItem1.initWithTitle_action_keyEquivalent(NSString(CFSTR('Item Text')), nil, NSString(CFSTR('')));
	menuItem1.setTarget(myController); // Who will handle it?
	menuItem1.setAction(sel_registerName(PChar('selectMenuItem:'))); // What method will handle it?
	theMiniMenu.addItem(menuItem1);
 
	// Create another menu item with standard message
	menuItem2 := NSMenuItem.alloc;
	menuItem2.initWithTitle_action_keyEquivalent(NSString(CFSTR('Quit')), nil, NSString(CFSTR('q')));
	menuItem2.setKeyEquivalentModifierMask(NSCommandKeyMask);
	menuItem2.setAction(sel_registerName(PChar('terminate:')));
	theMiniMenu.addItem(menuItem2);
 
	// Adding a menu is done with a dummy item to connect the menu to its parent
	dummyItem := NSMenuItem.alloc;
	dummyItem.initWithTitle_action_keyEquivalent(NSString(CFSTR('')), nil, NSString(CFSTR('')));
	dummyItem.setSubmenu(theMiniMenu);
	mainMenu.addItem(dummyItem);
end;
 
// ------------------ Main program ---------------------
 
var
	pool: NSAutoreleasePool;
	frame: NSRect = (origin:(x: 10; y: 1000); size:(width: 400; height: 400));
 
begin
	pool := NSAutoreleasePool.new;
	NSApp := NSApplication.sharedApplication;
 
	// Timer
	myTimerController := TimerController.alloc;
	gTimer := NSTimer.alloc;
	gTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats(0.02, myTimerController, sel_registerName(PChar('timerFireMethod:')), nil, true);
 
	SetupMenu;
	MakeWindow;
 
	// Main loop
	NSApp.run;
	pool.dealloc; // Free;
end.
 
! ABER:

um zu Zeichnen wird hier ein Timer benutzt, dies kommt für mich nicht in Frage. Außerdem flackert das Bild :(

aber so ungefähr kommt es hin. Bin natürlich für alle Vorschläge offen :)

Danke,
Key-Real
Zuletzt geändert von Lori am So 29. Sep 2013, 11:00, insgesamt 1-mal geändert.
Grund: Highlighter

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: OpenGL unter OSX

Beitrag von Scotty »

Warum nimmst du nicht die LCL?

lazarus / components / opengl / openglcontext.pas

Code: Alles auswählen

{
 
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
 
Author: Mattias Gaertner
 
Abstract:
TOpenGLControl is a LCL control with an opengl context.
It works under the following platforms:
- gtk with glx : full
- gtk2 with glx : full
- carbon with agl : full
- cocoa : no
- windows with wgl: full
- wince : no
- qt with glx : no (started)
- fpgui with glx : no
- nogui : no
}
unit OpenGLContext;
 ...
 

Key-Real
Beiträge: 10
Registriert: Sa 28. Sep 2013, 23:36

Re: OpenGL unter OSX

Beitrag von Key-Real »

Ich benutze Lazarus nur zum Kompilieren,
die LCL kommt nicht im Frage.
Es muss auch ohne Lazarus (pures FPC) gehen.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: OpenGL unter OSX

Beitrag von mschnell »

Key-Real hat geschrieben:until event.keypressed;
Sowas darf man nur machen, wenn in "event.keypressed();" ein entsprechend ausgelegtes Warten auf das Ereignis im Betriebssystem passiert. Ansonsten bekommt man entweder eine sehr hohe Latenz oder eine extreme Prozessor-Auslastung (die dann z.B. jede Aktivität von OpenGL be- oder ver-hindert). Außerdem will man ja nicht nur auf "Keypressed" sondern auch auf andere Ereignisse reagieren (z.B. Timer, Meldungen von Threads, ...)



In der englischen Mailing Liste haben wir gerade diskutiert, wie man genau dieses Problem (Event-Programmierung ohne Verwendung von "Lazarus" (also des GUI Teils der LCL, der auch "Application", "Platform" oder "Interface" genannt wird und durch entsprechendes Setzen der Konstante "LCLWidgetType" (die oben erwähnten "Dinger" wie "gtk" ... "nogui") beim Kompilieren ausgewählt wird) ) lösen kann:

In der fpc RTL ist bereits eine Event Queue (inklusive Anbindung an das aktuelle Betriebssystem zwecks Latenz- und Overhead-freiem Warten und Wecken) implementiert.

Sie wird durch folgende Funktionen angesprochen:

Schreiben in die Queue:
- TThread.Synchronize();
- TThread.Queue(); (gibt es momentan nur in der SVN-Version, macht das Zeug aber eigentlich erst brauchbar)

Lesen aus der Queue: (wartet, bei leerer Queue, auf Wunsch, bis etwas eingeschrieben wird (oder eine Maximalzeit abläuft) )
- CheckSynchronize();

Mitteilung an Checksynchronize, dass etwas in die Queue geschrieben wurde:
- WakeMainThread();


Ein (TTimer-ähnlicher) Timer ist bisher nicht implementiert.




Wenn ich (vermutlich erst nächstes Jahr) Zeit habe, möchte ich damit einen LCLWidgetType "ActiveNoGUI" implementieren (der dann auswählbarer Teil der LCL werden kann) . Dazu muss dann eine entsprechende TAppication Klasse und ein TTimer implementiert werden.

P.S.: der LCLWidgetType "CustomDrawn" soll auf OpenGL aufsetzen können. Keine Ahnung wie weit die da sind, und ob das auch für OSX implementiert wird. Das wäre aber für dich vermutlich ideal.

P.P.S.: bei mse ( http://www.lazarusforum.de/viewforum.php?f=53 ) gibt es die "activeNoGUI" Funktionalität bereits.

-Michael

Key-Real
Beiträge: 10
Registriert: Sa 28. Sep 2013, 23:36

Re: OpenGL unter OSX

Beitrag von Key-Real »

Leider löst das mein Problem nicht.
Ich muss erstma alles korrekt initialisieren...
Erst dann kann ich die Events abfragen, vieleicht durch multithreading

aber danke ;)
-> Kirill

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: OpenGL unter OSX

Beitrag von mschnell »

Key-Real hat geschrieben:Leider löst das mein Problem nicht.
Ich muss erstma alles korrekt initialisieren...
Erst dann kann ich die Events abfragen, vieleicht durch multithreadingl
Keine Ahnung was Du da meinst. Ich glaube Du hast nicht verstanden, was ich geschrieben habe :(

(Eine gui zu Multithreadden ist ausgesprochen schwierig bis ziemlich unmöglich. Da solltest Du die Fingen von lassen !

PS.: fpGUI solltest Du Dur vielleicht auch ansehen ( http://fpgui.sourceforge.net/ ). Das arbeitet ohne LCL und mit OpenGL.

-Michael

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: OpenGL unter OSX

Beitrag von mse »

mschnell hat geschrieben:Das arbeitet ohne LCL und mit OpenGL.
Wie kommst du darauf dass fpGUI mit OpenGL arbeitet? MSEgui hat ein experimentelles OpenGL backend, fpGUI AFAIK nicht.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: OpenGL unter OSX

Beitrag von mschnell »

Das scheint ein Irrtum gewesen zu sein. In den Projekt-Optionen gibt es nur die "fpGUIPlatform" "X11" und "gdi". Ich hatte gedacht, ich hätte da mal OpenGl gesehen.

Sorry,
-Michael

Key-Real
Beiträge: 10
Registriert: Sa 28. Sep 2013, 23:36

Re: OpenGL unter OSX

Beitrag von Key-Real »

Sorry Leutez,
ich rede von öffnen eines OpenGL Contextes unter MAC OSX!
und über EVENT-Bechandlung!

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: OpenGL unter OSX

Beitrag von mschnell »

Key-Real hat geschrieben:EVENT-Bechandlung!
Was genau meinst Du mit Event ?

In Object Pascal ist ein Event einfach ein Callback eines Objektes.

Das kann dann in verschiedenen Arten verwendet werden.

Bei einer Event-Queue, wie sie z.B. von TThread (für ".Synchronize und ".Queue") und von der LCL für GUIä-Bedienung zur Verfügung gestellt wird spricht man von "Asynchonen Mainthread-Events", weil sie vom Mainthread bearbeitet werden sollen, aber nicht vom Mainthread selber erzeugt werden.

"Events" einer externen (z.B. grafischen) Library (wie OpenGL) müssen zuerst einmal in asynchrone Mainthread Events umgewandelt werden, bevor das eigentliche User-Programm etwas damiot anfangen kann.

-Michael

Key-Real
Beiträge: 10
Registriert: Sa 28. Sep 2013, 23:36

Re: OpenGL unter OSX

Beitrag von Key-Real »

Dies ist meine Event-Handler Routine(gekürtzt) für ankommende Windows-Events:




Code: Alles auswählen

function gfxWindowProc(Window: HWnd; AMessage: Longint; WParam : WPARAM; LParam: LPARAM): LRESULT; stdcall; export;
begin
 
                  case AMessage of
                    wm_Destroy: begin
                            HALT;
                      end;
 
                    wm_close:
                      begin
                       PostMessage(gfxhWindow, WM_DESTROY, 0, 0);
                       exit;
                      end;
 
                    wm_keydown:
                      begin
                        case loword(wParam) of
                           VK_ESCAPE: begin
                                            PostMessage(gfxhWindow, WM_CLOSE, 0, 0);
                                            exit;
                                      end;
                        end;
                      end;
                    wm_keyup:
                      begin
                     end;
                    wm_syscommand:               // system wants something..
                      begin
                        case (wParam) of
                              SC_SCREENSAVE : begin         // ..don't start any screensavers.
                                                gfxwindowproc:= 0;
                                                exit;
                                              end;
 
                              SC_MONITORPOWER : begin       // ..and don't kill monitor power.
                                                 gfxwindowproc:= 0;
                                                 exit;
                                                end;
                        end;
                      end;
 
                    WM_MOUSEMOVE: begin
 
                                        gfxMouseX := lParam and $FFFF;
                                        gfxMouseY := (lParam shr 16) and $FFFF;
                                        exit;
                                end;
                    WM_LBUTTONDOWN: begin
                                          gfxMouseL:= true;
                                          exit;
                                    end;
 
                    WM_LBUTTONUP: begin
                                        gfxMouseL:= false;
                                        exit;
                                  end;
                    WM_MBUTTONDOWN: begin
                                         gfxMouseM:=true;
                                         exit;
                                      end;
                    WM_MBUTTONUP: begin
                                      gfxMouseM:=false;
                                      exit;
                                  end;
                    WM_RBUTTONDOWN: begin
                                         gfxMouseR:=true;
                                          exit;
                                    end;
                    WM_RBUTTONUP:begin
                                       gfxMouseR:=false;
                                       exit;
                                       end;
                    WM_SETCURSOR:begin
                                       SetCursor(0);
                                       exit;
                                 end;
 
                    WM_PAINT: begin
                                          // DRAW SOMETHING
                              end;
                         end;
                  end;
 
 
     gfxWindowProc := DefWindowProc(Window, AMessage, WParam, LParam);
 
  end;
 
 
end;
 
 
 



Das meine Ich mit Eventbechandlung.

Brauche das gleiche für OSX!

Bitte, kein GLUT,kein SDL, kein LCL.

Danke,
Kirill
Zuletzt geändert von Lori am So 6. Okt 2013, 12:03, insgesamt 2-mal geändert.
Grund: Highlighter

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: OpenGL unter OSX

Beitrag von mschnell »

Nochmal zur Erläuterung:

>>> "Events" einer externen (z.B. grafischen) Library (wie OpenGL) müssen zuerst einmal in asynchrone Mainthread Events umgewandelt werden, bevor das eigentliche User-Programm etwas damit anfangen kann.

Wie das realisiert wird, ist von der Machart der auf dem Rechner installierten GUI-Infrastruktur abhängig.

Das geht bei Windows (was in der LCL Widget Type Windows" realisiert ist) beispielsweise dadurch, dass der Mainthread immer auf eine Windows-Message wartet und wenn eine kommt dann entsprechend regiert. Die Windows-GUI schickt nämlich Messages, nachdem diese von Windows selbst in einer Queue gespeichert und eine nach der anderen an das Programm weitergegeben werden.

Bei GTK (in der LCL Widget Type "GTK") und ähnlichen GUIs realisiert das die LCL, indem sie selber eine Queue aufbaut in die die GUI Events von einem Callback der GUI eingespeichert werden und dann vom Mainthread eines nach dem anderen herausgeholt werden.

Wenn man die GUI per TCP/IP ankoppeln will (was zum Beispiel mit X11 möglich ist), könnte man einen TThread starten, der in einem Blocking Read auf TCP/IP Daten warten (die bei GUI-Event ankommen werden). Der Thread könnte dann die "Events" (ohne die LCL) als asynchrone Funktions-Aufrufe per TThread.Queue dem Mainthread zur Bearbeitung geben.

Keine Ahnung wie das bei OpenGL gemacht werden kann. Anscheinend hat es ja noch nie jemand ausprogrammiert.

Der von Dir gezeigte Code scheint Windows Messages aus openGL Events zu machen ("PostMessage"). Damit wäre also eine Methode wie beim LCL-Widget Typ "Windows" anwendbar: Du brauchst die Queue nicht selbst zu bauen, sondern du verwendest die Windows Message-Queue.

Die Messages empfängst Du mit einer "procedure.... message" in einem Form. Das geht aber - glaube ich - nur, wenn du die LCL einbindest. Vielleicht täusche ich mich da. Wenn Du die LCL nicht einbinden willst, musst du den Mechanismus hinter "procedure.... message" vermutlich selber mit Windows-API-Calls und RTL- Aufrufen programmieren.


P.S.: zur Ankopplung von OpenGL an ein Programm könntest Du dir den SDL Toolkit anschauen. Für Pascal-Programme gibt es da Jedi-SDL. Damit habe ich vor vielen Jahren mal ein Delphi-Programm gemacht. Ich glaube nicht, dass da ein GUI-Builder mitgeliefert wird. Gedacht ist wohl eher, ein OpenGL-Fenster (oder einen temporären Fullscreen) aufzubauen und die GUI parallel dazu mit den normalen Mitteln der Sprache zu programmieren.

-Michael

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: OpenGL unter OSX

Beitrag von mschnell »

P.S.: Ich mache zwar nicht viel in Windows aber:

Es ist durchaus möglich, dass in Windows das Warten auf Messages in er oben beschriebenen Funktion "Checksynchronnize" realisiert ist, die man in einem Programm ohne LCL aufrufen Kann, um den Mainthread auf irgendetwas warten zu lassen. TThread.Queue etc müssen nämlich PostMessage machen, um den Mainthread zu wecken.

Da kommen dann möglicherweise auch andere Windows Messages an, die vielleicht sogar schon irgendwie auf eine procedure .... message geleitet werden.

Wo man das procedure .... message aber verwenden darf, weiß ich nicht. Ich kenne es nur von Forms und die gibt es ja nur mit der LCL.

-Michael

Key-Real
Beiträge: 10
Registriert: Sa 28. Sep 2013, 23:36

Re: OpenGL unter OSX

Beitrag von Key-Real »

Es tut mir leid, aber wir sind vom Thema abgekommen :(
Ich wollte wissen wie man unter OSX(apple mac) korrekt einen OpenGL Context eröfnet und die
eingabe von der Tastatur und der Maus behandelt (vieleicht auch anderer Events, wie z.B. Das Fenster schließen oder Minimieren und so).
Danke,
Kirill

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: OpenGL unter OSX

Beitrag von Christian »

Ich glaub da ists besser bei Apple oder nem ObjectiveC Forum zu schaun.
https://developer.apple.com/opengl/

Hier ist nochn example das ganze mit GLU zu machen (hast ja nur GLUT ausgeschlossen)
http://ysflight.in.coocan.jp/programmin ... dow/e.html

hier wirst nicht viele Antworen ausserhalb der LCL erwarten können. Lazarus basiert nunmal auf der LCL.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Antworten