//============================================================================
//       Пример использования библиотеки OPENGL32.DLL в среде C--
//============================================================================
//            by Zolotov Alexandr       observer_page@mail.ru
//                   2002            http://observer-page.chat.ru
//============================================================================
#pragma option w32
?define _WINBASE_ TRUE
?include "windows.h--"
?include "wingdi.h--"
?include "opengl.h--"
?include "double.h--"


char classTitle="OpenGL";
struct MSG message;
dword WND;

struct PIXELFORMATDESCRIPTOR pfd=0; //Pixel format for our window
int pixel_format=0;                 //Pixel format
dword gl_rc;                        //OpenGL Rendering Context

byte text[200];
dword dc;
int opengl_lib;
float size=3;
float fog_color[4]={0.3,0.5,1,0};
float angle=0;

main()
{
  WND=CreateWindow();
  INIT();
  do{
    IF(PeekMessageA(#message,NULL,0,0,1)){
      TranslateMessage(#message);
      DispatchMessageA(#message);}
//***** There is main loop: **************************************************
  REDRAW();
  angle+=2;
//****************************************************************************
  }while(message.message!=WM_QUIT);
}

void INIT()
{
  pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
  pfd.nVersion=1;
  pfd.dwFlags=PFD_DOUBLEBUFFER|
              PFD_SUPPORT_OPENGL|
              PFD_DRAW_TO_WINDOW;
  pfd.iPixelType=PFD_TYPE_RGBA;
  pfd.cColorBits=16;
  pfd.cDepthBits=32;
  pfd.iLayerType=PFD_MAIN_PLANE;

  pfd.cRedBits=0;
  pfd.cRedShift=0;
  pfd.cGreenBits=0;
  pfd.cGreenShift=0;
  pfd.cBlueBits=0;
  pfd.cBlueShift=0;
  pfd.cAlphaBits=0;
  pfd.cAlphaShift=0;
  pfd.cAccumBits=0;
  pfd.cAccumRedBits=0;
  pfd.cAccumGreenBits=0;
  pfd.cAccumBlueBits=0;
  pfd.cAccumAlphaBits=0;
  pfd.cStencilBits=0;
  pfd.cAuxBuffers=0;
  pfd.bReserved=0;
  pfd.dwLayerMask=0;
  pfd.dwVisibleMask=0;
  pfd.dwDamageMask=0;

  dc=GetDC(WND);
  pixel_format=ChoosePixelFormat(dc,#pfd);
  if(pixel_format==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"Choose pixel format failed",#text,MB_OK);
  }

  SetPixelFormat(dc,pixel_format,#pfd);
  if(EAX==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"SetPixelFormat Failed",#text,MB_OK);
  }

  gl_rc=wglCreateContext(dc);
  if(EAX==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"OpenGL wglCreateContext Failed",#text,MB_OK);
  }

  wglMakeCurrent(dc,gl_rc);
  if(EAX==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"OpenGL wglMakeCurrent Failed",#text,MB_OK);
  }


  //
  // Build a display list for the box.
  //
  glNewList(1, GL_COMPILE) ; GLERROR();
  //
            glBegin(GL_POLYGON); // right
                glNormal3f(float 0.0,float 0.0,size);
                glVertex3f(size, size, size);
                glVertex3f(float -size,  size, size);
                glVertex3f(float -size, float -size, size);
                glVertex3f(size, float -size, size);
            glEnd();

            glBegin(GL_POLYGON);        //left
                glNormal3f( float 0.0,float  0.0, float -size);
                glVertex3f( size,  size, float -size);
                glVertex3f( size, float -size, float -size);
                glVertex3f(float -size, float -size, float -size);
                glVertex3f(float -size,  size, float -size);
            glEnd();

            glBegin(GL_POLYGON); //Font
                glNormal3f(float -size,float  0.0,float  0.0);
                glVertex3f(float -size,  size,  size);
                glVertex3f(float -size,  size, float -size);
                glVertex3f(float -size, float -size, float -size);
                glVertex3f(float -size, float -size,  size);
            glEnd();

            glBegin(GL_POLYGON);  //Back
                glNormal3f(size,float  0.0,float  0.0);
                glVertex3f(size,  size,  size);
                glVertex3f(size, float -size,  size);
                glVertex3f(size, float -size, float -size);
                glVertex3f(size,  size, float -size);
            glEnd();

            glBegin(GL_POLYGON);  //Top
                glNormal3f(float 0.0, size,float  0.0);
                glVertex3f(float -size, size, float -size);
                glVertex3f(float -size, size,  size);
                glVertex3f( size, size,  size);
                glVertex3f( size, size, float -size);
            glEnd();

            glBegin(GL_POLYGON);        //Bottom
                glNormal3f(float 0.0, float -size,float  0.0);
                glVertex3f(float -size, float -size, float -size);
                glVertex3f( size, float -size, float -size);
                glVertex3f( size, float -size,  size);
                glVertex3f(float -size, float -size,  size);
            glEnd();

        glEndList() ;


  glMatrixMode(GL_PROJECTION); GLERROR();
  glLoadIdentity();
  gluPerspective(lo_d(float 100),hi_d(float 100),
                 lo_d(float 1), hi_d(float 1),
                 lo_d(float 1), hi_d(float 1),
                 lo_d(float 70), hi_d(float 70));

  wglMakeCurrent(0,0);
  if(EAX==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"OpenGL wglMakeCurrent Failed",#text,MB_OK);
  }
}


void REDRAW()
{
  wglMakeCurrent(dc,gl_rc);
  if(EAX==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"OpenGL wglMakeCurrent Failed",#text,MB_OK);
  }

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(float 0,float 0,float -angle/20);

  glEnable(GL_FOG);
  glFogi(GL_FOG_MODE,GL_LINEAR);
  glFogf(GL_FOG_START,float 5);
  glFogf(GL_FOG_END,float 30);
  glFogfv(GL_FOG_COLOR,#fog_color);

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);

  // Clear the color and depth buffers
  glClearColor(float 0.3, float 0.5,float 1,float 1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // Set the material color to follow the current color
  glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE) ;
  glEnable(GL_COLOR_MATERIAL) ;

  glMatrixMode(GL_MODELVIEW);

  glRotatef(angle,float 1,float 0.2,float 0.7);
  glColor3f(float 0.5,float 0.5,float 0);
  glCallList(1);

  glFlush();
  SwapBuffers(dc);

  wglMakeCurrent(0,0);
  if(EAX==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"OpenGL wglMakeCurrent Failed",#text,MB_OK);
  }
}


void resize(word x,y)
{
  wglMakeCurrent(dc,gl_rc);
  if(EAX==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"OpenGL wglMakeCurrent Failed",#text,MB_OK);
  }

  glViewport(0,0,x,y);

  wglMakeCurrent(0,0);
  if(EAX==0){
    wsprintf(#text,"error code=%d",GetLastError());
    MessageBoxA(WND,"OpenGL wglMakeCurrent Failed",#text,MB_OK);
  }
}

void GLERROR()
{
  glGetError();
  if(EAX!=GL_NO_ERROR){
    wsprintf(#text,"error code=%d %s",glGetError(),gluErrorString(glGetError()));
    MessageBoxA(WND,#text,"OpenGL error",MB_OK);
  }
}


dword   WndProc(dword hwnd,msg,wPar,lPar) //Main window proc.
{
        switch(msg){
                case WM_DESTROY:
                        PostQuitMessage(0);
                        EAX=0;
                        break;
                case WM_SIZE:
                        resize(lPar&0xFFFF,lPar>>16);
                        EAX=0;
                        break;
                default:
                        DefWindowProcA(hwnd,msg,wPar,lPar);
        }
}


DWORD CreateWindow(void)  //Create a window and return hWnd
dword hInst;
struct WNDCLASSEX WndClassEx;
{
        hInst=GetModuleHandleA(0);
        WndClassEx.cbSize=sizeof(WndClassEx);
        WndClassEx.style=CS_HREDRAW|CS_VREDRAW;
        WndClassEx.lpfnWndProc=#WndProc;
        WndClassEx.cbWndExtra=0;
        WndClassEx.cbClsExtra=0;
        WndClassEx.hInstance=hInst;
        WndClassEx.hIcon=0;
        WndClassEx.hCursor=0;
        WndClassEx.hbrBackground=COLOR_WINDOW;
        WndClassEx.lpszMenuName=0;
        WndClassEx.lpszClassName=#classTitle;
        WndClassEx.hIconSm=0;
        RegisterClassExA(#WndClassEx); //зарегистрируем класс окна
                                       // и создадим окно
        WND=CreateWindowExA(0,#classTitle,"OpenGL TEST",
                            WS_OVERLAPPEDWINDOW,0,0,
                            400,300,0,0,hInst,0);
        ShowWindow(EAX,SW_SHOWNORMAL); //show window
        UpdateWindow(WND); //redraw window

        return WND;
}
