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/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 81835fb50a..f99c1d280e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -513,7 +513,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet 0) { + velocity.x -= velocityStep; + velocity.z += velocityStep; + color.blue = 0; + color.green = 255; + } else { + velocity.x += velocityStep; + velocity.z -= velocityStep; + color.blue = 255; + color.green = 0; + } + + if (numberEntitiesAdded <= MAX_ENTITIES) { + var properties = { + type: "Sphere", + collisionsWillMove: true, + position: center, + dimensions: {x: entitySize, y: entitySize, z: entitySize}, + color: color, + velocity: velocity, + gravity: gravity, + damping: damping, + lifetime: 20 + }; + Entities.addEntity(properties); + numberEntitiesAdded++; + } else { + Script.stop(); + } + + print("Particles Stats: " + Entities.getLifetimeInSeconds() + " seconds," + + " Queued packets:" + Entities.getLifetimePacketsQueued() + "," + + " PPS:" + Entities.getLifetimePPSQueued() + "," + + " BPS:" + Entities.getLifetimeBPSQueued() + "," + + " Sent packets:" + Entities.getLifetimePacketsSent() + "," + + " PPS:" + Entities.getLifetimePPS() + "," + + " BPS:" + Entities.getLifetimeBPS() + + "\n"); + } +} + + +// register the call back so it fires before each data send +print("here...\n"); +Entities.setPacketsPerSecond(40000); +Script.update.connect(draw); +print("and here...\n"); diff --git a/examples/collidingParticles.js b/examples/collidingParticles.js deleted file mode 100644 index 1f1899c8f2..0000000000 --- a/examples/collidingParticles.js +++ /dev/null @@ -1,160 +0,0 @@ -// -// collidingParticles.js -// examples -// -// Created by Brad Hefta-Gaub on 12/31/13. -// Copyright 2013 High Fidelity, Inc. -// -// This is an example script that creates a couple particles, and sends them on a collision course. -// One of the particles has a script that when it collides with another particle, it swaps colors with that particle. -// The other particle has a script that when it collides with another particle it set's it's script to a suicide script. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var currentIteration = 0; -var NUM_ITERATIONS_BEFORE_SEND = 15; // every 1/4th seconds send another - -var numberParticlesAdded = 0; -var MAX_PARTICLES = 1; - -var velocity = { - x: 1, - y: 0, - z: 1 }; - -var gravity = { - x: 0, - y: 0, - z: 0 }; - -var damping = 0.1; - -var scriptA = " " + - " function collisionWithParticle(other, collision) { " + - " print('collisionWithParticle(other.getID()=' + other.getID() + ')...'); " + - " Vec3.print('penetration=', collision.penetration); " + - " Vec3.print('contactPoint=', collision.contactPoint); " + - " print('myID=' + Particle.getID() + '\\n'); " + - " var colorBlack = { red: 0, green: 0, blue: 0 };" + - " var otherColor = other.getColor();" + - " print('otherColor=' + otherColor.red + ', ' + otherColor.green + ', ' + otherColor.blue + '\\n'); " + - " var myColor = Particle.getColor();" + - " print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " + - " Particle.setColor(otherColor); " + - " other.setColor(myColor); " + - " } " + - " Particle.collisionWithParticle.connect(collisionWithParticle); " + - " "; - -var scriptB = " " + - " function collisionWithParticle(other, collision) { " + - " print('collisionWithParticle(other.getID()=' + other.getID() + ')...'); " + - " Vec3.print('penetration=', collision.penetration); " + - " Vec3.print('contactPoint=', collision.contactPoint); " + - " print('myID=' + Particle.getID() + '\\n'); " + - " Particle.setScript('Particle.setShouldDie(true);'); " + - " } " + - " Particle.collisionWithParticle.connect(collisionWithParticle); " + - " "; - -var color = { - red: 255, - green: 255, - blue: 0 }; - -function draw(deltaTime) { - print("hello... draw()... currentIteration=" + currentIteration + "\n"); - - // on the first iteration, setup a single particle that's slowly moving - if (currentIteration == 0) { - var colorGreen = { red: 0, green: 255, blue: 0 }; - var startPosition = { - x: 2, - y: 0, - z: 2 }; - var largeRadius = 0.5; - var verySlow = { - x: 0.01, - y: 0, - z: 0.01 }; - - var properties = { - position: startPosition, - radius: largeRadius, - color: colorGreen, - velocity: verySlow, - gravity: gravity, - damping: damping, - inHand: false, - script: scriptA - }; - - Particles.addParticle(properties); - print("hello... added particle... script=\n"); - print(scriptA); - numberParticlesAdded++; - } - - if (currentIteration++ % NUM_ITERATIONS_BEFORE_SEND === 0) { - print("draw()... sending another... currentIteration=" +currentIteration + "\n"); - - var center = { - x: 0, - y: 0, - z: 0 }; - - var particleSize = 0.1; - - print("number of particles=" + numberParticlesAdded +"\n"); - - var velocityStep = 0.1; - if (velocity.x > 0) { - velocity.x -= velocityStep; - velocity.z += velocityStep; - color.blue = 0; - color.green = 255; - } else { - velocity.x += velocityStep; - velocity.z -= velocityStep; - color.blue = 255; - color.green = 0; - } - - if (numberParticlesAdded <= MAX_PARTICLES) { - var properties = { - position: center, - radius: particleSize, - color: color, - velocity: velocity, - gravity: gravity, - damping: damping, - inHand: false, - script: scriptB - }; - Particles.addParticle(properties); - print("hello... added particle... script=\n"); - print(scriptB); - numberParticlesAdded++; - } else { - Script.stop(); - } - - print("Particles Stats: " + Particles.getLifetimeInSeconds() + " seconds," + - " Queued packets:" + Particles.getLifetimePacketsQueued() + "," + - " PPS:" + Particles.getLifetimePPSQueued() + "," + - " BPS:" + Particles.getLifetimeBPSQueued() + "," + - " Sent packets:" + Particles.getLifetimePacketsSent() + "," + - " PPS:" + Particles.getLifetimePPS() + "," + - " BPS:" + Particles.getLifetimeBPS() + - "\n"); - } -} - - -// register the call back so it fires before each data send -print("here...\n"); -Particles.setPacketsPerSecond(40000); -Script.update.connect(draw); -print("and here...\n"); diff --git a/examples/editParticleExample.js b/examples/editEntityExample.js similarity index 80% rename from examples/editParticleExample.js rename to examples/editEntityExample.js index 54c94d0ef3..422e50b1eb 100644 --- a/examples/editParticleExample.js +++ b/examples/editEntityExample.js @@ -17,6 +17,7 @@ var stopAfter = moveUntil + 100; var expectedLifetime = (moveUntil/60) + 1; // 1 second after done moving... var originalProperties = { + type: "Sphere", position: { x: 10, y: 0, z: 0 }, @@ -30,8 +31,6 @@ var originalProperties = { z: 0 }, - radius : 0.1, - color: { red: 0, green: 255, blue: 0 }, @@ -43,15 +42,15 @@ var originalProperties = { var positionDelta = { x: 0.05, y: 0, z: 0 }; -var particleID = Particles.addParticle(originalProperties); +var entityID = Entities.addEntity(originalProperties); -function moveParticle(deltaTime) { +function moveEntity(deltaTime) { if (count >= moveUntil) { // delete it... if (count == moveUntil) { - print("calling Particles.deleteParticle()"); - Particles.deleteParticle(particleID); + print("calling Entities.deleteEntity()"); + Entities.deleteEntity(entityID); } // stop it... @@ -67,7 +66,7 @@ function moveParticle(deltaTime) { print("count =" + count); count++; - print("particleID.creatorTokenID = " + particleID.creatorTokenID); + print("entityID.creatorTokenID = " + entityID.creatorTokenID); var newProperties = { position: { @@ -80,13 +79,13 @@ function moveParticle(deltaTime) { }; - //print("particleID = " + particleID); + //print("entityID = " + entityID); print("newProperties.position = " + newProperties.position.x + "," + newProperties.position.y+ "," + newProperties.position.z); - Particles.editParticle(particleID, newProperties); + Entities.editEntity(entityID, newProperties); } // register the call back so it fires before each data send -Script.update.connect(moveParticle); +Script.update.connect(moveEntity); diff --git a/examples/particleBirds.js b/examples/entityBirds.js similarity index 93% rename from examples/particleBirds.js rename to examples/entityBirds.js index 6ed37aefe1..bbc35a5f58 100644 --- a/examples/particleBirds.js +++ b/examples/entityBirds.js @@ -5,7 +5,7 @@ // Created by Benjamin Arnold on May 29, 2014 // Copyright 2014 High Fidelity, Inc. // -// This sample script creates a swarm of tweeting bird particles that fly around the avatar. +// This sample script creates a swarm of tweeting bird entities that fly around the avatar. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -91,15 +91,16 @@ function addBird() size = 0.15; } var properties = { + type: "Sphere", lifetime: birdLifetime, position: Vec3.sum(randVector(-range, range), myPosition), velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: BIRD_GRAVITY, z: 0 }, - radius : size, + dimensions: { x: size * 2, y: size * 2, z: size * 2 }, color: color }; - birds.push(new Bird(Particles.addParticle(properties), tweet, properties.position)); + birds.push(new Bird(Entities.addEntity(properties), tweet, properties.position)); } var numBirds = 30; @@ -129,7 +130,7 @@ function updateBirds(deltaTime) { // Update all the birds for (var i = 0; i < numBirds; i++) { particleID = birds[i].particleID; - var properties = Particles.getParticleProperties(particleID); + var properties = Entities.getEntityProperties(particleID); // Tweeting behavior if (birds[i].tweeting == 0) { @@ -180,19 +181,19 @@ function updateBirds(deltaTime) { properties.velocity = vInterpolate(properties.velocity, desiredVelocity, 0.2); // If we are near the target, we should get a new target - if (Vec3.length(Vec3.subtract(properties.position, birds[i].targetPosition)) < (properties.radius / 5.0)) { + if (Vec3.length(Vec3.subtract(properties.position, birds[i].targetPosition)) < (properties.dimensions.x / 5.0)) { birds[i].moving = false; } } // Use a cosine wave offset to make it look like its flapping. - var offset = Math.cos(nowTimeInSeconds * BIRD_FLAP_SPEED) * properties.radius; + var offset = Math.cos(nowTimeInSeconds * BIRD_FLAP_SPEED) * properties.dimensions.x; properties.position.y = properties.position.y + (offset - birds[i].previousFlapOffset); // Change position relative to previous offset. birds[i].previousFlapOffset = offset; // Update the particle - Particles.editParticle(particleID, properties); + Entities.editEntity(particleID, properties); } } } diff --git a/examples/particleModelExample.js b/examples/entityModelExample.js similarity index 66% rename from examples/particleModelExample.js rename to examples/entityModelExample.js index d589e6bb31..067032fc6b 100644 --- a/examples/particleModelExample.js +++ b/examples/entityModelExample.js @@ -1,11 +1,11 @@ // -// particleModelExample.js +// entityModelExample.js // examples // // Created by Brad Hefta-Gaub on 1/28/14. // Copyright 2014 High Fidelity, Inc. // -// This is an example script that demonstrates creating and editing a particle +// This is an example script that demonstrates creating and editing a entity // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,40 +17,38 @@ var count = 0; var stopAfter = 100; var modelPropertiesA = { + type: "Model", position: { x: 1, y: 1, z: 1 }, velocity: { x: 0.5, y: 0, z: 0.5 }, - gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius : 0.25, - modelURL: HIFI_PUBLICK_BUCKET + "meshes/Feisar_Ship.FBX", + dimensions: { x: 0.5, y: 0.5, z: 0.5 }, + modelURL: HIFI_PUBLIC_BUCKET + "meshes/Feisar_Ship.FBX", lifetime: 20 }; var modelPropertiesB = { + type: "Model", position: { x: 1, y: 1.5, z: 1 }, velocity: { x: 0.5, y: 0, z: 0.5 }, - gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius : 0.25, - modelURL: HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16.svo", - modelScale: 450, - modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + dimensions: { x: 0.5, y: 0.5, z: 0.5 }, + modelURL: HIFI_PUBLIC_BUCKET + "meshes/orc.fbx", lifetime: 20 }; var ballProperties = { + type: "Sphere", position: { x: 1, y: 0.5, z: 1 }, velocity: { x: 0.5, y: 0, z: 0.5 }, - gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius : 0.25, + dimensions: { x: 0.5, y: 0.5, z: 0.5 }, color: { red: 255, green: 0, blue: 0 }, lifetime: 20 }; -var modelAParticleID = Particles.addParticle(modelPropertiesA); -var modelBParticleID = Particles.addParticle(modelPropertiesB); -var ballParticleID = Particles.addParticle(ballProperties); +var modelAEntityID = Entities.addEntity(modelPropertiesA); +var modelBEntityID = Entities.addEntity(modelPropertiesB); +var ballEntityID = Entities.addEntity(ballProperties); function endAfterAWhile(deltaTime) { // stop it... diff --git a/examples/findParticleExample.js b/examples/findEntitiesExample.js similarity index 59% rename from examples/findParticleExample.js rename to examples/findEntitiesExample.js index 635e30f344..01e77e1b2e 100644 --- a/examples/findParticleExample.js +++ b/examples/findEntitiesExample.js @@ -1,11 +1,11 @@ // -// findParticleExample.js +// findEntityExample.js // examples // // Created by Brad Hefta-Gaub on 1/24/14. // Copyright 2014 High Fidelity, Inc. // -// This is an example script that demonstrates "finding" particles +// This is an example script that demonstrates "finding" entities // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -13,21 +13,23 @@ var iteration = 0; -var particleA = Particles.addParticle( +var entityA = Entities.addEntity( { + type: "Sphere", position: { x: 2, y: 0, z: 2 }, velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 }, - radius : 0.1, + dimensions: { x: 0.1, y: 0.1, z: 0.1 }, color: { red: 0, green: 255, blue: 0 } }); -var particleB = Particles.addParticle( +var entityB = Entities.addEntity( { + type: "Sphere", position: { x: 5, y: 0, z: 5 }, velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 }, - radius : 0.1, + dimensions: { x: 0.1, y: 0.1, z: 0.1 }, color: { red: 0, green: 255, blue: 255 } }); @@ -36,14 +38,14 @@ var moveSearch = { x: 0.1, y: 0, z: 0.1}; var searchRadius = 1; var searchRadiusChange = 0; -print("particleA.creatorTokenID = " + particleA.creatorTokenID); -print("particleB.creatorTokenID = " + particleB.creatorTokenID); +print("entityA.creatorTokenID = " + entityA.creatorTokenID); +print("entityB.creatorTokenID = " + entityB.creatorTokenID); function scriptEnding() { - print("calling Particles.deleteParticle()"); - Particles.deleteParticle(particleA); - Particles.deleteParticle(particleB); + print("calling Entities.deleteEntity()"); + Entities.deleteEntity(entityA); + Entities.deleteEntity(entityB); } function printProperties(properties) { @@ -63,7 +65,7 @@ function printProperties(properties) { } } -function findParticles(deltaTime) { +function findEntities(deltaTime) { // run for a while, then clean up // stop it... @@ -76,35 +78,37 @@ function findParticles(deltaTime) { print("iteration =" + iteration); iteration++; - // Check to see if we've been notified of the actual identity of the particles we created - if (!particleA.isKnownID) { - var identifyA = Particles.identifyParticle(particleA); + // Check to see if we've been notified of the actual identity of the entities we created + if (!entityA.isKnownID) { + var identifyA = Entities.identifyEntity(entityA); if (identifyA.isKnownID) { - particleA = identifyA; - print(">>>> identified particleA.id = " + particleA.id); + entityA = identifyA; + print(">>>> identified entityA.id = " + entityA.id); } } - if (!particleB.isKnownID) { - var identifyB = Particles.identifyParticle(particleB); + if (!entityB.isKnownID) { + var identifyB = Entities.identifyEntity(entityB); if (identifyB.isKnownID) { - particleB = identifyB; - print(">>>> identified particleB.id = " + particleB.id); + entityB = identifyB; + print(">>>> identified entityB.id = " + entityB.id); } } - // also check to see if we can "find" particles... - print("searching for particles at:" + searchAt.x + ", " + searchAt.y + ", " + searchAt.z + " radius:" + searchRadius); - var foundParticles = Particles.findParticles(searchAt, searchRadius); - print("found this many particles: "+ foundParticles.length); - for (var i = 0; i < foundParticles.length; i++) { - print(" particle[" + i + "].id:" + foundParticles[i].id); - if (foundParticles[i].id == particleA.id) { - print(">>>> found particleA!!"); - var propertiesA = Particles.getParticleProperties(particleA); + // also check to see if we can "find" entities... + print("searching for entities at:" + searchAt.x + ", " + searchAt.y + ", " + searchAt.z + " radius:" + searchRadius); + var foundEntities = Entities.findEntities(searchAt, searchRadius); + print("found this many entities: "+ foundEntities.length); + for (var i = 0; i < foundEntities.length; i++) { + print(" foundEntities[" + i + "].id:" + foundEntities[i].id); + if (foundEntities[i].id == entityA.id) { + print(">>>> found entityA!!"); + var propertiesA = Entities.getEntityProperties(entityA); printProperties(propertiesA); } - if (foundParticles[i].id == particleB.id) { - print(">>>> found particleB!!"); + if (foundEntities[i].id == entityB.id) { + print(">>>> found entityB!!"); + var propertiesB = Entities.getEntityProperties(entityB); + printProperties(propertiesB); } } // move search @@ -125,7 +129,7 @@ function findParticles(deltaTime) { // register the call back so it fires before each data send -Script.update.connect(findParticles); +Script.update.connect(findEntities); // register our scriptEnding callback Script.scriptEnding.connect(scriptEnding); diff --git a/examples/flockingBirds.js b/examples/flockingBirds.js index 0eb348b7b9..92a7b75f52 100644 --- a/examples/flockingBirds.js +++ b/examples/flockingBirds.js @@ -24,7 +24,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var birdsInFlock = 40; +var birdsInFlock = 20; var birdLifetime = 60; // 2 minutes var count=0; // iterations @@ -60,7 +60,7 @@ var flockStartPosition = MyAvatar.position; var flockStartVelocity = { x: 0, y: 0, z: 0}; var flockStartThrust = { x: 0, y: 0, z: 0}; // slightly upward against gravity var INITIAL_XY_VELOCITY_SCALE = 2; -var birdRadius = 0.0925; +var birdRadius = 0.2; var baseBirdColor = { red: 0, green: 255, blue: 255 }; var glidingColor = { red: 255, green: 0, blue: 0 }; var thrustUpwardColor = { red: 0, green: 255, blue: 0 }; @@ -153,12 +153,13 @@ function createBirds() { } else { velocity = { x: 0, y: 0, z: 0}; } - birds[i].particle = Particles.addParticle({ + birds[i].particle = Entities.addEntity({ + type: "Sphere", position: position, velocity: velocity, gravity: flockGravity, damping: 0, - radius: birdRadius, + dimensions: { x: birdRadius, y: birdRadius, z: birdRadius}, color: baseBirdColor, lifetime: birdLifetime }); @@ -179,10 +180,10 @@ function updateBirds(deltaTime) { // identifyParticle() will check to see that the particle handle we have is in sync with the domain/server // context. If the handle is for a created particle that now has a known ID it will be updated to be a // handle with a known ID. - birds[i].particle = Particles.identifyParticle(birds[i].particle); + birds[i].particle = Entities.identifyEntity(birds[i].particle); if (birds[i].particle.isKnownID) { - birds[i].properties = Particles.getParticleProperties(birds[i].particle); + birds[i].properties = Entities.getEntityProperties(birds[i].particle); if (birds[i].properties.isKnownID) { knownBirds++; averageVelocity = Vec3.sum(averageVelocity, birds[i].properties.velocity); @@ -455,7 +456,7 @@ function updateBirds(deltaTime) { Vec3.print("birds["+i+"].newVelocity=", newVelocity); } - birds[i].particle = Particles.editParticle(birds[i].particle,{ velocity: newVelocity, color: color }); + birds[i].particle = Entities.editEntity(birds[i].particle,{ velocity: newVelocity, color: color }); } } diff --git a/examples/fountain.js b/examples/fountain.js index ab1b82cb76..aea53fb405 100644 --- a/examples/fountain.js +++ b/examples/fountain.js @@ -48,13 +48,15 @@ function vInterpolate(a, b, fraction) { var position = { x: 5.0, y: 0.6, z: 5.0 }; Voxels.setVoxel(position.x, 0, position.z, 0.5, 0, 0, 255); -var totalParticles = 0; +var totalEntities = 0; function makeFountain(deltaTime) { if (Math.random() < 0.10) { - //print("Made particle!\n"); + //print("Made entity!\n"); + var radius = (0.02 + (Math.random() * 0.05)); var properties = { + type: "Sphere", position: position, - radius: (0.02 + (Math.random() * 0.05)), + dimensions: { x: radius, y: radius, z: radius}, color: { red: 0, green: 0, blue: 128 }, velocity: { x: (Math.random() * 1.0 - 0.5), y: (1.0 + (Math.random() * 2.0)), @@ -64,10 +66,10 @@ function makeFountain(deltaTime) { lifetime: 1 } - Particles.addParticle(properties); - totalParticles++; + Entities.addEntity(properties); + totalEntities++; } - if (totalParticles > 100) { + if (totalEntities > 100) { Script.stop(); } } diff --git a/examples/frisbee.js b/examples/frisbee.js index 653a1d4b57..c534a8b3fb 100644 --- a/examples/frisbee.js +++ b/examples/frisbee.js @@ -129,7 +129,7 @@ function Hand(name, palm, tip, forwardButton, button3, trigger) { this.button3 = button3; this.trigger = trigger; this.holdingFrisbee = false; - this.particle = false; + this.entity = false; this.palmPosition = function() { return Controller.getSpatialControlPosition(this.palm); } this.grabButtonPressed = function() { return ( @@ -185,28 +185,29 @@ function playSound(sound, position) { function cleanupFrisbees() { simulatedFrisbees = []; - var particles = Particles.findParticles(MyAvatar.position, 1000); - for (particle in particles) { - Particles.deleteParticle(particles[particle]); + var entities = Entities.findEntities(MyAvatar.position, 1000); + for (entity in entities) { + Entities.deleteEntity(entities[entity]); } } function checkControllerSide(hand) { // If I don't currently have a frisbee in my hand, then try to catch closest one if (!hand.holdingFrisbee && hand.grabButtonPressed()) { - var closestParticle = Particles.findClosestParticle(hand.palmPosition(), CATCH_RADIUS); - var modelUrl = Particles.getParticleProperties(closestParticle).modelURL; - if (closestParticle.isKnownID && validFrisbeeURL(Particles.getParticleProperties(closestParticle).modelURL)) { - Particles.editParticle(closestParticle, {modelScale: 1, inHand: true, position: hand.holdPosition(), shouldDie: true}); - Particles.deleteParticle(closestParticle); + var closestEntity = Entities.findClosestEntity(hand.palmPosition(), CATCH_RADIUS); + var modelUrl = Entities.getEntityProperties(closestEntity).modelURL; + if (closestEntity.isKnownID && validFrisbeeURL(Entities.getEntityProperties(closestEntity).modelURL)) { + Entities.editEntity(closestEntity, {modelScale: 1, inHand: true, position: hand.holdPosition(), shouldDie: true}); + Entities.deleteEntity(closestEntity); debugPrint(hand.message + " HAND- CAUGHT SOMETHING!!"); var properties = { + type: "Model", position: hand.holdPosition(), velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0}, inHand: true, - radius: FRISBEE_RADIUS, + dimensions: { x: FRISBEE_RADIUS, y: FRISBEE_RADIUS / 5, z: FRISBEE_RADIUS }, damping: 0.999, modelURL: modelUrl, modelScale: FRISBEE_MODEL_SCALE, @@ -214,10 +215,10 @@ function checkControllerSide(hand) { lifetime: FRISBEE_LIFETIME }; - newParticle = Particles.addParticle(properties); + newEntity = Entities.addEntity(properties); hand.holdingFrisbee = true; - hand.particle = newParticle; + hand.entity = newEntity; playSound(catchSound, hand.holdPosition()); @@ -228,11 +229,12 @@ function checkControllerSide(hand) { // If '3' is pressed, and not holding a frisbee, make a new one if (hand.grabButtonPressed() && !hand.holdingFrisbee && newfrisbeeEnabled) { var properties = { + type: "Model", position: hand.holdPosition(), velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0}, inHand: true, - radius: FRISBEE_RADIUS, + dimensions: { x: FRISBEE_RADIUS, y: FRISBEE_RADIUS / 5, z: FRISBEE_RADIUS }, damping: 0.999, modelURL: frisbeeURL(), modelScale: FRISBEE_MODEL_SCALE, @@ -240,9 +242,9 @@ function checkControllerSide(hand) { lifetime: FRISBEE_LIFETIME }; - newParticle = Particles.addParticle(properties); + newEntity = Entities.addEntity(properties); hand.holdingFrisbee = true; - hand.particle = newParticle; + hand.entity = newEntity; // Play a new frisbee sound playSound(newSound, hand.holdPosition()); @@ -258,7 +260,7 @@ function checkControllerSide(hand) { position: hand.holdPosition(), modelRotation: hand.holdRotation() }; - Particles.editParticle(hand.particle, properties); + Entities.editEntity(hand.entity, properties); } else { debugPrint(">>>>> " + hand.name + "-FRISBEE IN HAND, not grabbing, THROW!!!"); // If frisbee just released, add velocity to it! @@ -271,12 +273,12 @@ function checkControllerSide(hand) { modelRotation: hand.holdRotation() }; - Particles.editParticle(hand.particle, properties); + Entities.editEntity(hand.entity, properties); - simulatedFrisbees.push(hand.particle); + simulatedFrisbees.push(hand.entity); hand.holdingFrisbee = false; - hand.particle = false; + hand.entity = false; playSound(throwSound, hand.holdPosition()); } @@ -323,7 +325,7 @@ function checkController(deltaTime) { function controlFrisbees(deltaTime) { var killSimulations = []; for (frisbee in simulatedFrisbees) { - var properties = Particles.getParticleProperties(simulatedFrisbees[frisbee]); + var properties = Entities.getEntityProperties(simulatedFrisbees[frisbee]); //get the horizon length from the velocity origin in order to get speed var speed = Vec3.length({x:properties.velocity.x, y:0, z:properties.velocity.z}); if (speed < MIN_SIMULATION_SPEED) { @@ -331,7 +333,7 @@ function controlFrisbees(deltaTime) { killSimulations.push(frisbee); continue; } - Particles.editParticle(simulatedFrisbees[frisbee], {modelRotation: Quat.multiply(properties.modelRotation, Quat.fromPitchYawRollDegrees(0, speed * deltaTime * SPIN_MULTIPLIER, 0))}); + Entities.editEntity(simulatedFrisbees[frisbee], {modelRotation: Quat.multiply(properties.modelRotation, Quat.fromPitchYawRollDegrees(0, speed * deltaTime * SPIN_MULTIPLIER, 0))}); } for (var i = killSimulations.length - 1; i >= 0; i--) { diff --git a/examples/globalCollisionsExample.js b/examples/globalCollisionsExample.js index 11d90cd15b..426aebd5d9 100644 --- a/examples/globalCollisionsExample.js +++ b/examples/globalCollisionsExample.js @@ -14,23 +14,23 @@ print("hello..."); -function particleCollisionWithVoxel(particle, voxel, collision) { - print("particleCollisionWithVoxel().."); - print(" particle.getID()=" + particle.id); +function entityCollisionWithVoxel(entity, voxel, collision) { + print("entityCollisionWithVoxel().."); + print(" entity.getID()=" + entity.id); print(" voxel color...=" + voxel.red + ", " + voxel.green + ", " + voxel.blue); Vec3.print('penetration=', collision.penetration); Vec3.print('contactPoint=', collision.contactPoint); } -function particleCollisionWithParticle(particleA, particleB, collision) { - print("particleCollisionWithParticle().."); - print(" particleA.getID()=" + particleA.id); - print(" particleB.getID()=" + particleB.id); +function entityCollisionWithEntity(entityA, entityB, collision) { + print("entityCollisionWithParticle().."); + print(" entityA.getID()=" + entityA.id); + print(" entityB.getID()=" + entityB.id); Vec3.print('penetration=', collision.penetration); Vec3.print('contactPoint=', collision.contactPoint); } -Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel); -Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle); +Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel); +Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); print("here... hello..."); diff --git a/examples/grenadeLauncher.js b/examples/grenadeLauncher.js index dc25282448..bca067326a 100644 --- a/examples/grenadeLauncher.js +++ b/examples/grenadeLauncher.js @@ -6,9 +6,9 @@ // // Copyright 2013 High Fidelity, Inc. // -// This is an example script that turns the hydra controllers and mouse into a particle gun. -// It reads the controller, watches for trigger pulls, and launches particles. -// When particles collide with voxels they blow big holes out of the voxels. +// This is an example script that turns the hydra controllers and mouse into a entity gun. +// It reads the controller, watches for trigger pulls, and launches entities. +// When entities collide with voxels they blow big holes out of the voxels. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -97,9 +97,11 @@ function shootBullet(position, velocity) { var BULLET_GRAVITY = -3.0; //Creates a grenade with a reasonable lifetime so that one is less likely to accidentally blow up //far away voxels - Particles.addParticle( - { position: position, - radius: BULLET_SIZE, + Entities.addEntity( + { type: "Sphere", + position: position, + collisionsWillMove: true, + dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, color: { red: 10, green: 10, blue: 10 }, velocity: velocity, gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, @@ -133,9 +135,11 @@ function shootTarget() { velocity.y += TARGET_UP_VELOCITY; //printVector("velocity", velocity); - Particles.addParticle( - { position: newPosition, - radius: TARGET_SIZE, + Entities.addEntity( + { type: "Sphere", + position: newPosition, + collisionsWillMove: true, + dimensions: { x: TARGET_SIZE, y: TARGET_SIZE, z: TARGET_SIZE }, color: { red: 0, green: 200, blue: 200 }, velocity: velocity, gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, @@ -152,13 +156,16 @@ function shootTarget() { -function particleCollisionWithVoxel(particle, voxel, collision) { +function entityCollisionWithVoxel(entity, voxel, collision) { + +print("entityCollisionWithVoxel...."); + var VOXEL_SIZE = 0.5; // Don't make this big. I mean it. var CRATER_RADIUS = 5; - var particleProperties = Particles.getParticleProperties(particle); - var position = particleProperties.position; - Particles.deleteParticle(particle); + var entityProperties = Entities.getEntityProperties(entity); + var position = entityProperties.position; + Entities.deleteEntity(entity); audioOptions.position = collision.contactPoint; Audio.playSound(impactSound, audioOptions); @@ -186,7 +193,7 @@ function particleCollisionWithVoxel(particle, voxel, collision) { } } -function particleCollisionWithParticle(particle1, particle2, collision) { +function entityCollisionWithEntity(entity1, entity2, collision) { score++; if (showScore) { Overlays.editOverlay(text, { text: "Score: " + score } ); @@ -198,8 +205,8 @@ function particleCollisionWithParticle(particle1, particle2, collision) { //print("hit, msecs = " + msecs); //Vec3.print("penetration = ", collision.penetration); //Vec3.print("contactPoint = ", collision.contactPoint); - Particles.deleteParticle(particle1); - Particles.deleteParticle(particle2); + Entities.deleteEntity(entity1); + Entities.deleteEntity(entity2); // play the sound near the camera so the shooter can hear it audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); Audio.playSound(targetHitSound, audioOptions); @@ -347,8 +354,8 @@ function scriptEnding() { MyAvatar.detachOne(gunModel); } -Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel); -Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle); +Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel); +Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); Script.scriptEnding.connect(scriptEnding); Script.update.connect(update); Controller.mousePressEvent.connect(mousePressEvent); diff --git a/examples/gun.js b/examples/gun.js index 6f1371e5d9..385664226c 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -6,9 +6,9 @@ // Modified by Philip on 3/3/14 // Copyright 2013 High Fidelity, Inc. // -// This is an example script that turns the hydra controllers and mouse into a particle gun. -// It reads the controller, watches for trigger pulls, and launches particles. -// When particles collide with voxels they blow little holes out of the voxels. +// This is an example script that turns the hydra controllers and mouse into a entity gun. +// It reads the controller, watches for trigger pulls, and launches entities. +// When entities collide with voxels they blow little holes out of the voxels. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -96,9 +96,10 @@ function printVector(string, vector) { function shootBullet(position, velocity) { var BULLET_SIZE = 0.01; var BULLET_GRAVITY = -0.02; - Particles.addParticle( - { position: position, - radius: BULLET_SIZE, + Entities.addEntity( + { type: "Sphere", + position: position, + dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, color: { red: 10, green: 10, blue: 10 }, velocity: velocity, gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, @@ -131,9 +132,10 @@ function shootTarget() { velocity.y += TARGET_UP_VELOCITY; //printVector("velocity", velocity); - Particles.addParticle( - { position: newPosition, - radius: TARGET_SIZE, + Entities.addEntity( + { type: "Sphere", + position: newPosition, + dimensions: { x: TARGET_SIZE, y: TARGET_SIZE, z: TARGET_SIZE }, color: { red: 0, green: 200, blue: 200 }, velocity: velocity, gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, @@ -150,11 +152,11 @@ function shootTarget() { -function particleCollisionWithVoxel(particle, voxel, collision) { +function entityCollisionWithVoxel(entity, voxel, collision) { var HOLE_SIZE = 0.125; - var particleProperties = Particles.getParticleProperties(particle); - var position = particleProperties.position; - Particles.deleteParticle(particle); + var entityProperties = Entities.getEntityProperties(entity); + var position = entityProperties.position; + Entities.deleteEntity(entity); // Make a hole in this voxel //Vec3.print("voxel penetration", collision.penetration); //Vec3.print("voxel contactPoint", collision.contactPoint); @@ -163,13 +165,13 @@ function particleCollisionWithVoxel(particle, voxel, collision) { Audio.playSound(impactSound, audioOptions); } -function particleCollisionWithParticle(particle1, particle2, collision) { +function entityCollisionWithEntity(entity1, entity2, collision) { score++; if (showScore) { Overlays.editOverlay(text, { text: "Score: " + score } ); } - // Sort out which particle is which + // Sort out which entity is which // Record shot time var endTime = new Date(); @@ -177,8 +179,8 @@ function particleCollisionWithParticle(particle1, particle2, collision) { //print("hit, msecs = " + msecs); //Vec3.print("penetration = ", collision.penetration); //Vec3.print("contactPoint = ", collision.contactPoint); - Particles.deleteParticle(particle1); - Particles.deleteParticle(particle2); + Entities.deleteEntity(entity1); + Entities.deleteEntity(entity2); // play the sound near the camera so the shooter can hear it audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); Audio.playSound(targetHitSound, audioOptions); @@ -240,7 +242,6 @@ function update(deltaTime) { for (var t = 0; t < numberOfTriggers; t++) { var shootABullet = false; var triggerValue = Controller.getTriggerValue(t); - if (triggerPulled[t]) { // must release to at least 0.1 if (triggerValue < 0.1) { @@ -254,8 +255,8 @@ function update(deltaTime) { } } + if (shootABullet) { - var palmController = t * controllersPerTrigger; var palmPosition = Controller.getSpatialControlPosition(palmController); @@ -324,8 +325,8 @@ function scriptEnding() { MyAvatar.detachOne(gunModel); } -Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel); -Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle); +Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel); +Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); Script.scriptEnding.connect(scriptEnding); Script.update.connect(update); Controller.mousePressEvent.connect(mousePressEvent); diff --git a/examples/leapOfFaith.js b/examples/leapOfFaith.js index 99d876c523..22c2ed013b 100644 --- a/examples/leapOfFaith.js +++ b/examples/leapOfFaith.js @@ -10,9 +10,6 @@ // - - - var jointList = MyAvatar.getJointNames(); var jointMappings = "\n# Joint list start"; for (var i = 0; i < jointList.length; i++) { @@ -66,24 +63,25 @@ function controlerToSkeletonOri( jointName, isRightSide, event ) { } -var jointParticles = []; -function updateJointParticle( joint, pos, ori, look ) { +var jointShperes = []; +function updateJointShpere( joint, pos, ori, look ) { /* print( "debug 1" ); - var jointID = jointParticles[ joint ]; + var jointID = jointShperes[ joint ]; if ( jointID == null ) { print( "debug create " + joint ); */ var radius = 0.005* look.r; var ballProperties = { + type: "Sphere", position: pos, velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius : radius, + dimensions: { x: radius, y: radius, z: radius }, color: look.c, lifetime: 0.05 }; - var atomPos = Particles.addParticle(ballProperties); + var atomPos = Entities.addEntity(ballProperties); /* // Zaxis var Zaxis = Vec3.multiply( Quat.getFront( ori ), - 1.5 * radius ) ; @@ -91,31 +89,31 @@ function updateJointParticle( joint, pos, ori, look ) { ballProperties.radius = 0.35* radius; ballProperties.color= { red: 255, green: 255, blue: 255 }; - var atomZ = Particles.addParticle(ballProperties); + var atomZ = Entities.addEntity(ballProperties); var up = Vec3.multiply( Quat.getUp( ori ), 1.5 * radius ) ; ballProperties.position = Vec3.sum(pos, up) ; - ballProperties.radius = 0.35* radius; + ballProperties.dimensions = { x: 0.35* radius, y: 0.35* radius, z: 0.35* radius }; ballProperties.color= { red: 0, green: 255, blue: 0 }; - var atomY = Particles.addParticle(ballProperties); + var atomY = Entities.addEntity(ballProperties); var right = Vec3.multiply( Quat.getRight( ori ), 1.5 * radius ) ; ballProperties.position = Vec3.sum(pos, right) ; - ballProperties.radius = 0.35* radius; + ballProperties.dimensions = { x: 0.35* radius, y: 0.35* radius, z: 0.35* radius }; ballProperties.color= { red: 255, green: 0, blue: 225 }; - var atomX = Particles.addParticle(ballProperties); + var atomX = Entities.addEntity(ballProperties); */ - // jointParticles[ joint ] = { p: atomPos, x: atomX, y: atomY, z: atomZ }; + // jointShperes[ joint ] = { p: atomPos, x: atomX, y: atomY, z: atomZ }; /* } else { //print( "debug update " + joint ); - var p = Particles.getParticleProperties( jointID.p ); + var p = Entities.getEntityProperties( jointID.p ); p.position = pos; // p.lifetime = 1.0; - Particles.editParticle( jointID.p, p ); + Entities.editEntity( jointID.p, p ); }*/ @@ -212,7 +210,7 @@ function onSpatialEventHandler( jointName, look ) { // MyAvatar.setJointRotationFromBindSpace(_jointName, controlerToSkeletonOri( _jointName, _side, spatialEvent )); - updateJointParticle(_jointName, + updateJointShpere(_jointName, avatarToWorldPos( spatialEvent.absTranslation ), avatarToWorldQuat( spatialEvent.absRotation ), _look ); diff --git a/examples/paintGun.js b/examples/paintGun.js deleted file mode 100644 index b5bb2a49da..0000000000 --- a/examples/paintGun.js +++ /dev/null @@ -1,101 +0,0 @@ -// -// paintGun.js -// examples -// -// Created by Brad Hefta-Gaub on 12/31/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 -// - -// initialize our triggers -var triggerPulled = new Array(); -var numberOfTriggers = Controller.getNumberOfTriggers(); -for (t = 0; t < numberOfTriggers; t++) { - triggerPulled[t] = false; -} - -function checkController(deltaTime) { - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; - - // this is expected for hydras - if (numberOfTriggers == 2 && controllersPerTrigger == 2) { - for (var t = 0; t < numberOfTriggers; t++) { - var shootABullet = false; - var triggerValue = Controller.getTriggerValue(t); - - if (triggerPulled[t]) { - // must release to at least 0.1 - if (triggerValue < 0.1) { - triggerPulled[t] = false; // unpulled - } - } else { - // must pull to at least 0.9 - if (triggerValue > 0.9) { - triggerPulled[t] = true; // pulled - shootABullet = true; - } - } - - if (shootABullet) { - var palmController = t * controllersPerTrigger; - var palmPosition = Controller.getSpatialControlPosition(palmController); - - var fingerTipController = palmController + 1; - var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController); - - var palmToFingerTipVector = - { x: (fingerTipPosition.x - palmPosition.x), - y: (fingerTipPosition.y - palmPosition.y), - z: (fingerTipPosition.z - palmPosition.z) }; - - // just off the front of the finger tip - var position = { x: fingerTipPosition.x + palmToFingerTipVector.x/2, - y: fingerTipPosition.y + palmToFingerTipVector.y/2, - z: fingerTipPosition.z + palmToFingerTipVector.z/2}; - - var linearVelocity = 25; - - var velocity = { x: palmToFingerTipVector.x * linearVelocity, - y: palmToFingerTipVector.y * linearVelocity, - z: palmToFingerTipVector.z * linearVelocity }; - - // This is the script for the particles that this gun shoots. - var script = - " function collisionWithVoxel(voxel, collision) { " + - " print('collisionWithVoxel(voxel)... '); " + - " Vec3.print('penetration=', collision.penetration); " + - " Vec3.print('contactPoint=', collision.contactPoint); " + - " print('myID=' + Particle.getID() + '\\n'); " + - " var voxelColor = { red: voxel.red, green: voxel.green, blue: voxel.blue };" + - " var voxelAt = { x: voxel.x, y: voxel.y, z: voxel.z };" + - " var voxelScale = voxel.s;" + - " print('voxelColor=' + voxelColor.red + ', ' + voxelColor.green + ', ' + voxelColor.blue + '\\n'); " + - " var myColor = Particle.getColor();" + - " print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " + - " Particle.setColor(voxelColor); " + - " Voxels.setVoxel(voxelAt.x, voxelAt.y, voxelAt.z, voxelScale, 255, 255, 0); " + - " print('Voxels.setVoxel(' + voxelAt.x + ', ' + voxelAt.y + ', ' + voxelAt.z + ', ' + voxelScale + ')... \\n'); " + - " } " + - " Particle.collisionWithVoxel.connect(collisionWithVoxel); "; - - Particles.addParticle( - { position: position, - radius: 0.01, - color: { red: 128, green: 128, blue: 128 }, - velocity: velocity, - gravity: { x: 0, y: -0.1, z: 0 }, - damping: 0, - script: script } - ); - } - } - } -} - - -// register the call back so it fires before each data send -Script.update.connect(checkController); diff --git a/examples/rideAlongWithAParticleExample.js b/examples/rideAlongWithAnEntityExample.js similarity index 61% rename from examples/rideAlongWithAParticleExample.js rename to examples/rideAlongWithAnEntityExample.js index 552f6fb7fe..ce09b296a3 100644 --- a/examples/rideAlongWithAParticleExample.js +++ b/examples/rideAlongWithAnEntityExample.js @@ -1,12 +1,10 @@ // -// rideAlongWithAParticleExample.js +// rideAlongWithAEntityExample.js // examples // // Created by Brad Hefta-Gaub on 1/24/14. // Copyright 2014 High Fidelity, Inc. // -// This is an example script that demonstrates "finding" particles -// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // @@ -14,31 +12,32 @@ var iteration = 0; var lengthOfRide = 2000; // in iterations -var particleA = Particles.addParticle( +var entityA = Entities.addEntity( { + type: "Sphere", position: { x: 10, y: 0, z: 10 }, velocity: { x: 5, y: 0, z: 5 }, gravity: { x: 0, y: 0, z: 0 }, - radius : 0.1, + dimensions: { x: 1, y: 1, z: 1 }, color: { red: 0, green: 255, blue: 0 }, damping: 0, lifetime: (lengthOfRide * 60) + 1 }); -function rideWithParticle(deltaTime) { +function rideWithEntity(deltaTime) { if (iteration <= lengthOfRide) { - // Check to see if we've been notified of the actual identity of the particles we created - if (!particleA.isKnownID) { - particleA = Particles.identifyParticle(particleA); + // Check to see if we've been notified of the actual identity of the entities we created + if (!entityA.isKnownID) { + entityA = Entities.identifyEntity(entityA); } - var propertiesA = Particles.getParticleProperties(particleA); + var propertiesA = Entities.getEntityProperties(entityA); var newPosition = propertiesA.position; - MyAvatar.position = { x: propertiesA.position.x, - y: propertiesA.position.y + 2, - z: propertiesA.position.z }; + MyAvatar.position = { x: propertiesA.position.x - 1, + y: propertiesA.position.y + 0, + z: propertiesA.position.z - 1 }; } else { Script.stop(); } @@ -49,5 +48,5 @@ function rideWithParticle(deltaTime) { // register the call back so it fires before each data send -Script.update.connect(rideWithParticle); +Script.update.connect(rideWithEntity); diff --git a/examples/spaceInvadersExample.js b/examples/spaceInvadersExample.js index 862d731f90..8d69f066d6 100644 --- a/examples/spaceInvadersExample.js +++ b/examples/spaceInvadersExample.js @@ -95,7 +95,7 @@ var currentMoveSound = 0; var numberOfSounds = 4; var stepsPerSound = invaderStepsPerCycle / numberOfSounds; -// if you set this to false, sounds will come from the location of particles instead of the player's head +// if you set this to false, sounds will come from the location of entities instead of the player's head var soundInMyHead = true; // models... @@ -134,18 +134,17 @@ invaderModels[4] = { function initializeMyShip() { myShipProperties = { + type: "Model", position: { x: middleX , y: gameAt.y, z: gameAt.z }, velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius: shipSize, + dimensions: { x: shipSize * 2, y: shipSize * 2, z: shipSize * 2 }, color: { red: 0, green: 255, blue: 0 }, modelURL: HIFI_PUBLIC_BUCKET + "meshes/myCannon16x16.svo", - modelScale: 450, - modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, lifetime: itemLifetimes }; - myShip = Particles.addParticle(myShipProperties); + myShip = Entities.addEntity(myShipProperties); } // calculate the correct invaderPosition for an column row @@ -173,16 +172,15 @@ function initializeInvaders() { invaders[row] = new Array(); for (var column = 0; column < invadersPerRow; column++) { invaderPosition = getInvaderPosition(row, column); - invaders[row][column] = Particles.addParticle({ + invaders[row][column] = Entities.addEntity({ + type: "Model", position: invaderPosition, velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius: invaderSize, + dimensions: { x: invaderSize * 2, y: invaderSize * 2, z: invaderSize * 2 }, color: { red: 255, green: 0, blue: 0 }, modelURL: invaderModels[row].modelURL, - modelScale: invaderModels[row].modelScale, - modelTranslation: invaderModels[row].modelTranslation, lifetime: itemLifetimes }); @@ -194,10 +192,10 @@ function initializeInvaders() { function moveInvaders() { for (var row = 0; row < numberOfRows; row++) { for (var column = 0; column < invadersPerRow; column++) { - props = Particles.getParticleProperties(invaders[row][column]); + props = Entities.getEntityProperties(invaders[row][column]); if (props.isKnownID) { invaderPosition = getInvaderPosition(row, column); - Particles.editParticle(invaders[row][column], + Entities.editEntity(invaders[row][column], { position: invaderPosition, velocity: { x: 0, y: 0, z: 0 } // always reset this, incase they got collided with @@ -266,19 +264,19 @@ Script.update.connect(update); function cleanupGame() { print("cleaning up game..."); - Particles.deleteParticle(myShip); - print("cleanupGame() ... Particles.deleteParticle(myShip)... myShip.id="+myShip.id); + Entities.deleteEntity(myShip); + print("cleanupGame() ... Entities.deleteEntity(myShip)... myShip.id="+myShip.id); for (var row = 0; row < numberOfRows; row++) { for (var column = 0; column < invadersPerRow; column++) { - Particles.deleteParticle(invaders[row][column]); - print("cleanupGame() ... Particles.deleteParticle(invaders[row][column])... invaders[row][column].id=" + Entities.deleteEntity(invaders[row][column]); + print("cleanupGame() ... Entities.deleteEntity(invaders[row][column])... invaders[row][column].id=" +invaders[row][column].id); } } // clean up our missile if (missileFired) { - Particles.deleteParticle(myMissile); + Entities.deleteEntity(myMissile); } Controller.releaseKeyEvents({text: " "}); @@ -293,8 +291,8 @@ function endGame() { } function moveShipTo(position) { - myShip = Particles.identifyParticle(myShip); - Particles.editParticle(myShip, { position: position }); + myShip = Entities.identifyEntity(myShip); + Entities.editEntity(myShip, { position: position }); } function fireMissile() { @@ -303,7 +301,7 @@ function fireMissile() { // If we've fired a missile, then check to see if it's still alive if (missileFired) { - var missileProperties = Particles.getParticleProperties(myMissile); + var missileProperties = Entities.getEntityProperties(myMissile); print("missileProperties.isKnownID=" + missileProperties.isKnownID); if (!missileProperties.isKnownID) { @@ -320,13 +318,14 @@ function fireMissile() { y: myShipProperties.position.y + (2* shipSize), z: myShipProperties.position.z }; - myMissile = Particles.addParticle( + myMissile = Entities.addEntity( { + type: "Sphere", position: missilePosition, velocity: { x: 0, y: 5, z: 0}, gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius: missileSize, + dimensions: { x: missileSize * 2, y: missileSize * 2, z: missileSize * 2 }, color: { red: 0, green: 0, blue: 255 }, lifetime: 5 }); @@ -371,14 +370,14 @@ function keyPressEvent(key) { Controller.keyPressEvent.connect(keyPressEvent); Controller.captureKeyEvents({text: " "}); -function deleteIfInvader(possibleInvaderParticle) { +function deleteIfInvader(possibleInvaderEntity) { for (var row = 0; row < numberOfRows; row++) { for (var column = 0; column < invadersPerRow; column++) { - invaders[row][column] = Particles.identifyParticle(invaders[row][column]); + invaders[row][column] = Entities.identifyEntity(invaders[row][column]); if (invaders[row][column].isKnownID) { - if (invaders[row][column].id == possibleInvaderParticle.id) { - Particles.deleteParticle(possibleInvaderParticle); - Particles.deleteParticle(myMissile); + if (invaders[row][column].id == possibleInvaderEntity.id) { + Entities.deleteEntity(possibleInvaderEntity); + Entities.deleteEntity(myMissile); // play the hit sound var options = new AudioInjectionOptions(); @@ -397,20 +396,20 @@ function deleteIfInvader(possibleInvaderParticle) { } } -function particleCollisionWithParticle(particleA, particleB, collision) { - print("particleCollisionWithParticle() a.id="+particleA.id + " b.id=" + particleB.id); - Vec3.print('particleCollisionWithParticle() penetration=', collision.penetration); - Vec3.print('particleCollisionWithParticle() contactPoint=', collision.contactPoint); +function entityCollisionWithEntity(entityA, entityB, collision) { + print("entityCollisionWithEntity() a.id="+entityA.id + " b.id=" + entityB.id); + Vec3.print('entityCollisionWithEntity() penetration=', collision.penetration); + Vec3.print('entityCollisionWithEntity() contactPoint=', collision.contactPoint); if (missileFired) { - myMissile = Particles.identifyParticle(myMissile); - if (myMissile.id == particleA.id) { - deleteIfInvader(particleB); - } else if (myMissile.id == particleB.id) { - deleteIfInvader(particleA); + myMissile = Entities.identifyEntity(myMissile); + if (myMissile.id == entityA.id) { + deleteIfInvader(entityB); + } else if (myMissile.id == entityB.id) { + deleteIfInvader(entityA); } } } -Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle); +Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); // initialize the game... diff --git a/examples/toyball.js b/examples/toyball.js index f79f3cb1f4..b41dd2bda5 100644 --- a/examples/toyball.js +++ b/examples/toyball.js @@ -6,10 +6,10 @@ // Copyright 2014 High Fidelity, Inc. // // This is an example script that turns the hydra controllers into a toy ball catch and throw game. -// It reads the controller, watches for button presses and trigger pulls, and launches particles. +// It reads the controller, watches for button presses and trigger pulls, and launches entities. // -// The particles it creates have a script that when they collide with Voxels, the -// particle will change it's color to match the voxel it hits. +// The entities it creates have a script that when they collide with Voxels, the +// entity will change it's color to match the voxel it hits. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -36,8 +36,8 @@ var THROWN_COLOR = { red: 128, green: 0, blue: 0 }; var leftBallAlreadyInHand = false; var rightBallAlreadyInHand = false; -var leftHandParticle; -var rightHandParticle; +var leftHandEntity; +var rightHandEntity; var newSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw"); var catchSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw"); @@ -90,18 +90,18 @@ function checkControllerSide(whichSide) { // If I don't currently have a ball in my hand, then try to catch closest one if (!ballAlreadyInHand && grabButtonPressed) { - var closestParticle = Particles.findClosestParticle(palmPosition, targetRadius); + var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius); - if (closestParticle.isKnownID) { + if (closestEntity.isKnownID) { debugPrint(handMessage + " HAND- CAUGHT SOMETHING!!"); if (whichSide == LEFT_PALM) { leftBallAlreadyInHand = true; - leftHandParticle = closestParticle; + leftHandEntity = closestEntity; } else { rightBallAlreadyInHand = true; - rightHandParticle = closestParticle; + rightHandEntity = closestEntity; } var ballPosition = getBallHoldPosition(whichSide); var properties = { position: { x: ballPosition.x, @@ -111,7 +111,7 @@ function checkControllerSide(whichSide) { velocity : { x: 0, y: 0, z: 0}, lifetime : 600, inHand: true }; - Particles.editParticle(closestParticle, properties); + Entities.editEntity(closestEntity, properties); var options = new AudioInjectionOptions(); options.position = ballPosition; @@ -131,26 +131,28 @@ function checkControllerSide(whichSide) { // If '3' is pressed, and not holding a ball, make a new one if (grabButtonPressed && !ballAlreadyInHand) { var ballPosition = getBallHoldPosition(whichSide); - var properties = { position: { x: ballPosition.x, - y: ballPosition.y, - z: ballPosition.z }, + var properties = { + type: "Sphere", + position: { x: ballPosition.x, + y: ballPosition.y, + z: ballPosition.z }, velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0}, inHand: true, - radius: BALL_RADIUS, + radius: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 }, damping: 0.999, color: HELD_COLOR, lifetime: 600 // 10 seconds - same as default, not needed but here as an example }; - newParticle = Particles.addParticle(properties); + newEntity = Entities.addEntity(properties); if (whichSide == LEFT_PALM) { leftBallAlreadyInHand = true; - leftHandParticle = newParticle; + leftHandEntity = newEntity; } else { rightBallAlreadyInHand = true; - rightHandParticle = newParticle; + rightHandEntity = newEntity; } // Play a new ball sound @@ -164,10 +166,10 @@ function checkControllerSide(whichSide) { if (ballAlreadyInHand) { if (whichSide == LEFT_PALM) { - handParticle = leftHandParticle; + handEntity = leftHandEntity; whichTip = LEFT_TIP; } else { - handParticle = rightHandParticle; + handEntity = rightHandEntity; whichTip = RIGHT_TIP; } @@ -179,7 +181,7 @@ function checkControllerSide(whichSide) { y: ballPosition.y, z: ballPosition.z }, }; - Particles.editParticle(handParticle, properties); + Entities.editEntity(handEntity, properties); } else { debugPrint(">>>>> " + handMessage + "-BALL IN HAND, not grabbing, THROW!!!"); // If toy ball just released, add velocity to it! @@ -195,14 +197,14 @@ function checkControllerSide(whichSide) { gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0}, }; - Particles.editParticle(handParticle, properties); + Entities.editEntity(handEntity, properties); if (whichSide == LEFT_PALM) { leftBallAlreadyInHand = false; - leftHandParticle = false; + leftHandEntity = false; } else { rightBallAlreadyInHand = false; - rightHandParticle = false; + rightHandEntity = false; } var options = new AudioInjectionOptions(); diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index a85181b89e..db5aa64210 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 b85e1e4440..7f9a9b5865 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include @@ -313,12 +312,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 @@ -361,16 +359,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(); @@ -447,7 +440,6 @@ Application::~Application() { _octreeProcessor.terminate(); _voxelHideShowThread.terminate(); _voxelEditSender.terminate(); - _particleEditSender.terminate(); _entityEditSender.terminate(); @@ -542,7 +534,6 @@ void Application::initializeGL() { _octreeProcessor.initialize(_enableProcessVoxelsThread); _voxelEditSender.initialize(_enableProcessVoxelsThread); _voxelHideShowThread.initialize(_enableProcessVoxelsThread); - _particleEditSender.initialize(_enableProcessVoxelsThread); _entityEditSender.initialize(_enableProcessVoxelsThread); if (_enableProcessVoxelsThread) { @@ -798,7 +789,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; @@ -1361,7 +1351,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); } @@ -1849,29 +1839,24 @@ void Application::init() { _voxels.setDisableFastVoxelPipeline(false); _voxels.init(); - _particles.init(); - _particles.setViewFrustum(getViewFrustum()); - _entities.init(); _entities.setViewFrustum(getViewFrustum()); _entityCollisionSystem.init(&_entityEditSender, _entities.getTree(), _voxels.getTree(), &_audio, &_avatarManager); + // connect the _entityCollisionSystem to our script engine's EntityScriptingInterface + connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithVoxel, + ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithVoxel); + + connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity, + ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithEntity); + _entityClipboardRenderer.init(); _entityClipboardRenderer.setViewFrustum(getViewFrustum()); _entityClipboardRenderer.setTree(&_entityClipboard); _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); @@ -2088,7 +2073,6 @@ void Application::updateThreads(float deltaTime) { _octreeProcessor.threadRoutine(); _voxelHideShowThread.threadRoutine(); _voxelEditSender.threadRoutine(); - _particleEditSender.threadRoutine(); _entityEditSender.threadRoutine(); } } @@ -2208,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... @@ -2271,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); } @@ -2331,7 +2303,6 @@ int Application::sendNackPackets() { if (node->getActiveSocket() && ( node->getType() == NodeType::VoxelServer - || node->getType() == NodeType::ParticleServer || node->getType() == NodeType::EntityServer) ) { @@ -2722,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); @@ -2919,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"); @@ -3503,13 +3461,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(); @@ -3547,7 +3498,6 @@ void Application::nodeKilled(SharedNodePointer node) { _octreeProcessor.nodeKilled(node); _voxelEditSender.nodeKilled(node); - _particleEditSender.nodeKilled(node); _entityEditSender.nodeKilled(node); if (node->getType() == NodeType::AudioMixer) { @@ -3591,43 +3541,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(); @@ -3719,9 +3632,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"; @@ -3847,9 +3757,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 3e64357063..64c7032403 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -35,8 +35,6 @@ #include #include #include -#include -#include #include #include #include @@ -64,7 +62,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" @@ -197,7 +194,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; } @@ -286,7 +282,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); @@ -478,9 +473,6 @@ private: VoxelSystem _sharedVoxelSystem; ViewFrustum _sharedVoxelSystemViewFrustum; - ParticleTreeRenderer _particles; - ParticleCollisionSystem _particleCollisionSystem; - EntityTreeRenderer _entities; EntityCollisionSystem _entityCollisionSystem; EntityTreeRenderer _entityClipboardRenderer; @@ -492,7 +484,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 3334219dbd..868654b9da 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: @@ -163,11 +156,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 b3a0a200d9..3a213cb64f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -298,8 +298,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())); @@ -346,9 +344,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); @@ -370,7 +365,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 69613f6f54..a1936050ff 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -367,7 +367,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..."; @@ -433,11 +432,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..."; @@ -463,7 +461,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 43a7949490..169583b14b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1004,9 +1004,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 b674254466..bf6f176d22 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1971,7 +1971,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 95263282b3..9bad475838 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -330,7 +330,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/entities/src/EntityCollisionSystem.cpp b/libraries/entities/src/EntityCollisionSystem.cpp index 7f987db9ed..903cd430de 100644 --- a/libraries/entities/src/EntityCollisionSystem.cpp +++ b/libraries/entities/src/EntityCollisionSystem.cpp @@ -66,7 +66,7 @@ void EntityCollisionSystem::checkEntity(EntityItem* entity) { void EntityCollisionSystem::emitGlobalEntityCollisionWithVoxel(EntityItem* entity, VoxelDetail* voxelDetails, const CollisionInfo& collision) { EntityItemID entityItemID = entity->getEntityItemID(); - emit EntityCollisionWithVoxel(entityItemID, *voxelDetails, collision); + emit entityCollisionWithVoxel(entityItemID, *voxelDetails, collision); } void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* entityA, @@ -74,7 +74,7 @@ void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* enti EntityItemID idA = entityA->getEntityItemID(); EntityItemID idB = entityB->getEntityItemID(); - emit EntityCollisionWithEntity(idA, idB, collision); + emit entityCollisionWithEntity(idA, idB, collision); } void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) { diff --git a/libraries/entities/src/EntityCollisionSystem.h b/libraries/entities/src/EntityCollisionSystem.h index b2cf7a9df4..4b483122fe 100644 --- a/libraries/entities/src/EntityCollisionSystem.h +++ b/libraries/entities/src/EntityCollisionSystem.h @@ -54,8 +54,8 @@ public: void updateCollisionSound(EntityItem* Entity, const glm::vec3 &penetration, float frequency); signals: - void EntityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const CollisionInfo& penetration); - void EntityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& penetration); + void entityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const CollisionInfo& penetration); + void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& penetration); private: void applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 0a79aa87d9..1497b2966e 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -97,6 +97,10 @@ public slots: Q_INVOKABLE void dumpTree() const; +signals: + void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const CollisionInfo& collision); + void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& collision); + private: void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); 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 be4fb68bfb..283765c265 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 ab596673f5..7632f47686 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 << PacketTypeDomainConnectionDenied << 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"; } }