diff --git a/README.md b/README.md index a42bbd1626..5678312f6f 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,18 @@ send your resume to hiring@highfidelity.io Building Interface & other High Fidelity Components ========= -Interface is our OS X and Linux build-able client for accessing our virtual +Interface is our Windows, OS X, and Linux build-able client for accessing our virtual world. +For detailed notes on building for Windows, please refer to the following wiki page: +https://github.com/highfidelity/hifi/wiki/Building-on-Windows + +For detailed notes on building for Ubuntu, please refer to the following wiki page: +https://github.com/highfidelity/hifi/wiki/Building-on-Ubuntu-13.04 + +Building on Mac OS X and Linux: +-------------------------------- + CMake ----- Hifi uses CMake to generate build files and project files @@ -45,9 +54,9 @@ If Cmake throws you an error related to Qt5 it likely cannot find your Qt5 cmake You can solve this by setting an environment variable, QT_CMAKE_PREFIX_PATH, to the location of the folder distributed with Qt5 that contains them. -For example, a Qt5 5.1.1 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment). +For example, a Qt5 5.2.0 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment). - export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.1.1/clang_64/lib/cmake/ + export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.2.0/clang_64/lib/cmake/ The path it needs to be set to will depend on where and how Qt5 was installed. @@ -64,7 +73,7 @@ components located in the build/target_name/Debug directories. Other dependencies & information ---- -In addition to CMake, Qt 5.1 is required to build all components. +In addition to CMake, Qt 5.2 is required to build all components. What can I build on? We have successfully built on OS X 10.8, Ubuntu and a few other modern Linux diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 51a91621da..60b9d75338 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -30,9 +30,6 @@ link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(metavoxels ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(particle-server ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(voxel-server ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(script-engine ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR}) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 2694bf83e2..93ec4bf991 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -23,8 +23,12 @@ #include "Agent.h" Agent::Agent(const QByteArray& packet) : - ThreadedAssignment(packet) + ThreadedAssignment(packet), + _voxelEditSender(), + _particleEditSender() { + _scriptEngine.getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender); + _scriptEngine.getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); } void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 8b2038a8b0..7495fc06bf 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -15,9 +15,12 @@ #include #include +#include #include #include #include +#include + class Agent : public ThreadedAssignment { Q_OBJECT @@ -39,6 +42,8 @@ signals: private: ScriptEngine _scriptEngine; ParticleTree _particleTree; + VoxelEditPacketSender _voxelEditSender; + ParticleEditPacketSender _particleEditSender; }; #endif /* defined(__hifi__Agent__) */ diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 5bf0417f22..cde5666ab9 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -8,15 +8,13 @@ #include -#include - -#include - #include "Agent.h" #include "AssignmentFactory.h" #include "audio/AudioMixer.h" #include "avatars/AvatarMixer.h" #include "metavoxels/MetavoxelServer.h" +#include "particles/ParticleServer.h" +#include "voxels/VoxelServer.h" ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet) { QDataStream packetStream(packet); diff --git a/libraries/octree-server/src/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp similarity index 100% rename from libraries/octree-server/src/OctreeInboundPacketProcessor.cpp rename to assignment-client/src/octree/OctreeInboundPacketProcessor.cpp diff --git a/libraries/octree-server/src/OctreeInboundPacketProcessor.h b/assignment-client/src/octree/OctreeInboundPacketProcessor.h similarity index 100% rename from libraries/octree-server/src/OctreeInboundPacketProcessor.h rename to assignment-client/src/octree/OctreeInboundPacketProcessor.h diff --git a/libraries/octree-server/src/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp similarity index 95% rename from libraries/octree-server/src/OctreeQueryNode.cpp rename to assignment-client/src/octree/OctreeQueryNode.cpp index f9363d9d80..58aea5c792 100644 --- a/libraries/octree-server/src/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -46,9 +46,12 @@ void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, con bool OctreeQueryNode::packetIsDuplicate() const { // since our packets now include header information, like sequence number, and createTime, we can't just do a memcmp // of the entire packet, we need to compare only the packet content... + int numBytesPacketHeader = numBytesForPacketHeaderGivenPacketType(getMyPacketType()); + if (_lastOctreePacketLength == getPacketLength()) { - if (memcmp(_lastOctreePacket + OCTREE_PACKET_HEADER_SIZE, - _octreePacket + OCTREE_PACKET_HEADER_SIZE , getPacketLength() - OCTREE_PACKET_HEADER_SIZE) == 0) { + if (memcmp(_lastOctreePacket + (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE), + _octreePacket + (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE), + getPacketLength() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE)) == 0) { return true; } } @@ -125,7 +128,7 @@ void OctreeQueryNode::resetOctreePacket(bool lastWasSurpressed) { *sequenceAt = _sequenceNumber; _octreePacketAt += sizeof(OCTREE_PACKET_SEQUENCE); _octreePacketAvailableBytes -= sizeof(OCTREE_PACKET_SEQUENCE); - if (!(lastWasSurpressed || _lastOctreePacketLength == OCTREE_PACKET_HEADER_SIZE)) { + if (!(lastWasSurpressed || _lastOctreePacketLength == (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE))) { _sequenceNumber++; } diff --git a/libraries/octree-server/src/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h similarity index 100% rename from libraries/octree-server/src/OctreeQueryNode.h rename to assignment-client/src/octree/OctreeQueryNode.h diff --git a/libraries/octree-server/src/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp similarity index 98% rename from libraries/octree-server/src/OctreeSendThread.cpp rename to assignment-client/src/octree/OctreeSendThread.cpp index 26df0ffb0b..a016553e5f 100644 --- a/libraries/octree-server/src/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -92,6 +92,13 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in bool packetSent = false; // did we send a packet? int packetsSent = 0; + + // double check that the node has an active socket, otherwise, don't send... + const HifiSockAddr* nodeAddress = node->getActiveSocket(); + if (!nodeAddress) { + return packetsSent; // without sending... + } + // Here's where we check to see if this packet is a duplicate of the last packet. If it is, we will silently // obscure the packet and not send it. This allows the callers and upper level logic to not need to know about // this rate control savings. @@ -136,14 +143,14 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in // actually send it NodeList::getInstance()->getNodeSocket().writeDatagram((char*) statsMessage, statsMessageLength, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeAddress->getAddress(), + nodeAddress->getPort()); packetSent = true; } else { // not enough room in the packet, send two packets NodeList::getInstance()->getNodeSocket().writeDatagram((char*) statsMessage, statsMessageLength, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeAddress->getAddress(), + nodeAddress->getPort()); // since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since // there was nothing else to send. @@ -162,8 +169,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in packetsSent++; NodeList::getInstance()->getNodeSocket().writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeAddress->getAddress(), + nodeAddress->getPort()); packetSent = true; @@ -183,8 +190,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in if (nodeData->isPacketWaiting()) { // just send the voxel packet NodeList::getInstance()->getNodeSocket().writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeAddress->getAddress(), + nodeAddress->getPort()); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); diff --git a/libraries/octree-server/src/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h similarity index 100% rename from libraries/octree-server/src/OctreeSendThread.h rename to assignment-client/src/octree/OctreeSendThread.h diff --git a/libraries/octree-server/src/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp similarity index 100% rename from libraries/octree-server/src/OctreeServer.cpp rename to assignment-client/src/octree/OctreeServer.cpp diff --git a/libraries/octree-server/src/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h similarity index 100% rename from libraries/octree-server/src/OctreeServer.h rename to assignment-client/src/octree/OctreeServer.h diff --git a/libraries/octree-server/src/OctreeServerConsts.h b/assignment-client/src/octree/OctreeServerConsts.h similarity index 100% rename from libraries/octree-server/src/OctreeServerConsts.h rename to assignment-client/src/octree/OctreeServerConsts.h diff --git a/libraries/particle-server/src/ParticleNodeData.h b/assignment-client/src/particles/ParticleNodeData.h similarity index 95% rename from libraries/particle-server/src/ParticleNodeData.h rename to assignment-client/src/particles/ParticleNodeData.h index 4ab16cb33a..450767613e 100644 --- a/libraries/particle-server/src/ParticleNodeData.h +++ b/assignment-client/src/particles/ParticleNodeData.h @@ -10,9 +10,10 @@ #ifndef __hifi__ParticleNodeData__ #define __hifi__ParticleNodeData__ -#include #include +#include "../octree/OctreeQueryNode.h" + class ParticleNodeData : public OctreeQueryNode { public: ParticleNodeData() : diff --git a/libraries/particle-server/src/ParticleServer.cpp b/assignment-client/src/particles/ParticleServer.cpp similarity index 100% rename from libraries/particle-server/src/ParticleServer.cpp rename to assignment-client/src/particles/ParticleServer.cpp diff --git a/libraries/particle-server/src/ParticleServer.h b/assignment-client/src/particles/ParticleServer.h similarity index 97% rename from libraries/particle-server/src/ParticleServer.h rename to assignment-client/src/particles/ParticleServer.h index 1c1e3b5be9..345ebe86e3 100644 --- a/libraries/particle-server/src/ParticleServer.h +++ b/assignment-client/src/particles/ParticleServer.h @@ -10,7 +10,7 @@ #ifndef __particle_server__ParticleServer__ #define __particle_server__ParticleServer__ -#include +#include "../octree/OctreeServer.h" #include "Particle.h" #include "ParticleServerConsts.h" diff --git a/libraries/particle-server/src/ParticleServerConsts.h b/assignment-client/src/particles/ParticleServerConsts.h similarity index 100% rename from libraries/particle-server/src/ParticleServerConsts.h rename to assignment-client/src/particles/ParticleServerConsts.h diff --git a/libraries/voxel-server/src/VoxelNodeData.h b/assignment-client/src/voxels/VoxelNodeData.h similarity index 79% rename from libraries/voxel-server/src/VoxelNodeData.h rename to assignment-client/src/voxels/VoxelNodeData.h index 54ef9da5b6..c24bfad6ce 100644 --- a/libraries/voxel-server/src/VoxelNodeData.h +++ b/assignment-client/src/voxels/VoxelNodeData.h @@ -3,15 +3,16 @@ // hifi // // Created by Stephen Birarda on 3/21/13. -// +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. // #ifndef __hifi__VoxelNodeData__ #define __hifi__VoxelNodeData__ -#include #include +#include "../octree/OctreeQueryNode.h" + class VoxelNodeData : public OctreeQueryNode { public: VoxelNodeData() : OctreeQueryNode() { }; diff --git a/libraries/voxel-server/src/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp similarity index 100% rename from libraries/voxel-server/src/VoxelServer.cpp rename to assignment-client/src/voxels/VoxelServer.cpp diff --git a/libraries/voxel-server/src/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h similarity index 98% rename from libraries/voxel-server/src/VoxelServer.h rename to assignment-client/src/voxels/VoxelServer.h index 183224b2a7..526a3b2c54 100644 --- a/libraries/voxel-server/src/VoxelServer.h +++ b/assignment-client/src/voxels/VoxelServer.h @@ -17,8 +17,7 @@ #include #include -#include - +#include "../octree/OctreeServer.h" #include "VoxelServerConsts.h" diff --git a/libraries/voxel-server/src/VoxelServerConsts.h b/assignment-client/src/voxels/VoxelServerConsts.h similarity index 100% rename from libraries/voxel-server/src/VoxelServerConsts.h rename to assignment-client/src/voxels/VoxelServerConsts.h diff --git a/domain-server/resources/web/assignment/placeholder.js b/domain-server/resources/web/assignment/placeholder.js index ee8f89cdd6..7c84767f31 100644 --- a/domain-server/resources/web/assignment/placeholder.js +++ b/domain-server/resources/web/assignment/placeholder.js @@ -8,11 +8,9 @@ var NUMBER_OF_CELLS = NUMBER_OF_CELLS_EACH_DIMENSION * NUMBER_OF_CELLS_EACH_DIME var currentCells = []; var nextCells = []; -var METER_LENGTH = 1 / TREE_SCALE; +var METER_LENGTH = 1; var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION; -print("TREE_SCALE = " + TREE_SCALE + "\n"); - // randomly populate the cell start values for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { // create the array to hold this row @@ -108,7 +106,7 @@ function sendNextCells() { // queue a packet to add a voxel for the new cell var color = (nextCells[i][j] == 1) ? 255 : 1; - Voxels.queueDestructiveVoxelAdd(x, y, 0, cellScale, color, color, color); + Voxels.setVoxel(x, y, 0, cellScale, color, color, color); } } } @@ -128,4 +126,6 @@ function step() { sendNextCells(); } -Agent.willSendVisualDataCallback.connect(step); \ No newline at end of file + +Script.willSendVisualDataCallback.connect(step); +Voxels.setPacketsPerSecond(200); \ No newline at end of file diff --git a/examples/particleModelExample.js b/examples/particleModelExample.js index e95cc0c2bf..2f36445d1a 100644 --- a/examples/particleModelExample.js +++ b/examples/particleModelExample.js @@ -11,7 +11,7 @@ var count = 0; var stopAfter = 100; -var modelProperties = { +var modelPropertiesA = { position: { x: 1, y: 1, z: 1 }, velocity: { x: 0.5, y: 0, z: 0.5 }, gravity: { x: 0, y: 0, z: 0 }, @@ -21,6 +21,18 @@ var modelProperties = { lifetime: 20 }; +var modelPropertiesB = { + position: { x: 1, y: 1.5, z: 1 }, + velocity: { x: 0.5, y: 0, z: 0.5 }, + gravity: { x: 0, y: 0, z: 0 }, + damping: 0, + radius : 0.25, + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + lifetime: 20 +}; + var ballProperties = { position: { x: 1, y: 0.5, z: 1 }, velocity: { x: 0.5, y: 0, z: 0.5 }, @@ -31,7 +43,8 @@ var ballProperties = { lifetime: 20 }; -var modelParticleID = Particles.addParticle(modelProperties); +var modelAParticleID = Particles.addParticle(modelPropertiesA); +var modelBParticleID = Particles.addParticle(modelPropertiesB); var ballParticleID = Particles.addParticle(ballProperties); function endAfterAWhile() { diff --git a/examples/spaceInvadersExample.js b/examples/spaceInvadersExample.js index 3a13a1c52f..c817afcdd4 100644 --- a/examples/spaceInvadersExample.js +++ b/examples/spaceInvadersExample.js @@ -10,17 +10,50 @@ var iteration = 0; -var invaderStepsPerCycle = 30; // the number of update steps it takes then invaders to move one column to the right +var gameOver = false; + +// horizontal movement of invaders +var invaderStepsPerCycle = 120; // the number of update steps it takes then invaders to move one column to the right var invaderStepOfCycle = 0; // current iteration in the cycle var invaderMoveDirection = 1; // 1 for moving to right, -1 for moving to left -var itemLifetimes = 60; -var gameAt = { x: 10, y: 0, z: 10 }; +// game length... +var itemLifetimes = 60; // 1 minute + + +// position the game to be basically near the avatar running the game... var gameSize = { x: 10, y: 20, z: 1 }; +var positionFromAvatarZ = 10; + +var avatarX = MyAvatar.position.x; +var avatarY = MyAvatar.position.y; +var avatarZ = MyAvatar.position.z; +var gameAtX = avatarX; +var gameAtY = avatarY; +var gameAtZ = avatarZ; + +// move the game to be "centered" on our X +if (gameAtX > (gameSize.x/2)) { + gameAtX -= (gameSize.x/2); +} + +// move the game to be "offset slightly" on our Y +if (gameAtY > (gameSize.y/4)) { + gameAtY -= (gameSize.y/4); +} + + +// move the game to be positioned away on our Z +if (gameAtZ > positionFromAvatarZ) { + gameAtZ -= positionFromAvatarZ; +} + +var gameAt = { x: gameAtX, y: gameAtY, z: gameAtZ }; var middleX = gameAt.x + (gameSize.x/2); var middleY = gameAt.y + (gameSize.y/2); -var shipSize = 0.2; +var invaderSize = 0.4; +var shipSize = 0.25; var missileSize = 0.1; var myShip; var myShipProperties; @@ -34,34 +67,97 @@ var invadersBottomCorner = { x: gameAt.x, y: middleY , z: gameAt.z }; var rowHeight = ((gameAt.y + gameSize.y) - invadersBottomCorner.y) / numberOfRows; var columnWidth = gameSize.x / (invadersPerRow + emptyColumns); +// vertical movement of invaders +var invaderRowOffset = 0; +var stepsPerRow = 20; // number of steps before invaders really move a whole row down. +var yPerStep = rowHeight/stepsPerRow; +var stepsToGround = (middleY - gameAt.y) / yPerStep; +var maxInvaderRowOffset=stepsToGround; + +// missile related items var missileFired = false; var myMissile; +// sounds +var hitSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/hit.raw"); +var shootSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/shoot.raw"); +var moveSounds = new Array(); +moveSounds[0] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/Lo1.raw"); +moveSounds[1] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/Lo2.raw"); +moveSounds[2] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/Lo3.raw"); +moveSounds[3] = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/Lo4.raw"); +var currentMoveSound = 0; +var numberOfSounds = 4; +var stepsPerSound = invaderStepsPerCycle / numberOfSounds; + +// if you set this to false, sounds will come from the location of particles instead of the player's head +var soundInMyHead = true; + +// models... +var invaderModels = new Array(); +invaderModels[0] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-large-purple.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; +invaderModels[1] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-large-cyan.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; +invaderModels[2] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-medium-cyan.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; +invaderModels[3] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-medium-green.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; +invaderModels[4] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-small-green.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; + + + +//modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX", +//modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/invader.svo", +// "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/spaceInvader3.fbx" + function initializeMyShip() { myShipProperties = { - position: { x: middleX , y: gameAt.y, z: gameAt.z }, - velocity: { x: 0, y: 0, z: 0 }, - gravity: { x: 0, y: 0, z: 0 }, - damping: 0, - radius: shipSize, - color: { red: 0, green: 255, blue: 0 }, - lifetime: itemLifetimes - }; + position: { x: middleX , y: gameAt.y, z: gameAt.z }, + velocity: { x: 0, y: 0, z: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + damping: 0, + radius: shipSize, + color: { red: 0, green: 255, blue: 0 }, + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/myCannon16x16.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + lifetime: itemLifetimes + }; myShip = Particles.addParticle(myShipProperties); } // calculate the correct invaderPosition for an column row function getInvaderPosition(row, column) { - var xMovePart = 0; var xBasePart = invadersBottomCorner.x + (column * columnWidth); + var xMovePart = 0; if (invaderMoveDirection > 0) { xMovePart = (invaderMoveDirection * columnWidth * (invaderStepOfCycle/invaderStepsPerCycle)); } else { xMovePart = columnWidth + (invaderMoveDirection * columnWidth * (invaderStepOfCycle/invaderStepsPerCycle)); } + + var y = invadersBottomCorner.y + (row * rowHeight) - (invaderRowOffset * rowHeight/stepsPerRow); + var invaderPosition = { x: xBasePart + xMovePart, - y: invadersBottomCorner.y + (row * rowHeight), + y: y, z: invadersBottomCorner.z }; return invaderPosition; @@ -77,8 +173,11 @@ function initializeInvaders() { velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius: shipSize, + radius: invaderSize, color: { red: 255, green: 0, blue: 0 }, + modelURL: invaderModels[row].modelURL, + modelScale: invaderModels[row].modelScale, + modelTranslation: invaderModels[row].modelTranslation, lifetime: itemLifetimes }); @@ -88,31 +187,73 @@ function initializeInvaders() { } function moveInvaders() { - print("moveInvaders()..."); for (var row = 0; row < numberOfRows; row++) { for (var column = 0; column < invadersPerRow; column++) { props = Particles.getParticleProperties(invaders[row][column]); if (props.isKnownID) { invaderPosition = getInvaderPosition(row, column); - Particles.editParticle(invaders[row][column], { position: invaderPosition }); + Particles.editParticle(invaders[row][column], + { + position: invaderPosition, + velocity: { x: 0, y: 0, z: 0 } // always reset this, incase they got collided with + }); } } } } +function displayGameOver() { + gameOver = true; + print("Game over..."); +} + function update() { - print("updating space invaders... iteration="+iteration); - iteration++; - invaderStepOfCycle++; - if (invaderStepOfCycle > invaderStepsPerCycle) { - invaderStepOfCycle = 0; - if (invaderMoveDirection > 0) { - invaderMoveDirection = -1; - } else { - invaderMoveDirection = 1; + if (!gameOver) { + //print("updating space invaders... iteration="+iteration); + iteration++; + + if (invaderStepOfCycle % stepsPerSound == 0) { + // play the move sound + var options = new AudioInjectionOptions();
 + if (soundInMyHead) { + options.position = { x: MyAvatar.position.x + 0.0, + y: MyAvatar.position.y + 0.1, + z: MyAvatar.position.z + 0.0 }; + } else { + options.position = getInvaderPosition(invadersPerRow / 2, numberOfRows / 2); + } + options.volume = 1.0; + Audio.playSound(moveSounds[currentMoveSound], options); + + // get ready for next move sound + currentMoveSound = (currentMoveSound+1) % numberOfSounds; } + + invaderStepOfCycle++; + + + if (invaderStepOfCycle > invaderStepsPerCycle) { + // handle left/right movement + invaderStepOfCycle = 0; + if (invaderMoveDirection > 0) { + invaderMoveDirection = -1; + } else { + invaderMoveDirection = 1; + } + + // handle downward movement + invaderRowOffset++; // move down one row + //print("invaderRowOffset="+invaderRowOffset); + + // check to see if invaders have reached "ground"... + if (invaderRowOffset > maxInvaderRowOffset) { + displayGameOver(); + return; + } + + } + moveInvaders(); } - moveInvaders(); } // register the call back so it fires before each data send @@ -134,6 +275,9 @@ function cleanupGame() { if (missileFired) { Particles.deleteParticle(myMissile); } + + Controller.releaseKeyEvents({text: " "}); + Script.stop(); } Script.scriptEnding.connect(cleanupGame); @@ -182,6 +326,17 @@ function fireMissile() { lifetime: 5 }); + var options = new AudioInjectionOptions();
 + if (soundInMyHead) { + options.position = { x: MyAvatar.position.x + 0.0, + y: MyAvatar.position.y + 0.1, + z: MyAvatar.position.z + 0.0 }; + } else { + options.position = missilePosition; + } + options.volume = 1.0; + Audio.playSound(shootSound, options); + missileFired = true; } } @@ -219,6 +374,18 @@ function deleteIfInvader(possibleInvaderParticle) { if (invaders[row][column].id == possibleInvaderParticle.id) { Particles.deleteParticle(possibleInvaderParticle); Particles.deleteParticle(myMissile); + + // play the hit sound + var options = new AudioInjectionOptions();
 + if (soundInMyHead) { + options.position = { x: MyAvatar.position.x + 0.0, + y: MyAvatar.position.y + 0.1, + z: MyAvatar.position.z + 0.0 }; + } else { + options.position = getInvaderPosition(row, column); + } + options.volume = 1.0; + Audio.playSound(hitSound, options); } } } @@ -243,4 +410,6 @@ Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle); initializeMyShip(); initializeInvaders(); +// shut down the game after 1 minute +var gameTimer = Script.setTimeout(endGame, itemLifetimes * 1000); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ca87c812d3..84ece357a7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -101,10 +101,12 @@ const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::D const int STATS_PELS_PER_LINE = 20; -void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) { - QString messageWithNewLine = message + "\n"; - fprintf(stdout, "%s", messageWithNewLine.toLocal8Bit().constData()); - Application::getInstance()->getLogger()->addMessage(messageWithNewLine.toLocal8Bit().constData()); +void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { + if (message.size() > 0) { + QString messageWithNewLine = message + "\n"; + fprintf(stdout, "%s", messageWithNewLine.toLocal8Bit().constData()); + Application::getInstance()->getLogger()->addMessage(messageWithNewLine.toLocal8Bit().constData()); + } } Application::Application(int& argc, char** argv, timeval &startup_time) : @@ -152,8 +154,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _resetRecentMaxPacketsSoon(true), _swatch(NULL), _pasteMode(false), - _logger(new FileLogger(this)), - _persistThread(NULL) + _logger(new FileLogger(this)) { _myAvatar = _avatarManager.getMyAvatar(); @@ -314,12 +315,7 @@ Application::~Application() { _voxelHideShowThread.terminate(); _voxelEditSender.terminate(); _particleEditSender.terminate(); - if (_persistThread) { - _persistThread->terminate(); - _persistThread->deleteLater(); - _persistThread = NULL; - } - + storeSizeAndPosition(); saveScripts(); _sharedVoxelSystem.changeTree(new VoxelTree); @@ -1260,7 +1256,8 @@ void Application::mousePressEvent(QMouseEvent* event) { pasteVoxels(); } - if (MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) && + MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) { _hoverVoxelOriginalColor[0] = _hoverVoxel.red; _hoverVoxelOriginalColor[1] = _hoverVoxel.green; _hoverVoxelOriginalColor[2] = _hoverVoxel.blue; @@ -1905,9 +1902,6 @@ void Application::init() { connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); - - - updateLocalOctreeCache(true); } void Application::closeMirrorView() { @@ -2060,7 +2054,7 @@ void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& f glm::vec4 oldVoxel(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s); // only do this work if MAKE_SOUND_ON_VOXEL_HOVER or MAKE_SOUND_ON_VOXEL_CLICK is enabled, // and make sure the tree is not already busy... because otherwise you'll have to wait. - if (!(_voxels.treeIsBusy() || _mousePressed)) { + if (!_mousePressed) { { PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()"); _isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face); @@ -2205,9 +2199,6 @@ void Application::updateThreads(float deltaTime) { _voxelHideShowThread.threadRoutine(); _voxelEditSender.threadRoutine(); _particleEditSender.threadRoutine(); - if (_persistThread) { - _persistThread->threadRoutine(); - } } } @@ -2882,7 +2873,8 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { } } - _avatarManager.renderAvatars(whichCamera.getMode() == CAMERA_MODE_MIRROR, selfAvatarOnly); + bool renderMyHead = (whichCamera.getInterpolatedMode() != CAMERA_MODE_FIRST_PERSON); + _avatarManager.renderAvatars(renderMyHead, selfAvatarOnly); if (!selfAvatarOnly) { // Render the world box @@ -3880,10 +3872,6 @@ void Application::domainChanged(const QString& domainHostname) { // reset the particle renderer _particles.clear(); - - // reset our persist thread - qDebug() << "Domain changed to" << domainHostname << ". Swapping persist cache."; - updateLocalOctreeCache(); } void Application::nodeKilled(SharedNodePointer node) { @@ -4153,49 +4141,6 @@ void Application::initAvatarAndViewFrustum() { updateMyAvatar(0.f); } -QString Application::getLocalVoxelCacheFileName() { - QString fileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - QDir logDir(fileName); - if (!logDir.exists(fileName)) { - logDir.mkdir(fileName); - } - - fileName.append(QString("/hifi.voxelscache.")); - fileName.append(_profile.getLastDomain()); - fileName.append(QString(".svo")); - - return fileName; -} - - -void Application::updateLocalOctreeCache(bool firstTime) { - // only do this if we've already got a persistThread or we're told this is the first time - if (firstTime || _persistThread) { - - if (_persistThread) { - _persistThread->terminate(); - _persistThread->deleteLater(); - _persistThread = NULL; - } - - QString localVoxelCacheFileName = getLocalVoxelCacheFileName(); - const int LOCAL_CACHE_PERSIST_INTERVAL = 1000 * 10; // every 10 seconds - - if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableLocalVoxelCache)) { - _persistThread = new OctreePersistThread(_voxels.getTree(), - localVoxelCacheFileName.toLocal8Bit().constData(),LOCAL_CACHE_PERSIST_INTERVAL); - - qDebug() << "updateLocalOctreeCache()... localVoxelCacheFileName=" << localVoxelCacheFileName; - } - - if (_persistThread) { - _voxels.beginLoadingLocalVoxelCache(); // while local voxels are importing, don't do individual node VBO updates - connect(_persistThread, SIGNAL(loadCompleted()), &_voxels, SLOT(localVoxelCacheLoaded())); - _persistThread->initialize(true); - } - } -} - void Application::checkVersion() { QNetworkRequest latestVersionRequest((QUrl(CHECK_VERSION_URL))); latestVersionRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); diff --git a/interface/src/Application.h b/interface/src/Application.h index bf9981a160..e82eaf1d6c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -484,11 +484,6 @@ private: FileLogger* _logger; - OctreePersistThread* _persistThread; - - QString getLocalVoxelCacheFileName(); - void updateLocalOctreeCache(bool firstTime = false); - void checkVersion(); void displayUpdateDialog(); bool shouldSkipVersion(QString latestVersion); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 9fede84a93..3689c4462e 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -56,6 +56,8 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p _numOutputCallbackBytes(0), _loopbackAudioOutput(NULL), _loopbackOutputDevice(NULL), + _proceduralAudioOutput(NULL), + _proceduralOutputDevice(NULL), _inputRingBuffer(0), _ringBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL), _scope(scope), @@ -75,7 +77,7 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p _muted(false) { // clear the array of locally injected samples - memset(_localInjectedSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); + memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); } void Audio::init(QGLWidget *parent) { @@ -272,6 +274,9 @@ void Audio::start() { // setup a loopback audio output device _loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); + + // setup a procedural audio output device + _proceduralAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); gettimeofday(&_lastReceiveTime, NULL); } @@ -332,7 +337,7 @@ void Audio::handleAudioInput() { memset(monoAudioSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); // zero out the locally injected audio in preparation for audio procedural sounds - memset(_localInjectedSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); + memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); if (!_muted) { // we aren't muted, downsample the input audio @@ -363,6 +368,22 @@ void Audio::handleAudioInput() { // add procedural effects to the appropriate input samples addProceduralSounds(monoAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + + if (!_proceduralOutputDevice) { + _proceduralOutputDevice = _proceduralAudioOutput->start(); + } + + // send whatever procedural sounds we want to locally loop back to the _proceduralOutputDevice + QByteArray proceduralOutput; + proceduralOutput.resize(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 4 * sizeof(int16_t)); + + linearResampling(_localProceduralSamples, + reinterpret_cast(proceduralOutput.data()), + NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL, + NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 4, + _desiredInputFormat, _outputFormat); + + _proceduralOutputDevice->write(proceduralOutput); NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); @@ -396,7 +417,7 @@ void Audio::handleAudioInput() { Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO) .updateValue(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes); } - delete[] inputAudioSamples; + delete[] inputAudioSamples; } } @@ -431,12 +452,6 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { static float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float) _outputFormat.sampleRate()) * (_desiredOutputFormat.channelCount() / (float) _outputFormat.channelCount()); - - static int numRequiredOutputSamples = NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / networkOutputToOutputRatio; - - QByteArray outputBuffer; - outputBuffer.resize(numRequiredOutputSamples * sizeof(int16_t)); - if (!_ringBuffer.isStarved() && _audioOutput->bytesFree() == _audioOutput->bufferSize()) { // we don't have any audio data left in the output buffer @@ -448,6 +463,14 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { // if there is anything in the ring buffer, decide what to do if (_ringBuffer.samplesAvailable() > 0) { + + + int numNetworkOutputSamples = _ringBuffer.samplesAvailable(); + int numDeviceOutputSamples = numNetworkOutputSamples / networkOutputToOutputRatio; + + QByteArray outputBuffer; + outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t)); + if (!_ringBuffer.isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (_jitterBufferSamples * 2))) { // starved and we don't have enough to start, keep waiting @@ -458,64 +481,28 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { // copy the samples we'll resample from the ring buffer - this also // pushes the read pointer of the ring buffer forwards - int16_t ringBufferSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO]; - _ringBuffer.readSamples(ringBufferSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO); - - // add the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL from each QByteArray - // in our _localInjectionByteArrays QVector to the _localInjectedSamples - - // add to the output samples whatever is in the _localAudioOutput byte array - // that lets this user hear sound effects and loopback (if enabled) - - for (int b = 0; b < _localInjectionByteArrays.size(); b++) { - QByteArray audioByteArray = _localInjectionByteArrays.at(b); - - int16_t* byteArraySamples = (int16_t*) audioByteArray.data(); - - int samplesToRead = qMin((int)(audioByteArray.size() / sizeof(int16_t)), - NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); - - for (int i = 0; i < samplesToRead; i++) { - _localInjectedSamples[i] = glm::clamp(_localInjectedSamples[i] + byteArraySamples[i], - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - } - - if (samplesToRead < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - // there isn't anything left to inject from this byte array, remove it from the vector - _localInjectionByteArrays.remove(b); - } else { - // pull out the bytes we just read for outputs - audioByteArray.remove(0, samplesToRead * sizeof(int16_t)); - - // still data left to read - replace the byte array in the QVector with the smaller one - _localInjectionByteArrays.replace(b, audioByteArray); - } - } - - for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { - ringBufferSamples[i * 2] = glm::clamp(ringBufferSamples[i * 2] + _localInjectedSamples[i], - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - ringBufferSamples[(i * 2) + 1] = glm::clamp(ringBufferSamples[(i * 2) + 1] + _localInjectedSamples[i], - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - } + int16_t* ringBufferSamples= new int16_t[numNetworkOutputSamples]; + _ringBuffer.readSamples(ringBufferSamples, numNetworkOutputSamples); + + // add the next numNetworkOutputSamples from each QByteArray + // in our _localInjectionByteArrays QVector to the localInjectedSamples // copy the packet from the RB to the output linearResampling(ringBufferSamples, (int16_t*) outputBuffer.data(), - NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, - numRequiredOutputSamples, + numNetworkOutputSamples, + numDeviceOutputSamples, _desiredOutputFormat, _outputFormat); if (_outputDevice) { - _outputDevice->write(outputBuffer); // add output (@speakers) data just written to the scope QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection, - Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, - NETWORK_BUFFER_LENGTH_BYTES_STEREO)), + Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, numNetworkOutputSamples)), Q_ARG(bool, true), Q_ARG(bool, false)); } + delete[] ringBufferSamples; } } @@ -672,7 +659,7 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { int16_t collisionSample = (int16_t) sample; monoInput[i] = glm::clamp(monoInput[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _localInjectedSamples[i] = glm::clamp(_localInjectedSamples[i] + collisionSample, + _localProceduralSamples[i] = glm::clamp(_localProceduralSamples[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); _collisionSoundMagnitude *= _collisionSoundDuration; @@ -696,7 +683,7 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { int16_t collisionSample = (int16_t) sample; monoInput[i] = glm::clamp(monoInput[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _localInjectedSamples[i] = glm::clamp(_localInjectedSamples[i] + collisionSample, + _localProceduralSamples[i] = glm::clamp(_localProceduralSamples[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); _drumSoundVolume *= (1.f - _drumSoundDecay); @@ -727,8 +714,8 @@ void Audio::startDrumSound(float volume, float frequency, float duration, float } void Audio::handleAudioByteArray(const QByteArray& audioByteArray) { - // add this byte array to our QVector - _localInjectionByteArrays.append(audioByteArray); + // TODO: either create a new audio device (up to the limit of the sound card or a hard limit) + // or send to the mixer and use delayed loopback } void Audio::renderToolIcon(int screenHeight) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index cc5a43d8e0..fa4fb62adf 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -86,8 +86,7 @@ private: QAudioFormat _inputFormat; QIODevice* _inputDevice; int _numInputCallbackBytes; - int16_t _localInjectedSamples[NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL]; - QVector _localInjectionByteArrays; + int16_t _localProceduralSamples[NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL]; QAudioOutput* _audioOutput; QAudioFormat _desiredOutputFormat; QAudioFormat _outputFormat; @@ -95,6 +94,8 @@ private: int _numOutputCallbackBytes; QAudioOutput* _loopbackAudioOutput; QIODevice* _loopbackOutputDevice; + QAudioOutput* _proceduralAudioOutput; + QIODevice* _proceduralOutputDevice; AudioRingBuffer _inputRingBuffer; AudioRingBuffer _ringBuffer; diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 94bc693c2b..7ec4f90eef 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -36,6 +36,7 @@ Camera::Camera() { _modeShiftRate = 1.0f; _linearModeShift = 0.0f; _mode = CAMERA_MODE_THIRD_PERSON; + _prevMode = CAMERA_MODE_THIRD_PERSON; _tightness = 10.0f; // default _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES; _aspectRatio = 16.f/9.f; @@ -123,6 +124,7 @@ void Camera::setModeShiftRate ( float rate ) { void Camera::setMode(CameraMode m) { + _prevMode = _mode; _mode = m; _modeShift = 0.0; _linearModeShift = 0.0; @@ -199,6 +201,17 @@ bool Camera::getFrustumNeedsReshape() const { return _frustumNeedsReshape; } +// call this when deciding whether to render the head or not +CameraMode Camera::getInterpolatedMode() const { + const float SHIFT_THRESHOLD_INTO_FIRST_PERSON = 0.7f; + const float SHIFT_THRESHOLD_OUT_OF_FIRST_PERSON = 0.6f; + if ((_mode == CAMERA_MODE_FIRST_PERSON && _linearModeShift < SHIFT_THRESHOLD_INTO_FIRST_PERSON) || + (_prevMode == CAMERA_MODE_FIRST_PERSON && _linearModeShift < SHIFT_THRESHOLD_OUT_OF_FIRST_PERSON)) { + return _prevMode; + } + return _mode; +} + // call this after reshaping the view frustum void Camera::setFrustumWasReshaped() { _frustumNeedsReshape = false; diff --git a/interface/src/Camera.h b/interface/src/Camera.h index 615135bc80..7fc9b47634 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -61,6 +61,8 @@ public: const glm::quat& getEyeOffsetOrientation () const { return _eyeOffsetOrientation; } float getScale () const { return _scale; } + CameraMode getInterpolatedMode() const; + bool getFrustumNeedsReshape() const; // call to find out if the view frustum needs to be reshaped void setFrustumWasReshaped(); // call this after reshaping the view frustum. @@ -68,6 +70,7 @@ private: bool _needsToInitialize; CameraMode _mode; + CameraMode _prevMode; bool _frustumNeedsReshape; glm::vec3 _position; glm::vec3 _idealPosition; diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 2938be80ea..24ec956c62 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -73,12 +73,12 @@ void DatagramProcessor::processDatagrams() { if (wantExtraDebugging && packetTypeForPacket(incomingPacket) == PacketTypeVoxelData) { int numBytesPacketHeader = numBytesForPacketHeader(incomingPacket); unsigned char* dataAt = reinterpret_cast(incomingPacket.data()) + numBytesPacketHeader; - dataAt += sizeof(VOXEL_PACKET_FLAGS); - VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SEQUENCE); - VOXEL_PACKET_SENT_TIME sentAt = (*(VOXEL_PACKET_SENT_TIME*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SENT_TIME); - VOXEL_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); + 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; printf("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 67eaa8782c..709f848a2f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -317,7 +317,6 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontFadeOnVoxelServerChanges); addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools())); - addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DisableLocalVoxelCache); QMenu* voxelProtoOptionsMenu = voxelOptionsMenu->addMenu("Voxel Server Protocol Options"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 5e49ca6fd1..6f7986fcc3 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -176,7 +176,6 @@ namespace MenuOption { const QString DestructiveAddVoxel = "Create Voxel is Destructive"; const QString DisableColorVoxels = "Disable Colored Voxels"; const QString DisableDeltaSending = "Disable Delta Sending"; - const QString DisableLocalVoxelCache = "Disable Local Voxel Cache"; const QString DisableLowRes = "Disable Lower Resolution While Moving"; const QString DisplayFrustum = "Display Frustum"; const QString DisplayLeapHands = "Display Leap Hands"; diff --git a/interface/src/ParticleTreeRenderer.cpp b/interface/src/ParticleTreeRenderer.cpp index d96ac2beaa..7a1991ca93 100644 --- a/interface/src/ParticleTreeRenderer.cpp +++ b/interface/src/ParticleTreeRenderer.cpp @@ -84,12 +84,11 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg const float alpha = 1.0f; Model* model = getModel(particle.getModelURL()); - - glm::vec3 translationAdjustment = particle.getModelTranslation(); - + glm::vec3 translationAdjustment = particle.getModelTranslation() * radius; + // set the position - glm::vec3 translation(position.x, position.y, position.z); - model->setTranslation(translation + translationAdjustment); + glm::vec3 translation = position + translationAdjustment; + model->setTranslation(translation); // set the rotation glm::quat rotation = particle.getModelRotation(); @@ -99,11 +98,21 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg // TODO: need to figure out correct scale adjust, this was arbitrarily set to make a couple models work const float MODEL_SCALE = 0.00575f; glm::vec3 scale(1.0f,1.0f,1.0f); - model->setScale(scale * MODEL_SCALE * radius * particle.getModelScale()); + + float modelScale = particle.getModelScale(); + model->setScale(scale * MODEL_SCALE * radius * modelScale); model->simulate(0.0f); model->render(alpha); // TODO: should we allow particles to have alpha on their models? + const bool wantDebugSphere = false; + if (wantDebugSphere) { + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glutWireSphere(radius, 15, 15); + glPopMatrix(); + } + glPopMatrix(); } else { glPushMatrix(); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 3297750fb9..1ffc6c3e5e 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -99,8 +99,6 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) _culledOnce = false; _inhideOutOfView = false; - _treeIsBusy = false; - } void VoxelSystem::elementDeleted(OctreeElement* element) { @@ -561,30 +559,30 @@ int VoxelSystem::parseData(const QByteArray& packet) { const unsigned char* dataAt = reinterpret_cast(packet.data()) + numBytesPacketHeader; - VOXEL_PACKET_FLAGS flags = (*(VOXEL_PACKET_FLAGS*)(dataAt)); - dataAt += sizeof(VOXEL_PACKET_FLAGS); - VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SEQUENCE); + 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); - VOXEL_PACKET_SENT_TIME sentAt = (*(VOXEL_PACKET_SENT_TIME*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SENT_TIME); + 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); - VOXEL_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); + OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt; - VOXEL_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - int dataBytes = packet.size() - VOXEL_PACKET_HEADER_SIZE; + OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; + int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); int subsection = 1; while (dataBytes > 0) { if (packetIsCompressed) { - if (dataBytes > sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE)) { - sectionLength = (*(VOXEL_PACKET_INTERNAL_SECTION_SIZE*)dataAt); - dataAt += sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE); - dataBytes -= sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE); + 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 @@ -594,9 +592,10 @@ int VoxelSystem::parseData(const QByteArray& packet) { } 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()); - lockTree(); + _tree->lockForWrite(); VoxelPacketData packetData(packetIsCompressed); packetData.loadFinalizedContent(dataAt, sectionLength); if (Application::getInstance()->getLogger()->extraDebugging()) { @@ -608,7 +607,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { packetData.getUncompressedSize()); } _tree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); - unlockTree(); + _tree->unlock(); dataBytes -= sectionLength; dataAt += sectionLength; @@ -1395,9 +1394,11 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { int VoxelSystem::_nodeCount = 0; void VoxelSystem::killLocalVoxels() { - lockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::killLocalVoxels()"); + _tree->lockForWrite(); _tree->eraseAllOctreeElements(); - unlockTree(); + _tree->unlock(); clearFreeBufferIndexes(); _voxelsInReadArrays = 0; // do we need to do this? setupNewVoxelsForDrawing(); @@ -1416,10 +1417,12 @@ bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void } void VoxelSystem::clearAllNodesBufferIndex() { + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::clearAllNodesBufferIndex()"); _nodeCount = 0; - lockTree(); + _tree->lockForRead(); // we won't change the tree so it's ok to treat this as a read _tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation); - unlockTree(); + _tree->unlock(); if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { qDebug("clearing buffer index of %d nodes", _nodeCount); } @@ -1481,7 +1484,8 @@ bool VoxelSystem::trueColorizeOperation(OctreeElement* element, void* extraData) } void VoxelSystem::trueColorize() { - PerformanceWarning warn(true, "trueColorize()",true); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "trueColorize()",true); _nodeCount = 0; _tree->recurseTreeWithOperation(trueColorizeOperation); qDebug("setting true color for %d nodes", _nodeCount); @@ -1951,9 +1955,13 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { return; } - lockTree(); - _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args); - unlockTree(); + { + 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; @@ -2150,35 +2158,47 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelDetail& detail, float& distance, BoxFace& face) { - lockTree(); - OctreeElement* element; - if (!_tree->findRayIntersection(origin, direction, element, distance, face)) { - unlockTree(); - return false; + + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::findRayIntersection()"); + bool result = false; // assume no intersection + if (_tree->tryLockForRead()) { + OctreeElement* element; + result = _tree->findRayIntersection(origin, direction, element, distance, face); + if (result) { + VoxelTreeElement* voxel = (VoxelTreeElement*)element; + detail.x = voxel->getCorner().x; + detail.y = voxel->getCorner().y; + detail.z = voxel->getCorner().z; + detail.s = voxel->getScale(); + detail.red = voxel->getColor()[0]; + detail.green = voxel->getColor()[1]; + detail.blue = voxel->getColor()[2]; + } + _tree->unlock(); } - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - detail.x = voxel->getCorner().x; - detail.y = voxel->getCorner().y; - detail.z = voxel->getCorner().z; - detail.s = voxel->getScale(); - detail.red = voxel->getColor()[0]; - detail.green = voxel->getColor()[1]; - detail.blue = voxel->getColor()[2]; - unlockTree(); - return true; + return result; } bool VoxelSystem::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) { - lockTree(); - bool result = _tree->findSpherePenetration(center, radius, penetration); - unlockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::findSpherePenetration()"); + bool result = false; // assume no penetration + if (_tree->tryLockForRead()) { + result = _tree->findSpherePenetration(center, radius, penetration); + _tree->unlock(); + } return result; } bool VoxelSystem::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) { - lockTree(); - bool result = _tree->findCapsulePenetration(start, end, radius, penetration); - unlockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::findCapsulePenetration()"); + bool result = false; // assume no penetration + if (_tree->tryLockForRead()) { + result = _tree->findCapsulePenetration(start, end, radius, penetration); + _tree->unlock(); + } return result; } @@ -2354,13 +2374,14 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) { - lockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::deleteVoxelAt()"); + _tree->lockForWrite(); _tree->deleteVoxelAt(x, y, z, s); - unlockTree(); + _tree->unlock(); // redraw! setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in? - }; VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const { @@ -2370,10 +2391,12 @@ VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) co void VoxelSystem::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive) { - //qDebug("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s); - lockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::createVoxel()"); + + _tree->lockForWrite(); _tree->createVoxel(x, y, z, s, red, green, blue, destructive); - unlockTree(); + _tree->unlock(); setupNewVoxelsForDrawing(); }; @@ -2744,37 +2767,3 @@ unsigned long VoxelSystem::getVoxelMemoryUsageGPU() { return (_initialMemoryUsageGPU - currentFreeMemory); } -void VoxelSystem::lockTree() { - _treeLock.lock(); - _treeIsBusy = true; -} - -void VoxelSystem::unlockTree() { - _treeIsBusy = false; - _treeLock.unlock(); -} - - -void VoxelSystem::localVoxelCacheLoaded() { - qDebug() << "localVoxelCacheLoaded()"; - - // Make sure that the application has properly set up the view frustum for our loaded state - Application::getInstance()->initAvatarAndViewFrustum(); - - _tree->setDirtyBit(); // make sure the tree thinks it's dirty - _setupNewVoxelsForDrawingLastFinished = 0; // don't allow the setupNewVoxelsForDrawing() shortcuts - _writeRenderFullVBO = true; // this will disable individual node updates, was reset by killLocalVoxels() - setupNewVoxelsForDrawing(); - _inhideOutOfView = false; // reenable hideOutOfView behavior -} - -void VoxelSystem::beginLoadingLocalVoxelCache() { - qDebug() << "beginLoadingLocalVoxelCache()"; - _writeRenderFullVBO = true; // this will disable individual node updates - _inhideOutOfView = true; // this will disable hidOutOfView which we want to do until local cache is loaded - killLocalVoxels(); - qDebug() << "DONE beginLoadingLocalVoxelCache()"; -} - - - diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index ca90424b70..d1404668bf 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -110,8 +110,6 @@ public: virtual void elementDeleted(OctreeElement* element); virtual void elementUpdated(OctreeElement* element); - bool treeIsBusy() const { return _treeIsBusy; } - VoxelTreeElement* getVoxelEnclosing(const glm::vec3& point); signals: @@ -144,9 +142,6 @@ public slots: void setUseVoxelShader(bool useVoxelShader); void setVoxelsAsPoints(bool voxelsAsPoints); - void localVoxelCacheLoaded(); - void beginLoadingLocalVoxelCache(); - protected: float _treeScale; unsigned long _maxVoxels; @@ -304,10 +299,6 @@ private: bool _useFastVoxelPipeline; bool _inhideOutOfView; - bool _treeIsBusy; // is the tree mutex locked? if so, it's busy, and if you can avoid it, don't access the tree - - void lockTree(); - void unlockTree(); }; #endif diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4b4c189729..259bf994e0 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -242,7 +242,9 @@ void Avatar::renderBody(bool forceRenderHead) { glm::vec3 pos = getPosition(); //printf("Render other at %.3f, %.2f, %.2f\n", pos.x, pos.y, pos.z); _skeletonModel.render(1.0f); - _head.render(1.0f); + if (forceRenderHead) { + _head.render(1.0f); + } _hand.render(false); } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d98d30cf6a..a4a85f5770 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -75,7 +75,6 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors); if (!selfAvatarOnly) { - // Render avatars of other nodes foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) { Avatar* avatar = static_cast(avatarPointer.data()); if (!avatar->isInitialized()) { @@ -84,7 +83,7 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { if (avatar == static_cast(_myAvatar.data())) { avatar->render(forceRenderHead); } else { - avatar->render(false); + avatar->render(true); } avatar->setDisplayingLookatVectors(renderLookAtVectors); } diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 2269d1d4a6..f8faed56ed 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -37,7 +37,6 @@ Head::Head(Avatar* owningAvatar) : _leftEyeBlinkVelocity(0.0f), _rightEyeBlinkVelocity(0.0f), _timeWithoutTalking(0.0f), - _cameraYaw(_yaw), _isCameraMoving(false), _faceModel(this) { @@ -189,8 +188,7 @@ glm::quat Head::getOrientation() const { glm::quat Head::getCameraOrientation () const { Avatar* owningAvatar = static_cast(_owningAvatar); - return owningAvatar->getWorldAlignedOrientation() - * glm::quat(glm::radians(glm::vec3(_pitch, _cameraYaw, 0.0f))); + return owningAvatar->getWorldAlignedOrientation(); } glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 94b8bd3dc7..169f2af749 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -96,7 +96,6 @@ private: float _leftEyeBlinkVelocity; float _rightEyeBlinkVelocity; float _timeWithoutTalking; - float _cameraYaw; bool _isCameraMoving; FaceModel _faceModel; diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index e2c3bfafdd..5a27b51b70 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -1632,7 +1632,18 @@ FBXGeometry readSVO(const QByteArray& model) { VoxelTree tree; ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); - tree.readBitstreamToTree((unsigned char*)model.data(), model.size(), args); + + unsigned char* dataAt = (unsigned char*)model.data(); + size_t dataSize = model.size(); + + if (tree.getWantSVOfileVersions()) { + // skip the type/version + dataAt += sizeof(PacketType); + dataSize -= sizeof(PacketType); + dataAt += sizeof(PacketVersion); + dataSize -= sizeof(PacketVersion); + } + tree.readBitstreamToTree(dataAt, dataSize, args); tree.recurseTreeWithOperation(addMeshVoxelsOperation, &mesh); geometry.meshes.append(mesh); diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 8a444e50fd..9bac210c39 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -70,9 +70,9 @@ qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) { // read to the end of the buffer int numSamplesToEnd = (_buffer + _sampleCapacity) - _nextOutput; memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t)); - + // read the rest from the beginning of the buffer - memcpy(data + numSamplesToEnd, _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); + memcpy(data + (numSamplesToEnd * sizeof(int16_t)), _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); } else { // read the data memcpy(data, _nextOutput, numReadSamples * sizeof(int16_t)); diff --git a/libraries/metavoxels/src/DatagramSequencer.cpp b/libraries/metavoxels/src/DatagramSequencer.cpp index ee218d7927..e941d9e4d3 100644 --- a/libraries/metavoxels/src/DatagramSequencer.cpp +++ b/libraries/metavoxels/src/DatagramSequencer.cpp @@ -171,7 +171,7 @@ void DatagramSequencer::receivedDatagram(const QByteArray& datagram) { } // read and dispatch the high-priority messages - quint32 highPriorityMessageCount; + int highPriorityMessageCount; _incomingPacketStream >> highPriorityMessageCount; int newHighPriorityMessages = highPriorityMessageCount - _receivedHighPriorityMessages; for (int i = 0; i < highPriorityMessageCount; i++) { diff --git a/libraries/octree-server/CMakeLists.txt b/libraries/octree-server/CMakeLists.txt deleted file mode 100644 index 64c73a4bd4..0000000000 --- a/libraries/octree-server/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(ROOT_DIR ../..) -set(MACRO_DIR ${ROOT_DIR}/cmake/macros) - -# setup for find modules -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") - -set(TARGET_NAME octree-server) - -find_package(Qt5Network REQUIRED) -find_package(Qt5Widgets REQUIRED) - -include(${MACRO_DIR}/SetupHifiLibrary.cmake) - -setup_hifi_library(${TARGET_NAME} ${OPTIONAL_SRCS}) - -qt5_use_modules(${TARGET_NAME} Network Widgets) - -include(${MACRO_DIR}/IncludeGLM.cmake) -include_glm(${TARGET_NAME} ${ROOT_DIR}) - -# link ZLIB -find_package(ZLIB) -include_directories(${ZLIB_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -# link in the shared library -include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) - -# link in the hifi octree library -link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) - -# link the embedded webserver -link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR}) diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index f004b45d14..76bb138516 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -30,10 +30,10 @@ typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE; const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE; // this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte -const int OCTREE_PACKET_HEADER_SIZE = MAX_PACKET_HEADER_BYTES + sizeof(OCTREE_PACKET_FLAGS) +const int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME); -const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - OCTREE_PACKET_HEADER_SIZE; +const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); const int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 0fe56cd936..b636d9baac 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -64,7 +64,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Hifi int flightTime = arrivedAt - sentAt + clockSkew; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - int dataBytes = packetLength - OCTREE_PACKET_HEADER_SIZE; + int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" diff --git a/libraries/particle-server/CMakeLists.txt b/libraries/particle-server/CMakeLists.txt deleted file mode 100644 index 9c63645e8d..0000000000 --- a/libraries/particle-server/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(ROOT_DIR ../..) -set(MACRO_DIR ${ROOT_DIR}/cmake/macros) - -# setup for find modules -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") - -set(TARGET_NAME particle-server) - -find_package(Qt5Widgets REQUIRED) - -include(${MACRO_DIR}/SetupHifiLibrary.cmake) - -setup_hifi_library(${TARGET_NAME} ${OPTIONAL_SRCS}) - -qt5_use_modules(${TARGET_NAME} Widgets) - -# inluce GLM -include(${MACRO_DIR}/IncludeGLM.cmake) -include_glm(${TARGET_NAME} ${ROOT_DIR}) - -# link in the shared library -include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) - -# link ZLIB -find_package(ZLIB) -include_directories(${ZLIB_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR}) - -# link in the embedded webserver -link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 12b59d28c9..d9f0beb81a 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -92,6 +92,10 @@ Particle::Particle(const ParticleID& particleID, const ParticleProperties& prope _script = DEFAULT_SCRIPT; _inHand = NOT_IN_HAND; _shouldDie = false; + _modelURL = DEFAULT_MODEL_URL; + _modelTranslation = DEFAULT_MODEL_TRANSLATION; + _modelRotation = DEFAULT_MODEL_ROTATION; + _modelScale = DEFAULT_MODEL_SCALE; setProperties(properties); } @@ -124,6 +128,10 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 _script = updateScript; _inHand = inHand; _shouldDie = false; + _modelURL = DEFAULT_MODEL_URL; + _modelTranslation = DEFAULT_MODEL_TRANSLATION; + _modelRotation = DEFAULT_MODEL_ROTATION; + _modelScale = DEFAULT_MODEL_SCALE; } void Particle::setMass(float value) { @@ -190,6 +198,12 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { success = packetData->appendRawData((const unsigned char*)qPrintable(_modelURL), modelURLLength); } } + + // modelScale + if (success) { + success = packetData->appendValue(getModelScale()); + } + // modelTranslation if (success) { success = packetData->appendValue(getModelTranslation()); @@ -198,11 +212,6 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { if (success) { success = packetData->appendValue(getModelRotation()); } - // modelScale - if (success) { - success = packetData->appendValue(getModelScale()); - } - return success; } @@ -319,6 +328,11 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += modelURLLength; bytesRead += modelURLLength; + // modelScale + memcpy(&_modelScale, dataAt, sizeof(_modelScale)); + dataAt += sizeof(_modelScale); + bytesRead += sizeof(_modelScale); + // modelTranslation memcpy(&_modelTranslation, dataAt, sizeof(_modelTranslation)); dataAt += sizeof(_modelTranslation); @@ -329,11 +343,6 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += bytes; bytesRead += bytes; - // modelScale - memcpy(&_modelScale, dataAt, sizeof(_modelScale)); - dataAt += sizeof(_modelScale); - bytesRead += sizeof(_modelScale); - //printf("Particle::readParticleDataFromBuffer()... "); debugDump(); } return bytesRead; @@ -498,6 +507,13 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr processedBytes += modelURLLength; } + // modelScale + if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { + memcpy(&newParticle._modelScale, dataAt, sizeof(newParticle._modelScale)); + dataAt += sizeof(newParticle._modelScale); + processedBytes += sizeof(newParticle._modelScale); + } + // modelTranslation if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_TRANSLATION) == CONTAINS_MODEL_TRANSLATION)) { memcpy(&newParticle._modelTranslation, dataAt, sizeof(newParticle._modelTranslation)); @@ -512,13 +528,6 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr processedBytes += bytes; } - // modelScale - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { - memcpy(&newParticle._modelScale, dataAt, sizeof(newParticle._modelScale)); - dataAt += sizeof(newParticle._modelScale); - processedBytes += sizeof(newParticle._modelScale); - } - const bool wantDebugging = false; if (wantDebugging) { qDebug("Particle::fromEditPacket()..."); @@ -696,6 +705,14 @@ bool Particle::encodeParticleEditMessageDetails(PacketType command, ParticleID i sizeOut += urlLength; } + // modelScale + if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { + float modelScale = properties.getModelScale(); + memcpy(copyAt, &modelScale, sizeof(modelScale)); + copyAt += sizeof(modelScale); + sizeOut += sizeof(modelScale); + } + // modelTranslation if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_TRANSLATION) == CONTAINS_MODEL_TRANSLATION)) { glm::vec3 modelTranslation = properties.getModelTranslation(); // should this be relative to TREE_SCALE?? @@ -711,14 +728,6 @@ bool Particle::encodeParticleEditMessageDetails(PacketType command, ParticleID i sizeOut += bytes; } - // modelScale - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { - float modelScale = properties.getModelScale(); - memcpy(copyAt, &modelScale, sizeof(modelScale)); - copyAt += sizeof(modelScale); - sizeOut += sizeof(modelScale); - } - bool wantDebugging = false; if (wantDebugging) { printf("encodeParticleEditMessageDetails()....\n"); @@ -931,9 +940,9 @@ ParticleProperties::ParticleProperties() : _inHand(false), _shouldDie(false), _modelURL(""), + _modelScale(DEFAULT_MODEL_SCALE), _modelTranslation(DEFAULT_MODEL_TRANSLATION), _modelRotation(DEFAULT_MODEL_ROTATION), - _modelScale(DEFAULT_MODEL_SCALE), _id(UNKNOWN_PARTICLE_ID), _idSet(false), @@ -950,9 +959,9 @@ ParticleProperties::ParticleProperties() : _inHandChanged(false), _shouldDieChanged(false), _modelURLChanged(false), + _modelScaleChanged(false), _modelTranslationChanged(false), _modelRotationChanged(false), - _modelScaleChanged(false), _defaultSettings(true) { } @@ -1004,6 +1013,10 @@ uint16_t ParticleProperties::getChangedBits() const { changedBits += CONTAINS_MODEL_URL; } + if (_modelScaleChanged) { + changedBits += CONTAINS_MODEL_SCALE; + } + if (_modelTranslationChanged) { changedBits += CONTAINS_MODEL_TRANSLATION; } @@ -1012,10 +1025,6 @@ uint16_t ParticleProperties::getChangedBits() const { changedBits += CONTAINS_MODEL_ROTATION; } - if (_modelScaleChanged) { - changedBits += CONTAINS_MODEL_SCALE; - } - return changedBits; } @@ -1045,14 +1054,14 @@ QScriptValue ParticleProperties::copyToScriptValue(QScriptEngine* engine) const properties.setProperty("modelURL", _modelURL); + properties.setProperty("modelScale", _modelScale); + QScriptValue modelTranslation = vec3toScriptValue(engine, _modelTranslation); properties.setProperty("modelTranslation", modelTranslation); QScriptValue modelRotation = quatToScriptValue(engine, _modelRotation); properties.setProperty("modelRotation", modelRotation); - properties.setProperty("modelScale", _modelScale); - if (_idSet) { properties.setProperty("id", _id); @@ -1203,7 +1212,17 @@ void ParticleProperties::copyFromScriptValue(const QScriptValue &object) { _modelURLChanged = true; } } - + + QScriptValue modelScale = object.property("modelScale"); + if (modelScale.isValid()) { + float newModelScale; + newModelScale = modelScale.toVariant().toFloat(); + if (_defaultSettings || newModelScale != _modelScale) { + _modelScale = newModelScale; + _modelScaleChanged = true; + } + } + QScriptValue modelTranslation = object.property("modelTranslation"); if (modelTranslation.isValid()) { QScriptValue x = modelTranslation.property("x"); @@ -1241,16 +1260,6 @@ void ParticleProperties::copyFromScriptValue(const QScriptValue &object) { } } - QScriptValue modelScale = object.property("modelScale"); - if (modelScale.isValid()) { - float newModelScale; - newModelScale = modelScale.toVariant().toFloat(); - if (_defaultSettings || newModelScale != _modelScale) { - _modelScale = newModelScale; - _modelScaleChanged = true; - } - } - _lastEdited = usecTimestampNow(); } @@ -1310,6 +1319,11 @@ void ParticleProperties::copyToParticle(Particle& particle) const { particle.setModelURL(_modelURL); somethingChanged = true; } + + if (_modelScaleChanged) { + particle.setModelScale(_modelScale); + somethingChanged = true; + } if (_modelTranslationChanged) { particle.setModelTranslation(_modelTranslation); @@ -1321,11 +1335,6 @@ void ParticleProperties::copyToParticle(Particle& particle) const { somethingChanged = true; } - if (_modelScaleChanged) { - particle.setModelScale(_modelScale); - somethingChanged = true; - } - if (somethingChanged) { bool wantDebug = false; if (wantDebug) { @@ -1350,9 +1359,9 @@ void ParticleProperties::copyFromParticle(const Particle& particle) { _inHand = particle.getInHand(); _shouldDie = particle.getShouldDie(); _modelURL = particle.getModelURL(); + _modelScale = particle.getModelScale(); _modelTranslation = particle.getModelTranslation(); _modelRotation = particle.getModelRotation(); - _modelScale = particle.getModelScale(); _id = particle.getID(); _idSet = true; @@ -1368,9 +1377,9 @@ void ParticleProperties::copyFromParticle(const Particle& particle) { _inHandChanged = false; _shouldDieChanged = false; _modelURLChanged = false; + _modelScaleChanged = false; _modelTranslationChanged = false; _modelRotationChanged = false; - _modelScaleChanged = false; _defaultSettings = false; } diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 925227055f..84efdd2916 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -56,13 +56,13 @@ const float DEFAULT_RADIUS = 0.1f / TREE_SCALE; const float MINIMUM_PARTICLE_ELEMENT_SIZE = (1.0f / 100000.0f) / TREE_SCALE; // smallest size container const glm::vec3 DEFAULT_GRAVITY(0, (-9.8f / TREE_SCALE), 0); const QString DEFAULT_SCRIPT(""); +const QString DEFAULT_MODEL_URL(""); const glm::vec3 DEFAULT_MODEL_TRANSLATION(0, 0, 0); const glm::quat DEFAULT_MODEL_ROTATION(0, 0, 0, 0); const float DEFAULT_MODEL_SCALE = 1.0f; const bool IN_HAND = true; // it's in a hand const bool NOT_IN_HAND = !IN_HAND; // it's not in a hand - /// A collection of properties of a particle used in the scripting API. Translates between the actual properties of a particle /// and a JavaScript style hash/QScriptValue storing a set of properties. Used in scripting to set/get the complete set of /// particle properties via JavaScript hashes/QScriptValues @@ -88,9 +88,9 @@ public: bool getInHand() const { return _inHand; } bool getShouldDie() const { return _shouldDie; } const QString& getModelURL() const { return _modelURL; } + float getModelScale() const { return _modelScale; } const glm::vec3& getModelTranslation() const { return _modelTranslation; } const glm::quat& getModelRotation() const { return _modelRotation; } - float getModelScale() const { return _modelScale; } quint64 getLastEdited() const { return _lastEdited; } uint16_t getChangedBits() const; @@ -113,10 +113,10 @@ public: // model related properties void setModelURL(const QString& url) { _modelURL = url; _modelURLChanged = true; } + void setModelScale(float scale) { _modelScale = scale; _modelScaleChanged = true; } void setModelTranslation(const glm::vec3& translation) { _modelTranslation = translation; _modelTranslationChanged = true; } void setModelRotation(const glm::quat& rotation) { _modelRotation = rotation; _modelRotationChanged = true; } - void setModelScale(float scale) { _modelScale = scale; _modelScaleChanged = true; } /// used by ParticleScriptingInterface to return ParticleProperties for unknown particles void setIsUnknownID() { _id = UNKNOWN_PARTICLE_ID; _idSet = true; } @@ -133,9 +133,9 @@ private: bool _inHand; bool _shouldDie; QString _modelURL; + float _modelScale; glm::vec3 _modelTranslation; glm::quat _modelRotation; - float _modelScale; uint32_t _id; bool _idSet; @@ -152,9 +152,9 @@ private: bool _inHandChanged; bool _shouldDieChanged; bool _modelURLChanged; + bool _modelScaleChanged; bool _modelTranslationChanged; bool _modelRotationChanged; - bool _modelScaleChanged; bool _defaultSettings; }; Q_DECLARE_METATYPE(ParticleProperties); @@ -227,9 +227,9 @@ public: // model related properties bool hasModel() const { return !_modelURL.isEmpty(); } const QString& getModelURL() const { return _modelURL; } + float getModelScale() const { return _modelScale; } const glm::vec3& getModelTranslation() const { return _modelTranslation; } const glm::quat& getModelRotation() const { return _modelRotation; } - float getModelScale() const { return _modelScale; } ParticleID getParticleID() const { return ParticleID(getID(), getCreatorTokenID(), getID() != UNKNOWN_PARTICLE_ID); } ParticleProperties getProperties() const; @@ -277,9 +277,9 @@ public: // model related properties void setModelURL(const QString& url) { _modelURL = url; } + void setModelScale(float scale) { _modelScale = scale; } void setModelTranslation(const glm::vec3& translation) { _modelTranslation = translation; } void setModelRotation(const glm::quat& rotation) { _modelRotation = rotation; } - void setModelScale(float scale) { _modelScale = scale; } void setProperties(const ParticleProperties& properties); @@ -344,9 +344,9 @@ protected: // model related items QString _modelURL; + float _modelScale; glm::vec3 _modelTranslation; glm::quat _modelRotation; - float _modelScale; uint32_t _creatorTokenID; bool _newlyCreated; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index cd9356ab15..d6b8005263 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -337,7 +337,7 @@ void NodeList::processSTUNResponse(const QByteArray& packet) { const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(RFC_5389_MAGIC_COOKIE); - size_t attributeStartIndex = NUM_BYTES_STUN_HEADER; + int attributeStartIndex = NUM_BYTES_STUN_HEADER; if (memcmp(packet.data() + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 3fd51949f9..16e7cca1c1 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -37,13 +37,15 @@ int packArithmeticallyCodedValue(int value, char* destination) { return 1; } else { // pack 255 and then recursively pack on - destination[0] = 255; + ((unsigned char*)destination)[0] = 255; return 1 + packArithmeticallyCodedValue(value - 255, destination + 1); } } PacketVersion versionForPacketType(PacketType type) { switch (type) { + case PacketTypeParticleData: + return 1; default: return 0; } diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 3b869e0ece..f22c81a71a 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -65,6 +65,8 @@ bool shouldDo(float desiredInterval, float deltaTime) { return randFloat() < deltaTime / desiredInterval; } + + void outputBufferBits(const unsigned char* buffer, int length, QDebug* continuedDebug) { for (int i = 0; i < length; i++) { outputBits(buffer[i], continuedDebug); @@ -76,6 +78,7 @@ void outputBits(unsigned char byte, QDebug* continuedDebug) { if (continuedDebug) { debug = *continuedDebug; + debug.nospace(); } QString resultString; @@ -85,12 +88,12 @@ void outputBits(unsigned char byte, QDebug* continuedDebug) { } else { resultString.sprintf("[ %d (0x%x): ", byte, byte); } - debug << resultString; - + debug << qPrintable(resultString); + for (int i = 0; i < 8; i++) { resultString.sprintf("%d", byte >> (7 - i) & 1); + debug << qPrintable(resultString); } - debug << resultString; debug << " ]"; } diff --git a/libraries/voxel-server/CMakeLists.txt b/libraries/voxel-server/CMakeLists.txt deleted file mode 100644 index 594d037767..0000000000 --- a/libraries/voxel-server/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(ROOT_DIR ../..) -set(MACRO_DIR ${ROOT_DIR}/cmake/macros) - -# setup for find modules -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") - -set(TARGET_NAME voxel-server) - -find_package(Qt5Widgets REQUIRED) - -include(${MACRO_DIR}/SetupHifiLibrary.cmake) - -setup_hifi_library(${TARGET_NAME} ${OPTIONAL_SRCS}) - -qt5_use_modules(${TARGET_NAME} Widgets) - -include(${MACRO_DIR}/IncludeGLM.cmake) -include_glm(${TARGET_NAME} ${ROOT_DIR}) - -# link ZLIB -find_package(ZLIB) -include_directories(${ZLIB_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -# link in the shared library -include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) - -# link in the embedded webserver -link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR}) - -# link in the hifi octree library -link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file diff --git a/libraries/voxels/src/VoxelPacketData.h b/libraries/voxels/src/VoxelPacketData.h index bf2a759225..637a91d0ec 100644 --- a/libraries/voxels/src/VoxelPacketData.h +++ b/libraries/voxels/src/VoxelPacketData.h @@ -26,20 +26,6 @@ #include "VoxelConstants.h" #include "VoxelTreeElement.h" -typedef unsigned char VOXEL_PACKET_FLAGS; -typedef uint16_t VOXEL_PACKET_SEQUENCE; -typedef quint64 VOXEL_PACKET_SENT_TIME; -typedef uint16_t VOXEL_PACKET_INTERNAL_SECTION_SIZE; -const int MAX_VOXEL_PACKET_SIZE = MAX_PACKET_SIZE; - -// this is overly conservative - uses 8 bytes for PacketType which could be as compact as a single byte -const int VOXEL_PACKET_HEADER_SIZE = MAX_PACKET_HEADER_BYTES + sizeof(VOXEL_PACKET_FLAGS) - + sizeof(VOXEL_PACKET_SEQUENCE) + sizeof(VOXEL_PACKET_SENT_TIME); - -const int MAX_VOXEL_PACKET_DATA_SIZE = MAX_PACKET_SIZE - VOXEL_PACKET_HEADER_SIZE; - -const int MAX_VOXEL_UNCOMRESSED_PACKET_SIZE = MAX_VOXEL_PACKET_DATA_SIZE; - /// Handles packing of the data portion of PacketType_VOXEL_DATA messages. class VoxelPacketData : public OctreePacketData { public: diff --git a/libraries/voxels/src/VoxelTreeElement.cpp b/libraries/voxels/src/VoxelTreeElement.cpp index c98ed77b74..6fd3997165 100644 --- a/libraries/voxels/src/VoxelTreeElement.cpp +++ b/libraries/voxels/src/VoxelTreeElement.cpp @@ -54,6 +54,8 @@ void VoxelTreeElement::splitChildren() { 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 } } @@ -143,7 +145,11 @@ void VoxelTreeElement::setColor(const nodeColor& color) { memcpy(&_currentColor,&color,sizeof(nodeColor)); } _isDirty = true; - _density = 1.0f; // If color set, assume leaf, re-averaging will update density if needed. + if (color[3]) { + _density = 1.0f; // If color set, assume leaf, re-averaging will update density if needed. + } else { + _density = 0.0f; + } markWithChangedTime(); } }