From a362fdc2ed37da917b759297b2181f9dff83af8a Mon Sep 17 00:00:00 2001 From: stojce Date: Tue, 10 Sep 2013 21:51:50 +0200 Subject: [PATCH 01/28] name the current domain server --- interface/src/Application.cpp | 8 ++- interface/src/Application.h | 4 +- libraries/shared/src/NodeList.cpp | 92 ++++++++++++++++++++++--------- libraries/shared/src/NodeList.h | 12 ++++ 4 files changed, 87 insertions(+), 29 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7989d8b715..089b1cd9fb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -147,6 +147,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : NodeList::getInstance()->addHook(&_voxels); NodeList::getInstance()->addHook(this); + NodeList::getInstance()->addDomainListener(this); // network receive thread and voxel parsing thread are both controlled by the --nonblocking command line @@ -236,6 +237,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : Application::~Application() { NodeList::getInstance()->removeHook(&_voxels); NodeList::getInstance()->removeHook(this); + NodeList::getInstance()->removeDomainListener(this); _sharedVoxelSystem.changeTree(new VoxelTree); @@ -314,8 +316,6 @@ void Application::initializeGL() { char title[50]; sprintf(title, "Interface: %4.2f seconds\n", startupTime); qDebug("%s", title); - _window->setWindowTitle(title); - const char LOGSTASH_INTERFACE_START_TIME_KEY[] = "interface-start-time"; // ask the Logstash class to record the startup time @@ -3235,6 +3235,10 @@ void Application::attachNewHeadToNode(Node* newNode) { } } +void Application::domainChanged(QString domain) { + _window->setWindowTitle(domain); +} + void Application::nodeAdded(Node* node) { } diff --git a/interface/src/Application.h b/interface/src/Application.h index 6c9f2cf66d..7a21c3ca51 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -76,7 +76,7 @@ static const float NODE_KILLED_RED = 1.0f; static const float NODE_KILLED_GREEN = 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 friend class VoxelPacketProcessor; @@ -142,6 +142,8 @@ public: virtual void nodeAdded(Node* node); virtual void nodeKilled(Node* node); virtual void packetSentNotification(ssize_t length); + + virtual void domainChanged(QString domain); public slots: void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index a982e22242..290b8ffb18 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -82,22 +82,20 @@ NodeList::~NodeList() { stopSilentNodeRemovalThread(); } -void NodeList::setDomainHostname(const char* domainHostname) { - memset(_domainHostname, 0, sizeof(_domainHostname)); - memcpy(_domainHostname, domainHostname, strlen(domainHostname)); - +void NodeList::setDomainHostname(const char* domainHostname) { // reset the domain IP so the hostname is checked again - setDomainIP(""); + resetDomainData(_domainHostname, domainHostname); } void NodeList::setDomainIP(const char* domainIP) { - memset(_domainIP, 0, sizeof(_domainIP)); - memcpy(_domainIP, domainIP, strlen(domainIP)); + resetDomainData(_domainIP, domainIP); } void NodeList::setDomainIPToLocalhost() { int ip = getLocalAddress(); - sprintf(_domainIP, "%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); + char _localIP[INET_ADDRSTRLEN]; + sprintf(_localIP, "%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); + setDomainIP(_localIP); } void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) { @@ -269,25 +267,8 @@ void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNo } void NodeList::sendDomainServerCheckIn() { - static bool printedDomainServerIP = false; - - // Lookup the IP address of the domain server if we need to - if (atoi(_domainIP) == 0) { - printf("Looking up %s\n", _domainHostname); - struct hostent* pHostInfo; - if ((pHostInfo = gethostbyname(_domainHostname)) != NULL) { - sockaddr_in tempAddress; - memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); - strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr)); - qDebug("Domain Server: %s\n", _domainHostname); - } else { - qDebug("Failed domain server lookup\n"); - } - } else if (!printedDomainServerIP) { - qDebug("Domain Server IP: %s\n", _domainIP); - printedDomainServerIP = true; - } + domainLookup(); static unsigned char* checkInPacket = NULL; static int checkInPacketSize = 0; @@ -650,6 +631,21 @@ void NodeListIterator::skipDeadAndStopIncrement() { } } +void NodeList::addDomainListener(DomainChangeListener* listener) { + _domainListeners.push_back(listener); + QString domain = (strlen(_domainHostname) > 0) ? _domainHostname : _domainIP; + 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) { _hooks.push_back(hook); } @@ -676,3 +672,47 @@ void NodeList::notifyHooksOfKilledNode(Node* node) { _hooks[i]->nodeKilled(node); } } + +void NodeList::notifyDomainChanged() { + QString domain = (strlen(_domainHostname) > 0) ? _domainHostname : _domainIP; + for (int i = 0; i < _domainListeners.size(); i++) { + _domainListeners[i]->domainChanged(domain); + } +} + +void NodeList::resetDomainData(char domainField[], const char* domainValue) { + memset(_domainHostname, 0, sizeof(_domainHostname)); + memcpy(_domainHostname, "", strlen("")); + + memset(_domainIP, 0, sizeof(_domainIP)); + memcpy(_domainIP, "", strlen("")); + + memset(domainField, 0, sizeof(&domainField)); + memcpy(domainField, domainValue, strlen(domainValue)); + + domainLookup(); + notifyDomainChanged(); +} + +void NodeList::domainLookup() { + static bool printedDomainServerIP = false; + + // Lookup the IP address of the domain server if we need to + if (atoi(_domainIP) == 0) { + printf("Looking up %s\n", _domainHostname); + struct hostent* pHostInfo; + if ((pHostInfo = gethostbyname(_domainHostname)) != NULL) { + sockaddr_in tempAddress; + memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); + strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr)); + + qDebug("Domain Server: %s\n", _domainHostname); + } else { + qDebug("Failed domain server lookup\n"); + } + } else if (!printedDomainServerIP) { + notifyDomainChanged(); + qDebug("Domain Server IP: %s\n", _domainIP); + printedDomainServerIP = true; + } +} diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index ea94e8c080..e7d08ddda5 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -54,6 +54,10 @@ public: virtual void nodeKilled(Node* node) = 0; }; +class DomainChangeListener { +public: + virtual void domainChanged(QString domain) = 0; +}; class NodeList { public: @@ -130,6 +134,9 @@ public: void notifyHooksOfAddedNode(Node* node); void notifyHooksOfKilledNode(Node* node); + void addDomainListener(DomainChangeListener* listener); + void removeDomainListener(DomainChangeListener* listener); + private: static NodeList* _sharedInstance; @@ -158,6 +165,11 @@ private: void timePingReply(sockaddr *nodeAddress, unsigned char *packetData); std::vector _hooks; + std::vector _domainListeners; + + void resetDomainData(char domainField[], const char* domainData); + void notifyDomainChanged(); + void domainLookup(); }; class NodeListIterator : public std::iterator { From 3d4341cee4f516da745a5e63e3c761c8b4cc4c6a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Sep 2013 15:18:45 -0700 Subject: [PATCH 02/28] hacking on voxel geometry shader --- .../resources/shaders/duplicate_geometry.geom | 46 ++++++ interface/resources/shaders/passthrough.geom | 150 ++++++++++++++++++ interface/resources/shaders/passthrough.vert | 6 + interface/src/Application.cpp | 4 + interface/src/Application.h | 2 + interface/src/renderer/TestGeometry.cpp | 65 ++++++++ interface/src/renderer/TestGeometry.h | 44 +++++ libraries/voxels/src/VoxelConstants.h | 6 +- 8 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 interface/resources/shaders/duplicate_geometry.geom create mode 100644 interface/resources/shaders/passthrough.geom create mode 100644 interface/resources/shaders/passthrough.vert create mode 100644 interface/src/renderer/TestGeometry.cpp create mode 100644 interface/src/renderer/TestGeometry.h diff --git a/interface/resources/shaders/duplicate_geometry.geom b/interface/resources/shaders/duplicate_geometry.geom new file mode 100644 index 0000000000..2ab92fc4e3 --- /dev/null +++ b/interface/resources/shaders/duplicate_geometry.geom @@ -0,0 +1,46 @@ +#version 420 + +layout(triangles) in; +layout (triangle_strip, max_vertices=6) out; + +layout (std140) uniform Matrices { + mat4 projModelViewMatrix; + mat3 normalMatrix; +}; + +in VertexData { + vec2 texCoord; + vec3 normal; +} VertexIn[]; + +out VertexData { + vec2 texCoord; + vec3 normal; +} VertexOut; + +void main() +{ + for(int i = 0; i < gl_in.length(); i++) + { + // copy attributes + gl_Position = projModelViewMatrix * gl_in[i].gl_Position; + VertexOut.normal = normalize(normalMatrix * VertexIn[i].normal); + VertexOut.texCoord = VertexIn[i].texCoord; + + // done with the vertex + EmitVertex(); + } + EndPrimitive(); + + for(int i = 0; i < gl_in.length(); i++) + { + // copy attributes and displace copy + gl_Position = projModelViewMatrix * (gl_in[i].gl_Position + vec4(20.0, 0.0, 0.0, 0.0)); + VertexOut.normal = normalize(normalMatrix * VertexIn[i].normal); + VertexOut.texCoord = VertexIn[i].texCoord; + + // done with the vertex + EmitVertex(); + } + EndPrimitive(); +} diff --git a/interface/resources/shaders/passthrough.geom b/interface/resources/shaders/passthrough.geom new file mode 100644 index 0000000000..1ce193cda9 --- /dev/null +++ b/interface/resources/shaders/passthrough.geom @@ -0,0 +1,150 @@ +#version 120 +#extension GL_ARB_geometry_shader4 : enable + +// use GL_POINTS +// have point be the corner of voxel +// have a second dataset (? similar to how voxel avatars pass in bones??) +// which is the voxel size? +// +// In vertex shader DON'T transform.. therefor passing the world coordinate xyz to geometric shader +// In geometric shader calculate xyz for triangles the same way we currently do triangles outside of OpenGL +// do transform on these triangles +// gl_Position = gl_ModelViewProjectionMatrix * cube_coord; +// +// output GL_TRIANGLE_STRIP +// +// NOTE: updateNodeInArrays() does the covert from voxel corner to 12 triangles or 36 points or 36*3 floats +// but since it operates on the array of floats, it is kinda weird and hard to follow. The %3 is for the +// xyz.. and identityVertices[j] term in the math is actually a string of floats but they should be thought +// of as triplets of x,y,z +// +// do we need to add the light to these colors?? +// + +//GEOMETRY SHADER +/////////////////////// +void main() +{ + //increment variable + int i; + vec4 vertex; + vec4 color,red,green,blue; + + green = vec4(0,1.0,0,1.0); + red = vec4(1.0,0,0,1.0); + blue = vec4(0,0,1.0,1.0); + + ///////////////////////////////////////////////////////////// + //This example has two parts + // step a) draw the primitive pushed down the pipeline + // there are gl_VerticesIn # of vertices + // put the vertex value into gl_Position + // use EmitVertex => 'create' a new vertex + // use EndPrimitive to signal that you are done creating a primitive! + // step b) create a new piece of geometry + // I just do the same loop, but I negate the vertex.z + // result => the primitive is now mirrored. + //Pass-thru! + for(i = 0; i < gl_VerticesIn; i++) { + color = gl_FrontColorIn[i]; + gl_FrontColor = color; // + gl_Position = gl_ModelViewProjectionMatrix * gl_PositionIn[i]; + EmitVertex(); + } + EndPrimitive(); + + for(i = 0; i < gl_VerticesIn; i++) { + gl_FrontColor = red; // + vertex = gl_PositionIn[i]; + vertex.y += 0.05f; + gl_Position = gl_ModelViewProjectionMatrix * vertex; + EmitVertex(); + } + EndPrimitive(); + + for(i = 0; i < gl_VerticesIn; i++) { + gl_FrontColor = green; // + vertex = gl_PositionIn[i]; + vertex.x += 0.05f; + gl_Position = gl_ModelViewProjectionMatrix * vertex; + EmitVertex(); + } + EndPrimitive(); + + for(i = 0; i < gl_VerticesIn; i++) { + gl_FrontColor = blue; // + vertex = gl_PositionIn[i]; + vertex.z += 0.05f; + gl_Position = gl_ModelViewProjectionMatrix * vertex; + EmitVertex(); + } + EndPrimitive(); + +/** + + for(i = 0; i < gl_VerticesIn; i++) { + green = vec4(0,1.0,0,1.0); + red = vec4(1.0,0,0,1.0); + //gl_FrontColor = gl_FrontColorIn[i]; + gl_FrontColor = red; + + // v -> v+x -> v+x+y + vertex = gl_PositionIn[i]; + gl_Position = vertex; + EmitVertex(); + vertex.x += 0.1f; + gl_Position = vertex; + EmitVertex(); + vertex.y += 0.1f; + gl_Position = vertex; + EmitVertex(); + EndPrimitive(); + + // v+x+y -> v+y -> v + vertex = gl_PositionIn[i]; + vertex.x += 0.1f; + vertex.y += 0.1f; + gl_Position = vertex; + EmitVertex(); + vertex.x -= 0.1f; + gl_Position = vertex; + EmitVertex(); + vertex.y -= 0.1f; + gl_Position = vertex; + EmitVertex(); + EndPrimitive(); + // v+z -> v+z+x -> v+z+x+y + gl_FrontColor = green; + vertex = gl_PositionIn[i]; + vertex.z -= 0.1f; + gl_Position = vertex; + EmitVertex(); + + vertex.x += 0.1f; + gl_Position = vertex; + EmitVertex(); + vertex.y += 0.1f; + gl_Position = vertex; + EmitVertex(); + EndPrimitive(); + + // v+z+x+y -> v+z+y -> v+z + vertex = gl_PositionIn[i]; + vertex.z -= 0.1f; + vertex.x += 0.1f; + vertex.y += 0.1f; + gl_Position = vertex; + EmitVertex(); + vertex.x -= 0.1f; + gl_Position = vertex; + EmitVertex(); + vertex.y -= 0.1f; + gl_Position = vertex; + EmitVertex(); + EndPrimitive(); + + } +**/ + + +} \ No newline at end of file diff --git a/interface/resources/shaders/passthrough.vert b/interface/resources/shaders/passthrough.vert new file mode 100644 index 0000000000..a3a6219b6a --- /dev/null +++ b/interface/resources/shaders/passthrough.vert @@ -0,0 +1,6 @@ +#version 120 + +void main(void) { + gl_FrontColor = gl_Color; //vec4(1.0, 0.0, 0.0, 1.0); + gl_Position = gl_Vertex;// ftransform(); +} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d90c82e6ca..503f8f434e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -389,6 +389,7 @@ void Application::paintGL() { } else { _glowEffect.prepare(); + glMatrixMode(GL_MODELVIEW); glPushMatrix(); @@ -1539,6 +1540,7 @@ void Application::init() { _glowEffect.init(); _ambientOcclusionEffect.init(); + _testGeometry.init(); _handControl.setScreenDimensions(_glWidget->width(), _glWidget->height()); @@ -2579,7 +2581,9 @@ void Application::displaySide(Camera& whichCamera) { // brad's frustum for debugging if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) { + _testGeometry.begin(); renderViewFrustum(_viewFrustum); + _testGeometry.end(); } // render voxel fades if they exist diff --git a/interface/src/Application.h b/interface/src/Application.h index e951afc735..690dbc154c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -51,6 +51,7 @@ #include "renderer/AmbientOcclusionEffect.h" #include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" +#include "renderer/TestGeometry.h" #include "renderer/TextureCache.h" #include "ui/BandwidthDialog.h" #include "ui/ChatEntry.h" @@ -342,6 +343,7 @@ private: GlowEffect _glowEffect; AmbientOcclusionEffect _ambientOcclusionEffect; + TestGeometry _testGeometry; #ifndef _WIN32 Audio _audio; diff --git a/interface/src/renderer/TestGeometry.cpp b/interface/src/renderer/TestGeometry.cpp new file mode 100644 index 0000000000..e30a210dde --- /dev/null +++ b/interface/src/renderer/TestGeometry.cpp @@ -0,0 +1,65 @@ +// +// TestGeometry.cpp +// interface +// +// Created by Brad Hefta-Gaub on 9/22/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. + +// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include + +#include "Application.h" +#include "TestGeometry.h" +#include "ProgramObject.h" +#include "RenderUtil.h" + +TestGeometry::TestGeometry() + : _initialized(false) +{ +} + +TestGeometry::~TestGeometry() { + if (_initialized) { + delete _testProgram; + } +} + +static ProgramObject* createGeometryShaderProgram(const QString& name) { + ProgramObject* program = new ProgramObject(); + program->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/passthrough.vert" ); + + + program->addShaderFromSourceFile(QGLShader::Geometry, "resources/shaders/" + name + ".geom" ); + + program->setGeometryInputType(GL_LINES); + program->setGeometryOutputType(GL_LINE_STRIP); + program->setGeometryOutputVertexCount(100); // hack? + + program->link(); + //program->log(); + + return program; +} + +void TestGeometry::init() { + if (_initialized) { + qDebug("[ERROR] TestProgram is already initialized.\n"); + return; + } + + switchToResourcesParentIfRequired(); + + _testProgram = createGeometryShaderProgram("passthrough"); + _initialized = true; +} + +void TestGeometry::begin() { + _testProgram->bind(); +} + +void TestGeometry::end() { + _testProgram->release(); +} + diff --git a/interface/src/renderer/TestGeometry.h b/interface/src/renderer/TestGeometry.h new file mode 100644 index 0000000000..cec13196b0 --- /dev/null +++ b/interface/src/renderer/TestGeometry.h @@ -0,0 +1,44 @@ +// +// TestGeometry.h +// interface +// +// Created by Andrzej Kapolka on 8/7/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__TestGeometry__ +#define __interface__TestGeometry__ + +#include +#include + +class QOpenGLFramebufferObject; + +class ProgramObject; + +/// A generic full screen glow effect. +class TestGeometry : public QObject { + Q_OBJECT + +public: + TestGeometry(); + ~TestGeometry(); + + void init(); + + /// Starts using the geometry shader effect. + void begin(); + + /// Stops using the geometry shader effect. + void end(); + +public slots: + +private: + + bool _initialized; + + ProgramObject* _testProgram; +}; + +#endif /* defined(__interface__TestGeometry__) */ diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 08fdbefee3..1c6e6cd0e6 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -33,9 +33,9 @@ const int NUMBER_OF_CHILDREN = 8; const int MAX_VOXEL_PACKET_SIZE = 1492; const int MAX_TREE_SLICE_BYTES = 26; const int MAX_VOXELS_PER_SYSTEM = 200000; -const int VERTICES_PER_VOXEL = 24; -const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; -const int INDICES_PER_VOXEL = 3 * 12; +const int VERTICES_PER_VOXEL = 24; // 6 sides * 4 corners per side +const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; // ???? xyz for each VERTICE_PER_VOXEL?? +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; typedef unsigned long int glBufferIndex; From 1dbc8459f848ec8afa813c8e254ba102bd418e52 Mon Sep 17 00:00:00 2001 From: Freddy Date: Wed, 25 Sep 2013 16:46:26 -0700 Subject: [PATCH 03/28] adding measured angular velocity to faceshift --- interface/src/devices/Faceshift.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index 213fbec817..ebc5d5b880 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -142,8 +142,14 @@ void Faceshift::receive(const QByteArray& buffer) { case fsMsg::MSG_OUT_TRACKING_STATE: { const fsTrackingData& data = static_cast(msg.get())->tracking_data(); if ((_tracking = data.m_trackingSuccessful)) { - _headRotation = glm::quat(data.m_headRotation.w, -data.m_headRotation.x, - data.m_headRotation.y, -data.m_headRotation.z); + glm::quat newRotation = glm::quat(data.m_headRotation.w, -data.m_headRotation.x, + data.m_headRotation.y, -data.m_headRotation.z); + glm::quat r = newRotation * glm::inverse(_headRotation); + //printf("angle = %.3f\n", 2 * acos(r.w)); + _headRotation = newRotation; + + //_headRotation = glm::quat(data.m_headRotation.w, -data.m_headRotation.x, + // data.m_headRotation.y, -data.m_headRotation.z); const float TRANSLATION_SCALE = 0.02f; _headTranslation = glm::vec3(data.m_headTranslation.x, data.m_headTranslation.y, -data.m_headTranslation.z) * TRANSLATION_SCALE; From 63efeccb13c939a2dad0eaec98b0f7dadf446098 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 25 Sep 2013 17:38:37 -0700 Subject: [PATCH 04/28] Renaming for clarity. --- interface/src/Application.cpp | 27 ++++++++++++--------------- interface/src/Application.h | 6 +++--- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e5d36b40fd..20b0f6e0af 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -116,7 +116,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _nudgeStarted(false), _lookingAlongX(false), _lookingAwayFromOrigin(true), - _isLookingAtOtherAvatar(false), + _lookatTargetAvatar(NULL), _lookatIndicatorScale(1.0f), _perfStatsOn(false), _chatEntryOn(false), @@ -974,7 +974,7 @@ void Application::mousePressEvent(QMouseEvent* event) { maybeEditVoxelUnderCursor(); - if (!_palette.isActive() && (!_isHoverVoxel || _isLookingAtOtherAvatar)) { + if (!_palette.isActive() && (!_isHoverVoxel || _lookatTargetAvatar)) { _pieMenu.mousePressEvent(_mouseX, _mouseY); } @@ -1503,7 +1503,7 @@ void Application::setListenModeSingleSource() { glm::vec3 eyePositionIgnored; uint16_t nodeID; - if (isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeID)) { + if (findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeID)) { _audio.addListenSource(nodeID); } } @@ -1600,8 +1600,8 @@ const float HEAD_SPHERE_RADIUS = 0.07; static uint16_t DEFAULT_NODE_ID_REF = 1; -Avatar* Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, - glm::vec3& eyePosition, uint16_t& nodeID = DEFAULT_NODE_ID_REF) { +Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, + glm::vec3& eyePosition, uint16_t& nodeID = DEFAULT_NODE_ID_REF) { NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { @@ -1748,8 +1748,8 @@ void Application::update(float deltaTime) { _faceshift.getEstimatedEyePitch(), _faceshift.getEstimatedEyeYaw(), 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f); } - _isLookingAtOtherAvatar = isLookingAtOtherAvatar(lookAtRayOrigin, lookAtRayDirection, lookAtSpot); - if (_isLookingAtOtherAvatar) { + _lookatTargetAvatar = findLookatTargetAvatar(lookAtRayOrigin, lookAtRayDirection, lookAtSpot); + if (_lookatTargetAvatar) { // If the mouse is over another avatar's head... _myAvatar.getHead().setLookAtPosition(lookAtSpot); } else if (_isHoverVoxel && !_faceshift.isActive()) { @@ -2063,15 +2063,15 @@ void Application::updateAvatar(float deltaTime) { const float MIDPOINT_OF_SCREEN = 0.5; // Only use gyro to set lookAt if mouse hasn't selected an avatar - if (!_isLookingAtOtherAvatar) { + if (!_lookatTargetAvatar) { // Set lookAtPosition if an avatar is at the center of the screen glm::vec3 screenCenterRayOrigin, screenCenterRayDirection; _viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection); glm::vec3 eyePosition; - _isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition); - if (_isLookingAtOtherAvatar) { + _lookatTargetAvatar = findLookatTargetAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition); + if (_lookatTargetAvatar) { glm::vec3 myLookAtFromMouse(eyePosition); _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); } @@ -2540,7 +2540,7 @@ void Application::displaySide(Camera& whichCamera) { Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); _myAvatar.setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); - if (Menu::getInstance()->isOptionChecked(MenuOption::LookAtIndicator) && _isLookingAtOtherAvatar) { + if (Menu::getInstance()->isOptionChecked(MenuOption::LookAtIndicator) && _lookatTargetAvatar) { renderLookatIndicator(_lookatOtherPosition, whichCamera); } } @@ -3342,10 +3342,7 @@ void Application::toggleFollowMode() { mouseRayOrigin, mouseRayDirection); glm::vec3 eyePositionIgnored; uint16_t nodeIDIgnored; - Avatar* leadingAvatar = isLookingAtOtherAvatar(mouseRayOrigin, - mouseRayDirection, - eyePositionIgnored, - nodeIDIgnored); + Avatar* leadingAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeIDIgnored); _myAvatar.follow(leadingAvatar); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 940a311f1e..c14434edc8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -195,8 +195,8 @@ private: void init(); void update(float deltaTime); - Avatar* isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, - glm::vec3& eyePosition, uint16_t& nodeID); + Avatar* findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, + glm::vec3& eyePosition, uint16_t& nodeID); bool isLookingAtMyAvatar(Avatar* avatar); void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera); @@ -315,7 +315,7 @@ private: bool _lookingAwayFromOrigin; glm::vec3 _nudgeGuidePosition; - bool _isLookingAtOtherAvatar; + Avatar* _lookatTargetAvatar; glm::vec3 _lookatOtherPosition; float _lookatIndicatorScale; From 4dec1832627760a68357e54463c3e21a91d3ff6e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 26 Sep 2013 12:07:13 -0700 Subject: [PATCH 05/28] Enlarge heads when they're moused over. --- interface/src/Application.cpp | 14 ++++++++++---- interface/src/Application.h | 5 +++++ interface/src/avatar/Avatar.cpp | 13 ++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20b0f6e0af..47544e408a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1596,10 +1596,14 @@ const float MAX_AVATAR_EDIT_VELOCITY = 1.0f; const float MAX_VOXEL_EDIT_DISTANCE = 20.0f; const float HEAD_SPHERE_RADIUS = 0.07; - static uint16_t DEFAULT_NODE_ID_REF = 1; - +void Application::updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, + glm::vec3& eyePosition) { + + _lookatTargetAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePosition, DEFAULT_NODE_ID_REF); +} + Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, glm::vec3& eyePosition, uint16_t& nodeID = DEFAULT_NODE_ID_REF) { @@ -1748,7 +1752,7 @@ void Application::update(float deltaTime) { _faceshift.getEstimatedEyePitch(), _faceshift.getEstimatedEyeYaw(), 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f); } - _lookatTargetAvatar = findLookatTargetAvatar(lookAtRayOrigin, lookAtRayDirection, lookAtSpot); + updateLookatTargetAvatar(lookAtRayOrigin, lookAtRayDirection, lookAtSpot); if (_lookatTargetAvatar) { // If the mouse is over another avatar's head... _myAvatar.getHead().setLookAtPosition(lookAtSpot); @@ -2070,7 +2074,7 @@ void Application::updateAvatar(float deltaTime) { _viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection); glm::vec3 eyePosition; - _lookatTargetAvatar = findLookatTargetAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition); + updateLookatTargetAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition); if (_lookatTargetAvatar) { glm::vec3 myLookAtFromMouse(eyePosition); _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); @@ -3415,6 +3419,8 @@ void Application::nodeKilled(Node* node) { fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller; _voxelFades.push_back(fade); } + } else if (node->getLinkedData() == _lookatTargetAvatar) { + _lookatTargetAvatar = NULL; } } diff --git a/interface/src/Application.h b/interface/src/Application.h index c14434edc8..5541f84573 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -130,6 +130,8 @@ public: TextureCache* getTextureCache() { return &_textureCache; } GlowEffect* getGlowEffect() { return &_glowEffect; } + Avatar* getLookatTargetAvatar() const { return _lookatTargetAvatar; } + static void controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes); @@ -195,6 +197,9 @@ private: void init(); void update(float deltaTime); + + void updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, + glm::vec3& eyePosition); Avatar* findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, glm::vec3& eyePosition, uint16_t& nodeID); bool isLookingAtMyAvatar(Avatar* avatar); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 1d50416b73..8aba7f8b4d 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -388,9 +388,20 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCamer } } + // head scale grows when avatar is looked at + if (Application::getInstance()->getLookatTargetAvatar() == this) { + const float BASE_MAX_SCALE = 3.0f; + const float GROW_SPEED = 0.1f; + _head.setScale(min(BASE_MAX_SCALE * glm::distance(_position, Application::getInstance()->getCamera()->getPosition()), + _head.getScale() + deltaTime * GROW_SPEED)); + + } else { + const float SHRINK_SPEED = 100.0f; + _head.setScale(max(_scale, _head.getScale() - deltaTime * SHRINK_SPEED)); + } + _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); - _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); _head.simulate(deltaTime, false, gyroCameraSensitivity); _hand.simulate(deltaTime, false); From 552d9fadd88862b3903c6d39f08e1395f7e1ab70 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 14:51:57 -0700 Subject: [PATCH 06/28] rearranged menus, some hacking on voxel shader --- interface/resources/shaders/passthrough.geom | 68 --- interface/resources/shaders/passthrough.vert | 6 +- interface/resources/shaders/voxel.geom | 86 ++++ interface/src/Application.cpp | 95 ++++- interface/src/Application.h | 6 +- interface/src/Menu.cpp | 221 +++++----- interface/src/Menu.h | 7 +- interface/src/VoxelSystem.cpp | 396 ++++++++++++------ interface/src/VoxelSystem.h | 18 + interface/src/renderer/TestGeometry.h | 44 -- .../{TestGeometry.cpp => VoxelShader.cpp} | 50 ++- interface/src/renderer/VoxelShader.h | 46 ++ 12 files changed, 670 insertions(+), 373 deletions(-) create mode 100644 interface/resources/shaders/voxel.geom delete mode 100644 interface/src/renderer/TestGeometry.h rename interface/src/renderer/{TestGeometry.cpp => VoxelShader.cpp} (50%) create mode 100644 interface/src/renderer/VoxelShader.h diff --git a/interface/resources/shaders/passthrough.geom b/interface/resources/shaders/passthrough.geom index 1ce193cda9..4ea2959b19 100644 --- a/interface/resources/shaders/passthrough.geom +++ b/interface/resources/shaders/passthrough.geom @@ -79,72 +79,4 @@ void main() EmitVertex(); } EndPrimitive(); - -/** - - for(i = 0; i < gl_VerticesIn; i++) { - green = vec4(0,1.0,0,1.0); - red = vec4(1.0,0,0,1.0); - //gl_FrontColor = gl_FrontColorIn[i]; - gl_FrontColor = red; - - // v -> v+x -> v+x+y - vertex = gl_PositionIn[i]; - gl_Position = vertex; - EmitVertex(); - vertex.x += 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.y += 0.1f; - gl_Position = vertex; - EmitVertex(); - EndPrimitive(); - - // v+x+y -> v+y -> v - vertex = gl_PositionIn[i]; - vertex.x += 0.1f; - vertex.y += 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.x -= 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.y -= 0.1f; - gl_Position = vertex; - EmitVertex(); - EndPrimitive(); - // v+z -> v+z+x -> v+z+x+y - gl_FrontColor = green; - vertex = gl_PositionIn[i]; - vertex.z -= 0.1f; - gl_Position = vertex; - EmitVertex(); - - vertex.x += 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.y += 0.1f; - gl_Position = vertex; - EmitVertex(); - EndPrimitive(); - - // v+z+x+y -> v+z+y -> v+z - vertex = gl_PositionIn[i]; - vertex.z -= 0.1f; - vertex.x += 0.1f; - vertex.y += 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.x -= 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.y -= 0.1f; - gl_Position = vertex; - EmitVertex(); - EndPrimitive(); - - } -**/ - - } \ No newline at end of file diff --git a/interface/resources/shaders/passthrough.vert b/interface/resources/shaders/passthrough.vert index a3a6219b6a..f770ab115f 100644 --- a/interface/resources/shaders/passthrough.vert +++ b/interface/resources/shaders/passthrough.vert @@ -1,6 +1,10 @@ #version 120 +attribute float voxelSizeIn; +varying float voxelSize; + void main(void) { gl_FrontColor = gl_Color; //vec4(1.0, 0.0, 0.0, 1.0); - gl_Position = gl_Vertex;// ftransform(); + gl_Position = gl_ModelViewMatrix * gl_Vertex;// ftransform(); + voxelSize = voxelSizeIn; } \ No newline at end of file diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom new file mode 100644 index 0000000000..d3f0b89f10 --- /dev/null +++ b/interface/resources/shaders/voxel.geom @@ -0,0 +1,86 @@ +#version 120 +#extension GL_ARB_geometry_shader4 : enable + +// +// VOXEL GEOMETRY SHADER +// +// Input: gl_VerticesIn/gl_PositionIn +// GL_POINTS +// Assumes vertex shader has not transformed coordinates +// Each gl_PositionIn is the corner of voxel +// +// Second dataset (? similar to how voxel avatars pass in bones??) +// which is the voxel size +// +// Note: In vertex shader DON'T transform. Therefore passing the world coordinate xyz to geometric shader +// In geometric shader calculate xyz for triangles the same way we currently do triangles outside of OpenGL +// do transform on these triangles +// +// gl_Position = gl_ModelViewProjectionMatrix * cube_coord; +// +// Output: GL_TRIANGLE_STRIP +// +// Issues: +// do we need to handle lighting of these colors?? +// how do we handle normals? +// check for size=0 and don't output the primitive +// + +varying in float voxelSize[1]; + +const int VERTICES_PER_FACE = 4; +const int COORD_PER_VERTEX = 3; +const int COORD_PER_FACE = COORD_PER_VERTEX * VERTICES_PER_FACE; + +void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec4 color) { + for (int v = 0; v < VERTICES_PER_FACE; v++ ) { + vec4 vertex = corner; + for (int c = 0; c < COORD_PER_VERTEX; c++ ) { + int cIndex = c + (v * COORD_PER_VERTEX); + vertex[c] += (facePoints[cIndex] * scale); + } + gl_FrontColor = color; + gl_Position = gl_ProjectionMatrix * vertex; + EmitVertex(); + } + EndPrimitive(); +} + + +void main() +{ + //increment variable + int i; + vec4 corner; + float scale; + + float bottomFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1 ); + float topFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 ); + float rightFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1 ); + float leftFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1 ); + 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 ); + + vec4 color,red,green,blue,yellow,cyan,purple; + + green = vec4(0,1.0,0,1.0); + red = vec4(1.0,0,0,1.0); + blue = vec4(0,0,1.0,1.0); + yellow = vec4(1.0,1.0,0,1.0); + cyan = vec4(0,1.0,1.0,1.0); + purple = vec4(1.0,0,1.0,1.0); + + for(i = 0; i < gl_VerticesIn; i++) { + gl_FrontColor = gl_FrontColorIn[i]; + corner = gl_PositionIn[i]; + scale = voxelSize[i]; + color = gl_FrontColorIn[i]; + + faceOfVoxel(corner, scale, bottomFace, color); + faceOfVoxel(corner, scale, topFace, color); + faceOfVoxel(corner, scale, rightFace, color); + faceOfVoxel(corner, scale, leftFace, color); + faceOfVoxel(corner, scale, frontFace, color); + faceOfVoxel(corner, scale, backFace, color); + } +} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 503f8f434e..b10ed430bf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -542,6 +542,10 @@ void Application::keyPressEvent(QKeyEvent* event) { _myAvatar.setDriveKeys(UP, 1); } break; + + case Qt::Key_Asterisk: + Menu::getInstance()->triggerOption(MenuOption::Stars); + break; case Qt::Key_C: if (isShifted) { @@ -811,8 +815,6 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_F: if (isShifted) { Menu::getInstance()->triggerOption(MenuOption::DisplayFrustum); - } else { - Menu::getInstance()->triggerOption(MenuOption::Fullscreen); } break; case Qt::Key_V: @@ -1540,7 +1542,7 @@ void Application::init() { _glowEffect.init(); _ambientOcclusionEffect.init(); - _testGeometry.init(); + _voxelShader.init(); _handControl.setScreenDimensions(_glWidget->width(), _glWidget->height()); @@ -2581,9 +2583,92 @@ void Application::displaySide(Camera& whichCamera) { // brad's frustum for debugging if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) { - _testGeometry.begin(); renderViewFrustum(_viewFrustum); - _testGeometry.end(); + } + + // brad's voxel shader debugging + if (false) { + + const float TEST_STRIP_COLOR[] = { 0.0f, 1.0f, 0.0f }; + glColor3fv(TEST_STRIP_COLOR); + + _voxelShader.begin(); + const float VOXEL_COLOR[] = { 1.0f, 0.0f, 0.0f }; + glColor3fv(VOXEL_COLOR); + + struct VoxelData + { + float x, y, z; // position + float s; // size + unsigned char r,g,b; // color + }; + + VoxelData voxels[3]; + + //VERTEX 0 + voxels[0].x = 0.0; + voxels[0].y = 0.0; + voxels[0].z = 1.0; + voxels[0].s = 0.1; + voxels[0].r = 255; + voxels[0].g = 0; + voxels[0].b = 0; + + //VERTEX 1 + voxels[1].x = 1.0; + voxels[1].y = 0.0; + voxels[1].z = 0.0; + voxels[1].s = 0.2; + voxels[1].r = 0; + voxels[1].g = 255; + voxels[1].b = 0; + + //VERTEX 2 + voxels[2].x = 0.0; + voxels[2].y = 1.0; + voxels[2].z = 0.0; + voxels[2].s = 0.3; + voxels[2].r = 0; + voxels[2].g = 0; + voxels[2].b = 255; + + GLuint VertexVBOID; + GLuint IndexVBOID; + + glGenBuffers(1, &VertexVBOID); + glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID); + glBufferData(GL_ARRAY_BUFFER, sizeof(voxels), &voxels[0].x, GL_STATIC_DRAW); + + ushort indices[3]; + indices[0] = 0; + indices[1] = 1; + indices[2] = 2; + + glGenBuffers(1, &IndexVBOID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + //Define this somewhere in your header file + #define BUFFER_OFFSET(i) ((void*)(i)) + + glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(VoxelData), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices + int loc = _voxelShader.attributeLocation("voxelSizeIn"); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 1, GL_FLOAT, false, sizeof(VoxelData), BUFFER_OFFSET(3*sizeof(float))); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelData), BUFFER_OFFSET(4*sizeof(float)));//The starting point of colors + + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID); + glDrawElements(GL_POINTS, 3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); //The starting point of the IBO + + glDeleteBuffers(1, &VertexVBOID); + glDeleteBuffers(1, &IndexVBOID); + + _voxelShader.end(); } // render voxel fades if they exist diff --git a/interface/src/Application.h b/interface/src/Application.h index 690dbc154c..0860d9057a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -51,7 +51,7 @@ #include "renderer/AmbientOcclusionEffect.h" #include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" -#include "renderer/TestGeometry.h" +#include "renderer/VoxelShader.h" #include "renderer/TextureCache.h" #include "ui/BandwidthDialog.h" #include "ui/ChatEntry.h" @@ -143,6 +143,8 @@ public: virtual void nodeAdded(Node* node); virtual void nodeKilled(Node* node); virtual void packetSentNotification(ssize_t length); + + VoxelShader& getVoxelShader() { return _voxelShader; } public slots: void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); @@ -343,7 +345,7 @@ private: GlowEffect _glowEffect; AmbientOcclusionEffect _ambientOcclusionEffect; - TestGeometry _testGeometry; + VoxelShader _voxelShader; #ifndef _WIN32 Audio _audio; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 560f72807b..6f385c3e99 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -188,50 +188,36 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Fullscreen, - Qt::Key_F, + Qt::CTRL | Qt::META | Qt::Key_F, false, appInstance, SLOT(setFullscreen(bool))); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::Key_H); - addActionToQMenuAndActionHash(viewMenu, + QMenu* avatarSizeMenu = viewMenu->addMenu("Avatar Size"); + + addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::IncreaseAvatarSize, Qt::Key_Plus, appInstance->getAvatar(), SLOT(increaseSize())); - addActionToQMenuAndActionHash(viewMenu, + addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::DecreaseAvatarSize, Qt::Key_Minus, appInstance->getAvatar(), SLOT(decreaseSize())); - addActionToQMenuAndActionHash(viewMenu, + addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::ResetAvatarSize, 0, appInstance->getAvatar(), SLOT(resetSize())); - - - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::Key_H); - - addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::SkeletonTracking, - 0, - false, - appInstance->getWebcam(), - SLOT(setSkeletonTrackingOn(bool))); - - addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::LEDTracking, - 0, - false, - appInstance->getWebcam()->getGrabber(), - SLOT(setLEDTrackingOn(bool))); - + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::OffAxisProjection, 0, false); - + addDisabledActionAndSeparator(viewMenu, "Stats"); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L); @@ -241,50 +227,119 @@ Menu::Menu() : addActionToQMenuAndActionHash(viewMenu, MenuOption::VoxelStats, 0, this, SLOT(voxelStatsDetails())); QMenu* developerMenu = addMenu("Developer"); - addDisabledActionAndSeparator(developerMenu, "Rendering"); - - addCheckableActionToQMenuAndActionHash(developerMenu, + + QMenu* renderOptionsMenu = developerMenu->addMenu("Rendering Options"); + + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, Qt::Key_Asterisk, true); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::GroundPlane, 0, true); + addActionToQMenuAndActionHash(renderOptionsMenu, + MenuOption::GlowMode, + 0, + appInstance->getGlowEffect(), + SLOT(cycleRenderMode())); + + QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxel Options"); + + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::Voxels, Qt::SHIFT | Qt::Key_V, true, appInstance, SLOT(setRenderVoxels(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::VoxelTextures); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AmbientOcclusion); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stars, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::GroundPlane, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Avatars, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AvatarAsBalls); + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader); - addActionToQMenuAndActionHash(developerMenu, + QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); + + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::AvatarAsBalls); + + addActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::VoxelMode, 0, appInstance->getAvatar()->getVoxels(), SLOT(cycleMode())); - addActionToQMenuAndActionHash(developerMenu, + addActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::FaceMode, 0, &appInstance->getAvatar()->getHead().getFace(), SLOT(cycleRenderMode())); - addActionToQMenuAndActionHash(developerMenu, - MenuOption::GlowMode, + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::UsePerlinFace, 0, false); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, true); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtIndicator, 0, true); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, + MenuOption::FaceshiftTCP, + 0, + false, + appInstance->getFaceshift(), + SLOT(setTCPEnabled(bool))); + + QMenu* webcamOptionsMenu = developerMenu->addMenu("Webcam Options"); + + addCheckableActionToQMenuAndActionHash(webcamOptionsMenu, + MenuOption::Webcam, + 0, + false, + appInstance->getWebcam(), + SLOT(setEnabled(bool))); + + addActionToQMenuAndActionHash(webcamOptionsMenu, + MenuOption::WebcamMode, 0, - appInstance->getGlowEffect(), - SLOT(cycleRenderMode())); + appInstance->getWebcam()->getGrabber(), + SLOT(cycleVideoSendMode())); + + addCheckableActionToQMenuAndActionHash(webcamOptionsMenu, + MenuOption::WebcamTexture, + 0, + false, + appInstance->getWebcam()->getGrabber(), + SLOT(setDepthOnly(bool))); + + QMenu* raveGloveOptionsMenu = developerMenu->addMenu("Rave Glove Options"); + + addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::SimulateLeapHand); + addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::TestRaveGlove); + + + QMenu* gyroOptionsMenu = developerMenu->addMenu("Gyro Options"); + addCheckableActionToQMenuAndActionHash(gyroOptionsMenu, MenuOption::GyroLook, 0, true); + addCheckableActionToQMenuAndActionHash(gyroOptionsMenu, MenuOption::HeadMouse); + + + QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options"); + addCheckableActionToQMenuAndActionHash(trackingOptionsMenu, + MenuOption::SkeletonTracking, + 0, + false, + appInstance->getWebcam(), + SLOT(setSkeletonTrackingOn(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::UsePerlinFace, 0, false); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtVectors, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtIndicator, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::FrameTimer); + addCheckableActionToQMenuAndActionHash(trackingOptionsMenu, + MenuOption::LEDTracking, + 0, + false, + appInstance->getWebcam()->getGrabber(), + SLOT(setLEDTrackingOn(bool))); addDisabledActionAndSeparator(developerMenu, "Testing"); + + QMenu* timingMenu = developerMenu->addMenu("Timing and Statistics Tools"); + addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true); + addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer); + addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests())); + addActionToQMenuAndActionHash(timingMenu, + MenuOption::TreeStats, + Qt::SHIFT | Qt::Key_S, + appInstance->getVoxels(), + SLOT(collectStatsForTreesAndVBOs())); QMenu* frustumMenu = developerMenu->addMenu("View Frustum Debugging Tools"); addCheckableActionToQMenuAndActionHash(frustumMenu, MenuOption::DisplayFrustum, Qt::SHIFT | Qt::Key_F); - addActionToQMenuAndActionHash(frustumMenu, MenuOption::FrustumRenderMode, Qt::SHIFT | Qt::Key_R, @@ -292,12 +347,6 @@ Menu::Menu() : SLOT(cycleFrustumRenderMode())); updateFrustumRenderModeAction(); - addActionToQMenuAndActionHash(developerMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests())); - addActionToQMenuAndActionHash(developerMenu, - MenuOption::TreeStats, - Qt::SHIFT | Qt::Key_S, - appInstance->getVoxels(), - SLOT(collectStatsForTreesAndVBOs())); QMenu* renderDebugMenu = developerMenu->addMenu("Render Debugging Tools"); addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::PipelineWarnings); @@ -337,18 +386,6 @@ Menu::Menu() : appInstance->getVoxels(), SLOT(falseColorizeInView())); - addActionToQMenuAndActionHash(renderDebugMenu, - MenuOption::FalseColorOccluded, - 0, - appInstance->getVoxels(), - SLOT(falseColorizeOccluded())); - - addActionToQMenuAndActionHash(renderDebugMenu, - MenuOption::FalseColorOccludedV2, - 0, - appInstance->getVoxels(), - SLOT(falseColorizeOccludedV2())); - addActionToQMenuAndActionHash(renderDebugMenu, MenuOption::FalseColorBySource, 0, @@ -361,32 +398,21 @@ Menu::Menu() : appInstance->getVoxels(), SLOT(trueColorize())); - - addCheckableActionToQMenuAndActionHash(developerMenu, - MenuOption::Webcam, - 0, - false, - appInstance->getWebcam(), - SLOT(setEnabled(bool))); - - addActionToQMenuAndActionHash(developerMenu, - MenuOption::WebcamMode, + addDisabledActionAndSeparator(renderDebugMenu, "Coverage Maps"); + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorOccluded, 0, - appInstance->getWebcam()->getGrabber(), - SLOT(cycleVideoSendMode())); - addCheckableActionToQMenuAndActionHash(developerMenu, - MenuOption::WebcamTexture, - 0, - false, - appInstance->getWebcam()->getGrabber(), - SLOT(setDepthOnly(bool))); + appInstance->getVoxels(), + SLOT(falseColorizeOccluded())); - addCheckableActionToQMenuAndActionHash(developerMenu, - MenuOption::FaceshiftTCP, - 0, - false, - appInstance->getFaceshift(), - SLOT(setTCPEnabled(bool))); + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorOccludedV2, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeOccludedV2())); + + addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMap, Qt::SHIFT | Qt::CTRL | Qt::Key_O); + addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P); QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools"); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoAudio); @@ -406,47 +432,38 @@ Menu::Menu() : appInstance, SLOT(setListenModeSingleSource())); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::TestPing, 0, true); + QMenu* voxelProtoOptionsMenu = developerMenu->addMenu("Voxel Server Protocol Options"); - addCheckableActionToQMenuAndActionHash(developerMenu, + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::SendVoxelColors, 0, true, appInstance->getAvatar(), SLOT(setWantColor(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::LowRes, 0, true, appInstance->getAvatar(), SLOT(setWantLowResMoving(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::DeltaSending, 0, true, appInstance->getAvatar(), SLOT(setWantDelta(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::OcclusionCulling, Qt::SHIFT | Qt::Key_C, true, appInstance->getAvatar(), SLOT(setWantOcclusionCulling(bool))); - - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::CoverageMap, Qt::SHIFT | Qt::CTRL | Qt::Key_O); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::SimulateLeapHand); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::TestRaveGlove); - - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::GyroLook, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::HeadMouse); - - addDisabledActionAndSeparator(developerMenu, "Voxels"); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DestructiveAddVoxel); + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::DestructiveAddVoxel); + #ifndef Q_OS_MAC QMenu* helpMenu = addMenu("Help"); QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 78ef65221c..a30fc4cdb0 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -201,9 +201,7 @@ namespace MenuOption { const QString TransmitterDrive = "Transmitter Drive"; const QString UsePerlinFace = "Use Perlin's Face"; const QString Quit = "Quit"; - const QString Webcam = "Webcam"; - const QString WebcamMode = "Cycle Webcam Send Mode"; - const QString WebcamTexture = "Webcam Texture"; + const QString UseVoxelShader = "Use Voxel Shader"; const QString Voxels = "Voxels"; const QString VoxelAddMode = "Add Voxel Mode"; const QString VoxelColorMode = "Color Voxel Mode"; @@ -214,6 +212,9 @@ namespace MenuOption { const QString VoxelSelectMode = "Select Voxel Mode"; const QString VoxelStats = "Voxel Stats"; const QString VoxelTextures = "Voxel Textures"; + const QString Webcam = "Webcam"; + const QString WebcamMode = "Cycle Webcam Send Mode"; + const QString WebcamTexture = "Webcam Texture"; } #endif /* defined(__hifi__Menu__) */ diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a1595f0de0..759a2f178a 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -74,6 +74,19 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float))); connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int))); + + _voxelShaderInitialized = false; + _initializingVoxelShader = false; + _writeVoxelShaderData = NULL; + _readVoxelShaderData = NULL; + + _readVerticesArray = NULL; + _writeVerticesArray = NULL; + _readColorsArray = NULL; + _writeColorsArray = NULL; + _writeVoxelDirtyArray = NULL; + _readVoxelDirtyArray = NULL; + } void VoxelSystem::nodeDeleted(VoxelNode* node) { @@ -125,13 +138,20 @@ VoxelSystem::~VoxelSystem() { glDeleteBuffers(1, &_vboNormalsID); glDeleteBuffers(1, &_vboColorsID); glDeleteBuffers(1, &_vboIndicesID); - + delete[] _readVerticesArray; delete[] _writeVerticesArray; delete[] _readColorsArray; delete[] _writeColorsArray; delete[] _writeVoxelDirtyArray; delete[] _readVoxelDirtyArray; + + // these are used when in VoxelShader mode. + glDeleteBuffers(1, &_vboVoxelsID); + glDeleteBuffers(1, &_vboVoxelsIndicesID); + + delete[] _writeVoxelShaderData; + delete[] _readVoxelShaderData; } delete _tree; @@ -141,6 +161,45 @@ VoxelSystem::~VoxelSystem() { VoxelNode::removeDeleteHook(this); } +bool VoxelSystem::getUseVoxelShader() { + bool useVoxelShader = false; //Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader); + + return useVoxelShader; +} + +void VoxelSystem::initVoxelShader() { + GLuint* indicesArray = new GLuint[_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++) { + indicesArray[n] = n; + } + + // bind the indices VBO to the actual indices array + glGenBuffers(1, &_vboVoxelsIndicesID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, _maxVoxels, indicesArray, GL_STATIC_DRAW); + + + glGenBuffers(1, &_vboVoxelsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_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 + _writeVoxelDirtyArray = new bool[_maxVoxels]; + memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; + memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + + // prep the data structures for incoming voxel data + _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; +} + void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { _tree->loadVoxelsFile(fileName, wantColorRandomizer); setupNewVoxelsForDrawing(); @@ -398,18 +457,24 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { int segmentLength = (segmentEnd - segmentStart) + 1; + if (getUseVoxelShader()) { + GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); + void* readDataAt = &_readVoxelShaderData[segmentStart]; + void* writeDataAt = &_writeVoxelShaderData[segmentStart]; + memcpy(readDataAt, writeDataAt, segmentSizeBytes); + } else { + GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); + segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); + } } void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { @@ -532,11 +597,29 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex, float voxelScale, const nodeColor& color) { - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(writeColorsAt +j) = color[j % 3]; + + if (getUseVoxelShader()) { + VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; + writeVerticesAt->x = startVertex.x * TREE_SCALE; + writeVerticesAt->y = startVertex.y * TREE_SCALE; + writeVerticesAt->z = startVertex.z * TREE_SCALE; + writeVerticesAt->s = voxelScale * TREE_SCALE; + writeVerticesAt->r = color[RED_INDEX]; + writeVerticesAt->g = color[GREEN_INDEX]; + writeVerticesAt->b = color[BLUE_INDEX]; + + /** + printf("updateNodeInArrays() nodeIndex=%lu writeVerticesAt=[%f,%f,%f,%f (%u,%u,%u)]\n", + nodeIndex, writeVerticesAt->x, writeVerticesAt->y, writeVerticesAt->z, writeVerticesAt->s, + writeVerticesAt->r, writeVerticesAt->g, writeVerticesAt->b ); + **/ + } else { + for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(writeColorsAt +j) = color[j % 3]; + } } } @@ -563,85 +646,89 @@ void VoxelSystem::init() { _voxelsInWriteArrays = 0; _voxelsInReadArrays = 0; - 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]; - } - } - - 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 verticesArray - glGenBuffers(1, &_vboVerticesID); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + //initVoxelShader(); - // 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); + if (true) { + GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; - // VBO for colorsArray - glGenBuffers(1, &_vboColorsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + // 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); - // 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); + for (int i = 0; i < INDICES_PER_VOXEL; i++) { + // add indices for this side of the cube + currentIndicesPos[i] = startIndex + identityIndices[i]; + } + } - // delete the indices and normals arrays that are no longer needed - delete[] indicesArray; - delete[] normalsArray; + 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]; + } + } + + glGenBuffers(1, &_vboVerticesID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + + // 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); + + // VBO for colorsArray + glGenBuffers(1, &_vboColorsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + + // 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; + delete[] normalsArray; - // we will track individual dirty sections with these arrays of bools - _writeVoxelDirtyArray = new bool[_maxVoxels]; - memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - _readVoxelDirtyArray = new bool[_maxVoxels]; - memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + // we will track individual dirty sections with these arrays of bools + _writeVoxelDirtyArray = new bool[_maxVoxels]; + memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; + memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - // prep the data structures for incoming voxel data - _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + // prep the data structures for incoming voxel data + _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - // create our simple fragment shader if we're the first system to init - if (!_perlinModulateProgram.isLinked()) { - switchToResourcesParentIfRequired(); - _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); - _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); - _perlinModulateProgram.link(); + // create our simple fragment shader if we're the first system to init + if (!_perlinModulateProgram.isLinked()) { + switchToResourcesParentIfRequired(); + _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); + _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); + _perlinModulateProgram.link(); - _perlinModulateProgram.bind(); - _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); - _perlinModulateProgram.release(); + _perlinModulateProgram.bind(); + _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); + _perlinModulateProgram.release(); + } } _initialized = true; } @@ -714,17 +801,34 @@ void VoxelSystem::updateVBOs() { } void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) { - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); + if (getUseVoxelShader()) { + int segmentLength = (segmentEnd - segmentStart) + 1; + GLintptr segmentStartAt = segmentStart * sizeof(VoxelShaderVBOData); + GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); + void* readVerticesFrom = &_readVoxelShaderData[segmentStart]; + + glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); + } else { + int segmentLength = (segmentEnd - segmentStart) + 1; + GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); +//printf("VoxelSystem::updateVBOSegment() segmentStart=%lu, segmentEnd=%lu, segmentSizeBytes=%lu \n", +// segmentStart, segmentEnd, segmentSizeBytes); + + + segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); + +//printf("VoxelSystem::updateVBOSegment() segmentStart=%lu, segmentEnd=%lu, segmentSizeBytes=%lu \n", +// segmentStart, segmentEnd, segmentSizeBytes); + } } void VoxelSystem::render(bool texture) { @@ -734,43 +838,85 @@ void VoxelSystem::render(bool texture) { pthread_mutex_lock(&_bufferWriteLock); updateVBOs(); + + //printf("render() _voxelsInReadArrays=%lu voxel shader=%s\n", _voxelsInReadArrays, debug::valueOf(getUseVoxelShader())); - // tell OpenGL where to find vertex and color information - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glVertexPointer(3, GL_FLOAT, 0, 0); - - glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glNormalPointer(GL_FLOAT, 0, 0); - - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); - - applyScaleAndBindProgram(texture); + if (getUseVoxelShader()) { - // for performance, enable backface culling - glEnable(GL_CULL_FACE); + Application::getInstance()->getVoxelShader().begin(); - // draw the number of voxels we have - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); - glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, - 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + //Define this somewhere in your header file + #define BUFFER_OFFSET(i) ((void*)(i)) - glDisable(GL_CULL_FACE); + glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices + int loc = Application::getInstance()->getVoxelShader().attributeLocation("voxelSizeIn"); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 1, GL_FLOAT, false, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(3*sizeof(float))); + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(4*sizeof(float)));//The starting point of colors - removeScaleAndReleaseProgram(texture); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); + glDrawElements(GL_POINTS, _voxelsInReadArrays, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); //The starting point of the IBO + + /** + for (int i=0; i < _voxelsInReadArrays; i++) { + VoxelShaderVBOData* readDataAt = &_readVoxelShaderData[i]; + printf("render() _voxelsInReadArrays=%lu i=%d readDataAt=[%f,%f,%f,%f (%u,%u,%u)]\n", + _voxelsInReadArrays, i, readDataAt->x, readDataAt->y, readDataAt->z, readDataAt->s, + readDataAt->r, readDataAt->g, readDataAt->b ); + } + **/ + + // deactivate vertex and color arrays after drawing + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + // bind with 0 to switch back to normal operation + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + Application::getInstance()->getVoxelShader().end(); + + } else { + // tell OpenGL where to find vertex and color information + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glVertexPointer(3, GL_FLOAT, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); + glNormalPointer(GL_FLOAT, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); + + applyScaleAndBindProgram(texture); - // deactivate vertex and color arrays after drawing - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); + // for performance, enable backface culling + glEnable(GL_CULL_FACE); - // bind with 0 to switch back to normal operation - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + // draw the number of voxels we have + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, + 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + + glDisable(GL_CULL_FACE); + + removeScaleAndReleaseProgram(texture); + + // deactivate vertex and color arrays after drawing + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + // bind with 0 to switch back to normal operation + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } pthread_mutex_unlock(&_bufferWriteLock); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 5ac5310b76..fe088ce042 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -23,11 +23,20 @@ #include "Camera.h" #include "Util.h" #include "world.h" +#include "renderer/VoxelShader.h" class ProgramObject; const int NUM_CHILDREN = 8; +struct VoxelShaderVBOData +{ + float x, y, z; // position + float s; // size + unsigned char r,g,b; // color +}; + + class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook { Q_OBJECT public: @@ -190,6 +199,15 @@ private: uint64_t _lastViewCulling; int _lastViewCullingElapsed; + bool getUseVoxelShader(); + void initVoxelShader(); + bool _voxelShaderInitialized; + bool _initializingVoxelShader; + 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 + VoxelShaderVBOData* _writeVoxelShaderData; + VoxelShaderVBOData* _readVoxelShaderData; + GLuint _vboVerticesID; GLuint _vboNormalsID; GLuint _vboColorsID; diff --git a/interface/src/renderer/TestGeometry.h b/interface/src/renderer/TestGeometry.h deleted file mode 100644 index cec13196b0..0000000000 --- a/interface/src/renderer/TestGeometry.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// TestGeometry.h -// interface -// -// Created by Andrzej Kapolka on 8/7/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef __interface__TestGeometry__ -#define __interface__TestGeometry__ - -#include -#include - -class QOpenGLFramebufferObject; - -class ProgramObject; - -/// A generic full screen glow effect. -class TestGeometry : public QObject { - Q_OBJECT - -public: - TestGeometry(); - ~TestGeometry(); - - void init(); - - /// Starts using the geometry shader effect. - void begin(); - - /// Stops using the geometry shader effect. - void end(); - -public slots: - -private: - - bool _initialized; - - ProgramObject* _testProgram; -}; - -#endif /* defined(__interface__TestGeometry__) */ diff --git a/interface/src/renderer/TestGeometry.cpp b/interface/src/renderer/VoxelShader.cpp similarity index 50% rename from interface/src/renderer/TestGeometry.cpp rename to interface/src/renderer/VoxelShader.cpp index e30a210dde..b8a907c917 100644 --- a/interface/src/renderer/TestGeometry.cpp +++ b/interface/src/renderer/VoxelShader.cpp @@ -1,5 +1,5 @@ // -// TestGeometry.cpp +// VoxelShader.cpp // interface // // Created by Brad Hefta-Gaub on 9/22/13. @@ -11,55 +11,59 @@ #include #include "Application.h" -#include "TestGeometry.h" +#include "VoxelShader.h" #include "ProgramObject.h" #include "RenderUtil.h" -TestGeometry::TestGeometry() +VoxelShader::VoxelShader() : _initialized(false) { + _program = NULL; } -TestGeometry::~TestGeometry() { +VoxelShader::~VoxelShader() { if (_initialized) { - delete _testProgram; + delete _program; } } -static ProgramObject* createGeometryShaderProgram(const QString& name) { +ProgramObject* VoxelShader::createGeometryShaderProgram(const QString& name) { ProgramObject* program = new ProgramObject(); program->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/passthrough.vert" ); - - program->addShaderFromSourceFile(QGLShader::Geometry, "resources/shaders/" + name + ".geom" ); - - program->setGeometryInputType(GL_LINES); - program->setGeometryOutputType(GL_LINE_STRIP); - program->setGeometryOutputVertexCount(100); // hack? - + program->setGeometryInputType(GL_POINTS); + program->setGeometryOutputType(GL_TRIANGLE_STRIP); + const int VERTICES_PER_FACE = 4; + const int FACES_PER_VOXEL = 6; + const int VERTICES_PER_VOXEL = VERTICES_PER_FACE * FACES_PER_VOXEL; + program->setGeometryOutputVertexCount(VERTICES_PER_VOXEL); program->link(); - //program->log(); - return program; } -void TestGeometry::init() { +void VoxelShader::init() { if (_initialized) { qDebug("[ERROR] TestProgram is already initialized.\n"); return; } - switchToResourcesParentIfRequired(); - - _testProgram = createGeometryShaderProgram("passthrough"); + _program = createGeometryShaderProgram("voxel"); _initialized = true; } -void TestGeometry::begin() { - _testProgram->bind(); +void VoxelShader::begin() { + _program->bind(); } -void TestGeometry::end() { - _testProgram->release(); +void VoxelShader::end() { + _program->release(); +} + +int VoxelShader::attributeLocation(const char * name) const { + if (_program) { + return _program->attributeLocation(name); + } else { + return -1; + } } diff --git a/interface/src/renderer/VoxelShader.h b/interface/src/renderer/VoxelShader.h new file mode 100644 index 0000000000..33e8ea0073 --- /dev/null +++ b/interface/src/renderer/VoxelShader.h @@ -0,0 +1,46 @@ +// +// VoxelShader.h +// interface +// +// Created by Brad Hefta-Gaub on 9/23/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__VoxelShader__ +#define __interface__VoxelShader__ + +#include + +class ProgramObject; + +/// A generic full screen glow effect. +class VoxelShader : public QObject { + Q_OBJECT + +public: + VoxelShader(); + ~VoxelShader(); + + void init(); + + /// Starts using the voxel geometry shader effect. + void begin(); + + /// Stops using the voxel geometry shader effect. + void end(); + + /// Gets access to attributes from the shader program + int attributeLocation(const char * name) const; + + static ProgramObject* createGeometryShaderProgram(const QString& name); + +public slots: + +private: + + bool _initialized; + + ProgramObject* _program; +}; + +#endif /* defined(__interface__VoxelShader__) */ From 91999dfe1f3b14c81036d336f58720a13c0a63b9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 26 Sep 2013 15:48:11 -0700 Subject: [PATCH 07/28] Pupil dilation. --- interface/src/Menu.cpp | 7 +++++ interface/src/avatar/Avatar.cpp | 2 ++ interface/src/avatar/BlendFace.cpp | 8 ++--- interface/src/avatar/BlendFace.h | 5 ++- interface/src/avatar/Head.cpp | 18 +++++------ interface/src/avatar/Head.h | 5 ++- interface/src/avatar/PerlinFace.cpp | 6 +++- interface/src/renderer/TextureCache.cpp | 41 +++++++++++++++++++++++++ interface/src/renderer/TextureCache.h | 36 ++++++++++++++++++++++ libraries/avatars/src/AvatarData.cpp | 8 ++++- libraries/avatars/src/HeadData.h | 4 +++ libraries/shared/src/PacketHeaders.cpp | 2 +- 12 files changed, 123 insertions(+), 19 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 560f72807b..77d00c393b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "Application.h" @@ -749,6 +750,10 @@ void Menu::editPreferences() { faceURL->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Face URL:", faceURL); + QSlider* pupilDilation = new QSlider(Qt::Horizontal); + pupilDilation->setValue(applicationInstance->getAvatar()->getHead().getPupilDilation() * pupilDilation->maximum()); + form->addRow("Pupil Dilation:", pupilDilation); + QSpinBox* fieldOfView = new QSpinBox(); fieldOfView->setMaximum(180); fieldOfView->setMinimum(1); @@ -790,6 +795,8 @@ void Menu::editPreferences() { Avatar::sendAvatarURLsMessage(avatarVoxelURL, faceModelURL); + applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum()); + _gyroCameraSensitivity = gyroCameraSensitivity->value(); applicationInstance->getAvatar()->setLeanScale(leanScale->value()); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 8aba7f8b4d..028bfef2ef 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -770,6 +770,7 @@ void Avatar::loadData(QSettings* settings) { _voxels.setVoxelURL(settings->value("voxelURL").toUrl()); _head.getBlendFace().setModelURL(settings->value("faceModelURL").toUrl()); + _head.setPupilDilation(settings->value("pupilDilation", 0.0f).toFloat()); _leanScale = loadSetting(settings, "leanScale", 0.05f); @@ -822,6 +823,7 @@ void Avatar::saveData(QSettings* set) { set->setValue("voxelURL", _voxels.getVoxelURL()); set->setValue("faceModelURL", _head.getBlendFace().getModelURL()); + set->setValue("pupilDilation", _head.getPupilDilation()); set->setValue("leanScale", _leanScale); set->setValue("scale", _newScale); diff --git a/interface/src/avatar/BlendFace.cpp b/interface/src/avatar/BlendFace.cpp index bb31437a1d..e531052726 100644 --- a/interface/src/avatar/BlendFace.cpp +++ b/interface/src/avatar/BlendFace.cpp @@ -28,7 +28,7 @@ BlendFace::~BlendFace() { } ProgramObject BlendFace::_eyeProgram; -GLuint BlendFace::_eyeTextureID; +DilatedTextureCache BlendFace::_eyeTextureCache("resources/images/eye.png", 50, 210); void BlendFace::init() { if (!_eyeProgram.isLinked()) { @@ -40,8 +40,6 @@ void BlendFace::init() { _eyeProgram.bind(); _eyeProgram.setUniformValue("texture", 0); _eyeProgram.release(); - - _eyeTextureID = Application::getInstance()->getTextureCache()->getFileTextureID("resources/images/eye.png"); } } @@ -92,7 +90,9 @@ bool BlendFace::render(float alpha) { // use texture coordinates only for the eye, for now glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glBindTexture(GL_TEXTURE_2D, _eyeTextureID); + _eyeTexture = _eyeTextureCache.getTexture(_owningHead->getPupilDilation()); + glBindTexture(GL_TEXTURE_2D, _eyeTexture->getID()); + glEnable(GL_TEXTURE_2D); _eyeProgram.bind(); diff --git a/interface/src/avatar/BlendFace.h b/interface/src/avatar/BlendFace.h index 8e7302a729..47b3caf758 100644 --- a/interface/src/avatar/BlendFace.h +++ b/interface/src/avatar/BlendFace.h @@ -15,6 +15,7 @@ #include "InterfaceConfig.h" #include "renderer/FBXReader.h" #include "renderer/ProgramObject.h" +#include "renderer/TextureCache.h" class QNetworkReply; @@ -62,8 +63,10 @@ private: QVector _blendedVertices; QVector _blendedNormals; + QSharedPointer _eyeTexture; + static ProgramObject _eyeProgram; - static GLuint _eyeTextureID; + static DilatedTextureCache _eyeTextureCache; }; #endif /* defined(__interface__BlendFace__) */ diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 2e17ad3557..6e437780e9 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -29,7 +29,7 @@ const float EYEBALL_RADIUS = 0.017; const float EYELID_RADIUS = 0.019; const float EYEBALL_COLOR[3] = { 0.9f, 0.9f, 0.8f }; -const float HAIR_SPRING_FORCE = 15.0f; +const float HAIR_SPRING_FORCE = 15.0f; const float HAIR_TORQUE_FORCE = 0.2f; const float HAIR_GRAVITY_FORCE = 0.001f; const float HAIR_DRAG = 10.0f; @@ -46,7 +46,7 @@ const float IRIS_PROTRUSION = 0.0145f; const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png"; ProgramObject Head::_irisProgram; -GLuint Head::_irisTextureID; +DilatedTextureCache Head::_irisTextureCache(IRIS_TEXTURE_FILENAME, 53, 127); int Head::_eyePositionLocation; Head::Head(Avatar* owningAvatar) : @@ -102,13 +102,6 @@ void Head::init() { _irisProgram.setUniformValue("texture", 0); _eyePositionLocation = _irisProgram.uniformLocation("eyePosition"); - - _irisTextureID = Application::getInstance()->getTextureCache()->getFileTextureID(IRIS_TEXTURE_FILENAME); - - glBindTexture(GL_TEXTURE_2D, _irisTextureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glBindTexture(GL_TEXTURE_2D, 0); } _blendFace.init(); } @@ -667,7 +660,12 @@ void Head::renderEyeBalls() { glPopMatrix(); _irisProgram.bind(); - glBindTexture(GL_TEXTURE_2D, _irisTextureID); + + _irisTexture = _irisTextureCache.getTexture(_pupilDilation); + glBindTexture(GL_TEXTURE_2D, _irisTexture->getID()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glEnable(GL_TEXTURE_2D); // render left iris diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 4c535edcba..ab07227fc6 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -24,6 +24,7 @@ #include "PerlinFace.h" #include "world.h" #include "devices/SerialInterface.h" +#include "renderer/TextureCache.h" enum eyeContactTargets { LEFT_EYE, @@ -135,8 +136,10 @@ private: PerlinFace _perlinFace; BlendFace _blendFace; + QSharedPointer _irisTexture; + static ProgramObject _irisProgram; - static GLuint _irisTextureID; + static DilatedTextureCache _irisTextureCache; static int _eyePositionLocation; // private methods diff --git a/interface/src/avatar/PerlinFace.cpp b/interface/src/avatar/PerlinFace.cpp index 41641673af..5784c51e67 100644 --- a/interface/src/avatar/PerlinFace.cpp +++ b/interface/src/avatar/PerlinFace.cpp @@ -248,7 +248,11 @@ void PerlinFace::render() { Head::_irisProgram.bind(); - glBindTexture(GL_TEXTURE_2D, Head::_irisTextureID); + _owningHead->_irisTexture = Head::_irisTextureCache.getTexture(_owningHead->_pupilDilation); + glBindTexture(GL_TEXTURE_2D, _owningHead->_irisTexture->getID()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glEnable(GL_TEXTURE_2D); orientation = _owningHead->getOrientation(); diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 3d04a828fc..ebb9c77890 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -154,3 +154,44 @@ QOpenGLFramebufferObject* TextureCache::createFramebufferObject() { return fbo; } + +Texture::Texture() { + glGenTextures(1, &_id); +} + +Texture::~Texture() { + glDeleteTextures(1, &_id); +} + +DilatedTextureCache::DilatedTextureCache(const QString& filename, int innerRadius, int outerRadius) : + _innerRadius(innerRadius), + _outerRadius(outerRadius) +{ + switchToResourcesParentIfRequired(); + _image = QImage(filename).convertToFormat(QImage::Format_ARGB32); +} + +QSharedPointer DilatedTextureCache::getTexture(float dilation) { + QSharedPointer texture = _textures.value(dilation); + if (texture.isNull()) { + texture = QSharedPointer(new Texture()); + + QImage dilatedImage = _image; + QPainter painter; + painter.begin(&dilatedImage); + QPainterPath path; + qreal radius = glm::mix(_innerRadius, _outerRadius, dilation); + path.addEllipse(QPointF(_image.width() / 2.0, _image.height() / 2.0), radius, radius); + painter.fillPath(path, Qt::black); + painter.end(); + + glBindTexture(GL_TEXTURE_2D, texture->getID()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dilatedImage.width(), dilatedImage.height(), 1, + GL_BGRA, GL_UNSIGNED_BYTE, dilatedImage.constBits()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + _textures.insert(dilation, texture); + } + return texture; +} diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index a970b1373c..11a847d838 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -10,7 +10,11 @@ #define __interface__TextureCache__ #include +#include +#include #include +#include +#include #include "InterfaceConfig.h" @@ -62,4 +66,36 @@ private: QOpenGLFramebufferObject* _tertiaryFramebufferObject; }; +/// A simple object wrapper for an OpenGL texture. +class Texture { +public: + + Texture(); + ~Texture(); + + GLuint getID() const { return _id; } + +private: + + GLuint _id; +}; + +/// Caches textures according to pupillary dilation. +class DilatedTextureCache { +public: + + DilatedTextureCache(const QString& filename, int innerRadius, int outerRadius); + + /// Returns a pointer to a texture with the requested amount of dilation. + QSharedPointer getTexture(float dilation); + +private: + + QImage _image; + int _innerRadius; + int _outerRadius; + + QMap > _textures; +}; + #endif /* defined(__interface__TextureCache__) */ diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index dab3d1651e..edc76bedca 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -211,6 +211,9 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += _headData->_blendshapeCoefficients.size() * sizeof(float); } + // pupil dilation + destinationBuffer += packFloatToByte(destinationBuffer, _headData->_pupilDilation, 1.0f); + // leap hand data destinationBuffer += _handData->encodeRemoteData(destinationBuffer); @@ -345,7 +348,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { _headData->_blendshapeCoefficients.size() * sizeof(float)); sourceBuffer += _headData->_blendshapeCoefficients.size() * sizeof(float); } - + + // pupil dilation + sourceBuffer += unpackFloatFromByte(sourceBuffer, _headData->_pupilDilation, 1.0f); + // leap hand data if (sourceBuffer - startPosition < numBytes) { // check passed, bytes match diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 88895a58f6..0f096059c0 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -46,6 +46,9 @@ public: const std::vector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } + float getPupilDilation() const { return _pupilDilation; } + void setPupilDilation(float pupilDilation) { _pupilDilation = pupilDilation; } + void addYaw(float yaw); void addPitch(float pitch); void addRoll(float roll); @@ -70,6 +73,7 @@ protected: float _averageLoudness; float _browAudioLift; std::vector _blendshapeCoefficients; + float _pupilDilation; AvatarData* _owningAvatar; private: diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index c3e67fb10f..1d5eb3f5d4 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -20,7 +20,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 1; case PACKET_TYPE_HEAD_DATA: - return 7; + return 8; case PACKET_TYPE_AVATAR_URLS: return 1; From 78453402792d296f277574ae657759f6262fbb63 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 16:26:49 -0700 Subject: [PATCH 08/28] menu cleanup, support for on the fly switching of maxVoxels and useVoxelShader --- interface/src/Application.cpp | 12 +- interface/src/Menu.cpp | 51 ++++- interface/src/Menu.h | 5 + interface/src/VoxelSystem.cpp | 313 ++++++++++++++------------ interface/src/VoxelSystem.h | 13 +- libraries/voxels/src/VoxelConstants.h | 2 +- 6 files changed, 237 insertions(+), 159 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b10ed430bf..1f231b9e2f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1521,7 +1521,6 @@ void Application::initDisplay() { } void Application::init() { - _voxels.init(); _sharedVoxelSystemViewFrustum.setPosition(glm::vec3(TREE_SCALE / 2.0f, TREE_SCALE / 2.0f, 3.0f * TREE_SCALE / 2.0f)); @@ -1573,9 +1572,13 @@ void Application::init() { if (Menu::getInstance()->getAudioJitterBufferSamples() != 0) { _audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples()); } - qDebug("Loaded settings.\n"); + // Set up VoxelSystem after loading preferences so we can get the desired max voxel count + _voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels()); + _voxels.init(); + + Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL(), _myAvatar.getHead().getBlendFace().getModelURL()); _palette.init(_glWidget->width(), _glWidget->height()); @@ -2915,7 +2918,10 @@ void Application::displayStats() { std::stringstream voxelStats; voxelStats.precision(4); - voxelStats << "Voxels Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K Updated: " << _voxels.getVoxelsUpdated()/1000.f << "K"; + voxelStats << "Voxels Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K " << + "Updated: " << _voxels.getVoxelsUpdated()/1000.f << "K " << + "Max: " << _voxels.getMaxVoxels()/1000.f << "K "; + drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6f385c3e99..3fd9334830 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -48,7 +48,8 @@ Menu::Menu() : _frustumDrawMode(FRUSTUM_DRAW_MODE_ALL), _viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET), _voxelModeActionsGroup(NULL), - _voxelStatsDialog(NULL) + _voxelStatsDialog(NULL), + _maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM) { Application *appInstance = Application::getInstance(); @@ -249,7 +250,8 @@ Menu::Menu() : SLOT(setRenderVoxels(bool))); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); - addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader); + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader, 0, + false, this, SLOT(switchVoxelShader())); QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); @@ -485,6 +487,7 @@ void Menu::loadSettings(QSettings* settings) { _gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f); _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); + _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); settings->beginGroup("View Frustum Offset Camera"); // in case settings is corrupt or missing loadSetting() will check for NaN @@ -508,6 +511,7 @@ void Menu::saveSettings(QSettings* settings) { settings->setValue("gyroCameraSensitivity", _gyroCameraSensitivity); settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples); settings->setValue("fieldOfView", _fieldOfView); + settings->setValue("maxVoxels", _maxVoxels); settings->beginGroup("View Frustum Offset Camera"); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch); @@ -755,9 +759,6 @@ void Menu::editPreferences() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); - QLineEdit* domainServerLineEdit = lineEditForDomainHostname(); - form->addRow("Domain server:", domainServerLineEdit); - QLineEdit* avatarURL = new QLineEdit(applicationInstance->getAvatar()->getVoxels()->getVoxelURL().toString()); avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Avatar URL:", avatarURL); @@ -785,6 +786,13 @@ void Menu::editPreferences() { audioJitterBufferSamples->setMinimum(-10000); audioJitterBufferSamples->setValue(_audioJitterBufferSamples); form->addRow("Audio Jitter Buffer Samples (0 for automatic):", audioJitterBufferSamples); + + QSpinBox* maxVoxels = new QSpinBox(); + maxVoxels->setMaximum(5000000); + maxVoxels->setMinimum(0); + maxVoxels->setSingleStep(50000); + maxVoxels->setValue(_maxVoxels); + form->addRow("Maximum Voxels:", maxVoxels); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); @@ -797,8 +805,6 @@ void Menu::editPreferences() { return; } - updateDSHostname(domainServerLineEdit->text()); - QUrl avatarVoxelURL(avatarURL->text()); applicationInstance->getAvatar()->getVoxels()->setVoxelURL(avatarVoxelURL); @@ -808,6 +814,8 @@ void Menu::editPreferences() { Avatar::sendAvatarURLsMessage(avatarVoxelURL, faceModelURL); _gyroCameraSensitivity = gyroCameraSensitivity->value(); + _maxVoxels = maxVoxels->value(); + applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels); applicationInstance->getAvatar()->setLeanScale(leanScale->value()); @@ -1007,3 +1015,32 @@ void Menu::updateFrustumRenderModeAction() { break; } } + +void Menu::switchVoxelShader() { + Application::getInstance()->getVoxels()->setUseVoxelShader(isOptionChecked(MenuOption::UseVoxelShader)); +} + +void Menu::displayGPUMemory() { + + 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]); + + // NVIDIA + // http://developer.download.nvidia.com/opengl/specs/GL_NVX_gpu_memory_info.txt + // + // GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 + // GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 + // GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 + // GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A + // GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B + + +} diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a30fc4cdb0..332f89176c 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -54,6 +54,8 @@ public: FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; } ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; } VoxelStatsDialog* getVoxelStatsDialog() const { return _voxelStatsDialog; } + int getMaxVoxels() const { return _maxVoxels; } + void handleViewFrustumOffsetKeyModifier(int key); @@ -78,6 +80,8 @@ private slots: void chooseVoxelPaintColor(); void runTests(); void resetSwatchColors(); + void displayGPUMemory(); + void switchVoxelShader(); private: static Menu* _instance; @@ -115,6 +119,7 @@ private: ViewFrustumOffset _viewFrustumOffset; QActionGroup* _voxelModeActionsGroup; VoxelStatsDialog* _voxelStatsDialog; + int _maxVoxels; }; namespace MenuOption { diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 759a2f178a..b430afdd10 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -74,9 +74,8 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float))); connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int))); - - _voxelShaderInitialized = false; - _initializingVoxelShader = false; + + _useVoxelShader = false; _writeVoxelShaderData = NULL; _readVoxelShaderData = NULL; @@ -132,28 +131,7 @@ void VoxelSystem::clearFreeBufferIndexes() { } VoxelSystem::~VoxelSystem() { - if (_initialized) { - // Destroy glBuffers - glDeleteBuffers(1, &_vboVerticesID); - glDeleteBuffers(1, &_vboNormalsID); - glDeleteBuffers(1, &_vboColorsID); - glDeleteBuffers(1, &_vboIndicesID); - - delete[] _readVerticesArray; - delete[] _writeVerticesArray; - delete[] _readColorsArray; - delete[] _writeColorsArray; - delete[] _writeVoxelDirtyArray; - delete[] _readVoxelDirtyArray; - - // these are used when in VoxelShader mode. - glDeleteBuffers(1, &_vboVoxelsID); - glDeleteBuffers(1, &_vboVoxelsIndicesID); - - delete[] _writeVoxelShaderData; - delete[] _readVoxelShaderData; - } - + cleanupVoxelMemory(); delete _tree; pthread_mutex_destroy(&_bufferWriteLock); pthread_mutex_destroy(&_treeLock); @@ -161,43 +139,172 @@ VoxelSystem::~VoxelSystem() { VoxelNode::removeDeleteHook(this); } -bool VoxelSystem::getUseVoxelShader() { - bool useVoxelShader = false; //Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader); - - return useVoxelShader; +void VoxelSystem::setMaxVoxels(int maxVoxels) { + pthread_mutex_lock(&_bufferWriteLock); + bool wasInitialized = _initialized; + if (wasInitialized) { + cleanupVoxelMemory(); + } + _maxVoxels = maxVoxels; + if (wasInitialized) { + init(); + } + pthread_mutex_unlock(&_bufferWriteLock); } -void VoxelSystem::initVoxelShader() { - GLuint* indicesArray = new GLuint[_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++) { - indicesArray[n] = n; +void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { + pthread_mutex_lock(&_bufferWriteLock); + bool wasInitialized = _initialized; + if (wasInitialized) { + cleanupVoxelMemory(); } + _useVoxelShader = useVoxelShader; + if (wasInitialized) { + init(); + } + pthread_mutex_unlock(&_bufferWriteLock); +} - // bind the indices VBO to the actual indices array - glGenBuffers(1, &_vboVoxelsIndicesID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _maxVoxels, indicesArray, GL_STATIC_DRAW); +void VoxelSystem::cleanupVoxelMemory() { + if (_initialized) { + if (_useVoxelShader) { + // these are used when in VoxelShader mode. + glDeleteBuffers(1, &_vboVoxelsID); + glDeleteBuffers(1, &_vboVoxelsIndicesID); + + delete[] _writeVoxelShaderData; + delete[] _readVoxelShaderData; + } else { + // Destroy glBuffers + glDeleteBuffers(1, &_vboVerticesID); + glDeleteBuffers(1, &_vboNormalsID); + glDeleteBuffers(1, &_vboColorsID); + glDeleteBuffers(1, &_vboIndicesID); + + delete[] _readVerticesArray; + delete[] _writeVerticesArray; + delete[] _readColorsArray; + delete[] _writeColorsArray; + delete[] _writeVoxelDirtyArray; + delete[] _readVoxelDirtyArray; + } + } + _initialized = false; // no longer initialized +} + +void VoxelSystem::initVoxelMemory() { + if (_useVoxelShader) { + GLuint* indicesArray = new GLuint[_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++) { + indicesArray[n] = n; + } + + // bind the indices VBO to the actual indices array + glGenBuffers(1, &_vboVoxelsIndicesID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, _maxVoxels, indicesArray, GL_STATIC_DRAW); - glGenBuffers(1, &_vboVoxelsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); - glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW); + glGenBuffers(1, &_vboVoxelsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW); - // delete the indices and normals arrays that are no longer needed - delete[] indicesArray; + // delete the indices and normals arrays that are no longer needed + delete[] indicesArray; - // we will track individual dirty sections with these arrays of bools - _writeVoxelDirtyArray = new bool[_maxVoxels]; - memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - _readVoxelDirtyArray = new bool[_maxVoxels]; - memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + // we will track individual dirty sections with these arrays of bools + _writeVoxelDirtyArray = new bool[_maxVoxels]; + memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; + memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - // prep the data structures for incoming voxel data - _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; - _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + // prep the data structures for incoming voxel data + _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + } else { + GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; + + // populate the indicesArray + // this will not change given new voxels, so we can set it all up now + for (int n = 0; n < _maxVoxels; n++) { + // fill the indices array + int voxelIndexOffset = n * INDICES_PER_VOXEL; + GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; + int startIndex = (n * VERTICES_PER_VOXEL); + + for (int i = 0; i < INDICES_PER_VOXEL; i++) { + // add indices for this side of the cube + currentIndicesPos[i] = startIndex + identityIndices[i]; + } + } + + 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]; + } + } + + glGenBuffers(1, &_vboVerticesID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + + // 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); + + // VBO for colorsArray + glGenBuffers(1, &_vboColorsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + + // 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; + delete[] normalsArray; + + + // we will track individual dirty sections with these arrays of bools + _writeVoxelDirtyArray = new bool[_maxVoxels]; + memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; + memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + + // prep the data structures for incoming voxel data + _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + + _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + + + // create our simple fragment shader if we're the first system to init + if (!_perlinModulateProgram.isLinked()) { + switchToResourcesParentIfRequired(); + _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); + _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); + _perlinModulateProgram.link(); + + _perlinModulateProgram.bind(); + _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); + _perlinModulateProgram.release(); + } + } } void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { @@ -457,7 +564,7 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { int segmentLength = (segmentEnd - segmentStart) + 1; - if (getUseVoxelShader()) { + if (_useVoxelShader) { GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); void* readDataAt = &_readVoxelShaderData[segmentStart]; void* writeDataAt = &_writeVoxelShaderData[segmentStart]; @@ -598,7 +705,7 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex, float voxelScale, const nodeColor& color) { - if (getUseVoxelShader()) { + if (_useVoxelShader) { VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; writeVerticesAt->x = startVertex.x * TREE_SCALE; writeVerticesAt->y = startVertex.y * TREE_SCALE; @@ -647,89 +754,7 @@ void VoxelSystem::init() { _voxelsInReadArrays = 0; // VBO for the verticesArray - //initVoxelShader(); - - if (true) { - 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]; - } - } - - 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]; - } - } - - glGenBuffers(1, &_vboVerticesID); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - - // 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); - - // VBO for colorsArray - glGenBuffers(1, &_vboColorsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - - // 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; - delete[] normalsArray; - - - // we will track individual dirty sections with these arrays of bools - _writeVoxelDirtyArray = new bool[_maxVoxels]; - memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - _readVoxelDirtyArray = new bool[_maxVoxels]; - memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - - // prep the data structures for incoming voxel data - _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - - _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - - - // create our simple fragment shader if we're the first system to init - if (!_perlinModulateProgram.isLinked()) { - switchToResourcesParentIfRequired(); - _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); - _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); - _perlinModulateProgram.link(); - - _perlinModulateProgram.bind(); - _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); - _perlinModulateProgram.release(); - } - } + initVoxelMemory(); _initialized = true; } @@ -801,7 +826,7 @@ void VoxelSystem::updateVBOs() { } void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) { - if (getUseVoxelShader()) { + if (_useVoxelShader) { int segmentLength = (segmentEnd - segmentStart) + 1; GLintptr segmentStartAt = segmentStart * sizeof(VoxelShaderVBOData); GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); @@ -839,9 +864,9 @@ void VoxelSystem::render(bool texture) { updateVBOs(); - //printf("render() _voxelsInReadArrays=%lu voxel shader=%s\n", _voxelsInReadArrays, debug::valueOf(getUseVoxelShader())); + //printf("render() _voxelsInReadArrays=%lu voxel shader=%s\n", _voxelsInReadArrays, debug::valueOf(_useVoxelShader)); - if (getUseVoxelShader()) { + if (_useVoxelShader) { Application::getInstance()->getVoxelShader().begin(); @@ -1349,7 +1374,7 @@ public: duplicateVBOIndex(0), leafNodes(0) { - memset(hasIndexFound, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); + memset(hasIndexFound, false, DEFAULT_MAX_VOXELS_PER_SYSTEM * sizeof(bool)); }; unsigned long totalNodes; @@ -1364,7 +1389,7 @@ public: unsigned long expectedMax; - bool hasIndexFound[MAX_VOXELS_PER_SYSTEM]; + bool hasIndexFound[DEFAULT_MAX_VOXELS_PER_SYSTEM]; }; bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData) { @@ -1439,7 +1464,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; glBufferIndex maxInVBO = 0; - for (glBufferIndex i = 0; i < MAX_VOXELS_PER_SYSTEM; i++) { + for (glBufferIndex i = 0; i < DEFAULT_MAX_VOXELS_PER_SYSTEM; i++) { if (args.hasIndexFound[i]) { minInVBO = std::min(minInVBO,i); maxInVBO = std::max(maxInVBO,i); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index fe088ce042..7a44034590 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -40,7 +40,7 @@ struct VoxelShaderVBOData class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook { Q_OBJECT public: - VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM); + VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = DEFAULT_MAX_VOXELS_PER_SYSTEM); ~VoxelSystem(); void setDataSourceID(int dataSourceID) { _dataSourceID = dataSourceID; } @@ -65,6 +65,10 @@ public: bool readFromSquareARGB32Pixels(const char* filename); bool readFromSchematicFile(const char* filename); + void setUseVoxelShader(bool useVoxelShader); + + void setMaxVoxels(int maxVoxels); + long int getMaxVoxels() const { return _maxVoxels; } long int getVoxelsCreated(); long int getVoxelsColored(); long int getVoxelsBytesRead(); @@ -200,9 +204,10 @@ private: int _lastViewCullingElapsed; bool getUseVoxelShader(); - void initVoxelShader(); - bool _voxelShaderInitialized; - bool _initializingVoxelShader; + void initVoxelMemory(); + void cleanupVoxelMemory(); + + bool _useVoxelShader; 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 VoxelShaderVBOData* _writeVoxelShaderData; diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 1c6e6cd0e6..0e89ab9cdb 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -32,7 +32,7 @@ const float VOXEL_SIZE_SCALE = TREE_SCALE * 400.0f; const int NUMBER_OF_CHILDREN = 8; const int MAX_VOXEL_PACKET_SIZE = 1492; const int MAX_TREE_SLICE_BYTES = 26; -const int MAX_VOXELS_PER_SYSTEM = 200000; +const int DEFAULT_MAX_VOXELS_PER_SYSTEM = 200000; const int VERTICES_PER_VOXEL = 24; // 6 sides * 4 corners per side const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; // ???? xyz for each VERTICE_PER_VOXEL?? const int INDICES_PER_VOXEL = 3 * 12; // 6 sides * 2 triangles per size * 3 vertices per triangle From fd0cc3b417368c82407b583931852628446f0986 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 16:33:37 -0700 Subject: [PATCH 09/28] style fixes --- interface/src/Application.cpp | 85 ----------------------------------- interface/src/Menu.cpp | 9 ++-- 2 files changed, 6 insertions(+), 88 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1f231b9e2f..1659127def 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2589,91 +2589,6 @@ void Application::displaySide(Camera& whichCamera) { renderViewFrustum(_viewFrustum); } - // brad's voxel shader debugging - if (false) { - - const float TEST_STRIP_COLOR[] = { 0.0f, 1.0f, 0.0f }; - glColor3fv(TEST_STRIP_COLOR); - - _voxelShader.begin(); - const float VOXEL_COLOR[] = { 1.0f, 0.0f, 0.0f }; - glColor3fv(VOXEL_COLOR); - - struct VoxelData - { - float x, y, z; // position - float s; // size - unsigned char r,g,b; // color - }; - - VoxelData voxels[3]; - - //VERTEX 0 - voxels[0].x = 0.0; - voxels[0].y = 0.0; - voxels[0].z = 1.0; - voxels[0].s = 0.1; - voxels[0].r = 255; - voxels[0].g = 0; - voxels[0].b = 0; - - //VERTEX 1 - voxels[1].x = 1.0; - voxels[1].y = 0.0; - voxels[1].z = 0.0; - voxels[1].s = 0.2; - voxels[1].r = 0; - voxels[1].g = 255; - voxels[1].b = 0; - - //VERTEX 2 - voxels[2].x = 0.0; - voxels[2].y = 1.0; - voxels[2].z = 0.0; - voxels[2].s = 0.3; - voxels[2].r = 0; - voxels[2].g = 0; - voxels[2].b = 255; - - GLuint VertexVBOID; - GLuint IndexVBOID; - - glGenBuffers(1, &VertexVBOID); - glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID); - glBufferData(GL_ARRAY_BUFFER, sizeof(voxels), &voxels[0].x, GL_STATIC_DRAW); - - ushort indices[3]; - indices[0] = 0; - indices[1] = 1; - indices[2] = 2; - - glGenBuffers(1, &IndexVBOID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); - - //Define this somewhere in your header file - #define BUFFER_OFFSET(i) ((void*)(i)) - - glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, sizeof(VoxelData), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices - int loc = _voxelShader.attributeLocation("voxelSizeIn"); - glEnableVertexAttribArray(loc); - glVertexAttribPointer(loc, 1, GL_FLOAT, false, sizeof(VoxelData), BUFFER_OFFSET(3*sizeof(float))); - - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelData), BUFFER_OFFSET(4*sizeof(float)));//The starting point of colors - - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID); - glDrawElements(GL_POINTS, 3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); //The starting point of the IBO - - glDeleteBuffers(1, &VertexVBOID); - glDeleteBuffers(1, &IndexVBOID); - - _voxelShader.end(); - } - // render voxel fades if they exist if (_voxelFades.size() > 0) { for(std::vector::iterator fade = _voxelFades.begin(); fade != _voxelFades.end();) { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3fd9334830..ec322def85 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -788,9 +788,12 @@ void Menu::editPreferences() { form->addRow("Audio Jitter Buffer Samples (0 for automatic):", audioJitterBufferSamples); QSpinBox* maxVoxels = new QSpinBox(); - maxVoxels->setMaximum(5000000); - maxVoxels->setMinimum(0); - maxVoxels->setSingleStep(50000); + const int MAX_MAX_VOXELS = 5000000; + const int MIN_MAX_VOXELS = 0; + const int STEP_MAX_VOXELS = 50000; + maxVoxels->setMaximum(MAX_MAX_VOXELS); + maxVoxels->setMinimum(MIN_MAX_VOXELS); + maxVoxels->setSingleStep(STEP_MAX_VOXELS); maxVoxels->setValue(_maxVoxels); form->addRow("Maximum Voxels:", maxVoxels); From 5695429a7883f08e6e03a24f96d1a42a72224b7e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 16:36:59 -0700 Subject: [PATCH 10/28] style fixes --- interface/src/VoxelSystem.cpp | 24 ------------------------ libraries/voxels/src/VoxelConstants.h | 2 +- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index b430afdd10..86d8704905 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -714,12 +714,6 @@ void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& s writeVerticesAt->r = color[RED_INDEX]; writeVerticesAt->g = color[GREEN_INDEX]; writeVerticesAt->b = color[BLUE_INDEX]; - - /** - printf("updateNodeInArrays() nodeIndex=%lu writeVerticesAt=[%f,%f,%f,%f (%u,%u,%u)]\n", - nodeIndex, writeVerticesAt->x, writeVerticesAt->y, writeVerticesAt->z, writeVerticesAt->s, - writeVerticesAt->r, writeVerticesAt->g, writeVerticesAt->b ); - **/ } else { for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); @@ -841,18 +835,11 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); -//printf("VoxelSystem::updateVBOSegment() segmentStart=%lu, segmentEnd=%lu, segmentSizeBytes=%lu \n", -// segmentStart, segmentEnd, segmentSizeBytes); - - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); - -//printf("VoxelSystem::updateVBOSegment() segmentStart=%lu, segmentEnd=%lu, segmentSizeBytes=%lu \n", -// segmentStart, segmentEnd, segmentSizeBytes); } } @@ -864,8 +851,6 @@ void VoxelSystem::render(bool texture) { updateVBOs(); - //printf("render() _voxelsInReadArrays=%lu voxel shader=%s\n", _voxelsInReadArrays, debug::valueOf(_useVoxelShader)); - if (_useVoxelShader) { Application::getInstance()->getVoxelShader().begin(); @@ -885,15 +870,6 @@ void VoxelSystem::render(bool texture) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); glDrawElements(GL_POINTS, _voxelsInReadArrays, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); //The starting point of the IBO - /** - for (int i=0; i < _voxelsInReadArrays; i++) { - VoxelShaderVBOData* readDataAt = &_readVoxelShaderData[i]; - printf("render() _voxelsInReadArrays=%lu i=%d readDataAt=[%f,%f,%f,%f (%u,%u,%u)]\n", - _voxelsInReadArrays, i, readDataAt->x, readDataAt->y, readDataAt->z, readDataAt->s, - readDataAt->r, readDataAt->g, readDataAt->b ); - } - **/ - // deactivate vertex and color arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 0e89ab9cdb..391be29282 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -34,7 +34,7 @@ const int MAX_VOXEL_PACKET_SIZE = 1492; const int MAX_TREE_SLICE_BYTES = 26; const int DEFAULT_MAX_VOXELS_PER_SYSTEM = 200000; const int VERTICES_PER_VOXEL = 24; // 6 sides * 4 corners per side -const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; // ???? xyz for each VERTICE_PER_VOXEL?? +const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; // xyz for each VERTICE_PER_VOXEL 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; From 864c00c6e02b604cb13fca26af95967f05072b35 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 16:38:29 -0700 Subject: [PATCH 11/28] removed some dead code --- .../resources/shaders/duplicate_geometry.geom | 46 ----------- interface/resources/shaders/passthrough.geom | 82 ------------------- 2 files changed, 128 deletions(-) delete mode 100644 interface/resources/shaders/duplicate_geometry.geom delete mode 100644 interface/resources/shaders/passthrough.geom diff --git a/interface/resources/shaders/duplicate_geometry.geom b/interface/resources/shaders/duplicate_geometry.geom deleted file mode 100644 index 2ab92fc4e3..0000000000 --- a/interface/resources/shaders/duplicate_geometry.geom +++ /dev/null @@ -1,46 +0,0 @@ -#version 420 - -layout(triangles) in; -layout (triangle_strip, max_vertices=6) out; - -layout (std140) uniform Matrices { - mat4 projModelViewMatrix; - mat3 normalMatrix; -}; - -in VertexData { - vec2 texCoord; - vec3 normal; -} VertexIn[]; - -out VertexData { - vec2 texCoord; - vec3 normal; -} VertexOut; - -void main() -{ - for(int i = 0; i < gl_in.length(); i++) - { - // copy attributes - gl_Position = projModelViewMatrix * gl_in[i].gl_Position; - VertexOut.normal = normalize(normalMatrix * VertexIn[i].normal); - VertexOut.texCoord = VertexIn[i].texCoord; - - // done with the vertex - EmitVertex(); - } - EndPrimitive(); - - for(int i = 0; i < gl_in.length(); i++) - { - // copy attributes and displace copy - gl_Position = projModelViewMatrix * (gl_in[i].gl_Position + vec4(20.0, 0.0, 0.0, 0.0)); - VertexOut.normal = normalize(normalMatrix * VertexIn[i].normal); - VertexOut.texCoord = VertexIn[i].texCoord; - - // done with the vertex - EmitVertex(); - } - EndPrimitive(); -} diff --git a/interface/resources/shaders/passthrough.geom b/interface/resources/shaders/passthrough.geom deleted file mode 100644 index 4ea2959b19..0000000000 --- a/interface/resources/shaders/passthrough.geom +++ /dev/null @@ -1,82 +0,0 @@ -#version 120 -#extension GL_ARB_geometry_shader4 : enable - -// use GL_POINTS -// have point be the corner of voxel -// have a second dataset (? similar to how voxel avatars pass in bones??) -// which is the voxel size? -// -// In vertex shader DON'T transform.. therefor passing the world coordinate xyz to geometric shader -// In geometric shader calculate xyz for triangles the same way we currently do triangles outside of OpenGL -// do transform on these triangles -// gl_Position = gl_ModelViewProjectionMatrix * cube_coord; -// -// output GL_TRIANGLE_STRIP -// -// NOTE: updateNodeInArrays() does the covert from voxel corner to 12 triangles or 36 points or 36*3 floats -// but since it operates on the array of floats, it is kinda weird and hard to follow. The %3 is for the -// xyz.. and identityVertices[j] term in the math is actually a string of floats but they should be thought -// of as triplets of x,y,z -// -// do we need to add the light to these colors?? -// - -//GEOMETRY SHADER -/////////////////////// -void main() -{ - //increment variable - int i; - vec4 vertex; - vec4 color,red,green,blue; - - green = vec4(0,1.0,0,1.0); - red = vec4(1.0,0,0,1.0); - blue = vec4(0,0,1.0,1.0); - - ///////////////////////////////////////////////////////////// - //This example has two parts - // step a) draw the primitive pushed down the pipeline - // there are gl_VerticesIn # of vertices - // put the vertex value into gl_Position - // use EmitVertex => 'create' a new vertex - // use EndPrimitive to signal that you are done creating a primitive! - // step b) create a new piece of geometry - // I just do the same loop, but I negate the vertex.z - // result => the primitive is now mirrored. - //Pass-thru! - for(i = 0; i < gl_VerticesIn; i++) { - color = gl_FrontColorIn[i]; - gl_FrontColor = color; // - gl_Position = gl_ModelViewProjectionMatrix * gl_PositionIn[i]; - EmitVertex(); - } - EndPrimitive(); - - for(i = 0; i < gl_VerticesIn; i++) { - gl_FrontColor = red; // - vertex = gl_PositionIn[i]; - vertex.y += 0.05f; - gl_Position = gl_ModelViewProjectionMatrix * vertex; - EmitVertex(); - } - EndPrimitive(); - - for(i = 0; i < gl_VerticesIn; i++) { - gl_FrontColor = green; // - vertex = gl_PositionIn[i]; - vertex.x += 0.05f; - gl_Position = gl_ModelViewProjectionMatrix * vertex; - EmitVertex(); - } - EndPrimitive(); - - for(i = 0; i < gl_VerticesIn; i++) { - gl_FrontColor = blue; // - vertex = gl_PositionIn[i]; - vertex.z += 0.05f; - gl_Position = gl_ModelViewProjectionMatrix * vertex; - EmitVertex(); - } - EndPrimitive(); -} \ No newline at end of file From 57b30c13d89284a1bd7772eb8f39ca1c6b8f5c88 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 16:45:09 -0700 Subject: [PATCH 12/28] style cleanup --- interface/resources/shaders/passthrough.vert | 6 ++--- interface/resources/shaders/voxel.geom | 27 +++++--------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/interface/resources/shaders/passthrough.vert b/interface/resources/shaders/passthrough.vert index f770ab115f..af55842c67 100644 --- a/interface/resources/shaders/passthrough.vert +++ b/interface/resources/shaders/passthrough.vert @@ -4,7 +4,7 @@ attribute float voxelSizeIn; varying float voxelSize; void main(void) { - gl_FrontColor = gl_Color; //vec4(1.0, 0.0, 0.0, 1.0); - gl_Position = gl_ModelViewMatrix * gl_Vertex;// ftransform(); - voxelSize = voxelSizeIn; + gl_FrontColor = gl_Color; + gl_Position = gl_ModelViewMatrix * gl_Vertex; // don't call ftransform(), because we do projection in geometry shader + voxelSize = voxelSizeIn; } \ No newline at end of file diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom index d3f0b89f10..0ea4075f65 100644 --- a/interface/resources/shaders/voxel.geom +++ b/interface/resources/shaders/voxel.geom @@ -47,8 +47,7 @@ void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec } -void main() -{ +void main() { //increment variable int i; vec4 corner; @@ -61,26 +60,14 @@ void main() 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 ); - vec4 color,red,green,blue,yellow,cyan,purple; - - green = vec4(0,1.0,0,1.0); - red = vec4(1.0,0,0,1.0); - blue = vec4(0,0,1.0,1.0); - yellow = vec4(1.0,1.0,0,1.0); - cyan = vec4(0,1.0,1.0,1.0); - purple = vec4(1.0,0,1.0,1.0); - for(i = 0; i < gl_VerticesIn; i++) { - gl_FrontColor = gl_FrontColorIn[i]; corner = gl_PositionIn[i]; scale = voxelSize[i]; - color = gl_FrontColorIn[i]; - - faceOfVoxel(corner, scale, bottomFace, color); - faceOfVoxel(corner, scale, topFace, color); - faceOfVoxel(corner, scale, rightFace, color); - faceOfVoxel(corner, scale, leftFace, color); - faceOfVoxel(corner, scale, frontFace, color); - faceOfVoxel(corner, scale, backFace, color); + faceOfVoxel(corner, scale, bottomFace, gl_FrontColorIn[i]); + faceOfVoxel(corner, scale, topFace, gl_FrontColorIn[i]); + faceOfVoxel(corner, scale, rightFace, gl_FrontColorIn[i]); + faceOfVoxel(corner, scale, leftFace, gl_FrontColorIn[i]); + faceOfVoxel(corner, scale, frontFace, gl_FrontColorIn[i]); + faceOfVoxel(corner, scale, backFace, gl_FrontColorIn[i]); } } \ No newline at end of file From 3f8e55da28e3c919afa802151857b33cf9881eed Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 16:46:34 -0700 Subject: [PATCH 13/28] style cleanup --- interface/src/Menu.cpp | 24 ------------------------ interface/src/Menu.h | 1 - 2 files changed, 25 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ec322def85..89ce92052e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1023,27 +1023,3 @@ void Menu::switchVoxelShader() { Application::getInstance()->getVoxels()->setUseVoxelShader(isOptionChecked(MenuOption::UseVoxelShader)); } -void Menu::displayGPUMemory() { - - 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]); - - // NVIDIA - // http://developer.download.nvidia.com/opengl/specs/GL_NVX_gpu_memory_info.txt - // - // GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 - // GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 - // GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 - // GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A - // GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B - - -} diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 332f89176c..3f242f5fd9 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -80,7 +80,6 @@ private slots: void chooseVoxelPaintColor(); void runTests(); void resetSwatchColors(); - void displayGPUMemory(); void switchVoxelShader(); private: From c0bfdfbc4f206003448eea14a7327b99f318a6fa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 16:54:20 -0700 Subject: [PATCH 14/28] fix comment --- interface/resources/shaders/voxel.geom | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom index 0ea4075f65..bfc94b3f26 100644 --- a/interface/resources/shaders/voxel.geom +++ b/interface/resources/shaders/voxel.geom @@ -12,16 +12,12 @@ // Second dataset (? similar to how voxel avatars pass in bones??) // which is the voxel size // -// Note: In vertex shader DON'T transform. Therefore passing the world coordinate xyz to geometric shader -// In geometric shader calculate xyz for triangles the same way we currently do triangles outside of OpenGL -// do transform on these triangles -// -// gl_Position = gl_ModelViewProjectionMatrix * cube_coord; -// +// Note: In vertex shader DON'T do projection transform. Therefore passing the 3D coordinates xyz to geometric shader +// // Output: GL_TRIANGLE_STRIP // // Issues: -// do we need to handle lighting of these colors?? +// how do we need to handle lighting of these colors?? // how do we handle normals? // check for size=0 and don't output the primitive // From 07515d1c5fca933a738a629bd8ffdfb3c2d036cc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 17:03:50 -0700 Subject: [PATCH 15/28] fix projection between shaders --- interface/resources/shaders/passthrough.vert | 2 +- interface/resources/shaders/voxel.geom | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/shaders/passthrough.vert b/interface/resources/shaders/passthrough.vert index af55842c67..f3d5c5b504 100644 --- a/interface/resources/shaders/passthrough.vert +++ b/interface/resources/shaders/passthrough.vert @@ -5,6 +5,6 @@ varying float voxelSize; void main(void) { gl_FrontColor = gl_Color; - gl_Position = gl_ModelViewMatrix * gl_Vertex; // don't call ftransform(), because we do projection in geometry shader + gl_Position = gl_Vertex; // don't call ftransform(), because we do projection in geometry shader voxelSize = voxelSizeIn; } \ No newline at end of file diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom index bfc94b3f26..6f4534a003 100644 --- a/interface/resources/shaders/voxel.geom +++ b/interface/resources/shaders/voxel.geom @@ -12,7 +12,7 @@ // Second dataset (? similar to how voxel avatars pass in bones??) // which is the voxel size // -// Note: In vertex shader DON'T do projection transform. Therefore passing the 3D coordinates xyz to geometric shader +// Note: In vertex shader doesn't do any transform. Therefore passing the 3D world coordinates xyz to us // // Output: GL_TRIANGLE_STRIP // @@ -36,7 +36,7 @@ void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec vertex[c] += (facePoints[cIndex] * scale); } gl_FrontColor = color; - gl_Position = gl_ProjectionMatrix * vertex; + gl_Position = gl_ModelViewProjectionMatrix * vertex; EmitVertex(); } EndPrimitive(); From 3ab92a592a7b9cb91ba6f61d71c18a3b03d37199 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 17:05:04 -0700 Subject: [PATCH 16/28] fix comments in shaders --- interface/resources/shaders/voxel.geom | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom index 6f4534a003..13b502357e 100644 --- a/interface/resources/shaders/voxel.geom +++ b/interface/resources/shaders/voxel.geom @@ -8,9 +8,7 @@ // GL_POINTS // Assumes vertex shader has not transformed coordinates // Each gl_PositionIn is the corner of voxel -// -// Second dataset (? similar to how voxel avatars pass in bones??) -// which is the voxel size +// varying voxelSize - which is the voxel size // // Note: In vertex shader doesn't do any transform. Therefore passing the 3D world coordinates xyz to us // From 2487a55be94091185915da97825e9cd1090a6644 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 19:04:19 -0700 Subject: [PATCH 17/28] add support for use of Byte normals --- interface/src/Application.cpp | 2 + interface/src/Menu.cpp | 3 ++ interface/src/Menu.h | 1 + interface/src/VoxelSystem.cpp | 82 +++++++++++++++++++++++++++-------- interface/src/VoxelSystem.h | 4 +- 5 files changed, 72 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8426b1fd55..7bf76466bc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1576,6 +1576,8 @@ void Application::init() { // Set up VoxelSystem after loading preferences so we can get the desired max voxel count _voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels()); + _voxels.setUseVoxelShader(Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader)); + _voxels.setUseByteNormals(Menu::getInstance()->isOptionChecked(MenuOption::UseByteNormals)); _voxels.init(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 0e796e28c2..fa42e4c274 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -253,6 +253,9 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader, 0, false, this, SLOT(switchVoxelShader())); + + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseByteNormals, 0, + false, Application::getInstance()->getVoxels(), SLOT(setUseByteNormals(bool))); QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3f242f5fd9..7cbbdbdc11 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -206,6 +206,7 @@ namespace MenuOption { const QString UsePerlinFace = "Use Perlin's Face"; const QString Quit = "Quit"; const QString UseVoxelShader = "Use Voxel Shader"; + const QString UseByteNormals = "Use Byte Normals"; const QString Voxels = "Voxels"; const QString VoxelAddMode = "Add Voxel Mode"; const QString VoxelColorMode = "Color Voxel Mode"; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 86d8704905..fe82da66a0 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -37,7 +37,7 @@ float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0, 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 }; -GLfloat identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, +GLbyte 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,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, 0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, @@ -75,7 +75,9 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float))); connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int))); - _useVoxelShader = false; + _useVoxelShader = false; + _useByteNormals = false; + _writeVoxelShaderData = NULL; _readVoxelShaderData = NULL; @@ -139,6 +141,20 @@ VoxelSystem::~VoxelSystem() { 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) { pthread_mutex_lock(&_bufferWriteLock); bool wasInitialized = _initialized; @@ -194,6 +210,7 @@ void VoxelSystem::cleanupVoxelMemory() { void VoxelSystem::initVoxelMemory() { if (_useVoxelShader) { + qDebug("Using Voxel Shader...\n"); GLuint* indicesArray = new GLuint[_maxVoxels]; // populate the indicesArray @@ -241,27 +258,55 @@ void VoxelSystem::initVoxelMemory() { } } - GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - GLfloat* normalsArrayEndPointer = normalsArray; + if (_useByteNormals) { + qDebug("Using Byte Normals...\n"); + GLbyte* normalsArray = new GLbyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + GLbyte* normalsArrayEndPointer = normalsArray; - // populate the normalsArray - for (int n = 0; n < _maxVoxels; n++) { - for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { - *(normalsArrayEndPointer++) = identityNormals[i]; + // 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; } + glGenBuffers(1, &_vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - // 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); - // VBO for colorsArray glGenBuffers(1, &_vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); @@ -276,7 +321,6 @@ void VoxelSystem::initVoxelMemory() { // delete the indices and normals arrays that are no longer needed delete[] indicesArray; - delete[] normalsArray; // we will track individual dirty sections with these arrays of bools @@ -890,7 +934,7 @@ void VoxelSystem::render(bool texture) { glVertexPointer(3, GL_FLOAT, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glNormalPointer(GL_FLOAT, 0, 0); + glNormalPointer((_useByteNormals ? GL_BYTE : GL_FLOAT), 0, 0); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); @@ -1769,7 +1813,7 @@ void VoxelSystem::falseColorizeOccludedV2() { void VoxelSystem::nodeAdded(Node* node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { uint16_t nodeID = node->getNodeID(); - printf("VoxelSystem... voxel server %u added...\n", nodeID); + qDebug("VoxelSystem... voxel server %u added...\n", nodeID); _voxelServerCount++; } } @@ -1792,7 +1836,7 @@ void VoxelSystem::nodeKilled(Node* node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { _voxelServerCount--; uint16_t nodeID = node->getNodeID(); - printf("VoxelSystem... voxel server %u removed...\n", nodeID); + qDebug("VoxelSystem... voxel server %u removed...\n", nodeID); if (_voxelServerCount > 0) { // Kill any voxels from the local tree that match this nodeID diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 7a44034590..5d3ac96d8c 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -128,6 +128,7 @@ public slots: void falseColorizeBySource(); void cancelImport(); + void setUseByteNormals(bool useByteNormals); protected: float _treeScale; @@ -203,10 +204,11 @@ private: uint64_t _lastViewCulling; int _lastViewCullingElapsed; - bool getUseVoxelShader(); void initVoxelMemory(); void cleanupVoxelMemory(); + bool _useByteNormals; + bool _useVoxelShader; 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 From 6b0f9314baba5f6dafc053f452468ae94963c4b9 Mon Sep 17 00:00:00 2001 From: Freddy Date: Thu, 26 Sep 2013 23:52:44 -0700 Subject: [PATCH 18/28] Faceshift drives body rotation, remove gyro-driven rotation --- interface/src/Application.cpp | 11 +++++--- interface/src/Menu.cpp | 7 ----- interface/src/Menu.h | 2 -- interface/src/avatar/Avatar.cpp | 4 +-- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/Head.cpp | 41 ++--------------------------- interface/src/avatar/Head.h | 5 +++- interface/src/avatar/MyAvatar.cpp | 12 ++++++--- interface/src/avatar/MyAvatar.h | 2 +- interface/src/devices/Faceshift.cpp | 12 ++++++--- interface/src/devices/Faceshift.h | 2 ++ 11 files changed, 38 insertions(+), 62 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8426b1fd55..360482e1f3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1750,6 +1750,11 @@ void Application::update(float deltaTime) { // Update faceshift _faceshift.update(); + + // Copy angular velocity if measured by faceshift, to the head + if (_faceshift.isActive()) { + _myAvatar.getHead().setAngularVelocity(_faceshift.getHeadAngularVelocity()); + } // if we have faceshift, use that to compute the lookat direction glm::vec3 lookAtRayOrigin = mouseRayOrigin, lookAtRayDirection = mouseRayDirection; @@ -1932,7 +1937,7 @@ void Application::update(float deltaTime) { if (!avatar->isInitialized()) { avatar->init(); } - avatar->simulate(deltaTime, NULL, 0.f); + avatar->simulate(deltaTime, NULL); avatar->setMouseRay(mouseRayOrigin, mouseRayDirection); } node->unlock(); @@ -1947,9 +1952,9 @@ void Application::update(float deltaTime) { } if (Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) { - _myAvatar.simulate(deltaTime, &_myTransmitter, Menu::getInstance()->getGyroCameraSensitivity()); + _myAvatar.simulate(deltaTime, &_myTransmitter); } else { - _myAvatar.simulate(deltaTime, NULL, Menu::getInstance()->getGyroCameraSensitivity()); + _myAvatar.simulate(deltaTime, NULL); } // no transmitter drive implies transmitter pick diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 0e796e28c2..7fd1bcd0fe 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -485,7 +485,6 @@ void Menu::loadSettings(QSettings* settings) { settings = Application::getInstance()->getSettings(); } - _gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f); _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); @@ -509,7 +508,6 @@ void Menu::saveSettings(QSettings* settings) { settings = Application::getInstance()->getSettings(); } - settings->setValue("gyroCameraSensitivity", _gyroCameraSensitivity); settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples); settings->setValue("fieldOfView", _fieldOfView); settings->setValue("maxVoxels", _maxVoxels); @@ -778,10 +776,6 @@ void Menu::editPreferences() { fieldOfView->setValue(_fieldOfView); form->addRow("Vertical Field of View (Degrees):", fieldOfView); - QDoubleSpinBox* gyroCameraSensitivity = new QDoubleSpinBox(); - gyroCameraSensitivity->setValue(_gyroCameraSensitivity); - form->addRow("Gyro Camera Sensitivity (0 - 1):", gyroCameraSensitivity); - QDoubleSpinBox* leanScale = new QDoubleSpinBox(); leanScale->setValue(applicationInstance->getAvatar()->getLeanScale()); form->addRow("Lean Scale:", leanScale); @@ -823,7 +817,6 @@ void Menu::editPreferences() { applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum()); - _gyroCameraSensitivity = gyroCameraSensitivity->value(); _maxVoxels = maxVoxels->value(); applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3f242f5fd9..1b1c236295 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -49,7 +49,6 @@ public: float getAudioJitterBufferSamples() const { return _audioJitterBufferSamples; } float getFieldOfView() const { return _fieldOfView; } - float getGyroCameraSensitivity() const { return _gyroCameraSensitivity; } BandwidthDialog* getBandwidthDialog() const { return _bandwidthDialog; } FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; } ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; } @@ -114,7 +113,6 @@ private: BandwidthDialog* _bandwidthDialog; float _fieldOfView; /// in Degrees, doesn't apply to HMD like Oculus FrustumDrawMode _frustumDrawMode; - float _gyroCameraSensitivity; ViewFrustumOffset _viewFrustumOffset; QActionGroup* _voxelModeActionsGroup; VoxelStatsDialog* _voxelStatsDialog; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 028bfef2ef..e3cdcac2c7 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -289,7 +289,7 @@ void Avatar::follow(Avatar* leadingAvatar) { } } -void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity) { +void Avatar::simulate(float deltaTime, Transmitter* transmitter) { glm::quat orientation = getOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; @@ -403,7 +403,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCamer _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); - _head.simulate(deltaTime, false, gyroCameraSensitivity); + _head.simulate(deltaTime, false); _hand.simulate(deltaTime, false); // use speed and angular velocity to determine walking vs. standing diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 1dd316f160..83cfd5993e 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -135,7 +135,7 @@ public: ~Avatar(); void init(); - void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity); + void simulate(float deltaTime, Transmitter* transmitter); void follow(Avatar* leadingAvatar); void render(bool lookingInMirror, bool renderAvatarBalls); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 6e437780e9..47677ec0e5 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -71,6 +71,7 @@ Head::Head(Avatar* owningAvatar) : _audioAttack(0.0f), _returnSpringScale(1.0f), _bodyRotation(0.0f, 0.0f, 0.0f), + _angularVelocity(0,0,0), _renderLookatVectors(false), _mohawkInitialized(false), _saccade(0.0f, 0.0f, 0.0f), @@ -132,7 +133,7 @@ void Head::resetHairPhysics() { } -void Head::simulate(float deltaTime, bool isMine, float gyroCameraSensitivity) { +void Head::simulate(float deltaTime, bool isMine) { // Update audio trailing average for rendering facial animations Faceshift* faceshift = Application::getInstance()->getFaceshift(); @@ -230,44 +231,6 @@ void Head::simulate(float deltaTime, bool isMine, float gyroCameraSensitivity) { // based on the nature of the lookat position, determine if the eyes can look / are looking at it. if (USING_PHYSICAL_MOHAWK) { updateHairPhysics(deltaTime); - - } - - // Update camera pitch and yaw independently from motion of head (for gyro-based interface) - if (isMine && _cameraFollowsHead && (gyroCameraSensitivity > 0.f)) { - // If we are using gyros and using gyroLook, have the camera follow head but with a null region - // to create stable rendering view with small head movements. - const float CAMERA_FOLLOW_HEAD_RATE_START = 0.1f; - const float CAMERA_FOLLOW_HEAD_RATE_MAX = 1.0f; - const float CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE = 1.05f; - const float CAMERA_STOP_TOLERANCE_DEGREES = 0.5f; - const float PITCH_START_RANGE = 20.f; - const float YAW_START_RANGE = 10.f; - float pitchStartTolerance = PITCH_START_RANGE - * (1.f - gyroCameraSensitivity) - + (2.f * CAMERA_STOP_TOLERANCE_DEGREES); - float yawStartTolerance = YAW_START_RANGE - * (1.f - gyroCameraSensitivity) - + (2.f * CAMERA_STOP_TOLERANCE_DEGREES); - - float cameraHeadAngleDifference = glm::length(glm::vec2(_pitch - _cameraPitch, _yaw - _cameraYaw)); - if (_isCameraMoving) { - _cameraFollowHeadRate = glm::clamp(_cameraFollowHeadRate * CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE, - 0.f, - CAMERA_FOLLOW_HEAD_RATE_MAX); - - _cameraPitch += (_pitch - _cameraPitch) * _cameraFollowHeadRate; - _cameraYaw += (_yaw - _cameraYaw) * _cameraFollowHeadRate; - if (cameraHeadAngleDifference < CAMERA_STOP_TOLERANCE_DEGREES) { - _isCameraMoving = false; - } - } else { - if ((fabs(_pitch - _cameraPitch) > pitchStartTolerance) || - (fabs(_yaw - _cameraYaw) > yawStartTolerance)) { - _isCameraMoving = true; - _cameraFollowHeadRate = CAMERA_FOLLOW_HEAD_RATE_START; - } - } } } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index ab07227fc6..0af640af04 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -44,7 +44,7 @@ public: void init(); void reset(); - void simulate(float deltaTime, bool isMine, float gyroCameraSensitivity); + void simulate(float deltaTime, bool isMine); void render(float alpha, bool isMine); void renderMohawk(); @@ -64,6 +64,8 @@ public: glm::quat getOrientation() const; glm::quat getCameraOrientation () const; + const glm::vec3& getAngularVelocity() const { return _angularVelocity; } + void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; } float getScale() const { return _scale; } glm::vec3 getPosition() const { return _position; } @@ -116,6 +118,7 @@ private: float _audioAttack; float _returnSpringScale; //strength of return springs glm::vec3 _bodyRotation; + glm::vec3 _angularVelocity; bool _renderLookatVectors; BendyLine _hairTuft[NUM_HAIR_TUFTS]; bool _mohawkInitialized; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3c2ce3dcb5..74291e66d4 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -65,7 +65,7 @@ void MyAvatar::reset() { _hand.reset(); } -void MyAvatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity) { +void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { glm::quat orientation = getOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; @@ -303,7 +303,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCam _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); - _head.simulate(deltaTime, true, gyroCameraSensitivity); + _head.simulate(deltaTime, true); _hand.simulate(deltaTime, true); const float WALKING_SPEED_THRESHOLD = 0.2f; @@ -337,7 +337,13 @@ void MyAvatar::updateFromGyrosAndOrWebcam(bool gyroLook, if (faceshift->isActive()) { estimatedPosition = faceshift->getHeadTranslation(); estimatedRotation = safeEulerAngles(faceshift->getHeadRotation()); - + // Rotate the body if the head is turned quickly + glm::vec3 headAngularVelocity = faceshift->getHeadAngularVelocity(); + const float FACESHIFT_YAW_VIEW_SENSITIVITY = 20.f; + const float FACESHIFT_MIN_YAW_VELOCITY = 1.0f; + if (fabs(headAngularVelocity.y) > FACESHIFT_MIN_YAW_VELOCITY) { + _bodyYawDelta += headAngularVelocity.y * FACESHIFT_YAW_VIEW_SENSITIVITY; + } } else if (gyros->isActive()) { estimatedRotation = gyros->getEstimatedRotation(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index feea7f4e7a..d0f7d74bf4 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -16,7 +16,7 @@ public: MyAvatar(Node* owningNode = NULL); void reset(); - void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity); + void simulate(float deltaTime, Transmitter* transmitter); void updateFromGyrosAndOrWebcam(bool gyroLook, float pitchFromTouch); void render(bool lookingInMirror, bool renderAvatarBalls); void renderScreenTint(ScreenTintLayer layer, Camera& whichCamera); diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index ebc5d5b880..1798acba46 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -144,12 +144,18 @@ void Faceshift::receive(const QByteArray& buffer) { if ((_tracking = data.m_trackingSuccessful)) { glm::quat newRotation = glm::quat(data.m_headRotation.w, -data.m_headRotation.x, data.m_headRotation.y, -data.m_headRotation.z); + // Compute angular velocity of the head glm::quat r = newRotation * glm::inverse(_headRotation); - //printf("angle = %.3f\n", 2 * acos(r.w)); + float theta = 2 * acos(r.w); + if (theta > EPSILON) { + float rMag = glm::length(glm::vec3(r.x, r.y, r.z)); + float AVERAGE_FACESHIFT_FRAME_TIME = 0.033f; + _headAngularVelocity = theta / AVERAGE_FACESHIFT_FRAME_TIME * glm::vec3(r.x, r.y, r.z) / rMag; + } else { + _headAngularVelocity = glm::vec3(0,0,0); + } _headRotation = newRotation; - //_headRotation = glm::quat(data.m_headRotation.w, -data.m_headRotation.x, - // data.m_headRotation.y, -data.m_headRotation.z); const float TRANSLATION_SCALE = 0.02f; _headTranslation = glm::vec3(data.m_headTranslation.x, data.m_headTranslation.y, -data.m_headTranslation.z) * TRANSLATION_SCALE; diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index ad98f72d38..22f474192d 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -30,6 +30,7 @@ public: bool isActive() const; const glm::quat& getHeadRotation() const { return _headRotation; } + const glm::vec3& getHeadAngularVelocity() const { return _headAngularVelocity; } const glm::vec3& getHeadTranslation() const { return _headTranslation; } float getEyeGazeLeftPitch() const { return _eyeGazeLeftPitch; } @@ -88,6 +89,7 @@ private: uint64_t _lastTrackingStateReceived; glm::quat _headRotation; + glm::vec3 _headAngularVelocity; glm::vec3 _headTranslation; float _eyeGazeLeftPitch; From f88a3633a5d20b9d5804cf2be34f8656fc7fa75e Mon Sep 17 00:00:00 2001 From: Freddy Date: Fri, 27 Sep 2013 00:40:41 -0700 Subject: [PATCH 19/28] Slow down when near other avatars for easier positioning --- interface/src/avatar/Avatar.cpp | 1 - interface/src/avatar/MyAvatar.cpp | 29 +++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e3cdcac2c7..9dc147cecb 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -28,7 +28,6 @@ using namespace std; const bool BALLS_ON = false; -const bool USING_AVATAR_GRAVITY = true; const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f); const float YAW_MAG = 500.0; const float MY_HAND_HOLDING_PULL = 0.2; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 74291e66d4..cf1ed4d1fc 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -23,7 +23,6 @@ using namespace std; -const bool USING_AVATAR_GRAVITY = true; const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f); const float YAW_MAG = 500.0; const float COLLISION_RADIUS_SCALAR = 1.2; // pertains to avatar-to-avatar collisions @@ -160,13 +159,11 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { _avatarTouch.simulate(deltaTime); // apply gravity - if (USING_AVATAR_GRAVITY) { - // For gravity, always move the avatar by the amount driven by gravity, so that the collision - // routines will detect it and collide every frame when pulled by gravity to a surface - const float MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY = 0.02f; - if (glm::length(_position - _lastCollisionPosition) > MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY) { - _velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime); - } + // For gravity, always move the avatar by the amount driven by gravity, so that the collision + // routines will detect it and collide every frame when pulled by gravity to a surface + const float MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY = 0.02f; + if (glm::length(_position - _lastCollisionPosition) > MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY) { + _velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime); } if (_isCollisionsOn) { @@ -211,14 +208,20 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { const float STATIC_FRICTION_STRENGTH = _scale * 20.f; applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_VELOCITY, STATIC_FRICTION_STRENGTH); + // Damp avatar velocity const float LINEAR_DAMPING_STRENGTH = 0.5f; const float SPEED_BRAKE_POWER = _scale * 10.0f; - // Note: PER changed squared damping strength to zero const float SQUARED_DAMPING_STRENGTH = 0.0f; + + float linearDamping = LINEAR_DAMPING_STRENGTH; + const float AVATAR_DAMPING_FACTOR = 120.f; + if (_distanceToNearestAvatar < _scale * PERIPERSONAL_RADIUS) { + linearDamping *= 1.f + AVATAR_DAMPING_FACTOR * (PERIPERSONAL_RADIUS - _distanceToNearestAvatar); + } if (_speedBrakes) { - applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH * SPEED_BRAKE_POWER, SQUARED_DAMPING_STRENGTH * SPEED_BRAKE_POWER); + applyDamping(deltaTime, _velocity, linearDamping * SPEED_BRAKE_POWER, SQUARED_DAMPING_STRENGTH * SPEED_BRAKE_POWER); } else { - applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH, SQUARED_DAMPING_STRENGTH); + applyDamping(deltaTime, _velocity, linearDamping, SQUARED_DAMPING_STRENGTH); } // pitch and roll the body as a function of forward speed and turning delta @@ -653,7 +656,9 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) { // Add one time jumping force if requested if (_shouldJump) { - _thrust += _scale * THRUST_JUMP * up; + if (glm::length(_gravity) > EPSILON) { + _thrust += _scale * THRUST_JUMP * up; + } _shouldJump = false; } From eb6af1afbfa037e4353dea7c56d04d62c5f73810 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Sep 2013 09:02:51 -0700 Subject: [PATCH 20/28] fix byte normals, fix crashes in switching between voxel shader and normal mode --- interface/src/VoxelSystem.cpp | 75 +++++++++++++++++++++++++------- interface/src/VoxelSystem.h | 4 ++ libraries/voxels/src/VoxelNode.h | 1 + 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index fe82da66a0..ed8de7f8a5 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -37,7 +37,7 @@ float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0, 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, +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,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, 0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, @@ -152,6 +152,10 @@ void VoxelSystem::setUseByteNormals(bool useByteNormals) { init(); } pthread_mutex_unlock(&_bufferWriteLock); + + if (wasInitialized) { + forceRedrawEntireTree(); + } } @@ -166,12 +170,17 @@ void VoxelSystem::setMaxVoxels(int maxVoxels) { init(); } pthread_mutex_unlock(&_bufferWriteLock); + + if (wasInitialized) { + forceRedrawEntireTree(); + } } void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { pthread_mutex_lock(&_bufferWriteLock); bool wasInitialized = _initialized; if (wasInitialized) { + clearAllNodesBufferIndex(); cleanupVoxelMemory(); } _useVoxelShader = useVoxelShader; @@ -179,6 +188,10 @@ void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { init(); } pthread_mutex_unlock(&_bufferWriteLock); + + if (wasInitialized) { + forceRedrawEntireTree(); + } } void VoxelSystem::cleanupVoxelMemory() { @@ -266,7 +279,7 @@ void VoxelSystem::initVoxelMemory() { // populate the normalsArray for (int n = 0; n < _maxVoxels; n++) { for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { - *(normalsArrayEndPointer++) = identityNormals[i]; + *(normalsArrayEndPointer++) = (identityNormals[i] * CHAR_MAX); } } @@ -750,20 +763,24 @@ void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& s float voxelScale, const nodeColor& color) { if (_useVoxelShader) { - VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; - writeVerticesAt->x = startVertex.x * TREE_SCALE; - writeVerticesAt->y = startVertex.y * TREE_SCALE; - writeVerticesAt->z = startVertex.z * TREE_SCALE; - writeVerticesAt->s = voxelScale * TREE_SCALE; - writeVerticesAt->r = color[RED_INDEX]; - writeVerticesAt->g = color[GREEN_INDEX]; - writeVerticesAt->b = color[BLUE_INDEX]; + if (_writeVoxelShaderData) { + VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; + writeVerticesAt->x = startVertex.x * TREE_SCALE; + writeVerticesAt->y = startVertex.y * TREE_SCALE; + writeVerticesAt->z = startVertex.z * TREE_SCALE; + writeVerticesAt->s = voxelScale * TREE_SCALE; + writeVerticesAt->r = color[RED_INDEX]; + writeVerticesAt->g = color[GREEN_INDEX]; + writeVerticesAt->b = color[BLUE_INDEX]; + } } else { - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(writeColorsAt +j) = color[j % 3]; + if (_writeVerticesArray && _writeColorsArray) { + for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(writeColorsAt +j) = color[j % 3]; + } } } } @@ -995,6 +1012,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) { _nodeCount++; if (node->isColored()) { diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 5d3ac96d8c..39807f918e 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -126,6 +126,8 @@ public slots: void falseColorizeOccluded(); void falseColorizeOccludedV2(); void falseColorizeBySource(); + void forceRedrawEntireTree(); + void clearAllNodesBufferIndex(); void cancelImport(); void setUseByteNormals(bool useByteNormals); @@ -172,6 +174,8 @@ private: static bool falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData); static bool falseColorizeBySourceOperation(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 updateNodeInArraysAsPartialVBO(VoxelNode* node); diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index b7f31e3b61..03a8fe3c57 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -70,6 +70,7 @@ public: void printDebugDetails(const char* label) const; bool isDirty() const { return _isDirty; } void clearDirtyBit() { _isDirty = false; } + void setDirtyBit() { _isDirty = true; } bool hasChangedSince(uint64_t time) const { return (_lastChanged > time); } void markWithChangedTime() { _lastChanged = usecTimestampNow(); } uint64_t getLastChanged() const { return _lastChanged; } From 605c2f30cfb8fc9820f44bb3d3fea5638f30233c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Sep 2013 10:17:10 -0700 Subject: [PATCH 21/28] add memory usage debugging --- interface/src/Application.cpp | 20 ++++++--- interface/src/VoxelSystem.cpp | 85 +++++++++++++++++++++++++++++++++-- interface/src/VoxelSystem.h | 10 +++++ 3 files changed, 105 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7bf76466bc..7c223043d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2822,28 +2822,36 @@ void Application::displayStats() { voxelStats << "Voxels Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K " << "Updated: " << _voxels.getVoxelsUpdated()/1000.f << "K " << "Max: " << _voxels.getMaxVoxels()/1000.f << "K "; - 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(""); char* voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_VOXELS); 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(""); voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ELAPSED); 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(""); voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ENCODE); 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(""); voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_MODE); 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); char avatarMixerStats[200]; @@ -2856,7 +2864,7 @@ void Application::displayStats() { 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()); if (_perfStatsOn) { diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ed8de7f8a5..88661dd2bd 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -214,14 +214,17 @@ void VoxelSystem::cleanupVoxelMemory() { delete[] _writeVerticesArray; delete[] _readColorsArray; delete[] _writeColorsArray; - delete[] _writeVoxelDirtyArray; - delete[] _readVoxelDirtyArray; } + delete[] _writeVoxelDirtyArray; + delete[] _readVoxelDirtyArray; } _initialized = false; // no longer initialized } void VoxelSystem::initVoxelMemory() { + _initialMemoryUsageGPU = getFreeMemoryGPU(); + _memoryUsageRAM = 0; + _memoryUsageVBO = 0; // our VBO allocations as we know them if (_useVoxelShader) { qDebug("Using Voxel Shader...\n"); GLuint* indicesArray = new GLuint[_maxVoxels]; @@ -235,12 +238,13 @@ void VoxelSystem::initVoxelMemory() { // bind the indices VBO to the actual indices array glGenBuffers(1, &_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); glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); 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[] indicesArray; @@ -248,12 +252,18 @@ void VoxelSystem::initVoxelMemory() { // we will track individual dirty sections with these arrays of bools _writeVoxelDirtyArray = new bool[_maxVoxels]; memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (_maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (_maxVoxels * sizeof(bool)); // prep the data structures for incoming voxel data _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); + _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); } else { GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; @@ -289,6 +299,7 @@ void VoxelSystem::initVoxelMemory() { glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels, normalsArray, GL_STATIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels; // delete the indices and normals arrays that are no longer needed delete[] normalsArray; @@ -310,6 +321,7 @@ void VoxelSystem::initVoxelMemory() { glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, normalsArray, GL_STATIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels; // delete the indices and normals arrays that are no longer needed delete[] normalsArray; @@ -319,11 +331,13 @@ void VoxelSystem::initVoxelMemory() { glGenBuffers(1, &_vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels; // VBO for colorsArray glGenBuffers(1, &_vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels; // VBO for the indicesArray glGenBuffers(1, &_vboIndicesID); @@ -331,6 +345,7 @@ void VoxelSystem::initVoxelMemory() { glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels, indicesArray, GL_STATIC_DRAW); + _memoryUsageVBO += INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels; // delete the indices and normals arrays that are no longer needed delete[] indicesArray; @@ -339,15 +354,22 @@ void VoxelSystem::initVoxelMemory() { // we will track individual dirty sections with these arrays of bools _writeVoxelDirtyArray = new bool[_maxVoxels]; memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (sizeof(bool) * _maxVoxels); + _readVoxelDirtyArray = new bool[_maxVoxels]; memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (sizeof(bool) * _maxVoxels); // prep the data structures for incoming voxel data _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); // create our simple fragment shader if we're the first system to init @@ -1897,3 +1919,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); +} + + + diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 39807f918e..5e56cfe8a6 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -69,6 +69,10 @@ public: void setMaxVoxels(int 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 getVoxelsColored(); long int getVoxelsBytesRead(); @@ -185,6 +189,8 @@ private: void updateVBOs(); + unsigned long getFreeMemoryGPU(); + // these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here static float _maxDistance; static float _minDistance; @@ -253,6 +259,10 @@ private: int _dataSourceID; int _voxelServerCount; + unsigned long _memoryUsageRAM; + unsigned long _memoryUsageVBO; + unsigned long _initialMemoryUsageGPU; + bool _hasMemoryUsageGPU; }; #endif From dbfc0956c1bfcf1de89b7658081a90d5eab9b62d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Sep 2013 13:26:58 -0700 Subject: [PATCH 22/28] added normals to voxel shader --- interface/resources/shaders/voxel.geom | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom index 13b502357e..ca8f729542 100644 --- a/interface/resources/shaders/voxel.geom +++ b/interface/resources/shaders/voxel.geom @@ -26,14 +26,17 @@ const int VERTICES_PER_FACE = 4; const int COORD_PER_VERTEX = 3; 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++ ) { vec4 vertex = corner; for (int c = 0; c < COORD_PER_VERTEX; c++ ) { int cIndex = c + (v * COORD_PER_VERTEX); 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; 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 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++) { corner = gl_PositionIn[i]; scale = voxelSize[i]; - faceOfVoxel(corner, scale, bottomFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, topFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, rightFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, leftFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, frontFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, backFace, gl_FrontColorIn[i]); + faceOfVoxel(corner, scale, bottomFace, gl_FrontColorIn[i], bottomNormal); + faceOfVoxel(corner, scale, topFace, gl_FrontColorIn[i], topNormal ); + faceOfVoxel(corner, scale, rightFace, gl_FrontColorIn[i], rightNormal ); + faceOfVoxel(corner, scale, leftFace, gl_FrontColorIn[i], leftNormal ); + faceOfVoxel(corner, scale, frontFace, gl_FrontColorIn[i], frontNormal ); + faceOfVoxel(corner, scale, backFace, gl_FrontColorIn[i], backNormal ); } } \ No newline at end of file From 8cffa8d872d5292d9dbd9a4971673b71d6830dbf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Sep 2013 15:04:44 -0700 Subject: [PATCH 23/28] add support for global normals for voxels --- interface/src/Menu.cpp | 3 + interface/src/Menu.h | 1 + interface/src/VoxelSystem.cpp | 355 ++++++++++++++++++-------- interface/src/VoxelSystem.h | 12 + libraries/voxels/src/VoxelConstants.h | 6 + 5 files changed, 266 insertions(+), 111 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index fa42e4c274..784614043a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -256,6 +256,9 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseByteNormals, 0, false, Application::getInstance()->getVoxels(), SLOT(setUseByteNormals(bool))); + + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseGlobalNormals, 0, + false, Application::getInstance()->getVoxels(), SLOT(setUseGlobalNormals(bool))); QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7cbbdbdc11..a2d0267d58 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -207,6 +207,7 @@ namespace MenuOption { const QString Quit = "Quit"; const QString UseVoxelShader = "Use Voxel Shader"; const QString UseByteNormals = "Use Byte Normals"; + const QString UseGlobalNormals = "Use Global Normals"; const QString Voxels = "Voxels"; const QString VoxelAddMode = "Add Voxel Mode"; const QString VoxelColorMode = "Color Voxel Mode"; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 88661dd2bd..faeec9352b 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -33,9 +33,11 @@ #include "VoxelConstants.h" #include "VoxelSystem.h" -float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, - 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, - 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; +float identityVerticesGlobalNormals[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; + +float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //0-7 + 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //8-15 + 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; // 16-23 GLfloat identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, 0,0,+1, 0,0,+1, 0,0,+1, 0,0,+1, @@ -51,6 +53,13 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- 10,11,15, 10,15,14, // Y+ 4,5,6, 4,6,7 }; // Z+ +GLubyte identityIndicesTop[] = { 2, 3, 7, 2, 7, 6 }; +GLubyte identityIndicesBottom[] = { 0, 1, 5, 0, 5, 4 }; +GLubyte identityIndicesLeft[] = { 0, 7, 3, 0, 4, 7 }; +GLubyte identityIndicesRight[] = { 1, 2, 6, 1, 6, 5 }; +GLubyte identityIndicesFront[] = { 0, 2, 1, 0, 3, 2 }; +GLubyte identityIndicesBack[] = { 4, 5, 6, 4, 6, 7 }; + VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) : NodeData(NULL), _treeScale(treeScale), @@ -77,6 +86,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) _useVoxelShader = false; _useByteNormals = false; + _useGlobalNormals = false; _writeVoxelShaderData = NULL; _readVoxelShaderData = NULL; @@ -145,6 +155,7 @@ void VoxelSystem::setUseByteNormals(bool useByteNormals) { pthread_mutex_lock(&_bufferWriteLock); bool wasInitialized = _initialized; if (wasInitialized) { + clearAllNodesBufferIndex(); cleanupVoxelMemory(); } _useByteNormals = useByteNormals; @@ -158,11 +169,29 @@ void VoxelSystem::setUseByteNormals(bool useByteNormals) { } } +void VoxelSystem::setUseGlobalNormals(bool useGlobalNormals) { + pthread_mutex_lock(&_bufferWriteLock); + bool wasInitialized = _initialized; + if (wasInitialized) { + clearAllNodesBufferIndex(); + cleanupVoxelMemory(); + } + _useGlobalNormals = useGlobalNormals; + if (wasInitialized) { + init(); + } + pthread_mutex_unlock(&_bufferWriteLock); + + if (wasInitialized) { + forceRedrawEntireTree(); + } +} void VoxelSystem::setMaxVoxels(int maxVoxels) { pthread_mutex_lock(&_bufferWriteLock); bool wasInitialized = _initialized; if (wasInitialized) { + clearAllNodesBufferIndex(); cleanupVoxelMemory(); } _maxVoxels = maxVoxels; @@ -206,9 +235,19 @@ void VoxelSystem::cleanupVoxelMemory() { } else { // Destroy glBuffers glDeleteBuffers(1, &_vboVerticesID); - glDeleteBuffers(1, &_vboNormalsID); glDeleteBuffers(1, &_vboColorsID); - glDeleteBuffers(1, &_vboIndicesID); + + if (!_useGlobalNormals) { + glDeleteBuffers(1, &_vboNormalsID); + glDeleteBuffers(1, &_vboIndicesID); + } else { + glDeleteBuffers(1, &_vboIndicesTop); + glDeleteBuffers(1, &_vboIndicesBottom); + glDeleteBuffers(1, &_vboIndicesLeft); + glDeleteBuffers(1, &_vboIndicesRight); + glDeleteBuffers(1, &_vboIndicesFront); + glDeleteBuffers(1, &_vboIndicesBack); + } delete[] _readVerticesArray; delete[] _writeVerticesArray; @@ -221,6 +260,34 @@ void VoxelSystem::cleanupVoxelMemory() { _initialized = false; // no longer initialized } +void VoxelSystem::setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]) { + GLuint* indicesArray = new GLuint[INDICES_PER_FACE * _maxVoxels]; + + // populate the indicesArray + // this will not change given new voxels, so we can set it all up now + for (int n = 0; n < _maxVoxels; n++) { + // fill the indices array + int voxelIndexOffset = n * INDICES_PER_FACE; + GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; + int startIndex = (n * GLOBAL_NORMALS_VERTICES_PER_VOXEL); + + for (int i = 0; i < INDICES_PER_FACE; i++) { + // add indices for this side of the cube + currentIndicesPos[i] = startIndex + faceIdentityIndices[i]; + } + } + + glGenBuffers(1, &faceVBOID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faceVBOID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + INDICES_PER_FACE * sizeof(GLuint) * _maxVoxels, + indicesArray, GL_STATIC_DRAW); + _memoryUsageVBO += INDICES_PER_FACE * sizeof(GLuint) * _maxVoxels; + + // delete the indices and normals arrays that are no longer needed + delete[] indicesArray; +} + void VoxelSystem::initVoxelMemory() { _initialMemoryUsageGPU = getFreeMemoryGPU(); _memoryUsageRAM = 0; @@ -265,91 +332,104 @@ void VoxelSystem::initVoxelMemory() { _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); } else { - GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; - - // populate the indicesArray - // this will not change given new voxels, so we can set it all up now - for (int n = 0; n < _maxVoxels; n++) { - // fill the indices array - int voxelIndexOffset = n * INDICES_PER_VOXEL; - GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; - int startIndex = (n * VERTICES_PER_VOXEL); - - for (int i = 0; i < INDICES_PER_VOXEL; i++) { - // add indices for this side of the cube - currentIndicesPos[i] = startIndex + identityIndices[i]; - } - } - - if (_useByteNormals) { - qDebug("Using Byte Normals...\n"); - GLbyte* normalsArray = new GLbyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - GLbyte* normalsArrayEndPointer = normalsArray; - - // populate the normalsArray - for (int n = 0; n < _maxVoxels; n++) { - for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { - *(normalsArrayEndPointer++) = (identityNormals[i] * CHAR_MAX); - } - } - - // VBO for the normalsArray - glGenBuffers(1, &_vboNormalsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glBufferData(GL_ARRAY_BUFFER, - VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels, - normalsArray, GL_STATIC_DRAW); - _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels; - - // delete the indices and normals arrays that are no longer needed - delete[] normalsArray; + if (_useGlobalNormals) { + // Global Normals mode uses a technique of not including normals on any voxel vertices, and instead + // rendering the voxel faces in 6 passes that use a global call to glNormal3f() + qDebug("Using Global Normals...\n"); + setupFaceIndices(_vboIndicesTop, identityIndicesTop); + setupFaceIndices(_vboIndicesBottom, identityIndicesBottom); + setupFaceIndices(_vboIndicesLeft, identityIndicesLeft); + setupFaceIndices(_vboIndicesRight, identityIndicesRight); + setupFaceIndices(_vboIndicesFront, identityIndicesFront); + setupFaceIndices(_vboIndicesBack, identityIndicesBack); } else { - qDebug("Using Float Normals...\n"); - GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - GLfloat* normalsArrayEndPointer = normalsArray; + if (_useByteNormals) { + qDebug("Using Byte Normals...\n"); + GLbyte* normalsArray = new GLbyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + GLbyte* normalsArrayEndPointer = normalsArray; - // populate the normalsArray + // populate the normalsArray + for (int n = 0; n < _maxVoxels; n++) { + for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { + *(normalsArrayEndPointer++) = (identityNormals[i] * CHAR_MAX); + } + } + + // VBO for the normalsArray + glGenBuffers(1, &_vboNormalsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); + glBufferData(GL_ARRAY_BUFFER, + VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels, + normalsArray, GL_STATIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels; + + // delete the indices and normals arrays that are no longer needed + delete[] normalsArray; + } else { + qDebug("Using Float Normals...\n"); + GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + GLfloat* normalsArrayEndPointer = normalsArray; + + // populate the normalsArray + for (int n = 0; n < _maxVoxels; n++) { + for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { + *(normalsArrayEndPointer++) = identityNormals[i]; + } + } + + // VBO for the normalsArray + glGenBuffers(1, &_vboNormalsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); + glBufferData(GL_ARRAY_BUFFER, + VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, + normalsArray, GL_STATIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels; + + // delete the indices and normals arrays that are no longer needed + delete[] normalsArray; + } + + GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; + + // populate the indicesArray + // this will not change given new voxels, so we can set it all up now for (int n = 0; n < _maxVoxels; n++) { - for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { - *(normalsArrayEndPointer++) = identityNormals[i]; + // fill the indices array + int voxelIndexOffset = n * INDICES_PER_VOXEL; + GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; + int startIndex = (n * VERTICES_PER_VOXEL); + + for (int i = 0; i < INDICES_PER_VOXEL; i++) { + // add indices for this side of the cube + currentIndicesPos[i] = startIndex + identityIndices[i]; } } - - // VBO for the normalsArray - glGenBuffers(1, &_vboNormalsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glBufferData(GL_ARRAY_BUFFER, - VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, - normalsArray, GL_STATIC_DRAW); - _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels; + + // VBO for the indicesArray + glGenBuffers(1, &_vboIndicesID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels, + indicesArray, GL_STATIC_DRAW); + _memoryUsageVBO += INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels; // delete the indices and normals arrays that are no longer needed - delete[] normalsArray; + delete[] indicesArray; + } - - + + // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel + int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL; glGenBuffers(1, &_vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels; + glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels; // VBO for colorsArray glGenBuffers(1, &_vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels; - - // VBO for the indicesArray - glGenBuffers(1, &_vboIndicesID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, - INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels, - indicesArray, GL_STATIC_DRAW); - _memoryUsageVBO += INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels; - - // delete the indices and normals arrays that are no longer needed - delete[] indicesArray; - + glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels; // we will track individual dirty sections with these arrays of bools _writeVoxelDirtyArray = new bool[_maxVoxels]; @@ -361,15 +441,15 @@ void VoxelSystem::initVoxelMemory() { _memoryUsageRAM += (sizeof(bool) * _maxVoxels); // prep the data structures for incoming voxel data - _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); - _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); + _writeVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels); + _readVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels); - _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); - _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); + _writeColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels); + _readColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels); // create our simple fragment shader if we're the first system to init @@ -649,16 +729,19 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, void* writeDataAt = &_writeVoxelShaderData[segmentStart]; memcpy(readDataAt, writeDataAt, segmentSizeBytes); } else { - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel + int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL; + + GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); + GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); + GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel); memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte); + segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); + GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel); + GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel); memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); } } @@ -797,10 +880,17 @@ void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& s } } else { if (_writeVerticesArray && _writeColorsArray) { - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); + int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL; + for (int j = 0; j < vertexPointsPerVoxel; j++ ) { + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel); + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * vertexPointsPerVoxel); + + if (_useGlobalNormals) { + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVerticesGlobalNormals[j] * voxelScale); + } else { + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); + } + *(writeColorsAt +j) = color[j % 3]; } } @@ -912,15 +1002,16 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); } else { + int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL; int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); + GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte); + segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); + GLubyte* readColorsFrom = _readColorsArray + (segmentStart * vertexPointsPerVoxel); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); } @@ -966,27 +1057,66 @@ void VoxelSystem::render(bool texture) { } else { // tell OpenGL where to find vertex and color information glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); glVertexPointer(3, GL_FLOAT, 0, 0); - glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glNormalPointer((_useByteNormals ? GL_BYTE : GL_FLOAT), 0, 0); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); + if (!_useGlobalNormals) { + glEnableClientState(GL_NORMAL_ARRAY); + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); + glNormalPointer((_useByteNormals ? GL_BYTE : GL_FLOAT), 0, 0); + } else { + glNormal3f(0,1.0f,0); // hack for now + } + applyScaleAndBindProgram(texture); // for performance, enable backface culling glEnable(GL_CULL_FACE); - // draw the number of voxels we have - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); - glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, - 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + if (!_useGlobalNormals) { + // draw the number of voxels we have + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, + 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + } else { + // draw voxels in 6 passes + + glNormal3f(0,1.0f,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesTop); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1, + INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + + glNormal3f(0,-1.0f,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesBottom); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1, + INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + + glNormal3f(-1.0f,0,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesLeft); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1, + INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + + glNormal3f(1.0f,0,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesRight); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1, + INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + + glNormal3f(0,0,-1.0f); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesFront); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1, + INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + + glNormal3f(0,0,1.0f); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesBack); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, INDICES_PER_FACE * _voxelsInReadArrays - 1, + INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + } + glDisable(GL_CULL_FACE); @@ -994,9 +1124,12 @@ void VoxelSystem::render(bool texture) { // deactivate vertex and color arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); + if (!_useGlobalNormals) { + glDisableClientState(GL_NORMAL_ARRAY); + } + // bind with 0 to switch back to normal operation glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 5e56cfe8a6..bf5beb6263 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -135,6 +135,7 @@ public slots: void cancelImport(); void setUseByteNormals(bool useByteNormals); + void setUseGlobalNormals(bool useGlobalNormals); protected: float _treeScale; @@ -218,6 +219,7 @@ private: void cleanupVoxelMemory(); bool _useByteNormals; + bool _useGlobalNormals; bool _useVoxelShader; GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO @@ -229,6 +231,14 @@ private: GLuint _vboNormalsID; GLuint _vboColorsID; GLuint _vboIndicesID; + + GLuint _vboIndicesTop; + GLuint _vboIndicesBottom; + GLuint _vboIndicesLeft; + GLuint _vboIndicesRight; + GLuint _vboIndicesFront; + GLuint _vboIndicesBack; + pthread_mutex_t _bufferWriteLock; pthread_mutex_t _treeLock; @@ -236,6 +246,8 @@ private: ViewFrustum _lastStableViewFrustum; ViewFrustum* _viewFrustum; + void setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]); + int newTreeToArrays(VoxelNode *currentNode); void cleanupRemovedVoxels(); diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 391be29282..1871aa8e31 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -38,6 +38,12 @@ const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; // xyz for each VERT const int INDICES_PER_VOXEL = 3 * 12; // 6 sides * 2 triangles per size * 3 vertices per triangle const int COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * VERTICES_PER_VOXEL; +const int VERTICES_PER_FACE = 4; // 6 sides * 4 corners per side +const int INDICES_PER_FACE = 3 * 2; // 1 side * 2 triangles per size * 3 vertices per triangle +const int GLOBAL_NORMALS_VERTICES_PER_VOXEL = 8; // no need for 3 copies because they don't include normal +const int GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL = 3 * GLOBAL_NORMALS_VERTICES_PER_VOXEL; +const int GLOBAL_NORMALS_COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * GLOBAL_NORMALS_VERTICES_PER_VOXEL; + typedef unsigned long int glBufferIndex; const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX; From c78aa591c53ff9aec7aa4a87b18e668713eaa9f3 Mon Sep 17 00:00:00 2001 From: Freddy Date: Fri, 27 Sep 2013 15:08:10 -0700 Subject: [PATCH 24/28] Fix spinning while flying, top speed now about Mach 1 --- interface/src/avatar/MyAvatar.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cf1ed4d1fc..4f7535318a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -211,7 +211,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { // Damp avatar velocity const float LINEAR_DAMPING_STRENGTH = 0.5f; 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; const float AVATAR_DAMPING_FACTOR = 120.f; @@ -225,12 +225,15 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } // pitch and roll the body as a function of forward speed and turning delta - const float BODY_PITCH_WHILE_WALKING = -20.0; - const float BODY_ROLL_WHILE_TURNING = 0.2; - float forwardComponentOfVelocity = glm::dot(getBodyFrontDirection(), _velocity); - orientation = orientation * glm::quat(glm::radians(glm::vec3( - BODY_PITCH_WHILE_WALKING * deltaTime * forwardComponentOfVelocity, 0.0f, - BODY_ROLL_WHILE_TURNING * deltaTime * _speed * _bodyYawDelta))); + const float HIGH_VELOCITY = 10.f; + if (glm::length(_velocity) < HIGH_VELOCITY) { + const float BODY_PITCH_WHILE_WALKING = -20.0; + const float BODY_ROLL_WHILE_TURNING = 0.2; + float forwardComponentOfVelocity = glm::dot(getBodyFrontDirection(), _velocity); + 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... const float BODY_UPRIGHT_FORCE = _scale * 10.0; @@ -648,8 +651,12 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) { // 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]) { - const float THRUST_INCREASE_RATE = 1.0; - _thrustMultiplier *= 1.f + deltaTime * THRUST_INCREASE_RATE; + const float THRUST_INCREASE_RATE = 1.05; + 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 { _thrustMultiplier = 1.f; } From ad8c676feab3c4bc51792f694a80026cfec5ca47 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 27 Sep 2013 16:23:07 -0700 Subject: [PATCH 25/28] sensibly initialize _shouldStop to false --- assignment-client/src/Agent.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index aabf9fba66..60b226c677 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -16,7 +16,10 @@ #include "Agent.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) +{ } From 39cf3375e552c4ae140e5a9fe1605c5e38c52a94 Mon Sep 17 00:00:00 2001 From: PhilipRosedale Date: Fri, 27 Sep 2013 16:27:42 -0700 Subject: [PATCH 26/28] small change to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d83e17dcd6..e0d85e3f6b 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ and features are available via menus in the Interface application. 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 you to run the full stack of the virtual world should you choose to. From a0f23d409ed711587ecc078c322eef93b3bc8433 Mon Sep 17 00:00:00 2001 From: stojce Date: Sat, 28 Sep 2013 13:16:50 +0200 Subject: [PATCH 27/28] Merging changes --- interface/src/Application.cpp | 1 + interface/src/Application.h | 4 +++- libraries/shared/src/NodeList.cpp | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 533a4b4246..f10f98c3b3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3423,6 +3423,7 @@ void Application::attachNewHeadToNode(Node* newNode) { } void Application::domainChanged(QString domain) { + qDebug("Application title set to: %s.\n", domain.toStdString().c_str()); _window->setWindowTitle(domain); } diff --git a/interface/src/Application.h b/interface/src/Application.h index a8e84e5c2a..620d6d57f5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -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_BLUE = 0.0f; -class Application : public QApplication, public NodeListHook, public PacketSenderNotify { +class Application : public QApplication, public NodeListHook, public PacketSenderNotify, public DomainChangeListener { Q_OBJECT friend class VoxelPacketProcessor; @@ -146,6 +146,8 @@ public: virtual void nodeKilled(Node* node); virtual void packetSentNotification(ssize_t length); + virtual void domainChanged(QString domain); + VoxelShader& getVoxelShader() { return _voxelShader; } public slots: diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 8901ca3271..7b31a2de15 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -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 _domainIP.clear(); + notifyDomainChanged(); } void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) { @@ -585,6 +586,7 @@ void NodeList::loadData(QSettings *settings) { if (domainServerHostname.size() > 0) { _domainHostname = domainServerHostname; + notifyDomainChanged(); } 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) { _hooks.push_back(hook); } @@ -704,3 +721,9 @@ void NodeList::notifyHooksOfKilledNode(Node* node) { _hooks[i]->nodeKilled(node); } } + +void NodeList::notifyDomainChanged() { + for (int i = 0; i < _domainListeners.size(); i++) { + _domainListeners[i]->domainChanged(_domainHostname); + } +} From 9645cd98310651fb163cf8c4897ae0d38843b9f7 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 28 Sep 2013 15:18:59 -0700 Subject: [PATCH 28/28] Click on voxels as way of moving around --- interface/src/Application.cpp | 11 +++++++++++ interface/src/avatar/MyAvatar.cpp | 29 ++++++++++++++++++++++++++--- interface/src/avatar/MyAvatar.h | 3 +++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f10f98c3b3..ed1e513b91 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1001,6 +1001,17 @@ void Application::mousePressEvent(QMouseEvent* event) { _audio.startCollisionSound(1.0, frequency, 0.0, HOVER_VOXEL_DECAY); _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()) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4f7535318a..96b9877ede 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -50,7 +50,9 @@ MyAvatar::MyAvatar(Node* owningNode) : _lastCollisionPosition(0, 0, 0), _speedBrakes(false), _isThrustOn(false), - _thrustMultiplier(1.0f) + _thrustMultiplier(1.0f), + _moveTarget(0,0,0), + _moveTargetStepCounter(0) { for (int i = 0; i < MAX_DRIVE_KEYS; i++) { _driveKeys[i] = false; @@ -64,6 +66,11 @@ void MyAvatar::reset() { _hand.reset(); } +void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) { + _moveTarget = moveTarget; + _moveTargetStepCounter = 0; +} + void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { 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) { _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(); if (myCamera->getMode() == CAMERA_MODE_FIRST_PERSON && !OculusManager::isConnected()) { @@ -324,7 +333,21 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { const float MOVING_SPEED_THRESHOLD = 0.01f; _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; // Zero thrust out now that we've added it to velocity in this frame diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d0f7d74bf4..95c1efd5a8 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -31,6 +31,7 @@ public: void setOrientation(const glm::quat& orientation); void setNewScale(const float scale); void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; } + void setMoveTarget(const glm::vec3 moveTarget); // getters float getNewScale() const { return _newScale; } @@ -73,6 +74,8 @@ public: bool _isThrustOn; float _thrustMultiplier; float _collisionRadius; + glm::vec3 _moveTarget; + int _moveTargetStepCounter; // private methods float getBallRenderAlpha(int ball, bool lookingInMirror) const;