diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 819f68086c..4f01fce125 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 fbx particles entities metavoxels + audio avatars octree voxels fbx entities metavoxels networking animation shared script-engine embedded-webserver ) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 140742ce88..60129aa444 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -26,7 +26,6 @@ #include #include -#include // TODO: consider moving to scriptengine.h #include // TODO: consider moving to scriptengine.h #include "avatars/ScriptableAvatar.h" @@ -38,7 +37,6 @@ static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; Agent::Agent(const QByteArray& packet) : ThreadedAssignment(packet), _voxelEditSender(), - _particleEditSender(), _entityEditSender(), _receivedAudioStream(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, InboundAudioStream::Settings(0, false, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, false, @@ -50,7 +48,6 @@ Agent::Agent(const QByteArray& packet) : _scriptEngine.setParent(this); _scriptEngine.getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender); - _scriptEngine.getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); _scriptEngine.getEntityScriptingInterface()->setPacketSender(&_entityEditSender); } @@ -75,9 +72,6 @@ void Agent::readPendingDatagrams() { _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()-> queueReceivedPacket(matchedNode,receivedPacket); break; - case NodeType::ParticleServer: - _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()-> - queueReceivedPacket(matchedNode, receivedPacket); break; case NodeType::EntityServer: _scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()-> @@ -86,31 +80,18 @@ void Agent::readPendingDatagrams() { } } - } else if (datagramPacketType == PacketTypeParticleAddResponse) { - // this will keep creatorTokenIDs to IDs mapped correctly - Particle::handleAddParticleResponse(receivedPacket); - - // also give our local particle tree a chance to remap any internal locally created particles - _particleViewer.getTree()->handleAddParticleResponse(receivedPacket); - - // Make sure our Node and NodeList knows we've heard from this node. - SharedNodePointer sourceNode = nodeList->sendingNodeForPacket(receivedPacket); - sourceNode->setLastHeardMicrostamp(usecTimestampNow()); - } else if (datagramPacketType == PacketTypeEntityAddResponse) { // this will keep creatorTokenIDs to IDs mapped correctly EntityItemID::handleAddEntityResponse(receivedPacket); - // also give our local particle tree a chance to remap any internal locally created particles + // also give our local entity tree a chance to remap any internal locally created entities _entityViewer.getTree()->handleAddEntityResponse(receivedPacket); // Make sure our Node and NodeList knows we've heard from this node. SharedNodePointer sourceNode = nodeList->sendingNodeForPacket(receivedPacket); sourceNode->setLastHeardMicrostamp(usecTimestampNow()); - } else if (datagramPacketType == PacketTypeParticleData - || datagramPacketType == PacketTypeParticleErase - || datagramPacketType == PacketTypeOctreeStats + } else if (datagramPacketType == PacketTypeOctreeStats || datagramPacketType == PacketTypeVoxelData || datagramPacketType == PacketTypeEntityData || datagramPacketType == PacketTypeEntityErase @@ -141,10 +122,6 @@ void Agent::readPendingDatagrams() { datagramPacketType = packetTypeForPacket(mutablePacket); } // fall through to piggyback message - if (datagramPacketType == PacketTypeParticleData || datagramPacketType == PacketTypeParticleErase) { - _particleViewer.processDatagram(mutablePacket, sourceNode); - } - if (datagramPacketType == PacketTypeEntityData || datagramPacketType == PacketTypeEntityErase) { _entityViewer.processDatagram(mutablePacket, sourceNode); } @@ -191,7 +168,6 @@ void Agent::run() { << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::VoxelServer - << NodeType::ParticleServer << NodeType::EntityServer ); @@ -248,11 +224,6 @@ void Agent::run() { _voxelViewer.init(); _scriptEngine.getVoxelsScriptingInterface()->setVoxelTree(_voxelViewer.getTree()); - _scriptEngine.registerGlobalObject("ParticleViewer", &_particleViewer); - _particleViewer.setJurisdictionListener(_scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()); - _particleViewer.init(); - _scriptEngine.getParticlesScriptingInterface()->setParticleTree(_particleViewer.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 9d808ba20d..28af2a392d 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -22,9 +22,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -64,10 +61,8 @@ public slots: private: ScriptEngine _scriptEngine; VoxelEditPacketSender _voxelEditSender; - ParticleEditPacketSender _particleEditSender; EntityEditPacketSender _entityEditSender; - ParticleTreeHeadlessViewer _particleViewer; VoxelTreeHeadlessViewer _voxelViewer; EntityTreeHeadlessViewer _entityViewer; diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index d5efcba8ae..63c87313fe 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 "particles/ParticleServer.h" #include "voxels/VoxelServer.h" ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet) { @@ -38,8 +37,6 @@ ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet return new Agent(packet); case Assignment::VoxelServerType: return new VoxelServer(packet); - case Assignment::ParticleServerType: - return new ParticleServer(packet); case Assignment::MetavoxelServerType: return new MetavoxelServer(packet); case Assignment::EntityServerType: diff --git a/assignment-client/src/particles/ParticleNodeData.h b/assignment-client/src/particles/ParticleNodeData.h deleted file mode 100644 index 3850b6da8d..0000000000 --- a/assignment-client/src/particles/ParticleNodeData.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// ParticleNodeData.h -// assignment-client/src/particles -// -// Created by Brad Hefta-Gaub on 12/4/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_ParticleNodeData_h -#define hifi_ParticleNodeData_h - -#include - -#include "../octree/OctreeQueryNode.h" - -class ParticleNodeData : public OctreeQueryNode { -public: - ParticleNodeData() : - OctreeQueryNode(), - _lastDeletedParticlesSentAt(0) { } - - virtual PacketType getMyPacketType() const { return PacketTypeParticleData; } - - quint64 getLastDeletedParticlesSentAt() const { return _lastDeletedParticlesSentAt; } - void setLastDeletedParticlesSentAt(quint64 sentAt) { _lastDeletedParticlesSentAt = sentAt; } - -private: - quint64 _lastDeletedParticlesSentAt; -}; - -#endif // hifi_ParticleNodeData_h diff --git a/assignment-client/src/particles/ParticleServer.cpp b/assignment-client/src/particles/ParticleServer.cpp deleted file mode 100644 index 674d22145f..0000000000 --- a/assignment-client/src/particles/ParticleServer.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// -// ParticleServer.cpp -// assignment-client/src/particles -// -// Created by Brad Hefta-Gaub on 12/4/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 "ParticleServer.h" -#include "ParticleServerConsts.h" -#include "ParticleNodeData.h" - -const char* PARTICLE_SERVER_NAME = "Particle"; -const char* PARTICLE_SERVER_LOGGING_TARGET_NAME = "particle-server"; -const char* LOCAL_PARTICLES_PERSIST_FILE = "resources/particles.svo"; - -ParticleServer::ParticleServer(const QByteArray& packet) : OctreeServer(packet) { - // nothing special to do here... -} - -ParticleServer::~ParticleServer() { - ParticleTree* tree = (ParticleTree*)_tree; - tree->removeNewlyCreatedHook(this); -} - -OctreeQueryNode* ParticleServer::createOctreeQueryNode() { - return new ParticleNodeData(); -} - -Octree* ParticleServer::createTree() { - ParticleTree* tree = new ParticleTree(true); - tree->addNewlyCreatedHook(this); - return tree; -} - -void ParticleServer::beforeRun() { - QTimer* pruneDeletedParticlesTimer = new QTimer(this); - connect(pruneDeletedParticlesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedParticles())); - const int PRUNE_DELETED_PARTICLES_INTERVAL_MSECS = 1 * 1000; // once every second - pruneDeletedParticlesTimer->start(PRUNE_DELETED_PARTICLES_INTERVAL_MSECS); -} - -void ParticleServer::particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode) { - unsigned char outputBuffer[MAX_PACKET_SIZE]; - unsigned char* copyAt = outputBuffer; - - int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(outputBuffer), PacketTypeParticleAddResponse); - int packetLength = numBytesPacketHeader; - copyAt += numBytesPacketHeader; - - // encode the creatorTokenID - uint32_t creatorTokenID = newParticle.getCreatorTokenID(); - memcpy(copyAt, &creatorTokenID, sizeof(creatorTokenID)); - copyAt += sizeof(creatorTokenID); - packetLength += sizeof(creatorTokenID); - - // encode the particle ID - uint32_t particleID = newParticle.getID(); - memcpy(copyAt, &particleID, sizeof(particleID)); - copyAt += sizeof(particleID); - packetLength += sizeof(particleID); - - NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, senderNode); -} - - -// ParticleServer will use the "special packets" to send list of recently deleted particles -bool ParticleServer::hasSpecialPacketToSend(const SharedNodePointer& node) { - bool shouldSendDeletedParticles = false; - - // check to see if any new particles have been added since we last sent to this node... - ParticleNodeData* nodeData = static_cast(node->getLinkedData()); - if (nodeData) { - quint64 deletedParticlesSentAt = nodeData->getLastDeletedParticlesSentAt(); - - ParticleTree* tree = static_cast(_tree); - shouldSendDeletedParticles = tree->hasParticlesDeletedSince(deletedParticlesSentAt); - } - - return shouldSendDeletedParticles; -} - -int ParticleServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { - unsigned char outputBuffer[MAX_PACKET_SIZE]; - size_t packetLength = 0; - - ParticleNodeData* nodeData = static_cast(node->getLinkedData()); - if (nodeData) { - quint64 deletedParticlesSentAt = nodeData->getLastDeletedParticlesSentAt(); - quint64 deletePacketSentAt = usecTimestampNow(); - - ParticleTree* tree = static_cast(_tree); - bool hasMoreToSend = true; - - // TODO: is it possible to send too many of these packets? what if you deleted 1,000,000 particles? - packetsSent = 0; - while (hasMoreToSend) { - hasMoreToSend = tree->encodeParticlesDeletedSince(queryNode->getSequenceNumber(), deletedParticlesSentAt, - outputBuffer, MAX_PACKET_SIZE, packetLength); - - //qDebug() << "sending PacketType_PARTICLE_ERASE packetLength:" << packetLength; - - NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); - queryNode->packetSent(outputBuffer, packetLength); - packetsSent++; - } - - nodeData->setLastDeletedParticlesSentAt(deletePacketSentAt); - } - - // TODO: caller is expecting a packetLength, what if we send more than one packet?? - return packetLength; -} - -void ParticleServer::pruneDeletedParticles() { - ParticleTree* tree = static_cast(_tree); - if (tree->hasAnyDeletedParticles()) { - - //qDebug() << "there are some deleted particles to consider..."; - quint64 earliestLastDeletedParticlesSent = usecTimestampNow() + 1; // in the future - foreach (const SharedNodePointer& otherNode, NodeList::getInstance()->getNodeHash()) { - if (otherNode->getLinkedData()) { - ParticleNodeData* nodeData = static_cast(otherNode->getLinkedData()); - quint64 nodeLastDeletedParticlesSentAt = nodeData->getLastDeletedParticlesSentAt(); - if (nodeLastDeletedParticlesSentAt < earliestLastDeletedParticlesSent) { - earliestLastDeletedParticlesSent = nodeLastDeletedParticlesSentAt; - } - } - } - //qDebug() << "earliestLastDeletedParticlesSent=" << earliestLastDeletedParticlesSent; - tree->forgetParticlesDeletedBefore(earliestLastDeletedParticlesSent); - } -} - diff --git a/assignment-client/src/particles/ParticleServer.h b/assignment-client/src/particles/ParticleServer.h deleted file mode 100644 index 0b379a903e..0000000000 --- a/assignment-client/src/particles/ParticleServer.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// ParticleServer.h -// assignment-client/src/particles -// -// Created by Brad Hefta-Gaub on 12/2/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_ParticleServer_h -#define hifi_ParticleServer_h - -#include "../octree/OctreeServer.h" - -#include "Particle.h" -#include "ParticleServerConsts.h" -#include "ParticleTree.h" - -/// Handles assignments of type ParticleServer - sending particles to various clients. -class ParticleServer : public OctreeServer, public NewlyCreatedParticleHook { - Q_OBJECT -public: - ParticleServer(const QByteArray& packet); - ~ParticleServer(); - - // Subclasses must implement these methods - virtual OctreeQueryNode* createOctreeQueryNode(); - virtual Octree* createTree(); - virtual char getMyNodeType() const { return NodeType::ParticleServer; } - virtual PacketType getMyQueryMessageType() const { return PacketTypeParticleQuery; } - virtual const char* getMyServerName() const { return PARTICLE_SERVER_NAME; } - virtual const char* getMyLoggingServerTargetName() const { return PARTICLE_SERVER_LOGGING_TARGET_NAME; } - virtual const char* getMyDefaultPersistFilename() const { return LOCAL_PARTICLES_PERSIST_FILE; } - virtual PacketType getMyEditNackType() const { return PacketTypeParticleEditNack; } - - // subclass may implement these method - virtual void beforeRun(); - virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent); - - virtual void particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode); - -public slots: - void pruneDeletedParticles(); - -private: -}; - -#endif // hifi_ParticleServer_h diff --git a/assignment-client/src/particles/ParticleServerConsts.h b/assignment-client/src/particles/ParticleServerConsts.h deleted file mode 100644 index 49df2a181e..0000000000 --- a/assignment-client/src/particles/ParticleServerConsts.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// ParticleServerConsts.h -// assignment-client/src/particles -// -// 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_ParticleServerConsts_h -#define hifi_ParticleServerConsts_h - -extern const char* PARTICLE_SERVER_NAME; -extern const char* PARTICLE_SERVER_LOGGING_TARGET_NAME; -extern const char* LOCAL_PARTICLES_PERSIST_FILE; - -#endif // hifi_ParticleServerConsts_h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 16ca977bae..f014310637 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -101,7 +101,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # link required hifi libraries -link_hifi_libraries(shared octree voxels fbx metavoxels networking particles entities avatars audio animation script-engine) +link_hifi_libraries(shared octree voxels fbx metavoxels networking entities avatars audio animation script-engine) # find any optional and required libraries find_package(ZLIB REQUIRED) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d3bed0c3ea..5f99dbc4fb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include @@ -323,12 +322,11 @@ 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::ParticleServer << NodeType::EntityServer + << NodeType::VoxelServer << NodeType::EntityServer << NodeType::MetavoxelServer); - // connect to the packet sent signal of the _voxelEditSender and the _particleEditSender + // connect to the packet sent signal of the _voxelEditSender and the _entityEditSender connect(&_voxelEditSender, &VoxelEditPacketSender::packetSent, this, &Application::packetSent); - connect(&_particleEditSender, &ParticleEditPacketSender::packetSent, this, &Application::packetSent); connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent); // move the silentNodeTimer to the _nodeThread @@ -371,16 +369,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // Tell our voxel edit sender about our known jurisdictions _voxelEditSender.setVoxelServerJurisdictions(&_voxelServerJurisdictions); - _particleEditSender.setServerJurisdictions(&_particleServerJurisdictions); _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions); - Particle::setVoxelEditPacketSender(&_voxelEditSender); - Particle::setParticleEditPacketSender(&_particleEditSender); - // For now we're going to set the PPS for outbound packets to be super high, this is // probably not the right long term solution. But for now, we're going to do this to - // allow you to move a particle around in your hand - _particleEditSender.setPacketsPerSecond(3000); // super high!! + // allow you to move an entity around in your hand _entityEditSender.setPacketsPerSecond(3000); // super high!! checkVersion(); @@ -457,7 +450,6 @@ Application::~Application() { _octreeProcessor.terminate(); _voxelHideShowThread.terminate(); _voxelEditSender.terminate(); - _particleEditSender.terminate(); _entityEditSender.terminate(); @@ -552,7 +544,6 @@ void Application::initializeGL() { _octreeProcessor.initialize(_enableProcessVoxelsThread); _voxelEditSender.initialize(_enableProcessVoxelsThread); _voxelHideShowThread.initialize(_enableProcessVoxelsThread); - _particleEditSender.initialize(_enableProcessVoxelsThread); _entityEditSender.initialize(_enableProcessVoxelsThread); if (_enableProcessVoxelsThread) { @@ -803,7 +794,6 @@ void Application::controlledBroadcastToNodes(const QByteArray& packet, const Nod channel = BandwidthMeter::AVATARS; break; case NodeType::VoxelServer: - case NodeType::ParticleServer: case NodeType::EntityServer: channel = BandwidthMeter::VOXELS; break; @@ -1366,7 +1356,7 @@ void Application::dropEvent(QDropEvent *event) { void Application::sendPingPackets() { QByteArray pingPacket = NodeList::getInstance()->constructPingPacket(); controlledBroadcastToNodes(pingPacket, NodeSet() - << NodeType::VoxelServer << NodeType::ParticleServer << NodeType::EntityServer + << NodeType::VoxelServer << NodeType::EntityServer << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::MetavoxelServer); } @@ -1856,9 +1846,6 @@ void Application::init() { _voxels.setDisableFastVoxelPipeline(false); _voxels.init(); - _particles.init(); - _particles.setViewFrustum(getViewFrustum()); - _entities.init(); _entities.setViewFrustum(getViewFrustum()); @@ -1870,15 +1857,6 @@ void Application::init() { _metavoxels.init(); - _particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio, &_avatarManager); - - // connect the _particleCollisionSystem to our script engine's ParticlesScriptingInterface - connect(&_particleCollisionSystem, &ParticleCollisionSystem::particleCollisionWithVoxel, - ScriptEngine::getParticlesScriptingInterface(), &ParticlesScriptingInterface::particleCollisionWithVoxel); - - connect(&_particleCollisionSystem, &ParticleCollisionSystem::particleCollisionWithParticle, - ScriptEngine::getParticlesScriptingInterface(), &ParticlesScriptingInterface::particleCollisionWithParticle); - _audio.init(_glWidget); _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings); @@ -2095,7 +2073,6 @@ void Application::updateThreads(float deltaTime) { _octreeProcessor.threadRoutine(); _voxelHideShowThread.threadRoutine(); _voxelEditSender.threadRoutine(); - _particleEditSender.threadRoutine(); _entityEditSender.threadRoutine(); } } @@ -2215,15 +2192,6 @@ void Application::update(float deltaTime) { updateDialogs(deltaTime); // update various stats dialogs if present updateCursor(deltaTime); // Handle cursor updates - { - PerformanceTimer perfTimer("particles"); - _particles.update(); // update the particles... - { - PerformanceTimer perfTimer("collisions"); - _particleCollisionSystem.update(); // collide the particles... - } - } - { PerformanceTimer perfTimer("entities"); _entities.update(); // update the models... @@ -2278,9 +2246,6 @@ void Application::update(float deltaTime) { if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions); } - if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) { - queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions); - } if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) { queryOctree(NodeType::EntityServer, PacketTypeEntityQuery, _entityServerJurisdictions); } @@ -2338,7 +2303,6 @@ int Application::sendNackPackets() { if (node->getActiveSocket() && ( node->getType() == NodeType::VoxelServer - || node->getType() == NodeType::ParticleServer || node->getType() == NodeType::EntityServer) ) { @@ -2729,11 +2693,6 @@ void Application::updateShadowMap() { _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE); } - { - PerformanceTimer perfTimer("particles"); - _particles.render(OctreeRenderer::SHADOW_RENDER_MODE); - } - { PerformanceTimer perfTimer("entities"); _entities.render(OctreeRenderer::SHADOW_RENDER_MODE); @@ -2926,14 +2885,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { _metavoxels.render(); } - // render particles... - if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) { - PerformanceTimer perfTimer("particles"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... particles..."); - _particles.render(); - } - // render models... if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) { PerformanceTimer perfTimer("entities"); @@ -3504,13 +3455,6 @@ void Application::domainChanged(const QString& domainHostname) { _octreeServerSceneStats.clear(); - _particleServerJurisdictions.lockForWrite(); - _particleServerJurisdictions.clear(); - _particleServerJurisdictions.unlock(); - - // reset the particle renderer - _particles.clear(); - // reset the model renderer _entities.clear(); @@ -3550,7 +3494,6 @@ void Application::nodeKilled(SharedNodePointer node) { _octreeProcessor.nodeKilled(node); _voxelEditSender.nodeKilled(node); - _particleEditSender.nodeKilled(node); _entityEditSender.nodeKilled(node); if (node->getType() == NodeType::AudioMixer) { @@ -3594,43 +3537,6 @@ void Application::nodeKilled(SharedNodePointer node) { } _octreeSceneStatsLock.unlock(); - } else if (node->getType() == NodeType::ParticleServer) { - QUuid nodeUUID = node->getUUID(); - // see if this is the first we've heard of this node... - _particleServerJurisdictions.lockForRead(); - if (_particleServerJurisdictions.find(nodeUUID) != _particleServerJurisdictions.end()) { - unsigned char* rootCode = _particleServerJurisdictions[nodeUUID].getRootOctalCode(); - VoxelPositionSize rootDetails; - voxelDetailsForCode(rootCode, rootDetails); - _particleServerJurisdictions.unlock(); - - qDebug("particle 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 particle server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server - _particleServerJurisdictions.lockForWrite(); - _particleServerJurisdictions.erase(_particleServerJurisdictions.find(nodeUUID)); - } - _particleServerJurisdictions.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) { QUuid nodeUUID = node->getUUID(); @@ -3722,9 +3628,6 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin if (sendingNode->getType() == NodeType::VoxelServer) { jurisdiction = &_voxelServerJurisdictions; serverType = "Voxel"; - } else if (sendingNode->getType() == NodeType::ParticleServer) { - jurisdiction = &_particleServerJurisdictions; - serverType = "Particle"; } else { jurisdiction = &_entityServerJurisdictions; serverType = "Entity"; @@ -3850,9 +3753,6 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser scriptEngine->getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender); scriptEngine->getVoxelsScriptingInterface()->setVoxelTree(_voxels.getTree()); scriptEngine->getVoxelsScriptingInterface()->setUndoStack(&_undoStack); - scriptEngine->getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); - scriptEngine->getParticlesScriptingInterface()->setParticleTree(_particles.getTree()); - scriptEngine->getEntityScriptingInterface()->setPacketSender(&_entityEditSender); scriptEngine->getEntityScriptingInterface()->setEntityTree(_entities.getTree()); diff --git a/interface/src/Application.h b/interface/src/Application.h index ce9ed0c1a6..d69fae4010 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -35,8 +35,6 @@ #include #include #include -#include -#include #include #include #include @@ -65,7 +63,6 @@ #include "devices/Visage.h" #include "devices/DdeFaceTracker.h" #include "entities/EntityTreeRenderer.h" -#include "particles/ParticleTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" #include "renderer/GeometryCache.h" @@ -198,7 +195,6 @@ public: VoxelSystem* getVoxels() { return &_voxels; } VoxelTree* getVoxelTree() { return _voxels.getTree(); } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } - ParticleTreeRenderer* getParticles() { return &_particles; } MetavoxelSystem* getMetavoxels() { return &_metavoxels; } EntityTreeRenderer* getEntities() { return &_entities; } bool getImportSucceded() { return _importSucceded; } @@ -288,7 +284,6 @@ public: glm::vec2 getViewportDimensions() const { return glm::vec2(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } NodeToJurisdictionMap& getVoxelServerJurisdictions() { return _voxelServerJurisdictions; } - NodeToJurisdictionMap& getParticleServerJurisdictions() { return _particleServerJurisdictions; } NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } void pasteVoxelsToOctalCode(const unsigned char* octalCodeDestination); @@ -477,9 +472,6 @@ private: VoxelSystem _sharedVoxelSystem; ViewFrustum _sharedVoxelSystemViewFrustum; - ParticleTreeRenderer _particles; - ParticleCollisionSystem _particleCollisionSystem; - EntityTreeRenderer _entities; EntityCollisionSystem _entityCollisionSystem; EntityTreeRenderer _entityClipboardRenderer; @@ -491,7 +483,7 @@ private: MetavoxelSystem _metavoxels; ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. - ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels, particles) + ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) ViewFrustum _displayViewFrustum; ViewFrustum _shadowViewFrustum; quint64 _lastQueriedTime; @@ -569,7 +561,6 @@ private: OctreePacketProcessor _octreeProcessor; VoxelHideShowThread _voxelHideShowThread; VoxelEditPacketSender _voxelEditSender; - ParticleEditPacketSender _particleEditSender; EntityEditPacketSender _entityEditSender; int _packetsPerSecond; @@ -582,7 +573,6 @@ private: void trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket); NodeToJurisdictionMap _voxelServerJurisdictions; - NodeToJurisdictionMap _particleServerJurisdictions; NodeToJurisdictionMap _entityServerJurisdictions; NodeToOctreeSceneStats _octreeServerSceneStats; QReadWriteLock _octreeSceneStatsLock; diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 0889007c76..93b9e56535 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -70,18 +70,11 @@ void DatagramProcessor::processDatagrams() { break; } - case PacketTypeParticleAddResponse: - // this will keep creatorTokenIDs to IDs mapped correctly - Particle::handleAddParticleResponse(incomingPacket); - application->getParticles()->getTree()->handleAddParticleResponse(incomingPacket); - break; case PacketTypeEntityAddResponse: // this will keep creatorTokenIDs to IDs mapped correctly EntityItemID::handleAddEntityResponse(incomingPacket); application->getEntities()->getTree()->handleAddEntityResponse(incomingPacket); break; - case PacketTypeParticleData: - case PacketTypeParticleErase: case PacketTypeEntityData: case PacketTypeEntityErase: case PacketTypeVoxelData: @@ -167,11 +160,6 @@ void DatagramProcessor::processDatagrams() { application->_voxelEditSender.processNackPacket(incomingPacket); } break; - case PacketTypeParticleEditNack: - if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) { - application->_particleEditSender.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 77009da18b..32b2622fa5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -291,8 +291,6 @@ Menu::Menu() : 0, true, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithVoxels, 0, false, avatar, SLOT(updateCollisionGroups())); - addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithParticles, - 0, true, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithEnvironment, 0, false, avatar, SLOT(updateCollisionGroups())); @@ -339,9 +337,6 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersEntityNodes, Qt::CTRL | Qt::SHIFT | Qt::Key_2, false, &nodeBounds, SLOT(setShowEntityNodes(bool))); - addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersParticleNodes, - Qt::CTRL | Qt::SHIFT | Qt::Key_3, false, - &nodeBounds, SLOT(setShowParticleNodes(bool))); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::OffAxisProjection, 0, false); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false); @@ -363,7 +358,6 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Avatars, 0, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Models, 0, true); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Particles, 0, true); QMenu* shadowMenu = renderOptionsMenu->addMenu("Shadows"); QActionGroup* shadowGroup = new QActionGroup(shadowMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 67a4163c67..4c505ab4cf 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -361,7 +361,6 @@ 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 CollideWithParticles = "Collide With Particles"; const QString CollideWithVoxels = "Collide With Voxels"; const QString Collisions = "Collisions"; const QString Console = "Console..."; @@ -426,11 +425,10 @@ namespace MenuOption { const QString NameLocation = "Name this location"; const QString NewVoxelCullingMode = "New Voxel Culling Mode"; const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity"; - const QString OctreeStats = "Voxel and Particle Statistics"; + const QString OctreeStats = "Voxel and Entity Statistics"; const QString OffAxisProjection = "Off-Axis Projection"; const QString OldVoxelCullingMode = "Old Voxel Culling Mode"; const QString Pair = "Pair"; - const QString Particles = "Particles"; const QString PasteToVoxel = "Paste to Voxel..."; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "Preferences..."; @@ -449,7 +447,6 @@ namespace MenuOption { const QString SettingsExport = "Export Settings"; const QString SettingsImport = "Import Settings"; const QString ShowBordersEntityNodes = "Show Entity Nodes"; - const QString ShowBordersParticleNodes = "Show Particle Nodes"; const QString ShowBordersVoxelNodes = "Show Voxel Nodes"; const QString ShowIKConstraints = "Show IK Constraints"; const QString SimpleShadows = "Simple"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0477f6e04e..9f809defc8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1003,9 +1003,6 @@ void Avatar::updateCollisionGroups() { if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) { _collisionGroups |= COLLISION_GROUP_VOXELS; } - if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithParticles)) { - _collisionGroups |= COLLISION_GROUP_PARTICLES; - } } void Avatar::setScale(float scale) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 36035880fd..9c7df58a96 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1970,7 +1970,6 @@ void MyAvatar::setCollisionGroups(quint32 collisionGroups) { 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)); - menu->setIsOptionChecked(MenuOption::CollideWithParticles, (bool)(_collisionGroups & COLLISION_GROUP_PARTICLES)); 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/particles/ParticleTreeRenderer.cpp b/interface/src/particles/ParticleTreeRenderer.cpp deleted file mode 100644 index 4d47adedf0..0000000000 --- a/interface/src/particles/ParticleTreeRenderer.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// -// ParticleTreeRenderer.cpp -// interface/src -// -// Created by Brad Hefta-Gaub on 12/6/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 "Application.h" -#include "InterfaceConfig.h" - -#include "ParticleTreeRenderer.h" - -ParticleTreeRenderer::ParticleTreeRenderer() : - OctreeRenderer() { -} - -ParticleTreeRenderer::~ParticleTreeRenderer() { - // delete the models in _particleModels - foreach(Model* model, _particleModels) { - delete model; - } - _particleModels.clear(); -} - -void ParticleTreeRenderer::init() { - OctreeRenderer::init(); -} - - -void ParticleTreeRenderer::update() { - if (_tree) { - ParticleTree* tree = static_cast(_tree); - tree->update(); - } -} - -void ParticleTreeRenderer::render(RenderMode renderMode) { - OctreeRenderer::render(renderMode); -} - -Model* ParticleTreeRenderer::getModel(const QString& url) { - Model* model = NULL; - - // if we don't already have this model then create it and initialize it - if (_particleModels.find(url) == _particleModels.end()) { - model = new Model(); - model->init(); - model->setURL(QUrl(url)); - _particleModels[url] = model; - } else { - model = _particleModels[url]; - } - return model; -} - -void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) { - // actually render it here... - // we need to iterate the actual particles of the element - ParticleTreeElement* particleTreeElement = (ParticleTreeElement*)element; - - const QList& particles = particleTreeElement->getParticles(); - - uint16_t numberOfParticles = particles.size(); - - for (uint16_t i = 0; i < numberOfParticles; i++) { - const Particle& particle = particles[i]; - // render particle aspoints - glm::vec3 position = particle.getPosition() * (float)TREE_SCALE; - glColor3ub(particle.getColor()[RED_INDEX],particle.getColor()[GREEN_INDEX],particle.getColor()[BLUE_INDEX]); - float radius = particle.getRadius() * (float)TREE_SCALE; - - bool drawAsModel = particle.hasModel(); - - args->_itemsRendered++; - - if (drawAsModel) { - glPushMatrix(); - const float alpha = 1.0f; - - Model* model = getModel(particle.getModelURL()); - glm::vec3 translationAdjustment = particle.getModelTranslation() * radius; - - // set the position - glm::vec3 translation = position + translationAdjustment; - model->setTranslation(translation); - - // set the rotation - glm::quat rotation = particle.getModelRotation(); - model->setRotation(rotation); - - // scale - // 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); - - float modelScale = particle.getModelScale(); - model->setScale(scale * MODEL_SCALE * radius * modelScale); - - model->simulate(0.0f); - - // TODO: should we allow particles to have alpha on their models? - Model::RenderMode modelRenderMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE - ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; - model->render(alpha, modelRenderMode); - - const bool wantDebugSphere = false; - if (wantDebugSphere) { - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(radius, 15, 15); - glPopMatrix(); - } - - glPopMatrix(); - } else { - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(radius, 15, 15); - glPopMatrix(); - } - } -} - -void ParticleTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { - if (_tree){ - _tree->lockForWrite(); - static_cast(_tree)->processEraseMessage(dataByteArray, sourceNode); - _tree->unlock(); - } -} diff --git a/interface/src/particles/ParticleTreeRenderer.h b/interface/src/particles/ParticleTreeRenderer.h deleted file mode 100644 index ccb8bfbdf3..0000000000 --- a/interface/src/particles/ParticleTreeRenderer.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// ParticleTreeRenderer.h -// interface/src -// -// Created by Brad Hefta-Gaub on 12/6/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_ParticleTreeRenderer_h -#define hifi_ParticleTreeRenderer_h - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "renderer/Model.h" - -// Generic client side Octree renderer class. -class ParticleTreeRenderer : public OctreeRenderer { -public: - ParticleTreeRenderer(); - virtual ~ParticleTreeRenderer(); - - virtual Octree* createTree() { return new ParticleTree(true); } - virtual char getMyNodeType() const { return NodeType::ParticleServer; } - virtual PacketType getMyQueryMessageType() const { return PacketTypeParticleQuery; } - virtual PacketType getExpectedPacketType() const { return PacketTypeParticleData; } - virtual void renderElement(OctreeElement* element, RenderArgs* args); - - void update(); - - ParticleTree* getTree() { return (ParticleTree*)_tree; } - - void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); - - virtual void init(); - virtual void render(RenderMode renderMode = DEFAULT_RENDER_MODE); - -protected: - Model* getModel(const QString& url); - - QMap _particleModels; -}; - -#endif // hifi_ParticleTreeRenderer_h diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index e3bd3a5cc3..49509cc9cf 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, and Particle nodes on the current domain, +// This class draws a border around the different Voxel, 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,20 +21,18 @@ NodeBounds::NodeBounds(QObject* parent) : QObject(parent), _showVoxelNodes(false), _showEntityNodes(false), - _showParticleNodes(false), _overlayText() { } void NodeBounds::draw() { - if (!(_showVoxelNodes || _showEntityNodes || _showParticleNodes)) { + if (!(_showVoxelNodes || _showEntityNodes)) { _overlayText[0] = '\0'; return; } NodeToJurisdictionMap& voxelServerJurisdictions = Application::getInstance()->getVoxelServerJurisdictions(); NodeToJurisdictionMap& entityServerJurisdictions = Application::getInstance()->getEntityServerJurisdictions(); - NodeToJurisdictionMap& particleServerJurisdictions = Application::getInstance()->getParticleServerJurisdictions(); NodeToJurisdictionMap* serverJurisdictions; // Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers @@ -63,8 +61,6 @@ void NodeBounds::draw() { serverJurisdictions = &voxelServerJurisdictions; } else if (nodeType == NodeType::EntityServer && _showEntityNodes) { serverJurisdictions = &entityServerJurisdictions; - } else if (nodeType == NodeType::ParticleServer && _showParticleNodes) { - serverJurisdictions = &particleServerJurisdictions; } else { continue; } @@ -90,7 +86,6 @@ void NodeBounds::draw() { const float VOXEL_NODE_SCALE = 1.00f; const float ENTITY_NODE_SCALE = 0.99f; - const float PARTICLE_NODE_SCALE = 0.98f; float scaleFactor = rootDetails.s * TREE_SCALE; @@ -103,8 +98,6 @@ void NodeBounds::draw() { scaleFactor *= VOXEL_NODE_SCALE; } else if (nodeType == NodeType::EntityServer) { scaleFactor *= ENTITY_NODE_SCALE; - } else { - scaleFactor *= PARTICLE_NODE_SCALE; } float red, green, blue; @@ -215,7 +208,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; - green = nodeType == NodeType::ParticleServer ? 1.0 : 0.0; + green = 0.0; blue = nodeType == NodeType::EntityServer ? 1.0 : 0.0; } diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index ffdcab3050..e51b9b1f42 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -229,9 +229,6 @@ void OctreeStatsDialog::showAllOctreeServers() { showOctreeServersOfType(serverCount, NodeType::VoxelServer, "Voxel", Application::getInstance()->getVoxelServerJurisdictions()); - showOctreeServersOfType(serverCount, NodeType::ParticleServer, "Particle", - Application::getInstance()->getParticleServerJurisdictions()); - showOctreeServersOfType(serverCount, NodeType::EntityServer, "Entity", Application::getInstance()->getEntityServerJurisdictions()); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index dd9ac67837..476e45cea9 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -268,7 +268,7 @@ void Stats::display( int voxelServerCount = 0; foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { - // TODO: this should also support particles and models + // TODO: this should also support entities if (node->getType() == NodeType::VoxelServer) { totalPingVoxel += node->getPingMs(); voxelServerCount++; diff --git a/interface/src/voxels/OctreePacketProcessor.cpp b/interface/src/voxels/OctreePacketProcessor.cpp index ce0d76322e..b3cf012869 100644 --- a/interface/src/voxels/OctreePacketProcessor.cpp +++ b/interface/src/voxels/OctreePacketProcessor.cpp @@ -85,18 +85,6 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode, if (sendingNode) { switch(voxelPacketType) { - case PacketTypeParticleErase: { - if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) { - app->_particles.processEraseMessage(mutablePacket, sendingNode); - } - } break; - - case PacketTypeParticleData: { - if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) { - app->_particles.processDatagram(mutablePacket, sendingNode); - } - } break; - case PacketTypeEntityErase: { if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) { app->_entities.processEraseMessage(mutablePacket, sendingNode); diff --git a/libraries/networking/src/Assignment.cpp b/libraries/networking/src/Assignment.cpp index 93dcd5e226..45dfe186e3 100644 --- a/libraries/networking/src/Assignment.cpp +++ b/libraries/networking/src/Assignment.cpp @@ -27,8 +27,6 @@ Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) { return Assignment::AgentType; case NodeType::VoxelServer: return Assignment::VoxelServerType; - case NodeType::ParticleServer: - return Assignment::ParticleServerType; case NodeType::EntityServer: return Assignment::EntityServerType; case NodeType::MetavoxelServer: @@ -137,8 +135,6 @@ const char* Assignment::getTypeName() const { return "agent"; case Assignment::VoxelServerType: return "voxel-server"; - case Assignment::ParticleServerType: - return "particle-server"; case Assignment::MetavoxelServerType: return "metavoxel-server"; default: diff --git a/libraries/networking/src/Assignment.h b/libraries/networking/src/Assignment.h index 2276fdf873..1f6b5b9bd6 100644 --- a/libraries/networking/src/Assignment.h +++ b/libraries/networking/src/Assignment.h @@ -30,7 +30,7 @@ public: AvatarMixerType, AgentType, VoxelServerType, - ParticleServerType, + UNUSED, MetavoxelServerType, EntityServerType, AllTypes diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 20461cb754..c2b35d3b7d 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -29,7 +29,6 @@ namespace NodeType { void NodeType::init() { TypeNameHash.insert(NodeType::DomainServer, "Domain Server"); TypeNameHash.insert(NodeType::VoxelServer, "Voxel Server"); - TypeNameHash.insert(NodeType::ParticleServer, "Particle Server"); TypeNameHash.insert(NodeType::EntityServer, "Entity Server"); TypeNameHash.insert(NodeType::MetavoxelServer, "Metavoxel Server"); TypeNameHash.insert(NodeType::Agent, "Agent"); diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 994ddd3bec..acb6c6f453 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -31,7 +31,6 @@ typedef quint8 NodeType_t; namespace NodeType { const NodeType_t DomainServer = 'D'; const NodeType_t VoxelServer = 'V'; - const NodeType_t ParticleServer = 'P'; const NodeType_t EntityServer = 'o'; // was ModelServer const NodeType_t MetavoxelServer = 'm'; const NodeType_t EnvironmentServer = 'E'; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index eddd63ca7a..6cb0809234 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -71,10 +71,6 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeOctreeStats: return 1; - case PacketTypeParticleData: - return 1; - case PacketTypeParticleErase: - return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: @@ -126,11 +122,6 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeStats); PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdiction); PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdictionRequest); - PACKET_TYPE_NAME_LOOKUP(PacketTypeParticleQuery); - PACKET_TYPE_NAME_LOOKUP(PacketTypeParticleData); - PACKET_TYPE_NAME_LOOKUP(PacketTypeParticleAddOrEdit); - PACKET_TYPE_NAME_LOOKUP(PacketTypeParticleErase); - PACKET_TYPE_NAME_LOOKUP(PacketTypeParticleAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeMetavoxelData); PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarIdentity); PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarBillboard); @@ -144,7 +135,6 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeVoxelEditNack); - PACKET_TYPE_NAME_LOOKUP(PacketTypeParticleEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); default: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 2d298d253d..e83c543e1d 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -50,11 +50,11 @@ enum PacketType { PacketTypeOctreeStats, // 26 PacketTypeJurisdiction, PacketTypeJurisdictionRequest, - PacketTypeParticleQuery, - PacketTypeParticleData, - PacketTypeParticleAddOrEdit, - PacketTypeParticleErase, - PacketTypeParticleAddResponse, + UNUSED_1, + UNUSED_2, + UNUSED_3, + UNUSED_4, + UNUSED_5, PacketTypeMetavoxelData, PacketTypeAvatarIdentity, PacketTypeAvatarBillboard, @@ -68,7 +68,7 @@ enum PacketType { PacketTypeEntityAddResponse, PacketTypeOctreeDataNack, // 45 PacketTypeVoxelEditNack, - PacketTypeParticleEditNack, + UNUSED_6, PacketTypeEntityEditNack, // 48 PacketTypeSignedTransactionPayment, PacketTypeIceServerHeartbeat, @@ -83,8 +83,8 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest << PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainOAuthRequest << PacketTypeCreateAssignment << PacketTypeRequestAssignment << PacketTypeStunResponse - << PacketTypeNodeJsonStats << PacketTypeVoxelQuery << PacketTypeParticleQuery << PacketTypeEntityQuery - << PacketTypeOctreeDataNack << PacketTypeVoxelEditNack << PacketTypeParticleEditNack << PacketTypeEntityEditNack + << PacketTypeNodeJsonStats << PacketTypeVoxelQuery << PacketTypeEntityQuery + << PacketTypeOctreeDataNack << PacketTypeVoxelEditNack << PacketTypeEntityEditNack << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; diff --git a/libraries/particles/CMakeLists.txt b/libraries/particles/CMakeLists.txt deleted file mode 100644 index 27fc816530..0000000000 --- a/libraries/particles/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(TARGET_NAME particles) - -# use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Gui Network Script) - -include_glm() - -link_hifi_libraries(shared octree fbx networking animation) -include_hifi_library_headers(script-engine) - -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() \ No newline at end of file diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp deleted file mode 100644 index c7a94985cf..0000000000 --- a/libraries/particles/src/Particle.cpp +++ /dev/null @@ -1,1521 +0,0 @@ -// -// Particle.cpp -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/4/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 -#include - - -// This is not ideal, but adding script-engine as a linked library, will cause a circular reference -// I'm open to other potential solutions. Could we change cmake to allow libraries to reference each others -// headers, but not link to each other, this is essentially what this construct is doing, but would be -// better to add includes to the include path, but not link -#include - -#include "ParticlesScriptingInterface.h" -#include "Particle.h" -#include "ParticleTree.h" - -uint32_t Particle::_nextID = 0; -VoxelEditPacketSender* Particle::_voxelEditSender = NULL; -ParticleEditPacketSender* Particle::_particleEditSender = NULL; - -// for locally created particles -std::map Particle::_tokenIDsToIDs; -uint32_t Particle::_nextCreatorTokenID = 0; - -uint32_t Particle::getIDfromCreatorTokenID(uint32_t creatorTokenID) { - if (_tokenIDsToIDs.find(creatorTokenID) != _tokenIDsToIDs.end()) { - return _tokenIDsToIDs[creatorTokenID]; - } - return UNKNOWN_PARTICLE_ID; -} - -uint32_t Particle::getNextCreatorTokenID() { - uint32_t creatorTokenID = _nextCreatorTokenID; - _nextCreatorTokenID++; - return creatorTokenID; -} - -void Particle::handleAddParticleResponse(const QByteArray& packet) { - const unsigned char* dataAt = reinterpret_cast(packet.data()); - int numBytesPacketHeader = numBytesForPacketHeader(packet); - dataAt += numBytesPacketHeader; - - uint32_t creatorTokenID; - memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID)); - dataAt += sizeof(creatorTokenID); - - uint32_t particleID; - memcpy(&particleID, dataAt, sizeof(particleID)); - dataAt += sizeof(particleID); - - // add our token to id mapping - _tokenIDsToIDs[creatorTokenID] = particleID; -} - -Particle::Particle() { - rgbColor noColor = { 0, 0, 0 }; - init(glm::vec3(0,0,0), 0, noColor, glm::vec3(0,0,0), - DEFAULT_GRAVITY, DEFAULT_DAMPING, DEFAULT_LIFETIME, NOT_IN_HAND, DEFAULT_SCRIPT, NEW_PARTICLE); -} - -Particle::Particle(const ParticleID& particleID, const ParticleProperties& properties) { - _id = particleID.id; - _creatorTokenID = particleID.creatorTokenID; - - // init values with defaults before calling setProperties - uint64_t now = usecTimestampNow(); - _lastEdited = now; - _lastUpdated = now; - _created = now; // will get updated as appropriate in setAge() - - _position = glm::vec3(0,0,0); - _radius = 0; - _mass = 1.0f; - rgbColor noColor = { 0, 0, 0 }; - memcpy(_color, noColor, sizeof(_color)); - _velocity = glm::vec3(0,0,0); - _damping = DEFAULT_DAMPING; - _lifetime = DEFAULT_LIFETIME; - _gravity = DEFAULT_GRAVITY; - _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); -} - - -Particle::~Particle() { -} - -void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity, - float damping, float lifetime, bool inHand, QString updateScript, uint32_t id) { - if (id == NEW_PARTICLE) { - _id = _nextID; - _nextID++; - } else { - _id = id; - } - quint64 now = usecTimestampNow(); - _lastEdited = now; - _lastUpdated = now; - _created = now; // will get updated as appropriate in setAge() - - _position = position; - _radius = radius; - _mass = 1.0f; - memcpy(_color, color, sizeof(_color)); - _velocity = velocity; - _damping = damping; - _lifetime = lifetime; - _gravity = gravity; - _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) { - if (value > 0.0f) { - _mass = value; - } -} - -bool Particle::appendParticleData(OctreePacketData* packetData) const { - - bool success = packetData->appendValue(getID()); - - //qDebug("Particle::appendParticleData()... getID()=%d", getID()); - - if (success) { - success = packetData->appendValue(getAge()); - } - if (success) { - success = packetData->appendValue(getLastUpdated()); - } - if (success) { - success = packetData->appendValue(getLastEdited()); - } - if (success) { - success = packetData->appendValue(getRadius()); - } - if (success) { - success = packetData->appendPosition(getPosition()); - } - if (success) { - success = packetData->appendColor(getColor()); - } - if (success) { - success = packetData->appendValue(getVelocity()); - } - if (success) { - success = packetData->appendValue(getGravity()); - } - if (success) { - success = packetData->appendValue(getDamping()); - } - if (success) { - success = packetData->appendValue(getLifetime()); - } - if (success) { - success = packetData->appendValue(getInHand()); - } - if (success) { - success = packetData->appendValue(getShouldDie()); - } - if (success) { - uint16_t scriptLength = _script.size() + 1; // include NULL - success = packetData->appendValue(scriptLength); - if (success) { - success = packetData->appendRawData((const unsigned char*)qPrintable(_script), scriptLength); - } - } - - // modelURL - if (success) { - uint16_t modelURLLength = _modelURL.size() + 1; // include NULL - success = packetData->appendValue(modelURLLength); - if (success) { - success = packetData->appendRawData((const unsigned char*)qPrintable(_modelURL), modelURLLength); - } - } - - // modelScale - if (success) { - success = packetData->appendValue(getModelScale()); - } - - // modelTranslation - if (success) { - success = packetData->appendValue(getModelTranslation()); - } - // modelRotation - if (success) { - success = packetData->appendValue(getModelRotation()); - } - return success; -} - -int Particle::expectedBytes() { - int expectedBytes = sizeof(uint32_t) // id - + sizeof(float) // age - + sizeof(quint64) // last updated - + sizeof(quint64) // lasted edited - + sizeof(float) // radius - + sizeof(glm::vec3) // position - + sizeof(rgbColor) // color - + sizeof(glm::vec3) // velocity - + sizeof(glm::vec3) // gravity - + sizeof(float) // damping - + sizeof(float) // lifetime - + sizeof(bool); // inhand - // potentially more... - return expectedBytes; -} - -int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { - int bytesRead = 0; - if (bytesLeftToRead >= expectedBytes()) { - int clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0; - - const unsigned char* dataAt = data; - - // id - memcpy(&_id, dataAt, sizeof(_id)); - dataAt += sizeof(_id); - bytesRead += sizeof(_id); - - // age - float age; - memcpy(&age, dataAt, sizeof(age)); - dataAt += sizeof(age); - bytesRead += sizeof(age); - setAge(age); - - // _lastUpdated - memcpy(&_lastUpdated, dataAt, sizeof(_lastUpdated)); - dataAt += sizeof(_lastUpdated); - bytesRead += sizeof(_lastUpdated); - _lastUpdated -= clockSkew; - - // _lastEdited - memcpy(&_lastEdited, dataAt, sizeof(_lastEdited)); - dataAt += sizeof(_lastEdited); - bytesRead += sizeof(_lastEdited); - _lastEdited -= clockSkew; - - // radius - memcpy(&_radius, dataAt, sizeof(_radius)); - dataAt += sizeof(_radius); - bytesRead += sizeof(_radius); - - // position - memcpy(&_position, dataAt, sizeof(_position)); - dataAt += sizeof(_position); - bytesRead += sizeof(_position); - - // color - memcpy(_color, dataAt, sizeof(_color)); - dataAt += sizeof(_color); - bytesRead += sizeof(_color); - - // velocity - memcpy(&_velocity, dataAt, sizeof(_velocity)); - dataAt += sizeof(_velocity); - bytesRead += sizeof(_velocity); - - // gravity - memcpy(&_gravity, dataAt, sizeof(_gravity)); - dataAt += sizeof(_gravity); - bytesRead += sizeof(_gravity); - - // damping - memcpy(&_damping, dataAt, sizeof(_damping)); - dataAt += sizeof(_damping); - bytesRead += sizeof(_damping); - - // lifetime - memcpy(&_lifetime, dataAt, sizeof(_lifetime)); - dataAt += sizeof(_lifetime); - bytesRead += sizeof(_lifetime); - - // inHand - memcpy(&_inHand, dataAt, sizeof(_inHand)); - dataAt += sizeof(_inHand); - bytesRead += sizeof(_inHand); - - // shouldDie - memcpy(&_shouldDie, dataAt, sizeof(_shouldDie)); - dataAt += sizeof(_shouldDie); - bytesRead += sizeof(_shouldDie); - - // script - uint16_t scriptLength; - memcpy(&scriptLength, dataAt, sizeof(scriptLength)); - dataAt += sizeof(scriptLength); - bytesRead += sizeof(scriptLength); - QString tempString((const char*)dataAt); - _script = tempString; - dataAt += scriptLength; - bytesRead += scriptLength; - - // modelURL - uint16_t modelURLLength; - memcpy(&modelURLLength, dataAt, sizeof(modelURLLength)); - dataAt += sizeof(modelURLLength); - bytesRead += sizeof(modelURLLength); - QString modelURLString((const char*)dataAt); - _modelURL = modelURLString; - 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); - bytesRead += sizeof(_modelTranslation); - - // modelRotation - int bytes = unpackOrientationQuatFromBytes(dataAt, _modelRotation); - dataAt += bytes; - bytesRead += bytes; - - //printf("Particle::readParticleDataFromBuffer()... "); debugDump(); - } - return bytesRead; -} - -Particle Particle::fromEditPacket(const unsigned char* data, int length, int& processedBytes, ParticleTree* tree, bool& valid) { - - Particle newParticle; // id and _lastUpdated will get set here... - const unsigned char* dataAt = data; - processedBytes = 0; - - // the first part of the data is our octcode... - int octets = numberOfThreeBitSectionsInCode(data, length); - int lengthOfOctcode = bytesRequiredForCodeLength(octets); - - // we don't actually do anything with this octcode... - dataAt += lengthOfOctcode; - processedBytes += lengthOfOctcode; - - // id - uint32_t editID; - - // check to make sure we have enough content to keep reading... - if (length - (processedBytes + (int)sizeof(editID)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - - memcpy(&editID, dataAt, sizeof(editID)); - dataAt += sizeof(editID); - processedBytes += sizeof(editID); - - bool isNewParticle = (editID == NEW_PARTICLE); - - // special case for handling "new" particles - if (isNewParticle) { - // If this is a NEW_PARTICLE, then we assume that there's an additional uint32_t creatorToken, that - // we want to send back to the creator as an map to the actual id - uint32_t creatorTokenID; - - // check to make sure we have enough content to keep reading... - if (length - (processedBytes + (int)sizeof(creatorTokenID)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - - memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID)); - dataAt += sizeof(creatorTokenID); - processedBytes += sizeof(creatorTokenID); - - newParticle.setCreatorTokenID(creatorTokenID); - newParticle._newlyCreated = true; - newParticle.setAge(0); // this guy is new! - - valid = true; - - } else { - // look up the existing particle - const Particle* existingParticle = tree->findParticleByID(editID, true); - - // copy existing properties before over-writing with new properties - if (existingParticle) { - newParticle = *existingParticle; - valid = true; - - } else { - // the user attempted to edit a particle that doesn't exist - qDebug() << "user attempted to edit a particle that doesn't exist... editID=" << editID; - - // NOTE: even though this is a bad particle ID, we have to consume the edit details, so that - // the buffer doesn't get corrupted for further processing... - valid = false; - } - newParticle._id = editID; - newParticle._newlyCreated = false; - } - - // lastEdited - // check to make sure we have enough content to keep reading... - if (length - (processedBytes + (int)sizeof(newParticle._lastEdited)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited)); - dataAt += sizeof(newParticle._lastEdited); - processedBytes += sizeof(newParticle._lastEdited); - - // All of the remaining items are optional, and may or may not be included based on their included values in the - // properties included bits - uint16_t packetContainsBits = 0; - if (!isNewParticle) { - if (length - (processedBytes + (int)sizeof(packetContainsBits)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&packetContainsBits, dataAt, sizeof(packetContainsBits)); - dataAt += sizeof(packetContainsBits); - processedBytes += sizeof(packetContainsBits); - } - - - // radius - if (isNewParticle || ((packetContainsBits & CONTAINS_RADIUS) == CONTAINS_RADIUS)) { - if (length - (processedBytes + (int)sizeof(newParticle._radius)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius)); - dataAt += sizeof(newParticle._radius); - processedBytes += sizeof(newParticle._radius); - } - - // position - if (isNewParticle || ((packetContainsBits & CONTAINS_POSITION) == CONTAINS_POSITION)) { - if (length - (processedBytes + (int)sizeof(newParticle._position)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._position, dataAt, sizeof(newParticle._position)); - dataAt += sizeof(newParticle._position); - processedBytes += sizeof(newParticle._position); - } - - // color - if (isNewParticle || ((packetContainsBits & CONTAINS_COLOR) == CONTAINS_COLOR)) { - if (length - (processedBytes + (int)sizeof(newParticle._color)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(newParticle._color, dataAt, sizeof(newParticle._color)); - dataAt += sizeof(newParticle._color); - processedBytes += sizeof(newParticle._color); - } - - // velocity - if (isNewParticle || ((packetContainsBits & CONTAINS_VELOCITY) == CONTAINS_VELOCITY)) { - if (length - (processedBytes + (int)sizeof(newParticle._velocity)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._velocity, dataAt, sizeof(newParticle._velocity)); - dataAt += sizeof(newParticle._velocity); - processedBytes += sizeof(newParticle._velocity); - } - - // gravity - if (isNewParticle || ((packetContainsBits & CONTAINS_GRAVITY) == CONTAINS_GRAVITY)) { - if (length - (processedBytes + (int)sizeof(newParticle._gravity)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._gravity, dataAt, sizeof(newParticle._gravity)); - dataAt += sizeof(newParticle._gravity); - processedBytes += sizeof(newParticle._gravity); - } - - // damping - if (isNewParticle || ((packetContainsBits & CONTAINS_DAMPING) == CONTAINS_DAMPING)) { - if (length - (processedBytes + (int)sizeof(newParticle._damping)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._damping, dataAt, sizeof(newParticle._damping)); - dataAt += sizeof(newParticle._damping); - processedBytes += sizeof(newParticle._damping); - } - - // lifetime - if (isNewParticle || ((packetContainsBits & CONTAINS_LIFETIME) == CONTAINS_LIFETIME)) { - if (length - (processedBytes + (int)sizeof(newParticle._lifetime)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._lifetime, dataAt, sizeof(newParticle._lifetime)); - dataAt += sizeof(newParticle._lifetime); - processedBytes += sizeof(newParticle._lifetime); - } - - // TODO: make inHand and shouldDie into single bits - // inHand - if (isNewParticle || ((packetContainsBits & CONTAINS_INHAND) == CONTAINS_INHAND)) { - if (length - (processedBytes + (int)sizeof(newParticle._inHand)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._inHand, dataAt, sizeof(newParticle._inHand)); - dataAt += sizeof(newParticle._inHand); - processedBytes += sizeof(newParticle._inHand); - } - - // shouldDie - if (isNewParticle || ((packetContainsBits & CONTAINS_SHOULDDIE) == CONTAINS_SHOULDDIE)) { - if (length - (processedBytes + (int)sizeof(newParticle._shouldDie)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._shouldDie, dataAt, sizeof(newParticle._shouldDie)); - dataAt += sizeof(newParticle._shouldDie); - processedBytes += sizeof(newParticle._shouldDie); - } - - // script - if (isNewParticle || ((packetContainsBits & CONTAINS_SCRIPT) == CONTAINS_SCRIPT)) { - uint16_t scriptLength; - if (length - (processedBytes + (int)sizeof(scriptLength)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&scriptLength, dataAt, sizeof(scriptLength)); - dataAt += sizeof(scriptLength); - processedBytes += sizeof(scriptLength); - - if (length - (processedBytes + (int)scriptLength) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - QString tempString((const char*)dataAt); - newParticle._script = tempString; - dataAt += scriptLength; - processedBytes += scriptLength; - } - - // modelURL - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_URL) == CONTAINS_MODEL_URL)) { - uint16_t modelURLLength; - if (length - (processedBytes + (int)sizeof(modelURLLength)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&modelURLLength, dataAt, sizeof(modelURLLength)); - dataAt += sizeof(modelURLLength); - processedBytes += sizeof(modelURLLength); - - if (length - (processedBytes + (int)modelURLLength) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - QString tempString((const char*)dataAt); - newParticle._modelURL = tempString; - dataAt += modelURLLength; - processedBytes += modelURLLength; - } - - // modelScale - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { - if (length - (processedBytes + (int)sizeof(newParticle._modelScale)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - 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)) { - if (length - (processedBytes + (int)sizeof(newParticle._modelTranslation)) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - memcpy(&newParticle._modelTranslation, dataAt, sizeof(newParticle._modelTranslation)); - dataAt += sizeof(newParticle._modelTranslation); - processedBytes += sizeof(newParticle._modelTranslation); - } - - // modelRotation - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_ROTATION) == CONTAINS_MODEL_ROTATION)) { - const int expectedBytesForPackedQuat = sizeof(uint16_t) * 4; // this is how we pack the quats - if (length - (processedBytes + expectedBytesForPackedQuat) < 0) { - valid = false; - processedBytes = length; - return newParticle; // fail as if we read the entire buffer - } - int bytes = unpackOrientationQuatFromBytes(dataAt, newParticle._modelRotation); - dataAt += bytes; - processedBytes += bytes; - } - - const bool wantDebugging = false; - if (wantDebugging) { - qDebug("Particle::fromEditPacket()..."); - qDebug() << " Particle id in packet:" << editID; - newParticle.debugDump(); - } - - return newParticle; -} - -void Particle::debugDump() const { - qDebug("Particle id :%u", _id); - qDebug(" age:%f", getAge()); - qDebug(" edited ago:%f", getEditedAgo()); - qDebug(" should die:%s", debug::valueOf(getShouldDie())); - qDebug(" position:%f,%f,%f", _position.x, _position.y, _position.z); - qDebug(" radius:%f", getRadius()); - qDebug(" velocity:%f,%f,%f", _velocity.x, _velocity.y, _velocity.z); - qDebug(" gravity:%f,%f,%f", _gravity.x, _gravity.y, _gravity.z); - qDebug(" color:%d,%d,%d", _color[0], _color[1], _color[2]); -} - -bool Particle::encodeParticleEditMessageDetails(PacketType command, ParticleID id, const ParticleProperties& properties, - unsigned char* bufferOut, int sizeIn, int& sizeOut) { - - bool success = true; // assume the best - unsigned char* copyAt = bufferOut; - sizeOut = 0; - - // get the octal code for the particle - - // this could be a problem if the caller doesn't include position.... - glm::vec3 rootPosition(0); - float rootScale = 0.5f; - unsigned char* octcode = pointToOctalCode(rootPosition.x, rootPosition.y, rootPosition.z, rootScale); - - // TODO: Consider this old code... including the correct octree for where the particle will go matters for - // particle servers with different jurisdictions, but for now, we'll send everything to the root, since the - // tree does the right thing... - // - //unsigned char* octcode = pointToOctalCode(details[i].position.x, details[i].position.y, - // details[i].position.z, details[i].radius); - - int octets = numberOfThreeBitSectionsInCode(octcode); - int lengthOfOctcode = bytesRequiredForCodeLength(octets); - - // add it to our message - memcpy(copyAt, octcode, lengthOfOctcode); - copyAt += lengthOfOctcode; - sizeOut += lengthOfOctcode; - - // Now add our edit content details... - bool isNewParticle = (id.id == NEW_PARTICLE); - - // id - memcpy(copyAt, &id.id, sizeof(id.id)); - copyAt += sizeof(id.id); - sizeOut += sizeof(id.id); - - // special case for handling "new" particles - if (isNewParticle) { - // If this is a NEW_PARTICLE, then we assume that there's an additional uint32_t creatorToken, that - // we want to send back to the creator as an map to the actual id - memcpy(copyAt, &id.creatorTokenID, sizeof(id.creatorTokenID)); - copyAt += sizeof(id.creatorTokenID); - sizeOut += sizeof(id.creatorTokenID); - } - - // lastEdited - quint64 lastEdited = properties.getLastEdited(); - memcpy(copyAt, &lastEdited, sizeof(lastEdited)); - copyAt += sizeof(lastEdited); - sizeOut += sizeof(lastEdited); - - // For new particles, all remaining items are mandatory, for an edited particle, All of the remaining items are - // optional, and may or may not be included based on their included values in the properties included bits - uint16_t packetContainsBits = properties.getChangedBits(); - if (!isNewParticle) { - memcpy(copyAt, &packetContainsBits, sizeof(packetContainsBits)); - copyAt += sizeof(packetContainsBits); - sizeOut += sizeof(packetContainsBits); - } - - // radius - if (isNewParticle || ((packetContainsBits & CONTAINS_RADIUS) == CONTAINS_RADIUS)) { - float radius = properties.getRadius() / (float) TREE_SCALE; - memcpy(copyAt, &radius, sizeof(radius)); - copyAt += sizeof(radius); - sizeOut += sizeof(radius); - } - - // position - if (isNewParticle || ((packetContainsBits & CONTAINS_POSITION) == CONTAINS_POSITION)) { - glm::vec3 position = properties.getPosition() / (float)TREE_SCALE; - memcpy(copyAt, &position, sizeof(position)); - copyAt += sizeof(position); - sizeOut += sizeof(position); - } - - // color - if (isNewParticle || ((packetContainsBits & CONTAINS_COLOR) == CONTAINS_COLOR)) { - rgbColor color = { properties.getColor().red, properties.getColor().green, properties.getColor().blue }; - memcpy(copyAt, color, sizeof(color)); - copyAt += sizeof(color); - sizeOut += sizeof(color); - } - - // velocity - if (isNewParticle || ((packetContainsBits & CONTAINS_VELOCITY) == CONTAINS_VELOCITY)) { - glm::vec3 velocity = properties.getVelocity() / (float)TREE_SCALE; - memcpy(copyAt, &velocity, sizeof(velocity)); - copyAt += sizeof(velocity); - sizeOut += sizeof(velocity); - } - - // gravity - if (isNewParticle || ((packetContainsBits & CONTAINS_GRAVITY) == CONTAINS_GRAVITY)) { - glm::vec3 gravity = properties.getGravity() / (float)TREE_SCALE; - memcpy(copyAt, &gravity, sizeof(gravity)); - copyAt += sizeof(gravity); - sizeOut += sizeof(gravity); - } - - // damping - if (isNewParticle || ((packetContainsBits & CONTAINS_DAMPING) == CONTAINS_DAMPING)) { - float damping = properties.getDamping(); - memcpy(copyAt, &damping, sizeof(damping)); - copyAt += sizeof(damping); - sizeOut += sizeof(damping); - } - - // lifetime - if (isNewParticle || ((packetContainsBits & CONTAINS_LIFETIME) == CONTAINS_LIFETIME)) { - float lifetime = properties.getLifetime(); - memcpy(copyAt, &lifetime, sizeof(lifetime)); - copyAt += sizeof(lifetime); - sizeOut += sizeof(lifetime); - } - - // inHand - if (isNewParticle || ((packetContainsBits & CONTAINS_INHAND) == CONTAINS_INHAND)) { - bool inHand = properties.getInHand(); - memcpy(copyAt, &inHand, sizeof(inHand)); - copyAt += sizeof(inHand); - sizeOut += sizeof(inHand); - } - - // shoulDie - if (isNewParticle || ((packetContainsBits & CONTAINS_SHOULDDIE) == CONTAINS_SHOULDDIE)) { - bool shouldDie = properties.getShouldDie(); - memcpy(copyAt, &shouldDie, sizeof(shouldDie)); - copyAt += sizeof(shouldDie); - sizeOut += sizeof(shouldDie); - } - - // script - if (isNewParticle || ((packetContainsBits & CONTAINS_SCRIPT) == CONTAINS_SCRIPT)) { - uint16_t scriptLength = properties.getScript().size() + 1; - memcpy(copyAt, &scriptLength, sizeof(scriptLength)); - copyAt += sizeof(scriptLength); - sizeOut += sizeof(scriptLength); - memcpy(copyAt, qPrintable(properties.getScript()), scriptLength); - copyAt += scriptLength; - sizeOut += scriptLength; - } - - // modelURL - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_URL) == CONTAINS_MODEL_URL)) { - uint16_t urlLength = properties.getModelURL().size() + 1; - memcpy(copyAt, &urlLength, sizeof(urlLength)); - copyAt += sizeof(urlLength); - sizeOut += sizeof(urlLength); - memcpy(copyAt, qPrintable(properties.getModelURL()), urlLength); - copyAt += urlLength; - 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?? - memcpy(copyAt, &modelTranslation, sizeof(modelTranslation)); - copyAt += sizeof(modelTranslation); - sizeOut += sizeof(modelTranslation); - } - - // modelRotation - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_ROTATION) == CONTAINS_MODEL_ROTATION)) { - int bytes = packOrientationQuatToBytes(copyAt, properties.getModelRotation()); - copyAt += bytes; - sizeOut += bytes; - } - - bool wantDebugging = false; - if (wantDebugging) { - qDebug("encodeParticleEditMessageDetails()...."); - qDebug("Particle id :%u", id.id); - qDebug(" nextID:%u", _nextID); - } - - // cleanup - delete[] octcode; - - return success; -} - -// adjust any internal timestamps to fix clock skew for this server -void Particle::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew) { - unsigned char* dataAt = codeColorBuffer; - int octets = numberOfThreeBitSectionsInCode(dataAt); - int lengthOfOctcode = bytesRequiredForCodeLength(octets); - dataAt += lengthOfOctcode; - - // id - uint32_t id; - memcpy(&id, dataAt, sizeof(id)); - dataAt += sizeof(id); - // special case for handling "new" particles - if (id == NEW_PARTICLE) { - // If this is a NEW_PARTICLE, then we assume that there's an additional uint32_t creatorToken, that - // we want to send back to the creator as an map to the actual id - dataAt += sizeof(uint32_t); - } - - // lastEdited - quint64 lastEditedInLocalTime; - memcpy(&lastEditedInLocalTime, dataAt, sizeof(lastEditedInLocalTime)); - quint64 lastEditedInServerTime = lastEditedInLocalTime + clockSkew; - memcpy(dataAt, &lastEditedInServerTime, sizeof(lastEditedInServerTime)); - const bool wantDebug = false; - if (wantDebug) { - qDebug("Particle::adjustEditPacketForClockSkew()..."); - qDebug() << " lastEditedInLocalTime: " << lastEditedInLocalTime; - qDebug() << " clockSkew: " << clockSkew; - qDebug() << " lastEditedInServerTime: " << lastEditedInServerTime; - } -} - -// HALTING_* params are determined using expected acceleration of gravity over some timescale. -// This is a HACK for particles that bounce in a 1.0 gravitational field and should eventually be made more universal. -const float HALTING_PARTICLE_PERIOD = 0.0167f; // ~1/60th of a second -const float HALTING_PARTICLE_SPEED = 9.8 * HALTING_PARTICLE_PERIOD / (float)(TREE_SCALE); - -void Particle::applyHardCollision(const CollisionInfo& collisionInfo) { - // - // Update the particle in response to a hard collision. Position will be reset exactly - // to outside the colliding surface. Velocity will be modified according to elasticity. - // - // if elasticity = 0.0, collision is inelastic (vel normal to collision is lost) - // if elasticity = 1.0, collision is 100% elastic. - // - glm::vec3 position = getPosition(); - glm::vec3 velocity = getVelocity(); - - const float EPSILON = 0.0f; - glm::vec3 relativeVelocity = collisionInfo._addedVelocity - velocity; - float velocityDotPenetration = glm::dot(relativeVelocity, collisionInfo._penetration); - if (velocityDotPenetration < EPSILON) { - // particle is moving into collision surface - // - // TODO: do something smarter here by comparing the mass of the particle vs that of the other thing - // (other's mass could be stored in the Collision Info). The smaller mass should surrender more - // position offset and should slave more to the other's velocity in the static-friction case. - position -= collisionInfo._penetration; - - if (glm::length(relativeVelocity) < HALTING_PARTICLE_SPEED) { - // static friction kicks in and particle moves with colliding object - velocity = collisionInfo._addedVelocity; - } else { - glm::vec3 direction = glm::normalize(collisionInfo._penetration); - velocity += glm::dot(relativeVelocity, direction) * (1.0f + collisionInfo._elasticity) * direction; // dynamic reflection - velocity += glm::clamp(collisionInfo._damping, 0.0f, 1.0f) * (relativeVelocity - glm::dot(relativeVelocity, direction) * direction); // dynamic friction - } - } - - // change the local particle too... - setPosition(position); - setVelocity(velocity); -} - -void Particle::update(const quint64& now) { - if (_lastUpdated == 0) { - _lastUpdated = now; - } - float timeElapsed = (float)(now - _lastUpdated) / (float)(USECS_PER_SECOND); - _lastUpdated = now; - - // calculate our default shouldDie state... then allow script to change it if it wants... - bool isInHand = getInHand(); - bool shouldDie = (getAge() > getLifetime()) || getShouldDie(); - setShouldDie(shouldDie); - - executeUpdateScripts(); // allow the javascript to alter our state - - // If the ball is in hand, it doesn't move or have gravity effect it - if (!isInHand) { - _position += _velocity * timeElapsed; - - // handle bounces off the ground... - if (_position.y <= 0) { - _velocity = _velocity * glm::vec3(1,-1,1); - _position.y = 0; - } - - // handle gravity.... - _velocity += _gravity * timeElapsed; - - // handle damping - glm::vec3 dampingResistance = _velocity * _damping; - _velocity -= dampingResistance * timeElapsed; - //qDebug("applying damping to Particle timeElapsed=%f",timeElapsed); - } -} - -void Particle::startParticleScriptContext(ScriptEngine& engine, ParticleScriptObject& particleScriptable) { - if (_voxelEditSender) { - engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender); - } - if (_particleEditSender) { - engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender); - } - - // Add the "this" Particle object - engine.registerGlobalObject("Particle", &particleScriptable); - engine.evaluate(); -} - -void Particle::endParticleScriptContext(ScriptEngine& engine, ParticleScriptObject& particleScriptable) { - if (_voxelEditSender) { - _voxelEditSender->releaseQueuedMessages(); - } - if (_particleEditSender) { - _particleEditSender->releaseQueuedMessages(); - } -} - -void Particle::executeUpdateScripts() { - // Only run this particle script if there's a script attached directly to the particle. - if (!_script.isEmpty()) { - ScriptEngine engine(_script); - ParticleScriptObject particleScriptable(this); - startParticleScriptContext(engine, particleScriptable); - particleScriptable.emitUpdate(); - endParticleScriptContext(engine, particleScriptable); - } -} - -void Particle::collisionWithParticle(Particle* other, const glm::vec3& penetration) { - // Only run this particle script if there's a script attached directly to the particle. - if (!_script.isEmpty()) { - ScriptEngine engine(_script); - ParticleScriptObject particleScriptable(this); - startParticleScriptContext(engine, particleScriptable); - ParticleScriptObject otherParticleScriptable(other); - particleScriptable.emitCollisionWithParticle(&otherParticleScriptable, penetration); - endParticleScriptContext(engine, particleScriptable); - } -} - -void Particle::collisionWithVoxel(VoxelDetail* voxelDetails, const glm::vec3& penetration) { - // Only run this particle script if there's a script attached directly to the particle. - if (!_script.isEmpty()) { - ScriptEngine engine(_script); - ParticleScriptObject particleScriptable(this); - startParticleScriptContext(engine, particleScriptable); - particleScriptable.emitCollisionWithVoxel(*voxelDetails, penetration); - endParticleScriptContext(engine, particleScriptable); - } -} - -void Particle::setAge(float age) { - quint64 ageInUsecs = age * USECS_PER_SECOND; - _created = usecTimestampNow() - ageInUsecs; -} - -void Particle::copyChangedProperties(const Particle& other) { - float age = getAge(); - *this = other; - setAge(age); -} - -ParticleProperties Particle::getProperties() const { - ParticleProperties properties; - properties.copyFromParticle(*this); - return properties; -} - -void Particle::setProperties(const ParticleProperties& properties) { - properties.copyToParticle(*this); -} - -ParticleProperties::ParticleProperties() : - _position(0), - _color(), - _radius(DEFAULT_RADIUS), - _velocity(0), - _gravity(DEFAULT_GRAVITY), - _damping(DEFAULT_DAMPING), - _lifetime(DEFAULT_LIFETIME), - _script(""), - _inHand(false), - _shouldDie(false), - _modelURL(""), - _modelScale(DEFAULT_MODEL_SCALE), - _modelTranslation(DEFAULT_MODEL_TRANSLATION), - _modelRotation(DEFAULT_MODEL_ROTATION), - - _id(UNKNOWN_PARTICLE_ID), - _idSet(false), - _lastEdited(usecTimestampNow()), - - _positionChanged(false), - _colorChanged(false), - _radiusChanged(false), - _velocityChanged(false), - _gravityChanged(false), - _dampingChanged(false), - _lifetimeChanged(false), - _scriptChanged(false), - _inHandChanged(false), - _shouldDieChanged(false), - _modelURLChanged(false), - _modelScaleChanged(false), - _modelTranslationChanged(false), - _modelRotationChanged(false), - _defaultSettings(true) -{ -} - - -uint16_t ParticleProperties::getChangedBits() const { - uint16_t changedBits = 0; - if (_radiusChanged) { - changedBits += CONTAINS_RADIUS; - } - - if (_positionChanged) { - changedBits += CONTAINS_POSITION; - } - - if (_colorChanged) { - changedBits += CONTAINS_COLOR; - } - - if (_velocityChanged) { - changedBits += CONTAINS_VELOCITY; - } - - if (_gravityChanged) { - changedBits += CONTAINS_GRAVITY; - } - - if (_dampingChanged) { - changedBits += CONTAINS_DAMPING; - } - - if (_lifetimeChanged) { - changedBits += CONTAINS_LIFETIME; - } - - if (_inHandChanged) { - changedBits += CONTAINS_INHAND; - } - - if (_scriptChanged) { - changedBits += CONTAINS_SCRIPT; - } - - if (_shouldDieChanged) { - changedBits += CONTAINS_SHOULDDIE; - } - - if (_modelURLChanged) { - changedBits += CONTAINS_MODEL_URL; - } - - if (_modelScaleChanged) { - changedBits += CONTAINS_MODEL_SCALE; - } - - if (_modelTranslationChanged) { - changedBits += CONTAINS_MODEL_TRANSLATION; - } - - if (_modelRotationChanged) { - changedBits += CONTAINS_MODEL_ROTATION; - } - - return changedBits; -} - - -QScriptValue ParticleProperties::copyToScriptValue(QScriptEngine* engine) const { - QScriptValue properties = engine->newObject(); - - QScriptValue position = vec3toScriptValue(engine, _position); - properties.setProperty("position", position); - - QScriptValue color = xColorToScriptValue(engine, _color); - properties.setProperty("color", color); - - properties.setProperty("radius", _radius); - - QScriptValue velocity = vec3toScriptValue(engine, _velocity); - properties.setProperty("velocity", velocity); - - QScriptValue gravity = vec3toScriptValue(engine, _gravity); - properties.setProperty("gravity", gravity); - - properties.setProperty("damping", _damping); - properties.setProperty("lifetime", _lifetime); - properties.setProperty("script", _script); - properties.setProperty("inHand", _inHand); - properties.setProperty("shouldDie", _shouldDie); - - 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); - - - if (_idSet) { - properties.setProperty("id", _id); - properties.setProperty("isKnownID", (_id != UNKNOWN_PARTICLE_ID)); - } - - return properties; -} - -void ParticleProperties::copyFromScriptValue(const QScriptValue &object) { - - QScriptValue position = object.property("position"); - if (position.isValid()) { - QScriptValue x = position.property("x"); - QScriptValue y = position.property("y"); - QScriptValue z = position.property("z"); - if (x.isValid() && y.isValid() && z.isValid()) { - glm::vec3 newPosition; - newPosition.x = x.toVariant().toFloat(); - newPosition.y = y.toVariant().toFloat(); - newPosition.z = z.toVariant().toFloat(); - if (_defaultSettings || newPosition != _position) { - _position = newPosition; - _positionChanged = true; - } - } - } - - QScriptValue color = object.property("color"); - if (color.isValid()) { - QScriptValue red = color.property("red"); - QScriptValue green = color.property("green"); - QScriptValue blue = color.property("blue"); - if (red.isValid() && green.isValid() && blue.isValid()) { - xColor newColor; - newColor.red = red.toVariant().toInt(); - newColor.green = green.toVariant().toInt(); - newColor.blue = blue.toVariant().toInt(); - if (_defaultSettings || (newColor.red != _color.red || - newColor.green != _color.green || - newColor.blue != _color.blue)) { - _color = newColor; - _colorChanged = true; - } - } - } - - QScriptValue radius = object.property("radius"); - if (radius.isValid()) { - float newRadius; - newRadius = radius.toVariant().toFloat(); - if (_defaultSettings || newRadius != _radius) { - _radius = newRadius; - _radiusChanged = true; - } - } - - QScriptValue velocity = object.property("velocity"); - if (velocity.isValid()) { - QScriptValue x = velocity.property("x"); - QScriptValue y = velocity.property("y"); - QScriptValue z = velocity.property("z"); - if (x.isValid() && y.isValid() && z.isValid()) { - glm::vec3 newVelocity; - newVelocity.x = x.toVariant().toFloat(); - newVelocity.y = y.toVariant().toFloat(); - newVelocity.z = z.toVariant().toFloat(); - if (_defaultSettings || newVelocity != _velocity) { - _velocity = newVelocity; - _velocityChanged = true; - } - } - } - - QScriptValue gravity = object.property("gravity"); - if (gravity.isValid()) { - QScriptValue x = gravity.property("x"); - QScriptValue y = gravity.property("y"); - QScriptValue z = gravity.property("z"); - if (x.isValid() && y.isValid() && z.isValid()) { - glm::vec3 newGravity; - newGravity.x = x.toVariant().toFloat(); - newGravity.y = y.toVariant().toFloat(); - newGravity.z = z.toVariant().toFloat(); - if (_defaultSettings || newGravity != _gravity) { - _gravity = newGravity; - _gravityChanged = true; - } - } - } - - QScriptValue damping = object.property("damping"); - if (damping.isValid()) { - float newDamping; - newDamping = damping.toVariant().toFloat(); - if (_defaultSettings || newDamping != _damping) { - _damping = newDamping; - _dampingChanged = true; - } - } - - QScriptValue lifetime = object.property("lifetime"); - if (lifetime.isValid()) { - float newLifetime; - newLifetime = lifetime.toVariant().toFloat(); - if (_defaultSettings || newLifetime != _lifetime) { - _lifetime = newLifetime; - _lifetimeChanged = true; - } - } - - QScriptValue script = object.property("script"); - if (script.isValid()) { - QString newScript; - newScript = script.toVariant().toString(); - if (_defaultSettings || newScript != _script) { - _script = newScript; - _scriptChanged = true; - } - } - - QScriptValue inHand = object.property("inHand"); - if (inHand.isValid()) { - bool newInHand; - newInHand = inHand.toVariant().toBool(); - if (_defaultSettings || newInHand != _inHand) { - _inHand = newInHand; - _inHandChanged = true; - } - } - - QScriptValue shouldDie = object.property("shouldDie"); - if (shouldDie.isValid()) { - bool newShouldDie; - newShouldDie = shouldDie.toVariant().toBool(); - if (_defaultSettings || newShouldDie != _shouldDie) { - _shouldDie = newShouldDie; - _shouldDieChanged = true; - } - } - - QScriptValue modelURL = object.property("modelURL"); - if (modelURL.isValid()) { - QString newModelURL; - newModelURL = modelURL.toVariant().toString(); - if (_defaultSettings || newModelURL != _modelURL) { - _modelURL = newModelURL; - _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"); - QScriptValue y = modelTranslation.property("y"); - QScriptValue z = modelTranslation.property("z"); - if (x.isValid() && y.isValid() && z.isValid()) { - glm::vec3 newModelTranslation; - newModelTranslation.x = x.toVariant().toFloat(); - newModelTranslation.y = y.toVariant().toFloat(); - newModelTranslation.z = z.toVariant().toFloat(); - if (_defaultSettings || newModelTranslation != _modelTranslation) { - _modelTranslation = newModelTranslation; - _modelTranslationChanged = true; - } - } - } - - - QScriptValue modelRotation = object.property("modelRotation"); - if (modelRotation.isValid()) { - QScriptValue x = modelRotation.property("x"); - QScriptValue y = modelRotation.property("y"); - QScriptValue z = modelRotation.property("z"); - QScriptValue w = modelRotation.property("w"); - if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { - glm::quat newModelRotation; - newModelRotation.x = x.toVariant().toFloat(); - newModelRotation.y = y.toVariant().toFloat(); - newModelRotation.z = z.toVariant().toFloat(); - newModelRotation.w = w.toVariant().toFloat(); - if (_defaultSettings || newModelRotation != _modelRotation) { - _modelRotation = newModelRotation; - _modelRotationChanged = true; - } - } - } - - _lastEdited = usecTimestampNow(); -} - -void ParticleProperties::copyToParticle(Particle& particle) const { - bool somethingChanged = false; - if (_positionChanged) { - particle.setPosition(_position / (float) TREE_SCALE); - somethingChanged = true; - } - - if (_colorChanged) { - particle.setColor(_color); - somethingChanged = true; - } - - if (_radiusChanged) { - particle.setRadius(_radius / (float) TREE_SCALE); - somethingChanged = true; - } - - if (_velocityChanged) { - particle.setVelocity(_velocity / (float) TREE_SCALE); - somethingChanged = true; - } - - if (_gravityChanged) { - particle.setGravity(_gravity / (float) TREE_SCALE); - somethingChanged = true; - } - - if (_dampingChanged) { - particle.setDamping(_damping); - somethingChanged = true; - } - - if (_lifetimeChanged) { - particle.setLifetime(_lifetime); - somethingChanged = true; - } - - if (_scriptChanged) { - particle.setScript(_script); - somethingChanged = true; - } - - if (_inHandChanged) { - particle.setInHand(_inHand); - somethingChanged = true; - } - - if (_shouldDieChanged) { - particle.setShouldDie(_shouldDie); - somethingChanged = true; - } - - if (_modelURLChanged) { - particle.setModelURL(_modelURL); - somethingChanged = true; - } - - if (_modelScaleChanged) { - particle.setModelScale(_modelScale); - somethingChanged = true; - } - - if (_modelTranslationChanged) { - particle.setModelTranslation(_modelTranslation); - somethingChanged = true; - } - - if (_modelRotationChanged) { - particle.setModelRotation(_modelRotation); - somethingChanged = true; - } - - if (somethingChanged) { - bool wantDebug = false; - if (wantDebug) { - uint64_t now = usecTimestampNow(); - int elapsed = now - _lastEdited; - qDebug() << "ParticleProperties::copyToParticle() AFTER update... edited AGO=" << elapsed << - "now=" << now << " _lastEdited=" << _lastEdited; - } - particle.setLastEdited(_lastEdited); - } -} - -void ParticleProperties::copyFromParticle(const Particle& particle) { - _position = particle.getPosition() * (float) TREE_SCALE; - _color = particle.getXColor(); - _radius = particle.getRadius() * (float) TREE_SCALE; - _velocity = particle.getVelocity() * (float) TREE_SCALE; - _gravity = particle.getGravity() * (float) TREE_SCALE; - _damping = particle.getDamping(); - _lifetime = particle.getLifetime(); - _script = particle.getScript(); - _inHand = particle.getInHand(); - _shouldDie = particle.getShouldDie(); - _modelURL = particle.getModelURL(); - _modelScale = particle.getModelScale(); - _modelTranslation = particle.getModelTranslation(); - _modelRotation = particle.getModelRotation(); - - _id = particle.getID(); - _idSet = true; - - _positionChanged = false; - _colorChanged = false; - _radiusChanged = false; - _velocityChanged = false; - _gravityChanged = false; - _dampingChanged = false; - _lifetimeChanged = false; - _scriptChanged = false; - _inHandChanged = false; - _shouldDieChanged = false; - _modelURLChanged = false; - _modelScaleChanged = false; - _modelTranslationChanged = false; - _modelRotationChanged = false; - _defaultSettings = false; -} - -QScriptValue ParticlePropertiesToScriptValue(QScriptEngine* engine, const ParticleProperties& properties) { - return properties.copyToScriptValue(engine); -} - -void ParticlePropertiesFromScriptValue(const QScriptValue &object, ParticleProperties& properties) { - properties.copyFromScriptValue(object); -} - - -QScriptValue ParticleIDtoScriptValue(QScriptEngine* engine, const ParticleID& id) { - QScriptValue obj = engine->newObject(); - obj.setProperty("id", id.id); - obj.setProperty("creatorTokenID", id.creatorTokenID); - obj.setProperty("isKnownID", id.isKnownID); - return obj; -} - -void ParticleIDfromScriptValue(const QScriptValue &object, ParticleID& id) { - id.id = object.property("id").toVariant().toUInt(); - id.creatorTokenID = object.property("creatorTokenID").toVariant().toUInt(); - id.isKnownID = object.property("isKnownID").toVariant().toBool(); -} - - diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h deleted file mode 100644 index 1ee0f6e79b..0000000000 --- a/libraries/particles/src/Particle.h +++ /dev/null @@ -1,433 +0,0 @@ -// -// Particle.h -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/4/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_Particle_h -#define hifi_Particle_h - -#include -#include - -#include -#include - -#include -#include -#include - -class Particle; -class ParticleEditPacketSender; -class ParticleProperties; -class ParticlesScriptingInterface; -class ParticleScriptObject; -class ParticleTree; -class ScriptEngine; -class VoxelEditPacketSender; -class VoxelsScriptingInterface; -struct VoxelDetail; - -const uint32_t NEW_PARTICLE = 0xFFFFFFFF; -const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF; -const uint32_t UNKNOWN_PARTICLE_ID = 0xFFFFFFFF; - -const uint16_t CONTAINS_RADIUS = 1; -const uint16_t CONTAINS_POSITION = 2; -const uint16_t CONTAINS_COLOR = 4; -const uint16_t CONTAINS_VELOCITY = 8; -const uint16_t CONTAINS_GRAVITY = 16; -const uint16_t CONTAINS_DAMPING = 32; -const uint16_t CONTAINS_LIFETIME = 64; -const uint16_t CONTAINS_INHAND = 128; -const uint16_t CONTAINS_SCRIPT = 256; -const uint16_t CONTAINS_SHOULDDIE = 512; -const uint16_t CONTAINS_MODEL_URL = 1024; -const uint16_t CONTAINS_MODEL_TRANSLATION = 1024; -const uint16_t CONTAINS_MODEL_ROTATION = 2048; -const uint16_t CONTAINS_MODEL_SCALE = 4096; - -const float DEFAULT_LIFETIME = 10.0f; // particles live for 10 seconds by default -const float DEFAULT_DAMPING = 0.99f; -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 -/// all units for position, velocity, gravity, radius, etc are in meter units -class ParticleProperties { -public: - ParticleProperties(); - - QScriptValue copyToScriptValue(QScriptEngine* engine) const; - void copyFromScriptValue(const QScriptValue& object); - - void copyToParticle(Particle& particle) const; - void copyFromParticle(const Particle& particle); - - const glm::vec3& getPosition() const { return _position; } - xColor getColor() const { return _color; } - float getRadius() const { return _radius; } - const glm::vec3& getVelocity() const { return _velocity; } - const glm::vec3& getGravity() const { return _gravity; } - float getDamping() const { return _damping; } - float getLifetime() const { return _lifetime; } - const QString& getScript() const { return _script; } - 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; } - - quint64 getLastEdited() const { return _lastEdited; } - uint16_t getChangedBits() const; - - /// set position in meter units - void setPosition(const glm::vec3& value) { _position = value; _positionChanged = true; } - - /// set velocity in meter units - void setVelocity(const glm::vec3& value) { _velocity = value; _velocityChanged = true; } - void setColor(const xColor& value) { _color = value; _colorChanged = true; } - void setRadius(float value) { _radius = value; _radiusChanged = true; } - - /// set gravity in meter units - void setGravity(const glm::vec3& value) { _gravity = value; _gravityChanged = true; } - void setInHand(bool inHand) { _inHand = inHand; _inHandChanged = true; } - void setDamping(float value) { _damping = value; _dampingChanged = true; } - void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; _shouldDieChanged = true; } - void setLifetime(float value) { _lifetime = value; _lifetimeChanged = true; } - void setScript(const QString& updateScript) { _script = updateScript; _scriptChanged = true; } - - // 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; } - - /// used by ParticleScriptingInterface to return ParticleProperties for unknown particles - void setIsUnknownID() { _id = UNKNOWN_PARTICLE_ID; _idSet = true; } - -private: - glm::vec3 _position; - xColor _color; - float _radius; - glm::vec3 _velocity; - glm::vec3 _gravity; - float _damping; - float _lifetime; - QString _script; - bool _inHand; - bool _shouldDie; - QString _modelURL; - float _modelScale; - glm::vec3 _modelTranslation; - glm::quat _modelRotation; - - uint32_t _id; - bool _idSet; - quint64 _lastEdited; - - bool _positionChanged; - bool _colorChanged; - bool _radiusChanged; - bool _velocityChanged; - bool _gravityChanged; - bool _dampingChanged; - bool _lifetimeChanged; - bool _scriptChanged; - bool _inHandChanged; - bool _shouldDieChanged; - bool _modelURLChanged; - bool _modelScaleChanged; - bool _modelTranslationChanged; - bool _modelRotationChanged; - bool _defaultSettings; -}; -Q_DECLARE_METATYPE(ParticleProperties); -QScriptValue ParticlePropertiesToScriptValue(QScriptEngine* engine, const ParticleProperties& properties); -void ParticlePropertiesFromScriptValue(const QScriptValue &object, ParticleProperties& properties); - - -/// Abstract ID for editing particles. Used in Particle JS API - When particles are created in the JS api, they are given a -/// local creatorTokenID, the actual id for the particle is not known until the server responds to the creator with the -/// correct mapping. This class works with the scripting API an allows the developer to edit particles they created. -class ParticleID { -public: - ParticleID() : - id(NEW_PARTICLE), creatorTokenID(UNKNOWN_TOKEN), isKnownID(false) { }; - - ParticleID(uint32_t id, uint32_t creatorTokenID, bool isKnownID) : - id(id), creatorTokenID(creatorTokenID), isKnownID(isKnownID) { }; - - ParticleID(uint32_t id) : - id(id), creatorTokenID(UNKNOWN_TOKEN), isKnownID(true) { }; - - uint32_t id; - uint32_t creatorTokenID; - bool isKnownID; -}; - -Q_DECLARE_METATYPE(ParticleID); -Q_DECLARE_METATYPE(QVector); -QScriptValue ParticleIDtoScriptValue(QScriptEngine* engine, const ParticleID& properties); -void ParticleIDfromScriptValue(const QScriptValue &object, ParticleID& properties); - - - -/// Particle class - this is the actual particle class. -class Particle { - -public: - Particle(); - - Particle(const ParticleID& particleID, const ParticleProperties& properties); - - /// creates an NEW particle from an PACKET_TYPE_PARTICLE_ADD_OR_EDIT edit data buffer - static Particle fromEditPacket(const unsigned char* data, int length, int& processedBytes, ParticleTree* tree, bool& valid); - - virtual ~Particle(); - virtual void init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, - glm::vec3 gravity = DEFAULT_GRAVITY, float damping = DEFAULT_DAMPING, float lifetime = DEFAULT_LIFETIME, - bool inHand = NOT_IN_HAND, QString updateScript = DEFAULT_SCRIPT, uint32_t id = NEW_PARTICLE); - - /// get position in domain scale units (0.0 - 1.0) - const glm::vec3& getPosition() const { return _position; } - - const rgbColor& getColor() const { return _color; } - xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } - - /// get radius in domain scale units (0.0 - 1.0) - float getRadius() const { return _radius; } - float getMass() const { return _mass; } - - /// get velocity in domain scale units (0.0 - 1.0) - const glm::vec3& getVelocity() const { return _velocity; } - - /// get gravity in domain scale units (0.0 - 1.0) - const glm::vec3& getGravity() const { return _gravity; } - - bool getInHand() const { return _inHand; } - float getDamping() const { return _damping; } - float getLifetime() const { return _lifetime; } - - // 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; } - - ParticleID getParticleID() const { return ParticleID(getID(), getCreatorTokenID(), getID() != UNKNOWN_PARTICLE_ID); } - ParticleProperties getProperties() const; - - /// The last updated/simulated time of this particle from the time perspective of the authoritative server/source - quint64 getLastUpdated() const { return _lastUpdated; } - - /// The last edited time of this particle from the time perspective of the authoritative server/source - quint64 getLastEdited() const { return _lastEdited; } - void setLastEdited(quint64 lastEdited) { _lastEdited = lastEdited; } - - /// lifetime of the particle in seconds - float getAge() const { return static_cast(usecTimestampNow() - _created) / static_cast(USECS_PER_SECOND); } - float getEditedAgo() const { return static_cast(usecTimestampNow() - _lastEdited) / static_cast(USECS_PER_SECOND); } - uint32_t getID() const { return _id; } - void setID(uint32_t id) { _id = id; } - bool getShouldDie() const { return _shouldDie; } - QString getScript() const { return _script; } - uint32_t getCreatorTokenID() const { return _creatorTokenID; } - bool isNewlyCreated() const { return _newlyCreated; } - - /// set position in domain scale units (0.0 - 1.0) - void setPosition(const glm::vec3& value) { _position = value; } - - /// set velocity in domain scale units (0.0 - 1.0) - void setVelocity(const glm::vec3& value) { _velocity = value; } - void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } - void setColor(const xColor& value) { - _color[RED_INDEX] = value.red; - _color[GREEN_INDEX] = value.green; - _color[BLUE_INDEX] = value.blue; - } - /// set radius in domain scale units (0.0 - 1.0) - void setRadius(float value) { _radius = value; } - void setMass(float value); - - /// set gravity in domain scale units (0.0 - 1.0) - void setGravity(const glm::vec3& value) { _gravity = value; } - void setInHand(bool inHand) { _inHand = inHand; } - void setDamping(float value) { _damping = value; } - void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; } - void setLifetime(float value) { _lifetime = value; } - void setScript(QString updateScript) { _script = updateScript; } - void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; } - - // 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 setProperties(const ParticleProperties& properties); - - bool appendParticleData(OctreePacketData* packetData) const; - int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); - static int expectedBytes(); - - static bool encodeParticleEditMessageDetails(PacketType command, ParticleID id, const ParticleProperties& details, - unsigned char* bufferOut, int sizeIn, int& sizeOut); - - static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew); - - void applyHardCollision(const CollisionInfo& collisionInfo); - - void update(const quint64& now); - void collisionWithParticle(Particle* other, const glm::vec3& penetration); - void collisionWithVoxel(VoxelDetail* voxel, const glm::vec3& penetration); - - void debugDump() const; - - // similar to assignment/copy, but it handles keeping lifetime accurate - void copyChangedProperties(const Particle& other); - - static VoxelEditPacketSender* getVoxelEditPacketSender() { return _voxelEditSender; } - static ParticleEditPacketSender* getParticleEditPacketSender() { return _particleEditSender; } - - static void setVoxelEditPacketSender(VoxelEditPacketSender* senderInterface) - { _voxelEditSender = senderInterface; } - - static void setParticleEditPacketSender(ParticleEditPacketSender* senderInterface) - { _particleEditSender = senderInterface; } - - - // these methods allow you to create particles, and later edit them. - static uint32_t getIDfromCreatorTokenID(uint32_t creatorTokenID); - static uint32_t getNextCreatorTokenID(); - static void handleAddParticleResponse(const QByteArray& packet); - -protected: - static VoxelEditPacketSender* _voxelEditSender; - static ParticleEditPacketSender* _particleEditSender; - - void startParticleScriptContext(ScriptEngine& engine, ParticleScriptObject& particleScriptable); - void endParticleScriptContext(ScriptEngine& engine, ParticleScriptObject& particleScriptable); - void executeUpdateScripts(); - - void setAge(float age); - - glm::vec3 _position; - rgbColor _color; - float _radius; - float _mass; - glm::vec3 _velocity; - uint32_t _id; - static uint32_t _nextID; - bool _shouldDie; - glm::vec3 _gravity; - float _damping; - float _lifetime; - QString _script; - bool _inHand; - - // model related items - QString _modelURL; - float _modelScale; - glm::vec3 _modelTranslation; - glm::quat _modelRotation; - - uint32_t _creatorTokenID; - bool _newlyCreated; - - quint64 _lastUpdated; - quint64 _lastEdited; - - // this doesn't go on the wire, we send it as lifetime - quint64 _created; - - // used by the static interfaces for creator token ids - static uint32_t _nextCreatorTokenID; - static std::map _tokenIDsToIDs; -}; - -/// Scriptable interface to a single Particle object. Used exclusively in the JavaScript API for interacting with single -/// Particles. -class ParticleScriptObject : public QObject { - Q_OBJECT -public: - ParticleScriptObject(Particle* particle) { _particle = particle; } - //~ParticleScriptObject() { qDebug() << "~ParticleScriptObject() this=" << this; } - - void emitUpdate() { emit update(); } - void emitCollisionWithParticle(QObject* other, const glm::vec3& penetration) - { emit collisionWithParticle(other, penetration); } - void emitCollisionWithVoxel(const VoxelDetail& voxel, const glm::vec3& penetration) - { emit collisionWithVoxel(voxel, penetration); } - -public slots: - unsigned int getID() const { return _particle->getID(); } - - /// get position in meter units - glm::vec3 getPosition() const { return _particle->getPosition() * (float)TREE_SCALE; } - - /// get velocity in meter units - glm::vec3 getVelocity() const { return _particle->getVelocity() * (float)TREE_SCALE; } - xColor getColor() const { return _particle->getXColor(); } - - /// get gravity in meter units - glm::vec3 getGravity() const { return _particle->getGravity() * (float)TREE_SCALE; } - - float getDamping() const { return _particle->getDamping(); } - - /// get radius in meter units - float getRadius() const { return _particle->getRadius() * (float)TREE_SCALE; } - bool getShouldDie() { return _particle->getShouldDie(); } - float getAge() const { return _particle->getAge(); } - float getLifetime() const { return _particle->getLifetime(); } - ParticleProperties getProperties() const { return _particle->getProperties(); } - - /// set position in meter units - void setPosition(glm::vec3 value) { _particle->setPosition(value / (float)TREE_SCALE); } - - /// set velocity in meter units - void setVelocity(glm::vec3 value) { _particle->setVelocity(value / (float)TREE_SCALE); } - - /// set gravity in meter units - void setGravity(glm::vec3 value) { _particle->setGravity(value / (float)TREE_SCALE); } - - void setDamping(float value) { _particle->setDamping(value); } - void setColor(xColor value) { _particle->setColor(value); } - - /// set radius in meter units - void setRadius(float value) { _particle->setRadius(value / (float)TREE_SCALE); } - void setShouldDie(bool value) { _particle->setShouldDie(value); } - void setScript(const QString& script) { _particle->setScript(script); } - void setLifetime(float value) const { return _particle->setLifetime(value); } - void setProperties(const ParticleProperties& properties) { return _particle->setProperties(properties); } - -signals: - void update(); - void collisionWithVoxel(const VoxelDetail& voxel, const glm::vec3& penetration); - void collisionWithParticle(QObject* other, const glm::vec3& penetration); - -private: - Particle* _particle; -}; - - - -#endif // hifi_Particle_h diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp deleted file mode 100644 index 17d1dd3bc6..0000000000 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ /dev/null @@ -1,278 +0,0 @@ -// -// ParticleCollisionSystem.cpp -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/4/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 -#include - -#include "Particle.h" -#include "ParticleCollisionSystem.h" -#include "ParticleEditPacketSender.h" -#include "ParticleTree.h" - -const int MAX_COLLISIONS_PER_PARTICLE = 16; - -ParticleCollisionSystem::ParticleCollisionSystem(ParticleEditPacketSender* packetSender, - ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio, - AvatarHashMap* avatars) : _collisions(MAX_COLLISIONS_PER_PARTICLE) { - init(packetSender, particles, voxels, audio, avatars); -} - -void ParticleCollisionSystem::init(ParticleEditPacketSender* packetSender, - ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio, - AvatarHashMap* avatars) { - _packetSender = packetSender; - _particles = particles; - _voxels = voxels; - _audio = audio; - _avatars = avatars; -} - -ParticleCollisionSystem::~ParticleCollisionSystem() { -} - -bool ParticleCollisionSystem::updateOperation(OctreeElement* element, void* extraData) { - ParticleCollisionSystem* system = static_cast(extraData); - ParticleTreeElement* particleTreeElement = static_cast(element); - - // iterate the particles... - QList& particles = particleTreeElement->getParticles(); - uint16_t numberOfParticles = particles.size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - Particle* particle = &particles[i]; - system->checkParticle(particle); - } - - return true; -} - - -void ParticleCollisionSystem::update() { - // update all particles - if (_particles->tryLockForRead()) { - _particles->recurseTreeWithOperation(updateOperation, this); - _particles->unlock(); - } -} - - -void ParticleCollisionSystem::checkParticle(Particle* particle) { - updateCollisionWithVoxels(particle); - updateCollisionWithParticles(particle); - updateCollisionWithAvatars(particle); -} - -void ParticleCollisionSystem::emitGlobalParticleCollisionWithVoxel(Particle* particle, - VoxelDetail* voxelDetails, const CollisionInfo& collision) { - ParticleID particleID = particle->getParticleID(); - emit particleCollisionWithVoxel(particleID, *voxelDetails, collision); -} - -void ParticleCollisionSystem::emitGlobalParticleCollisionWithParticle(Particle* particleA, - Particle* particleB, const CollisionInfo& collision) { - - ParticleID idA = particleA->getParticleID(); - ParticleID idB = particleB->getParticleID(); - emit particleCollisionWithParticle(idA, idB, collision); -} - -void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) { - glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE); - float radius = particle->getRadius() * (float)(TREE_SCALE); - const float ELASTICITY = 0.4f; - const float DAMPING = 0.05f; - const float COLLISION_FREQUENCY = 0.5f; - CollisionInfo collisionInfo; - collisionInfo._damping = DAMPING; - collisionInfo._elasticity = ELASTICITY; - VoxelDetail* voxelDetails = NULL; - if (_voxels->findSpherePenetration(center, radius, collisionInfo._penetration, (void**)&voxelDetails)) { - - // let the particles run their collision scripts if they have them - particle->collisionWithVoxel(voxelDetails, collisionInfo._penetration); - - // 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. - updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY); - collisionInfo._contactPoint = (float)TREE_SCALE * (particle->getPosition() + particle->getRadius() * glm::normalize(collisionInfo._penetration)); - // let the global script run their collision scripts for particles if they have them - emitGlobalParticleCollisionWithVoxel(particle, voxelDetails, collisionInfo); - - // we must scale back down to the octree reference frame before updating the particle properties - collisionInfo._penetration /= (float)(TREE_SCALE); - collisionInfo._contactPoint /= (float)(TREE_SCALE); - particle->applyHardCollision(collisionInfo); - queueParticlePropertiesUpdate(particle); - - delete voxelDetails; // cleanup returned details - } -} - -void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA) { - glm::vec3 center = particleA->getPosition() * (float)(TREE_SCALE); - float radius = particleA->getRadius() * (float)(TREE_SCALE); - //const float ELASTICITY = 0.4f; - //const float DAMPING = 0.0f; - const float COLLISION_FREQUENCY = 0.5f; - glm::vec3 penetration; - Particle* particleB; - if (_particles->findSpherePenetration(center, radius, penetration, (void**)&particleB, Octree::NoLock)) { - // NOTE: 'penetration' is the depth that 'particleA' overlaps 'particleB'. It points from A into B. - - // Even if the particles overlap... when the particles are already moving appart - // we don't want to count this as a collision. - glm::vec3 relativeVelocity = particleA->getVelocity() - particleB->getVelocity(); - if (glm::dot(relativeVelocity, penetration) > 0.0f) { - particleA->collisionWithParticle(particleB, penetration); - particleB->collisionWithParticle(particleA, penetration * -1.0f); // the penetration is reversed - - CollisionInfo collision; - collision._penetration = penetration; - // for now the contactPoint is the average between the the two paricle centers - collision._contactPoint = (0.5f * (float)TREE_SCALE) * (particleA->getPosition() + particleB->getPosition()); - emitGlobalParticleCollisionWithParticle(particleA, particleB, collision); - - glm::vec3 axis = glm::normalize(penetration); - glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis; - - // particles that are in hand are assigned an ureasonably large mass for collisions - // which effectively makes them immovable but allows the other ball to reflect correctly. - const float MAX_MASS = 1.0e6f; - float massA = (particleA->getInHand()) ? MAX_MASS : particleA->getMass(); - float massB = (particleB->getInHand()) ? MAX_MASS : particleB->getMass(); - float totalMass = massA + massB; - - // handle particle A - particleA->setVelocity(particleA->getVelocity() - axialVelocity * (2.0f * massB / totalMass)); - particleA->setPosition(particleA->getPosition() - 0.5f * penetration); - ParticleProperties propertiesA; - ParticleID idA(particleA->getID()); - propertiesA.copyFromParticle(*particleA); - propertiesA.setVelocity(particleA->getVelocity() * (float)TREE_SCALE); - propertiesA.setPosition(particleA->getPosition() * (float)TREE_SCALE); - _packetSender->queueParticleEditMessage(PacketTypeParticleAddOrEdit, idA, propertiesA); - - // handle particle B - particleB->setVelocity(particleB->getVelocity() + axialVelocity * (2.0f * massA / totalMass)); - particleA->setPosition(particleB->getPosition() + 0.5f * penetration); - ParticleProperties propertiesB; - ParticleID idB(particleB->getID()); - propertiesB.copyFromParticle(*particleB); - propertiesB.setVelocity(particleB->getVelocity() * (float)TREE_SCALE); - propertiesB.setPosition(particleB->getPosition() * (float)TREE_SCALE); - _packetSender->queueParticleEditMessage(PacketTypeParticleAddOrEdit, idB, propertiesB); - - _packetSender->releaseQueuedMessages(); - - updateCollisionSound(particleA, penetration, COLLISION_FREQUENCY); - } - } -} - -void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { - // particles that are in hand, don't collide with avatars - if (!_avatars || particle->getInHand()) { - return; - } - - glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE); - float radius = particle->getRadius() * (float)(TREE_SCALE); - const float ELASTICITY = 0.9f; - const float DAMPING = 0.1f; - const float COLLISION_FREQUENCY = 0.5f; - glm::vec3 penetration; - - _collisions.clear(); - foreach (const AvatarSharedPointer& avatarPointer, _avatars->getAvatarHash()) { - AvatarData* avatar = avatarPointer.data(); - - float totalRadius = avatar->getBoundingRadius() + radius; - glm::vec3 relativePosition = center - avatar->getPosition(); - if (glm::dot(relativePosition, relativePosition) > (totalRadius * totalRadius)) { - continue; - } - - if (avatar->findSphereCollisions(center, radius, _collisions)) { - int numCollisions = _collisions.size(); - for (int i = 0; i < numCollisions; ++i) { - CollisionInfo* collision = _collisions.getCollision(i); - collision->_damping = DAMPING; - collision->_elasticity = ELASTICITY; - - collision->_addedVelocity /= (float)(TREE_SCALE); - glm::vec3 relativeVelocity = collision->_addedVelocity - particle->getVelocity(); - - if (glm::dot(relativeVelocity, collision->_penetration) <= 0.f) { - // only collide when particle and collision point are moving toward each other - // (doing this prevents some "collision snagging" when particle penetrates the object) - updateCollisionSound(particle, collision->_penetration, COLLISION_FREQUENCY); - collision->_penetration /= (float)(TREE_SCALE); - particle->applyHardCollision(*collision); - queueParticlePropertiesUpdate(particle); - } - } - } - } -} - -void ParticleCollisionSystem::queueParticlePropertiesUpdate(Particle* particle) { - // queue the result for sending to the particle server - ParticleProperties properties; - ParticleID particleID(particle->getID()); - properties.copyFromParticle(*particle); - - properties.setPosition(particle->getPosition() * (float)TREE_SCALE); - properties.setVelocity(particle->getVelocity() * (float)TREE_SCALE); - _packetSender->queueParticleEditMessage(PacketTypeParticleAddOrEdit, particleID, properties); -} - - -void ParticleCollisionSystem::updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency) { - - // consider whether to have the collision make a sound - const float AUDIBLE_COLLISION_THRESHOLD = 0.3f; - const float COLLISION_LOUDNESS = 1.f; - const float DURATION_SCALING = 0.004f; - const float NOISE_SCALING = 0.1f; - glm::vec3 velocity = particle->getVelocity() * (float)(TREE_SCALE); - - /* - // how do we want to handle this?? - // - glm::vec3 gravity = particle->getGravity() * (float)(TREE_SCALE); - - if (glm::length(gravity) > EPSILON) { - // If gravity is on, remove the effect of gravity on velocity for this - // frame, so that we are not constantly colliding with the surface - velocity -= _scale * glm::length(gravity) * GRAVITY_EARTH * deltaTime * glm::normalize(gravity); - } - */ - float normalSpeed = glm::dot(velocity, glm::normalize(penetration)); - // NOTE: it is possible for normalSpeed to be NaN at this point - // (sometimes the average penetration of a bunch of voxels is a zero length vector which cannot be normalized) - // however the check below will fail (NaN comparisons always fail) and everything will be fine. - - if (normalSpeed > AUDIBLE_COLLISION_THRESHOLD) { - // Volume is proportional to collision velocity - // Base frequency is modified upward by the angle of the collision - // Noise is a function of the angle of collision - // Duration of the sound is a function of both base frequency and velocity of impact - float tangentialSpeed = glm::length(velocity) - normalSpeed; - _audio->startCollisionSound( std::min(COLLISION_LOUDNESS * normalSpeed, 1.f), - frequency * (1.f + tangentialSpeed / normalSpeed), - std::min(tangentialSpeed / normalSpeed * NOISE_SCALING, 1.f), - 1.f - DURATION_SCALING * powf(frequency, 0.5f) / normalSpeed, false); - } -} diff --git a/libraries/particles/src/ParticleCollisionSystem.h b/libraries/particles/src/ParticleCollisionSystem.h deleted file mode 100644 index cf9c4b938c..0000000000 --- a/libraries/particles/src/ParticleCollisionSystem.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// ParticleCollisionSystem.h -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/4/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_ParticleCollisionSystem_h -#define hifi_ParticleCollisionSystem_h - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "Particle.h" - -class AbstractAudioInterface; -class AvatarData; -class ParticleEditPacketSender; -class ParticleTree; -class VoxelTree; - -const glm::vec3 NO_ADDED_VELOCITY = glm::vec3(0); - -class ParticleCollisionSystem : public QObject { -Q_OBJECT -public: - ParticleCollisionSystem(ParticleEditPacketSender* packetSender = NULL, ParticleTree* particles = NULL, - VoxelTree* voxels = NULL, AbstractAudioInterface* audio = NULL, - AvatarHashMap* avatars = NULL); - - void init(ParticleEditPacketSender* packetSender, ParticleTree* particles, VoxelTree* voxels, - AbstractAudioInterface* audio = NULL, AvatarHashMap* _avatars = NULL); - - ~ParticleCollisionSystem(); - - void update(); - - void checkParticle(Particle* particle); - void updateCollisionWithVoxels(Particle* particle); - void updateCollisionWithParticles(Particle* particle); - void updateCollisionWithAvatars(Particle* particle); - void queueParticlePropertiesUpdate(Particle* particle); - void updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency); - -signals: - void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel, const CollisionInfo& penetration); - void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const CollisionInfo& penetration); - -private: - static bool updateOperation(OctreeElement* element, void* extraData); - void emitGlobalParticleCollisionWithVoxel(Particle* particle, VoxelDetail* voxelDetails, const CollisionInfo& penetration); - void emitGlobalParticleCollisionWithParticle(Particle* particleA, Particle* particleB, const CollisionInfo& penetration); - - ParticleEditPacketSender* _packetSender; - ParticleTree* _particles; - VoxelTree* _voxels; - AbstractAudioInterface* _audio; - AvatarHashMap* _avatars; - CollisionList _collisions; -}; - -#endif // hifi_ParticleCollisionSystem_h diff --git a/libraries/particles/src/ParticleEditPacketSender.cpp b/libraries/particles/src/ParticleEditPacketSender.cpp deleted file mode 100644 index db9e2114ba..0000000000 --- a/libraries/particles/src/ParticleEditPacketSender.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// ParticleEditPacketSender.cpp -// libraries/particles/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 "ParticleEditPacketSender.h" -#include "Particle.h" - - -void ParticleEditPacketSender::sendEditParticleMessage(PacketType type, ParticleID particleID, const ParticleProperties& properties) { - // allows app to disable sending if for example voxels have been disabled - if (!_shouldSend) { - return; // bail early - } - - static unsigned char bufferOut[MAX_PACKET_SIZE]; - int sizeOut = 0; - - // This encodes the voxel edit message into a buffer... - if (Particle::encodeParticleEditMessageDetails(type, particleID, properties, &bufferOut[0], _maxPacketSize, 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 (!serversExist()) { - queuePendingPacketToNodes(type, bufferOut, sizeOut); - } else { - queuePacketToNodes(bufferOut, sizeOut); - } - } -} - -void ParticleEditPacketSender::adjustEditPacketForClockSkew(PacketType type, - unsigned char* codeColorBuffer, size_t length, int clockSkew) { - Particle::adjustEditPacketForClockSkew(codeColorBuffer, length, clockSkew); -} - - -void ParticleEditPacketSender::queueParticleEditMessage(PacketType type, ParticleID particleID, - const ParticleProperties& properties) { - if (!_shouldSend) { - return; // bail early - } - - // use MAX_PACKET_SIZE since it's static and guaranteed to be larger than _maxPacketSize - static unsigned char bufferOut[MAX_PACKET_SIZE]; - int sizeOut = 0; - - if (Particle::encodeParticleEditMessageDetails(type, particleID, properties, &bufferOut[0], _maxPacketSize, sizeOut)) { - queueOctreeEditMessage(type, bufferOut, sizeOut); - } -} - diff --git a/libraries/particles/src/ParticleEditPacketSender.h b/libraries/particles/src/ParticleEditPacketSender.h deleted file mode 100644 index daa8294ef1..0000000000 --- a/libraries/particles/src/ParticleEditPacketSender.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// ParticleEditPacketSender.h -// libraries/particles/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 -// - -#ifndef hifi_ParticleEditPacketSender_h -#define hifi_ParticleEditPacketSender_h - -#include -#include "Particle.h" - -/// Utility for processing, packing, queueing and sending of outbound edit voxel messages. -class ParticleEditPacketSender : public OctreeEditPacketSender { - Q_OBJECT -public: - /// Send particle add message immediately - /// NOTE: ParticleProperties assumes that all distances are in meter units - void sendEditParticleMessage(PacketType type, ParticleID particleID, const ParticleProperties& properties); - - /// 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. - /// NOTE: ParticleProperties assumes that all distances are in meter units - void queueParticleEditMessage(PacketType type, ParticleID particleID, const ParticleProperties& properties); - - // My server type is the particle server - virtual char getMyNodeType() const { return NodeType::ParticleServer; } - virtual void adjustEditPacketForClockSkew(PacketType type, unsigned char* codeColorBuffer, size_t length, int clockSkew); -}; -#endif // hifi_ParticleEditPacketSender_h diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp deleted file mode 100644 index 02e48f031f..0000000000 --- a/libraries/particles/src/ParticleTree.cpp +++ /dev/null @@ -1,658 +0,0 @@ -// -// ParticleTree.cpp -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/4/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 "ParticleTree.h" - -ParticleTree::ParticleTree(bool shouldReaverage) : Octree(shouldReaverage) { - _rootElement = createNewElement(); -} - -ParticleTreeElement* ParticleTree::createNewElement(unsigned char * octalCode) { - ParticleTreeElement* newElement = new ParticleTreeElement(octalCode); - newElement->setTree(this); - return newElement; -} - -bool ParticleTree::handlesEditPacketType(PacketType packetType) const { - // we handle these types of "edit" packets - switch (packetType) { - case PacketTypeParticleAddOrEdit: - case PacketTypeParticleErase: - return true; - default: - return false; - } -} - -class FindAndDeleteParticlesArgs { -public: - QList _idsToDelete; -}; - -bool ParticleTree::findAndDeleteOperation(OctreeElement* element, void* extraData) { - //qDebug() << "findAndDeleteOperation()"; - - FindAndDeleteParticlesArgs* args = static_cast< FindAndDeleteParticlesArgs*>(extraData); - - // if we've found and deleted all our target particles, then we can stop looking - if (args->_idsToDelete.size() <= 0) { - return false; - } - - ParticleTreeElement* particleTreeElement = static_cast(element); - - //qDebug() << "findAndDeleteOperation() args->_idsToDelete.size():" << args->_idsToDelete.size(); - - for (QList::iterator it = args->_idsToDelete.begin(); it != args->_idsToDelete.end(); it++) { - uint32_t particleID = *it; - //qDebug() << "findAndDeleteOperation() particleID:" << particleID; - - if (particleTreeElement->removeParticleWithID(particleID)) { - // if the particle was in this element, then remove it from our search list. - //qDebug() << "findAndDeleteOperation() it = args->_idsToDelete.erase(it)"; - it = args->_idsToDelete.erase(it); - } - - if (it == args->_idsToDelete.end()) { - //qDebug() << "findAndDeleteOperation() breaking"; - break; - } - } - - // if we've found and deleted all our target particles, then we can stop looking - if (args->_idsToDelete.size() <= 0) { - return false; - } - return true; -} - - -class FindAndUpdateParticleArgs { -public: - const Particle& searchParticle; - bool found; -}; - -bool ParticleTree::findAndUpdateOperation(OctreeElement* element, void* extraData) { - FindAndUpdateParticleArgs* args = static_cast(extraData); - ParticleTreeElement* particleTreeElement = static_cast(element); - // Note: updateParticle() will only operate on correctly found particles - if (particleTreeElement->updateParticle(args->searchParticle)) { - args->found = true; - return false; // stop searching - } - return true; -} - -void ParticleTree::storeParticle(const Particle& particle, const SharedNodePointer& senderNode) { - // First, look for the existing particle in the tree.. - FindAndUpdateParticleArgs args = { particle, false }; - recurseTreeWithOperation(findAndUpdateOperation, &args); - - // if we didn't find it in the tree, then store it... - if (!args.found) { - glm::vec3 position = particle.getPosition(); - float size = std::max(MINIMUM_PARTICLE_ELEMENT_SIZE, particle.getRadius()); - - ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size); - element->storeParticle(particle); - } - // what else do we need to do here to get reaveraging to work - _isDirty = true; -} - -class FindAndUpdateParticleWithIDandPropertiesArgs { -public: - const ParticleID& particleID; - const ParticleProperties& properties; - bool found; -}; - -bool ParticleTree::findAndUpdateWithIDandPropertiesOperation(OctreeElement* element, void* extraData) { - FindAndUpdateParticleWithIDandPropertiesArgs* args = static_cast(extraData); - ParticleTreeElement* particleTreeElement = static_cast(element); - // Note: updateParticle() will only operate on correctly found particles - if (particleTreeElement->updateParticle(args->particleID, args->properties)) { - args->found = true; - return false; // stop searching - } - - // if we've found our particle stop searching - if (args->found) { - return false; - } - - return true; -} - -void ParticleTree::updateParticle(const ParticleID& particleID, const ParticleProperties& properties) { - // First, look for the existing particle in the tree.. - FindAndUpdateParticleWithIDandPropertiesArgs args = { particleID, properties, false }; - recurseTreeWithOperation(findAndUpdateWithIDandPropertiesOperation, &args); - // if we found it in the tree, then mark the tree as dirty - if (args.found) { - _isDirty = true; - } -} - -void ParticleTree::addParticle(const ParticleID& particleID, const ParticleProperties& properties) { - // This only operates on locally created particles - if (particleID.isKnownID) { - return; // not allowed - } - Particle particle(particleID, properties); - glm::vec3 position = particle.getPosition(); - float size = std::max(MINIMUM_PARTICLE_ELEMENT_SIZE, particle.getRadius()); - - ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size); - element->storeParticle(particle); - - _isDirty = true; -} - -void ParticleTree::deleteParticle(const ParticleID& particleID) { - if (particleID.isKnownID) { - FindAndDeleteParticlesArgs args; - args._idsToDelete.push_back(particleID.id); - recurseTreeWithOperation(findAndDeleteOperation, &args); - } -} - -// scans the tree and handles mapping locally created particles to know IDs. -// in the event that this tree is also viewing the scene, then we need to also -// search the tree to make sure we don't have a duplicate particle from the viewing -// operation. -bool ParticleTree::findAndUpdateParticleIDOperation(OctreeElement* element, void* extraData) { - bool keepSearching = true; - - FindAndUpdateParticleIDArgs* args = static_cast(extraData); - ParticleTreeElement* particleTreeElement = static_cast(element); - - // Note: updateParticleID() will only operate on correctly found particles - particleTreeElement->updateParticleID(args); - - // if we've found and replaced both the creatorTokenID and the viewedParticle, then we - // can stop looking, otherwise we will keep looking - if (args->creatorTokenFound && args->viewedParticleFound) { - keepSearching = false; - } - - return keepSearching; -} - -void ParticleTree::handleAddParticleResponse(const QByteArray& packet) { - int numBytesPacketHeader = numBytesForPacketHeader(packet); - - const unsigned char* dataAt = reinterpret_cast(packet.data()) + numBytesPacketHeader; - - uint32_t creatorTokenID; - memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID)); - dataAt += sizeof(creatorTokenID); - - uint32_t particleID; - memcpy(&particleID, dataAt, sizeof(particleID)); - dataAt += sizeof(particleID); - - // update particles in our tree - bool assumeParticleFound = !getIsViewing(); // if we're not a viewing tree, then we don't have to find the actual particle - FindAndUpdateParticleIDArgs args = { - particleID, - creatorTokenID, - false, - assumeParticleFound, - getIsViewing() - }; - - const bool wantDebug = false; - if (wantDebug) { - qDebug() << "looking for creatorTokenID=" << creatorTokenID << " particleID=" << particleID - << " getIsViewing()=" << getIsViewing(); - } - lockForWrite(); - recurseTreeWithOperation(findAndUpdateParticleIDOperation, &args); - unlock(); -} - - -class FindNearPointArgs { -public: - glm::vec3 position; - float targetRadius; - bool found; - const Particle* closestParticle; - float closestParticleDistance; -}; - - -bool ParticleTree::findNearPointOperation(OctreeElement* element, void* extraData) { - FindNearPointArgs* args = static_cast(extraData); - ParticleTreeElement* particleTreeElement = static_cast(element); - - glm::vec3 penetration; - bool sphereIntersection = particleTreeElement->getAACube().findSpherePenetration(args->position, - args->targetRadius, penetration); - - // If this particleTreeElement contains the point, then search it... - if (sphereIntersection) { - const Particle* thisClosestParticle = particleTreeElement->getClosestParticle(args->position); - - // we may have gotten NULL back, meaning no particle was available - if (thisClosestParticle) { - glm::vec3 particlePosition = thisClosestParticle->getPosition(); - float distanceFromPointToParticle = glm::distance(particlePosition, args->position); - - // If we're within our target radius - if (distanceFromPointToParticle <= args->targetRadius) { - // we are closer than anything else we've found - if (distanceFromPointToParticle < args->closestParticleDistance) { - args->closestParticle = thisClosestParticle; - args->closestParticleDistance = distanceFromPointToParticle; - args->found = true; - } - } - } - - // we should be able to optimize this... - return true; // keep searching in case children have closer particles - } - - // if this element doesn't contain the point, then none of it's children can contain the point, so stop searching - return false; -} - -const Particle* ParticleTree::findClosestParticle(glm::vec3 position, float targetRadius) { - FindNearPointArgs args = { position, targetRadius, false, NULL, FLT_MAX }; - lockForRead(); - recurseTreeWithOperation(findNearPointOperation, &args); - unlock(); - return args.closestParticle; -} - -class FindAllNearPointArgs { -public: - glm::vec3 position; - float targetRadius; - QVector particles; -}; - - -bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData) { - FindAllNearPointArgs* args = static_cast(extraData); - glm::vec3 penetration; - bool sphereIntersection = element->getAACube().findSpherePenetration(args->position, - args->targetRadius, penetration); - - // If this element contains the point, then search it... - if (sphereIntersection) { - ParticleTreeElement* particleTreeElement = static_cast(element); - particleTreeElement->getParticles(args->position, args->targetRadius, args->particles); - return true; // keep searching in case children have closer particles - } - - // if this element doesn't contain the point, then none of it's children can contain the point, so stop searching - return false; -} - -void ParticleTree::findParticles(const glm::vec3& center, float radius, QVector& foundParticles) { - FindAllNearPointArgs args = { center, radius }; - lockForRead(); - recurseTreeWithOperation(findInSphereOperation, &args); - unlock(); - // swap the two lists of particle pointers instead of copy - foundParticles.swap(args.particles); -} - -class FindParticlesInCubeArgs { -public: - FindParticlesInCubeArgs(const AACube& cube) - : _cube(cube), _foundParticles() { - } - - AACube _cube; - QVector _foundParticles; -}; - -bool ParticleTree::findInCubeOperation(OctreeElement* element, void* extraData) { - FindParticlesInCubeArgs* args = static_cast< FindParticlesInCubeArgs*>(extraData); - const AACube& elementBox = element->getAACube(); - if (elementBox.touches(args->_cube)) { - ParticleTreeElement* particleTreeElement = static_cast(element); - particleTreeElement->getParticles(args->_cube, args->_foundParticles); - return true; - } - return false; -} - -void ParticleTree::findParticles(const AACube& cube, QVector foundParticles) { - FindParticlesInCubeArgs args(cube); - lockForRead(); - recurseTreeWithOperation(findInCubeOperation, &args); - unlock(); - // swap the two lists of particle pointers instead of copy - foundParticles.swap(args._foundParticles); -} - -class FindByIDArgs { -public: - uint32_t id; - bool found; - const Particle* foundParticle; -}; - - -bool ParticleTree::findByIDOperation(OctreeElement* element, void* extraData) { -//qDebug() << "ParticleTree::findByIDOperation()...."; - - FindByIDArgs* args = static_cast(extraData); - ParticleTreeElement* particleTreeElement = static_cast(element); - - // if already found, stop looking - if (args->found) { - return false; - } - - // as the tree element if it has this particle - const Particle* foundParticle = particleTreeElement->getParticleWithID(args->id); - if (foundParticle) { - args->foundParticle = foundParticle; - args->found = true; - return false; - } - - // keep looking - return true; -} - - -const Particle* ParticleTree::findParticleByID(uint32_t id, bool alreadyLocked) { - FindByIDArgs args = { id, false, NULL }; - - if (!alreadyLocked) { - lockForRead(); - } - recurseTreeWithOperation(findByIDOperation, &args); - if (!alreadyLocked) { - unlock(); - } - return args.foundParticle; -} - - -int ParticleTree::processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, - const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode) { - - int processedBytes = 0; - // we handle these types of "edit" packets - switch (packetType) { - case PacketTypeParticleAddOrEdit: { - bool isValid; - Particle newParticle = Particle::fromEditPacket(editData, maxLength, processedBytes, this, isValid); - if (isValid) { - storeParticle(newParticle, senderNode); - if (newParticle.isNewlyCreated()) { - notifyNewlyCreatedParticle(newParticle, senderNode); - } - } - } break; - - // TODO: wire in support here for server to get PACKET_TYPE_PARTICLE_ERASE messages - // instead of using PACKET_TYPE_PARTICLE_ADD_OR_EDIT messages to delete particles - case PacketTypeParticleErase: - processedBytes = 0; - break; - default: - processedBytes = 0; - break; - } - - return processedBytes; -} - -void ParticleTree::notifyNewlyCreatedParticle(const Particle& newParticle, const SharedNodePointer& senderNode) { - _newlyCreatedHooksLock.lockForRead(); - for (size_t i = 0; i < _newlyCreatedHooks.size(); i++) { - _newlyCreatedHooks[i]->particleCreated(newParticle, senderNode); - } - _newlyCreatedHooksLock.unlock(); -} - -void ParticleTree::addNewlyCreatedHook(NewlyCreatedParticleHook* hook) { - _newlyCreatedHooksLock.lockForWrite(); - _newlyCreatedHooks.push_back(hook); - _newlyCreatedHooksLock.unlock(); -} - -void ParticleTree::removeNewlyCreatedHook(NewlyCreatedParticleHook* hook) { - _newlyCreatedHooksLock.lockForWrite(); - for (size_t i = 0; i < _newlyCreatedHooks.size(); i++) { - if (_newlyCreatedHooks[i] == hook) { - _newlyCreatedHooks.erase(_newlyCreatedHooks.begin() + i); - break; - } - } - _newlyCreatedHooksLock.unlock(); -} - - -bool ParticleTree::updateOperation(OctreeElement* element, void* extraData) { - ParticleTreeUpdateArgs* args = static_cast(extraData); - ParticleTreeElement* particleTreeElement = static_cast(element); - particleTreeElement->update(*args); - return true; -} - -bool ParticleTree::pruneOperation(OctreeElement* element, void* extraData) { - ParticleTreeElement* particleTreeElement = static_cast(element); - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - ParticleTreeElement* childAt = particleTreeElement->getChildAtIndex(i); - if (childAt && childAt->isLeaf() && !childAt->hasParticles()) { - particleTreeElement->deleteChildAtIndex(i); - } - } - return true; -} - -void ParticleTree::update() { - lockForWrite(); - _isDirty = true; - - ParticleTreeUpdateArgs args = { }; - recurseTreeWithOperation(updateOperation, &args); - - // now add back any of the particles that moved elements.... - int movingParticles = args._movingParticles.size(); - for (int i = 0; i < movingParticles; i++) { - bool shouldDie = args._movingParticles[i].getShouldDie(); - - // if the particle is still inside our total bounds, then re-add it - AACube treeBounds = getRoot()->getAACube(); - - if (!shouldDie && treeBounds.contains(args._movingParticles[i].getPosition())) { - storeParticle(args._movingParticles[i]); - } else { - uint32_t particleID = args._movingParticles[i].getID(); - quint64 deletedAt = usecTimestampNow(); - _recentlyDeletedParticlesLock.lockForWrite(); - _recentlyDeletedParticleIDs.insert(deletedAt, particleID); - _recentlyDeletedParticlesLock.unlock(); - } - } - - // prune the tree... - recurseTreeWithOperation(pruneOperation, NULL); - unlock(); -} - - -bool ParticleTree::hasParticlesDeletedSince(quint64 sinceTime) { - // we can probably leverage the ordered nature of QMultiMap to do this quickly... - bool hasSomethingNewer = false; - - _recentlyDeletedParticlesLock.lockForRead(); - QMultiMap::const_iterator iterator = _recentlyDeletedParticleIDs.constBegin(); - while (iterator != _recentlyDeletedParticleIDs.constEnd()) { - //qDebug() << "considering... time/key:" << iterator.key(); - if (iterator.key() > sinceTime) { - //qDebug() << "YES newer... time/key:" << iterator.key(); - hasSomethingNewer = true; - } - ++iterator; - } - _recentlyDeletedParticlesLock.unlock(); - return hasSomethingNewer; -} - -// sinceTime is an in/out parameter - it will be side effected with the last time sent out -bool ParticleTree::encodeParticlesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, unsigned char* outputBuffer, - size_t maxLength, size_t& outputLength) { - - bool hasMoreToSend = true; - - unsigned char* copyAt = outputBuffer; - size_t numBytesPacketHeader = populatePacketHeader(reinterpret_cast(outputBuffer), PacketTypeParticleErase); - copyAt += numBytesPacketHeader; - outputLength = numBytesPacketHeader; - - // pack in flags - OCTREE_PACKET_FLAGS flags = 0; - memcpy(copyAt, &flags, sizeof(OCTREE_PACKET_FLAGS)); - copyAt += sizeof(OCTREE_PACKET_FLAGS); - outputLength += sizeof(OCTREE_PACKET_FLAGS); - - // pack in sequence number - memcpy(copyAt, &sequenceNumber, sizeof(OCTREE_PACKET_SEQUENCE)); - copyAt += sizeof(OCTREE_PACKET_SEQUENCE); - outputLength += sizeof(OCTREE_PACKET_SEQUENCE); - - // pack in timestamp - OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); - memcpy(copyAt, &now, sizeof(OCTREE_PACKET_SENT_TIME)); - copyAt += sizeof(OCTREE_PACKET_SENT_TIME); - outputLength += sizeof(OCTREE_PACKET_SENT_TIME); - - - uint16_t numberOfIds = 0; // placeholder for now - unsigned char* numberOfIDsAt = copyAt; - memcpy(copyAt, &numberOfIds, sizeof(numberOfIds)); - copyAt += sizeof(numberOfIds); - outputLength += sizeof(numberOfIds); - - // we keep a multi map of particle IDs to timestamps, we only want to include the particle IDs that have been - // deleted since we last sent to this node - _recentlyDeletedParticlesLock.lockForRead(); - QMultiMap::const_iterator iterator = _recentlyDeletedParticleIDs.constBegin(); - while (iterator != _recentlyDeletedParticleIDs.constEnd()) { - QList values = _recentlyDeletedParticleIDs.values(iterator.key()); - for (int valueItem = 0; valueItem < values.size(); ++valueItem) { - - // if the timestamp is more recent then out last sent time, include it - if (iterator.key() > sinceTime) { - uint32_t particleID = values.at(valueItem); - memcpy(copyAt, &particleID, sizeof(particleID)); - copyAt += sizeof(particleID); - outputLength += sizeof(particleID); - numberOfIds++; - - // check to make sure we have room for one more id... - if (outputLength + sizeof(uint32_t) > maxLength) { - break; - } - } - } - - // check to make sure we have room for one more id... - if (outputLength + sizeof(uint32_t) > maxLength) { - - // let our caller know how far we got - sinceTime = iterator.key(); - break; - } - ++iterator; - } - - // if we got to the end, then we're done sending - if (iterator == _recentlyDeletedParticleIDs.constEnd()) { - hasMoreToSend = false; - } - _recentlyDeletedParticlesLock.unlock(); - - // replace the correct count for ids included - memcpy(numberOfIDsAt, &numberOfIds, sizeof(numberOfIds)); - - return hasMoreToSend; -} - -// called by the server when it knows all nodes have been sent deleted packets - -void ParticleTree::forgetParticlesDeletedBefore(quint64 sinceTime) { - //qDebug() << "forgetParticlesDeletedBefore()"; - QSet keysToRemove; - - _recentlyDeletedParticlesLock.lockForWrite(); - QMultiMap::iterator iterator = _recentlyDeletedParticleIDs.begin(); - - // First find all the keys in the map that are older and need to be deleted - while (iterator != _recentlyDeletedParticleIDs.end()) { - if (iterator.key() <= sinceTime) { - keysToRemove << iterator.key(); - } - ++iterator; - } - - // Now run through the keysToRemove and remove them - foreach (quint64 value, keysToRemove) { - //qDebug() << "removing the key, _recentlyDeletedParticleIDs.remove(value); time/key:" << value; - _recentlyDeletedParticleIDs.remove(value); - } - - _recentlyDeletedParticlesLock.unlock(); -} - - -void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { - - const unsigned char* packetData = (const unsigned char*)dataByteArray.constData(); - const unsigned char* dataAt = packetData; - size_t packetLength = dataByteArray.size(); - - size_t numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); - size_t processedBytes = numBytesPacketHeader; - dataAt += numBytesPacketHeader; - - dataAt += sizeof(OCTREE_PACKET_FLAGS); - dataAt += sizeof(OCTREE_PACKET_SEQUENCE); - dataAt += sizeof(OCTREE_PACKET_SENT_TIME); - - uint16_t numberOfIds = 0; // placeholder for now - memcpy(&numberOfIds, dataAt, sizeof(numberOfIds)); - dataAt += sizeof(numberOfIds); - processedBytes += sizeof(numberOfIds); - - if (numberOfIds > 0) { - FindAndDeleteParticlesArgs args; - - for (size_t i = 0; i < numberOfIds; i++) { - if (processedBytes + sizeof(uint32_t) > packetLength) { - break; // bail to prevent buffer overflow - } - - uint32_t particleID = 0; // placeholder for now - memcpy(&particleID, dataAt, sizeof(particleID)); - dataAt += sizeof(particleID); - processedBytes += sizeof(particleID); - - args._idsToDelete.push_back(particleID); - } - - // calling recurse to actually delete the particles - recurseTreeWithOperation(findAndDeleteOperation, &args); - } -} diff --git a/libraries/particles/src/ParticleTree.h b/libraries/particles/src/ParticleTree.h deleted file mode 100644 index 9cb3e637f3..0000000000 --- a/libraries/particles/src/ParticleTree.h +++ /dev/null @@ -1,100 +0,0 @@ -// -// ParticleTree.h -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/4/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_ParticleTree_h -#define hifi_ParticleTree_h - -#include -#include "ParticleTreeElement.h" - -class NewlyCreatedParticleHook { -public: - virtual void particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode) = 0; -}; - -class ParticleTree : public Octree { - Q_OBJECT -public: - ParticleTree(bool shouldReaverage = false); - - /// Implements our type specific root element factory - virtual ParticleTreeElement* createNewElement(unsigned char * octalCode = NULL); - - /// Type safe version of getRoot() - ParticleTreeElement* getRoot() { return static_cast(_rootElement); } - - - // These methods will allow the OctreeServer to send your tree inbound edit packets of your - // own definition. Implement these to allow your octree based server to support editing - virtual bool getWantSVOfileVersions() const { return true; } - virtual PacketType expectedDataPacketType() const { return PacketTypeParticleData; } - 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& senderNode); - - virtual void update(); - - void storeParticle(const Particle& particle, const SharedNodePointer& senderNode = SharedNodePointer()); - void updateParticle(const ParticleID& particleID, const ParticleProperties& properties); - void addParticle(const ParticleID& particleID, const ParticleProperties& properties); - void deleteParticle(const ParticleID& particleID); - const Particle* findClosestParticle(glm::vec3 position, float targetRadius); - const Particle* findParticleByID(uint32_t id, bool alreadyLocked = false); - - /// finds all particles that touch a sphere - /// \param center the center of the sphere - /// \param radius the radius of the sphere - /// \param foundParticles[out] vector of const Particle* - /// \remark Side effect: any initial contents in foundParticles will be lost - void findParticles(const glm::vec3& center, float radius, QVector& foundParticles); - - /// finds all particles that touch a box - /// \param box the query box - /// \param foundParticles[out] vector of non-const Particle* - /// \remark Side effect: any initial contents in particles will be lost - void findParticles(const AACube& box, QVector foundParticles); - - void addNewlyCreatedHook(NewlyCreatedParticleHook* hook); - void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook); - - bool hasAnyDeletedParticles() const { return _recentlyDeletedParticleIDs.size() > 0; } - bool hasParticlesDeletedSince(quint64 sinceTime); - bool encodeParticlesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, unsigned char* packetData, size_t maxLength, size_t& outputLength); - void forgetParticlesDeletedBefore(quint64 sinceTime); - - void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); - void handleAddParticleResponse(const QByteArray& packet); - -private: - - static bool updateOperation(OctreeElement* element, void* extraData); - static bool findAndUpdateOperation(OctreeElement* element, void* extraData); - static bool findAndUpdateWithIDandPropertiesOperation(OctreeElement* element, void* extraData); - static bool findNearPointOperation(OctreeElement* element, void* extraData); - static bool findInSphereOperation(OctreeElement* element, void* extraData); - static bool pruneOperation(OctreeElement* element, void* extraData); - static bool findByIDOperation(OctreeElement* element, void* extraData); - static bool findAndDeleteOperation(OctreeElement* element, void* extraData); - static bool findAndUpdateParticleIDOperation(OctreeElement* element, void* extraData); - - static bool findInCubeOperation(OctreeElement* element, void* extraData); - - void notifyNewlyCreatedParticle(const Particle& newParticle, const SharedNodePointer& senderNode); - - QReadWriteLock _newlyCreatedHooksLock; - std::vector _newlyCreatedHooks; - - - QReadWriteLock _recentlyDeletedParticlesLock; - QMultiMap _recentlyDeletedParticleIDs; -}; - -#endif // hifi_ParticleTree_h diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp deleted file mode 100644 index 9d3826d8c2..0000000000 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ /dev/null @@ -1,343 +0,0 @@ -// -// ParticleTreeElement.cpp -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/4/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 "ParticleTree.h" -#include "ParticleTreeElement.h" - -ParticleTreeElement::ParticleTreeElement(unsigned char* octalCode) : OctreeElement(), _particles(NULL) { - init(octalCode); -}; - -ParticleTreeElement::~ParticleTreeElement() { - _voxelMemoryUsage -= sizeof(ParticleTreeElement); - QList* tmpParticles = _particles; - _particles = NULL; - delete tmpParticles; -} - -// 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* ParticleTreeElement::createNewElement(unsigned char* octalCode) { - ParticleTreeElement* newChild = new ParticleTreeElement(octalCode); - newChild->setTree(_myTree); - return newChild; -} - -void ParticleTreeElement::init(unsigned char* octalCode) { - OctreeElement::init(octalCode); - _particles = new QList; - _voxelMemoryUsage += sizeof(ParticleTreeElement); -} - -ParticleTreeElement* ParticleTreeElement::addChildAtIndex(int index) { - ParticleTreeElement* newElement = (ParticleTreeElement*)OctreeElement::addChildAtIndex(index); - newElement->setTree(_myTree); - return newElement; -} - - -OctreeElement::AppendState ParticleTreeElement::appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const { - bool success = true; // assume the best... - - // write our particles out... - uint16_t numberOfParticles = _particles->size(); - success = packetData->appendValue(numberOfParticles); - - if (success) { - for (uint16_t i = 0; i < numberOfParticles; i++) { - const Particle& particle = (*_particles)[i]; - success = particle.appendParticleData(packetData); - if (!success) { - break; - } - } - } - return success ? OctreeElement::COMPLETED : OctreeElement::NONE; -} - -void ParticleTreeElement::update(ParticleTreeUpdateArgs& args) { - markWithChangedTime(); - // TODO: early exit when _particles is empty - - // update our contained particles - QList::iterator particleItr = _particles->begin(); - while(particleItr != _particles->end()) { - Particle& particle = (*particleItr); - particle.update(_lastChanged); - - // If the particle wants to die, or if it's left our bounding box, then move it - // into the arguments moving particles. These will be added back or deleted completely - if (particle.getShouldDie() || !_cube.contains(particle.getPosition())) { - args._movingParticles.push_back(particle); - - // erase this particle - particleItr = _particles->erase(particleItr); - } else { - ++particleItr; - } - } - // TODO: if _particles is empty after while loop consider freeing memory in _particles if - // internal array is too big (QList internal array does not decrease size except in dtor and - // assignment operator). Otherwise _particles could become a "resource leak" for large - // roaming piles of particles. -} - -bool ParticleTreeElement::findSpherePenetration(const glm::vec3& center, float radius, - glm::vec3& penetration, void** penetratedObject) const { - QList::iterator particleItr = _particles->begin(); - QList::const_iterator particleEnd = _particles->end(); - while(particleItr != particleEnd) { - Particle& particle = (*particleItr); - glm::vec3 particleCenter = particle.getPosition(); - float particleRadius = particle.getRadius(); - - // don't penetrate yourself - if (particleCenter == center && particleRadius == radius) { - return false; - } - - // We've considered making "inHand" particles not collide, if we want to do that, - // we should change this setting... but now, we do allow inHand particles to collide - const bool IN_HAND_PARTICLES_DONT_COLLIDE = false; - if (IN_HAND_PARTICLES_DONT_COLLIDE) { - // don't penetrate if the particle is "inHand" -- they don't collide - if (particle.getInHand()) { - ++particleItr; - continue; - } - } - - if (findSphereSpherePenetration(center, radius, particleCenter, particleRadius, penetration)) { - // return true on first valid particle penetration - *penetratedObject = (void*)(&particle); - return true; - } - ++particleItr; - } - return false; -} - -bool ParticleTreeElement::updateParticle(const Particle& particle) { - // NOTE: this method must first lookup the particle by ID, hence it is O(N) - // and "particle is not found" is worst-case (full N) but maybe we don't care? - // (guaranteed that num particles per elemen is small?) - const bool wantDebug = false; - uint16_t numberOfParticles = _particles->size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - Particle& thisParticle = (*_particles)[i]; - if (thisParticle.getID() == particle.getID()) { - int difference = thisParticle.getLastUpdated() - particle.getLastUpdated(); - bool changedOnServer = thisParticle.getLastEdited() < particle.getLastEdited(); - bool localOlder = thisParticle.getLastUpdated() < particle.getLastUpdated(); - if (changedOnServer || localOlder) { - if (wantDebug) { - qDebug("local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s", - particle.getID(), (changedOnServer ? "CHANGED" : "same"), - (localOlder ? "OLDER" : "NEWER"), - difference, debug::valueOf(particle.isNewlyCreated()) ); - } - thisParticle.copyChangedProperties(particle); - } else { - if (wantDebug) { - qDebug(">>> IGNORING SERVER!!! Would've caused jutter! <<< " - "local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s", - particle.getID(), (changedOnServer ? "CHANGED" : "same"), - (localOlder ? "OLDER" : "NEWER"), - difference, debug::valueOf(particle.isNewlyCreated()) ); - } - } - return true; - } - } - return false; -} - -bool ParticleTreeElement::updateParticle(const ParticleID& particleID, const ParticleProperties& properties) { - uint16_t numberOfParticles = _particles->size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - // note: unlike storeParticle() which is called from inbound packets, this is only called by local editors - // and therefore we can be confident that this change is higher priority and should be honored - Particle& thisParticle = (*_particles)[i]; - - bool found = false; - if (particleID.isKnownID) { - found = thisParticle.getID() == particleID.id; - } else { - found = thisParticle.getCreatorTokenID() == particleID.creatorTokenID; - } - if (found) { - thisParticle.setProperties(properties); - - const bool wantDebug = false; - if (wantDebug) { - uint64_t now = usecTimestampNow(); - int elapsed = now - thisParticle.getLastEdited(); - - qDebug() << "ParticleTreeElement::updateParticle() AFTER update... edited AGO=" << elapsed << - "now=" << now << " thisParticle.getLastEdited()=" << thisParticle.getLastEdited(); - } - return true; - } - } - return false; -} - -void ParticleTreeElement::updateParticleID(FindAndUpdateParticleIDArgs* args) { - uint16_t numberOfParticles = _particles->size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - Particle& thisParticle = (*_particles)[i]; - - if (!args->creatorTokenFound) { - // first, we're looking for matching creatorTokenIDs, if we find that, then we fix it to know the actual ID - if (thisParticle.getCreatorTokenID() == args->creatorTokenID) { - thisParticle.setID(args->particleID); - args->creatorTokenFound = true; - } - } - - // if we're in an isViewing tree, we also need to look for an kill any viewed particles - if (!args->viewedParticleFound && args->isViewing) { - if (thisParticle.getCreatorTokenID() == UNKNOWN_TOKEN && thisParticle.getID() == args->particleID) { - _particles->removeAt(i); // remove the particle at this index - numberOfParticles--; // this means we have 1 fewer particle in this list - i--; // and we actually want to back up i as well. - args->viewedParticleFound = true; - } - } - } -} - - - -const Particle* ParticleTreeElement::getClosestParticle(glm::vec3 position) const { - const Particle* closestParticle = NULL; - float closestParticleDistance = FLT_MAX; - uint16_t numberOfParticles = _particles->size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - float distanceToParticle = glm::distance(position, (*_particles)[i].getPosition()); - if (distanceToParticle < closestParticleDistance) { - closestParticle = &(*_particles)[i]; - } - } - return closestParticle; -} - -void ParticleTreeElement::getParticles(const glm::vec3& searchPosition, float searchRadius, QVector& foundParticles) const { - uint16_t numberOfParticles = _particles->size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - const Particle* particle = &(*_particles)[i]; - float distance = glm::length(particle->getPosition() - searchPosition); - if (distance < searchRadius + particle->getRadius()) { - foundParticles.push_back(particle); - } - } -} - -void ParticleTreeElement::getParticles(const AACube& box, QVector& foundParticles) { - QList::iterator particleItr = _particles->begin(); - QList::iterator particleEnd = _particles->end(); - AACube particleCube; - while(particleItr != particleEnd) { - Particle* particle = &(*particleItr); - float radius = particle->getRadius(); - // NOTE: we actually do box-box collision queries here, which is sloppy but good enough for now - // TODO: decide whether to replace particleBox-box query with sphere-box (requires a square root - // but will be slightly more accurate). - particleCube.setBox(particle->getPosition() - glm::vec3(radius), 2.f * radius); - if (particleCube.touches(_cube)) { - foundParticles.push_back(particle); - } - ++particleItr; - } -} - -const Particle* ParticleTreeElement::getParticleWithID(uint32_t id) const { - // NOTE: this lookup is O(N) but maybe we don't care? (guaranteed that num particles per elemen is small?) - const Particle* foundParticle = NULL; - uint16_t numberOfParticles = _particles->size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - if ((*_particles)[i].getID() == id) { - foundParticle = &(*_particles)[i]; - break; - } - } - return foundParticle; -} - -bool ParticleTreeElement::removeParticleWithID(uint32_t id) { - bool foundParticle = false; - if (_particles) { - uint16_t numberOfParticles = _particles->size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - if ((*_particles)[i].getID() == id) { - foundParticle = true; - _particles->removeAt(i); - break; - } - } - } - return foundParticle; -} - -int ParticleTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, - ReadBitstreamToTreeParams& args) { - - const unsigned char* dataAt = data; - int bytesRead = 0; - uint16_t numberOfParticles = 0; - int expectedBytesPerParticle = Particle::expectedBytes(); - - if (bytesLeftToRead >= (int)sizeof(numberOfParticles)) { - // read our particles in.... - numberOfParticles = *(uint16_t*)dataAt; - dataAt += sizeof(numberOfParticles); - bytesLeftToRead -= (int)sizeof(numberOfParticles); - bytesRead += sizeof(numberOfParticles); - - if (bytesLeftToRead >= (int)(numberOfParticles * expectedBytesPerParticle)) { - for (uint16_t i = 0; i < numberOfParticles; i++) { - Particle tempParticle; - int bytesForThisParticle = tempParticle.readParticleDataFromBuffer(dataAt, bytesLeftToRead, args); - _myTree->storeParticle(tempParticle); - dataAt += bytesForThisParticle; - bytesLeftToRead -= bytesForThisParticle; - bytesRead += bytesForThisParticle; - } - } - } - - return bytesRead; -} - -// will average a "common reduced LOD view" from the the child elements... -void ParticleTreeElement::calculateAverageFromChildren() { - // nothing to do here yet... -} - -// will detect if children are leaves AND collapsable into the parent node -// and in that case will collapse children and make this node -// a leaf, returns TRUE if all the leaves are collapsed into a -// single node -bool ParticleTreeElement::collapseChildren() { - // nothing to do here yet... - return false; -} - - -void ParticleTreeElement::storeParticle(const Particle& particle) { - _particles->push_back(particle); - markWithChangedTime(); -} - diff --git a/libraries/particles/src/ParticleTreeElement.h b/libraries/particles/src/ParticleTreeElement.h deleted file mode 100644 index bb7e3c72d5..0000000000 --- a/libraries/particles/src/ParticleTreeElement.h +++ /dev/null @@ -1,132 +0,0 @@ -// -// ParticleTreeElement.h -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/4/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_ParticleTreeElement_h -#define hifi_ParticleTreeElement_h - -//#include - -#include -#include - -#include "Particle.h" -#include "ParticleTree.h" - -class ParticleTree; -class ParticleTreeElement; - -class ParticleTreeUpdateArgs { -public: - QList _movingParticles; -}; - -class FindAndUpdateParticleIDArgs { -public: - uint32_t particleID; - uint32_t creatorTokenID; - bool creatorTokenFound; - bool viewedParticleFound; - bool isViewing; -}; - - - -class ParticleTreeElement : public OctreeElement { - friend class ParticleTree; // to allow createElement to new us... - - ParticleTreeElement(unsigned char* octalCode = NULL); - - virtual OctreeElement* createNewElement(unsigned char* octalCode = NULL); - -public: - virtual ~ParticleTreeElement(); - - // type safe versions of OctreeElement methods - ParticleTreeElement* getChildAtIndex(int index) { return (ParticleTreeElement*)OctreeElement::getChildAtIndex(index); } - - // methods you can and should override to implement your tree functionality - - /// Adds a child to the current element. Override this if there is additional child initialization your class needs. - virtual ParticleTreeElement* addChildAtIndex(int index); - - /// Override this to implement LOD averaging on changes to the tree. - virtual void calculateAverageFromChildren(); - - /// Override this to implement LOD collapsing and identical child pruning on changes to the tree. - virtual bool collapseChildren(); - - /// Should this element be considered to have content in it. This will be used in collision and ray casting methods. - /// By default we assume that only leaves are actual content, but some octrees may have different semantics. - virtual bool hasContent() const { return isLeaf(); } - - /// Override this to break up large octree elements when an edit operation is performed on a smaller octree element. - /// For example, if the octrees represent solid cubes and a delete of a smaller octree element is done then the - /// meaningful split would be to break the larger cube into smaller cubes of the same color/texture. - virtual void splitChildren() { } - - /// Override to indicate that this element requires a split before editing lower elements in the octree - virtual bool requiresSplit() const { return false; } - - /// Override to serialize the state of this element. This is used for persistance and for transmission across the network. - virtual OctreeElement::AppendState appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const; - - /// Override to deserialize the state of this element. This is used for loading from a persisted file or from reading - /// from the network. - virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); - - /// Override to indicate that the item is currently rendered in the rendering engine. By default we assume that if - /// the element should be rendered, then your rendering engine is rendering. But some rendering engines my have cases - /// where an element is not actually rendering all should render elements. If the isRendered() state doesn't match the - /// shouldRender() state, the tree will remark elements as changed even in cases there the elements have not changed. - virtual bool isRendered() const { return getShouldRender(); } - virtual bool deleteApproved() const { return !hasParticles(); } - - virtual bool findSpherePenetration(const glm::vec3& center, float radius, - glm::vec3& penetration, void** penetratedObject) const; - - const QList& getParticles() const { return *_particles; } - QList& getParticles() { return *_particles; } - bool hasParticles() const { return _particles->size() > 0; } - - void update(ParticleTreeUpdateArgs& args); - void setTree(ParticleTree* tree) { _myTree = tree; } - - bool updateParticle(const Particle& particle); - bool updateParticle(const ParticleID& particleID, const ParticleProperties& properties); - void updateParticleID(FindAndUpdateParticleIDArgs* args); - - const Particle* getClosestParticle(glm::vec3 position) const; - - /// finds all particles that touch a sphere - /// \param position the center of the query sphere - /// \param radius the radius of the query sphere - /// \param particles[out] vector of const Particle* - void getParticles(const glm::vec3& position, float radius, QVector& foundParticles) const; - - /// finds all particles that touch a box - /// \param box the query box - /// \param particles[out] vector of non-const Particle* - void getParticles(const AACube& box, QVector& foundParticles); - - const Particle* getParticleWithID(uint32_t id) const; - - bool removeParticleWithID(uint32_t id); - -protected: - virtual void init(unsigned char * octalCode); - - void storeParticle(const Particle& particle); - - ParticleTree* _myTree; - QList* _particles; -}; - -#endif // hifi_ParticleTreeElement_h diff --git a/libraries/particles/src/ParticleTreeHeadlessViewer.cpp b/libraries/particles/src/ParticleTreeHeadlessViewer.cpp deleted file mode 100644 index 1c47447b1a..0000000000 --- a/libraries/particles/src/ParticleTreeHeadlessViewer.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// ParticleTreeHeadlessViewer.cpp -// libraries/particles/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 "ParticleTreeHeadlessViewer.h" - -ParticleTreeHeadlessViewer::ParticleTreeHeadlessViewer() : - OctreeHeadlessViewer() { -} - -ParticleTreeHeadlessViewer::~ParticleTreeHeadlessViewer() { -} - -void ParticleTreeHeadlessViewer::init() { - OctreeHeadlessViewer::init(); -} - - -void ParticleTreeHeadlessViewer::update() { - if (_tree) { - ParticleTree* tree = static_cast(_tree); - if (tree->tryLockForWrite()) { - tree->update(); - tree->unlock(); - } - } -} - -void ParticleTreeHeadlessViewer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { - static_cast(_tree)->processEraseMessage(dataByteArray, sourceNode); -} diff --git a/libraries/particles/src/ParticleTreeHeadlessViewer.h b/libraries/particles/src/ParticleTreeHeadlessViewer.h deleted file mode 100644 index 119c46e202..0000000000 --- a/libraries/particles/src/ParticleTreeHeadlessViewer.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// ParticleTreeHeadlessViewer.h -// libraries/particles/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_ParticleTreeHeadlessViewer_h -#define hifi_ParticleTreeHeadlessViewer_h - -#include -#include -#include -#include -#include -#include "ParticleTree.h" -#include - -// Generic client side Octree renderer class. -class ParticleTreeHeadlessViewer : public OctreeHeadlessViewer { - Q_OBJECT -public: - ParticleTreeHeadlessViewer(); - virtual ~ParticleTreeHeadlessViewer(); - - virtual Octree* createTree() { return new ParticleTree(true); } - virtual char getMyNodeType() const { return NodeType::ParticleServer; } - virtual PacketType getMyQueryMessageType() const { return PacketTypeParticleQuery; } - virtual PacketType getExpectedPacketType() const { return PacketTypeParticleData; } - - void update(); - - ParticleTree* getTree() { return (ParticleTree*)_tree; } - - void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); - - virtual void init(); -}; - -#endif // hifi_ParticleTreeHeadlessViewer_h diff --git a/libraries/particles/src/ParticlesScriptingInterface.cpp b/libraries/particles/src/ParticlesScriptingInterface.cpp deleted file mode 100644 index 4adfed358e..0000000000 --- a/libraries/particles/src/ParticlesScriptingInterface.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// -// ParticlesScriptingInterface.cpp -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/6/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 "ParticlesScriptingInterface.h" -#include "ParticleTree.h" - -ParticlesScriptingInterface::ParticlesScriptingInterface() : - _nextCreatorTokenID(0), - _particleTree(NULL) -{ -} - - -void ParticlesScriptingInterface::queueParticleMessage(PacketType packetType, - ParticleID particleID, const ParticleProperties& properties) { - getParticlePacketSender()->queueParticleEditMessage(packetType, particleID, properties); -} - -ParticleID ParticlesScriptingInterface::addParticle(const ParticleProperties& properties) { - - // The application will keep track of creatorTokenID - uint32_t creatorTokenID = Particle::getNextCreatorTokenID(); - - ParticleID id(NEW_PARTICLE, creatorTokenID, false ); - - // queue the packet - queueParticleMessage(PacketTypeParticleAddOrEdit, id, properties); - - // If we have a local particle tree set, then also update it. - if (_particleTree) { - _particleTree->lockForWrite(); - _particleTree->addParticle(id, properties); - _particleTree->unlock(); - } - - return id; -} - -ParticleID ParticlesScriptingInterface::identifyParticle(ParticleID particleID) { - uint32_t actualID = particleID.id; - - if (!particleID.isKnownID) { - actualID = Particle::getIDfromCreatorTokenID(particleID.creatorTokenID); - if (actualID == UNKNOWN_PARTICLE_ID) { - return particleID; // bailing early - } - - // found it! - particleID.id = actualID; - particleID.isKnownID = true; - } - return particleID; -} - -ParticleProperties ParticlesScriptingInterface::getParticleProperties(ParticleID particleID) { - ParticleProperties results; - ParticleID identity = identifyParticle(particleID); - if (!identity.isKnownID) { - results.setIsUnknownID(); - return results; - } - if (_particleTree) { - _particleTree->lockForRead(); - const Particle* particle = _particleTree->findParticleByID(identity.id, true); - if (particle) { - results.copyFromParticle(*particle); - } else { - results.setIsUnknownID(); - } - _particleTree->unlock(); - } - - return results; -} - - - -ParticleID ParticlesScriptingInterface::editParticle(ParticleID particleID, const ParticleProperties& properties) { - uint32_t actualID = particleID.id; - - // if the particle is unknown, attempt to look it up - if (!particleID.isKnownID) { - actualID = Particle::getIDfromCreatorTokenID(particleID.creatorTokenID); - } - - // if at this point, we know the id, send the update to the particle server - if (actualID != UNKNOWN_PARTICLE_ID) { - particleID.id = actualID; - particleID.isKnownID = true; - queueParticleMessage(PacketTypeParticleAddOrEdit, particleID, properties); - } - - // If we have a local particle tree set, then also update it. We can do this even if we don't know - // the actual id, because we can edit out local particles just with creatorTokenID - if (_particleTree) { - _particleTree->lockForWrite(); - _particleTree->updateParticle(particleID, properties); - _particleTree->unlock(); - } - - return particleID; -} - - -// TODO: This deleteParticle() method uses the PacketType_PARTICLE_ADD_OR_EDIT message to send -// a changed particle with a shouldDie() property set to true. This works and is currently the only -// way to tell the particle server to delete a particle. But we should change this to use the PacketType_PARTICLE_ERASE -// message which takes a list of particle id's to delete. -void ParticlesScriptingInterface::deleteParticle(ParticleID particleID) { - - // setup properties to kill the particle - ParticleProperties properties; - properties.setShouldDie(true); - - uint32_t actualID = particleID.id; - - // if the particle is unknown, attempt to look it up - if (!particleID.isKnownID) { - actualID = Particle::getIDfromCreatorTokenID(particleID.creatorTokenID); - } - - // if at this point, we know the id, send the update to the particle server - if (actualID != UNKNOWN_PARTICLE_ID) { - particleID.id = actualID; - particleID.isKnownID = true; - queueParticleMessage(PacketTypeParticleAddOrEdit, particleID, properties); - } - - // If we have a local particle tree set, then also update it. - if (_particleTree) { - _particleTree->lockForWrite(); - _particleTree->deleteParticle(particleID); - _particleTree->unlock(); - } -} - -ParticleID ParticlesScriptingInterface::findClosestParticle(const glm::vec3& center, float radius) const { - ParticleID result(UNKNOWN_PARTICLE_ID, UNKNOWN_TOKEN, false); - if (_particleTree) { - _particleTree->lockForRead(); - const Particle* closestParticle = _particleTree->findClosestParticle(center/(float)TREE_SCALE, - radius/(float)TREE_SCALE); - _particleTree->unlock(); - if (closestParticle) { - result.id = closestParticle->getID(); - result.isKnownID = true; - } - } - return result; -} - - -QVector ParticlesScriptingInterface::findParticles(const glm::vec3& center, float radius) const { - QVector result; - if (_particleTree) { - _particleTree->lockForRead(); - QVector particles; - _particleTree->findParticles(center/(float)TREE_SCALE, radius/(float)TREE_SCALE, particles); - _particleTree->unlock(); - - foreach (const Particle* particle, particles) { - ParticleID thisParticleID(particle->getID(), UNKNOWN_TOKEN, true); - result << thisParticleID; - } - } - return result; -} - diff --git a/libraries/particles/src/ParticlesScriptingInterface.h b/libraries/particles/src/ParticlesScriptingInterface.h deleted file mode 100644 index e1d628f45a..0000000000 --- a/libraries/particles/src/ParticlesScriptingInterface.h +++ /dev/null @@ -1,73 +0,0 @@ -// -// ParticlesScriptingInterface.h -// libraries/particles/src -// -// Created by Brad Hefta-Gaub on 12/6/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_ParticlesScriptingInterface_h -#define hifi_ParticlesScriptingInterface_h - -#include - -#include - -#include -#include "ParticleEditPacketSender.h" - -/// handles scripting of Particle commands from JS passed to assigned clients -class ParticlesScriptingInterface : public OctreeScriptingInterface { - Q_OBJECT -public: - ParticlesScriptingInterface(); - - ParticleEditPacketSender* getParticlePacketSender() const { return (ParticleEditPacketSender*)getPacketSender(); } - virtual NodeType_t getServerNodeType() const { return NodeType::ParticleServer; } - virtual OctreeEditPacketSender* createPacketSender() { return new ParticleEditPacketSender(); } - - void setParticleTree(ParticleTree* particleTree) { _particleTree = particleTree; } - ParticleTree* getParticleTree(ParticleTree*) { return _particleTree; } - -public slots: - /// adds a particle with the specific properties - ParticleID addParticle(const ParticleProperties& properties); - - /// identify a recently created particle to determine its true ID - ParticleID identifyParticle(ParticleID particleID); - - /// gets the current particle properties for a specific particle - /// this function will not find return results in script engine contexts which don't have access to particles - ParticleProperties getParticleProperties(ParticleID particleID); - - /// edits a particle updating only the included properties, will return the identified ParticleID in case of - /// successful edit, if the input particleID is for an unknown particle this function will have no effect - ParticleID editParticle(ParticleID particleID, const ParticleProperties& properties); - - /// deletes a particle - void deleteParticle(ParticleID particleID); - - /// finds the closest particle to the center point, within the radius - /// will return a ParticleID.isKnownID = false if no particles are in the radius - /// this function will not find any particles in script engine contexts which don't have access to particles - ParticleID findClosestParticle(const glm::vec3& center, float radius) const; - - /// finds particles within the search sphere specified by the center point and radius - /// this function will not find any particles in script engine contexts which don't have access to particles - QVector findParticles(const glm::vec3& center, float radius) const; - -signals: - void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel, const CollisionInfo& collision); - void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const CollisionInfo& collision); - -private: - void queueParticleMessage(PacketType packetType, ParticleID particleID, const ParticleProperties& properties); - - uint32_t _nextCreatorTokenID; - ParticleTree* _particleTree; -}; - -#endif // hifi_ParticlesScriptingInterface_h diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 6a59f8ad10..7073280ee5 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 fbx particles entities animation) +link_hifi_libraries(shared octree voxels fbx entities animation) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 51789aec3a..eb5dd07ffb 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -43,7 +42,6 @@ #include "XMLHttpRequestClass.h" VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface; -ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface; EntityScriptingInterface ScriptEngine::_entityScriptingInterface; static QScriptValue soundConstructor(QScriptContext* context, QScriptEngine* engine) { @@ -236,7 +234,6 @@ void ScriptEngine::init() { _isInitialized = true; _voxelsScriptingInterface.init(); - _particlesScriptingInterface.init(); // register various meta-types registerMetaTypes(this); @@ -248,10 +245,6 @@ void ScriptEngine::init() { registerAvatarTypes(this); Bitstream::registerTypes(this); - qScriptRegisterMetaType(this, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue); - qScriptRegisterMetaType(this, ParticleIDtoScriptValue, ParticleIDfromScriptValue); - qScriptRegisterSequenceMetaType >(this); - qScriptRegisterMetaType(this, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValue); qScriptRegisterMetaType(this, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue); qScriptRegisterMetaType(this, RayToEntityIntersectionResultToScriptValue, RayToEntityIntersectionResultFromScriptValue); @@ -286,7 +279,6 @@ void ScriptEngine::init() { registerGlobalObject("Audio", &_audioScriptingInterface); registerGlobalObject("Controller", _controllerScriptingInterface); registerGlobalObject("Entities", &_entityScriptingInterface); - registerGlobalObject("Particles", &_particlesScriptingInterface); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Uuid", &_uuidLibrary); @@ -299,14 +291,12 @@ void ScriptEngine::init() { 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("COLLISION_GROUP_PARTICLES", newVariant(QVariant(COLLISION_GROUP_PARTICLES))); 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); - _particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); } QScriptValue ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { @@ -421,16 +411,6 @@ void ScriptEngine::run() { } } - if (_particlesScriptingInterface.getParticlePacketSender()->serversExist()) { - // release the queue of edit voxel messages. - _particlesScriptingInterface.getParticlePacketSender()->releaseQueuedMessages(); - - // since we're in non-threaded mode, call process so that the packets are sent - if (!_particlesScriptingInterface.getParticlePacketSender()->isThreaded()) { - _particlesScriptingInterface.getParticlePacketSender()->process(); - } - } - if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { // release the queue of edit voxel messages. _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); @@ -568,16 +548,6 @@ void ScriptEngine::run() { } } - if (_particlesScriptingInterface.getParticlePacketSender()->serversExist()) { - // release the queue of edit voxel messages. - _particlesScriptingInterface.getParticlePacketSender()->releaseQueuedMessages(); - - // since we're in non-threaded mode, call process so that the packets are sent - if (!_particlesScriptingInterface.getParticlePacketSender()->isThreaded()) { - _particlesScriptingInterface.getParticlePacketSender()->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 130dc501f9..d556475859 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -31,7 +31,6 @@ #include "Vec3.h" class EntityScriptingInterface; -class ParticlesScriptingInterface; class VoxelsScriptingInterface; const QString NO_SCRIPT(""); @@ -51,9 +50,6 @@ public: /// Access the VoxelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return &_voxelsScriptingInterface; } - /// Access the ParticlesScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener - static ParticlesScriptingInterface* getParticlesScriptingInterface() { return &_particlesScriptingInterface; } - /// Access the EntityScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener static EntityScriptingInterface* getEntityScriptingInterface() { return &_entityScriptingInterface; } @@ -143,7 +139,6 @@ private: void stopTimer(QTimer* timer); static VoxelsScriptingInterface _voxelsScriptingInterface; - static ParticlesScriptingInterface _particlesScriptingInterface; static EntityScriptingInterface _entityScriptingInterface; AbstractControllerScriptingInterface* _controllerScriptingInterface; diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index 0f134c1b23..e6daf949b3 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -23,7 +23,6 @@ class Shape; const quint32 COLLISION_GROUP_ENVIRONMENT = 1U << 0; const quint32 COLLISION_GROUP_AVATARS = 1U << 1; const quint32 COLLISION_GROUP_VOXELS = 1U << 2; -const quint32 COLLISION_GROUP_PARTICLES = 1U << 3; const quint32 VALID_COLLISION_GROUPS = 0x0f; // CollisionInfo contains details about the collision between two things: BodyA and BodyB. diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt index 5143c04918..e19a7c87e6 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 fbx metavoxels networking particles entities avatars audio animation script-engine) +link_hifi_libraries(shared octree voxels fbx metavoxels networking entities avatars audio animation script-engine) link_shared_dependencies() diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index fee8f3ff37..05d6cb593d 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -25,30 +25,30 @@ #include "OctreeTests.h" -enum ParticlePropertyList { - PARTICLE_PROP_PAGED_PROPERTY, - PARTICLE_PROP_CUSTOM_PROPERTIES_INCLUDED, - PARTICLE_PROP_VISIBLE, - PARTICLE_PROP_POSITION, - PARTICLE_PROP_RADIUS, - PARTICLE_PROP_MODEL_URL, - PARTICLE_PROP_ROTATION, - PARTICLE_PROP_COLOR, - PARTICLE_PROP_SCRIPT, - PARTICLE_PROP_ANIMATION_URL, - PARTICLE_PROP_ANIMATION_FPS, - PARTICLE_PROP_ANIMATION_FRAME_INDEX, - PARTICLE_PROP_ANIMATION_PLAYING, - PARTICLE_PROP_SHOULD_BE_DELETED, - PARTICLE_PROP_VELOCITY, - PARTICLE_PROP_GRAVITY, - PARTICLE_PROP_DAMPING, - PARTICLE_PROP_MASS, - PARTICLE_PROP_LIFETIME, - PARTICLE_PROP_PAUSE_SIMULATION, +enum ExamplePropertyList { + EXAMPLE_PROP_PAGED_PROPERTY, + EXAMPLE_PROP_CUSTOM_PROPERTIES_INCLUDED, + EXAMPLE_PROP_VISIBLE, + EXAMPLE_PROP_POSITION, + EXAMPLE_PROP_RADIUS, + EXAMPLE_PROP_MODEL_URL, + EXAMPLE_PROP_ROTATION, + EXAMPLE_PROP_COLOR, + EXAMPLE_PROP_SCRIPT, + EXAMPLE_PROP_ANIMATION_URL, + EXAMPLE_PROP_ANIMATION_FPS, + EXAMPLE_PROP_ANIMATION_FRAME_INDEX, + EXAMPLE_PROP_ANIMATION_PLAYING, + EXAMPLE_PROP_SHOULD_BE_DELETED, + EXAMPLE_PROP_VELOCITY, + EXAMPLE_PROP_GRAVITY, + EXAMPLE_PROP_DAMPING, + EXAMPLE_PROP_MASS, + EXAMPLE_PROP_LIFETIME, + EXAMPLE_PROP_PAUSE_SIMULATION, }; -typedef PropertyFlags ParticlePropertyFlags; +typedef PropertyFlags ExamplePropertyFlags; void OctreeTests::propertyFlagsTests(bool verbose) { @@ -96,17 +96,16 @@ void OctreeTests::propertyFlagsTests(bool verbose) { { if (verbose) { - qDebug() << "Test 2: ParticlePropertyFlags: using setHasProperty()"; + qDebug() << "Test 2: ExamplePropertyFlags: using setHasProperty()"; } testsTaken++; - ParticlePropertyFlags props2; - props2.setHasProperty(PARTICLE_PROP_VISIBLE); - props2.setHasProperty(PARTICLE_PROP_ANIMATION_URL); - props2.setHasProperty(PARTICLE_PROP_ANIMATION_FPS); - props2.setHasProperty(PARTICLE_PROP_ANIMATION_FRAME_INDEX); - props2.setHasProperty(PARTICLE_PROP_ANIMATION_PLAYING); - props2.setHasProperty(PARTICLE_PROP_PAUSE_SIMULATION); + EntityPropertyFlags props2; + props2.setHasProperty(PROP_VISIBLE); + props2.setHasProperty(PROP_ANIMATION_URL); + props2.setHasProperty(PROP_ANIMATION_FPS); + props2.setHasProperty(PROP_ANIMATION_FRAME_INDEX); + props2.setHasProperty(PROP_ANIMATION_PLAYING); QByteArray encoded = props2.encode(); @@ -122,17 +121,15 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 2: ParticlePropertyFlags: using setHasProperty()"; + qDebug() << "FAILED - Test 2: ExamplePropertyFlags: using setHasProperty()"; } if (verbose) { - qDebug() << "Test 2b: remove flag with setHasProperty() PARTICLE_PROP_PAUSE_SIMULATION"; + qDebug() << "Test 2b: remove flag with setHasProperty() PROP_PAUSE_SIMULATION"; } testsTaken++; - props2.setHasProperty(PARTICLE_PROP_PAUSE_SIMULATION, false); - encoded = props2.encode(); if (verbose) { @@ -147,24 +144,24 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 2b: remove flag with setHasProperty() PARTICLE_PROP_PAUSE_SIMULATION"; + qDebug() << "FAILED - Test 2b: remove flag with setHasProperty() EXAMPLE_PROP_PAUSE_SIMULATION"; } } { if (verbose) { - qDebug() << "Test 3: ParticlePropertyFlags: using | operator"; + qDebug() << "Test 3: ExamplePropertyFlags: using | operator"; } testsTaken++; - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props = ParticlePropertyFlags(PARTICLE_PROP_VISIBLE) - | ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_URL) - | ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FPS) - | ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FRAME_INDEX) - | ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_PLAYING) - | ParticlePropertyFlags(PARTICLE_PROP_PAUSE_SIMULATION); + props = ExamplePropertyFlags(EXAMPLE_PROP_VISIBLE) + | ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_URL) + | ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_FPS) + | ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_FRAME_INDEX) + | ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_PLAYING) + | ExamplePropertyFlags(EXAMPLE_PROP_PAUSE_SIMULATION); QByteArray encoded = props.encode(); @@ -179,16 +176,16 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 3: ParticlePropertyFlags: using | operator"; + qDebug() << "FAILED - Test 3: ExamplePropertyFlags: using | operator"; } if (verbose) { - qDebug() << "Test 3b: remove flag with -= PARTICLE_PROP_PAUSE_SIMULATION"; + qDebug() << "Test 3b: remove flag with -= EXAMPLE_PROP_PAUSE_SIMULATION"; } testsTaken++; - props -= PARTICLE_PROP_PAUSE_SIMULATION; + props -= EXAMPLE_PROP_PAUSE_SIMULATION; encoded = props.encode(); @@ -204,25 +201,25 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 3b: remove flag with -= PARTICLE_PROP_PAUSE_SIMULATION"; + qDebug() << "FAILED - Test 3b: remove flag with -= EXAMPLE_PROP_PAUSE_SIMULATION"; } } { if (verbose) { - qDebug() << "Test 3c: ParticlePropertyFlags: using |= operator"; + qDebug() << "Test 3c: ExamplePropertyFlags: using |= operator"; } testsTaken++; - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props |= PARTICLE_PROP_VISIBLE; - props |= PARTICLE_PROP_ANIMATION_URL; - props |= PARTICLE_PROP_ANIMATION_FPS; - props |= PARTICLE_PROP_ANIMATION_FRAME_INDEX; - props |= PARTICLE_PROP_ANIMATION_PLAYING; - props |= PARTICLE_PROP_PAUSE_SIMULATION; + props |= EXAMPLE_PROP_VISIBLE; + props |= EXAMPLE_PROP_ANIMATION_URL; + props |= EXAMPLE_PROP_ANIMATION_FPS; + props |= EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + props |= EXAMPLE_PROP_ANIMATION_PLAYING; + props |= EXAMPLE_PROP_PAUSE_SIMULATION; QByteArray encoded = props.encode(); @@ -238,24 +235,24 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - 3c: ParticlePropertyFlags: using |= operator"; + qDebug() << "FAILED - 3c: ExamplePropertyFlags: using |= operator"; } } { if (verbose) { - qDebug() << "Test 4: ParticlePropertyFlags: using + operator"; + qDebug() << "Test 4: ExamplePropertyFlags: using + operator"; } testsTaken++; - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props = ParticlePropertyFlags(PARTICLE_PROP_VISIBLE) - + ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_URL) - + ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FPS) - + ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FRAME_INDEX) - + ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_PLAYING) - + ParticlePropertyFlags(PARTICLE_PROP_PAUSE_SIMULATION); + props = ExamplePropertyFlags(EXAMPLE_PROP_VISIBLE) + + ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_URL) + + ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_FPS) + + ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_FRAME_INDEX) + + ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_PLAYING) + + ExamplePropertyFlags(EXAMPLE_PROP_PAUSE_SIMULATION); QByteArray encoded = props.encode(); @@ -271,23 +268,23 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 4: ParticlePropertyFlags: using + operator"; + qDebug() << "FAILED - Test 4: ExamplePropertyFlags: using + operator"; } } { if (verbose) { - qDebug() << "Test 5: ParticlePropertyFlags: using += operator"; + qDebug() << "Test 5: ExamplePropertyFlags: using += operator"; } testsTaken++; - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props += PARTICLE_PROP_VISIBLE; - props += PARTICLE_PROP_ANIMATION_URL; - props += PARTICLE_PROP_ANIMATION_FPS; - props += PARTICLE_PROP_ANIMATION_FRAME_INDEX; - props += PARTICLE_PROP_ANIMATION_PLAYING; - props += PARTICLE_PROP_PAUSE_SIMULATION; + props += EXAMPLE_PROP_VISIBLE; + props += EXAMPLE_PROP_ANIMATION_URL; + props += EXAMPLE_PROP_ANIMATION_FPS; + props += EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + props += EXAMPLE_PROP_ANIMATION_PLAYING; + props += EXAMPLE_PROP_PAUSE_SIMULATION; QByteArray encoded = props.encode(); @@ -303,24 +300,24 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 5: ParticlePropertyFlags: using += operator"; + qDebug() << "FAILED - Test 5: ExamplePropertyFlags: using += operator"; } } { if (verbose) { - qDebug() << "Test 6: ParticlePropertyFlags: using = ... << operator"; + qDebug() << "Test 6: ExamplePropertyFlags: using = ... << operator"; } testsTaken++; - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props = ParticlePropertyFlags(PARTICLE_PROP_VISIBLE) - << ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_URL) - << ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FPS) - << ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FRAME_INDEX) - << ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_PLAYING) - << ParticlePropertyFlags(PARTICLE_PROP_PAUSE_SIMULATION); + props = ExamplePropertyFlags(EXAMPLE_PROP_VISIBLE) + << ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_URL) + << ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_FPS) + << ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_FRAME_INDEX) + << ExamplePropertyFlags(EXAMPLE_PROP_ANIMATION_PLAYING) + << ExamplePropertyFlags(EXAMPLE_PROP_PAUSE_SIMULATION); QByteArray encoded = props.encode(); @@ -336,24 +333,24 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 6: ParticlePropertyFlags: using = ... << operator"; + qDebug() << "FAILED - Test 6: ExamplePropertyFlags: using = ... << operator"; } } { if (verbose) { - qDebug() << "Test 7: ParticlePropertyFlags: using <<= operator"; + qDebug() << "Test 7: ExamplePropertyFlags: using <<= operator"; } testsTaken++; - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props <<= PARTICLE_PROP_VISIBLE; - props <<= PARTICLE_PROP_ANIMATION_URL; - props <<= PARTICLE_PROP_ANIMATION_FPS; - props <<= PARTICLE_PROP_ANIMATION_FRAME_INDEX; - props <<= PARTICLE_PROP_ANIMATION_PLAYING; - props <<= PARTICLE_PROP_PAUSE_SIMULATION; + props <<= EXAMPLE_PROP_VISIBLE; + props <<= EXAMPLE_PROP_ANIMATION_URL; + props <<= EXAMPLE_PROP_ANIMATION_FPS; + props <<= EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + props <<= EXAMPLE_PROP_ANIMATION_PLAYING; + props <<= EXAMPLE_PROP_PAUSE_SIMULATION; QByteArray encoded = props.encode(); @@ -369,24 +366,24 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 7: ParticlePropertyFlags: using <<= operator"; + qDebug() << "FAILED - Test 7: ExamplePropertyFlags: using <<= operator"; } } { if (verbose) { - qDebug() << "Test 8: ParticlePropertyFlags: using << enum operator"; + qDebug() << "Test 8: ExamplePropertyFlags: using << enum operator"; } testsTaken++; - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props << PARTICLE_PROP_VISIBLE; - props << PARTICLE_PROP_ANIMATION_URL; - props << PARTICLE_PROP_ANIMATION_FPS; - props << PARTICLE_PROP_ANIMATION_FRAME_INDEX; - props << PARTICLE_PROP_ANIMATION_PLAYING; - props << PARTICLE_PROP_PAUSE_SIMULATION; + props << EXAMPLE_PROP_VISIBLE; + props << EXAMPLE_PROP_ANIMATION_URL; + props << EXAMPLE_PROP_ANIMATION_FPS; + props << EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + props << EXAMPLE_PROP_ANIMATION_PLAYING; + props << EXAMPLE_PROP_PAUSE_SIMULATION; QByteArray encoded = props.encode(); @@ -402,26 +399,26 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 8: ParticlePropertyFlags: using << enum operator"; + qDebug() << "FAILED - Test 8: ExamplePropertyFlags: using << enum operator"; } } { if (verbose) { - qDebug() << "Test 9: ParticlePropertyFlags: using << flags operator "; + qDebug() << "Test 9: ExamplePropertyFlags: using << flags operator "; } testsTaken++; - ParticlePropertyFlags props; - ParticlePropertyFlags props2; + ExamplePropertyFlags props; + ExamplePropertyFlags props2; - props << PARTICLE_PROP_VISIBLE; - props << PARTICLE_PROP_ANIMATION_URL; - props << PARTICLE_PROP_ANIMATION_FPS; + props << EXAMPLE_PROP_VISIBLE; + props << EXAMPLE_PROP_ANIMATION_URL; + props << EXAMPLE_PROP_ANIMATION_FPS; - props2 << PARTICLE_PROP_ANIMATION_FRAME_INDEX; - props2 << PARTICLE_PROP_ANIMATION_PLAYING; - props2 << PARTICLE_PROP_PAUSE_SIMULATION; + props2 << EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + props2 << EXAMPLE_PROP_ANIMATION_PLAYING; + props2 << EXAMPLE_PROP_PAUSE_SIMULATION; props << props2; @@ -439,15 +436,15 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 9: ParticlePropertyFlags: using << flags operator"; + qDebug() << "FAILED - Test 9: ExamplePropertyFlags: using << flags operator"; } } { if (verbose) { - qDebug() << "Test 10: ParticlePropertyFlags comparison"; + qDebug() << "Test 10: ExamplePropertyFlags comparison"; } - ParticlePropertyFlags propsA; + ExamplePropertyFlags propsA; if (verbose) { qDebug() << "!propsA:" << (!propsA) << "{ expect true }"; @@ -459,15 +456,15 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 10a: ParticlePropertyFlags comparison, uninitialized !propsA"; + qDebug() << "FAILED - Test 10a: ExamplePropertyFlags comparison, uninitialized !propsA"; } - propsA << PARTICLE_PROP_VISIBLE; - propsA << PARTICLE_PROP_ANIMATION_URL; - propsA << PARTICLE_PROP_ANIMATION_FPS; - propsA << PARTICLE_PROP_ANIMATION_FRAME_INDEX; - propsA << PARTICLE_PROP_ANIMATION_PLAYING; - propsA << PARTICLE_PROP_PAUSE_SIMULATION; + propsA << EXAMPLE_PROP_VISIBLE; + propsA << EXAMPLE_PROP_ANIMATION_URL; + propsA << EXAMPLE_PROP_ANIMATION_FPS; + propsA << EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + propsA << EXAMPLE_PROP_ANIMATION_PLAYING; + propsA << EXAMPLE_PROP_PAUSE_SIMULATION; if (verbose) { qDebug() << "!propsA:" << (!propsA) << "{ expect false }"; @@ -479,16 +476,16 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 10b: ParticlePropertyFlags comparison, initialized !propsA"; + qDebug() << "FAILED - Test 10b: ExamplePropertyFlags comparison, initialized !propsA"; } - ParticlePropertyFlags propsB; - propsB << PARTICLE_PROP_VISIBLE; - propsB << PARTICLE_PROP_ANIMATION_URL; - propsB << PARTICLE_PROP_ANIMATION_FPS; - propsB << PARTICLE_PROP_ANIMATION_FRAME_INDEX; - propsB << PARTICLE_PROP_ANIMATION_PLAYING; - propsB << PARTICLE_PROP_PAUSE_SIMULATION; + ExamplePropertyFlags propsB; + propsB << EXAMPLE_PROP_VISIBLE; + propsB << EXAMPLE_PROP_ANIMATION_URL; + propsB << EXAMPLE_PROP_ANIMATION_FPS; + propsB << EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + propsB << EXAMPLE_PROP_ANIMATION_PLAYING; + propsB << EXAMPLE_PROP_PAUSE_SIMULATION; if (verbose) { qDebug() << "propsA == propsB:" << (propsA == propsB) << "{ expect true }"; @@ -501,7 +498,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 10c: ParticlePropertyFlags comparison, propsA == propsB"; + qDebug() << "FAILED - Test 10c: ExamplePropertyFlags comparison, propsA == propsB"; } testsTaken++; @@ -511,14 +508,14 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 10d: ParticlePropertyFlags comparison, propsA != propsB"; + qDebug() << "FAILED - Test 10d: ExamplePropertyFlags comparison, propsA != propsB"; } if (verbose) { - qDebug() << "AFTER propsB -= PARTICLE_PROP_PAUSE_SIMULATION..."; + qDebug() << "AFTER propsB -= EXAMPLE_PROP_PAUSE_SIMULATION..."; } - propsB -= PARTICLE_PROP_PAUSE_SIMULATION; + propsB -= EXAMPLE_PROP_PAUSE_SIMULATION; if (verbose) { qDebug() << "propsA == propsB:" << (propsA == propsB) << "{ expect false }"; @@ -531,7 +528,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 10e: ParticlePropertyFlags comparison, AFTER propsB -= PARTICLE_PROP_PAUSE_SIMULATION"; + qDebug() << "FAILED - Test 10e: ExamplePropertyFlags comparison, AFTER propsB -= EXAMPLE_PROP_PAUSE_SIMULATION"; } if (verbose) { @@ -549,18 +546,18 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 10f: ParticlePropertyFlags comparison, AFTER propsB = propsA"; + qDebug() << "FAILED - Test 10f: ExamplePropertyFlags comparison, AFTER propsB = propsA"; } } { if (verbose) { - qDebug() << "Test 11: ParticlePropertyFlags testing individual properties"; + qDebug() << "Test 11: ExamplePropertyFlags testing individual properties"; } - ParticlePropertyFlags props; + ExamplePropertyFlags props; if (verbose) { - qDebug() << "ParticlePropertyFlags props;"; + qDebug() << "ExamplePropertyFlags props;"; } QByteArray encoded = props.encode(); @@ -578,36 +575,36 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11a: ParticlePropertyFlags testing individual properties"; + qDebug() << "FAILED - Test 11a: ExamplePropertyFlags testing individual properties"; } if (verbose) { - qDebug() << "Test 11b: props.getHasProperty(PARTICLE_PROP_VISIBLE)" << (props.getHasProperty(PARTICLE_PROP_VISIBLE)) + qDebug() << "Test 11b: props.getHasProperty(EXAMPLE_PROP_VISIBLE)" << (props.getHasProperty(EXAMPLE_PROP_VISIBLE)) << "{ expect false }"; } testsTaken++; - bool resultB = props.getHasProperty(PARTICLE_PROP_VISIBLE); + bool resultB = props.getHasProperty(EXAMPLE_PROP_VISIBLE); bool expectedB = false; if (resultB == expectedB) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11b: props.getHasProperty(PARTICLE_PROP_VISIBLE)"; + qDebug() << "FAILED - Test 11b: props.getHasProperty(EXAMPLE_PROP_VISIBLE)"; } if (verbose) { - qDebug() << "props << PARTICLE_PROP_VISIBLE;"; + qDebug() << "props << EXAMPLE_PROP_VISIBLE;"; } - props << PARTICLE_PROP_VISIBLE; + props << EXAMPLE_PROP_VISIBLE; testsTaken++; - bool resultC = props.getHasProperty(PARTICLE_PROP_VISIBLE); + bool resultC = props.getHasProperty(EXAMPLE_PROP_VISIBLE); bool expectedC = true; if (resultC == expectedC) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11c: props.getHasProperty(PARTICLE_PROP_VISIBLE) after props << PARTICLE_PROP_VISIBLE"; + qDebug() << "FAILED - Test 11c: props.getHasProperty(EXAMPLE_PROP_VISIBLE) after props << EXAMPLE_PROP_VISIBLE"; } encoded = props.encode(); @@ -615,7 +612,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) { if (verbose) { qDebug() << "props... encoded="; outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); - qDebug() << "props.getHasProperty(PARTICLE_PROP_VISIBLE)" << (props.getHasProperty(PARTICLE_PROP_VISIBLE)) + qDebug() << "props.getHasProperty(EXAMPLE_PROP_VISIBLE)" << (props.getHasProperty(EXAMPLE_PROP_VISIBLE)) << "{ expect true }"; } @@ -627,19 +624,19 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11c: ParticlePropertyFlags testing individual properties"; + qDebug() << "FAILED - Test 11c: ExamplePropertyFlags testing individual properties"; } if (verbose) { - qDebug() << "props << PARTICLE_PROP_ANIMATION_URL;"; + qDebug() << "props << EXAMPLE_PROP_ANIMATION_URL;"; } - props << PARTICLE_PROP_ANIMATION_URL; + props << EXAMPLE_PROP_ANIMATION_URL; encoded = props.encode(); if (verbose) { qDebug() << "props... encoded="; outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); - qDebug() << "props.getHasProperty(PARTICLE_PROP_VISIBLE)" << (props.getHasProperty(PARTICLE_PROP_VISIBLE)) + qDebug() << "props.getHasProperty(EXAMPLE_PROP_VISIBLE)" << (props.getHasProperty(EXAMPLE_PROP_VISIBLE)) << "{ expect true }"; } char expectedBytesD[] = { (char)136, (char)16 }; @@ -650,61 +647,61 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11d: ParticlePropertyFlags testing individual properties"; + qDebug() << "FAILED - Test 11d: ExamplePropertyFlags testing individual properties"; } testsTaken++; - bool resultE = props.getHasProperty(PARTICLE_PROP_VISIBLE); + bool resultE = props.getHasProperty(EXAMPLE_PROP_VISIBLE); bool expectedE = true; if (resultE == expectedE) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11e: props.getHasProperty(PARTICLE_PROP_VISIBLE) after props << PARTICLE_PROP_ANIMATION_URL"; + qDebug() << "FAILED - Test 11e: props.getHasProperty(EXAMPLE_PROP_VISIBLE) after props << EXAMPLE_PROP_ANIMATION_URL"; } if (verbose) { qDebug() << "props << ... more ..."; } - props << PARTICLE_PROP_ANIMATION_FPS; - props << PARTICLE_PROP_ANIMATION_FRAME_INDEX; - props << PARTICLE_PROP_ANIMATION_PLAYING; - props << PARTICLE_PROP_PAUSE_SIMULATION; + props << EXAMPLE_PROP_ANIMATION_FPS; + props << EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + props << EXAMPLE_PROP_ANIMATION_PLAYING; + props << EXAMPLE_PROP_PAUSE_SIMULATION; encoded = props.encode(); if (verbose) { qDebug() << "props... encoded="; outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); - qDebug() << "props.getHasProperty(PARTICLE_PROP_VISIBLE)" << (props.getHasProperty(PARTICLE_PROP_VISIBLE)) + qDebug() << "props.getHasProperty(EXAMPLE_PROP_VISIBLE)" << (props.getHasProperty(EXAMPLE_PROP_VISIBLE)) << "{ expect true }"; } testsTaken++; - bool resultF = props.getHasProperty(PARTICLE_PROP_VISIBLE); + bool resultF = props.getHasProperty(EXAMPLE_PROP_VISIBLE); bool expectedF = true; if (resultF == expectedF) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11f: props.getHasProperty(PARTICLE_PROP_VISIBLE) after props << more"; + qDebug() << "FAILED - Test 11f: props.getHasProperty(EXAMPLE_PROP_VISIBLE) after props << more"; } if (verbose) { - qDebug() << "ParticlePropertyFlags propsB = props & PARTICLE_PROP_VISIBLE;"; + qDebug() << "ExamplePropertyFlags propsB = props & EXAMPLE_PROP_VISIBLE;"; } - ParticlePropertyFlags propsB = props & PARTICLE_PROP_VISIBLE; + ExamplePropertyFlags propsB = props & EXAMPLE_PROP_VISIBLE; if (verbose) { - qDebug() << "propsB.getHasProperty(PARTICLE_PROP_VISIBLE)" << (propsB.getHasProperty(PARTICLE_PROP_VISIBLE)) + qDebug() << "propsB.getHasProperty(EXAMPLE_PROP_VISIBLE)" << (propsB.getHasProperty(EXAMPLE_PROP_VISIBLE)) << "{ expect true }"; } testsTaken++; - bool resultG = propsB.getHasProperty(PARTICLE_PROP_VISIBLE); + bool resultG = propsB.getHasProperty(EXAMPLE_PROP_VISIBLE); bool expectedG = true; if (resultG == expectedG) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11g: propsB = props & PARTICLE_PROP_VISIBLE"; + qDebug() << "FAILED - Test 11g: propsB = props & EXAMPLE_PROP_VISIBLE"; } encoded = propsB.encode(); @@ -720,20 +717,20 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 11h: ParticlePropertyFlags testing individual properties"; + qDebug() << "FAILED - Test 11h: ExamplePropertyFlags testing individual properties"; } if (verbose) { - qDebug() << "ParticlePropertyFlags propsC = ~propsB;"; + qDebug() << "ExamplePropertyFlags propsC = ~propsB;"; } - ParticlePropertyFlags propsC = ~propsB; + ExamplePropertyFlags propsC = ~propsB; if (verbose) { - qDebug() << "propsC.getHasProperty(PARTICLE_PROP_VISIBLE)" << (propsC.getHasProperty(PARTICLE_PROP_VISIBLE)) + qDebug() << "propsC.getHasProperty(EXAMPLE_PROP_VISIBLE)" << (propsC.getHasProperty(EXAMPLE_PROP_VISIBLE)) << "{ expect false }"; } testsTaken++; - bool resultI = propsC.getHasProperty(PARTICLE_PROP_VISIBLE); + bool resultI = propsC.getHasProperty(EXAMPLE_PROP_VISIBLE); bool expectedI = false; if (resultI == expectedI) { testsPassed++; @@ -751,16 +748,16 @@ void OctreeTests::propertyFlagsTests(bool verbose) { { if (verbose) { - qDebug() << "Test 12: ParticlePropertyFlags: decode tests"; + qDebug() << "Test 12: ExamplePropertyFlags: decode tests"; } - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props << PARTICLE_PROP_VISIBLE; - props << PARTICLE_PROP_ANIMATION_URL; - props << PARTICLE_PROP_ANIMATION_FPS; - props << PARTICLE_PROP_ANIMATION_FRAME_INDEX; - props << PARTICLE_PROP_ANIMATION_PLAYING; - props << PARTICLE_PROP_PAUSE_SIMULATION; + props << EXAMPLE_PROP_VISIBLE; + props << EXAMPLE_PROP_ANIMATION_URL; + props << EXAMPLE_PROP_ANIMATION_FPS; + props << EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + props << EXAMPLE_PROP_ANIMATION_PLAYING; + props << EXAMPLE_PROP_PAUSE_SIMULATION; QByteArray encoded = props.encode(); if (verbose) { @@ -769,7 +766,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) { qDebug() << "encoded.size()=" << encoded.size(); } - ParticlePropertyFlags propsDecoded; + ExamplePropertyFlags propsDecoded; propsDecoded.decode(encoded); if (verbose) { @@ -812,7 +809,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) { qDebug() << "encoded.size()=" << encoded.size() << "includes extra garbage"; } - ParticlePropertyFlags propsDecodedExtra; + ExamplePropertyFlags propsDecodedExtra; propsDecodedExtra.decode(encoded); if (verbose) { @@ -838,16 +835,16 @@ void OctreeTests::propertyFlagsTests(bool verbose) { { if (verbose) { - qDebug() << "Test 13: ParticlePropertyFlags: QByteArray << / >> tests"; + qDebug() << "Test 13: ExamplePropertyFlags: QByteArray << / >> tests"; } - ParticlePropertyFlags props; + ExamplePropertyFlags props; - props << PARTICLE_PROP_VISIBLE; - props << PARTICLE_PROP_ANIMATION_URL; - props << PARTICLE_PROP_ANIMATION_FPS; - props << PARTICLE_PROP_ANIMATION_FRAME_INDEX; - props << PARTICLE_PROP_ANIMATION_PLAYING; - props << PARTICLE_PROP_PAUSE_SIMULATION; + props << EXAMPLE_PROP_VISIBLE; + props << EXAMPLE_PROP_ANIMATION_URL; + props << EXAMPLE_PROP_ANIMATION_FPS; + props << EXAMPLE_PROP_ANIMATION_FRAME_INDEX; + props << EXAMPLE_PROP_ANIMATION_PLAYING; + props << EXAMPLE_PROP_PAUSE_SIMULATION; if (verbose) { qDebug() << "testing encoded << props"; @@ -859,7 +856,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) { outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); } - ParticlePropertyFlags propsDecoded; + ExamplePropertyFlags propsDecoded; if (verbose) { qDebug() << "testing encoded >> propsDecoded"; } @@ -876,7 +873,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) { testsPassed++; } else { testsFailed++; - qDebug() << "FAILED - Test 13: ParticlePropertyFlags: QByteArray << / >> tests"; + qDebug() << "FAILED - Test 13: ExamplePropertyFlags: QByteArray << / >> tests"; } }