Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Di Mai 14, 2024 12:09

Foren-Übersicht » English » English Programming Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 9 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Sa Feb 03, 2007 17:21 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
Well, I've had good help from here so far and I thought I'd ask a question that's been on my mind since starting with OpenGL. The question is around coordinates and sizing and the fact that they're usually GLFloats and appear to be between small values like -1.0 and 1.0... as I've been coding simple 2D / VCL programs (with limited graphics) for years, I'm obviously much better suited to working in unit of pixels and I'm wondering what's the simplest way to go about this in OpenGL (but not in 2D orthographic - as I've done that already for 2D stuff).

I'm building up a concept of 3D Album Cover picking for addition to my HMusicCentre application so I'm only a little way down the experimental path so far - but I have the drawing working and the picking working. Here I include a link to a .zip file here that contains all the required files to simply compile it in Delphi 7... there's also the small .exe included - here: http://www.hmusiccentre.org.uk/download ... icking.zip - it's only 360K, so if anyone helpful wanted to get hold it and see what I'm doing that'd be great.

Here's how it looks... my Album Covers spin around and wobble a bit, then - when the mouse goes over them - they lean at a shallower angle so that the user can see what they are more clearly - that's the idea anyway. I'm drawing my quads using the GLFloat coordinates, but measuring where my mouse is using Pixels - not a great idea I am sure.

Bild

At the moment, I'm displaying my OpenGL stuff directly to a TForm that is around 1000 x 600 pixels in size, and I'm setting up OpenGL with the following code...

Code:
  1. DC := GetDC (Handle);
  2. SetupPixelFormat (DC);
  3. RC := wglCreateContext (DC);
  4. wglMakeCurrent (DC,RC);
  5.  
  6. glMatrixMode (GL_PROJECTION);
  7. glFrustum (-0.1,0.1,-0.1,0.1,0.3,25.0);
  8. glMatrixMode (GL_MODELVIEW);
  9.  
  10. glEnable (GL_DEPTH_TEST);
  11. glDepthFunc (GL_LESS);
  12. glHint (GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
  13. glEnable (GL_TEXTURE_2D);
...which I guess is pretty standard stuff. Then I draw my Quads with a function that takes a number of GLFloats for position, angles, rotation and size...

Code:
  1. DSquare (1,-1.5,-2,-10,-Flipper1,AlbumCoverSize,Lean1);
...what I'd like to be able to do is set up my program so that I can address my (X,Y,Z) coordinates and sizes etc. with pixels... obviously Angles will need to be as they are now. It's all in the source code and is kind of self-explanatory I think.

So, when I used the 2D orthographic mode, I used:

Code:
  1. glOrtho (0,pOGL.Width,0,pOGL.Height,-10,10);
  2. glMatrixMode (GL_MODELVIEW);
...which makes sense to me... with 3D I'll admit that I've got a little confused. Should I be using something like glViewport or gluPerspective or a combination of both? How would I set up my OpenGL application so that I'm drawing directly to a TForm in 3D and I have the entire TForm area to draw to and I can address my coordinates in pixels?

Something like:

Code:
  1.  
  2. glViewport (0,0,Form1.Width,Form1.Height);
  3. glMatrixMode (GL_PROJECTION);
  4. glLoadIdentity;
  5. gluPerspective (45.0,Form1.Width / Form1.Height,0.1,100.0);
  6. glMatrixMode (GL_MODELVIEW);
  7. glLoadIdentity;
  8.  
...which I've seen in another example... is that on the right track? Also - is this approach inadvisable for some reason that I'm not aware of? Should I be sticking to my small GLFloats and finding another way to recognise where my mouse is on the screen without using Delphi's OnMouseOver event?

P.S. I understand that different coordinates systems are used by these technologies as well... with 1,1 being top-left in Delphi and 1,1 being bottom-left in OpenGL... I think!

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Rephrase...
BeitragVerfasst: Sa Feb 03, 2007 18:54 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
Hmm... is my question best asked: "How can I have a 1:1 relationship between OpenGL coordinates and screen / canvas / form / handle pixels in 3D?" or even "Can I actually have a 1:1 relationship between pixels and OpenGL coordinates / units in 3D?".

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Feb 03, 2007 20:18 
Offline
Ernährungsberater
Benutzeravatar

Registriert: Sa Jan 01, 2005 17:11
Beiträge: 2067
Programmiersprache: C++
Look for gluUnProject.
It only works if you're pointing on an object. If you're pointing in the deep space the result will be crap.

_________________
Steppity,steppity,step,step,step! :twisted:
❆ ❄ ❄ ❄ ❅ ❄ ❆ ❄ ❅ ❄ ❅ ❄ ❅ ❄ ❄
❄ ❄ ❄ ❅ ❄ ❄ ❄ ❅ ❄ ❄ ❆ ❄ ❄


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Yup, I'm stuck...
BeitragVerfasst: Sa Feb 03, 2007 20:50 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
I think I might have to go back to some OpenGL basics because I think I am lacking some understanding of the simple stuff. I know how to use pixels as my units when using orthographic projection - I was a little surprised to find that I could not do this so simply with perspective... I mean, surely if I'm defining a vertex at -0.2,0.3 I should be able to define a vertex at the relevant position on my screen if I understand the pixels, say 20,40 or something like that. That's what's getting me confused... and I think it's all to do with how I'm setting up OpenGL, using glFrustrum or gluPerspective.

I'll do a bit of research into gluUnProject as well... see if I can make sense of this. My code below is the simplest display a triangle on screen example I could come up with - in my perfect world, I wouldn't be constrained to passing in units to the DrawTriangleByUnits procedure, I could pass in pixels and still end up with my triangle being drawn, but with much more idea of where I wanted it to be, rather than using fractions of a screen.

Code:
  1. unit Main;
  2.  
  3. interface
  4.  
  5. uses
  6.   OpenGL, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   StdCtrls, ExtCtrls, ComCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     Timer1: TTimer;
  12.     procedure FormCreate (Sender : TObject);
  13.     procedure Timer1Timer (Sender : TObject);
  14.   private
  15.     procedure Draw;
  16.     procedure DrawTriangleByUnits ( Width, Height : GLFloat);
  17.     procedure DrawTriangleByPixels ( Width, Height : Integer);
  18.   public
  19.   end;
  20.  
  21. var
  22.   Form1 : TForm1;
  23.   Flipper1 : GLFloat;
  24.  
  25.  
  26. implementation
  27.  
  28.  
  29. {$R *.DFM}
  30.  
  31.  
  32. procedure setupPixelFormat ( DC :HDC
  33.                            );
  34. const
  35.    PFD : TPIXELFORMATDESCRIPTOR = (nSize : SizeOf (TPIXELFORMATDESCRIPTOR);
  36.          nVersion : 1;
  37.          dwFlags : PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER;
  38.          iPixelType : PFD_TYPE_RGBA;
  39.          cColorBits : 24;
  40.          cRedBits : 0; cRedShift : 0; cGreenBits : 0;  cGreenShift : 0; cBlueBits : 0; cBlueShift : 0;
  41.          cAlphaBits : 0; cAlphaShift : 0; cAccumBits : 0; cAccumRedBits : 0; cAccumGreenBits : 0;
  42.          cAccumBlueBits : 0; cAccumAlphaBits : 0; cDepthBits : 16; cStencilBits : 0; cAuxBuffers : 0;
  43.          iLayerType : PFD_MAIN_PLANE; bReserved : 0; dwLayerMask : 0; dwVisibleMask : 0; dwDamageMask : 0);
  44. var
  45.   PixelFormat : Integer;
  46. begin
  47.   PixelFormat := ChoosePixelFormat (DC,@PFD);
  48.   if (PixelFormat = 0) then
  49.   begin
  50.     Exit;
  51.   end;
  52.  
  53.   if (SetPixelFormat (DC,PixelFormat,@PFD) <> True) then
  54.   begin
  55.     Exit;
  56.   end;
  57. end;
  58.  
  59.  
  60. procedure TForm1.FormCreate ( Sender : TObject
  61.                             );
  62. var
  63.   DC : HDC;
  64.   RC : HGLRC;
  65. begin
  66.   DC := GetDC (Handle);
  67.   SetupPixelFormat (DC);
  68.   RC := wglCreateContext (DC);
  69.   wglMakeCurrent (DC,RC);
  70.  
  71.   { Question is here... is there a way to set up OpenGL so that its units are
  72.     equivalent to pixels? So I could then create do "glVertex (100,100,0);"
  73.     instead of "glVertex (-1,-1,0);"? }
  74.  
  75.   { These three lines, and the next three lines can be interchanged to produce
  76.     working results for "DrawTriangleByUnits" - but slightly different. Does a
  77.     way exist to use glFrustrum, or gluPerspective to allow me to define my
  78.     vertexes in pixels instead of units... the answer is "yes" for "glOrtho",
  79.     there you just pass "(0,pOGL.Width,0,pOGL.Height,-10,10);" }
  80.   glMatrixMode (GL_PROJECTION);
  81.   glFrustum (-0.1,0.1,-0.1,0.1,0.3,25.0);
  82.   glMatrixMode (GL_MODELVIEW);
  83.  
  84.   { Use the three lines above, or these three lines. I prefer the way that the
  85.     triangle looks with the three lines above. }
  86.   // glMatrixMode (GL_PROJECTION);
  87.   // gluPerspective (45.0,Form1.Width / Form1.Height,1.0,500.0);
  88.   // glMatrixMode (GL_MODELVIEW);
  89.  
  90.   glEnable (GL_DEPTH_TEST);
  91.   glDepthFunc (GL_LESS);
  92.   glHint (GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
  93.   glEnable (GL_TEXTURE_2D);
  94.  
  95.   Flipper1 := 0;
  96.   glClearColor (0,0,0.3,1);
  97. end;
  98.  
  99.  
  100. procedure TForm1.Draw;
  101. begin
  102.   glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  103.  
  104.   { Works as you would expect... }
  105.   DrawTriangleByUnits (1,1);
  106.  
  107.   { Obviously can't work, as OpenGL is set up to use units... not pixels. }
  108. //  DrawTriangleByPixels (100,100);
  109.  
  110.   if (Flipper1 = 360) then
  111.   begin
  112.     Flipper1 := 0;
  113.   end;
  114.  
  115.   SwapBuffers (wglGetCurrentDC);
  116. end;
  117.  
  118.  
  119. { This is working exactly as I would have expected, translating and setting the
  120.   origin and drawing vertexes around it to form a triangle of varying colours. }
  121.  
  122. procedure TForm1.DrawTriangleByUnits ( Width, Height : GLFloat
  123.                                      );
  124. begin
  125.   glLoadIdentity;
  126.   glTranslate (0,0,-4);
  127.   glRotate (Flipper1,0,1,0);
  128.   glBegin (GL_TRIANGLES);
  129.     glColor3f (1,0,0);
  130.     glVertex (-Width,-Height,0);
  131.     glColor3f (0,1,0);
  132.     glVertex (Width,-Height,0);
  133.     glColor3f (0,0,1);
  134.     glVertex (0,Height,0);
  135.   glEnd;
  136. end;
  137.  
  138.  
  139. { How can I set up OpenGL so that the units it uses are relevant to the number
  140.   of pixels I have on my target, whether that be a TPanel or TForm? Obviously
  141.   this procedure will not work as OpenGL is currently set up. }
  142.  
  143. procedure TForm1.DrawTriangleByPixels ( Width, Height : Integer
  144.                                       );
  145. begin
  146.   glLoadIdentity;
  147.   { This line would be different if 0,0 wasn't in the centre of the screen. }
  148.   glTranslate (0,0,-4);
  149.   glRotate (Flipper1,0,1,0);
  150.   { Coordinates for glVertex might very well also be different... }
  151.   glBegin (GL_TRIANGLES);
  152.     glColor3f (1,0,0);
  153.     glVertex (-Width,-Height,0);
  154.     glColor3f (0,1,0);
  155.     glVertex (Width,-Height,0);
  156.     glColor3f (0,0,1);
  157.     glVertex (0,Height,0);
  158.   glEnd;
  159. end;
  160.  
  161.  
  162. procedure TForm1.Timer1Timer ( Sender : TObject
  163.                              );
  164. begin
  165.   Flipper1 := Flipper1 + 1;
  166.   Draw;
  167. end;
  168.  
  169.  
  170. end.

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Feb 04, 2007 01:35 
Offline
Ernährungsberater
Benutzeravatar

Registriert: Sa Jan 01, 2005 17:11
Beiträge: 2067
Programmiersprache: C++
In theory you can calculate this by the values given to gluPerspective. Nevertheless I would say, that it will be better to draw a big rectangle at that deep you want you objects and use gluUnProject with the edges of your window to get these coordinates. Will be the easiest but not niced way.

_________________
Steppity,steppity,step,step,step! :twisted:
❆ ❄ ❄ ❄ ❅ ❄ ❆ ❄ ❅ ❄ ❅ ❄ ❅ ❄ ❄
❄ ❄ ❄ ❅ ❄ ❄ ❄ ❅ ❄ ❄ ❆ ❄ ❄


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: gluUnProject...
BeitragVerfasst: So Feb 04, 2007 01:53 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
I had a quick look at gluUnProject which seems to convert Windows screen coordinates to OpenGL coordinates - sounded like something I wanted (although I must say, it sounds like a lot of code for something I'd hoped would be part of the set-up process that I'd just missed). Anyway, I got hold of a function just to give it a go...

Code:
  1.  
  2. function GetOpenGLPos ( X, Y : Integer
  3.                       ) : T3D_Point;
  4. var
  5.   viewport : array [1..4]  of Integer;
  6.   modelview : array [1..16] of Double;
  7.   projection : array [1..16] of Double;
  8.   winZ : Single;
  9. begin
  10.   glGetDoublev (GL_MODELVIEW_MATRIX,@modelview);
  11.   glGetDoublev (GL_PROJECTION_MATRIX,@projection);
  12.   glGetIntegerv (GL_VIEWPORT,@viewport);
  13.  
  14.   if (Y = 0) then
  15.   begin
  16.     Y := 1;
  17.   end;
  18.  
  19.   glReadPixels (X,-Y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,@winZ);
  20.   gluUnProject (X,viewport[4] - Y,winZ,@modelview,@projection,@viewport,Result[1],Result[2],Result[3]);
  21. end;
  22.  
...and then in my TForm's OnMouseDown event I used the following code to see if I could convert an X and Y mouse positional value to something that appeared relevant in OpenGL coordinates...

Code:
  1.  
  2. OpenGLPoint := GetOpenGLPos (X,Y);
  3. ShowMessage (IntToStr (X) + ', ' + IntToStr (Y) + ', ' + FloatToStr (OpenGLPoint[1]) + ', ' + FloatToStr (OpenGLPoint[2]) + ', ' + FloatToStr (OpenGLPoint[3]));
  4.  
...to be honest, it didn't make much sense to me. Even though I left my mouse in the same place and dismissed the message box with the Return key, the OpenGL coordinates reported by the function seemed to vary wildy. I got constant values for the X and Y mouse coordinates - as you would expect - but massive differences in the reported OpenGL coordinates - sometimes flipping between positive and negative without me even moving the mouse.

I guess what I'd originally hoped for... a way to just use pixel coordinates in OpenGL, without being in orthographic mode, isn't either possible - or there's certainly a good reason for why people don't use it... I just wonder what that reason is. As I had mentioned, at the beginning, working in pixels is just more natural for me... maybe I'll have to work in these units after all...

So, that said, is there a way to change the granularity of the OpenGL units... like, when you set up a program, the default values seem to be from -1 to 1... is there a way (or is there absolutely no reason to do this) to have say -10 to 10?

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: gluUnProject...
BeitragVerfasst: So Feb 04, 2007 02:13 
Offline
Ernährungsberater
Benutzeravatar

Registriert: Sa Jan 01, 2005 17:11
Beiträge: 2067
Programmiersprache: C++
dpm_dpmartin hat geschrieben:
I guess what I'd originally hoped for... a way to just use pixel coordinates in OpenGL, without being in orthographic mode, isn't either possible - or there's certainly a good reason for why people don't use it... I just wonder what that reason is. As I had mentioned, at the beginning, working in pixels is just more natural for me... maybe I'll have to work in these units after all...

If you change windowresolution or using fullscreen on different pc you have to take care of different windowwidths. When using OpenGL units you don't have to care at all.

dpm_dpmartin hat geschrieben:
So, that said, is there a way to change the granularity of the OpenGL units... like, when you set up a program, the default values seem to be from -1 to 1... is there a way (or is there absolutely no reason to do this) to have say -10 to 10?

You can use glScalef(x, y, z) to scale each axis.

Attached to this post is a sample where a cube is drawn at the position of the mouse. The origin of that code is from Sulaco. At the bottom of that page, the last tutorial from him :cry:


Dateianhänge:
Maus.rar [216.72 KiB]
267-mal heruntergeladen

_________________
Steppity,steppity,step,step,step! :twisted:
❆ ❄ ❄ ❄ ❅ ❄ ❆ ❄ ❅ ❄ ❅ ❄ ❅ ❄ ❄
❄ ❄ ❄ ❅ ❄ ❄ ❄ ❅ ❄ ❄ ❆ ❄ ❄
Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Thanks!
BeitragVerfasst: So Feb 04, 2007 11:34 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
Well, you're right - that definitely works.

You made a very interesting comment, to me, about the fact that using the OpenGL unit (or fractions of the screen, i.e. 0.1) means that you don't have to really care about what resolution your user is running in - if they're running in 800x600 then OpenGL will scale everything correctly and if they're running in 1024x768, again - everything will be scaled according to the fractions of the screen.

I get this. However, it kind of goes exactly against what I was wanting to do really. In my program, I also encourage my users to run in whatever screen resolution they wish to - but running in a higher resolution means that they will get more Album covers on their screen... because they define the size of the Album Covers they wish to do - in pixels. So, as the screen real-estate grows. This part of my program is what I'm looking to covert across to OpenGL...

The following example picture show what I mean I hope, although they're all at 1024x768 in the program, the user can choose how big their Album Covers are... if they select a size, then change their resolution, the amount they see will differ according to how many HMusicCentre can fit nicely onto the screen.

HMusicCentre with a cover size (in pixels of 216):
Bild

HMusicCentre with a cover size (in pixels of 130):
Bild

HMusicCentre with a cover size (in pixels of 95):
Bild

I'm sure there's a clever way of getting around this. I don't want to use orthographic projection because I do want to do some things in 3D (my Album Covers) and make things rotate and translate (and potentially scale). I can't do that kind of stuff in 3D with glOrtho (0,pOGL.Width,0,pOGL.Height,-10,10); can I, even though there is a depth part to the call... as opposed to gluOrtho2D which doesn't have that at all?

At the moment, my plan is to start work in a non-orthographic projection mode... my next question then comes down to whether I can 'limit' the amount of perspective while still getting the 3D parts, for example - I would like my Album Covers arranged on the screen to look as 'flat' as possible... but I might want the current Album playing to have its texture (and other Albums by the same Artist) placed on the faces of a cube that comes closer to the user and rotates - I'd still need to see perspective on that.

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Feb 04, 2007 19:07 
Offline
Ernährungsberater
Benutzeravatar

Registriert: Sa Jan 01, 2005 17:11
Beiträge: 2067
Programmiersprache: C++
Ok, before reading you second topic I answer to this:
I have thought a bit and found a result:
If you're looking at a wall covered with song covers, only the covers in center of your view will be squares. Right or left of them, the covers are getting rectancles. This is because of the perspective view and here is your problem: You want to force 2D in 3D what is not thought for. But for a solution you can mix 2D and 3D. There is no problem with drawing in 2D, then switching to 3D and continue drawing. No problem at all and will solve your problem.
Or as an alternative you can draw a "real" room with covers on the wall where the user can look around and select covers.

_________________
Steppity,steppity,step,step,step! :twisted:
❆ ❄ ❄ ❄ ❅ ❄ ❆ ❄ ❅ ❄ ❅ ❄ ❅ ❄ ❄
❄ ❄ ❄ ❅ ❄ ❄ ❄ ❅ ❄ ❄ ❆ ❄ ❄


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 9 Beiträge ] 
Foren-Übersicht » English » English Programming Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.025s | 20 Queries | GZIP : On ]