From 6b0d7c30f0857cef3437c09a08399681a7f32cc5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 16:58:49 -0800 Subject: [PATCH 01/16] added debugging option for forced clock skew --- interface/src/main.cpp | 11 +++++++++++ libraries/shared/src/SharedUtil.cpp | 3 ++- libraries/shared/src/SharedUtil.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 07788fefe0..c348ab6dc3 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -19,11 +19,22 @@ #include #include +#include int main(int argc, const char * argv[]) { timeval startup_time; gettimeofday(&startup_time, NULL); + // Debug option to demonstrate that the client's local time does not + // need to be in sync with any other network node. This forces clock + // skew for the individual client + const char* TIME_ADJUST = "--usecTimestampNowAdjust"; + const char* timeAdjustOption = getCmdOption(argc, argv, TIME_ADJUST); + if (timeAdjustOption) { + ::usecTimestampNowAdjust = atoi(timeAdjustOption); + qDebug("timeAdjustOption=%s usecTimestampNowAdjust=%d\n", timeAdjustOption, ::usecTimestampNowAdjust); + } + int exitCode; { Application app(argc, const_cast(argv), startup_time); diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 9a6bb8b4c3..3d79e7fcc2 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -30,10 +30,11 @@ uint64_t usecTimestamp(const timeval *time) { return (time->tv_sec * 1000000 + time->tv_usec); } +int usecTimestampNowAdjust = 0; uint64_t usecTimestampNow() { timeval now; gettimeofday(&now, NULL); - return (now.tv_sec * 1000000 + now.tv_usec); + return (now.tv_sec * 1000000 + now.tv_usec) + usecTimestampNowAdjust; } float randFloat () { diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index cd6444624f..7752e2e72c 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -56,6 +56,7 @@ static const uint64_t USECS_PER_SECOND = 1000 * 1000; uint64_t usecTimestamp(const timeval *time); uint64_t usecTimestampNow(); +extern int usecTimestampNowAdjust; float randFloat(); int randIntInRange (int min, int max); From 1badc8dc5df5e5c0e7a1afdc82662817eb59195c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 16:59:36 -0800 Subject: [PATCH 02/16] first pass at removing timestamps from particles removed _lastUpdated/getLastUpdated() --- libraries/octree-server/src/OctreeServer.cpp | 10 ++++++ libraries/particles/src/Particle.cpp | 31 ++++--------------- libraries/particles/src/Particle.h | 6 ++-- .../particles/src/ParticleEditHandle.cpp | 4 +-- .../src/ParticleScriptingInterface.cpp | 2 +- .../particles/src/ParticleTreeElement.cpp | 10 ++++-- libraries/shared/src/PacketHeaders.cpp | 2 +- 7 files changed, 30 insertions(+), 35 deletions(-) diff --git a/libraries/octree-server/src/OctreeServer.cpp b/libraries/octree-server/src/OctreeServer.cpp index ffb5f9c976..7ab0705d40 100644 --- a/libraries/octree-server/src/OctreeServer.cpp +++ b/libraries/octree-server/src/OctreeServer.cpp @@ -656,6 +656,16 @@ void OctreeServer::run() { _persistThread->initialize(true); } } + + // Debug option to demonstrate that the server's local time does not + // need to be in sync with any other network node. This forces clock + // skew for the individual server node + const char* TIME_ADJUST = "--usecTimestampNowAdjust"; + const char* timeAdjustOption = getCmdOption(_argc, _argv, TIME_ADJUST); + if (timeAdjustOption) { + ::usecTimestampNowAdjust = atoi(timeAdjustOption); + qDebug("timeAdjustOption=%s usecTimestampNowAdjust=%d\n", timeAdjustOption, ::usecTimestampNowAdjust); + } // Check to see if the user passed in a command line option for setting packet send rate const char* PACKETS_PER_SECOND = "--packetsPerSecond"; diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index fb5d603d7d..beb8203b66 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -42,8 +42,9 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 } else { _id = id; } - _lastUpdated = usecTimestampNow(); - _lastEdited = _lastUpdated; + uint64_t now = usecTimestampNow(); + _lastEdited = now; + _lastSimulated = now; _position = position; _radius = radius; @@ -65,9 +66,6 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { if (success) { success = packetData->appendValue(getCreated()); } - if (success) { - success = packetData->appendValue(getLastUpdated()); - } if (success) { success = packetData->appendValue(getLastEdited()); } @@ -124,11 +122,6 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += sizeof(_created); bytesRead += sizeof(_created); - // lastupdated - memcpy(&_lastUpdated, dataAt, sizeof(_lastUpdated)); - dataAt += sizeof(_lastUpdated); - bytesRead += sizeof(_lastUpdated); - // _lastEdited memcpy(&_lastEdited, dataAt, sizeof(_lastEdited)); dataAt += sizeof(_lastEdited); @@ -186,7 +179,7 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef Particle Particle::fromEditPacket(unsigned char* data, int length, int& processedBytes) { - Particle newParticle; // id and lastUpdated will get set here... + Particle newParticle; // id and _lastSimulated will get set here... unsigned char* dataAt = data; processedBytes = 0; @@ -224,11 +217,6 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe dataAt += sizeof(newParticle._created); processedBytes += sizeof(newParticle._created); - // lastUpdated - memcpy(&newParticle._lastUpdated, dataAt, sizeof(newParticle._lastUpdated)); - dataAt += sizeof(newParticle._lastUpdated); - processedBytes += sizeof(newParticle._lastUpdated); - // lastEdited memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited)); dataAt += sizeof(newParticle._lastEdited); @@ -292,7 +280,6 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe void Particle::debugDump() const { printf("Particle id :%u\n", _id); printf(" created:%llu\n", _created); - printf(" last updated:%llu\n", _lastUpdated); printf(" last edited:%llu\n", _lastEdited); printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z); printf(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z); @@ -347,11 +334,6 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, copyAt += sizeof(created); sizeOut += sizeof(created); - // lastUpdated - memcpy(copyAt, &details[i].lastUpdated, sizeof(details[i].lastUpdated)); - copyAt += sizeof(details[i].lastUpdated); - sizeOut += sizeof(details[i].lastUpdated); - // lastEdited memcpy(copyAt, &details[i].lastEdited, sizeof(details[i].lastEdited)); copyAt += sizeof(details[i].lastEdited); @@ -405,7 +387,6 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, if (wantDebugging) { printf("encodeParticleEditMessageDetails()....\n"); printf("Particle id :%u\n", details[i].id); - printf(" last updated:%llu\n", details[i].lastUpdated); printf(" nextID:%u\n", _nextID); } } @@ -419,7 +400,7 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, void Particle::update() { uint64_t now = usecTimestampNow(); - uint64_t elapsed = now - _lastUpdated; + uint64_t elapsed = now - _lastSimulated; uint64_t USECS_PER_SECOND = 1000 * 1000; float timeElapsed = (float)((float)elapsed/(float)USECS_PER_SECOND); @@ -454,7 +435,7 @@ void Particle::update() { //printf("applying damping to Particle timeElapsed=%f\n",timeElapsed); } - _lastUpdated = now; + _lastSimulated = now; } void Particle::runScript() { diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 33e8960670..68e2b10174 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -25,7 +25,6 @@ const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF; class ParticleDetail { public: uint32_t id; - uint64_t lastUpdated; uint64_t lastEdited; glm::vec3 position; float radius; @@ -70,7 +69,6 @@ public: float getDamping() const { return _damping; } uint64_t getCreated() const { return _created; } uint64_t getLifetime() const { return usecTimestampNow() - _created; } - uint64_t getLastUpdated() const { return _lastUpdated; } uint64_t getLastEdited() const { return _lastEdited; } uint32_t getID() const { return _id; } bool getShouldDie() const { return _shouldDie; } @@ -116,7 +114,6 @@ protected: rgbColor _color; float _radius; glm::vec3 _velocity; - uint64_t _lastUpdated; uint64_t _created; uint64_t _lastEdited; uint32_t _id; @@ -129,6 +126,9 @@ protected: uint32_t _creatorTokenID; bool _newlyCreated; + + uint64_t _lastSimulated; + }; class ParticleScriptObject : public QObject { diff --git a/libraries/particles/src/ParticleEditHandle.cpp b/libraries/particles/src/ParticleEditHandle.cpp index 28356ce63e..88d3143a0f 100644 --- a/libraries/particles/src/ParticleEditHandle.cpp +++ b/libraries/particles/src/ParticleEditHandle.cpp @@ -45,7 +45,7 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor // setup a ParticleDetail struct with the data uint64_t now = usecTimestampNow(); - ParticleDetail addParticleDetail = { NEW_PARTICLE, now, now, + ParticleDetail addParticleDetail = { NEW_PARTICLE, now, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, _creatorTokenID }; @@ -71,7 +71,7 @@ bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor // setup a ParticleDetail struct with the data uint64_t now = usecTimestampNow(); - ParticleDetail newParticleDetail = { _id, now, now, + ParticleDetail newParticleDetail = { _id, now, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, _creatorTokenID }; diff --git a/libraries/particles/src/ParticleScriptingInterface.cpp b/libraries/particles/src/ParticleScriptingInterface.cpp index ec8209208c..8edfae3b88 100644 --- a/libraries/particles/src/ParticleScriptingInterface.cpp +++ b/libraries/particles/src/ParticleScriptingInterface.cpp @@ -23,7 +23,7 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl // setup a ParticleDetail struct with the data uint64_t now = usecTimestampNow(); - ParticleDetail addParticleDetail = { NEW_PARTICLE, now, now, + ParticleDetail addParticleDetail = { NEW_PARTICLE, now, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, creatorTokenID }; diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index a631eae926..9ab0a2b4e9 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -119,18 +119,20 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { uint16_t numberOfParticles = _particles.size(); for (uint16_t i = 0; i < numberOfParticles; i++) { if (_particles[i].getID() == particle.getID()) { - int difference = _particles[i].getLastUpdated() - particle.getLastUpdated(); + //int difference = _particles[i].getLastUpdated() - particle.getLastUpdated(); + //bool localOlder = _particles[i].getLastUpdated() < particle.getLastUpdated(); bool changedOnServer = _particles[i].getLastEdited() < particle.getLastEdited(); - bool localOlder = _particles[i].getLastUpdated() < particle.getLastUpdated(); - if (changedOnServer || localOlder) { + if (changedOnServer /*|| localOlder*/) { if (wantDebug) { + /** printf("local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s\n", particle.getID(), (changedOnServer ? "CHANGED" : "same"), (localOlder ? "OLDER" : "NEWER"), difference, debug::valueOf(particle.isNewlyCreated()) ); + **/ } uint64_t actuallyCreated = particle.getCreated(); @@ -141,11 +143,13 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { _particles[i].setCreated(actuallyCreated); } else { if (wantDebug) { + /** printf(">>> NO CHANGE <<< -- local particle [id:%d] %s and %s than server particle by %d, " "particle.isNewlyCreated()=%s\n", particle.getID(), (changedOnServer ? "CHANGED" : "same"), (localOlder ? "OLDER" : "NEWER"), difference, debug::valueOf(particle.isNewlyCreated()) ); + **/ } } return true; diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index e7c16367aa..24865fff5c 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -54,7 +54,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 2; case PACKET_TYPE_PARTICLE_DATA: - return 3; + return 4; default: return 0; From 8b1c39a47168d726b4d72f5a8fd0e232f9d8539d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 17:03:53 -0800 Subject: [PATCH 03/16] more lastUpdated-ectomy --- .../particles/src/ParticleTreeElement.cpp | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index 9ab0a2b4e9..6905bb7021 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -119,20 +119,12 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { uint16_t numberOfParticles = _particles.size(); for (uint16_t i = 0; i < numberOfParticles; i++) { if (_particles[i].getID() == particle.getID()) { - //int difference = _particles[i].getLastUpdated() - particle.getLastUpdated(); - //bool localOlder = _particles[i].getLastUpdated() < particle.getLastUpdated(); - bool changedOnServer = _particles[i].getLastEdited() < particle.getLastEdited(); - - if (changedOnServer /*|| localOlder*/) { - + if (changedOnServer) { if (wantDebug) { - /** - printf("local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s\n", + printf("local particle [id:%d] %s, particle.isNewlyCreated()=%s\n", particle.getID(), (changedOnServer ? "CHANGED" : "same"), - (localOlder ? "OLDER" : "NEWER"), - difference, debug::valueOf(particle.isNewlyCreated()) ); - **/ + debug::valueOf(particle.isNewlyCreated()) ); } uint64_t actuallyCreated = particle.getCreated(); @@ -143,13 +135,9 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { _particles[i].setCreated(actuallyCreated); } else { if (wantDebug) { - /** - printf(">>> NO CHANGE <<< -- local particle [id:%d] %s and %s than server particle by %d, " - "particle.isNewlyCreated()=%s\n", + printf(">>> NO CHANGE <<< -- local particle [id:%d] %s particle.isNewlyCreated()=%s\n", particle.getID(), (changedOnServer ? "CHANGED" : "same"), - (localOlder ? "OLDER" : "NEWER"), - difference, debug::valueOf(particle.isNewlyCreated()) ); - **/ + debug::valueOf(particle.isNewlyCreated()) ); } } return true; From c68a226094763c45b6d0c32b9cb5950210e8a475 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 17:43:48 -0800 Subject: [PATCH 04/16] removing of created timestamp from wire format, still supports lifetime --- libraries/particles/src/Particle.cpp | 55 ++++++++++--------- libraries/particles/src/Particle.h | 12 ++-- .../particles/src/ParticleTreeElement.cpp | 6 +- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index beb8203b66..d68a55ce3b 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -36,7 +36,6 @@ Particle::~Particle() { void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString updateScript, uint32_t id) { if (id == NEW_PARTICLE) { - _created = usecTimestampNow(); _id = _nextID; _nextID++; } else { @@ -45,7 +44,8 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 uint64_t now = usecTimestampNow(); _lastEdited = now; _lastSimulated = now; - + _created = now; // will get updated as appropriate in setLifetime() + _position = position; _radius = radius; memcpy(_color, color, sizeof(_color)); @@ -64,7 +64,7 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { //printf("Particle::appendParticleData()... getID()=%d\n", getID()); if (success) { - success = packetData->appendValue(getCreated()); + success = packetData->appendValue(getLifetime()); } if (success) { success = packetData->appendValue(getLastEdited()); @@ -101,9 +101,17 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { } int Particle::expectedBytes() { - int expectedBytes = sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(float) + - sizeof(glm::vec3) + sizeof(rgbColor) + sizeof(glm::vec3) + - sizeof(glm::vec3) + sizeof(float) + sizeof(bool); + int expectedBytes = sizeof(uint32_t) // id + + sizeof(float) // lifetime + + sizeof(uint64_t) // lastedited + + sizeof(float) // radius + + sizeof(glm::vec3) // position + + sizeof(rgbColor) // color + + sizeof(glm::vec3) // velocity + + sizeof(glm::vec3) // gravity + + sizeof(float) // damping + + sizeof(bool); // inhand + // potentially more... return expectedBytes; } @@ -117,10 +125,12 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += sizeof(_id); bytesRead += sizeof(_id); - // created - memcpy(&_created, dataAt, sizeof(_created)); - dataAt += sizeof(_created); - bytesRead += sizeof(_created); + // lifetime + float lifetime; + memcpy(&lifetime, dataAt, sizeof(lifetime)); + dataAt += sizeof(lifetime); + bytesRead += sizeof(lifetime); + setLifetime(lifetime); // _lastEdited memcpy(&_lastEdited, dataAt, sizeof(_lastEdited)); @@ -207,16 +217,14 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe processedBytes += sizeof(creatorTokenID); newParticle.setCreatorTokenID(creatorTokenID); newParticle._newlyCreated = true; + + newParticle.setLifetime(0); // this guy is new! + } else { newParticle._id = editID; newParticle._newlyCreated = false; } - // created - memcpy(&newParticle._created, dataAt, sizeof(newParticle._created)); - dataAt += sizeof(newParticle._created); - processedBytes += sizeof(newParticle._created); - // lastEdited memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited)); dataAt += sizeof(newParticle._lastEdited); @@ -279,7 +287,7 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe void Particle::debugDump() const { printf("Particle id :%u\n", _id); - printf(" created:%llu\n", _created); + printf(" lifetime:%f\n", getLifetime()); printf(" last edited:%llu\n", _lastEdited); printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z); printf(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z); @@ -312,7 +320,6 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, sizeOut += lengthOfOctcode; // Now add our edit content details... - uint64_t created = usecTimestampNow(); // id memcpy(copyAt, &details[i].id, sizeof(details[i].id)); @@ -325,15 +332,8 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, memcpy(copyAt, &details[i].creatorTokenID, sizeof(details[i].creatorTokenID)); copyAt += sizeof(details[i].creatorTokenID); sizeOut += sizeof(details[i].creatorTokenID); - } else { - created = 0; } - // created - memcpy(copyAt, &created, sizeof(created)); - copyAt += sizeof(created); - sizeOut += sizeof(created); - // lastEdited memcpy(copyAt, &details[i].lastEdited, sizeof(details[i].lastEdited)); copyAt += sizeof(details[i].lastEdited); @@ -413,7 +413,7 @@ void Particle::update() { bool isInHand = getInHand(); bool shouldDie = !isInHand && !isStillMoving && isReallyOld; setShouldDie(shouldDie); - + runScript(); // allow the javascript to alter our state // If the ball is in hand, it doesn't move or have gravity effect it @@ -465,3 +465,8 @@ void Particle::runScript() { } } } + +void Particle::setLifetime(float lifetime) { + uint64_t lifetimeInUsecs = lifetime * USECS_PER_SECOND; + _created = usecTimestampNow() - lifetimeInUsecs; +} diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 68e2b10174..aa884762ad 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -67,8 +67,10 @@ public: const glm::vec3& getGravity() const { return _gravity; } bool getInHand() const { return _inHand; } float getDamping() const { return _damping; } - uint64_t getCreated() const { return _created; } - uint64_t getLifetime() const { return usecTimestampNow() - _created; } + + /// lifetime of the particle in seconds + float getLifetime() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } + uint64_t getLastEdited() const { return _lastEdited; } uint32_t getID() const { return _id; } bool getShouldDie() const { return _shouldDie; } @@ -91,7 +93,7 @@ public: void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; } void setUpdateScript(QString updateScript) { _updateScript = updateScript; } void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; } - void setCreated(uint64_t created) { _created = created; } + void setLifetime(float lifetime); bool appendParticleData(OctreePacketData* packetData) const; int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); @@ -144,8 +146,8 @@ public slots: float getDamping() const { return _particle->getDamping(); } float getRadius() const { return _particle->getRadius(); } bool getShouldDie() { return _particle->getShouldDie(); } - float getCreated() const { return ((float)_particle->getCreated() / (float)USECS_PER_SECOND); } - float getLifetime() const { return ((float)_particle->getLifetime() / (float)USECS_PER_SECOND); } + //float getCreated() const { return ((float)_particle->getCreated() / (float)USECS_PER_SECOND); } + float getLifetime() const { return _particle->getLifetime(); } void setPosition(glm::vec3 value) { _particle->setPosition(value); } diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index 6905bb7021..3d9f208408 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -127,12 +127,12 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { debug::valueOf(particle.isNewlyCreated()) ); } - uint64_t actuallyCreated = particle.getCreated(); + float actualLifetime = particle.getLifetime(); if (!particle.isNewlyCreated()) { - actuallyCreated = _particles[i].getCreated(); + actualLifetime = _particles[i].getLifetime(); } _particles[i] = particle; - _particles[i].setCreated(actuallyCreated); + _particles[i].setLifetime(actualLifetime); } else { if (wantDebug) { printf(">>> NO CHANGE <<< -- local particle [id:%d] %s particle.isNewlyCreated()=%s\n", From 920ef65ccbbeffca4f570c766cff152554f02fa1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 19:01:42 -0800 Subject: [PATCH 05/16] removed _lastedEdited changed to editedAgo --- libraries/particles/src/Particle.cpp | 51 +++++++++++-------- libraries/particles/src/Particle.h | 20 +++++--- .../particles/src/ParticleEditHandle.cpp | 6 +-- .../src/ParticleScriptingInterface.cpp | 3 +- .../particles/src/ParticleTreeElement.cpp | 10 +--- 5 files changed, 49 insertions(+), 41 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index d68a55ce3b..3f231ac483 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -42,7 +42,7 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 _id = id; } uint64_t now = usecTimestampNow(); - _lastEdited = now; + _edited = now; _lastSimulated = now; _created = now; // will get updated as appropriate in setLifetime() @@ -67,7 +67,7 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { success = packetData->appendValue(getLifetime()); } if (success) { - success = packetData->appendValue(getLastEdited()); + success = packetData->appendValue(getEditedAgo()); } if (success) { success = packetData->appendValue(getRadius()); @@ -103,7 +103,7 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { int Particle::expectedBytes() { int expectedBytes = sizeof(uint32_t) // id + sizeof(float) // lifetime - + sizeof(uint64_t) // lastedited + + sizeof(float) // edited ago + sizeof(float) // radius + sizeof(glm::vec3) // position + sizeof(rgbColor) // color @@ -132,10 +132,12 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef bytesRead += sizeof(lifetime); setLifetime(lifetime); - // _lastEdited - memcpy(&_lastEdited, dataAt, sizeof(_lastEdited)); - dataAt += sizeof(_lastEdited); - bytesRead += sizeof(_lastEdited); + // edited ago + float editedAgo; + memcpy(&editedAgo, dataAt, sizeof(editedAgo)); + dataAt += sizeof(editedAgo); + bytesRead += sizeof(editedAgo); + setEditedAgo(editedAgo); // radius memcpy(&_radius, dataAt, sizeof(_radius)); @@ -225,11 +227,9 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe newParticle._newlyCreated = false; } - // lastEdited - memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited)); - dataAt += sizeof(newParticle._lastEdited); - processedBytes += sizeof(newParticle._lastEdited); - + // clearly we just edited it + newParticle.setEditedAgo(0); + // radius memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius)); dataAt += sizeof(newParticle._radius); @@ -288,7 +288,7 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe void Particle::debugDump() const { printf("Particle id :%u\n", _id); printf(" lifetime:%f\n", getLifetime()); - printf(" last edited:%llu\n", _lastEdited); + printf(" edited ago:%f\n", getEditedAgo()); printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z); printf(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z); printf(" gravity:%f,%f,%f\n", _gravity.x, _gravity.y, _gravity.z); @@ -334,11 +334,6 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, sizeOut += sizeof(details[i].creatorTokenID); } - // lastEdited - memcpy(copyAt, &details[i].lastEdited, sizeof(details[i].lastEdited)); - copyAt += sizeof(details[i].lastEdited); - sizeOut += sizeof(details[i].lastEdited); - // radius memcpy(copyAt, &details[i].radius, sizeof(details[i].radius)); copyAt += sizeof(details[i].radius); @@ -399,20 +394,25 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, void Particle::update() { + uint64_t now = usecTimestampNow(); uint64_t elapsed = now - _lastSimulated; - uint64_t USECS_PER_SECOND = 1000 * 1000; float timeElapsed = (float)((float)elapsed/(float)USECS_PER_SECOND); + // calculate our default shouldDie state... then allow script to change it if it wants... float velocityScalar = glm::length(getVelocity()); const float STILL_MOVING = 0.05 / TREE_SCALE; bool isStillMoving = (velocityScalar > STILL_MOVING); - const uint64_t REALLY_OLD = 30 * 1000 * 1000; + const float REALLY_OLD = 300.0f; // 300 seconds bool isReallyOld = (getLifetime() > REALLY_OLD); bool isInHand = getInHand(); bool shouldDie = !isInHand && !isStillMoving && isReallyOld; setShouldDie(shouldDie); + +printf("Particle::update()... timeElapsed: %f lifeTime:%f editedAgo:%f isInHand:%s isStillMoveing:%s isReallyOld:%s shouldDie:%s\n", + timeElapsed, getLifetime(), getEditedAgo(), debug::valueOf(isInHand), debug::valueOf(isStillMoving), + debug::valueOf(isReallyOld), debug::valueOf(shouldDie)); runScript(); // allow the javascript to alter our state @@ -470,3 +470,14 @@ void Particle::setLifetime(float lifetime) { uint64_t lifetimeInUsecs = lifetime * USECS_PER_SECOND; _created = usecTimestampNow() - lifetimeInUsecs; } + +void Particle::setEditedAgo(float editedAgo) { + uint64_t editedAgoInUsecs = editedAgo * USECS_PER_SECOND; + _edited = usecTimestampNow() - editedAgoInUsecs; +} + +void Particle::copyChangedProperties(const Particle& other) { + float lifetime = getLifetime(); + *this = other; + setLifetime(lifetime); +} diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index aa884762ad..e818a2e91d 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -25,7 +25,6 @@ const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF; class ParticleDetail { public: uint32_t id; - uint64_t lastEdited; glm::vec3 position; float radius; rgbColor color; @@ -70,8 +69,8 @@ public: /// lifetime of the particle in seconds float getLifetime() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } - - uint64_t getLastEdited() const { return _lastEdited; } + /// seconds since last edited + float getEditedAgo() const { return (float)(usecTimestampNow() - _edited) / (float)USECS_PER_SECOND; } uint32_t getID() const { return _id; } bool getShouldDie() const { return _shouldDie; } QString getUpdateScript() const { return _updateScript; } @@ -93,7 +92,6 @@ public: void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; } void setUpdateScript(QString updateScript) { _updateScript = updateScript; } void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; } - void setLifetime(float lifetime); bool appendParticleData(OctreePacketData* packetData) const; int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); @@ -105,19 +103,24 @@ public: void update(); void debugDump() const; + + // similar to an assignment, but it handles no breaking lifetime and editedAgo + void copyChangedProperties(const Particle& other); + protected: void runScript(); static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3); static void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3); static QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color); static void xColorFromScriptValue(const QScriptValue &object, xColor& color); + + void setLifetime(float lifetime); + void setEditedAgo(float editedAgo); glm::vec3 _position; rgbColor _color; float _radius; glm::vec3 _velocity; - uint64_t _created; - uint64_t _lastEdited; uint32_t _id; static uint32_t _nextID; bool _shouldDie; @@ -128,8 +131,11 @@ protected: uint32_t _creatorTokenID; bool _newlyCreated; - + + // these are never included in wire time uint64_t _lastSimulated; + uint64_t _created; + uint64_t _edited; }; diff --git a/libraries/particles/src/ParticleEditHandle.cpp b/libraries/particles/src/ParticleEditHandle.cpp index 88d3143a0f..d8466816c4 100644 --- a/libraries/particles/src/ParticleEditHandle.cpp +++ b/libraries/particles/src/ParticleEditHandle.cpp @@ -44,8 +44,7 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor glm::vec3 gravity, float damping, bool inHand, QString updateScript) { // setup a ParticleDetail struct with the data - uint64_t now = usecTimestampNow(); - ParticleDetail addParticleDetail = { NEW_PARTICLE, now, + ParticleDetail addParticleDetail = { NEW_PARTICLE, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, _creatorTokenID }; @@ -70,8 +69,7 @@ bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor } // setup a ParticleDetail struct with the data - uint64_t now = usecTimestampNow(); - ParticleDetail newParticleDetail = { _id, now, + ParticleDetail newParticleDetail = { _id, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, _creatorTokenID }; diff --git a/libraries/particles/src/ParticleScriptingInterface.cpp b/libraries/particles/src/ParticleScriptingInterface.cpp index 8edfae3b88..758b50035d 100644 --- a/libraries/particles/src/ParticleScriptingInterface.cpp +++ b/libraries/particles/src/ParticleScriptingInterface.cpp @@ -22,8 +22,7 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl _nextCreatorTokenID++; // setup a ParticleDetail struct with the data - uint64_t now = usecTimestampNow(); - ParticleDetail addParticleDetail = { NEW_PARTICLE, now, + ParticleDetail addParticleDetail = { NEW_PARTICLE, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, creatorTokenID }; diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index 3d9f208408..b142c1f568 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -119,20 +119,14 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { uint16_t numberOfParticles = _particles.size(); for (uint16_t i = 0; i < numberOfParticles; i++) { if (_particles[i].getID() == particle.getID()) { - bool changedOnServer = _particles[i].getLastEdited() < particle.getLastEdited(); + bool changedOnServer = _particles[i].getEditedAgo() > particle.getEditedAgo(); if (changedOnServer) { if (wantDebug) { printf("local particle [id:%d] %s, particle.isNewlyCreated()=%s\n", particle.getID(), (changedOnServer ? "CHANGED" : "same"), debug::valueOf(particle.isNewlyCreated()) ); } - - float actualLifetime = particle.getLifetime(); - if (!particle.isNewlyCreated()) { - actualLifetime = _particles[i].getLifetime(); - } - _particles[i] = particle; - _particles[i].setLifetime(actualLifetime); + _particles[i].copyChangedProperties(particle); } else { if (wantDebug) { printf(">>> NO CHANGE <<< -- local particle [id:%d] %s particle.isNewlyCreated()=%s\n", From c6933239d9c2c1419c845f70194f2ff33ff8c554 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 19:21:30 -0800 Subject: [PATCH 06/16] fixed comment --- libraries/particles/src/Particle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index e818a2e91d..051f9bf59d 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -104,7 +104,7 @@ public: void debugDump() const; - // similar to an assignment, but it handles no breaking lifetime and editedAgo + // similar to assignment/copy, but it handles keeping lifetime accurate void copyChangedProperties(const Particle& other); protected: From 6e2c0032b5c6ed1189ebcbd11a32b748eac2eadc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 19:22:15 -0800 Subject: [PATCH 07/16] removed dead code --- libraries/particles/src/Particle.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 051f9bf59d..995a8675ce 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -152,10 +152,8 @@ public slots: float getDamping() const { return _particle->getDamping(); } float getRadius() const { return _particle->getRadius(); } bool getShouldDie() { return _particle->getShouldDie(); } - //float getCreated() const { return ((float)_particle->getCreated() / (float)USECS_PER_SECOND); } float getLifetime() const { return _particle->getLifetime(); } - void setPosition(glm::vec3 value) { _particle->setPosition(value); } void setVelocity(glm::vec3 value) { _particle->setVelocity(value); } void setGravity(glm::vec3 value) { _particle->setGravity(value); } From 5b36953e8187359fdeea140ac8767df6df97f43e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 19:33:52 -0800 Subject: [PATCH 08/16] cleanup clockSkew debug options and remove some chatty logs --- interface/src/main.cpp | 11 ++++++----- libraries/octree-server/src/OctreeServer.cpp | 11 ++++++----- libraries/particles/src/Particle.cpp | 12 ++++++++---- libraries/shared/src/SharedUtil.cpp | 6 +++++- libraries/shared/src/SharedUtil.h | 2 +- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c348ab6dc3..7a5703a881 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -28,11 +28,12 @@ int main(int argc, const char * argv[]) { // Debug option to demonstrate that the client's local time does not // need to be in sync with any other network node. This forces clock // skew for the individual client - const char* TIME_ADJUST = "--usecTimestampNowAdjust"; - const char* timeAdjustOption = getCmdOption(argc, argv, TIME_ADJUST); - if (timeAdjustOption) { - ::usecTimestampNowAdjust = atoi(timeAdjustOption); - qDebug("timeAdjustOption=%s usecTimestampNowAdjust=%d\n", timeAdjustOption, ::usecTimestampNowAdjust); + const char* CLOCK_SKEW = "--clockSkew"; + const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW); + if (clockSkewOption) { + int clockSkew = atoi(clockSkewOption); + usecTimestampNowForceClockSkew(clockSkew); + qDebug("clockSkewOption=%s clockSkew=%d\n", clockSkewOption, clockSkew); } int exitCode; diff --git a/libraries/octree-server/src/OctreeServer.cpp b/libraries/octree-server/src/OctreeServer.cpp index 7ab0705d40..a8010cefaf 100644 --- a/libraries/octree-server/src/OctreeServer.cpp +++ b/libraries/octree-server/src/OctreeServer.cpp @@ -660,11 +660,12 @@ void OctreeServer::run() { // Debug option to demonstrate that the server's local time does not // need to be in sync with any other network node. This forces clock // skew for the individual server node - const char* TIME_ADJUST = "--usecTimestampNowAdjust"; - const char* timeAdjustOption = getCmdOption(_argc, _argv, TIME_ADJUST); - if (timeAdjustOption) { - ::usecTimestampNowAdjust = atoi(timeAdjustOption); - qDebug("timeAdjustOption=%s usecTimestampNowAdjust=%d\n", timeAdjustOption, ::usecTimestampNowAdjust); + const char* CLOCK_SKEW = "--clockSkew"; + const char* clockSkewOption = getCmdOption(_argc, _argv, CLOCK_SKEW); + if (clockSkewOption) { + int clockSkew = atoi(clockSkewOption); + usecTimestampNowForceClockSkew(clockSkew); + qDebug("clockSkewOption=%s clockSkew=%d\n", clockSkewOption, clockSkew); } // Check to see if the user passed in a command line option for setting packet send rate diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 3f231ac483..c2f86c7b75 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -409,11 +409,15 @@ void Particle::update() { bool isInHand = getInHand(); bool shouldDie = !isInHand && !isStillMoving && isReallyOld; setShouldDie(shouldDie); - -printf("Particle::update()... timeElapsed: %f lifeTime:%f editedAgo:%f isInHand:%s isStillMoveing:%s isReallyOld:%s shouldDie:%s\n", - timeElapsed, getLifetime(), getEditedAgo(), debug::valueOf(isInHand), debug::valueOf(isStillMoving), - debug::valueOf(isReallyOld), debug::valueOf(shouldDie)); + bool wantDebug = false; + if (wantDebug) { + printf("Particle::update()... timeElapsed: %f lifeTime:%f editedAgo:%f " + "isInHand:%s isStillMoveing:%s isReallyOld:%s shouldDie:%s\n", + timeElapsed, getLifetime(), getEditedAgo(), debug::valueOf(isInHand), debug::valueOf(isStillMoving), + debug::valueOf(isReallyOld), debug::valueOf(shouldDie)); + } + runScript(); // allow the javascript to alter our state // If the ball is in hand, it doesn't move or have gravity effect it diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 3d79e7fcc2..4d178a6ee9 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -31,10 +31,14 @@ uint64_t usecTimestamp(const timeval *time) { } int usecTimestampNowAdjust = 0; +void usecTimestampNowForceClockSkew(int clockSkew) { + ::usecTimestampNowAdjust = clockSkew; +} + uint64_t usecTimestampNow() { timeval now; gettimeofday(&now, NULL); - return (now.tv_sec * 1000000 + now.tv_usec) + usecTimestampNowAdjust; + return (now.tv_sec * 1000000 + now.tv_usec) + ::usecTimestampNowAdjust; } float randFloat () { diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 7752e2e72c..893922ec28 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -56,7 +56,7 @@ static const uint64_t USECS_PER_SECOND = 1000 * 1000; uint64_t usecTimestamp(const timeval *time); uint64_t usecTimestampNow(); -extern int usecTimestampNowAdjust; +void usecTimestampNowForceClockSkew(int clockSkew); float randFloat(); int randIntInRange (int min, int max); From 95df772707b77b371f66f81a9b4592ff90ca0944 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 19:36:34 -0800 Subject: [PATCH 09/16] make really old 30 seconds not 300 --- libraries/particles/src/Particle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index c2f86c7b75..9248bf540f 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -404,7 +404,7 @@ void Particle::update() { float velocityScalar = glm::length(getVelocity()); const float STILL_MOVING = 0.05 / TREE_SCALE; bool isStillMoving = (velocityScalar > STILL_MOVING); - const float REALLY_OLD = 300.0f; // 300 seconds + const float REALLY_OLD = 30.0f; // 30 seconds bool isReallyOld = (getLifetime() > REALLY_OLD); bool isInHand = getInHand(); bool shouldDie = !isInHand && !isStillMoving && isReallyOld; From d430558ea9ea437bd46997b6d2397847195e42bf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 18 Dec 2013 21:08:34 -0800 Subject: [PATCH 10/16] fix expectedBytes() mismatch between edit packets and normal packets --- libraries/particles/src/Particle.cpp | 15 ++++++++++++++- libraries/particles/src/Particle.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 9248bf540f..ec0783d0d9 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -115,6 +115,19 @@ int Particle::expectedBytes() { return expectedBytes; } +int Particle::expectedEditMessageBytes() { + int expectedBytes = sizeof(uint32_t) // id + + sizeof(float) // radius + + sizeof(glm::vec3) // position + + sizeof(rgbColor) // color + + sizeof(glm::vec3) // velocity + + sizeof(glm::vec3) // gravity + + sizeof(float) // damping + + sizeof(bool); // inhand + // potentially more... + return expectedBytes; +} + int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { int bytesRead = 0; if (bytesLeftToRead >= expectedBytes()) { @@ -308,7 +321,7 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, int octets = numberOfThreeBitSectionsInCode(octcode); int lengthOfOctcode = bytesRequiredForCodeLength(octets); - int lenfthOfEditData = lengthOfOctcode + expectedBytes(); + int lenfthOfEditData = lengthOfOctcode + expectedEditMessageBytes(); // make sure we have room to copy this particle if (sizeOut + lenfthOfEditData > sizeIn) { diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 995a8675ce..5090828724 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -96,6 +96,7 @@ public: bool appendParticleData(OctreePacketData* packetData) const; int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); static int expectedBytes(); + static int expectedEditMessageBytes(); static bool encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details, unsigned char* bufferOut, int sizeIn, int& sizeOut); From c3b222cfc218ff09784869eabf211a52c197b910 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 19 Dec 2013 11:23:55 -0600 Subject: [PATCH 11/16] Print assignment request details to log --- domain-server/src/DomainServer.cpp | 6 ++++-- interface/src/avatar/Avatar.cpp | 4 ---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ec955f5fb4..47b0295941 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -220,12 +220,12 @@ void DomainServer::readAvailableDatagrams() { } } else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { - qDebug("Received a request for assignment.\n"); - if (_assignmentQueue.size() > 0) { // construct the requested assignment from the packet data Assignment requestAssignment(packetData, receivedBytes); + qDebug("Received a request for assignment type %i from %s.\n", requestAssignment.getType() ,qPrintable(senderSockAddr.getAddress().toString())); + Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); if (assignmentToDeploy) { @@ -243,6 +243,8 @@ void DomainServer::readAvailableDatagrams() { } } + } else { + qDebug("Received an invalid assignment request from %s.\n", qPrintable(senderSockAddr.getAddress().toString())); } } } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f4a09ad069..7762f5afbc 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -338,8 +338,6 @@ void Avatar::render(bool forceRenderHead) { } } - - // returns true if the Leap controls any of the avatar's hands. bool Avatar::updateLeapHandPositions() { bool returnValue = false; @@ -443,8 +441,6 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } - - void Avatar::renderBody(bool forceRenderHead) { if (_head.getVideoFace().isFullFrame()) { From 57bf31e1a6c22b7bc3049d48660efd644c01de7e Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 19 Dec 2013 11:25:51 -0600 Subject: [PATCH 12/16] Wrong spacing --- domain-server/src/DomainServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 47b0295941..ee6caaaf9b 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -224,7 +224,7 @@ void DomainServer::readAvailableDatagrams() { // construct the requested assignment from the packet data Assignment requestAssignment(packetData, receivedBytes); - qDebug("Received a request for assignment type %i from %s.\n", requestAssignment.getType() ,qPrintable(senderSockAddr.getAddress().toString())); + qDebug("Received a request for assignment type %i from %s.\n", requestAssignment.getType(), qPrintable(senderSockAddr.getAddress().toString())); Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); From e2b7e083981f27f3fb3b9593219d9262136697dd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 19 Dec 2013 09:50:53 -0800 Subject: [PATCH 13/16] revert back to timestamps, fix a couple other bugs --- interface/src/avatar/Hand.cpp | 103 +++++++++--------- interface/src/avatar/Hand.h | 2 +- libraries/octree/src/Octree.cpp | 11 +- libraries/octree/src/Octree.h | 2 +- libraries/octree/src/OctreeElement.cpp | 3 +- libraries/octree/src/OctreeElement.h | 3 +- libraries/particles/src/Particle.cpp | 52 +++++---- libraries/particles/src/Particle.h | 19 ++-- .../particles/src/ParticleCollisionSystem.cpp | 32 +++++- .../particles/src/ParticleEditHandle.cpp | 6 +- .../src/ParticleScriptingInterface.cpp | 3 +- libraries/particles/src/ParticleTree.cpp | 44 ++++++++ libraries/particles/src/ParticleTree.h | 2 + .../particles/src/ParticleTreeElement.cpp | 48 ++++++-- libraries/particles/src/ParticleTreeElement.h | 5 +- libraries/shared/src/PacketHeaders.cpp | 2 +- 16 files changed, 227 insertions(+), 110 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 2fa59ee43f..a25fa086de 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -77,6 +77,8 @@ void Hand::reset() { } void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) { + Application* app = Application::getInstance(); + ParticleTree* particles = app->getParticles()->getTree(); bool ballFromHand = Menu::getInstance()->isOptionChecked(MenuOption::BallFromHand); int handID = palm.getSixenseID(); @@ -85,14 +87,14 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f glm::vec3 targetPosition = (ballFromHand ? palm.getPosition() : fingerTipPosition) / (float)TREE_SCALE; float targetRadius = CATCH_RADIUS / (float)TREE_SCALE; - const Particle* closestParticle = Application::getInstance()->getParticles() - ->getTree()->findClosestParticle(targetPosition, targetRadius); + // If I don't currently have a ball in my hand, then I can catch this closest particle + if (!ballAlreadyInHand && grabButtonPressed) { - if (closestParticle) { - // If I don't currently have a ball in my hand, then I can catch this closest particle - if (!ballAlreadyInHand && grabButtonPressed) { - ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID()); + const Particle* closestParticle = particles->findClosestParticle(targetPosition, targetRadius); + + if (closestParticle) { + ParticleEditHandle* caughtParticle = app->newParticleEditHandle(closestParticle->getID()); glm::vec3 newPosition = targetPosition; glm::vec3 newVelocity = NO_VELOCITY; @@ -117,10 +119,7 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f _ballParticleEditHandles[handID] = caughtParticle; caughtParticle = NULL; // Play a catch sound! - Application::getInstance()->getAudio()->startDrumSound(1.0, - 300, - 0.5, - 0.05); + app->getAudio()->startDrumSound(1.0, 300, 0.5, 0.05); } } @@ -155,20 +154,17 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f qDebug("Created New Ball\n"); #endif glm::vec3 ballPosition = ballFromHand ? palm.getPosition() : fingerTipPosition; - _ballParticleEditHandles[handID] = Application::getInstance()->makeParticle( - ballPosition / (float)TREE_SCALE, - TOY_BALL_RADIUS / (float) TREE_SCALE, - TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]], - NO_VELOCITY / (float)TREE_SCALE, - TOY_BALL_GRAVITY / (float) TREE_SCALE, - TOY_BALL_DAMPING, - IN_HAND, - TOY_BALL_UPDATE_SCRIPT); + _ballParticleEditHandles[handID] = app->makeParticle( + ballPosition / (float)TREE_SCALE, + TOY_BALL_RADIUS / (float) TREE_SCALE, + TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]], + NO_VELOCITY / (float)TREE_SCALE, + TOY_BALL_GRAVITY / (float) TREE_SCALE, + TOY_BALL_DAMPING, + IN_HAND, + TOY_BALL_UPDATE_SCRIPT); // Play a new ball sound - Application::getInstance()->getAudio()->startDrumSound(1.0, - 2000, - 0.5, - 0.02); + app->getAudio()->startDrumSound(1.0, 2000, 0.5, 0.02); } } else { @@ -176,10 +172,16 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f #ifdef DEBUG_HAND //qDebug("Ball in hand\n"); #endif + + uint32_t particleInHandID = _ballParticleEditHandles[handID]->getID(); + const Particle* particleInHand = particles->findParticleByID(particleInHandID); + xColor colorForParticleInHand = particleInHand ? particleInHand->getXColor() + : TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]]; + glm::vec3 ballPosition = ballFromHand ? palm.getPosition() : fingerTipPosition; _ballParticleEditHandles[handID]->updateParticle(ballPosition / (float)TREE_SCALE, TOY_BALL_RADIUS / (float) TREE_SCALE, - TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]], + colorForParticleInHand, NO_VELOCITY / (float)TREE_SCALE, TOY_BALL_GRAVITY / (float) TREE_SCALE, TOY_BALL_DAMPING, @@ -201,9 +203,14 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f #ifdef DEBUG_HAND qDebug("Threw ball, v = %.3f\n", glm::length(ballVelocity)); #endif + uint32_t particleInHandID = _ballParticleEditHandles[handID]->getID(); + const Particle* particleInHand = particles->findParticleByID(particleInHandID); + xColor colorForParticleInHand = particleInHand ? particleInHand->getXColor() + : TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]]; + _ballParticleEditHandles[handID]->updateParticle(ballPosition / (float)TREE_SCALE, TOY_BALL_RADIUS / (float) TREE_SCALE, - TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]], + colorForParticleInHand, ballVelocity / (float)TREE_SCALE, TOY_BALL_GRAVITY / (float) TREE_SCALE, TOY_BALL_DAMPING, @@ -216,12 +223,7 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f _ballParticleEditHandles[handID] = NULL; // Play a throw sound - Application::getInstance()->getAudio()->startDrumSound(1.0, - 3000, - 0.5, - 0.02); - - + app->getAudio()->startDrumSound(1.0, 3000, 0.5, 0.02); } } @@ -474,30 +476,27 @@ void Hand::calculateGeometry() { } } -void Hand::render( bool isMine) { +void Hand::render(bool isMine) { _renderAlpha = 1.0; - - - - if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { - for (int i = 0; i < getNumPalms(); i++) { - PalmData& palm = getPalms()[i]; - if (!palm.isActive()) { - continue; - } - glm::vec3 position = palm.getPosition(); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glColor3f(0.0f, 1.0f, 0.0f); - glutSolidSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10); - glPopMatrix(); + if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) { + for (int i = 0; i < getNumPalms(); i++) { + PalmData& palm = getPalms()[i]; + if (!palm.isActive()) { + continue; } + glm::vec3 position = palm.getPosition(); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glColor3f(0.0f, 1.0f, 0.0f); + glutSolidSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10); + glPopMatrix(); } + } if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayLeapHands)) { - renderLeapHands(); + renderLeapHands(isMine); } if (isMine) { @@ -520,7 +519,7 @@ void Hand::render( bool isMine) { } -void Hand::renderLeapHands() { +void Hand::renderLeapHands(bool isMine) { const float alpha = 1.0f; const float TARGET_ALPHA = 0.5f; @@ -532,7 +531,7 @@ void Hand::renderLeapHands() { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); - if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayHandTargets)) { + if (isMine && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHandTargets)) { for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& palm = getPalms()[i]; if (!palm.isActive()) { @@ -541,8 +540,8 @@ void Hand::renderLeapHands() { glm::vec3 targetPosition = ballFromHand ? palm.getPosition() : palm.getTipPosition(); glPushMatrix(); - const Particle* closestParticle = Application::getInstance()->getParticles() - ->getTree()->findClosestParticle(targetPosition / (float)TREE_SCALE, + ParticleTree* particles = Application::getInstance()->getParticles()->getTree(); + const Particle* closestParticle = particles->findClosestParticle(targetPosition / (float)TREE_SCALE, CATCH_RADIUS / (float)TREE_SCALE); // If we are hitting a particle then draw the target green, otherwise yellow diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 6afad1bbed..d7acba6a3e 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -89,7 +89,7 @@ private: void setLeapHands(const std::vector& handPositions, const std::vector& handNormals); - void renderLeapHands(); + void renderLeapHands(bool isMine); void renderLeapFingerTrails(); void updateCollisions(); diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 5bd99ee308..dfc0eac1c8 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -583,7 +583,7 @@ public: float radius; glm::vec3& penetration; bool found; - OctreeElement* penetratedElement; + void* penetratedObject; /// the type is defined by the type of Octree, the caller is assumed to know the type }; bool findSpherePenetrationOp(OctreeElement* element, void* extraData) { @@ -599,23 +599,22 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) { } if (element->hasContent()) { glm::vec3 elementPenetration; - if (element->findSpherePenetration(args->center, args->radius, elementPenetration)) { + if (element->findSpherePenetration(args->center, args->radius, elementPenetration, &args->penetratedObject)) { args->penetration = addPenetrations(args->penetration, elementPenetration * (float)TREE_SCALE); args->found = true; - args->penetratedElement = element; } } return false; } bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, - OctreeElement** penetratedElement) { + void** penetratedObject) { SphereArgs args = { center / (float)TREE_SCALE, radius / TREE_SCALE, penetration, false, NULL }; penetration = glm::vec3(0.0f, 0.0f, 0.0f); recurseTreeWithOperation(findSpherePenetrationOp, &args); - if (penetratedElement) { - *penetratedElement = args.penetratedElement; + if (penetratedObject) { + *penetratedObject = args.penetratedObject; } return args.found; } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index de74476a30..43ba3062b3 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -221,7 +221,7 @@ public: OctreeElement*& node, float& distance, BoxFace& face); bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, - OctreeElement** penetratedElement = NULL); + void** penetratedObject = NULL); bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 62561772bb..f59121877a 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1285,7 +1285,8 @@ void OctreeElement::notifyUpdateHooks() { } } -bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const { +bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, + glm::vec3& penetration, void** penetratedObject) const { return _box.findSpherePenetration(center, radius, penetration); } diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 1b5b92cf2b..969b49f303 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -93,7 +93,8 @@ public: virtual bool deleteApproved() const { return true; } - virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const; + virtual bool findSpherePenetration(const glm::vec3& center, float radius, + glm::vec3& penetration, void** penetratedObject) const; // Base class methods you don't need to implement const unsigned char* getOctalCode() const { return (_octcodePointer) ? _octalCode.pointer : &_octalCode.buffer[0]; } diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index ec0783d0d9..ebad0480a1 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -42,8 +42,8 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 _id = id; } uint64_t now = usecTimestampNow(); - _edited = now; - _lastSimulated = now; + _lastEdited = now; + _lastUpdated = now; _created = now; // will get updated as appropriate in setLifetime() _position = position; @@ -67,7 +67,10 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { success = packetData->appendValue(getLifetime()); } if (success) { - success = packetData->appendValue(getEditedAgo()); + success = packetData->appendValue(getLastUpdated()); + } + if (success) { + success = packetData->appendValue(getLastEdited()); } if (success) { success = packetData->appendValue(getRadius()); @@ -103,7 +106,8 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { int Particle::expectedBytes() { int expectedBytes = sizeof(uint32_t) // id + sizeof(float) // lifetime - + sizeof(float) // edited ago + + sizeof(uint64_t) // last updated + + sizeof(uint64_t) // lasted edited + sizeof(float) // radius + sizeof(glm::vec3) // position + sizeof(rgbColor) // color @@ -117,6 +121,7 @@ int Particle::expectedBytes() { int Particle::expectedEditMessageBytes() { int expectedBytes = sizeof(uint32_t) // id + + sizeof(uint64_t) // lasted edited + sizeof(float) // radius + sizeof(glm::vec3) // position + sizeof(rgbColor) // color @@ -145,12 +150,15 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef bytesRead += sizeof(lifetime); setLifetime(lifetime); - // edited ago - float editedAgo; - memcpy(&editedAgo, dataAt, sizeof(editedAgo)); - dataAt += sizeof(editedAgo); - bytesRead += sizeof(editedAgo); - setEditedAgo(editedAgo); + // _lastUpdated + memcpy(&_lastUpdated, dataAt, sizeof(_lastUpdated)); + dataAt += sizeof(_lastUpdated); + bytesRead += sizeof(_lastUpdated); + + // _lastEdited + memcpy(&_lastEdited, dataAt, sizeof(_lastEdited)); + dataAt += sizeof(_lastEdited); + bytesRead += sizeof(_lastEdited); // radius memcpy(&_radius, dataAt, sizeof(_radius)); @@ -204,7 +212,7 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef Particle Particle::fromEditPacket(unsigned char* data, int length, int& processedBytes) { - Particle newParticle; // id and _lastSimulated will get set here... + Particle newParticle; // id and _lastUpdated will get set here... unsigned char* dataAt = data; processedBytes = 0; @@ -240,8 +248,10 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe newParticle._newlyCreated = false; } - // clearly we just edited it - newParticle.setEditedAgo(0); + // lastEdited + memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited)); + dataAt += sizeof(newParticle._lastEdited); + processedBytes += sizeof(newParticle._lastEdited); // radius memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius)); @@ -347,6 +357,11 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, sizeOut += sizeof(details[i].creatorTokenID); } + // radius + memcpy(copyAt, &details[i].lastEdited, sizeof(details[i].lastEdited)); + copyAt += sizeof(details[i].lastEdited); + sizeOut += sizeof(details[i].lastEdited); + // radius memcpy(copyAt, &details[i].radius, sizeof(details[i].radius)); copyAt += sizeof(details[i].radius); @@ -409,7 +424,7 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, void Particle::update() { uint64_t now = usecTimestampNow(); - uint64_t elapsed = now - _lastSimulated; + uint64_t elapsed = now - _lastUpdated; float timeElapsed = (float)((float)elapsed/(float)USECS_PER_SECOND); @@ -423,7 +438,7 @@ void Particle::update() { bool shouldDie = !isInHand && !isStillMoving && isReallyOld; setShouldDie(shouldDie); - bool wantDebug = false; + bool wantDebug = true; if (wantDebug) { printf("Particle::update()... timeElapsed: %f lifeTime:%f editedAgo:%f " "isInHand:%s isStillMoveing:%s isReallyOld:%s shouldDie:%s\n", @@ -452,7 +467,7 @@ void Particle::update() { //printf("applying damping to Particle timeElapsed=%f\n",timeElapsed); } - _lastSimulated = now; + _lastUpdated = now; } void Particle::runScript() { @@ -488,11 +503,6 @@ void Particle::setLifetime(float lifetime) { _created = usecTimestampNow() - lifetimeInUsecs; } -void Particle::setEditedAgo(float editedAgo) { - uint64_t editedAgoInUsecs = editedAgo * USECS_PER_SECOND; - _edited = usecTimestampNow() - editedAgoInUsecs; -} - void Particle::copyChangedProperties(const Particle& other) { float lifetime = getLifetime(); *this = other; diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 5090828724..cbf4c94bd3 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -25,6 +25,7 @@ const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF; class ParticleDetail { public: uint32_t id; + uint64_t lastEdited; glm::vec3 position; float radius; rgbColor color; @@ -66,11 +67,16 @@ public: const glm::vec3& getGravity() const { return _gravity; } bool getInHand() const { return _inHand; } float getDamping() const { return _damping; } + + /// The last updated/simulated time of this particle from the time perspective of the authoritative server/source + uint64_t getLastUpdated() const { return _lastUpdated; } + + /// The last edited time of this particle from the time perspective of the authoritative server/source + uint64_t getLastEdited() const { return _lastEdited; } /// lifetime of the particle in seconds float getLifetime() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } - /// seconds since last edited - float getEditedAgo() const { return (float)(usecTimestampNow() - _edited) / (float)USECS_PER_SECOND; } + float getEditedAgo() const { return (float)(usecTimestampNow() - _lastEdited) / (float)USECS_PER_SECOND; } uint32_t getID() const { return _id; } bool getShouldDie() const { return _shouldDie; } QString getUpdateScript() const { return _updateScript; } @@ -116,7 +122,6 @@ protected: static void xColorFromScriptValue(const QScriptValue &object, xColor& color); void setLifetime(float lifetime); - void setEditedAgo(float editedAgo); glm::vec3 _position; rgbColor _color; @@ -133,11 +138,11 @@ protected: uint32_t _creatorTokenID; bool _newlyCreated; - // these are never included in wire time - uint64_t _lastSimulated; + uint64_t _lastUpdated; + uint64_t _lastEdited; + + // this doesn't go on the wire, we send it as lifetime uint64_t _created; - uint64_t _edited; - }; class ParticleScriptObject : public QObject { diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 8281deb12d..7b773540b0 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -73,8 +73,7 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) { const float VOXEL_DAMPING = 0.0; const float VOXEL_COLLISION_FREQUENCY = 0.5f; glm::vec3 penetration; - OctreeElement* penetratedVoxel; - if (_voxels->findSpherePenetration(center, radius, penetration, &penetratedVoxel)) { + if (_voxels->findSpherePenetration(center, radius, penetration)) { penetration /= (float)TREE_SCALE; updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); @@ -88,11 +87,29 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { const float VOXEL_DAMPING = 0.0; const float VOXEL_COLLISION_FREQUENCY = 0.5f; glm::vec3 penetration; - OctreeElement* penetratedElement; - if (_particles->findSpherePenetration(center, radius, penetration, &penetratedElement)) { + Particle* penetratedParticle; + if (_particles->findSpherePenetration(center, radius, penetration, (void**)&penetratedParticle)) { penetration /= (float)TREE_SCALE; updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); - applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); + + // apply a hard collision to both particles of half the penetration each + + float particleShare, penetratedParticleShare; + if (particle->getInHand() && penetratedParticle->getInHand()) { + particleShare = 0.5f; + penetratedParticleShare = -0.5f; + } else if (particle->getInHand()) { + particleShare = 0.f; + penetratedParticleShare = -1.f; + } else if (penetratedParticle->getInHand()) { + particleShare = -1.f; + penetratedParticleShare = 0.f; + } else { + particleShare = 0.5f; + penetratedParticleShare = -0.5f; + } + applyHardCollision(particle, penetration * particleShare, VOXEL_ELASTICITY, VOXEL_DAMPING); + applyHardCollision(penetratedParticle, penetration * penetratedParticleShare, VOXEL_ELASTICITY, VOXEL_DAMPING); } } @@ -172,7 +189,7 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::vec3& penetration, float elasticity, float damping, const glm::vec3& addedVelocity) { // - // Update the avatar in response to a hard collision. Position will be reset exactly + // 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 = 1.0, collision is inelastic. @@ -197,6 +214,9 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm:: velocity *= 0.f; } } +printf("ParticleCollisionSystem::applyHardCollision() particle id:%d new velocity:%f,%f,%f inHand:%s\n", + particle->getID(), velocity.x, velocity.y, velocity.z, debug::valueOf(particle->getInHand())); + ParticleEditHandle particleEditHandle(_packetSender, _particles, particle->getID()); particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity, particle->getGravity(), particle->getDamping(), particle->getInHand(), particle->getUpdateScript()); diff --git a/libraries/particles/src/ParticleEditHandle.cpp b/libraries/particles/src/ParticleEditHandle.cpp index d8466816c4..88d3143a0f 100644 --- a/libraries/particles/src/ParticleEditHandle.cpp +++ b/libraries/particles/src/ParticleEditHandle.cpp @@ -44,7 +44,8 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor glm::vec3 gravity, float damping, bool inHand, QString updateScript) { // setup a ParticleDetail struct with the data - ParticleDetail addParticleDetail = { NEW_PARTICLE, + uint64_t now = usecTimestampNow(); + ParticleDetail addParticleDetail = { NEW_PARTICLE, now, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, _creatorTokenID }; @@ -69,7 +70,8 @@ bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor } // setup a ParticleDetail struct with the data - ParticleDetail newParticleDetail = { _id, + uint64_t now = usecTimestampNow(); + ParticleDetail newParticleDetail = { _id, now, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, _creatorTokenID }; diff --git a/libraries/particles/src/ParticleScriptingInterface.cpp b/libraries/particles/src/ParticleScriptingInterface.cpp index 758b50035d..8edfae3b88 100644 --- a/libraries/particles/src/ParticleScriptingInterface.cpp +++ b/libraries/particles/src/ParticleScriptingInterface.cpp @@ -22,7 +22,8 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl _nextCreatorTokenID++; // setup a ParticleDetail struct with the data - ParticleDetail addParticleDetail = { NEW_PARTICLE, + uint64_t now = usecTimestampNow(); + ParticleDetail addParticleDetail = { NEW_PARTICLE, now, position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, inHand, updateScript, creatorTokenID }; diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index e0fc3e972e..576f0f1c19 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -119,6 +119,50 @@ const Particle* ParticleTree::findClosestParticle(glm::vec3 position, float targ return args.closestParticle; } +class FindByIDArgs { +public: + uint32_t id; + bool found; + const Particle* foundParticle; +}; + + +bool ParticleTree::findByIDOperation(OctreeElement* element, void* extraData) { + FindByIDArgs* args = static_cast(extraData); + ParticleTreeElement* particleTreeElement = static_cast(element); + + // if already found, stop looking + if (args->found) { + printf("ParticleTree::findByIDOperation(id[%d]) already found, ending search...\n",args->id); + 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; + printf("ParticleTree::findByIDOperation(id[%d]) FOUND IT particle=%p...\n",args->id, foundParticle); + return false; + } + + // keep looking + printf("ParticleTree::findByIDOperation(id[%d]) keep looking\n",args->id); + return true; +} + + +const Particle* ParticleTree::findParticleByID(uint32_t id) { + +printf("ParticleTree::findParticleByID(id[%d])\n",id); + // First, look for the existing particle in the tree.. + FindByIDArgs args = { id, false, NULL }; + lockForRead(); + recurseTreeWithOperation(findByIDOperation, &args); + unlock(); + return args.foundParticle; +} + int ParticleTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, unsigned char* editData, int maxLength, Node* senderNode) { diff --git a/libraries/particles/src/ParticleTree.h b/libraries/particles/src/ParticleTree.h index 0594b2f4b2..64d6982322 100644 --- a/libraries/particles/src/ParticleTree.h +++ b/libraries/particles/src/ParticleTree.h @@ -46,6 +46,7 @@ public: void storeParticle(const Particle& particle); const Particle* findClosestParticle(glm::vec3 position, float targetRadius); + const Particle* findParticleByID(uint32_t id); void addNewlyCreatedHook(NewlyCreatedParticleHook* hook); void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook); @@ -56,6 +57,7 @@ private: static bool findAndUpdateOperation(OctreeElement* element, void* extraData); static bool findNearPointOperation(OctreeElement* element, void* extraData); static bool pruneOperation(OctreeElement* element, void* extraData); + static bool findByIDOperation(OctreeElement* element, void* extraData); void notifyNewlyCreatedParticle(const Particle& newParticle, Node* senderNode); diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index b142c1f568..b9c5fa4643 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -86,7 +86,9 @@ void ParticleTreeElement::update(ParticleTreeUpdateArgs& args) { } } -bool ParticleTreeElement::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const { +bool ParticleTreeElement::findSpherePenetration(const glm::vec3& center, float radius, + glm::vec3& penetration, void** penetratedObject) const { + uint16_t numberOfParticles = _particles.size(); for (uint16_t i = 0; i < numberOfParticles; i++) { glm::vec3 particleCenter = _particles[i].getPosition(); @@ -96,8 +98,19 @@ bool ParticleTreeElement::findSpherePenetration(const glm::vec3& center, float r 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 (_particles[i].getInHand()) { + return false; + } + } if (findSphereSpherePenetration(center, radius, particleCenter, particleRadius, penetration)) { + *penetratedObject = (void*)&_particles[i]; return true; } } @@ -119,19 +132,24 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { uint16_t numberOfParticles = _particles.size(); for (uint16_t i = 0; i < numberOfParticles; i++) { if (_particles[i].getID() == particle.getID()) { - bool changedOnServer = _particles[i].getEditedAgo() > particle.getEditedAgo(); - if (changedOnServer) { + int difference = _particles[i].getLastUpdated() - particle.getLastUpdated(); + bool changedOnServer = _particles[i].getLastEdited() < particle.getLastEdited(); + bool localOlder = _particles[i].getLastUpdated() < particle.getLastUpdated(); + if (changedOnServer || localOlder) { if (wantDebug) { - printf("local particle [id:%d] %s, particle.isNewlyCreated()=%s\n", - particle.getID(), (changedOnServer ? "CHANGED" : "same"), - debug::valueOf(particle.isNewlyCreated()) ); + printf("local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s\n", + particle.getID(), (changedOnServer ? "CHANGED" : "same"), + (localOlder ? "OLDER" : "NEWER"), + difference, debug::valueOf(particle.isNewlyCreated()) ); } _particles[i].copyChangedProperties(particle); } else { if (wantDebug) { - printf(">>> NO CHANGE <<< -- local particle [id:%d] %s particle.isNewlyCreated()=%s\n", - particle.getID(), (changedOnServer ? "CHANGED" : "same"), - debug::valueOf(particle.isNewlyCreated()) ); + printf(">>> NO CHANGE <<< -- local particle [id:%d] %s and %s than server particle by %d, " + "particle.isNewlyCreated()=%s\n", + particle.getID(), (changedOnServer ? "CHANGED" : "same"), + (localOlder ? "OLDER" : "NEWER"), + difference, debug::valueOf(particle.isNewlyCreated()) ); } } return true; @@ -153,6 +171,18 @@ const Particle* ParticleTreeElement::getClosestParticle(glm::vec3 position) cons return closestParticle; } +const Particle* ParticleTreeElement::getParticleWithID(uint32_t id) const { + 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; +} + int ParticleTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { diff --git a/libraries/particles/src/ParticleTreeElement.h b/libraries/particles/src/ParticleTreeElement.h index cc58122515..0f9b3682c1 100644 --- a/libraries/particles/src/ParticleTreeElement.h +++ b/libraries/particles/src/ParticleTreeElement.h @@ -72,7 +72,8 @@ public: virtual bool isRendered() const { return getShouldRender(); } virtual bool deleteApproved() const { return !hasParticles(); } - virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const; + virtual bool findSpherePenetration(const glm::vec3& center, float radius, + glm::vec3& penetration, void** penetratedObject) const; const std::vector& getParticles() const { return _particles; } std::vector& getParticles() { return _particles; } @@ -84,6 +85,8 @@ public: bool containsParticle(const Particle& particle) const; bool updateParticle(const Particle& particle); const Particle* getClosestParticle(glm::vec3 position) const; + const Particle* getParticleWithID(uint32_t id) const; + protected: void storeParticle(const Particle& particle); diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 24865fff5c..05e4b4e21d 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -54,7 +54,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 2; case PACKET_TYPE_PARTICLE_DATA: - return 4; + return 5; default: return 0; From b48161ae2693e82650546c8382a5cae6213ddb3f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 19 Dec 2013 09:59:36 -0800 Subject: [PATCH 14/16] cleanup debug --- libraries/particles/src/Particle.cpp | 2 +- libraries/particles/src/ParticleCollisionSystem.cpp | 7 +++++-- libraries/particles/src/ParticleTree.cpp | 7 ------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index ebad0480a1..e4afcd90e7 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -438,7 +438,7 @@ void Particle::update() { bool shouldDie = !isInHand && !isStillMoving && isReallyOld; setShouldDie(shouldDie); - bool wantDebug = true; + bool wantDebug = false; if (wantDebug) { printf("Particle::update()... timeElapsed: %f lifeTime:%f editedAgo:%f " "isInHand:%s isStillMoveing:%s isReallyOld:%s shouldDie:%s\n", diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 7b773540b0..e1286f91e2 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -214,8 +214,11 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm:: velocity *= 0.f; } } -printf("ParticleCollisionSystem::applyHardCollision() particle id:%d new velocity:%f,%f,%f inHand:%s\n", - particle->getID(), velocity.x, velocity.y, velocity.z, debug::valueOf(particle->getInHand())); + const bool wantDebug = false; + if (wantDebug) { + printf("ParticleCollisionSystem::applyHardCollision() particle id:%d new velocity:%f,%f,%f inHand:%s\n", + particle->getID(), velocity.x, velocity.y, velocity.z, debug::valueOf(particle->getInHand())); + } ParticleEditHandle particleEditHandle(_packetSender, _particles, particle->getID()); particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity, diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index 576f0f1c19..e770347fd8 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -111,7 +111,6 @@ bool ParticleTree::findNearPointOperation(OctreeElement* element, void* extraDat } const Particle* ParticleTree::findClosestParticle(glm::vec3 position, float targetRadius) { - // First, look for the existing particle in the tree.. FindNearPointArgs args = { position, targetRadius, false, NULL, FLT_MAX }; lockForRead(); recurseTreeWithOperation(findNearPointOperation, &args); @@ -133,7 +132,6 @@ bool ParticleTree::findByIDOperation(OctreeElement* element, void* extraData) { // if already found, stop looking if (args->found) { - printf("ParticleTree::findByIDOperation(id[%d]) already found, ending search...\n",args->id); return false; } @@ -142,20 +140,15 @@ bool ParticleTree::findByIDOperation(OctreeElement* element, void* extraData) { if (foundParticle) { args->foundParticle = foundParticle; args->found = true; - printf("ParticleTree::findByIDOperation(id[%d]) FOUND IT particle=%p...\n",args->id, foundParticle); return false; } // keep looking - printf("ParticleTree::findByIDOperation(id[%d]) keep looking\n",args->id); return true; } const Particle* ParticleTree::findParticleByID(uint32_t id) { - -printf("ParticleTree::findParticleByID(id[%d])\n",id); - // First, look for the existing particle in the tree.. FindByIDArgs args = { id, false, NULL }; lockForRead(); recurseTreeWithOperation(findByIDOperation, &args); From 26366e9fe7437f1d04c4fe3af101187c9953940c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 19 Dec 2013 10:05:20 -0800 Subject: [PATCH 15/16] cleanup debug --- libraries/particles/src/ParticleTreeElement.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index b9c5fa4643..3d1a552d17 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -128,7 +128,7 @@ bool ParticleTreeElement::containsParticle(const Particle& particle) const { } bool ParticleTreeElement::updateParticle(const Particle& particle) { - bool wantDebug = false; + const bool wantDebug = false; uint16_t numberOfParticles = _particles.size(); for (uint16_t i = 0; i < numberOfParticles; i++) { if (_particles[i].getID() == particle.getID()) { @@ -145,8 +145,8 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { _particles[i].copyChangedProperties(particle); } else { if (wantDebug) { - printf(">>> NO CHANGE <<< -- local particle [id:%d] %s and %s than server particle by %d, " - "particle.isNewlyCreated()=%s\n", + printf(">>> IGNORING SERVER!!! Would've caused jutter! <<< " + "local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s\n", particle.getID(), (changedOnServer ? "CHANGED" : "same"), (localOlder ? "OLDER" : "NEWER"), difference, debug::valueOf(particle.isNewlyCreated()) ); From 864fc10d3aefca8711275e8e8b366584283f1774 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 19 Dec 2013 10:39:42 -0800 Subject: [PATCH 16/16] debug cleanup and change to Particle::update() to handle clock skew slightly better --- libraries/particles/src/Particle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index e4afcd90e7..83d313c95f 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -424,7 +424,7 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, void Particle::update() { uint64_t now = usecTimestampNow(); - uint64_t elapsed = now - _lastUpdated; + int elapsed = now - _lastUpdated; // making this signed slightly improves clock skew behavior float timeElapsed = (float)((float)elapsed/(float)USECS_PER_SECOND); @@ -438,7 +438,7 @@ void Particle::update() { bool shouldDie = !isInHand && !isStillMoving && isReallyOld; setShouldDie(shouldDie); - bool wantDebug = false; + const bool wantDebug = false; if (wantDebug) { printf("Particle::update()... timeElapsed: %f lifeTime:%f editedAgo:%f " "isInHand:%s isStillMoveing:%s isReallyOld:%s shouldDie:%s\n",