mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 01:27:37 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
This commit is contained in:
commit
5dc7b64c03
16 changed files with 422 additions and 180 deletions
|
@ -84,7 +84,7 @@ and features are available via menus in the Interface application.
|
||||||
Other components
|
Other components
|
||||||
========
|
========
|
||||||
|
|
||||||
voxel-server, animation-server, audio-mixer, avatar-mixer, domain-server,
|
assignment-client, animation-server, domain-server,
|
||||||
pairing-server and space-server are architectural components that will allow
|
pairing-server and space-server are architectural components that will allow
|
||||||
you to run the full stack of the virtual world should you choose to.
|
you to run the full stack of the virtual world should you choose to.
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,10 @@
|
||||||
#include "Agent.h"
|
#include "Agent.h"
|
||||||
#include "voxels/VoxelScriptingInterface.h"
|
#include "voxels/VoxelScriptingInterface.h"
|
||||||
|
|
||||||
Agent::Agent(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) {
|
Agent::Agent(const unsigned char* dataBuffer, int numBytes) :
|
||||||
|
Assignment(dataBuffer, numBytes),
|
||||||
|
_shouldStop(false)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,17 @@ const int VERTICES_PER_FACE = 4;
|
||||||
const int COORD_PER_VERTEX = 3;
|
const int COORD_PER_VERTEX = 3;
|
||||||
const int COORD_PER_FACE = COORD_PER_VERTEX * VERTICES_PER_FACE;
|
const int COORD_PER_FACE = COORD_PER_VERTEX * VERTICES_PER_FACE;
|
||||||
|
|
||||||
void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec4 color) {
|
void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec4 color, vec4 normal) {
|
||||||
for (int v = 0; v < VERTICES_PER_FACE; v++ ) {
|
for (int v = 0; v < VERTICES_PER_FACE; v++ ) {
|
||||||
vec4 vertex = corner;
|
vec4 vertex = corner;
|
||||||
for (int c = 0; c < COORD_PER_VERTEX; c++ ) {
|
for (int c = 0; c < COORD_PER_VERTEX; c++ ) {
|
||||||
int cIndex = c + (v * COORD_PER_VERTEX);
|
int cIndex = c + (v * COORD_PER_VERTEX);
|
||||||
vertex[c] += (facePoints[cIndex] * scale);
|
vertex[c] += (facePoints[cIndex] * scale);
|
||||||
}
|
}
|
||||||
gl_FrontColor = color;
|
|
||||||
|
gl_FrontColor = color * (gl_LightModel.ambient + gl_LightSource[0].ambient +
|
||||||
|
gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position)));
|
||||||
|
|
||||||
gl_Position = gl_ModelViewProjectionMatrix * vertex;
|
gl_Position = gl_ModelViewProjectionMatrix * vertex;
|
||||||
EmitVertex();
|
EmitVertex();
|
||||||
}
|
}
|
||||||
|
@ -54,14 +57,21 @@ void main() {
|
||||||
float frontFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 );
|
float frontFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 );
|
||||||
float backFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1 );
|
float backFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1 );
|
||||||
|
|
||||||
|
vec4 bottomNormal = vec4(0.0, -1, 0.0, 0.0);
|
||||||
|
vec4 topNormal = vec4(0.0, 1, 0.0, 0.0);
|
||||||
|
vec4 rightNormal = vec4( -1, 0.0, 0.0, 0.0);
|
||||||
|
vec4 leftNormal = vec4( 1, 0.0, 0.0, 0.0);
|
||||||
|
vec4 frontNormal = vec4(0.0, 0.0, -1, 0.0);
|
||||||
|
vec4 backNormal = vec4(0.0, 0.0, 1, 0.0);
|
||||||
|
|
||||||
for(i = 0; i < gl_VerticesIn; i++) {
|
for(i = 0; i < gl_VerticesIn; i++) {
|
||||||
corner = gl_PositionIn[i];
|
corner = gl_PositionIn[i];
|
||||||
scale = voxelSize[i];
|
scale = voxelSize[i];
|
||||||
faceOfVoxel(corner, scale, bottomFace, gl_FrontColorIn[i]);
|
faceOfVoxel(corner, scale, bottomFace, gl_FrontColorIn[i], bottomNormal);
|
||||||
faceOfVoxel(corner, scale, topFace, gl_FrontColorIn[i]);
|
faceOfVoxel(corner, scale, topFace, gl_FrontColorIn[i], topNormal );
|
||||||
faceOfVoxel(corner, scale, rightFace, gl_FrontColorIn[i]);
|
faceOfVoxel(corner, scale, rightFace, gl_FrontColorIn[i], rightNormal );
|
||||||
faceOfVoxel(corner, scale, leftFace, gl_FrontColorIn[i]);
|
faceOfVoxel(corner, scale, leftFace, gl_FrontColorIn[i], leftNormal );
|
||||||
faceOfVoxel(corner, scale, frontFace, gl_FrontColorIn[i]);
|
faceOfVoxel(corner, scale, frontFace, gl_FrontColorIn[i], frontNormal );
|
||||||
faceOfVoxel(corner, scale, backFace, gl_FrontColorIn[i]);
|
faceOfVoxel(corner, scale, backFace, gl_FrontColorIn[i], backNormal );
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -151,6 +151,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
|
|
||||||
NodeList::getInstance()->addHook(&_voxels);
|
NodeList::getInstance()->addHook(&_voxels);
|
||||||
NodeList::getInstance()->addHook(this);
|
NodeList::getInstance()->addHook(this);
|
||||||
|
NodeList::getInstance()->addDomainListener(this);
|
||||||
|
|
||||||
|
|
||||||
// network receive thread and voxel parsing thread are both controlled by the --nonblocking command line
|
// network receive thread and voxel parsing thread are both controlled by the --nonblocking command line
|
||||||
|
@ -231,6 +232,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
NodeList::getInstance()->removeHook(&_voxels);
|
NodeList::getInstance()->removeHook(&_voxels);
|
||||||
NodeList::getInstance()->removeHook(this);
|
NodeList::getInstance()->removeHook(this);
|
||||||
|
NodeList::getInstance()->removeDomainListener(this);
|
||||||
|
|
||||||
_sharedVoxelSystem.changeTree(new VoxelTree);
|
_sharedVoxelSystem.changeTree(new VoxelTree);
|
||||||
|
|
||||||
|
@ -309,8 +311,6 @@ void Application::initializeGL() {
|
||||||
char title[50];
|
char title[50];
|
||||||
sprintf(title, "Interface: %4.2f seconds\n", startupTime);
|
sprintf(title, "Interface: %4.2f seconds\n", startupTime);
|
||||||
qDebug("%s", title);
|
qDebug("%s", title);
|
||||||
_window->setWindowTitle(title);
|
|
||||||
|
|
||||||
const char LOGSTASH_INTERFACE_START_TIME_KEY[] = "interface-start-time";
|
const char LOGSTASH_INTERFACE_START_TIME_KEY[] = "interface-start-time";
|
||||||
|
|
||||||
// ask the Logstash class to record the startup time
|
// ask the Logstash class to record the startup time
|
||||||
|
@ -1001,6 +1001,17 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
||||||
|
|
||||||
_audio.startCollisionSound(1.0, frequency, 0.0, HOVER_VOXEL_DECAY);
|
_audio.startCollisionSound(1.0, frequency, 0.0, HOVER_VOXEL_DECAY);
|
||||||
_isHoverVoxelSounding = true;
|
_isHoverVoxelSounding = true;
|
||||||
|
|
||||||
|
const float PERCENTAGE_TO_MOVE_TOWARD = 0.90f;
|
||||||
|
glm::vec3 newTarget = getMouseVoxelWorldCoordinates(_hoverVoxel);
|
||||||
|
glm::vec3 myPosition = _myAvatar.getPosition();
|
||||||
|
|
||||||
|
// If there is not an action tool set (add, delete, color), move to this voxel
|
||||||
|
if (!(Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode) ||
|
||||||
|
Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) ||
|
||||||
|
Menu::getInstance()->isOptionChecked(MenuOption::VoxelColorMode))) {
|
||||||
|
_myAvatar.setMoveTarget(myPosition + (newTarget - myPosition) * PERCENTAGE_TO_MOVE_TOWARD);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (event->button() == Qt::RightButton && Menu::getInstance()->isVoxelModeActionChecked()) {
|
} else if (event->button() == Qt::RightButton && Menu::getInstance()->isVoxelModeActionChecked()) {
|
||||||
|
@ -1577,7 +1588,6 @@ void Application::init() {
|
||||||
// Set up VoxelSystem after loading preferences so we can get the desired max voxel count
|
// Set up VoxelSystem after loading preferences so we can get the desired max voxel count
|
||||||
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
|
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
|
||||||
_voxels.setUseVoxelShader(Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader));
|
_voxels.setUseVoxelShader(Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader));
|
||||||
_voxels.setUseByteNormals(Menu::getInstance()->isOptionChecked(MenuOption::UseByteNormals));
|
|
||||||
_voxels.init();
|
_voxels.init();
|
||||||
|
|
||||||
|
|
||||||
|
@ -2827,28 +2837,36 @@ void Application::displayStats() {
|
||||||
voxelStats << "Voxels Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K " <<
|
voxelStats << "Voxels Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K " <<
|
||||||
"Updated: " << _voxels.getVoxelsUpdated()/1000.f << "K " <<
|
"Updated: " << _voxels.getVoxelsUpdated()/1000.f << "K " <<
|
||||||
"Max: " << _voxels.getMaxVoxels()/1000.f << "K ";
|
"Max: " << _voxels.getMaxVoxels()/1000.f << "K ";
|
||||||
|
|
||||||
drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
|
voxelStats.str("");
|
||||||
|
voxelStats << "Voxels Memory RAM: " << _voxels.getVoxelMemoryUsageRAM() / 1000000.f << "MB " <<
|
||||||
|
"VBO: " << _voxels.getVoxelMemoryUsageVBO() / 1000000.f << "MB ";
|
||||||
|
if (_voxels.hasVoxelMemoryUsageGPU()) {
|
||||||
|
voxelStats << "GPU: " << _voxels.getVoxelMemoryUsageGPU() / 1000000.f << "MB ";
|
||||||
|
}
|
||||||
|
|
||||||
|
drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
char* voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_VOXELS);
|
char* voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_VOXELS);
|
||||||
voxelStats << "Voxels Sent from Server: " << voxelDetails;
|
voxelStats << "Voxels Sent from Server: " << voxelDetails;
|
||||||
drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ELAPSED);
|
voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ELAPSED);
|
||||||
voxelStats << "Scene Send Time from Server: " << voxelDetails;
|
voxelStats << "Scene Send Time from Server: " << voxelDetails;
|
||||||
drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 290, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ENCODE);
|
voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ENCODE);
|
||||||
voxelStats << "Encode Time on Server: " << voxelDetails;
|
voxelStats << "Encode Time on Server: " << voxelDetails;
|
||||||
drawtext(10, statsVerticalOffset + 290, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_MODE);
|
voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_MODE);
|
||||||
voxelStats << "Sending Mode: " << voxelDetails;
|
voxelStats << "Sending Mode: " << voxelDetails;
|
||||||
drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
Node *avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
|
Node *avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
|
||||||
char avatarMixerStats[200];
|
char avatarMixerStats[200];
|
||||||
|
@ -2861,7 +2879,7 @@ void Application::displayStats() {
|
||||||
sprintf(avatarMixerStats, "No Avatar Mixer");
|
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||||
}
|
}
|
||||||
|
|
||||||
drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
drawtext(10, statsVerticalOffset + 350, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
||||||
drawtext(10, statsVerticalOffset + 450, 0.10f, 0, 1.0, 0, (char *)LeapManager::statusString().c_str());
|
drawtext(10, statsVerticalOffset + 450, 0.10f, 0, 1.0, 0, (char *)LeapManager::statusString().c_str());
|
||||||
|
|
||||||
if (_perfStatsOn) {
|
if (_perfStatsOn) {
|
||||||
|
@ -3414,6 +3432,11 @@ void Application::attachNewHeadToNode(Node* newNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::domainChanged(QString domain) {
|
||||||
|
qDebug("Application title set to: %s.\n", domain.toStdString().c_str());
|
||||||
|
_window->setWindowTitle(domain);
|
||||||
|
}
|
||||||
|
|
||||||
void Application::nodeAdded(Node* node) {
|
void Application::nodeAdded(Node* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ static const float NODE_KILLED_RED = 1.0f;
|
||||||
static const float NODE_KILLED_GREEN = 0.0f;
|
static const float NODE_KILLED_GREEN = 0.0f;
|
||||||
static const float NODE_KILLED_BLUE = 0.0f;
|
static const float NODE_KILLED_BLUE = 0.0f;
|
||||||
|
|
||||||
class Application : public QApplication, public NodeListHook, public PacketSenderNotify {
|
class Application : public QApplication, public NodeListHook, public PacketSenderNotify, public DomainChangeListener {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
friend class VoxelPacketProcessor;
|
friend class VoxelPacketProcessor;
|
||||||
|
@ -146,6 +146,8 @@ public:
|
||||||
virtual void nodeKilled(Node* node);
|
virtual void nodeKilled(Node* node);
|
||||||
virtual void packetSentNotification(ssize_t length);
|
virtual void packetSentNotification(ssize_t length);
|
||||||
|
|
||||||
|
virtual void domainChanged(QString domain);
|
||||||
|
|
||||||
VoxelShader& getVoxelShader() { return _voxelShader; }
|
VoxelShader& getVoxelShader() { return _voxelShader; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -254,9 +254,6 @@ Menu::Menu() :
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader, 0,
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader, 0,
|
||||||
false, this, SLOT(switchVoxelShader()));
|
false, this, SLOT(switchVoxelShader()));
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseByteNormals, 0,
|
|
||||||
false, Application::getInstance()->getVoxels(), SLOT(setUseByteNormals(bool)));
|
|
||||||
|
|
||||||
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true);
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true);
|
||||||
|
|
|
@ -205,6 +205,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,11 +33,13 @@
|
||||||
#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 };
|
|
||||||
|
|
||||||
GLbyte identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-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,
|
0,0,+1, 0,0,+1, 0,0,+1, 0,0,+1,
|
||||||
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,0,
|
0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0,
|
||||||
|
@ -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),
|
||||||
|
@ -76,8 +85,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
||||||
connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));
|
connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));
|
||||||
|
|
||||||
_useVoxelShader = false;
|
_useVoxelShader = false;
|
||||||
_useByteNormals = false;
|
|
||||||
|
|
||||||
_writeVoxelShaderData = NULL;
|
_writeVoxelShaderData = NULL;
|
||||||
_readVoxelShaderData = NULL;
|
_readVoxelShaderData = NULL;
|
||||||
|
|
||||||
|
@ -141,24 +149,11 @@ VoxelSystem::~VoxelSystem() {
|
||||||
VoxelNode::removeDeleteHook(this);
|
VoxelNode::removeDeleteHook(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::setUseByteNormals(bool useByteNormals) {
|
|
||||||
pthread_mutex_lock(&_bufferWriteLock);
|
|
||||||
bool wasInitialized = _initialized;
|
|
||||||
if (wasInitialized) {
|
|
||||||
cleanupVoxelMemory();
|
|
||||||
}
|
|
||||||
_useByteNormals = useByteNormals;
|
|
||||||
if (wasInitialized) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&_bufferWriteLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -166,12 +161,17 @@ void VoxelSystem::setMaxVoxels(int maxVoxels) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&_bufferWriteLock);
|
pthread_mutex_unlock(&_bufferWriteLock);
|
||||||
|
|
||||||
|
if (wasInitialized) {
|
||||||
|
forceRedrawEntireTree();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::setUseVoxelShader(bool useVoxelShader) {
|
void VoxelSystem::setUseVoxelShader(bool useVoxelShader) {
|
||||||
pthread_mutex_lock(&_bufferWriteLock);
|
pthread_mutex_lock(&_bufferWriteLock);
|
||||||
bool wasInitialized = _initialized;
|
bool wasInitialized = _initialized;
|
||||||
if (wasInitialized) {
|
if (wasInitialized) {
|
||||||
|
clearAllNodesBufferIndex();
|
||||||
cleanupVoxelMemory();
|
cleanupVoxelMemory();
|
||||||
}
|
}
|
||||||
_useVoxelShader = useVoxelShader;
|
_useVoxelShader = useVoxelShader;
|
||||||
|
@ -179,6 +179,10 @@ void VoxelSystem::setUseVoxelShader(bool useVoxelShader) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&_bufferWriteLock);
|
pthread_mutex_unlock(&_bufferWriteLock);
|
||||||
|
|
||||||
|
if (wasInitialized) {
|
||||||
|
forceRedrawEntireTree();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::cleanupVoxelMemory() {
|
void VoxelSystem::cleanupVoxelMemory() {
|
||||||
|
@ -193,22 +197,58 @@ 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);
|
|
||||||
|
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;
|
||||||
delete[] _readColorsArray;
|
delete[] _readColorsArray;
|
||||||
delete[] _writeColorsArray;
|
delete[] _writeColorsArray;
|
||||||
delete[] _writeVoxelDirtyArray;
|
|
||||||
delete[] _readVoxelDirtyArray;
|
|
||||||
}
|
}
|
||||||
|
delete[] _writeVoxelDirtyArray;
|
||||||
|
delete[] _readVoxelDirtyArray;
|
||||||
}
|
}
|
||||||
_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();
|
||||||
|
_memoryUsageRAM = 0;
|
||||||
|
_memoryUsageVBO = 0; // our VBO allocations as we know them
|
||||||
if (_useVoxelShader) {
|
if (_useVoxelShader) {
|
||||||
qDebug("Using Voxel Shader...\n");
|
qDebug("Using Voxel Shader...\n");
|
||||||
GLuint* indicesArray = new GLuint[_maxVoxels];
|
GLuint* indicesArray = new GLuint[_maxVoxels];
|
||||||
|
@ -222,12 +262,13 @@ void VoxelSystem::initVoxelMemory() {
|
||||||
// bind the indices VBO to the actual indices array
|
// bind the indices VBO to the actual indices array
|
||||||
glGenBuffers(1, &_vboVoxelsIndicesID);
|
glGenBuffers(1, &_vboVoxelsIndicesID);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _maxVoxels, indicesArray, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * _maxVoxels, indicesArray, GL_STATIC_DRAW);
|
||||||
|
_memoryUsageVBO += sizeof(GLuint) * _maxVoxels;
|
||||||
|
|
||||||
glGenBuffers(1, &_vboVoxelsID);
|
glGenBuffers(1, &_vboVoxelsID);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);
|
||||||
glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW);
|
||||||
|
_memoryUsageVBO += _maxVoxels * sizeof(VoxelShaderVBOData);
|
||||||
|
|
||||||
// delete the indices and normals arrays that are no longer needed
|
// delete the indices and normals arrays that are no longer needed
|
||||||
delete[] indicesArray;
|
delete[] indicesArray;
|
||||||
|
@ -235,106 +276,62 @@ void VoxelSystem::initVoxelMemory() {
|
||||||
// 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];
|
||||||
memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
||||||
|
_memoryUsageRAM += (_maxVoxels * sizeof(bool));
|
||||||
|
|
||||||
_readVoxelDirtyArray = new bool[_maxVoxels];
|
_readVoxelDirtyArray = new bool[_maxVoxels];
|
||||||
memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
||||||
|
_memoryUsageRAM += (_maxVoxels * sizeof(bool));
|
||||||
|
|
||||||
// prep the data structures for incoming voxel data
|
// prep the data structures for incoming voxel data
|
||||||
_writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
_writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
||||||
|
_memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);
|
||||||
|
|
||||||
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
||||||
|
_memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);
|
||||||
} else {
|
} 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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// delete the indices and normals arrays that are no longer needed
|
|
||||||
delete[] normalsArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Depending on if we're using per vertex normals, we will need more or less vertex points per voxel
|
||||||
|
int vertexPointsPerVoxel = GLOBAL_NORMALS_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 += 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 += 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);
|
|
||||||
|
|
||||||
// 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];
|
||||||
memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
||||||
|
_memoryUsageRAM += (sizeof(bool) * _maxVoxels);
|
||||||
|
|
||||||
_readVoxelDirtyArray = new bool[_maxVoxels];
|
_readVoxelDirtyArray = new bool[_maxVoxels];
|
||||||
memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
||||||
|
_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];
|
||||||
_readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
_memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels);
|
||||||
|
_readVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels];
|
||||||
|
_memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels);
|
||||||
|
|
||||||
_writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
_writeColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels];
|
||||||
_readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _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
|
// create our simple fragment shader if we're the first system to init
|
||||||
|
@ -614,16 +611,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 = GLOBAL_NORMALS_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -750,20 +750,25 @@ void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& s
|
||||||
float voxelScale, const nodeColor& color) {
|
float voxelScale, const nodeColor& color) {
|
||||||
|
|
||||||
if (_useVoxelShader) {
|
if (_useVoxelShader) {
|
||||||
VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];
|
if (_writeVoxelShaderData) {
|
||||||
writeVerticesAt->x = startVertex.x * TREE_SCALE;
|
VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];
|
||||||
writeVerticesAt->y = startVertex.y * TREE_SCALE;
|
writeVerticesAt->x = startVertex.x * TREE_SCALE;
|
||||||
writeVerticesAt->z = startVertex.z * TREE_SCALE;
|
writeVerticesAt->y = startVertex.y * TREE_SCALE;
|
||||||
writeVerticesAt->s = voxelScale * TREE_SCALE;
|
writeVerticesAt->z = startVertex.z * TREE_SCALE;
|
||||||
writeVerticesAt->r = color[RED_INDEX];
|
writeVerticesAt->s = voxelScale * TREE_SCALE;
|
||||||
writeVerticesAt->g = color[GREEN_INDEX];
|
writeVerticesAt->r = color[RED_INDEX];
|
||||||
writeVerticesAt->b = color[BLUE_INDEX];
|
writeVerticesAt->g = color[GREEN_INDEX];
|
||||||
|
writeVerticesAt->b = color[BLUE_INDEX];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
|
if (_writeVerticesArray && _writeColorsArray) {
|
||||||
GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
|
int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL;
|
||||||
GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
|
for (int j = 0; j < vertexPointsPerVoxel; j++ ) {
|
||||||
*(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale);
|
GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel);
|
||||||
*(writeColorsAt +j) = color[j % 3];
|
GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * vertexPointsPerVoxel);
|
||||||
|
*(writeVerticesAt+j) = startVertex[j % 3] + (identityVerticesGlobalNormals[j] * voxelScale);
|
||||||
|
*(writeColorsAt +j) = color[j % 3];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -873,15 +878,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 = GLOBAL_NORMALS_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);
|
||||||
}
|
}
|
||||||
|
@ -927,15 +933,11 @@ 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);
|
||||||
|
|
||||||
|
@ -944,10 +946,38 @@ void VoxelSystem::render(bool 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
|
// draw voxels in 6 passes
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
|
||||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1,
|
glNormal3f(0,1.0f,0);
|
||||||
36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 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);
|
||||||
|
|
||||||
|
@ -955,7 +985,6 @@ 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);
|
||||||
|
|
||||||
// bind with 0 to switch back to normal operation
|
// bind with 0 to switch back to normal operation
|
||||||
|
@ -995,6 +1024,34 @@ void VoxelSystem::killLocalVoxels() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool VoxelSystem::clearAllNodesBufferIndexOperation(VoxelNode* node, void* extraData) {
|
||||||
|
_nodeCount++;
|
||||||
|
node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::clearAllNodesBufferIndex() {
|
||||||
|
_nodeCount = 0;
|
||||||
|
_tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation);
|
||||||
|
qDebug("clearing buffer index of %d nodes\n", _nodeCount);
|
||||||
|
_tree->setDirtyBit();
|
||||||
|
setupNewVoxelsForDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelSystem::forceRedrawEntireTreeOperation(VoxelNode* node, void* extraData) {
|
||||||
|
_nodeCount++;
|
||||||
|
node->setDirtyBit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::forceRedrawEntireTree() {
|
||||||
|
_nodeCount = 0;
|
||||||
|
_tree->recurseTreeWithOperation(forceRedrawEntireTreeOperation);
|
||||||
|
qDebug("forcing redraw of %d nodes\n", _nodeCount);
|
||||||
|
_tree->setDirtyBit();
|
||||||
|
setupNewVoxelsForDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) {
|
bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) {
|
||||||
_nodeCount++;
|
_nodeCount++;
|
||||||
if (node->isColored()) {
|
if (node->isColored()) {
|
||||||
|
@ -1852,3 +1909,58 @@ void VoxelSystem::nodeKilled(Node* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long VoxelSystem::getFreeMemoryGPU() {
|
||||||
|
// We can't ask all GPUs how much memory they have in use, but we can ask them about how much is free.
|
||||||
|
// So, we can record the free memory before we create our VBOs and the free memory after, and get a basic
|
||||||
|
// idea how how much we're using.
|
||||||
|
|
||||||
|
_hasMemoryUsageGPU = false; // assume the worst
|
||||||
|
unsigned long freeMemory = 0;
|
||||||
|
const int NUM_RESULTS = 4; // see notes, these APIs return up to 4 results
|
||||||
|
GLint results[NUM_RESULTS] = { 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// ATI
|
||||||
|
// http://www.opengl.org/registry/specs/ATI/meminfo.txt
|
||||||
|
//
|
||||||
|
// TEXTURE_FREE_MEMORY_ATI 0x87FC
|
||||||
|
// RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
|
||||||
|
const GLenum VBO_FREE_MEMORY_ATI = 0x87FB;
|
||||||
|
glGetIntegerv(VBO_FREE_MEMORY_ATI, &results[0]);
|
||||||
|
GLenum errorATI = glGetError();
|
||||||
|
|
||||||
|
if (errorATI == GL_NO_ERROR) {
|
||||||
|
_hasMemoryUsageGPU = true;
|
||||||
|
freeMemory = results[0];
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// NVIDIA
|
||||||
|
// http://developer.download.nvidia.com/opengl/specs/GL_NVX_gpu_memory_info.txt
|
||||||
|
//
|
||||||
|
//const GLenum GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX = 0x9047;
|
||||||
|
//const GLenum GPU_MEMORY_INFO_EVICTION_COUNT_NVX = 0x904A;
|
||||||
|
//const GLenum GPU_MEMORY_INFO_EVICTED_MEMORY_NVX = 0x904B;
|
||||||
|
//const GLenum GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048;
|
||||||
|
|
||||||
|
const GLenum GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049;
|
||||||
|
results[0] = 0;
|
||||||
|
glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &results[0]);
|
||||||
|
freeMemory += results[0];
|
||||||
|
GLenum errorNVIDIA = glGetError();
|
||||||
|
|
||||||
|
if (errorNVIDIA == GL_NO_ERROR) {
|
||||||
|
_hasMemoryUsageGPU = true;
|
||||||
|
freeMemory = results[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned long BYTES_PER_KBYTE = 1024;
|
||||||
|
return freeMemory * BYTES_PER_KBYTE; // API results in KB, we want it in bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long VoxelSystem::getVoxelMemoryUsageGPU() {
|
||||||
|
unsigned long currentFreeMemory = getFreeMemoryGPU();
|
||||||
|
return (_initialMemoryUsageGPU - currentFreeMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,10 @@ public:
|
||||||
|
|
||||||
void setMaxVoxels(int maxVoxels);
|
void setMaxVoxels(int maxVoxels);
|
||||||
long int getMaxVoxels() const { return _maxVoxels; }
|
long int getMaxVoxels() const { return _maxVoxels; }
|
||||||
|
unsigned long getVoxelMemoryUsageRAM() const { return _memoryUsageRAM; }
|
||||||
|
unsigned long getVoxelMemoryUsageVBO() const { return _memoryUsageVBO; }
|
||||||
|
bool hasVoxelMemoryUsageGPU() const { return _hasMemoryUsageGPU; }
|
||||||
|
unsigned long getVoxelMemoryUsageGPU();
|
||||||
long int getVoxelsCreated();
|
long int getVoxelsCreated();
|
||||||
long int getVoxelsColored();
|
long int getVoxelsColored();
|
||||||
long int getVoxelsBytesRead();
|
long int getVoxelsBytesRead();
|
||||||
|
@ -126,9 +130,10 @@ public slots:
|
||||||
void falseColorizeOccluded();
|
void falseColorizeOccluded();
|
||||||
void falseColorizeOccludedV2();
|
void falseColorizeOccludedV2();
|
||||||
void falseColorizeBySource();
|
void falseColorizeBySource();
|
||||||
|
void forceRedrawEntireTree();
|
||||||
|
void clearAllNodesBufferIndex();
|
||||||
|
|
||||||
void cancelImport();
|
void cancelImport();
|
||||||
void setUseByteNormals(bool useByteNormals);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float _treeScale;
|
float _treeScale;
|
||||||
|
@ -172,6 +177,8 @@ private:
|
||||||
static bool falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData);
|
static bool falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData);
|
||||||
static bool falseColorizeBySourceOperation(VoxelNode* node, void* extraData);
|
static bool falseColorizeBySourceOperation(VoxelNode* node, void* extraData);
|
||||||
static bool killSourceVoxelsOperation(VoxelNode* node, void* extraData);
|
static bool killSourceVoxelsOperation(VoxelNode* node, void* extraData);
|
||||||
|
static bool forceRedrawEntireTreeOperation(VoxelNode* node, void* extraData);
|
||||||
|
static bool clearAllNodesBufferIndexOperation(VoxelNode* node, void* extraData);
|
||||||
|
|
||||||
int updateNodeInArraysAsFullVBO(VoxelNode* node);
|
int updateNodeInArraysAsFullVBO(VoxelNode* node);
|
||||||
int updateNodeInArraysAsPartialVBO(VoxelNode* node);
|
int updateNodeInArraysAsPartialVBO(VoxelNode* node);
|
||||||
|
@ -181,6 +188,8 @@ private:
|
||||||
|
|
||||||
void updateVBOs();
|
void updateVBOs();
|
||||||
|
|
||||||
|
unsigned long getFreeMemoryGPU();
|
||||||
|
|
||||||
// these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here
|
// these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here
|
||||||
static float _maxDistance;
|
static float _maxDistance;
|
||||||
static float _minDistance;
|
static float _minDistance;
|
||||||
|
@ -207,8 +216,6 @@ private:
|
||||||
void initVoxelMemory();
|
void initVoxelMemory();
|
||||||
void cleanupVoxelMemory();
|
void cleanupVoxelMemory();
|
||||||
|
|
||||||
bool _useByteNormals;
|
|
||||||
|
|
||||||
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
|
||||||
GLuint _vboVoxelsIndicesID; /// when using voxel shader, we'll use this VBO for our indexes
|
GLuint _vboVoxelsIndicesID; /// when using voxel shader, we'll use this VBO for our indexes
|
||||||
|
@ -216,9 +223,15 @@ private:
|
||||||
VoxelShaderVBOData* _readVoxelShaderData;
|
VoxelShaderVBOData* _readVoxelShaderData;
|
||||||
|
|
||||||
GLuint _vboVerticesID;
|
GLuint _vboVerticesID;
|
||||||
GLuint _vboNormalsID;
|
|
||||||
GLuint _vboColorsID;
|
GLuint _vboColorsID;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -226,6 +239,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();
|
||||||
|
|
||||||
|
@ -249,6 +264,10 @@ private:
|
||||||
int _dataSourceID;
|
int _dataSourceID;
|
||||||
|
|
||||||
int _voxelServerCount;
|
int _voxelServerCount;
|
||||||
|
unsigned long _memoryUsageRAM;
|
||||||
|
unsigned long _memoryUsageVBO;
|
||||||
|
unsigned long _initialMemoryUsageGPU;
|
||||||
|
bool _hasMemoryUsageGPU;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -50,7 +50,9 @@ MyAvatar::MyAvatar(Node* owningNode) :
|
||||||
_lastCollisionPosition(0, 0, 0),
|
_lastCollisionPosition(0, 0, 0),
|
||||||
_speedBrakes(false),
|
_speedBrakes(false),
|
||||||
_isThrustOn(false),
|
_isThrustOn(false),
|
||||||
_thrustMultiplier(1.0f)
|
_thrustMultiplier(1.0f),
|
||||||
|
_moveTarget(0,0,0),
|
||||||
|
_moveTargetStepCounter(0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
|
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
|
||||||
_driveKeys[i] = false;
|
_driveKeys[i] = false;
|
||||||
|
@ -64,6 +66,11 @@ void MyAvatar::reset() {
|
||||||
_hand.reset();
|
_hand.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) {
|
||||||
|
_moveTarget = moveTarget;
|
||||||
|
_moveTargetStepCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
|
void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
|
|
||||||
glm::quat orientation = getOrientation();
|
glm::quat orientation = getOrientation();
|
||||||
|
@ -165,8 +172,10 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
if (glm::length(_position - _lastCollisionPosition) > MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY) {
|
if (glm::length(_position - _lastCollisionPosition) > MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY) {
|
||||||
_velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime);
|
_velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only collide if we are not moving to a target
|
||||||
|
if (_isCollisionsOn && (glm::length(_moveTarget) < EPSILON)) {
|
||||||
|
|
||||||
if (_isCollisionsOn) {
|
|
||||||
Camera* myCamera = Application::getInstance()->getCamera();
|
Camera* myCamera = Application::getInstance()->getCamera();
|
||||||
|
|
||||||
if (myCamera->getMode() == CAMERA_MODE_FIRST_PERSON && !OculusManager::isConnected()) {
|
if (myCamera->getMode() == CAMERA_MODE_FIRST_PERSON && !OculusManager::isConnected()) {
|
||||||
|
@ -211,7 +220,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
// Damp avatar velocity
|
// Damp avatar velocity
|
||||||
const float LINEAR_DAMPING_STRENGTH = 0.5f;
|
const float LINEAR_DAMPING_STRENGTH = 0.5f;
|
||||||
const float SPEED_BRAKE_POWER = _scale * 10.0f;
|
const float SPEED_BRAKE_POWER = _scale * 10.0f;
|
||||||
const float SQUARED_DAMPING_STRENGTH = 0.0f;
|
const float SQUARED_DAMPING_STRENGTH = 0.007f;
|
||||||
|
|
||||||
float linearDamping = LINEAR_DAMPING_STRENGTH;
|
float linearDamping = LINEAR_DAMPING_STRENGTH;
|
||||||
const float AVATAR_DAMPING_FACTOR = 120.f;
|
const float AVATAR_DAMPING_FACTOR = 120.f;
|
||||||
|
@ -225,12 +234,15 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pitch and roll the body as a function of forward speed and turning delta
|
// pitch and roll the body as a function of forward speed and turning delta
|
||||||
const float BODY_PITCH_WHILE_WALKING = -20.0;
|
const float HIGH_VELOCITY = 10.f;
|
||||||
const float BODY_ROLL_WHILE_TURNING = 0.2;
|
if (glm::length(_velocity) < HIGH_VELOCITY) {
|
||||||
float forwardComponentOfVelocity = glm::dot(getBodyFrontDirection(), _velocity);
|
const float BODY_PITCH_WHILE_WALKING = -20.0;
|
||||||
orientation = orientation * glm::quat(glm::radians(glm::vec3(
|
const float BODY_ROLL_WHILE_TURNING = 0.2;
|
||||||
BODY_PITCH_WHILE_WALKING * deltaTime * forwardComponentOfVelocity, 0.0f,
|
float forwardComponentOfVelocity = glm::dot(getBodyFrontDirection(), _velocity);
|
||||||
BODY_ROLL_WHILE_TURNING * deltaTime * _speed * _bodyYawDelta)));
|
orientation = orientation * glm::quat(glm::radians(glm::vec3(
|
||||||
|
BODY_PITCH_WHILE_WALKING * deltaTime * forwardComponentOfVelocity, 0.0f,
|
||||||
|
BODY_ROLL_WHILE_TURNING * deltaTime * _speed * _bodyYawDelta)));
|
||||||
|
}
|
||||||
|
|
||||||
// these forces keep the body upright...
|
// these forces keep the body upright...
|
||||||
const float BODY_UPRIGHT_FORCE = _scale * 10.0;
|
const float BODY_UPRIGHT_FORCE = _scale * 10.0;
|
||||||
|
@ -321,7 +333,21 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
const float MOVING_SPEED_THRESHOLD = 0.01f;
|
const float MOVING_SPEED_THRESHOLD = 0.01f;
|
||||||
_moving = _speed > MOVING_SPEED_THRESHOLD;
|
_moving = _speed > MOVING_SPEED_THRESHOLD;
|
||||||
|
|
||||||
// update position by velocity, and subtract the change added earlier for gravity
|
// If a move target is set, update position explicitly
|
||||||
|
const float MOVE_FINISHED_TOLERANCE = 0.1f;
|
||||||
|
const float MOVE_SPEED_FACTOR = 2.f;
|
||||||
|
const int MOVE_TARGET_MAX_STEPS = 250;
|
||||||
|
if ((glm::length(_moveTarget) > EPSILON) && (_moveTargetStepCounter < MOVE_TARGET_MAX_STEPS)) {
|
||||||
|
if (glm::length(_position - _moveTarget) > MOVE_FINISHED_TOLERANCE) {
|
||||||
|
_position += (_moveTarget - _position) * (deltaTime * MOVE_SPEED_FACTOR);
|
||||||
|
_moveTargetStepCounter++;
|
||||||
|
} else {
|
||||||
|
// Move completed
|
||||||
|
_moveTarget = glm::vec3(0,0,0);
|
||||||
|
_moveTargetStepCounter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_position += _velocity * deltaTime;
|
_position += _velocity * deltaTime;
|
||||||
|
|
||||||
// Zero thrust out now that we've added it to velocity in this frame
|
// Zero thrust out now that we've added it to velocity in this frame
|
||||||
|
@ -648,8 +674,12 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) {
|
||||||
|
|
||||||
// If thrust keys are being held down, slowly increase thrust to allow reaching great speeds
|
// If thrust keys are being held down, slowly increase thrust to allow reaching great speeds
|
||||||
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
|
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
|
||||||
const float THRUST_INCREASE_RATE = 1.0;
|
const float THRUST_INCREASE_RATE = 1.05;
|
||||||
_thrustMultiplier *= 1.f + deltaTime * THRUST_INCREASE_RATE;
|
const float MAX_THRUST_MULTIPLIER = 75.0;
|
||||||
|
//printf("m = %.3f\n", _thrustMultiplier);
|
||||||
|
if (_thrustMultiplier < MAX_THRUST_MULTIPLIER) {
|
||||||
|
_thrustMultiplier *= 1.f + deltaTime * THRUST_INCREASE_RATE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_thrustMultiplier = 1.f;
|
_thrustMultiplier = 1.f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
void setOrientation(const glm::quat& orientation);
|
void setOrientation(const glm::quat& orientation);
|
||||||
void setNewScale(const float scale);
|
void setNewScale(const float scale);
|
||||||
void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; }
|
void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; }
|
||||||
|
void setMoveTarget(const glm::vec3 moveTarget);
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
float getNewScale() const { return _newScale; }
|
float getNewScale() const { return _newScale; }
|
||||||
|
@ -73,6 +74,8 @@ public:
|
||||||
bool _isThrustOn;
|
bool _isThrustOn;
|
||||||
float _thrustMultiplier;
|
float _thrustMultiplier;
|
||||||
float _collisionRadius;
|
float _collisionRadius;
|
||||||
|
glm::vec3 _moveTarget;
|
||||||
|
int _moveTargetStepCounter;
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
float getBallRenderAlpha(int ball, bool lookingInMirror) const;
|
float getBallRenderAlpha(int ball, bool lookingInMirror) const;
|
||||||
|
|
|
@ -109,6 +109,7 @@ void NodeList::setDomainHostname(const QString& domainHostname) {
|
||||||
|
|
||||||
// reset our _domainIP to the null address so that a lookup happens on next check in
|
// reset our _domainIP to the null address so that a lookup happens on next check in
|
||||||
_domainIP.clear();
|
_domainIP.clear();
|
||||||
|
notifyDomainChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
|
void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
|
||||||
|
@ -585,6 +586,7 @@ void NodeList::loadData(QSettings *settings) {
|
||||||
|
|
||||||
if (domainServerHostname.size() > 0) {
|
if (domainServerHostname.size() > 0) {
|
||||||
_domainHostname = domainServerHostname;
|
_domainHostname = domainServerHostname;
|
||||||
|
notifyDomainChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
|
@ -678,6 +680,21 @@ void NodeListIterator::skipDeadAndStopIncrement() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeList::addDomainListener(DomainChangeListener* listener) {
|
||||||
|
_domainListeners.push_back(listener);
|
||||||
|
QString domain = _domainHostname.isEmpty() ? _domainIP.toString() : _domainHostname;
|
||||||
|
listener->domainChanged(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeList::removeDomainListener(DomainChangeListener* listener) {
|
||||||
|
for (int i = 0; i < _domainListeners.size(); i++) {
|
||||||
|
if (_domainListeners[i] == listener) {
|
||||||
|
_domainListeners.erase(_domainListeners.begin() + i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NodeList::addHook(NodeListHook* hook) {
|
void NodeList::addHook(NodeListHook* hook) {
|
||||||
_hooks.push_back(hook);
|
_hooks.push_back(hook);
|
||||||
}
|
}
|
||||||
|
@ -704,3 +721,9 @@ void NodeList::notifyHooksOfKilledNode(Node* node) {
|
||||||
_hooks[i]->nodeKilled(node);
|
_hooks[i]->nodeKilled(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeList::notifyDomainChanged() {
|
||||||
|
for (int i = 0; i < _domainListeners.size(); i++) {
|
||||||
|
_domainListeners[i]->domainChanged(_domainHostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,10 @@ public:
|
||||||
virtual void nodeKilled(Node* node) = 0;
|
virtual void nodeKilled(Node* node) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DomainChangeListener {
|
||||||
|
public:
|
||||||
|
virtual void domainChanged(QString domain) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class NodeList {
|
class NodeList {
|
||||||
public:
|
public:
|
||||||
|
@ -136,6 +140,9 @@ public:
|
||||||
void notifyHooksOfAddedNode(Node* node);
|
void notifyHooksOfAddedNode(Node* node);
|
||||||
void notifyHooksOfKilledNode(Node* node);
|
void notifyHooksOfKilledNode(Node* node);
|
||||||
|
|
||||||
|
void addDomainListener(DomainChangeListener* listener);
|
||||||
|
void removeDomainListener(DomainChangeListener* listener);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static NodeList* _sharedInstance;
|
static NodeList* _sharedInstance;
|
||||||
|
|
||||||
|
@ -167,6 +174,11 @@ private:
|
||||||
void timePingReply(sockaddr *nodeAddress, unsigned char *packetData);
|
void timePingReply(sockaddr *nodeAddress, unsigned char *packetData);
|
||||||
|
|
||||||
std::vector<NodeListHook*> _hooks;
|
std::vector<NodeListHook*> _hooks;
|
||||||
|
std::vector<DomainChangeListener*> _domainListeners;
|
||||||
|
|
||||||
|
void resetDomainData(char domainField[], const char* domainData);
|
||||||
|
void notifyDomainChanged();
|
||||||
|
void domainLookup();
|
||||||
};
|
};
|
||||||
|
|
||||||
class NodeListIterator : public std::iterator<std::input_iterator_tag, Node> {
|
class NodeListIterator : public std::iterator<std::input_iterator_tag, Node> {
|
||||||
|
|
|
@ -443,7 +443,7 @@ void ViewFrustum::printDebugDetails() const {
|
||||||
|
|
||||||
glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const {
|
glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const {
|
||||||
|
|
||||||
glm::vec4 pointVec4 = glm::vec4(point,1) ;
|
glm::vec4 pointVec4 = glm::vec4(point,1);
|
||||||
glm::vec4 projectedPointVec4 = _ourModelViewProjectionMatrix * pointVec4;
|
glm::vec4 projectedPointVec4 = _ourModelViewProjectionMatrix * pointVec4;
|
||||||
pointInView = (projectedPointVec4.w > 0); // math! If the w result is negative then the point is behind the viewer
|
pointInView = (projectedPointVec4.w > 0); // math! If the w result is negative then the point is behind the viewer
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ public:
|
||||||
void printDebugDetails(const char* label) const;
|
void printDebugDetails(const char* label) const;
|
||||||
bool isDirty() const { return _isDirty; }
|
bool isDirty() const { return _isDirty; }
|
||||||
void clearDirtyBit() { _isDirty = false; }
|
void clearDirtyBit() { _isDirty = false; }
|
||||||
|
void setDirtyBit() { _isDirty = true; }
|
||||||
bool hasChangedSince(uint64_t time) const { return (_lastChanged > time); }
|
bool hasChangedSince(uint64_t time) const { return (_lastChanged > time); }
|
||||||
void markWithChangedTime() { _lastChanged = usecTimestampNow(); }
|
void markWithChangedTime() { _lastChanged = usecTimestampNow(); }
|
||||||
uint64_t getLastChanged() const { return _lastChanged; }
|
uint64_t getLastChanged() const { return _lastChanged; }
|
||||||
|
|
Loading…
Reference in a new issue