mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 16:36:54 +02:00
add support for global normals for voxels
This commit is contained in:
parent
dbfc0956c1
commit
8cffa8d872
5 changed files with 266 additions and 111 deletions
|
@ -256,6 +256,9 @@ Menu::Menu() :
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseByteNormals, 0,
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseByteNormals, 0,
|
||||||
false, Application::getInstance()->getVoxels(), SLOT(setUseByteNormals(bool)));
|
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");
|
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
||||||
|
|
||||||
|
|
|
@ -207,6 +207,7 @@ namespace MenuOption {
|
||||||
const QString Quit = "Quit";
|
const QString Quit = "Quit";
|
||||||
const QString UseVoxelShader = "Use Voxel Shader";
|
const QString UseVoxelShader = "Use Voxel Shader";
|
||||||
const QString UseByteNormals = "Use Byte Normals";
|
const QString UseByteNormals = "Use Byte Normals";
|
||||||
|
const QString UseGlobalNormals = "Use Global Normals";
|
||||||
const QString Voxels = "Voxels";
|
const QString Voxels = "Voxels";
|
||||||
const QString VoxelAddMode = "Add Voxel Mode";
|
const QString VoxelAddMode = "Add Voxel Mode";
|
||||||
const QString VoxelColorMode = "Color Voxel Mode";
|
const QString VoxelColorMode = "Color Voxel Mode";
|
||||||
|
|
|
@ -33,9 +33,11 @@
|
||||||
#include "VoxelConstants.h"
|
#include "VoxelConstants.h"
|
||||||
#include "VoxelSystem.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,
|
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 };
|
||||||
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 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,
|
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,
|
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+
|
10,11,15, 10,15,14, // Y+
|
||||||
4,5,6, 4,6,7 }; // Z+
|
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)
|
VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
||||||
: NodeData(NULL),
|
: NodeData(NULL),
|
||||||
_treeScale(treeScale),
|
_treeScale(treeScale),
|
||||||
|
@ -77,6 +86,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
||||||
|
|
||||||
_useVoxelShader = false;
|
_useVoxelShader = false;
|
||||||
_useByteNormals = false;
|
_useByteNormals = false;
|
||||||
|
_useGlobalNormals = false;
|
||||||
|
|
||||||
_writeVoxelShaderData = NULL;
|
_writeVoxelShaderData = NULL;
|
||||||
_readVoxelShaderData = NULL;
|
_readVoxelShaderData = NULL;
|
||||||
|
@ -145,6 +155,7 @@ void VoxelSystem::setUseByteNormals(bool useByteNormals) {
|
||||||
pthread_mutex_lock(&_bufferWriteLock);
|
pthread_mutex_lock(&_bufferWriteLock);
|
||||||
bool wasInitialized = _initialized;
|
bool wasInitialized = _initialized;
|
||||||
if (wasInitialized) {
|
if (wasInitialized) {
|
||||||
|
clearAllNodesBufferIndex();
|
||||||
cleanupVoxelMemory();
|
cleanupVoxelMemory();
|
||||||
}
|
}
|
||||||
_useByteNormals = useByteNormals;
|
_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) {
|
void VoxelSystem::setMaxVoxels(int maxVoxels) {
|
||||||
pthread_mutex_lock(&_bufferWriteLock);
|
pthread_mutex_lock(&_bufferWriteLock);
|
||||||
bool wasInitialized = _initialized;
|
bool wasInitialized = _initialized;
|
||||||
if (wasInitialized) {
|
if (wasInitialized) {
|
||||||
|
clearAllNodesBufferIndex();
|
||||||
cleanupVoxelMemory();
|
cleanupVoxelMemory();
|
||||||
}
|
}
|
||||||
_maxVoxels = maxVoxels;
|
_maxVoxels = maxVoxels;
|
||||||
|
@ -206,9 +235,19 @@ void VoxelSystem::cleanupVoxelMemory() {
|
||||||
} else {
|
} else {
|
||||||
// Destroy glBuffers
|
// Destroy glBuffers
|
||||||
glDeleteBuffers(1, &_vboVerticesID);
|
glDeleteBuffers(1, &_vboVerticesID);
|
||||||
glDeleteBuffers(1, &_vboNormalsID);
|
|
||||||
glDeleteBuffers(1, &_vboColorsID);
|
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[] _readVerticesArray;
|
||||||
delete[] _writeVerticesArray;
|
delete[] _writeVerticesArray;
|
||||||
|
@ -221,6 +260,34 @@ void VoxelSystem::cleanupVoxelMemory() {
|
||||||
_initialized = false; // no longer initialized
|
_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() {
|
void VoxelSystem::initVoxelMemory() {
|
||||||
_initialMemoryUsageGPU = getFreeMemoryGPU();
|
_initialMemoryUsageGPU = getFreeMemoryGPU();
|
||||||
_memoryUsageRAM = 0;
|
_memoryUsageRAM = 0;
|
||||||
|
@ -265,91 +332,104 @@ void VoxelSystem::initVoxelMemory() {
|
||||||
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
||||||
_memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);
|
_memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);
|
||||||
} else {
|
} else {
|
||||||
GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels];
|
if (_useGlobalNormals) {
|
||||||
|
// Global Normals mode uses a technique of not including normals on any voxel vertices, and instead
|
||||||
// populate the indicesArray
|
// rendering the voxel faces in 6 passes that use a global call to glNormal3f()
|
||||||
// this will not change given new voxels, so we can set it all up now
|
qDebug("Using Global Normals...\n");
|
||||||
for (int n = 0; n < _maxVoxels; n++) {
|
setupFaceIndices(_vboIndicesTop, identityIndicesTop);
|
||||||
// fill the indices array
|
setupFaceIndices(_vboIndicesBottom, identityIndicesBottom);
|
||||||
int voxelIndexOffset = n * INDICES_PER_VOXEL;
|
setupFaceIndices(_vboIndicesLeft, identityIndicesLeft);
|
||||||
GLuint* currentIndicesPos = indicesArray + voxelIndexOffset;
|
setupFaceIndices(_vboIndicesRight, identityIndicesRight);
|
||||||
int startIndex = (n * VERTICES_PER_VOXEL);
|
setupFaceIndices(_vboIndicesFront, identityIndicesFront);
|
||||||
|
setupFaceIndices(_vboIndicesBack, identityIndicesBack);
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
qDebug("Using Float Normals...\n");
|
if (_useByteNormals) {
|
||||||
GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
qDebug("Using Byte Normals...\n");
|
||||||
GLfloat* normalsArrayEndPointer = normalsArray;
|
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 n = 0; n < _maxVoxels; n++) {
|
||||||
for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) {
|
// fill the indices array
|
||||||
*(normalsArrayEndPointer++) = identityNormals[i];
|
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
|
// VBO for the indicesArray
|
||||||
glGenBuffers(1, &_vboNormalsID);
|
glGenBuffers(1, &_vboIndicesID);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
||||||
glBufferData(GL_ARRAY_BUFFER,
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||||
VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels,
|
INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels,
|
||||||
normalsArray, GL_STATIC_DRAW);
|
indicesArray, GL_STATIC_DRAW);
|
||||||
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels;
|
_memoryUsageVBO += INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels;
|
||||||
|
|
||||||
// delete the indices and normals arrays that are no longer needed
|
// 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);
|
glGenBuffers(1, &_vboVerticesID);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
|
||||||
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
||||||
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels;
|
_memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels;
|
||||||
|
|
||||||
// VBO for colorsArray
|
// VBO for colorsArray
|
||||||
glGenBuffers(1, &_vboColorsID);
|
glGenBuffers(1, &_vboColorsID);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
||||||
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
||||||
_memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels;
|
_memoryUsageVBO += vertexPointsPerVoxel * 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;
|
|
||||||
|
|
||||||
|
|
||||||
// we will track individual dirty sections with these arrays of bools
|
// we will track individual dirty sections with these arrays of bools
|
||||||
_writeVoxelDirtyArray = new bool[_maxVoxels];
|
_writeVoxelDirtyArray = new bool[_maxVoxels];
|
||||||
|
@ -361,15 +441,15 @@ void VoxelSystem::initVoxelMemory() {
|
||||||
_memoryUsageRAM += (sizeof(bool) * _maxVoxels);
|
_memoryUsageRAM += (sizeof(bool) * _maxVoxels);
|
||||||
|
|
||||||
// prep the data structures for incoming voxel data
|
// prep the data structures for incoming voxel data
|
||||||
_writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
_writeVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels];
|
||||||
_memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels);
|
_memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels);
|
||||||
_readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
_readVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels];
|
||||||
_memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels);
|
_memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels);
|
||||||
|
|
||||||
_writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
_writeColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels];
|
||||||
_memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels);
|
_memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels);
|
||||||
_readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
_readColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels];
|
||||||
_memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels);
|
_memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels);
|
||||||
|
|
||||||
|
|
||||||
// create our simple fragment shader if we're the first system to init
|
// 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];
|
void* writeDataAt = &_writeVoxelShaderData[segmentStart];
|
||||||
memcpy(readDataAt, writeDataAt, segmentSizeBytes);
|
memcpy(readDataAt, writeDataAt, segmentSizeBytes);
|
||||||
} else {
|
} else {
|
||||||
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
|
// Depending on if we're using per vertex normals, we will need more or less vertex points per voxel
|
||||||
GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
|
int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL;
|
||||||
GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
|
|
||||||
GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * 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);
|
memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes);
|
||||||
|
|
||||||
segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
|
segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte);
|
||||||
segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
|
segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte);
|
||||||
GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
|
GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel);
|
||||||
GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
|
GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel);
|
||||||
memcpy(readColorsAt, writeColorsAt, segmentSizeBytes);
|
memcpy(readColorsAt, writeColorsAt, segmentSizeBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -797,10 +880,17 @@ void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& s
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_writeVerticesArray && _writeColorsArray) {
|
if (_writeVerticesArray && _writeColorsArray) {
|
||||||
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
|
int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL;
|
||||||
GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
|
for (int j = 0; j < vertexPointsPerVoxel; j++ ) {
|
||||||
GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
|
GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel);
|
||||||
*(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale);
|
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];
|
*(writeColorsAt +j) = color[j % 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -912,15 +1002,16 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
|
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
|
||||||
} else {
|
} else {
|
||||||
|
int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL;
|
||||||
int segmentLength = (segmentEnd - segmentStart) + 1;
|
int segmentLength = (segmentEnd - segmentStart) + 1;
|
||||||
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
|
GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat);
|
||||||
GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
|
GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat);
|
||||||
GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
|
GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * vertexPointsPerVoxel);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
|
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
|
||||||
segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
|
segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte);
|
||||||
segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
|
segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte);
|
||||||
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
|
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * vertexPointsPerVoxel);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
|
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
|
||||||
}
|
}
|
||||||
|
@ -966,27 +1057,66 @@ void VoxelSystem::render(bool texture) {
|
||||||
} else {
|
} else {
|
||||||
// tell OpenGL where to find vertex and color information
|
// tell OpenGL where to find vertex and color information
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glEnableClientState(GL_NORMAL_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
|
||||||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
|
|
||||||
glNormalPointer((_useByteNormals ? GL_BYTE : GL_FLOAT), 0, 0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
||||||
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
|
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);
|
applyScaleAndBindProgram(texture);
|
||||||
|
|
||||||
// for performance, enable backface culling
|
// for performance, enable backface culling
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
// draw the number of voxels we have
|
if (!_useGlobalNormals) {
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
// draw the number of voxels we have
|
||||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1,
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
||||||
36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
|
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);
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
@ -994,9 +1124,12 @@ void VoxelSystem::render(bool texture) {
|
||||||
|
|
||||||
// deactivate vertex and color arrays after drawing
|
// deactivate vertex and color arrays after drawing
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
|
if (!_useGlobalNormals) {
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
// bind with 0 to switch back to normal operation
|
// bind with 0 to switch back to normal operation
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
|
@ -135,6 +135,7 @@ public slots:
|
||||||
|
|
||||||
void cancelImport();
|
void cancelImport();
|
||||||
void setUseByteNormals(bool useByteNormals);
|
void setUseByteNormals(bool useByteNormals);
|
||||||
|
void setUseGlobalNormals(bool useGlobalNormals);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float _treeScale;
|
float _treeScale;
|
||||||
|
@ -218,6 +219,7 @@ private:
|
||||||
void cleanupVoxelMemory();
|
void cleanupVoxelMemory();
|
||||||
|
|
||||||
bool _useByteNormals;
|
bool _useByteNormals;
|
||||||
|
bool _useGlobalNormals;
|
||||||
|
|
||||||
bool _useVoxelShader;
|
bool _useVoxelShader;
|
||||||
GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO
|
GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO
|
||||||
|
@ -229,6 +231,14 @@ private:
|
||||||
GLuint _vboNormalsID;
|
GLuint _vboNormalsID;
|
||||||
GLuint _vboColorsID;
|
GLuint _vboColorsID;
|
||||||
GLuint _vboIndicesID;
|
GLuint _vboIndicesID;
|
||||||
|
|
||||||
|
GLuint _vboIndicesTop;
|
||||||
|
GLuint _vboIndicesBottom;
|
||||||
|
GLuint _vboIndicesLeft;
|
||||||
|
GLuint _vboIndicesRight;
|
||||||
|
GLuint _vboIndicesFront;
|
||||||
|
GLuint _vboIndicesBack;
|
||||||
|
|
||||||
pthread_mutex_t _bufferWriteLock;
|
pthread_mutex_t _bufferWriteLock;
|
||||||
pthread_mutex_t _treeLock;
|
pthread_mutex_t _treeLock;
|
||||||
|
|
||||||
|
@ -236,6 +246,8 @@ private:
|
||||||
ViewFrustum _lastStableViewFrustum;
|
ViewFrustum _lastStableViewFrustum;
|
||||||
ViewFrustum* _viewFrustum;
|
ViewFrustum* _viewFrustum;
|
||||||
|
|
||||||
|
void setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]);
|
||||||
|
|
||||||
int newTreeToArrays(VoxelNode *currentNode);
|
int newTreeToArrays(VoxelNode *currentNode);
|
||||||
void cleanupRemovedVoxels();
|
void cleanupRemovedVoxels();
|
||||||
|
|
||||||
|
|
|
@ -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 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 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;
|
typedef unsigned long int glBufferIndex;
|
||||||
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue