mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 21:57:00 +02:00
Merge pull request #360 from ey6es/master
Dragging support for adding/deleting voxels, toggle for voxel noise texture, fix for threading issue with voxels (believe this is what caused the bad triangles).
This commit is contained in:
commit
24f52ff2fc
4 changed files with 107 additions and 68 deletions
|
@ -138,6 +138,7 @@ Application::Application(int& argc, char** argv) :
|
||||||
_mouseY(0),
|
_mouseY(0),
|
||||||
_mousePressed(false),
|
_mousePressed(false),
|
||||||
_mouseVoxelScale(1.0f / 1024.0f),
|
_mouseVoxelScale(1.0f / 1024.0f),
|
||||||
|
_justEditedVoxel(false),
|
||||||
_paintOn(false),
|
_paintOn(false),
|
||||||
_dominantColor(0),
|
_dominantColor(0),
|
||||||
_perfStatsOn(false),
|
_perfStatsOn(false),
|
||||||
|
@ -738,8 +739,13 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
||||||
|
|
||||||
// detect drag
|
// detect drag
|
||||||
glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
|
glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
|
||||||
if (_colorVoxelMode->isChecked() && event->buttons().testFlag(Qt::LeftButton) && mouseVoxelPos != _lastMouseVoxelPos) {
|
if (!_justEditedVoxel && mouseVoxelPos != _lastMouseVoxelPos) {
|
||||||
addVoxelUnderCursor();
|
if (event->buttons().testFlag(Qt::LeftButton)) {
|
||||||
|
maybeEditVoxelUnderCursor();
|
||||||
|
|
||||||
|
} else if (event->buttons().testFlag(Qt::RightButton) && checkedVoxelModeAction() != 0) {
|
||||||
|
deleteVoxelUnderCursor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,13 +754,8 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
||||||
_mouseX = event->x();
|
_mouseX = event->x();
|
||||||
_mouseY = event->y();
|
_mouseY = event->y();
|
||||||
_mousePressed = true;
|
_mousePressed = true;
|
||||||
|
maybeEditVoxelUnderCursor();
|
||||||
if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) {
|
|
||||||
addVoxelUnderCursor();
|
|
||||||
|
|
||||||
} else if (_deleteVoxelMode->isChecked()) {
|
|
||||||
deleteVoxelUnderCursor();
|
|
||||||
}
|
|
||||||
} else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) {
|
} else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) {
|
||||||
deleteVoxelUnderCursor();
|
deleteVoxelUnderCursor();
|
||||||
}
|
}
|
||||||
|
@ -927,6 +928,12 @@ void Application::idle() {
|
||||||
_mouseVoxel.green = paintColor.green();
|
_mouseVoxel.green = paintColor.green();
|
||||||
_mouseVoxel.blue = paintColor.blue();
|
_mouseVoxel.blue = paintColor.blue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we just edited, use the currently selected voxel as the "last" for drag detection
|
||||||
|
if (_justEditedVoxel) {
|
||||||
|
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
|
||||||
|
_justEditedVoxel = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// walking triggers the handControl to stop
|
// walking triggers the handControl to stop
|
||||||
|
@ -1202,6 +1209,8 @@ void Application::initMenu() {
|
||||||
(_renderVoxels = renderMenu->addAction("Voxels"))->setCheckable(true);
|
(_renderVoxels = renderMenu->addAction("Voxels"))->setCheckable(true);
|
||||||
_renderVoxels->setChecked(true);
|
_renderVoxels->setChecked(true);
|
||||||
_renderVoxels->setShortcut(Qt::Key_V);
|
_renderVoxels->setShortcut(Qt::Key_V);
|
||||||
|
(_renderVoxelTextures = renderMenu->addAction("Voxel Textures"))->setCheckable(true);
|
||||||
|
_renderVoxelTextures->setChecked(true);
|
||||||
(_renderStarsOn = renderMenu->addAction("Stars"))->setCheckable(true);
|
(_renderStarsOn = renderMenu->addAction("Stars"))->setCheckable(true);
|
||||||
_renderStarsOn->setChecked(true);
|
_renderStarsOn->setChecked(true);
|
||||||
_renderStarsOn->setShortcut(Qt::Key_Asterisk);
|
_renderStarsOn->setShortcut(Qt::Key_Asterisk);
|
||||||
|
@ -1678,7 +1687,7 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
|
|
||||||
// Draw voxels
|
// Draw voxels
|
||||||
if (_renderVoxels->isChecked()) {
|
if (_renderVoxels->isChecked()) {
|
||||||
_voxels.render();
|
_voxels.render(_renderVoxelTextures->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
// indicate what we'll be adding/removing in mouse mode, if anything
|
// indicate what we'll be adding/removing in mouse mode, if anything
|
||||||
|
@ -2020,18 +2029,22 @@ void Application::shiftPaintingColor() {
|
||||||
_paintingVoxel.blue = (_dominantColor == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100);
|
_paintingVoxel.blue = (_dominantColor == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::addVoxelUnderCursor() {
|
void Application::maybeEditVoxelUnderCursor() {
|
||||||
if (_mouseVoxel.s != 0) {
|
if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) {
|
||||||
PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ?
|
if (_mouseVoxel.s != 0) {
|
||||||
PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL);
|
PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ?
|
||||||
sendVoxelEditMessage(message, _mouseVoxel);
|
PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL);
|
||||||
|
sendVoxelEditMessage(message, _mouseVoxel);
|
||||||
|
|
||||||
|
// create the voxel locally so it appears immediately
|
||||||
|
_voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s,
|
||||||
|
_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue, _destructiveAddVoxel->isChecked());
|
||||||
|
|
||||||
// create the voxel locally so it appears immediately
|
// remember the position for drag detection
|
||||||
_voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s,
|
_justEditedVoxel = true;
|
||||||
_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue, _destructiveAddVoxel->isChecked());
|
}
|
||||||
|
} else if (_deleteVoxelMode->isChecked()) {
|
||||||
// remember the position for drag detection
|
deleteVoxelUnderCursor();
|
||||||
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2043,7 +2056,7 @@ void Application::deleteVoxelUnderCursor() {
|
||||||
_voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
_voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||||
|
|
||||||
// remember the position for drag detection
|
// remember the position for drag detection
|
||||||
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
|
_justEditedVoxel = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ private:
|
||||||
|
|
||||||
void setupPaintingVoxel();
|
void setupPaintingVoxel();
|
||||||
void shiftPaintingColor();
|
void shiftPaintingColor();
|
||||||
void addVoxelUnderCursor();
|
void maybeEditVoxelUnderCursor();
|
||||||
void deleteVoxelUnderCursor();
|
void deleteVoxelUnderCursor();
|
||||||
|
|
||||||
void resetSensors();
|
void resetSensors();
|
||||||
|
@ -135,6 +135,7 @@ private:
|
||||||
QAction* _gyroLook; // Whether to allow the gyro data from head to move your view
|
QAction* _gyroLook; // Whether to allow the gyro data from head to move your view
|
||||||
QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view
|
QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view
|
||||||
QAction* _renderVoxels; // Whether to render voxels
|
QAction* _renderVoxels; // Whether to render voxels
|
||||||
|
QAction* _renderVoxelTextures; // Whether to render noise textures on voxels
|
||||||
QAction* _renderStarsOn; // Whether to display the stars
|
QAction* _renderStarsOn; // Whether to display the stars
|
||||||
QAction* _renderAtmosphereOn; // Whether to display the atmosphere
|
QAction* _renderAtmosphereOn; // Whether to display the atmosphere
|
||||||
QAction* _renderAvatarsOn; // Whether to render avatars
|
QAction* _renderAvatarsOn; // Whether to render avatars
|
||||||
|
@ -204,6 +205,7 @@ private:
|
||||||
VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor
|
VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor
|
||||||
float _mouseVoxelScale; // the scale for adding/removing voxels
|
float _mouseVoxelScale; // the scale for adding/removing voxels
|
||||||
glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit
|
glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit
|
||||||
|
bool _justEditedVoxel; // set when we've just added/deleted/colored a voxel
|
||||||
|
|
||||||
bool _paintOn; // Whether to paint voxels as you fly around
|
bool _paintOn; // Whether to paint voxels as you fly around
|
||||||
unsigned char _dominantColor; // The dominant color of the voxel we're painting
|
unsigned char _dominantColor; // The dominant color of the voxel we're painting
|
||||||
|
|
|
@ -46,7 +46,8 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- .
|
||||||
|
|
||||||
VoxelSystem::VoxelSystem() {
|
VoxelSystem::VoxelSystem() {
|
||||||
_voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
|
_voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
|
||||||
_renderFullVBO = true;
|
_writeRenderFullVBO = true;
|
||||||
|
_readRenderFullVBO = true;
|
||||||
_tree = new VoxelTree();
|
_tree = new VoxelTree();
|
||||||
pthread_mutex_init(&_bufferWriteLock, NULL);
|
pthread_mutex_init(&_bufferWriteLock, NULL);
|
||||||
pthread_mutex_init(&_treeLock, NULL);
|
pthread_mutex_init(&_treeLock, NULL);
|
||||||
|
@ -57,7 +58,8 @@ VoxelSystem::~VoxelSystem() {
|
||||||
delete[] _writeVerticesArray;
|
delete[] _writeVerticesArray;
|
||||||
delete[] _readColorsArray;
|
delete[] _readColorsArray;
|
||||||
delete[] _writeColorsArray;
|
delete[] _writeColorsArray;
|
||||||
delete[] _voxelDirtyArray;
|
delete[] _writeVoxelDirtyArray;
|
||||||
|
delete[] _readVoxelDirtyArray;
|
||||||
delete _tree;
|
delete _tree;
|
||||||
pthread_mutex_destroy(&_bufferWriteLock);
|
pthread_mutex_destroy(&_bufferWriteLock);
|
||||||
pthread_mutex_destroy(&_treeLock);
|
pthread_mutex_destroy(&_treeLock);
|
||||||
|
@ -180,14 +182,15 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||||
_lastViewCullingElapsed = (endViewCulling - start) / 1000.0;
|
_lastViewCullingElapsed = (endViewCulling - start) / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool didWriteFullVBO = _writeRenderFullVBO;
|
||||||
if (_tree->isDirty()) {
|
if (_tree->isDirty()) {
|
||||||
static char buffer[64] = { 0 };
|
static char buffer[64] = { 0 };
|
||||||
if (_renderWarningsOn) {
|
if (_renderWarningsOn) {
|
||||||
sprintf(buffer, "newTreeToArrays() _renderFullVBO=%s", (_renderFullVBO ? "yes" : "no"));
|
sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", (_writeRenderFullVBO ? "yes" : "no"));
|
||||||
};
|
};
|
||||||
PerformanceWarning warn(_renderWarningsOn, buffer);
|
PerformanceWarning warn(_renderWarningsOn, buffer);
|
||||||
_callsToTreesToArrays++;
|
_callsToTreesToArrays++;
|
||||||
if (_renderFullVBO) {
|
if (_writeRenderFullVBO) {
|
||||||
_voxelsInWriteArrays = 0; // reset our VBO
|
_voxelsInWriteArrays = 0; // reset our VBO
|
||||||
}
|
}
|
||||||
_voxelsUpdated = newTreeToArrays(_tree->rootNode);
|
_voxelsUpdated = newTreeToArrays(_tree->rootNode);
|
||||||
|
@ -195,16 +198,22 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||||
|
|
||||||
// since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are
|
// since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are
|
||||||
// ok again, until/unless we call removeOutOfView()
|
// ok again, until/unless we call removeOutOfView()
|
||||||
_renderFullVBO = false;
|
_writeRenderFullVBO = false;
|
||||||
} else {
|
} else {
|
||||||
_voxelsUpdated = 0;
|
_voxelsUpdated = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
|
||||||
|
pthread_mutex_lock(&_bufferWriteLock);
|
||||||
|
|
||||||
if (_voxelsUpdated) {
|
if (_voxelsUpdated) {
|
||||||
_voxelsDirty=true;
|
_voxelsDirty=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated
|
// copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated
|
||||||
copyWrittenDataToReadArrays();
|
copyWrittenDataToReadArrays(didWriteFullVBO);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_bufferWriteLock);
|
||||||
|
|
||||||
double end = usecTimestampNow();
|
double end = usecTimestampNow();
|
||||||
double elapsedmsec = (end - start) / 1000.0;
|
double elapsedmsec = (end - start) / 1000.0;
|
||||||
|
@ -218,30 +227,32 @@ void VoxelSystem::cleanupRemovedVoxels() {
|
||||||
while (!_removedVoxels.isEmpty()) {
|
while (!_removedVoxels.isEmpty()) {
|
||||||
delete _removedVoxels.extract();
|
delete _removedVoxels.extract();
|
||||||
}
|
}
|
||||||
_renderFullVBO = true; // if we remove voxels, we must update our full VBOs
|
_writeRenderFullVBO = true; // if we remove voxels, we must update our full VBOs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::copyWrittenDataToReadArraysFullVBOs() {
|
void VoxelSystem::copyWrittenDataToReadArraysFullVBOs() {
|
||||||
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
|
|
||||||
pthread_mutex_lock(&_bufferWriteLock);
|
|
||||||
int bytesOfVertices = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);
|
int bytesOfVertices = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);
|
||||||
int bytesOfColors = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte);
|
int bytesOfColors = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte);
|
||||||
memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices);
|
memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices);
|
||||||
memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
|
memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
|
||||||
_voxelsInReadArrays = _voxelsInWriteArrays;
|
_voxelsInReadArrays = _voxelsInWriteArrays;
|
||||||
pthread_mutex_unlock(&_bufferWriteLock);
|
|
||||||
|
// clear our dirty flags
|
||||||
|
memset(_writeVoxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool));
|
||||||
|
|
||||||
|
// let the reader know to get the full array
|
||||||
|
_readRenderFullVBO = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() {
|
void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() {
|
||||||
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
|
|
||||||
pthread_mutex_lock(&_bufferWriteLock);
|
|
||||||
|
|
||||||
glBufferIndex segmentStart = 0;
|
glBufferIndex segmentStart = 0;
|
||||||
glBufferIndex segmentEnd = 0;
|
glBufferIndex segmentEnd = 0;
|
||||||
bool inSegment = false;
|
bool inSegment = false;
|
||||||
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
|
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
|
||||||
bool thisVoxelDirty = _voxelDirtyArray[i];
|
bool thisVoxelDirty = _writeVoxelDirtyArray[i];
|
||||||
|
_readVoxelDirtyArray[i] |= thisVoxelDirty;
|
||||||
|
_writeVoxelDirtyArray[i] = false;
|
||||||
if (!inSegment) {
|
if (!inSegment) {
|
||||||
if (thisVoxelDirty) {
|
if (thisVoxelDirty) {
|
||||||
segmentStart = i;
|
segmentStart = i;
|
||||||
|
@ -290,14 +301,12 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() {
|
||||||
|
|
||||||
// update our length
|
// update our length
|
||||||
_voxelsInReadArrays = _voxelsInWriteArrays;
|
_voxelsInReadArrays = _voxelsInWriteArrays;
|
||||||
|
|
||||||
pthread_mutex_unlock(&_bufferWriteLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::copyWrittenDataToReadArrays() {
|
void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
|
||||||
PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()");
|
PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()");
|
||||||
if (_voxelsDirty && _voxelsUpdated) {
|
if (_voxelsDirty && _voxelsUpdated) {
|
||||||
if (_renderFullVBO) {
|
if (fullVBOs) {
|
||||||
copyWrittenDataToReadArraysFullVBOs();
|
copyWrittenDataToReadArraysFullVBOs();
|
||||||
} else {
|
} else {
|
||||||
copyWrittenDataToReadArraysPartialVBOs();
|
copyWrittenDataToReadArraysPartialVBOs();
|
||||||
|
@ -327,7 +336,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_renderFullVBO) {
|
if (_writeRenderFullVBO) {
|
||||||
voxelsUpdated += updateNodeInArraysAsFullVBO(node);
|
voxelsUpdated += updateNodeInArraysAsFullVBO(node);
|
||||||
} else {
|
} else {
|
||||||
voxelsUpdated += updateNodeInArraysAsPartialVBO(node);
|
voxelsUpdated += updateNodeInArraysAsPartialVBO(node);
|
||||||
|
@ -365,7 +374,7 @@ int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) {
|
||||||
*(writeColorsAt +j) = node->getColor()[j % 3];
|
*(writeColorsAt +j) = node->getColor()[j % 3];
|
||||||
}
|
}
|
||||||
node->setBufferIndex(nodeIndex);
|
node->setBufferIndex(nodeIndex);
|
||||||
_voxelDirtyArray[nodeIndex] = true; // just in case we switch to Partial mode
|
_writeVoxelDirtyArray[nodeIndex] = true; // just in case we switch to Partial mode
|
||||||
_voxelsInWriteArrays++; // our know vertices in the arrays
|
_voxelsInWriteArrays++; // our know vertices in the arrays
|
||||||
return 1; // rendered
|
return 1; // rendered
|
||||||
}
|
}
|
||||||
|
@ -402,7 +411,7 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) {
|
||||||
node->setBufferIndex(nodeIndex);
|
node->setBufferIndex(nodeIndex);
|
||||||
_voxelsInWriteArrays++;
|
_voxelsInWriteArrays++;
|
||||||
}
|
}
|
||||||
_voxelDirtyArray[nodeIndex] = true;
|
_writeVoxelDirtyArray[nodeIndex] = true;
|
||||||
|
|
||||||
// populate the array with points for the 8 vertices
|
// populate the array with points for the 8 vertices
|
||||||
// and RGB color for each added vertex
|
// and RGB color for each added vertex
|
||||||
|
@ -431,9 +440,11 @@ void VoxelSystem::init() {
|
||||||
_voxelsInReadArrays = 0;
|
_voxelsInReadArrays = 0;
|
||||||
_unusedArraySpace = 0;
|
_unusedArraySpace = 0;
|
||||||
|
|
||||||
// we will track individual dirty sections with this array of bools
|
// we will track individual dirty sections with these arrays of bools
|
||||||
_voxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];
|
_writeVoxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];
|
||||||
memset(_voxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));
|
memset(_writeVoxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));
|
||||||
|
_readVoxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];
|
||||||
|
memset(_readVoxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));
|
||||||
|
|
||||||
// prep the data structures for incoming voxel data
|
// prep the data structures for incoming voxel data
|
||||||
_writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
|
_writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
|
||||||
|
@ -530,7 +541,7 @@ void VoxelSystem::init() {
|
||||||
|
|
||||||
void VoxelSystem::updateFullVBOs() {
|
void VoxelSystem::updateFullVBOs() {
|
||||||
glBufferIndex segmentStart = 0;
|
glBufferIndex segmentStart = 0;
|
||||||
glBufferIndex segmentEnd = _voxelsInWriteArrays;
|
glBufferIndex segmentEnd = _voxelsInReadArrays;
|
||||||
|
|
||||||
int segmentLength = (segmentEnd - segmentStart) + 1;
|
int segmentLength = (segmentEnd - segmentStart) + 1;
|
||||||
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
|
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
|
||||||
|
@ -544,21 +555,21 @@ void VoxelSystem::updateFullVBOs() {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
|
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
|
||||||
|
|
||||||
// consider the _voxelDirtyArray[] clean!
|
// consider the _readVoxelDirtyArray[] clean!
|
||||||
memset(_voxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool));
|
memset(_readVoxelDirtyArray, false, _voxelsInReadArrays * sizeof(bool));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::updatePartialVBOs() {
|
void VoxelSystem::updatePartialVBOs() {
|
||||||
glBufferIndex segmentStart = 0;
|
glBufferIndex segmentStart = 0;
|
||||||
glBufferIndex segmentEnd = 0;
|
glBufferIndex segmentEnd = 0;
|
||||||
bool inSegment = false;
|
bool inSegment = false;
|
||||||
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
|
for (glBufferIndex i = 0; i < _voxelsInReadArrays; i++) {
|
||||||
bool thisVoxelDirty = _voxelDirtyArray[i];
|
bool thisVoxelDirty = _readVoxelDirtyArray[i];
|
||||||
if (!inSegment) {
|
if (!inSegment) {
|
||||||
if (thisVoxelDirty) {
|
if (thisVoxelDirty) {
|
||||||
segmentStart = i;
|
segmentStart = i;
|
||||||
inSegment = true;
|
inSegment = true;
|
||||||
_voxelDirtyArray[i] = false; // consider us clean!
|
_readVoxelDirtyArray[i] = false; // consider us clean!
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!thisVoxelDirty) {
|
if (!thisVoxelDirty) {
|
||||||
|
@ -578,13 +589,13 @@ void VoxelSystem::updatePartialVBOs() {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
|
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
|
||||||
}
|
}
|
||||||
_voxelDirtyArray[i] = false; // consider us clean!
|
_readVoxelDirtyArray[i] = false; // consider us clean!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we got to the end of the array, and we're in an active dirty segment...
|
// if we got to the end of the array, and we're in an active dirty segment...
|
||||||
if (inSegment) {
|
if (inSegment) {
|
||||||
segmentEnd = _voxelsInWriteArrays - 1;
|
segmentEnd = _voxelsInReadArrays - 1;
|
||||||
inSegment = false;
|
inSegment = false;
|
||||||
int segmentLength = (segmentEnd - segmentStart) + 1;
|
int segmentLength = (segmentEnd - segmentStart) + 1;
|
||||||
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
|
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
|
||||||
|
@ -603,22 +614,27 @@ void VoxelSystem::updatePartialVBOs() {
|
||||||
void VoxelSystem::updateVBOs() {
|
void VoxelSystem::updateVBOs() {
|
||||||
static char buffer[40] = { 0 };
|
static char buffer[40] = { 0 };
|
||||||
if (_renderWarningsOn) {
|
if (_renderWarningsOn) {
|
||||||
sprintf(buffer, "updateVBOs() _renderFullVBO=%s", (_renderFullVBO ? "yes" : "no"));
|
sprintf(buffer, "updateVBOs() _readRenderFullVBO=%s", (_readRenderFullVBO ? "yes" : "no"));
|
||||||
};
|
};
|
||||||
PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays
|
PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays
|
||||||
if (_voxelsDirty) {
|
if (_voxelsDirty) {
|
||||||
if (_renderFullVBO) {
|
if (_readRenderFullVBO) {
|
||||||
updateFullVBOs();
|
updateFullVBOs();
|
||||||
} else {
|
} else {
|
||||||
updatePartialVBOs();
|
updatePartialVBOs();
|
||||||
}
|
}
|
||||||
_voxelsDirty = false;
|
_voxelsDirty = false;
|
||||||
|
_readRenderFullVBO = false;
|
||||||
}
|
}
|
||||||
_callsToTreesToArrays = 0; // clear it
|
_callsToTreesToArrays = 0; // clear it
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::render() {
|
void VoxelSystem::render(bool texture) {
|
||||||
PerformanceWarning warn(_renderWarningsOn, "render()");
|
PerformanceWarning warn(_renderWarningsOn, "render()");
|
||||||
|
|
||||||
|
// get the lock so that the update thread won't change anything
|
||||||
|
pthread_mutex_lock(&_bufferWriteLock);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
updateVBOs();
|
updateVBOs();
|
||||||
// tell OpenGL where to find vertex and color information
|
// tell OpenGL where to find vertex and color information
|
||||||
|
@ -635,9 +651,11 @@ void VoxelSystem::render() {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
||||||
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
|
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
|
||||||
|
|
||||||
_perlinModulateProgram->bind();
|
if (texture) {
|
||||||
glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID);
|
_perlinModulateProgram->bind();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID);
|
||||||
|
}
|
||||||
|
|
||||||
// for performance, disable blending and enable backface culling
|
// for performance, disable blending and enable backface culling
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
@ -650,9 +668,11 @@ void VoxelSystem::render() {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
_perlinModulateProgram->release();
|
if (texture) {
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
_perlinModulateProgram->release();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// 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_NORMAL_ARRAY);
|
||||||
|
@ -664,6 +684,8 @@ void VoxelSystem::render() {
|
||||||
|
|
||||||
// scale back down to 1 so heads aren't massive
|
// scale back down to 1 so heads aren't massive
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_bufferWriteLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelSystem::_nodeCount = 0;
|
int VoxelSystem::_nodeCount = 0;
|
||||||
|
@ -1012,7 +1034,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
|
||||||
glBufferIndex maxDirty = 0;
|
glBufferIndex maxDirty = 0;
|
||||||
|
|
||||||
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
|
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
|
||||||
if (_voxelDirtyArray[i]) {
|
if (_writeVoxelDirtyArray[i]) {
|
||||||
minDirty = std::min(minDirty,i);
|
minDirty = std::min(minDirty,i);
|
||||||
maxDirty = std::max(maxDirty,i);
|
maxDirty = std::max(maxDirty,i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void simulate(float deltaTime) { };
|
void simulate(float deltaTime) { };
|
||||||
void render();
|
void render(bool texture);
|
||||||
|
|
||||||
unsigned long getVoxelsUpdated() const {return _voxelsUpdated;};
|
unsigned long getVoxelsUpdated() const {return _voxelsUpdated;};
|
||||||
unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;};
|
unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;};
|
||||||
|
@ -118,13 +118,15 @@ private:
|
||||||
GLubyte* _readColorsArray;
|
GLubyte* _readColorsArray;
|
||||||
GLfloat* _writeVerticesArray;
|
GLfloat* _writeVerticesArray;
|
||||||
GLubyte* _writeColorsArray;
|
GLubyte* _writeColorsArray;
|
||||||
bool* _voxelDirtyArray;
|
bool* _writeVoxelDirtyArray;
|
||||||
|
bool* _readVoxelDirtyArray;
|
||||||
unsigned long _voxelsUpdated;
|
unsigned long _voxelsUpdated;
|
||||||
unsigned long _voxelsInWriteArrays;
|
unsigned long _voxelsInWriteArrays;
|
||||||
unsigned long _voxelsInReadArrays;
|
unsigned long _voxelsInReadArrays;
|
||||||
unsigned long _unusedArraySpace;
|
unsigned long _unusedArraySpace;
|
||||||
|
|
||||||
bool _renderFullVBO;
|
bool _writeRenderFullVBO;
|
||||||
|
bool _readRenderFullVBO;
|
||||||
|
|
||||||
double _setupNewVoxelsForDrawingLastElapsed;
|
double _setupNewVoxelsForDrawingLastElapsed;
|
||||||
double _setupNewVoxelsForDrawingLastFinished;
|
double _setupNewVoxelsForDrawingLastFinished;
|
||||||
|
@ -148,7 +150,7 @@ private:
|
||||||
void cleanupRemovedVoxels();
|
void cleanupRemovedVoxels();
|
||||||
|
|
||||||
void setupNewVoxelsForDrawing();
|
void setupNewVoxelsForDrawing();
|
||||||
void copyWrittenDataToReadArrays();
|
void copyWrittenDataToReadArrays(bool fullVBOs);
|
||||||
|
|
||||||
bool _voxelsDirty;
|
bool _voxelsDirty;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue