summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--BSPGenerator.cpp2
-rw-r--r--BSPGenerator.h9
-rw-r--r--BSPTree.h12
-rw-r--r--CMakeLists.txt21
-rw-r--r--Color.h19
-rw-r--r--Cuboid.cpp133
-rw-r--r--Cuboid.h29
-rw-r--r--DisplayClass.cpp54
-rw-r--r--DisplayClass.h10
-rw-r--r--Matrix.h45
-rw-r--r--Triangle.h45
-rw-r--r--Vector.h43
-rw-r--r--Vertex.h18
-rw-r--r--gl.h12
-rw-r--r--main.cpp399
16 files changed, 856 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2837841
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/build
+
+/.project
+/.cproject
+/.settings
diff --git a/BSPGenerator.cpp b/BSPGenerator.cpp
new file mode 100644
index 0000000..a4cab6e
--- /dev/null
+++ b/BSPGenerator.cpp
@@ -0,0 +1,2 @@
+#include "BSPGenerator.h"
+
diff --git a/BSPGenerator.h b/BSPGenerator.h
new file mode 100644
index 0000000..f6195e8
--- /dev/null
+++ b/BSPGenerator.h
@@ -0,0 +1,9 @@
+#ifndef _BSPGENERATOR_H_
+#define _BSPGENERATOR_H_
+
+class BSPGenerator {
+ public:
+
+};
+
+#endif /* _BSPGENERATOR_H_ */
diff --git a/BSPTree.h b/BSPTree.h
new file mode 100644
index 0000000..345f143
--- /dev/null
+++ b/BSPTree.h
@@ -0,0 +1,12 @@
+#ifndef _BSPTREE_H_
+#define _BSPTREE_H_
+
+#include "Triangle.h"
+#include <list>
+
+class BSPTree {
+ private:
+
+};
+
+#endif /* _BSPTREE_H_ */
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..50e80ca
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.6)
+project(C3D)
+
+find_package(OpenGL REQUIRED)
+
+include_directories(${OPENGL_INCLUDE_DIR})
+
+add_executable(c3d
+ BSPGenerator.cpp BSPGenerator.h
+ BSPTree.h
+ Color.h
+ Cuboid.cpp Cuboid.h
+ DisplayClass.cpp DisplayClass.h
+ gl.h
+ main.cpp
+ Matrix.h
+ Triangle.h
+ Vector.h
+ Vertex.h
+)
+target_link_libraries(c3d ${OPENGL_LIBRARIES})
diff --git a/Color.h b/Color.h
new file mode 100644
index 0000000..ad242c7
--- /dev/null
+++ b/Color.h
@@ -0,0 +1,19 @@
+#ifndef _COLOR_H_
+#define _COLOR_H_
+
+class Color
+{
+ public:
+ Color(float r0 = 0, float g0 = 0, float b0 = 0, float a0 = 1.0) : r(r0), g(g0), b(b0), a(a0) {}
+
+ float getR() const {return r;}
+ float getG() const {return g;}
+ float getB() const {return b;}
+ float getA() const {return a;}
+
+ private:
+ float r, g, b, a;
+};
+
+#endif /*_COLOR_H_*/
+
diff --git a/Cuboid.cpp b/Cuboid.cpp
new file mode 100644
index 0000000..5557e39
--- /dev/null
+++ b/Cuboid.cpp
@@ -0,0 +1,133 @@
+#include "Cuboid.h"
+#include "gl.h"
+
+#include <iostream>
+//#include <stdlib.h>
+//#include <time.h>
+
+
+Cuboid::Cuboid(float height, float width, float depth, float x, float y, float z)
+{
+ setSize(height, width, depth);
+ setPos(x, y, z);
+}
+
+float Cuboid::getHeight()
+{
+ return height;
+}
+
+float Cuboid::getWidth()
+{
+ return width;
+}
+
+float Cuboid::getDepth()
+{
+ return depth;
+}
+
+float Cuboid::getPosX()
+{
+ return x;
+}
+
+float Cuboid::getPosY()
+{
+ return y;
+}
+
+float Cuboid::getPosZ()
+{
+ return z;
+}
+
+void Cuboid::setSize(float h, float w, float d)
+{
+ height = h;
+ width = w;
+ depth = d;
+}
+
+void Cuboid::setPos(float x, float y, float z)
+{
+ this->x = x;
+ this->y = y;
+ this->z = z;
+}
+
+std::list<Triangle> Cuboid::getTriangles(const Matrix &modelview)
+{
+ std::list<Triangle> triangles;
+ //srand(time(NULL));
+ // width, height, depth
+ // Front face
+ Color c(0.0, 0.0, 1.0);
+
+ triangles.push_back(Triangle(Vertex(x , y , z),
+ Vertex(x+width, y , z),
+ Vertex(x , y-height, z), c));
+
+ triangles.push_back(Triangle(Vertex(x , y-height, z),
+ Vertex(x+width, y , z),
+ Vertex(x+width, y-height, z), c));
+
+ // Back face
+ c = Color(1.0, 1.0, 0.0);
+
+ triangles.push_back(Triangle(Vertex(x , y , z-depth),
+ Vertex(x , y-height, z-depth),
+ Vertex(x+width, y , z-depth), c));
+
+ triangles.push_back(Triangle(Vertex(x , y-height, z-depth),
+ Vertex(x+width, y , z-depth),
+ Vertex(x+width, y-height, z-depth), c));
+
+ // Left face
+ c = Color(0.0, 1.0, 0.0);
+
+ triangles.push_back(Triangle(Vertex(x, y , z ),
+ Vertex(x, y-height, z ),
+ Vertex(x, y , z-depth), c));
+
+ triangles.push_back(Triangle(Vertex(x, y-height, z-depth),
+ Vertex(x, y , z-depth),
+ Vertex(x, y-height, z ), c));
+
+ // Right face
+
+ triangles.push_back(Triangle(Vertex(x+width, y , z ),
+ Vertex(x+width, y-height, z ),
+ Vertex(x+width, y , z-depth), c));
+
+ triangles.push_back(Triangle(Vertex(x+width, y-height, z-depth),
+ Vertex(x+width, y , z-depth),
+ Vertex(x+width, y-height, z ), c));
+
+ // Top face
+ c = Color(1.0, 0.0, 0.0);
+
+ triangles.push_back(Triangle(Vertex(x , y, z ),
+ Vertex(x+width, y, z ),
+ Vertex(x , y, z-depth), c));
+
+ triangles.push_back(Triangle(Vertex(x+width, y, z ),
+ Vertex(x+width, y, z-depth),
+ Vertex(x , y, z-depth), c));
+
+ // Bottom face
+
+ triangles.push_back(Triangle(Vertex(x , y-height, z ),
+ Vertex(x+width, y-height, z ),
+ Vertex(x , y-height, z-depth), c));
+
+ triangles.push_back(Triangle(Vertex(x+width, y-height, z ),
+ Vertex(x+width, y-height, z-depth),
+ Vertex(x , y-height, z-depth), c));
+
+ for(std::list<Triangle>::iterator t = triangles.begin(); t != triangles.end(); ++t) {
+ t->transform(modelview);
+ }
+
+ return triangles;
+}
diff --git a/Cuboid.h b/Cuboid.h
new file mode 100644
index 0000000..661dc0d
--- /dev/null
+++ b/Cuboid.h
@@ -0,0 +1,29 @@
+#ifndef _CUBOID_H_
+#define _CUBOID_H_
+
+#include "Triangle.h"
+#include "Matrix.h"
+
+#include <iostream>
+#include <list>
+
+class Cuboid
+{
+ public:
+ Cuboid(float height, float width, float depth, float x, float y, float z);
+ float getHeight();
+ float getWidth();
+ float getDepth();
+ float getPosX();
+ float getPosY();
+ float getPosZ();
+ void setSize(float h, float w, float d);
+ void setPos(float x, float y, float z);
+ std::list<Triangle> getTriangles(const Matrix &modelview);
+
+ private:
+ float height, width, depth;
+ float x, y, z;
+};
+#endif /*_CUBOID_H_*/
+
diff --git a/DisplayClass.cpp b/DisplayClass.cpp
new file mode 100644
index 0000000..836988d
--- /dev/null
+++ b/DisplayClass.cpp
@@ -0,0 +1,54 @@
+#include "Cuboid.h"
+#include "DisplayClass.h"
+#include "Matrix.h"
+#include "gl.h"
+#include <algorithm>
+
+
+void DisplayClass::renderScene(unsigned long delta)
+{
+
+ Cuboid cube1(2, 2, 1, -1, 1, 0.5);
+ Cuboid cube2(1, 1, 2, -0.5, 0.5, -1.5);
+ static float angle = 0.0;
+ angle += delta*0.05;
+ if(angle >= 360)
+ angle -= 360;
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ Matrix p(GL_PROJECTION_MATRIX);
+ Matrix m;
+
+ std::list<Triangle> triangles;
+
+ glLoadIdentity(); // Clean up matrix
+ glTranslatef(0.0, 0.0, -10.0); // Then set up transformation
+ glRotatef(angle, 0.0, 1.0, 0.0);
+ //glRotatef(angle*2, 1.0, 0.0, 0.0);
+ //glRotatef(angle*3, 0.0, 0.0, 1.0);
+
+ glRotatef(-angle*5, 0.0, 0.0, 1.0);
+ m.store(); // Save current transformation
+
+ std::list<Triangle> t1 = cube1.getTriangles(m);
+ triangles.splice(triangles.end(), t1);
+
+ glRotatef(angle*10, 0.0, 0.0, 1.0);
+ m.store();
+
+ std::list<Triangle> t2 = cube2.getTriangles(m);
+ triangles.splice(triangles.end(), t2);
+
+ //std::sort(triangles.begin(), triangles.end(), Sorter(p));
+
+ glLoadIdentity();
+
+ glBegin(GL_TRIANGLES);
+ for(std::list<Triangle>::reverse_iterator t = triangles.rbegin(); t != triangles.rend(); ++t) {
+ t->render();
+ }
+ glEnd();
+
+ glFlush();
+}
diff --git a/DisplayClass.h b/DisplayClass.h
new file mode 100644
index 0000000..adb2422
--- /dev/null
+++ b/DisplayClass.h
@@ -0,0 +1,10 @@
+#ifndef _DISPLAYCLASS_H_
+#define _DISPLAYCLASS_H_
+
+class DisplayClass
+{
+ public:
+ void renderScene(unsigned long delta);
+};
+#endif /*_DISPLAYCLASS_H_*/
+
diff --git a/Matrix.h b/Matrix.h
new file mode 100644
index 0000000..f8c178f
--- /dev/null
+++ b/Matrix.h
@@ -0,0 +1,45 @@
+#ifndef _MATRIX_H_
+#define _MATRIX_H_
+
+#include "gl.h"
+#include "Vector.h"
+#include "Vertex.h"
+
+class Matrix
+{
+ public:
+ Matrix(GLenum pname = GL_MODELVIEW_MATRIX) {
+ store(pname);
+ }
+
+ Matrix(float in[16]) {
+ for(int i = 0; i < 16; ++i)
+ f[i] = in[i];
+ }
+
+ Vertex operator*(const Vertex &v) const {
+ Vector r(v.getX()*m[0][0] + v.getY()*m[1][0] + v.getZ()*m[2][0] + m[3][0],
+ v.getX()*m[0][1] + v.getY()*m[1][1] + v.getZ()*m[2][1] + m[3][1],
+ v.getX()*m[0][2] + v.getY()*m[1][2] + v.getZ()*m[2][2] + m[3][2]);
+ float w = v.getX()*m[0][3] + v.getY()*m[1][3] + v.getZ()*m[2][3] + m[3][3];
+
+ return r/w;
+ }
+
+ void load() {
+ glLoadMatrixf(f);
+ }
+
+ void store(GLenum pname = GL_MODELVIEW_MATRIX) {
+ glGetFloatv(pname, f);
+ }
+
+ private:
+ union {
+ float f[16];
+ float m[4][4];
+ };
+};
+
+#endif /*_MATRIX_H_*/
+
diff --git a/Triangle.h b/Triangle.h
new file mode 100644
index 0000000..807b5b9
--- /dev/null
+++ b/Triangle.h
@@ -0,0 +1,45 @@
+#ifndef _TRIANGLE_H_
+#define _TRIANGLE_H_
+
+#include "gl.h"
+#include "Color.h"
+#include "Vector.h"
+#include "Vertex.h"
+#include "Matrix.h"
+
+class Triangle
+{
+ public:
+ Triangle(const Vertex &v1, const Vertex &v2, const Vertex &v3, const Color &c0) : c(c0)
+ {
+ v[0] = v1;
+ v[1] = v2;
+ v[2] = v3;
+ }
+
+ const Vertex& getVertex(int i) const {return v[i];}
+ const Color& getColor() const {return c;}
+
+ void render() const {
+ glColor4f(c.getR(), c.getG(), c.getB(), c.getA());
+
+ for(int i = 0; i < 3; ++i)
+ {
+ glVertex3f(v[i].getX(), v[i].getY(), v[i].getZ());
+ }
+ }
+
+ void transform(const Matrix &m) {
+ for(int i = 0; i < 3; ++i)
+ {
+ v[i] = m*v[i];
+ }
+ }
+
+ private:
+ Vertex v[3];
+ Color c;
+};
+
+#endif /*_TRIANGLE_H_*/
+
diff --git a/Vector.h b/Vector.h
new file mode 100644
index 0000000..f884c49
--- /dev/null
+++ b/Vector.h
@@ -0,0 +1,43 @@
+#ifndef _VECTOR_H_
+#define _VECTOR_H_
+
+#include "Vertex.h"
+
+class Vector : public Vertex {
+ public:
+ Vector(float x0 = 0, float y0 = 0, float z0 = 0) : Vertex(x0, y0, z0) {}
+ Vector(const Vertex &v) : Vertex(v) {}
+
+ Vector operator+(const Vector &v) const {
+ return Vector(x+v.x, y+v.y, z+v.z);
+ }
+
+ Vector operator*(float f) const {
+ return Vector(x*f, y*f, z*f);
+ }
+
+ Vector operator/(float f) const {
+ return (*this)*(1/f);
+ }
+
+ Vector operator-() const {
+ return Vector(-x, -y, -z);
+ }
+
+ Vector cross(const Vector &v) const {
+ return Vector(y*v.z - z*v.y,
+ z*v.x - x*v.z,
+ x*v.y - y*v.x);
+ }
+
+ float dot(const Vector &v) const {
+ return x*v.x + y*v.y + z*v.z;
+ }
+};
+
+static inline Vector operator-(const Vertex &v1, const Vertex &v2) {
+ return Vector(v1.getX()-v2.getX(), v1.getY()-v2.getY(), v1.getZ()-v2.getZ());
+}
+
+#endif /*_VECTOR_H_*/
+
diff --git a/Vertex.h b/Vertex.h
new file mode 100644
index 0000000..c82bd59
--- /dev/null
+++ b/Vertex.h
@@ -0,0 +1,18 @@
+#ifndef _VERTEX_H_
+#define _VERTEX_H_
+
+class Vertex
+{
+ public:
+ Vertex(float x0 = 0, float y0 = 0, float z0 = 0) : x(x0), y(y0), z(z0) {}
+
+ float getX() const {return x;}
+ float getY() const {return y;}
+ float getZ() const {return z;}
+
+ protected:
+ float x, y, z;
+};
+
+#endif /*_VERTEX_H_*/
+
diff --git a/gl.h b/gl.h
new file mode 100644
index 0000000..fb5face
--- /dev/null
+++ b/gl.h
@@ -0,0 +1,12 @@
+#ifndef _GL_H_
+#define _GL_H_
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#endif /* _GL_H_ */
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..87f5060
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,399 @@
+#include "DisplayClass.h"
+#include "gl.h"
+
+#ifdef _WIN32
+#else
+#include <iostream>
+#include <X11/X.h>
+#include <GL/glx.h>
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#define MIN_FRAME_DELTA 16
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 640
+
+void initGL(bool multisample);
+void resize(int width, int height);
+
+void initGL(bool multisample) {
+ glClearColor(0.0, 0.0, 0.0, 1.0);
+ glClearDepth(1.0);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+
+ //glEnable(GL_BLEND);
+ //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+#ifndef _WIN32
+ if(multisample)
+ glEnable(GL_MULTISAMPLE_ARB);
+#endif
+
+ resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+}
+
+void resize(int width, int height)
+{
+ if(height==0)
+ {
+ height=1;
+ }
+
+ glViewport(0, 0, width, height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(50.0f,(GLfloat)width/(GLfloat)height, 0.1, 1000);
+
+ glMatrixMode(GL_MODELVIEW);
+}
+
+
+#ifdef _WIN32
+
+bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC);
+void WGLUninit(HWND hWnd, HDC hDC, HGLRC hRC);
+LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) {
+ WNDCLASS wc;
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wc.lpfnWndProc = (WNDPROC)wndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = "3D";
+
+ if (!RegisterClass(&wc))
+ {
+ MessageBox(0, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
+ return false; // Exit And Return FALSE
+ }
+
+ DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
+ DWORD dwStyle = WS_OVERLAPPEDWINDOW;
+
+ RECT windowRect;
+ windowRect.left = 0;
+ windowRect.right = DEFAULT_WIDTH;
+ windowRect.top = 0;
+ windowRect.bottom = DEFAULT_HEIGHT;
+
+ AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
+
+ *hWnd = CreateWindowEx(dwExStyle, "3D" /* Class Name */, "3D" /* Title*/, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle,
+ 0, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, 0, 0, hInstance, 0);
+ if(!*hWnd)
+ {
+ MessageBox(0, "Window Creation Error.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
+ return false;
+ }
+
+ static PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
+ 1, // Version Number
+ PFD_DRAW_TO_WINDOW | // Format Must Support Window
+ PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
+ PFD_DOUBLEBUFFER, // Must Support Double Buffering
+ PFD_TYPE_RGBA, // Request An RGBA Format
+ 16, // Select Our Color Depth
+ 0, 0, 0, 0, 0, 0, // Color Bits Ignored
+ 0, // No Alpha Buffer
+ 0, // Shift Bit Ignored
+ 0, // No Accumulation Buffer
+ 0, 0, 0, 0, // Accumulation Bits Ignored
+ 16, // 16Bit Z-Buffer (Depth Buffer)
+ 0, // No Stencil Buffer
+ 0, // No Auxiliary Buffer
+ PFD_MAIN_PLANE, // Main Drawing Layer
+ 0, // Reserved
+ 0, 0, 0 // Layer Masks Ignored
+ };
+
+ *hDC=GetDC(*hWnd);
+ if (!*hDC)
+ {
+ WGLUninit(*hWnd, 0, 0);
+ MessageBox(0, "Can't Create A GL Device Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
+ return false;
+ }
+
+ GLuint pixelFormat = ChoosePixelFormat(*hDC, &pfd);
+ if(!pixelFormat)
+ {
+ WGLUninit(*hWnd, *hDC, 0);
+ MessageBox(0, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
+ return false;
+ }
+
+ if(!SetPixelFormat(*hDC, pixelFormat, &pfd))
+ {
+ WGLUninit(*hWnd, *hDC, 0);
+ MessageBox(0, "Can't Set The PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
+ return false;
+ }
+
+ *hRC=wglCreateContext(*hDC);
+ if(!*hRC)
+ {
+ WGLUninit(*hWnd, *hDC, 0);
+ MessageBox(0, "Can't Create A GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
+ return false;
+ }
+
+ if(!wglMakeCurrent(*hDC, *hRC))
+ {
+ WGLUninit(*hWnd, *hDC, *hRC);
+ MessageBox(0, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
+ return false;
+ }
+
+ ShowWindow(*hWnd, SW_SHOW);
+ SetForegroundWindow(*hWnd);
+ SetFocus(*hWnd);
+
+ return true;
+}
+
+void WGLUninit(HWND hWnd, HDC hDC, HGLRC hRC) {
+ wglMakeCurrent(0, 0);
+
+ if(hRC)
+ wglDeleteContext(hRC);
+
+ if(hDC)
+ ReleaseDC(hWnd, hDC);
+
+ if(hWnd)
+ DestroyWindow(hWnd);
+}
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ HWND hWnd = 0;
+ HDC hDC = 0;
+ HGLRC hRC = 0;
+
+ if(!WGLInit(hInstance, &hWnd, &hDC, &hRC))
+ {
+ return 0;
+ }
+
+ initGL(false);
+
+ bool running = true;
+ MSG msg;
+
+ while(running)
+ {
+ unsigned long delta = 0;
+ unsigned long ticks = GetTickCount();
+
+ while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if(msg.message == WM_QUIT)
+ {
+ running = false;
+ break;
+ }
+ else // If Not, Deal With Window Messages
+ {
+ TranslateMessage(&msg); // Translate The Message
+ DispatchMessage(&msg); // Dispatch The Message
+ }
+ }
+
+ delta = GetTickCount()-ticks;
+
+ if(delta < MIN_FRAME_DELTA) {
+ Sleep(MIN_FRAME_DELTA - delta);
+ delta = GetTickCount()-ticks;
+ }
+
+ ticks += delta;
+
+ static DisplayClass render;
+ render.renderScene(delta);
+ SwapBuffers(hDC);
+ }
+
+ WGLUninit(hWnd, hDC, hRC);
+ return msg.wParam;
+}
+
+LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ switch(uMsg) {
+ case WM_CLOSE:
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_SIZE:
+ resize(LOWORD(lParam), HIWORD(lParam));
+ return 0;
+
+ default:
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+ }
+}
+
+#else
+
+bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, bool *multisample) {
+ static const int msAttributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_X_RENDERABLE, True,
+ GLX_DOUBLEBUFFER, True,
+ GLX_DEPTH_SIZE, 1,
+ GLX_SAMPLE_BUFFERS, 1,
+ GLX_SAMPLES, 4,
+ None};
+
+ static const int attributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_X_RENDERABLE, True,
+ GLX_DOUBLEBUFFER, True,
+ GLX_DEPTH_SIZE, 1,
+ None};
+
+ bool ok = false;
+ *multisample = true;
+
+ int nElements;
+ GLXFBConfig *fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), msAttributeList, &nElements);
+ if(!fbConfig || !nElements) {
+ if(fbConfig) {
+ XFree(fbConfig);
+ }
+
+ *multisample = false;
+ fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), attributeList, &nElements);
+ }
+
+ if(fbConfig && nElements) {
+ XVisualInfo *vi = glXGetVisualFromFBConfig(disp, *fbConfig);
+
+ if(vi) {
+ Colormap cmap = XCreateColormap(disp, RootWindow(disp, vi->screen), vi->visual, AllocNone);
+ XSetWindowAttributes swa;
+ swa.colormap = cmap;
+ swa.border_pixel = 0;
+ swa.event_mask = /*PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask*/0;
+
+ *wnd = XCreateWindow(disp, RootWindow(disp, vi->screen), 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, 0, vi->depth, InputOutput,
+ vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa);
+
+ XClassHint chint;
+ chint.res_name = const_cast<char*>("3D");
+ chint.res_class = const_cast<char*>("3d");
+ XSetClassHint(disp, *wnd, &chint);
+
+ char *str = const_cast<char*>("3D");
+ XTextProperty name;
+ if(XStringListToTextProperty(&str, 1, &name) != 0)
+ {
+ XSetWMName(disp, *wnd, &name);
+ XFree(name.value);
+ }
+
+ XSetWMProtocols(disp, *wnd, &windele, 1);
+
+ XMapWindow(disp, *wnd);
+
+ *gc = glXCreateContext(disp, vi, NULL, True);
+
+ glXMakeCurrent(disp, *wnd, *gc);
+
+ ok = true;
+
+ XFree(vi);
+ }
+ }
+
+ if(fbConfig)
+ XFree(fbConfig);
+
+ XSync(disp, 0);
+
+ return ok;
+}
+
+int main() {
+ Display *disp = XOpenDisplay(0);
+ Atom windele = XInternAtom(disp, "WM_DELETE_WINDOW", False);
+ Window wnd;
+ GLXContext gc;
+
+ bool multisample;
+ if(!GLXinit(disp, windele, &wnd, &gc, &multisample))
+ return 1;
+ initGL(multisample);
+
+ GLint samples;
+ glGetIntegerv(GL_SAMPLES, &samples);
+ std::cerr << "Using " << samples << " samples" << std::endl;
+
+ bool running = true;
+
+ unsigned long delta = 0;
+ unsigned long frames = 0, tocks = 0;
+
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ unsigned long ticks = tv.tv_usec;
+
+ while(running) {
+ while(XPending(disp)) {
+ XEvent event;
+ XNextEvent(disp, &event);
+ switch(event.type) {
+ case ClientMessage:
+ if(static_cast<Atom>(event.xclient.data.l[0]) == windele)
+ running = false;
+ break;
+ }
+ }
+
+ if(!running) break;
+
+ static DisplayClass render;
+ render.renderScene(delta);
+
+ glXSwapBuffers(disp, wnd);
+ XSync(disp, 0);
+
+ gettimeofday(&tv, NULL);
+ delta = ((tv.tv_usec + 1000000 - ticks)%1000000)/1000;
+
+ if(delta < MIN_FRAME_DELTA) {
+ usleep((MIN_FRAME_DELTA-delta)*1000);
+
+ gettimeofday(&tv, NULL);
+ delta = ((tv.tv_usec + 1000000 - ticks)%1000000)/1000;
+ }
+
+ ticks = (ticks + delta*1000) % 1000000;
+
+ frames++;
+ tocks += delta*1000;
+ if(tocks > 1000000) {
+ std::cerr << frames << std::endl;
+ frames = 0;
+ tocks -= 1000000;
+ }
+ }
+
+ XDestroyWindow(disp, wnd);
+ glXDestroyContext(disp, gc);
+ XCloseDisplay(disp);
+
+ return 0;
+}
+
+#endif