polyvox/examples/OpenGL/OpenGLWidget.cpp

163 lines
5.4 KiB
C++

#include "OpenGLWidget.h"
//Some namespaces we need
using namespace std;
using namespace PolyVox;
using namespace std;
OpenGLWidget::OpenGLWidget(QWidget *parent)
:QGLWidget(parent)
{
}
void OpenGLWidget::setVolume(PolyVox::Volume<PolyVox::uint8_t>* volData)
{
//First we free anything from the previous volume (if there was one).
m_mapOpenGLSurfacePatches.clear();
m_mapIndexedSurfacePatches.clear();
m_volData = volData;
//If we have any volume data then generate the new surface patches.
if(m_volData != 0)
{
//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_t uRegionZ = 0; uRegionZ < g_uVolumeSideLengthInRegions; ++uRegionZ)
{
for(uint16_t uRegionY = 0; uRegionY < g_uVolumeSideLengthInRegions; ++uRegionY)
{
for(uint16_t 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_t regionStartX = uRegionX * g_uRegionSideLength;
uint16_t regionStartY = uRegionY * g_uRegionSideLength;
uint16_t regionStartZ = uRegionZ * g_uRegionSideLength;
uint16_t regionEndX = regionStartX + g_uRegionSideLength + 1; //Why do we need the '+1' here?
uint16_t regionEndY = regionStartY + g_uRegionSideLength + 1; //Why do we need the '+1' here?
uint16_t 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(m_volData, PolyVox::Region(regLowerCorner, regUpperCorner), ispCurrent);
Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ);
if(m_bUseOpenGLVertexBufferObjects)
{
OpenGLSurfacePatch openGLSurfacePatch = BuildOpenGLSurfacePatch(*ispCurrent);
m_mapOpenGLSurfacePatches.insert(make_pair(v3dRegPos, openGLSurfacePatch));
}
else
{
m_mapIndexedSurfacePatches.insert(make_pair(v3dRegPos, ispCurrent));
}
//delete ispCurrent;
}
}
}
}
}
void OpenGLWidget::initializeGL()
{
m_bUseOpenGLVertexBufferObjects = true;
if(m_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);
}
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_t uRegionZ = 0; uRegionZ < g_uVolumeSideLengthInRegions; ++uRegionZ)
{
for(uint16_t uRegionY = 0; uRegionY < g_uVolumeSideLengthInRegions; ++uRegionY)
{
for(uint16_t uRegionX = 0; uRegionX < g_uVolumeSideLengthInRegions; ++uRegionX)
{
Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ);
if(m_bUseOpenGLVertexBufferObjects)
{
renderRegionVertexBufferObject(m_mapOpenGLSurfacePatches[v3dRegPos]);
}
else
{
IndexedSurfacePatch* ispCurrent = m_mapIndexedSurfacePatches[v3dRegPos];
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
}