mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 12:42:58 +02:00
Merge pull request #1406 from ZappoMan/particle_blinky_bug
Fix Particle Blinkiness on Clock Skew, and remove all global time stamps from wire formats
This commit is contained in:
commit
9980065659
10 changed files with 129 additions and 110 deletions
|
@ -19,11 +19,23 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
int main(int argc, const char * argv[]) {
|
int main(int argc, const char * argv[]) {
|
||||||
timeval startup_time;
|
timeval startup_time;
|
||||||
gettimeofday(&startup_time, NULL);
|
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* 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;
|
int exitCode;
|
||||||
{
|
{
|
||||||
Application app(argc, const_cast<char**>(argv), startup_time);
|
Application app(argc, const_cast<char**>(argv), startup_time);
|
||||||
|
|
|
@ -656,6 +656,17 @@ void OctreeServer::run() {
|
||||||
_persistThread->initialize(true);
|
_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* 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
|
// Check to see if the user passed in a command line option for setting packet send rate
|
||||||
const char* PACKETS_PER_SECOND = "--packetsPerSecond";
|
const char* PACKETS_PER_SECOND = "--packetsPerSecond";
|
||||||
|
|
|
@ -36,15 +36,16 @@ Particle::~Particle() {
|
||||||
void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
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) {
|
float damping, bool inHand, QString updateScript, uint32_t id) {
|
||||||
if (id == NEW_PARTICLE) {
|
if (id == NEW_PARTICLE) {
|
||||||
_created = usecTimestampNow();
|
|
||||||
_id = _nextID;
|
_id = _nextID;
|
||||||
_nextID++;
|
_nextID++;
|
||||||
} else {
|
} else {
|
||||||
_id = id;
|
_id = id;
|
||||||
}
|
}
|
||||||
_lastUpdated = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
_lastEdited = _lastUpdated;
|
_edited = now;
|
||||||
|
_lastSimulated = now;
|
||||||
|
_created = now; // will get updated as appropriate in setLifetime()
|
||||||
|
|
||||||
_position = position;
|
_position = position;
|
||||||
_radius = radius;
|
_radius = radius;
|
||||||
memcpy(_color, color, sizeof(_color));
|
memcpy(_color, color, sizeof(_color));
|
||||||
|
@ -63,13 +64,10 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
||||||
//printf("Particle::appendParticleData()... getID()=%d\n", getID());
|
//printf("Particle::appendParticleData()... getID()=%d\n", getID());
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
success = packetData->appendValue(getCreated());
|
success = packetData->appendValue(getLifetime());
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
success = packetData->appendValue(getLastUpdated());
|
success = packetData->appendValue(getEditedAgo());
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
success = packetData->appendValue(getLastEdited());
|
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
success = packetData->appendValue(getRadius());
|
success = packetData->appendValue(getRadius());
|
||||||
|
@ -103,9 +101,17 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Particle::expectedBytes() {
|
int Particle::expectedBytes() {
|
||||||
int expectedBytes = sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(float) +
|
int expectedBytes = sizeof(uint32_t) // id
|
||||||
sizeof(glm::vec3) + sizeof(rgbColor) + sizeof(glm::vec3) +
|
+ sizeof(float) // lifetime
|
||||||
sizeof(glm::vec3) + sizeof(float) + sizeof(bool);
|
+ sizeof(float) // edited ago
|
||||||
|
+ 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;
|
return expectedBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,20 +125,19 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
dataAt += sizeof(_id);
|
dataAt += sizeof(_id);
|
||||||
bytesRead += sizeof(_id);
|
bytesRead += sizeof(_id);
|
||||||
|
|
||||||
// created
|
// lifetime
|
||||||
memcpy(&_created, dataAt, sizeof(_created));
|
float lifetime;
|
||||||
dataAt += sizeof(_created);
|
memcpy(&lifetime, dataAt, sizeof(lifetime));
|
||||||
bytesRead += sizeof(_created);
|
dataAt += sizeof(lifetime);
|
||||||
|
bytesRead += sizeof(lifetime);
|
||||||
|
setLifetime(lifetime);
|
||||||
|
|
||||||
// lastupdated
|
// edited ago
|
||||||
memcpy(&_lastUpdated, dataAt, sizeof(_lastUpdated));
|
float editedAgo;
|
||||||
dataAt += sizeof(_lastUpdated);
|
memcpy(&editedAgo, dataAt, sizeof(editedAgo));
|
||||||
bytesRead += sizeof(_lastUpdated);
|
dataAt += sizeof(editedAgo);
|
||||||
|
bytesRead += sizeof(editedAgo);
|
||||||
// _lastEdited
|
setEditedAgo(editedAgo);
|
||||||
memcpy(&_lastEdited, dataAt, sizeof(_lastEdited));
|
|
||||||
dataAt += sizeof(_lastEdited);
|
|
||||||
bytesRead += sizeof(_lastEdited);
|
|
||||||
|
|
||||||
// radius
|
// radius
|
||||||
memcpy(&_radius, dataAt, sizeof(_radius));
|
memcpy(&_radius, dataAt, sizeof(_radius));
|
||||||
|
@ -186,7 +191,7 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
|
|
||||||
|
|
||||||
Particle Particle::fromEditPacket(unsigned char* data, int length, int& processedBytes) {
|
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;
|
unsigned char* dataAt = data;
|
||||||
processedBytes = 0;
|
processedBytes = 0;
|
||||||
|
|
||||||
|
@ -214,26 +219,17 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
||||||
processedBytes += sizeof(creatorTokenID);
|
processedBytes += sizeof(creatorTokenID);
|
||||||
newParticle.setCreatorTokenID(creatorTokenID);
|
newParticle.setCreatorTokenID(creatorTokenID);
|
||||||
newParticle._newlyCreated = true;
|
newParticle._newlyCreated = true;
|
||||||
|
|
||||||
|
newParticle.setLifetime(0); // this guy is new!
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
newParticle._id = editID;
|
newParticle._id = editID;
|
||||||
newParticle._newlyCreated = false;
|
newParticle._newlyCreated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// created
|
// clearly we just edited it
|
||||||
memcpy(&newParticle._created, dataAt, sizeof(newParticle._created));
|
newParticle.setEditedAgo(0);
|
||||||
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);
|
|
||||||
processedBytes += sizeof(newParticle._lastEdited);
|
|
||||||
|
|
||||||
// radius
|
// radius
|
||||||
memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius));
|
memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius));
|
||||||
dataAt += sizeof(newParticle._radius);
|
dataAt += sizeof(newParticle._radius);
|
||||||
|
@ -291,9 +287,8 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
||||||
|
|
||||||
void Particle::debugDump() const {
|
void Particle::debugDump() const {
|
||||||
printf("Particle id :%u\n", _id);
|
printf("Particle id :%u\n", _id);
|
||||||
printf(" created:%llu\n", _created);
|
printf(" lifetime:%f\n", getLifetime());
|
||||||
printf(" last updated:%llu\n", _lastUpdated);
|
printf(" edited ago:%f\n", getEditedAgo());
|
||||||
printf(" last edited:%llu\n", _lastEdited);
|
|
||||||
printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z);
|
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(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z);
|
||||||
printf(" gravity:%f,%f,%f\n", _gravity.x, _gravity.y, _gravity.z);
|
printf(" gravity:%f,%f,%f\n", _gravity.x, _gravity.y, _gravity.z);
|
||||||
|
@ -325,7 +320,6 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
||||||
sizeOut += lengthOfOctcode;
|
sizeOut += lengthOfOctcode;
|
||||||
|
|
||||||
// Now add our edit content details...
|
// Now add our edit content details...
|
||||||
uint64_t created = usecTimestampNow();
|
|
||||||
|
|
||||||
// id
|
// id
|
||||||
memcpy(copyAt, &details[i].id, sizeof(details[i].id));
|
memcpy(copyAt, &details[i].id, sizeof(details[i].id));
|
||||||
|
@ -338,25 +332,8 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
||||||
memcpy(copyAt, &details[i].creatorTokenID, sizeof(details[i].creatorTokenID));
|
memcpy(copyAt, &details[i].creatorTokenID, sizeof(details[i].creatorTokenID));
|
||||||
copyAt += sizeof(details[i].creatorTokenID);
|
copyAt += sizeof(details[i].creatorTokenID);
|
||||||
sizeOut += sizeof(details[i].creatorTokenID);
|
sizeOut += sizeof(details[i].creatorTokenID);
|
||||||
} else {
|
|
||||||
created = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// created
|
|
||||||
memcpy(copyAt, &created, sizeof(created));
|
|
||||||
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);
|
|
||||||
sizeOut += sizeof(details[i].lastEdited);
|
|
||||||
|
|
||||||
// radius
|
// radius
|
||||||
memcpy(copyAt, &details[i].radius, sizeof(details[i].radius));
|
memcpy(copyAt, &details[i].radius, sizeof(details[i].radius));
|
||||||
copyAt += sizeof(details[i].radius);
|
copyAt += sizeof(details[i].radius);
|
||||||
|
@ -405,7 +382,6 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
||||||
if (wantDebugging) {
|
if (wantDebugging) {
|
||||||
printf("encodeParticleEditMessageDetails()....\n");
|
printf("encodeParticleEditMessageDetails()....\n");
|
||||||
printf("Particle id :%u\n", details[i].id);
|
printf("Particle id :%u\n", details[i].id);
|
||||||
printf(" last updated:%llu\n", details[i].lastUpdated);
|
|
||||||
printf(" nextID:%u\n", _nextID);
|
printf(" nextID:%u\n", _nextID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,21 +394,30 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
||||||
|
|
||||||
|
|
||||||
void Particle::update() {
|
void Particle::update() {
|
||||||
|
|
||||||
uint64_t now = usecTimestampNow();
|
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);
|
float timeElapsed = (float)((float)elapsed/(float)USECS_PER_SECOND);
|
||||||
|
|
||||||
|
|
||||||
// calculate our default shouldDie state... then allow script to change it if it wants...
|
// calculate our default shouldDie state... then allow script to change it if it wants...
|
||||||
float velocityScalar = glm::length(getVelocity());
|
float velocityScalar = glm::length(getVelocity());
|
||||||
const float STILL_MOVING = 0.05 / TREE_SCALE;
|
const float STILL_MOVING = 0.05 / TREE_SCALE;
|
||||||
bool isStillMoving = (velocityScalar > STILL_MOVING);
|
bool isStillMoving = (velocityScalar > STILL_MOVING);
|
||||||
const uint64_t REALLY_OLD = 30 * 1000 * 1000;
|
const float REALLY_OLD = 30.0f; // 30 seconds
|
||||||
bool isReallyOld = (getLifetime() > REALLY_OLD);
|
bool isReallyOld = (getLifetime() > REALLY_OLD);
|
||||||
bool isInHand = getInHand();
|
bool isInHand = getInHand();
|
||||||
bool shouldDie = !isInHand && !isStillMoving && isReallyOld;
|
bool shouldDie = !isInHand && !isStillMoving && isReallyOld;
|
||||||
setShouldDie(shouldDie);
|
setShouldDie(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
|
runScript(); // allow the javascript to alter our state
|
||||||
|
|
||||||
// If the ball is in hand, it doesn't move or have gravity effect it
|
// If the ball is in hand, it doesn't move or have gravity effect it
|
||||||
|
@ -454,7 +439,7 @@ void Particle::update() {
|
||||||
//printf("applying damping to Particle timeElapsed=%f\n",timeElapsed);
|
//printf("applying damping to Particle timeElapsed=%f\n",timeElapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastUpdated = now;
|
_lastSimulated = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Particle::runScript() {
|
void Particle::runScript() {
|
||||||
|
@ -484,3 +469,19 @@ void Particle::runScript() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -25,8 +25,6 @@ const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF;
|
||||||
class ParticleDetail {
|
class ParticleDetail {
|
||||||
public:
|
public:
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint64_t lastUpdated;
|
|
||||||
uint64_t lastEdited;
|
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
float radius;
|
float radius;
|
||||||
rgbColor color;
|
rgbColor color;
|
||||||
|
@ -68,10 +66,11 @@ public:
|
||||||
const glm::vec3& getGravity() const { return _gravity; }
|
const glm::vec3& getGravity() const { return _gravity; }
|
||||||
bool getInHand() const { return _inHand; }
|
bool getInHand() const { return _inHand; }
|
||||||
float getDamping() const { return _damping; }
|
float getDamping() const { return _damping; }
|
||||||
uint64_t getCreated() const { return _created; }
|
|
||||||
uint64_t getLifetime() const { return usecTimestampNow() - _created; }
|
/// lifetime of the particle in seconds
|
||||||
uint64_t getLastUpdated() const { return _lastUpdated; }
|
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; }
|
uint32_t getID() const { return _id; }
|
||||||
bool getShouldDie() const { return _shouldDie; }
|
bool getShouldDie() const { return _shouldDie; }
|
||||||
QString getUpdateScript() const { return _updateScript; }
|
QString getUpdateScript() const { return _updateScript; }
|
||||||
|
@ -93,7 +92,6 @@ public:
|
||||||
void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; }
|
void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; }
|
||||||
void setUpdateScript(QString updateScript) { _updateScript = updateScript; }
|
void setUpdateScript(QString updateScript) { _updateScript = updateScript; }
|
||||||
void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; }
|
void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; }
|
||||||
void setCreated(uint64_t created) { _created = created; }
|
|
||||||
|
|
||||||
bool appendParticleData(OctreePacketData* packetData) const;
|
bool appendParticleData(OctreePacketData* packetData) const;
|
||||||
int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
|
int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
|
||||||
|
@ -105,20 +103,24 @@ public:
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
void debugDump() const;
|
void debugDump() const;
|
||||||
|
|
||||||
|
// similar to assignment/copy, but it handles keeping lifetime accurate
|
||||||
|
void copyChangedProperties(const Particle& other);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void runScript();
|
void runScript();
|
||||||
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);
|
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);
|
||||||
static void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3);
|
static void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3);
|
||||||
static QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color);
|
static QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color);
|
||||||
static void xColorFromScriptValue(const QScriptValue &object, xColor& color);
|
static void xColorFromScriptValue(const QScriptValue &object, xColor& color);
|
||||||
|
|
||||||
|
void setLifetime(float lifetime);
|
||||||
|
void setEditedAgo(float editedAgo);
|
||||||
|
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
rgbColor _color;
|
rgbColor _color;
|
||||||
float _radius;
|
float _radius;
|
||||||
glm::vec3 _velocity;
|
glm::vec3 _velocity;
|
||||||
uint64_t _lastUpdated;
|
|
||||||
uint64_t _created;
|
|
||||||
uint64_t _lastEdited;
|
|
||||||
uint32_t _id;
|
uint32_t _id;
|
||||||
static uint32_t _nextID;
|
static uint32_t _nextID;
|
||||||
bool _shouldDie;
|
bool _shouldDie;
|
||||||
|
@ -129,6 +131,12 @@ protected:
|
||||||
|
|
||||||
uint32_t _creatorTokenID;
|
uint32_t _creatorTokenID;
|
||||||
bool _newlyCreated;
|
bool _newlyCreated;
|
||||||
|
|
||||||
|
// these are never included in wire time
|
||||||
|
uint64_t _lastSimulated;
|
||||||
|
uint64_t _created;
|
||||||
|
uint64_t _edited;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParticleScriptObject : public QObject {
|
class ParticleScriptObject : public QObject {
|
||||||
|
@ -144,9 +152,7 @@ public slots:
|
||||||
float getDamping() const { return _particle->getDamping(); }
|
float getDamping() const { return _particle->getDamping(); }
|
||||||
float getRadius() const { return _particle->getRadius(); }
|
float getRadius() const { return _particle->getRadius(); }
|
||||||
bool getShouldDie() { return _particle->getShouldDie(); }
|
bool getShouldDie() { return _particle->getShouldDie(); }
|
||||||
float getCreated() const { return ((float)_particle->getCreated() / (float)USECS_PER_SECOND); }
|
float getLifetime() const { return _particle->getLifetime(); }
|
||||||
float getLifetime() const { return ((float)_particle->getLifetime() / (float)USECS_PER_SECOND); }
|
|
||||||
|
|
||||||
|
|
||||||
void setPosition(glm::vec3 value) { _particle->setPosition(value); }
|
void setPosition(glm::vec3 value) { _particle->setPosition(value); }
|
||||||
void setVelocity(glm::vec3 value) { _particle->setVelocity(value); }
|
void setVelocity(glm::vec3 value) { _particle->setVelocity(value); }
|
||||||
|
|
|
@ -44,8 +44,7 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor
|
||||||
glm::vec3 gravity, float damping, bool inHand, QString updateScript) {
|
glm::vec3 gravity, float damping, bool inHand, QString updateScript) {
|
||||||
|
|
||||||
// setup a ParticleDetail struct with the data
|
// setup a ParticleDetail struct with the data
|
||||||
uint64_t now = usecTimestampNow();
|
ParticleDetail addParticleDetail = { NEW_PARTICLE,
|
||||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now, now,
|
|
||||||
position, radius, {color.red, color.green, color.blue },
|
position, radius, {color.red, color.green, color.blue },
|
||||||
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
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
|
// setup a ParticleDetail struct with the data
|
||||||
uint64_t now = usecTimestampNow();
|
ParticleDetail newParticleDetail = { _id,
|
||||||
ParticleDetail newParticleDetail = { _id, now, now,
|
|
||||||
position, radius, {color.red, color.green, color.blue },
|
position, radius, {color.red, color.green, color.blue },
|
||||||
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,7 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl
|
||||||
_nextCreatorTokenID++;
|
_nextCreatorTokenID++;
|
||||||
|
|
||||||
// setup a ParticleDetail struct with the data
|
// setup a ParticleDetail struct with the data
|
||||||
uint64_t now = usecTimestampNow();
|
ParticleDetail addParticleDetail = { NEW_PARTICLE,
|
||||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now, now,
|
|
||||||
position, radius, {color.red, color.green, color.blue }, velocity,
|
position, radius, {color.red, color.green, color.blue }, velocity,
|
||||||
gravity, damping, inHand, updateScript, creatorTokenID };
|
gravity, damping, inHand, updateScript, creatorTokenID };
|
||||||
|
|
||||||
|
|
|
@ -119,33 +119,19 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) {
|
||||||
uint16_t numberOfParticles = _particles.size();
|
uint16_t numberOfParticles = _particles.size();
|
||||||
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
||||||
if (_particles[i].getID() == particle.getID()) {
|
if (_particles[i].getID() == particle.getID()) {
|
||||||
int difference = _particles[i].getLastUpdated() - particle.getLastUpdated();
|
bool changedOnServer = _particles[i].getEditedAgo() > particle.getEditedAgo();
|
||||||
|
if (changedOnServer) {
|
||||||
bool changedOnServer = _particles[i].getLastEdited() < particle.getLastEdited();
|
|
||||||
bool localOlder = _particles[i].getLastUpdated() < particle.getLastUpdated();
|
|
||||||
|
|
||||||
if (changedOnServer || localOlder) {
|
|
||||||
|
|
||||||
if (wantDebug) {
|
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"),
|
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||||
(localOlder ? "OLDER" : "NEWER"),
|
debug::valueOf(particle.isNewlyCreated()) );
|
||||||
difference, debug::valueOf(particle.isNewlyCreated()) );
|
|
||||||
}
|
}
|
||||||
|
_particles[i].copyChangedProperties(particle);
|
||||||
uint64_t actuallyCreated = particle.getCreated();
|
|
||||||
if (!particle.isNewlyCreated()) {
|
|
||||||
actuallyCreated = _particles[i].getCreated();
|
|
||||||
}
|
|
||||||
_particles[i] = particle;
|
|
||||||
_particles[i].setCreated(actuallyCreated);
|
|
||||||
} else {
|
} else {
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
printf(">>> NO CHANGE <<< -- local particle [id:%d] %s and %s than server particle by %d, "
|
printf(">>> NO CHANGE <<< -- local particle [id:%d] %s particle.isNewlyCreated()=%s\n",
|
||||||
"particle.isNewlyCreated()=%s\n",
|
|
||||||
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||||
(localOlder ? "OLDER" : "NEWER"),
|
debug::valueOf(particle.isNewlyCreated()) );
|
||||||
difference, debug::valueOf(particle.isNewlyCreated()) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -54,7 +54,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
case PACKET_TYPE_PARTICLE_DATA:
|
case PACKET_TYPE_PARTICLE_DATA:
|
||||||
return 3;
|
return 4;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -30,10 +30,15 @@ uint64_t usecTimestamp(const timeval *time) {
|
||||||
return (time->tv_sec * 1000000 + time->tv_usec);
|
return (time->tv_sec * 1000000 + time->tv_usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int usecTimestampNowAdjust = 0;
|
||||||
|
void usecTimestampNowForceClockSkew(int clockSkew) {
|
||||||
|
::usecTimestampNowAdjust = clockSkew;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t usecTimestampNow() {
|
uint64_t usecTimestampNow() {
|
||||||
timeval now;
|
timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
return (now.tv_sec * 1000000 + now.tv_usec);
|
return (now.tv_sec * 1000000 + now.tv_usec) + ::usecTimestampNowAdjust;
|
||||||
}
|
}
|
||||||
|
|
||||||
float randFloat () {
|
float randFloat () {
|
||||||
|
|
|
@ -56,6 +56,7 @@ static const uint64_t USECS_PER_SECOND = 1000 * 1000;
|
||||||
|
|
||||||
uint64_t usecTimestamp(const timeval *time);
|
uint64_t usecTimestamp(const timeval *time);
|
||||||
uint64_t usecTimestampNow();
|
uint64_t usecTimestampNow();
|
||||||
|
void usecTimestampNowForceClockSkew(int clockSkew);
|
||||||
|
|
||||||
float randFloat();
|
float randFloat();
|
||||||
int randIntInRange (int min, int max);
|
int randIntInRange (int min, int max);
|
||||||
|
|
Loading…
Reference in a new issue