//============================================================================
//       Пример использования библиотеки OPENGL32.DLL в среде C--
//============================================================================
//            by Zolotov Alexandr       observer_page@mail.ru
//                   2002            http://observer-page.chat.ru
//============================================================================
#pragma option w32
#jumptomain NONE
#inline TRUE	//insert inline functions
?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; //Pixel format for our window
int pixel_format;                 //Pixel format
dword gl_rc;                        //OpenGL Rendering Context

dword dc;
#define size float 2;
#define NUMPOLIG 34
float fog_color[4]={0.3,0.5,1,0};
float angle=0,zooms=-30.0;
int napravl=0,zoom=0;
int os=0;

struct VR{
	float x,y,z;
}vr[4]={1.0,0.2,0.7,
	0.2,1.0,0.7,
	0.7,0.2,0.7,
	1.0,0.7,0.2};

struct CMM{
	float x0,y0,z0;
	float x1,y1,z1;
	float x2,y2,z2;
	float x3,y3,z3;
	float x4,y4,z4;
}cmm[NUMPOLIG]={
	size, 0,      0,
	-size,size*2, size,
	-size,-size*2,size,
	-size,-size*2,-size,
	-size,size*2, -size,
	size, 0,      0,
	0,    size*3, size,
	-size,size*2, size,
	-size,size*2, -size,
	0,    size*3, -size,
	size, 0,      0,
	-size,-size*2,size,
	0,    -size*3,size,
	0,    -size*3,-size,
	-size,-size*2,-size,
	0,    -size,  0,
	0,    size*3, -size,
	0,    size*3,  size,
	size, size*3,  size,
	size, size*3, -size,
	0,    size,   0,
	0,    -size*3,-size,
	size, -size*3,-size,
	size, -size*3, size,
	0,    -size*3, size,
	-size,0,        0,
	-size*2,size*3, size,
	-size*2,-size*3,size,
	-size*2,-size*3,-size,
	-size*2, size*3,-size,
	-size,  0,      0,
	-size,  size*4, size,
	-size*2,size*3, size,
	-size*2,size*3, -size,
	-size,  size*4, -size,
	-size,  0,      0,
	-size*2,-size*3,size,
	-size,  -size*4,size,
	-size,  -size*4,-size,
	-size*2,-size*3,-size,
	0,      size,   0,
	-size,  size*4, -size,
	-size,  size*4,  size,
	 size,  size*4,  size,
	 size,  size*4, -size,
	0,      -size,   0,
	-size,  -size*4, -size,
	size,   -size*4, -size,
	size,   -size*4, size,
	-size,  -size*4, size,
	0,      0,       -size,
	-size,  size*2,  -size,
	-size,  -size*2, -size,
	-size*2,-size*3, -size,
	-size*2, size*3, -size,
	0,      0,       size,
	-size,  size*2,  size,
	-size,  -size*2, size,
	-size*2,-size*3, size,
	-size*2, size*3, size,
	0,      0,      -size,
	size,   size*4, -size,
	size,   size*3, -size,
	0,      size*3, -size,
	-size,  size*4, -size,
	0,      0,      size,
	size,   size*4, size,
	size,   size*3, size,
	0,      size*3, size,
	-size,  size*4, size,
	0,      0,      -size,
	size,   -size*4,-size,
	size,   -size*3,-size,
	0,      -size*3,-size,
	-size,  -size*4,-size,
	0,      0,      size,
	size,   -size*4,size,
	size,   -size*3,size,
	0,      -size*3,size,
	-size,  -size*4,size,
	0,      0,      -size,
	-size,  -size*4,-size,
	0,      -size*3,-size,
	-size,  -size*2,-size,
	-size*2,-size*3,-size,
	0,      0,      size,
	-size,  -size*4,size,
	0,      -size*3,size,
	-size,  -size*2,size,
	-size*2,-size*3,size,
	0,      0,      -size,
	-size,  size*4, -size,
	0,      size*3, -size,
	-size,  size*2, -size,
	-size*2,size*3, -size,
	0,      0,      size,
	-size,  size*4, size,
	0,      size*3, size,
	-size,  size*2, size,
	-size*2, size*3,size,
	size,   0,      0,
	size,   size*4, size,
	size,   size*2, size,
	size,   size*2, -size,
	size,   size*4, -size,
	size,   0,      0,
	size,   -size*4,size,
	size,   -size*2,size,
	size,   -size*2,-size,
	size,   -size*4,-size,
	0,      0,      size,
	size*2, size,   size,
	0,      size,   size,
	0,      -size,  size,
	size*2, -size,  size,
	0,      0,      -size,
	size*2, size,   -size,
	0,      size,   -size,
	0,      -size,  -size,
	size*2, -size,  -size,
	0,      size,   0,
	size*2, size,   -size,
	0,      size,   -size,
	0,      size,   size,
	size*2, size,   size,
	0,      -size,  0,
	size*2, -size,  -size,
	0,      -size,  -size,
	0,      -size,  size,
	size*2, -size,  size,
	-size,  0,      0,
	0,      size,   size,
	0,      -size,  size,
	0,      -size,  -size,
	0,      size,   -size,
	size,   0,      0,
	size*2, size,   size,
	size*2, -size,  size,
	size*2, -size,  -size,
	size*2, size,   -size,
	0,      0,      size,
	size*5, size,   size,
	size*3, size,   size,
	size*3, -size,  size,
	size*5, -size,  size,
	0,      0,      -size,
	size*5, size,   -size,
	size*3, size,   -size,
	size*3, -size,  -size,
	size*5, -size,  -size,
	0,      size,   0,
	size*5, size,   -size,
	size*3, size,   -size,
	size*3, size,   size,
	size*5, size,   size,
	0,      -size,  0,
	size*5, -size,  -size,
	size*3, -size,  -size,
	size*3, -size,  size,
	size*5, -size,  size,
	-size,  0,      0,
	size*3, size,   size,
	size*3, -size,  size,
	size*3, -size,  -size,
	size*3, size,   -size,
	size,   0,      0,
	size*5, size,   size,
	size*5, -size,  size,
	size*5, -size,  -size,
	size*5, size,   -size };

void Errors(char *mes)
char text[200];
{
	wsprintf(#text,"error code=%d",GetLastError());
	MessageBoxA(WND,mes,#text,MB_OK);
	ExitProcess(1);
}

main()
{
	CreateWindow();
	INIT();
	do{
		IF(PeekMessageA(#message,NULL,0,0,1)){
			TranslateMessage(#message);
			DispatchMessageA(#message);}
//***** There is main loop: **************************************************
		REDRAW();
		IF(napravl==0){
			angle+=0.8;
			IF(angle>360)napravl++;
		}
		ELSE{
			angle-=0.8;
			IF(angle<0.8){
				napravl--;
				os++;
				IF(os==4)os=0;
			}
		}
		IF(zoom==0){
			zooms+=0.005;
			IF(zooms>-10.0)zoom++;
		}
		ELSE{
			zooms-=0.001;
			IF(zooms<-29.0)zoom--;
		}
//****************************************************************************
	}while(message.message!=WM_QUIT);
	ExitProcess(0);
}

void INIT()
{
	pfd=0;
	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;
	dc=GetDC(WND);
	IF(EAX=pixel_format=ChoosePixelFormat(dc,#pfd)==0)
		Errors("Choose pixel format failed");
	IF(SetPixelFormat(dc,pixel_format,#pfd)==0)Errors("SetPixelFormat Failed");
	IF(EAX=gl_rc=wglCreateContext(dc)==0)Errors("OpenGL wglCreateContext Failed");
	IF(wglMakeCurrent(dc,gl_rc)==0)Errors("OpenGL wglMakeCurrent Failed");
	glNewList(1, GL_COMPILE) ; GLERROR();
	FOR(ESI=#cmm;ESI<sizeof(cmm)+#cmm;ESI+=sizeof(CMM)){
		glBegin(GL_POLYGON);
		glNormal3fv(ESI);
		glVertex3fv(ESI+12);
		glVertex3fv(ESI+24);
		glVertex3fv(ESI+36);
		glVertex3fv(ESI+48);
		glEnd();
	}
	glEndList() ;
	glMatrixMode(GL_PROJECTION); GLERROR();
	glLoadIdentity();
	@PUSH_DOUBLE(float 100);
	@PUSH_DOUBLE(float 1);
	@PUSH_DOUBLE(float 1);
	@PUSH_DOUBLE(float 100);
	gluPerspective();
	IF(wglMakeCurrent(0,0)==0)Errors("OpenGL wglMakeCurrent Failed");
}

void REDRAW()
{
	IF(wglMakeCurrent(dc,gl_rc)==0)Errors("OpenGL wglMakeCurrent Failed");
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(float 0,float 0,float zooms);
	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,vr[os].x,vr[os].y,vr[os].z);
	ESI=os*sizeof(VR)+#vr;
	glRotatef(angle,DSFLOAT[ESI],DSFLOAT[ESI+4],DSFLOAT[ESI+8]);
	glColor3f(float 0.5,float 0.5,float 0);
	glCallList(1);
	glFlush();
	SwapBuffers(dc);
	IF(wglMakeCurrent(0,0)==0)Errors("OpenGL wglMakeCurrent Failed");
}

void resize(word x,y)
{
	IF(wglMakeCurrent(dc,gl_rc)==0)Errors("OpenGL wglMakeCurrent Failed");
	glViewport(0,0,x,y);
	IF(wglMakeCurrent(0,0)==0)Errors("OpenGL wglMakeCurrent Failed");
}

void GLERROR()
char text[200];
{
	IF(glGetError()!=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);
	}
}

void CreateWindow(void)  //Create a window and return hWnd
dword hInst;
struct WNDCLASSEX WndClassEx;
{
	WndClassEx.hInstance=hInst=GetModuleHandleA(0);
	WndClassEx.cbSize=sizeof(WndClassEx);
	WndClassEx.style=CS_HREDRAW|CS_VREDRAW;
	WndClassEx.lpfnWndProc=#WndProc;
	WndClassEx.hIconSm=WndClassEx.lpszMenuName=WndClassEx.hCursor=
		WndClassEx.hIcon=WndClassEx.cbClsExtra=WndClassEx.cbWndExtra=0;
	WndClassEx.hbrBackground=COLOR_WINDOW;
	WndClassEx.lpszClassName=#classTitle;
	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
}
