diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index d46109ba..8ec8416e 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -1,19 +1,167 @@ #include "OpenGLWidget.h" +//Some namespaces we need +using namespace std; +using namespace PolyVox; +using namespace std; OpenGLWidget::OpenGLWidget(QWidget *parent) :QGLWidget(parent) { + g_bUseOpenGLVertexBufferObjects = true; + + + + g_volData = new Volume(g_uVolumeSideLength); + + //Make our volume contain a sphere in the center. + uint16 minPos = 0; + uint16 midPos = g_volData->getSideLength() / 2; + uint16 maxPos = g_volData->getSideLength() - 1; + createCubeInVolume(*g_volData, Vector3DUint16(minPos, minPos, minPos), Vector3DUint16(maxPos, maxPos, maxPos), 0); + + createSphereInVolume(*g_volData, 50.0f, 5); + createSphereInVolume(*g_volData, 40.0f, 4); + createSphereInVolume(*g_volData, 30.0f, 3); + createSphereInVolume(*g_volData, 20.0f, 2); + createSphereInVolume(*g_volData, 10.0f, 1); + + createCubeInVolume(*g_volData, Vector3DUint16(minPos, minPos, minPos), Vector3DUint16(midPos-1, midPos-1, midPos-1), 0); + createCubeInVolume(*g_volData, Vector3DUint16(midPos+1, midPos+1, minPos), Vector3DUint16(maxPos, maxPos, midPos-1), 0); + createCubeInVolume(*g_volData, Vector3DUint16(midPos+1, minPos, midPos+1), Vector3DUint16(maxPos, midPos-1, maxPos), 0); + createCubeInVolume(*g_volData, Vector3DUint16(minPos, midPos+1, midPos+1), Vector3DUint16(midPos-1, maxPos, maxPos), 0); + + } void OpenGLWidget::initializeGL() { + if(g_bUseOpenGLVertexBufferObjects) + { +#ifdef WIN32 + //If we are on Windows we will need GLEW to access recent OpenGL functionality + GLenum err = glewInit(); + if (GLEW_OK != err) + { + /* Problem: glewInit failed, something is seriously wrong. */ + cout << "Error: " << glewGetErrorString(err) << endl; + } +#endif + } + + glShadeModel(GL_SMOOTH); // Enable Smooth Shading + glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background + glClearDepth(1.0f); // Depth Buffer Setup + glEnable(GL_DEPTH_TEST); // Enables Depth Testing + glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do + glEnable ( GL_COLOR_MATERIAL ); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glEnable(GL_LIGHTING); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_LIGHT0); + + glShadeModel(GL_SMOOTH); + + //Our volume is broken down into cuboid regions, and we create one mesh for each region. + //This three-level for loop iterates over each region. + for(uint16 uRegionZ = 0; uRegionZ < g_uVolumeSideLengthInRegions; ++uRegionZ) + { + for(uint16 uRegionY = 0; uRegionY < g_uVolumeSideLengthInRegions; ++uRegionY) + { + for(uint16 uRegionX = 0; uRegionX < g_uVolumeSideLengthInRegions; ++uRegionX) + { + //Create a new surface patch (which is basiaclly the PolyVox term for a mesh). + IndexedSurfacePatch* ispCurrent = new IndexedSurfacePatch(); + + //Compute the extents of the current region + //FIXME - This is a little complex? PolyVox could + //provide more functions for dealing with regions? + uint16 regionStartX = uRegionX * g_uRegionSideLength; + uint16 regionStartY = uRegionY * g_uRegionSideLength; + uint16 regionStartZ = uRegionZ * g_uRegionSideLength; + + uint16 regionEndX = regionStartX + g_uRegionSideLength + 1; //Why do we need the '+1' here? + uint16 regionEndY = regionStartY + g_uRegionSideLength + 1; //Why do we need the '+1' here? + uint16 regionEndZ = regionStartZ + g_uRegionSideLength + 1; //Why do we need the '+1' here? + + Vector3DInt32 regLowerCorner(regionStartX, regionStartY, regionStartZ); + Vector3DInt32 regUpperCorner(regionEndX, regionEndY, regionEndZ); + + //Extract the surface for this region + extractReferenceSurface(g_volData, Region(regLowerCorner, regUpperCorner), ispCurrent); + + + if(g_bUseOpenGLVertexBufferObjects) + { + g_openGLSurfacePatches[uRegionX][uRegionY][uRegionZ] = BuildOpenGLSurfacePatch(*ispCurrent); + } + else + { + g_indexedSurfacePatches[uRegionX][uRegionY][uRegionZ] = ispCurrent; + } + //delete ispCurrent; + } + } + } } void OpenGLWidget::resizeGL(int w, int h) { + glViewport ( 0, 0, w, h ); + glMatrixMode ( GL_PROJECTION ); // Select The Projection Matrix + glLoadIdentity ( ); // Reset The Projection Matrix + if ( h==0 ) // Calculate The Aspect Ratio Of The Window + gluPerspective ( 80, ( float ) w, 1.0, 5000.0 ); + else + gluPerspective ( 80, ( float ) w / ( float ) h, 1.0, 5000.0 ); + glMatrixMode ( GL_MODELVIEW ); // Select The Model View Matrix + glLoadIdentity ( ); // Reset The Model View Matrix } void OpenGLWidget::paintGL() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer + + glMatrixMode ( GL_MODELVIEW ); // Select The Model View Matrix + glLoadIdentity(); // Reset The Current Modelview Matrix + + //Moves the camera back so we can see the volume + glTranslatef(0.0f, 0.0f, -100.0f); + + //Rotate the volume by the required amount + //glRotatef(g_xRotation, 1.0f, 0.0f, 0.0f); + //glRotatef(g_yRotation, 0.0f, 1.0f, 0.0f); + + //Centre the volume on the origin + glTranslatef(-g_uVolumeSideLength/2,-g_uVolumeSideLength/2,-g_uVolumeSideLength/2); + + for(uint16 uRegionZ = 0; uRegionZ < g_uVolumeSideLengthInRegions; ++uRegionZ) + { + for(uint16 uRegionY = 0; uRegionY < g_uVolumeSideLengthInRegions; ++uRegionY) + { + for(uint16 uRegionX = 0; uRegionX < g_uVolumeSideLengthInRegions; ++uRegionX) + { + if(g_bUseOpenGLVertexBufferObjects) + { + renderRegionVertexBufferObject(g_openGLSurfacePatches[uRegionX][uRegionY][uRegionZ]); + } + else + { + IndexedSurfacePatch* ispCurrent = g_indexedSurfacePatches[uRegionX][uRegionY][uRegionZ]; + renderRegionImmediateMode(*ispCurrent); + + } + } + } + } + + GLenum errCode; + const GLubyte *errString; + + if ((errCode = glGetError()) != GL_NO_ERROR) + { + errString = gluErrorString(errCode); + cout << "OpenGL Error: " << errString << endl; + } // Reset The Current Modelview Matrix } \ No newline at end of file diff --git a/examples/OpenGL/OpenGLWidget.h b/examples/OpenGL/OpenGLWidget.h index 799ade9c..4fb1c280 100644 --- a/examples/OpenGL/OpenGLWidget.h +++ b/examples/OpenGL/OpenGLWidget.h @@ -1,8 +1,27 @@ #ifndef __PolyVox_OpenGLWidget_H__ #define __PolyVox_OpenGLWidget_H__ +#ifdef WIN32 +#include "glew/glew.h" +#else +#include // The GL Header File +#endif + #include +#include "PolyVoxCore/Volume.h" +#include "PolyVoxCore/IndexedSurfacePatch.h" +#include "PolyVoxCore/SurfaceExtractors.h" +#include "PolyVoxCore/Utility.h" + +#include "OpenGLImmediateModeSupport.h" +#include "OpenGLVertexBufferObjectSupport.h" +#include "Shapes.h" + +const PolyVox::uint16 g_uVolumeSideLength = 256; +const PolyVox::uint16 g_uRegionSideLength = 16; +const PolyVox::uint16 g_uVolumeSideLengthInRegions = g_uVolumeSideLength / g_uRegionSideLength; + class OpenGLWidget : public QGLWidget { @@ -14,6 +33,16 @@ class OpenGLWidget : public QGLWidget void resizeGL(int w, int h); void paintGL(); + private: + + bool g_bUseOpenGLVertexBufferObjects; + + //Creates a volume 128x128x128 + PolyVox::Volume* g_volData; + + //Rather than storing one big mesh, the volume is broken into regions and a mesh is stored for each region + OpenGLSurfacePatch g_openGLSurfacePatches[g_uVolumeSideLengthInRegions][g_uVolumeSideLengthInRegions][g_uVolumeSideLengthInRegions]; + PolyVox::IndexedSurfacePatch* g_indexedSurfacePatches[g_uVolumeSideLengthInRegions][g_uVolumeSideLengthInRegions][g_uVolumeSideLengthInRegions]; }; #endif //__PolyVox_OpenGLWidget_H__ \ No newline at end of file