mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 18:47:28 +02:00
Merge pull request #7867 from huffman/fix/query-octree-crash
Fix crash in JurisdictionMap
This commit is contained in:
commit
cef4a49c35
9 changed files with 186 additions and 227 deletions
|
@ -3688,11 +3688,11 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
} else {
|
||||
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
|
||||
|
||||
unsigned char* rootCode = map.getRootOctalCode();
|
||||
auto rootCode = map.getRootOctalCode();
|
||||
|
||||
if (rootCode) {
|
||||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
voxelDetailsForCode(rootCode.get(), rootDetails);
|
||||
AACube serverBounds(glm::vec3(rootDetails.x * TREE_SCALE,
|
||||
rootDetails.y * TREE_SCALE,
|
||||
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
|
||||
|
@ -3752,11 +3752,11 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
} else {
|
||||
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
|
||||
|
||||
unsigned char* rootCode = map.getRootOctalCode();
|
||||
auto rootCode = map.getRootOctalCode();
|
||||
|
||||
if (rootCode) {
|
||||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
voxelDetailsForCode(rootCode.get(), rootDetails);
|
||||
AACube serverBounds(glm::vec3(rootDetails.x * TREE_SCALE,
|
||||
rootDetails.y * TREE_SCALE,
|
||||
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
|
||||
|
@ -4283,9 +4283,9 @@ void Application::nodeKilled(SharedNodePointer node) {
|
|||
return;
|
||||
}
|
||||
|
||||
unsigned char* rootCode = _entityServerJurisdictions[nodeUUID].getRootOctalCode();
|
||||
auto rootCode = _entityServerJurisdictions[nodeUUID].getRootOctalCode();
|
||||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
voxelDetailsForCode(rootCode.get(), rootDetails);
|
||||
|
||||
qCDebug(interfaceapp, "model server going away...... v[%f, %f, %f, %f]",
|
||||
(double)rootDetails.x, (double)rootDetails.y, (double)rootDetails.z, (double)rootDetails.s);
|
||||
|
@ -4404,27 +4404,33 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
|
|||
serverType = "Entity";
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
|
||||
jurisdiction->withReadLock([&] {
|
||||
if (jurisdiction->find(nodeUUID) != jurisdiction->end()) {
|
||||
found = true;
|
||||
return;
|
||||
}
|
||||
|
||||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(octreeStats.getJurisdictionRoot(), rootDetails);
|
||||
voxelDetailsForCode(octreeStats.getJurisdictionRoot().get(), rootDetails);
|
||||
|
||||
qCDebug(interfaceapp, "stats from new %s server... [%f, %f, %f, %f]",
|
||||
qPrintable(serverType),
|
||||
(double)rootDetails.x, (double)rootDetails.y, (double)rootDetails.z, (double)rootDetails.s);
|
||||
});
|
||||
// store jurisdiction details for later use
|
||||
// This is bit of fiddling is because JurisdictionMap assumes it is the owner of the values used to construct it
|
||||
// but OctreeSceneStats thinks it's just returning a reference to its contents. So we need to make a copy of the
|
||||
// details from the OctreeSceneStats to construct the JurisdictionMap
|
||||
JurisdictionMap jurisdictionMap;
|
||||
jurisdictionMap.copyContents(octreeStats.getJurisdictionRoot(), octreeStats.getJurisdictionEndNodes());
|
||||
jurisdiction->withWriteLock([&] {
|
||||
(*jurisdiction)[nodeUUID] = jurisdictionMap;
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
// store jurisdiction details for later use
|
||||
// This is bit of fiddling is because JurisdictionMap assumes it is the owner of the values used to construct it
|
||||
// but OctreeSceneStats thinks it's just returning a reference to its contents. So we need to make a copy of the
|
||||
// details from the OctreeSceneStats to construct the JurisdictionMap
|
||||
JurisdictionMap jurisdictionMap;
|
||||
jurisdictionMap.copyContents(octreeStats.getJurisdictionRoot(), octreeStats.getJurisdictionEndNodes());
|
||||
jurisdiction->withWriteLock([&] {
|
||||
(*jurisdiction)[nodeUUID] = jurisdictionMap;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return statsMessageLength;
|
||||
|
|
|
@ -433,13 +433,13 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
|
|||
}
|
||||
const JurisdictionMap& map = serverJurisdictions[nodeUUID];
|
||||
|
||||
unsigned char* rootCode = map.getRootOctalCode();
|
||||
auto rootCode = map.getRootOctalCode();
|
||||
|
||||
if (rootCode) {
|
||||
QString rootCodeHex = octalCodeToHexString(rootCode);
|
||||
QString rootCodeHex = octalCodeToHexString(rootCode.get());
|
||||
|
||||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
voxelDetailsForCode(rootCode.get(), rootDetails);
|
||||
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
|
||||
serverDetails << " jurisdiction: "
|
||||
<< qPrintable(rootCodeHex)
|
||||
|
|
|
@ -17,90 +17,11 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <NodeList.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
#include <OctalCode.h>
|
||||
|
||||
#include "OctreeLogging.h"
|
||||
#include "JurisdictionMap.h"
|
||||
|
||||
|
||||
// standard assignment
|
||||
// copy assignment
|
||||
JurisdictionMap& JurisdictionMap::operator=(const JurisdictionMap& other) {
|
||||
copyContents(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
JurisdictionMap::JurisdictionMap(const JurisdictionMap& other) : _rootOctalCode(NULL) {
|
||||
copyContents(other);
|
||||
}
|
||||
|
||||
void JurisdictionMap::copyContents(unsigned char* rootCodeIn, const std::vector<unsigned char*>& endNodesIn) {
|
||||
unsigned char* rootCode;
|
||||
std::vector<unsigned char*> endNodes;
|
||||
if (rootCodeIn) {
|
||||
size_t bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(rootCodeIn));
|
||||
rootCode = new unsigned char[bytes];
|
||||
memcpy(rootCode, rootCodeIn, bytes);
|
||||
} else {
|
||||
rootCode = new unsigned char[1];
|
||||
*rootCode = 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < endNodesIn.size(); i++) {
|
||||
if (endNodesIn[i]) {
|
||||
size_t bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodesIn[i]));
|
||||
unsigned char* endNodeCode = new unsigned char[bytes];
|
||||
memcpy(endNodeCode, endNodesIn[i], bytes);
|
||||
endNodes.push_back(endNodeCode);
|
||||
}
|
||||
}
|
||||
init(rootCode, endNodes);
|
||||
}
|
||||
|
||||
void JurisdictionMap::copyContents(const JurisdictionMap& other) {
|
||||
_nodeType = other._nodeType;
|
||||
copyContents(other._rootOctalCode, other._endNodes);
|
||||
}
|
||||
|
||||
JurisdictionMap::~JurisdictionMap() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void JurisdictionMap::clear() {
|
||||
if (_rootOctalCode) {
|
||||
delete[] _rootOctalCode;
|
||||
_rootOctalCode = NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _endNodes.size(); i++) {
|
||||
if (_endNodes[i]) {
|
||||
delete[] _endNodes[i];
|
||||
}
|
||||
}
|
||||
_endNodes.clear();
|
||||
}
|
||||
|
||||
JurisdictionMap::JurisdictionMap(NodeType_t type) : _rootOctalCode(NULL) {
|
||||
_nodeType = type;
|
||||
unsigned char* rootCode = new unsigned char[1];
|
||||
*rootCode = 0;
|
||||
|
||||
std::vector<unsigned char*> emptyEndNodes;
|
||||
init(rootCode, emptyEndNodes);
|
||||
}
|
||||
|
||||
JurisdictionMap::JurisdictionMap(const char* filename) : _rootOctalCode(NULL) {
|
||||
clear(); // clean up our own memory
|
||||
readFromFile(filename);
|
||||
}
|
||||
|
||||
JurisdictionMap::JurisdictionMap(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes)
|
||||
: _rootOctalCode(NULL) {
|
||||
init(rootOctalCode, endNodes);
|
||||
}
|
||||
|
||||
void myDebugoutputBits(unsigned char byte, bool withNewLine) {
|
||||
void myDebugOutputBits(unsigned char byte, bool withNewLine) {
|
||||
if (isalnum(byte)) {
|
||||
printf("[ %d (%c): ", byte, byte);
|
||||
} else {
|
||||
|
@ -117,13 +38,12 @@ void myDebugoutputBits(unsigned char byte, bool withNewLine) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void myDebugPrintOctalCode(const unsigned char* octalCode, bool withNewLine) {
|
||||
if (!octalCode) {
|
||||
printf("NULL");
|
||||
printf("nullptr");
|
||||
} else {
|
||||
for (size_t i = 0; i < bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(octalCode)); i++) {
|
||||
myDebugoutputBits(octalCode[i],false);
|
||||
myDebugOutputBits(octalCode[i], false);
|
||||
}
|
||||
}
|
||||
if (withNewLine) {
|
||||
|
@ -131,6 +51,55 @@ void myDebugPrintOctalCode(const unsigned char* octalCode, bool withNewLine) {
|
|||
}
|
||||
}
|
||||
|
||||
// standard assignment
|
||||
// copy assignment
|
||||
JurisdictionMap& JurisdictionMap::operator=(const JurisdictionMap& other) {
|
||||
copyContents(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
JurisdictionMap::JurisdictionMap(const JurisdictionMap& other) : _rootOctalCode(nullptr) {
|
||||
copyContents(other);
|
||||
}
|
||||
|
||||
void JurisdictionMap::copyContents(const OctalCodePtr& rootCodeIn, const OctalCodePtrList& endNodesIn) {
|
||||
OctalCodePtr rootCode = rootCodeIn;
|
||||
if (!rootCode) {
|
||||
rootCode = createOctalCodePtr(1);
|
||||
*rootCode = 0;
|
||||
}
|
||||
|
||||
OctalCodePtrList emptyEndNodes;
|
||||
init(rootCode, endNodesIn);
|
||||
}
|
||||
|
||||
void JurisdictionMap::copyContents(const JurisdictionMap& other) {
|
||||
_nodeType = other._nodeType;
|
||||
|
||||
OctalCodePtr rootOctalCode;
|
||||
OctalCodePtrList endNodes;
|
||||
|
||||
std::tie(rootOctalCode, endNodes) = other.getRootAndEndNodeOctalCodes();
|
||||
|
||||
init(rootOctalCode, endNodes);
|
||||
}
|
||||
|
||||
JurisdictionMap::~JurisdictionMap() {
|
||||
}
|
||||
|
||||
JurisdictionMap::JurisdictionMap(NodeType_t type) : _rootOctalCode(nullptr) {
|
||||
_nodeType = type;
|
||||
OctalCodePtr rootCode = createOctalCodePtr(1);
|
||||
*rootCode = 0;
|
||||
|
||||
OctalCodePtrList emptyEndNodes;
|
||||
init(rootCode, emptyEndNodes);
|
||||
}
|
||||
|
||||
JurisdictionMap::JurisdictionMap(const char* filename) : _rootOctalCode(nullptr) {
|
||||
readFromFile(filename);
|
||||
}
|
||||
|
||||
JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHexCodes) {
|
||||
|
||||
|
@ -139,8 +108,8 @@ JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHe
|
|||
|
||||
_rootOctalCode = hexStringToOctalCode(QString(rootHexCode));
|
||||
|
||||
qCDebug(octree, "JurisdictionMap::JurisdictionMap() _rootOctalCode=%p octalCode=", _rootOctalCode);
|
||||
myDebugPrintOctalCode(_rootOctalCode, true);
|
||||
qCDebug(octree, "JurisdictionMap::JurisdictionMap() _rootOctalCode=%p octalCode=", _rootOctalCode.get());
|
||||
myDebugPrintOctalCode(_rootOctalCode.get(), true);
|
||||
|
||||
QString endNodesHexStrings(endNodesHexCodes);
|
||||
QString delimiterPattern(",");
|
||||
|
@ -149,7 +118,7 @@ JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHe
|
|||
for (int i = 0; i < endNodeList.size(); i++) {
|
||||
QString endNodeHexString = endNodeList.at(i);
|
||||
|
||||
unsigned char* endNodeOctcode = hexStringToOctalCode(endNodeHexString);
|
||||
auto endNodeOctcode = hexStringToOctalCode(endNodeHexString);
|
||||
|
||||
qCDebug(octree, "JurisdictionMap::JurisdictionMap() endNodeList(%d)=%s",
|
||||
i, endNodeHexString.toLocal8Bit().constData());
|
||||
|
@ -157,15 +126,29 @@ JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHe
|
|||
//printOctalCode(endNodeOctcode);
|
||||
_endNodes.push_back(endNodeOctcode);
|
||||
|
||||
qCDebug(octree, "JurisdictionMap::JurisdictionMap() endNodeOctcode=%p octalCode=", endNodeOctcode);
|
||||
myDebugPrintOctalCode(endNodeOctcode, true);
|
||||
qCDebug(octree, "JurisdictionMap::JurisdictionMap() endNodeOctcode=%p octalCode=", endNodeOctcode.get());
|
||||
myDebugPrintOctalCode(endNodeOctcode.get(), true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<OctalCodePtr, OctalCodePtrList> JurisdictionMap::getRootAndEndNodeOctalCodes() const {
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
return std::tuple<OctalCodePtr, OctalCodePtrList>(_rootOctalCode, _endNodes);
|
||||
}
|
||||
|
||||
void JurisdictionMap::init(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes) {
|
||||
clear(); // clean up our own memory
|
||||
OctalCodePtr JurisdictionMap::getRootOctalCode() const {
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
return _rootOctalCode;
|
||||
}
|
||||
|
||||
OctalCodePtrList JurisdictionMap::getEndNodeOctalCodes() const {
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
return _endNodes;
|
||||
}
|
||||
|
||||
void JurisdictionMap::init(OctalCodePtr rootOctalCode, const OctalCodePtrList& endNodes) {
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
_rootOctalCode = rootOctalCode;
|
||||
_endNodes = endNodes;
|
||||
}
|
||||
|
@ -173,17 +156,19 @@ void JurisdictionMap::init(unsigned char* rootOctalCode, const std::vector<unsig
|
|||
JurisdictionMap::Area JurisdictionMap::isMyJurisdiction(const unsigned char* nodeOctalCode, int childIndex) const {
|
||||
// to be in our jurisdiction, we must be under the root...
|
||||
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
|
||||
// if the node is an ancestor of my root, then we return ABOVE
|
||||
if (isAncestorOf(nodeOctalCode, _rootOctalCode)) {
|
||||
if (isAncestorOf(nodeOctalCode, _rootOctalCode.get())) {
|
||||
return ABOVE;
|
||||
}
|
||||
|
||||
// otherwise...
|
||||
bool isInJurisdiction = isAncestorOf(_rootOctalCode, nodeOctalCode, childIndex);
|
||||
bool isInJurisdiction = isAncestorOf(_rootOctalCode.get(), nodeOctalCode, childIndex);
|
||||
// if we're under the root, then we can't be under any of the endpoints
|
||||
if (isInJurisdiction) {
|
||||
for (size_t i = 0; i < _endNodes.size(); i++) {
|
||||
bool isUnderEndNode = isAncestorOf(_endNodes[i], nodeOctalCode);
|
||||
bool isUnderEndNode = isAncestorOf(_endNodes[i].get(), nodeOctalCode);
|
||||
if (isUnderEndNode) {
|
||||
isInJurisdiction = false;
|
||||
break;
|
||||
|
@ -200,8 +185,9 @@ bool JurisdictionMap::readFromFile(const char* filename) {
|
|||
QString rootCode = settings.value("root","00").toString();
|
||||
qCDebug(octree) << "rootCode=" << rootCode;
|
||||
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
_rootOctalCode = hexStringToOctalCode(rootCode);
|
||||
printOctalCode(_rootOctalCode);
|
||||
printOctalCode(_rootOctalCode.get());
|
||||
|
||||
settings.beginGroup("endNodes");
|
||||
const QStringList childKeys = settings.childKeys();
|
||||
|
@ -211,8 +197,8 @@ bool JurisdictionMap::readFromFile(const char* filename) {
|
|||
values.insert(childKey, childValue);
|
||||
qCDebug(octree) << childKey << "=" << childValue;
|
||||
|
||||
unsigned char* octcode = hexStringToOctalCode(childValue);
|
||||
printOctalCode(octcode);
|
||||
auto octcode = hexStringToOctalCode(childValue);
|
||||
printOctalCode(octcode.get());
|
||||
|
||||
_endNodes.push_back(octcode);
|
||||
}
|
||||
|
@ -221,12 +207,14 @@ bool JurisdictionMap::readFromFile(const char* filename) {
|
|||
}
|
||||
|
||||
void JurisdictionMap::displayDebugDetails() const {
|
||||
QString rootNodeValue = octalCodeToHexString(_rootOctalCode);
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
|
||||
QString rootNodeValue = octalCodeToHexString(_rootOctalCode.get());
|
||||
|
||||
qCDebug(octree) << "root:" << rootNodeValue;
|
||||
|
||||
for (size_t i = 0; i < _endNodes.size(); i++) {
|
||||
QString value = octalCodeToHexString(_endNodes[i]);
|
||||
QString value = octalCodeToHexString(_endNodes[i].get());
|
||||
qCDebug(octree) << "End node[" << i << "]: " << rootNodeValue;
|
||||
}
|
||||
}
|
||||
|
@ -236,15 +224,16 @@ bool JurisdictionMap::writeToFile(const char* filename) {
|
|||
QString settingsFile(filename);
|
||||
QSettings settings(settingsFile, QSettings::IniFormat);
|
||||
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
|
||||
QString rootNodeValue = octalCodeToHexString(_rootOctalCode);
|
||||
QString rootNodeValue = octalCodeToHexString(_rootOctalCode.get());
|
||||
|
||||
settings.setValue("root", rootNodeValue);
|
||||
|
||||
settings.beginGroup("endNodes");
|
||||
for (size_t i = 0; i < _endNodes.size(); i++) {
|
||||
QString key = QString("endnode%1").arg(i);
|
||||
QString value = octalCodeToHexString(_endNodes[i]);
|
||||
QString value = octalCodeToHexString(_endNodes[i].get());
|
||||
settings.setValue(key, value);
|
||||
}
|
||||
settings.endGroup();
|
||||
|
@ -271,18 +260,19 @@ std::unique_ptr<NLPacket> JurisdictionMap::packIntoPacket() {
|
|||
packet->writePrimitive(type);
|
||||
|
||||
// add the root jurisdiction
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
if (_rootOctalCode) {
|
||||
size_t bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_rootOctalCode));
|
||||
size_t bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_rootOctalCode.get()));
|
||||
// No root or end node details to pack!
|
||||
packet->writePrimitive(bytes);
|
||||
packet->write(reinterpret_cast<char*>(_rootOctalCode), bytes);
|
||||
packet->write(reinterpret_cast<char*>(_rootOctalCode.get()), bytes);
|
||||
|
||||
// if and only if there's a root jurisdiction, also include the end nodes
|
||||
int endNodeCount = (int)_endNodes.size();
|
||||
packet->writePrimitive(endNodeCount);
|
||||
|
||||
for (int i=0; i < endNodeCount; i++) {
|
||||
unsigned char* endNodeCode = _endNodes[i];
|
||||
auto endNodeCode = _endNodes[i].get();
|
||||
size_t bytes = 0;
|
||||
if (endNodeCode) {
|
||||
bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
|
||||
|
@ -299,15 +289,17 @@ std::unique_ptr<NLPacket> JurisdictionMap::packIntoPacket() {
|
|||
}
|
||||
|
||||
int JurisdictionMap::unpackFromPacket(ReceivedMessage& message) {
|
||||
clear();
|
||||
|
||||
// read the root jurisdiction
|
||||
int bytes = 0;
|
||||
message.readPrimitive(&bytes);
|
||||
|
||||
std::lock_guard<std::mutex> lock(_octalCodeMutex);
|
||||
_rootOctalCode = nullptr;
|
||||
_endNodes.clear();
|
||||
|
||||
if (bytes > 0 && bytes <= message.getBytesLeftToRead()) {
|
||||
_rootOctalCode = new unsigned char[bytes];
|
||||
message.read(reinterpret_cast<char*>(_rootOctalCode), bytes);
|
||||
_rootOctalCode = createOctalCodePtr(bytes);
|
||||
message.read(reinterpret_cast<char*>(_rootOctalCode.get()), bytes);
|
||||
|
||||
// if and only if there's a root jurisdiction, also include the end nodes
|
||||
int endNodeCount = 0;
|
||||
|
@ -318,8 +310,8 @@ int JurisdictionMap::unpackFromPacket(ReceivedMessage& message) {
|
|||
message.readPrimitive(&bytes);
|
||||
|
||||
if (bytes <= message.getBytesLeftToRead()) {
|
||||
unsigned char* endNodeCode = new unsigned char[bytes];
|
||||
message.read(reinterpret_cast<char*>(endNodeCode), bytes);
|
||||
auto endNodeCode = createOctalCodePtr(bytes);
|
||||
message.read(reinterpret_cast<char*>(endNodeCode.get()), bytes);
|
||||
|
||||
// if the endNodeCode was 0 length then don't add it
|
||||
if (bytes > 0) {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <NLPacket.h>
|
||||
#include <Node.h>
|
||||
#include <OctalCode.h>
|
||||
|
||||
class JurisdictionMap {
|
||||
public:
|
||||
|
@ -41,8 +42,8 @@ public:
|
|||
|
||||
// application constructors
|
||||
JurisdictionMap(const char* filename);
|
||||
JurisdictionMap(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes);
|
||||
JurisdictionMap(const char* rootHextString, const char* endNodesHextString);
|
||||
|
||||
~JurisdictionMap();
|
||||
|
||||
Area isMyJurisdiction(const unsigned char* nodeOctalCode, int childIndex) const;
|
||||
|
@ -50,11 +51,12 @@ public:
|
|||
bool writeToFile(const char* filename);
|
||||
bool readFromFile(const char* filename);
|
||||
|
||||
unsigned char* getRootOctalCode() const { return _rootOctalCode; }
|
||||
unsigned char* getEndNodeOctalCode(int index) const { return _endNodes[index]; }
|
||||
int getEndNodeCount() const { return (int)_endNodes.size(); }
|
||||
// Provide an atomic way to get both the rootOctalCode and endNodeOctalCodes.
|
||||
std::tuple<OctalCodePtr, OctalCodePtrList> getRootAndEndNodeOctalCodes() const;
|
||||
OctalCodePtr getRootOctalCode() const;
|
||||
OctalCodePtrList getEndNodeOctalCodes() const;
|
||||
|
||||
void copyContents(unsigned char* rootCodeIn, const std::vector<unsigned char*>& endNodesIn);
|
||||
void copyContents(const OctalCodePtr& rootCodeIn, const OctalCodePtrList& endNodesIn);
|
||||
|
||||
int unpackFromPacket(ReceivedMessage& message);
|
||||
std::unique_ptr<NLPacket> packIntoPacket();
|
||||
|
@ -69,11 +71,11 @@ public:
|
|||
|
||||
private:
|
||||
void copyContents(const JurisdictionMap& other); // use assignment instead
|
||||
void clear();
|
||||
void init(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes);
|
||||
void init(OctalCodePtr rootOctalCode, const OctalCodePtrList& endNodes);
|
||||
|
||||
unsigned char* _rootOctalCode;
|
||||
std::vector<unsigned char*> _endNodes;
|
||||
mutable std::mutex _octalCodeMutex;
|
||||
OctalCodePtr _rootOctalCode { nullptr };
|
||||
OctalCodePtrList _endNodes;
|
||||
NodeType_t _nodeType;
|
||||
};
|
||||
|
||||
|
|
|
@ -78,12 +78,12 @@ void OctreeHeadlessViewer::queryOctree() {
|
|||
}
|
||||
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
|
||||
|
||||
unsigned char* rootCode = map.getRootOctalCode();
|
||||
auto rootCode = map.getRootOctalCode();
|
||||
if (!rootCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
voxelDetailsForCode(rootCode.get(), rootDetails);
|
||||
foundRootDetails = true;
|
||||
});
|
||||
|
||||
|
@ -146,7 +146,7 @@ void OctreeHeadlessViewer::queryOctree() {
|
|||
}
|
||||
|
||||
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
|
||||
unsigned char* rootCode = map.getRootOctalCode();
|
||||
auto rootCode = map.getRootOctalCode();
|
||||
|
||||
if (!rootCode) {
|
||||
if (wantExtraDebugging) {
|
||||
|
@ -154,7 +154,7 @@ void OctreeHeadlessViewer::queryOctree() {
|
|||
}
|
||||
return;
|
||||
}
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
voxelDetailsForCode(rootCode.get(), rootDetails);
|
||||
foundRootDetails = true;
|
||||
});
|
||||
|
||||
|
|
|
@ -110,29 +110,21 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) {
|
|||
_treesRemoved = other._treesRemoved;
|
||||
|
||||
// before copying the jurisdictions, delete any current values...
|
||||
if (_jurisdictionRoot) {
|
||||
delete[] _jurisdictionRoot;
|
||||
_jurisdictionRoot = NULL;
|
||||
}
|
||||
for (size_t i = 0; i < _jurisdictionEndNodes.size(); i++) {
|
||||
if (_jurisdictionEndNodes[i]) {
|
||||
delete[] _jurisdictionEndNodes[i];
|
||||
}
|
||||
}
|
||||
_jurisdictionRoot = nullptr;
|
||||
_jurisdictionEndNodes.clear();
|
||||
|
||||
// Now copy the values from the other
|
||||
if (other._jurisdictionRoot) {
|
||||
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(other._jurisdictionRoot));
|
||||
_jurisdictionRoot = new unsigned char[bytes];
|
||||
memcpy(_jurisdictionRoot, other._jurisdictionRoot, bytes);
|
||||
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(other._jurisdictionRoot.get()));
|
||||
_jurisdictionRoot = createOctalCodePtr(bytes);
|
||||
memcpy(_jurisdictionRoot.get(), other._jurisdictionRoot.get(), bytes);
|
||||
}
|
||||
for (size_t i = 0; i < other._jurisdictionEndNodes.size(); i++) {
|
||||
unsigned char* endNodeCode = other._jurisdictionEndNodes[i];
|
||||
auto& endNodeCode = other._jurisdictionEndNodes[i];
|
||||
if (endNodeCode) {
|
||||
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
|
||||
unsigned char* endNodeCodeCopy = new unsigned char[bytes];
|
||||
memcpy(endNodeCodeCopy, endNodeCode, bytes);
|
||||
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode.get()));
|
||||
auto endNodeCodeCopy = createOctalCodePtr(bytes);
|
||||
memcpy(endNodeCodeCopy.get(), endNodeCode.get(), bytes);
|
||||
_jurisdictionEndNodes.push_back(endNodeCodeCopy);
|
||||
}
|
||||
}
|
||||
|
@ -162,37 +154,12 @@ void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeEleme
|
|||
_isFullScene = isFullScene;
|
||||
_isMoving = isMoving;
|
||||
|
||||
if (_jurisdictionRoot) {
|
||||
delete[] _jurisdictionRoot;
|
||||
_jurisdictionRoot = NULL;
|
||||
}
|
||||
// clear existing endNodes before copying new ones...
|
||||
for (size_t i=0; i < _jurisdictionEndNodes.size(); i++) {
|
||||
if (_jurisdictionEndNodes[i]) {
|
||||
delete[] _jurisdictionEndNodes[i];
|
||||
}
|
||||
}
|
||||
_jurisdictionEndNodes.clear();
|
||||
|
||||
// setup jurisdictions
|
||||
if (jurisdictionMap) {
|
||||
unsigned char* jurisdictionRoot = jurisdictionMap->getRootOctalCode();
|
||||
if (jurisdictionRoot) {
|
||||
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(jurisdictionRoot));
|
||||
_jurisdictionRoot = new unsigned char[bytes];
|
||||
memcpy(_jurisdictionRoot, jurisdictionRoot, bytes);
|
||||
}
|
||||
|
||||
// copy new endNodes...
|
||||
for (int i = 0; i < jurisdictionMap->getEndNodeCount(); i++) {
|
||||
unsigned char* endNodeCode = jurisdictionMap->getEndNodeOctalCode(i);
|
||||
if (endNodeCode) {
|
||||
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
|
||||
unsigned char* endNodeCodeCopy = new unsigned char[bytes];
|
||||
memcpy(endNodeCodeCopy, endNodeCode, bytes);
|
||||
_jurisdictionEndNodes.push_back(endNodeCodeCopy);
|
||||
}
|
||||
}
|
||||
std::tie(_jurisdictionRoot, _jurisdictionEndNodes) = jurisdictionMap->getRootAndEndNodeOctalCodes();
|
||||
} else {
|
||||
_jurisdictionRoot = nullptr;
|
||||
_jurisdictionEndNodes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,15 +237,7 @@ void OctreeSceneStats::reset() {
|
|||
_existsInPacketBitsWritten = 0;
|
||||
_treesRemoved = 0;
|
||||
|
||||
if (_jurisdictionRoot) {
|
||||
delete[] _jurisdictionRoot;
|
||||
_jurisdictionRoot = NULL;
|
||||
}
|
||||
for (size_t i = 0; i < _jurisdictionEndNodes.size(); i++) {
|
||||
if (_jurisdictionEndNodes[i]) {
|
||||
delete[] _jurisdictionEndNodes[i];
|
||||
}
|
||||
}
|
||||
_jurisdictionRoot = nullptr;
|
||||
_jurisdictionEndNodes.clear();
|
||||
}
|
||||
|
||||
|
@ -418,9 +377,9 @@ int OctreeSceneStats::packIntoPacket() {
|
|||
// add the root jurisdiction
|
||||
if (_jurisdictionRoot) {
|
||||
// copy the
|
||||
int bytes = (int)bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_jurisdictionRoot));
|
||||
int bytes = (int)bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_jurisdictionRoot.get()));
|
||||
_statsPacket->writePrimitive(bytes);
|
||||
_statsPacket->write(reinterpret_cast<char*>(_jurisdictionRoot), bytes);
|
||||
_statsPacket->write(reinterpret_cast<char*>(_jurisdictionRoot.get()), bytes);
|
||||
|
||||
// if and only if there's a root jurisdiction, also include the end elements
|
||||
int endNodeCount = (int)_jurisdictionEndNodes.size();
|
||||
|
@ -428,10 +387,10 @@ int OctreeSceneStats::packIntoPacket() {
|
|||
_statsPacket->writePrimitive(endNodeCount);
|
||||
|
||||
for (int i=0; i < endNodeCount; i++) {
|
||||
unsigned char* endNodeCode = _jurisdictionEndNodes[i];
|
||||
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
|
||||
auto& endNodeCode = _jurisdictionEndNodes[i];
|
||||
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode.get()));
|
||||
_statsPacket->writePrimitive(bytes);
|
||||
_statsPacket->write(reinterpret_cast<char*>(endNodeCode), bytes);
|
||||
_statsPacket->write(reinterpret_cast<char*>(endNodeCode.get()), bytes);
|
||||
}
|
||||
} else {
|
||||
int bytes = 0;
|
||||
|
@ -500,17 +459,7 @@ int OctreeSceneStats::unpackFromPacket(ReceivedMessage& packet) {
|
|||
packet.readPrimitive(&_existsInPacketBitsWritten);
|
||||
packet.readPrimitive(&_treesRemoved);
|
||||
// before allocating new juridiction, clean up existing ones
|
||||
if (_jurisdictionRoot) {
|
||||
delete[] _jurisdictionRoot;
|
||||
_jurisdictionRoot = NULL;
|
||||
}
|
||||
|
||||
// clear existing endNodes before copying new ones...
|
||||
for (size_t i = 0; i < _jurisdictionEndNodes.size(); i++) {
|
||||
if (_jurisdictionEndNodes[i]) {
|
||||
delete[] _jurisdictionEndNodes[i];
|
||||
}
|
||||
}
|
||||
_jurisdictionRoot = nullptr;
|
||||
_jurisdictionEndNodes.clear();
|
||||
|
||||
// read the root jurisdiction
|
||||
|
@ -518,11 +467,11 @@ int OctreeSceneStats::unpackFromPacket(ReceivedMessage& packet) {
|
|||
packet.readPrimitive(&bytes);
|
||||
|
||||
if (bytes == 0) {
|
||||
_jurisdictionRoot = NULL;
|
||||
_jurisdictionRoot = nullptr;
|
||||
_jurisdictionEndNodes.clear();
|
||||
} else {
|
||||
_jurisdictionRoot = new unsigned char[bytes];
|
||||
packet.read(reinterpret_cast<char*>(_jurisdictionRoot), bytes);
|
||||
_jurisdictionRoot = createOctalCodePtr(bytes);
|
||||
packet.read(reinterpret_cast<char*>(_jurisdictionRoot.get()), bytes);
|
||||
|
||||
// if and only if there's a root jurisdiction, also include the end elements
|
||||
_jurisdictionEndNodes.clear();
|
||||
|
@ -535,8 +484,8 @@ int OctreeSceneStats::unpackFromPacket(ReceivedMessage& packet) {
|
|||
|
||||
packet.readPrimitive(&bytes);
|
||||
|
||||
unsigned char* endNodeCode = new unsigned char[bytes];
|
||||
packet.read(reinterpret_cast<char*>(endNodeCode), bytes);
|
||||
auto endNodeCode = createOctalCodePtr(bytes);
|
||||
packet.read(reinterpret_cast<char*>(endNodeCode.get()), bytes);
|
||||
|
||||
_jurisdictionEndNodes.push_back(endNodeCode);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "JurisdictionMap.h"
|
||||
#include "OctreePacketData.h"
|
||||
#include "SequenceNumberStats.h"
|
||||
#include "OctalCode.h"
|
||||
|
||||
#define GREENISH 0x40ff40d0
|
||||
#define YELLOWISH 0xffef40c0
|
||||
|
@ -143,10 +144,10 @@ public:
|
|||
const char* getItemValue(Item item);
|
||||
|
||||
/// Returns OctCode for root element of the jurisdiction of this particular octree server
|
||||
unsigned char* getJurisdictionRoot() const { return _jurisdictionRoot; }
|
||||
OctalCodePtr getJurisdictionRoot() const { return _jurisdictionRoot; }
|
||||
|
||||
/// Returns list of OctCodes for end elements of the jurisdiction of this particular octree server
|
||||
const std::vector<unsigned char*>& getJurisdictionEndNodes() const { return _jurisdictionEndNodes; }
|
||||
const OctalCodePtrList& getJurisdictionEndNodes() const { return _jurisdictionEndNodes; }
|
||||
|
||||
bool isMoving() const { return _isMoving; }
|
||||
bool isFullScene() const { return _isFullScene; }
|
||||
|
@ -277,8 +278,8 @@ private:
|
|||
static const int MAX_ITEM_VALUE_LENGTH = 128;
|
||||
char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH];
|
||||
|
||||
unsigned char* _jurisdictionRoot;
|
||||
std::vector<unsigned char*> _jurisdictionEndNodes;
|
||||
OctalCodePtr _jurisdictionRoot;
|
||||
std::vector<OctalCodePtr> _jurisdictionEndNodes;
|
||||
};
|
||||
|
||||
/// Map between element IDs and their reported OctreeSceneStats. Typically used by classes that need to know which elements sent
|
||||
|
|
|
@ -304,14 +304,18 @@ bool isAncestorOf(const unsigned char* possibleAncestor, const unsigned char* po
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned char* hexStringToOctalCode(const QString& input) {
|
||||
OctalCodePtr createOctalCodePtr(size_t size) {
|
||||
return OctalCodePtr(new unsigned char[size], std::default_delete<unsigned char[]>());
|
||||
}
|
||||
|
||||
OctalCodePtr hexStringToOctalCode(const QString& input) {
|
||||
const int HEX_NUMBER_BASE = 16;
|
||||
const int HEX_BYTE_SIZE = 2;
|
||||
int stringIndex = 0;
|
||||
int byteArrayIndex = 0;
|
||||
|
||||
// allocate byte array based on half of string length
|
||||
unsigned char* bytes = new unsigned char[(input.length()) / HEX_BYTE_SIZE];
|
||||
auto bytes = createOctalCodePtr(input.length() / HEX_BYTE_SIZE);
|
||||
|
||||
// loop through the string - 2 bytes at a time converting
|
||||
// it to decimal equivalent and store in byte array
|
||||
|
@ -321,15 +325,14 @@ unsigned char* hexStringToOctalCode(const QString& input) {
|
|||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
bytes[byteArrayIndex] = (unsigned char)value;
|
||||
bytes.get()[byteArrayIndex] = (unsigned char)value;
|
||||
stringIndex += HEX_BYTE_SIZE;
|
||||
byteArrayIndex++;
|
||||
}
|
||||
|
||||
// something went wrong
|
||||
if (!ok) {
|
||||
delete[] bytes;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
#ifndef hifi_OctalCode_h
|
||||
#define hifi_OctalCode_h
|
||||
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
|
||||
#include <memory>
|
||||
|
||||
const int BITS_IN_OCTAL = 3;
|
||||
const int NUMBER_OF_COLORS = 3; // RGB!
|
||||
const int SIZE_OF_COLOR_DATA = NUMBER_OF_COLORS * sizeof(unsigned char); // size in bytes
|
||||
|
@ -22,6 +24,9 @@ const int RED_INDEX = 0;
|
|||
const int GREEN_INDEX = 1;
|
||||
const int BLUE_INDEX = 2;
|
||||
|
||||
using OctalCodePtr = std::shared_ptr<unsigned char>;
|
||||
using OctalCodePtrList = std::vector<OctalCodePtr>;
|
||||
|
||||
void printOctalCode(const unsigned char* octalCode);
|
||||
size_t bytesRequiredForCodeLength(unsigned char threeBitCodes);
|
||||
int branchIndexWithDescendant(const unsigned char* ancestorOctalCode, const unsigned char* descendantOctalCode);
|
||||
|
@ -57,7 +62,8 @@ typedef enum {
|
|||
|
||||
OctalCodeComparison compareOctalCodes(const unsigned char* code1, const unsigned char* code2);
|
||||
|
||||
OctalCodePtr createOctalCodePtr(size_t size);
|
||||
QString octalCodeToHexString(const unsigned char* octalCode);
|
||||
unsigned char* hexStringToOctalCode(const QString& input);
|
||||
OctalCodePtr hexStringToOctalCode(const QString& input);
|
||||
|
||||
#endif // hifi_OctalCode_h
|
||||
|
|
Loading…
Reference in a new issue