From 59360094e5ac1ddeb5eda365ac4ccf765786635f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 27 Nov 2009 20:47:58 +0100 Subject: Initial commit --- .gitignore | 5 + BSPGenerator.cpp | 2 + BSPGenerator.h | 9 ++ BSPTree.h | 12 ++ CMakeLists.txt | 21 +++ Color.h | 19 +++ Cuboid.cpp | 133 +++++++++++++++++++ Cuboid.h | 29 ++++ DisplayClass.cpp | 54 ++++++++ DisplayClass.h | 10 ++ Matrix.h | 45 +++++++ Triangle.h | 45 +++++++ Vector.h | 43 ++++++ Vertex.h | 18 +++ gl.h | 12 ++ main.cpp | 399 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 856 insertions(+) create mode 100644 .gitignore create mode 100644 BSPGenerator.cpp create mode 100644 BSPGenerator.h create mode 100644 BSPTree.h create mode 100644 CMakeLists.txt create mode 100644 Color.h create mode 100644 Cuboid.cpp create mode 100644 Cuboid.h create mode 100644 DisplayClass.cpp create mode 100644 DisplayClass.h create mode 100644 Matrix.h create mode 100644 Triangle.h create mode 100644 Vector.h create mode 100644 Vertex.h create mode 100644 gl.h create mode 100644 main.cpp 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 + +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 +//#include +//#include + + +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 Cuboid::getTriangles(const Matrix &modelview) +{ + std::list 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::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 +#include + +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 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 + + +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 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 t1 = cube1.getTriangles(m); + triangles.splice(triangles.end(), t1); + + glRotatef(angle*10, 0.0, 0.0, 1.0); + m.store(); + + std::list t2 = cube2.getTriangles(m); + triangles.splice(triangles.end(), t2); + + //std::sort(triangles.begin(), triangles.end(), Sorter(p)); + + glLoadIdentity(); + + glBegin(GL_TRIANGLES); + for(std::list::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 +#endif + +#include +#include + +#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 +#include +#include +#include +#include +#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("3D"); + chint.res_class = const_cast("3d"); + XSetClassHint(disp, *wnd, &chint); + + char *str = const_cast("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(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 -- cgit v1.2.3