mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 03:53:52 +02:00
first cut at using partial property info in particle edits
This commit is contained in:
parent
b4b3720fcf
commit
d831f9df5e
11 changed files with 439 additions and 293 deletions
|
@ -21,14 +21,14 @@ EditPacketBuffer::EditPacketBuffer(PACKET_TYPE type, unsigned char* buffer, ssiz
|
|||
_nodeUUID = nodeUUID;
|
||||
_currentType = type;
|
||||
_currentSize = length;
|
||||
memcpy(_currentBuffer, buffer, length);
|
||||
memcpy(_currentBuffer, buffer, length);
|
||||
};
|
||||
|
||||
const int OctreeEditPacketSender::DEFAULT_MAX_PENDING_MESSAGES = PacketSender::DEFAULT_PACKETS_PER_SECOND;
|
||||
const int OctreeEditPacketSender::DEFAULT_MAX_PENDING_MESSAGES = PacketSender::DEFAULT_PACKETS_PER_SECOND;
|
||||
|
||||
|
||||
OctreeEditPacketSender::OctreeEditPacketSender(PacketSenderNotify* notify) :
|
||||
PacketSender(notify),
|
||||
OctreeEditPacketSender::OctreeEditPacketSender(PacketSenderNotify* notify) :
|
||||
PacketSender(notify),
|
||||
_shouldSend(true),
|
||||
_maxPendingMessages(DEFAULT_MAX_PENDING_MESSAGES),
|
||||
_releaseQueuedMessagesPending(false),
|
||||
|
@ -57,7 +57,7 @@ bool OctreeEditPacketSender::serversExist() const {
|
|||
bool hasServers = false;
|
||||
bool atLeastOnJurisdictionMissing = false; // assume the best
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
||||
|
||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||
// only send to the NodeTypes that are getMyNodeType()
|
||||
if (node->getType() == getMyNodeType()) {
|
||||
|
@ -78,15 +78,15 @@ bool OctreeEditPacketSender::serversExist() const {
|
|||
break; // no point in looking further...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (hasServers && !atLeastOnJurisdictionMissing);
|
||||
}
|
||||
|
||||
// This method is called when the edit packet layer has determined that it has a fully formed packet destined for
|
||||
// a known nodeID.
|
||||
// a known nodeID.
|
||||
void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) {
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
||||
|
||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||
// only send to the NodeTypes that are getMyNodeType()
|
||||
if (node->getType() == getMyNodeType() &&
|
||||
|
@ -94,7 +94,7 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c
|
|||
if (nodeList->getNodeActiveSocketOrPing(node.data())) {
|
||||
const HifiSockAddr* nodeAddress = node->getActiveSocket();
|
||||
queuePacketForSending(*nodeAddress, buffer, length);
|
||||
|
||||
|
||||
// debugging output...
|
||||
bool wantDebugging = false;
|
||||
if (wantDebugging) {
|
||||
|
@ -103,10 +103,10 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c
|
|||
uint64_t createdAt = (*((uint64_t*)(buffer + numBytesPacketHeader + sizeof(sequence))));
|
||||
uint64_t queuedAt = usecTimestampNow();
|
||||
uint64_t transitTime = queuedAt - createdAt;
|
||||
|
||||
qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] <<
|
||||
" - command to node bytes=" << length <<
|
||||
" sequence=" << sequence <<
|
||||
|
||||
qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] <<
|
||||
" - command to node bytes=" << length <<
|
||||
" sequence=" << sequence <<
|
||||
" transitTimeSoFar=" << transitTime << " usecs";
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c
|
|||
|
||||
void OctreeEditPacketSender::processPreServerExistsPackets() {
|
||||
assert(serversExist()); // we should only be here if we have jurisdictions
|
||||
|
||||
|
||||
// First send out all the single message packets...
|
||||
while (!_preServerSingleMessagePackets.empty()) {
|
||||
EditPacketBuffer* packet = _preServerSingleMessagePackets.front();
|
||||
|
@ -133,7 +133,7 @@ void OctreeEditPacketSender::processPreServerExistsPackets() {
|
|||
_preServerPackets.erase(_preServerPackets.begin());
|
||||
}
|
||||
|
||||
// if while waiting for the jurisdictions the caller called releaseQueuedMessages()
|
||||
// if while waiting for the jurisdictions the caller called releaseQueuedMessages()
|
||||
// then we want to honor that request now.
|
||||
if (_releaseQueuedMessagesPending) {
|
||||
releaseQueuedMessages();
|
||||
|
@ -160,17 +160,17 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t l
|
|||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
}
|
||||
|
||||
|
||||
assert(serversExist()); // we must have jurisdictions to be here!!
|
||||
|
||||
int headerBytes = numBytesForPacketHeader(buffer) + sizeof(short) + sizeof(uint64_t);
|
||||
unsigned char* octCode = buffer + headerBytes; // skip the packet header to get to the octcode
|
||||
|
||||
|
||||
// We want to filter out edit messages for servers based on the server's Jurisdiction
|
||||
// But we can't really do that with a packed message, since each edit message could be destined
|
||||
// But we can't really do that with a packed message, since each edit message could be destined
|
||||
// for a different server... So we need to actually manage multiple queued packets... one
|
||||
// for each server
|
||||
|
||||
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
// only send to the NodeTypes that are getMyNodeType()
|
||||
if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) {
|
||||
|
@ -181,7 +181,12 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t l
|
|||
const JurisdictionMap& map = (*_serverJurisdictions)[nodeUUID];
|
||||
isMyJurisdiction = (map.isMyJurisdiction(octCode, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN);
|
||||
if (isMyJurisdiction) {
|
||||
|
||||
qDebug() << "calling queuePacketToNode(nodeUUID, buffer, length); nodeUUID=" << nodeUUID << " length=" << length;
|
||||
|
||||
queuePacketToNode(nodeUUID, buffer, length);
|
||||
} else {
|
||||
qDebug() << "not my jurisdiction skipping queuePacketToNode(nodeUUID, buffer, length); nodeUUID=" << nodeUUID << " length=" << length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,10 +195,14 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t l
|
|||
|
||||
// NOTE: codeColorBuffer - is JUST the octcode/color and does not contain the packet header!
|
||||
void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned char* codeColorBuffer, ssize_t length) {
|
||||
|
||||
qDebug() << "queueOctreeEditMessage() line:" << __LINE__;
|
||||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "queueOctreeEditMessage() line:" << __LINE__;
|
||||
|
||||
// If we don't have jurisdictions, then we will simply queue up all of these packets and wait till we have
|
||||
// jurisdictions for processing
|
||||
if (!serversExist()) {
|
||||
|
@ -211,52 +220,61 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c
|
|||
}
|
||||
return; // bail early
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "queueOctreeEditMessage() line:" << __LINE__;
|
||||
|
||||
// We want to filter out edit messages for servers based on the server's Jurisdiction
|
||||
// But we can't really do that with a packed message, since each edit message could be destined
|
||||
// But we can't really do that with a packed message, since each edit message could be destined
|
||||
// for a different server... So we need to actually manage multiple queued packets... one
|
||||
// for each server
|
||||
|
||||
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
// only send to the NodeTypes that are getMyNodeType()
|
||||
if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) {
|
||||
QUuid nodeUUID = node->getUUID();
|
||||
bool isMyJurisdiction = true;
|
||||
|
||||
|
||||
if (_serverJurisdictions) {
|
||||
// we need to get the jurisdiction for this
|
||||
// here we need to get the "pending packet" for this server
|
||||
if ((*_serverJurisdictions).find(nodeUUID) != (*_serverJurisdictions).end()) {
|
||||
const JurisdictionMap& map = (*_serverJurisdictions)[nodeUUID];
|
||||
isMyJurisdiction = (map.isMyJurisdiction(codeColorBuffer, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN);
|
||||
qDebug() << "queueOctreeEditMessage() line:" << __LINE__ << " isMyJurisdiction=" << isMyJurisdiction;
|
||||
} else {
|
||||
isMyJurisdiction = false;
|
||||
qDebug() << "queueOctreeEditMessage() line:" << __LINE__;
|
||||
}
|
||||
}
|
||||
if (isMyJurisdiction) {
|
||||
EditPacketBuffer& packetBuffer = _pendingEditPackets[nodeUUID];
|
||||
packetBuffer._nodeUUID = nodeUUID;
|
||||
|
||||
|
||||
qDebug() << "queueOctreeEditMessage() line:" << __LINE__;
|
||||
|
||||
// If we're switching type, then we send the last one and start over
|
||||
if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) ||
|
||||
(packetBuffer._currentSize + length >= _maxPacketSize)) {
|
||||
releaseQueuedPacket(packetBuffer);
|
||||
initializePacket(packetBuffer, type);
|
||||
}
|
||||
|
||||
|
||||
// If the buffer is empty and not correctly initialized for our type...
|
||||
if (type != packetBuffer._currentType && packetBuffer._currentSize == 0) {
|
||||
initializePacket(packetBuffer, type);
|
||||
}
|
||||
|
||||
|
||||
// This is really the first time we know which server/node this particular edit message
|
||||
// is going to, so we couldn't adjust for clock skew till now. But here's our chance.
|
||||
// We call this virtual function that allows our specific type of EditPacketSender to
|
||||
// fixup the buffer for any clock skew
|
||||
if (node->getClockSkewUsec() != 0) {
|
||||
adjustEditPacketForClockSkew(codeColorBuffer, length, node->getClockSkewUsec());
|
||||
qDebug() << "queueOctreeEditMessage() line:" << __LINE__;
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "queueOctreeEditMessage() line:" << __LINE__;
|
||||
|
||||
memcpy(&packetBuffer._currentBuffer[packetBuffer._currentSize], codeColorBuffer, length);
|
||||
packetBuffer._currentSize += length;
|
||||
}
|
||||
|
@ -265,7 +283,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c
|
|||
}
|
||||
|
||||
void OctreeEditPacketSender::releaseQueuedMessages() {
|
||||
// if we don't yet have jurisdictions then we can't actually release messages yet because we don't
|
||||
// if we don't yet have jurisdictions then we can't actually release messages yet because we don't
|
||||
// know where to send them to. Instead, just remember this request and when we eventually get jurisdictions
|
||||
// call release again at that time.
|
||||
if (!serversExist()) {
|
||||
|
@ -273,12 +291,14 @@ void OctreeEditPacketSender::releaseQueuedMessages() {
|
|||
} else {
|
||||
for (std::map<QUuid, EditPacketBuffer>::iterator i = _pendingEditPackets.begin(); i != _pendingEditPackets.end(); i++) {
|
||||
releaseQueuedPacket(i->second);
|
||||
qDebug() << "releaseQueuedMessages() line:" << __LINE__;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OctreeEditPacketSender::releaseQueuedPacket(EditPacketBuffer& packetBuffer) {
|
||||
if (packetBuffer._currentSize > 0 && packetBuffer._currentType != PACKET_TYPE_UNKNOWN) {
|
||||
qDebug() << "OctreeEditPacketSender::releaseQueuedPacket() line:" << __LINE__;
|
||||
queuePacketToNode(packetBuffer._nodeUUID, &packetBuffer._currentBuffer[0], packetBuffer._currentSize);
|
||||
}
|
||||
packetBuffer._currentSize = 0;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "ParticlesScriptingInterface.h"
|
||||
#include "Particle.h"
|
||||
#include "ParticleTree.h"
|
||||
|
||||
uint32_t Particle::_nextID = 0;
|
||||
VoxelEditPacketSender* Particle::_voxelEditSender = NULL;
|
||||
|
@ -57,6 +58,8 @@ void Particle::handleAddParticleResponse(unsigned char* packetData , int packetL
|
|||
memcpy(&particleID, dataAt, sizeof(particleID));
|
||||
dataAt += sizeof(particleID);
|
||||
|
||||
qDebug() << "handleAddParticleResponse()... particleID=" << particleID << " creatorTokenID=" << creatorTokenID;
|
||||
|
||||
// add our token to id mapping
|
||||
_tokenIDsToIDs[creatorTokenID] = particleID;
|
||||
}
|
||||
|
@ -278,7 +281,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, ParticleTree* tree) {
|
||||
Particle newParticle; // id and _lastUpdated will get set here...
|
||||
unsigned char* dataAt = data;
|
||||
processedBytes = 0;
|
||||
|
@ -309,10 +312,30 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
newParticle._newlyCreated = true;
|
||||
|
||||
newParticle.setAge(0); // this guy is new!
|
||||
qDebug() << "fromEditPacket() NEW_PARTICLE";
|
||||
|
||||
} else {
|
||||
qDebug() << "fromEditPacket() existingParticle id=" << editID;
|
||||
|
||||
// look up the existing particle
|
||||
|
||||
qDebug() << "fromEditPacket() existingParticle id=" << editID << "calling tree->findParticleByID(editID)";
|
||||
const Particle* existingParticle = tree->findParticleByID(editID, true);
|
||||
qDebug() << "fromEditPacket() existingParticle id=" << editID << "DONE tree->findParticleByID(editID)";
|
||||
|
||||
// copy existing properties before over-writing with new properties
|
||||
if (existingParticle) {
|
||||
newParticle = *existingParticle;
|
||||
qDebug() << "found it...";
|
||||
existingParticle->debugDump();
|
||||
} else {
|
||||
qDebug() << "WHOA! Didn't find it...";
|
||||
}
|
||||
|
||||
newParticle._id = editID;
|
||||
newParticle._newlyCreated = false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// lastEdited
|
||||
|
@ -320,55 +343,92 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
dataAt += sizeof(newParticle._lastEdited);
|
||||
processedBytes += sizeof(newParticle._lastEdited);
|
||||
|
||||
// All of the remaining items are optional, and may or may not be included based on their included values in the
|
||||
// properties included bits
|
||||
uint16_t packetContainsBits = 0;
|
||||
memcpy(&packetContainsBits, dataAt, sizeof(packetContainsBits));
|
||||
dataAt += sizeof(packetContainsBits);
|
||||
processedBytes += sizeof(packetContainsBits);
|
||||
|
||||
qDebug() << "fromEditPacket() packetContainsBits=" << packetContainsBits;
|
||||
|
||||
// radius
|
||||
memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius));
|
||||
dataAt += sizeof(newParticle._radius);
|
||||
processedBytes += sizeof(newParticle._radius);
|
||||
if ((packetContainsBits & PACKET_CONTAINS_RADIUS) == PACKET_CONTAINS_RADIUS) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_RADIUS";
|
||||
|
||||
memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius));
|
||||
dataAt += sizeof(newParticle._radius);
|
||||
processedBytes += sizeof(newParticle._radius);
|
||||
}
|
||||
|
||||
// position
|
||||
memcpy(&newParticle._position, dataAt, sizeof(newParticle._position));
|
||||
dataAt += sizeof(newParticle._position);
|
||||
processedBytes += sizeof(newParticle._position);
|
||||
if ((packetContainsBits & PACKET_CONTAINS_POSITION) == PACKET_CONTAINS_POSITION) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_POSITION";
|
||||
memcpy(&newParticle._position, dataAt, sizeof(newParticle._position));
|
||||
dataAt += sizeof(newParticle._position);
|
||||
processedBytes += sizeof(newParticle._position);
|
||||
}
|
||||
|
||||
// color
|
||||
memcpy(newParticle._color, dataAt, sizeof(newParticle._color));
|
||||
dataAt += sizeof(newParticle._color);
|
||||
processedBytes += sizeof(newParticle._color);
|
||||
if ((packetContainsBits & PACKET_CONTAINS_COLOR) == PACKET_CONTAINS_COLOR) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_COLOR";
|
||||
memcpy(newParticle._color, dataAt, sizeof(newParticle._color));
|
||||
dataAt += sizeof(newParticle._color);
|
||||
processedBytes += sizeof(newParticle._color);
|
||||
}
|
||||
|
||||
// velocity
|
||||
memcpy(&newParticle._velocity, dataAt, sizeof(newParticle._velocity));
|
||||
dataAt += sizeof(newParticle._velocity);
|
||||
processedBytes += sizeof(newParticle._velocity);
|
||||
if ((packetContainsBits & PACKET_CONTAINS_VELOCITY) == PACKET_CONTAINS_VELOCITY) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_VELOCITY";
|
||||
memcpy(&newParticle._velocity, dataAt, sizeof(newParticle._velocity));
|
||||
dataAt += sizeof(newParticle._velocity);
|
||||
processedBytes += sizeof(newParticle._velocity);
|
||||
}
|
||||
|
||||
// gravity
|
||||
memcpy(&newParticle._gravity, dataAt, sizeof(newParticle._gravity));
|
||||
dataAt += sizeof(newParticle._gravity);
|
||||
processedBytes += sizeof(newParticle._gravity);
|
||||
if ((packetContainsBits & PACKET_CONTAINS_GRAVITY) == PACKET_CONTAINS_GRAVITY) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_GRAVITY";
|
||||
memcpy(&newParticle._gravity, dataAt, sizeof(newParticle._gravity));
|
||||
dataAt += sizeof(newParticle._gravity);
|
||||
processedBytes += sizeof(newParticle._gravity);
|
||||
}
|
||||
|
||||
// damping
|
||||
memcpy(&newParticle._damping, dataAt, sizeof(newParticle._damping));
|
||||
dataAt += sizeof(newParticle._damping);
|
||||
processedBytes += sizeof(newParticle._damping);
|
||||
if ((packetContainsBits & PACKET_CONTAINS_DAMPING) == PACKET_CONTAINS_DAMPING) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_DAMPING";
|
||||
memcpy(&newParticle._damping, dataAt, sizeof(newParticle._damping));
|
||||
dataAt += sizeof(newParticle._damping);
|
||||
processedBytes += sizeof(newParticle._damping);
|
||||
}
|
||||
|
||||
// lifetime
|
||||
memcpy(&newParticle._lifetime, dataAt, sizeof(newParticle._lifetime));
|
||||
dataAt += sizeof(newParticle._lifetime);
|
||||
processedBytes += sizeof(newParticle._lifetime);
|
||||
if ((packetContainsBits & PACKET_CONTAINS_LIFETIME) == PACKET_CONTAINS_LIFETIME) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_LIFETIME";
|
||||
memcpy(&newParticle._lifetime, dataAt, sizeof(newParticle._lifetime));
|
||||
dataAt += sizeof(newParticle._lifetime);
|
||||
processedBytes += sizeof(newParticle._lifetime);
|
||||
}
|
||||
|
||||
// inHand
|
||||
memcpy(&newParticle._inHand, dataAt, sizeof(newParticle._inHand));
|
||||
dataAt += sizeof(newParticle._inHand);
|
||||
processedBytes += sizeof(newParticle._inHand);
|
||||
if ((packetContainsBits & PACKET_CONTAINS_INHAND) == PACKET_CONTAINS_INHAND) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_INHAND";
|
||||
memcpy(&newParticle._inHand, dataAt, sizeof(newParticle._inHand));
|
||||
dataAt += sizeof(newParticle._inHand);
|
||||
processedBytes += sizeof(newParticle._inHand);
|
||||
}
|
||||
|
||||
// script
|
||||
uint16_t scriptLength;
|
||||
memcpy(&scriptLength, dataAt, sizeof(scriptLength));
|
||||
dataAt += sizeof(scriptLength);
|
||||
processedBytes += sizeof(scriptLength);
|
||||
QString tempString((const char*)dataAt);
|
||||
newParticle._script = tempString;
|
||||
dataAt += scriptLength;
|
||||
processedBytes += scriptLength;
|
||||
if ((packetContainsBits & PACKET_CONTAINS_SCRIPT) == PACKET_CONTAINS_SCRIPT) {
|
||||
qDebug() << "fromEditPacket() PACKET_CONTAINS_SCRIPT";
|
||||
uint16_t scriptLength;
|
||||
memcpy(&scriptLength, dataAt, sizeof(scriptLength));
|
||||
dataAt += sizeof(scriptLength);
|
||||
processedBytes += sizeof(scriptLength);
|
||||
QString tempString((const char*)dataAt);
|
||||
newParticle._script = tempString;
|
||||
dataAt += scriptLength;
|
||||
processedBytes += scriptLength;
|
||||
}
|
||||
|
||||
const bool wantDebugging = true;
|
||||
if (wantDebugging) {
|
||||
|
@ -386,116 +446,168 @@ void Particle::debugDump() const {
|
|||
printf(" age:%f\n", getAge());
|
||||
printf(" edited ago:%f\n", getEditedAgo());
|
||||
printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z);
|
||||
printf(" radius:%f\n", getRadius());
|
||||
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(" color:%d,%d,%d\n", _color[0], _color[1], _color[2]);
|
||||
}
|
||||
|
||||
bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details,
|
||||
bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, ParticleID id, const ParticleProperties& properties,
|
||||
unsigned char* bufferOut, int sizeIn, int& sizeOut) {
|
||||
|
||||
bool success = true; // assume the best
|
||||
unsigned char* copyAt = bufferOut;
|
||||
sizeOut = 0;
|
||||
|
||||
for (int i = 0; i < count && success; i++) {
|
||||
// get the octal code for the particle
|
||||
unsigned char* octcode = pointToOctalCode(details[i].position.x, details[i].position.y,
|
||||
details[i].position.z, details[i].radius);
|
||||
// get the octal code for the particle
|
||||
|
||||
int octets = numberOfThreeBitSectionsInCode(octcode);
|
||||
int lengthOfOctcode = bytesRequiredForCodeLength(octets);
|
||||
int lenfthOfEditData = lengthOfOctcode + expectedEditMessageBytes();
|
||||
// this could be a problem if the caller doesn't include position....
|
||||
glm::vec3 rootPosition(0);
|
||||
float rootScale = 0.5f;
|
||||
unsigned char* octcode = pointToOctalCode(rootPosition.x, rootPosition.y, rootPosition.z, rootScale);
|
||||
|
||||
// make sure we have room to copy this particle
|
||||
if (sizeOut + lenfthOfEditData > sizeIn) {
|
||||
success = false;
|
||||
} else {
|
||||
// add it to our message
|
||||
memcpy(copyAt, octcode, lengthOfOctcode);
|
||||
copyAt += lengthOfOctcode;
|
||||
sizeOut += lengthOfOctcode;
|
||||
// old code... this matters for particle servers with different jurisdictions, but for now, we'll send
|
||||
// everything to the root, since the tree does the right thing...
|
||||
//
|
||||
//unsigned char* octcode = pointToOctalCode(details[i].position.x, details[i].position.y,
|
||||
// details[i].position.z, details[i].radius);
|
||||
|
||||
// Now add our edit content details...
|
||||
int octets = numberOfThreeBitSectionsInCode(octcode);
|
||||
int lengthOfOctcode = bytesRequiredForCodeLength(octets);
|
||||
int lenfthOfEditData = lengthOfOctcode + expectedEditMessageBytes();
|
||||
|
||||
// id
|
||||
memcpy(copyAt, &details[i].id, sizeof(details[i].id));
|
||||
copyAt += sizeof(details[i].id);
|
||||
sizeOut += sizeof(details[i].id);
|
||||
// special case for handling "new" particles
|
||||
if (details[i].id == NEW_PARTICLE) {
|
||||
// If this is a NEW_PARTICLE, then we assume that there's an additional uint32_t creatorToken, that
|
||||
// we want to send back to the creator as an map to the actual id
|
||||
memcpy(copyAt, &details[i].creatorTokenID, sizeof(details[i].creatorTokenID));
|
||||
copyAt += sizeof(details[i].creatorTokenID);
|
||||
sizeOut += sizeof(details[i].creatorTokenID);
|
||||
}
|
||||
// make sure we have room to copy this particle
|
||||
if (sizeOut + lenfthOfEditData > sizeIn) {
|
||||
success = false;
|
||||
} else {
|
||||
// add it to our message
|
||||
memcpy(copyAt, octcode, lengthOfOctcode);
|
||||
copyAt += lengthOfOctcode;
|
||||
sizeOut += lengthOfOctcode;
|
||||
|
||||
// lastEdited
|
||||
memcpy(copyAt, &details[i].lastEdited, sizeof(details[i].lastEdited));
|
||||
copyAt += sizeof(details[i].lastEdited);
|
||||
sizeOut += sizeof(details[i].lastEdited);
|
||||
// Now add our edit content details...
|
||||
|
||||
// radius
|
||||
memcpy(copyAt, &details[i].radius, sizeof(details[i].radius));
|
||||
copyAt += sizeof(details[i].radius);
|
||||
sizeOut += sizeof(details[i].radius);
|
||||
// id
|
||||
memcpy(copyAt, &id.id, sizeof(id.id));
|
||||
copyAt += sizeof(id.id);
|
||||
sizeOut += sizeof(id.id);
|
||||
// special case for handling "new" particles
|
||||
if (id.id == NEW_PARTICLE) {
|
||||
// If this is a NEW_PARTICLE, then we assume that there's an additional uint32_t creatorToken, that
|
||||
// we want to send back to the creator as an map to the actual id
|
||||
memcpy(copyAt, &id.creatorTokenID, sizeof(id.creatorTokenID));
|
||||
copyAt += sizeof(id.creatorTokenID);
|
||||
sizeOut += sizeof(id.creatorTokenID);
|
||||
}
|
||||
|
||||
// position
|
||||
memcpy(copyAt, &details[i].position, sizeof(details[i].position));
|
||||
copyAt += sizeof(details[i].position);
|
||||
sizeOut += sizeof(details[i].position);
|
||||
// lastEdited
|
||||
uint64_t lastEdited = properties.getLastEdited();
|
||||
memcpy(copyAt, &lastEdited, sizeof(lastEdited));
|
||||
copyAt += sizeof(lastEdited);
|
||||
sizeOut += sizeof(lastEdited);
|
||||
|
||||
// color
|
||||
memcpy(copyAt, details[i].color, sizeof(details[i].color));
|
||||
copyAt += sizeof(details[i].color);
|
||||
sizeOut += sizeof(details[i].color);
|
||||
// All of the remaining items are optional, and may or may not be included based on their included values in the
|
||||
// properties included bits
|
||||
uint16_t packetContainsBits = properties.getChangedBits();
|
||||
memcpy(copyAt, &packetContainsBits, sizeof(packetContainsBits));
|
||||
copyAt += sizeof(packetContainsBits);
|
||||
sizeOut += sizeof(packetContainsBits);
|
||||
|
||||
// velocity
|
||||
memcpy(copyAt, &details[i].velocity, sizeof(details[i].velocity));
|
||||
copyAt += sizeof(details[i].velocity);
|
||||
sizeOut += sizeof(details[i].velocity);
|
||||
qDebug() << " packetContainsBits = " << packetContainsBits;
|
||||
|
||||
// gravity
|
||||
memcpy(copyAt, &details[i].gravity, sizeof(details[i].gravity));
|
||||
copyAt += sizeof(details[i].gravity);
|
||||
sizeOut += sizeof(details[i].gravity);
|
||||
// radius
|
||||
if ((packetContainsBits & PACKET_CONTAINS_RADIUS) == PACKET_CONTAINS_RADIUS) {
|
||||
printf("encodeParticleEditMessageDetails() including PACKET_CONTAINS_RADIUS\n");
|
||||
float radius = properties.getRadius();
|
||||
memcpy(copyAt, &radius, sizeof(radius));
|
||||
copyAt += sizeof(radius);
|
||||
sizeOut += sizeof(radius);
|
||||
}
|
||||
|
||||
// damping
|
||||
memcpy(copyAt, &details[i].damping, sizeof(details[i].damping));
|
||||
copyAt += sizeof(details[i].damping);
|
||||
sizeOut += sizeof(details[i].damping);
|
||||
// position
|
||||
if ((packetContainsBits & PACKET_CONTAINS_POSITION) == PACKET_CONTAINS_POSITION) {
|
||||
printf("encodeParticleEditMessageDetails() including PACKET_CONTAINS_POSITION\n");
|
||||
memcpy(copyAt, &properties.getPosition(), sizeof(properties.getPosition()));
|
||||
copyAt += sizeof(properties.getPosition());
|
||||
sizeOut += sizeof(properties.getPosition());
|
||||
}
|
||||
|
||||
// damping
|
||||
memcpy(copyAt, &details[i].lifetime, sizeof(details[i].lifetime));
|
||||
copyAt += sizeof(details[i].lifetime);
|
||||
sizeOut += sizeof(details[i].lifetime);
|
||||
// color
|
||||
if ((packetContainsBits & PACKET_CONTAINS_COLOR) == PACKET_CONTAINS_COLOR) {
|
||||
printf("encodeParticleEditMessageDetails() including PACKET_CONTAINS_COLOR\n");
|
||||
rgbColor color = { properties.getColor().red, properties.getColor().green, properties.getColor().blue };
|
||||
memcpy(copyAt, color, sizeof(color));
|
||||
copyAt += sizeof(color);
|
||||
sizeOut += sizeof(color);
|
||||
}
|
||||
|
||||
// inHand
|
||||
memcpy(copyAt, &details[i].inHand, sizeof(details[i].inHand));
|
||||
copyAt += sizeof(details[i].inHand);
|
||||
sizeOut += sizeof(details[i].inHand);
|
||||
// velocity
|
||||
if ((packetContainsBits & PACKET_CONTAINS_VELOCITY) == PACKET_CONTAINS_VELOCITY) {
|
||||
printf("encodeParticleEditMessageDetails() including PACKET_CONTAINS_VELOCITY\n");
|
||||
memcpy(copyAt, &properties.getVelocity(), sizeof(properties.getVelocity()));
|
||||
copyAt += sizeof(properties.getVelocity());
|
||||
sizeOut += sizeof(properties.getVelocity());
|
||||
}
|
||||
|
||||
// script
|
||||
uint16_t scriptLength = details[i].updateScript.size() + 1;
|
||||
// gravity
|
||||
if ((packetContainsBits & PACKET_CONTAINS_GRAVITY) == PACKET_CONTAINS_GRAVITY) {
|
||||
printf("encodeParticleEditMessageDetails() including PACKET_CONTAINS_GRAVITY\n");
|
||||
memcpy(copyAt, &properties.getGravity(), sizeof(properties.getGravity()));
|
||||
copyAt += sizeof(properties.getGravity());
|
||||
sizeOut += sizeof(properties.getGravity());
|
||||
}
|
||||
|
||||
// damping
|
||||
if ((packetContainsBits & PACKET_CONTAINS_DAMPING) == PACKET_CONTAINS_DAMPING) {
|
||||
printf("encodeParticleEditMessageDetails() including PACKET_CONTAINS_DAMPING\n");
|
||||
float damping = properties.getDamping();
|
||||
memcpy(copyAt, &damping, sizeof(damping));
|
||||
copyAt += sizeof(damping);
|
||||
sizeOut += sizeof(damping);
|
||||
}
|
||||
|
||||
// lifetime
|
||||
if ((packetContainsBits & PACKET_CONTAINS_LIFETIME) == PACKET_CONTAINS_LIFETIME) {
|
||||
printf("encodeParticleEditMessageDetails() including PACKET_CONTAINS_LIFETIME\n");
|
||||
float lifetime = properties.getLifetime();
|
||||
memcpy(copyAt, &lifetime, sizeof(lifetime));
|
||||
copyAt += sizeof(lifetime);
|
||||
sizeOut += sizeof(lifetime);
|
||||
}
|
||||
|
||||
// inHand
|
||||
if ((packetContainsBits & PACKET_CONTAINS_INHAND) == PACKET_CONTAINS_INHAND) {
|
||||
printf("encodeParticleEditMessageDetails() including PACKET_CONTAINS_INHAND\n");
|
||||
bool inHand = properties.getInHand();
|
||||
memcpy(copyAt, &inHand, sizeof(inHand));
|
||||
copyAt += sizeof(inHand);
|
||||
sizeOut += sizeof(inHand);
|
||||
}
|
||||
|
||||
// script
|
||||
if ((packetContainsBits & PACKET_CONTAINS_SCRIPT) == PACKET_CONTAINS_SCRIPT) {
|
||||
printf("encodeParticleEditMessageDetails() including SCRIPT\n");
|
||||
|
||||
uint16_t scriptLength = properties.getScript().size() + 1;
|
||||
memcpy(copyAt, &scriptLength, sizeof(scriptLength));
|
||||
copyAt += sizeof(scriptLength);
|
||||
sizeOut += sizeof(scriptLength);
|
||||
memcpy(copyAt, qPrintable(details[i].updateScript), scriptLength);
|
||||
memcpy(copyAt, qPrintable(properties.getScript()), scriptLength);
|
||||
copyAt += scriptLength;
|
||||
sizeOut += scriptLength;
|
||||
|
||||
bool wantDebugging = false;
|
||||
if (wantDebugging) {
|
||||
printf("encodeParticleEditMessageDetails()....\n");
|
||||
printf("Particle id :%u\n", details[i].id);
|
||||
printf(" nextID:%u\n", _nextID);
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
delete[] octcode;
|
||||
|
||||
bool wantDebugging = false;
|
||||
if (wantDebugging) {
|
||||
printf("encodeParticleEditMessageDetails()....\n");
|
||||
printf("Particle id :%u\n", id.id);
|
||||
printf(" nextID:%u\n", _nextID);
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup
|
||||
delete[] octcode;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -696,7 +808,7 @@ void Particle::setProperties(const ParticleProperties& properties) {
|
|||
ParticleProperties::ParticleProperties() :
|
||||
_position(0),
|
||||
_color(),
|
||||
_radius(DEFAULT_RADIUS),
|
||||
_radius(0),
|
||||
_velocity(0),
|
||||
_gravity(DEFAULT_GRAVITY),
|
||||
_damping(DEFAULT_DAMPING),
|
||||
|
@ -705,6 +817,7 @@ ParticleProperties::ParticleProperties() :
|
|||
_inHand(false),
|
||||
_shouldDie(false),
|
||||
|
||||
_lastEdited(usecTimestampNow()),
|
||||
_positionChanged(false),
|
||||
_colorChanged(false),
|
||||
_radiusChanged(false),
|
||||
|
@ -718,6 +831,55 @@ ParticleProperties::ParticleProperties() :
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
uint16_t ParticleProperties::getChangedBits() const {
|
||||
uint16_t changedBits = 0;
|
||||
if (_radiusChanged) {
|
||||
changedBits += PACKET_CONTAINS_RADIUS;
|
||||
}
|
||||
|
||||
if (_positionChanged) {
|
||||
changedBits += PACKET_CONTAINS_POSITION;
|
||||
}
|
||||
|
||||
if (_colorChanged) {
|
||||
changedBits += PACKET_CONTAINS_COLOR;
|
||||
}
|
||||
|
||||
if (_velocityChanged) {
|
||||
changedBits += PACKET_CONTAINS_VELOCITY;
|
||||
}
|
||||
|
||||
if (_gravityChanged) {
|
||||
changedBits += PACKET_CONTAINS_GRAVITY;
|
||||
}
|
||||
|
||||
if (_dampingChanged) {
|
||||
changedBits += PACKET_CONTAINS_DAMPING;
|
||||
}
|
||||
|
||||
if (_lifetimeChanged) {
|
||||
changedBits += PACKET_CONTAINS_LIFETIME;
|
||||
}
|
||||
|
||||
if (_inHandChanged) {
|
||||
changedBits += PACKET_CONTAINS_INHAND;
|
||||
}
|
||||
|
||||
if (_scriptChanged) {
|
||||
changedBits += PACKET_CONTAINS_SCRIPT;
|
||||
}
|
||||
|
||||
// how do we want to handle this?
|
||||
|
||||
//if (_shouldDieChanged) {
|
||||
// changedBits += PACKET_CONTAINS_SHOULDDIE;
|
||||
//}
|
||||
|
||||
return changedBits;
|
||||
}
|
||||
|
||||
|
||||
QScriptValue ParticleProperties::copyToScriptValue(QScriptEngine* engine) const {
|
||||
QScriptValue properties = engine->newObject();
|
||||
|
||||
|
@ -783,13 +945,18 @@ void ParticleProperties::copyFromScriptValue(const QScriptValue &object) {
|
|||
}
|
||||
|
||||
QScriptValue radius = object.property("radius");
|
||||
qDebug() << "copyFromScriptValue() line:" << __LINE__;
|
||||
if (radius.isValid()) {
|
||||
qDebug() << "copyFromScriptValue() line:" << __LINE__;
|
||||
float newRadius;
|
||||
newRadius = radius.toVariant().toFloat();
|
||||
qDebug() << "copyFromScriptValue() line:" << __LINE__ << " newRadius=" << newRadius;
|
||||
qDebug() << "copyFromScriptValue() line:" << __LINE__ << " _radius=" << _radius;
|
||||
if (newRadius != _radius) {
|
||||
_radius = newRadius;
|
||||
_radiusChanged = true;
|
||||
}
|
||||
qDebug() << "copyFromScriptValue() line:" << __LINE__ << " _radiusChanged=" << _radiusChanged;
|
||||
}
|
||||
|
||||
QScriptValue velocity = object.property("velocity");
|
||||
|
@ -875,6 +1042,8 @@ void ParticleProperties::copyFromScriptValue(const QScriptValue &object) {
|
|||
_shouldDieChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
_lastEdited = usecTimestampNow();
|
||||
}
|
||||
|
||||
void ParticleProperties::copyToParticle(Particle& particle) const {
|
||||
|
|
|
@ -25,26 +25,21 @@ class VoxelEditPacketSender;
|
|||
class ParticleEditPacketSender;
|
||||
class ParticleProperties;
|
||||
class Particle;
|
||||
class ParticleTree;
|
||||
|
||||
const uint32_t NEW_PARTICLE = 0xFFFFFFFF;
|
||||
const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF;
|
||||
const uint32_t UNKNOWN_PARTICLE_ID = 0xFFFFFFFF;
|
||||
|
||||
class ParticleDetail {
|
||||
public:
|
||||
uint32_t id;
|
||||
uint64_t lastEdited;
|
||||
glm::vec3 position;
|
||||
float radius;
|
||||
rgbColor color;
|
||||
glm::vec3 velocity;
|
||||
glm::vec3 gravity;
|
||||
float damping;
|
||||
float lifetime;
|
||||
bool inHand;
|
||||
QString updateScript;
|
||||
uint32_t creatorTokenID;
|
||||
};
|
||||
const uint16_t PACKET_CONTAINS_RADIUS = 1;
|
||||
const uint16_t PACKET_CONTAINS_POSITION = 2;
|
||||
const uint16_t PACKET_CONTAINS_COLOR = 4;
|
||||
const uint16_t PACKET_CONTAINS_VELOCITY = 8;
|
||||
const uint16_t PACKET_CONTAINS_GRAVITY = 16;
|
||||
const uint16_t PACKET_CONTAINS_DAMPING = 32;
|
||||
const uint16_t PACKET_CONTAINS_LIFETIME = 64;
|
||||
const uint16_t PACKET_CONTAINS_INHAND = 128;
|
||||
const uint16_t PACKET_CONTAINS_SCRIPT = 256;
|
||||
|
||||
const float DEFAULT_LIFETIME = 60.0f * 60.0f * 24.0f; // particles live for 1 day by default
|
||||
const float DEFAULT_DAMPING = 0.99f;
|
||||
|
@ -74,10 +69,13 @@ public:
|
|||
const glm::vec3& getGravity() const { return _gravity; }
|
||||
float getDamping() const { return _damping; }
|
||||
float getLifetime() const { return _lifetime; }
|
||||
QString getScript() const { return _script; }
|
||||
const QString& getScript() const { return _script; }
|
||||
bool getInHand() const { return _inHand; }
|
||||
bool getShouldDie() const { return _shouldDie; }
|
||||
|
||||
uint64_t getLastEdited() const { return _lastEdited; }
|
||||
uint16_t getChangedBits() const;
|
||||
|
||||
private:
|
||||
glm::vec3 _position;
|
||||
xColor _color;
|
||||
|
@ -90,6 +88,7 @@ private:
|
|||
bool _inHand;
|
||||
bool _shouldDie;
|
||||
|
||||
uint64_t _lastEdited;
|
||||
bool _positionChanged;
|
||||
bool _colorChanged;
|
||||
bool _radiusChanged;
|
||||
|
@ -138,7 +137,7 @@ public:
|
|||
bool inHand = NOT_IN_HAND, QString updateScript = DEFAULT_SCRIPT, uint32_t id = NEW_PARTICLE);
|
||||
|
||||
/// creates an NEW particle from an PACKET_TYPE_PARTICLE_ADD_OR_EDIT edit data buffer
|
||||
static Particle fromEditPacket(unsigned char* data, int length, int& processedBytes);
|
||||
static Particle fromEditPacket(unsigned char* data, int length, int& processedBytes, ParticleTree* tree);
|
||||
|
||||
virtual ~Particle();
|
||||
virtual void init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
|
@ -196,7 +195,7 @@ public:
|
|||
static int expectedBytes();
|
||||
static int expectedEditMessageBytes();
|
||||
|
||||
static bool encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details,
|
||||
static bool encodeParticleEditMessageDetails(PACKET_TYPE command, ParticleID id, const ParticleProperties& details,
|
||||
unsigned char* bufferOut, int sizeIn, int& sizeOut);
|
||||
|
||||
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew);
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "ParticleTree.h"
|
||||
|
||||
std::map<uint32_t,ParticleEditHandle*> ParticleEditHandle::_allHandles;
|
||||
uint32_t ParticleEditHandle::_nextCreatorTokenID = 0;
|
||||
|
||||
ParticleEditHandle::ParticleEditHandle(ParticleEditPacketSender* packetSender, ParticleTree* localTree, uint32_t id) {
|
||||
if (id == NEW_PARTICLE) {
|
||||
|
@ -43,13 +42,14 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor
|
|||
glm::vec3 gravity, float damping, float lifetime, bool inHand, QString updateScript) {
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
/****
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now,
|
||||
position, radius, {color.red, color.green, color.blue },
|
||||
velocity, gravity, damping, lifetime, inHand, updateScript, _creatorTokenID };
|
||||
|
||||
// queue the packet
|
||||
_packetSender->queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &addParticleDetail);
|
||||
_packetSender->queueParticleEditMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &addParticleDetail);
|
||||
|
||||
// release them
|
||||
_packetSender->releaseQueuedMessages();
|
||||
|
@ -59,6 +59,8 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor
|
|||
// we can't really do this here, because if we create a particle locally, we'll get a ghost particle
|
||||
// because we can't really handle updating/deleting it locally
|
||||
}
|
||||
****/
|
||||
|
||||
}
|
||||
|
||||
bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
|
@ -69,6 +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,
|
||||
position, radius, {color.red, color.green, color.blue },
|
||||
|
@ -86,6 +89,7 @@ bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor
|
|||
Particle tempParticle(position, radius, rcolor, velocity, gravity, damping, lifetime, inHand, updateScript, _id);
|
||||
_localTree->storeParticle(tempParticle);
|
||||
}
|
||||
***/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@ private:
|
|||
uint32_t _creatorTokenID;
|
||||
uint32_t _id;
|
||||
bool _isKnownID;
|
||||
static uint32_t _nextCreatorTokenID;
|
||||
static std::map<uint32_t,ParticleEditHandle*> _allHandles;
|
||||
ParticleEditPacketSender* _packetSender;
|
||||
ParticleTree* _localTree;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "Particle.h"
|
||||
|
||||
|
||||
void ParticleEditPacketSender::sendEditParticleMessage(PACKET_TYPE type, const ParticleDetail& detail) {
|
||||
void ParticleEditPacketSender::sendEditParticleMessage(PACKET_TYPE type, ParticleID particleID, const ParticleProperties& properties) {
|
||||
// allows app to disable sending if for example voxels have been disabled
|
||||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
|
@ -26,35 +26,42 @@ void ParticleEditPacketSender::sendEditParticleMessage(PACKET_TYPE type, const P
|
|||
int sizeOut = 0;
|
||||
|
||||
// This encodes the voxel edit message into a buffer...
|
||||
if (Particle::encodeParticleEditMessageDetails(type, 1, &detail, &bufferOut[0], _maxPacketSize, sizeOut)){
|
||||
if (Particle::encodeParticleEditMessageDetails(type, particleID, properties, &bufferOut[0], _maxPacketSize, sizeOut)){
|
||||
// If we don't have voxel jurisdictions, then we will simply queue up these packets and wait till we have
|
||||
// jurisdictions for processing
|
||||
if (!serversExist()) {
|
||||
queuePendingPacketToNodes(type, bufferOut, sizeOut);
|
||||
} else {
|
||||
|
||||
qDebug("calling queuePacketToNodes(bufferOut, sizeOut=%d)... ", sizeOut);
|
||||
|
||||
queuePacketToNodes(bufferOut, sizeOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEditPacketSender::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew) {
|
||||
void ParticleEditPacketSender::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew) {
|
||||
Particle::adjustEditPacketForClockSkew(codeColorBuffer, length, clockSkew);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ParticleEditPacketSender::queueParticleEditMessages(PACKET_TYPE type, int numberOfDetails, ParticleDetail* details) {
|
||||
void ParticleEditPacketSender::queueParticleEditMessage(PACKET_TYPE type, ParticleID particleID, const ParticleProperties& properties) {
|
||||
|
||||
qDebug() << "ParticleEditPacketSender::queueParticleEditMessage() id.id=" << particleID.id << " id.creatorTokenID=" << particleID.creatorTokenID;
|
||||
|
||||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
}
|
||||
|
||||
for (int i = 0; i < numberOfDetails; i++) {
|
||||
// use MAX_PACKET_SIZE since it's static and guaranteed to be larger than _maxPacketSize
|
||||
static unsigned char bufferOut[MAX_PACKET_SIZE];
|
||||
int sizeOut = 0;
|
||||
|
||||
if (Particle::encodeParticleEditMessageDetails(type, 1, &details[i], &bufferOut[0], _maxPacketSize, sizeOut)) {
|
||||
queueOctreeEditMessage(type, bufferOut, sizeOut);
|
||||
}
|
||||
}
|
||||
// use MAX_PACKET_SIZE since it's static and guaranteed to be larger than _maxPacketSize
|
||||
static unsigned char bufferOut[MAX_PACKET_SIZE];
|
||||
int sizeOut = 0;
|
||||
|
||||
if (Particle::encodeParticleEditMessageDetails(type, particleID, properties, &bufferOut[0], _maxPacketSize, sizeOut)) {
|
||||
|
||||
qDebug("calling queueOctreeEditMessage(bufferOut, sizeOut=%d)... ", sizeOut);
|
||||
|
||||
queueOctreeEditMessage(type, bufferOut, sizeOut);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,14 +19,14 @@ class ParticleEditPacketSender : public OctreeEditPacketSender {
|
|||
public:
|
||||
ParticleEditPacketSender(PacketSenderNotify* notify = NULL) : OctreeEditPacketSender(notify) { }
|
||||
~ParticleEditPacketSender() { }
|
||||
|
||||
/// Send particle add message immediately
|
||||
void sendEditParticleMessage(PACKET_TYPE type, const ParticleDetail& detail);
|
||||
|
||||
/// Queues an array of several voxel edit messages. Will potentially send a pending multi-command packet. Determines
|
||||
/// which voxel-server node or nodes the packet should be sent to. Can be called even before voxel servers are known, in
|
||||
/// Send particle add message immediately
|
||||
void sendEditParticleMessage(PACKET_TYPE type, ParticleID particleID, const ParticleProperties& properties);
|
||||
|
||||
/// Queues an array of several voxel edit messages. Will potentially send a pending multi-command packet. Determines
|
||||
/// which voxel-server node or nodes the packet should be sent to. Can be called even before voxel servers are known, in
|
||||
/// which case up to MaxPendingMessages will be buffered and processed when voxel servers are known.
|
||||
void queueParticleEditMessages(PACKET_TYPE type, int numberOfDetails, ParticleDetail* details);
|
||||
void queueParticleEditMessage(PACKET_TYPE type, ParticleID particleID, const ParticleProperties& properties);
|
||||
|
||||
// My server type is the particle server
|
||||
virtual unsigned char getMyNodeType() const { return NODE_TYPE_PARTICLE_SERVER; }
|
||||
|
|
|
@ -15,7 +15,7 @@ ParticleTree::ParticleTree(bool shouldReaverage) : Octree(shouldReaverage) {
|
|||
}
|
||||
|
||||
ParticleTreeElement* ParticleTree::createNewElement(unsigned char * octalCode) const {
|
||||
ParticleTreeElement* newElement = new ParticleTreeElement(octalCode);
|
||||
ParticleTreeElement* newElement = new ParticleTreeElement(octalCode);
|
||||
return newElement;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ public:
|
|||
const Particle& searchParticle;
|
||||
bool found;
|
||||
};
|
||||
|
||||
|
||||
bool ParticleTree::findAndUpdateOperation(OctreeElement* element, void* extraData) {
|
||||
FindAndUpdateParticleArgs* args = static_cast<FindAndUpdateParticleArgs*>(extraData);
|
||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||
|
@ -51,7 +51,7 @@ void ParticleTree::storeParticle(const Particle& particle, Node* senderNode) {
|
|||
// First, look for the existing particle in the tree..
|
||||
FindAndUpdateParticleArgs args = { particle, false };
|
||||
recurseTreeWithOperation(findAndUpdateOperation, &args);
|
||||
|
||||
|
||||
// if we didn't find it in the tree, then store it...
|
||||
if (!args.found) {
|
||||
glm::vec3 position = particle.getPosition();
|
||||
|
@ -59,7 +59,7 @@ void ParticleTree::storeParticle(const Particle& particle, Node* senderNode) {
|
|||
ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size);
|
||||
|
||||
element->storeParticle(particle, senderNode);
|
||||
}
|
||||
}
|
||||
// what else do we need to do here to get reaveraging to work
|
||||
_isDirty = true;
|
||||
}
|
||||
|
@ -72,25 +72,25 @@ public:
|
|||
const Particle* closestParticle;
|
||||
float closestParticleDistance;
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool ParticleTree::findNearPointOperation(OctreeElement* element, void* extraData) {
|
||||
FindNearPointArgs* args = static_cast<FindNearPointArgs*>(extraData);
|
||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||
|
||||
glm::vec3 penetration;
|
||||
bool sphereIntersection = particleTreeElement->getAABox().findSpherePenetration(args->position,
|
||||
bool sphereIntersection = particleTreeElement->getAABox().findSpherePenetration(args->position,
|
||||
args->targetRadius, penetration);
|
||||
|
||||
// If this particleTreeElement contains the point, then search it...
|
||||
if (sphereIntersection) {
|
||||
const Particle* thisClosestParticle = particleTreeElement->getClosestParticle(args->position);
|
||||
|
||||
|
||||
// we may have gotten NULL back, meaning no particle was available
|
||||
if (thisClosestParticle) {
|
||||
glm::vec3 particlePosition = thisClosestParticle->getPosition();
|
||||
float distanceFromPointToParticle = glm::distance(particlePosition, args->position);
|
||||
|
||||
|
||||
// If we're within our target radius
|
||||
if (distanceFromPointToParticle <= args->targetRadius) {
|
||||
// we are closer than anything else we've found
|
||||
|
@ -101,11 +101,11 @@ bool ParticleTree::findNearPointOperation(OctreeElement* element, void* extraDat
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// we should be able to optimize this...
|
||||
return true; // keep searching in case children have closer particles
|
||||
}
|
||||
|
||||
|
||||
// if this element doesn't contain the point, then none of it's children can contain the point, so stop searching
|
||||
return false;
|
||||
}
|
||||
|
@ -124,9 +124,11 @@ public:
|
|||
bool found;
|
||||
const Particle* foundParticle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool ParticleTree::findByIDOperation(OctreeElement* element, void* extraData) {
|
||||
qDebug() << "ParticleTree::findByIDOperation()....";
|
||||
|
||||
FindByIDArgs* args = static_cast<FindByIDArgs*>(extraData);
|
||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||
|
||||
|
@ -134,7 +136,7 @@ bool ParticleTree::findByIDOperation(OctreeElement* element, void* extraData) {
|
|||
if (args->found) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// as the tree element if it has this particle
|
||||
const Particle* foundParticle = particleTreeElement->getParticleWithID(args->id);
|
||||
if (foundParticle) {
|
||||
|
@ -142,17 +144,23 @@ bool ParticleTree::findByIDOperation(OctreeElement* element, void* extraData) {
|
|||
args->found = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// keep looking
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const Particle* ParticleTree::findParticleByID(uint32_t id) {
|
||||
const Particle* ParticleTree::findParticleByID(uint32_t id, bool alreadyLocked) {
|
||||
FindByIDArgs args = { id, false, NULL };
|
||||
lockForRead();
|
||||
if (!alreadyLocked) {
|
||||
qDebug() << "ParticleTree::findParticleByID().... about to call lockForRead()....";
|
||||
lockForRead();
|
||||
qDebug() << "ParticleTree::findParticleByID().... after call lockForRead()....";
|
||||
}
|
||||
recurseTreeWithOperation(findByIDOperation, &args);
|
||||
unlock();
|
||||
if (!alreadyLocked) {
|
||||
unlock();
|
||||
}
|
||||
return args.foundParticle;
|
||||
}
|
||||
|
||||
|
@ -164,13 +172,21 @@ int ParticleTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* p
|
|||
// we handle these types of "edit" packets
|
||||
switch (packetType) {
|
||||
case PACKET_TYPE_PARTICLE_ADD_OR_EDIT: {
|
||||
Particle newParticle = Particle::fromEditPacket(editData, maxLength, processedBytes);
|
||||
|
||||
qDebug() << " got PACKET_TYPE_PARTICLE_ADD_OR_EDIT... ";
|
||||
|
||||
Particle newParticle = Particle::fromEditPacket(editData, maxLength, processedBytes, this);
|
||||
qDebug() << "PACKET_TYPE_PARTICLE_ADD_OR_EDIT... calling storeParticle() ";
|
||||
storeParticle(newParticle, senderNode);
|
||||
qDebug() << "PACKET_TYPE_PARTICLE_ADD_OR_EDIT... AFTER storeParticle() ";
|
||||
if (newParticle.isNewlyCreated()) {
|
||||
qDebug() << "PACKET_TYPE_PARTICLE_ADD_OR_EDIT... calling notifyNewlyCreatedParticle() ";
|
||||
notifyNewlyCreatedParticle(newParticle, senderNode);
|
||||
qDebug() << "PACKET_TYPE_PARTICLE_ADD_OR_EDIT... AFTER notifyNewlyCreatedParticle() ";
|
||||
}
|
||||
qDebug() << " DONE... PACKET_TYPE_PARTICLE_ADD_OR_EDIT... ";
|
||||
} break;
|
||||
|
||||
|
||||
case PACKET_TYPE_PARTICLE_ERASE: {
|
||||
processedBytes = 0;
|
||||
} break;
|
||||
|
@ -227,7 +243,7 @@ void ParticleTree::update() {
|
|||
|
||||
ParticleTreeUpdateArgs args = { };
|
||||
recurseTreeWithOperation(updateOperation, &args);
|
||||
|
||||
|
||||
// now add back any of the particles that moved elements....
|
||||
int movingParticles = args._movingParticles.size();
|
||||
for (int i = 0; i < movingParticles; i++) {
|
||||
|
@ -235,12 +251,12 @@ void ParticleTree::update() {
|
|||
|
||||
// if the particle is still inside our total bounds, then re-add it
|
||||
AABox treeBounds = getRoot()->getAABox();
|
||||
|
||||
|
||||
if (!shouldDie && treeBounds.contains(args._movingParticles[i].getPosition())) {
|
||||
storeParticle(args._movingParticles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// prune the tree...
|
||||
recurseTreeWithOperation(pruneOperation, NULL);
|
||||
}
|
||||
|
|
|
@ -21,14 +21,14 @@ class ParticleTree : public Octree {
|
|||
Q_OBJECT
|
||||
public:
|
||||
ParticleTree(bool shouldReaverage = false);
|
||||
|
||||
|
||||
/// Implements our type specific root element factory
|
||||
virtual ParticleTreeElement* createNewElement(unsigned char * octalCode = NULL) const;
|
||||
|
||||
|
||||
/// Type safe version of getRoot()
|
||||
ParticleTreeElement* getRoot() { return (ParticleTreeElement*)_rootNode; }
|
||||
|
||||
|
||||
|
||||
|
||||
// These methods will allow the OctreeServer to send your tree inbound edit packets of your
|
||||
// own definition. Implement these to allow your octree based server to support editing
|
||||
virtual bool getWantSVOfileVersions() const { return true; }
|
||||
|
@ -37,11 +37,11 @@ public:
|
|||
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
||||
unsigned char* editData, int maxLength, Node* senderNode);
|
||||
|
||||
virtual void update();
|
||||
virtual void update();
|
||||
|
||||
void storeParticle(const Particle& particle, Node* senderNode = NULL);
|
||||
const Particle* findClosestParticle(glm::vec3 position, float targetRadius);
|
||||
const Particle* findParticleByID(uint32_t id);
|
||||
const Particle* findParticleByID(uint32_t id, bool alreadyLocked = false);
|
||||
|
||||
void addNewlyCreatedHook(NewlyCreatedParticleHook* hook);
|
||||
void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook);
|
||||
|
@ -53,9 +53,9 @@ private:
|
|||
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);
|
||||
|
||||
|
||||
QReadWriteLock _newlyCreatedHooksLock;
|
||||
std::vector<NewlyCreatedParticleHook*> _newlyCreatedHooks;
|
||||
};
|
||||
|
|
|
@ -10,53 +10,12 @@
|
|||
|
||||
|
||||
|
||||
void ParticlesScriptingInterface::queueParticleMessage(PACKET_TYPE packetType, ParticleDetail& particleDetails) {
|
||||
getParticlePacketSender()->queueParticleEditMessages(packetType, 1, &particleDetails);
|
||||
}
|
||||
void ParticlesScriptingInterface::queueParticleMessage(PACKET_TYPE packetType,
|
||||
ParticleID particleID, const ParticleProperties& properties) {
|
||||
|
||||
ParticleID ParticlesScriptingInterface::addParticle(glm::vec3 position, float radius,
|
||||
xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, float lifetime, bool inHand, QString script) {
|
||||
qDebug() << "ParticlesScriptingInterface::queueParticleMessage()...";
|
||||
|
||||
// The application will keep track of creatorTokenID
|
||||
uint32_t creatorTokenID = Particle::getNextCreatorTokenID();
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now,
|
||||
position, radius, {color.red, color.green, color.blue }, velocity,
|
||||
gravity, damping, lifetime, inHand, script, creatorTokenID };
|
||||
|
||||
// queue the packet
|
||||
queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, addParticleDetail);
|
||||
|
||||
ParticleID id(NEW_PARTICLE, creatorTokenID, false);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
void ParticlesScriptingInterface::editParticle(ParticleID particleID, glm::vec3 position, float radius,
|
||||
xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, float lifetime, bool inHand, QString script) {
|
||||
|
||||
uint32_t actualID = particleID.id; // may not be valid... will check below..
|
||||
|
||||
// if we don't know the actual id, look it up
|
||||
if (!particleID.isKnownID) {
|
||||
actualID = Particle::getIDfromCreatorTokenID(particleID.creatorTokenID);
|
||||
|
||||
// if we couldn't fine it, then bail without changing anything...
|
||||
if (actualID == UNKNOWN_PARTICLE_ID) {
|
||||
return; // no changes...
|
||||
}
|
||||
}
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail editParticleDetail = { actualID , now,
|
||||
position, radius, {color.red, color.green, color.blue }, velocity,
|
||||
gravity, damping, lifetime, inHand, script, UNKNOWN_TOKEN };
|
||||
|
||||
// queue the packet
|
||||
queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, editParticleDetail);
|
||||
getParticlePacketSender()->queueParticleEditMessage(packetType, particleID, properties);
|
||||
}
|
||||
|
||||
ParticleID ParticlesScriptingInterface::addParticle(const ParticleProperties& properties) {
|
||||
|
@ -64,53 +23,33 @@ ParticleID ParticlesScriptingInterface::addParticle(const ParticleProperties& pr
|
|||
// The application will keep track of creatorTokenID
|
||||
uint32_t creatorTokenID = Particle::getNextCreatorTokenID();
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
uint64_t now = usecTimestampNow();
|
||||
xColor color = properties.getColor();
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now,
|
||||
properties.getPosition(), properties.getRadius(),
|
||||
{color.red, color.green, color.blue }, properties.getVelocity(),
|
||||
properties.getGravity(), properties.getDamping(), properties.getLifetime(),
|
||||
properties.getInHand(), properties.getScript(),
|
||||
creatorTokenID };
|
||||
ParticleID id(NEW_PARTICLE, creatorTokenID, false );
|
||||
|
||||
// queue the packet
|
||||
queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, addParticleDetail);
|
||||
queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, id, properties);
|
||||
|
||||
ParticleID id(NEW_PARTICLE, creatorTokenID, false );
|
||||
return id;
|
||||
}
|
||||
|
||||
void ParticlesScriptingInterface::editParticle(ParticleID particleID, const ParticleProperties& properties) {
|
||||
|
||||
uint32_t actualID = particleID.id; // may not be valid... will check below..
|
||||
qDebug() << "ParticlesScriptingInterface::editParticle() id.id=" << particleID.id << " id.creatorTokenID=" << particleID.creatorTokenID;
|
||||
|
||||
// if we don't know the actual id, look it up
|
||||
uint32_t actualID = particleID.id;
|
||||
if (!particleID.isKnownID) {
|
||||
actualID = Particle::getIDfromCreatorTokenID(particleID.creatorTokenID);
|
||||
|
||||
qDebug() << "ParticlesScriptingInterface::editParticle()... actualID: " << actualID;
|
||||
|
||||
// if we couldn't fine it, then bail without changing anything...
|
||||
// hmmm... we kind of want to bail if someone attempts to edit an unknown
|
||||
if (actualID == UNKNOWN_PARTICLE_ID) {
|
||||
return; // no changes...
|
||||
return; // bailing early
|
||||
}
|
||||
qDebug() << "ParticlesScriptingInterface::editParticle() actualID=" << actualID;
|
||||
}
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
uint64_t now = usecTimestampNow();
|
||||
particleID.id = actualID;
|
||||
particleID.isKnownID = true;
|
||||
|
||||
xColor color = properties.getColor();
|
||||
ParticleDetail editParticleDetail = { actualID, now,
|
||||
properties.getPosition(), properties.getRadius(),
|
||||
{color.red, color.green, color.blue }, properties.getVelocity(),
|
||||
properties.getGravity(), properties.getDamping(), properties.getLifetime(),
|
||||
properties.getInHand(), properties.getScript(),
|
||||
UNKNOWN_TOKEN };
|
||||
|
||||
|
||||
// queue the packet
|
||||
queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, editParticleDetail);
|
||||
queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, particleID, properties);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,19 +24,12 @@ public:
|
|||
virtual OctreeEditPacketSender* createPacketSender() { return new ParticleEditPacketSender(); }
|
||||
|
||||
public slots:
|
||||
ParticleID addParticle(glm::vec3 position, float radius,
|
||||
xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, float lifetime, bool inHand, QString script);
|
||||
|
||||
void editParticle(ParticleID particleID, glm::vec3 position, float radius,
|
||||
xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, float lifetime, bool inHand, QString script);
|
||||
|
||||
ParticleID addParticle(const ParticleProperties& properties);
|
||||
|
||||
void editParticle(ParticleID particleID, const ParticleProperties& properties);
|
||||
void deleteParticle(ParticleID particleID);
|
||||
|
||||
private:
|
||||
void queueParticleMessage(PACKET_TYPE packetType, ParticleDetail& particleDetails);
|
||||
void queueParticleMessage(PACKET_TYPE packetType, ParticleID particleID, const ParticleProperties& properties);
|
||||
|
||||
uint32_t _nextCreatorTokenID;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue