This commit is contained in:
Freddy 2013-09-27 15:13:43 -07:00
commit d63ead8727
5 changed files with 266 additions and 111 deletions

View file

@ -256,6 +256,9 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseByteNormals, 0,
false, Application::getInstance()->getVoxels(), SLOT(setUseByteNormals(bool)));
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseGlobalNormals, 0,
false, Application::getInstance()->getVoxels(), SLOT(setUseGlobalNormals(bool)));
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");

View file

@ -205,6 +205,7 @@ namespace MenuOption {
const QString Quit = "Quit";
const QString UseVoxelShader = "Use Voxel Shader";
const QString UseByteNormals = "Use Byte Normals";
const QString UseGlobalNormals = "Use Global Normals";
const QString Voxels = "Voxels";
const QString VoxelAddMode = "Add Voxel Mode";
const QString VoxelColorMode = "Color Voxel Mode";

View file

@ -33,9 +33,11 @@
#include "VoxelConstants.h"
#include "VoxelSystem.h"
float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1,
0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1,
0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 };
float identityVerticesGlobalNormals[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 };
float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //0-7
0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //8-15
0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; // 16-23
GLfloat identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1,
0,0,+1, 0,0,+1, 0,0,+1, 0,0,+1,
@ -51,6 +53,13 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z-
10,11,15, 10,15,14, // Y+
4,5,6, 4,6,7 }; // Z+
GLubyte identityIndicesTop[] = { 2, 3, 7, 2, 7, 6 };
GLubyte identityIndicesBottom[] = { 0, 1, 5, 0, 5, 4 };
GLubyte identityIndicesLeft[] = { 0, 7, 3, 0, 4, 7 };
GLubyte identityIndicesRight[] = { 1, 2, 6, 1, 6, 5 };
GLubyte identityIndicesFront[] = { 0, 2, 1, 0, 3, 2 };
GLubyte identityIndicesBack[] = { 4, 5, 6, 4, 6, 7 };
VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
: NodeData(NULL),
_treeScale(treeScale),
@ -77,6 +86,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
_useVoxelShader = false;
_useByteNormals = false;
_useGlobalNormals = false;
_writeVoxelShaderData = NULL;
_readVoxelShaderData = NULL;
@ -145,6 +155,7 @@ void VoxelSystem::setUseByteNormals(bool useByteNormals) {
pthread_mutex_lock(&_bufferWriteLock);
bool wasInitialized = _initialized;
if (wasInitialized) {
clearAllNodesBufferIndex();
cleanupVoxelMemory();
}
_useByteNormals = useByteNormals;
@ -158,11 +169,29 @@ void VoxelSystem::setUseByteNormals(bool useByteNormals) {
}
}
void VoxelSystem::setUseGlobalNormals(bool useGlobalNormals) {
pthread_mutex_lock(&_bufferWriteLock);
bool wasInitialized = _initialized;
if (wasInitialized) {
clearAllNodesBufferIndex();
cleanupVoxelMemory();
}
_useGlobalNormals = useGlobalNormals;
if (wasInitialized) {
init();
}
pthread_mutex_unlock(&_bufferWriteLock);
if (wasInitialized) {
forceRedrawEntireTree();
}
}
void VoxelSystem::setMaxVoxels(int maxVoxels) {
pthread_mutex_lock(&_bufferWriteLock);
bool wasInitialized = _initialized;
if (wasInitialized) {
clearAllNodesBufferIndex();
cleanupVoxelMemory();
}
_maxVoxels = maxVoxels;
@ -206,9 +235,19 @@ void VoxelSystem::cleanupVoxelMemory() {
} else {
// Destroy glBuffers
glDeleteBuffers(1, &_vboVerticesID);
glDeleteBuffers(1, &_vboNormalsID);
glDeleteBuffers(1, &_vboColorsID);
glDeleteBuffers(1, &_vboIndicesID);
if (!_useGlobalNormals) {
glDeleteBuffers(1, &_vboNormalsID);
glDeleteBuffers(1, &_vboIndicesID);
} else {
glDeleteBuffers(1, &_vboIndicesTop);
glDeleteBuffers(1, &_vboIndicesBottom);
glDeleteBuffers(1, &_vboIndicesLeft);
glDeleteBuffers(1, &_vboIndicesRight);
glDeleteBuffers(1, &_vboIndicesFront);
glDeleteBuffers(1, &_vboIndicesBack);
}
delete[] _readVerticesArray;
delete[] _writeVerticesArray;
@ -221,6 +260,34 @@ void VoxelSystem::cleanupVoxelMemory() {
_initialized = false; // no longer initialized
}
void VoxelSystem::setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]) {
GLuint* indicesArray = new GLuint[INDICES_PER_FACE * _maxVoxels];
// populate the indicesArray
// this will not change given new voxels, so we can set it all up now
for (int n = 0; n < _maxVoxels; n++) {
// fill the indices array
int voxelIndexOffset = n * INDICES_PER_FACE;
GLuint* currentIndicesPos = indicesArray + voxelIndexOffset;
int startIndex = (n * GLOBAL_NORMALS_VERTICES_PER_VOXEL);
for (int i = 0; i < INDICES_PER_FACE; i++) {
// add indices for this side of the cube
currentIndicesPos[i] = startIndex + faceIdentityIndices[i];
}
}
glGenBuffers(1, &faceVBOID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faceVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
INDICES_PER_FACE * sizeof(GLuint) * _maxVoxels,
indicesArray, GL_STATIC_DRAW);
_memoryUsageVBO += INDICES_PER_FACE * sizeof(GLuint) * _maxVoxels;
// delete the indices and normals arrays that are no longer needed
delete[] indicesArray;
}
void VoxelSystem::initVoxelMemory() {
_initialMemoryUsageGPU = getFreeMemoryGPU();
_memoryUsageRAM = 0;
@ -265,91 +332,104 @@ void VoxelSystem::initVoxelMemory() {
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
_memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);
} else {
GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels];
// populate the indicesArray
// this will not change given new voxels, so we can set it all up now
for (int n = 0; n < _maxVoxels; n++) {
// fill the indices array
int voxelIndexOffset = n * INDICES_PER_VOXEL;
GLuint* currentIndicesPos = indicesArray + voxelIndexOffset;
int startIndex = (n * VERTICES_PER_VOXEL);
for (int i = 0; i < INDICES_PER_VOXEL; i++) {
// add indices for this side of the cube
currentIndicesPos[i] = startIndex + identityIndices[i];
}
}
if (_useByteNormals) {
qDebug("Using Byte Normals...\n");
GLbyte* normalsArray = new GLbyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
GLbyte* normalsArrayEndPointer = normalsArray;
// populate the normalsArray
for (int n = 0; n < _maxVoxels; n++) {
for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) {
*(normalsArrayEndPointer++) = (identityNormals[i] * CHAR_MAX);
}
}
// VBO for the normalsArray
glGenBuffers(1, &_vboNormalsID);
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
glBufferData(GL_ARRAY_BUFFER,
VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels,
normalsArray, GL_STATIC_DRAW);
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels;
// delete the indices and normals arrays that are no longer needed
delete[] normalsArray;
if (_useGlobalNormals) {
// Global Normals mode uses a technique of not including normals on any voxel vertices, and instead
// rendering the voxel faces in 6 passes that use a global call to glNormal3f()
qDebug("Using Global Normals...\n");
setupFaceIndices(_vboIndicesTop, identityIndicesTop);
setupFaceIndices(_vboIndicesBottom, identityIndicesBottom);
setupFaceIndices(_vboIndicesLeft, identityIndicesLeft);
setupFaceIndices(_vboIndicesRight, identityIndicesRight);
setupFaceIndices(_vboIndicesFront, identityIndicesFront);
setupFaceIndices(_vboIndicesBack, identityIndicesBack);
} else {
qDebug("Using Float Normals...\n");
GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
GLfloat* normalsArrayEndPointer = normalsArray;
if (_useByteNormals) {
qDebug("Using Byte Normals...\n");
GLbyte* normalsArray = new GLbyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
GLbyte* normalsArrayEndPointer = normalsArray;
// populate the normalsArray
// populate the normalsArray
for (int n = 0; n < _maxVoxels; n++) {
for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) {
*(normalsArrayEndPointer++) = (identityNormals[i] * CHAR_MAX);
}
}
// VBO for the normalsArray
glGenBuffers(1, &_vboNormalsID);
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
glBufferData(GL_ARRAY_BUFFER,
VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels,
normalsArray, GL_STATIC_DRAW);
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels;
// delete the indices and normals arrays that are no longer needed
delete[] normalsArray;
} else {
qDebug("Using Float Normals...\n");
GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
GLfloat* normalsArrayEndPointer = normalsArray;
// populate the normalsArray
for (int n = 0; n < _maxVoxels; n++) {
for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) {
*(normalsArrayEndPointer++) = identityNormals[i];
}
}
// VBO for the normalsArray
glGenBuffers(1, &_vboNormalsID);
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
glBufferData(GL_ARRAY_BUFFER,
VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels,
normalsArray, GL_STATIC_DRAW);
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels;
// delete the indices and normals arrays that are no longer needed
delete[] normalsArray;
}
GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels];
// populate the indicesArray
// this will not change given new voxels, so we can set it all up now
for (int n = 0; n < _maxVoxels; n++) {
for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) {
*(normalsArrayEndPointer++) = identityNormals[i];
// fill the indices array
int voxelIndexOffset = n * INDICES_PER_VOXEL;
GLuint* currentIndicesPos = indicesArray + voxelIndexOffset;
int startIndex = (n * VERTICES_PER_VOXEL);
for (int i = 0; i < INDICES_PER_VOXEL; i++) {
// add indices for this side of the cube
currentIndicesPos[i] = startIndex + identityIndices[i];
}
}
// VBO for the normalsArray
glGenBuffers(1, &_vboNormalsID);
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
glBufferData(GL_ARRAY_BUFFER,
VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels,
normalsArray, GL_STATIC_DRAW);
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels;
// VBO for the indicesArray
glGenBuffers(1, &_vboIndicesID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels,
indicesArray, GL_STATIC_DRAW);
_memoryUsageVBO += INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels;
// delete the indices and normals arrays that are no longer needed
delete[] normalsArray;
delete[] indicesArray;
}
// Depending on if we're using per vertex normals, we will need more or less vertex points per voxel
int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL;
glGenBuffers(1, &_vboVerticesID);
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels;
glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
_memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels;
// VBO for colorsArray
glGenBuffers(1, &_vboColorsID);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels;
// VBO for the indicesArray
glGenBuffers(1, &_vboIndicesID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels,
indicesArray, GL_STATIC_DRAW);
_memoryUsageVBO += INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels;
// delete the indices and normals arrays that are no longer needed
delete[] indicesArray;
glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
_memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels;
// we will track individual dirty sections with these arrays of bools
_writeVoxelDirtyArray = new bool[_maxVoxels];
@ -361,15 +441,15 @@ void VoxelSystem::initVoxelMemory() {
_memoryUsageRAM += (sizeof(bool) * _maxVoxels);
// prep the data structures for incoming voxel data
_writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
_memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels);
_readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
_memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels);
_writeVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels];
_memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels);
_readVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels];
_memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels);
_writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
_memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels);
_readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
_memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels);
_writeColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels];
_memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels);
_readColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels];
_memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels);
// create our simple fragment shader if we're the first system to init
@ -649,16 +729,19 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart,
void* writeDataAt = &_writeVoxelShaderData[segmentStart];
memcpy(readDataAt, writeDataAt, segmentSizeBytes);
} else {
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
// Depending on if we're using per vertex normals, we will need more or less vertex points per voxel
int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL;
GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat);
GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat);
GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel);
GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel);
memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes);
segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte);
segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte);
GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel);
GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel);
memcpy(readColorsAt, writeColorsAt, segmentSizeBytes);
}
}
@ -797,10 +880,17 @@ void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& s
}
} else {
if (_writeVerticesArray && _writeColorsArray) {
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
*(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale);
int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL;
for (int j = 0; j < vertexPointsPerVoxel; j++ ) {
GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel);
GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * vertexPointsPerVoxel);
if (_useGlobalNormals) {
*(writeVerticesAt+j) = startVertex[j % 3] + (identityVerticesGlobalNormals[j] * voxelScale);
} else {
*(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale);
}
*(writeColorsAt +j) = color[j % 3];
}
}
@ -912,15 +1002,16 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg
glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
} else {
int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL;
int segmentLength = (segmentEnd - segmentStart) + 1;
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat);
GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat);
GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * vertexPointsPerVoxel);
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte);
segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte);
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * vertexPointsPerVoxel);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
}
@ -966,27 +1057,66 @@ void VoxelSystem::render(bool texture) {
} else {
// tell OpenGL where to find vertex and color information
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
glNormalPointer((_useByteNormals ? GL_BYTE : GL_FLOAT), 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
if (!_useGlobalNormals) {
glEnableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
glNormalPointer((_useByteNormals ? GL_BYTE : GL_FLOAT), 0, 0);
} else {
glNormal3f(0,1.0f,0); // hack for now
}
applyScaleAndBindProgram(texture);
// for performance, enable backface culling
glEnable(GL_CULL_FACE);
// draw the number of voxels we have
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1,
36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
if (!_useGlobalNormals) {
// draw the number of voxels we have
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1,
36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
} else {
// draw voxels in 6 passes
glNormal3f(0,1.0f,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesTop);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1,
INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
glNormal3f(0,-1.0f,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesBottom);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1,
INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
glNormal3f(-1.0f,0,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesLeft);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1,
INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
glNormal3f(1.0f,0,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesRight);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1,
INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
glNormal3f(0,0,-1.0f);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesFront);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1,
INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
glNormal3f(0,0,1.0f);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesBack);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1,
INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
}
glDisable(GL_CULL_FACE);
@ -994,9 +1124,12 @@ void VoxelSystem::render(bool texture) {
// deactivate vertex and color arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
if (!_useGlobalNormals) {
glDisableClientState(GL_NORMAL_ARRAY);
}
// bind with 0 to switch back to normal operation
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

View file

@ -135,6 +135,7 @@ public slots:
void cancelImport();
void setUseByteNormals(bool useByteNormals);
void setUseGlobalNormals(bool useGlobalNormals);
protected:
float _treeScale;
@ -218,6 +219,7 @@ private:
void cleanupVoxelMemory();
bool _useByteNormals;
bool _useGlobalNormals;
bool _useVoxelShader;
GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO
@ -229,6 +231,14 @@ private:
GLuint _vboNormalsID;
GLuint _vboColorsID;
GLuint _vboIndicesID;
GLuint _vboIndicesTop;
GLuint _vboIndicesBottom;
GLuint _vboIndicesLeft;
GLuint _vboIndicesRight;
GLuint _vboIndicesFront;
GLuint _vboIndicesBack;
pthread_mutex_t _bufferWriteLock;
pthread_mutex_t _treeLock;
@ -236,6 +246,8 @@ private:
ViewFrustum _lastStableViewFrustum;
ViewFrustum* _viewFrustum;
void setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]);
int newTreeToArrays(VoxelNode *currentNode);
void cleanupRemovedVoxels();

View file

@ -38,6 +38,12 @@ const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; // xyz for each VERT
const int INDICES_PER_VOXEL = 3 * 12; // 6 sides * 2 triangles per size * 3 vertices per triangle
const int COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * VERTICES_PER_VOXEL;
const int VERTICES_PER_FACE = 4; // 6 sides * 4 corners per side
const int INDICES_PER_FACE = 3 * 2; // 1 side * 2 triangles per size * 3 vertices per triangle
const int GLOBAL_NORMALS_VERTICES_PER_VOXEL = 8; // no need for 3 copies because they don't include normal
const int GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL = 3 * GLOBAL_NORMALS_VERTICES_PER_VOXEL;
const int GLOBAL_NORMALS_COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * GLOBAL_NORMALS_VERTICES_PER_VOXEL;
typedef unsigned long int glBufferIndex;
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;