(WINAPI OpenGL) Почему не удаётся использовать writeln?

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

(WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение xterro » 22.12.2015 12:27:18

Доброго времени суток, есть небольшая программка, рисующая всякую всячину в окошке при помощи OpenGL(просто тестовый пример), добавил вот функцию v2w, для перевода видовых координат в мировые и хочу посмотреть, чтоже у меня получается на выходе этой функции. Для этого планировал использовать обычный writeln, но если добавить его в функцию wndproc, т.е там где собственно и идёт вызов функции, где обрабатываются нажатия клавиш, мышки etc. то при запуске приложение просто зависает, что не так делаю?

Код: Выделить всё

{$MODE objfpc}{$H+}
{$APPTYPE GUI}

program ogl_fpc_source01;

uses
    {$ifdef windows} 
    windows,
    {$endif}
    gl, glu;

var

    msg : TMSG;      // Windows messages
    hWindow : HWnd;   // Windows Handle to the OGL Window
    dcWindow : hDc;   // Device Context for the OGL Window
    rcWindow : HGLRC;   // Render Context for the OGL Window

    width, height, bits : longint;
    fullscreen, active : boolean;
   zoom : real;
   w, h : integer;
   wx, wy : real;
   //vx, vy : integer;
   cur_wx, cur_wy : real;
   tmp_wx, tmp_wy : real;


{ viewport to world coordinates translation }
procedure v2w(vx, vy : integer; var wx, wy : real);
var
   viewport : array[0..3] of integer;
   modelview : array[0..15] of real;
   projection : array[0..15] of real;
   wz : real;
begin
   glGetDoublev(GL_MODELVIEW_MATRIX, @modelview);     //get the modelview info
   glGetDoublev(GL_PROJECTION_MATRIX, @projection); //get the projection matrix info
   glGetIntegerv(GL_VIEWPORT, @viewport);           //get the viewport info
   
   gluUnProject(vx, viewport[3]-vy-1, 0, @modelview, @projection, @viewport, @wx, @wy, @wz);
end;
   
   
// Simple OGL initialisation for testing. //
procedure OpenGL_Init();
begin
   
   zoom := 1.0;
   w := 1200;   
   h := 800;
   
   wx := 0;
   wy := 0;
   
   
    glShadeModel(GL_SMOOTH);
//   glEnable(GL_LINE_SMOOTH);
   
  //  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
   //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
   glEnable(GL_BLEND);                                  // Включается смешение цветов, необходимое
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   
   
    glClearColor( 0.0, 0.0, 0.0, 1.0 );
   
    glMatrixMode(GL_PROJECTION);                           
    glLoadIdentity();                                       
   gluOrtho2D(wx, w, wy, h);
   
   glMatrixMode(GL_MODELVIEW);                             
    glLoadIdentity;

   
   
end;

function OpenGL_Render() : boolean;
var
   i, j : real;
begin
    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
   
    { draw here }
   
    glClear( GL_COLOR_BUFFER_BIT );
   glLoadIdentity();
   
   glTranslatef(wx, wy, 0.0);
   glScalef(zoom, zoom, 0.0);
   
   
   glColor3f(1.0, 1.0, 1.0);
   glBegin(GL_LINE_LOOP);
      glVertex2f(1.0, 1.0);
      glVertex2f(1.0, h-1);
      glVertex2f(w-1, h-1);
      glVertex2f(w-1, 1.0);
   glEnd();
   
   i := 0;
   j := 0;
   glColor3f(0.5, 0.5, 0.5);
   glBegin(GL_POINTS);
      while i < 1200 do begin
         while j < 800 do begin
            glVertex2f(i, j);
            j := j + 20;
         end;
         j := 0;
         i := i + 20;
      end;
   glEnd();
   
   glColor3f(1.0, 0.0, 0.0); 
   glBegin(GL_LINES);
      glVertex2f(0.0, 0.0);
      glVertex2f(100, 100);
   glEnd();
   
   
   
    swapBuffers( dcWindow );   // put opengl stuff to screen
    result := true;
end;

procedure OpenGL_Resize(width : integer; height : integer);

//   ar : real;
begin
    if (Height = 0) then                                       
        Height := 1;                                         
    glViewport(0, 0, width, height); 
   //ar := width/height;
   
   
      
   {
   glMatrixMode(GL_PROJECTION);                           
    glLoadIdentity();                                       
    if(width > height) then
      gluOrtho2D(0, w, 0, h*ar)
   else
      gluOrtho2D(0, w*ar, 0, h);
   glMatrixMode(GL_MODELVIEW);                             
    glLoadIdentity;  }                       
end;
     

// Try, Throw, Catch mechanism. Simple proc to display given errors. //
procedure ThrowError(pcErrorMessage : pChar);
begin
    MessageBox(0, pcErrorMessage, 'Error', MB_OK);
    Halt(0);
end;


// Standard WinProc. Handles all the messages from the System. //
function GLWndProc(Window: HWnd; AMessage, WParam, LParam: Longint): Longint; stdcall; export;
begin
    GLWndProc := 0;

    case amessage of
        wm_create:
        begin
            active := true;      // if GL Window was created correctly, then set
            exit;         // active-flag to "true".
        end;
       
        wm_paint:
        begin
            OpenGL_Render();
            exit;         // nothing to paint to Windows as we do all drawing with OGL
        end;
       
        wm_size:
        begin
            OpenGL_Resize(LOWORD(lParam), HIWORD(lParam));
            OpenGL_Render();
            active := true;
          //  exit;
        end;
       
        wm_move:
        begin
            //writeln('move window');
         exit;
        end;
       
        wm_erasebkgnd:
        begin
            exit; // чтобы не перезаливалось окно и не мерцало
        end;
      
      { --- MOUSE --- }
      
      wm_lbuttondown:
      begin
         exit;
      end;
      
      wm_lbuttonup:
      begin
         exit;
      end;
      
      wm_mousewheel:
      begin
         if wparam > 0 then
            //if zoom < 2 then
               zoom := zoom + 0.05
         else
            if zoom > 0.3 then
               zoom := zoom - 0.05;
         
         opengl_render();
   //      exit;
      end;
      
      wm_mbuttondown:
      begin
         //cur_x := loword(lparam);
         //cur_y := hiword(lparam);
         v2w(loword(lparam), hiword(lparam), cur_wx, cur_wy);
                       //  writeln('mouse mbutton down');   // Если раскоментить, то при нажатии средней кнопки мыши, программа зависает (
      //   exit;
      end;
      
      wm_mbuttonup:
      begin
         
         exit;
      end;
      
      
      wm_mousemove:
      begin
         if wparam = MK_MBUTTON then
         begin
            { нажата средняя кнопка мыши, двигаем область рисования }
            v2w(loword(lparam), hiword(lparam), tmp_wx, tmp_wy);
            wx := wx + (tmp_wx - cur_wx);
            wy := wy - (tmp_wy - cur_wy);
            opengl_render();
         end;
      //   exit;
      end;

      { --- KEYBOARD --- }
        wm_keydown:
        begin           
         case wParam of
            VK_ESCAPE    : begin {SendMessage(hWindow,wm_destroy,0,0);} end;
            VK_ADD       : begin zoom := zoom + 0.25; opengl_render();  end;
            VK_SUBTRACT : begin zoom := zoom - 0.25; opengl_render();  end;
            VK_UP       : begin wy := wy + 10; opengl_render(); end;
            VK_DOWN    : begin wy := wy - 10; opengl_render(); end;
            VK_LEFT    : begin wx := wx - 10; opengl_render(); end;
            VK_RIGHT    : begin wx := wx + 10; opengl_render(); end;
         end;
           // exit;         // check for ESC key. If pressed, then send quit message
        end;
      
      
      wm_keyup:
      begin
         case wParam of
            VK_F1 : begin { line    } end;
            VK_F2 : begin { rect    } end;
            VK_F3 : begin { circle  } end;
            VK_F4 : begin { arc     } end;
            VK_F5 : begin { polygon } end;
            VK_F6 : begin { text    } end;
         end;
      //   exit;
      end;

        wm_destroy:
        begin
            active := false;   // if quit message was sent, exit the main loop by setting
            PostQuitMessage(0);   // the active-flag to "false".
     //       exit;
        end;

        wm_syscommand:      // system wants something..
        begin
            case (wParam) of
                SC_SCREENSAVE : begin      // ..don't start any screensavers.
                    GLWndProc := 0;
                end;

                SC_MONITORPOWER : begin   // ..and don't kill monitor power.
                    GLWndProc := 0;
                end;
            end;
        end;
    end;
    GLWndProc := DefWindowProc(Window, AMessage, WParam, LParam);   // let Windows deal with the rest of the messages.
end;


// Register the Window Class. //
function WindowRegister: Boolean;
var
    WindowClass: WndClass;
begin
    WindowClass.Style           := cs_hRedraw or cs_vRedraw;
    WindowClass.lpfnWndProc     := WndProc(@GLWndProc);      // Handle to our Windows messaging interface func.
    WindowClass.cbClsExtra      := 0;
    WindowClass.cbWndExtra      := 0;
    WindowClass.hInstance       := system.MainInstance;         // Get the Windows Instance for our app.
    WindowClass.hIcon           := LoadIcon(0, idi_Application);
    WindowClass.hCursor         := LoadCursor(0, idc_Arrow);
  //  WindowClass.hbrBackground   := GetStockObject(WHITE_BRUSH);
    WindowClass.lpszMenuName    := nil;
    WindowClass.lpszClassName   := 'GLWindow';         // Name the specified Window Class

    WindowRegister := RegisterClass(WindowClass) <> 0;
end;


// Create the OGL Window. //
function WindowCreate(pcApplicationName : pChar): HWnd;
var
    hWindow: HWnd;      // Handle to Window
//   dmScreenSettings : DEVMODE;   // Used for Full Screen Mode
begin
    hWindow := CreateWindow('GLWindow',
              pcApplicationName,
              WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN or WS_CLIPSIBLINGS,
              cw_UseDefault,
              cw_UseDefault,
              width,
              height,
              0, 0,
              system.MainInstance,
              nil);

    if hWindow <> 0 then
    begin
        ShowWindow(hWindow, CmdShow);
        UpdateWindow(hWindow);
    end;
    WindowCreate := hWindow;
end;


// Init the Window and bind OGL to it. //
function WindowInit(hParent : HWnd): Boolean;
var
    FunctionError : integer;
    pfd : PIXELFORMATDESCRIPTOR;
    iFormat : integer;   // Pixel Format

begin
    FunctionError := 0;

    dcWindow := GetDC( hParent );   // Get Device Context

    FillChar(pfd, sizeof(pfd), 0);   // Define Pixel Format
    pfd.nSize         := sizeof(pfd);
    pfd.nVersion      := 1;
    pfd.dwFlags       := PFD_SUPPORT_OPENGL OR PFD_DRAW_TO_WINDOW OR PFD_DOUBLEBUFFER;
    pfd.iPixelType    := PFD_TYPE_RGBA;
    pfd.cColorBits    := bits;
    pfd.cDepthBits    := 32;
    pfd.iLayerType    := PFD_MAIN_PLANE;

    iFormat := ChoosePixelFormat( dcWindow, @pfd );   // Create Pixel Format

    if (iFormat = 0) then
        FunctionError := 1;

    SetPixelFormat( dcWindow, iFormat, @pfd );      // Set Pixel Format
    rcWindow := wglCreateContext( dcWindow );      // Create OpenGL Context

    if (rcWindow = 0) then
        FunctionError := 2;

    wglMakeCurrent( dcWindow, rcWindow );      // Bind OpenGL to our Window

    if FunctionError = 0 then
        WindowInit := true
    else
        WindowInit := false;
end;


// Main function to create the Window. //
function CreateOGLWindow(pcApplicationName : pChar; iApplicationWidth, iApplicationHeight, iApplicationBits : longint; bApplicationFullscreen : boolean):Boolean;
begin
    width := iApplicationWidth;
    height := iApplicationHeight;
    bits := iApplicationBits;
    fullscreen := bApplicationFullscreen;

    if not WindowRegister then begin
        ThrowError('Could not register the Application Window!');
        CreateOGLWindow := false;
        Exit;
    end;

    hWindow := WindowCreate(pcApplicationName);
    if longint(hWindow) = 0 then begin
        ThrowError('Could not create Application Window!');
        CreateOGLWindow := false;
        Exit;
    end;

    if not WindowInit(hWindow) then begin
        ThrowError('Could not initialise Application Window!');
        CreateOGLWindow := false;
        Exit;
    end;

    CreateOGLWindow := true;
end;


// Kill Application Window again. //
procedure KillOGLWindow();
begin
    wglMakeCurrent( dcWindow, 0 );   // Kill Device Context
    wglDeleteContext( rcWindow );   // Kill Render Context
    ReleaseDC( hWindow, dcWindow );   // Release Window
    DestroyWindow( hWindow );      // Kill Window itself
end;


// Main Loop. //
begin
    CreateOGLWindow('tura', 1024, 768, 32, false);
    OpenGL_Init();         // init opengl stuff

    repeat            // start main proc
        if PeekMessage(@msg,0,0,0,0) = true then
        begin
            GetMessage(@msg,0,0,0);
            TranslateMessage(msg);
            DispatchMessage(msg);
        end;
        //OpenGL_Render();
    until active = false;      // end main proc
   
    KillOGLWindow();      // kill window stuff
end.


P.S. Код самодостаточен, можно его скопироваьт в фалик и сделать fpc файлик.pas :)

И ещё один момент, почему в событии:

Код: Выделить всё
wm_mousewheel:
      begin
         if wparam > 0 then
            //if zoom < 2 then  // Если я хочу ограничить максимальное увеличение, то увеличения вообще не происходит? Если закометить эту строчку то всё работает О_о
               zoom := zoom + 0.05
         else
            if zoom > 0.3 then
               zoom := zoom - 0.05;
         
         opengl_render();
   //      exit;
      end;
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение v-t-l » 22.12.2015 13:15:01

xterro писал(а):Для этого планировал использовать обычный writeln, но если добавить его в функцию wndproc, т.е там где собственно и идёт вызов функции, где обрабатываются нажатия клавиш, мышки etc. то при запуске приложение просто зависает, что не так делаю?

Код: Выделить всё
{$APPTYPE GUI}
v-t-l
энтузиаст
 
Сообщения: 733
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение Дож » 22.12.2015 13:18:07

Чтобы при запуске программы была консоль, должно быть {$APPTYPE CONSOLE}, либо нужно создавать консоль средствами WinApi. Просто так Output никуда не привязан в GUI приложении.

Можно перенаправить Writeln в файл, если прибиндить Output (через Assign и Rewrite).
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение sts » 22.12.2015 13:21:44

они хотят сказать что writeln для "консольных" приложений, а в приложениях с графическим интерфейсом это не прокатит, в опенгл окне самому надо текст рисовать, ее функциями, смутно припоминаю что можно и через TCanvas но там какието ограничения и не всегда работает.
sts
постоялец
 
Сообщения: 431
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение zub » 22.12.2015 14:13:50

1) про
Код: Выделить всё
ShowWindow(hWindow, {CmdShow}SW_SHOW);

я уже говорил
2)
смени
{$APPTYPE GUI}
на
{$APPTYPE CONSOLE}
при этом будет создана консоль и вывод будет в нее, инче придется самому создавать консоль и перенаправлять в нее.
а еще лучше для таких вещей использовать лог, можно штатный lclный с его DebugLn, хотя у тебя приложение не лцлное)) - значит какуюто свою аналочиную сущьность
3)
>> то увеличения вообще не происходит?
потому что этой строчкой ты нарушаешь связь if-else, и твой else начинает относится не к тому if`у
Сделай так
Код: Выделить всё
      wm_mousewheel:
      begin
         if wparam > 0 then
           begin
             if zoom < 2 then
             zoom := zoom + 0.05
           end
         else
           if zoom > 0.3 then
             zoom := zoom - 0.05;
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение xterro » 22.12.2015 14:27:08

Спасибо, теперь всё работает )

потому что этой строчкой ты нарушаешь связь if-else, и твой else начинает относится не к тому if`у

Хм, а вот этого я не знал, даже не подумал бы о таком :?
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение zub » 22.12.2015 14:30:23

Код: Выделить всё
         if wparam > 0 then
            //if zoom < 2 then  // Если я хочу ограничить максимальное увеличение, то увеличения вообще не происходит? Если закометить эту строчку то всё работает О_о
               zoom := zoom + 0.05
         else
            if zoom > 0.3 then
               zoom := zoom - 0.05;

это не питон, то что else стоит под первым ифом не значит что он к нему относится)) else всегда относится к последнему ифу. Хочешь иначе - заворачивай в begin\end.
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение xterro » 22.12.2015 14:34:04

Просто сам if это своего рода блок, т.е если после ифа несколько строк кода, то нужно его поместить в begin-end, а если там идёт другой if, т.е думал что нет смысла оборачивать его внешним begin-end. Вот они различия с тем же Си, в мелочах ))
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение zub » 22.12.2015 14:35:52

>>Вот они различия с тем же Си, в мелочах ))
сомневаюсь что в си не так, попробуй привести тотже код на си в двух вариантах, чтоб последний else относился к первму ифу в первом варианте и к последнему ифу во втором варианте
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение Дож » 22.12.2015 14:47:43

xterro писал(а):Просто сам if это своего рода блок, т.е если после ифа несколько строк кода, то нужно его поместить в begin-end, а если там идёт другой if, т.е думал что нет смысла оборачивать его внешним begin-end. Вот они различия с тем же Си, в мелочах ))

В Си то же самое
Код: Выделить всё
if (a) if (b) X; else Y;

также будет воспринято, как в паскале
Код: Выделить всё
if a then if b then X else Y;

(это общепринятая практика разрешения т.н. конфликта сдвига/свёртки).
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение xterro » 22.12.2015 14:53:46

Всё, въехал, действительно неоднозначно получалось )
У меня теперь другая забота, почему v2w не работет, нули на выходе :D
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение Дож » 22.12.2015 15:01:54

xterro писал(а):Всё, въехал, действительно неоднозначно получалось )

У меня для этого есть простое правило: если у if есть else, то основной блок я всегда пишу с begin/end.
Код: Выделить всё
// ПЛОХО
if A then
  X
else
  Y;

// ХОРОШО
if A then begin
  X;
end else
  Y;


Число строк не увеличивается, а неоднозначности отпадают.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение zub » 22.12.2015 15:05:25

Тут вариантов не много
либо на вход приходит не то либо матрицы от glя получены не те.

нет желания зкад попробовать? зачем писать 2 варианта одного и того же?
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение xterro » 22.12.2015 15:35:14

Ну, это я больше для своих образовательных целей, хочу понять, как это всё делается и работает(покоя мне всё эта тема не даёт), даётся правда это как-то с трудом :( но думаю, со временем разберусь. CAD-ы я особо не использую, максимум kiCAD какой-нибудь для поделок, вечер скоротать, а так мне их больше применять негде. Была задумка сделать некий аналог kicad-а, но так как я элементарно ещё с матрицами и преобразованиями над ними плаваю(да и в целом смутно представляю, как это всё организовано в плане вывода на экран), то решил оставить эту затею. Может быть, когда-нибудь, когда ум просветлеет в этой части, вернусь к этому вопросу, а сейчас пока тесты да баловство, удовлетворения интереса для. :)
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: (WINAPI OpenGL) Почему не удаётся использовать writeln?

Сообщение zub » 22.12.2015 18:26:06

>>хочу понять, как это всё делается и работает
От просто чтото порисовать на экране до "это всё делается" (т.е. загружается\сохраняется\выделяется\удаляется\редактируется) шажок довольно большой прибется сделать))
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 20

Рейтинг@Mail.ru