int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { unsigned char* bufferStart = destinationBuffer; // back a boolean (cut to 1 byte) to designate if this query uses the sent view frustum memcpy(destinationBuffer, &_usesFrustum, sizeof(_usesFrustum)); destinationBuffer += sizeof(_usesFrustum); if (_usesFrustum) { // TODO: DRY this up to a shared method // that can pack any type given the number of bytes // and return the number of bytes to push the pointer // camera details memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition)); destinationBuffer += sizeof(_cameraPosition); destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov); destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio); destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip); destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); destinationBuffer += sizeof(_cameraEyeOffsetPosition); } // desired Max Octree PPS memcpy(destinationBuffer, &_maxQueryPPS, sizeof(_maxQueryPPS)); destinationBuffer += sizeof(_maxQueryPPS); // desired voxelSizeScale memcpy(destinationBuffer, &_octreeElementSizeScale, sizeof(_octreeElementSizeScale)); destinationBuffer += sizeof(_octreeElementSizeScale); // desired boundaryLevelAdjust memcpy(destinationBuffer, &_boundaryLevelAdjust, sizeof(_boundaryLevelAdjust)); destinationBuffer += sizeof(_boundaryLevelAdjust); memcpy(destinationBuffer, &_cameraCenterRadius, sizeof(_cameraCenterRadius)); destinationBuffer += sizeof(_cameraCenterRadius); // create a QByteArray that holds the binary representation of the JSON parameters QByteArray binaryParametersDocument; if (!_jsonParameters.isEmpty()) { binaryParametersDocument = QJsonDocument(_jsonParameters).toBinaryData(); } // write the size of the JSON parameters uint16_t binaryParametersBytes = binaryParametersDocument.size(); memcpy(destinationBuffer, &binaryParametersBytes, sizeof(binaryParametersBytes)); destinationBuffer += sizeof(binaryParametersBytes); // pack the binary JSON parameters // NOTE: for now we assume that the filters that will be set are all small enough that we will not have a packet > MTU if (binaryParametersDocument.size() > 0) { memcpy(destinationBuffer, binaryParametersDocument.data(), binaryParametersBytes); destinationBuffer += binaryParametersBytes; } return destinationBuffer - bufferStart; }
int Referential::pack(unsigned char* destinationBuffer) const { unsigned char* startPosition = destinationBuffer; *destinationBuffer++ = (unsigned char)_type; memcpy(destinationBuffer, &_version, sizeof(_version)); destinationBuffer += sizeof(_version); destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, _translation, 0); destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _rotation); destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, _scale, 0); return destinationBuffer - startPosition; }
bool OctreePacketData::appendValue(const glm::quat& value) { const size_t VALUES_PER_QUAT = 4; const size_t PACKED_QUAT_SIZE = sizeof(uint16_t) * VALUES_PER_QUAT; unsigned char data[PACKED_QUAT_SIZE]; int length = packOrientationQuatToBytes(data, value); bool success = append(data, length); if (success) { _bytesOfValues += length; _totalBytesOfValues += length; } return success; }
int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { unsigned char* bufferStart = destinationBuffer; // TODO: DRY this up to a shared method // that can pack any type given the number of bytes // and return the number of bytes to push the pointer // camera details memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition)); destinationBuffer += sizeof(_cameraPosition); destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov); destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio); destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip); destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); destinationBuffer += sizeof(_cameraEyeOffsetPosition); // bitMask of less than byte wide items unsigned char bitItems = 0; // NOTE: we need to keep these here for new clients to talk to old servers. After we know that the clients and // servers and clients have all been updated we could remove these bits. New servers will always force these // features on old clients even if they don't ask for them. (which old clients will properly handle). New clients // will always ask for these so that old servers will use these features. setAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); setAtBit(bitItems, WANT_COLOR_AT_BIT); setAtBit(bitItems, WANT_DELTA_AT_BIT); setAtBit(bitItems, WANT_COMPRESSION); *destinationBuffer++ = bitItems; // desired Max Octree PPS memcpy(destinationBuffer, &_maxQueryPPS, sizeof(_maxQueryPPS)); destinationBuffer += sizeof(_maxQueryPPS); // desired voxelSizeScale memcpy(destinationBuffer, &_octreeElementSizeScale, sizeof(_octreeElementSizeScale)); destinationBuffer += sizeof(_octreeElementSizeScale); // desired boundaryLevelAdjust memcpy(destinationBuffer, &_boundaryLevelAdjust, sizeof(_boundaryLevelAdjust)); destinationBuffer += sizeof(_boundaryLevelAdjust); memcpy(destinationBuffer, &_cameraCenterRadius, sizeof(_cameraCenterRadius)); destinationBuffer += sizeof(_cameraCenterRadius); return destinationBuffer - bufferStart; }
int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { unsigned char* bufferStart = destinationBuffer; // TODO: DRY this up to a shared method // that can pack any type given the number of bytes // and return the number of bytes to push the pointer // camera details memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition)); destinationBuffer += sizeof(_cameraPosition); destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov); destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio); destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip); destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); destinationBuffer += sizeof(_cameraEyeOffsetPosition); // bitMask of less than byte wide items unsigned char bitItems = 0; if (_wantLowResMoving) { setAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); } if (_wantColor) { setAtBit(bitItems, WANT_COLOR_AT_BIT); } if (_wantDelta) { setAtBit(bitItems, WANT_DELTA_AT_BIT); } if (_wantOcclusionCulling) { setAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT); } if (_wantCompression) { setAtBit(bitItems, WANT_COMPRESSION); } *destinationBuffer++ = bitItems; // desired Max Octree PPS memcpy(destinationBuffer, &_maxOctreePPS, sizeof(_maxOctreePPS)); destinationBuffer += sizeof(_maxOctreePPS); // desired voxelSizeScale memcpy(destinationBuffer, &_octreeElementSizeScale, sizeof(_octreeElementSizeScale)); destinationBuffer += sizeof(_octreeElementSizeScale); // desired boundaryLevelAdjust memcpy(destinationBuffer, &_boundaryLevelAdjust, sizeof(_boundaryLevelAdjust)); destinationBuffer += sizeof(_boundaryLevelAdjust); return destinationBuffer - bufferStart; }
bool OctreePacketData::appendValue(const QVector<glm::quat>& value) { uint16_t qVecSize = value.size(); bool success = appendValue(qVecSize); if (success) { QByteArray dataByteArray(udt::MAX_PACKET_SIZE, 0); unsigned char* start = reinterpret_cast<unsigned char*>(dataByteArray.data()); unsigned char* destinationBuffer = start; for (int index = 0; index < value.size(); index++) { destinationBuffer += packOrientationQuatToBytes(destinationBuffer, value[index]); } int quatsSize = destinationBuffer - start; success = append(start, quatsSize); if (success) { _bytesOfValues += quatsSize; _totalBytesOfValues += quatsSize; } } return success; }
bool ModelItem::encodeModelEditMessageDetails(PacketType command, ModelItemID id, const ModelItemProperties& properties, unsigned char* bufferOut, int sizeIn, int& sizeOut) { bool success = true; // assume the best unsigned char* copyAt = bufferOut; sizeOut = 0; // get the octal code for the modelItem // this could be a problem if the caller doesn't include position.... glm::vec3 rootPosition(0); float rootScale = 0.5f; unsigned char* octcode = pointToOctalCode(rootPosition.x, rootPosition.y, rootPosition.z, rootScale); // TODO: Consider this old code... including the correct octree for where the modelItem will go matters for // modelItem servers with different jurisdictions, but for now, we'll send everything to the root, since the // tree does the right thing... // //unsigned char* octcode = pointToOctalCode(details[i].position.x, details[i].position.y, // details[i].position.z, details[i].radius); int octets = numberOfThreeBitSectionsInCode(octcode); int lengthOfOctcode = bytesRequiredForCodeLength(octets); // add it to our message memcpy(copyAt, octcode, lengthOfOctcode); copyAt += lengthOfOctcode; sizeOut += lengthOfOctcode; // Now add our edit content details... bool isNewModelItem = (id.id == NEW_MODEL); // id memcpy(copyAt, &id.id, sizeof(id.id)); copyAt += sizeof(id.id); sizeOut += sizeof(id.id); // special case for handling "new" modelItems if (isNewModelItem) { // If this is a NEW_MODEL, then we assume that there's an additional uint32_t creatorToken, that // we want to send back to the creator as an map to the actual id memcpy(copyAt, &id.creatorTokenID, sizeof(id.creatorTokenID)); copyAt += sizeof(id.creatorTokenID); sizeOut += sizeof(id.creatorTokenID); } // lastEdited quint64 lastEdited = properties.getLastEdited(); memcpy(copyAt, &lastEdited, sizeof(lastEdited)); copyAt += sizeof(lastEdited); sizeOut += sizeof(lastEdited); // For new modelItems, all remaining items are mandatory, for an edited modelItem, All of the remaining items are // optional, and may or may not be included based on their included values in the properties included bits uint16_t packetContainsBits = properties.getChangedBits(); if (!isNewModelItem) { memcpy(copyAt, &packetContainsBits, sizeof(packetContainsBits)); copyAt += sizeof(packetContainsBits); sizeOut += sizeof(packetContainsBits); } // radius if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_RADIUS) == MODEL_PACKET_CONTAINS_RADIUS)) { float radius = properties.getRadius() / (float) TREE_SCALE; memcpy(copyAt, &radius, sizeof(radius)); copyAt += sizeof(radius); sizeOut += sizeof(radius); } // position if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_POSITION) == MODEL_PACKET_CONTAINS_POSITION)) { glm::vec3 position = properties.getPosition() / (float)TREE_SCALE; memcpy(copyAt, &position, sizeof(position)); copyAt += sizeof(position); sizeOut += sizeof(position); } // color if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_COLOR) == MODEL_PACKET_CONTAINS_COLOR)) { rgbColor color = { properties.getColor().red, properties.getColor().green, properties.getColor().blue }; memcpy(copyAt, color, sizeof(color)); copyAt += sizeof(color); sizeOut += sizeof(color); } // shoulDie if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_SHOULDDIE) == MODEL_PACKET_CONTAINS_SHOULDDIE)) { bool shouldDie = properties.getShouldDie(); memcpy(copyAt, &shouldDie, sizeof(shouldDie)); copyAt += sizeof(shouldDie); sizeOut += sizeof(shouldDie); } // modelURL if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_MODEL_URL) == MODEL_PACKET_CONTAINS_MODEL_URL)) { uint16_t urlLength = properties.getModelURL().size() + 1; memcpy(copyAt, &urlLength, sizeof(urlLength)); copyAt += sizeof(urlLength); sizeOut += sizeof(urlLength); memcpy(copyAt, qPrintable(properties.getModelURL()), urlLength); copyAt += urlLength; sizeOut += urlLength; } // modelRotation if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_MODEL_ROTATION) == MODEL_PACKET_CONTAINS_MODEL_ROTATION)) { int bytes = packOrientationQuatToBytes(copyAt, properties.getModelRotation()); copyAt += bytes; sizeOut += bytes; } // animationURL if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_ANIMATION_URL) == MODEL_PACKET_CONTAINS_ANIMATION_URL)) { uint16_t urlLength = properties.getAnimationURL().size() + 1; memcpy(copyAt, &urlLength, sizeof(urlLength)); copyAt += sizeof(urlLength); sizeOut += sizeof(urlLength); memcpy(copyAt, qPrintable(properties.getAnimationURL()), urlLength); copyAt += urlLength; sizeOut += urlLength; } // animationIsPlaying if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_ANIMATION_PLAYING) == MODEL_PACKET_CONTAINS_ANIMATION_PLAYING)) { bool animationIsPlaying = properties.getAnimationIsPlaying(); memcpy(copyAt, &animationIsPlaying, sizeof(animationIsPlaying)); copyAt += sizeof(animationIsPlaying); sizeOut += sizeof(animationIsPlaying); } // animationFrameIndex if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_ANIMATION_FRAME) == MODEL_PACKET_CONTAINS_ANIMATION_FRAME)) { float animationFrameIndex = properties.getAnimationFrameIndex(); memcpy(copyAt, &animationFrameIndex, sizeof(animationFrameIndex)); copyAt += sizeof(animationFrameIndex); sizeOut += sizeof(animationFrameIndex); } // animationFPS if (isNewModelItem || ((packetContainsBits & MODEL_PACKET_CONTAINS_ANIMATION_FPS) == MODEL_PACKET_CONTAINS_ANIMATION_FPS)) { float animationFPS = properties.getAnimationFPS(); memcpy(copyAt, &animationFPS, sizeof(animationFPS)); copyAt += sizeof(animationFPS); sizeOut += sizeof(animationFPS); } bool wantDebugging = false; if (wantDebugging) { qDebug("encodeModelItemEditMessageDetails()...."); qDebug("ModelItem id :%u", id.id); qDebug(" nextID:%u", _nextID); } // cleanup delete[] octcode; return success; }