From e1d8022409182e097ca765ed1c04e4fa4c7ccbd3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 14:11:31 -0800 Subject: [PATCH 01/27] working on removing voxels --- assignment-client/src/Agent.cpp | 21 +-- assignment-client/src/Agent.h | 3 - interface/src/Application.cpp | 273 +------------------------------- interface/src/Application.h | 37 ----- 4 files changed, 5 insertions(+), 329 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f3efccf31a..36166b7ac4 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +//#include #include // TODO: consider moving to scriptengine.h @@ -37,7 +37,6 @@ static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; Agent::Agent(const QByteArray& packet) : ThreadedAssignment(packet), - _voxelEditSender(), _entityEditSender(), _receivedAudioStream(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, InboundAudioStream::Settings(0, false, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, false, @@ -48,7 +47,6 @@ Agent::Agent(const QByteArray& packet) : // be the parent of the script engine so it gets moved when we do _scriptEngine.setParent(this); - _scriptEngine.getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender); _scriptEngine.getEntityScriptingInterface()->setPacketSender(&_entityEditSender); } @@ -69,11 +67,6 @@ void Agent::readPendingDatagrams() { if (matchedNode) { // PacketType_JURISDICTION, first byte is the node type... switch (receivedPacket[headerBytes]) { - case NodeType::VoxelServer: - _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()-> - queueReceivedPacket(matchedNode,receivedPacket); - break; - break; case NodeType::EntityServer: _scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()-> queueReceivedPacket(matchedNode, receivedPacket); @@ -93,7 +86,6 @@ void Agent::readPendingDatagrams() { sourceNode->setLastHeardMicrostamp(usecTimestampNow()); } else if (datagramPacketType == PacketTypeOctreeStats - || datagramPacketType == PacketTypeVoxelData || datagramPacketType == PacketTypeEntityData || datagramPacketType == PacketTypeEntityErase ) { @@ -127,10 +119,6 @@ void Agent::readPendingDatagrams() { _entityViewer.processDatagram(mutablePacket, sourceNode); } - if (datagramPacketType == PacketTypeVoxelData) { - _voxelViewer.processDatagram(mutablePacket, sourceNode); - } - } else if (datagramPacketType == PacketTypeMixedAudio || datagramPacketType == PacketTypeSilentAudioFrame) { _receivedAudioStream.parseData(receivedPacket); @@ -168,7 +156,6 @@ void Agent::run() { nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer - << NodeType::VoxelServer << NodeType::EntityServer ); @@ -221,12 +208,6 @@ void Agent::run() { _scriptEngine.registerGlobalObject("SoundCache", &SoundCache::getInstance()); - _scriptEngine.registerGlobalObject("VoxelViewer", &_voxelViewer); - // connect the VoxelViewer and the VoxelScriptingInterface to each other - _voxelViewer.setJurisdictionListener(_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()); - _voxelViewer.init(); - _scriptEngine.getVoxelsScriptingInterface()->setVoxelTree(_voxelViewer.getTree()); - _scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer); _entityViewer.setJurisdictionListener(_scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()); _entityViewer.init(); diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 28af2a392d..61780f515d 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -60,10 +60,7 @@ public slots: private: ScriptEngine _scriptEngine; - VoxelEditPacketSender _voxelEditSender; EntityEditPacketSender _entityEditSender; - - VoxelTreeHeadlessViewer _voxelViewer; EntityTreeHeadlessViewer _entityViewer; MixedAudioStream _receivedAudioStream; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6ddf116acd..729b8f990c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -62,7 +62,6 @@ #include #include #include -#include #include #include #include @@ -151,15 +150,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _frameCount(0), _fps(60.0f), _justStarted(true), - _voxelImportDialog(NULL), - _voxelImporter(), - _importSucceded(false), - _sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard), _entities(true, this, this), _entityCollisionSystem(), _entityClipboardRenderer(false, this, this), _entityClipboard(), - _wantToKillLocalVoxels(false), _viewFrustum(), _lastQueriedViewFrustum(), _lastQueriedTime(usecTimestampNow()), @@ -177,7 +171,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _audio(), _enableProcessVoxelsThread(true), _octreeProcessor(), - _voxelHideShowThread(&_voxels), _packetsPerSecond(0), _bytesPerSecond(0), _nodeBoundsDisplay(this), @@ -275,8 +268,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(nodeList, &NodeList::nodeAdded, this, &Application::nodeAdded); connect(nodeList, &NodeList::nodeKilled, this, &Application::nodeKilled); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); - connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); - connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); connect(nodeList, &NodeList::uuidChanged, _myAvatar, &MyAvatar::setSessionUUID); connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); @@ -313,10 +304,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _settings = new QSettings(this); _numChangedSettings = 0; - // Check to see if the user passed in a command line option for loading a local - // Voxel File. - _voxelsFilename = getCmdOption(argc, constArgv, "-i"); - #ifdef _WIN32 WSADATA WsaData; int wsaresult = WSAStartup(MAKEWORD(2,2), &WsaData); @@ -327,8 +314,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : << NodeType::VoxelServer << NodeType::EntityServer << NodeType::MetavoxelServer); - // connect to the packet sent signal of the _voxelEditSender and the _entityEditSender - connect(&_voxelEditSender, &VoxelEditPacketSender::packetSent, this, &Application::packetSent); + // connect to the packet sent signal of the _entityEditSender connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent); // move the silentNodeTimer to the _nodeThread @@ -373,8 +359,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // initialization continues in initializeGL when OpenGL context is ready - // Tell our voxel edit sender about our known jurisdictions - _voxelEditSender.setVoxelServerJurisdictions(&_voxelServerJurisdictions); + // Tell our entity edit sender about our known jurisdictions _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions); // For now we're going to set the PPS for outbound packets to be super high, this is @@ -386,9 +371,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _overlays.init(glCanvas.data()); // do this before scripts load - LocalVoxelsList::getInstance()->addPersistantTree(DOMAIN_TREE_NAME, _voxels.getTree()); - LocalVoxelsList::getInstance()->addPersistantTree(CLIPBOARD_TREE_NAME, &_clipboard); - _runningScriptsWidget->setRunningScripts(getRunningScripts()); connect(_runningScriptsWidget, &RunningScriptsWidget::stopScriptName, this, &Application::stopScript); @@ -446,9 +428,6 @@ Application::~Application() { // make sure we don't call the idle timer any more delete idleTimer; - _sharedVoxelSystem.changeTree(new VoxelTree); - delete _voxelImportDialog; - // let the avatar mixer know we're out MyAvatar::sendKillAvatar(); @@ -467,11 +446,8 @@ Application::~Application() { _audio.thread()->wait(); _octreeProcessor.terminate(); - _voxelHideShowThread.terminate(); - _voxelEditSender.terminate(); _entityEditSender.terminate(); - VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown Menu::getInstance()->deleteLater(); _myAvatar = NULL; @@ -481,9 +457,6 @@ void Application::saveSettings() { Menu::getInstance()->saveSettings(); _rearMirrorTools->saveSettings(_settings); - if (_voxelImportDialog) { - _voxelImportDialog->saveSettings(_settings); - } _settings->sync(); _numChangedSettings = 0; } @@ -568,14 +541,8 @@ void Application::initializeGL() { // create thread for parsing of voxel data independent of the main network and rendering threads _octreeProcessor.initialize(_enableProcessVoxelsThread); - _voxelEditSender.initialize(_enableProcessVoxelsThread); - _voxelHideShowThread.initialize(_enableProcessVoxelsThread); _entityEditSender.initialize(_enableProcessVoxelsThread); - if (_enableProcessVoxelsThread) { - qDebug("Voxel parsing thread created."); - } - // call our timer function every second QTimer* timer = new QTimer(this); connect(timer, SIGNAL(timeout()), SLOT(timer())); @@ -797,10 +764,6 @@ void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { foreach(NodeType_t type, destinationNodeTypes) { - // Intercept data to voxel server when voxels are disabled - if (type == NodeType::VoxelServer && !Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { - continue; - } // Perform the broadcast for one type int nReceivingNodes = NodeList::getInstance()->broadcastToNodes(packet, NodeSet() << type); @@ -812,7 +775,6 @@ void Application::controlledBroadcastToNodes(const QByteArray& packet, const Nod case NodeType::AvatarMixer: channel = BandwidthMeter::AVATARS; break; - case NodeType::VoxelServer: case NodeType::EntityServer: channel = BandwidthMeter::VOXELS; break; @@ -1093,11 +1055,6 @@ void Application::keyPressEvent(QKeyEvent* event) { Menu::getInstance()->triggerOption(MenuOption::DisplayFrustum); } break; - case Qt::Key_V: - if (isShifted) { - Menu::getInstance()->triggerOption(MenuOption::Voxels); - } - break; case Qt::Key_P: Menu::getInstance()->triggerOption(MenuOption::FirstPerson); break; @@ -1442,7 +1399,7 @@ void Application::dropEvent(QDropEvent *event) { void Application::sendPingPackets() { QByteArray pingPacket = NodeList::getInstance()->constructPingPacket(); controlledBroadcastToNodes(pingPacket, NodeSet() - << NodeType::VoxelServer << NodeType::EntityServer + << NodeType::EntityServer << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::MetavoxelServer); } @@ -1588,63 +1545,10 @@ void Application::setEnableVRMode(bool enableVRMode) { resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } -void Application::setRenderVoxels(bool voxelRender) { - _voxelEditSender.setShouldSend(voxelRender); - if (!voxelRender) { - doKillLocalVoxels(); - } -} - void Application::setLowVelocityFilter(bool lowVelocityFilter) { SixenseManager::getInstance().setLowVelocityFilter(lowVelocityFilter); } -void Application::doKillLocalVoxels() { - _wantToKillLocalVoxels = true; -} - -void Application::removeVoxel(glm::vec3 position, - float scale) { - VoxelDetail voxel; - voxel.x = position.x / TREE_SCALE; - voxel.y = position.y / TREE_SCALE; - voxel.z = position.z / TREE_SCALE; - voxel.s = scale / TREE_SCALE; - _voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, voxel); - - // delete it locally to see the effect immediately (and in case no voxel server is present) - _voxels.getTree()->deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s); -} - - -void Application::makeVoxel(glm::vec3 position, - float scale, - unsigned char red, - unsigned char green, - unsigned char blue, - bool isDestructive) { - VoxelDetail voxel; - voxel.x = position.x / TREE_SCALE; - voxel.y = position.y / TREE_SCALE; - voxel.z = position.z / TREE_SCALE; - voxel.s = scale / TREE_SCALE; - voxel.red = red; - voxel.green = green; - voxel.blue = blue; - PacketType message = isDestructive ? PacketTypeVoxelSetDestructive : PacketTypeVoxelSet; - _voxelEditSender.sendVoxelEditMessage(message, voxel); - - // create the voxel locally so it appears immediately - _voxels.getTree()->createVoxel(voxel.x, voxel.y, voxel.z, voxel.s, - voxel.red, voxel.green, voxel.blue, - isDestructive); - } - -glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel) { - return glm::vec3((mouseVoxel.x + mouseVoxel.s / 2.0f) * TREE_SCALE, (mouseVoxel.y + mouseVoxel.s / 2.0f) * TREE_SCALE, - (mouseVoxel.z + mouseVoxel.s / 2.0f) * TREE_SCALE); -} - bool Application::mouseOnScreen() const { if (OculusManager::isConnected()) { GLCanvas::SharedPointer glCanvas = DependencyManager::get(); @@ -1728,88 +1632,6 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa return true; } -bool Application::sendVoxelsOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; - if (voxel->isColored()) { - const unsigned char* nodeOctalCode = voxel->getOctalCode(); - unsigned char* codeColorBuffer = NULL; - int codeLength = 0; - int bytesInCode = 0; - int codeAndColorLength; - - // If the newBase is NULL, then don't rebase - if (args->newBaseOctCode) { - codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); - codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer); - bytesInCode = bytesRequiredForCodeLength(codeLength); - codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; - } else { - codeLength = numberOfThreeBitSectionsInCode(nodeOctalCode); - bytesInCode = bytesRequiredForCodeLength(codeLength); - codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; - codeColorBuffer = new unsigned char[codeAndColorLength]; - memcpy(codeColorBuffer, nodeOctalCode, bytesInCode); - } - - // copy the colors over - codeColorBuffer[bytesInCode + RED_INDEX] = voxel->getColor()[RED_INDEX]; - codeColorBuffer[bytesInCode + GREEN_INDEX] = voxel->getColor()[GREEN_INDEX]; - codeColorBuffer[bytesInCode + BLUE_INDEX] = voxel->getColor()[BLUE_INDEX]; - getInstance()->_voxelEditSender.queueVoxelEditMessage(PacketTypeVoxelSetDestructive, - codeColorBuffer, codeAndColorLength); - - delete[] codeColorBuffer; - } - return true; // keep going -} - -void Application::exportVoxels(const VoxelDetail& sourceVoxel) { - QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); - QString suggestedName = desktopLocation.append("/voxels.svo"); - - QString fileNameString = QFileDialog::getSaveFileName(DependencyManager::get().data(), - tr("Export Voxels"), suggestedName, - tr("Sparse Voxel Octree Files (*.svo)")); - QByteArray fileNameAscii = fileNameString.toLocal8Bit(); - const char* fileName = fileNameAscii.data(); - - VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); - if (selectedNode) { - VoxelTree exportTree; - getVoxelTree()->copySubTreeIntoNewTree(selectedNode, &exportTree, true); - exportTree.writeToSVOFile(fileName); - } - - // restore the main window's active state - _window->activateWindow(); -} - -void Application::importVoxels() { - _importSucceded = false; - - if (!_voxelImportDialog) { - _voxelImportDialog = new VoxelImportDialog(_window); - _voxelImportDialog->loadSettings(_settings); - } - - if (!_voxelImportDialog->exec()) { - qDebug() << "Import succeeded." << endl; - _importSucceded = true; - } else { - qDebug() << "Import failed." << endl; - if (_sharedVoxelSystem.getTree() == _voxelImporter.getVoxelTree()) { - _sharedVoxelSystem.killLocalVoxels(); - _sharedVoxelSystem.changeTree(&_clipboard); - } - } - - // restore the main window's active state - _window->activateWindow(); - - emit importDone(); -} - bool Application::importEntities(const QString& filename) { _entityClipboard.eraseAllOctreeElements(); bool success = _entityClipboard.readFromSVOFile(filename.toLocal8Bit().constData()); @@ -1823,71 +1645,6 @@ void Application::pasteEntities(float x, float y, float z) { _entityClipboard.sendEntities(&_entityEditSender, _entities.getTree(), x, y, z); } -void Application::cutVoxels(const VoxelDetail& sourceVoxel) { - copyVoxels(sourceVoxel); - deleteVoxelAt(sourceVoxel); -} - -void Application::copyVoxels(const VoxelDetail& sourceVoxel) { - // switch to and clear the clipboard first... - _sharedVoxelSystem.killLocalVoxels(); - if (_sharedVoxelSystem.getTree() != &_clipboard) { - _clipboard.eraseAllOctreeElements(); - _sharedVoxelSystem.changeTree(&_clipboard); - } - - // then copy onto it if there is something to copy - VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); - if (selectedNode) { - getVoxelTree()->copySubTreeIntoNewTree(selectedNode, _sharedVoxelSystem.getTree(), true); - _sharedVoxelSystem.forceRedrawEntireTree(); - } -} - -void Application::pasteVoxelsToOctalCode(const unsigned char* octalCodeDestination) { - // Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to - // the server as an set voxel message, this will also rebase the voxels to the new location - SendVoxelsOperationArgs args; - args.newBaseOctCode = octalCodeDestination; - _sharedVoxelSystem.getTree()->recurseTreeWithOperation(sendVoxelsOperation, &args); - - // Switch back to clipboard if it was an import - if (_sharedVoxelSystem.getTree() != &_clipboard) { - _sharedVoxelSystem.killLocalVoxels(); - _sharedVoxelSystem.changeTree(&_clipboard); - } - - _voxelEditSender.releaseQueuedMessages(); -} - -void Application::pasteVoxels(const VoxelDetail& sourceVoxel) { - unsigned char* calculatedOctCode = NULL; - VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); - - // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the - // voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a - // target octalCode for where the user is pointing. - const unsigned char* octalCodeDestination; - if (selectedNode) { - octalCodeDestination = selectedNode->getOctalCode(); - } else { - octalCodeDestination = calculatedOctCode = pointToVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); - } - - pasteVoxelsToOctalCode(octalCodeDestination); - - if (calculatedOctCode) { - delete[] calculatedOctCode; - } -} - -void Application::nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) { - VoxelTreeElement* nodeToNudge = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); - if (nodeToNudge) { - _voxels.getTree()->nudgeSubTree(nodeToNudge, nudgeVec, _voxelEditSender); - } -} - void Application::initDisplay() { glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); @@ -1898,23 +1655,6 @@ void Application::initDisplay() { } void Application::init() { - _sharedVoxelSystemViewFrustum.setPosition(glm::vec3(TREE_SCALE / 2.0f, - TREE_SCALE / 2.0f, - 3.0f * TREE_SCALE / 2.0f)); - _sharedVoxelSystemViewFrustum.setNearClip(TREE_SCALE / 2.0f); - _sharedVoxelSystemViewFrustum.setFarClip(3.0f * TREE_SCALE / 2.0f); - _sharedVoxelSystemViewFrustum.setFieldOfView(90.0f); - _sharedVoxelSystemViewFrustum.setOrientation(glm::quat()); - _sharedVoxelSystemViewFrustum.calculate(); - _sharedVoxelSystem.setViewFrustum(&_sharedVoxelSystemViewFrustum); - - VoxelTreeElement::removeUpdateHook(&_sharedVoxelSystem); - - // Cleanup of the original shared tree - _sharedVoxelSystem.init(); - - _voxelImportDialog = new VoxelImportDialog(_window); - _environment.init(); DependencyManager::get()->init(this); @@ -1987,16 +1727,11 @@ void Application::init() { // fire off an immediate domain-server check in now that settings are loaded NodeList::getInstance()->sendDomainServerCheckIn(); - // Set up VoxelSystem after loading preferences so we can get the desired max voxel count - _voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels()); - _voxels.setDisableFastVoxelPipeline(false); - _voxels.init(); - _entities.init(); _entities.setViewFrustum(getViewFrustum()); EntityTree* entityTree = _entities.getTree(); - _entityCollisionSystem.init(&_entityEditSender, entityTree, _voxels.getTree(), &_audio, &_avatarManager); + _entityCollisionSystem.init(&_entityEditSender, entityTree, NULL, &_audio, &_avatarManager); entityTree->setSimulation(&_entityCollisionSystem); // connect the _entityCollisionSystem to our script engine's EntityScriptingInterface diff --git a/interface/src/Application.h b/interface/src/Application.h index a3c3d51d59..1191752650 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -71,10 +71,7 @@ #include "ui/ToolWindow.h" #include "ui/VoxelImportDialog.h" #include "voxels/VoxelFade.h" -#include "voxels/VoxelHideShowThread.h" -#include "voxels/VoxelImporter.h" #include "voxels/OctreePacketProcessor.h" -#include "voxels/VoxelSystem.h" #include "UndoStackScriptingInterface.h" @@ -174,7 +171,6 @@ public: void removeVoxel(glm::vec3 position, float scale); - glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel); bool isThrottleRendering() const { return DependencyManager::get()->isThrottleRendering(); } MyAvatar* getAvatar() { return _myAvatar; } @@ -184,22 +180,16 @@ public: ViewFrustum* getViewFrustum() { return &_viewFrustum; } ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } - VoxelSystem* getVoxels() { return &_voxels; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } MetavoxelSystem* getMetavoxels() { return &_metavoxels; } EntityTreeRenderer* getEntities() { return &_entities; } - VoxelSystem* getSharedVoxelSystem() { return &_sharedVoxelSystem; } Environment* getEnvironment() { return &_environment; } PrioVR* getPrioVR() { return &_prioVR; } QUndoStack* getUndoStack() { return &_undoStack; } MainWindow* getWindow() { return _window; } - VoxelImporter* getVoxelImporter() { return &_voxelImporter; } - VoxelTree* getClipboard() { return &_clipboard; } EntityTree* getEntityClipboard() { return &_entityClipboard; } EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; } - VoxelTree* getVoxelTree() { return _voxels.getTree(); } - bool getImportSucceded() { return _importSucceded; } bool isMousePressed() const { return _mousePressed; } bool isMouseHidden() const { return DependencyManager::get()->cursor().shape() == Qt::BlankCursor; } @@ -294,9 +284,7 @@ public: glm::vec2 getViewportDimensions() const { return glm::vec2(DependencyManager::get()->getDeviceWidth(), DependencyManager::get()->getDeviceHeight()); } - NodeToJurisdictionMap& getVoxelServerJurisdictions() { return _voxelServerJurisdictions; } NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } - void pasteVoxelsToOctalCode(const unsigned char* octalCodeDestination); void skipVersion(QString latestVersion); @@ -346,17 +334,7 @@ public slots: bool exportEntities(const QString& filename, float x, float y, float z, float scale); bool importEntities(const QString& filename); - void importVoxels(); // doesn't include source voxel because it goes to clipboard - void cutVoxels(const VoxelDetail& sourceVoxel); - void copyVoxels(const VoxelDetail& sourceVoxel); - void pasteVoxels(const VoxelDetail& sourceVoxel); - void deleteVoxels(const VoxelDetail& sourceVoxel); - void exportVoxels(const VoxelDetail& sourceVoxel); - void nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec); - - void setRenderVoxels(bool renderVoxels); void setLowVelocityFilter(bool lowVelocityFilter); - void doKillLocalVoxels(); void loadDialog(); void loadScriptURLDialog(); void toggleLogDialog(); @@ -418,7 +396,6 @@ private: void updateProjectionMatrix(); void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true); - static bool sendVoxelsOperation(OctreeElement* node, void* extraData); void sendPingPackets(); void initDisplay(); @@ -493,22 +470,11 @@ private: bool _justStarted; Stars _stars; - VoxelSystem _voxels; - VoxelTree _clipboard; // if I copy/paste - VoxelImportDialog* _voxelImportDialog; - VoxelImporter _voxelImporter; - bool _importSucceded; - VoxelSystem _sharedVoxelSystem; - ViewFrustum _sharedVoxelSystemViewFrustum; - EntityTreeRenderer _entities; EntityCollisionSystem _entityCollisionSystem; EntityTreeRenderer _entityClipboardRenderer; EntityTree _entityClipboard; - QByteArray _voxelsFilename; - bool _wantToKillLocalVoxels; - MetavoxelSystem _metavoxels; ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. @@ -569,8 +535,6 @@ private: bool _enableProcessVoxelsThread; OctreePacketProcessor _octreeProcessor; - VoxelHideShowThread _voxelHideShowThread; - VoxelEditPacketSender _voxelEditSender; EntityEditPacketSender _entityEditSender; int _packetsPerSecond; @@ -582,7 +546,6 @@ private: int parseOctreeStats(const QByteArray& packet, const SharedNodePointer& sendingNode); void trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket); - NodeToJurisdictionMap _voxelServerJurisdictions; NodeToJurisdictionMap _entityServerJurisdictions; NodeToOctreeSceneStats _octreeServerSceneStats; QReadWriteLock _octreeSceneStatsLock; From 4ea9bbc309fdb60fdd07c7a7161a0ebb7be07ab2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 18:08:58 -0800 Subject: [PATCH 02/27] first major pass at voxelEctomy --- assignment-client/src/Agent.h | 2 - assignment-client/src/AssignmentFactory.cpp | 3 - assignment-client/src/voxels/VoxelNodeData.h | 25 - assignment-client/src/voxels/VoxelServer.cpp | 102 - assignment-client/src/voxels/VoxelServer.h | 62 - .../src/voxels/VoxelServerConsts.h | 21 - interface/src/Application.cpp | 107 +- interface/src/Application.h | 23 +- interface/src/DatagramProcessor.cpp | 5 - interface/src/Menu.cpp | 32 - interface/src/Menu.h | 2 - interface/src/avatar/Avatar.cpp | 1 + interface/src/avatar/MyAvatar.cpp | 15 +- interface/src/avatar/SkeletonModel.cpp | 1 + .../scripting/ClipboardScriptingInterface.cpp | 118 -- .../scripting/ClipboardScriptingInterface.h | 24 - interface/src/ui/ApplicationOverlay.cpp | 1 + interface/src/ui/NodeBounds.cpp | 17 +- interface/src/ui/NodeBounds.h | 3 - interface/src/ui/OctreeStatsDialog.cpp | 23 +- interface/src/ui/OctreeStatsDialog.h | 1 - interface/src/ui/PreferencesDialog.cpp | 2 +- interface/src/ui/ScriptEditorWidget.cpp | 1 + interface/src/ui/ScriptEditorWindow.cpp | 2 + interface/src/ui/Stats.cpp | 40 +- interface/src/ui/VoxelImportDialog.cpp | 362 ---- interface/src/ui/VoxelImportDialog.h | 81 - .../src/ui/overlays/LocalVoxelsOverlay.cpp | 127 -- .../src/ui/overlays/LocalVoxelsOverlay.h | 54 - interface/src/ui/overlays/Overlays.cpp | 3 - .../src/voxels/OctreePacketProcessor.cpp | 16 +- interface/src/voxels/VoxelHideShowThread.cpp | 47 - interface/src/voxels/VoxelHideShowThread.h | 35 - interface/src/voxels/VoxelImporter.cpp | 119 -- interface/src/voxels/VoxelImporter.h | 51 - interface/src/voxels/VoxelSystem.cpp | 1661 ----------------- interface/src/voxels/VoxelSystem.h | 246 --- .../src/EntityTreeRenderer.cpp | 11 - .../src/EntityTreeRenderer.h | 1 - .../entities/src/EntityCollisionSystem.cpp | 45 +- .../entities/src/EntityCollisionSystem.h | 8 +- libraries/entities/src/EntityItem.cpp | 2 - libraries/entities/src/EntityItem.h | 1 - .../entities/src/EntityScriptingInterface.h | 7 +- libraries/fbx/src/FBXReader.cpp | 166 -- libraries/fbx/src/FBXReader.h | 3 - libraries/render-utils/src/GeometryCache.cpp | 9 +- libraries/script-engine/src/LocalVoxels.cpp | 165 -- libraries/script-engine/src/LocalVoxels.h | 102 - libraries/script-engine/src/ScriptEngine.cpp | 40 +- libraries/script-engine/src/ScriptEngine.h | 7 +- libraries/voxels/src/LocalVoxelsList.cpp | 63 - libraries/voxels/src/LocalVoxelsList.h | 62 - .../voxels/src/VoxelEditPacketSender.cpp | 155 -- libraries/voxels/src/VoxelEditPacketSender.h | 63 - libraries/voxels/src/VoxelTree.cpp | 591 ------ libraries/voxels/src/VoxelTree.h | 87 - libraries/voxels/src/VoxelTreeCommands.cpp | 160 -- libraries/voxels/src/VoxelTreeCommands.h | 51 - libraries/voxels/src/VoxelTreeElement.cpp | 253 --- libraries/voxels/src/VoxelTreeElement.h | 123 -- .../voxels/src/VoxelTreeHeadlessViewer.cpp | 24 - .../voxels/src/VoxelTreeHeadlessViewer.h | 42 - .../voxels/src/VoxelsScriptingInterface.cpp | 215 --- .../voxels/src/VoxelsScriptingInterface.h | 108 -- 65 files changed, 43 insertions(+), 5956 deletions(-) delete mode 100644 assignment-client/src/voxels/VoxelNodeData.h delete mode 100644 assignment-client/src/voxels/VoxelServer.cpp delete mode 100644 assignment-client/src/voxels/VoxelServer.h delete mode 100644 assignment-client/src/voxels/VoxelServerConsts.h delete mode 100644 interface/src/ui/VoxelImportDialog.cpp delete mode 100644 interface/src/ui/VoxelImportDialog.h delete mode 100644 interface/src/ui/overlays/LocalVoxelsOverlay.cpp delete mode 100644 interface/src/ui/overlays/LocalVoxelsOverlay.h delete mode 100644 interface/src/voxels/VoxelHideShowThread.cpp delete mode 100644 interface/src/voxels/VoxelHideShowThread.h delete mode 100644 interface/src/voxels/VoxelImporter.cpp delete mode 100644 interface/src/voxels/VoxelImporter.h delete mode 100644 interface/src/voxels/VoxelSystem.cpp delete mode 100644 interface/src/voxels/VoxelSystem.h delete mode 100644 libraries/script-engine/src/LocalVoxels.cpp delete mode 100644 libraries/script-engine/src/LocalVoxels.h delete mode 100644 libraries/voxels/src/LocalVoxelsList.cpp delete mode 100644 libraries/voxels/src/LocalVoxelsList.h delete mode 100644 libraries/voxels/src/VoxelEditPacketSender.cpp delete mode 100644 libraries/voxels/src/VoxelEditPacketSender.h delete mode 100644 libraries/voxels/src/VoxelTree.cpp delete mode 100644 libraries/voxels/src/VoxelTree.h delete mode 100644 libraries/voxels/src/VoxelTreeCommands.cpp delete mode 100644 libraries/voxels/src/VoxelTreeCommands.h delete mode 100644 libraries/voxels/src/VoxelTreeElement.cpp delete mode 100644 libraries/voxels/src/VoxelTreeElement.h delete mode 100644 libraries/voxels/src/VoxelTreeHeadlessViewer.cpp delete mode 100644 libraries/voxels/src/VoxelTreeHeadlessViewer.h delete mode 100644 libraries/voxels/src/VoxelsScriptingInterface.cpp delete mode 100644 libraries/voxels/src/VoxelsScriptingInterface.h diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 61780f515d..ffae3c6c21 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include "MixedAudioStream.h" diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 63c87313fe..78e905edfa 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -17,7 +17,6 @@ #include "avatars/AvatarMixer.h" #include "metavoxels/MetavoxelServer.h" #include "entities/EntityServer.h" -#include "voxels/VoxelServer.h" ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet) { QDataStream packetStream(packet); @@ -35,8 +34,6 @@ ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet return new AvatarMixer(packet); case Assignment::AgentType: return new Agent(packet); - case Assignment::VoxelServerType: - return new VoxelServer(packet); case Assignment::MetavoxelServerType: return new MetavoxelServer(packet); case Assignment::EntityServerType: diff --git a/assignment-client/src/voxels/VoxelNodeData.h b/assignment-client/src/voxels/VoxelNodeData.h deleted file mode 100644 index dada32ac3e..0000000000 --- a/assignment-client/src/voxels/VoxelNodeData.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// VoxelNodeData.h -// assignment-client/src/voxels -// -// Created by Stephen Birarda on 3/21/13. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelNodeData_h -#define hifi_VoxelNodeData_h - -#include - -#include "../octree/OctreeQueryNode.h" - -class VoxelNodeData : public OctreeQueryNode { -public: - VoxelNodeData() : OctreeQueryNode() { } - virtual PacketType getMyPacketType() const { return PacketTypeVoxelData; } -}; - -#endif // hifi_VoxelNodeData_h diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp deleted file mode 100644 index a83e3e99e3..0000000000 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// VoxelServer.cpp -// assignment-client/src/voxels -// -// Created by Brad Hefta-Gaub on 9/16/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "VoxelServer.h" -#include "VoxelServerConsts.h" -#include "VoxelNodeData.h" - -const char* VOXEL_SERVER_NAME = "Voxel"; -const char* VOXEL_SERVER_LOGGING_TARGET_NAME = "voxel-server"; -const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; - -VoxelServer::VoxelServer(const QByteArray& packet) : OctreeServer(packet) { - // nothing special to do here... -} - -VoxelServer::~VoxelServer() { - // nothing special to do here... -} - -OctreeQueryNode* VoxelServer::createOctreeQueryNode() { - return new VoxelNodeData(); -} - -Octree* VoxelServer::createTree() { - return new VoxelTree(true); -} - -bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { - bool shouldSendEnvironments = _sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, OCTREE_SEND_INTERVAL_USECS); - return shouldSendEnvironments; -} - -int VoxelServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { - - unsigned char* copyAt = _tempOutputBuffer; - - int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_tempOutputBuffer), PacketTypeEnvironmentData); - copyAt += numBytesPacketHeader; - int envPacketLength = numBytesPacketHeader; - - // pack in flags - OCTREE_PACKET_FLAGS flags = 0; - OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; - *flagsAt = flags; - copyAt += sizeof(OCTREE_PACKET_FLAGS); - envPacketLength += sizeof(OCTREE_PACKET_FLAGS); - - // pack in sequence number - OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; - *sequenceAt = queryNode->getSequenceNumber(); - copyAt += sizeof(OCTREE_PACKET_SEQUENCE); - envPacketLength += sizeof(OCTREE_PACKET_SEQUENCE); - - // pack in timestamp - OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); - OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; - *timeAt = now; - copyAt += sizeof(OCTREE_PACKET_SENT_TIME); - envPacketLength += sizeof(OCTREE_PACKET_SENT_TIME); - - int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); - - for (int i = 0; i < environmentsToSend; i++) { - envPacketLength += getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength); - } - - NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); - queryNode->packetSent(_tempOutputBuffer, envPacketLength); - packetsSent = 1; - - return envPacketLength; -} - - -void VoxelServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { - // should we send environments? Default is yes, but this command line suppresses sending - readOptionBool(QString("sendEnvironments"), settingsSectionObject, _sendEnvironments); - bool dontSendEnvironments = !_sendEnvironments; - if (dontSendEnvironments) { - qDebug("Sending environments suppressed..."); - } else { - // should we send environments? Default is yes, but this command line suppresses sending - //const char* MINIMAL_ENVIRONMENT = "--minimalEnvironment"; - //_sendMinimalEnvironment = cmdOptionExists(_argc, _argv, MINIMAL_ENVIRONMENT); - - readOptionBool(QString("minimalEnvironment"), settingsSectionObject, _sendMinimalEnvironment); - qDebug("Using Minimal Environment=%s", debug::valueOf(_sendMinimalEnvironment)); - } - qDebug("Sending environments=%s", debug::valueOf(_sendEnvironments)); - - NodeList::getInstance()->addNodeTypeToInterestSet(NodeType::AnimationServer); -} diff --git a/assignment-client/src/voxels/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h deleted file mode 100644 index 4d21695f33..0000000000 --- a/assignment-client/src/voxels/VoxelServer.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// VoxelServer.h -// assignment-client/src/voxels -// -// Created by Brad Hefta-Gaub on 8/21/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelServer_h -#define hifi_VoxelServer_h - -#include -#include -#include - -#include -#include - -#include "../octree/OctreeServer.h" - -#include "VoxelServerConsts.h" - -/// Handles assignments of type VoxelServer - sending voxels to various clients. -class VoxelServer : public OctreeServer { -public: - VoxelServer(const QByteArray& packet); - ~VoxelServer(); - - bool wantSendEnvironments() const { return _sendEnvironments; } - bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; } - EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; } - int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); } - - // Subclasses must implement these methods - virtual OctreeQueryNode* createOctreeQueryNode(); - virtual char getMyNodeType() const { return NodeType::VoxelServer; } - virtual PacketType getMyQueryMessageType() const { return PacketTypeVoxelQuery; } - virtual const char* getMyServerName() const { return VOXEL_SERVER_NAME; } - virtual const char* getMyLoggingServerTargetName() const { return VOXEL_SERVER_LOGGING_TARGET_NAME; } - virtual const char* getMyDefaultPersistFilename() const { return LOCAL_VOXELS_PERSIST_FILE; } - virtual PacketType getMyEditNackType() const { return PacketTypeVoxelEditNack; } - virtual QString getMyDomainSettingsKey() const { return QString("voxel_server_settings"); } - - // subclass may implement these method - virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent); - -protected: - virtual Octree* createTree(); - virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject); - -private: - bool _sendEnvironments; - bool _sendMinimalEnvironment; - EnvironmentData _environmentData[3]; - unsigned char _tempOutputBuffer[MAX_PACKET_SIZE]; -}; - -#endif // hifi_VoxelServer_h diff --git a/assignment-client/src/voxels/VoxelServerConsts.h b/assignment-client/src/voxels/VoxelServerConsts.h deleted file mode 100644 index 5764e7d4cf..0000000000 --- a/assignment-client/src/voxels/VoxelServerConsts.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// VoxelServerConsts.h -// assignment-client/src/voxels -// -// Created by Brad Hefta-Gaub on 8/21/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelServerConsts_h -#define hifi_VoxelServerConsts_h - -extern const char* VOXEL_SERVER_NAME; -extern const char* VOXEL_SERVER_LOGGING_TARGET_NAME; -extern const char* LOCAL_VOXELS_PERSIST_FILE; - -const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000; - -#endif // hifi_VoxelServerConsts_h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 729b8f990c..40b6c4003a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -169,7 +169,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isTouchPressed(false), _mousePressed(false), _audio(), - _enableProcessVoxelsThread(true), + _enableProcessOctreeThread(true), _octreeProcessor(), _packetsPerSecond(0), _bytesPerSecond(0), @@ -311,7 +311,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // tell the NodeList instance who to tell the domain server we care about nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer - << NodeType::VoxelServer << NodeType::EntityServer + << NodeType::EntityServer << NodeType::MetavoxelServer); // connect to the packet sent signal of the _entityEditSender @@ -539,9 +539,9 @@ void Application::initializeGL() { init(); qDebug( "init() complete."); - // create thread for parsing of voxel data independent of the main network and rendering threads - _octreeProcessor.initialize(_enableProcessVoxelsThread); - _entityEditSender.initialize(_enableProcessVoxelsThread); + // create thread for parsing of octee data independent of the main network and rendering threads + _octreeProcessor.initialize(_enableProcessOctreeThread); + _entityEditSender.initialize(_enableProcessOctreeThread); // call our timer function every second QTimer* timer = new QTimer(this); @@ -1731,20 +1731,14 @@ void Application::init() { _entities.setViewFrustum(getViewFrustum()); EntityTree* entityTree = _entities.getTree(); - _entityCollisionSystem.init(&_entityEditSender, entityTree, NULL, &_audio, &_avatarManager); + _entityCollisionSystem.init(&_entityEditSender, entityTree, &_audio, &_avatarManager); entityTree->setSimulation(&_entityCollisionSystem); - // connect the _entityCollisionSystem to our script engine's EntityScriptingInterface - connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithVoxel, - ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithVoxel); connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity, ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithEntity); // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts - connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithVoxel, - &_entities, &EntityTreeRenderer::entityCollisionWithVoxel); - connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity, &_entities, &EntityTreeRenderer::entityCollisionWithEntity); @@ -1951,10 +1945,8 @@ void Application::updateThreads(float deltaTime) { PerformanceWarning warn(showWarnings, "Application::updateThreads()"); // parse voxel packets - if (!_enableProcessVoxelsThread) { + if (!_enableProcessOctreeThread) { _octreeProcessor.threadRoutine(); - _voxelHideShowThread.threadRoutine(); - _voxelEditSender.threadRoutine(); _entityEditSender.threadRoutine(); } } @@ -2134,9 +2126,6 @@ void Application::update(float deltaTime) { if (queryIsDue || viewIsDifferentEnough) { _lastQueriedTime = now; - if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { - queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions); - } if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) { queryOctree(NodeType::EntityServer, PacketTypeEntityQuery, _entityServerJurisdictions); } @@ -2837,14 +2826,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr glColor3f(1,0,0); DependencyManager::get()->renderSphere(originSphereRadius, 15, 15); - // Draw voxels - if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { - PerformanceTimer perfTimer("voxels"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... voxels..."); - _voxels.render(); - } - // also, metavoxels if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) { PerformanceTimer perfTimer("metavoxels"); @@ -3308,20 +3289,6 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { } } -void Application::deleteVoxels(const VoxelDetail& voxel) { - deleteVoxelAt(voxel); -} - -void Application::deleteVoxelAt(const VoxelDetail& voxel) { - if (voxel.s != 0) { - // sending delete to the server is sufficient, server will send new version so we see updates soon enough - _voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, voxel); - - // delete it locally to see the effect immediately (and in case no voxel server is present) - _voxels.getTree()->deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s); - } -} - void Application::resetSensors() { DependencyManager::get()->reset(); DependencyManager::get()->reset(); @@ -3422,10 +3389,6 @@ void Application::clearDomainOctreeDetails() { _environment.resetToDefault(); // reset our node to stats and node to jurisdiction maps... since these must be changing... - _voxelServerJurisdictions.lockForWrite(); - _voxelServerJurisdictions.clear(); - _voxelServerJurisdictions.unlock(); - _entityServerJurisdictions.lockForWrite(); _entityServerJurisdictions.clear(); _entityServerJurisdictions.unlock(); @@ -3437,8 +3400,6 @@ void Application::clearDomainOctreeDetails() { // reset the model renderer _entities.clear(); - // reset the voxels renderer - _voxels.killLocalVoxels(); } void Application::domainChanged(const QString& domainHostname) { @@ -3475,51 +3436,13 @@ void Application::nodeKilled(SharedNodePointer node) { _octreeProcessor.nodeKilled(node); - _voxelEditSender.nodeKilled(node); _entityEditSender.nodeKilled(node); if (node->getType() == NodeType::AudioMixer) { QMetaObject::invokeMethod(&_audio, "audioMixerKilled"); } - if (node->getType() == NodeType::VoxelServer) { - QUuid nodeUUID = node->getUUID(); - // see if this is the first we've heard of this node... - _voxelServerJurisdictions.lockForRead(); - if (_voxelServerJurisdictions.find(nodeUUID) != _voxelServerJurisdictions.end()) { - unsigned char* rootCode = _voxelServerJurisdictions[nodeUUID].getRootOctalCode(); - VoxelPositionSize rootDetails; - voxelDetailsForCode(rootCode, rootDetails); - _voxelServerJurisdictions.unlock(); - - qDebug("voxel server going away...... v[%f, %f, %f, %f]", - rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s); - - // Add the jurisditionDetails object to the list of "fade outs" - if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnVoxelServerChanges)) { - VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE); - fade.voxelDetails = rootDetails; - const float slightly_smaller = 0.99f; - fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller; - _voxelFadesLock.lockForWrite(); - _voxelFades.push_back(fade); - _voxelFadesLock.unlock(); - } - - // If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server - _voxelServerJurisdictions.lockForWrite(); - _voxelServerJurisdictions.erase(_voxelServerJurisdictions.find(nodeUUID)); - } - _voxelServerJurisdictions.unlock(); - - // also clean up scene stats for that server - _octreeSceneStatsLock.lockForWrite(); - if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { - _octreeServerSceneStats.erase(nodeUUID); - } - _octreeSceneStatsLock.unlock(); - - } else if (node->getType() == NodeType::EntityServer) { + if (node->getType() == NodeType::EntityServer) { QUuid nodeUUID = node->getUUID(); // see if this is the first we've heard of this node... @@ -3563,7 +3486,7 @@ void Application::nodeKilled(SharedNodePointer node) { } } -void Application::trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket) { +void Application::trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket) { // Attempt to identify the sender from it's address. if (sendingNode) { @@ -3607,10 +3530,7 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin // see if this is the first we've heard of this node... NodeToJurisdictionMap* jurisdiction = NULL; QString serverType; - if (sendingNode->getType() == NodeType::VoxelServer) { - jurisdiction = &_voxelServerJurisdictions; - serverType = "Voxel"; - } else { + if (sendingNode->getType() == NodeType::EntityServer) { jurisdiction = &_entityServerJurisdictions; serverType = "Entity"; } @@ -3704,9 +3624,6 @@ void joystickFromScriptValue(const QScriptValue &object, Joystick* &out) { void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) { // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so // we can use the same ones from the application. - scriptEngine->getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender); - scriptEngine->getVoxelsScriptingInterface()->setVoxelTree(_voxels.getTree()); - scriptEngine->getVoxelsScriptingInterface()->setUndoStack(&_undoStack); scriptEngine->getEntityScriptingInterface()->setPacketSender(&_entityEditSender); scriptEngine->getEntityScriptingInterface()->setEntityTree(_entities.getTree()); @@ -3968,10 +3885,6 @@ void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject qDebug() << "Voxel costs are" << satoshisPerVoxel << "per voxel and" << satoshisPerMeterCubed << "per meter cubed"; qDebug() << "Destination wallet UUID for voxel payments is" << voxelWalletUUID; - - _voxelEditSender.setSatoshisPerVoxel(satoshisPerVoxel); - _voxelEditSender.setSatoshisPerMeterCubed(satoshisPerMeterCubed); - _voxelEditSender.setDestinationWalletUUID(voxelWalletUUID); } QString Application::getPreviousScriptLocation() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 1191752650..75cc07400f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -36,7 +36,6 @@ #include #include #include -#include #include "Audio.h" #include "Camera.h" @@ -69,7 +68,6 @@ #include "ui/ApplicationOverlay.h" #include "ui/RunningScriptsWidget.h" #include "ui/ToolWindow.h" -#include "ui/VoxelImportDialog.h" #include "voxels/VoxelFade.h" #include "voxels/OctreePacketProcessor.h" @@ -121,7 +119,6 @@ class Application : public QApplication, public AbstractViewStateInterface, Abst Q_OBJECT friend class OctreePacketProcessor; - friend class VoxelEditPacketSender; friend class DatagramProcessor; public: @@ -162,15 +159,6 @@ public: bool event(QEvent* event); bool eventFilter(QObject* object, QEvent* event); - void makeVoxel(glm::vec3 position, - float scale, - unsigned char red, - unsigned char green, - unsigned char blue, - bool isDestructive); - - void removeVoxel(glm::vec3 position, float scale); - bool isThrottleRendering() const { return DependencyManager::get()->isThrottleRendering(); } MyAvatar* getAvatar() { return _myAvatar; } @@ -429,12 +417,7 @@ private: void updateShadowMap(); void renderRearViewMirror(const QRect& region, bool billboard = false); void renderViewFrustum(ViewFrustum& viewFrustum); - void checkBandwidthMeterClick(); - - void deleteVoxelAt(const VoxelDetail& voxel); - void eyedropperVoxelUnderCursor(); - void setMenuShortcutsEnabled(bool enabled); static void attachNewHeadToNode(Node *newNode); @@ -485,7 +468,7 @@ private: float _trailingAudioLoudness; - OctreeQuery _octreeQuery; // NodeData derived class for querying voxels from voxel server + OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers AvatarManager _avatarManager; MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) @@ -533,7 +516,7 @@ private: Audio _audio; - bool _enableProcessVoxelsThread; + bool _enableProcessOctreeThread; OctreePacketProcessor _octreeProcessor; EntityEditPacketSender _entityEditSender; @@ -544,7 +527,7 @@ private: float _idleLoopMeasuredJitter; int parseOctreeStats(const QByteArray& packet, const SharedNodePointer& sendingNode); - void trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket); + void trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket); NodeToJurisdictionMap _entityServerJurisdictions; NodeToOctreeSceneStats _octreeServerSceneStats; diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 96680423ed..1b7e27776e 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -167,11 +167,6 @@ void DatagramProcessor::processDatagrams() { } break; } - case PacketTypeVoxelEditNack: - if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) { - application->_voxelEditSender.processNackPacket(incomingPacket); - } - break; case PacketTypeEntityEditNack: if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) { application->_entityEditSender.processNackPacket(incomingPacket); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3e9bdde1ff..f7e8df90e4 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -635,11 +635,6 @@ Menu::Menu() : connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled())); - addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, - Qt::CTRL | Qt::SHIFT | Qt::Key_V, - this, - SLOT(pasteToVoxel())); - #ifndef Q_OS_MAC QMenu* helpMenu = addMenu("Help"); QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp); @@ -1259,33 +1254,6 @@ void Menu::nameLocation() { _newLocationDialog->showNormal(); } -void Menu::pasteToVoxel() { - QInputDialog pasteToOctalCodeDialog(Application::getInstance()->getWindow()); - pasteToOctalCodeDialog.setWindowTitle("Paste to Voxel"); - pasteToOctalCodeDialog.setLabelText("Octal Code:"); - QString octalCode = ""; - pasteToOctalCodeDialog.setTextValue(octalCode); - pasteToOctalCodeDialog.setWindowFlags(Qt::Sheet); - pasteToOctalCodeDialog.resize(pasteToOctalCodeDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, - pasteToOctalCodeDialog.size().height()); - - int dialogReturn = pasteToOctalCodeDialog.exec(); - if (dialogReturn == QDialog::Accepted && !pasteToOctalCodeDialog.textValue().isEmpty()) { - // we got an octalCode to paste to... - QString locationToPaste = pasteToOctalCodeDialog.textValue(); - unsigned char* octalCodeDestination = hexStringToOctalCode(locationToPaste); - - // check to see if it was a legit octcode... - if (locationToPaste == octalCodeToHexString(octalCodeDestination)) { - Application::getInstance()->pasteVoxelsToOctalCode(octalCodeDestination); - } else { - qDebug() << "Problem with octcode..."; - } - } - - sendFakeEnterEvent(); -} - void Menu::toggleLoginMenuItem() { AccountManager& accountManager = AccountManager::getInstance(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a3e32b3682..3fa3d7372d 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -190,7 +190,6 @@ public slots: void importSettings(); void exportSettings(); void toggleAddressBar(); - void pasteToVoxel(); void toggleLoginMenuItem(); void toggleSixense(bool shouldEnable); @@ -428,7 +427,6 @@ namespace MenuOption { const QString OffAxisProjection = "Off-Axis Projection"; const QString OldVoxelCullingMode = "Old Voxel Culling Mode"; const QString Pair = "Pair"; - const QString PasteToVoxel = "Paste to Voxel..."; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "Preferences..."; const QString Quit = "Quit"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 3e57fc7dba..6a659abf93 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -41,6 +41,7 @@ #include "ModelReferential.h" #include "Physics.h" #include "Recorder.h" +#include "Util.h" #include "world.h" #include "devices/OculusManager.h" diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 81d00bae74..f34f5f2c67 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -42,6 +42,7 @@ #include "Recorder.h" #include "devices/Faceshift.h" #include "devices/OculusManager.h" +#include "Util.h" using namespace std; @@ -1459,20 +1460,6 @@ static CollisionList myCollisions(64); void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) { - quint64 now = usecTimestampNow(); - if (_voxelShapeManager.needsUpdate(now)) { - // We use a multiple of the avatar's boundingRadius as the size of the cube of interest. - float cubeScale = 6.0f * getBoundingRadius(); - glm::vec3 corner = getPosition() - glm::vec3(0.5f * cubeScale); - AACube boundingCube(corner, cubeScale); - - // query the VoxelTree for cubes that touch avatar's boundingCube - CubeList cubes; - if (Application::getInstance()->getVoxelTree()->findContentInCube(boundingCube, cubes)) { - _voxelShapeManager.updateVoxels(now, cubes); - } - } - // TODO: Andrew to do ground/walking detection in ragdoll mode if (!Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagdoll)) { const float MAX_VOXEL_COLLISION_SPEED = 100.0f; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index b707861677..77cbfd4e87 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -21,6 +21,7 @@ #include "Menu.h" #include "SkeletonModel.h" #include "SkeletonRagdoll.h" +#include "Util.h" enum StandingFootState { LEFT_FOOT, diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index 23ec175d09..30cd3ba44d 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -15,124 +15,6 @@ ClipboardScriptingInterface::ClipboardScriptingInterface() { connect(this, SIGNAL(readyToImport()), Application::getInstance(), SLOT(importVoxels())); } -void ClipboardScriptingInterface::cutVoxel(const VoxelDetail& sourceVoxel) { - cutVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); -} - -void ClipboardScriptingInterface::cutVoxel(float x, float y, float z, float s) { - VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - s / (float)TREE_SCALE }; - Application::getInstance()->cutVoxels(sourceVoxel); -} - -void ClipboardScriptingInterface::copyVoxel(const VoxelDetail& sourceVoxel) { - copyVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); -} - -void ClipboardScriptingInterface::copyVoxel(float x, float y, float z, float s) { - VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - s / (float)TREE_SCALE }; - Application::getInstance()->copyVoxels(sourceVoxel); -} - -void ClipboardScriptingInterface::pasteVoxel(const VoxelDetail& destinationVoxel) { - pasteVoxel(destinationVoxel.x, destinationVoxel.y, destinationVoxel.z, destinationVoxel.s); -} - -void ClipboardScriptingInterface::pasteVoxel(float x, float y, float z, float s) { - VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - s / (float)TREE_SCALE }; - - Application::getInstance()->pasteVoxels(sourceVoxel); -} - -void ClipboardScriptingInterface::deleteVoxel(const VoxelDetail& sourceVoxel) { - deleteVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); -} - -void ClipboardScriptingInterface::deleteVoxel(float x, float y, float z, float s) { - VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - s / (float)TREE_SCALE }; - Application::getInstance()->deleteVoxels(sourceVoxel); -} - -void ClipboardScriptingInterface::exportVoxel(const VoxelDetail& sourceVoxel) { - exportVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); -} - -void ClipboardScriptingInterface::exportVoxel(float x, float y, float z, float s) { - VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - s / (float)TREE_SCALE }; - - Application::getInstance()->exportVoxels(sourceVoxel); -} - -bool ClipboardScriptingInterface::importVoxels() { - qDebug() << "Importing ... "; - QEventLoop loop; - connect(Application::getInstance(), SIGNAL(importDone()), &loop, SLOT(quit())); - emit readyToImport(); - loop.exec(); - - return Application::getInstance()->getImportSucceded(); -} - -bool ClipboardScriptingInterface::importVoxels(const QString& filename) { - qDebug() << "Importing ... "; - - VoxelImporter* importer = Application::getInstance()->getVoxelImporter(); - - if (!importer->validImportFile(filename)) { - return false; - } - - QEventLoop loop; - connect(importer, SIGNAL(importDone()), &loop, SLOT(quit())); - importer->import(filename); - loop.exec(); - - return true; -} - -bool ClipboardScriptingInterface::importVoxels(const QString& filename, float x, float y, float z, float s) { - bool success = importVoxels(filename); - - if (success) { - pasteVoxel(x, y, z, s); - } - - return success; -} - -bool ClipboardScriptingInterface::importVoxels(const QString& filename, const VoxelDetail& destinationVoxel) { - return importVoxels(filename, destinationVoxel.x, destinationVoxel.y, destinationVoxel.z, destinationVoxel.s); -} - -void ClipboardScriptingInterface::nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) { - nudgeVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s, nudgeVec); -} - -void ClipboardScriptingInterface::nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec) { - glm::vec3 nudgeVecInTreeSpace = nudgeVec / (float)TREE_SCALE; - VoxelDetail sourceVoxel = { x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - s / (float)TREE_SCALE }; - - Application::getInstance()->nudgeVoxelsByVector(sourceVoxel, nudgeVecInTreeSpace); -} - - bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) { return Application::getInstance()->exportEntities(filename, x, y, z, s); } diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 98afc8d6a1..bc270210dc 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -12,7 +12,6 @@ #define hifi_ClipboardScriptingInterface_h #include -#include class ClipboardScriptingInterface : public QObject { Q_OBJECT @@ -23,29 +22,6 @@ signals: void readyToImport(); public slots: - void cutVoxel(const VoxelDetail& sourceVoxel); - void cutVoxel(float x, float y, float z, float s); - - void copyVoxel(const VoxelDetail& sourceVoxel); - void copyVoxel(float x, float y, float z, float s); - - void pasteVoxel(const VoxelDetail& destinationVoxel); - void pasteVoxel(float x, float y, float z, float s); - - void deleteVoxel(const VoxelDetail& sourceVoxel); - void deleteVoxel(float x, float y, float z, float s); - - void exportVoxel(const VoxelDetail& sourceVoxel); - void exportVoxel(float x, float y, float z, float s); - - bool importVoxels(); - bool importVoxels(const QString& filename); - bool importVoxels(const QString& filename, float x, float y, float z, float s); - bool importVoxels(const QString& filename, const VoxelDetail& destinationVoxel); - - void nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec); - void nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec); - bool importEntities(const QString& filename); bool exportEntities(const QString& filename, float x, float y, float z, float s); void pasteEntities(float x, float y, float z, float s); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 120c5b3043..24fbc35457 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -20,6 +20,7 @@ #include "ApplicationOverlay.h" #include "devices/OculusManager.h" +#include "Util.h" #include "ui/Stats.h" // Used to fade the UI diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index fe8a394fe4..a2688cba8e 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -5,7 +5,7 @@ // Created by Ryan Huffman on 05/14/14. // Copyright 2014 High Fidelity, Inc. // -// This class draws a border around the different Voxel, Entity nodes on the current domain, +// This class draws a border around the different Entity nodes on the current domain, // and a semi-transparent cube around the currently mouse-overed node. // // Distributed under the Apache License, Version 2.0. @@ -21,19 +21,17 @@ NodeBounds::NodeBounds(QObject* parent) : QObject(parent), - _showVoxelNodes(false), _showEntityNodes(false), _overlayText() { } void NodeBounds::draw() { - if (!(_showVoxelNodes || _showEntityNodes)) { + if (!_showEntityNodes) { _overlayText[0] = '\0'; return; } - NodeToJurisdictionMap& voxelServerJurisdictions = Application::getInstance()->getVoxelServerJurisdictions(); NodeToJurisdictionMap& entityServerJurisdictions = Application::getInstance()->getEntityServerJurisdictions(); NodeToJurisdictionMap* serverJurisdictions; @@ -54,9 +52,7 @@ void NodeBounds::draw() { nodeList->eachNode([&](const SharedNodePointer& node){ NodeType_t nodeType = node->getType(); - if (nodeType == NodeType::VoxelServer && _showVoxelNodes) { - serverJurisdictions = &voxelServerJurisdictions; - } else if (nodeType == NodeType::EntityServer && _showEntityNodes) { + if (nodeType == NodeType::EntityServer && _showEntityNodes) { serverJurisdictions = &entityServerJurisdictions; } else { return; @@ -81,7 +77,6 @@ void NodeBounds::draw() { glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR) + ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f); - const float VOXEL_NODE_SCALE = 1.00f; const float ENTITY_NODE_SCALE = 0.99f; float scaleFactor = rootDetails.s * TREE_SCALE; @@ -91,9 +86,7 @@ void NodeBounds::draw() { scaleFactor *= 0.92 + (rootDetails.s * 0.08); // Scale different node types slightly differently because it's common for them to overlap. - if (nodeType == NodeType::VoxelServer) { - scaleFactor *= VOXEL_NODE_SCALE; - } else if (nodeType == NodeType::EntityServer) { + if (nodeType == NodeType::EntityServer) { scaleFactor *= ENTITY_NODE_SCALE; } @@ -205,7 +198,7 @@ void NodeBounds::drawNodeBorder(const glm::vec3& center, float scale, float red, } void NodeBounds::getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue) { - red = nodeType == NodeType::VoxelServer ? 1.0 : 0.0; + red = nodeType == 0.0; green = 0.0; blue = nodeType == NodeType::EntityServer ? 1.0 : 0.0; } diff --git a/interface/src/ui/NodeBounds.h b/interface/src/ui/NodeBounds.h index 39f98200d1..66255a6432 100644 --- a/interface/src/ui/NodeBounds.h +++ b/interface/src/ui/NodeBounds.h @@ -23,7 +23,6 @@ class NodeBounds : public QObject { public: NodeBounds(QObject* parent = NULL); - bool getShowVoxelNodes() { return _showVoxelNodes; } bool getShowEntityNodes() { return _showEntityNodes; } bool getShowParticleNodes() { return _showParticleNodes; } @@ -31,7 +30,6 @@ public: void drawOverlay(); public slots: - void setShowVoxelNodes(bool value) { _showVoxelNodes = value; } void setShowEntityNodes(bool value) { _showEntityNodes = value; } void setShowParticleNodes(bool value) { _showParticleNodes = value; } @@ -40,7 +38,6 @@ protected: void getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue); private: - bool _showVoxelNodes; bool _showEntityNodes; bool _showParticleNodes; char _overlayText[MAX_OVERLAY_TEXT_LENGTH + 1]; diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 403b8827bd..1980aa3ed6 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -49,7 +49,6 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo _serverVoxels = AddStatItem("Elements on Servers"); _localVoxels = AddStatItem("Local Elements"); _localVoxelsMemory = AddStatItem("Elements Memory"); - _voxelsRendered = AddStatItem("Voxels Rendered"); _sendingMode = AddStatItem("Sending Mode"); layout()->setSizeConstraint(QLayout::SetFixedSize); @@ -122,31 +121,15 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { // Update labels - VoxelSystem* voxels = Application::getInstance()->getVoxels(); QLabel* label; QLocale locale(QLocale::English); std::stringstream statsValue; statsValue.precision(4); - // Voxels Rendered - label = _labels[_voxelsRendered]; - statsValue << "Max: " << voxels->getMaxVoxels() / 1000.0f << "K " << - "Drawn: " << voxels->getVoxelsWritten() / 1000.0f << "K " << - "Abandoned: " << voxels->getAbandonedVoxels() / 1000.0f << "K " << - "ReadBuffer: " << voxels->getVoxelsRendered() / 1000.0f << "K " << - "Changed: " << voxels->getVoxelsUpdated() / 1000.0f << "K "; - label->setText(statsValue.str().c_str()); - - // Voxels Memory Usage + // Octree Elements Memory Usage label = _labels[_localVoxelsMemory]; statsValue.str(""); - statsValue << - "Elements RAM: " << OctreeElement::getTotalMemoryUsage() / 1000000.0f << "MB " - "Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.0f << "MB " << - "VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.0f << "MB "; - if (voxels->hasVoxelMemoryUsageGPU()) { - statsValue << "GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.0f << "MB "; - } + statsValue << "Elements RAM: " << OctreeElement::getTotalMemoryUsage() / 1000000.0f << "MB "; label->setText(statsValue.str().c_str()); // Local Voxels @@ -227,8 +210,6 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { void OctreeStatsDialog::showAllOctreeServers() { int serverCount = 0; - showOctreeServersOfType(serverCount, NodeType::VoxelServer, "Voxel", - Application::getInstance()->getVoxelServerJurisdictions()); showOctreeServersOfType(serverCount, NodeType::EntityServer, "Entity", Application::getInstance()->getEntityServerJurisdictions()); diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index 2488667a09..2db1430d28 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -63,7 +63,6 @@ private: int _serverVoxels; int _localVoxels; int _localVoxelsMemory; - int _voxelsRendered; int _voxelServerLables[MAX_VOXEL_SERVERS]; int _voxelServerLabelsCount; details _extraServerDetails[MAX_VOXEL_SERVERS]; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 7baacd3d5a..b00d697a1c 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include "Application.h" #include "MainWindow.h" @@ -214,7 +215,6 @@ void PreferencesDialog::savePreferences() { myAvatar->setLeanScale(ui.leanScaleSpin->value()); myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); - Application::getInstance()->getVoxels()->setMaxVoxels(ui.maxVoxelsSpin->value()); GLCanvas::SharedPointer glCanvas = DependencyManager::get(); Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); diff --git a/interface/src/ui/ScriptEditorWidget.cpp b/interface/src/ui/ScriptEditorWidget.cpp index b55c753061..f4a509baa6 100644 --- a/interface/src/ui/ScriptEditorWidget.cpp +++ b/interface/src/ui/ScriptEditorWidget.cpp @@ -13,6 +13,7 @@ #include "ScriptEditorWidget.h" #include +#include #include #include #include diff --git a/interface/src/ui/ScriptEditorWindow.cpp b/interface/src/ui/ScriptEditorWindow.cpp index 895d725699..0496040724 100644 --- a/interface/src/ui/ScriptEditorWindow.cpp +++ b/interface/src/ui/ScriptEditorWindow.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "ui_scriptEditorWindow.h" #include "ScriptEditorWindow.h" #include "ScriptEditorWidget.h" diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index eced2d87fd..3881760a7e 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -471,8 +471,6 @@ void Stats::display( verticalOffset = 0; horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3; - VoxelSystem* voxels = Application::getInstance()->getVoxels(); - lines = _expanded ? 14 : 3; drawBackground(backgroundColor, horizontalOffset, 0, glCanvas->width() - horizontalOffset, @@ -510,38 +508,6 @@ void Stats::display( drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); } - voxelStats.str(""); - voxelStats.precision(4); - voxelStats << "Voxels Drawn: " << voxels->getVoxelsWritten() / 1000.0f << "K " << - "Abandoned: " << voxels->getAbandonedVoxels() / 1000.0f << "K "; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); - - if (_expanded) { - // Local Voxel Memory Usage - voxelStats.str(""); - voxelStats << " Voxels Memory Nodes: " << VoxelTreeElement::getTotalMemoryUsage() / 1000000.0f << "MB"; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); - - voxelStats.str(""); - voxelStats << - " Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.0f << "MB / " << - "VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.0f << "MB"; - if (voxels->hasVoxelMemoryUsageGPU()) { - voxelStats << " / GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.0f << "MB"; - } - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); - - // Voxel Rendering - voxelStats.str(""); - voxelStats.precision(4); - voxelStats << " Voxel Rendering Slots Max: " << voxels->getMaxVoxels() / 1000.0f << "K"; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); - } - // iterate all the current voxel stats, and list their sending modes, and total voxel counts std::stringstream sendingMode(""); sendingMode << "Octree Sending Mode: ["; @@ -612,7 +578,7 @@ void Stats::display( } QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' '); - unsigned long localTotal = VoxelTreeElement::getNodeCount(); + unsigned long localTotal = OctreeElement::getNodeCount(); QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' '); // Server Octree Elements @@ -641,8 +607,8 @@ void Stats::display( drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); // Local Voxels - unsigned long localInternal = VoxelTreeElement::getInternalNodeCount(); - unsigned long localLeaves = VoxelTreeElement::getLeafNodeCount(); + unsigned long localInternal = OctreeElement::getInternalNodeCount(); + unsigned long localLeaves = OctreeElement::getLeafNodeCount(); QString localInternalString = locale.toString((uint)localInternal); QString localLeavesString = locale.toString((uint)localLeaves); diff --git a/interface/src/ui/VoxelImportDialog.cpp b/interface/src/ui/VoxelImportDialog.cpp deleted file mode 100644 index 930fed133d..0000000000 --- a/interface/src/ui/VoxelImportDialog.cpp +++ /dev/null @@ -1,362 +0,0 @@ -// -// VoxelImportDialog.cpp -// interface/src/ui -// -// Created by Clement Brisset on 8/12/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "InterfaceConfig.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include "Application.h" - -#include "VoxelImportDialog.h" -#include "voxels/VoxelImporter.h" - -const QString SETTINGS_GROUP_NAME = "VoxelImport"; -const QString IMPORT_DIALOG_SETTINGS_KEY = "VoxelImportDialogSettings"; - -const QString WINDOW_NAME = QObject::tr("Import Voxels"); -const QString IMPORT_BUTTON_NAME = QObject::tr("Import Voxels"); -const QString LOADING_BUTTON_NAME = QObject::tr("Loading ..."); -const QString PLACE_BUTTON_NAME = QObject::tr("Place voxels"); -const QString IMPORT_INFO = QObject::tr("Import %1 as voxels"); -const QString CANCEL_BUTTON_NAME = QObject::tr("Cancel"); - -const QString DOWNLOAD_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); -const int SHORT_FILE_EXTENSION = 4; -const int SECOND_INDEX_LETTER = 1; - -QIcon HiFiIconProvider::icon(QFileIconProvider::IconType type) const { - - // types - // Computer, Desktop, Trashcan, Network, Drive, Folder, File - QString typeString; - - switch (type) { - case QFileIconProvider::Computer: - typeString = "computer"; - break; - - case QFileIconProvider::Desktop: - typeString = "desktop"; - break; - - case QFileIconProvider::Trashcan: - case QFileIconProvider::Network: - case QFileIconProvider::Drive: - case QFileIconProvider::Folder: - typeString = "folder"; - break; - - default: - typeString = "file"; - break; - } - - return QIcon(PathUtils::resourcesPath() + "icons/" + typeString + ".svg"); -} - -QIcon HiFiIconProvider::icon(const QFileInfo &info) const { - const QString ext = info.suffix().toLower(); - - if (info.isDir()) { - if (info.absoluteFilePath() == QDir::homePath()) { - return QIcon(PathUtils::resourcesPath() + "icons/home.svg"); - } else if (info.absoluteFilePath() == QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)) { - return QIcon(PathUtils::resourcesPath() + "icons/desktop.svg"); - } else if (info.absoluteFilePath() == QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)) { - return QIcon(PathUtils::resourcesPath() + "icons/documents.svg"); - } - return QIcon(PathUtils::resourcesPath() + "icons/folder.svg"); - } - - QFileInfo iconFile(PathUtils::resourcesPath() + "icons/" + iconsMap[ext]); - if (iconFile.exists() && iconFile.isFile()) { - return QIcon(iconFile.filePath()); - } - - return QIcon(PathUtils::resourcesPath() + "icons/file.svg"); -} - -QString HiFiIconProvider::type(const QFileInfo &info) const { - if (info.isFile()) { - if (info.suffix().size() > SHORT_FILE_EXTENSION) { - // Capitalize extension - return info.suffix().left(SECOND_INDEX_LETTER).toUpper() + info.suffix().mid(SECOND_INDEX_LETTER); - } - return info.suffix().toUpper(); - } - - return QFileIconProvider::type(info); -} - -VoxelImportDialog::VoxelImportDialog(QWidget* parent) : - QFileDialog(parent, WINDOW_NAME, DOWNLOAD_LOCATION, NULL), - _cancelButton(CANCEL_BUTTON_NAME, this), - _importButton(IMPORT_BUTTON_NAME, this), - _importer(Application::getInstance()->getVoxelImporter()), - _mode(importMode), - _progressBar(this), - _didImport(false) { - - setOption(QFileDialog::DontUseNativeDialog, true); - setFileMode(QFileDialog::ExistingFile); - setViewMode(QFileDialog::Detail); - - setImportTypes(); - setLayout(); - - _progressBar.setRange(0, 100); - - connect(&_importButton, SIGNAL(pressed()), this, SLOT(accept())); - connect(&_cancelButton, SIGNAL(pressed()), this, SLOT(cancel())); - connect(this, SIGNAL(currentChanged(QString)), SLOT(saveCurrentFile(QString))); -} - -void VoxelImportDialog::cancel() { - switch (getMode()) { - case importMode: - _importer->cancel(); - close(); - break; - default: - _importer->reset(); - setMode(importMode); - break; - } - emit canceled(); -} - -void VoxelImportDialog::saveSettings(QSettings* settings) { - settings->beginGroup(SETTINGS_GROUP_NAME); - settings->setValue(IMPORT_DIALOG_SETTINGS_KEY, saveState()); - settings->endGroup(); -} - -void VoxelImportDialog::loadSettings(QSettings* settings) { - settings->beginGroup(SETTINGS_GROUP_NAME); - restoreState(settings->value(IMPORT_DIALOG_SETTINGS_KEY).toByteArray()); - settings->endGroup(); -} - -bool VoxelImportDialog::prompt() { - reset(); - exec(); - return _didImport; -} - -void VoxelImportDialog::reset() { - setMode(importMode); - _didImport = false; -} - -void VoxelImportDialog::setMode(dialogMode mode) { - dialogMode previousMode = _mode; - _mode = mode; - - switch (_mode) { - case importMode: - _progressBar.setValue(0); - _importButton.setEnabled(true); - _importButton.setText(IMPORT_BUTTON_NAME); - findChild("sidebar")->setEnabled(true); - findChild("treeView")->setEnabled(true); - findChild("backButton")->setEnabled(true); - findChild("forwardButton")->setEnabled(true); - findChild("toParentButton")->setEnabled(true); - break; - case loadingMode: - // Connect to VoxelImporter signals - connect(_importer, SIGNAL(importProgress(int)), this, SLOT(updateProgressBar(int))); - connect(_importer, SIGNAL(importDone()), this, SLOT(afterImport())); - - _importButton.setEnabled(false); - _importButton.setText(LOADING_BUTTON_NAME); - findChild("sidebar")->setEnabled(false); - findChild("treeView")->setEnabled(false); - findChild("backButton")->setEnabled(false); - findChild("forwardButton")->setEnabled(false); - findChild("toParentButton")->setEnabled(false); - break; - case finishedMode: - if (previousMode == loadingMode) { - // Disconnect from VoxelImporter signals - disconnect(_importer, SIGNAL(importProgress(int)), this, SLOT(setProgressBarValue(int))); - disconnect(_importer, SIGNAL(importDone()), this, SLOT(afterImport())); - } - setMode(importMode); - break; - } -} - -void VoxelImportDialog::setProgressBarValue(int value) { - _progressBar.setValue(value); -} - -void VoxelImportDialog::accept() { - if (getMode() == importMode) { - QString filename = getCurrentFile(); - - // If file is invalid we ignore the call - if (!_importer->validImportFile(filename)) { - return; - } - // Let's prepare the dialog window for import - setMode(loadingMode); - - _importer->import(filename); - } -} - -void VoxelImportDialog::afterImport() { - setMode(finishedMode); - _didImport = true; - close(); -} - -void VoxelImportDialog::saveCurrentFile(QString filename) { - _currentFile = QFileInfo(filename).isFile() ? filename : ""; -} - -void VoxelImportDialog::setLayout() { - QGridLayout* gridLayout = (QGridLayout*) layout(); - gridLayout->addWidget(&_progressBar, 2, 0, 2, 1); - gridLayout->addWidget(&_cancelButton, 2, 1, 2, 1); - gridLayout->addWidget(&_importButton, 2, 2, 2, 1); - - // set ObjectName used in qss for styling - _progressBar.setObjectName("progressBar"); - _importButton.setObjectName("importButton"); - _cancelButton.setObjectName("cancelButton"); - - // set fixed size - _importButton.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - _cancelButton.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - _cancelButton.setFlat(true); - int progressBarHeight = 7; - _progressBar.setFixedHeight(progressBarHeight); - _progressBar.setTextVisible(false); - - QGridLayout* subLayout = new QGridLayout(); - subLayout->addWidget(findChild("lookInLabel"), 0, 0, 1, 5); - - QSize BUTTON_SIZE = QSize(43, 33); - QPushButton* button = (QPushButton*) findChild("backButton"); - button->setIcon(QIcon()); - button->setFixedSize(BUTTON_SIZE); - subLayout->addWidget(button, 1, 0, 1, 1); - - button = (QPushButton*) findChild("forwardButton"); - button->setIcon(QIcon()); - button->setFixedSize(BUTTON_SIZE); - subLayout->addWidget(button, 1, 1, 1, 1); - - button = (QPushButton*) findChild("toParentButton"); - button->setIcon(QIcon()); - button->setFixedSize(BUTTON_SIZE); - subLayout->addWidget(button, 1, 2, 1, 1); - - gridLayout->addLayout(subLayout, 0, 0, 1, 1); - - // hide unused embedded widgets in QFileDialog - QWidget* widget = findChild("lookInCombo"); - widget->hide(); - - widget = findChild("newFolderButton"); - widget->hide(); - - widget = findChild("listModeButton"); - widget->hide(); - - widget = findChild("detailModeButton"); - widget->hide(); - - widget = findChild("fileNameEdit"); - widget->hide(); - - widget = findChild("fileTypeCombo"); - widget->hide(); - - widget = findChild("fileTypeLabel"); - widget->hide(); - - widget = findChild("fileNameLabel"); - widget->hide(); - - widget = findChild("buttonBox"); - widget->hide(); - - QSplitter* splitter = findChild("splitter"); - splitter->setHandleWidth(0); - - // remove blue outline on Mac - widget = findChild("sidebar"); - widget->setAttribute(Qt::WA_MacShowFocusRect, false); - - widget = findChild("treeView"); - widget->setAttribute(Qt::WA_MacShowFocusRect, false); - - QFile styleSheet(PathUtils::resourcesPath() + "styles/import_dialog.qss"); - if (styleSheet.open(QIODevice::ReadOnly)) { - QDir::setCurrent(PathUtils::resourcesPath()); - setStyleSheet(styleSheet.readAll()); - } - -} - -void VoxelImportDialog::setImportTypes() { - QFile config(PathUtils::resourcesPath() + "config/config.json"); - config.open(QFile::ReadOnly | QFile::Text); - QJsonDocument document = QJsonDocument::fromJson(config.readAll()); - if (!document.isNull() && !document.isEmpty()) { - - QString importFormatsInfo; - QString importFormatsFilterList; - QHash iconsMap; - - QJsonObject configObject = document.object(); - if (!configObject.isEmpty()) { - QJsonArray fileFormats = configObject["importFormats"].toArray(); - int formatsCounter = 0; - foreach (const QJsonValue& fileFormat, fileFormats) { - QJsonObject fileFormatObject = fileFormat.toObject(); - - QString ext(fileFormatObject["extension"].toString()); - QString icon(fileFormatObject.value("icon").toString()); - - if (formatsCounter > 0) { - importFormatsInfo.append(","); - } - - // set ' or' on last import type text - if (formatsCounter == fileFormats.count() - 1) { - importFormatsInfo.append(" or"); - } - - importFormatsFilterList.append(QString("*.%1 ").arg(ext)); - importFormatsInfo.append(" .").append(ext); - iconsMap[ext] = icon; - formatsCounter++; - } - } - - // set custom file icons - setIconProvider(new HiFiIconProvider(iconsMap)); - setNameFilter(importFormatsFilterList); - - setLabelText(QFileDialog::LookIn, QString(IMPORT_INFO).arg(importFormatsInfo)); - } -} diff --git a/interface/src/ui/VoxelImportDialog.h b/interface/src/ui/VoxelImportDialog.h deleted file mode 100644 index 54faf7449a..0000000000 --- a/interface/src/ui/VoxelImportDialog.h +++ /dev/null @@ -1,81 +0,0 @@ -// -// VoxelImportDialog.h -// interface/src/ui -// -// Created by Clement Brisset on 8/12/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelImportDialog_h -#define hifi_VoxelImportDialog_h - -#include "InterfaceConfig.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include "voxels/VoxelImporter.h" - -class HiFiIconProvider : public QFileIconProvider { -public: - HiFiIconProvider(const QHash map) { iconsMap = map; }; - virtual QIcon icon(IconType type) const; - virtual QIcon icon(const QFileInfo &info) const; - virtual QString type(const QFileInfo &info) const; - QHash iconsMap; -}; - -enum dialogMode { - importMode, - loadingMode, - finishedMode -}; - -class VoxelImportDialog : public QFileDialog { - Q_OBJECT - -public: - VoxelImportDialog(QWidget* parent = NULL); - - QString getCurrentFile() const { return _currentFile; } - dialogMode getMode() const { return _mode; } - - void setMode(dialogMode mode); - void reset(); - bool prompt(); - void loadSettings(QSettings* settings); - void saveSettings(QSettings* settings); - -signals: - void canceled(); - -private slots: - void setProgressBarValue(int value); - void accept(); - void cancel(); - void saveCurrentFile(QString filename); - void afterImport(); - -private: - QPushButton _cancelButton; - QString _currentFile; - QPushButton _importButton; - VoxelImporter* _importer; - dialogMode _mode; - QProgressBar _progressBar; - bool _didImport; - - void setLayout(); - void setImportTypes(); -}; - -#endif // hifi_VoxelImportDialog_h diff --git a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp deleted file mode 100644 index b3dac02468..0000000000 --- a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// LocalVoxelsOverlay.cpp -// interface/src/ui/overlays -// -// Created by Clément Brisset on 2/28/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include - -#include - -#include "Application.h" -#include "LocalVoxelsOverlay.h" -#include "voxels/VoxelSystem.h" - -QMap LocalVoxelsOverlay::_voxelSystemMap; - -LocalVoxelsOverlay::LocalVoxelsOverlay() : - Volume3DOverlay(), - _voxelCount(0) -{ -} - -LocalVoxelsOverlay::LocalVoxelsOverlay(const LocalVoxelsOverlay* localVoxelsOverlay) : - Volume3DOverlay(localVoxelsOverlay), - _voxelCount(localVoxelsOverlay->_voxelCount) -{ -} - -LocalVoxelsOverlay::~LocalVoxelsOverlay() { - _voxelSystem->changeTree(new VoxelTree()); - _voxelSystem.clear(); - if (_voxelSystemMap.value(_treeName).isNull()) { - _voxelSystemMap.remove(_treeName); - } - _tree.clear(); - LocalVoxelsList::getInstance()->remove(_treeName); -} - -void LocalVoxelsOverlay::update(float deltatime) { - if (!_voxelSystem->isInitialized()) { - _voxelSystem->init(); - } - - _tree->lockForRead(); - if (_visible && _voxelCount != _tree->getOctreeElementsCount()) { - _voxelCount = _tree->getOctreeElementsCount(); - _voxelSystem->forceRedrawEntireTree(); - } - _tree->unlock(); -} - -void LocalVoxelsOverlay::render(RenderArgs* args) { - glm::vec3 dimensions = getDimensions(); - float size = glm::length(dimensions); - if (_visible && size > 0 && _voxelSystem && _voxelSystem->isInitialized()) { - - float glowLevel = getGlowLevel(); - Glower* glower = NULL; - if (glowLevel > 0.0f) { - glower = new Glower(glowLevel); - } - - glPushMatrix(); { - glTranslatef(_position.x, _position.y, _position.z); - glScalef(dimensions.x, dimensions.y, dimensions.z); - _voxelSystem->render(); - } glPopMatrix(); - - if (glower) { - delete glower; - } - } -} - -void LocalVoxelsOverlay::setProperties(const QScriptValue &properties) { - Volume3DOverlay::setProperties(properties); - - if (properties.property("scale").isValid()) { - setSize(properties.property("scale").toVariant().toFloat()); - } - - QScriptValue treeName = properties.property("name"); - if (treeName.isValid()) { - if ((_treeName = treeName.toString()) == DOMAIN_TREE_NAME) { - qDebug() << "addOverlay(): Can't create overlay from domain tree"; - return; - } - _tree = LocalVoxelsList::getInstance()->getTree(_treeName); - if (_tree.isNull()) { - qDebug() << "addOverlay(): Invalid tree name"; - return; - } - - _voxelSystem = _voxelSystemMap[_treeName]; - if (_voxelSystem.isNull()) { - _voxelSystem = StrongVoxelSystemPointer(new VoxelSystem(1, - DEFAULT_MAX_VOXELS_PER_SYSTEM, - _tree.data())); - _voxelSystemMap.insert(_treeName, _voxelSystem); - } - } -} - -LocalVoxelsOverlay* LocalVoxelsOverlay::createClone() const { - return new LocalVoxelsOverlay(this); -} - -QScriptValue LocalVoxelsOverlay::getProperty(const QString& property) { - if (property == "scale") { - return vec3toScriptValue(_scriptEngine, getDimensions()); - } - if (property == "name") { - return _treeName; - } - - return Volume3DOverlay::getProperty(property); -} - diff --git a/interface/src/ui/overlays/LocalVoxelsOverlay.h b/interface/src/ui/overlays/LocalVoxelsOverlay.h deleted file mode 100644 index 4afa44f9be..0000000000 --- a/interface/src/ui/overlays/LocalVoxelsOverlay.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// LocalVoxelsOverlay.h -// interface/src/ui/overlays -// -// Created by Clément Brisset on 2/28/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_LocalVoxelsOverlay_h -#define hifi_LocalVoxelsOverlay_h - -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include -#include -#include -#include - -#include - -#include "Volume3DOverlay.h" - -typedef QSharedPointer StrongVoxelSystemPointer; -typedef QWeakPointer WeakVoxelSystemPointer; - -class LocalVoxelsOverlay : public Volume3DOverlay { - Q_OBJECT -public: - LocalVoxelsOverlay(); - LocalVoxelsOverlay(const LocalVoxelsOverlay* localVoxelsOverlay); - ~LocalVoxelsOverlay(); - - virtual void update(float deltatime); - virtual void render(RenderArgs* args); - - virtual void setProperties(const QScriptValue& properties); - virtual QScriptValue getProperty(const QString& property); - - virtual LocalVoxelsOverlay* createClone() const; -private: - static QMap _voxelSystemMap; // treeName/voxelSystem - - QString _treeName; - StrongVoxelTreePointer _tree; // so that the tree doesn't get freed - unsigned long _voxelCount; - StrongVoxelSystemPointer _voxelSystem; -}; - -#endif // hifi_LocalVoxelsOverlay_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index ace4ecf353..46be62649b 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -21,7 +21,6 @@ #include "ImageOverlay.h" #include "Line3DOverlay.h" #include "LocalModelsOverlay.h" -#include "LocalVoxelsOverlay.h" #include "ModelOverlay.h" #include "Overlays.h" #include "Rectangle3DOverlay.h" @@ -166,8 +165,6 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay = new Line3DOverlay(); } else if (type == "grid") { thisOverlay = new Grid3DOverlay(); - } else if (type == "localvoxels") { - thisOverlay = new LocalVoxelsOverlay(); } else if (type == "localmodels") { thisOverlay = new LocalModelsOverlay(Application::getInstance()->getEntityClipboardRenderer()); } else if (type == "model") { diff --git a/interface/src/voxels/OctreePacketProcessor.cpp b/interface/src/voxels/OctreePacketProcessor.cpp index 9f53492e70..cae38834f7 100644 --- a/interface/src/voxels/OctreePacketProcessor.cpp +++ b/interface/src/voxels/OctreePacketProcessor.cpp @@ -32,12 +32,6 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode, bool wasStatsPacket = false; - // check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that - if (app->_wantToKillLocalVoxels) { - app->_voxels.killLocalVoxels(); - app->_wantToKillLocalVoxels = false; - } - PacketType voxelPacketType = packetTypeForPacket(mutablePacket); // note: PacketType_OCTREE_STATS can have PacketType_VOXEL_DATA @@ -80,7 +74,7 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode, } - app->trackIncomingVoxelPacket(mutablePacket, sendingNode, wasStatsPacket); + app->trackIncomingOctreePacket(mutablePacket, sendingNode, wasStatsPacket); if (sendingNode) { @@ -101,12 +95,8 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode, app->_environment.parseData(*sendingNode->getActiveSocket(), mutablePacket); } break; - default : { - if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { - app->_voxels.setDataSourceUUID(sendingNode->getUUID()); - app->_voxels.parseData(mutablePacket); - app->_voxels.setDataSourceUUID(QUuid()); - } + default: { + // nothing to do } break; } } diff --git a/interface/src/voxels/VoxelHideShowThread.cpp b/interface/src/voxels/VoxelHideShowThread.cpp deleted file mode 100644 index 089da0d1da..0000000000 --- a/interface/src/voxels/VoxelHideShowThread.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// VoxelHideShowThread.cpp -// interface/src/voxels -// -// Created by Brad Hefta-Gaub on 12/1/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include - -#include "Application.h" -#include "VoxelHideShowThread.h" - -VoxelHideShowThread::VoxelHideShowThread(VoxelSystem* theSystem) : - _theSystem(theSystem) { -} - -bool VoxelHideShowThread::process() { - const quint64 MSECS_TO_USECS = 1000; - const quint64 SECS_TO_USECS = 1000 * MSECS_TO_USECS; - const quint64 FRAME_RATE = 60; - const quint64 USECS_PER_FRAME = SECS_TO_USECS / FRAME_RATE; // every 60fps - - quint64 start = usecTimestampNow(); - _theSystem->checkForCulling(); - quint64 end = usecTimestampNow(); - quint64 elapsed = end - start; - - bool showExtraDebugging = Application::getInstance()->getLogger()->extraDebugging(); - if (showExtraDebugging && elapsed > USECS_PER_FRAME) { - qDebug() << "VoxelHideShowThread::process()... checkForCulling took" << elapsed; - } - - if (isStillRunning()) { - if (elapsed < USECS_PER_FRAME) { - quint64 sleepFor = USECS_PER_FRAME - elapsed; - usleep(sleepFor); - } - } - return isStillRunning(); // keep running till they terminate us -} diff --git a/interface/src/voxels/VoxelHideShowThread.h b/interface/src/voxels/VoxelHideShowThread.h deleted file mode 100644 index 6aa3c108ba..0000000000 --- a/interface/src/voxels/VoxelHideShowThread.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// VoxelHideShowThread.h -// interface/src/voxels -// -// Created by Brad Hefta-Gaub on 12/1/13. -// Copyright 2013 High Fidelity, Inc. -// -// Threaded or non-threaded voxel persistence -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelHideShowThread_h -#define hifi_VoxelHideShowThread_h - -#include -#include "VoxelSystem.h" - -/// Generalized threaded processor for handling received inbound packets. -class VoxelHideShowThread : public GenericThread { - Q_OBJECT -public: - - VoxelHideShowThread(VoxelSystem* theSystem); - -protected: - /// Implements generic processing behavior for this thread. - virtual bool process(); - -private: - VoxelSystem* _theSystem; -}; - -#endif // hifi_VoxelHideShowThread_h diff --git a/interface/src/voxels/VoxelImporter.cpp b/interface/src/voxels/VoxelImporter.cpp deleted file mode 100644 index b713813fb0..0000000000 --- a/interface/src/voxels/VoxelImporter.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// VoxelImporter.cpp -// interface/src/voxels -// -// Created by Clement Brisset on 8/9/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include - -#include -#include - -#include "voxels/VoxelImporter.h" - -const QStringList SUPPORTED_EXTENSIONS = QStringList() << "png" << "svo" << "schematic"; - -class ImportTask : public QObject, public QRunnable { -public: - ImportTask(const QString &filename); - void run(); - -private: - QString _filename; -}; - -VoxelImporter::VoxelImporter() : - _voxelTree(true), - _task(NULL) -{ - LocalVoxelsList::getInstance()->addPersistantTree(IMPORT_TREE_NAME, &_voxelTree); - - connect(&_voxelTree, SIGNAL(importProgress(int)), this, SIGNAL(importProgress(int))); -} - -VoxelImporter::~VoxelImporter() { - cleanupTask(); -} - -void VoxelImporter::cancel() { - if (_task) { - disconnect(_task, 0, 0, 0); - } - reset(); -} - -void VoxelImporter::reset() { - _voxelTree.eraseAllOctreeElements(); - cleanupTask(); -} - -void VoxelImporter::import(const QString& filename) { - // If present, abort existing import - if (_task) { - cleanupTask(); - } - - // If not already done, we switch to the local tree - if (Application::getInstance()->getSharedVoxelSystem()->getTree() != &_voxelTree) { - Application::getInstance()->getSharedVoxelSystem()->changeTree(&_voxelTree); - } - - // Creation and launch of the import task on the thread pool - _task = new ImportTask(filename); - connect(_task, SIGNAL(destroyed()), SLOT(finishImport())); - QThreadPool::globalInstance()->start(_task); -} - -void VoxelImporter::cleanupTask() { - // If a task is running, we cancel it and put the pointer to null - if (_task) { - _task = NULL; - _voxelTree.cancelImport(); - } -} - -void VoxelImporter::finishImport() { - cleanupTask(); - emit importDone(); -} - -bool VoxelImporter::validImportFile(const QString& filename) { - QFileInfo fileInfo = QFileInfo(filename); - return fileInfo.isFile() && SUPPORTED_EXTENSIONS.indexOf(fileInfo.suffix().toLower()) != -1; -} - -ImportTask::ImportTask(const QString &filename) - : _filename(filename) -{ - setAutoDelete(true); -} - -void ImportTask::run() { - VoxelSystem* voxelSystem = Application::getInstance()->getSharedVoxelSystem(); - // We start by cleaning up the shared voxel system just in case - voxelSystem->killLocalVoxels(); - - // Then we call the right method for the job - if (_filename.endsWith(".png", Qt::CaseInsensitive)) { - voxelSystem->getTree()->readFromSquareARGB32Pixels(_filename.toLocal8Bit().data()); - } else if (_filename.endsWith(".svo", Qt::CaseInsensitive)) { - voxelSystem->getTree()->readFromSVOFile(_filename.toLocal8Bit().data()); - } else if (_filename.endsWith(".schematic", Qt::CaseInsensitive)) { - voxelSystem->getTree()->readFromSchematicFile(_filename.toLocal8Bit().data()); - } else { - // We should never get here. - qDebug() << "[ERROR] Invalid file extension." << endl; - } - - // Here we reaverage the tree so that it is ready for preview - voxelSystem->getTree()->reaverageOctreeElements(); -} diff --git a/interface/src/voxels/VoxelImporter.h b/interface/src/voxels/VoxelImporter.h deleted file mode 100644 index 21ebbeea2e..0000000000 --- a/interface/src/voxels/VoxelImporter.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// VoxelImporter.h -// interface/src/voxels -// -// Created by Clement Brisset on 8/9/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelImporter_h -#define hifi_VoxelImporter_h - -#include -#include -#include - -#include "voxels/VoxelSystem.h" - -class ImportTask; - -class VoxelImporter : public QObject { - Q_OBJECT -public: - VoxelImporter(); - ~VoxelImporter(); - - void reset(); - void cancel(); - VoxelTree* getVoxelTree() { return &_voxelTree; } - bool validImportFile(const QString& filename); - -public slots: - void import(const QString& filename); - -signals: - void importDone(); - void importProgress(int); - -private: - VoxelTree _voxelTree; - ImportTask* _task; - - void cleanupTask(); - -private slots: - void finishImport(); -}; - -#endif // hifi_VoxelImporter_h diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp deleted file mode 100644 index 114b6ba481..0000000000 --- a/interface/src/voxels/VoxelSystem.cpp +++ /dev/null @@ -1,1661 +0,0 @@ -// -// VoxelSystem.cpp -// interface/src/voxels -// -// Created by Philip on 12/31/12. -// Copyright 2012 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include // to load voxels from file -#include // to load voxels from file - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Application.h" -#include "Menu.h" -#include "VoxelConstants.h" -#include "VoxelSystem.h" - -const bool VoxelSystem::DONT_BAIL_EARLY = false; - -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, - 0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, - 0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, - -1,0,0, +1,0,0, +1,0,0, -1,0,0, - -1,0,0, +1,0,0, +1,0,0, -1,0,0 }; - -GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- - 8,9,13, 8,13,12, // Y- - 16,23,19, 16,20,23, // X- - 17,18,22, 17,22,21, // X+ - 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 }; - -static glm::vec3 grayColor = glm::vec3(0.3f, 0.3f, 0.3f); - -VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) - : NodeData(), - _treeScale(treeScale), - _maxVoxels(maxVoxels), - _initialized(false), - _writeArraysLock(QReadWriteLock::Recursive), - _readArraysLock(QReadWriteLock::Recursive), - _drawHaze(false), - _farHazeDistance(300.0f), - _hazeColor(grayColor) -{ - - _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; - _writeRenderFullVBO = true; - _readRenderFullVBO = true; - _tree = (tree) ? tree : new VoxelTree(); - - _tree->getRoot()->setVoxelSystem(this); - - VoxelTreeElement::addDeleteHook(this); - VoxelTreeElement::addUpdateHook(this); - _falseColorizeBySource = false; - _dataSourceUUID = QUuid(); - _voxelServerCount = 0; - - _viewFrustum = Application::getInstance()->getViewFrustum(); - - _readVerticesArray = NULL; - _writeVerticesArray = NULL; - _readColorsArray = NULL; - _writeColorsArray = NULL; - _writeVoxelDirtyArray = NULL; - _readVoxelDirtyArray = NULL; - - _inSetupNewVoxelsForDrawing = false; - _useFastVoxelPipeline = false; - - _culledOnce = false; - _inhideOutOfView = false; - - _lastKnownVoxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE; - _lastKnownBoundaryLevelAdjust = 0; -} - -void VoxelSystem::elementDeleted(OctreeElement* element) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - if (voxel->getVoxelSystem() == this) { - if ((_voxelsInWriteArrays != 0)) { - forceRemoveNodeFromArrays(voxel); - } else { - if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { - qDebug("VoxelSystem::elementDeleted() while _voxelsInWriteArrays==0, is that expected? "); - } - } - } -} - -void VoxelSystem::setDisableFastVoxelPipeline(bool disableFastVoxelPipeline) { - _useFastVoxelPipeline = !disableFastVoxelPipeline; - setupNewVoxelsForDrawing(); -} - -void VoxelSystem::elementUpdated(OctreeElement* element) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - - // If we're in SetupNewVoxelsForDrawing() or _writeRenderFullVBO then bail.. - if (!_useFastVoxelPipeline || _inSetupNewVoxelsForDrawing || _writeRenderFullVBO) { - return; - } - - if (voxel->getVoxelSystem() == this) { - bool shouldRender = false; // assume we don't need to render it - // if it's colored, we might need to render it! - float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale(); - int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); - shouldRender = voxel->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust); - - if (voxel->getShouldRender() != shouldRender) { - voxel->setShouldRender(shouldRender); - } - - if (!voxel->isLeaf()) { - - // As we check our children, see if any of them went from shouldRender to NOT shouldRender - // then we probably dropped LOD and if we don't have color, we want to average our children - // for a new color. - int childrenGotHiddenCount = 0; - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - VoxelTreeElement* childVoxel = voxel->getChildAtIndex(i); - if (childVoxel) { - bool wasShouldRender = childVoxel->getShouldRender(); - bool isShouldRender = childVoxel->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust); - if (wasShouldRender && !isShouldRender) { - childrenGotHiddenCount++; - } - } - } - if (childrenGotHiddenCount > 0) { - voxel->calculateAverageFromChildren(); - } - } - - const bool REUSE_INDEX = true; - const bool DONT_FORCE_REDRAW = false; - updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW); - _voxelsUpdated++; - - voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things. - - setupNewVoxelsForDrawingSingleNode(); - } -} - -// returns an available index, starts by reusing a previously freed index, but if there isn't one available -// it will use the end of the VBO array and grow our accounting of that array. -// and makes the index available for some other node to use -glBufferIndex VoxelSystem::getNextBufferIndex() { - glBufferIndex output = GLBUFFER_INDEX_UNKNOWN; - // if there's a free index, use it... - if (_freeIndexes.size() > 0) { - _freeIndexLock.lock(); - output = _freeIndexes.back(); - _freeIndexes.pop_back(); - _freeIndexLock.unlock(); - } else { - output = _voxelsInWriteArrays; - _voxelsInWriteArrays++; - } - return output; -} - -// Release responsibility of the buffer/vbo index from the VoxelTreeElement, and makes the index available for some other node to use -// will also "clean up" the index data for the buffer/vbo slot, so that if it's in the middle of the draw range, the triangles -// will be "invisible" -void VoxelSystem::freeBufferIndex(glBufferIndex index) { - if (_voxelsInWriteArrays == 0) { - qDebug() << "freeBufferIndex() called when _voxelsInWriteArrays == 0!"; - } - - // make the index available for next node that needs to be drawn - _freeIndexLock.lock(); - _freeIndexes.push_back(index); - _freeIndexLock.unlock(); - - // make the VBO slot "invisible" in case this slot is not used - const glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX); - const float voxelScale = 0; - const nodeColor BLACK = {0, 0, 0, 0}; - updateArraysDetails(index, startVertex, voxelScale, BLACK); -} - -// This will run through the list of _freeIndexes and reset their VBO array values to be "invisible". -void VoxelSystem::clearFreeBufferIndexes() { - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "clearFreeBufferIndexes()"); - _voxelsInWriteArrays = 0; // reset our VBO - - // clear out freeIndexes - { - PerformanceWarning warn(showWarnings,"clearFreeBufferIndexes() : _freeIndexLock.lock()"); - _freeIndexLock.lock(); - } - { - PerformanceWarning warn(showWarnings,"clearFreeBufferIndexes() : _freeIndexes.clear()"); - _freeIndexes.clear(); - } - _freeIndexLock.unlock(); -} - -VoxelSystem::~VoxelSystem() { - VoxelTreeElement::removeDeleteHook(this); - VoxelTreeElement::removeUpdateHook(this); - - cleanupVoxelMemory(); - delete _tree; -} - - -// This is called by the main application thread on both the initialization of the application and when -// the preferences dialog box is called/saved -void VoxelSystem::setMaxVoxels(unsigned long maxVoxels) { - if (maxVoxels == _maxVoxels) { - return; - } - bool wasInitialized = _initialized; - if (wasInitialized) { - clearAllNodesBufferIndex(); - cleanupVoxelMemory(); - } - _maxVoxels = maxVoxels; - if (wasInitialized) { - initVoxelMemory(); - } - if (wasInitialized) { - forceRedrawEntireTree(); - } -} - -void VoxelSystem::cleanupVoxelMemory() { - if (_initialized) { - _readArraysLock.lockForWrite(); - _initialized = false; // no longer initialized - // Destroy glBuffers - glDeleteBuffers(1, &_vboVerticesID); - glDeleteBuffers(1, &_vboColorsID); - - glDeleteBuffers(1, &_vboIndicesTop); - glDeleteBuffers(1, &_vboIndicesBottom); - glDeleteBuffers(1, &_vboIndicesLeft); - glDeleteBuffers(1, &_vboIndicesRight); - glDeleteBuffers(1, &_vboIndicesFront); - glDeleteBuffers(1, &_vboIndicesBack); - - delete[] _readVerticesArray; - delete[] _writeVerticesArray; - delete[] _readColorsArray; - delete[] _writeColorsArray; - - _readVerticesArray = NULL; - _writeVerticesArray = NULL; - _readColorsArray = NULL; - _writeColorsArray = NULL; - - delete[] _writeVoxelDirtyArray; - delete[] _readVoxelDirtyArray; - _writeVoxelDirtyArray = _readVoxelDirtyArray = NULL; - _readArraysLock.unlock(); - - } -} - -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 (unsigned long 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() { - _readArraysLock.lockForWrite(); - _writeArraysLock.lockForWrite(); - - _memoryUsageRAM = 0; - _memoryUsageVBO = 0; // our VBO allocations as we know them - - // 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() - setupFaceIndices(_vboIndicesTop, identityIndicesTop); - setupFaceIndices(_vboIndicesBottom, identityIndicesBottom); - setupFaceIndices(_vboIndicesLeft, identityIndicesLeft); - setupFaceIndices(_vboIndicesRight, identityIndicesRight); - setupFaceIndices(_vboIndicesFront, identityIndicesFront); - setupFaceIndices(_vboIndicesBack, identityIndicesBack); - - // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - glGenBuffers(1, &_vboVerticesID); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - 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, 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]; - 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[vertexPointsPerVoxel * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels); - _readVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _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 - if (!_program.isLinked()) { - _program.addShaderFromSourceFile(QGLShader::Vertex, - PathUtils::resourcesPath() + "shaders/voxel.vert"); - _program.addShaderFromSourceFile(QGLShader::Fragment, - PathUtils::resourcesPath() + "shaders/voxel.frag"); - _program.link(); - } - _initialized = true; - - _writeArraysLock.unlock(); - _readArraysLock.unlock(); - - // fog for haze - if (_drawHaze) { - GLfloat fogColor[] = {_hazeColor.x, _hazeColor.y, _hazeColor.z, 1.0f}; - glFogi(GL_FOG_MODE, GL_LINEAR); - glFogfv(GL_FOG_COLOR, fogColor); - glFogf(GL_FOG_START, 0.0f); - glFogf(GL_FOG_END, _farHazeDistance); - } -} - -int VoxelSystem::parseData(const QByteArray& packet) { - bool showTimingDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showTimingDetails, "VoxelSystem::parseData()",showTimingDetails); - - PacketType command = packetTypeForPacket(packet); - int numBytesPacketHeader = numBytesForPacketHeader(packet); - switch(command) { - case PacketTypeVoxelData: { - PerformanceWarning warn(showTimingDetails, "VoxelSystem::parseData() PacketType_VOXEL_DATA part...",showTimingDetails); - - const unsigned char* dataAt = reinterpret_cast(packet.data()) + numBytesPacketHeader; - - OCTREE_PACKET_FLAGS flags = (*(OCTREE_PACKET_FLAGS*)(dataAt)); - dataAt += sizeof(OCTREE_PACKET_FLAGS); - OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt); - dataAt += sizeof(OCTREE_PACKET_SEQUENCE); - - OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt); - dataAt += sizeof(OCTREE_PACKET_SENT_TIME); - - bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT); - bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); - - OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); - int flightTime = arrivedAt - sentAt; - - OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - unsigned int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); - - int subsection = 1; - while (dataBytes > 0) { - if (packetIsCompressed) { - if (dataBytes > sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE)) { - sectionLength = (*(OCTREE_PACKET_INTERNAL_SECTION_SIZE*)dataAt); - dataAt += sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); - dataBytes -= sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); - } else { - sectionLength = 0; - dataBytes = 0; // stop looping something is wrong - } - } else { - sectionLength = dataBytes; - } - - if (sectionLength) { - PerformanceWarning warn(showTimingDetails, "VoxelSystem::parseData() section"); - // ask the VoxelTree to read the bitstream into the tree - ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceUUID()); - _tree->lockForWrite(); - OctreePacketData packetData(packetIsCompressed); - packetData.loadFinalizedContent(dataAt, sectionLength); - if (Application::getInstance()->getLogger()->extraDebugging()) { - qDebug("VoxelSystem::parseData() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%u" - " subsection:%d sectionLength:%d uncompressed:%d", - debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), - sequence, flightTime, packet.size(), dataBytes, subsection, sectionLength, - packetData.getUncompressedSize()); - } - _tree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); - _tree->unlock(); - - dataBytes -= sectionLength; - dataAt += sectionLength; - } - } - subsection++; - } - default: - break; - } - if (!_useFastVoxelPipeline || _writeRenderFullVBO) { - setupNewVoxelsForDrawing(); - } else { - setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY); - } - - Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::VOXELS).updateValue(packet.size()); - - return packet.size(); -} - -void VoxelSystem::setupNewVoxelsForDrawing() { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "setupNewVoxelsForDrawing()"); - - if (!_initialized) { - return; // bail early if we're not initialized - } - - quint64 start = usecTimestampNow(); - quint64 sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; - - bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging - if (!iAmDebugging && sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) { - return; // bail early, it hasn't been long enough since the last time we ran - } - - _inSetupNewVoxelsForDrawing = true; - - bool didWriteFullVBO = _writeRenderFullVBO; - if (_tree->isDirty()) { - static char buffer[64] = { 0 }; - if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { - sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO)); - }; - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); - _callsToTreesToArrays++; - - if (_writeRenderFullVBO) { - clearFreeBufferIndexes(); - } - _voxelsUpdated = newTreeToArrays(_tree->getRoot()); - _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean - - _writeRenderFullVBO = false; - } else { - _voxelsUpdated = 0; - } - - // lock on the buffer write lock so we can't modify the data when the GPU is reading it - _readArraysLock.lockForWrite(); - - if (_voxelsUpdated) { - _voxelsDirty=true; - } - - // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated - copyWrittenDataToReadArrays(didWriteFullVBO); - _readArraysLock.unlock(); - - quint64 end = usecTimestampNow(); - int elapsedmsec = (end - start) / 1000; - _setupNewVoxelsForDrawingLastFinished = end; - _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; - _inSetupNewVoxelsForDrawing = false; - - bool extraDebugging = Application::getInstance()->getLogger()->extraDebugging(); - if (extraDebugging) { - qDebug("setupNewVoxelsForDrawing()... _voxelsUpdated=%lu...",_voxelsUpdated); - _viewFrustum->printDebugDetails(); - } -} - -void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "setupNewVoxelsForDrawingSingleNode() xxxxx"); - - quint64 start = usecTimestampNow(); - quint64 sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; - - bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging - if (allowBailEarly && !iAmDebugging && - sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) { - return; // bail early, it hasn't been long enough since the last time we ran - } - - // lock on the buffer write lock so we can't modify the data when the GPU is reading it - { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "setupNewVoxelsForDrawingSingleNode()... _bufferWriteLock.lock();" ); - _readArraysLock.lockForWrite(); - } - - _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty - - // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated - copyWrittenDataToReadArrays(_writeRenderFullVBO); - - // after... - _voxelsUpdated = 0; - _readArraysLock.unlock(); - - quint64 end = usecTimestampNow(); - int elapsedmsec = (end - start) / 1000; - _setupNewVoxelsForDrawingLastFinished = end; - _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; -} - - - -class recreateVoxelGeometryInViewArgs { -public: - VoxelSystem* thisVoxelSystem; - ViewFrustum thisViewFrustum; - unsigned long nodesScanned; - float voxelSizeScale; - int boundaryLevelAdjust; - - recreateVoxelGeometryInViewArgs(VoxelSystem* voxelSystem) : - thisVoxelSystem(voxelSystem), - thisViewFrustum(*voxelSystem->getViewFrustum()), - nodesScanned(0), - voxelSizeScale(Menu::getInstance()->getVoxelSizeScale()), - boundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust()) - { - } -}; - -// The goal of this operation is to remove any old references to old geometry, and if the voxel -// should be visible, create new geometry for it. -bool VoxelSystem::recreateVoxelGeometryInViewOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - recreateVoxelGeometryInViewArgs* args = (recreateVoxelGeometryInViewArgs*)extraData; - - args->nodesScanned++; - - // reset the old geometry... - // note: this doesn't "mark the voxel as changed", so it only releases the old buffer index thereby forgetting the - // old geometry - voxel->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - - bool shouldRender = voxel->calculateShouldRender(&args->thisViewFrustum, args->voxelSizeScale, args->boundaryLevelAdjust); - bool inView = voxel->isInView(args->thisViewFrustum); - voxel->setShouldRender(inView && shouldRender); - if (shouldRender && inView) { - // recreate the geometry - args->thisVoxelSystem->updateNodeInArrays(voxel, false, true); // DONT_REUSE_INDEX, FORCE_REDRAW - } - - return true; // keep recursing! -} - - -// TODO: other than cleanupRemovedVoxels() is there anyplace we attempt to detect too many abandoned slots??? -void VoxelSystem::recreateVoxelGeometryInView() { - - qDebug() << "recreateVoxelGeometryInView()..."; - - recreateVoxelGeometryInViewArgs args(this); - _writeArraysLock.lockForWrite(); // don't let anyone read or write our write arrays until we're done - _tree->lockForRead(); // don't let anyone change our tree structure until we're run - - // reset our write arrays bookkeeping to think we've got no voxels in it - clearFreeBufferIndexes(); - - // do we need to reset out _writeVoxelDirtyArray arrays?? - memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - - _tree->recurseTreeWithOperation(recreateVoxelGeometryInViewOperation,(void*)&args); - _tree->unlock(); - _writeArraysLock.unlock(); -} - -void VoxelSystem::checkForCulling() { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "checkForCulling()"); - quint64 start = usecTimestampNow(); - - // track how long its been since we were last moving. If we have recently moved then only use delta frustums, if - // it's been a long time since we last moved, then go ahead and do a full frustum cull. - if (isViewChanging()) { - _lastViewIsChanging = start; - } - quint64 sinceLastMoving = (start - _lastViewIsChanging) / 1000; - bool enoughTime = (sinceLastMoving >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)); - - // These has changed events will occur before we stop. So we need to remember this for when we finally have stopped - // moving long enough to be enoughTime - if (hasViewChanged()) { - _hasRecentlyChanged = true; - } - - // If we have recently changed, but it's been enough time since we last moved, then we will do a full frustum - // hide/show culling pass - bool forceFullFrustum = enoughTime && _hasRecentlyChanged; - - // in hide mode, we only track the full frustum culls, because we don't care about the partials. - if (forceFullFrustum) { - _lastViewCulling = start; - _hasRecentlyChanged = false; - } - - // This would be a good place to do a special processing pass, for example, switching the LOD of the scene - bool fullRedraw = (_lastKnownVoxelSizeScale != Menu::getInstance()->getVoxelSizeScale() || - _lastKnownBoundaryLevelAdjust != Menu::getInstance()->getBoundaryLevelAdjust()); - - _lastKnownVoxelSizeScale = Menu::getInstance()->getVoxelSizeScale(); - _lastKnownBoundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); - - if (fullRedraw) { - // this will remove all old geometry and recreate the correct geometry for all in view voxels - recreateVoxelGeometryInView(); - } else { - hideOutOfView(forceFullFrustum); - } - - if (forceFullFrustum) { - quint64 endViewCulling = usecTimestampNow(); - _lastViewCullingElapsed = (endViewCulling - start) / 1000; - } -} - -void VoxelSystem::copyWrittenDataToReadArraysFullVBOs() { - copyWrittenDataSegmentToReadArrays(0, _voxelsInWriteArrays - 1); - _voxelsInReadArrays = _voxelsInWriteArrays; - - // clear our dirty flags - memset(_writeVoxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool)); - - // let the reader know to get the full array - _readRenderFullVBO = true; -} - -void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { - glBufferIndex segmentStart = 0; - bool inSegment = false; - for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { - bool thisVoxelDirty = _writeVoxelDirtyArray[i]; - _readVoxelDirtyArray[i] |= thisVoxelDirty; - _writeVoxelDirtyArray[i] = false; - if (!inSegment) { - if (thisVoxelDirty) { - segmentStart = i; - inSegment = true; - } - } else { - if (!thisVoxelDirty) { - // If we got here because because this voxel is NOT dirty, so the last dirty voxel was the one before - // this one and so that's where the "segment" ends - copyWrittenDataSegmentToReadArrays(segmentStart, i - 1); - inSegment = false; - } - } - } - - // if we got to the end of the array, and we're in an active dirty segment... - if (inSegment) { - copyWrittenDataSegmentToReadArrays(segmentStart, _voxelsInWriteArrays - 1); - } - - // update our length - _voxelsInReadArrays = _voxelsInWriteArrays; -} - -void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { - int segmentLength = (segmentEnd - segmentStart) + 1; - // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - - GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); - GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); - GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel); - memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - - segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); - GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel); - GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel); - memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); -} - -void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { - static unsigned int lockForReadAttempt = 0; - static unsigned int lockForWriteAttempt = 0; - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "copyWrittenDataToReadArrays()"); - - // attempt to get the writeArraysLock for reading and the readArraysLock for writing - // so we can copy from the write to the read... if we fail, that's ok, we'll get it the next - // time around, the only side effect is the VBOs won't be updated this frame - const int WAIT_FOR_LOCK_IN_MS = 5; - if (_readArraysLock.tryLockForWrite(WAIT_FOR_LOCK_IN_MS)) { - lockForWriteAttempt = 0; - if (_writeArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) { - lockForReadAttempt = 0; - if (_voxelsDirty && _voxelsUpdated) { - if (fullVBOs) { - copyWrittenDataToReadArraysFullVBOs(); - } else { - copyWrittenDataToReadArraysPartialVBOs(); - } - } - _writeArraysLock.unlock(); - } else { - lockForReadAttempt++; - // only report error of first failure - if (lockForReadAttempt == 1) { - qDebug() << "couldn't get _writeArraysLock.LockForRead()..."; - } - } - _readArraysLock.unlock(); - } else { - lockForWriteAttempt++; - // only report error of first failure - if (lockForWriteAttempt == 1) { - qDebug() << "couldn't get _readArraysLock.LockForWrite()..."; - } - } -} - -int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) { - int voxelsUpdated = 0; - bool shouldRender = false; // assume we don't need to render it - // if it's colored, we might need to render it! - float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();; - int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); - shouldRender = voxel->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust); - - voxel->setShouldRender(shouldRender); - // let children figure out their renderness - if (!voxel->isLeaf()) { - - // As we check our children, see if any of them went from shouldRender to NOT shouldRender - // then we probably dropped LOD and if we don't have color, we want to average our children - // for a new color. - int childrenGotHiddenCount = 0; - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - VoxelTreeElement* childVoxel = voxel->getChildAtIndex(i); - if (childVoxel) { - bool wasShouldRender = childVoxel->getShouldRender(); - voxelsUpdated += newTreeToArrays(childVoxel); - bool isShouldRender = childVoxel->getShouldRender(); - if (wasShouldRender && !isShouldRender) { - childrenGotHiddenCount++; - } - } - } - if (childrenGotHiddenCount > 0) { - voxel->calculateAverageFromChildren(); - } - } - - // update their geometry in the array. depending on our over all mode (fullVBO or not) we will reuse or not reuse the index - if (_writeRenderFullVBO) { - const bool DONT_REUSE_INDEX = false; - const bool FORCE_REDRAW = true; - voxelsUpdated += updateNodeInArrays(voxel, DONT_REUSE_INDEX, FORCE_REDRAW); - } else { - const bool REUSE_INDEX = true; - const bool DONT_FORCE_REDRAW = false; - voxelsUpdated += updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW); - } - voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things. - - return voxelsUpdated; -} - -// called as response to elementDeleted() in fast pipeline case. The node -// is being deleted, but it's state is such that it thinks it should render -// and therefore we can't use the normal render calculations. This method -// will forcibly remove it from the VBOs because we know better!!! -int VoxelSystem::forceRemoveNodeFromArrays(VoxelTreeElement* node) { - - if (!_initialized) { - return 0; - } - - // if the node is not in the VBOs then we have nothing to do! - if (node->isKnownBufferIndex()) { - // If this node has not yet been written to the array, then add it to the end of the array. - glBufferIndex nodeIndex = node->getBufferIndex(); - node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible! - return 1; // updated! - } - return 0; // not-updated -} - -int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, bool forceDraw) { - // If we've run out of room, then just bail... - if (_voxelsInWriteArrays >= _maxVoxels && (_freeIndexes.size() == 0)) { - // We need to think about what else we can do in this case. This basically means that all of our available - // VBO slots are used up, but we're trying to render more voxels. At this point, if this happens we'll just - // not render these Voxels. We need to think about ways to keep the entire scene intact but maybe lower quality - // possibly shifting down to lower LOD or something. This debug message is to help identify, if/when/how this - // state actually occurs. - if (Application::getInstance()->getLogger()->extraDebugging()) { - qDebug("OH NO! updateNodeInArrays() BAILING (_voxelsInWriteArrays >= _maxVoxels)"); - } - return 0; - } - - if (!_initialized) { - return 0; - } - - // If we've changed any attributes (our renderness, our color, etc), or we've been told to force a redraw - // then update the Arrays... - if (forceDraw || node->isDirty()) { - // If we're should render, use our legit location and scale, - if (node->getShouldRender()) { - glm::vec3 startVertex = node->getCorner(); - float voxelScale = node->getScale(); - - glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; - if (reuseIndex && node->isKnownBufferIndex()) { - nodeIndex = node->getBufferIndex(); - } else { - nodeIndex = getNextBufferIndex(); - node->setBufferIndex(nodeIndex); - node->setVoxelSystem(this); - } - - // populate the array with points for the 8 vertices and RGB color for each added vertex - updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor()); - return 1; // updated! - } else { - // If we shouldn't render, and we're in reuseIndex mode, then free our index, this only operates - // on nodes with known index values, so it's safe to call for any node. - if (reuseIndex) { - return forceRemoveNodeFromArrays(node); - } - } - } - return 0; // not-updated -} - -void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex, - float voxelScale, const nodeColor& color) { - - if (_initialized && nodeIndex <= _maxVoxels) { - _writeVoxelDirtyArray[nodeIndex] = true; - - if (_writeVerticesArray && _writeColorsArray) { - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - for (int j = 0; j < vertexPointsPerVoxel; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * vertexPointsPerVoxel); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVerticesGlobalNormals[j] * voxelScale); - *(writeColorsAt +j) = color[j % 3]; - } - } - } -} - -glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float voxelScale, int index) const { - const float* identityVertex = identityVertices + index * 3; - return startVertex + glm::vec3(identityVertex[0], identityVertex[1], identityVertex[2]) * voxelScale; -} - -ProgramObject VoxelSystem::_program; -ProgramObject VoxelSystem::_perlinModulateProgram; - -void VoxelSystem::init() { - if (_initialized) { - qDebug("[ERROR] VoxelSystem is already initialized."); - return; - } - - _callsToTreesToArrays = 0; - _setupNewVoxelsForDrawingLastFinished = 0; - _setupNewVoxelsForDrawingLastElapsed = 0; - _lastViewCullingElapsed = _lastViewCulling = _lastAudit = _lastViewIsChanging = 0; - _hasRecentlyChanged = false; - - _voxelsDirty = false; - _voxelsInWriteArrays = 0; - _voxelsInReadArrays = 0; - - // VBO for the verticesArray - _initialMemoryUsageGPU = getFreeMemoryGPU(); - initVoxelMemory(); - -} - -void VoxelSystem::changeTree(VoxelTree* newTree) { - _tree = newTree; - - _tree->setDirtyBit(); - _tree->getRoot()->setVoxelSystem(this); - - setupNewVoxelsForDrawing(); -} - -void VoxelSystem::updateFullVBOs() { - bool outputWarning = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(outputWarning, "updateFullVBOs()"); - - { - static char buffer[128] = { 0 }; - if (outputWarning) { - sprintf(buffer, "updateFullVBOs() : updateVBOSegment(0, _voxelsInReadArrays=%lu);", _voxelsInReadArrays); - }; - - PerformanceWarning warn(outputWarning,buffer); - updateVBOSegment(0, _voxelsInReadArrays); - } - - { - PerformanceWarning warn(outputWarning,"updateFullVBOs() : memset(_readVoxelDirtyArray...)"); - // consider the _readVoxelDirtyArray[] clean! - memset(_readVoxelDirtyArray, false, _voxelsInReadArrays * sizeof(bool)); - } -} - -void VoxelSystem::updatePartialVBOs() { - glBufferIndex segmentStart = 0; - bool inSegment = false; - for (glBufferIndex i = 0; i < _voxelsInReadArrays; i++) { - bool thisVoxelDirty = _readVoxelDirtyArray[i]; - if (!inSegment) { - if (thisVoxelDirty) { - segmentStart = i; - inSegment = true; - _readVoxelDirtyArray[i] = false; // consider us clean! - } - } else { - if (!thisVoxelDirty) { - // If we got here because because this voxel is NOT dirty, so the last dirty voxel was the one before - // this one and so that's where the "segment" ends - updateVBOSegment(segmentStart, i - 1); - inSegment = false; - } - _readVoxelDirtyArray[i] = false; // consider us clean! - } - } - - // if we got to the end of the array, and we're in an active dirty segment... - if (inSegment) { - updateVBOSegment(segmentStart, _voxelsInReadArrays - 1); - inSegment = false; - } -} - -void VoxelSystem::updateVBOs() { - static char buffer[40] = { 0 }; - if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { - sprintf(buffer, "updateVBOs() _readRenderFullVBO=%s", debug::valueOf(_readRenderFullVBO)); - }; - // would like to include _callsToTreesToArrays - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); - if (_voxelsDirty) { - - // attempt to lock the read arrays, to for copying from them to the actual GPU VBOs. - // if we fail to get the lock, that's ok, our VBOs will update on the next frame... - const int WAIT_FOR_LOCK_IN_MS = 5; - if (_readArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) { - if (_readRenderFullVBO) { - updateFullVBOs(); - } else { - updatePartialVBOs(); - } - _voxelsDirty = false; - _readRenderFullVBO = false; - _readArraysLock.unlock(); - } else { - qDebug() << "updateVBOs().... couldn't get _readArraysLock.tryLockForRead()"; - } - } - _callsToTreesToArrays = 0; // clear it -} - -// this should only be called on the main application thread during render -void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) { - bool showWarning = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarning, "updateVBOSegment()"); - - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); - GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); - - { - PerformanceWarning warn(showWarning, "updateVBOSegment() : glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);"); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - } - - { - PerformanceWarning warn(showWarning, "updateVBOSegment() : glBufferSubData() _vboVerticesID);"); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - } - - segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte); - segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); - GLubyte* readColorsFrom = _readColorsArray + (segmentStart * vertexPointsPerVoxel); - - { - PerformanceWarning warn(showWarning, "updateVBOSegment() : glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);"); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - } - - { - PerformanceWarning warn(showWarning, "updateVBOSegment() : glBufferSubData() _vboColorsID);"); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); - } -} - -void VoxelSystem::render() { - bool texture = Menu::getInstance()->isOptionChecked(MenuOption::VoxelTextures); - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "render()"); - - // If we got here and we're not initialized then bail! - if (!_initialized) { - return; - } - - updateVBOs(); - - if (_drawHaze) { - glEnable(GL_FOG); - } - - { - PerformanceWarning warn(showWarnings, "render().. TRIANGLES..."); - - { - PerformanceWarning warn(showWarnings,"render().. setup before glDrawRangeElementsEXT()..."); - - // tell OpenGL where to find vertex and color information - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glVertexPointer(3, GL_FLOAT, 0, 0); - - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); - - applyScaleAndBindProgram(texture); - - // for performance, enable backface culling and disable blending - glEnable(GL_CULL_FACE); - glDisable(GL_BLEND); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } - - // draw voxels in 6 passes - - { - PerformanceWarning warn(showWarnings, "render().. glDrawRangeElementsEXT()..."); - - glNormal3f(0,1.0f,0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesTop); - glDrawRangeElementsEXT(GL_TRIANGLES, 0, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _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, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _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, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _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, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _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, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _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, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, - INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); - } - { - PerformanceWarning warn(showWarnings, "render().. cleanup after glDrawRangeElementsEXT()..."); - - glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); - - removeScaleAndReleaseProgram(texture); - - // 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); - } - } - - if (_drawHaze) { - glDisable(GL_FOG); - } -} - -void VoxelSystem::applyScaleAndBindProgram(bool texture) { - if (texture) { - bindPerlinModulateProgram(); - glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPermutationNormalTextureID()); - } else { - _program.bind(); - } - - glPushMatrix(); - glScalef(_treeScale, _treeScale, _treeScale); - - DependencyManager::get()->setPrimaryDrawBuffers(true, true); -} - -void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { - // scale back down to 1 so heads aren't massive - glPopMatrix(); - - if (texture) { - _perlinModulateProgram.release(); - glBindTexture(GL_TEXTURE_2D, 0); - } else { - _program.release(); - } - - DependencyManager::get()->setPrimaryDrawBuffers(true, false); -} - -int VoxelSystem::_nodeCount = 0; - -void VoxelSystem::killLocalVoxels() { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "VoxelSystem::killLocalVoxels()"); - _tree->lockForWrite(); - VoxelSystem* voxelSystem = _tree->getRoot()->getVoxelSystem(); - _tree->eraseAllOctreeElements(); - _tree->getRoot()->setVoxelSystem(voxelSystem); - _tree->unlock(); - clearFreeBufferIndexes(); - _voxelsInReadArrays = 0; // do we need to do this? - setupNewVoxelsForDrawing(); -} - -// only called on main thread -bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void* extraData) { - _nodeCount++; - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - voxel->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - return true; -} - -// only called on main thread, and also always followed by a call to cleanupVoxelMemory() -// you shouldn't be calling this on any other thread or without also cleaning up voxel memory -void VoxelSystem::clearAllNodesBufferIndex() { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "VoxelSystem::clearAllNodesBufferIndex()"); - _nodeCount = 0; - _tree->lockForRead(); // we won't change the tree so it's ok to treat this as a read - _tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation); - clearFreeBufferIndexes(); // this should be called too - _tree->unlock(); - if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { - qDebug("clearing buffer index of %d nodes", _nodeCount); - } -} - -bool VoxelSystem::forceRedrawEntireTreeOperation(OctreeElement* element, void* extraData) { - _nodeCount++; - element->setDirtyBit(); - return true; -} - -void VoxelSystem::forceRedrawEntireTree() { - _nodeCount = 0; - _tree->recurseTreeWithOperation(forceRedrawEntireTreeOperation); - qDebug("forcing redraw of %d nodes", _nodeCount); - _tree->setDirtyBit(); - setupNewVoxelsForDrawing(); -} - -bool VoxelSystem::isViewChanging() { - bool result = false; // assume the best - - // If our viewFrustum has changed since our _lastKnownViewFrustum - if (!_lastKnownViewFrustum.isVerySimilar(_viewFrustum)) { - result = true; - _lastKnownViewFrustum = *_viewFrustum; // save last known - } - return result; -} - -bool VoxelSystem::hasViewChanged() { - bool result = false; // assume the best - - // If we're still changing, report no change yet. - if (isViewChanging()) { - return false; - } - - // If our viewFrustum has changed since our _lastKnownViewFrustum - if (!_lastStableViewFrustum.isVerySimilar(_viewFrustum)) { - result = true; - _lastStableViewFrustum = *_viewFrustum; // save last stable - } - return result; -} - -// combines the removeOutOfView args into a single class -class hideOutOfViewArgs { -public: - VoxelSystem* thisVoxelSystem; - VoxelTree* tree; - ViewFrustum thisViewFrustum; - ViewFrustum lastViewFrustum; - bool culledOnce; - bool wantDeltaFrustums; - unsigned long nodesScanned; - unsigned long nodesRemoved; - unsigned long nodesInside; - unsigned long nodesIntersect; - unsigned long nodesOutside; - unsigned long nodesInsideInside; - unsigned long nodesIntersectInside; - unsigned long nodesOutsideInside; - unsigned long nodesInsideOutside; - unsigned long nodesOutsideOutside; - unsigned long nodesShown; - - hideOutOfViewArgs(VoxelSystem* voxelSystem, VoxelTree* tree, - bool culledOnce, bool widenViewFrustum, bool wantDeltaFrustums) : - thisVoxelSystem(voxelSystem), - tree(tree), - thisViewFrustum(*voxelSystem->getViewFrustum()), - lastViewFrustum(*voxelSystem->getLastCulledViewFrustum()), - culledOnce(culledOnce), - wantDeltaFrustums(wantDeltaFrustums), - nodesScanned(0), - nodesRemoved(0), - nodesInside(0), - nodesIntersect(0), - nodesOutside(0), - nodesInsideInside(0), - nodesIntersectInside(0), - nodesOutsideInside(0), - nodesInsideOutside(0), - nodesOutsideOutside(0), - nodesShown(0) - { - // Widen the FOV for trimming - if (widenViewFrustum) { - float originalFOV = thisViewFrustum.getFieldOfView(); - float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND; - thisViewFrustum.setFieldOfView(wideFOV); - thisViewFrustum.calculate(); - } - } -}; - -void VoxelSystem::hideOutOfView(bool forceFullFrustum) { - - // don't re-enter... - if (_inhideOutOfView) { - return; - } - - _inhideOutOfView = true; - - bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showDebugDetails, "hideOutOfView()"); - bool widenFrustum = true; - - - // When using "delta" view frustums and only hide/show items that are in the difference - // between the two view frustums. There are some potential problems with this mode. - // - // 1) This work well for rotating, but what about moving forward? - // In the move forward case, you'll get new voxel details, but those - // new voxels will be in the last view. - // - // 2) Also, voxels will arrive from the network that are OUTSIDE of the view - // frustum... these won't get hidden... and so we can't assume they are correctly - // hidden... - // - // Both these problems are solved by intermittently calling this with forceFullFrustum set - // to true. This will essentially clean up the improperly hidden or shown voxels. - // - bool wantDeltaFrustums = !forceFullFrustum; - hideOutOfViewArgs args(this, this->_tree, _culledOnce, widenFrustum, wantDeltaFrustums); - - const bool wantViewFrustumDebugging = false; // change to true for additional debugging - if (wantViewFrustumDebugging) { - args.thisViewFrustum.printDebugDetails(); - if (_culledOnce) { - args.lastViewFrustum.printDebugDetails(); - } - } - - if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.isVerySimilar(args.thisViewFrustum)) { - _inhideOutOfView = false; - return; - } - - { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "VoxelSystem::... recurseTreeWithOperation(hideOutOfViewOperation)"); - _tree->lockForRead(); - _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args); - _tree->unlock(); - } - _lastCulledViewFrustum = args.thisViewFrustum; // save last stable - _culledOnce = true; - - if (args.nodesRemoved) { - _tree->setDirtyBit(); - setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY); - } - - bool extraDebugDetails = false; // Application::getInstance()->getLogger()->extraDebugging(); - if (extraDebugDetails) { - qDebug("hideOutOfView() scanned=%ld removed=%ld show=%ld inside=%ld intersect=%ld outside=%ld", - args.nodesScanned, args.nodesRemoved, args.nodesShown, args.nodesInside, - args.nodesIntersect, args.nodesOutside - ); - qDebug("inside/inside=%ld intersect/inside=%ld outside/outside=%ld", - args.nodesInsideInside, args.nodesIntersectInside, args.nodesOutsideOutside - ); - - qDebug() << "args.thisViewFrustum...."; - args.thisViewFrustum.printDebugDetails(); - } - _inhideOutOfView = false; -} - -bool VoxelSystem::hideAllSubTreeOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - hideOutOfViewArgs* args = (hideOutOfViewArgs*)extraData; - - // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine - // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not - // consider that case. - ViewFrustum::location inLastCulledFrustum; - - if (args->culledOnce && args->wantDeltaFrustums) { - inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); - - // if this node is fully OUTSIDE our last culled view frustum, then we don't need to recurse further - if (inLastCulledFrustum == ViewFrustum::OUTSIDE) { - args->nodesOutsideOutside++; - return false; - } - } - - args->nodesOutside++; - if (voxel->isKnownBufferIndex()) { - args->nodesRemoved++; - VoxelSystem* thisVoxelSystem = args->thisVoxelSystem; - thisVoxelSystem->_voxelsUpdated += thisVoxelSystem->forceRemoveNodeFromArrays(voxel); - thisVoxelSystem->setupNewVoxelsForDrawingSingleNode(); - } - - return true; -} - -bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - hideOutOfViewArgs* args = (hideOutOfViewArgs*)extraData; - - // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine - // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not - // consider that case. - if (args->culledOnce && args->wantDeltaFrustums) { - ViewFrustum::location inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); - - // if this node is fully inside our last culled view frustum, then we don't need to recurse further - if (inLastCulledFrustum == ViewFrustum::INSIDE) { - args->nodesInsideInside++; - return false; - } - } - - args->nodesInside++; - - float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale(); - int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); - bool shouldRender = voxel->calculateShouldRender(&args->thisViewFrustum, voxelSizeScale, boundaryLevelAdjust); - voxel->setShouldRender(shouldRender); - - if (shouldRender && !voxel->isKnownBufferIndex()) { - // These are both needed to force redraw... - voxel->setDirtyBit(); - voxel->markWithChangedTime(); - args->nodesShown++; - } - - return true; // keep recursing! -} - -// "hide" voxels in the VBOs that are still in the tree that but not in view. -// We don't remove them from the tree, we don't delete them, we do remove them -// from the VBOs and mark them as such in the tree. -bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - hideOutOfViewArgs* args = (hideOutOfViewArgs*)extraData; - - // If we're still recursing the tree using this operator, then we don't know if we're inside or outside... - // so before we move forward we need to determine our frustum location - ViewFrustum::location inFrustum = voxel->inFrustum(args->thisViewFrustum); - - // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine - // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not - // consider that case. - ViewFrustum::location inLastCulledFrustum = ViewFrustum::OUTSIDE; // assume outside, but should get reset to actual value - - if (args->culledOnce && args->wantDeltaFrustums) { - inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); - } - - // ok, now do some processing for this node... - switch (inFrustum) { - case ViewFrustum::OUTSIDE: { - // If this node is outside the current view, then we might want to hide it... unless it was previously OUTSIDE, - // if it was previously outside, then we can safely assume it's already hidden, and we can also safely assume - // that all of it's children are outside both of our views, in which case we can just stop recursing... - if (args->culledOnce && args->wantDeltaFrustums && inLastCulledFrustum == ViewFrustum::OUTSIDE) { - args->nodesScanned++; - args->nodesOutsideOutside++; - return false; // stop recursing this branch! - } - - // if this node is fully OUTSIDE the view, but previously intersected and/or was inside the last view, then - // we need to hide it. Additionally we know that ALL of it's children are also fully OUTSIDE so we can recurse - // the children and simply mark them as hidden - args->tree->recurseElementWithOperation(voxel, hideAllSubTreeOperation, args ); - return false; - - } break; - case ViewFrustum::INSIDE: { - // If this node is INSIDE the current view, then we might want to show it... unless it was previously INSIDE, - // if it was previously INSIDE, then we can safely assume it's already shown, and we can also safely assume - // that all of it's children are INSIDE both of our views, in which case we can just stop recursing... - if (args->culledOnce && args->wantDeltaFrustums && inLastCulledFrustum == ViewFrustum::INSIDE) { - args->nodesScanned++; - args->nodesInsideInside++; - return false; // stop recursing this branch! - } - - // if this node is fully INSIDE the view, but previously INTERSECTED and/or was OUTSIDE the last view, then - // we need to show it. Additionally we know that ALL of it's children are also fully INSIDE so we can recurse - // the children and simply mark them as visible (as appropriate based on LOD) - args->tree->recurseElementWithOperation(voxel, showAllSubTreeOperation, args); - return false; - } break; - case ViewFrustum::INTERSECT: { - args->nodesScanned++; - // If this node INTERSECTS the current view, then we might want to show it... unless it was previously INSIDE - // the last known view, in which case it will already be visible, and we know that all it's children are also - // previously INSIDE and visible. So in this case stop recursing - if (args->culledOnce && args->wantDeltaFrustums && inLastCulledFrustum == ViewFrustum::INSIDE) { - args->nodesIntersectInside++; - return false; // stop recursing this branch! - } - - args->nodesIntersect++; - - // if the child node INTERSECTs the view, then we want to check to see if it thinks it should render - // if it should render but is missing it's VBO index, then we want to flip it on, and we can stop recursing from - // here because we know will block any children anyway - - float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale(); - int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); - bool shouldRender = voxel->calculateShouldRender(&args->thisViewFrustum, voxelSizeScale, boundaryLevelAdjust); - voxel->setShouldRender(shouldRender); - - if (voxel->getShouldRender() && !voxel->isKnownBufferIndex()) { - voxel->setDirtyBit(); // will this make it draw? - voxel->markWithChangedTime(); // both are needed to force redraw - args->nodesShown++; - return false; - } - - // If it INTERSECTS but shouldn't be displayed, then it's probably a parent and it is at least partially in view. - // So we DO want to recurse the children because some of them may not be in view... nothing specifically to do, - // just keep iterating the children - return true; - - } break; - } // switch - - return true; // keep going! -} - - -void VoxelSystem::nodeAdded(SharedNodePointer node) { - if (node->getType() == NodeType::VoxelServer) { - qDebug("VoxelSystem... voxel server %s added...", node->getUUID().toString().toLocal8Bit().constData()); - _voxelServerCount++; - } -} - -bool VoxelSystem::killSourceVoxelsOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - QUuid killedNodeID = *(QUuid*)extraData; - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - VoxelTreeElement* childNode = voxel->getChildAtIndex(i); - if (childNode) { - if (childNode->matchesSourceUUID(killedNodeID)) { - voxel->safeDeepDeleteChildAtIndex(i); - } - } - } - return true; -} - -void VoxelSystem::nodeKilled(SharedNodePointer node) { - if (node->getType() == NodeType::VoxelServer) { - _voxelServerCount--; - QUuid nodeUUID = node->getUUID(); - qDebug("VoxelSystem... voxel server %s removed...", nodeUUID.toString().toLocal8Bit().constData()); - } -} - -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); -} - -void VoxelSystem::bindPerlinModulateProgram() { - if (!_perlinModulateProgram.isLinked()) { - _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, - PathUtils::resourcesPath() + "shaders/perlin_modulate.vert"); - _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, - PathUtils::resourcesPath() + "shaders/perlin_modulate.frag"); - _perlinModulateProgram.link(); - - _perlinModulateProgram.bind(); - _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); - - } else { - _perlinModulateProgram.bind(); - } -} - diff --git a/interface/src/voxels/VoxelSystem.h b/interface/src/voxels/VoxelSystem.h deleted file mode 100644 index b6413a0f68..0000000000 --- a/interface/src/voxels/VoxelSystem.h +++ /dev/null @@ -1,246 +0,0 @@ -// -// VoxelSystem.h -// interface/src/voxels -// -// Created by Philip on 12/31/12. -// Copyright 2012 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelSystem_h -#define hifi_VoxelSystem_h - -#include "InterfaceConfig.h" -#include - -#include - -#include -#include -#include -#include - -#include "Camera.h" -#include "Util.h" -#include "world.h" - -class ProgramObject; - -const int NUM_CHILDREN = 8; - - -class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook { - Q_OBJECT - - friend class VoxelHideShowThread; - -public: - VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = DEFAULT_MAX_VOXELS_PER_SYSTEM, VoxelTree* tree = NULL); - ~VoxelSystem(); - - void setDataSourceUUID(const QUuid& dataSourceUUID) { _dataSourceUUID = dataSourceUUID; } - const QUuid& getDataSourceUUID() const { return _dataSourceUUID; } - - int parseData(const QByteArray& packet); - - bool isInitialized() { return _initialized; } - virtual void init(); - void render(); - - void changeTree(VoxelTree* newTree); - VoxelTree* getTree() const { return _tree; } - ViewFrustum* getViewFrustum() const { return _viewFrustum; } - void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; } - unsigned long getVoxelsUpdated() const { return _voxelsUpdated; } - unsigned long getVoxelsRendered() const { return _voxelsInReadArrays; } - unsigned long getVoxelsWritten() const { return _voxelsInWriteArrays; } - unsigned long getAbandonedVoxels() const { return _freeIndexes.size(); } - - ViewFrustum* getLastCulledViewFrustum() { return &_lastCulledViewFrustum; } - - void setMaxVoxels(unsigned long 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(); - - void killLocalVoxels(); - - virtual void hideOutOfView(bool forceFullFrustum = false); - bool hasViewChanged(); - bool isViewChanging(); - - virtual void elementDeleted(OctreeElement* element); - virtual void elementUpdated(OctreeElement* element); - -public slots: - void nodeAdded(SharedNodePointer node); - void nodeKilled(SharedNodePointer node); - - - // Methods that recurse tree - void forceRedrawEntireTree(); - void clearAllNodesBufferIndex(); - - void setDisableFastVoxelPipeline(bool disableFastVoxelPipeline); - -protected: - float _treeScale; - unsigned long _maxVoxels; - VoxelTree* _tree; - - void setupNewVoxelsForDrawing(); - static const bool DONT_BAIL_EARLY; // by default we will bail early, if you want to force not bailing, then use this - void setupNewVoxelsForDrawingSingleNode(bool allowBailEarly = true); - - /// called on the hide/show thread to hide any out of view voxels and show any newly in view voxels. - void checkForCulling(); - - /// single pass to remove old VBO data and fill it with correct current view, used when switching LOD or needing to force - /// a full redraw of everything in view - void recreateVoxelGeometryInView(); - - glm::vec3 computeVoxelVertex(const glm::vec3& startVertex, float voxelScale, int index) const; - - virtual void updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex, - float voxelScale, const nodeColor& color); - virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd); - virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd); - - - virtual void applyScaleAndBindProgram(bool texture); /// used in render() to apply shadows and textures - virtual void removeScaleAndReleaseProgram(bool texture); /// stop the shaders for shadows and textures - -private: - // disallow copying of VoxelSystem objects - VoxelSystem(const VoxelSystem&); - VoxelSystem& operator= (const VoxelSystem&); - - bool _initialized; - int _callsToTreesToArrays; - - // Operation functions for tree recursion methods - static int _nodeCount; - static bool killSourceVoxelsOperation(OctreeElement* element, void* extraData); - static bool forceRedrawEntireTreeOperation(OctreeElement* element, void* extraData); - static bool clearAllNodesBufferIndexOperation(OctreeElement* element, void* extraData); - static bool hideOutOfViewOperation(OctreeElement* element, void* extraData); - static bool hideAllSubTreeOperation(OctreeElement* element, void* extraData); - static bool showAllSubTreeOperation(OctreeElement* element, void* extraData); - static bool getVoxelEnclosingOperation(OctreeElement* element, void* extraData); - static bool recreateVoxelGeometryInViewOperation(OctreeElement* element, void* extraData); - - int updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, bool forceDraw); - int forceRemoveNodeFromArrays(VoxelTreeElement* node); - - void copyWrittenDataToReadArraysFullVBOs(); - void copyWrittenDataToReadArraysPartialVBOs(); - - void updateVBOs(); - - unsigned long getFreeMemoryGPU(); - - // these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here - static float _maxDistance; - static float _minDistance; - - GLfloat* _readVerticesArray; - GLubyte* _readColorsArray; - - QReadWriteLock _writeArraysLock; - QReadWriteLock _readArraysLock; - - - GLfloat* _writeVerticesArray; - GLubyte* _writeColorsArray; - bool* _writeVoxelDirtyArray; - bool* _readVoxelDirtyArray; - unsigned long _voxelsUpdated; - unsigned long _voxelsInReadArrays; - unsigned long _voxelsInWriteArrays; - - bool _writeRenderFullVBO; - bool _readRenderFullVBO; - - int _setupNewVoxelsForDrawingLastElapsed; - quint64 _setupNewVoxelsForDrawingLastFinished; - quint64 _lastViewCulling; - quint64 _lastViewIsChanging; - quint64 _lastAudit; - int _lastViewCullingElapsed; - bool _hasRecentlyChanged; - - void initVoxelMemory(); - void cleanupVoxelMemory(); - - GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO - GLuint _vboVoxelsIndicesID; /// when using voxel shader, we'll use this VBO for our indexes - - GLuint _vboVerticesID; - GLuint _vboColorsID; - - GLuint _vboIndicesTop; - GLuint _vboIndicesBottom; - GLuint _vboIndicesLeft; - GLuint _vboIndicesRight; - GLuint _vboIndicesFront; - GLuint _vboIndicesBack; - - ViewFrustum _lastKnownViewFrustum; - ViewFrustum _lastStableViewFrustum; - ViewFrustum* _viewFrustum; - - ViewFrustum _lastCulledViewFrustum; // used for hide/show visible passes - bool _culledOnce; - - void setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]); - - int newTreeToArrays(VoxelTreeElement* currentNode); - - void copyWrittenDataToReadArrays(bool fullVBOs); - - void updateFullVBOs(); // all voxels in the VBO - void updatePartialVBOs(); // multiple segments, only dirty voxels - - bool _voxelsDirty; - - static ProgramObject _program; - static ProgramObject _perlinModulateProgram; - - static void bindPerlinModulateProgram(); - - int _hookID; - std::vector _freeIndexes; - QMutex _freeIndexLock; - - void freeBufferIndex(glBufferIndex index); - void clearFreeBufferIndexes(); - glBufferIndex getNextBufferIndex(); - - bool _falseColorizeBySource; - QUuid _dataSourceUUID; - - int _voxelServerCount; - unsigned long _memoryUsageRAM; - unsigned long _memoryUsageVBO; - unsigned long _initialMemoryUsageGPU; - bool _hasMemoryUsageGPU; - - bool _inSetupNewVoxelsForDrawing; - bool _useFastVoxelPipeline; - - bool _inhideOutOfView; - - float _lastKnownVoxelSizeScale; - int _lastKnownBoundaryLevelAdjust; - - // haze - bool _drawHaze; - float _farHazeDistance; - glm::vec3 _hazeColor; -}; - -#endif // hifi_VoxelSystem_h diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 9f1185cfb9..66078b387d 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -887,17 +887,6 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const } } -void EntityTreeRenderer::entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, - const Collision& collision) { - QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID); - if (entityScript.property("collisionWithVoxel").isValid()) { - QScriptValueList args; - args << entityID.toScriptValue(_entitiesScriptEngine); - args << collisionToScriptValue(_entitiesScriptEngine, collision); - entityScript.property("collisionWithVoxel").call(entityScript, args); - } -} - void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) { QScriptValue entityScriptA = loadEntityScript(idA); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 92cc2c4dcc..2f88e854da 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -102,7 +102,6 @@ public slots: void deletingEntity(const EntityItemID& entityID); void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); void entitySciptChanging(const EntityItemID& entityID); - void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); // optional slots that can be wired to menu items diff --git a/libraries/entities/src/EntityCollisionSystem.cpp b/libraries/entities/src/EntityCollisionSystem.cpp index f0ffbefb46..cf6398847c 100644 --- a/libraries/entities/src/EntityCollisionSystem.cpp +++ b/libraries/entities/src/EntityCollisionSystem.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -30,19 +29,17 @@ const int MAX_COLLISIONS_PER_Entity = 16; EntityCollisionSystem::EntityCollisionSystem() : SimpleEntitySimulation(), _packetSender(NULL), - _voxels(NULL), _audio(NULL), _avatars(NULL), _collisions(MAX_COLLISIONS_PER_Entity) { } void EntityCollisionSystem::init(EntityEditPacketSender* packetSender, - EntityTree* entities, VoxelTree* voxels, AbstractAudioInterface* audio, + EntityTree* entities, AbstractAudioInterface* audio, AvatarHashMap* avatars) { assert(entities); setEntityTree(entities); _packetSender = packetSender; - _voxels = voxels; _audio = audio; _avatars = avatars; } @@ -64,17 +61,10 @@ void EntityCollisionSystem::updateCollisions() { void EntityCollisionSystem::checkEntity(EntityItem* entity) { - updateCollisionWithVoxels(entity); updateCollisionWithEntities(entity); updateCollisionWithAvatars(entity); } -void EntityCollisionSystem::emitGlobalEntityCollisionWithVoxel(EntityItem* entity, - VoxelDetail* voxelDetails, const Collision& collision) { - EntityItemID entityItemID = entity->getEntityItemID(); - emit entityCollisionWithVoxel(entityItemID, *voxelDetails, collision); -} - void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const Collision& collision) { @@ -83,39 +73,6 @@ void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* enti emit entityCollisionWithEntity(idA, idB, collision); } -void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) { - - if (entity->getIgnoreForCollisions() || !entity->getCollisionsWillMove()) { - return; // bail early if this entity is to be ignored or wont move - } - - glm::vec3 center = entity->getPosition() * (float)(TREE_SCALE); - float radius = entity->getRadius() * (float)(TREE_SCALE); - const float ELASTICITY = 0.4f; - const float DAMPING = 0.05f; - CollisionInfo collisionInfo; - collisionInfo._damping = DAMPING; - collisionInfo._elasticity = ELASTICITY; - VoxelDetail* voxelDetails = NULL; - if (_voxels->findSpherePenetration(center, radius, collisionInfo._penetration, (void**)&voxelDetails)) { - - // findSpherePenetration() only computes the penetration but we also want some other collision info - // so we compute it ourselves here. Note that we must multiply scale by TREE_SCALE when feeding - // the results to systems outside of this octree reference frame. - collisionInfo._contactPoint = (float)TREE_SCALE * (entity->getPosition() + entity->getRadius() * glm::normalize(collisionInfo._penetration)); - // let the global script run their collision scripts for Entities if they have them - Collision collision(collisionInfo._contactPoint, collisionInfo._penetration); - emitGlobalEntityCollisionWithVoxel(entity, voxelDetails, collision); - - // we must scale back down to the octree reference frame before updating the Entity properties - collisionInfo._penetration /= (float)(TREE_SCALE); - collisionInfo._contactPoint /= (float)(TREE_SCALE); - - applyHardCollision(entity, collisionInfo); - delete voxelDetails; // cleanup returned details - } -} - void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { if (entityA->getIgnoreForCollisions()) { diff --git a/libraries/entities/src/EntityCollisionSystem.h b/libraries/entities/src/EntityCollisionSystem.h index 48b7c17ead..593c5efd74 100644 --- a/libraries/entities/src/EntityCollisionSystem.h +++ b/libraries/entities/src/EntityCollisionSystem.h @@ -22,7 +22,6 @@ #include #include #include -#include #include "EntityItem.h" #include "SimpleEntitySimulation.h" @@ -31,14 +30,13 @@ class AbstractAudioInterface; class AvatarData; class EntityEditPacketSender; class EntityTree; -class VoxelTree; class EntityCollisionSystem : public QObject, public SimpleEntitySimulation { Q_OBJECT public: EntityCollisionSystem(); - void init(EntityEditPacketSender* packetSender, EntityTree* entities, VoxelTree* voxels, + void init(EntityEditPacketSender* packetSender, EntityTree* entities, AbstractAudioInterface* audio = NULL, AvatarHashMap* _avatars = NULL); ~EntityCollisionSystem(); @@ -46,25 +44,21 @@ public: void updateCollisions(); void checkEntity(EntityItem* Entity); - void updateCollisionWithVoxels(EntityItem* Entity); void updateCollisionWithEntities(EntityItem* Entity); void updateCollisionWithAvatars(EntityItem* Entity); void queueEntityPropertiesUpdate(EntityItem* Entity); void updateCollisionSound(EntityItem* Entity, const glm::vec3 &penetration, float frequency); signals: - void entityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const Collision& collision); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); private: void applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo); static bool updateOperation(OctreeElement* element, void* extraData); - void emitGlobalEntityCollisionWithVoxel(EntityItem* Entity, VoxelDetail* voxelDetails, const Collision& penetration); void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const Collision& penetration); EntityEditPacketSender* _packetSender; - VoxelTree* _voxels; AbstractAudioInterface* _audio; AvatarHashMap* _avatars; CollisionList _collisions; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 348efac9a3..1b9e0d6f86 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -16,8 +16,6 @@ #include #include #include // usecTimestampNow() -#include -#include #include "EntityScriptingInterface.h" #include "EntityItem.h" diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 0d0aa96706..4ac7e69bad 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -22,7 +22,6 @@ #include // for EncodeBitstreamParams class #include // for OctreeElement::AppendState #include -#include #include "EntityItemID.h" #include "EntityItemProperties.h" diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 20aaf09f9a..e0fc721516 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -87,12 +87,12 @@ public slots: /// this function will not find any models in script engine contexts which don't have access to models Q_INVOKABLE QVector findEntities(const glm::vec3& center, float radius) const; - /// If the scripting context has visible voxels, this will determine a ray intersection, the results - /// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate + /// If the scripting context has visible entities, this will determine a ray intersection, the results + /// may be inaccurate if the engine is unable to access the visible entities, in which case result.accurate /// will be false. Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking = false); - /// If the scripting context has visible voxels, this will determine a ray intersection, and will block in + /// If the scripting context has visible entities, this will determine a ray intersection, and will block in /// order to return an accurate result Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking = false); @@ -102,7 +102,6 @@ public slots: Q_INVOKABLE void dumpTree() const; signals: - void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index c747bf6d9e..9532f44acf 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -26,8 +26,6 @@ #include #include -#include - #include "FBXReader.h" @@ -2544,167 +2542,3 @@ FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool l FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { return extractFBXGeometry(parseFBX(device), mapping, loadLightmaps, lightmapLevel); } - -bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - if (!voxel->isLeaf()) { - return true; - } - FBXMesh& mesh = *static_cast(extraData); - FBXMeshPart& part = mesh.parts[0]; - - const int FACE_COUNT = 6; - const int VERTICES_PER_FACE = 4; - const int VERTEX_COUNT = FACE_COUNT * VERTICES_PER_FACE; - const float EIGHT_BIT_MAXIMUM = 255.0f; - glm::vec3 color = glm::vec3(voxel->getColor()[0], voxel->getColor()[1], voxel->getColor()[2]) / EIGHT_BIT_MAXIMUM; - QString colorName; - colorName.sprintf("%d,%d,%d",(int)voxel->getColor()[0], (int)voxel->getColor()[1], (int)voxel->getColor()[2]); - part.materialID = colorName; - for (int i = 0; i < VERTEX_COUNT; i++) { - part.quadIndices.append(part.quadIndices.size()); - mesh.colors.append(color); - } - glm::vec3 corner = voxel->getCorner(); - float scale = voxel->getScale(); - - mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z)); - mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z)); - for (int i = 0; i < VERTICES_PER_FACE; i++) { - mesh.normals.append(glm::vec3(-1.0f, 0.0f, 0.0f)); - } - - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z + scale)); - for (int i = 0; i < VERTICES_PER_FACE; i++) { - mesh.normals.append(glm::vec3(1.0f, 0.0f, 0.0f)); - } - - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z)); - for (int i = 0; i < VERTICES_PER_FACE; i++) { - mesh.normals.append(glm::vec3(0.0f, -1.0f, 0.0f)); - } - - mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z)); - mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z)); - for (int i = 0; i < VERTICES_PER_FACE; i++) { - mesh.normals.append(glm::vec3(0.0f, 1.0f, 0.0f)); - } - - mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z)); - mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z)); - for (int i = 0; i < VERTICES_PER_FACE; i++) { - mesh.normals.append(glm::vec3(0.0f, 0.0f, -1.0f)); - } - - mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z + scale)); - mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z + scale)); - for (int i = 0; i < VERTICES_PER_FACE; i++) { - mesh.normals.append(glm::vec3(0.0f, 0.0f, 1.0f)); - } - mesh.meshExtents.maximum = glm::vec3(1.0f, 1.0f, 1.0f); - - return true; -} - -FBXGeometry readSVO(const QByteArray& model) { - FBXGeometry geometry; - - // we have one joint - FBXJoint joint = { false }; - joint.parentIndex = -1; - geometry.joints.append(joint); - - // and one mesh with one cluster and one part - FBXMesh mesh; - mesh.isEye = false; - - FBXCluster cluster = { 0 }; - mesh.clusters.append(cluster); - - FBXMeshPart part; - part.diffuseColor = glm::vec3(1.0f, 1.0f, 1.0f); - part.shininess = 96.0f; - part.opacity = 1.0f; - mesh.parts.append(part); - - VoxelTree tree; - - unsigned char* dataAt = (unsigned char*)model.data(); - size_t dataSize = model.size(); - - PacketVersion gotVersion = 0; - - // NOTE: SPECIAL CASE for old voxel svo files. The old voxel SVO files didn't have header - // details. They started with the the octalcode for the root. Which was always 00 which matches PacketTypeUnknown - unsigned char* firstByteAt = (unsigned char*)model.data(); - unsigned char firstByteValue = *firstByteAt; - if (tree.expectedDataPacketType() == PacketTypeVoxelData && firstByteValue == 0) { - qDebug() << "Detected OLD Voxels format."; - gotVersion = 0; - } else if (tree.getWantSVOfileVersions()) { - // skip the type/version - dataAt += sizeof(PacketType); - dataSize -= sizeof(PacketType); - - gotVersion = *dataAt; - dataAt += sizeof(PacketVersion); - dataSize -= sizeof(PacketVersion); - } - bool hasBufferBreaks = tree.versionHasSVOfileBreaks(gotVersion); - - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, - SharedNodePointer(), false, gotVersion); - - if (!hasBufferBreaks) { - tree.readBitstreamToTree(dataAt, dataSize, args); - } else { - const unsigned long MAX_CHUNK_LENGTH = MAX_OCTREE_PACKET_SIZE * 2; - while (dataSize > 0) { - quint16 chunkLength = 0; - - chunkLength = *dataAt; - dataAt += sizeof(chunkLength); - dataSize -= sizeof(chunkLength); - - if (chunkLength > dataSize) { - qDebug() << "UNEXPECTED chunk size of:" << chunkLength - << "greater than remaining length:" << dataSize; - break; - } - - if (chunkLength > MAX_CHUNK_LENGTH) { - qDebug() << "UNEXPECTED chunk size of:" << chunkLength - << "greater than MAX_CHUNK_LENGTH:" << MAX_CHUNK_LENGTH; - break; - } - - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, - SharedNodePointer(), false, gotVersion); - - tree.readBitstreamToTree(dataAt, chunkLength, args); - dataAt += chunkLength; - dataSize -= chunkLength; - } - } - tree.recurseTreeWithOperation(addMeshVoxelsOperation, &mesh); - - geometry.meshes.append(mesh); - - geometry.meshExtents.maximum = glm::vec3(1.0f, 1.0f, 1.0f); - - return geometry; -} diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 3d07d29e7d..44b2bfe4a5 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -283,7 +283,4 @@ FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool l /// \exception QString if an error occurs in parsing FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); -/// Reads SVO geometry from the supplied model data. -FBXGeometry readSVO(const QByteArray& model); - #endif // hifi_FBXReader_h diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 7e415a5d0d..b703921099 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1367,14 +1367,7 @@ void GeometryReader::run() { if (urlValid) { // Let's read the binaries from the network FBXGeometry fbxgeo; - if (_url.path().toLower().endsWith(".svo")) { - QByteArray fileBinary = _reply->readAll(); - if (fileBinary.isEmpty() || fileBinary.isNull()) { - throw QString("Read File binary is empty?!"); - } - fbxgeo = readSVO(fileBinary); - - } else if (_url.path().toLower().endsWith(".fbx")) { + if (_url.path().toLower().endsWith(".fbx")) { bool grabLightmaps = true; float lightmapLevel = 1.0f; // HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber... diff --git a/libraries/script-engine/src/LocalVoxels.cpp b/libraries/script-engine/src/LocalVoxels.cpp deleted file mode 100644 index 9a6fb2b6d1..0000000000 --- a/libraries/script-engine/src/LocalVoxels.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// -// LocalVoxels.cpp -// libraries/script-engine/src -// -// Created by Clément Brisset on 2/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "LocalVoxels.h" - -LocalVoxels::LocalVoxels(QString name) : - QObject(NULL), - _name(name), - _tree(new VoxelTree(true)) -{ - LocalVoxelsList::getInstance()->insert(_name, _tree); -} - -LocalVoxels::~LocalVoxels() { - _tree.clear(); - LocalVoxelsList::getInstance()->remove(_name); -} - -VoxelDetail LocalVoxels::getVoxelAt(float x, float y, float z, float scale) { - // setup a VoxelDetail struct with the data - VoxelDetail result = {0,0,0,0,0,0,0}; - if (_tree) { - _tree->lockForRead(); - - VoxelTreeElement* voxel = static_cast(_tree->getOctreeElementAt(x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - scale / (float)TREE_SCALE)); - _tree->unlock(); - if (voxel) { - // Note: these need to be in voxel space because the VoxelDetail -> js converter will upscale - result.x = voxel->getCorner().x; - result.y = voxel->getCorner().y; - result.z = voxel->getCorner().z; - result.s = voxel->getScale(); - result.red = voxel->getColor()[RED_INDEX]; - result.green = voxel->getColor()[GREEN_INDEX]; - result.blue = voxel->getColor()[BLUE_INDEX]; - } - } - return result; -} - -void LocalVoxels::setVoxelNonDestructive(float x, float y, float z, float scale, - uchar red, uchar green, uchar blue) { - if (_name == DOMAIN_TREE_NAME) { - qDebug() << "LocalVoxels::setVoxelNonDestructive(): Please use the \"Voxels\" interface to modify the domain tree."; - return; - } - if (_tree ) { - _tree->createVoxel(x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - scale / (float)TREE_SCALE, - red, green, blue, false); - } -} - -void LocalVoxels::setVoxel(float x, float y, float z, float scale, - uchar red, uchar green, uchar blue) { - if (_name == DOMAIN_TREE_NAME) { - qDebug() << "LocalVoxels::setVoxel(): Please use the \"Voxels\" interface to modify the domain tree."; - return; - } - if (_tree ) { - _tree->createVoxel(x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - scale / (float)TREE_SCALE, - red, green, blue, true); - } -} - -void LocalVoxels::eraseVoxel(float x, float y, float z, float scale) { - if (_name == DOMAIN_TREE_NAME) { - qDebug() << "LocalVoxels::eraseVoxel(): Please use the \"Voxels\" interface to modify the domain tree."; - return; - } - if (_tree ) { - _tree->deleteVoxelAt(x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - scale / (float)TREE_SCALE); - } -} - -void LocalVoxels::copyTo(float x, float y, float z, float scale, const QString destination) { - if (destination == DOMAIN_TREE_NAME) { - qDebug() << "LocalVoxels::copyTo(): Please use the \"Voxels\" interface to modify the domain tree."; - return; - } - StrongVoxelTreePointer destinationTree = LocalVoxelsList::getInstance()->getTree(destination); - VoxelTreeElement* destinationNode = destinationTree->getVoxelAt(x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - scale / (float)TREE_SCALE); - destinationTree->copyFromTreeIntoSubTree(_tree.data(), destinationNode); -} - -void LocalVoxels::pasteFrom(float x, float y, float z, float scale, const QString source) { - if (_name == DOMAIN_TREE_NAME) { - qDebug() << "LocalVoxels::pasteFrom(): Please use the \"Voxels\" interface to modify the domain tree."; - return; - } - StrongVoxelTreePointer sourceTree = LocalVoxelsList::getInstance()->getTree(source); - VoxelTreeElement* sourceNode = _tree->getVoxelAt(x / (float)TREE_SCALE, - y / (float)TREE_SCALE, - z / (float)TREE_SCALE, - scale / (float)TREE_SCALE); - _tree->copySubTreeIntoNewTree(sourceNode, sourceTree.data(), true); -} - -RayToVoxelIntersectionResult LocalVoxels::findRayIntersection(const PickRay& ray) { - return findRayIntersectionWorker(ray, Octree::TryLock); -} - -RayToVoxelIntersectionResult LocalVoxels::findRayIntersectionBlocking(const PickRay& ray) { - return findRayIntersectionWorker(ray, Octree::Lock); -} - -RayToVoxelIntersectionResult LocalVoxels::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType) { - RayToVoxelIntersectionResult result; - if (_tree) { - OctreeElement* element; - result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, NULL, - lockType, &result.accurate); - if (result.intersects) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - result.voxel.x = voxel->getCorner().x; - result.voxel.y = voxel->getCorner().y; - result.voxel.z = voxel->getCorner().z; - result.voxel.s = voxel->getScale(); - result.voxel.red = voxel->getColor()[0]; - result.voxel.green = voxel->getColor()[1]; - result.voxel.blue = voxel->getColor()[2]; - result.intersection = ray.origin + (ray.direction * result.distance); - } - } - return result; -} - -glm::vec3 LocalVoxels::getFaceVector(const QString& face) { - if (face == "MIN_X_FACE") { - return glm::vec3(-1, 0, 0); - } else if (face == "MAX_X_FACE") { - return glm::vec3(1, 0, 0); - } else if (face == "MIN_Y_FACE") { - return glm::vec3(0, -1, 0); - } else if (face == "MAX_Y_FACE") { - return glm::vec3(0, 1, 0); - } else if (face == "MIN_Z_FACE") { - return glm::vec3(0, 0, -1); - } else if (face == "MAX_Z_FACE") { - return glm::vec3(0, 0, 1); - } - return glm::vec3(0, 0, 0); //error case -} diff --git a/libraries/script-engine/src/LocalVoxels.h b/libraries/script-engine/src/LocalVoxels.h deleted file mode 100644 index f6f52aa264..0000000000 --- a/libraries/script-engine/src/LocalVoxels.h +++ /dev/null @@ -1,102 +0,0 @@ -// -// LocalVoxels.h -// libraries/script-engine/src -// -// Created by Clément Brisset on 2/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_LocalVoxels_h -#define hifi_LocalVoxels_h - -#include - -#include -#include - - -/// object allowing JS scripters to use their own local trees -class LocalVoxels : public QObject { - Q_OBJECT - -public: - LocalVoxels(QString name); - ~LocalVoxels(); - - /// checks the local voxel tree for a voxel at the specified location and scale - /// \param x the x-coordinate of the voxel (in meter units) - /// \param y the y-coordinate of the voxel (in meter units) - /// \param z the z-coordinate of the voxel (in meter units) - /// \param scale the scale of the voxel (in meter units) - Q_INVOKABLE VoxelDetail getVoxelAt(float x, float y, float z, float scale); - - /// creates a non destructive voxel in the local tree - /// \param x the x-coordinate of the voxel (in meter units) - /// \param y the y-coordinate of the voxel (in meter units) - /// \param z the z-coordinate of the voxel (in meter units) - /// \param scale the scale of the voxel (in meter units) - /// \param red the R value for RGB color of voxel - /// \param green the G value for RGB color of voxel - /// \param blue the B value for RGB color of voxel - Q_INVOKABLE void setVoxelNonDestructive(float x, float y, float z, float scale, uchar red, uchar green, uchar blue); - - /// creates a voxel in the local tree - /// \param x the x-coordinate of the voxel (in meter units) - /// \param y the y-coordinate of the voxel (in meter units) - /// \param z the z-coordinate of the voxel (in meter units) - /// \param scale the scale of the voxel (in meter units) - /// \param red the R value for RGB color of voxel - /// \param green the G value for RGB color of voxel - /// \param blue the B value for RGB color of voxel - Q_INVOKABLE void setVoxel(float x, float y, float z, float scale, uchar red, uchar green, uchar blue); - - /// erase the voxel and its children at the given coordinate - /// \param x the x-coordinate of the voxel (in meter units) - /// \param y the y-coordinate of the voxel (in meter units) - /// \param z the z-coordinate of the voxel (in meter units) - /// \param scale the scale of the voxel (in meter units) - Q_INVOKABLE void eraseVoxel(float x, float y, float z, float scale); - - /// copy the given subtree onto destination's root node - /// \param x the x-coordinate of the subtree (in meter units) - /// \param y the y-coordinate of the subtree (in meter units) - /// \param z the z-coordinate of the subtree (in meter units) - /// \param scale the scale of the subtree (in meter units) - /// \param destination LocalVoxels' destination tree - Q_INVOKABLE void copyTo(float x, float y, float z, float scale, const QString destination); - - ///copy source in the given subtree - /// \param x the x-coordinate of the subtree (in meter units) - /// \param y the y-coordinate of the subtree (in meter units) - /// \param z the z-coordinate of the subtree (in meter units) - /// \param scale the scale of the subtree (in meter units) - /// \param source LocalVoxels' source tree - Q_INVOKABLE void pasteFrom(float x, float y, float z, float scale, const QString source); - - /// If the scripting context has visible voxels, this will determine a ray intersection, the results - /// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate - /// will be false. - Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray); - - /// If the scripting context has visible voxels, this will determine a ray intersection, and will block in - /// order to return an accurate result - Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersectionBlocking(const PickRay& ray); - - /// returns a voxel space axis aligned vector for the face, useful in doing voxel math - Q_INVOKABLE glm::vec3 getFaceVector(const QString& face); - -private: - /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode - RayToVoxelIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType); - - QString _name; - StrongVoxelTreePointer _tree; -}; - - - - -#endif // hifi_LocalVoxels_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index ac6291469e..c7be5a973b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -28,22 +28,19 @@ #include #include #include -#include -#include +//#include #include "AnimationObject.h" #include "ArrayBufferViewClass.h" #include "DataViewClass.h" #include "EventTypes.h" #include "MenuItemProperties.h" -#include "LocalVoxels.h" #include "ScriptEngine.h" #include "TypedArrays.h" #include "XMLHttpRequestClass.h" #include "MIDIEvent.h" -VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface; EntityScriptingInterface ScriptEngine::_entityScriptingInterface; static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){ @@ -200,8 +197,6 @@ void ScriptEngine::handleScriptDownload() { } } -Q_SCRIPT_DECLARE_QMETAOBJECT(LocalVoxels, QString) - void ScriptEngine::init() { if (_isInitialized) { return; // only initialize once @@ -209,12 +204,9 @@ void ScriptEngine::init() { _isInitialized = true; - _voxelsScriptingInterface.init(); - // register various meta-types registerMetaTypes(this); registerMIDIMetaTypes(this); - registerVoxelMetaTypes(this); registerEventTypes(this); registerMenuItemProperties(this); registerAnimationTypes(this); @@ -237,9 +229,6 @@ void ScriptEngine::init() { QScriptValue printConstructorValue = newFunction(debugPrint); globalObject().setProperty("print", printConstructorValue); - QScriptValue localVoxelsValue = scriptValueFromQMetaObject(); - globalObject().setProperty("LocalVoxels", localVoxelsValue); - QScriptValue audioEffectOptionsConstructorValue = newFunction(AudioEffectOptions::constructor); globalObject().setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue); @@ -257,19 +246,14 @@ void ScriptEngine::init() { registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("AnimationCache", DependencyManager::get().data()); - registerGlobalObject("Voxels", &_voxelsScriptingInterface); - // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); globalObject().setProperty("COLLISION_GROUP_ENVIRONMENT", newVariant(QVariant(COLLISION_GROUP_ENVIRONMENT))); globalObject().setProperty("COLLISION_GROUP_AVATARS", newVariant(QVariant(COLLISION_GROUP_AVATARS))); - globalObject().setProperty("COLLISION_GROUP_VOXELS", newVariant(QVariant(COLLISION_GROUP_VOXELS))); globalObject().setProperty("AVATAR_MOTION_OBEY_LOCAL_GRAVITY", newVariant(QVariant(AVATAR_MOTION_OBEY_LOCAL_GRAVITY))); globalObject().setProperty("AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY", newVariant(QVariant(AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY))); - // let the VoxelPacketSender know how frequently we plan to call it - _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); } QScriptValue ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { @@ -379,18 +363,8 @@ void ScriptEngine::run() { break; } - if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) { - // release the queue of edit voxel messages. - _voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); - - // since we're in non-threaded mode, call process so that the packets are sent - if (!_voxelsScriptingInterface.getVoxelPacketSender()->isThreaded()) { - _voxelsScriptingInterface.getVoxelPacketSender()->process(); - } - } - if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { - // release the queue of edit voxel messages. + // release the queue of edit entity messages. _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent @@ -516,16 +490,6 @@ void ScriptEngine::run() { // kill the avatar identity timer delete _avatarIdentityTimer; - if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) { - // release the queue of edit voxel messages. - _voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); - - // since we're in non-threaded mode, call process so that the packets are sent - if (!_voxelsScriptingInterface.getVoxelPacketSender()->isThreaded()) { - _voxelsScriptingInterface.getVoxelPacketSender()->process(); - } - } - if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 7474ac8725..10f419937a 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include "AbstractControllerScriptingInterface.h" #include "ArrayBufferClass.h" @@ -31,7 +31,6 @@ #include "Vec3.h" class EntityScriptingInterface; -class VoxelsScriptingInterface; const QString NO_SCRIPT(""); @@ -44,9 +43,6 @@ public: const QString& fileNameString = QString(""), AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); - /// Access the VoxelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener - static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return &_voxelsScriptingInterface; } - /// Access the EntityScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener static EntityScriptingInterface* getEntityScriptingInterface() { return &_entityScriptingInterface; } @@ -141,7 +137,6 @@ private: QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); - static VoxelsScriptingInterface _voxelsScriptingInterface; static EntityScriptingInterface _entityScriptingInterface; AbstractControllerScriptingInterface* _controllerScriptingInterface; diff --git a/libraries/voxels/src/LocalVoxelsList.cpp b/libraries/voxels/src/LocalVoxelsList.cpp deleted file mode 100644 index 55becb0976..0000000000 --- a/libraries/voxels/src/LocalVoxelsList.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// LocalVoxelsList.cpp -// libraries/voxels/src -// -// Created by Clément Brisset on 2/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "LocalVoxelsList.h" - -static void doNothing(VoxelTree* t) { - // do nothing -} - -LocalVoxelsList* LocalVoxelsList::_instance = NULL; - -LocalVoxelsList* LocalVoxelsList::getInstance() { - if (!_instance) { - _instance = new LocalVoxelsList(); - } - - return _instance; -} - -LocalVoxelsList::LocalVoxelsList() { -} - -LocalVoxelsList::~LocalVoxelsList() { - _instance = NULL; -} - -StrongVoxelTreePointer LocalVoxelsList::getTree(QString treeName) { - return _trees.value(treeName); -} - -void LocalVoxelsList::addPersistantTree(QString treeName, VoxelTree* tree) { - StrongVoxelTreePointer treePtr(tree, doNothing); - _persistantTrees.push_back(treePtr); - _trees.insert(treeName, treePtr); -} - -void LocalVoxelsList::insert(QString treeName, StrongVoxelTreePointer& tree) { - // If the key don't already exist or the value is null - if (!_trees.contains(treeName) || !_trees.value(treeName)) { - _trees.insert(treeName, tree); - qDebug() << "LocalVoxelsList : added local tree (" << treeName << ")"; - } else { - // if not we replace the tree created by the user with the existing one - tree = _trees.value(treeName); - qDebug() << "[WARNING] LocalVoxelsList : local tree already exist (" << treeName << ")"; - } -} - -void LocalVoxelsList::remove(QString treeName) { - // if the tree is not used anymore (no strong pointer) - if (!_trees.value(treeName)) { - // then remove it from the list - _trees.remove(treeName); - } -} diff --git a/libraries/voxels/src/LocalVoxelsList.h b/libraries/voxels/src/LocalVoxelsList.h deleted file mode 100644 index d22d72446f..0000000000 --- a/libraries/voxels/src/LocalVoxelsList.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// LocalVoxelsList.h -// libraries/voxels/src -// -// Created by Clément Brisset on 2/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_LocalVoxelsList_h -#define hifi_LocalVoxelsList_h - -#include -#include -#include -#include - -#include "VoxelTree.h" - -typedef QSharedPointer StrongVoxelTreePointer; -typedef QWeakPointer WeakVoxelTreePointer; - -static const QString DOMAIN_TREE_NAME = "domain"; -static const QString CLIPBOARD_TREE_NAME = "clipboard"; -static const QString IMPORT_TREE_NAME = "import"; - -/// Handles the the storage and cleanup of local named trees used by JS -class LocalVoxelsList { -public: - static LocalVoxelsList* getInstance(); - ~LocalVoxelsList(); - - /// Lookup up a tree in the QHash and return a strong pointer to it. - /// \param treeName name of the tree to look up - StrongVoxelTreePointer getTree(QString treeName); - - /// Add a that will stay in the list until destruction of the instance and won't be destroyed then either. - /// \param treeName name to give to the tree in the list - /// \param tree standard pointer to the tree - void addPersistantTree(QString treeName, VoxelTree* tree); - - /// insert a local tree in the list - /// \param treeName name to give to the tree in the list - /// \param tree strong pointer to the tree - void insert(QString treeName, StrongVoxelTreePointer& tree); - - /// remove a tree from the list if it's not being used anymore - /// \param treeName name of the tree to remove - void remove(QString treeName); - -private: - static LocalVoxelsList* _instance; - LocalVoxelsList(); - - QHash _trees; - - QList _persistantTrees; -}; - -#endif // hifi_LocalVoxelsList_h diff --git a/libraries/voxels/src/VoxelEditPacketSender.cpp b/libraries/voxels/src/VoxelEditPacketSender.cpp deleted file mode 100644 index 50d6617278..0000000000 --- a/libraries/voxels/src/VoxelEditPacketSender.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// -// VoxelEditPacketSender.cpp -// libraries/voxels/src -// -// Created by Brad Hefta-Gaub on 8/12/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include "VoxelEditPacketSender.h" - -#define GUESS_OF_VOXELCODE_SIZE 10 -#define MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE 1500 -#define SIZE_OF_COLOR_DATA sizeof(rgbColor) -/// creates an "insert" or "remove" voxel message for a voxel code corresponding to the closest voxel which encloses a cube -/// with lower corners at x,y,z, having side of length S. The input values x,y,z range 0.0 <= v < 1.0 message should be either -/// PacketTypeVoxelSet, PacketTypeVoxelSetDestructive, or PacketTypeVoxelErase. The buffer is returned to caller becomes -/// responsibility of caller and MUST be deleted by caller. -bool createVoxelEditMessage(PacketType command, short int sequence, - int voxelCount, const VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut) { - - bool success = true; // assume the best - int messageSize = MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE; // just a guess for now - unsigned char* messageBuffer = new unsigned char[messageSize]; - - int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(messageBuffer), command); - unsigned short int* sequenceAt = (unsigned short int*) &messageBuffer[numBytesPacketHeader]; - *sequenceAt = sequence; - - // pack in timestamp - quint64 now = usecTimestampNow(); - quint64* timeAt = (quint64*)&messageBuffer[numBytesPacketHeader + sizeof(sequence)]; - *timeAt = now; - - unsigned char* copyAt = &messageBuffer[numBytesPacketHeader + sizeof(sequence) + sizeof(now)]; - int actualMessageSize = numBytesPacketHeader + sizeof(sequence) + sizeof(now); - - for (int i = 0; i < voxelCount && success; i++) { - // get the coded voxel - unsigned char* voxelData = pointToVoxel(voxelDetails[i].x,voxelDetails[i].y,voxelDetails[i].z, - voxelDetails[i].s,voxelDetails[i].red,voxelDetails[i].green,voxelDetails[i].blue); - - int lengthOfVoxelData = bytesRequiredForCodeLength(*voxelData)+SIZE_OF_COLOR_DATA; - - // make sure we have room to copy this voxel - if (actualMessageSize + lengthOfVoxelData > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) { - success = false; - } else { - // add it to our message - memcpy(copyAt, voxelData, lengthOfVoxelData); - copyAt += lengthOfVoxelData; - actualMessageSize += lengthOfVoxelData; - } - // cleanup - delete[] voxelData; - } - - if (success) { - // finally, copy the result to the output - bufferOut = new unsigned char[actualMessageSize]; - sizeOut = actualMessageSize; - memcpy(bufferOut, messageBuffer, actualMessageSize); - } - - delete[] messageBuffer; // clean up our temporary buffer - return success; -} - -/// encodes the voxel details portion of a voxel edit message -bool encodeVoxelEditMessageDetails(PacketType, int voxelCount, VoxelDetail* voxelDetails, - unsigned char* bufferOut, int sizeIn, int& sizeOut) { - - bool success = true; // assume the best - unsigned char* copyAt = bufferOut; - sizeOut = 0; - - for (int i = 0; i < voxelCount && success; i++) { - // get the coded voxel - unsigned char* voxelData = pointToVoxel(voxelDetails[i].x,voxelDetails[i].y,voxelDetails[i].z, - voxelDetails[i].s,voxelDetails[i].red,voxelDetails[i].green,voxelDetails[i].blue); - - int lengthOfVoxelData = bytesRequiredForCodeLength(*voxelData)+SIZE_OF_COLOR_DATA; - - // make sure we have room to copy this voxel - if (sizeOut + lengthOfVoxelData > sizeIn) { - success = false; - } else { - // add it to our message - memcpy(copyAt, voxelData, lengthOfVoxelData); - copyAt += lengthOfVoxelData; - sizeOut += lengthOfVoxelData; - } - // cleanup - delete[] voxelData; - } - - return success; -} - -void VoxelEditPacketSender::sendVoxelEditMessage(PacketType type, const VoxelDetail& detail) { - // allows app to disable sending if for example voxels have been disabled - if (!_shouldSend) { - return; // bail early - } - - unsigned char* bufferOut; - int sizeOut; - - // This encodes the voxel edit message into a buffer... - if (createVoxelEditMessage(type, 0, 1, &detail, bufferOut, sizeOut)){ - // If we don't have voxel jurisdictions, then we will simply queue up these packets and wait till we have - // jurisdictions for processing - if (!voxelServersExist()) { - queuePendingPacketToNodes(type, bufferOut, sizeOut, satoshiCostForMessage(detail)); - } else { - queuePacketToNodes(bufferOut, sizeOut, satoshiCostForMessage(detail)); - } - - // either way, clean up the created buffer - delete[] bufferOut; - } -} - -void VoxelEditPacketSender::queueVoxelEditMessages(PacketType type, int numberOfDetails, VoxelDetail* details) { - if (!_shouldSend) { - return; // bail early - } - - for (int i = 0; i < numberOfDetails; i++) { - // use MAX_PACKET_SIZE since it's static and guarenteed to be larger than _maxPacketSize - unsigned char bufferOut[MAX_PACKET_SIZE]; - int sizeOut = 0; - - if (encodeVoxelEditMessageDetails(type, 1, &details[i], &bufferOut[0], _maxPacketSize, sizeOut)) { - queueOctreeEditMessage(type, bufferOut, sizeOut, satoshiCostForMessage(details[i])); - } - } -} - -qint64 VoxelEditPacketSender::satoshiCostForMessage(const VoxelDetail& details) { - if (_satoshisPerVoxel == 0 && _satoshisPerMeterCubed == 0) { - return 0; - } else { - float meterScale = details.s * TREE_SCALE; - float totalVolume = meterScale * meterScale * meterScale; - - return _satoshisPerVoxel + (qint64) floorf(totalVolume * _satoshisPerMeterCubed); - } -} diff --git a/libraries/voxels/src/VoxelEditPacketSender.h b/libraries/voxels/src/VoxelEditPacketSender.h deleted file mode 100644 index 3b85155036..0000000000 --- a/libraries/voxels/src/VoxelEditPacketSender.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// VoxelEditPacketSender.h -// libraries/voxels/src -// -// Created by Brad Hefta-Gaub on 8/12/13. -// Copyright 2013 High Fidelity, Inc. -// -// Voxel Packet Sender -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelEditPacketSender_h -#define hifi_VoxelEditPacketSender_h - -#include - -#include "VoxelDetail.h" - -/// Utility for processing, packing, queueing and sending of outbound edit voxel messages. -class VoxelEditPacketSender : public OctreeEditPacketSender { - Q_OBJECT -public: - /// Send voxel edit message immediately - void sendVoxelEditMessage(PacketType type, const VoxelDetail& detail); - - /// Queues a single voxel edit message. Will potentially send a pending multi-command packet. Determines which voxel-server - /// node or nodes the packet should be sent to. Can be called even before voxel servers are known, in which case up to - /// MaxPendingMessages will be buffered and processed when voxel servers are known. - void queueVoxelEditMessage(PacketType type, unsigned char* codeColorBuffer, size_t length) { - queueOctreeEditMessage(type, codeColorBuffer, length); - } - - /// Queues an array of several voxel edit messages. Will potentially send a pending multi-command packet. Determines - /// which voxel-server node or nodes the packet should be sent to. Can be called even before voxel servers are known, in - /// which case up to MaxPendingMessages will be buffered and processed when voxel servers are known. - void queueVoxelEditMessages(PacketType type, int numberOfDetails, VoxelDetail* details); - - /// call this to inform the VoxelEditPacketSender of the voxel server jurisdictions. This is required for normal operation. - /// The internal contents of the jurisdiction map may change throughout the lifetime of the VoxelEditPacketSender. This map - /// can be set prior to voxel servers being present, so long as the contents of the map accurately reflect the current - /// known jurisdictions. - void setVoxelServerJurisdictions(NodeToJurisdictionMap* voxelServerJurisdictions) { - setServerJurisdictions(voxelServerJurisdictions); - } - - // is there a voxel server available to send packets to - bool voxelServersExist() const { return serversExist(); } - - // My server type is the voxel server - virtual char getMyNodeType() const { return NodeType::VoxelServer; } - - void setSatoshisPerVoxel(qint64 satoshisPerVoxel) { _satoshisPerVoxel = satoshisPerVoxel; } - void setSatoshisPerMeterCubed(qint64 satoshisPerMeterCubed) { _satoshisPerMeterCubed = satoshisPerMeterCubed; } - - qint64 satoshiCostForMessage(const VoxelDetail& details); - -private: - qint64 _satoshisPerVoxel; - qint64 _satoshisPerMeterCubed; -}; -#endif // hifi_VoxelEditPacketSender_h diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp deleted file mode 100644 index 0809e922e1..0000000000 --- a/libraries/voxels/src/VoxelTree.cpp +++ /dev/null @@ -1,591 +0,0 @@ -// -// VoxelTree.cpp -// libraries/voxels/src -// -// Created by Stephen Birarda on 3/13/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include -#include -#include - -#include "VoxelTree.h" -#include "Tags.h" - -// Voxel Specific operations.... - -VoxelTree::VoxelTree(bool shouldReaverage) : Octree(shouldReaverage) -{ - _rootElement = createNewElement(); -} - -VoxelTreeElement* VoxelTree::createNewElement(unsigned char * octalCode) { - VoxelSystem* voxelSystem = NULL; - if (_rootElement) { - voxelSystem = (static_cast(_rootElement))->getVoxelSystem(); - } - VoxelTreeElement* newElement = new VoxelTreeElement(octalCode); - newElement->setVoxelSystem(voxelSystem); - return newElement; -} - - -void VoxelTree::deleteVoxelAt(float x, float y, float z, float s) { - deleteOctreeElementAt(x, y, z, s); -} - -VoxelTreeElement* VoxelTree::getVoxelAt(float x, float y, float z, float s) const { - return static_cast(getOctreeElementAt(x, y, z, s)); -} - -VoxelTreeElement* VoxelTree::getEnclosingVoxelAt(float x, float y, float z, float s) const { - return static_cast(getOctreeEnclosingElementAt(x, y, z, s)); -} - -void VoxelTree::createVoxel(float x, float y, float z, float s, - unsigned char red, unsigned char green, unsigned char blue, bool destructive) { - - unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); - lockForWrite(); - readCodeColorBufferToTree(voxelData, destructive); - unlock(); - delete[] voxelData; -} - -class NodeChunkArgs { -public: - VoxelTree* thisVoxelTree; - glm::vec3 nudgeVec; - VoxelEditPacketSender* voxelEditSenderPtr; - int childOrder[NUMBER_OF_CHILDREN]; -}; - -float findNewLeafSize(const glm::vec3& nudgeAmount, float leafSize) { - // we want the smallest non-zero and non-negative new leafSize - float newLeafSizeX = fabs(fmod(nudgeAmount.x, leafSize)); - float newLeafSizeY = fabs(fmod(nudgeAmount.y, leafSize)); - float newLeafSizeZ = fabs(fmod(nudgeAmount.z, leafSize)); - - float newLeafSize = leafSize; - if (newLeafSizeX) { - newLeafSize = std::min(newLeafSize, newLeafSizeX); - } - if (newLeafSizeY) { - newLeafSize = std::min(newLeafSize, newLeafSizeY); - } - if (newLeafSizeZ) { - newLeafSize = std::min(newLeafSize, newLeafSizeZ); - } - return newLeafSize; -} - -void reorderChildrenForNudge(void* extraData) { - NodeChunkArgs* args = (NodeChunkArgs*)extraData; - glm::vec3 nudgeVec = args->nudgeVec; - int lastToNudgeVote[NUMBER_OF_CHILDREN] = { 0 }; - - const int POSITIVE_X_ORDERING[4] = {0, 1, 2, 3}; - const int NEGATIVE_X_ORDERING[4] = {4, 5, 6, 7}; - const int POSITIVE_Y_ORDERING[4] = {0, 1, 4, 5}; - const int NEGATIVE_Y_ORDERING[4] = {2, 3, 6, 7}; - const int POSITIVE_Z_ORDERING[4] = {0, 2, 4, 6}; - const int NEGATIVE_Z_ORDERING[4] = {1, 3, 5, 7}; - - if (nudgeVec.x > 0) { - for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { - lastToNudgeVote[POSITIVE_X_ORDERING[i]]++; - } - } else if (nudgeVec.x < 0) { - for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { - lastToNudgeVote[NEGATIVE_X_ORDERING[i]]++; - } - } - if (nudgeVec.y > 0) { - for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { - lastToNudgeVote[POSITIVE_Y_ORDERING[i]]++; - } - } else if (nudgeVec.y < 0) { - for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { - lastToNudgeVote[NEGATIVE_Y_ORDERING[i]]++; - } - } - if (nudgeVec.z > 0) { - for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { - lastToNudgeVote[POSITIVE_Z_ORDERING[i]]++; - } - } else if (nudgeVec.z < 0) { - for (int i = 0; i < NUMBER_OF_CHILDREN / 2; i++) { - lastToNudgeVote[NEGATIVE_Z_ORDERING[i]]++; - } - } - - int nUncountedVotes = NUMBER_OF_CHILDREN; - - while (nUncountedVotes > 0) { - int maxNumVotes = 0; - int maxVoteIndex = -1; - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - if (lastToNudgeVote[i] > maxNumVotes) { - maxNumVotes = lastToNudgeVote[i]; - maxVoteIndex = i; - } else if (lastToNudgeVote[i] == maxNumVotes && maxVoteIndex == -1) { - maxVoteIndex = i; - } - } - lastToNudgeVote[maxVoteIndex] = -1; - args->childOrder[nUncountedVotes - 1] = maxVoteIndex; - nUncountedVotes--; - } -} - -bool VoxelTree::nudgeCheck(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - if (voxel->isLeaf()) { - // we have reached the deepest level of elements/voxels - // now there are two scenarios - // 1) this element's size is <= the minNudgeAmount - // in which case we will simply call nudgeLeaf on this leaf - // 2) this element's size is still not <= the minNudgeAmount - // in which case we need to break this leaf down until the leaf sizes are <= minNudgeAmount - - NodeChunkArgs* args = (NodeChunkArgs*)extraData; - - // get octal code of this element - const unsigned char* octalCode = element->getOctalCode(); - - // get voxel position/size - VoxelPositionSize unNudgedDetails; - voxelDetailsForCode(octalCode, unNudgedDetails); - - // find necessary leaf size - float newLeafSize = findNewLeafSize(args->nudgeVec, unNudgedDetails.s); - - // check to see if this unNudged element can be nudged - if (unNudgedDetails.s <= newLeafSize) { - args->thisVoxelTree->nudgeLeaf(voxel, extraData); - return false; - } else { - // break the current leaf into smaller chunks - args->thisVoxelTree->chunkifyLeaf(voxel); - } - } - return true; -} - -void VoxelTree::chunkifyLeaf(VoxelTreeElement* element) { - // because this function will continue being called recursively - // we only need to worry about breaking this specific leaf down - if (!element->isColored()) { - return; - } - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - element->addChildAtIndex(i); - element->getChildAtIndex(i)->setColor(element->getColor()); - } -} - -// This function is called to nudge the leaves of a tree, given that the -// nudge amount is >= to the leaf scale. -void VoxelTree::nudgeLeaf(VoxelTreeElement* element, void* extraData) { - NodeChunkArgs* args = (NodeChunkArgs*)extraData; - - // get octal code of this element - const unsigned char* octalCode = element->getOctalCode(); - - // get voxel position/size - VoxelPositionSize unNudgedDetails; - voxelDetailsForCode(octalCode, unNudgedDetails); - - VoxelDetail voxelDetails; - voxelDetails.x = unNudgedDetails.x; - voxelDetails.y = unNudgedDetails.y; - voxelDetails.z = unNudgedDetails.z; - voxelDetails.s = unNudgedDetails.s; - voxelDetails.red = element->getColor()[RED_INDEX]; - voxelDetails.green = element->getColor()[GREEN_INDEX]; - voxelDetails.blue = element->getColor()[BLUE_INDEX]; - glm::vec3 nudge = args->nudgeVec; - - // delete the old element - args->voxelEditSenderPtr->sendVoxelEditMessage(PacketTypeVoxelErase, voxelDetails); - - // nudge the old element - voxelDetails.x += nudge.x; - voxelDetails.y += nudge.y; - voxelDetails.z += nudge.z; - - // create a new voxel in its stead - args->voxelEditSenderPtr->sendVoxelEditMessage(PacketTypeVoxelSetDestructive, voxelDetails); -} - -// Recurses voxel element with an operation function -void VoxelTree::recurseNodeForNudge(VoxelTreeElement* element, RecurseOctreeOperation operation, void* extraData) { - NodeChunkArgs* args = (NodeChunkArgs*)extraData; - if (operation(element, extraData)) { - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - // XXXBHG cleanup!! - VoxelTreeElement* child = (VoxelTreeElement*)element->getChildAtIndex(args->childOrder[i]); - if (child) { - recurseNodeForNudge(child, operation, extraData); - } - } - } -} - -void VoxelTree::nudgeSubTree(VoxelTreeElement* elementToNudge, const glm::vec3& nudgeAmount, VoxelEditPacketSender& voxelEditSender) { - if (nudgeAmount == glm::vec3(0, 0, 0)) { - return; - } - - NodeChunkArgs args; - args.thisVoxelTree = this; - args.nudgeVec = nudgeAmount; - args.voxelEditSenderPtr = &voxelEditSender; - reorderChildrenForNudge(&args); - - recurseNodeForNudge(elementToNudge, nudgeCheck, &args); -} - - - - - -bool VoxelTree::readFromSquareARGB32Pixels(const char* filename) { - emit importProgress(0); - int minAlpha = INT_MAX; - - QImage pngImage = QImage(filename); - - for (int i = 0; i < pngImage.width(); ++i) { - for (int j = 0; j < pngImage.height(); ++j) { - minAlpha = std::min(qAlpha(pngImage.pixel(i, j)) , minAlpha); - } - } - - int maxSize = std::max(pngImage.width(), pngImage.height()); - - int scale = 1; - while (maxSize > scale) {scale *= 2;} - float size = 1.0f / scale; - - emit importSize(size * pngImage.width(), 1.0f, size * pngImage.height()); - - QRgb pixel; - int minNeighborhoodAlpha; - - for (int i = 0; i < pngImage.width(); ++i) { - for (int j = 0; j < pngImage.height(); ++j) { - emit importProgress((100 * (i * pngImage.height() + j)) / - (pngImage.width() * pngImage.height())); - - pixel = pngImage.pixel(i, j); - minNeighborhoodAlpha = qAlpha(pixel) - 1; - - if (i != 0) { - minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i - 1, j))); - } - if (j != 0) { - minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i, j - 1))); - } - if (i < pngImage.width() - 1) { - minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i + 1, j))); - } - if (j < pngImage.height() - 1) { - minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i, j + 1))); - } - - while (qAlpha(pixel) > minNeighborhoodAlpha) { - ++minNeighborhoodAlpha; - createVoxel(i * size, - (minNeighborhoodAlpha - minAlpha) * size, - j * size, - size, - qRed(pixel), - qGreen(pixel), - qBlue(pixel), - true); - } - - } - } - - emit importProgress(100); - return true; -} - -bool VoxelTree::readFromSchematicFile(const char *fileName) { - _stopImport = false; - emit importProgress(0); - - std::stringstream ss; - int err = retrieveData(std::string(fileName), ss); - if (err && ss.get() != TAG_Compound) { - qDebug("[ERROR] Invalid schematic file."); - return false; - } - - ss.get(); - TagCompound schematics(ss); - if (!schematics.getBlocksId() || !schematics.getBlocksData()) { - qDebug("[ERROR] Invalid schematic data."); - return false; - } - - int max = (schematics.getWidth() > schematics.getLength()) ? schematics.getWidth() : schematics.getLength(); - max = (max > schematics.getHeight()) ? max : schematics.getHeight(); - - int scale = 1; - while (max > scale) {scale *= 2;} - float size = 1.0f / scale; - - emit importSize(size * schematics.getWidth(), - size * schematics.getHeight(), - size * schematics.getLength()); - - int create = 1; - int red = 128, green = 128, blue = 128; - int count = 0; - - for (int y = 0; y < schematics.getHeight(); ++y) { - for (int z = 0; z < schematics.getLength(); ++z) { - emit importProgress((int) 100 * (y * schematics.getLength() + z) / (schematics.getHeight() * schematics.getLength())); - - for (int x = 0; x < schematics.getWidth(); ++x) { - if (_stopImport) { - qDebug("Canceled import at %d voxels.", count); - _stopImport = false; - return true; - } - - int pos = ((y * schematics.getLength()) + z) * schematics.getWidth() + x; - int id = schematics.getBlocksId()[pos]; - int data = schematics.getBlocksData()[pos]; - - create = 1; - computeBlockColor(id, data, red, green, blue, create); - - switch (create) { - case 1: - createVoxel(size * x, size * y, size * z, size, red, green, blue, true); - ++count; - break; - case 2: - switch (data) { - case 0: - createVoxel(size * x + size / 2, size * y + size / 2, size * z , size / 2, red, green, blue, true); - createVoxel(size * x + size / 2, size * y + size / 2, size * z + size / 2, size / 2, red, green, blue, true); - break; - case 1: - createVoxel(size * x , size * y + size / 2, size * z , size / 2, red, green, blue, true); - createVoxel(size * x , size * y + size / 2, size * z + size / 2, size / 2, red, green, blue, true); - break; - case 2: - createVoxel(size * x , size * y + size / 2, size * z + size / 2, size / 2, red, green, blue, true); - createVoxel(size * x + size / 2, size * y + size / 2, size * z + size / 2, size / 2, red, green, blue, true); - break; - case 3: - createVoxel(size * x , size * y + size / 2, size * z , size / 2, red, green, blue, true); - createVoxel(size * x + size / 2, size * y + size / 2, size * z , size / 2, red, green, blue, true); - break; - } - count += 2; - // There's no break on purpose. - case 3: - createVoxel(size * x , size * y, size * z , size / 2, red, green, blue, true); - createVoxel(size * x + size / 2, size * y, size * z , size / 2, red, green, blue, true); - createVoxel(size * x , size * y, size * z + size / 2, size / 2, red, green, blue, true); - createVoxel(size * x + size / 2, size * y, size * z + size / 2, size / 2, red, green, blue, true); - count += 4; - break; - } - } - } - } - - emit importProgress(100); - qDebug("Created %d voxels from minecraft import.", count); - - return true; -} - -class ReadCodeColorBufferToTreeArgs { -public: - const unsigned char* codeColorBuffer; - int lengthOfCode; - bool destructive; - bool pathChanged; -}; - -void VoxelTree::readCodeColorBufferToTree(const unsigned char* codeColorBuffer, bool destructive) { - ReadCodeColorBufferToTreeArgs args; - args.codeColorBuffer = codeColorBuffer; - args.lengthOfCode = numberOfThreeBitSectionsInCode(codeColorBuffer); - args.destructive = destructive; - args.pathChanged = false; - VoxelTreeElement* node = getRoot(); - readCodeColorBufferToTreeRecursion(node, args); -} - -void VoxelTree::readCodeColorBufferToTreeRecursion(VoxelTreeElement* node, ReadCodeColorBufferToTreeArgs& args) { - int lengthOfNodeCode = numberOfThreeBitSectionsInCode(node->getOctalCode()); - - // Since we traverse the tree in code order, we know that if our code - // matches, then we've reached our target node. - if (lengthOfNodeCode == args.lengthOfCode) { - // we've reached our target -- we might have found our node, but that node might have children. - // in this case, we only allow you to set the color if you explicitly asked for a destructive - // write. - if (!node->isLeaf() && args.destructive) { - // if it does exist, make sure it has no children - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - node->deleteChildAtIndex(i); - } - } else { - if (!node->isLeaf()) { - qDebug("WARNING! operation would require deleting children, add Voxel ignored!"); - } - } - - // If we get here, then it means, we either had a true leaf to begin with, or we were in - // destructive mode and we deleted all the child trees. So we can color. - if (node->isLeaf()) { - // give this node its color - int octalCodeBytes = bytesRequiredForCodeLength(args.lengthOfCode); - - nodeColor newColor; - memcpy(newColor, args.codeColorBuffer + octalCodeBytes, SIZE_OF_COLOR_DATA); - newColor[SIZE_OF_COLOR_DATA] = 1; - node->setColor(newColor); - - // It's possible we just reset the node to it's exact same color, in - // which case we don't consider this to be dirty... - if (node->isDirty()) { - // track our tree dirtiness - _isDirty = true; - // track that path has changed - args.pathChanged = true; - } - } - return; - } - - // Ok, we know we haven't reached our target node yet, so keep looking - //printOctalCode(args.codeColorBuffer); - int childIndex = branchIndexWithDescendant(node->getOctalCode(), args.codeColorBuffer); - VoxelTreeElement* childNode = node->getChildAtIndex(childIndex); - - // If the branch we need to traverse does not exist, then create it on the way down... - if (!childNode) { - childNode = node->addChildAtIndex(childIndex); - } - - // recurse... - readCodeColorBufferToTreeRecursion(childNode, args); - - // Unwinding... - - // If the lower level did some work, then we need to let this node know, so it can - // do any bookkeeping it wants to, like color re-averaging, time stamp marking, etc - if (args.pathChanged) { - node->handleSubtreeChanged(this); - } -} - -bool VoxelTree::handlesEditPacketType(PacketType packetType) const { - // we handle these types of "edit" packets - switch (packetType) { - case PacketTypeVoxelSet: - case PacketTypeVoxelSetDestructive: - case PacketTypeVoxelErase: - return true; - default: - return false; - - } -} - -const unsigned int REPORT_OVERFLOW_WARNING_INTERVAL = 100; -unsigned int overflowWarnings = 0; -int VoxelTree::processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, - const unsigned char* editData, int maxLength, const SharedNodePointer& node) { - - // we handle these types of "edit" packets - switch (packetType) { - case PacketTypeVoxelSet: - case PacketTypeVoxelSetDestructive: { - bool destructive = (packetType == PacketTypeVoxelSetDestructive); - int octets = numberOfThreeBitSectionsInCode(editData, maxLength); - - if (octets == OVERFLOWED_OCTCODE_BUFFER) { - overflowWarnings++; - if (overflowWarnings % REPORT_OVERFLOW_WARNING_INTERVAL == 1) { - qDebug() << "WARNING! Got voxel edit record that would overflow buffer in numberOfThreeBitSectionsInCode()" - " [NOTE: this is warning number" << overflowWarnings << ", the next" << - (REPORT_OVERFLOW_WARNING_INTERVAL-1) << "will be suppressed.]"; - - QDebug debug = qDebug(); - debug << "edit data contents:"; - outputBufferBits(editData, maxLength, &debug); - } - return maxLength; - } - - const int COLOR_SIZE_IN_BYTES = 3; - int voxelCodeSize = bytesRequiredForCodeLength(octets); - int voxelDataSize = voxelCodeSize + COLOR_SIZE_IN_BYTES; - - if (voxelDataSize > maxLength) { - overflowWarnings++; - if (overflowWarnings % REPORT_OVERFLOW_WARNING_INTERVAL == 1) { - qDebug() << "WARNING! Got voxel edit record that would overflow buffer." - " [NOTE: this is warning number" << overflowWarnings << ", the next" << - (REPORT_OVERFLOW_WARNING_INTERVAL-1) << "will be suppressed.]"; - - QDebug debug = qDebug(); - debug << "edit data contents:"; - outputBufferBits(editData, maxLength, &debug); - } - return maxLength; - } - - readCodeColorBufferToTree(editData, destructive); - - return voxelDataSize; - } break; - - case PacketTypeVoxelErase: - processRemoveOctreeElementsBitstream((unsigned char*)packetData, packetLength); - return maxLength; - default: - return 0; - } -} - -class VoxelTreeDebugOperator : public RecurseOctreeOperator { -public: - virtual bool preRecursion(OctreeElement* element); - virtual bool postRecursion(OctreeElement* element) { return true; } -}; - -bool VoxelTreeDebugOperator::preRecursion(OctreeElement* element) { - VoxelTreeElement* treeElement = static_cast(element); - qDebug() << "VoxelTreeElement [" << treeElement << ":" << treeElement->getAACube() << "]"; - qDebug() << " isLeaf:" << treeElement->isLeaf(); - qDebug() << " color:" << treeElement->getColor()[0] << ", " - << treeElement->getColor()[1] << ", " - << treeElement->getColor()[2]; - return true; -} - -void VoxelTree::dumpTree() { - // First, look for the existing entity in the tree.. - VoxelTreeDebugOperator theOperator; - recurseTreeWithOperator(&theOperator); -} - diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h deleted file mode 100644 index 547f590270..0000000000 --- a/libraries/voxels/src/VoxelTree.h +++ /dev/null @@ -1,87 +0,0 @@ -// -// VoxelTree.h -// libraries/voxels/src -// -// Created by Stephen Birarda on 3/13/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelTree_h -#define hifi_VoxelTree_h - -#include - -#include "VoxelTreeElement.h" -#include "VoxelEditPacketSender.h" - -class ReadCodeColorBufferToTreeArgs; - -class VoxelTree : public Octree { - Q_OBJECT -public: - - VoxelTree(bool shouldReaverage = false); - - virtual VoxelTreeElement* createNewElement(unsigned char * octalCode = NULL); - VoxelTreeElement* getRoot() { return static_cast(_rootElement); } - - void deleteVoxelAt(float x, float y, float z, float s); - - /// Find the voxel at position x,y,z,s - /// \return pointer to the VoxelTreeElement or NULL if none at x,y,z,s. - VoxelTreeElement* getVoxelAt(float x, float y, float z, float s) const; - - /// Find the voxel at position x,y,z,s - /// \return pointer to the VoxelTreeElement or to the smallest enclosing parent if none at x,y,z,s. - VoxelTreeElement* getEnclosingVoxelAt(float x, float y, float z, float s) const; - - void createVoxel(float x, float y, float z, float s, - unsigned char red, unsigned char green, unsigned char blue, bool destructive = false); - - void nudgeSubTree(VoxelTreeElement* elementToNudge, const glm::vec3& nudgeAmount, VoxelEditPacketSender& voxelEditSender); - - /// reads voxels from square image with alpha as a Y-axis - bool readFromSquareARGB32Pixels(const char *filename); - - /// reads from minecraft file - bool readFromSchematicFile(const char* filename); - - void readCodeColorBufferToTree(const unsigned char* codeColorBuffer, bool destructive = false); - - - virtual bool getWantSVOfileVersions() const { return true; } - virtual bool canProcessVersion(PacketVersion thisVersion) const { - return thisVersion == 0 || thisVersion == versionForPacketType(expectedDataPacketType()); } - virtual PacketVersion expectedVersion() const { return versionForPacketType(expectedDataPacketType()); } - - virtual PacketType expectedDataPacketType() const { return PacketTypeVoxelData; } - virtual bool handlesEditPacketType(PacketType packetType) const; - virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, - const unsigned char* editData, int maxLength, const SharedNodePointer& node); - virtual bool recurseChildrenWithData() const { return false; } - - /// some versions of the SVO file will include breaks with buffer lengths between each buffer chunk in the SVO - /// file. If the Octree subclass expects this for this particular version of the file, it should override this - /// method and return true. - virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const { - if (thisVersion == 0) { - return false; // old versions didn't have buffer breaks - } - return true; - } - - virtual void dumpTree(); - -private: - // helper functions for nudgeSubTree - void recurseNodeForNudge(VoxelTreeElement* element, RecurseOctreeOperation operation, void* extraData); - static bool nudgeCheck(OctreeElement* element, void* extraData); - void nudgeLeaf(VoxelTreeElement* element, void* extraData); - void chunkifyLeaf(VoxelTreeElement* element); - void readCodeColorBufferToTreeRecursion(VoxelTreeElement* node, ReadCodeColorBufferToTreeArgs& args); -}; - -#endif // hifi_VoxelTree_h diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp deleted file mode 100644 index 4ddc280749..0000000000 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// -// VoxelTreeCommands.cpp -// libraries/voxels/src -// -// Created by Clement on 4/4/14. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "VoxelTree.h" - -#include "VoxelTreeCommands.h" - - - -struct SendVoxelsOperationArgs { - const unsigned char* newBaseOctCode; - VoxelEditPacketSender* packetSender; -}; - -bool sendVoxelsOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = static_cast(element); - SendVoxelsOperationArgs* args = static_cast(extraData); - if (voxel->isColored()) { - const unsigned char* nodeOctalCode = voxel->getOctalCode(); - unsigned char* codeColorBuffer = NULL; - int codeLength = 0; - int bytesInCode = 0; - int codeAndColorLength; - - // If the newBase is NULL, then don't rebase - if (args->newBaseOctCode) { - codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); - codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer); - bytesInCode = bytesRequiredForCodeLength(codeLength); - codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; - } else { - codeLength = numberOfThreeBitSectionsInCode(nodeOctalCode); - bytesInCode = bytesRequiredForCodeLength(codeLength); - codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; - codeColorBuffer = new unsigned char[codeAndColorLength]; - memcpy(codeColorBuffer, nodeOctalCode, bytesInCode); - } - - // copy the colors over - codeColorBuffer[bytesInCode + RED_INDEX] = voxel->getColor()[RED_INDEX]; - codeColorBuffer[bytesInCode + GREEN_INDEX] = voxel->getColor()[GREEN_INDEX]; - codeColorBuffer[bytesInCode + BLUE_INDEX] = voxel->getColor()[BLUE_INDEX]; - args->packetSender->queueVoxelEditMessage(PacketTypeVoxelSetDestructive, - codeColorBuffer, codeAndColorLength); - - delete[] codeColorBuffer; - } - return true; // keep going -} - - -AddVoxelCommand::AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender, QUndoCommand* parent) : - QUndoCommand("Add Voxel", parent), - _tree(tree), - _packetSender(packetSender), - _voxel(voxel) -{ -} - -void AddVoxelCommand::redo() { - if (_tree) { - _tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel); - } -} - -void AddVoxelCommand::undo() { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); - } -} - -DeleteVoxelCommand::DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender, QUndoCommand* parent) : - QUndoCommand("Delete Voxel", parent), - _tree(tree), - _packetSender(packetSender), - _voxel(voxel), - _oldTree(NULL) -{ - _tree->lockForRead(); - VoxelTreeElement* element = _tree->getEnclosingVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - if (element->getScale() == _voxel.s) { - if (!element->hasContent() && !element->isLeaf()) { - _oldTree = new VoxelTree(); - _tree->copySubTreeIntoNewTree(element, _oldTree, false); - } else { - _voxel.red = element->getColor()[0]; - _voxel.green = element->getColor()[1]; - _voxel.blue = element->getColor()[2]; - } - } else if (element->hasContent() && element->isLeaf()) { - _voxel.red = element->getColor()[0]; - _voxel.green = element->getColor()[1]; - _voxel.blue = element->getColor()[2]; - } else { - _voxel.s = 0.0f; - } - _tree->unlock(); -} - -DeleteVoxelCommand::~DeleteVoxelCommand() { - delete _oldTree; -} - -void DeleteVoxelCommand::redo() { - if (_voxel.s == 0.0f) { - return; - } - - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); - } -} - -void DeleteVoxelCommand::undo() { - if (_voxel.s == 0.0f) { - return; - } - - if (_oldTree) { - VoxelTreeElement* element = _oldTree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - if (element) { - if (_tree) { - _tree->lockForWrite(); - _oldTree->copySubTreeIntoNewTree(element, _tree, false); - _tree->unlock(); - } - if (_packetSender) { - SendVoxelsOperationArgs args; - args.newBaseOctCode = NULL; - args.packetSender = _packetSender; - _oldTree->recurseTreeWithOperation(sendVoxelsOperation, &args); - _packetSender->releaseQueuedMessages(); - } - } - } else { - if (_tree) { - _tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel); - } - } -} diff --git a/libraries/voxels/src/VoxelTreeCommands.h b/libraries/voxels/src/VoxelTreeCommands.h deleted file mode 100644 index 8df1f0dc14..0000000000 --- a/libraries/voxels/src/VoxelTreeCommands.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// VoxelTreeCommands.h -// libraries/voxels/src -// -// Created by Clement on 4/4/14. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelTreeCommands_h -#define hifi_VoxelTreeCommands_h - -#include -#include - -#include "VoxelDetail.h" -#include "VoxelEditPacketSender.h" - -class VoxelTree; - -class AddVoxelCommand : public QUndoCommand { -public: - AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL); - - virtual void redo(); - virtual void undo(); - -private: - VoxelTree* _tree; - VoxelEditPacketSender* _packetSender; - VoxelDetail _voxel; -}; - -class DeleteVoxelCommand : public QUndoCommand { -public: - DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL); - ~DeleteVoxelCommand(); - - virtual void redo(); - virtual void undo(); - -private: - VoxelTree* _tree; - VoxelEditPacketSender* _packetSender; - VoxelDetail _voxel; - VoxelTree* _oldTree; -}; - -#endif // hifi_VoxelTreeCommands_h diff --git a/libraries/voxels/src/VoxelTreeElement.cpp b/libraries/voxels/src/VoxelTreeElement.cpp deleted file mode 100644 index f81e8c073f..0000000000 --- a/libraries/voxels/src/VoxelTreeElement.cpp +++ /dev/null @@ -1,253 +0,0 @@ -// -// VoxelTreeElement.cpp -// libraries/voxels/src -// -// Created by Stephen Birarda on 3/13/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include - -#include "VoxelConstants.h" -#include "VoxelTreeElement.h" -#include "VoxelTree.h" - -VoxelTreeElement::VoxelTreeElement(unsigned char* octalCode) : - OctreeElement(), - _exteriorOcclusions(OctreeElement::HalfSpace::All), - _interiorOcclusions(OctreeElement::HalfSpace::None) -{ - init(octalCode); -}; - -VoxelTreeElement::~VoxelTreeElement() { - _voxelMemoryUsage -= sizeof(VoxelTreeElement); -} - -// This will be called primarily on addChildAt(), which means we're adding a child of our -// own type to our own tree. This means we should initialize that child with any tree and type -// specific settings that our children must have. One example is out VoxelSystem, which -// we know must match ours. -OctreeElement* VoxelTreeElement::createNewElement(unsigned char* octalCode) { - VoxelTreeElement* newChild = new VoxelTreeElement(octalCode); - newChild->setVoxelSystem(getVoxelSystem()); // our child is always part of our voxel system NULL ok - return newChild; -} - -void VoxelTreeElement::init(unsigned char* octalCode) { - setVoxelSystem(NULL); - setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - _falseColored = false; // assume true color - _color[0] = _color[1] = _color[2] = _color[3] = 0; - _density = 0.0f; - OctreeElement::init(octalCode); - _voxelMemoryUsage += sizeof(VoxelTreeElement); -} - -bool VoxelTreeElement::requiresSplit() const { - return isLeaf() && isColored(); -} - -void VoxelTreeElement::splitChildren() { - if (requiresSplit()) { - const nodeColor& ourColor = getColor(); - - // for colored leaves, we must add *all* the children - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - addChildAtIndex(i)->setColor(ourColor); - } - nodeColor noColor = { 0, 0, 0, 0}; - setColor(noColor); // set our own color to noColor so we are a pure non-leaf - } -} - -OctreeElement::AppendState VoxelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const { - return packetData->appendColor(getColor()) ? OctreeElement::COMPLETED : OctreeElement::NONE; -} - - -int VoxelTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, - ReadBitstreamToTreeParams& args) { - const int BYTES_PER_COLOR = 3; - - if (bytesLeftToRead < BYTES_PER_COLOR) { - qDebug() << "UNEXPECTED: readElementDataFromBuffer() only had " << bytesLeftToRead << " bytes. " - "Not enough for meaningful data."; - return bytesLeftToRead; - } - - - // pull the color for this child - nodeColor newColor = { 128, 128, 128, 1}; - if (args.includeColor) { - memcpy(newColor, data, BYTES_PER_COLOR); - } - setColor(newColor); - return BYTES_PER_COLOR; -} - - -const uint8_t INDEX_FOR_NULL = 0; -uint8_t VoxelTreeElement::_nextIndex = INDEX_FOR_NULL + 1; // start at 1, 0 is reserved for NULL -std::map VoxelTreeElement::_mapVoxelSystemPointersToIndex; -std::map VoxelTreeElement::_mapIndexToVoxelSystemPointers; - -VoxelSystem* VoxelTreeElement::getVoxelSystem() const { - if (_voxelSystemIndex > INDEX_FOR_NULL) { - if (_mapIndexToVoxelSystemPointers.end() != _mapIndexToVoxelSystemPointers.find(_voxelSystemIndex)) { - - VoxelSystem* voxelSystem = _mapIndexToVoxelSystemPointers[_voxelSystemIndex]; - return voxelSystem; - } - } - return NULL; -} - -void VoxelTreeElement::setVoxelSystem(VoxelSystem* voxelSystem) { - if (!voxelSystem) { - _voxelSystemIndex = INDEX_FOR_NULL; - } else { - uint8_t index; - if (_mapVoxelSystemPointersToIndex.end() != _mapVoxelSystemPointersToIndex.find(voxelSystem)) { - index = _mapVoxelSystemPointersToIndex[voxelSystem]; - } else { - index = _nextIndex; - _nextIndex++; - _mapVoxelSystemPointersToIndex[voxelSystem] = index; - _mapIndexToVoxelSystemPointers[index] = voxelSystem; - } - _voxelSystemIndex = index; - } -} - -void VoxelTreeElement::setColor(const nodeColor& color) { - if (_color[0] != color[0] || _color[1] != color[1] || _color[2] != color[2]) { - memcpy(&_color,&color,sizeof(nodeColor)); - _isDirty = true; - if (color[3]) { - _density = 1.0f; // If color set, assume leaf, re-averaging will update density if needed. - } else { - _density = 0.0f; - } - markWithChangedTime(); - } -} - - - -// will average the child colors... -void VoxelTreeElement::calculateAverageFromChildren() { - int colorArray[4] = {0,0,0,0}; - float density = 0.0f; - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - VoxelTreeElement* childAt = getChildAtIndex(i); - if (childAt && childAt->isColored()) { - for (int j = 0; j < 3; j++) { - colorArray[j] += childAt->getColor()[j]; // color averaging should always be based on true colors - } - colorArray[3]++; - } - if (childAt) { - density += childAt->getDensity(); - } - } - density /= (float) NUMBER_OF_CHILDREN; - // - // The VISIBLE_ABOVE_DENSITY sets the density of matter above which an averaged color voxel will - // be set. It is an important physical constant in our universe. A number below 0.5 will cause - // things to get 'fatter' at a distance, because upward averaging will make larger voxels out of - // less data, which is (probably) going to be preferable because it gives a sense that there is - // something out there to go investigate. A number above 0.5 would cause the world to become - // more 'empty' at a distance. Exactly 0.5 would match the physical world, at least for materials - // that are not shiny and have equivalent ambient reflectance. - // - const float VISIBLE_ABOVE_DENSITY = 0.10f; - nodeColor newColor = { 0, 0, 0, 0}; - if (density > VISIBLE_ABOVE_DENSITY) { - // The density of material in the space of the voxel sets whether it is actually colored - for (int c = 0; c < 3; c++) { - // set the average color value - newColor[c] = colorArray[c] / colorArray[3]; - } - // set the alpha to 1 to indicate that this isn't transparent - newColor[3] = 1; - } - // Set the color from the average of the child colors, and update the density - setColor(newColor); - setDensity(density); -} - -// will detect if children are leaves AND the same color -// and in that case will delete the children and make this node -// a leaf, returns TRUE if all the leaves are collapsed into a -// single node -bool VoxelTreeElement::collapseChildren() { - // scan children, verify that they are ALL present and accounted for - bool allChildrenMatch = true; // assume the best (ottimista) - int red = 0; - int green = 0; - int blue = 0; - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - VoxelTreeElement* childAt = getChildAtIndex(i); - // if no child, child isn't a leaf, or child doesn't have a color - if (!childAt || !childAt->isLeaf() || !childAt->isColored()) { - allChildrenMatch = false; - break; - } else { - if (i==0) { - red = childAt->getColor()[0]; - green = childAt->getColor()[1]; - blue = childAt->getColor()[2]; - } else if (red != childAt->getColor()[0] || - green != childAt->getColor()[1] || blue != childAt->getColor()[2]) { - allChildrenMatch=false; - break; - } - } - } - - - if (allChildrenMatch) { - //qDebug("allChildrenMatch: pruning tree\n"); - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - OctreeElement* childAt = getChildAtIndex(i); - delete childAt; // delete all the child nodes - setChildAtIndex(i, NULL); // set it to NULL - } - nodeColor collapsedColor; - collapsedColor[0]=red; - collapsedColor[1]=green; - collapsedColor[2]=blue; - collapsedColor[3]=1; // color is set - setColor(collapsedColor); - } - return allChildrenMatch; -} - - -bool VoxelTreeElement::findSpherePenetration(const glm::vec3& center, float radius, - glm::vec3& penetration, void** penetratedObject) const { - if (_cube.findSpherePenetration(center, radius, penetration)) { - - // if the caller wants details about the voxel, then return them here... - if (penetratedObject) { - VoxelDetail* voxelDetails = new VoxelDetail; - voxelDetails->x = _cube.getCorner().x; - voxelDetails->y = _cube.getCorner().y; - voxelDetails->z = _cube.getCorner().z; - voxelDetails->s = _cube.getScale(); - voxelDetails->red = getColor()[RED_INDEX]; - voxelDetails->green = getColor()[GREEN_INDEX]; - voxelDetails->blue = getColor()[BLUE_INDEX]; - - *penetratedObject = (void*)voxelDetails; - } - return true; - } - return false; -} - diff --git a/libraries/voxels/src/VoxelTreeElement.h b/libraries/voxels/src/VoxelTreeElement.h deleted file mode 100644 index 0ea91d4657..0000000000 --- a/libraries/voxels/src/VoxelTreeElement.h +++ /dev/null @@ -1,123 +0,0 @@ -// -// VoxelTreeElement.h -// libraries/voxels/src -// -// Created by Stephen Birarda on 3/13/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelTreeElement_h -#define hifi_VoxelTreeElement_h - -//#define HAS_AUDIT_CHILDREN -//#define SIMPLE_CHILD_ARRAY -#define SIMPLE_EXTERNAL_CHILDREN - -#include - -#include -#include -#include - -#include "ViewFrustum.h" -#include "VoxelConstants.h" - -class VoxelTree; -class VoxelTreeElement; -class VoxelSystem; - -class VoxelTreeElement : public OctreeElement { - friend class VoxelTree; // to allow createElement to new us... - - VoxelTreeElement(unsigned char* octalCode = NULL); - - virtual OctreeElement* createNewElement(unsigned char* octalCode = NULL); - -public: - virtual ~VoxelTreeElement(); - virtual void init(unsigned char * octalCode); - - virtual bool hasContent() const { return isColored(); } - virtual void splitChildren(); - virtual bool requiresSplit() const; - virtual OctreeElement::AppendState appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const; - virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); - virtual void calculateAverageFromChildren(); - virtual bool collapseChildren(); - virtual bool findSpherePenetration(const glm::vec3& center, float radius, - glm::vec3& penetration, void** penetratedObject) const; - - - - glBufferIndex getBufferIndex() const { return _glBufferIndex; } - bool isKnownBufferIndex() const { return !_unknownBufferIndex; } - void setBufferIndex(glBufferIndex index) { _glBufferIndex = index; _unknownBufferIndex =(index == GLBUFFER_INDEX_UNKNOWN);} - VoxelSystem* getVoxelSystem() const; - void setVoxelSystem(VoxelSystem* voxelSystem); - - virtual bool isRendered() const { return isKnownBufferIndex(); } - - bool isColored() const { return _color[3] == 1; } - - void setColor(const nodeColor& color); - const nodeColor& getColor() const { return _color; } - - void setDensity(float density) { _density = density; } - float getDensity() const { return _density; } - - void setInteriorOcclusions(unsigned char interiorExclusions); - void setExteriorOcclusions(unsigned char exteriorOcclusions); - unsigned char getExteriorOcclusions() const; - unsigned char getInteriorOcclusions() const; - - // type safe versions of OctreeElement methods - VoxelTreeElement* getChildAtIndex(int childIndex) { return (VoxelTreeElement*)OctreeElement::getChildAtIndex(childIndex); } - VoxelTreeElement* addChildAtIndex(int childIndex) { return (VoxelTreeElement*)OctreeElement::addChildAtIndex(childIndex); } - -protected: - - uint32_t _glBufferIndex : 24; /// Client only, vbo index for this voxel if being rendered, 3 bytes - uint32_t _voxelSystemIndex : 8; /// Client only, index to the VoxelSystem rendering this voxel, 1 bytes - - // Support for _voxelSystemIndex, we use these static member variables to track the VoxelSystems that are - // in use by various voxel nodes. We map the VoxelSystem pointers into an 1 byte key, this limits us to at - // most 255 voxel systems in use at a time within the client. Which is far more than we need. - static uint8_t _nextIndex; - static std::map _mapVoxelSystemPointersToIndex; - static std::map _mapIndexToVoxelSystemPointers; - - float _density; /// Client and server, If leaf: density = 1, if internal node: 0-1 density of voxels inside, 4 bytes - - nodeColor _color; /// Client and server, true color of this voxel, 4 bytes - -private: - unsigned char _exteriorOcclusions; ///< Exterior shared partition boundaries that are completely occupied - unsigned char _interiorOcclusions; ///< Interior shared partition boundaries with siblings -}; - -inline void VoxelTreeElement::setExteriorOcclusions(unsigned char exteriorOcclusions) { - if (_exteriorOcclusions != exteriorOcclusions) { - _exteriorOcclusions = exteriorOcclusions; - setDirtyBit(); - } -} - -inline void VoxelTreeElement::setInteriorOcclusions(unsigned char interiorOcclusions) { - if (_interiorOcclusions != interiorOcclusions) { - _interiorOcclusions = interiorOcclusions; - setDirtyBit(); - } -} - -inline unsigned char VoxelTreeElement::getInteriorOcclusions() const { - return _interiorOcclusions; -} - -inline unsigned char VoxelTreeElement::getExteriorOcclusions() const { - return _exteriorOcclusions; -} - -#endif // hifi_VoxelTreeElement_h diff --git a/libraries/voxels/src/VoxelTreeHeadlessViewer.cpp b/libraries/voxels/src/VoxelTreeHeadlessViewer.cpp deleted file mode 100644 index 5aaa8c8d97..0000000000 --- a/libraries/voxels/src/VoxelTreeHeadlessViewer.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// VoxelTreeHeadlessViewer.cpp -// libraries/voxels/src -// -// Created by Brad Hefta-Gaub on 2/26/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "VoxelTreeHeadlessViewer.h" - -VoxelTreeHeadlessViewer::VoxelTreeHeadlessViewer() : - OctreeHeadlessViewer() { -} - -VoxelTreeHeadlessViewer::~VoxelTreeHeadlessViewer() { -} - -void VoxelTreeHeadlessViewer::init() { - OctreeHeadlessViewer::init(); -} - diff --git a/libraries/voxels/src/VoxelTreeHeadlessViewer.h b/libraries/voxels/src/VoxelTreeHeadlessViewer.h deleted file mode 100644 index 291ad7f813..0000000000 --- a/libraries/voxels/src/VoxelTreeHeadlessViewer.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// VoxelTreeHeadlessViewer.h -// libraries/voxels/src -// -// Created by Brad Hefta-Gaub on 2/26/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelTreeHeadlessViewer_h -#define hifi_VoxelTreeHeadlessViewer_h - -#include -#include -#include -#include -#include -#include "VoxelTree.h" -#include - -// Generic client side Octree renderer class. -class VoxelTreeHeadlessViewer : public OctreeHeadlessViewer { - Q_OBJECT -public: - VoxelTreeHeadlessViewer(); - virtual ~VoxelTreeHeadlessViewer(); - - virtual char getMyNodeType() const { return NodeType::VoxelServer; } - virtual PacketType getMyQueryMessageType() const { return PacketTypeVoxelQuery; } - virtual PacketType getExpectedPacketType() const { return PacketTypeVoxelData; } - - VoxelTree* getTree() { return (VoxelTree*)_tree; } - - virtual void init(); - -protected: - virtual Octree* createTree() { return new VoxelTree(true); } -}; - -#endif // hifi_VoxelTreeHeadlessViewer_h diff --git a/libraries/voxels/src/VoxelsScriptingInterface.cpp b/libraries/voxels/src/VoxelsScriptingInterface.cpp deleted file mode 100644 index c11aca2872..0000000000 --- a/libraries/voxels/src/VoxelsScriptingInterface.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// -// VoxelsScriptingInterface.cpp -// libraries/voxels/src -// -// Created by Stephen Birarda on 9/17/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "VoxelTreeCommands.h" - -#include "VoxelsScriptingInterface.h" - -void VoxelsScriptingInterface::queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails) { - getVoxelPacketSender()->queueVoxelEditMessages(addPacketType, 1, &addVoxelDetails); -} - -VoxelDetail VoxelsScriptingInterface::getVoxelAt(float x, float y, float z, float scale) { - // setup a VoxelDetail struct with the data - VoxelDetail result = {0,0,0,0,0,0,0}; - - if (_tree) { - _tree->lockForRead(); - - VoxelTreeElement* voxel = static_cast(_tree->getOctreeElementAt(x / (float)TREE_SCALE, y / (float)TREE_SCALE, - z / (float)TREE_SCALE, scale / (float)TREE_SCALE)); - _tree->unlock(); - if (voxel) { - // Note: these need to be in voxel space because the VoxelDetail -> js converter will upscale - result.x = voxel->getCorner().x; - result.y = voxel->getCorner().y; - result.z = voxel->getCorner().z; - result.s = voxel->getScale(); - result.red = voxel->getColor()[RED_INDEX]; - result.green = voxel->getColor()[GREEN_INDEX]; - result.blue = voxel->getColor()[BLUE_INDEX]; - } - } - return result; -} - -void VoxelsScriptingInterface::setVoxelNonDestructive(float x, float y, float z, float scale, - uchar red, uchar green, uchar blue) { - // setup a VoxelDetail struct with the data - VoxelDetail addVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, - scale / (float)TREE_SCALE, red, green, blue}; - - - // handle the local tree also... - if (_tree) { - if (_undoStack) { - AddVoxelCommand* command = new AddVoxelCommand(_tree, - addVoxelDetail, - getVoxelPacketSender()); - - // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. - _undoStack->push(command); - } else { - // queue the add packet - queueVoxelAdd(PacketTypeVoxelSet, addVoxelDetail); - _tree->createVoxel(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s, red, green, blue, false); - } - } -} - -void VoxelsScriptingInterface::setVoxel(float x, float y, float z, float scale, - uchar red, uchar green, uchar blue) { - // setup a VoxelDetail struct with the data - VoxelDetail addVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, - scale / (float)TREE_SCALE, red, green, blue}; - - // handle the local tree also... - if (_tree) { - if (_undoStack) { - AddVoxelCommand* addCommand = new AddVoxelCommand(_tree, - addVoxelDetail, - getVoxelPacketSender()); - DeleteVoxelCommand* deleteCommand = new DeleteVoxelCommand(_tree, - addVoxelDetail, - getVoxelPacketSender()); - _undoStackMutex.lock(); - - _undoStack->beginMacro(addCommand->text()); - // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. - _undoStack->push(deleteCommand); - _undoStack->push(addCommand); - _undoStack->endMacro(); - - //Unlock the mutex - _undoStackMutex.unlock(); - } else { - // queue the destructive add - queueVoxelAdd(PacketTypeVoxelSetDestructive, addVoxelDetail); - _tree->createVoxel(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s, red, green, blue, true); - } - } -} - -void VoxelsScriptingInterface::eraseVoxel(float x, float y, float z, float scale) { - // setup a VoxelDetail struct with data - VoxelDetail deleteVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, - scale / (float)TREE_SCALE}; - - - // handle the local tree also... - if (_tree) { - VoxelTreeElement* deleteVoxelElement = _tree->getVoxelAt(deleteVoxelDetail.x, deleteVoxelDetail.y, deleteVoxelDetail.z, deleteVoxelDetail.s); - if (deleteVoxelElement) { - deleteVoxelDetail.red = deleteVoxelElement->getColor()[0]; - deleteVoxelDetail.green = deleteVoxelElement->getColor()[1]; - deleteVoxelDetail.blue = deleteVoxelElement->getColor()[2]; - } - - if (_undoStack) { - - DeleteVoxelCommand* command = new DeleteVoxelCommand(_tree, - deleteVoxelDetail, - getVoxelPacketSender()); - - _undoStackMutex.lock(); - // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. - _undoStack->push(command); - _undoStackMutex.unlock(); - } else { - getVoxelPacketSender()->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &deleteVoxelDetail); - _tree->deleteVoxelAt(deleteVoxelDetail.x, deleteVoxelDetail.y, deleteVoxelDetail.z, deleteVoxelDetail.s); - } - } -} - -RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersection(const PickRay& ray) { - return findRayIntersectionWorker(ray, Octree::TryLock); -} - -RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersectionBlocking(const PickRay& ray) { - return findRayIntersectionWorker(ray, Octree::Lock); -} - -RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersectionWorker(const PickRay& ray, - Octree::lockType lockType) { - RayToVoxelIntersectionResult result; - if (_tree) { - OctreeElement* element; - result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, NULL, - lockType, &result.accurate); - if (result.intersects) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - result.voxel.x = voxel->getCorner().x; - result.voxel.y = voxel->getCorner().y; - result.voxel.z = voxel->getCorner().z; - result.voxel.s = voxel->getScale(); - result.voxel.red = voxel->getColor()[0]; - result.voxel.green = voxel->getColor()[1]; - result.voxel.blue = voxel->getColor()[2]; - result.intersection = ray.origin + (ray.direction * result.distance); - } - } - return result; -} - -glm::vec3 VoxelsScriptingInterface::getFaceVector(const QString& face) { - if (face == "MIN_X_FACE") { - return glm::vec3(-1, 0, 0); - } else if (face == "MAX_X_FACE") { - return glm::vec3(1, 0, 0); - } else if (face == "MIN_Y_FACE") { - return glm::vec3(0, -1, 0); - } else if (face == "MAX_Y_FACE") { - return glm::vec3(0, 1, 0); - } else if (face == "MIN_Z_FACE") { - return glm::vec3(0, 0, -1); - } else if (face == "MAX_Z_FACE") { - return glm::vec3(0, 0, 1); - } - return glm::vec3(0, 0, 0); //error case -} - -VoxelDetail VoxelsScriptingInterface::getVoxelEnclosingPoint(const glm::vec3& point) { - VoxelDetail result = { 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 0 }; - if (_tree) { - OctreeElement* element = _tree->getElementEnclosingPoint(point / (float)TREE_SCALE); - if (element) { - VoxelTreeElement* voxel = static_cast(element); - result.x = voxel->getCorner().x; - result.y = voxel->getCorner().y; - result.z = voxel->getCorner().z; - result.s = voxel->getScale(); - result.red = voxel->getColor()[0]; - result.green = voxel->getColor()[1]; - result.blue = voxel->getColor()[2]; - } - } - return result; -} - -VoxelDetail VoxelsScriptingInterface::getVoxelEnclosingPointBlocking(const glm::vec3& point) { - VoxelDetail result = { 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 0 }; - if (_tree) { - OctreeElement* element = _tree->getElementEnclosingPoint(point / (float)TREE_SCALE, Octree::Lock); - if (element) { - VoxelTreeElement* voxel = static_cast(element); - result.x = voxel->getCorner().x; - result.y = voxel->getCorner().y; - result.z = voxel->getCorner().z; - result.s = voxel->getScale(); - result.red = voxel->getColor()[0]; - result.green = voxel->getColor()[1]; - result.blue = voxel->getColor()[2]; - } - } - return result; -} - diff --git a/libraries/voxels/src/VoxelsScriptingInterface.h b/libraries/voxels/src/VoxelsScriptingInterface.h deleted file mode 100644 index 2e1fc2a8d5..0000000000 --- a/libraries/voxels/src/VoxelsScriptingInterface.h +++ /dev/null @@ -1,108 +0,0 @@ -// -// VoxelsScriptingInterface.h -// libraries/voxels/src -// -// Created by Stephen Birarda on 9/17/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelsScriptingInterface_h -#define hifi_VoxelsScriptingInterface_h - -#include - -#include -#include - -#include "VoxelConstants.h" -#include "VoxelEditPacketSender.h" -#include "VoxelTree.h" - -class QUndoStack; - -/// handles scripting of voxel commands from JS passed to assigned clients -class VoxelsScriptingInterface : public OctreeScriptingInterface { - Q_OBJECT -public: - VoxelsScriptingInterface() : _tree(NULL), _undoStack(NULL) {}; - VoxelEditPacketSender* getVoxelPacketSender() { return (VoxelEditPacketSender*)getPacketSender(); } - - virtual NodeType_t getServerNodeType() const { return NodeType::VoxelServer; } - virtual OctreeEditPacketSender* createPacketSender() { return new VoxelEditPacketSender(); } - void setVoxelTree(VoxelTree* tree) { _tree = tree; } - void setUndoStack(QUndoStack* undoStack) { _undoStack = undoStack; } - -public: - /// provide the world scale - Q_INVOKABLE const int getTreeScale() const { return TREE_SCALE; } - - /// checks the local voxel tree for a voxel at the specified location and scale - /// \param x the x-coordinate of the voxel (in meter units) - /// \param y the y-coordinate of the voxel (in meter units) - /// \param z the z-coordinate of the voxel (in meter units) - /// \param scale the scale of the voxel (in meter units) - Q_INVOKABLE VoxelDetail getVoxelAt(float x, float y, float z, float scale); - - /// queues the creation of a voxel which will be sent by calling process on the PacketSender - /// \param x the x-coordinate of the voxel (in meter units) - /// \param y the y-coordinate of the voxel (in meter units) - /// \param z the z-coordinate of the voxel (in meter units) - /// \param scale the scale of the voxel (in meter units) - /// \param red the R value for RGB color of voxel - /// \param green the G value for RGB color of voxel - /// \param blue the B value for RGB color of voxel - Q_INVOKABLE void setVoxelNonDestructive(float x, float y, float z, float scale, uchar red, uchar green, uchar blue); - - /// queues the destructive creation of a voxel which will be sent by calling process on the PacketSender - /// \param x the x-coordinate of the voxel (in meter units) - /// \param y the y-coordinate of the voxel (in meter units) - /// \param z the z-coordinate of the voxel (in meter units) - /// \param scale the scale of the voxel (in meter units) - /// \param red the R value for RGB color of voxel - /// \param green the G value for RGB color of voxel - /// \param blue the B value for RGB color of voxel - Q_INVOKABLE void setVoxel(float x, float y, float z, float scale, uchar red, uchar green, uchar blue); - - /// queues the deletion of a voxel, sent by calling process on the PacketSender - /// \param x the x-coordinate of the voxel (in meter units) - /// \param y the y-coordinate of the voxel (in meter units) - /// \param z the z-coordinate of the voxel (in meter units) - /// \param scale the scale of the voxel (in meter units) - Q_INVOKABLE void eraseVoxel(float x, float y, float z, float scale); - - /// If the scripting context has visible voxels, this will determine a ray intersection, the results - /// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate - /// will be false. - Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray); - - /// If the scripting context has visible voxels, this will determine a ray intersection, and will block in - /// order to return an accurate result - Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersectionBlocking(const PickRay& ray); - - /// returns a voxel space axis aligned vector for the face, useful in doing voxel math - Q_INVOKABLE glm::vec3 getFaceVector(const QString& face); - - /// checks the local voxel tree for the smallest voxel enclosing the point - /// \param point the x,y,z coordinates of the point (in meter units) - /// \return VoxelDetail - if no voxel encloses the point then VoxelDetail items will be 0 - Q_INVOKABLE VoxelDetail getVoxelEnclosingPoint(const glm::vec3& point); - - /// checks the local voxel tree for the smallest voxel enclosing the point and uses a blocking lock - /// \param point the x,y,z coordinates of the point (in meter units) - /// \return VoxelDetail - if no voxel encloses the point then VoxelDetail items will be 0 - Q_INVOKABLE VoxelDetail getVoxelEnclosingPointBlocking(const glm::vec3& point); - -private: - /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode - RayToVoxelIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType); - - void queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails); - VoxelTree* _tree; - QUndoStack* _undoStack; - QMutex _undoStackMutex; -}; - -#endif // hifi_VoxelsScriptingInterface_h From 141e23195873d0f7be08e7ed91050a2e43410211 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 18:41:56 -0800 Subject: [PATCH 03/27] more work on voxelEctomy --- assignment-client/src/Agent.cpp | 1 - .../octree/OctreeInboundPacketProcessor.cpp | 6 +- .../src/octree/OctreeInboundPacketProcessor.h | 6 +- .../src/octree/OctreeSendThread.cpp | 6 +- .../src/octree/OctreeSendThread.h | 4 +- assignment-client/src/octree/OctreeServer.cpp | 6 +- assignment-client/src/octree/OctreeServer.h | 2 +- .../src/octree/OctreeServerConsts.h | 2 +- interface/src/Application.cpp | 10 +-- interface/src/Menu.cpp | 68 ++++++++----------- interface/src/Menu.h | 22 ++---- interface/src/avatar/Avatar.cpp | 3 - interface/src/avatar/MyAvatar.cpp | 6 +- interface/src/ui/LodToolsDialog.cpp | 6 +- interface/src/ui/PreferencesDialog.cpp | 6 +- interface/src/ui/overlays/Overlays.cpp | 4 +- libraries/entities/src/EntityTreeElement.cpp | 4 +- libraries/octree/src/OctreeElement.cpp | 2 +- libraries/octree/src/OctreeElement.h | 6 +- 19 files changed, 71 insertions(+), 99 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 36166b7ac4..adde541504 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -25,7 +25,6 @@ #include #include #include -//#include #include // TODO: consider moving to scriptengine.h diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index e880615b71..a2ea44152b 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -148,7 +148,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin qDebug() << " --- inside while loop ---"; qDebug() << " maxSize=" << maxSize; qDebug("OctreeInboundPacketProcessor::processPacket() %c " - "packetData=%p packetLength=%d voxelData=%p atByte=%d maxSize=%d", + "packetData=%p packetLength=%d editData=%p atByte=%d maxSize=%d", packetType, packetData, packet.size(), editData, atByte, maxSize); } @@ -174,7 +174,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin processTime += thisProcessTime; lockWaitTime += thisLockWaitTime; - // skip to next voxel edit record in the packet + // skip to next edit record in the packet editData += editDataBytesRead; atByte += editDataBytesRead; @@ -188,7 +188,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin if (debugProcessPacket) { qDebug("OctreeInboundPacketProcessor::processPacket() DONE LOOPING FOR %c " - "packetData=%p packetLength=%d voxelData=%p atByte=%d", + "packetData=%p packetLength=%d editData=%p atByte=%d", packetType, packetData, packet.size(), editData, atByte); } diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.h b/assignment-client/src/octree/OctreeInboundPacketProcessor.h index 2fb83123c4..8f07f9d566 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.h +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.h @@ -5,7 +5,7 @@ // Created by Brad Hefta-Gaub on 8/21/13. // Copyright 2013 High Fidelity, Inc. // -// Threaded or non-threaded network packet processor for the voxel-server +// Threaded or non-threaded network packet processor for octree servers // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -53,7 +53,7 @@ typedef QHash::iterator NodeToSenderStatsMapIterator; typedef QHash::const_iterator NodeToSenderStatsMapConstIterator; -/// Handles processing of incoming network packets for the voxel-server. As with other ReceivedPacketProcessor classes +/// Handles processing of incoming network packets for the octee servers. As with other ReceivedPacketProcessor classes /// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket() class OctreeInboundPacketProcessor : public ReceivedPacketProcessor { Q_OBJECT @@ -89,7 +89,7 @@ private: private: void trackInboundPacket(const QUuid& nodeUUID, unsigned short int sequence, quint64 transitTime, - int voxelsInPacket, quint64 processTime, quint64 lockWaitTime); + int elementsInPacket, quint64 processTime, quint64 lockWaitTime); OctreeServer* _myServer; int _receivedPacketCount; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 46ea49e9a7..1a6e54b9f5 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -147,10 +147,10 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes int statsMessageLength = nodeData->stats.getStatsMessageLength(); int piggyBackSize = nodeData->getPacketLength() + statsMessageLength; - // If the size of the stats message and the voxel message will fit in a packet, then piggyback them + // If the size of the stats message and the octree message will fit in a packet, then piggyback them if (piggyBackSize < MAX_PACKET_SIZE) { - // copy voxel message to back of stats message + // copy octree message to back of stats message memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength()); statsMessageLength += nodeData->getPacketLength(); @@ -240,7 +240,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes } else { // If there's actually a packet waiting, then send it. if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) { - // just send the voxel packet + // just send the octree packet OctreeServer::didCallWriteDatagram(this); NodeList::getInstance()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index d8eed27802..d0507fc83d 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -5,7 +5,7 @@ // Created by Brad Hefta-Gaub on 8/21/13. // Copyright 2013 High Fidelity, Inc. // -// Threaded or non-threaded object for sending voxels to a client +// Threaded or non-threaded object for sending octree data packets to a client // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -22,7 +22,7 @@ class OctreeServer; -/// Threaded processor for sending voxel packets to a single client +/// Threaded processor for sending octree packets to a single client class OctreeSendThread : public GenericThread { Q_OBJECT public: diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 4be2c9873f..cb206f626e 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -358,7 +358,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url statsString += "Uptime: " + getUptime(); statsString += "\r\n\r\n"; - // display voxel file load time + // display octree file load time if (isInitialLoadComplete()) { if (isPersistEnabled()) { statsString += QString("%1 File Persist Enabled...\r\n").arg(getMyServerName()); @@ -373,7 +373,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url statsString += "\r\n"; } else { - statsString += "Voxels not yet loaded...\r\n"; + statsString += "Octree file not yet loaded...\r\n"; } statsString += "\r\n\r\n"; @@ -712,7 +712,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url } statsString += QString().sprintf("Element Node Memory Usage: %8.2f %s\r\n", - OctreeElement::getVoxelMemoryUsage() / memoryScale, memoryScaleLabel); + OctreeElement::getOctreeMemoryUsage() / memoryScale, memoryScaleLabel); statsString += QString().sprintf("Octcode Memory Usage: %8.2f %s\r\n", OctreeElement::getOctcodeMemoryUsage() / memoryScale, memoryScaleLabel); statsString += QString().sprintf("External Children Memory Usage: %8.2f %s\r\n", diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 4999594a98..a467a8a650 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -121,7 +121,7 @@ public: void forceNodeShutdown(SharedNodePointer node); public slots: - /// runs the voxel server assignment + /// runs the octree server assignment void run(); void nodeAdded(SharedNodePointer node); void nodeKilled(SharedNodePointer node); diff --git a/assignment-client/src/octree/OctreeServerConsts.h b/assignment-client/src/octree/OctreeServerConsts.h index a10c81494c..02f59f3802 100644 --- a/assignment-client/src/octree/OctreeServerConsts.h +++ b/assignment-client/src/octree/OctreeServerConsts.h @@ -19,6 +19,6 @@ const int MAX_FILENAME_LENGTH = 1024; const int INTERVALS_PER_SECOND = 60; const int OCTREE_SEND_INTERVAL_USECS = (1000 * 1000)/INTERVALS_PER_SECOND; -const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels +const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for sending octree elements #endif // hifi_OctreeServerConsts_h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 40b6c4003a..89fcbeceb7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2268,7 +2268,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); _octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); - _octreeQuery.setOctreeSizeScale(Menu::getInstance()->getVoxelSizeScale()); + _octreeQuery.setOctreeSizeScale(Menu::getInstance()->getOctreeSizeScale()); _octreeQuery.setBoundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust()); unsigned char queryPacket[MAX_PACKET_SIZE]; @@ -2321,7 +2321,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node int perServerPPS = 0; const int SMALL_BUDGET = 10; int perUnknownServer = SMALL_BUDGET; - int totalPPS = Menu::getInstance()->getMaxVoxelPacketsPerSecond(); + int totalPPS = Menu::getInstance()->getMaxOctreePacketsPerSecond(); // determine PPS based on number of servers if (inViewServers >= 1) { @@ -2669,7 +2669,7 @@ bool Application::shouldRenderMesh(float largestDimension, float distanceToCamer } float Application::getSizeScale() const { - return Menu::getInstance()->getVoxelSizeScale(); + return Menu::getInstance()->getOctreeSizeScale(); } int Application::getBoundaryLevelAdjust() const { @@ -3457,7 +3457,7 @@ void Application::nodeKilled(SharedNodePointer node) { rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s); // Add the jurisditionDetails object to the list of "fade outs" - if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnVoxelServerChanges)) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnOctreeServerChanges)) { VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE); fade.voxelDetails = rootDetails; const float slightly_smaller = 0.99f; @@ -3543,7 +3543,7 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin qPrintable(serverType), rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s); // Add the jurisditionDetails object to the list of "fade outs" - if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnVoxelServerChanges)) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnOctreeServerChanges)) { VoxelFade fade(VoxelFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE); fade.voxelDetails = rootDetails; const float slightly_smaller = 0.99f; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f7e8df90e4..fa447a2d30 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -108,8 +108,7 @@ Menu::Menu() : #if defined(Q_OS_MAC) || defined(Q_OS_WIN) _speechRecognizer(), #endif - _maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM), - _voxelSizeScale(DEFAULT_OCTREE_SIZE_SCALE), + _octreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE), _oculusUIAngularSize(DEFAULT_OCULUS_UI_ANGULAR_SIZE), _sixenseReticleMoveSpeed(DEFAULT_SIXENSE_RETICLE_MOVE_SPEED), _invertSixenseButtons(DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS), @@ -118,7 +117,7 @@ Menu::Menu() : _avatarLODIncreaseFPS(ADJUST_LOD_UP_FPS), _avatarLODDistanceMultiplier(DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER), _boundaryLevelAdjust(0), - _maxVoxelPacketsPerSecond(DEFAULT_MAX_VOXEL_PPS), + _maxOctreePacketsPerSecond(DEFAULT_MAX_VOXEL_PPS), _lastAdjust(usecTimestampNow()), _lastAvatarDetailDrop(usecTimestampNow()), _fpsAverage(FIVE_SECONDS_OF_FRAMES), @@ -315,8 +314,6 @@ Menu::Menu() : avatar, SLOT(onToggleRagdoll())); addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithAvatars, 0, true, avatar, SLOT(updateCollisionGroups())); - addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithVoxels, - 0, false, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithEnvironment, 0, false, avatar, SLOT(updateCollisionGroups())); @@ -390,6 +387,9 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Avatars, 0, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Entities, 0, true); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DontFadeOnOctreeServerChanges); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DisableAutoAdjustLOD); QMenu* shadowMenu = renderOptionsMenu->addMenu("Shadows"); QActionGroup* shadowGroup = new QActionGroup(shadowMenu); @@ -424,12 +424,6 @@ Menu::Menu() : resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false)); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, Qt::Key_Asterisk, true); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, - MenuOption::Voxels, - Qt::SHIFT | Qt::Key_V, - true, - appInstance, - SLOT(setRenderVoxels(bool))); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true, DependencyManager::get().data(), SLOT(toggleGlowEffect(bool))); @@ -456,12 +450,6 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false); - QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels"); - addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); - addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); - addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontFadeOnVoxelServerChanges); - addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DisableAutoAdjustLOD); - QMenu* metavoxelOptionsMenu = developerMenu->addMenu("Metavoxels"); addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::DisplayHermiteData, 0, false, Application::getInstance()->getMetavoxels(), SLOT(refreshVoxelData())); @@ -671,9 +659,8 @@ void Menu::loadSettings(QSettings* settings) { _realWorldFieldOfView = loadSetting(settings, "realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES); _faceshiftEyeDeflection = loadSetting(settings, "faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION); _faceshiftHostname = settings->value("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME).toString(); - _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); - _maxVoxelPacketsPerSecond = loadSetting(settings, "maxVoxelsPPS", DEFAULT_MAX_VOXEL_PPS); - _voxelSizeScale = loadSetting(settings, "voxelSizeScale", DEFAULT_OCTREE_SIZE_SCALE); + _maxOctreePacketsPerSecond = loadSetting(settings, "maxOctreePPS", DEFAULT_MAX_OCTREE_PPS); + _octreeSizeScale = loadSetting(settings, "octreeSizeScale", DEFAULT_OCTREE_SIZE_SCALE); _automaticAvatarLOD = settings->value("automaticAvatarLOD", true).toBool(); _avatarLODDecreaseFPS = loadSetting(settings, "avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS); _avatarLODIncreaseFPS = loadSetting(settings, "avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS); @@ -738,9 +725,8 @@ void Menu::saveSettings(QSettings* settings) { settings->setValue("fieldOfView", _fieldOfView); settings->setValue("faceshiftEyeDeflection", _faceshiftEyeDeflection); settings->setValue("faceshiftHostname", _faceshiftHostname); - settings->setValue("maxVoxels", _maxVoxels); - settings->setValue("maxVoxelsPPS", _maxVoxelPacketsPerSecond); - settings->setValue("voxelSizeScale", _voxelSizeScale); + settings->setValue("maxOctreePPS", _maxOctreePacketsPerSecond); + settings->setValue("octreeSizeScale", _octreeSizeScale); settings->setValue("automaticAvatarLOD", _automaticAvatarLOD); settings->setValue("avatarLODDecreaseFPS", _avatarLODDecreaseFPS); settings->setValue("avatarLODIncreaseFPS", _avatarLODIncreaseFPS); @@ -1423,8 +1409,8 @@ QString Menu::getLODFeedbackText() { } // distance feedback - float voxelSizeScale = getVoxelSizeScale(); - float relativeToDefault = voxelSizeScale / DEFAULT_OCTREE_SIZE_SCALE; + float octreeSizeScale = getOctreeSizeScale(); + float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE; QString result; if (relativeToDefault > 1.01) { result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback); @@ -1475,29 +1461,29 @@ void Menu::autoAdjustLOD(float currentFPS) { quint64 elapsed = now - _lastAdjust; if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS - && _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { + && _octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { - _voxelSizeScale *= ADJUST_LOD_DOWN_BY; + _octreeSizeScale *= ADJUST_LOD_DOWN_BY; - if (_voxelSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { - _voxelSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; + if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { + _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; } changed = true; _lastAdjust = now; qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() - << "_voxelSizeScale=" << _voxelSizeScale; + << "_octreeSizeScale=" << _octreeSizeScale; } if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS - && _voxelSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { - _voxelSizeScale *= ADJUST_LOD_UP_BY; - if (_voxelSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { - _voxelSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; + && _octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { + _octreeSizeScale *= ADJUST_LOD_UP_BY; + if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { + _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; } changed = true; _lastAdjust = now; qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() - << "_voxelSizeScale=" << _voxelSizeScale; + << "_octreeSizeScale=" << _octreeSizeScale; } if (changed) { @@ -1514,8 +1500,8 @@ void Menu::resetLODAdjust() { _lastAvatarDetailDrop = _lastAdjust = usecTimestampNow(); } -void Menu::setVoxelSizeScale(float sizeScale) { - _voxelSizeScale = sizeScale; +void Menu::setOctreeSizeScale(float sizeScale) { + _octreeSizeScale = sizeScale; _shouldRenderTableNeedsRebuilding = true; bumpSettings(); } @@ -1526,14 +1512,14 @@ void Menu::setBoundaryLevelAdjust(int boundaryLevelAdjust) { bumpSettings(); } -// TODO: This is essentially the same logic used to render voxels, but since models are more detailed then voxels +// TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells // I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it. bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) { - const float voxelToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it. - float voxelSizeScale = getVoxelSizeScale(); + const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it. + float octreeSizeScale = getOctreeSizeScale(); int boundaryLevelAdjust = getBoundaryLevelAdjust(); float maxScale = (float)TREE_SCALE; - float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, voxelSizeScale) / voxelToMeshRatio; + float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio; if (_shouldRenderTableNeedsRebuilding) { _shouldRenderTable.clear(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3fa3d7372d..3655735c14 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -122,7 +122,6 @@ public: OctreeStatsDialog* getOctreeStatsDialog() const { return _octreeStatsDialog; } LodToolsDialog* getLodToolsDialog() const { return _lodToolsDialog; } HMDToolsDialog* getHMDToolsDialog() const { return _hmdToolsDialog; } - int getMaxVoxels() const { return _maxVoxels; } bool getShadowsEnabled() const; @@ -132,8 +131,8 @@ public: QString getLODFeedbackText(); void autoAdjustLOD(float currentFPS); void resetLODAdjust(); - void setVoxelSizeScale(float sizeScale); - float getVoxelSizeScale() const { return _voxelSizeScale; } + void setOctreeSizeScale(float sizeScale); + float getOctreeSizeScale() const { return _octreeSizeScale; } void setAutomaticAvatarLOD(bool automaticAvatarLOD) { _automaticAvatarLOD = automaticAvatarLOD; bumpSettings(); } bool getAutomaticAvatarLOD() const { return _automaticAvatarLOD; } void setAvatarLODDecreaseFPS(float avatarLODDecreaseFPS) { _avatarLODDecreaseFPS = avatarLODDecreaseFPS; bumpSettings(); } @@ -152,8 +151,8 @@ public: #endif // User Tweakable PPS from Voxel Server - int getMaxVoxelPacketsPerSecond() const { return _maxVoxelPacketsPerSecond; } - void setMaxVoxelPacketsPerSecond(int maxVoxelPacketsPerSecond) { _maxVoxelPacketsPerSecond = maxVoxelPacketsPerSecond; bumpSettings(); } + int getMaxOctreePacketsPerSecond() const { return _maxOctreePacketsPerSecond; } + void setMaxOctreePacketsPerSecond(int value) { _maxOctreePacketsPerSecond = value; bumpSettings(); } QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu, const QString& actionName, @@ -292,8 +291,7 @@ private: #if defined(Q_OS_MAC) || defined(Q_OS_WIN) SpeechRecognizer _speechRecognizer; #endif - int _maxVoxels; - float _voxelSizeScale; + float _octreeSizeScale; float _oculusUIAngularSize; float _sixenseReticleMoveSpeed; bool _invertSixenseButtons; @@ -302,7 +300,7 @@ private: float _avatarLODIncreaseFPS; float _avatarLODDistanceMultiplier; int _boundaryLevelAdjust; - int _maxVoxelPacketsPerSecond; + int _maxOctreePacketsPerSecond; QString replaceLastOccurrence(QChar search, QChar replace, QString string); quint64 _lastAdjust; quint64 _lastAvatarDetailDrop; @@ -356,14 +354,12 @@ namespace MenuOption { const QString CollideAsRagdoll = "Collide With Self (Ragdoll)"; const QString CollideWithAvatars = "Collide With Other Avatars"; const QString CollideWithEnvironment = "Collide With World Boundaries"; - const QString CollideWithVoxels = "Collide With Voxels"; const QString Collisions = "Collisions"; const QString Console = "Console..."; const QString ControlWithSpeech = "Control With Speech"; const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene"; const QString DontDoPrecisionPicking = "Don't Do Precision Picking"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; - const QString DecreaseVoxelSize = "Decrease Voxel Size"; const QString DisableActivityLogger = "Disable Activity Logger"; const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD"; const QString DisableLightEntities = "Disable Light Entities"; @@ -377,7 +373,7 @@ namespace MenuOption { const QString DisplayModelElementChildProxies = "Display Model Element Children"; const QString DisplayModelElementProxy = "Display Model Element Bounds"; const QString DisplayTimingDetails = "Display Timing Details"; - const QString DontFadeOnVoxelServerChanges = "Don't Fade In/Out on Voxel Server Changes"; + const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes"; const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoServerAudio = "Echo Server Audio"; const QString EditEntitiesHelp = "Edit Entities Help..."; @@ -403,7 +399,6 @@ namespace MenuOption { const QString HeadMouse = "Head Mouse"; const QString HMDTools = "HMD Tools"; const QString IncreaseAvatarSize = "Increase Avatar Size"; - const QString IncreaseVoxelSize = "Increase Voxel Size"; const QString KeyboardMotorControl = "Enable Keyboard Motor Control"; const QString LeapMotionOnHMD = "Leap Motion on HMD"; const QString LoadScript = "Open and Run Script File..."; @@ -484,9 +479,6 @@ namespace MenuOption { const QString UploadSkeleton = "Upload Skeleton Model"; const QString UserInterface = "User Interface"; const QString Visage = "Visage"; - const QString VoxelMode = "Cycle Voxel Mode"; - const QString Voxels = "Voxels"; - const QString VoxelTextures = "Voxel Textures"; const QString WalletPrivateKey = "Wallet Private Key..."; const QString Wireframe = "Wireframe"; } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6a659abf93..0b5dd47152 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1043,9 +1043,6 @@ void Avatar::updateCollisionGroups() { if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) { _collisionGroups |= COLLISION_GROUP_AVATARS; } - if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) { - _collisionGroups |= COLLISION_GROUP_VOXELS; - } } void Avatar::setScale(float scale) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f34f5f2c67..6128488628 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1924,8 +1924,7 @@ void MyAvatar::updateMotionBehavior() { if (menu->isOptionChecked(MenuOption::StandOnNearbyFloors)) { _motionBehaviors |= AVATAR_MOTION_STAND_ON_NEARBY_FLOORS; // standing on floors requires collision with voxels - _collisionGroups |= COLLISION_GROUP_VOXELS; - menu->setIsOptionChecked(MenuOption::CollideWithVoxels, true); + // TODO: determine what to do with this now that voxels are gone } else { _motionBehaviors &= ~AVATAR_MOTION_STAND_ON_NEARBY_FLOORS; } @@ -1978,7 +1977,8 @@ void MyAvatar::setCollisionGroups(quint32 collisionGroups) { Menu* menu = Menu::getInstance(); menu->setIsOptionChecked(MenuOption::CollideWithEnvironment, (bool)(_collisionGroups & COLLISION_GROUP_ENVIRONMENT)); menu->setIsOptionChecked(MenuOption::CollideWithAvatars, (bool)(_collisionGroups & COLLISION_GROUP_AVATARS)); - menu->setIsOptionChecked(MenuOption::CollideWithVoxels, (bool)(_collisionGroups & COLLISION_GROUP_VOXELS)); + + // TODO: what to do about this now that voxels are gone if (! (_collisionGroups & COLLISION_GROUP_VOXELS)) { // no collision with voxels --> disable standing on floors _motionBehaviors &= ~AVATAR_MOTION_STAND_ON_NEARBY_FLOORS; diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp index 6df5121104..388d360dc2 100644 --- a/interface/src/ui/LodToolsDialog.cpp +++ b/interface/src/ui/LodToolsDialog.cpp @@ -47,7 +47,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : _lodSize->setTickPosition(QSlider::TicksBelow); _lodSize->setFixedWidth(SLIDER_WIDTH); _lodSize->setPageStep(PAGE_STEP_LOD_SIZE); - int sliderValue = Menu::getInstance()->getVoxelSizeScale() / TREE_SCALE; + int sliderValue = Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE; _lodSize->setValue(sliderValue); form->addRow("LOD Size Scale:", _lodSize); connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int))); @@ -116,7 +116,7 @@ LodToolsDialog::~LodToolsDialog() { } void LodToolsDialog::reloadSliders() { - _lodSize->setValue(Menu::getInstance()->getVoxelSizeScale() / TREE_SCALE); + _lodSize->setValue(Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE); _boundaryLevelAdjust->setValue(Menu::getInstance()->getBoundaryLevelAdjust()); _feedback->setText(Menu::getInstance()->getLODFeedbackText()); } @@ -156,7 +156,7 @@ void LodToolsDialog::updateAvatarLODValues() { void LodToolsDialog::sizeScaleValueChanged(int value) { float realValue = value * TREE_SCALE; - Menu::getInstance()->setVoxelSizeScale(realValue); + Menu::getInstance()->setOctreeSizeScale(realValue); _feedback->setText(Menu::getInstance()->getLODFeedbackText()); } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index b00d697a1c..21787c56e3 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -144,9 +144,7 @@ void PreferencesDialog::loadPreferences() { ui.avatarScaleSpin->setValue(myAvatar->getScale()); - ui.maxVoxelsSpin->setValue(menuInstance->getMaxVoxels()); - - ui.maxVoxelsPPSSpin->setValue(menuInstance->getMaxVoxelPacketsPerSecond()); + ui.maxVoxelsPPSSpin->setValue(menuInstance->getMaxOctreePacketsPerSecond()); ui.oculusUIAngularSizeSpin->setValue(menuInstance->getOculusUIAngularSize()); @@ -227,7 +225,7 @@ void PreferencesDialog::savePreferences() { Menu::getInstance()->setFaceshiftHostname(ui.faceshiftHostnameEdit->text()); - Menu::getInstance()->setMaxVoxelPacketsPerSecond(ui.maxVoxelsPPSSpin->value()); + Menu::getInstance()->setMaxOctreePacketsPerSecond(ui.maxVoxelsPPSSpin->value()); Menu::getInstance()->setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value()); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 46be62649b..19f2bda526 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -85,7 +85,7 @@ void Overlays::render2D() { QReadLocker lock(&_lock); RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(), - Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), + Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; foreach(Overlay* thisOverlay, _overlays2D) { @@ -107,7 +107,7 @@ void Overlays::render3D(bool drawFront, RenderArgs::RenderMode renderMode, Rende float myAvatarScale = 1.0f; RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(), - Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), + Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 55693b6ff9..1c8b62de16 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -25,7 +25,7 @@ EntityTreeElement::EntityTreeElement(unsigned char* octalCode) : OctreeElement() }; EntityTreeElement::~EntityTreeElement() { - _voxelMemoryUsage -= sizeof(EntityTreeElement); + _octreeMemoryUsage -= sizeof(EntityTreeElement); delete _entityItems; _entityItems = NULL; } @@ -43,7 +43,7 @@ OctreeElement* EntityTreeElement::createNewElement(unsigned char* octalCode) { void EntityTreeElement::init(unsigned char* octalCode) { OctreeElement::init(octalCode); _entityItems = new QList; - _voxelMemoryUsage += sizeof(EntityTreeElement); + _octreeMemoryUsage += sizeof(EntityTreeElement); } EntityTreeElement* EntityTreeElement::addChildAtIndex(int index) { diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index c6938ff1f6..e74b6619bd 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -29,7 +29,7 @@ #include "Octree.h" #include "SharedUtil.h" -quint64 OctreeElement::_voxelMemoryUsage = 0; +quint64 OctreeElement::_octreeMemoryUsage = 0; quint64 OctreeElement::_octcodeMemoryUsage = 0; quint64 OctreeElement::_externalChildrenMemoryUsage = 0; quint64 OctreeElement::_voxelNodeCount = 0; diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 3bd13a2f3c..434342372f 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -192,10 +192,10 @@ public: static unsigned long getInternalNodeCount() { return _voxelNodeCount - _voxelNodeLeafCount; } static unsigned long getLeafNodeCount() { return _voxelNodeLeafCount; } - static quint64 getVoxelMemoryUsage() { return _voxelMemoryUsage; } + static quint64 getOctreeMemoryUsage() { return _octreeMemoryUsage; } static quint64 getOctcodeMemoryUsage() { return _octcodeMemoryUsage; } static quint64 getExternalChildrenMemoryUsage() { return _externalChildrenMemoryUsage; } - static quint64 getTotalMemoryUsage() { return _voxelMemoryUsage + _octcodeMemoryUsage + _externalChildrenMemoryUsage; } + static quint64 getTotalMemoryUsage() { return _octreeMemoryUsage + _octcodeMemoryUsage + _externalChildrenMemoryUsage; } static quint64 getGetChildAtIndexTime() { return _getChildAtIndexTime; } static quint64 getGetChildAtIndexCalls() { return _getChildAtIndexCalls; } @@ -334,7 +334,7 @@ protected: static quint64 _voxelNodeCount; static quint64 _voxelNodeLeafCount; - static quint64 _voxelMemoryUsage; + static quint64 _octreeMemoryUsage; static quint64 _octcodeMemoryUsage; static quint64 _externalChildrenMemoryUsage; From 49d8f2b2f507cc161dafb5d45c1ad36d368eec79 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 18:52:33 -0800 Subject: [PATCH 04/27] more work on voxelEctomy --- interface/src/Camera.cpp | 1 - interface/src/DatagramProcessor.cpp | 20 +------- interface/src/Menu.cpp | 2 +- interface/src/Util.cpp | 1 - interface/src/avatar/Head.h | 2 +- interface/src/devices/SixenseManager.cpp | 1 - interface/src/ui/HMDToolsDialog.cpp | 2 - interface/src/ui/LodToolsDialog.cpp | 2 - interface/src/voxels/VoxelFade.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 1 - libraries/script-engine/src/ScriptEngine.cpp | 1 - libraries/voxels/src/VoxelConstants.h | 50 -------------------- libraries/voxels/src/VoxelDetail.h | 1 - 13 files changed, 5 insertions(+), 81 deletions(-) delete mode 100644 libraries/voxels/src/VoxelConstants.h diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index b2fd30a1a6..313b7b7774 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include "Application.h" diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 1b7e27776e..4db9a295c2 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -81,31 +81,15 @@ void DatagramProcessor::processDatagrams() { break; case PacketTypeEntityData: case PacketTypeEntityErase: - case PacketTypeVoxelData: - case PacketTypeVoxelErase: case PacketTypeOctreeStats: case PacketTypeEnvironmentData: { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::networkReceive()... _octreeProcessor.queueReceivedPacket()"); - bool wantExtraDebugging = application->getLogger()->extraDebugging(); - if (wantExtraDebugging && packetTypeForPacket(incomingPacket) == PacketTypeVoxelData) { - int numBytesPacketHeader = numBytesForPacketHeader(incomingPacket); - unsigned char* dataAt = reinterpret_cast(incomingPacket.data()) + numBytesPacketHeader; - dataAt += sizeof(OCTREE_PACKET_FLAGS); - OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt); - dataAt += sizeof(OCTREE_PACKET_SEQUENCE); - OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt); - dataAt += sizeof(OCTREE_PACKET_SENT_TIME); - OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); - int flightTime = arrivedAt - sentAt; - - qDebug("got an Octree data or erase message, sequence:%d flightTime:%d", sequence, flightTime); - } - + SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket); if (matchedNode) { - // add this packet to our list of voxel packets and process them on the voxel processing + // add this packet to our list of octree packets and process them on the octree data processing application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket); } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index fa447a2d30..06fa152932 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -117,7 +117,7 @@ Menu::Menu() : _avatarLODIncreaseFPS(ADJUST_LOD_UP_FPS), _avatarLODDistanceMultiplier(DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER), _boundaryLevelAdjust(0), - _maxOctreePacketsPerSecond(DEFAULT_MAX_VOXEL_PPS), + _maxOctreePacketsPerSecond(DEFAULT_MAX_OCTREE_PPS), _lastAdjust(usecTimestampNow()), _lastAvatarDetailDrop(usecTimestampNow()), _fpsAverage(FIVE_SECONDS_OF_FRAMES), diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 45a7dabb40..7b79024479 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -25,7 +25,6 @@ #include #include "InterfaceConfig.h" -#include "VoxelConstants.h" #include "world.h" #include "Application.h" diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 57d74adaf0..6ae0d7c728 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -18,7 +18,7 @@ #include -#include +#include // for IDENTITY_* #include "FaceModel.h" #include "InterfaceConfig.h" diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 5fb4a71091..690a01a77e 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -508,7 +508,6 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { QMouseEvent mouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton, 0); //Only send the mouse event if the opposite left button isnt held down. - //This is specifically for edit voxels if (triggerButton == Qt::LeftButton) { if (!_triggerPressed[(int)(!index)]) { application->mouseMoveEvent(&mouseEvent, deviceID); diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 23d6d5df2f..632cc8979f 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -19,8 +19,6 @@ #include #include -#include - #include "MainWindow.h" #include "Menu.h" #include "devices/OculusManager.h" diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp index 388d360dc2..d9f2d788cd 100644 --- a/interface/src/ui/LodToolsDialog.cpp +++ b/interface/src/ui/LodToolsDialog.cpp @@ -20,8 +20,6 @@ #include #include -#include - #include "Menu.h" #include "ui/LodToolsDialog.h" diff --git a/interface/src/voxels/VoxelFade.cpp b/interface/src/voxels/VoxelFade.cpp index 7bb3be67ab..aeb44e67ae 100644 --- a/interface/src/voxels/VoxelFade.cpp +++ b/interface/src/voxels/VoxelFade.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include "Application.h" #include "VoxelFade.h" diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index a5ee3f7fff..d5b6c29362 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include "AvatarData.h" diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index c7be5a973b..fc9cdc5430 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -28,7 +28,6 @@ #include #include #include -//#include #include "AnimationObject.h" #include "ArrayBufferViewClass.h" diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h deleted file mode 100644 index 34a7667273..0000000000 --- a/libraries/voxels/src/VoxelConstants.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// VoxelConstants.h -// libraries/voxels/src -// -// Created by Brad Hefta-Gaub on 4/29/13. -// Copyright 2013 High Fidelity, Inc. -// -// Various important constants used throughout the system related to voxels -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelConstants_h -#define hifi_VoxelConstants_h - -#include -#include -#include -#include -#include -#include -#include - -// this is where the coordinate system is represented - -const int DEFAULT_MAX_VOXELS_PER_SYSTEM = 500000; -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; - -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; - -const float SIXTY_FPS_IN_MILLISECONDS = 1000.0f / 60.0f; -const float VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0f; // once a second is fine - -const quint64 CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS = 1000 * 5; // 1 packet every 50 milliseconds - - -const int DEFAULT_MAX_VOXEL_PPS = 600; // the default maximum PPS we think a voxel server should send to a client - -#endif // hifi_VoxelConstants_h diff --git a/libraries/voxels/src/VoxelDetail.h b/libraries/voxels/src/VoxelDetail.h index 5ef7f0ff4e..1e53fd33d2 100644 --- a/libraries/voxels/src/VoxelDetail.h +++ b/libraries/voxels/src/VoxelDetail.h @@ -17,7 +17,6 @@ #include #include #include -#include "VoxelConstants.h" struct VoxelDetail { float x; From 278ed96f14ce7c828359db92e52663b5b6b93388 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 18:54:53 -0800 Subject: [PATCH 05/27] more work on voxelEctomy --- libraries/octree/src/Octree.cpp | 2 - libraries/voxels/src/Tags.cpp | 419 --------------------------- libraries/voxels/src/Tags.h | 183 ------------ libraries/voxels/src/VoxelDetail.cpp | 122 -------- libraries/voxels/src/VoxelDetail.h | 67 ----- 5 files changed, 793 deletions(-) delete mode 100644 libraries/voxels/src/Tags.cpp delete mode 100644 libraries/voxels/src/Tags.h delete mode 100644 libraries/voxels/src/VoxelDetail.cpp delete mode 100644 libraries/voxels/src/VoxelDetail.h diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 0c92125b53..e41730e63c 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -29,8 +29,6 @@ #include #include -//#include "Tags.h" - #include "CoverageMap.h" #include "OctreeConstants.h" #include "OctreeElementBag.h" diff --git a/libraries/voxels/src/Tags.cpp b/libraries/voxels/src/Tags.cpp deleted file mode 100644 index 003e9ae80d..0000000000 --- a/libraries/voxels/src/Tags.cpp +++ /dev/null @@ -1,419 +0,0 @@ -// -// Tags.cpp -// libraries/voxels/src -// -// Created by Clement Brisset on 7/3/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include -#include - -#include "Tags.h" - -Tag::Tag(int tagId, std::stringstream &ss) : _tagId(tagId) { - int size = ss.get() << 8 | ss.get(); - - _name.clear(); - for (int i = 0; i < size; ++i) { _name += ss.get(); - } -} - -Tag* Tag::readTag(int tagId, std::stringstream &ss) { - - switch (tagId) { - case TAG_Byte: - return new TagByte(ss); - case TAG_Short: - return new TagShort(ss); - case TAG_Int: - return new TagInt(ss); - case TAG_Long: - return new TagLong(ss); - case TAG_Float: - return new TagFloat(ss); - case TAG_Double: - return new TagDouble(ss); - case TAG_Byte_Array: - return new TagByteArray(ss); - case TAG_String: - return new TagString(ss); - case TAG_List: - return new TagList(ss); - case TAG_Compound: - return new TagCompound(ss); - case TAG_Int_Array: - return new TagIntArray(ss); - default: - return NULL; - } -} - -TagByte::TagByte(std::stringstream &ss) : Tag(TAG_Byte, ss) { - _data = ss.get(); -} - -TagShort::TagShort(std::stringstream &ss) : Tag(TAG_Short, ss) { - _data = ss.get() << 8 | ss.get(); -} - -TagInt::TagInt(std::stringstream &ss) : Tag(TAG_Int, ss) { - _data = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get(); -} - -TagLong::TagLong(std::stringstream &ss) : Tag(TAG_Long, ss) { - _data = (((int64_t) ss.get()) << 56 | ((int64_t) ss.get()) << 48 - |((int64_t) ss.get()) << 40 | ((int64_t) ss.get()) << 32 - | ss.get() << 24 | ss.get() << 16 - | ss.get() << 8 | ss.get()); -} - -// We don't need Float and double, so we just ignore the bytes -TagFloat::TagFloat(std::stringstream &ss) : Tag(TAG_Float, ss) { - ss.seekg(4, ss.cur); -} - -TagDouble::TagDouble(std::stringstream &ss) : Tag(TAG_Double, ss) { - ss.seekg(8, ss.cur); -} - -TagByteArray::TagByteArray(std::stringstream &ss) : Tag(TAG_Byte_Array, ss) { - _size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get(); - - _data = new char[_size]; - for (int i = 0; i < _size; ++i) { - _data[i] = ss.get(); - } -} - -TagString::TagString(std::stringstream &ss) : Tag(TAG_String, ss) { - _size = ss.get() << 8 | ss.get(); - - for (int i = 0; i < _size; ++i) { - _data += ss.get(); - } -} - -TagList::TagList(std::stringstream &ss) : - Tag(TAG_List, ss) { - _tagId = ss.get(); - _size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get(); - - for (int i = 0; i < _size; ++i) { - ss.putback(0); - ss.putback(0); - _data.push_back(readTag(_tagId, ss)); - } -} - -TagList::~TagList() { - while (!_data.empty()) { - delete _data.back(); - _data.pop_back(); - } -} - -TagCompound::TagCompound(std::stringstream &ss) : - Tag(TAG_Compound, ss), - _size(0), - _width(0), - _length(0), - _height(0), - _blocksData(NULL), - _blocksId(NULL) -{ - int tagId; - - while (TAG_End != (tagId = ss.get())) { - _data.push_back(readTag(tagId, ss)); - ++_size; - - if (NULL == _data.back()) { - _blocksId = NULL; - _blocksData = NULL; - return; - } else if (TAG_Short == tagId) { - if ("Width" == _data.back()->getName()) { - _width = ((TagShort*) _data.back())->getData(); - } else if ("Height" == _data.back()->getName()) { - _height = ((TagShort*) _data.back())->getData(); - } else if ("Length" == _data.back()->getName()) { - _length = ((TagShort*) _data.back())->getData(); - } - } else if (TAG_Byte_Array == tagId) { - if ("Blocks" == _data.back()->getName()) { - _blocksId = ((TagByteArray*) _data.back())->getData(); - } else if ("Data" == _data.back()->getName()) { - _blocksData = ((TagByteArray*) _data.back())->getData(); - } - } - } -} - -TagCompound::~TagCompound() { - while (!_data.empty()) { - delete _data.back(); - _data.pop_back(); - } -} - -TagIntArray::TagIntArray(std::stringstream &ss) : Tag(TAG_Int_Array, ss) { - _size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get(); - - _data = new int[_size]; - for (int i = 0; i < _size; ++i) { - _data[i] = ss.get(); - } -} - -int retrieveData(std::string filename, std::stringstream &ss) { - std::ifstream file(filename.c_str(), std::ios::binary); - - int type = file.peek(); - if (type == 0x0A) { - ss.flush(); - std::copy(std::istreambuf_iterator(file), - std::istreambuf_iterator(), - std::ostreambuf_iterator(ss)); - return 0; - } - - if (type == 0x1F) { - int ret = ungzip(file, ss); - return ret; - } - - std::cerr << "[ERROR] Schematic compression type not recognize : " << type << std::endl; - return 1; -} - -int ungzip(std::ifstream &file, std::stringstream &ss) { - std::string gzipedBytes; - gzipedBytes.clear(); - ss.flush(); - - while (!file.eof()) { - gzipedBytes += (char) file.get(); - } - file.close(); - - if (gzipedBytes.size() == 0) { - ss << gzipedBytes; - return 0; - } - - unsigned int full_length = gzipedBytes.size(); - unsigned int half_length = gzipedBytes.size()/2; - unsigned int uncompLength = full_length; - - char* uncomp = (char*) calloc(sizeof(char), uncompLength); - - z_stream strm; - strm.next_in = (Bytef *) gzipedBytes.c_str(); - strm.avail_in = full_length; - strm.total_out = 0; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - - bool done = false; - - if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) { - free(uncomp); - return 1; - } - - while (!done) { - // If our output buffer is too small - if (strm.total_out >= uncompLength) { - // Increase size of output buffer - char* uncomp2 = (char*) calloc(sizeof(char), uncompLength + half_length); - memcpy(uncomp2, uncomp, uncompLength); - uncompLength += half_length; - free(uncomp); - uncomp = uncomp2; - } - - strm.next_out = (Bytef *) (uncomp + strm.total_out); - strm.avail_out = uncompLength - strm.total_out; - - // Inflate another chunk. - int err = inflate (&strm, Z_SYNC_FLUSH); - if (err == Z_STREAM_END) { - done = true; - } else if (err != Z_OK) { - break; - } - } - - if (inflateEnd (&strm) != Z_OK) { - free(uncomp); - return 1; - } - - for (size_t i = 0; i < strm.total_out; ++i) { - ss << uncomp[i]; - } - free(uncomp); - - return 0; -} - - -void computeBlockColor(int id, int data, int& red, int& green, int& blue, int& create) { - - switch (id) { - case 1: - case 14: - case 15: - case 16: - case 21: - case 56: - case 73: - case 74: - case 97: - case 129: red = 128; green = 128; blue = 128; break; - case 2: red = 77; green = 117; blue = 66; break; - case 3: - case 60: red = 116; green = 83; blue = 56; break; - case 4: red = 71; green = 71; blue = 71; break; - case 5: - case 125: red = 133; green = 94; blue = 62; break; - case 7: red = 35; green = 35; blue = 35; break; - case 8: - case 9: red = 100; green = 109; blue = 185; break; - case 10: - case 11: red = 192; green = 64; blue = 8; break; - case 12: red = 209; green = 199; blue = 155; break; - case 13: red = 96; green = 94; blue = 93; break; - case 17: red = 71; green = 56; blue = 35; break; - case 18: red = 76; green = 104; blue = 64; break; - case 19: red = 119; green = 119; blue = 37; break; - case 22: red = 22; green = 44; blue = 86; break; - case 23: - case 29: - case 33: - case 61: - case 62: - case 158: red = 61; green = 61; blue = 61; break; - case 24: red = 209; green = 202; blue = 156; break; - case 25: - case 58: - case 84: - case 137: red = 57; green = 38; blue = 25; break; - case 35: - switch (data) { - case 0: red = 234; green = 234; blue = 234; break; - case 1: red = 224; green = 140; blue = 84; break; - case 2: red = 185; green = 90; blue = 194; break; - case 3: red = 124; green = 152; blue = 208; break; - case 4: red = 165; green = 154; blue = 35; break; - case 5: red = 70; green = 187; blue = 61; break; - case 6: red = 206; green = 124; blue = 145; break; - case 7: red = 66; green = 66; blue = 66; break; - case 8: red = 170; green = 176; blue = 176; break; - case 9: red = 45; green = 108; blue = 35; break; - case 10: red = 130; green = 62; blue = 8; break; - case 11: red = 43; green = 51; blue = 29; break; - case 12: red = 73; green = 47; blue = 29; break; - case 13: red = 57; green = 76; blue = 36; break; - case 14: red = 165; green = 58; blue = 53; break; - case 15: red = 24; green = 24; blue = 24; break; - default: - create = 0; - break; - } - break; - case 41: red = 239; green = 238; blue = 105; break; - case 42: red = 146; green = 146; blue = 146; break; - case 43: - case 98: red = 161; green = 161; blue = 161; break; - case 44: - create = 3; - - switch (data) { - case 0: red = 161; green = 161; blue = 161; break; - case 1: red = 209; green = 202; blue = 156; break; - case 2: red = 133; green = 94; blue = 62; break; - case 3: red = 71; green = 71; blue = 71; break; - case 4: red = 121; green = 67; blue = 53; break; - case 5: red = 161; green = 161; blue = 161; break; - case 6: red = 45; green = 22; blue = 26; break; - case 7: red = 195; green = 192; blue = 185; break; - default: - create = 0; - break; - } - break; - case 45: red = 121; green = 67; blue = 53; break; - case 46: red = 118; green = 36; blue = 13; break; - case 47: red = 155; green = 127; blue = 76; break; - case 48: red = 61; green = 79; blue = 61; break; - case 49: red = 52; green = 41; blue = 74; break; - case 52: red = 12; green = 66; blue = 71; break; - case 53: - case 67: - case 108: - case 109: - case 114: - case 128: - case 134: - case 135: - case 136: - case 156: - create = 2; - - switch (id) { - case 53: - case 134: - case 135: - case 136: red = 133; green = 94; blue = 62; break; - case 67: red = 71; green = 71; blue = 71; break; - case 108: red = 121; green = 67; blue = 53; break; - case 109: red = 161; green = 161; blue = 161; break; - case 114: red = 45; green = 22; blue = 26; break; - case 128: red = 209; green = 202; blue = 156; break; - case 156: red = 195; green = 192; blue = 185; break; - default: - create = 0; - break; - } - break; - case 54: - case 95: - case 146: red = 155; green = 105; blue = 32; break; - case 57: red = 145; green = 219; blue = 215; break; - case 79: red = 142; green = 162; blue = 195; break; - case 80: red = 255; green = 255; blue = 255; break; - case 81: red = 8; green = 64; blue = 15; break; - case 82: red = 150; green = 155; blue = 166; break; - case 86: - case 91: red = 179; green = 108; blue = 17; break; - case 87: - case 153: red = 91; green = 31; blue = 30; break; - case 88: red = 68; green = 49; blue = 38; break; - case 89: red = 180; green = 134; blue = 65; break; - case 103: red = 141; green = 143; blue = 36; break; - case 110: red = 103; green = 92; blue = 95; break; - case 112: red = 45; green = 22; blue = 26; break; - case 121: red = 183; green = 178; blue = 129; break; - case 123: red = 101; green = 59; blue = 31; break; - case 124: red = 213; green = 178; blue = 123; break; - case 130: red = 38; green = 54; blue = 56; break; - case 133: red = 53; green = 84; blue = 85; break; - case 152: red = 131; green = 22; blue = 7; break; - case 155: red = 195; green = 192; blue = 185; break; - case 159: red = 195; green = 165; blue = 150; break; - case 170: red = 168; green = 139; blue = 15; break; - case 172: red = 140; green = 86; blue = 61; break; - case 173: red = 9; green = 9; blue = 9; break; - default: - create = 0; - break; - } -} - diff --git a/libraries/voxels/src/Tags.h b/libraries/voxels/src/Tags.h deleted file mode 100644 index 1ac231f27c..0000000000 --- a/libraries/voxels/src/Tags.h +++ /dev/null @@ -1,183 +0,0 @@ -// -// Tags.h -// libraries/voxels/src -// -// Created by Clement Brisset on 7/3/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Tags_h -#define hifi_Tags_h - -#include - -#include -#include - -#include -#include -#include - -#define TAG_End 0 -#define TAG_Byte 1 -#define TAG_Short 2 -#define TAG_Int 3 -#define TAG_Long 4 -#define TAG_Float 5 -#define TAG_Double 6 -#define TAG_Byte_Array 7 -#define TAG_String 8 -#define TAG_List 9 -#define TAG_Compound 10 -#define TAG_Int_Array 11 - -int retrieveData(std::string filename, std::stringstream &ss); -int ungzip(std::ifstream &file, std::stringstream &ss); -void computeBlockColor(int id, int data, int& r, int& g, int& b, int& create); - -class Tag { -public: - Tag(int tagId, std::stringstream &ss); - - int getTagId() const {return _tagId;} - std::string getName () const {return _name; } - - static Tag* readTag(int tagId, std::stringstream &ss); - -protected: - int _tagId; - std::string _name; -}; - -class TagByte : public Tag { -public: - TagByte(std::stringstream &ss); - - int8_t getData() const {return _data;} - -private: - int8_t _data; -}; - -class TagShort : public Tag { -public: - TagShort(std::stringstream &ss); - - int16_t getData() const {return _data;} - -private: - int16_t _data; -}; - -class TagInt : public Tag { -public: - TagInt(std::stringstream &ss); - - int32_t getData() const {return _data;} - -private: - int32_t _data; -}; - -class TagLong : public Tag { -public: - TagLong(std::stringstream &ss); - - int64_t getData() const {return _data;} - -private: - int64_t _data; -}; - -class TagFloat : public Tag { -public: - TagFloat(std::stringstream &ss); -}; - -class TagDouble : public Tag { -public: - TagDouble(std::stringstream &ss); -}; - -class TagByteArray : public Tag { -public: - TagByteArray(std::stringstream &ss); - - int getSize() const {return _size;} - char* getData() const {return _data;} - -private: - int _size; - char* _data; -}; - -class TagString : public Tag { -public: - TagString(std::stringstream &ss); - - int getSize() const {return _size;} - std::string getData() const {return _data;} - -private: - int _size; - std::string _data; -}; - -class TagList : public Tag { -public: - TagList(std::stringstream &ss); - ~TagList(); - - int getTagId() const {return _tagId;} - int getSize () const {return _size; } - std::list getData () const {return _data; } - -private: - int _tagId; - int _size; - std::list _data; -}; - -class TagCompound : public Tag { -public: - TagCompound(std::stringstream &ss); - ~TagCompound(); - - int getSize () const {return _size; } - std::list getData () const {return _data; } - - int getWidth () const {return _width; } - int getLength () const {return _length; } - int getHeight () const {return _height; } - char* getBlocksId () const {return _blocksId; } - char* getBlocksData() const {return _blocksData;} - -private: - int _size; - std::list _data; - - // Specific to schematics file - int _width; - int _length; - int _height; - char* _blocksData; - char* _blocksId; -}; - -class TagIntArray : public Tag { -public: - TagIntArray(std::stringstream &ss); - ~TagIntArray() {delete _data;} - - int getSize() const {return _size;} - int* getData() const {return _data;} - -private: - int _size; - int* _data; -}; - -#endif // hifi_Tags_h diff --git a/libraries/voxels/src/VoxelDetail.cpp b/libraries/voxels/src/VoxelDetail.cpp deleted file mode 100644 index c1f7497d18..0000000000 --- a/libraries/voxels/src/VoxelDetail.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// VoxelDetail.cpp -// libraries/voxels/src -// -// Created by Brad Hefta-Gaub on 1/29/2014. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include "VoxelDetail.h" - -void registerVoxelMetaTypes(QScriptEngine* engine) { - qScriptRegisterMetaType(engine, voxelDetailToScriptValue, voxelDetailFromScriptValue); - qScriptRegisterMetaType(engine, rayToVoxelIntersectionResultToScriptValue, rayToVoxelIntersectionResultFromScriptValue); -} - -QScriptValue voxelDetailToScriptValue(QScriptEngine* engine, const VoxelDetail& voxelDetail) { - QScriptValue obj = engine->newObject(); - obj.setProperty("x", voxelDetail.x * (float)TREE_SCALE); - obj.setProperty("y", voxelDetail.y * (float)TREE_SCALE); - obj.setProperty("z", voxelDetail.z * (float)TREE_SCALE); - obj.setProperty("s", voxelDetail.s * (float)TREE_SCALE); - obj.setProperty("red", voxelDetail.red); - obj.setProperty("green", voxelDetail.green); - obj.setProperty("blue", voxelDetail.blue); - return obj; -} - -void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& voxelDetail) { - voxelDetail.x = object.property("x").toVariant().toFloat() / (float)TREE_SCALE; - voxelDetail.y = object.property("y").toVariant().toFloat() / (float)TREE_SCALE; - voxelDetail.z = object.property("z").toVariant().toFloat() / (float)TREE_SCALE; - voxelDetail.s = object.property("s").toVariant().toFloat() / (float)TREE_SCALE; - voxelDetail.red = object.property("red").toVariant().toInt(); - voxelDetail.green = object.property("green").toVariant().toInt(); - voxelDetail.blue = object.property("blue").toVariant().toInt(); -} - -RayToVoxelIntersectionResult::RayToVoxelIntersectionResult() : - intersects(false), - accurate(true), // assume it's accurate - voxel(), - distance(0), - face() -{ -}; - -QScriptValue rayToVoxelIntersectionResultToScriptValue(QScriptEngine* engine, const RayToVoxelIntersectionResult& value) { - QScriptValue obj = engine->newObject(); - obj.setProperty("intersects", value.intersects); - obj.setProperty("accurate", value.accurate); - QScriptValue voxelValue = voxelDetailToScriptValue(engine, value.voxel); - obj.setProperty("voxel", voxelValue); - obj.setProperty("distance", value.distance); - - QString faceName = ""; - // handle BoxFace - switch (value.face) { - case MIN_X_FACE: - faceName = "MIN_X_FACE"; - break; - case MAX_X_FACE: - faceName = "MAX_X_FACE"; - break; - case MIN_Y_FACE: - faceName = "MIN_Y_FACE"; - break; - case MAX_Y_FACE: - faceName = "MAX_Y_FACE"; - break; - case MIN_Z_FACE: - faceName = "MIN_Z_FACE"; - break; - case MAX_Z_FACE: - faceName = "MAX_Z_FACE"; - break; - case UNKNOWN_FACE: - faceName = "UNKNOWN_FACE"; - break; - } - obj.setProperty("face", faceName); - - QScriptValue intersection = vec3toScriptValue(engine, value.intersection); - obj.setProperty("intersection", intersection); - return obj; -} - -void rayToVoxelIntersectionResultFromScriptValue(const QScriptValue& object, RayToVoxelIntersectionResult& value) { - value.intersects = object.property("intersects").toVariant().toBool(); - value.accurate = object.property("accurate").toVariant().toBool(); - QScriptValue voxelValue = object.property("voxel"); - if (voxelValue.isValid()) { - voxelDetailFromScriptValue(voxelValue, value.voxel); - } - value.distance = object.property("distance").toVariant().toFloat(); - - QString faceName = object.property("face").toVariant().toString(); - if (faceName == "MIN_X_FACE") { - value.face = MIN_X_FACE; - } else if (faceName == "MAX_X_FACE") { - value.face = MAX_X_FACE; - } else if (faceName == "MIN_Y_FACE") { - value.face = MIN_Y_FACE; - } else if (faceName == "MAX_Y_FACE") { - value.face = MAX_Y_FACE; - } else if (faceName == "MIN_Z_FACE") { - value.face = MIN_Z_FACE; - } else { - value.face = MAX_Z_FACE; - }; - QScriptValue intersection = object.property("intersection"); - if (intersection.isValid()) { - vec3FromScriptValue(intersection, value.intersection); - } -} - - - - diff --git a/libraries/voxels/src/VoxelDetail.h b/libraries/voxels/src/VoxelDetail.h deleted file mode 100644 index 1e53fd33d2..0000000000 --- a/libraries/voxels/src/VoxelDetail.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// VoxelDetail.h -// libraries/voxels/src -// -// Created by Brad Hefta-Gaub on 1/29/2014. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_VoxelDetail_h -#define hifi_VoxelDetail_h - -#include - -#include -#include -#include - -struct VoxelDetail { - float x; - float y; - float z; - float s; - unsigned char red; - unsigned char green; - unsigned char blue; -}; - -Q_DECLARE_METATYPE(VoxelDetail) - -void registerVoxelMetaTypes(QScriptEngine* engine); - -QScriptValue voxelDetailToScriptValue(QScriptEngine* engine, const VoxelDetail& color); -void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& color); - -class RayToVoxelIntersectionResult { -public: - RayToVoxelIntersectionResult(); - bool intersects; - bool accurate; - VoxelDetail voxel; - float distance; - BoxFace face; - glm::vec3 intersection; -}; - -Q_DECLARE_METATYPE(RayToVoxelIntersectionResult) - -QScriptValue rayToVoxelIntersectionResultToScriptValue(QScriptEngine* engine, const RayToVoxelIntersectionResult& results); -void rayToVoxelIntersectionResultFromScriptValue(const QScriptValue& object, RayToVoxelIntersectionResult& results); - - -inline QDebug operator<<(QDebug debug, const VoxelDetail& details) { - debug << "VoxelDetail[ (" - << details.x * (float)TREE_SCALE << "," << details.y * (float)TREE_SCALE << "," << details.z * (float)TREE_SCALE - << " ) to (" - << details.x + details.s * (float)TREE_SCALE << "," << details.y + details.s * (float)TREE_SCALE - << "," << details.z + details.s * (float)TREE_SCALE << ") size: (" - << details.s * (float)TREE_SCALE << "," << details.s * (float)TREE_SCALE << "," << details.s * (float)TREE_SCALE << ")" - << " in meters]"; - - return debug; -} - -#endif // hifi_VoxelDetail_h From f1de9cabe9844d8efc6f39edd779a5ffeff03be5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 19:07:32 -0800 Subject: [PATCH 06/27] comment --- interface/src/Environment.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 1fd3c7a73c..645bbbdc4f 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -72,6 +72,7 @@ void Environment::renderAtmospheres(Camera& camera) { QMutexLocker locker(&_mutex); foreach (const ServerData& serverData, _data) { + // TODO: do something about EnvironmentData foreach (const EnvironmentData& environmentData, serverData) { renderAtmosphere(camera, environmentData); } From 27d8ccb51ee2afc23e04eacfe580a63d89c9fd12 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 19:58:04 -0800 Subject: [PATCH 07/27] more voxelEctomy --- assignment-client/CMakeLists.txt | 2 +- .../src/octree/OctreeSendThread.cpp | 4 +- domain-server/src/DomainServer.cpp | 2 +- interface/CMakeLists.txt | 2 +- interface/src/Application.cpp | 13 ++-- interface/src/ui/BandwidthMeter.cpp | 2 +- interface/src/ui/BandwidthMeter.h | 2 +- interface/src/ui/OctreeStatsDialog.cpp | 40 +++++------ interface/src/ui/OctreeStatsDialog.h | 10 +-- interface/src/ui/Stats.cpp | 72 +++++++++---------- interface/src/ui/Stats.h | 2 +- libraries/avatars/CMakeLists.txt | 2 +- .../{voxels => environment}/CMakeLists.txt | 6 +- .../src/EnvironmentData.cpp | 0 .../src/EnvironmentData.h | 0 libraries/fbx/CMakeLists.txt | 2 +- libraries/script-engine/CMakeLists.txt | 2 +- tests/octree/CMakeLists.txt | 2 +- 18 files changed, 80 insertions(+), 85 deletions(-) rename libraries/{voxels => environment}/CMakeLists.txt (79%) rename libraries/{voxels => environment}/src/EnvironmentData.cpp (100%) rename libraries/{voxels => environment}/src/EnvironmentData.h (100%) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 73dfbe7a8b..b56eea5c90 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -6,7 +6,7 @@ include_glm() # link in the shared libraries link_hifi_libraries( - audio avatars octree voxels gpu model fbx entities metavoxels + audio avatars octree environment gpu model fbx entities metavoxels networking animation shared script-engine embedded-webserver physics ) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 1a6e54b9f5..b90e7ceb8e 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -430,7 +430,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus bool wantOcclusionCulling = nodeData->getWantOcclusionCulling(); CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP; - float voxelSizeScale = nodeData->getOctreeSizeScale(); + float octreeSizeScale = nodeData->getOctreeSizeScale(); int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust(); int boundaryLevelAdjust = boundaryLevelAdjustClient + (viewFrustumChanged && nodeData->getWantLowResMoving() @@ -438,7 +438,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor, WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, - wantOcclusionCulling, coverageMap, boundaryLevelAdjust, voxelSizeScale, + wantOcclusionCulling, coverageMap, boundaryLevelAdjust, octreeSizeScale, nodeData->getLastTimeBagEmpty(), isFullScene, &nodeData->stats, _myServer->getJurisdiction(), &nodeData->extraEncodeData); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index cea5bec3ef..2c04771cb6 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -561,7 +561,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSetisActive() ? static_cast(visage.data()) : NULL))); } -struct SendVoxelsOperationArgs { - const unsigned char* newBaseOctCode; -}; - bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { QVector entities; _entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE, @@ -2183,8 +2179,7 @@ int Application::sendNackPackets() { nodeList->eachNode([&](const SharedNodePointer& node){ - if (node->getActiveSocket() - && (node->getType() == NodeType::VoxelServer || node->getType() == NodeType::EntityServer)) { + if (node->getActiveSocket() && node->getType() == NodeType::EntityServer) { QUuid nodeUUID = node->getUUID(); @@ -2424,7 +2419,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node nodeList->writeUnverifiedDatagram(reinterpret_cast(queryPacket), packetLength, node); // Feed number of bytes to corresponding channel of the bandwidth meter - _bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength); + _bandwidthMeter.outputStream(BandwidthMeter::OCTREE).updateValue(packetLength); } }); } @@ -3569,7 +3564,7 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin } void Application::packetSent(quint64 length) { - _bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(length); + _bandwidthMeter.outputStream(BandwidthMeter::OCTREE).updateValue(length); } void Application::loadScripts() { diff --git a/interface/src/ui/BandwidthMeter.cpp b/interface/src/ui/BandwidthMeter.cpp index d28d85428d..44c82afe38 100644 --- a/interface/src/ui/BandwidthMeter.cpp +++ b/interface/src/ui/BandwidthMeter.cpp @@ -48,7 +48,7 @@ namespace { // .cpp-local BandwidthMeter::ChannelInfo BandwidthMeter::_CHANNELS[] = { { "Audio" , "Kbps", 8000.0 / 1024.0, 0x33cc99ff }, { "Avatars" , "Kbps", 8000.0 / 1024.0, 0xffef40c0 }, - { "Voxels" , "Kbps", 8000.0 / 1024.0, 0xd0d0d0a0 }, + { "Octree" , "Kbps", 8000.0 / 1024.0, 0xd0d0d0a0 }, { "Metavoxels", "Kbps", 8000.0 / 1024.0, 0xd0d0d0a0 } }; diff --git a/interface/src/ui/BandwidthMeter.h b/interface/src/ui/BandwidthMeter.h index 9931355f8e..0829cc86e9 100644 --- a/interface/src/ui/BandwidthMeter.h +++ b/interface/src/ui/BandwidthMeter.h @@ -34,7 +34,7 @@ public: static size_t const N_STREAMS = N_CHANNELS * 2; // Channel usage. - enum ChannelIndex { AUDIO, AVATARS, VOXELS, METAVOXELS }; + enum ChannelIndex { AUDIO, AVATARS, OCTREE, METAVOXELS }; // Meta information held for a communication channel (bidirectional). struct ChannelInfo { diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 1980aa3ed6..9209faeaf4 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -28,10 +28,10 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo _model(model) { _statCount = 0; - _voxelServerLabelsCount = 0; + _octreeServerLabelsCount = 0; for (int i = 0; i < MAX_VOXEL_SERVERS; i++) { - _voxelServerLables[i] = 0; + _octreeServerLables[i] = 0; _extraServerDetails[i] = LESS; } @@ -46,9 +46,9 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo this->QDialog::setLayout(_form); // Setup stat items - _serverVoxels = AddStatItem("Elements on Servers"); - _localVoxels = AddStatItem("Local Elements"); - _localVoxelsMemory = AddStatItem("Elements Memory"); + _serverElements = AddStatItem("Elements on Servers"); + _localElements = AddStatItem("Local Elements"); + _localElementsMemory = AddStatItem("Elements Memory"); _sendingMode = AddStatItem("Sending Mode"); layout()->setSizeConstraint(QLayout::SetFixedSize); @@ -127,13 +127,13 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { statsValue.precision(4); // Octree Elements Memory Usage - label = _labels[_localVoxelsMemory]; + label = _labels[_localElementsMemory]; statsValue.str(""); statsValue << "Elements RAM: " << OctreeElement::getTotalMemoryUsage() / 1000000.0f << "MB "; label->setText(statsValue.str().c_str()); - // Local Voxels - label = _labels[_localVoxels]; + // Local Elements + label = _labels[_localElements]; unsigned long localTotal = OctreeElement::getNodeCount(); unsigned long localInternal = OctreeElement::getInternalNodeCount(); unsigned long localLeaves = OctreeElement::getLeafNodeCount(); @@ -191,11 +191,11 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { label = _labels[_sendingMode]; label->setText(sendingMode.str().c_str()); - // Server Voxels + // Server Elements QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' '); QString serversInternalString = locale.toString((uint)totalInternal); QString serversLeavesString = locale.toString((uint)totalLeaves); - label = _labels[_serverVoxels]; + label = _labels[_serverElements]; statsValue.str(""); statsValue << "Total: " << qPrintable(serversTotalString) << " / " << @@ -213,13 +213,13 @@ void OctreeStatsDialog::showAllOctreeServers() { showOctreeServersOfType(serverCount, NodeType::EntityServer, "Entity", Application::getInstance()->getEntityServerJurisdictions()); - if (_voxelServerLabelsCount > serverCount) { - for (int i = serverCount; i < _voxelServerLabelsCount; i++) { - int serverLabel = _voxelServerLables[i]; + if (_octreeServerLabelsCount > serverCount) { + for (int i = serverCount; i < _octreeServerLabelsCount; i++) { + int serverLabel = _octreeServerLables[i]; RemoveStatItem(serverLabel); - _voxelServerLables[i] = 0; + _octreeServerLables[i] = 0; } - _voxelServerLabelsCount = serverCount; + _octreeServerLabelsCount = serverCount; } } @@ -235,14 +235,14 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser if (node->getType() == serverType) { serverCount++; - if (serverCount > _voxelServerLabelsCount) { + if (serverCount > _octreeServerLabelsCount) { char label[128] = { 0 }; sprintf(label, "%s Server %d", serverTypeName, serverCount); - int thisServerRow = _voxelServerLables[serverCount-1] = AddStatItem(label); + int thisServerRow = _octreeServerLables[serverCount-1] = AddStatItem(label); _labels[thisServerRow]->setTextFormat(Qt::RichText); _labels[thisServerRow]->setTextInteractionFlags(Qt::TextBrowserInteraction); connect(_labels[thisServerRow], SIGNAL(linkActivated(const QString&)), this, SLOT(moreless(const QString&))); - _voxelServerLabelsCount++; + _octreeServerLabelsCount++; } std::stringstream serverDetails(""); @@ -335,7 +335,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser serverDetails << "
" << "Node UUID: " << qPrintable(nodeUUID.toString()) << " "; - serverDetails << "
" << "Voxels: " << + serverDetails << "
" << "Elements: " << qPrintable(totalString) << " total " << qPrintable(internalString) << " internal " << qPrintable(leavesString) << " leaves "; @@ -399,7 +399,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser linkDetails << " " << " [most...]"; } serverDetails << linkDetails.str(); - _labels[_voxelServerLables[serverCount - 1]]->setText(serverDetails.str().c_str()); + _labels[_octreeServerLables[serverCount - 1]]->setText(serverDetails.str().c_str()); } // is VOXEL_SERVER }); } diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index 2db1430d28..03683d8171 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -60,11 +60,11 @@ private: int _statCount; int _sendingMode; - int _serverVoxels; - int _localVoxels; - int _localVoxelsMemory; - int _voxelServerLables[MAX_VOXEL_SERVERS]; - int _voxelServerLabelsCount; + int _serverElements; + int _localElements; + int _localElementsMemory; + int _octreeServerLables[MAX_VOXEL_SERVERS]; + int _octreeServerLabelsCount; details _extraServerDetails[MAX_VOXEL_SERVERS]; }; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 3881760a7e..dc8e45a1a7 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -33,7 +33,7 @@ const int STATS_PELS_PER_LINE = 20; const int STATS_GENERAL_MIN_WIDTH = 165; const int STATS_PING_MIN_WIDTH = 190; const int STATS_GEO_MIN_WIDTH = 240; -const int STATS_VOXEL_MIN_WIDTH = 410; +const int STATS_OCTREE_MIN_WIDTH = 410; Stats* Stats::getInstance() { static Stats stats; @@ -47,7 +47,7 @@ Stats::Stats(): _generalStatsWidth(STATS_GENERAL_MIN_WIDTH), _pingStatsWidth(STATS_PING_MIN_WIDTH), _geoStatsWidth(STATS_GEO_MIN_WIDTH), - _voxelStatsWidth(STATS_VOXEL_MIN_WIDTH), + _octreeStatsWidth(STATS_OCTREE_MIN_WIDTH), _lastHorizontalOffset(0), _metavoxelInternal(0), _metavoxelLeaves(0), @@ -127,7 +127,7 @@ void Stats::resetWidth(int width, int horizontalOffset) { - STATS_GENERAL_MIN_WIDTH - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0) - STATS_GEO_MIN_WIDTH - - STATS_VOXEL_MIN_WIDTH; + - STATS_OCTREE_MIN_WIDTH; int panels = 4; @@ -139,7 +139,7 @@ void Stats::resetWidth(int width, int horizontalOffset) { panels = 3; } _geoStatsWidth = STATS_GEO_MIN_WIDTH; - _voxelStatsWidth = STATS_VOXEL_MIN_WIDTH; + _octreeStatsWidth = STATS_OCTREE_MIN_WIDTH; if (extraSpace > panels) { _generalStatsWidth += (int) extraSpace / panels; @@ -147,7 +147,7 @@ void Stats::resetWidth(int width, int horizontalOffset) { _pingStatsWidth += (int) extraSpace / panels; } _geoStatsWidth += (int) extraSpace / panels; - _voxelStatsWidth += glCanvas->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3); + _octreeStatsWidth += glCanvas->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3); } } @@ -204,7 +204,7 @@ void Stats::display( int font = 2; QLocale locale(QLocale::English); - std::stringstream voxelStats; + std::stringstream octreeStats; if (_lastHorizontalOffset != horizontalOffset) { resetWidth(glCanvas->width(), horizontalOffset); @@ -479,33 +479,33 @@ void Stats::display( // Model/Entity render details EntityTreeRenderer* entities = Application::getInstance()->getEntities(); - voxelStats.str(""); - voxelStats << "Entity Items rendered: " << entities->getItemsRendered() + octreeStats.str(""); + octreeStats << "Entity Items rendered: " << entities->getItemsRendered() << " / Out of view:" << entities->getItemsOutOfView() << " / Too small:" << entities->getItemsTooSmall(); verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); if (_expanded) { - voxelStats.str(""); - voxelStats << " Meshes rendered: " << entities->getMeshesRendered() + octreeStats.str(""); + octreeStats << " Meshes rendered: " << entities->getMeshesRendered() << " / Out of view:" << entities->getMeshesOutOfView() << " / Too small:" << entities->getMeshesTooSmall(); verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - voxelStats.str(""); - voxelStats << " Triangles: " << entities->getTrianglesRendered() + octreeStats.str(""); + octreeStats << " Triangles: " << entities->getTrianglesRendered() << " / Quads:" << entities->getQuadsRendered() << " / Material Switches:" << entities->getMaterialSwitches(); verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - voxelStats.str(""); - voxelStats << " Mesh Parts Rendered Opaque: " << entities->getOpaqueMeshPartsRendered() + octreeStats.str(""); + octreeStats << " Mesh Parts Rendered Opaque: " << entities->getOpaqueMeshPartsRendered() << " / Translucent:" << entities->getTranslucentMeshPartsRendered(); verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } // iterate all the current voxel stats, and list their sending modes, and total voxel counts @@ -556,13 +556,13 @@ void Stats::display( // Incoming packets if (_expanded) { - voxelStats.str(""); + octreeStats.str(""); QString packetsString = locale.toString((int)voxelPacketsToProcess); QString maxString = locale.toString((int)_recentMaxPackets); - voxelStats << "Voxel Packets to Process: " << qPrintable(packetsString) + octreeStats << "Octree Packets to Process: " << qPrintable(packetsString) << " [Recent Max: " << qPrintable(maxString) << "]"; verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) { @@ -583,28 +583,28 @@ void Stats::display( // Server Octree Elements if (!_expanded) { - voxelStats.str(""); - voxelStats << "Octree Elements Server: " << qPrintable(serversTotalString) + octreeStats.str(""); + octreeStats << "Octree Elements Server: " << qPrintable(serversTotalString) << " Local:" << qPrintable(localTotalString); verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } if (_expanded) { - voxelStats.str(""); - voxelStats << "Octree Elements -"; + octreeStats.str(""); + octreeStats << "Octree Elements -"; verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); QString serversInternalString = locale.toString((uint)totalInternal); QString serversLeavesString = locale.toString((uint)totalLeaves); - voxelStats.str(""); - voxelStats << " Server: " << qPrintable(serversTotalString) << + octreeStats.str(""); + octreeStats << " Server: " << qPrintable(serversTotalString) << " Internal: " << qPrintable(serversInternalString) << " Leaves: " << qPrintable(serversLeavesString); verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); // Local Voxels unsigned long localInternal = OctreeElement::getInternalNodeCount(); @@ -612,21 +612,21 @@ void Stats::display( QString localInternalString = locale.toString((uint)localInternal); QString localLeavesString = locale.toString((uint)localLeaves); - voxelStats.str(""); - voxelStats << " Local: " << qPrintable(serversTotalString) << + octreeStats.str(""); + octreeStats << " Local: " << qPrintable(serversTotalString) << " Internal: " << qPrintable(localInternalString) << " Leaves: " << qPrintable(localLeavesString) << ""; verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } // LOD Details if (_expanded) { - voxelStats.str(""); + octreeStats.str(""); QString displayLODDetails = Menu::getInstance()->getLODFeedbackText(); - voxelStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed()); + octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed()); verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } } diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 5a38b5ed9f..d253c303a8 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -46,7 +46,7 @@ private: int _generalStatsWidth; int _pingStatsWidth; int _geoStatsWidth; - int _voxelStatsWidth; + int _octreeStatsWidth; int _lastHorizontalOffset; diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index bacae45406..b7731a0e3d 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(Network Script) include_glm() -link_hifi_libraries(audio shared octree voxels networking physics gpu model fbx) +link_hifi_libraries(audio shared octree networking physics gpu model fbx) # call macro to include our dependency includes and bubble them up via a property on our target include_dependency_includes() diff --git a/libraries/voxels/CMakeLists.txt b/libraries/environment/CMakeLists.txt similarity index 79% rename from libraries/voxels/CMakeLists.txt rename to libraries/environment/CMakeLists.txt index 75b5143321..962628cd85 100644 --- a/libraries/voxels/CMakeLists.txt +++ b/libraries/environment/CMakeLists.txt @@ -1,11 +1,11 @@ -set(TARGET_NAME voxels) +set(TARGET_NAME environment) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Widgets Script) +setup_hifi_library() include_glm() -link_hifi_libraries(shared octree networking) +link_hifi_libraries(shared networking) # find ZLIB find_package(ZLIB REQUIRED) diff --git a/libraries/voxels/src/EnvironmentData.cpp b/libraries/environment/src/EnvironmentData.cpp similarity index 100% rename from libraries/voxels/src/EnvironmentData.cpp rename to libraries/environment/src/EnvironmentData.cpp diff --git a/libraries/voxels/src/EnvironmentData.h b/libraries/environment/src/EnvironmentData.h similarity index 100% rename from libraries/voxels/src/EnvironmentData.h rename to libraries/environment/src/EnvironmentData.h diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index 15d2bbdab6..67fe920568 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library() include_glm() -link_hifi_libraries(shared gpu model networking octree voxels) +link_hifi_libraries(shared gpu model networking octree) find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index c153e093cd..7ab73ceefb 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(Gui Network Script Widgets) include_glm() -link_hifi_libraries(shared octree voxels gpu model fbx entities animation audio physics metavoxels) +link_hifi_libraries(shared octree gpu model fbx entities animation audio physics metavoxels) # call macro to include our dependency includes and bubble them up via a property on our target include_dependency_includes() diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt index 5a025a3a0e..7fc6b56332 100644 --- a/tests/octree/CMakeLists.txt +++ b/tests/octree/CMakeLists.txt @@ -5,6 +5,6 @@ setup_hifi_project(Script Network) include_glm() # link in the shared libraries -link_hifi_libraries(shared octree voxels gpu model fbx metavoxels networking entities avatars audio animation script-engine physics) +link_hifi_libraries(shared octree gpu model fbx metavoxels networking entities avatars audio animation script-engine physics) include_dependency_includes() From 95bb125e4893563ec4f78050ab6a812594bb6165 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 20:13:57 -0800 Subject: [PATCH 08/27] more voxelEctomy --- interface/src/Application.cpp | 32 +++++++++---------- interface/src/Application.h | 8 ++--- .../VoxelFade.cpp => octree/OctreeFade.cpp} | 28 ++++++++-------- .../VoxelFade.h => octree/OctreeFade.h} | 12 +++---- .../OctreePacketProcessor.cpp | 0 .../OctreePacketProcessor.h | 0 6 files changed, 40 insertions(+), 40 deletions(-) rename interface/src/{voxels/VoxelFade.cpp => octree/OctreeFade.cpp} (69%) rename interface/src/{voxels/VoxelFade.h => octree/OctreeFade.h} (84%) rename interface/src/{voxels => octree}/OctreePacketProcessor.cpp (100%) rename interface/src/{voxels => octree}/OctreePacketProcessor.h (100%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9236f316fa..c8018e41a0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2897,21 +2897,21 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr renderViewFrustum(_viewFrustum); } - // render voxel fades if they exist - if (_voxelFades.size() > 0) { - PerformanceTimer perfTimer("voxelFades"); + // render octree fades if they exist + if (_octreeFades.size() > 0) { + PerformanceTimer perfTimer("octreeFades"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... voxel fades..."); - _voxelFadesLock.lockForWrite(); - for(std::vector::iterator fade = _voxelFades.begin(); fade != _voxelFades.end();) { + "Application::displaySide() ... octree fades..."); + _octreeFadesLock.lockForWrite(); + for(std::vector::iterator fade = _octreeFades.begin(); fade != _octreeFades.end();) { fade->render(); if(fade->isDone()) { - fade = _voxelFades.erase(fade); + fade = _octreeFades.erase(fade); } else { ++fade; } } - _voxelFadesLock.unlock(); + _octreeFadesLock.unlock(); } // give external parties a change to hook in @@ -3453,13 +3453,13 @@ void Application::nodeKilled(SharedNodePointer node) { // Add the jurisditionDetails object to the list of "fade outs" if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnOctreeServerChanges)) { - VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE); + OctreeFade fade(OctreeFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE); fade.voxelDetails = rootDetails; const float slightly_smaller = 0.99f; fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller; - _voxelFadesLock.lockForWrite(); - _voxelFades.push_back(fade); - _voxelFadesLock.unlock(); + _octreeFadesLock.lockForWrite(); + _octreeFades.push_back(fade); + _octreeFadesLock.unlock(); } // If the model server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server @@ -3539,13 +3539,13 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin // Add the jurisditionDetails object to the list of "fade outs" if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnOctreeServerChanges)) { - VoxelFade fade(VoxelFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE); + OctreeFade fade(OctreeFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE); fade.voxelDetails = rootDetails; const float slightly_smaller = 0.99f; fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller; - _voxelFadesLock.lockForWrite(); - _voxelFades.push_back(fade); - _voxelFadesLock.unlock(); + _octreeFadesLock.lockForWrite(); + _octreeFades.push_back(fade); + _octreeFadesLock.unlock(); } } else { jurisdiction->unlock(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 75cc07400f..943d48bbac 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -68,8 +68,8 @@ #include "ui/ApplicationOverlay.h" #include "ui/RunningScriptsWidget.h" #include "ui/ToolWindow.h" -#include "voxels/VoxelFade.h" -#include "voxels/OctreePacketProcessor.h" +#include "octree/OctreeFade.h" +#include "octree/OctreePacketProcessor.h" #include "UndoStackScriptingInterface.h" @@ -535,8 +535,8 @@ private: NodeBounds _nodeBoundsDisplay; - std::vector _voxelFades; - QReadWriteLock _voxelFadesLock; + std::vector _octreeFades; + QReadWriteLock _octreeFadesLock; ControllerScriptingInterface _controllerScriptingInterface; QPointer _logDialog; QPointer _snapshotShareDialog; diff --git a/interface/src/voxels/VoxelFade.cpp b/interface/src/octree/OctreeFade.cpp similarity index 69% rename from interface/src/voxels/VoxelFade.cpp rename to interface/src/octree/OctreeFade.cpp index aeb44e67ae..fa33d46491 100644 --- a/interface/src/voxels/VoxelFade.cpp +++ b/interface/src/octree/OctreeFade.cpp @@ -1,5 +1,5 @@ // -// VoxelFade.cpp +// OctreeFade.cpp // interface/src/voxels // // Created by Brad Hefta-Gaub on 8/6/13. @@ -16,19 +16,19 @@ #include #include "Application.h" -#include "VoxelFade.h" +#include "OctreeFade.h" -const float VoxelFade::FADE_OUT_START = 0.5f; -const float VoxelFade::FADE_OUT_END = 0.05f; -const float VoxelFade::FADE_OUT_STEP = 0.9f; -const float VoxelFade::FADE_IN_START = 0.05f; -const float VoxelFade::FADE_IN_END = 0.5f; -const float VoxelFade::FADE_IN_STEP = 1.1f; -const float VoxelFade::DEFAULT_RED = 0.5f; -const float VoxelFade::DEFAULT_GREEN = 0.5f; -const float VoxelFade::DEFAULT_BLUE = 0.5f; +const float OctreeFade::FADE_OUT_START = 0.5f; +const float OctreeFade::FADE_OUT_END = 0.05f; +const float OctreeFade::FADE_OUT_STEP = 0.9f; +const float OctreeFade::FADE_IN_START = 0.05f; +const float OctreeFade::FADE_IN_END = 0.5f; +const float OctreeFade::FADE_IN_STEP = 1.1f; +const float OctreeFade::DEFAULT_RED = 0.5f; +const float OctreeFade::DEFAULT_GREEN = 0.5f; +const float OctreeFade::DEFAULT_BLUE = 0.5f; -VoxelFade::VoxelFade(FadeDirection direction, float red, float green, float blue) : +OctreeFade::OctreeFade(FadeDirection direction, float red, float green, float blue) : direction(direction), red(red), green(green), @@ -37,7 +37,7 @@ VoxelFade::VoxelFade(FadeDirection direction, float red, float green, float blue opacity = (direction == FADE_OUT) ? FADE_OUT_START : FADE_IN_START; } -void VoxelFade::render() { +void OctreeFade::render() { DependencyManager::get()->begin(); glDisable(GL_LIGHTING); @@ -59,7 +59,7 @@ void VoxelFade::render() { opacity *= (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP; } -bool VoxelFade::isDone() const { +bool OctreeFade::isDone() const { if (direction == FADE_OUT) { return opacity <= FADE_OUT_END; } else { diff --git a/interface/src/voxels/VoxelFade.h b/interface/src/octree/OctreeFade.h similarity index 84% rename from interface/src/voxels/VoxelFade.h rename to interface/src/octree/OctreeFade.h index 1843fa2d67..bb305d8769 100644 --- a/interface/src/voxels/VoxelFade.h +++ b/interface/src/octree/OctreeFade.h @@ -1,5 +1,5 @@ // -// VoxelFade.h +// OctreeFade.h // interface/src/voxels // // Created by Brad Hefta-Gaub on 8/6/13. @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_VoxelFade_h -#define hifi_VoxelFade_h +#ifndef hifi_OctreeFade_h +#define hifi_OctreeFade_h #include // for VoxelPositionSize -class VoxelFade { +class OctreeFade { public: enum FadeDirection { FADE_OUT, FADE_IN}; @@ -36,11 +36,11 @@ public: float green; float blue; - VoxelFade(FadeDirection direction = FADE_OUT, float red = DEFAULT_RED, + OctreeFade(FadeDirection direction = FADE_OUT, float red = DEFAULT_RED, float green = DEFAULT_GREEN, float blue = DEFAULT_BLUE); void render(); bool isDone() const; }; -#endif // hifi_VoxelFade_h +#endif // hifi_OctreeFade_h diff --git a/interface/src/voxels/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp similarity index 100% rename from interface/src/voxels/OctreePacketProcessor.cpp rename to interface/src/octree/OctreePacketProcessor.cpp diff --git a/interface/src/voxels/OctreePacketProcessor.h b/interface/src/octree/OctreePacketProcessor.h similarity index 100% rename from interface/src/voxels/OctreePacketProcessor.h rename to interface/src/octree/OctreePacketProcessor.h From 5cef7d0e9df647733b0b093a69c14ad593665944 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 20:24:27 -0800 Subject: [PATCH 09/27] more voxelEctomy --- .../resources/describe-settings.json | 96 +------------------ domain-server/src/DomainServer.cpp | 3 +- interface/src/ui/Stats.cpp | 28 +++--- libraries/networking/src/Assignment.cpp | 6 +- libraries/networking/src/Assignment.h | 4 +- libraries/networking/src/Node.cpp | 2 - libraries/networking/src/Node.h | 2 - libraries/octree/src/JurisdictionListener.h | 2 +- libraries/octree/src/JurisdictionMap.h | 2 +- libraries/octree/src/JurisdictionSender.h | 2 +- 10 files changed, 24 insertions(+), 123 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index ae6f116537..3435f49b71 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -410,99 +410,5 @@ "advanced": true } ] - }, - - - { - "name": "voxel_server_settings", - "label": "Voxel Server Settings", - "assignment-types": [3], - "settings": [ - { - "name": "persistFilename", - "label": "Persistant Filename", - "help": "the filename for your voxels", - "placeholder": "resources/voxels.svo", - "default": "resources/voxels.svo", - "advanced": true - }, - { - "name": "persistInterval", - "label": "Persist Interval", - "help": "Interval between persist checks in msecs.", - "placeholder": "30000", - "default": "30000", - "advanced": true - }, - { - "name": "NoPersist", - "type": "checkbox", - "help": "Don't persist your voxels to a file.", - "default": false, - "advanced": true - }, - { - "name": "backupExtensionFormat", - "label": "Backup File Extension Format:", - "help": "Format used to create the extension for the backup of your persisted voxels.", - "placeholder": ".backup.%Y-%m-%d.%H:%M:%S.%z", - "default": ".backup.%Y-%m-%d.%H:%M:%S.%z", - "advanced": true - }, - { - "name": "backupInterval", - "label": "Backup Interval", - "help": "Interval between backup checks in msecs.", - "placeholder": "1800000", - "default": "1800000", - "advanced": true - }, - { - "name": "NoBackup", - "type": "checkbox", - "help": "Don't regularly backup your persisted voxels to a backup file.", - "default": false, - "advanced": true - }, - { - "name": "statusHost", - "label": "Status Hostname", - "help": "host name or IP address of the server for accessing the status page", - "placeholder": "", - "default": "", - "advanced": true - }, - { - "name": "statusPort", - "label": "Status Port", - "help": "port of the server for accessing the status page", - "placeholder": "", - "default": "", - "advanced": true - }, - { - "name": "clockSkew", - "label": "Clock Skew", - "help": "Number of msecs to skew the server clock by to test clock skew", - "placeholder": "0", - "default": "0", - "advanced": true - }, - { - "name": "sendEnvironments", - "type": "checkbox", - "help": "send environmental data", - "default": false, - "advanced": true - }, - { - "name": "minimalEnvironment", - "type": "checkbox", - "help": "send minimal environmental data if sending environmental data", - "default": false, - "advanced": true - } - ] - } - + } ] \ No newline at end of file diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 2c04771cb6..3da06a9c0e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -550,7 +550,8 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet(static_cast(defaultedType) + 1)) { if (!excludedTypes.contains(defaultedType) - && defaultedType != Assignment::UNUSED + && defaultedType != Assignment::UNUSED_0 + && defaultedType != Assignment::UNUSED_1 && defaultedType != Assignment::AgentType) { // type has not been set from a command line or config file config, use the default // by clearing whatever exists and writing a single default assignment with no payload diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index dc8e45a1a7..43565fcca8 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -313,7 +313,7 @@ void Stats::display( horizontalOffset = _lastHorizontalOffset + _generalStatsWidth +1; if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { - int pingAudio = -1, pingAvatar = -1, pingVoxel = -1, pingVoxelMax = -1; + int pingAudio = -1, pingAvatar = -1, pingVoxel = -1, pingOctreeMax = -1; NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); @@ -323,22 +323,22 @@ void Stats::display( pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : -1; // Now handle voxel servers, since there could be more than one, we average their ping times - unsigned long totalPingVoxel = 0; - int voxelServerCount = 0; + unsigned long totalPingOctree = 0; + int octreeServerCount = 0; - nodeList->eachNode([&totalPingVoxel, &pingVoxelMax, &voxelServerCount](const SharedNodePointer& node){ + nodeList->eachNode([&totalPingOctree, &pingOctreeMax, &octreeServerCount](const SharedNodePointer& node){ // TODO: this should also support entities - if (node->getType() == NodeType::VoxelServer) { - totalPingVoxel += node->getPingMs(); - voxelServerCount++; - if (pingVoxelMax < node->getPingMs()) { - pingVoxelMax = node->getPingMs(); + if (node->getType() == NodeType::EntityServer) { + totalPingOctree += node->getPingMs(); + octreeServerCount++; + if (pingOctreeMax < node->getPingMs()) { + pingOctreeMax = node->getPingMs(); } } }); - if (voxelServerCount) { - pingVoxel = totalPingVoxel/voxelServerCount; + if (octreeServerCount) { + pingVoxel = totalPingOctree / octreeServerCount; } lines = _expanded ? 4 : 3; @@ -366,9 +366,9 @@ void Stats::display( char voxelAvgPing[30]; if (pingVoxel >= 0) { - sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel); + sprintf(voxelAvgPing, "Entities avg ping: %d", pingVoxel); } else { - sprintf(voxelAvgPing, "Voxel avg ping: --"); + sprintf(voxelAvgPing, "Entities avg ping: --"); } verticalOffset += STATS_PELS_PER_LINE; @@ -381,7 +381,7 @@ void Stats::display( if (_expanded) { char voxelMaxPing[30]; if (pingVoxel >= 0) { // Average is only meaningful if pingVoxel is valid. - sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax); + sprintf(voxelMaxPing, "Voxel max ping: %d", pingOctreeMax); } else { sprintf(voxelMaxPing, "Voxel max ping: --"); } diff --git a/libraries/networking/src/Assignment.cpp b/libraries/networking/src/Assignment.cpp index 45dfe186e3..e01edcd003 100644 --- a/libraries/networking/src/Assignment.cpp +++ b/libraries/networking/src/Assignment.cpp @@ -25,8 +25,6 @@ Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) { return Assignment::AvatarMixerType; case NodeType::Agent: return Assignment::AgentType; - case NodeType::VoxelServer: - return Assignment::VoxelServerType; case NodeType::EntityServer: return Assignment::EntityServerType; case NodeType::MetavoxelServer: @@ -133,8 +131,8 @@ const char* Assignment::getTypeName() const { return "avatar-mixer"; case Assignment::AgentType: return "agent"; - case Assignment::VoxelServerType: - return "voxel-server"; + case Assignment::EntityServerType: + return "entity-server"; case Assignment::MetavoxelServerType: return "metavoxel-server"; default: diff --git a/libraries/networking/src/Assignment.h b/libraries/networking/src/Assignment.h index 1f6b5b9bd6..1e620ed32b 100644 --- a/libraries/networking/src/Assignment.h +++ b/libraries/networking/src/Assignment.h @@ -29,8 +29,8 @@ public: AudioMixerType, AvatarMixerType, AgentType, - VoxelServerType, - UNUSED, + UNUSED_0, + UNUSED_1, MetavoxelServerType, EntityServerType, AllTypes diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 61f8ee05a1..2095acdf66 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -28,13 +28,11 @@ namespace NodeType { void NodeType::init() { TypeNameHash.insert(NodeType::DomainServer, "Domain Server"); - TypeNameHash.insert(NodeType::VoxelServer, "Voxel Server"); TypeNameHash.insert(NodeType::EntityServer, "Entity Server"); TypeNameHash.insert(NodeType::MetavoxelServer, "Metavoxel Server"); TypeNameHash.insert(NodeType::Agent, "Agent"); TypeNameHash.insert(NodeType::AudioMixer, "Audio Mixer"); TypeNameHash.insert(NodeType::AvatarMixer, "Avatar Mixer"); - TypeNameHash.insert(NodeType::AnimationServer, "Animation Server"); TypeNameHash.insert(NodeType::Unassigned, "Unassigned"); } diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index acb6c6f453..6399c80edc 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -30,14 +30,12 @@ typedef quint8 NodeType_t; namespace NodeType { const NodeType_t DomainServer = 'D'; - const NodeType_t VoxelServer = 'V'; const NodeType_t EntityServer = 'o'; // was ModelServer const NodeType_t MetavoxelServer = 'm'; const NodeType_t EnvironmentServer = 'E'; const NodeType_t Agent = 'I'; const NodeType_t AudioMixer = 'M'; const NodeType_t AvatarMixer = 'W'; - const NodeType_t AnimationServer = 'a'; const NodeType_t Unassigned = 1; void init(); diff --git a/libraries/octree/src/JurisdictionListener.h b/libraries/octree/src/JurisdictionListener.h index 8b69cd0aeb..7fb4fb33c7 100644 --- a/libraries/octree/src/JurisdictionListener.h +++ b/libraries/octree/src/JurisdictionListener.h @@ -30,7 +30,7 @@ public: static const int DEFAULT_PACKETS_PER_SECOND = 1; static const int NO_SERVER_CHECK_RATE = 60; // if no servers yet detected, keep checking at 60fps - JurisdictionListener(NodeType_t type = NodeType::VoxelServer); + JurisdictionListener(NodeType_t type = NodeType::EntityServer); virtual bool process(); diff --git a/libraries/octree/src/JurisdictionMap.h b/libraries/octree/src/JurisdictionMap.h index 9820045321..ba75e3102b 100644 --- a/libraries/octree/src/JurisdictionMap.h +++ b/libraries/octree/src/JurisdictionMap.h @@ -31,7 +31,7 @@ public: }; // standard constructors - JurisdictionMap(NodeType_t type = NodeType::VoxelServer); // default constructor + JurisdictionMap(NodeType_t type = NodeType::EntityServer); // default constructor JurisdictionMap(const JurisdictionMap& other); // copy constructor // standard assignment diff --git a/libraries/octree/src/JurisdictionSender.h b/libraries/octree/src/JurisdictionSender.h index bfa370c6ca..a7d23d85c7 100644 --- a/libraries/octree/src/JurisdictionSender.h +++ b/libraries/octree/src/JurisdictionSender.h @@ -27,7 +27,7 @@ class JurisdictionSender : public ReceivedPacketProcessor { public: static const int DEFAULT_PACKETS_PER_SECOND = 1; - JurisdictionSender(JurisdictionMap* map, NodeType_t type = NodeType::VoxelServer); + JurisdictionSender(JurisdictionMap* map, NodeType_t type = NodeType::EntityServer); ~JurisdictionSender(); void setJurisdiction(JurisdictionMap* map) { _jurisdictionMap = map; } From 67595ea5714ad52652c81fc62314fe3d8ecd3825 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 20:35:21 -0800 Subject: [PATCH 10/27] more voxelEctomy --- libraries/networking/src/PacketHeaders.cpp | 11 ----------- libraries/networking/src/PacketHeaders.h | 16 ++++++++-------- libraries/octree/src/Octree.cpp | 12 ------------ 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 3f08cdec69..b5adddf307 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -68,9 +68,6 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeCreateAssignment: case PacketTypeRequestAssignment: return 2; - case PacketTypeVoxelSet: - case PacketTypeVoxelSetDestructive: - return 1; case PacketTypeOctreeStats: return 1; case PacketTypeEntityAddOrEdit: @@ -82,8 +79,6 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeMetavoxelData: return 10; - case PacketTypeVoxelData: - return VERSION_VOXELS_HAS_FILE_BREAKS; default: return 0; } @@ -114,11 +109,6 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeMuteEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioStreamStats); PACKET_TYPE_NAME_LOOKUP(PacketTypeDataServerConfirm); - PACKET_TYPE_NAME_LOOKUP(PacketTypeVoxelQuery); - PACKET_TYPE_NAME_LOOKUP(PacketTypeVoxelData); - PACKET_TYPE_NAME_LOOKUP(PacketTypeVoxelSet); - PACKET_TYPE_NAME_LOOKUP(PacketTypeVoxelSetDestructive); - PACKET_TYPE_NAME_LOOKUP(PacketTypeVoxelErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeStats); PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdiction); PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdictionRequest); @@ -134,7 +124,6 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); - PACKET_TYPE_NAME_LOOKUP(PacketTypeVoxelEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 7557ea31e1..a0d342459c 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -42,11 +42,11 @@ enum PacketType { PacketTypeMuteEnvironment, PacketTypeAudioStreamStats, PacketTypeDataServerConfirm, // 20 - PacketTypeVoxelQuery, - PacketTypeVoxelData, - PacketTypeVoxelSet, - PacketTypeVoxelSetDestructive, - PacketTypeVoxelErase, // 25 + UNUSED_5, + UNUSED_6, + UNUSED_7, + UNUSED_8, + UNUSED_9, // 25 PacketTypeOctreeStats, PacketTypeJurisdiction, PacketTypeJurisdictionRequest, @@ -67,7 +67,7 @@ enum PacketType { PacketTypeEntityErase, PacketTypeEntityAddResponse, PacketTypeOctreeDataNack, // 45 - PacketTypeVoxelEditNack, + UNUSED_10, PacketTypeAudioEnvironment, PacketTypeEntityEditNack, PacketTypeSignedTransactionPayment, @@ -83,8 +83,8 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest << PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainConnectionDenied << PacketTypeCreateAssignment << PacketTypeRequestAssignment << PacketTypeStunResponse - << PacketTypeNodeJsonStats << PacketTypeVoxelQuery << PacketTypeEntityQuery - << PacketTypeOctreeDataNack << PacketTypeVoxelEditNack << PacketTypeEntityEditNack + << PacketTypeNodeJsonStats << PacketTypeEntityQuery + << PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index e41730e63c..9abf0ec7a1 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1946,18 +1946,6 @@ bool Octree::readFromSVOFile(const char* fileName) { dataLength -= sizeof(expectedType); gotVersion = *dataAt; - // NOTE: SPECIAL CASE for old voxel svo files. The old voxel SVO files didn't have header - // details. They started with the the octalcode for the root. Which was always 00 which matches PacketTypeUnknown - unsigned char* firstByteAt = (unsigned char*)&fileHeader; - unsigned char firstByteValue = *firstByteAt; - if (expectedType == PacketTypeVoxelData && firstByteValue == 0) { - gotType = PacketTypeVoxelData; - gotVersion = 0; - qDebug() << "Detected OLD Voxels format."; - headerLength = 0; // old format files don't have headers - file.seekg( 0, std::ios::beg ); // rewind to the beginning so old logic will work - } - if (gotType == expectedType) { if (canProcessVersion(gotVersion)) { dataAt += sizeof(gotVersion); From 48285b21c4a77aa72689e56200d8bcbc275bd800 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Dec 2014 20:50:07 -0800 Subject: [PATCH 11/27] remove voxel related scripts --- examples/ControlACs.js | 10 +- examples/acScripts/ControlledAC.js | 14 +- examples/addVoxelOnMouseClickExample.js | 64 - examples/clipboardExample.js | 162 --- examples/editModels.js | 2 +- examples/editVoxels.js | 1518 ----------------------- examples/fallingSand.js | 648 ---------- examples/fountain.js | 2 +- examples/gameoflife.js | 140 --- examples/gamepad.js | 2 +- examples/grenadeLauncher.js | 40 - examples/growTrees.js | 834 ------------- examples/gun.js | 14 - examples/inspect.js | 9 - examples/libraries/ModelImporter.js | 2 +- examples/libraries/walkApi.js | 4 +- examples/lookAtExample.js | 2 +- examples/movingVoxel.js | 52 - examples/rayPickExample.js | 24 - examples/ribbon.js | 176 --- examples/rockPaperScissorsCells.js | 272 ---- examples/voxelsoundwaves.js | 226 ---- examples/voxelwall.js | 103 -- 23 files changed, 17 insertions(+), 4303 deletions(-) delete mode 100644 examples/addVoxelOnMouseClickExample.js delete mode 100644 examples/clipboardExample.js delete mode 100644 examples/editVoxels.js delete mode 100644 examples/fallingSand.js delete mode 100644 examples/gameoflife.js delete mode 100644 examples/growTrees.js delete mode 100644 examples/movingVoxel.js delete mode 100644 examples/ribbon.js delete mode 100644 examples/rockPaperScissorsCells.js delete mode 100644 examples/voxelsoundwaves.js delete mode 100644 examples/voxelwall.js diff --git a/examples/ControlACs.js b/examples/ControlACs.js index 73a4385c24..0edbde4ad1 100644 --- a/examples/ControlACs.js +++ b/examples/ControlACs.js @@ -145,13 +145,9 @@ function sendCommand(id, action) { return; } - Voxels.setVoxel(controlVoxelPosition.x + id * controlVoxelSize, - controlVoxelPosition.y, - controlVoxelPosition.z, - controlVoxelSize, - COLORS[action].red, - COLORS[action].green, - COLORS[action].blue); + // TODO: Fix this to use some mechanism other than voxels + //Voxels.setVoxel(controlVoxelPosition.x + id * controlVoxelSize, controlVoxelPosition.y, controlVoxelPosition.z, + // controlVoxelSize, COLORS[action].red, COLORS[action].green, COLORS[action].blue); } function mousePressEvent(event) { diff --git a/examples/acScripts/ControlledAC.js b/examples/acScripts/ControlledAC.js index b19d27946a..4e400670e5 100644 --- a/examples/acScripts/ControlledAC.js +++ b/examples/acScripts/ControlledAC.js @@ -82,10 +82,9 @@ function getAction(controlVoxel) { if (controlVoxel.red === COLORS[i].red && controlVoxel.green === COLORS[i].green && controlVoxel.blue === COLORS[i].blue) { - Voxels.eraseVoxel(controlVoxelPosition.x, - controlVoxelPosition.y, - controlVoxelPosition.z, - controlVoxelSize); + + // TODO: Fix this to use some mechanism other than voxels + //Voxels.eraseVoxel(controlVoxelPosition.x, controlVoxelPosition.y, controlVoxelPosition.z, controlVoxelSize); return parseInt(i); } } @@ -101,10 +100,9 @@ function update(event) { return; } - var controlVoxel = Voxels.getVoxelAt(controlVoxelPosition.x, - controlVoxelPosition.y, - controlVoxelPosition.z, - controlVoxelSize); + // TODO: Fix this to use some mechanism other than voxels + // Voxels.getVoxelAt(controlVoxelPosition.x, controlVoxelPosition.y, controlVoxelPosition.z, controlVoxelSize); + var controlVoxel = false; var action = getAction(controlVoxel); switch(action) { diff --git a/examples/addVoxelOnMouseClickExample.js b/examples/addVoxelOnMouseClickExample.js deleted file mode 100644 index 4fa175577c..0000000000 --- a/examples/addVoxelOnMouseClickExample.js +++ /dev/null @@ -1,64 +0,0 @@ -// -// addVoxelOnMouseClickExample.js -// examples -// -// Created by Brad Hefta-Gaub on 2/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// This is an example script that demonstrates use of the Camera and Voxels class to implement -// clicking on a voxel and adding a new voxel on the clicked on face -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -function mousePressEvent(event) { - print("mousePressEvent event.x,y=" + event.x + ", " + event.y); - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - if (intersection.intersects) { - - // Note: due to the current C++ "click on voxel" behavior, these values may be the animated color for the voxel - print("clicked on voxel.red/green/blue=" + intersection.voxel.red + ", " - + intersection.voxel.green + ", " + intersection.voxel.blue); - print("clicked on voxel.x/y/z/s=" + intersection.voxel.x + ", " - + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); - print("clicked on face=" + intersection.face); - print("clicked on distance=" + intersection.distance); - - var newVoxel = { - x: intersection.voxel.x, - y: intersection.voxel.y, - z: intersection.voxel.z, - s: intersection.voxel.s, - red: 255, - green: 0, - blue: 255 }; - - if (intersection.face == "MIN_X_FACE") { - newVoxel.x -= newVoxel.s; - } else if (intersection.face == "MAX_X_FACE") { - newVoxel.x += newVoxel.s; - } else if (intersection.face == "MIN_Y_FACE") { - newVoxel.y -= newVoxel.s; - } else if (intersection.face == "MAX_Y_FACE") { - newVoxel.y += newVoxel.s; - } else if (intersection.face == "MIN_Z_FACE") { - newVoxel.z -= newVoxel.s; - } else if (intersection.face == "MAX_Z_FACE") { - newVoxel.z += newVoxel.s; - } - - print("Voxels.setVoxel("+newVoxel.x + ", " - + newVoxel.y + ", " + newVoxel.z + ", " + newVoxel.s + ", " - + newVoxel.red + ", " + newVoxel.green + ", " + newVoxel.blue + ")" ); - - Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); - } -} - -Controller.mousePressEvent.connect(mousePressEvent); - -function scriptEnding() { -} -Script.scriptEnding.connect(scriptEnding); diff --git a/examples/clipboardExample.js b/examples/clipboardExample.js deleted file mode 100644 index 0b6371e2b7..0000000000 --- a/examples/clipboardExample.js +++ /dev/null @@ -1,162 +0,0 @@ -// -// clipboardExample.js -// examples -// -// Created by Brad Hefta-Gaub on 1/28/14. -// Copyright 2014 High Fidelity, Inc. -// -// This is an example script that demonstrates use of the Clipboard class -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var selectedVoxel = { x: 0, y: 0, z: 0, s: 0 }; -var selectedSize = 4; - -function setupMenus() { - // hook up menus - Menu.menuItemEvent.connect(menuItemEvent); - - // delete the standard application menu item - Menu.removeMenuItem("Edit", "Cut"); - Menu.removeMenuItem("Edit", "Copy"); - Menu.removeMenuItem("Edit", "Paste"); - Menu.removeMenuItem("Edit", "Delete"); - Menu.removeMenuItem("Edit", "Nudge"); - Menu.removeMenuItem("Edit", "Replace from File"); - Menu.removeMenuItem("File", "Export Voxels"); - Menu.removeMenuItem("File", "Import Voxels"); - - // delete the standard application menu item - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Cut", shortcutKey: "CTRL+X", afterItem: "Voxels" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Copy", shortcutKey: "CTRL+C", afterItem: "Cut" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste", shortcutKey: "CTRL+V", afterItem: "Copy" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Nudge", shortcutKey: "CTRL+N", afterItem: "Paste" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Replace from File", shortcutKey: "CTRL+R", afterItem: "Nudge" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", shortcutKeyEvent: { text: "backspace" }, afterItem: "Nudge" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Export Voxels", shortcutKey: "CTRL+E", afterItem: "Voxels" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Import Voxels", shortcutKey: "CTRL+I", afterItem: "Export Voxels" }); -} - -function menuItemEvent(menuItem) { - var debug = true; - if (debug) { - print("menuItemEvent " + menuItem); - } - - // Note: this sample uses Alt+ as the key codes for these clipboard items - if (menuItem == "Copy") { - print("copying..."); - Clipboard.copyVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Cut") { - print("cutting..."); - Clipboard.cutVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Paste") { - print("pasting..."); - Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Delete") { - print("deleting..."); - Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Export Voxels") { - print("export"); - Clipboard.exportVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Import Voxels") { - print("import"); - Clipboard.importVoxels(); - } - if (menuItem == "Nudge") { - print("nudge"); - Clipboard.nudgeVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s, { x: -1, y: 0, z: 0 }); - } - if (menuItem == "Replace from File") { - var filename = Window.browse("Select file to load replacement", "", "Voxel Files (*.png *.svo *.schematic)"); - if (filename) { - Clipboard.importVoxel(filename, selectedVoxel); - } - } -} - -var selectCube = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0}, - size: selectedSize, - color: { red: 255, green: 255, blue: 0}, - alpha: 1, - solid: false, - visible: false, - lineWidth: 4 - }); - - -function mouseMoveEvent(event) { - - var pickRay = Camera.computePickRay(event.x, event.y); - - var debug = false; - if (debug) { - print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y); - print("called Camera.computePickRay()"); - print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z); - print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z); - } - - var intersection = Voxels.findRayIntersection(pickRay); - - if (intersection.intersects) { - if (debug) { - print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", " - + intersection.voxel.green + ", " + intersection.voxel.blue); - print("intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " - + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); - print("intersection face=" + intersection.face); - print("intersection distance=" + intersection.distance); - print("intersection intersection.x/y/z=" + intersection.intersection.x + ", " - + intersection.intersection.y + ", " + intersection.intersection.z); - } - - - - var x = Math.floor(intersection.voxel.x / selectedSize) * selectedSize; - var y = Math.floor(intersection.voxel.y / selectedSize) * selectedSize; - var z = Math.floor(intersection.voxel.z / selectedSize) * selectedSize; - selectedVoxel = { x: x, y: y, z: z, s: selectedSize }; - Overlays.editOverlay(selectCube, { position: selectedVoxel, size: selectedSize, visible: true } ); - } else { - Overlays.editOverlay(selectCube, { visible: false } ); - selectedVoxel = { x: 0, y: 0, z: 0, s: 0 }; - } -} - -Controller.mouseMoveEvent.connect(mouseMoveEvent); - -function wheelEvent(event) { - var debug = false; - if (debug) { - print("wheelEvent"); - print(" event.x,y=" + event.x + ", " + event.y); - print(" event.delta=" + event.delta); - print(" event.orientation=" + event.orientation); - print(" event.isLeftButton=" + event.isLeftButton); - print(" event.isRightButton=" + event.isRightButton); - print(" event.isMiddleButton=" + event.isMiddleButton); - print(" event.isShifted=" + event.isShifted); - print(" event.isControl=" + event.isControl); - print(" event.isMeta=" + event.isMeta); - print(" event.isAlt=" + event.isAlt); - } -} - -Controller.wheelEvent.connect(wheelEvent); - -function scriptEnding() { - Overlays.deleteOverlay(selectCube); -} - -Script.scriptEnding.connect(scriptEnding); - -setupMenus(); \ No newline at end of file diff --git a/examples/editModels.js b/examples/editModels.js index e0ade3b6a3..491e6c9f33 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1720,7 +1720,7 @@ var ModelImporter = function (opts) { this.mouseMoveEvent = function (event) { if (self._importing) { var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); + var intersection = false; //Voxels.findRayIntersection(pickRay); var distance = 2;// * self._scale; diff --git a/examples/editVoxels.js b/examples/editVoxels.js deleted file mode 100644 index ff096973a3..0000000000 --- a/examples/editVoxels.js +++ /dev/null @@ -1,1518 +0,0 @@ -// -// editVoxels.js -// examples -// -// Created by Philip Rosedale on February 8, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// Captures mouse clicks and edits voxels accordingly. -// -// click = create a new voxel on this face, same color as old (default color picker state) -// right click or control + click = delete this voxel -// shift + click = recolor this voxel -// 1 - 8 = pick new color from palette -// 9 = create a new voxel in front of the camera -// -// Click and drag to create more new voxels in the same direction -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var editToolsOn = true; // starts out off - -var windowDimensions = Controller.getViewportDimensions(); -var WORLD_SCALE = Voxels.getTreeScale(); - -var NEW_VOXEL_SIZE = 1.0; -var NEW_VOXEL_DISTANCE_FROM_CAMERA = 3.0; -var PIXELS_PER_EXTRUDE_VOXEL = 16; -var WHEEL_PIXELS_PER_SCALE_CHANGE = 100; -var MAX_VOXEL_SCALE_POWER = 4; -var MIN_VOXEL_SCALE_POWER = -8; -var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER); -var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER); -var WHITE_COLOR = { red: 255, green: 255, blue: 255 }; - -var MAX_PASTE_VOXEL_SCALE = 256; -var MIN_PASTE_VOXEL_SCALE = .256; - -var zFightingSizeAdjustRatio = 0.004; // used to adjust preview voxels to prevent z fighting -var previewLineWidth = 1.5; - -var inspectJsIsRunning = false; -var isAdding = false; -var isExtruding = false; -var extrudeDirection = { x: 0, y: 0, z: 0 }; -var extrudeScale = 0.0; -var lastVoxelPosition = { x: 0, y: 0, z: 0 }; -var lastVoxelColor = { red: 0, green: 0, blue: 0 }; -var lastVoxelScale = 0; -var dragStart = { x: 0, y: 0 }; -var wheelPixelsMoved = 0; - -// Create a table of the different colors you can choose -var colors = new Array(); -colors[0] = { red: 120, green: 181, blue: 126 }; -colors[1] = { red: 75, green: 155, blue: 103 }; -colors[2] = { red: 56, green: 132, blue: 86 }; -colors[3] = { red: 83, green: 211, blue: 83 }; -colors[4] = { red: 236, green: 174, blue: 0 }; -colors[5] = { red: 234, green: 133, blue: 0 }; -colors[6] = { red: 211, green: 115, blue: 0 }; -colors[7] = { red: 48, green: 116, blue: 119 }; -colors[8] = { red: 36, green: 64, blue: 64 }; -var numColors = 9; -var whichColor = 0; // Starting color is 'Copy' mode - -// Create sounds for for every script actions that require one -// start with audio slightly above the avatar -var audioOptions = { - position: Vec3.sum(MyAvatar.position, { x: 0, y: 1, z: 0 } ), - volume: 1.0 -}; - -function SoundArray() { - this.audioOptions = audioOptions - this.sounds = new Array(); - this.addSound = function (soundURL) { - this.sounds[this.sounds.length] = SoundCache.getSound(soundURL); - } - this.play = function (index) { - if (0 <= index && index < this.sounds.length) { - Audio.playSound(this.sounds[index], this.audioOptions); - } else { - print("[ERROR] editVoxels.js:randSound.play() : Index " + index + " out of range."); - } - } - this.playRandom = function () { - if (this.sounds.length > 0) { - rand = Math.floor(Math.random() * this.sounds.length); - Audio.playSound(this.sounds[rand], this.audioOptions); - } else { - print("[ERROR] editVoxels.js:randSound.playRandom() : Array is empty."); - } - } -} - -var addVoxelSound = new SoundArray(); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+1.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+2.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+3.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+4.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+5.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+6.raw"); - -var delVoxelSound = new SoundArray(); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+A1.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+A2.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+A3.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+B1.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+B2.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+B3.raw"); - -var resizeVoxelSound = new SoundArray(); -resizeVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Size/V+Size+Minus.raw"); -resizeVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Size/V+Size+Plus.raw"); -var voxelSizeMinus = 0; -var voxelSizePlus = 1; - -var swatchesSound = new SoundArray(); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+1.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+2.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+3.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+4.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+5.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+6.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+7.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+8.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+9.raw"); - -var undoSound = new SoundArray(); -undoSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Undo/Undo+1.raw"); -undoSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Undo/Undo+2.raw"); -undoSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Undo/Undo+3.raw"); - -var scriptInitSound = new SoundArray(); -scriptInitSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Script+Init/Script+Init+A.raw"); -scriptInitSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Script+Init/Script+Init+B.raw"); -scriptInitSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Script+Init/Script+Init+C.raw"); -scriptInitSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Script+Init/Script+Init+D.raw"); - -var modeSwitchSound = new SoundArray(); -modeSwitchSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Mode+Switch/Mode+1.raw"); -modeSwitchSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Mode+Switch/Mode+2.raw"); -modeSwitchSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Mode+Switch/Mode+3.raw"); - -var initialVoxelSound = new SoundArray(); -initialVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Initial+Voxel/Initial+V.raw"); - -var colorInheritSound = new SoundArray(); -colorInheritSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Color+Inherit/Inherit+A.raw"); -colorInheritSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Color+Inherit/Inherit+B.raw"); -colorInheritSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Color+Inherit/Inherit+C.raw"); - -// previewAsVoxel - by default, we will preview adds/deletes/recolors as just 4 lines on the intersecting face. But if you -// the preview to show a full voxel then set this to true and the voxel will be displayed for voxel editing -var previewAsVoxel = false; - -var voxelPreview = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0}, - size: 1, - color: { red: 255, green: 0, blue: 0}, - alpha: 1, - solid: false, - visible: false, - lineWidth: 4 - }); - -var linePreviewTop = []; -var linePreviewBottom = []; -var linePreviewLeft = []; -var linePreviewRight = []; - -// Currend cursor index -var currentCursor = 0; - -function addLineOverlay() { - return Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); -} - -//Cursor line previews for up to three cursors -linePreviewTop[0] = addLineOverlay(); -linePreviewTop[1] = addLineOverlay(); -linePreviewTop[2] = addLineOverlay(); - -linePreviewBottom[0] = addLineOverlay(); -linePreviewBottom[1] = addLineOverlay(); -linePreviewBottom[2] = addLineOverlay(); - -linePreviewLeft[0] = addLineOverlay(); -linePreviewLeft[1] = addLineOverlay(); -linePreviewLeft[2] = addLineOverlay(); - -linePreviewRight[0] = addLineOverlay(); -linePreviewRight[1] = addLineOverlay(); -linePreviewRight[2] = addLineOverlay(); - -// these will be used below -var scaleSelectorWidth = 144; -var scaleSelectorHeight = 37; - -// These will be our "overlay IDs" -var swatches = new Array(); -var swatchExtraPadding = 5; -var swatchHeight = 37; -var swatchWidth = 27; -var swatchesWidth = swatchWidth * numColors + numColors + swatchExtraPadding * 2; -var swatchesX = (windowDimensions.x - (swatchesWidth + scaleSelectorWidth)) / 2; -var swatchesY = windowDimensions.y - swatchHeight + 1; - -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; - -// create the overlays, position them in a row, set their colors, and for the selected one, use a different source image -// location so that it displays the "selected" marker -for (s = 0; s < numColors; s++) { - - var extraWidth = 0; - - if (s == 0) { - extraWidth = swatchExtraPadding; - } - - var imageFromX = swatchExtraPadding - extraWidth + s * swatchWidth; - var imageFromY = swatchHeight + 1; - - var swatchX = swatchExtraPadding - extraWidth + swatchesX + ((swatchWidth - 1) * s); - - if (s == (numColors - 1)) { - extraWidth = swatchExtraPadding; - } - - swatches[s] = Overlays.addOverlay("image", { - x: swatchX, - y: swatchesY, - width: swatchWidth + extraWidth, - height: swatchHeight, - subImage: { x: imageFromX, y: imageFromY, width: swatchWidth + extraWidth, height: swatchHeight }, - imageURL: toolIconUrl + "swatches.svg", - color: colors[s], - alpha: 1, - visible: editToolsOn - }); -} - - -// These will be our tool palette overlays -var numberOfTools = 3; -var toolHeight = 50; -var toolWidth = 50; -var toolVerticalSpacing = 4; -var toolsHeight = toolHeight * numberOfTools + toolVerticalSpacing * (numberOfTools - 1); -var toolsX = 8; -var toolsY = (windowDimensions.y - toolsHeight) / 2; - -var voxelToolAt = 0; -var recolorToolAt = 1; -var eyedropperToolAt = 2; - -var pasteModeColor = { red: 132, green: 61, blue: 255 }; - -var voxelTool = Overlays.addOverlay("image", { - x: 0, y: 0, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-tool.svg", - visible: editToolsOn, - alpha: 0.9 - }); - -var recolorTool = Overlays.addOverlay("image", { - x: 0, y: 0, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "paint-tool.svg", - visible: editToolsOn, - alpha: 0.9 - }); - -var eyedropperTool = Overlays.addOverlay("image", { - x: 0, y: 0, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "eyedropper-tool.svg", - visible: editToolsOn, - alpha: 0.9 - }); - - -var copyScale = true; -function ScaleSelector() { - this.x = swatchesX + swatchesWidth; - this.y = swatchesY; - this.width = scaleSelectorWidth; - this.height = scaleSelectorHeight; - - this.displayPower = false; - this.scale = 1.0; - this.power = 0; - - this.FIRST_PART = this.width * 40.0 / 100.0; - this.SECOND_PART = this.width * 37.0 / 100.0; - - this.buttonsOverlay = Overlays.addOverlay("image", { - x: this.x, y: this.y, - width: this.width, height: this.height, - //subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - visible: editToolsOn - }); - this.textOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - topMargin: 13, - text: this.scale.toString(), - backgroundAlpha: 0.0, - visible: editToolsOn - }); - this.powerOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - leftMargin: 28, - text: this.power.toString(), - backgroundAlpha: 0.0, - visible: false - }); - this.setScale = function(scale) { - if (scale > MAX_VOXEL_SCALE) { - scale = MAX_VOXEL_SCALE; - } - if (scale < MIN_VOXEL_SCALE) { - scale = MIN_VOXEL_SCALE; - } - - this.scale = scale; - this.power = Math.floor(Math.log(scale) / Math.log(2)); - rescaleImport(); - this.update(); - } - - this.show = function(doShow) { - Overlays.editOverlay(this.buttonsOverlay, {visible: doShow}); - Overlays.editOverlay(this.textOverlay, {visible: doShow}); - Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower}); - } - - this.move = function() { - this.x = swatchesX + swatchesWidth; - this.y = swatchesY; - - Overlays.editOverlay(this.buttonsOverlay, { - x: this.x, y: this.y, - }); - Overlays.editOverlay(this.textOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - Overlays.editOverlay(this.powerOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - } - - - this.switchDisplay = function() { - this.displayPower = !this.displayPower; - - if (this.displayPower) { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 18, - text: "2" - }); - Overlays.editOverlay(this.powerOverlay, { - text: this.power.toString(), - visible: editToolsOn - }); - } else { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 13, - text: this.scale.toString() - }); - Overlays.editOverlay(this.powerOverlay, { - visible: false - }); - } - } - - this.update = function() { - if (this.displayPower) { - Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()}); - } else { - Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()}); - } - } - - this.incrementScale = function() { - copyScale = false; - if (this.power < MAX_VOXEL_SCALE_POWER) { - ++this.power; - this.scale *= 2.0; - this.update(); - rescaleImport(); - resizeVoxelSound.play(voxelSizePlus); - } - } - - this.decrementScale = function() { - copyScale = false; - if (MIN_VOXEL_SCALE_POWER < this.power) { - --this.power; - this.scale /= 2.0; - this.update(); - rescaleImport(); - resizeVoxelSound.play(voxelSizePlus); - } - } - - this.clicked = function(x, y) { - if (this.x < x && x < this.x + this.width && - this.y < y && y < this.y + this.height) { - - if (x < this.x + this.FIRST_PART) { - this.decrementScale(); - } else if (x < this.x + this.FIRST_PART + this.SECOND_PART) { - this.switchDisplay(); - } else { - this.incrementScale(); - } - return true; - } - return false; - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.buttonsOverlay); - Overlays.deleteOverlay(this.textOverlay); - Overlays.deleteOverlay(this.powerOverlay); - } - -} -var scaleSelector = new ScaleSelector(); - - -///////////////////////////////////// IMPORT MODULE /////////////////////////////// -// Move the following code to a separate file when include will be available. -var importTree; -var importPreview; -var importBoundaries; -var xImportGuide; -var yImportGuide; -var zImportGuide; -var isImporting; -var importPosition; -var importDistance; - -function initImport() { - importPreview = Overlays.addOverlay("localvoxels", { - name: "import", - position: { x: 0, y: 0, z: 0}, - scale: 1, - visible: false - }); - importBoundaries = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: 1, - color: { red: 128, blue: 128, green: 128 }, - lineWIdth: 4, - solid: false, - visible: false - }); - - xImportGuide = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 255, green: 0, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - yImportGuide = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - zImportGuide = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - - - isImporting = false; - importPosition = { x: 0, y: 0, z: 0 }; -} - -function importVoxels() { - isImporting = Clipboard.importVoxels(); - return isImporting; -} - -function moveImport(position) { - importPosition = position; - Overlays.editOverlay(importPreview, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - Overlays.editOverlay(importBoundaries, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - - - Overlays.editOverlay(xImportGuide, { - position: { x: importPosition.x, y: 0, z: importPosition.z }, - end: { x: importPosition.x + scaleSelector.scale, y: 0, z: importPosition.z } - }); - Overlays.editOverlay(yImportGuide, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z }, - end: { x: importPosition.x, y: 0, z: importPosition.z } - }); - Overlays.editOverlay(zImportGuide, { - position: { x: importPosition.x, y: 0, z: importPosition.z }, - end: { x: importPosition.x, y: 0, z: importPosition.z + scaleSelector.scale } - }); - rescaleImport(); -} - -function rescaleImport() { - if (0 < scaleSelector.scale) { - Overlays.editOverlay(importPreview, { - scale: scaleSelector.scale - }); - Overlays.editOverlay(importBoundaries, { - size: scaleSelector.scale - }); - - Overlays.editOverlay(xImportGuide, { - end: { x: importPosition.x + scaleSelector.scale, y: 0, z: importPosition.z } - }); - Overlays.editOverlay(yImportGuide, { - end: { x: importPosition.x, y: 0, z: importPosition.z } - }); - Overlays.editOverlay(zImportGuide, { - end: { x: importPosition.x, y: 0, z: importPosition.z + scaleSelector.scale } - }); - } -} - -function showImport(doShow) { - Overlays.editOverlay(importPreview, { - visible: doShow - }); - Overlays.editOverlay(importBoundaries, { - visible: doShow - }); - - Overlays.editOverlay(xImportGuide, { - visible: doShow - }); - Overlays.editOverlay(yImportGuide, { - visible: doShow - }); - Overlays.editOverlay(zImportGuide, { - visible: doShow - }); -} - -function placeImport() { - if (isImporting) { - Clipboard.pasteVoxel(importPosition.x, importPosition.y, importPosition.z, scaleSelector.scale); - isImporting = false; - } -} - -function cancelImport() { - if (isImporting) { - isImporting = false; - showImport(false); - } -} - -function cleanupImport() { - Overlays.deleteOverlay(importPreview); - Overlays.deleteOverlay(importBoundaries); - Overlays.deleteOverlay(xImportGuide); - Overlays.deleteOverlay(yImportGuide); - Overlays.deleteOverlay(zImportGuide); - isImporting = false; - importPostion = { x: 0, y: 0, z: 0 }; -} -/////////////////////////////////// END IMPORT MODULE ///////////////////////////// -initImport(); - -if (editToolsOn) { - moveTools(); -} - -function setAudioPosition() { - var position = MyAvatar.position; - var forwardVector = Quat.getFront(MyAvatar.orientation); - audioOptions.position = Vec3.sum(position, forwardVector); -} - -function getNewPasteVoxel(pickRay) { - - var voxelSize = scaleSelector.scale; - var origin = { x: pickRay.direction.x, y: pickRay.direction.y, z: pickRay.direction.z }; - - origin.x += pickRay.origin.x; - origin.y += pickRay.origin.y; - origin.z += pickRay.origin.z; - - origin.x -= voxelSize / 2; - origin.y -= voxelSize / 2; - origin.z += voxelSize / 2; - - return {origin: origin, voxelSize: voxelSize}; -} - -function getNewVoxelPosition() { - var camera = Camera.getPosition(); - var forwardVector = Quat.getFront(MyAvatar.orientation); - var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, NEW_VOXEL_DISTANCE_FROM_CAMERA)); - return newPosition; -} - -var trackLastMouseX = 0; -var trackLastMouseY = 0; -var trackAsDelete = false; -var trackAsRecolor = false; -var trackAsEyedropper = false; - -var voxelToolSelected = false; -var recolorToolSelected = false; -var eyedropperToolSelected = false; -var pasteMode = false; - - -function calculateVoxelFromIntersection(intersection, operation) { - //print("calculateVoxelFromIntersection() operation="+operation); - var resultVoxel; - - var wantDebug = false; - if (wantDebug) { - print(">>>>> calculateVoxelFromIntersection().... intersection voxel.red/green/blue=" + intersection.voxel.red + ", " - + intersection.voxel.green + ", " + intersection.voxel.blue); - print(" intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " - + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); - print(" intersection face=" + intersection.face); - print(" intersection distance=" + intersection.distance); - print(" intersection intersection.x/y/z=" + intersection.intersection.x + ", " - + intersection.intersection.y + ", " + intersection.intersection.z); - } - - var voxelSize = scaleSelector.scale; - var x; - var y; - var z; - - // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest - // ancestor voxel of our target size that contains our intersected voxel. - if (voxelSize > intersection.voxel.s) { - if (wantDebug) { - print("voxelSize > intersection.voxel.s.... choose the larger voxel that encompasses the one selected"); - } - x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize; - y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize; - z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize; - } else { - // otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of. - // if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result - // in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting - // voxel this still works and results in returning the intersecting voxel which is what we want - var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5)); - if (wantDebug) { - print("adjustToCenter=" + adjustToCenter.x + "," + adjustToCenter.y + "," + adjustToCenter.z); - } - var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter); - x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize; - y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize; - z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize; - } - resultVoxel = { x: x, y: y, z: z, s: voxelSize }; - highlightAt = { x: x, y: y, z: z, s: voxelSize }; - - // we only do the "add to the face we're pointing at" adjustment, if the operation is an add - // operation, and the target voxel size is equal to or smaller than the intersecting voxel. - var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s)); - if (wantDebug) { - print("wantAddAdjust="+wantAddAdjust); - } - - var zFightingSizeAdjust = zFightingSizeAdjustRatio * intersection.distance; - - // now we also want to calculate the "edge square" for the face for this voxel - if (intersection.face == "MIN_X_FACE") { - - highlightAt.x = x - zFightingSizeAdjust; - highlightAt.y = y + zFightingSizeAdjust; - highlightAt.z = z + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x -= voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z + voxelSize }; - - } else if (intersection.face == "MAX_X_FACE") { - - highlightAt.x = x + voxelSize + zFightingSizeAdjust; - highlightAt.y = y + zFightingSizeAdjust; - highlightAt.z = z + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x += resultVoxel.s; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z + voxelSize }; - - } else if (intersection.face == "MIN_Y_FACE") { - - highlightAt.x = x + zFightingSizeAdjust; - highlightAt.y = y - zFightingSizeAdjust; - highlightAt.z = z + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y -= voxelSize; - } - - resultVoxel.topRight = {x: highlightAt.x , y: highlightAt.y, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x , y: highlightAt.y, z: highlightAt.z + voxelSize }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize , y: highlightAt.y, z: highlightAt.z + voxelSize }; - - } else if (intersection.face == "MAX_Y_FACE") { - - highlightAt.x = x + zFightingSizeAdjust; - highlightAt.y = y + voxelSize + zFightingSizeAdjust; - highlightAt.z = z + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y += resultVoxel.s; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z}; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize}; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z + voxelSize}; - - } else if (intersection.face == "MIN_Z_FACE") { - - highlightAt.x = x + zFightingSizeAdjust; - highlightAt.y = y + zFightingSizeAdjust; - highlightAt.z = z - zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z -= voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z}; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y + voxelSize, z: highlightAt.z}; - - } else if (intersection.face == "MAX_Z_FACE") { - - highlightAt.x = x + zFightingSizeAdjust; - highlightAt.y = y + zFightingSizeAdjust; - highlightAt.z = z + voxelSize + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z += resultVoxel.s; - } - - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z}; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; - resultVoxel.topRight = {x: highlightAt.x + voxelSize, y: highlightAt.y + voxelSize, z: highlightAt.z}; - - } - - return resultVoxel; -} - -function showPreviewVoxel() { - var voxelColor; - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - var intersection = Voxels.findRayIntersection(pickRay); - - voxelColor = { red: colors[whichColor].red, - green: colors[whichColor].green, - blue: colors[whichColor].blue }; - - var guidePosition; - if (trackAsRecolor || recolorToolSelected || trackAsEyedropper || eyedropperToolSelected) { - Overlays.editOverlay(voxelPreview, { visible: true }); - } else if (voxelToolSelected && !isExtruding) { - Overlays.editOverlay(voxelPreview, { visible: true }); - } else if (isExtruding) { - Overlays.editOverlay(voxelPreview, { visible: false }); - } -} - -function showPreviewLines() { - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - - if (pasteMode) { // free voxel pasting - - Overlays.editOverlay(voxelPreview, { visible: false }); - Overlays.editOverlay(linePreviewLeft, { visible: false }); - - var pasteVoxel = getNewPasteVoxel(pickRay); - - // X axis - Overlays.editOverlay(linePreviewBottom[currentCursor], { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x + pasteVoxel.voxelSize, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z }, - visible: true - }); - - // Y axis - Overlays.editOverlay(linePreviewRight[currentCursor], { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y + pasteVoxel.voxelSize, z: pasteVoxel.origin.z }, - visible: true - }); - - // Z axis - Overlays.editOverlay(linePreviewTop[currentCursor], { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z - pasteVoxel.voxelSize }, - visible: true - }); - - return; - } - - var intersection = Voxels.findRayIntersection(pickRay); - - if (intersection.intersects) { - resultVoxel = calculateVoxelFromIntersection(intersection,""); - Overlays.editOverlay(voxelPreview, { visible: false }); - Overlays.editOverlay(linePreviewTop[currentCursor], { position: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true }); - Overlays.editOverlay(linePreviewBottom[currentCursor], { position: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true }); - Overlays.editOverlay(linePreviewLeft[currentCursor], { position: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true }); - Overlays.editOverlay(linePreviewRight[currentCursor], { position: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true }); - colors[0] = {red: intersection.voxel.red, green: intersection.voxel.green , blue: intersection.voxel.blue }; - - if (copyScale) { - scaleSelector.setScale(intersection.voxel.s); - } - moveTools(); - } else if (intersection.accurate) { - Overlays.editOverlay(voxelPreview, { visible: false }); - Overlays.editOverlay(linePreviewTop[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewBottom[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewLeft[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewRight[currentCursor], { visible: false }); - } -} - -function showPreviewGuides() { - if (editToolsOn && !isImporting && (voxelToolSelected || recolorToolSelected || eyedropperToolSelected)) { - if (previewAsVoxel) { - showPreviewVoxel(); - - // make sure alternative is hidden - Overlays.editOverlay(linePreviewTop[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewBottom[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewLeft[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewRight[currentCursor], { visible: false }); - } else { - showPreviewLines(); - } - } else { - // make sure all previews are off - Overlays.editOverlay(voxelPreview, { visible: false }); - Overlays.editOverlay(linePreviewTop[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewBottom[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewLeft[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewRight[currentCursor], { visible: false }); - } -} - -function trackMouseEvent(event) { - trackLastMouseX = event.x; - trackLastMouseY = event.y; - trackAsDelete = event.isControl; - trackAsRecolor = event.isShifted; - trackAsEyedropper = event.isMeta; - showPreviewGuides(); -} - -function trackKeyPressEvent(event) { - if (!editToolsOn) { - return; - } - - if (event.text == "CONTROL") { - trackAsDelete = true; - moveTools(); - } - if (event.text == "SHIFT") { - trackAsRecolor = true; - moveTools(); - } - if (event.text == "META") { - trackAsEyedropper = true; - moveTools(); - } - if (event.text == "ALT") { - inspectJsIsRunning = true; - } - showPreviewGuides(); -} - -function trackKeyReleaseEvent(event) { - // on TAB release, toggle our tool state - if (event.text == "TAB") { - editToolsOn = !editToolsOn; - moveTools(); - setAudioPosition(); // make sure we set the audio position before playing sounds - showPreviewGuides(); - scaleSelector.show(editToolsOn); - scriptInitSound.playRandom(); - } - - if (event.text == "ALT") { - inspectJsIsRunning = false; - } - - if (editToolsOn) { - if (event.text == "ESC") { - pasteMode = false; - moveTools(); - } - if (event.text == "-") { - scaleSelector.decrementScale(); - } - if (event.text == "+") { - scaleSelector.incrementScale(); - } - if (event.text == "CONTROL") { - trackAsDelete = false; - moveTools(); - } - if (event.text == "SHIFT") { - trackAsRecolor = false; - moveTools(); - } - if (event.text == "META") { - trackAsEyedropper = false; - moveTools(); - } - - // on F1 toggle the preview mode between cubes and lines - if (event.text == "F1") { - previewAsVoxel = !previewAsVoxel; - } - - showPreviewGuides(); - } -} - -function mousePressEvent(event) { - // if our tools are off, then don't do anything - if (!editToolsOn) { - return; - } - if (inspectJsIsRunning) { - return; - } - - if (event.deviceID == 1500) { // Left Hydra Controller - currentCursor = 0; - } else if (event.deviceID == 1501) { // Right Hydra Controller - currentCursor = 1; - } else { - currentCursor = 2; - } - - var clickedOnSomething = false; - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - if (clickedOverlay == voxelTool) { - modeSwitchSound.play(0); - voxelToolSelected = !voxelToolSelected; - recolorToolSelected = false; - eyedropperToolSelected = false; - moveTools(); - clickedOnSomething = true; - } else if (clickedOverlay == recolorTool) { - modeSwitchSound.play(1); - voxelToolSelected = false; - recolorToolSelected = !recolorToolSelected; - eyedropperToolSelected = false; - moveTools(); - clickedOnSomething = true; - } else if (clickedOverlay == eyedropperTool) { - modeSwitchSound.play(2); - voxelToolSelected = false; - recolorToolSelected = false; - eyedropperToolSelected = !eyedropperToolSelected; - moveTools(); - clickedOnSomething = true; - } else if (scaleSelector.clicked(event.x, event.y)) { - if (isImporting) { - rescaleImport(); - } - clickedOnSomething = true; - } else { - // if the user clicked on one of the color swatches, update the selectedSwatch - for (s = 0; s < numColors; s++) { - if (clickedOverlay == swatches[s]) { - whichColor = s; - moveTools(); - clickedOnSomething = true; - swatchesSound.play(whichColor); - break; - } - } - } - if (clickedOnSomething || isImporting || (!voxelToolSelected && !recolorToolSelected && !eyedropperToolSelected)) { - return; // no further processing - } - - // TODO: does any of this stuff need to execute if we're panning or orbiting? - trackMouseEvent(event); // used by preview support - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - audioOptions.position = Vec3.sum(pickRay.origin, pickRay.direction); - - if (pasteMode) { - var pasteVoxel = getNewPasteVoxel(pickRay); - Clipboard.pasteVoxel(pasteVoxel.origin.x, pasteVoxel.origin.y, pasteVoxel.origin.z, pasteVoxel.voxelSize); - pasteMode = false; - moveTools(); - return; - } - - if (intersection.intersects) { - if (trackAsDelete || event.isRightButton && !trackAsEyedropper) { - // Delete voxel - voxelDetails = calculateVoxelFromIntersection(intersection,"delete"); - Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); - delVoxelSound.playRandom(); - Overlays.editOverlay(voxelPreview, { visible: false }); - } else if (eyedropperToolSelected || trackAsEyedropper) { - colors[whichColor].red = intersection.voxel.red; - colors[whichColor].green = intersection.voxel.green; - colors[whichColor].blue = intersection.voxel.blue; - moveTools(); - swatchesSound.play(whichColor); - - } else if (recolorToolSelected || trackAsRecolor) { - // Recolor Voxel - voxelDetails = calculateVoxelFromIntersection(intersection,"recolor"); - - // doing this erase then set will make sure we only recolor just the target voxel - Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, - colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue); - swatchesSound.play(whichColor); - Overlays.editOverlay(voxelPreview, { visible: false }); - } else if (voxelToolSelected) { - // Add voxel on face - newColor = { red: colors[whichColor].red, - green: colors[whichColor].green, - blue: colors[whichColor].blue - }; - - voxelDetails = calculateVoxelFromIntersection(intersection,"add"); - Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, - newColor.red, newColor.green, newColor.blue); - lastVoxelPosition = { x: voxelDetails.x, y: voxelDetails.y, z: voxelDetails.z }; - lastVoxelColor = { red: newColor.red, green: newColor.green, blue: newColor.blue }; - lastVoxelScale = voxelDetails.s; - if (lastVoxelScale > MAX_VOXEL_SCALE) { - lastVoxelScale = MAX_VOXEL_SCALE; - } - - addVoxelSound.playRandom(); - - Overlays.editOverlay(voxelPreview, { visible: false }); - dragStart = { x: event.x, y: event.y }; - isAdding = true; - } - } -} - -function keyPressEvent(event) { - // if our tools are off, then don't do anything - if (editToolsOn) { - var nVal = parseInt(event.text); - if (event.text == "`") { - copyScale = true; - } else if ((nVal > 0) && (nVal <= numColors)) { - whichColor = nVal - 1; - print("Color = " + (whichColor + 1)); - swatchesSound.play(whichColor); - moveTools(); - } else if (event.text == "0" && voxelToolSelected) { - // Create a brand new 1 meter voxel in front of your avatar - var newPosition = getNewVoxelPosition(); - var newVoxel = { - x: newPosition.x, - y: newPosition.y , - z: newPosition.z, - s: NEW_VOXEL_SIZE, - red: colors[whichColor].red, - green: colors[whichColor].green, - blue: colors[whichColor].blue }; - Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); - setAudioPosition(); - initialVoxelSound.playRandom(); - } else if (event.text == "z") { - undoSound.playRandom(); - } - } - - trackKeyPressEvent(event); // used by preview support -} - -function keyReleaseEvent(event) { - trackKeyReleaseEvent(event); // used by preview support -} - - -// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already -// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that -// added it. -var voxelMenuAddedDelete = false; -function setupVoxelMenus() { - // hook up menus - Menu.menuItemEvent.connect(menuItemEvent); - - // add our menuitems - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Voxels", isSeparator: true, beforeItem: "Physics" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Cut", shortcutKey: "CTRL+X", afterItem: "Voxels" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Copy", shortcutKey: "CTRL+C", afterItem: "Cut" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste", shortcutKey: "CTRL+V", afterItem: "Copy" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Nudge", shortcutKey: "CTRL+N", afterItem: "Paste" }); - - - if (!Menu.menuItemExists("Edit","Delete")) { - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", - shortcutKeyEvent: { text: "backspace" }, afterItem: "Nudge" }); - voxelMenuAddedDelete = true; - } - - Menu.addMenuItem({ menuName: "File", menuItemName: "Voxels", isSeparator: true, beforeItem: "Settings" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Export Voxels", shortcutKey: "CTRL+E", afterItem: "Voxels" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Import Voxels", shortcutKey: "CTRL+I", afterItem: "Export Voxels" }); -} - -function cleanupMenus() { - // delete our menuitems - Menu.removeSeparator("Edit", "Voxels"); - Menu.removeMenuItem("Edit", "Cut"); - Menu.removeMenuItem("Edit", "Copy"); - Menu.removeMenuItem("Edit", "Paste"); - Menu.removeMenuItem("Edit", "Nudge"); - if (voxelMenuAddedDelete) { - Menu.removeMenuItem("Edit", "Delete"); - } - Menu.removeSeparator("File", "Voxels"); - Menu.removeMenuItem("File", "Export Voxels"); - Menu.removeMenuItem("File", "Import Voxels"); -} - -function menuItemEvent(menuItem) { - - // handle clipboard items - if (editToolsOn) { - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - var intersection = Voxels.findRayIntersection(pickRay); - selectedVoxel = calculateVoxelFromIntersection(intersection,"select"); - if (menuItem == "Copy") { - print("copying..."); - Clipboard.copyVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - pasteMode = true; - moveTools(); - } - if (menuItem == "Cut") { - print("cutting..."); - Clipboard.cutVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - pasteMode = true; - moveTools(); - } - if (menuItem == "Paste") { - if (isImporting) { - print("placing import..."); - placeImport(); - showImport(false); - } else { - print("pasting..."); - Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - pasteMode = false; - moveTools(); - } - if (menuItem == "Delete") { - print("deleting..."); - if (isImporting) { - cancelImport(); - } else if (voxelToolSelected) { - Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - } - - if (menuItem == "Export Voxels") { - print("export"); - Clipboard.exportVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Import Voxels") { - print("importing..."); - if (importVoxels()) { - showImport(true); - } - moveTools(); - } - if (menuItem == "Nudge") { - print("nudge"); - Clipboard.nudgeVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s, { x: -1, y: 0, z: 0 }); - } - } -} - -function mouseMoveEvent(event) { - if (!editToolsOn || inspectJsIsRunning) { - return; - } - - if (event.deviceID == 1500) { // Left Hydra Controller - currentCursor = 0; - } else if (event.deviceID == 1501) { // Right Hydra Controller - currentCursor = 1; - } else { - currentCursor = 2; - } - - // Move Import Preview - if (isImporting) { - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - - var distance = 2 * scaleSelector.scale; - - if (intersection.intersects) { - var intersectionDistance = Vec3.length(Vec3.subtract(pickRay.origin, intersection.intersection)); - if (intersectionDistance < distance) { - distance = intersectionDistance * 0.99; - } - - } - - var targetPosition = { x: pickRay.direction.x * distance, - y: pickRay.direction.y * distance, - z: pickRay.direction.z * distance - }; - targetPosition.x += pickRay.origin.x; - targetPosition.y += pickRay.origin.y; - targetPosition.z += pickRay.origin.z; - - if (targetPosition.x < 0) targetPosition.x = 0; - if (targetPosition.y < 0) targetPosition.y = 0; - if (targetPosition.z < 0) targetPosition.z = 0; - - var nudgeFactor = scaleSelector.scale; - var newPosition = { - x: Math.floor(targetPosition.x / nudgeFactor) * nudgeFactor, - y: Math.floor(targetPosition.y / nudgeFactor) * nudgeFactor, - z: Math.floor(targetPosition.z / nudgeFactor) * nudgeFactor - } - - moveImport(newPosition); - } - - if (isAdding) { - var pickRay = Camera.computePickRay(event.x, event.y); - var distance = Vec3.length(Vec3.subtract(pickRay.origin, lastVoxelPosition)); - var mouseSpot = Vec3.sum(Vec3.multiply(pickRay.direction, distance), pickRay.origin); - var delta = Vec3.subtract(mouseSpot, lastVoxelPosition); - - if (!isExtruding) { - // Use the drag direction to tell which way to 'extrude' this voxel - extrudeScale = lastVoxelScale; - extrudeDirection = { x: 0, y: 0, z: 0 }; - isExtruding = true; - if (delta.x > lastVoxelScale) extrudeDirection.x = 1; - else if (delta.x < -lastVoxelScale) extrudeDirection.x = -1; - else if (delta.y > lastVoxelScale) extrudeDirection.y = 1; - else if (delta.y < -lastVoxelScale) extrudeDirection.y = -1; - else if (delta.z > lastVoxelScale) extrudeDirection.z = 1; - else if (delta.z < -lastVoxelScale) extrudeDirection.z = -1; - else isExtruding = false; - } else { - // Extrude if mouse has moved by a voxel in the extrude direction - var distanceInDirection = Vec3.dot(delta, extrudeDirection); - if (distanceInDirection > extrudeScale) { - lastVoxelPosition = Vec3.sum(lastVoxelPosition, Vec3.multiply(extrudeDirection, extrudeScale)); - Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, extrudeScale, - lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); - } - } - } - - // update the add voxel/delete voxel overlay preview - trackMouseEvent(event); -} - -function mouseReleaseEvent(event) { - // if our tools are off, then don't do anything - if (!editToolsOn) { - return; - } - if (inspectJsIsRunning) { - return; - } - - isAdding = false; - isExtruding = false; -} - -function moveTools() { - // move the swatches - swatchesX = (windowDimensions.x - (swatchesWidth + scaleSelectorWidth)) / 2; - swatchesY = windowDimensions.y - swatchHeight + 1; - - // create the overlays, position them in a row, set their colors, and for the selected one, use a different source image - // location so that it displays the "selected" marker - for (s = 0; s < numColors; s++) { - var extraWidth = 0; - - if (s == 0) { - extraWidth = swatchExtraPadding; - } - - var imageFromX = swatchExtraPadding - extraWidth + s * swatchWidth; - var imageFromY = swatchHeight + 1; - if (s == whichColor) { - imageFromY = 0; - } - - var swatchX = swatchExtraPadding - extraWidth + swatchesX + ((swatchWidth - 1) * s); - - if (s == (numColors - 1)) { - extraWidth = swatchExtraPadding; - } - - Overlays.editOverlay(swatches[s], { - x: swatchX, - y: swatchesY, - subImage: { x: imageFromX, y: imageFromY, width: swatchWidth + extraWidth, height: swatchHeight }, - color: colors[s], - alpha: 1, - visible: editToolsOn - }); - } - - // move the tools - toolsY = (windowDimensions.y - toolsHeight) / 2; - - var voxelToolOffset = 1, - recolorToolOffset = 1, - eyedropperToolOffset = 1; - - var voxelToolColor = WHITE_COLOR; - - if (recolorToolSelected) { - recolorToolOffset = 2; - } else if (eyedropperToolSelected) { - eyedropperToolOffset = 2; - } else if (voxelToolSelected) { - if (pasteMode) { - voxelToolColor = pasteModeColor; - } - voxelToolOffset = 2; - } - - Overlays.editOverlay(voxelTool, { - subImage: { x: 0, y: toolHeight * voxelToolOffset, width: toolWidth, height: toolHeight }, - x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * voxelToolAt), width: toolWidth, height: toolHeight, - color: voxelToolColor, - visible: editToolsOn - }); - - Overlays.editOverlay(recolorTool, { - subImage: { x: 0, y: toolHeight * recolorToolOffset, width: toolWidth, height: toolHeight }, - x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * recolorToolAt), width: toolWidth, height: toolHeight, - visible: editToolsOn - }); - - Overlays.editOverlay(eyedropperTool, { - subImage: { x: 0, y: toolHeight * eyedropperToolOffset, width: toolWidth, height: toolHeight }, - x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * eyedropperToolAt), width: toolWidth, height: toolHeight, - visible: editToolsOn - }); - - scaleSelector.move(); -} - -var lastFingerAddVoxel = { x: -1, y: -1, z: -1}; // off of the build-able area -var lastFingerDeleteVoxel = { x: -1, y: -1, z: -1}; // off of the build-able area - -function checkControllers() { - var controllersPerPalm = 2; // palm and finger - for (var palm = 0; palm < 2; palm++) { - var palmController = palm * controllersPerPalm; - var fingerTipController = palmController + 1; - var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController); - - var BUTTON_COUNT = 6; - var BUTTON_BASE = palm * BUTTON_COUNT; - var BUTTON_1 = BUTTON_BASE + 1; - var BUTTON_2 = BUTTON_BASE + 2; - var FINGERTIP_VOXEL_SIZE = 0.05; - - if (Controller.isButtonPressed(BUTTON_1)) { - if (Vec3.length(Vec3.subtract(fingerTipPosition,lastFingerAddVoxel)) > (FINGERTIP_VOXEL_SIZE / 2)) { - newColor = { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; - - Voxels.setVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE, - newColor.red, newColor.green, newColor.blue); - - lastFingerAddVoxel = fingerTipPosition; - } - } else if (Controller.isButtonPressed(BUTTON_2)) { - if (Vec3.length(Vec3.subtract(fingerTipPosition,lastFingerDeleteVoxel)) > (FINGERTIP_VOXEL_SIZE / 2)) { - Voxels.eraseVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE); - lastFingerDeleteVoxel = fingerTipPosition; - } - } - } -} - -function update(deltaTime) { - if (editToolsOn) { - var newWindowDimensions = Controller.getViewportDimensions(); - if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) { - windowDimensions = newWindowDimensions; - moveTools(); - } - - checkControllers(); - } -} - -function wheelEvent(event) { - wheelPixelsMoved += event.delta; - if (Math.abs(wheelPixelsMoved) > WHEEL_PIXELS_PER_SCALE_CHANGE) - { - - if (wheelPixelsMoved > 0) { - scaleSelector.decrementScale(); - } else { - scaleSelector.incrementScale(); - } - trackMouseEvent(event); - wheelPixelsMoved = 0; - - if (isImporting) { - rescaleImport(); - } - } -} - -// Controller.wheelEvent.connect(wheelEvent); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.keyPressEvent.connect(keyPressEvent); -Controller.keyReleaseEvent.connect(keyReleaseEvent); -Controller.captureKeyEvents({ text: "+" }); -Controller.captureKeyEvents({ text: "-" }); - - -function scriptEnding() { - Overlays.deleteOverlay(voxelPreview); - for (var i = 0; i < linePreviewTop.length; i++) { - Overlays.deleteOverlay(linePreviewTop[i]); - Overlays.deleteOverlay(linePreviewBottom[i]); - Overlays.deleteOverlay(linePreviewLeft[i]); - Overlays.deleteOverlay(linePreviewRight[i]); - } - for (s = 0; s < numColors; s++) { - Overlays.deleteOverlay(swatches[s]); - } - Overlays.deleteOverlay(voxelTool); - Overlays.deleteOverlay(recolorTool); - Overlays.deleteOverlay(eyedropperTool); - Controller.releaseKeyEvents({ text: "+" }); - Controller.releaseKeyEvents({ text: "-" }); - cleanupImport(); - scaleSelector.cleanup(); - cleanupMenus(); -} -Script.scriptEnding.connect(scriptEnding); - -Script.update.connect(update); - -setupVoxelMenus(); diff --git a/examples/fallingSand.js b/examples/fallingSand.js deleted file mode 100644 index c85196f10e..0000000000 --- a/examples/fallingSand.js +++ /dev/null @@ -1,648 +0,0 @@ -// -// fallingSand.js -// examples -// -// Created by Ben Arnold on 7/14/14. -// Copyright 2014 High Fidelity, Inc. -// -// This sample script allows the user to place sand voxels that will undergo -// cellular automata physics. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting -var previewLineWidth = 2.0; - -var voxelSize = 1; -var windowDimensions = Controller.getViewportDimensions(); -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; - -var MAX_VOXEL_SCALE_POWER = 5; -var MIN_VOXEL_SCALE_POWER = -8; -var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER); -var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER); - - -var linePreviewTop = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewBottom = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewLeft = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewRight = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - - -var UIColor = { red: 119, green: 103, blue: 53}; -var activeUIColor = { red: 234, green: 206, blue: 106}; - -var toolHeight = 50; -var toolWidth = 50; - -var editToolsOn = true; - -var voxelToolSelected = false; - -var scaleSelectorWidth = 144; -var scaleSelectorHeight = 37; - -var scaleSelectorX = windowDimensions.x / 5.0; -var scaleSelectorY = windowDimensions.y - scaleSelectorHeight; - -var voxelTool = Overlays.addOverlay("image", { - x: scaleSelectorX + scaleSelectorWidth + 1, y: windowDimensions.y - toolHeight, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-tool.svg", - visible: editToolsOn, - color: UIColor, - alpha: 0.9 - }); - -var copyScale = true; -function ScaleSelector() { - this.x = scaleSelectorX; - this.y = scaleSelectorY; - this.width = scaleSelectorWidth; - this.height = scaleSelectorHeight; - - this.displayPower = false; - this.scale = 1.0; - this.power = 0; - - this.FIRST_PART = this.width * 40.0 / 100.0; - this.SECOND_PART = this.width * 37.0 / 100.0; - - this.buttonsOverlay = Overlays.addOverlay("image", { - x: this.x, y: this.y, - width: this.width, height: this.height, - //subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - visible: editToolsOn, - color: activeUIColor - }); - this.textOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - topMargin: 13, - text: this.scale.toString(), - backgroundAlpha: 0.0, - visible: editToolsOn, - color: activeUIColor - }); - this.powerOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - leftMargin: 28, - text: this.power.toString(), - backgroundAlpha: 0.0, - visible: false, - color: activeUIColor - }); - this.setScale = function(scale) { - if (scale > MAX_VOXEL_SCALE) { - scale = MAX_VOXEL_SCALE; - } - if (scale < MIN_VOXEL_SCALE) { - scale = MIN_VOXEL_SCALE; - } - - this.scale = scale; - this.power = Math.floor(Math.log(scale) / Math.log(2)); - this.update(); - } - - this.show = function(doShow) { - Overlays.editOverlay(this.buttonsOverlay, {visible: doShow}); - Overlays.editOverlay(this.textOverlay, {visible: doShow}); - Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower}); - } - - this.move = function() { - this.x = swatchesX + swatchesWidth; - this.y = swatchesY; - - Overlays.editOverlay(this.buttonsOverlay, { - x: this.x, y: this.y, - }); - Overlays.editOverlay(this.textOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - Overlays.editOverlay(this.powerOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - } - - - this.switchDisplay = function() { - this.displayPower = !this.displayPower; - - if (this.displayPower) { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 18, - text: "2" - }); - Overlays.editOverlay(this.powerOverlay, { - text: this.power.toString(), - visible: editToolsOn - }); - } else { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 13, - text: this.scale.toString() - }); - Overlays.editOverlay(this.powerOverlay, { - visible: false - }); - } - } - - this.update = function() { - if (this.displayPower) { - Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()}); - } else { - Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()}); - } - } - - this.incrementScale = function() { - copyScale = false; - if (this.power < MAX_VOXEL_SCALE_POWER) { - ++this.power; - this.scale *= 2.0; - this.update(); - } - } - - this.decrementScale = function() { - copyScale = false; - if (MIN_VOXEL_SCALE_POWER < this.power) { - --this.power; - this.scale /= 2.0; - this.update(); - } - } - - this.clicked = function(x, y) { - if (this.x < x && x < this.x + this.width && - this.y < y && y < this.y + this.height) { - - if (x < this.x + this.FIRST_PART) { - this.decrementScale(); - } else if (x < this.x + this.FIRST_PART + this.SECOND_PART) { - this.switchDisplay(); - } else { - this.incrementScale(); - } - return true; - } - return false; - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.buttonsOverlay); - Overlays.deleteOverlay(this.textOverlay); - Overlays.deleteOverlay(this.powerOverlay); - } - -} -var scaleSelector = new ScaleSelector(); - -function calculateVoxelFromIntersection(intersection, operation) { - - var resultVoxel; - - var x; - var y; - var z; - - // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest - // ancestor voxel of our target size that contains our intersected voxel. - if (voxelSize > intersection.voxel.s) { - x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize; - y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize; - z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize; - } else { - // otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of. - // if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result - // in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting - // voxel this still works and results in returning the intersecting voxel which is what we want - var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5)); - - var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter); - x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize; - y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize; - z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize; - } - resultVoxel = { x: x, y: y, z: z, s: voxelSize }; - var highlightAt = { x: x, y: y, z: z, s: voxelSize }; - - - - // we only do the "add to the face we're pointing at" adjustment, if the operation is an add - // operation, and the target voxel size is equal to or smaller than the intersecting voxel. - var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s)); - - // now we also want to calculate the "edge square" for the face for this voxel - if (intersection.face == "MIN_X_FACE") { - - highlightAt.x = x - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x -= voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MAX_X_FACE") { - - highlightAt.x = x + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x += resultVoxel.s; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MIN_Y_FACE") { - - highlightAt.y = y - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y -= voxelSize; - } - - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MAX_Y_FACE") { - - highlightAt.y = y + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y += voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust}; - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; - - } else if (intersection.face == "MIN_Z_FACE") { - - highlightAt.z = z - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z -= voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; - - } else if (intersection.face == "MAX_Z_FACE") { - - highlightAt.z = z + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z += voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; - resultVoxel.topLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; - - } - return resultVoxel; -} - -var trackLastMouseX = 0; -var trackLastMouseY = 0; - -function showPreviewLines() { - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - - var intersection = Voxels.findRayIntersection(pickRay); - - if (intersection.intersects) { - var resultVoxel = calculateVoxelFromIntersection(intersection, ""); - Overlays.editOverlay(linePreviewTop, { position: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true }); - Overlays.editOverlay(linePreviewBottom, { position: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true }); - Overlays.editOverlay(linePreviewLeft, { position: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true }); - Overlays.editOverlay(linePreviewRight, { position: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true }); - } else { - Overlays.editOverlay(linePreviewTop, { visible: false }); - Overlays.editOverlay(linePreviewBottom, { visible: false }); - Overlays.editOverlay(linePreviewLeft, { visible: false }); - Overlays.editOverlay(linePreviewRight, { visible: false }); - } -} - -function mouseMoveEvent(event) { - trackLastMouseX = event.x; - trackLastMouseY = event.y; - if (!voxelToolSelected) { - return; - } - showPreviewLines(); -} - -var BRUSH_RADIUS = 2; - -function mousePressEvent(event) { - var mouseX = event.x; - var mouseY = event.y; - - var clickedOnSomething = false; - // Check if we clicked an overlay - var clickedOverlay = Overlays.getOverlayAtPoint({x: mouseX, y: mouseY}); - - if (clickedOverlay == voxelTool) { - voxelToolSelected = !voxelToolSelected; - - if (voxelToolSelected == true) { - Overlays.editOverlay(voxelTool, { - color: activeUIColor - }); - } else { - Overlays.editOverlay(voxelTool, { - color: UIColor - }); - } - - clickedOnSomething = true; - } else if (scaleSelector.clicked(event.x, event.y)) { - clickedOnSomething = true; - voxelSize = scaleSelector.scale; - } - - // Return if we clicked on the UI or the voxel tool is disabled - if (clickedOnSomething || !voxelToolSelected) { - return; - } - - // Compute the picking ray for the click - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - var resultVoxel = calculateVoxelFromIntersection(intersection, "add"); - - - //Add a clump of sand voxels - makeSphere(resultVoxel.x, resultVoxel.y, resultVoxel.z, voxelSize * BRUSH_RADIUS, voxelSize); -} - -var sandArray = []; -var numSand = 0; - - -//These arrays are used to buffer add/remove operations so they can be batched together -var addArray = []; -var addArraySize = 0; -var removeArray = []; -var removeArraySize = 0; - -//The colors must be different -var activeSandColor = { r: 234, g: 206, b: 106}; -var inactiveSandColor = { r: 233, g: 206, b: 106}; - -//This is used as an optimization, so that we -//will check our 6 neighbors at most once. -var adjacentVoxels = []; -var numAdjacentVoxels = 0; -//Stores a list of voxels we need to activate -var activateMap = {}; - -var UPDATES_PER_SECOND = 12.0; // frames per second -var frameIndex = 0.0; -var oldFrameIndex = 0; - -function update(deltaTime) { - frameIndex += deltaTime * UPDATES_PER_SECOND; - if (Math.floor(frameIndex) == oldFrameIndex) { - return; - } - oldFrameIndex++; - - //Clear the activate map each frame - activateMap = {}; - - //Update all sand in our sandArray - var i = 0; - while (i < numSand) { - //Update the sand voxel and if it doesn't move, deactivate it - if (updateSand(i) == false) { - deactivateSand(i); - } else { - i++; - } - } - - for (var i = 0; i < removeArraySize; i++) { - var voxel = removeArray[i]; - Voxels.eraseVoxel(voxel.x, voxel.y, voxel.z, voxel.s); - } - removeArraySize = 0; - - //Add all voxels that have moved - for (var i = 0; i < addArraySize; i++) { - var voxel = addArray[i]; - Voxels.setVoxel(voxel.x, voxel.y, voxel.z, voxel.s, voxel.r, voxel.g, voxel.b); - } - addArraySize = 0; - - for (var key in activateMap) { - var voxel = activateMap[key]; - Voxels.setVoxel(voxel.x, voxel.y, voxel.z, voxel.s, activeSandColor.r, activeSandColor.g, activeSandColor.b); - sandArray[numSand++] = { x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b }; - } -} - -//Adds a sphere of sand at the center cx,cy,cz -function makeSphere(cx, cy, cz, r, voxelSize) { - - var r2 = r * r; - var distance2; - var dx; - var dy; - var dz; - - for (var x = cx - r; x <= cx + r; x += voxelSize) { - for (var y = cy - r; y <= cy + r; y += voxelSize) { - for (var z = cz - r; z <= cz + r; z += voxelSize) { - dx = Math.abs(x - cx); - dy = Math.abs(y - cy); - dz = Math.abs(z - cz); - distance2 = dx * dx + dy * dy + dz * dz; - if (distance2 <= r2 && isVoxelEmpty(x, y, z, voxelSize)) { - Voxels.setVoxel(x, y, z, voxelSize, activeSandColor.r, activeSandColor.g, activeSandColor.b); - sandArray[numSand++] = { x: x, y: y, z: z, s: voxelSize, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b }; - } - } - } - } -} - -//Check if a given voxel is empty -function isVoxelEmpty(x, y, z, s, isAdjacent) { - var halfSize = s / 2; - var point = {x: x + halfSize, y: y + halfSize, z: z + halfSize }; - - var adjacent = Voxels.getVoxelEnclosingPointBlocking(point); - //If color is all 0, we assume its air. - - if (adjacent.red == 0 && adjacent.green == 0 && adjacent.blue == 0) { - return true; - } - - if (isAdjacent) { - adjacentVoxels[numAdjacentVoxels++] = adjacent; - } - - return false; -} - -//Moves voxel to x,y,z if the space is empty -function tryMoveVoxel(voxel, x, y, z) { - //If the adjacent voxel is empty, we will move to it. - if (isVoxelEmpty(x, y, z, voxel.s, false)) { - var hsize = voxel.s / 2; - for (var i = 0; i < 5; i++) { - var point = {x: voxel.x + directionVecs[i].x * voxel.s + hsize, y: voxel.y + directionVecs[i].y * voxel.s + hsize, z: voxel.z + directionVecs[i].z * voxel.s + hsize }; - adjacentVoxels[numAdjacentVoxels++] = Voxels.getVoxelEnclosingPointBlocking(point); - } - moveVoxel(voxel, x, y, z); - - //Get all adjacent voxels for activation - return true; - } - return false; -} - -//Moves voxel to x,y,z -function moveVoxel(voxel, x, y, z) { - activateNeighbors(); - removeArray[removeArraySize++] = {x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s}; - addArray[addArraySize++] = {x: x, y: y, z: z, s: voxel.s, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b}; - voxel.x = x; - voxel.y = y; - voxel.z = z; -} - -var LEFT = 0; -var BACK = 1; -var RIGHT = 2; -var FRONT = 3; -var TOP = 4; - -//These indicate the different directions to neighbor voxels, so we can iterate them -var directionVecs = []; -directionVecs[LEFT] = {x: -1, y: 0, z: 0}; //Left -directionVecs[BACK] = {x: 0, y: 0, z: -1}; //Back -directionVecs[RIGHT] = {x: 1, y: 0, z: 0}; //Right -directionVecs[FRONT] = {x: 0, y: 0, z: 1}; //Front -directionVecs[TOP] = {x: 0, y: 1, z: 0}; //Top - -function updateSand(i) { - var voxel = sandArray[i]; - var size = voxel.s; - var hsize = size / 2; - numAdjacentVoxels = 0; - - //Down - if (tryMoveVoxel(voxel, voxel.x, voxel.y - size, voxel.z)) { - return true; - } - - //Left, back, right, front - for (var i = 0; i < 4; i++) { - if (isVoxelEmpty(voxel.x + directionVecs[i].x * size, voxel.y + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size, size, true) - && isVoxelEmpty(voxel.x + directionVecs[i].x * size, (voxel.y - size) + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size, size, false)) { - //get the rest of the adjacent voxels - for (var j = i + 1; j < 5; j++) { - var point = {x: voxel.x + directionVecs[j].x * size + hsize, y: voxel.y + directionVecs[j].y * size + hsize, z: voxel.z + directionVecs[j].z * size + hsize }; - adjacentVoxels[numAdjacentVoxels++] = Voxels.getVoxelEnclosingPointBlocking(point); - } - moveVoxel(voxel, voxel.x + directionVecs[i].x * size, voxel.y + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size); - return true; - } - } - - return false; -} - -function activateNeighbors() { - for (var i = 0; i < numAdjacentVoxels; i++) { - var voxel = adjacentVoxels[i]; - //Check if this neighbor is inactive, if so, activate it - if (voxel.red == inactiveSandColor.r && voxel.green == inactiveSandColor.g && voxel.blue == inactiveSandColor.b) { - activateMap[voxel.x.toString() + "," + voxel.y.toString() + ',' + voxel.z.toString()] = voxel; - } - } -} - -//Deactivates a sand voxel to save processing power -function deactivateSand(i) { - var voxel = sandArray[i]; - addArray[addArraySize++] = {x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s, r: inactiveSandColor.r, g: inactiveSandColor.g, b: inactiveSandColor.b}; - sandArray[i] = sandArray[numSand-1]; - numSand--; -} - -//Cleanup -function scriptEnding() { - for (var i = 0; i < numSand; i++) { - var voxel = sandArray[i]; - Voxels.eraseVoxel(voxel.x, voxel.y, voxel.z, voxel.s); - } - Overlays.deleteOverlay(linePreviewTop); - Overlays.deleteOverlay(linePreviewBottom); - Overlays.deleteOverlay(linePreviewLeft); - Overlays.deleteOverlay(linePreviewRight); - scaleSelector.cleanup(); - Overlays.deleteOverlay(voxelTool); -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); - -Script.update.connect(update); -Script.scriptEnding.connect(scriptEnding); - -Voxels.setMaxPacketSize(1); //this is needed or a bug occurs :( -Voxels.setPacketsPerSecond(10000); \ No newline at end of file diff --git a/examples/fountain.js b/examples/fountain.js index aea53fb405..0e6ab521f7 100644 --- a/examples/fountain.js +++ b/examples/fountain.js @@ -46,7 +46,7 @@ function vInterpolate(a, b, fraction) { } var position = { x: 5.0, y: 0.6, z: 5.0 }; -Voxels.setVoxel(position.x, 0, position.z, 0.5, 0, 0, 255); +//Voxels.setVoxel(position.x, 0, position.z, 0.5, 0, 0, 255); var totalEntities = 0; function makeFountain(deltaTime) { diff --git a/examples/gameoflife.js b/examples/gameoflife.js deleted file mode 100644 index 3fcbfa8138..0000000000 --- a/examples/gameoflife.js +++ /dev/null @@ -1,140 +0,0 @@ -// -// gameoflife.js -// examples -// -// Copyright 2014 High Fidelity, Inc. -// -// The following is an example of Conway's Game of Life (http://en.wikipedia.org/wiki/Conway's_Game_of_Life) -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var NUMBER_OF_CELLS_EACH_DIMENSION = 64; -var NUMBER_OF_CELLS = NUMBER_OF_CELLS_EACH_DIMENSION * NUMBER_OF_CELLS_EACH_DIMENSION; - -var currentCells = []; -var nextCells = []; - -var METER_LENGTH = 1; -var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION; - -// randomly populate the cell start values -for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - // create the array to hold this row - currentCells[i] = []; - - // create the array to hold this row in the nextCells array - nextCells[i] = []; - - for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - currentCells[i][j] = Math.floor(Math.random() * 2); - - // put the same value in the nextCells array for first board draw - nextCells[i][j] = currentCells[i][j]; - } -} - -function isNeighbourAlive(i, j) { - if (i < 0 || i >= NUMBER_OF_CELLS_EACH_DIMENSION - || i < 0 || j >= NUMBER_OF_CELLS_EACH_DIMENSION) { - return 0; - } else { - return currentCells[i][j]; - } -} - -function updateCells() { - var i = 0; - var j = 0; - - for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - // figure out the number of live neighbours for the i-j cell - var liveNeighbours = - isNeighbourAlive(i + 1, j - 1) + isNeighbourAlive(i + 1, j) + isNeighbourAlive(i + 1, j + 1) + - isNeighbourAlive(i, j - 1) + isNeighbourAlive(i, j + 1) + - isNeighbourAlive(i - 1, j - 1) + isNeighbourAlive(i - 1, j) + isNeighbourAlive(i - 1, j + 1); - - if (currentCells[i][j]) { - // live cell - - if (liveNeighbours < 2) { - // rule #1 - under-population - this cell will die - // mark it zero to mark the change - nextCells[i][j] = 0; - } else if (liveNeighbours < 4) { - // rule #2 - this cell lives - // mark it -1 to mark no change - nextCells[i][j] = -1; - } else { - // rule #3 - overcrowding - this cell dies - // mark it zero to mark the change - nextCells[i][j] = 0; - } - } else { - // dead cell - if (liveNeighbours == 3) { - // rule #4 - reproduction - this cell revives - // mark it one to mark the change - nextCells[i][j] = 1; - } else { - // this cell stays dead - // mark it -1 for no change - nextCells[i][j] = -1; - } - } - - if (Math.random() < 0.001) { - // Random mutation to keep things interesting in there. - nextCells[i][j] = 1; - } - } - } - - for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - if (nextCells[i][j] != -1) { - // there has been a change to this cell, change the value in the currentCells array - currentCells[i][j] = nextCells[i][j]; - } - } - } -} - -function sendNextCells() { - for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - if (nextCells[i][j] != -1) { - // there has been a change to the state of this cell, send it - - // find the x and y position for this voxel, z = 0 - var x = j * cellScale; - var y = i * cellScale; - - // queue a packet to add a voxel for the new cell - var color = (nextCells[i][j] == 1) ? 255 : 1; - Voxels.setVoxel(x, y, 0, cellScale, color, color, color); - } - } - } -} - -var sentFirstBoard = false; - -function step(deltaTime) { - if (sentFirstBoard) { - // we've already sent the first full board, perform a step in time - updateCells(); - } else { - // this will be our first board send - sentFirstBoard = true; - } - - sendNextCells(); -} - -print("here"); -Script.update.connect(step); -Voxels.setPacketsPerSecond(200); -print("now here"); diff --git a/examples/gamepad.js b/examples/gamepad.js index cc275e6267..6caa9c476c 100644 --- a/examples/gamepad.js +++ b/examples/gamepad.js @@ -116,7 +116,7 @@ function updateWarp() { direction: { x: 0, y: -1, z: 0 } }; - var intersection = Voxels.findRayIntersection(pickRay); + var intersection = Entities.findRayIntersection(pickRay); if (intersection.intersects && intersection.distance < WARP_PICK_MAX_DISTANCE) { // Warp 1 meter above the object - this is an approximation diff --git a/examples/grenadeLauncher.js b/examples/grenadeLauncher.js index 3907e41ea6..d09aeab6a8 100644 --- a/examples/grenadeLauncher.js +++ b/examples/grenadeLauncher.js @@ -155,45 +155,6 @@ function shootTarget() { Audio.playSound(targetLaunchSound, audioOptions); } - - -function entityCollisionWithVoxel(entity, voxel, collision) { - -print("entityCollisionWithVoxel...."); - - var VOXEL_SIZE = 0.5; - // Don't make this big. I mean it. - var CRATER_RADIUS = 5; - var entityProperties = Entities.getEntityProperties(entity); - var position = entityProperties.position; - Entities.deleteEntity(entity); - - audioOptions.position = collision.contactPoint; - Audio.playSound(impactSound, audioOptions); - - // Make a crater - var center = collision.contactPoint; - var RADIUS = CRATER_RADIUS * VOXEL_SIZE; - var RADIUS2 = RADIUS * RADIUS; - var distance2; - var dx; - var dy; - var dz; - for (var x = center.x - RADIUS; x <= center.x + RADIUS; x += VOXEL_SIZE) { - for (var y = center.y - RADIUS; y <= center.y + RADIUS; y += VOXEL_SIZE) { - for (var z = center.z - RADIUS; z <= center.z + RADIUS; z += VOXEL_SIZE) { - dx = Math.abs(x - center.x); - dy = Math.abs(y - center.y); - dz = Math.abs(z - center.z); - distance2 = dx * dx + dy * dy + dz * dz; - if (distance2 <= RADIUS2) { - Voxels.eraseVoxel(x, y, z, VOXEL_SIZE); - } - } - } - } -} - function entityCollisionWithEntity(entity1, entity2, collision) { score++; if (showScore) { @@ -355,7 +316,6 @@ function scriptEnding() { MyAvatar.detachOne(gunModel); } -Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel); Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); Script.scriptEnding.connect(scriptEnding); Script.update.connect(update); diff --git a/examples/growTrees.js b/examples/growTrees.js deleted file mode 100644 index a5b55eecd6..0000000000 --- a/examples/growTrees.js +++ /dev/null @@ -1,834 +0,0 @@ -// -// growPlants.js -// examples -// -// Created by Benjamin Arnold on May 29, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// This sample script allows the user to grow different types of plants on the voxels -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting -var previewLineWidth = 2.0; - -var voxelSize = 1; -var windowDimensions = Controller.getViewportDimensions(); -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; - -var MAX_VOXEL_SCALE_POWER = 5; -var MIN_VOXEL_SCALE_POWER = -8; -var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER); -var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER); - - -var linePreviewTop = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewBottom = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewLeft = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewRight = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - - -var UIColor = { red: 0, green: 160, blue: 0}; -var activeUIColor = { red: 0, green: 255, blue: 0}; - -var toolHeight = 50; -var toolWidth = 50; - -var editToolsOn = true; - -var voxelToolSelected = false; - -var scaleSelectorWidth = 144; -var scaleSelectorHeight = 37; - -var scaleSelectorX = windowDimensions.x / 5.0; -var scaleSelectorY = windowDimensions.y - scaleSelectorHeight; - -var voxelTool = Overlays.addOverlay("image", { - x: scaleSelectorX + scaleSelectorWidth + 1, y: windowDimensions.y - toolHeight, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-tool.svg", - visible: editToolsOn, - color: UIColor, - alpha: 0.9 - }); - -var copyScale = true; -function ScaleSelector() { - this.x = scaleSelectorX; - this.y = scaleSelectorY; - this.width = scaleSelectorWidth; - this.height = scaleSelectorHeight; - - this.displayPower = false; - this.scale = 1.0; - this.power = 0; - - this.FIRST_PART = this.width * 40.0 / 100.0; - this.SECOND_PART = this.width * 37.0 / 100.0; - - this.buttonsOverlay = Overlays.addOverlay("image", { - x: this.x, y: this.y, - width: this.width, height: this.height, - //subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - visible: editToolsOn, - color: activeUIColor - }); - this.textOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - topMargin: 13, - text: this.scale.toString(), - backgroundAlpha: 0.0, - visible: editToolsOn, - color: activeUIColor - }); - this.powerOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - leftMargin: 28, - text: this.power.toString(), - backgroundAlpha: 0.0, - visible: false, - color: activeUIColor - }); - this.setScale = function(scale) { - if (scale > MAX_VOXEL_SCALE) { - scale = MAX_VOXEL_SCALE; - } - if (scale < MIN_VOXEL_SCALE) { - scale = MIN_VOXEL_SCALE; - } - - this.scale = scale; - this.power = Math.floor(Math.log(scale) / Math.log(2)); - this.update(); - } - - this.show = function(doShow) { - Overlays.editOverlay(this.buttonsOverlay, {visible: doShow}); - Overlays.editOverlay(this.textOverlay, {visible: doShow}); - Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower}); - } - - this.move = function() { - this.x = swatchesX + swatchesWidth; - this.y = swatchesY; - - Overlays.editOverlay(this.buttonsOverlay, { - x: this.x, y: this.y, - }); - Overlays.editOverlay(this.textOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - Overlays.editOverlay(this.powerOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - } - - - this.switchDisplay = function() { - this.displayPower = !this.displayPower; - - if (this.displayPower) { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 18, - text: "2" - }); - Overlays.editOverlay(this.powerOverlay, { - text: this.power.toString(), - visible: editToolsOn - }); - } else { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 13, - text: this.scale.toString() - }); - Overlays.editOverlay(this.powerOverlay, { - visible: false - }); - } - } - - this.update = function() { - if (this.displayPower) { - Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()}); - } else { - Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()}); - } - } - - this.incrementScale = function() { - copyScale = false; - if (this.power < MAX_VOXEL_SCALE_POWER) { - ++this.power; - this.scale *= 2.0; - this.update(); - } - } - - this.decrementScale = function() { - copyScale = false; - if (MIN_VOXEL_SCALE_POWER < this.power) { - --this.power; - this.scale /= 2.0; - this.update(); - } - } - - this.clicked = function(x, y) { - if (this.x < x && x < this.x + this.width && - this.y < y && y < this.y + this.height) { - - if (x < this.x + this.FIRST_PART) { - this.decrementScale(); - } else if (x < this.x + this.FIRST_PART + this.SECOND_PART) { - this.switchDisplay(); - } else { - this.incrementScale(); - } - return true; - } - return false; - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.buttonsOverlay); - Overlays.deleteOverlay(this.textOverlay); - Overlays.deleteOverlay(this.powerOverlay); - } - -} -var scaleSelector = new ScaleSelector(); - - -function calculateVoxelFromIntersection(intersection, operation) { - - var resultVoxel; - - var x; - var y; - var z; - - // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest - // ancestor voxel of our target size that contains our intersected voxel. - if (voxelSize > intersection.voxel.s) { - x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize; - y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize; - z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize; - } else { - // otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of. - // if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result - // in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting - // voxel this still works and results in returning the intersecting voxel which is what we want - var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5)); - - var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter); - x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize; - y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize; - z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize; - } - resultVoxel = { x: x, y: y, z: z, s: voxelSize }; - var highlightAt = { x: x, y: y, z: z, s: voxelSize }; - - - - // we only do the "add to the face we're pointing at" adjustment, if the operation is an add - // operation, and the target voxel size is equal to or smaller than the intersecting voxel. - var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s)); - - // now we also want to calculate the "edge square" for the face for this voxel - if (intersection.face == "MIN_X_FACE") { - - highlightAt.x = x - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x -= voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MAX_X_FACE") { - - highlightAt.x = x + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x += resultVoxel.s; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MIN_Y_FACE") { - - highlightAt.y = y - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y -= voxelSize; - } - - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MAX_Y_FACE") { - - highlightAt.y = y + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y += voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust}; - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; - - } else if (intersection.face == "MIN_Z_FACE") { - - highlightAt.z = z - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z -= voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; - - } else if (intersection.face == "MAX_Z_FACE") { - - highlightAt.z = z + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z += voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; - resultVoxel.topLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; - - } - return resultVoxel; -} - -var trackLastMouseX = 0; -var trackLastMouseY = 0; - -function showPreviewLines() { - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - - var intersection = Voxels.findRayIntersection(pickRay); - - if (intersection.intersects) { - var resultVoxel = calculateVoxelFromIntersection(intersection, ""); - Overlays.editOverlay(linePreviewTop, { position: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true }); - Overlays.editOverlay(linePreviewBottom, { position: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true }); - Overlays.editOverlay(linePreviewLeft, { position: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true }); - Overlays.editOverlay(linePreviewRight, { position: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true }); - } else { - Overlays.editOverlay(linePreviewTop, { visible: false }); - Overlays.editOverlay(linePreviewBottom, { visible: false }); - Overlays.editOverlay(linePreviewLeft, { visible: false }); - Overlays.editOverlay(linePreviewRight, { visible: false }); - } -} - -function mouseMoveEvent(event) { - trackLastMouseX = event.x; - trackLastMouseY = event.y; - if (!voxelToolSelected) { - return; - } - showPreviewLines(); -} - - -// Array of possible trees, right now there is only one -var treeTypes = []; - -treeTypes.push({ - name: "Tall Green", - // Voxel Colors - wood: { r: 133, g: 81, b: 53 }, - leaves: { r: 22, g: 83, b: 31 }, - - // How tall the tree is - height: { min: 20, max: 60 }, - middleHeight: 0.3, - - // Chance of making a branch - branchChance: { min: 0.01, max: 0.1 }, - branchLength: { min: 30, max: 60 }, - branchThickness: { min: 2, max: 7}, - - // The width of the core, affects width and shape - coreWidth: { min: 1, max: 4 }, - - //TODO: Make this quadratic splines instead of linear - bottomThickness: { min: 2, max: 8 }, - middleThickness: { min: 1, max: 4 }, - topThickness: { min: 3, max: 6 }, - - //Modifies leaves at top - leafCapSizeOffset: 0 -}); - -// Applies noise to color -var colorNoiseRange = 0.2; - - -// Useful constants -var LEFT = 0; -var BACK = 1; -var RIGHT = 2; -var FRONT = 3; -var UP = 4; - -// Interpolates between min and max of treevar based on b -function interpolate(treeVar, b) { - return (treeVar.min + (treeVar.max - treeVar.min) * b); -} - -function makeBranch(x, y, z, step, length, dir, thickness, wood, leaves) { - var moveDir; - - var currentThickness; - //thickness attenuates to thickness - 3 - var finalThickness = thickness - 3; - if (finalThickness < 1) { - finalThickness = 1; - } - //Iterative branch generation - while (true) { - - //If we are at the end, place a ball of leaves - if (step == 0) { - makeSphere(x, y, z, 2 + finalThickness, leaves); - return; - } - //thickness attenuation - currentThickness = Math.round((finalThickness + (thickness - finalThickness) * (step/length))) - 1; - - - // If the branch is thick, grow a vertical slice - if (currentThickness > 0) { - for (var i = -currentThickness; i <= currentThickness; i++) { - var len = currentThickness - Math.abs(i); - switch (dir) { - case 0: //left - case 2: //right - growInDirection(x, y + i * voxelSize, z, len, len, BACK, wood, false, true); - growInDirection(x, y + i * voxelSize, z, len, len, FRONT, wood, false, false) - break; - case 1: //back - case 3: //front - growInDirection(x, y + i * voxelSize, z, len, len, LEFT, wood, false, true); - growInDirection(x, y + i * voxelSize, z, len, len, RIGHT, wood, false, false) - break; - } - } - } else { - //Otherwise place a single voxel - var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; - Voxels.setVoxel(x, y, z, voxelSize, wood.r * colorNoise, wood.g * colorNoise, wood.b * colorNoise); - } - - // determines random change in direction for branch - var r = Math.floor(Math.random() * 9); - - - if (r >= 6){ - moveDir = dir; //in same direction - } else if (r >= 4) { - moveDir = UP; //up - } - else if (dir == LEFT){ - if (r >= 2){ - moveDir = FRONT; - } - else{ - moveDir = BACK; - } - } - else if (dir == BACK){ - if (r >= 2){ - moveDir = LEFT; - } - else{ - moveDir = RIGHT; - } - } - else if (dir == RIGHT){ - if (r >= 2){ - moveDir = BACK; - } - else{ - moveDir = FRONT; - } - } - else if (dir == FRONT){ - if (r >= 2){ - moveDir = RIGHT; - } - else{ - moveDir = LEFT; - } - } - - //Move the branch by moveDir - switch (moveDir) { - case 0: //left - x = x - voxelSize; - break; - case 1: //back - z = z - voxelSize; - break; - case 2: //right - x = x + voxelSize; - break; - case 3: //front - z = z + voxelSize; - break; - case 4: //up - y = y + voxelSize; - break; - } - - step--; - } -} - -// Places a sphere of voxels -function makeSphere(x, y, z, radius, color) { - if (radius <= 0) { - return; - } - var width = radius * 2 + 1; - var distance; - - for (var i = -radius; i <= radius; i++){ - for (var j = -radius; j <= radius; j++){ - for (var k = -radius; k <= radius; k++){ - distance = Math.sqrt(i * i + j * j + k * k); - if (distance <= radius){ - var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; - Voxels.setVoxel(x + i * voxelSize, y + j * voxelSize, z + k * voxelSize, voxelSize, color.r * colorNoise, color.g * colorNoise, color.b * colorNoise); - } - } - } - } -} - -function growInDirection(x, y, z, step, length, dir, color, isSideBranching, addVoxel) { - - - if (addVoxel == true) { - var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; - Voxels.setVoxel(x, y, z, voxelSize, color.r * colorNoise, color.g * colorNoise, color.b * colorNoise); - } - - // If this is a main vein, it will branch outward perpendicular to its motion - if (isSideBranching == true){ - var step2; - if (step >= length - 1){ - step2 = length; - } - else{ - step2 = step + 1; - } - growInDirection(x, y, z, step, length, BACK, color, false, false); - growInDirection(x, y, z, step, length, FRONT, color, false, false); - } - - if (step < 1) return; - - // Recursively move in the direction - if (dir == LEFT) { //left - growInDirection(x - voxelSize, y, z, step - 1, length, dir, color, isSideBranching, true); - } - else if (dir == BACK) { //back - growInDirection(x, y, z - voxelSize, step - 1, length, dir, color, isSideBranching, true); - } - else if (dir == RIGHT) { //right - growInDirection(x + voxelSize, y, z, step - 1, length, dir, color, isSideBranching, true); - } - else if (dir == FRONT) {//front - growInDirection(x, y, z + voxelSize, step - 1, length, dir, color, isSideBranching, true); - } - -} - -// Grows the thickness of the tree -function growHorizontalSlice(x, y, z, thickness, color, side) { - // The side variable determines which directions we should grow in - // it is an optimization that prevents us from visiting voxels multiple - // times for trees with a coreWidth > 1 - - // side: - // 8 == all directions - // 0 1 2 - // 3 -1 4 - // 5 6 7 - - Voxels.setVoxel(x, y, z, voxelSize, color.r, color.g, color.b); - - //We are done if there is no thickness - if (thickness == 0) { - return; - } - - - switch (side) { - case 0: - growInDirection(x, y, z, thickness, thickness, LEFT, color, true, false); - break; - case 1: - growInDirection(x, y, z, thickness, thickness, BACK, color, false, false); - break; - case 2: - growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); - break; - case 3: - growInDirection(x, y, z, thickness, thickness, LEFT, color, false, false); - break; - case 4: - growInDirection(x, y, z, thickness, thickness, BACK, color, false, false); - break; - case 5: - growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); - break; - case 6: - growInDirection(x, y, z, thickness, thickness, FRONT, color, false, false); - break; - case 7: - growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); - break; - case 8: - if (thickness > 1){ - growInDirection(x, y, z, thickness, thickness, LEFT, color, true, false); - growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false) - } else if (thickness == 1){ - Voxels.setVoxel(x - voxelSize, y, z, voxelSize, color.r, color.g, color.b); - Voxels.setVoxel(x + voxelSize, y, z, voxelSize, color.r, color.g, color.b); - Voxels.setVoxel(x, y, z - voxelSize, voxelSize, color.r, color.g, color.b); - Voxels.setVoxel(x, y, z + voxelSize, voxelSize, color.r, color.g, color.b); - } - break; - } -} - -function computeSide(x, z, coreWidth) { - // side: - // 8 == all directions - // 0 1 2 - // 3 -1 4 - // 5 6 7 - - // if the core is only a single block, we can grow out in all directions - if (coreWidth == 1){ - return 8; - } - - // Back face - if (z == 0) { - if (x == 0) { - return 0; - } else if (x == coreWidth - 1) { - return 2; - } else { - return 1; - } - } - - // Front face - if (z == (coreWidth - 1)) { - if (x == 0) { - return 5; - } else if (x == (coreWidth - 1)) { - return 7; - } else { - return 6; - } - } - - // Left face - if (x == 0) { - return 3; - } - - // Right face - if (x == (coreWidth - 1)) { - return 4; - } - - //Interior - return -1; -} - - -function growTree(x, y, z, tree) { - - // The size of the tree, from 0-1 - var treeSize = Math.random(); - - // Get tree properties by interpolating with the treeSize - var height = interpolate(tree.height, treeSize); - var baseHeight = Math.ceil(tree.middleHeight * height); - var bottomThickness = interpolate(tree.bottomThickness, treeSize); - var middleThickness = interpolate(tree.middleThickness, treeSize); - var topThickness = interpolate(tree.topThickness, treeSize); - var coreWidth = Math.ceil(interpolate(tree.coreWidth, treeSize)); - - var thickness; - var side; - - //Loop upwards through each slice of the tree - for (var i = 0; i < height; i++){ - - //Branch properties are based on current height as well as the overall tree size - var branchChance = interpolate(tree.branchChance, i / height); - var branchLength = Math.ceil(interpolate(tree.branchLength, (i / height) * treeSize)); - var branchThickness = Math.round(interpolate(tree.branchThickness, (i / height) * treeSize)); - - // Get the "thickness" of the tree by doing linear interpolation between the middle thickness - // and the top and bottom thickness. - if (i <= baseHeight && baseHeight != 0){ - thickness = (i / (baseHeight) * (middleThickness - bottomThickness) + bottomThickness); - } else { - var denom = ((height - baseHeight)) * (topThickness - middleThickness) + middleThickness; - if (denom != 0) { - thickness = (i - baseHeight) / denom; - } else { - thickness = 0; - } - } - // The core of the tree is a vertical rectangular prism through the middle of the tree - - //Loop through the "core", which helps shape the trunk - var startX = x - Math.floor(coreWidth / 2) * voxelSize; - var startZ = z - Math.floor(coreWidth / 2) * voxelSize; - for (var j = 0; j < coreWidth; j++) { - for (var k = 0; k < coreWidth; k++) { - //determine which side of the tree we are on - side = computeSide(j, k, coreWidth); - //grow a horizontal slice of the tree - growHorizontalSlice(startX + j * voxelSize, y + i * voxelSize, startZ + k * voxelSize, Math.floor(thickness), tree.wood, side); - - // Branches - if (side != -1) { - var r = Math.random(); - if (r <= branchChance){ - var dir = Math.floor((Math.random() * 4)); - makeBranch(startX + j * voxelSize, y + i * voxelSize, startZ + k * voxelSize, branchLength, branchLength, dir, branchThickness, tree.wood, tree.leaves); - - } - } - } - } - } - - makeSphere(x, y + height * voxelSize, z, topThickness + coreWidth + tree.leafCapSizeOffset, tree.leaves); -} - -function mousePressEvent(event) { - var mouseX = event.x; - var mouseY = event.y; - - var clickedOnSomething = false; - // Check if we clicked an overlay - var clickedOverlay = Overlays.getOverlayAtPoint({x: mouseX, y: mouseY}); - - if (clickedOverlay == voxelTool) { - voxelToolSelected = !voxelToolSelected; - - if (voxelToolSelected == true) { - Overlays.editOverlay(voxelTool, { - color: activeUIColor - }); - } else { - Overlays.editOverlay(voxelTool, { - color: UIColor - }); - } - - clickedOnSomething = true; - } else if (scaleSelector.clicked(event.x, event.y)) { - clickedOnSomething = true; - voxelSize = scaleSelector.scale; - } - - // Return if we clicked on the UI or the voxel tool is disabled - if (clickedOnSomething || !voxelToolSelected) { - return; - } - - // Compute the picking ray for the click - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - var resultVoxel = calculateVoxelFromIntersection(intersection, "add"); - - // Currently not in use, could randomly select a tree - var treeIndex = Math.floor(Math.random() * treeTypes.length); - - // Grow the first tree type - growTree(resultVoxel.x, resultVoxel.y, resultVoxel.z, treeTypes[0]); - -} - - -function scriptEnding() { - Overlays.deleteOverlay(linePreviewTop); - Overlays.deleteOverlay(linePreviewBottom); - Overlays.deleteOverlay(linePreviewLeft); - Overlays.deleteOverlay(linePreviewRight); - scaleSelector.cleanup(); - Overlays.deleteOverlay(voxelTool); -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); - -Script.scriptEnding.connect(scriptEnding); - -Voxels.setPacketsPerSecond(10000); diff --git a/examples/gun.js b/examples/gun.js index 2386e61539..27e6f4e37c 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -156,19 +156,6 @@ function shootTarget() { -function entityCollisionWithVoxel(entity, voxel, collision) { - var HOLE_SIZE = 0.125; - var entityProperties = Entities.getEntityProperties(entity); - var position = entityProperties.position; - Entities.deleteEntity(entity); - // Make a hole in this voxel - //Vec3.print("voxel penetration", collision.penetration); - //Vec3.print("voxel contactPoint", collision.contactPoint); - Voxels.eraseVoxel(collision.contactPoint.x, collision.contactPoint.y, collision.contactPoint.z, HOLE_SIZE); - audioOptions.position = collision.contactPoint; - Audio.playSound(impactSound, audioOptions); -} - function entityCollisionWithEntity(entity1, entity2, collision) { score++; if (showScore) { @@ -329,7 +316,6 @@ function scriptEnding() { MyAvatar.detachOne(gunModel); } -Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel); Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); Script.scriptEnding.connect(scriptEnding); Script.update.connect(update); diff --git a/examples/inspect.js b/examples/inspect.js index 49ebc86de1..ff0925db97 100644 --- a/examples/inspect.js +++ b/examples/inspect.js @@ -221,13 +221,11 @@ function mousePressEvent(event) { // Compute trajectories related values var pickRay = Camera.computePickRay(mouseLastX, mouseLastY); - var voxelIntersection = Voxels.findRayIntersection(pickRay); var modelIntersection = Entities.findRayIntersection(pickRay); position = Camera.getPosition(); var avatarTarget = MyAvatar.getTargetAvatarPosition(); - var voxelTarget = voxelIntersection.intersection; var distance = -1; @@ -246,13 +244,6 @@ function mousePressEvent(event) { string = "Inspecting avatar"; } - if ((distance == -1 || Vec3.length(Vec3.subtract(voxelTarget, position)) < distance) && - (voxelTarget.x != 0 || voxelTarget.y != 0 || voxelTarget.z != 0)) { - distance = Vec3.length(Vec3.subtract(voxelTarget, position)); - center = voxelTarget; - string = "Inspecting voxel"; - } - if (distance == -1) { return; } diff --git a/examples/libraries/ModelImporter.js b/examples/libraries/ModelImporter.js index a0c35bb663..1e52c8fdec 100644 --- a/examples/libraries/ModelImporter.js +++ b/examples/libraries/ModelImporter.js @@ -93,7 +93,7 @@ ModelImporter = function (opts) { this.mouseMoveEvent = function (event) { if (self._importing) { var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); + var intersection = Entities.findRayIntersection(pickRay); var distance = 2;// * self._scale; diff --git a/examples/libraries/walkApi.js b/examples/libraries/walkApi.js index d2622d5833..f800682af5 100644 --- a/examples/libraries/walkApi.js +++ b/examples/libraries/walkApi.js @@ -181,7 +181,9 @@ spatialInformation = (function() { // use the blocking version of findRayIntersection to avoid errors var pickRay = {origin: MyAvatar.position, direction: {x:0, y:-1, z:0}}; - return Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;; + + // TODO: change this to use entities? + return false; // Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;; } } diff --git a/examples/lookAtExample.js b/examples/lookAtExample.js index 729281fa03..7e3010eb8a 100644 --- a/examples/lookAtExample.js +++ b/examples/lookAtExample.js @@ -61,7 +61,7 @@ function mousePressEvent(event) { cancelLookAt(); } else { var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); + var intersection = Entities.findRayIntersection(pickRay); if (intersection.intersects) { // remember the old mode we were in diff --git a/examples/movingVoxel.js b/examples/movingVoxel.js deleted file mode 100644 index c55957cd04..0000000000 --- a/examples/movingVoxel.js +++ /dev/null @@ -1,52 +0,0 @@ -// -// movingVoxel.js -// examples -// -// Copyright 2014 High Fidelity, Inc. -// -// This sample script creates a voxel moving back and forth in a line -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var position = { x: 0, y: 0, z: 0 }; -var oldPosition = { x: 0, y: 0, z:0 }; -var size = 0.25; -var direction = 1.0; -var range = 2.0; -var color = { r: 100, g: 50, b: 150 }; -var colorEdge = { r:255, g:250, b:175 }; -var frame = 0; -var thisColor = color; - -function moveVoxel(deltaTime) { - frame++; - if (frame % 3 == 0) { - // Get a new position - position.x += direction * size; - if (position.x < 0) { - direction *= -1.0; - position.x = 0; - thisColor = colorEdge; - } - if (position.x > range) { - direction *= -1.0; - position.x = range; - thisColor = colorEdge; - } - // Create a new voxel - Voxels.setVoxel(position.x, position.y, position.z, size, thisColor.r, thisColor.g, thisColor.b); - // delete old voxel - Voxels.eraseVoxel(oldPosition.x, oldPosition.y, oldPosition.z, size); - // Copy old location to new - oldPosition.x = position.x; - oldPosition.y = position.y; - oldPosition.z = position.z; - thisColor = color; - } -} - -Voxels.setPacketsPerSecond(300); -// Connect a call back that happens every frame -Script.update.connect(moveVoxel); \ No newline at end of file diff --git a/examples/rayPickExample.js b/examples/rayPickExample.js index c3b6581007..b0b7c24fef 100644 --- a/examples/rayPickExample.js +++ b/examples/rayPickExample.js @@ -18,30 +18,6 @@ function mouseMoveEvent(event) { print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z); print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z); var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - if (!intersection.accurate) { - print(">>> NOTE: intersection not accurate. will try calling Voxels.findRayIntersectionBlocking()"); - intersection = Voxels.findRayIntersectionBlocking(pickRay); - print(">>> AFTER BLOCKING CALL intersection.accurate=" + intersection.accurate); - } - - if (intersection.intersects) { - print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", " - + intersection.voxel.green + ", " + intersection.voxel.blue); - print("intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " - + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); - print("intersection face=" + intersection.face); - print("intersection distance=" + intersection.distance); - print("intersection intersection.x/y/z=" + intersection.intersection.x + ", " - + intersection.intersection.y + ", " + intersection.intersection.z); - - // also test the getVoxelAt() api which should find and return same voxel - - var voxelAt = Voxels.getVoxelAt(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s); - print("voxelAt.x/y/z/s=" + voxelAt.x + ", " + voxelAt.y + ", " + voxelAt.z + ": " + voxelAt.s); - print("voxelAt.red/green/blue=" + voxelAt.red + ", " + voxelAt.green + ", " + voxelAt.blue); - } - intersection = Entities.findRayIntersection(pickRay); if (!intersection.accurate) { print(">>> NOTE: intersection not accurate. will try calling Entities.findRayIntersectionBlocking()"); diff --git a/examples/ribbon.js b/examples/ribbon.js deleted file mode 100644 index dd3d46fbfc..0000000000 --- a/examples/ribbon.js +++ /dev/null @@ -1,176 +0,0 @@ -// -// ribbon.js -// examples -// -// Created by Andrzej Kapolka on 2/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -function vectorMultiply(vector, scalar) { - return [ vector[0] * scalar, vector[1] * scalar, vector[2] * scalar ]; -} - -function vectorAdd(firstVector, secondVector) { - return [ firstVector[0] + secondVector[0], firstVector[1] + secondVector[1], firstVector[2] + secondVector[2] ]; -} - -function vectorSubtract(firstVector, secondVector) { - return [ firstVector[0] - secondVector[0], firstVector[1] - secondVector[1], firstVector[2] - secondVector[2] ]; -} - -function vectorCross(firstVector, secondVector) { - return [ firstVector[1] * secondVector[2] - firstVector[2] * secondVector[1], - firstVector[2] * secondVector[0] - firstVector[0] * secondVector[2], - firstVector[0] * secondVector[1] - firstVector[1] * secondVector[0] ]; -} - -function vectorLength(vector) { - return Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]); -} - -function vectorNormalize(vector) { - return vectorMultiply(vector, 1.0 / vectorLength(vector)); -} - -function vectorClone(vector) { - return [ vector[0], vector[1], vector[2] ]; -} - -function mix(first, second, amount) { - return first + (second - first) * amount; -} - -function vectorMix(firstVector, secondVector, amount) { - return vectorAdd(firstVector, vectorMultiply(vectorSubtract(secondVector, firstVector), amount)); -} - -function randomVector(minVector, maxVector) { - return [ mix(minVector[0], maxVector[0], Math.random()), mix(minVector[1], maxVector[1], Math.random()), - mix(minVector[2], maxVector[2], Math.random()) ]; -} - -function applyToLine(start, end, granularity, fn) { - // determine the number of steps from the maximum length - var steps = Math.max( - Math.abs(Math.floor(start[0] / granularity) - Math.floor(end[0] / granularity)), - Math.abs(Math.floor(start[1] / granularity) - Math.floor(end[1] / granularity)), - Math.abs(Math.floor(start[2] / granularity) - Math.floor(end[2] / granularity))); - var position = vectorClone(start); - var increment = vectorMultiply(vectorSubtract(end, start), 1.0 / steps); - for (var i = 0; i <= steps; i++) { - fn(granularity * Math.floor(position[0] / granularity), - granularity * Math.floor(position[1] / granularity), - granularity * Math.floor(position[2] / granularity), - granularity); - position = vectorAdd(position, increment); - } -} - -function drawLine(start, end, color, granularity) { - applyToLine(start, end, granularity, function(x, y, z, scale) { - Voxels.setVoxel(x, y, z, scale, color[0], color[1], color[2]); - }); -} - -function eraseLine(start, end, granularity) { - applyToLine(start, end, granularity, function(x, y, z, scale) { - Voxels.eraseVoxel(x, y, z, scale); - }); -} - -function getHueColor(hue) { - // see http://en.wikipedia.org/wiki/HSL_and_HSV - var hPrime = hue / 60.0; - var x = Math.floor(255.0 * (1.0 - Math.abs(hPrime % 2.0 - 1.0))); - if (hPrime < 1) { - return [255, x, 0]; - - } else if (hPrime < 2) { - return [x, 255, 0]; - - } else if (hPrime < 3) { - return [0, 255, x]; - - } else if (hPrime < 4) { - return [0, x, 255]; - - } else if (hPrime < 5) { - return [x, 0, 255]; - - } else { // hPrime < 6 - return [255, 0, x]; - } -} - -var UNIT_MIN = [-1.0, -1.0, -1.0]; -var UNIT_MAX = [1.0, 1.0, 1.0]; - -var EPSILON = 0.00001; - -var BOUNDS_MIN = [5.0, 0.0, 5.0]; -var BOUNDS_MAX = [15.0, 10.0, 15.0]; - -var GRANULARITY = 1.0 / 16.0; - -var WIDTH = 0.5; - -var HISTORY_LENGTH = 300; - -var stateHistory = []; -var position; -var velocity; -var hueAngle = 0; -var smoothedOffset; - -function step(deltaTime) { - if (stateHistory.length === 0) { - // start at a random position within the bounds, with a random velocity - position = randomVector(BOUNDS_MIN, BOUNDS_MAX); - do { - velocity = randomVector(UNIT_MIN, UNIT_MAX); - } while (vectorLength(velocity) < EPSILON); - velocity = vectorMultiply(velocity, GRANULARITY * 0.5 / vectorLength(velocity)); - smoothedOffset = [0.0, 0.0, 0.0]; - } - - var right = vectorCross(velocity, [0.0, 1.0, 0.0]); - if (vectorLength(right) < EPSILON) { - right = [1.0, 0.0, 0.0]; - } else { - right = vectorNormalize(right); - } - var up = vectorNormalize(vectorCross(right, velocity)); - var ANGULAR_SPEED = 2.0; - var radians = hueAngle * Math.PI * ANGULAR_SPEED / 180.0; - var offset = vectorAdd(vectorMultiply(right, WIDTH * Math.cos(radians)), vectorMultiply(up, WIDTH * Math.sin(radians))); - var OFFSET_SMOOTHING = 0.9; - smoothedOffset = vectorMix(offset, smoothedOffset, OFFSET_SMOOTHING); - - var state = { start: vectorAdd(position, smoothedOffset), end: vectorSubtract(position, smoothedOffset) }; - drawLine(state.start, state.end, getHueColor(hueAngle), GRANULARITY); - stateHistory.push(state); - if (stateHistory.length > HISTORY_LENGTH) { - var last = stateHistory.shift(); - eraseLine(last.start, last.end, GRANULARITY); - } - - // update position, check against bounds - position = vectorAdd(position, velocity); - for (var i = 0; i < 3; i++) { - if (position[i] < BOUNDS_MIN[i]) { - velocity[i] = -velocity[i]; - position[i] += 2.0 * (BOUNDS_MIN[i] - position[i]); - - } else if (position[i] > BOUNDS_MAX[i]) { - velocity[i] = -velocity[i]; - position[i] += 2.0 * (BOUNDS_MAX[i] - position[i]); - } - } - var MAX_HUE_ANGLE = 360; - hueAngle = (hueAngle + 1) % MAX_HUE_ANGLE; -} - -Script.update.connect(step); diff --git a/examples/rockPaperScissorsCells.js b/examples/rockPaperScissorsCells.js deleted file mode 100644 index 2a9cb00a0b..0000000000 --- a/examples/rockPaperScissorsCells.js +++ /dev/null @@ -1,272 +0,0 @@ -// rockPaperScissorsCells.js -// examples -// -// Created by Ben Arnold on 7/16/14. -// Copyright 2014 High Fidelity, Inc. -// -// This sample script creates a voxel wall that simulates the Rock Paper Scissors cellular -// automata. http://www.gamedev.net/blog/844/entry-2249737-another-cellular-automaton-video/ -// If multiple instances of this script are run, they will combine into a larger wall. -// NOTE: You must run each instance one at a time. If they all start at once there are race conditions. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var NUMBER_OF_CELLS_EACH_DIMENSION = 48; -var NUMBER_OF_CELLS_REGION_EACH_DIMESION = 16; -var REGIONS_EACH_DIMENSION = NUMBER_OF_CELLS_EACH_DIMENSION / NUMBER_OF_CELLS_REGION_EACH_DIMESION; - -var isLocal = false; - -var currentCells = []; -var nextCells = []; - -var cornerPosition = {x: 100, y: 0, z: 0 } -var position = {x: 0, y: 0, z: 0 }; - -var METER_LENGTH = 1; -var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION; - -var viewerPosition = {x: cornerPosition.x + (NUMBER_OF_CELLS_EACH_DIMENSION / 2) * cellScale, y: cornerPosition.y + (NUMBER_OF_CELLS_EACH_DIMENSION / 2) * cellScale, z: cornerPosition.z }; - -viewerPosition.z += 50; -var yaw = 0; -var orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0); - -//Feel free to add new cell types here. It can be more than three. -var cellTypes = []; -cellTypes[0] = { r: 255, g: 0, b: 0 }; -cellTypes[1] = { r: 0, g: 255, b: 0 }; -cellTypes[2] = { r: 0, g:0, b: 255 }; -cellTypes[3] = { r: 0, g: 255, b: 255 }; - - -//Check for free region for AC -var regionMarkerX = -1; -var regionMarkerY = -1; -var regionMarkerI = -1; -var regionMarkerJ = -1; - -var regionMarkerColor = {r: 254, g: 0, b: 253}; - -function setRegionToColor(startX, startY, width, height, color) { - for (var i = startY; i < startY + height; i++) { - for (var j = startX; j < startX + width; j++) { - - currentCells[i][j] = { changed: true, type: color }; - - // put the same value in the nextCells array for first board draw - nextCells[i][j] = { changed: true, type: color }; - } - } -} - -function init() { - - for (var i = 0; i < REGIONS_EACH_DIMENSION; i++) { - for (var j = 0; j < REGIONS_EACH_DIMENSION; j++) { - var x = cornerPosition.x + (j) * cellScale; - var y = cornerPosition.y + (i + NUMBER_OF_CELLS_EACH_DIMENSION) * cellScale; - var z = cornerPosition.z; - var voxel = Voxels.getVoxelAt(x, y, z, cellScale); - if (voxel.x != x || voxel.y != y || voxel.z != z || voxel.s != cellScale || - voxel.red != regionMarkerColor.r || voxel.green != regionMarkerColor.g || voxel.blue != regionMarkerColor.b) { - regionMarkerX = x; - regionMarkerY = y; - regionMarkerI = i; - regionMarkerJ = j; - i = REGIONS_EACH_DIMENSION; //force quit loop - break; - } - } - } - - //Didnt find an open spot, end script - if (regionMarkerX == -1) { - Script.stop(); - } - - position.x = cornerPosition.x + regionMarkerJ * NUMBER_OF_CELLS_REGION_EACH_DIMESION; - position.y = cornerPosition.y + regionMarkerI * NUMBER_OF_CELLS_REGION_EACH_DIMESION; - position.z = cornerPosition.z; - - Voxels.setVoxel(regionMarkerX, regionMarkerY, cornerPosition.z, cellScale, regionMarkerColor.r, regionMarkerColor.g, regionMarkerColor.b); - - for (var i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) { - // create the array to hold this row - currentCells[i] = []; - - // create the array to hold this row in the nextCells array - nextCells[i] = []; - } - - var width = NUMBER_OF_CELLS_REGION_EACH_DIMESION / 2; - setRegionToColor(0, 0, width, width, 0); - setRegionToColor(0, width, width, width, 1); - setRegionToColor(width, width, width, width, 2); - setRegionToColor(width, 0, width, width, 3); -} - -function updateCells() { - var i = 0; - var j = 0; - var cell; - var y = 0; - var x = 0; - - for (i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) { - - cell = currentCells[i][j]; - - var r = Math.floor(Math.random() * 8); - - switch (r){ - case 0: - y = i - 1; - x = j - 1; - break; - case 1: - y = i; - x = j-1; - break; - case 2: - y = i + 1; - x = j - 1; - break; - case 3: - y = i + 1; - x = j; - break; - case 4: - y = i + 1; - x = j + 1; - break; - case 5: - y = i; - x = j + 1; - break; - case 6: - y = i - 1; - x = j + 1; - break; - case 7: - y = i - 1; - x = j; - break; - default: - continue; - - } - - //check the voxel grid instead of local array when on the edge - if (x == -1 || x == NUMBER_OF_CELLS_REGION_EACH_DIMESION || - y == -1 || y == NUMBER_OF_CELLS_REGION_EACH_DIMESION) { - - var voxel = Voxels.getVoxelAt(position.x + x * cellScale, position.y + y * cellScale, position.z, cellScale); - var predatorCellType = ((cell.type + 1) % cellTypes.length); - var predatorCellColor = cellTypes[predatorCellType]; - if (voxel.red == predatorCellColor.r && voxel.green == predatorCellColor.g && voxel.blue == predatorCellColor.b) { - nextCells[i][j].type = predatorCellType; - nextCells[i][j].changed = true; - } - } else { - - if (currentCells[y][x].type == ((cell.type + 1) % cellTypes.length)) { - nextCells[i][j].type = currentCells[y][x].type; - nextCells[i][j].changed = true; - } else { - //indicate no update - nextCells[i][j].changed = false; - } - } - } - } - - for (i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) { - if (nextCells[i][j].changed == true) { - // there has been a change to this cell, change the value in the currentCells array - currentCells[i][j].type = nextCells[i][j].type; - currentCells[i][j].changed = true; - } - } - } -} - -function sendNextCells() { - for (var i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) { - for (var j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) { - if (nextCells[i][j].changed == true) { - // there has been a change to the state of this cell, send it - - // find the x and y position for this voxel, z = 0 - var x = j * cellScale; - var y = i * cellScale; - var type = nextCells[i][j].type; - - // queue a packet to add a voxel for the new cell - Voxels.setVoxel(position.x + x, position.y + y, position.z, cellScale, cellTypes[type].r, cellTypes[type].g, cellTypes[type].b); - } - } - } -} - -var sentFirstBoard = false; -var voxelViewerInit = false; - -var UPDATES_PER_SECOND = 6.0; -var frameIndex = 1.0; -var oldFrameIndex = 0; - -var framesToWait = UPDATES_PER_SECOND; - -function step(deltaTime) { - - if (isLocal == false) { - if (voxelViewerInit == false) { - VoxelViewer.setPosition(viewerPosition); - VoxelViewer.setOrientation(orientation); - voxelViewerInit = true; - } - VoxelViewer.queryOctree(); - } - - frameIndex += deltaTime * UPDATES_PER_SECOND; - if (Math.floor(frameIndex) == oldFrameIndex) { - return; - } - oldFrameIndex++; - - if (frameIndex <= framesToWait) { - return; - } - - if (sentFirstBoard) { - // we've already sent the first full board, perform a step in time - updateCells(); - } else { - // this will be our first board send - sentFirstBoard = true; - init(); - } - - if (isLocal == false) { - VoxelViewer.queryOctree(); - } - sendNextCells(); -} - -function scriptEnding() { - Voxels.eraseVoxel(regionMarkerX, regionMarkerY, position.z, cellScale); -} - -Script.scriptEnding.connect(scriptEnding); - -Script.update.connect(step); -Voxels.setPacketsPerSecond(2000); - -// test for local... -Menu.isOptionChecked("Voxels"); -isLocal = true; // will only get here on local client \ No newline at end of file diff --git a/examples/voxelsoundwaves.js b/examples/voxelsoundwaves.js deleted file mode 100644 index 6de46e23cf..0000000000 --- a/examples/voxelsoundwaves.js +++ /dev/null @@ -1,226 +0,0 @@ - - - -var wallX = 8000; -var wallY = 8000; -var wallZ = 8000;//location - - -var VOXELSIZE=12;//size of each voxel - -var FACTOR = 0.75; - -var loud=1.0; -var maxLoud=500; -var minLoud=200;//range of loudness - - - -var maxB={color:225,direction:0,speed:1}; -var minB={color:50,direction:1,speed:1}; -var maxG={color:200,direction:0,speed:1}; -var minG={color:30,direction:1,speed:1}; -var maxR={color:255,direction:0,speed:1}; -var minR={color:150,direction:1,speed:1};//color objects -var addVoxArray=[]; -var removeVoxArray=[]; -var numAddVox=0; -var numRemoveVox=0;//array for voxels removed and added - - -var height; -var wallWidth=34; -var wallHeight=25; -var maxHeight=wallHeight; -var minHeight=0;//properties of wall - - -var heightSamplesArray=[]; -var sampleIndex=0;//declare new array of heights - -var direction=1; - - - - -//initiate and fill array of heights -for(var k=0;k Date: Wed, 31 Dec 2014 16:29:55 -0800 Subject: [PATCH 14/27] modify extrapolation behavior when bullet enabled Allows Bullet to specify an object as "at rest" by setting velocity to zero. Also, moved velocity damping above position integration to get the same order of operations as Bullet. --- libraries/entities/CMakeLists.txt | 1 + libraries/entities/src/EntityItem.cpp | 61 +++++++++++++++++---------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 2da7745837..7589599548 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -4,6 +4,7 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) include_glm() +include_bullet() link_hifi_libraries(avatars shared octree gpu model fbx networking animation) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d0b019467c..12b95c48d2 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -648,7 +648,8 @@ void EntityItem::simulate(const quint64& now) { glm::vec3 angularVelocity = glm::radians(getAngularVelocity()); float angularSpeed = glm::length(angularVelocity); - if (angularSpeed < EPSILON_VELOCITY_LENGTH) { + const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.0017453f; // ~0.1 degree/sec + if (angularSpeed < EPSILON_ANGULAR_VELOCITY_LENGTH) { setAngularVelocity(NO_ANGULAR_VELOCITY); } else { float angle = timeElapsed * angularSpeed; @@ -670,9 +671,31 @@ void EntityItem::simulate(const quint64& now) { } } +#ifdef USE_BULLET_PHYSICS + // When Bullet is available we assume that "zero velocity" means "at rest" + // because of collision conditions this simulation does not know about + // so we don't fall in for the non-zero gravity case here. + if (hasVelocity()) { +#else // !USE_BULLET_PHYSICS if (hasVelocity() || hasGravity()) { - glm::vec3 position = getPosition(); +#endif // USE_BULLET_PHYSICS + + // linear damping glm::vec3 velocity = getVelocity(); + float dampingTimescale = getDamping(); + if (dampingTimescale > 0.0f) { + float dampingFactor = glm::clamp(timeElapsed / dampingTimescale, 0.0f, 1.0f); + velocity *= (1.0f - dampingFactor); + if (wantDebug) { + qDebug() << " dampingTimescale:" << dampingTimescale; + qDebug() << " velocity AFTER dampingResistance:" << velocity; + qDebug() << " glm::length(velocity):" << glm::length(velocity); + qDebug() << " EPSILON_VELOCITY_LENGTH:" << EPSILON_VELOCITY_LENGTH; + } + } + + // integrate position forward + glm::vec3 position = getPosition(); glm::vec3 newPosition = position + (velocity * timeElapsed); if (wantDebug) { @@ -701,10 +724,10 @@ void EntityItem::simulate(const quint64& now) { position.y = getDistanceToBottomOfEntity(); } - // handle gravity.... + // apply gravity if (hasGravity()) { // handle resting on surface case, this is definitely a bit of a hack, and it only works on the - // "ground" plane of the domain, but for now it what we've got + // "ground" plane of the domain, but for now it's what we've got if (isRestingOnSurface()) { velocity.y = 0.0f; position.y = getDistanceToBottomOfEntity(); @@ -712,28 +735,15 @@ void EntityItem::simulate(const quint64& now) { velocity += getGravity() * timeElapsed; } } - - // handle damping for velocity - float dampingTimescale = getDamping(); - if (dampingTimescale > 0.0f) { - float dampingFactor = glm::clamp(timeElapsed / dampingTimescale, 0.0f, 1.0f); - velocity *= (1.0f - dampingFactor); - if (wantDebug) { - qDebug() << " dampingTimescale:" << dampingTimescale; - qDebug() << " newVelocity:" << velocity; - } - } - - if (wantDebug) { - qDebug() << " velocity AFTER dampingResistance:" << velocity; - qDebug() << " glm::length(velocity):" << glm::length(velocity); - qDebug() << " EPSILON_VELOCITY_LENGTH:" << EPSILON_VELOCITY_LENGTH; - } - // round velocity to zero if it's close enough... +#ifdef USE_BULLET_PHYSICS + // When Bullet is available we assume that it will tell us when velocities go to zero... +#else // !USE_BULLET_PHYSICS + // ... otherwise we help things come to rest by clamping small velocities. if (glm::length(velocity) <= EPSILON_VELOCITY_LENGTH) { velocity = NO_VELOCITY; } +#endif // USE_BULLET_PHYSICS // NOTE: the simulation should NOT set any DirtyFlags on this entity setPosition(position); // this will automatically recalculate our collision shape @@ -751,7 +761,13 @@ void EntityItem::simulate(const quint64& now) { } bool EntityItem::isMoving() const { +#ifdef USE_BULLET_PHYSICS + // When Bullet is available we assume that "zero velocity" means "at rest" + // because of collision conditions this simulation does not know about. + return hasVelocity() || hasAngularVelocity(); +#else // !USE_BULLET_PHYSICS return hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity(); +#endif //USE_BULLET_PHYSICS } bool EntityItem::lifetimeHasExpired() const { @@ -1009,7 +1025,6 @@ const float MIN_GRAVITY_DELTA = 0.001f; const float MIN_SPIN_DELTA = 0.0003f; void EntityItem::updatePosition(const glm::vec3& value) { - glm::vec3 debugPosition = value * (float) TREE_SCALE; if (glm::distance(_position, value) * (float)TREE_SCALE > MIN_POSITION_DELTA) { _position = value; recalculateCollisionShape(); From 4cc641320bbe6630104e119b8346646c42682956 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 2 Jan 2015 15:04:48 -0800 Subject: [PATCH 15/27] fix PerformanceTimer to handle timer stacks on multiple threads --- libraries/shared/src/PerfStat.cpp | 20 ++++++++++++++++---- libraries/shared/src/PerfStat.h | 11 ++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index b811a719bc..f5f6964b6d 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -13,7 +13,8 @@ #include #include -#include +#include +#include #include "PerfStat.h" @@ -77,15 +78,26 @@ void PerformanceTimerRecord::tallyResult(const quint64& now) { // PerformanceTimer // ---------------------------------------------------------------------------- -QString PerformanceTimer::_fullName; +QHash PerformanceTimer::_fullNames; QMap PerformanceTimer::_records; +PerformanceTimer::PerformanceTimer(const QString& name) : + _start(0), + _name(name) +{ + QString& fullName = _fullNames[QThread::currentThread()]; + fullName.append("/"); + fullName.append(_name); + _start = usecTimestampNow(); +} + PerformanceTimer::~PerformanceTimer() { quint64 elapsedusec = (usecTimestampNow() - _start); - PerformanceTimerRecord& namedRecord = _records[_fullName]; + QString& fullName = _fullNames[QThread::currentThread()]; + PerformanceTimerRecord& namedRecord = _records[fullName]; namedRecord.accumulateResult(elapsedusec); - _fullName.resize(_fullName.size() - (_name.size() + 1)); + fullName.resize(fullName.size() - (_name.size() + 1)); } // static diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 4f94be73b1..81731abfa9 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -73,14 +73,7 @@ private: class PerformanceTimer { public: - PerformanceTimer(const QString& name) : - _start(0), - _name(name) { - _fullName.append("/"); - _fullName.append(_name); - _start = usecTimestampNow(); - } - + PerformanceTimer(const QString& name); ~PerformanceTimer(); static const PerformanceTimerRecord& getTimerRecord(const QString& name) { return _records[name]; }; @@ -91,7 +84,7 @@ public: private: quint64 _start; QString _name; - static QString _fullName; + static QHash _fullNames; static QMap _records; }; From 1df54cffd6c22b2bbc468a5efca61213b6cf9a04 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 2 Jan 2015 17:28:51 -0800 Subject: [PATCH 16/27] add audio starvation detection --- interface/src/Audio.cpp | 20 +++++++++++++++++++- interface/src/Audio.h | 12 +++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 5bcd9bb647..be382523ff 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -124,7 +124,7 @@ Audio::Audio(QObject* parent) : _audioOutputMsecsUnplayedStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), _lastSentAudioPacket(0), _packetSentTimeGaps(1, APPROXIMATELY_30_SECONDS_OF_AUDIO_PACKETS), - _audioOutputIODevice(_receivedAudioStream) + _audioOutputIODevice(_receivedAudioStream, this) { // clear the array of locally injected samples memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); @@ -1823,6 +1823,16 @@ bool Audio::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) { return supportedFormat; } +void Audio::outputNotify() { + int recentUnfulfilled = _audioOutputIODevice.getRecentUnfulfilledReads(); + if (recentUnfulfilled > 0) { + qDebug() << "WARNING --- WE HAD at least:" << recentUnfulfilled << "recently unfulfilled readData() calls"; + + // TODO: Ryan Huffman -- add code here to increase the AUDIO_OUTPUT_BUFFER_SIZE_FRAMES... this code only + // runs in cases where the audio device requested data samples, and ran dry because we couldn't fulfill the request + } +} + bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) { bool supportedFormat = false; @@ -1856,6 +1866,8 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) // setup our general output device for audio-mixer audio _audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); + connect(_audioOutput, &QAudioOutput::notify, this, &Audio::outputNotify); + _audioOutput->setBufferSize(AUDIO_OUTPUT_BUFFER_SIZE_FRAMES * _outputFrameSize * sizeof(int16_t)); qDebug() << "Output Buffer capacity in frames: " << _audioOutput->bufferSize() / sizeof(int16_t) / (float)_outputFrameSize; @@ -1934,6 +1946,7 @@ qint64 Audio::AudioOutputIODevice::readData(char * data, qint64 maxSize) { int samplesRequested = maxSize / sizeof(int16_t); int samplesPopped; int bytesWritten; + if ((samplesPopped = _receivedAudioStream.popSamples(samplesRequested, false)) > 0) { AudioRingBuffer::ConstIterator lastPopOutput = _receivedAudioStream.getLastPopOutput(); lastPopOutput.readSamples((int16_t*)data, samplesPopped); @@ -1943,5 +1956,10 @@ qint64 Audio::AudioOutputIODevice::readData(char * data, qint64 maxSize) { bytesWritten = maxSize; } + int bytesAudioOutputUnplayed = _audio->_audioOutput->bufferSize() - _audio->_audioOutput->bytesFree(); + if (bytesAudioOutputUnplayed == 0 && bytesWritten == 0) { + _unfulfilledReads++; + } + return bytesWritten; } diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 47fe00a84c..da21db27dc 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -72,16 +72,22 @@ public: class AudioOutputIODevice : public QIODevice { public: - AudioOutputIODevice(MixedProcessedAudioStream& receivedAudioStream) : _receivedAudioStream(receivedAudioStream) {}; + AudioOutputIODevice(MixedProcessedAudioStream& receivedAudioStream, Audio* audio) : + _receivedAudioStream(receivedAudioStream), _audio(audio), _unfulfilledReads(0) {}; void start() { open(QIODevice::ReadOnly); } void stop() { close(); } qint64 readData(char * data, qint64 maxSize); qint64 writeData(const char * data, qint64 maxSize) { return 0; } + + int getRecentUnfulfilledReads() { int unfulfilledReads = _unfulfilledReads; _unfulfilledReads = 0; return unfulfilledReads; } private: MixedProcessedAudioStream& _receivedAudioStream; + Audio* _audio; + int _unfulfilledReads; }; + friend class AudioOutputIODevice; // setup for audio I/O Audio(QObject* parent = 0); @@ -170,11 +176,15 @@ public slots: const AudioStreamStats& getAudioMixerAvatarStreamAudioStats() const { return _audioMixerAvatarStreamAudioStats; } const QHash& getAudioMixerInjectedStreamAudioStatsMap() const { return _audioMixerInjectedStreamAudioStatsMap; } + void outputNotify(); + signals: bool muteToggled(); void preProcessOriginalInboundAudio(unsigned int sampleTime, QByteArray& samples, const QAudioFormat& format); void processInboundAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format); void processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format); + + private: void outputFormatChanged(); From 30200ef7eb03799410a396ed7ba9b1dfeca0257c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 5 Jan 2015 09:17:46 -0800 Subject: [PATCH 17/27] add damping to ObjectMotionState --- libraries/physics/src/ObjectMotionState.cpp | 10 ++++++++++ libraries/physics/src/ObjectMotionState.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index ded2291229..4abe52a861 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -48,6 +48,8 @@ ObjectMotionState::ObjectMotionState() : _volume(DEFAULT_VOLUME), _friction(DEFAULT_FRICTION), _restitution(DEFAULT_RESTITUTION), + _linearDamping(0.0f), + _angularDamping(0.0f), _wasInWorld(false), _motionType(MOTION_TYPE_STATIC), _body(NULL), @@ -79,6 +81,14 @@ void ObjectMotionState::setRestitution(float restitution) { _restitution = btMax(btMin(fabsf(restitution), 1.0f), 0.0f); } +void ObjectMotionState::setLinearDamping(float damping) { + _linearDamping = btMax(btMin(fabsf(damping), 1.0f), 0.0f); +} + +void ObjectMotionState::setAngularDamping(float damping) { + _angularDamping = btMax(btMin(fabsf(damping), 1.0f), 0.0f); +} + void ObjectMotionState::setVolume(float volume) { _volume = btMax(btMin(fabsf(volume), MAX_VOLUME), MIN_VOLUME); } diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index ea9dcad0fc..24a00609cf 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -66,6 +66,8 @@ public: void setDensity(float density); void setFriction(float friction); void setRestitution(float restitution); + void setLinearDamping(float damping); + void setAngularDamping(float damping); void setVolume(float volume); float getMass() const { return _volume * _density; } @@ -93,6 +95,8 @@ protected: float _volume; float _friction; float _restitution; + float _linearDamping; + float _angularDamping; bool _wasInWorld; MotionType _motionType; From 3b7770f40555413bfa01f28a089de731ee54fbeb Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 5 Jan 2015 11:23:01 -0800 Subject: [PATCH 18/27] change meaning of damping to agree with bullet 0 = no damping 1 = 100% damping The new formula is: velocity *= (1 - damping)^dt --- libraries/entities/src/EntityItem.cpp | 53 +++++++++++++++---------- libraries/entities/src/EntityItem.h | 16 +++++++- libraries/physics/src/PhysicsEngine.cpp | 2 + 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5bdd755759..99c55740f7 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -29,7 +29,7 @@ const float EntityItem::DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const float EntityItem::DEFAULT_MASS = 1.0f; const float EntityItem::DEFAULT_LIFETIME = EntityItem::IMMORTAL; const QString EntityItem::DEFAULT_USER_DATA = QString(""); -const float EntityItem::DEFAULT_DAMPING = 2.0f; +const float EntityItem::DEFAULT_DAMPING = 0.39347f; // approx timescale = 2.0 sec (see damping timescale formula in header) const glm::vec3 EntityItem::NO_VELOCITY = glm::vec3(0, 0, 0); const float EntityItem::EPSILON_VELOCITY_LENGTH = (1.0f / 1000.0f) / (float)TREE_SCALE; // really small: 1mm/second const glm::vec3 EntityItem::DEFAULT_VELOCITY = EntityItem::NO_VELOCITY; @@ -647,7 +647,17 @@ void EntityItem::simulate(const quint64& now) { if (hasAngularVelocity()) { glm::quat rotation = getRotation(); + + // angular damping glm::vec3 angularVelocity = glm::radians(getAngularVelocity()); + if (_angularDamping > 0.0f) { + angularVelocity *= powf(1.0f - _angularDamping, timeElapsed); + if (wantDebug) { + qDebug() << " angularDamping :" << _angularDamping; + qDebug() << " newAngularVelocity:" << angularVelocity; + } + } + float angularSpeed = glm::length(angularVelocity); const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.0017453f; // ~0.1 degree/sec @@ -656,20 +666,8 @@ void EntityItem::simulate(const quint64& now) { } else { float angle = timeElapsed * angularSpeed; glm::quat dQ = glm::angleAxis(angle, glm::normalize(angularVelocity)); - rotation = dQ * rotation; + rotation = glm::normalize(dQ * rotation); setRotation(rotation); - - // handle damping for angular velocity - float dampingTimescale = getAngularDamping(); - if (dampingTimescale > 0.0f) { - float dampingFactor = glm::clamp(timeElapsed / dampingTimescale, 0.0f, 1.0f); - glm::vec3 newAngularVelocity = (1.0f - dampingFactor) * getAngularVelocity(); - setAngularVelocity(newAngularVelocity); - if (wantDebug) { - qDebug() << " dampingTimescale :" << dampingTimescale; - qDebug() << " newAngularVelocity:" << newAngularVelocity; - } - } } } @@ -684,12 +682,10 @@ void EntityItem::simulate(const quint64& now) { // linear damping glm::vec3 velocity = getVelocity(); - float dampingTimescale = getDamping(); - if (dampingTimescale > 0.0f) { - float dampingFactor = glm::clamp(timeElapsed / dampingTimescale, 0.0f, 1.0f); - velocity *= (1.0f - dampingFactor); + if (_damping > 0.0f) { + velocity *= powf(1.0f - _damping, timeElapsed); if (wantDebug) { - qDebug() << " dampingTimescale:" << dampingTimescale; + qDebug() << " damping:" << _damping; qDebug() << " velocity AFTER dampingResistance:" << velocity; qDebug() << " glm::length(velocity):" << glm::length(velocity); qDebug() << " EPSILON_VELOCITY_LENGTH:" << EPSILON_VELOCITY_LENGTH; @@ -822,12 +818,12 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(mass, updateMass); SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocityInMeters); SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravityInMeters); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, setDamping); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, updateDamping); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, updateLifetime); SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript); SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint); SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, updateAngularVelocity); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, setAngularDamping); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, updateAngularDamping); SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel); SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha); SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible); @@ -1023,6 +1019,7 @@ const float MIN_DIMENSION_DELTA = 0.0001f; const float MIN_ALIGNMENT_DOT = 0.9999f; const float MIN_MASS_DELTA = 0.001f; const float MIN_VELOCITY_DELTA = 0.025f; +const float MIN_DAMPING_DELTA = 0.001f; const float MIN_GRAVITY_DELTA = 0.001f; const float MIN_SPIN_DELTA = 0.0003f; @@ -1098,6 +1095,13 @@ void EntityItem::updateVelocityInMeters(const glm::vec3& value) { } } +void EntityItem::updateDamping(float value) { + if (fabsf(_damping - value) > MIN_DAMPING_DELTA) { + _damping = glm::clamp(value, 0.0f, 1.0f); + _dirtyFlags |= EntityItem::DIRTY_VELOCITY; + } +} + void EntityItem::updateGravity(const glm::vec3& value) { if (glm::distance(_gravity, value) * (float)TREE_SCALE > MIN_GRAVITY_DELTA) { _gravity = value; @@ -1120,6 +1124,13 @@ void EntityItem::updateAngularVelocity(const glm::vec3& value) { } } +void EntityItem::updateAngularDamping(float value) { + if (fabsf(_angularDamping - value) > MIN_DAMPING_DELTA) { + _angularDamping = glm::clamp(value, 0.0f, 1.0f); + _dirtyFlags |= EntityItem::DIRTY_VELOCITY; + } +} + void EntityItem::updateIgnoreForCollisions(bool value) { if (_ignoreForCollisions != value) { _ignoreForCollisions = value; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7acb55e8c3..5a1b162e4f 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -285,9 +285,11 @@ public: void updateMass(float value); void updateVelocity(const glm::vec3& value); void updateVelocityInMeters(const glm::vec3& value); + void updateDamping(float value); void updateGravity(const glm::vec3& value); void updateGravityInMeters(const glm::vec3& value); void updateAngularVelocity(const glm::vec3& value); + void updateAngularDamping(float value); void updateIgnoreForCollisions(bool value); void updateCollisionsWillMove(bool value); void updateLifetime(float value); @@ -325,17 +327,27 @@ protected: float _mass; glm::vec3 _velocity; glm::vec3 _gravity; - float _damping; // timescale + float _damping; float _lifetime; QString _script; glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; - float _angularDamping; // timescale + float _angularDamping; bool _visible; bool _ignoreForCollisions; bool _collisionsWillMove; bool _locked; QString _userData; + + // NOTE: Damping is applied like this: v *= pow(1 - damping, dt) + // + // Hence the damping coefficient must range from 0 (no damping) to 1 (immediate stop). + // Each damping value relates to a corresponding exponential decay timescale as follows: + // + // timescale = -1 / ln(1 - damping) + // + // damping = 1 - exp(-1 / timescale) + // // NOTE: Radius support is obsolete, but these private helper functions are available for this class to // parse old data streams diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index a6317b4fcf..f6700455a6 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -327,6 +327,7 @@ bool PhysicsEngine::addObject(ObjectMotionState* motionState) { body->setFlags(BT_DISABLE_WORLD_GRAVITY); body->setRestitution(motionState->_restitution); body->setFriction(motionState->_friction); + body->setDamping(motionState->_linearDamping, motionState->_angularDamping); _dynamicsWorld->addRigidBody(body); return true; } @@ -438,6 +439,7 @@ void PhysicsEngine::updateObjectEasy(btRigidBody* body, ObjectMotionState* motio } body->setRestitution(motionState->_restitution); body->setFriction(motionState->_friction); + body->setDamping(motionState->_linearDamping, motionState->_angularDamping); if (flags & EntityItem::DIRTY_MASS) { float mass = motionState->getMass(); From 21b2d14956fa8efd88551a989584c1e8fb6c1f4a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 5 Jan 2015 11:25:15 -0800 Subject: [PATCH 19/27] converting existing JS scripts to use new damping Old formula the scripts were using: v *= damping So a value of 0.999 was "little damping" and a value of 0.001 was "very strong damping", but now that is reversed. New formula: v *= (1 j- damping)^dt A damping value of 0.001 now means "very little damping" and a value of 0.999 means "very strong damping". --- examples/butterflies.js | 4 ++-- examples/cameraExample.js | 2 +- examples/frisbee.js | 6 +++--- examples/grenadeLauncher.js | 2 +- examples/gun.js | 2 +- examples/toyball.js | 2 +- examples/twoFallingEntities.js | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/butterflies.js b/examples/butterflies.js index edc33f7625..6eaa4ba66d 100644 --- a/examples/butterflies.js +++ b/examples/butterflies.js @@ -79,7 +79,7 @@ function addButterfly() { rotation: Quat.fromPitchYawRollDegrees(-80 + Math.random() * 20, Math.random() * 360.0, 0.0), velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: GRAVITY, z: 0 }, - damping: 0.9999, + damping: 0.00001, dimensions: dimensions, color: color, animationURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/content/butterfly/butterfly.fbx", @@ -138,4 +138,4 @@ Script.scriptEnding.connect(function() { for (var i = 0; i < numButterflies; i++) { Entities.deleteEntity(butterflies[i]); } -}); \ No newline at end of file +}); diff --git a/examples/cameraExample.js b/examples/cameraExample.js index 4c02ce2f2e..85d35623b6 100644 --- a/examples/cameraExample.js +++ b/examples/cameraExample.js @@ -11,7 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var damping = 0.9; +var damping = 0.001; var yaw = 0.0; var pitch = 0.0; var roll = 0.0; diff --git a/examples/frisbee.js b/examples/frisbee.js index cf271f4f04..2d60827858 100644 --- a/examples/frisbee.js +++ b/examples/frisbee.js @@ -208,7 +208,7 @@ function checkControllerSide(hand) { gravity: { x: 0, y: 0, z: 0}, inHand: true, dimensions: { x: FRISBEE_RADIUS, y: FRISBEE_RADIUS / 5, z: FRISBEE_RADIUS }, - damping: 0.999, + damping: 0.00001, modelURL: modelUrl, modelScale: FRISBEE_MODEL_SCALE, modelRotation: hand.holdRotation(), @@ -235,7 +235,7 @@ function checkControllerSide(hand) { gravity: { x: 0, y: 0, z: 0}, inHand: true, dimensions: { x: FRISBEE_RADIUS, y: FRISBEE_RADIUS / 5, z: FRISBEE_RADIUS }, - damping: 0.999, + damping: 0.00001, modelURL: frisbeeURL(), modelScale: FRISBEE_MODEL_SCALE, modelRotation: hand.holdRotation(), @@ -444,4 +444,4 @@ Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Menu.menuItemEvent.connect(menuItemEvent); Script.scriptEnding.connect(scriptEnding); Script.update.connect(checkController); -Script.update.connect(controlFrisbees); \ No newline at end of file +Script.update.connect(controlFrisbees); diff --git a/examples/grenadeLauncher.js b/examples/grenadeLauncher.js index 3907e41ea6..088e3aa43c 100644 --- a/examples/grenadeLauncher.js +++ b/examples/grenadeLauncher.js @@ -145,7 +145,7 @@ function shootTarget() { velocity: velocity, gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, lifetime: 1000.0, - damping: 0.99 }); + damping: 0.0001 }); // Record start time shotTime = new Date(); diff --git a/examples/gun.js b/examples/gun.js index 2386e61539..829ef68759 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -144,7 +144,7 @@ function shootTarget() { velocity: velocity, gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, lifetime: TARGET_LIFETIME, - damping: 0.99 }); + damping: 0.0001 }); // Record start time shotTime = new Date(); diff --git a/examples/toyball.js b/examples/toyball.js index e39ca9c8b4..9b91d1f098 100644 --- a/examples/toyball.js +++ b/examples/toyball.js @@ -137,7 +137,7 @@ function checkControllerSide(whichSide) { gravity: { x: 0, y: 0, z: 0}, inHand: true, radius: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 }, - damping: 0.999, + damping: 0.00001, color: HELD_COLOR, lifetime: 600 // 10 seconds - same as default, not needed but here as an example diff --git a/examples/twoFallingEntities.js b/examples/twoFallingEntities.js index 0d157b70c3..b4a1f18bad 100644 --- a/examples/twoFallingEntities.js +++ b/examples/twoFallingEntities.js @@ -12,7 +12,7 @@ var properties = { velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: -0.05, z: 0}, radius: radius, - damping: 0.999, + damping: 0.00001, color: { red: 200, green: 0, blue: 0 }, lifetime: 60 }; @@ -22,4 +22,4 @@ position.x -= radius * 1.0; properties.position = position; var newEntityTwo = Entities.addEntity(properties); -Script.stop(); // no need to run anymore \ No newline at end of file +Script.stop(); // no need to run anymore From 458ea6759e9b264f1cd66bef681a9568bde63957 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 5 Jan 2015 11:27:29 -0800 Subject: [PATCH 20/27] Adding the shadow.slh file containing the shader functions used for shadowing, itis used by both normal and cascaded shadow deferred lighting passes --- interface/src/Application.cpp | 18 ++-- .../src/RenderableModelEntityItem.cpp | 9 +- libraries/render-utils/src/Shadow.slh | 98 +++++++++++++++++++ libraries/render-utils/src/TextureCache.cpp | 7 +- .../directional_light_cascaded_shadow_map.slf | 29 ++---- 5 files changed, 130 insertions(+), 31 deletions(-) create mode 100755 libraries/render-utils/src/Shadow.slh diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2c510c4980..02ee60a012 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2795,13 +2795,14 @@ void Application::updateShadowMap() { QOpenGLFramebufferObject* fbo = DependencyManager::get()->getShadowFramebufferObject(); fbo->bind(); glEnable(GL_DEPTH_TEST); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(/*GL_COLOR_BUFFER_BIT | */GL_DEPTH_BUFFER_BIT); glm::vec3 lightDirection = -getSunDirection(); glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); glm::quat inverseRotation = glm::inverse(rotation); - const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; + //const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; + const float SHADOW_MATRIX_DISTANCES[] = { 1.0f, 2.5f, 5.0f, 10.0f, 20.0f }; const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f), glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; @@ -2855,8 +2856,8 @@ void Application::updateShadowMap() { glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); // stretch out our extents in z so that we get all of the avatars - minima.z -= _viewFrustum.getFarClip() * 0.5f; - maxima.z += _viewFrustum.getFarClip() * 0.5f; + // minima.z -= _viewFrustum.getFarClip() * 0.5f; + // maxima.z += _viewFrustum.getFarClip() * 0.5f; // save the combined matrix for rendering _shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) * @@ -2897,8 +2898,9 @@ void Application::updateShadowMap() { viewTransform.setRotation(rotation); setViewTransform(viewTransform); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt + glDisable(GL_POLYGON_OFFSET_FILL); + //glEnable(GL_POLYGON_OFFSET_FILL); + //glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt { PerformanceTimer perfTimer("avatarManager"); @@ -2907,7 +2909,7 @@ void Application::updateShadowMap() { { PerformanceTimer perfTimer("entities"); - // _entities.render(RenderArgs::SHADOW_RENDER_MODE); + _entities.render(RenderArgs::SHADOW_RENDER_MODE); } // render JS/scriptable overlays @@ -2921,7 +2923,7 @@ void Application::updateShadowMap() { _overlays.renderWorld(true, RenderArgs::SHADOW_RENDER_MODE); } - glDisable(GL_POLYGON_OFFSET_FILL); + //glDisable(GL_POLYGON_OFFSET_FILL); glPopMatrix(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 92e925d73e..699603cb21 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -166,7 +166,14 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); - _model->renderInScene(alpha, args); + // filter out if not needed to render + if (args && (args->_renderMode == RenderArgs::SHADOW_RENDER_MODE)) { + if (isMoving() || isAnimatingSomething()) { + _model->renderInScene(alpha, args); + } + } else { + _model->renderInScene(alpha, args); + } } else { // if we couldn't get a model, then just draw a cube glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh new file mode 100755 index 0000000000..ff3cc68658 --- /dev/null +++ b/libraries/render-utils/src/Shadow.slh @@ -0,0 +1,98 @@ + +<@if not SHADOW_SLH@> +<@def SHADOW_SLH@> + +// the shadow texture +uniform sampler2DShadow shadowMap; + +// the distances to the cascade sections +uniform vec3 shadowDistances; + +// the inverse of the size of the shadow map +uniform float shadowScale; + +vec2 samples[8] = vec2[8]( + vec2(-2.0, -2.0), + vec2(2.0, -2.0), + vec2(2.0, 2.0), + vec2(-2.0, 2.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(-1.0, 0.0), + vec2(0.0, -1.0) +); + +vec4 evalShadowTexcoord(vec4 position) { + // compute the index of the cascade to use and the corresponding texture coordinates + int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); + vec3 shadowTexcoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), + dot(gl_EyePlaneR[shadowIndex], position)); + + return vec4(shadowTexcoord, shadowIndex); +} + +float evalShadowAttenuationPCF(vec4 shadowTexcoord) { + float radiusScale = (shadowTexcoord.w + 1.0); + float shadowAttenuation = (0.25 * ( + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) + )); + + if ((shadowAttenuation > 0) && (shadowAttenuation < 1.0)) { + radiusScale *= 0.5; + shadowAttenuation = 0.5 * shadowAttenuation + (0.125 * ( + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[4], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[5], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[6], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[7], 0.0)) + )); + } + + return shadowAttenuation; +} + +float evalShadowAttenuationBasic(vec4 shadowTexcoord) { + float radiusScale = 0.5; + float shadowAttenuation = (0.25 * ( + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + + texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) + )); + return shadowAttenuation; +} + +float evalShadowAttenuation(vec4 shadowTexcoord) { + return evalShadowAttenuationBasic(shadowTexcoord); +} + + +vec3 debugShadowMap(float shadowAttenuation, vec4 shadowTexcoord) { + vec3 colorArray[4]; + colorArray[0].xyz = vec3(1.0, 1.0, 1.0); + colorArray[1].xyz = vec3(1.0, 0.0, 0.0); + colorArray[2].xyz = vec3(0.0, 1.0, 0.0); + colorArray[3].xyz = vec3(0.0, 0.0, 1.0); + + vec2 offsetArray[4]; + offsetArray[0] = vec2(0.0, 0.0); + offsetArray[1] = vec2(0.5, 0.0); + offsetArray[2] = vec2(0.0, 0.5); + offsetArray[3] = vec2(0.5, 0.5); + + return shadowAttenuation * colorArray[int(shadowTexcoord.w)]; + // return shadowAttenuation * vec3(2.0*(shadowTexcoord.xy - offsetArray[int(shadowTexcoord.w)]), 0); + } + +<@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 1591f5cb26..086a878b2d 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -299,8 +299,9 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { glGenTextures(1, &_shadowDepthTextureID); glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, - 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, + 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + //0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); @@ -308,6 +309,8 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glBindTexture(GL_TEXTURE_2D, 0); _shadowFramebufferObject->bind(); diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf index b314beb6dc..fde4b4db0e 100644 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf @@ -24,14 +24,7 @@ uniform sampler2D specularMap; // the depth texture uniform sampler2D depthMap; -// the shadow texture -uniform sampler2DShadow shadowMap; - -// the distances to the cascade sections -uniform vec3 shadowDistances; - -// the inverse of the size of the shadow map -uniform float shadowScale; +<@include Shadow.slh@> // the distance to the near clip plane uniform float near; @@ -55,17 +48,9 @@ void main(void) { float z = near / (depthVal * depthScale - 1.0); vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); - // compute the index of the cascade to use and the corresponding texture coordinates - int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); - vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), - dot(gl_EyePlaneR[shadowIndex], position)); - - // evaluate the shadow test but only relevant for light facing fragments - float shadowAttenuation = (0.25 * - (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r)); + // Eval shadow Texcoord and then Attenuation + vec4 shadowTexcoord = evalShadowTexcoord(position); + float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); // get the normal from the map vec3 normalizedNormal = normalize(normalVal.xyz * 2.0 - vec3(1.0)); @@ -75,7 +60,7 @@ void main(void) { // Light mapped or not ? if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) { - normalVal.a = 0.0; + normalVal.a = 1.0; // need to catch normals perpendicular to the projection plane hence the magic number for the threshold // it should be just 0, but we have innacurracy so we need to overshoot @@ -108,4 +93,8 @@ void main(void) { vec4 specularColor = specularVal; gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normalVal.a); } + + if (gl_FragCoord.x > 1024) { + gl_FragColor = vec4(debugShadowMap(shadowAttenuation, shadowTexcoord) * diffuse, normalVal.a); + } } From bf6b8f9ca752068620323cd0922c1f4e464a1ae7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 5 Jan 2015 12:01:09 -0800 Subject: [PATCH 21/27] do not zero small velocities for non-bullet case --- libraries/entities/src/EntityItem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 99c55740f7..05ef9cd101 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -714,10 +714,12 @@ void EntityItem::simulate(const quint64& now) { if (position.y <= getDistanceToBottomOfEntity()) { velocity = velocity * glm::vec3(1,-1,1); - // if we've slowed considerably, then just stop moving +#ifndef USE_BULLET_PHYSICS + // if we've slowed considerably, then just stop moving, but only if no BULLET if (glm::length(velocity) <= EPSILON_VELOCITY_LENGTH) { velocity = NO_VELOCITY; } +#endif // !USE_BULLET_PHYSICS position.y = getDistanceToBottomOfEntity(); } From 6fb4e1f622a85aba5c7f59227bbf5cb74cb53d02 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 5 Jan 2015 12:23:55 -0800 Subject: [PATCH 22/27] oops, need to update angularVelocity after damping --- libraries/entities/src/EntityItem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 05ef9cd101..f18d2ff75a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -662,13 +662,14 @@ void EntityItem::simulate(const quint64& now) { const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.0017453f; // ~0.1 degree/sec if (angularSpeed < EPSILON_ANGULAR_VELOCITY_LENGTH) { - setAngularVelocity(NO_ANGULAR_VELOCITY); + angularVelocity = NO_ANGULAR_VELOCITY; } else { float angle = timeElapsed * angularSpeed; glm::quat dQ = glm::angleAxis(angle, glm::normalize(angularVelocity)); rotation = glm::normalize(dQ * rotation); setRotation(rotation); } + setAngularVelocity(angularVelocity); } #ifdef USE_BULLET_PHYSICS From e3d474db3db84f673a178d55ad82672f3debc39f Mon Sep 17 00:00:00 2001 From: dev Date: Mon, 5 Jan 2015 12:27:16 -0800 Subject: [PATCH 23/27] FIx shaders for mac --- libraries/render-utils/src/Shadow.slh | 41 +++++++++++++------ .../directional_light_cascaded_shadow_map.slf | 5 ++- .../src/directional_light_shadow_map.slf | 19 +++------ 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index ff3cc68658..9f50167ebc 100755 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -14,6 +14,17 @@ // the shadow texture uniform sampler2DShadow shadowMap; +// Fetching it +float fetchShadow(vec3 texcoord) { +<@if GLPROFILE == PC_GL @> + return texture(shadowMap, texcoord); +<@elif GLPROFILE == MAC_GL@> + return shadow2D(shadowMap, texcoord).r; +<@else@> + return shadow2D(shadowMap, texcoord).r; +<@endif@> +} + // the distances to the cascade sections uniform vec3 shadowDistances; @@ -32,6 +43,12 @@ vec2 samples[8] = vec2[8]( ); vec4 evalShadowTexcoord(vec4 position) { + // compute the corresponding texture coordinates + vec3 shadowTexcoord = vec3(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position)); + return vec4(shadowTexcoord, 0.0); +} + +vec4 evalCascadedShadowTexcoord(vec4 position) { // compute the index of the cascade to use and the corresponding texture coordinates int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); vec3 shadowTexcoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), @@ -43,19 +60,19 @@ vec4 evalShadowTexcoord(vec4 position) { float evalShadowAttenuationPCF(vec4 shadowTexcoord) { float radiusScale = (shadowTexcoord.w + 1.0); float shadowAttenuation = (0.25 * ( - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) )); if ((shadowAttenuation > 0) && (shadowAttenuation < 1.0)) { radiusScale *= 0.5; shadowAttenuation = 0.5 * shadowAttenuation + (0.125 * ( - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[4], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[5], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[6], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[7], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[4], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[5], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[6], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[7], 0.0)) )); } @@ -65,10 +82,10 @@ float evalShadowAttenuationPCF(vec4 shadowTexcoord) { float evalShadowAttenuationBasic(vec4 shadowTexcoord) { float radiusScale = 0.5; float shadowAttenuation = (0.25 * ( - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + - texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) )); return shadowAttenuation; } diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf index fde4b4db0e..7db53f052b 100644 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf @@ -24,6 +24,7 @@ uniform sampler2D specularMap; // the depth texture uniform sampler2D depthMap; +// Everything about shadow <@include Shadow.slh@> // the distance to the near clip plane @@ -49,7 +50,7 @@ void main(void) { vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalShadowTexcoord(position); + vec4 shadowTexcoord = evalCascadedShadowTexcoord(position); float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); // get the normal from the map @@ -94,7 +95,9 @@ void main(void) { gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normalVal.a); } +/* //DEBUG: if (gl_FragCoord.x > 1024) { gl_FragColor = vec4(debugShadowMap(shadowAttenuation, shadowTexcoord) * diffuse, normalVal.a); } +*/ } diff --git a/libraries/render-utils/src/directional_light_shadow_map.slf b/libraries/render-utils/src/directional_light_shadow_map.slf index 056e866699..7a34f56f93 100644 --- a/libraries/render-utils/src/directional_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_shadow_map.slf @@ -24,11 +24,8 @@ uniform sampler2D specularMap; // the depth texture uniform sampler2D depthMap; -// the shadow texture -uniform sampler2DShadow shadowMap; - -// the inverse of the size of the shadow map -uniform float shadowScale; +// Everything about shadow +<@include Shadow.slh@> // the distance to the near clip plane uniform float near; @@ -52,15 +49,9 @@ void main(void) { float z = near / (depthVal * depthScale - 1.0); vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); - // compute the corresponding texture coordinates - vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position)); - - // evaluate the shadow test but only relevant for light facing fragments - float shadowAttenuation = (0.25 * - (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r)); + // Eval shadow Texcoord and then Attenuation + vec4 shadowTexcoord = evalShadowTexcoord(position); + float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); // get the normal from the map vec3 normalizedNormal = normalize(normalVal.xyz * 2.0 - vec3(1.0)); From 0b8b4c6d08499699a7521941459a32f5861cfc7e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 5 Jan 2015 13:01:21 -0800 Subject: [PATCH 24/27] for simple shadow map, cover 2 regions of the view frustum and not just one for similar quality --- interface/src/Application.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 02ee60a012..1bfbd37a74 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2801,8 +2801,7 @@ void Application::updateShadowMap() { glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); glm::quat inverseRotation = glm::inverse(rotation); - //const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; - const float SHADOW_MATRIX_DISTANCES[] = { 1.0f, 2.5f, 5.0f, 10.0f, 20.0f }; + const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f), glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; @@ -2821,8 +2820,10 @@ void Application::updateShadowMap() { const glm::vec2& coord = MAP_COORDS[i]; glViewport(coord.s * fbo->width(), coord.t * fbo->height(), targetSize, targetSize); + // if simple shadow then since the resolution is twice as much as with cascaded, cover 2 regions with the map, not just one + int regionIncrement = (matrixCount == 1 ? 2 : 1); float nearScale = SHADOW_MATRIX_DISTANCES[i] * frustumScale; - float farScale = SHADOW_MATRIX_DISTANCES[i + 1] * frustumScale; + float farScale = SHADOW_MATRIX_DISTANCES[i + regionIncrement] * frustumScale; glm::vec3 points[] = { glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale), glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale), @@ -2856,8 +2857,8 @@ void Application::updateShadowMap() { glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); // stretch out our extents in z so that we get all of the avatars - // minima.z -= _viewFrustum.getFarClip() * 0.5f; - // maxima.z += _viewFrustum.getFarClip() * 0.5f; + minima.z -= _viewFrustum.getFarClip() * 0.5f; + maxima.z += _viewFrustum.getFarClip() * 0.5f; // save the combined matrix for rendering _shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) * From 7529b3d1b040aa54e267610911a686b44d0082e5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 5 Jan 2015 13:10:32 -0800 Subject: [PATCH 25/27] clean code --- interface/src/Application.cpp | 2 +- libraries/render-utils/src/Shadow.slh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1bfbd37a74..6db12e6937 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2795,7 +2795,7 @@ void Application::updateShadowMap() { QOpenGLFramebufferObject* fbo = DependencyManager::get()->getShadowFramebufferObject(); fbo->bind(); glEnable(GL_DEPTH_TEST); - glClear(/*GL_COLOR_BUFFER_BIT | */GL_DEPTH_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); glm::vec3 lightDirection = -getSunDirection(); glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index 9f50167ebc..a8d0ce457a 100755 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -112,4 +112,4 @@ vec3 debugShadowMap(float shadowAttenuation, vec4 shadowTexcoord) { // return shadowAttenuation * vec3(2.0*(shadowTexcoord.xy - offsetArray[int(shadowTexcoord.w)]), 0); } -<@endif@> \ No newline at end of file +<@endif@> From 3e4cbfd2dc22157321903e5bbf5e919f23881739 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 5 Jan 2015 13:12:28 -0800 Subject: [PATCH 26/27] clean code --- interface/src/Application.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6db12e6937..39e061b67a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2899,9 +2899,8 @@ void Application::updateShadowMap() { viewTransform.setRotation(rotation); setViewTransform(viewTransform); - glDisable(GL_POLYGON_OFFSET_FILL); - //glEnable(GL_POLYGON_OFFSET_FILL); - //glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt { PerformanceTimer perfTimer("avatarManager"); @@ -2924,7 +2923,7 @@ void Application::updateShadowMap() { _overlays.renderWorld(true, RenderArgs::SHADOW_RENDER_MODE); } - //glDisable(GL_POLYGON_OFFSET_FILL); + glDisable(GL_POLYGON_OFFSET_FILL); glPopMatrix(); From 901ea16ba09deefd30fc99ce8e56c225d4a864d8 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 5 Jan 2015 13:17:12 -0800 Subject: [PATCH 27/27] clean code --- libraries/render-utils/src/TextureCache.cpp | 2 -- .../src/directional_light_cascaded_shadow_map.slf | 6 ------ 2 files changed, 8 deletions(-) diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 086a878b2d..df860338ab 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -301,14 +301,12 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); - //0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf index 7db53f052b..e2a58de14b 100644 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf @@ -94,10 +94,4 @@ void main(void) { vec4 specularColor = specularVal; gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normalVal.a); } - -/* //DEBUG: - if (gl_FragCoord.x > 1024) { - gl_FragColor = vec4(debugShadowMap(shadowAttenuation, shadowTexcoord) * diffuse, normalVal.a); - } -*/ }