From 23ef5b5404bc295f68723aa558f97a2fadf65e6a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 10:22:19 -0700 Subject: [PATCH 01/10] added some comments --- libraries/octree/src/Octree.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 3ec1871023..cbdc4753dc 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -602,7 +602,6 @@ public: bool findRayIntersectionOp(OctreeElement* element, void* extraData) { RayArgs* args = static_cast(extraData); - bool keepSearching = true; if (element->findRayIntersection(args->origin, args->direction, keepSearching, args->element, args->distance, args->face, args->intersectedObject)) { @@ -1336,14 +1335,23 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, } } - // write the color data... + // write the child element data... if (continueThisLevel && params.includeColor) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { if (oneAtBit(childrenColoredBits, i)) { OctreeElement* childElement = element->getChildAtIndex(i); if (childElement) { + int bytesBeforeChild = packetData->getUncompressedSize(); + + // TODO: we want to support the ability for a childElement to "partially" write it's data. + // for example, consider the case of the model server where the entire contents of the + // element may be larger than can fit in a single MTU/packetData. In this case, we want + // to allow the appendElementData() to respond that it produced partial data, which should be + // written, but that the childElement needs to be reprocessed in an additional pass or passes + // to be completed. In the case that an element was partially written, we need to continueThisLevel = childElement->appendElementData(packetData, params); + int bytesAfterChild = packetData->getUncompressedSize(); if (!continueThisLevel) { From 8d4a8f7e67aa1ee28a1f33e1058a5de9b66afd83 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 10:22:49 -0700 Subject: [PATCH 02/10] first cut at partial model elements --- libraries/models/src/ModelTreeElement.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index b87557d073..3fc2537dc7 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -55,6 +55,7 @@ bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBit // write our models out... first determine which of the models are in view based on our params uint16_t numberOfModels = 0; + uint16_t actualNumberOfModels = 0; QVector indexesOfModelsToInclude; for (uint16_t i = 0; i < _modelItems->size(); i++) { @@ -72,17 +73,35 @@ bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBit } } + int numberOfModelsOffset = packetData->getUncompressedByteOffset(); success = packetData->appendValue(numberOfModels); if (success) { foreach (uint16_t i, indexesOfModelsToInclude) { const ModelItem& model = (*_modelItems)[i]; + + LevelDetails modelLevel = packetData->startLevel(); + success = model.appendModelData(packetData); + + if (success) { + packetData->endLevel(modelLevel); + actualNumberOfModels++; + } if (!success) { + qDebug() << "ModelTreeElement::appendElementData()... model i=" << i << "didn't fit..."; + packetData->discardLevel(modelLevel); break; } } } + + if (!success) { + qDebug() << "ModelTreeElement::appendElementData()... updatePriorBytes()... actualNumberOfModels=" << actualNumberOfModels; + success = packetData->updatePriorBytes(numberOfModelsOffset, + (const unsigned char*)&actualNumberOfModels, sizeof(actualNumberOfModels)); + } + return success; } @@ -433,6 +452,7 @@ int ModelTreeElement::readElementDataFromBuffer(const unsigned char* data, int b if (bytesLeftToRead >= (int)sizeof(numberOfModels)) { // read our models in.... numberOfModels = *(uint16_t*)dataAt; + dataAt += sizeof(numberOfModels); bytesLeftToRead -= (int)sizeof(numberOfModels); bytesRead += sizeof(numberOfModels); From b48c70a7f7d3a5c1acf3dacfea7906d614a695fa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 10:23:50 -0700 Subject: [PATCH 03/10] first cut at PropertyFlags template class --- libraries/shared/src/PropertyFlags.cpp | 11 ++ libraries/shared/src/PropertyFlags.h | 245 +++++++++++++++++++++++++ 2 files changed, 256 insertions(+) create mode 100644 libraries/shared/src/PropertyFlags.cpp create mode 100644 libraries/shared/src/PropertyFlags.h diff --git a/libraries/shared/src/PropertyFlags.cpp b/libraries/shared/src/PropertyFlags.cpp new file mode 100644 index 0000000000..8413ce8172 --- /dev/null +++ b/libraries/shared/src/PropertyFlags.cpp @@ -0,0 +1,11 @@ +// +// PropertyFlags.cpp +// libraries/shared/src +// +// Created by Brad Hefta-Gaub on 6/3/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + diff --git a/libraries/shared/src/PropertyFlags.h b/libraries/shared/src/PropertyFlags.h new file mode 100644 index 0000000000..b5758f2206 --- /dev/null +++ b/libraries/shared/src/PropertyFlags.h @@ -0,0 +1,245 @@ +// +// PropertyFlags.h +// libraries/shared/src +// +// Created by Brad Hefta-Gaub on 6/3/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// +// TODO: +// * implement decode +// * add operators + +#ifndef hifi_PropertyFlags_h +#define hifi_PropertyFlags_h + +#include +#include + +templateclass PropertyFlags { +public: + typedef Enum enum_type; + inline PropertyFlags() : _maxFlag(-1) { }; + inline PropertyFlags(const PropertyFlags& other) : _flags(other._flags), _maxFlag(other._maxFlag) {} + inline PropertyFlags(Enum flag) : _maxFlag(-1) { setHasProperty(flag); } + + void clear() { _flags.clear(); _maxFlag = -1; } + + void setHasProperty(Enum flag, bool value = true); + bool getHasProperty(Enum flag); + QByteArray encode(); + void decode(const QByteArray& fromEncoded); + + + inline PropertyFlags& operator=(const PropertyFlags &other) { _flags = other._flags; _maxFlag = other._maxFlag; return *this; } + + inline PropertyFlags& operator|=(PropertyFlags other) { _flags |= other._flags; _maxFlag = max(_maxFlag, other._maxFlag); return *this; } + inline PropertyFlags& operator|=(Enum flag) { PropertyFlags other(flag); _flags |= other._flags; _maxFlag = max(_maxFlag, other._maxFlag); return *this; } + + inline PropertyFlags& operator&=(PropertyFlags other) { _flags &= other._flags; shinkIfNeeded(); return *this; } + inline PropertyFlags& operator&=(Enum flag) { PropertyFlags other(flag); _flags &= other._flags; shinkIfNeeded(); return *this; } + + inline PropertyFlags& operator^=(PropertyFlags other) { _flags ^= other._flags; shinkIfNeeded(); return *this; } + inline PropertyFlags& operator^=(Enum flag) { PropertyFlags other(flag); _flags ^= other._flags; shinkIfNeeded(); return *this; } + + + inline PropertyFlags operator|(PropertyFlags other) const { PropertyFlags result(*this); result |= other; return result; } + inline PropertyFlags operator|(Enum flag) const { PropertyFlags result(*this); PropertyFlags other(flag); result |= other; return result; } + + inline PropertyFlags operator^(PropertyFlags other) const { PropertyFlags result(*this); result ^= other; return result; } + inline PropertyFlags operator^(Enum flag) const { PropertyFlags result(*this); PropertyFlags other(flag); result ^= other; return result; } + + inline PropertyFlags operator&(PropertyFlags other) const { PropertyFlags result(*this); result &= other; return result; } + inline PropertyFlags operator&(Enum flag) const { PropertyFlags result(*this); PropertyFlags other(flag); result &= other; return result; } + + /* + inline PropertyFlags operator~() const { return PropertyFlags(Enum(~i)); } + inline bool operator!() const { return !i; } + */ + + +private: + void shinkIfNeeded(); + + QBitArray _flags; + int _maxFlag; +}; + + +template inline void PropertyFlags::setHasProperty(Enum flag, bool value) { + if (flag > _maxFlag) { + if (value) { + _maxFlag = flag; + _flags.resize(_maxFlag + 1); + } else { + return; // bail early, we're setting a flag outside of our current _maxFlag to false, which is already the default + } + } + qDebug() << "_flags.setBit("< inline bool PropertyFlags::getHasProperty(Enum flag) { + if (flag > _maxFlag) { + return false; + } + return _flags.testBit(flag); +} + +const int BITS_PER_BYTE = 8; + +template inline QByteArray PropertyFlags::encode() { + const bool debug = false; + QByteArray output; + + outputBufferBits((const unsigned char*)output.constData(), output.size()); + + if (debug) qDebug() << "PropertyFlags::encode()"; + + // we should size the array to the correct size. + int lengthInBytes = (_maxFlag / (BITS_PER_BYTE - 1)) + 1; + + if (debug) qDebug() << " lengthInBytes=" << lengthInBytes; + + output.fill(0, lengthInBytes); + + if (debug) outputBufferBits((const unsigned char*)output.constData(), output.size()); + + // next pack the number of header bits in, the first N-1 to be set to 1, the last to be set to 0 + for(int i = 0; i < lengthInBytes; i++) { + int outputIndex = i; + if (debug) qDebug() << "outputIndex:" << outputIndex; + int bitValue = (i < (lengthInBytes - 1) ? 1 : 0); + + if (debug) qDebug() << " length code bit["<< outputIndex << "]=" << bitValue; + + char original = output.at(outputIndex / BITS_PER_BYTE); + int shiftBy = BITS_PER_BYTE - ((outputIndex % BITS_PER_BYTE) + 1); + char thisBit = ( bitValue << shiftBy); + + if (debug) { + qDebug() << "bitValue:" << bitValue; + qDebug() << "shiftBy:" << shiftBy; + qDebug() << "original:"; + outputBits(original); + + qDebug() << "thisBit:"; + outputBits(thisBit); + } + + output[i / BITS_PER_BYTE] = (original | thisBit); + } + + if (debug) outputBufferBits((const unsigned char*)output.constData(), output.size()); + + // finally pack the the actual bits from the bit array + for(int i = lengthInBytes; i < (lengthInBytes + _maxFlag + 1); i++) { + int flagIndex = i - lengthInBytes; + int outputIndex = i; + if (debug) qDebug() << "flagIndex:" << flagIndex; + if (debug) qDebug() << "outputIndex:" << outputIndex; + + + int bitValue = ( _flags[flagIndex] ? 1 : 0); + + if (debug) qDebug() << " encode bit["< inline void PropertyFlags::decode(const QByteArray& fromEncoded) { +} + +template inline void PropertyFlags::shinkIfNeeded() { + bool maxFlagWas = _maxFlag; + while (_maxFlag >= 0) { + if (_flags.testBit(_maxFlag)) { + break; + } + _maxFlag--; + } + if (maxFlagWas != _maxFlag) { + _flags.resize(_maxFlag + 1); + } +} + + + +/*** + +BitArr.resize(8*byteArr.count()); +for(int i=0; i +class QFlags +{ + typedef void **Zero; + int i; +public: + typedef Enum enum_type; + Q_DECL_CONSTEXPR inline QFlags(const QFlags &f) : i(f.i) {} + Q_DECL_CONSTEXPR inline QFlags(Enum f) : i(f) {} + Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {} + inline QFlags(QFlag f) : i(f) {} + + inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; } + inline QFlags &operator&=(int mask) { i &= mask; return *this; } + inline QFlags &operator&=(uint mask) { i &= mask; return *this; } + inline QFlags &operator|=(QFlags f) { i |= f.i; return *this; } + inline QFlags &operator|=(Enum f) { i |= f; return *this; } + inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; } + inline QFlags &operator^=(Enum f) { i ^= f; return *this; } + + Q_DECL_CONSTEXPR inline operator int() const { return i; } + + Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); } + Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); } + Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(Enum(i ^ f.i)); } + Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(Enum(i ^ f)); } + Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(Enum(i & mask)); } + Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(Enum(i & mask)); } + Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(Enum(i & f)); } + Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(Enum(~i)); } + + Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } + + inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); } +}; + +***/ + +#endif // hifi_PropertyFlags_h + From 2b851453255ed6ff8e42e9d27db88ac7d60ef6db Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 11:41:09 -0700 Subject: [PATCH 04/10] added test suite for PropertyFlags, latest work on PropertyFlags --- libraries/shared/src/PropertyFlags.h | 190 ++++++++++++++++++++++++--- tests/octree/CMakeLists.txt | 39 ++++++ tests/octree/src/OctreeTests.cpp | 143 ++++++++++++++++++++ tests/octree/src/OctreeTests.h | 22 ++++ tests/octree/src/main.cpp | 16 +++ 5 files changed, 392 insertions(+), 18 deletions(-) create mode 100644 tests/octree/CMakeLists.txt create mode 100644 tests/octree/src/OctreeTests.cpp create mode 100644 tests/octree/src/OctreeTests.h create mode 100644 tests/octree/src/main.cpp diff --git a/libraries/shared/src/PropertyFlags.h b/libraries/shared/src/PropertyFlags.h index b5758f2206..d8131d0c75 100644 --- a/libraries/shared/src/PropertyFlags.h +++ b/libraries/shared/src/PropertyFlags.h @@ -11,49 +11,65 @@ // // TODO: // * implement decode -// * add operators +// * more operators, operator==, operator!=, operator!, operator~ +// * iterator to enumerate the set values? +// * operator<<(enum) to work similar to set #ifndef hifi_PropertyFlags_h #define hifi_PropertyFlags_h +#include +#include + #include #include +#include + templateclass PropertyFlags { public: typedef Enum enum_type; - inline PropertyFlags() : _maxFlag(-1) { }; + inline PropertyFlags() : _maxFlag(INT_MIN), _minFlag(INT_MAX) { }; inline PropertyFlags(const PropertyFlags& other) : _flags(other._flags), _maxFlag(other._maxFlag) {} - inline PropertyFlags(Enum flag) : _maxFlag(-1) { setHasProperty(flag); } + inline PropertyFlags(Enum flag) : _maxFlag(INT_MIN), _minFlag(INT_MAX) { setHasProperty(flag); } - void clear() { _flags.clear(); _maxFlag = -1; } + void clear() { _flags.clear(); _maxFlag = INT_MIN; _minFlag = INT_MAX; } + Enum firstFlag() const { return _minFlag; } + Enum lastFlag() const { return _maxFlag; } + void setHasProperty(Enum flag, bool value = true); bool getHasProperty(Enum flag); QByteArray encode(); void decode(const QByteArray& fromEncoded); - inline PropertyFlags& operator=(const PropertyFlags &other) { _flags = other._flags; _maxFlag = other._maxFlag; return *this; } + PropertyFlags& operator=(const PropertyFlags &other); - inline PropertyFlags& operator|=(PropertyFlags other) { _flags |= other._flags; _maxFlag = max(_maxFlag, other._maxFlag); return *this; } - inline PropertyFlags& operator|=(Enum flag) { PropertyFlags other(flag); _flags |= other._flags; _maxFlag = max(_maxFlag, other._maxFlag); return *this; } + PropertyFlags& operator|=(PropertyFlags other); + PropertyFlags& operator|=(Enum flag); - inline PropertyFlags& operator&=(PropertyFlags other) { _flags &= other._flags; shinkIfNeeded(); return *this; } - inline PropertyFlags& operator&=(Enum flag) { PropertyFlags other(flag); _flags &= other._flags; shinkIfNeeded(); return *this; } + PropertyFlags& operator&=(PropertyFlags other); + PropertyFlags& operator&=(Enum flag); - inline PropertyFlags& operator^=(PropertyFlags other) { _flags ^= other._flags; shinkIfNeeded(); return *this; } - inline PropertyFlags& operator^=(Enum flag) { PropertyFlags other(flag); _flags ^= other._flags; shinkIfNeeded(); return *this; } + PropertyFlags& operator^=(PropertyFlags other); + PropertyFlags& operator^=(Enum flag); + PropertyFlags& operator-=(PropertyFlags other); + PropertyFlags& operator-=(Enum flag); - inline PropertyFlags operator|(PropertyFlags other) const { PropertyFlags result(*this); result |= other; return result; } - inline PropertyFlags operator|(Enum flag) const { PropertyFlags result(*this); PropertyFlags other(flag); result |= other; return result; } + PropertyFlags operator|(PropertyFlags other) const; + PropertyFlags operator|(Enum flag) const; - inline PropertyFlags operator^(PropertyFlags other) const { PropertyFlags result(*this); result ^= other; return result; } - inline PropertyFlags operator^(Enum flag) const { PropertyFlags result(*this); PropertyFlags other(flag); result ^= other; return result; } + PropertyFlags operator&(PropertyFlags other) const; + PropertyFlags operator&(Enum flag) const; + + PropertyFlags operator^(PropertyFlags other) const; + PropertyFlags operator^(Enum flag) const; + + PropertyFlags operator-(PropertyFlags other) const; + PropertyFlags operator-(Enum flag) const; - inline PropertyFlags operator&(PropertyFlags other) const { PropertyFlags result(*this); result &= other; return result; } - inline PropertyFlags operator&(Enum flag) const { PropertyFlags result(*this); PropertyFlags other(flag); result &= other; return result; } /* inline PropertyFlags operator~() const { return PropertyFlags(Enum(~i)); } @@ -63,13 +79,21 @@ public: private: void shinkIfNeeded(); + void debugDumpBits(); QBitArray _flags; int _maxFlag; + int _minFlag; }; template inline void PropertyFlags::setHasProperty(Enum flag, bool value) { + // keep track of our min flag + if (flag < _minFlag) { + if (value) { + _minFlag = flag; + } + } if (flag > _maxFlag) { if (value) { _maxFlag = flag; @@ -78,7 +102,6 @@ template inline void PropertyFlags::setHasProperty(Enum fla return; // bail early, we're setting a flag outside of our current _maxFlag to false, which is already the default } } - qDebug() << "_flags.setBit("< inline QByteArray PropertyFlags::encode() { template inline void PropertyFlags::decode(const QByteArray& fromEncoded) { } +template inline void PropertyFlags::debugDumpBits() { + for(int i = 0; i < _flags.size(); i++) { + qDebug() << "bit[" << i << "]=" << _flags.at(i); + } +} + + +template inline PropertyFlags& PropertyFlags::operator=(const PropertyFlags &other) { + _flags = other._flags; + _maxFlag = other._maxFlag; + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator|=(PropertyFlags other) { + _flags |= other._flags; + _maxFlag = std::max(_maxFlag, other._maxFlag); + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator|=(Enum flag) { + PropertyFlags other(flag); + _flags |= other._flags; + _maxFlag = std::max(_maxFlag, other._maxFlag); + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator&=(PropertyFlags other) { + _flags &= other._flags; + shinkIfNeeded(); + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator&=(Enum flag) { + PropertyFlags other(flag); + _flags &= other._flags; + shinkIfNeeded(); + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator^=(PropertyFlags other) { + _flags ^= other._flags; + shinkIfNeeded(); + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator^=(Enum flag) { + PropertyFlags other(flag); + _flags ^= other._flags; + shinkIfNeeded(); + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator-=(PropertyFlags other) { + for(int flag = other.firstFlag(); flag <= other.lastFlag(); flag++) { + //qDebug() << "checking other.getHasProperty(flag) flag=" << flag; + if (other.getHasProperty(flag)) { + //qDebug() << "setting setHasProperty(flag) flag=" << flag; + setHasProperty(flag, false); + } + } + + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator-=(Enum flag) { + bool debug = false; + if (debug) { + qDebug() << "operator-=(Enum flag) flag=" << flag << "before..."; + debugDumpBits(); + } + setHasProperty(flag, false); + + if (debug) { + qDebug() << "after..."; + debugDumpBits(); + } + + return *this; +} + +template inline PropertyFlags PropertyFlags::operator|(PropertyFlags other) const { + PropertyFlags result(*this); + result |= other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator|(Enum flag) const { + PropertyFlags result(*this); + PropertyFlags other(flag); + result |= other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator&(PropertyFlags other) const { + PropertyFlags result(*this); + result &= other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator&(Enum flag) const { + PropertyFlags result(*this); + PropertyFlags other(flag); + result &= other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator^(PropertyFlags other) const { + PropertyFlags result(*this); + result ^= other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator^(Enum flag) const { + PropertyFlags result(*this); + PropertyFlags other(flag); + result ^= other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator-(PropertyFlags other) const { + PropertyFlags result(*this); + result -= other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator-(Enum flag) const { + PropertyFlags result(*this); + result.setHasProperty(flag, false); + return result; +} + template inline void PropertyFlags::shinkIfNeeded() { bool maxFlagWas = _maxFlag; while (_maxFlag >= 0) { diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt new file mode 100644 index 0000000000..cbdfd02054 --- /dev/null +++ b/tests/octree/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 2.8) + +if (WIN32) + cmake_policy (SET CMP0020 NEW) +endif (WIN32) + +set(TARGET_NAME octree-tests) + +set(ROOT_DIR ../..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") + +#find_package(Qt5Network REQUIRED) +#find_package(Qt5Script REQUIRED) +#find_package(Qt5Widgets REQUIRED) + +include(${MACRO_DIR}/SetupHifiProject.cmake) +setup_hifi_project(${TARGET_NAME} TRUE) + +include(${MACRO_DIR}/AutoMTC.cmake) +auto_mtc(${TARGET_NAME} ${ROOT_DIR}) + +#qt5_use_modules(${TARGET_NAME} Network Script Widgets) + +#include glm +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + +# link in the shared libraries +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) +link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) + +IF (WIN32) + #target_link_libraries(${TARGET_NAME} Winmm Ws2_32) +ENDIF(WIN32) + diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp new file mode 100644 index 0000000000..1a66a0b2ae --- /dev/null +++ b/tests/octree/src/OctreeTests.cpp @@ -0,0 +1,143 @@ +// +// OctreeTests.h +// tests/physics/src +// +// Created by Brad Hefta-Gaub on 06/04/2014. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include + +#include "OctreeTests.h" + +enum ModelPropertyList { + PROP_PAGED_PROPERTY, + PROP_CUSTOM_PROPERTIES_INCLUDED, + PROP_VISIBLE, + PROP_POSITION, + PROP_RADIUS, + PROP_MODEL_URL, + PROP_ROTATION, + PROP_COLOR, + PROP_SCRIPT, + PROP_ANIMATION_URL, + PROP_ANIMATION_FPS, + PROP_ANIMATION_FRAME_INDEX, + PROP_ANIMATION_PLAYING, + PROP_SHOULD_BE_DELETED +}; + +typedef PropertyFlags ModelPropertyFlags; + +enum ParticlePropertyList { + PARTICLE_PROP_PAGED_PROPERTY, + PARTICLE_PROP_CUSTOM_PROPERTIES_INCLUDED, + PARTICLE_PROP_VISIBLE, + PARTICLE_PROP_POSITION, + PARTICLE_PROP_RADIUS, + PARTICLE_PROP_MODEL_URL, + PARTICLE_PROP_ROTATION, + PARTICLE_PROP_COLOR, + PARTICLE_PROP_SCRIPT, + PARTICLE_PROP_ANIMATION_URL, + PARTICLE_PROP_ANIMATION_FPS, + PARTICLE_PROP_ANIMATION_FRAME_INDEX, + PARTICLE_PROP_ANIMATION_PLAYING, + PARTICLE_PROP_SHOULD_BE_DELETED, + PARTICLE_PROP_VELOCITY, + PARTICLE_PROP_GRAVITY, + PARTICLE_PROP_DAMPING, + PARTICLE_PROP_MASS, + PARTICLE_PROP_LIFETIME, + PARTICLE_PROP_PAUSE_SIMULATION, +}; + +typedef PropertyFlags ParticlePropertyFlags; + + +void OctreeTests::propertyFlagsTests() { + qDebug() << "******************************************************************************************"; + qDebug() << "OctreeTests::propertyFlagsTests()"; + + { + qDebug() << "Test 1: ModelProperties: PROP_VISIBLE, PROP_POSITION, PROP_RADIUS, PROP_MODEL_URL, PROP_ROTATION"; + ModelPropertyFlags props; + props.setHasProperty(PROP_VISIBLE); + props.setHasProperty(PROP_POSITION); + props.setHasProperty(PROP_RADIUS); + props.setHasProperty(PROP_MODEL_URL); + props.setHasProperty(PROP_ROTATION); + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 2: ParticlePropertyFlags: PROP_VISIBLE, PARTICLE_PROP_ANIMATION_URL, PARTICLE_PROP_ANIMATION_FPS, " + "PARTICLE_PROP_ANIMATION_FRAME_INDEX, PARTICLE_PROP_ANIMATION_PLAYING, PARTICLE_PROP_PAUSE_SIMULATION"; + ParticlePropertyFlags props2; + props2.setHasProperty(PARTICLE_PROP_VISIBLE); + props2.setHasProperty(PARTICLE_PROP_ANIMATION_URL); + props2.setHasProperty(PARTICLE_PROP_ANIMATION_FPS); + props2.setHasProperty(PARTICLE_PROP_ANIMATION_FRAME_INDEX); + props2.setHasProperty(PARTICLE_PROP_ANIMATION_PLAYING); + props2.setHasProperty(PARTICLE_PROP_PAUSE_SIMULATION); + + QByteArray encoded = props2.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + + qDebug() << "Test 2b: remove flag with setHasProperty() PARTICLE_PROP_PAUSE_SIMULATION"; + + props2.setHasProperty(PARTICLE_PROP_PAUSE_SIMULATION, false); + + encoded = props2.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + + } + + { + qDebug() << "Test 3: ParticlePropertyFlags: using | operator"; + ParticlePropertyFlags props; + + props = ParticlePropertyFlags(PARTICLE_PROP_VISIBLE) + | ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_URL) + | ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FPS) + | ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FRAME_INDEX) + | ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_PLAYING) + | ParticlePropertyFlags(PARTICLE_PROP_PAUSE_SIMULATION); + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + + qDebug() << "Test 3b: remove flag with -= PARTICLE_PROP_PAUSE_SIMULATION"; + props -= PARTICLE_PROP_PAUSE_SIMULATION; + + encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + + } + + + + qDebug() << "******************************************************************************************"; +} + +void OctreeTests::runAllTests() { + propertyFlagsTests(); +} diff --git a/tests/octree/src/OctreeTests.h b/tests/octree/src/OctreeTests.h new file mode 100644 index 0000000000..53b0d9fb83 --- /dev/null +++ b/tests/octree/src/OctreeTests.h @@ -0,0 +1,22 @@ +// +// OctreeTests.h +// tests/physics/src +// +// Created by Brad Hefta-Gaub on 06/04/2014. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_OctreeTests_h +#define hifi_OctreeTests_h + +namespace OctreeTests { + + void propertyFlagsTests(); + + void runAllTests(); +} + +#endif // hifi_OctreeTests_h diff --git a/tests/octree/src/main.cpp b/tests/octree/src/main.cpp new file mode 100644 index 0000000000..ec3dc19e01 --- /dev/null +++ b/tests/octree/src/main.cpp @@ -0,0 +1,16 @@ +// +// main.cpp +// tests/octree/src +// +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "OctreeTests.h" + +int main(int argc, char** argv) { + OctreeTests::runAllTests(); + return 0; +} From 78d3f1454c222554d750d0ea70335d87d670fd84 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 14:19:35 -0700 Subject: [PATCH 05/10] more operators --- libraries/shared/src/PropertyFlags.h | 146 ++++++++++++---- tests/octree/src/OctreeTests.cpp | 241 ++++++++++++++++++++++++++- 2 files changed, 350 insertions(+), 37 deletions(-) diff --git a/libraries/shared/src/PropertyFlags.h b/libraries/shared/src/PropertyFlags.h index d8131d0c75..4c4dc6b386 100644 --- a/libraries/shared/src/PropertyFlags.h +++ b/libraries/shared/src/PropertyFlags.h @@ -11,9 +11,7 @@ // // TODO: // * implement decode -// * more operators, operator==, operator!=, operator!, operator~ // * iterator to enumerate the set values? -// * operator<<(enum) to work similar to set #ifndef hifi_PropertyFlags_h #define hifi_PropertyFlags_h @@ -29,14 +27,18 @@ templateclass PropertyFlags { public: typedef Enum enum_type; - inline PropertyFlags() : _maxFlag(INT_MIN), _minFlag(INT_MAX) { }; - inline PropertyFlags(const PropertyFlags& other) : _flags(other._flags), _maxFlag(other._maxFlag) {} - inline PropertyFlags(Enum flag) : _maxFlag(INT_MIN), _minFlag(INT_MAX) { setHasProperty(flag); } + inline PropertyFlags() : + _maxFlag(INT_MIN), _minFlag(INT_MAX), _trailingFlipped(false) { }; + inline PropertyFlags(const PropertyFlags& other) : + _flags(other._flags), _maxFlag(other._maxFlag), _minFlag(other._minFlag), + _trailingFlipped(other._trailingFlipped) {} + inline PropertyFlags(Enum flag) : + _maxFlag(INT_MIN), _minFlag(INT_MAX), _trailingFlipped(false) { setHasProperty(flag); } - void clear() { _flags.clear(); _maxFlag = INT_MIN; _minFlag = INT_MAX; } + void clear() { _flags.clear(); _maxFlag = INT_MIN; _minFlag = INT_MAX; _trailingFlipped = false; } - Enum firstFlag() const { return _minFlag; } - Enum lastFlag() const { return _maxFlag; } + Enum firstFlag() const { return (Enum)_minFlag; } + Enum lastFlag() const { return (Enum)_maxFlag; } void setHasProperty(Enum flag, bool value = true); bool getHasProperty(Enum flag); @@ -44,7 +46,12 @@ public: void decode(const QByteArray& fromEncoded); - PropertyFlags& operator=(const PropertyFlags &other); + bool operator==(const PropertyFlags& other) const { return _flags == other._flags; } + bool operator!=(const PropertyFlags& other) const { return _flags != other._flags; } + bool operator!() const { return _flags.size() == 0; } + + + PropertyFlags& operator=(const PropertyFlags& other); PropertyFlags& operator|=(PropertyFlags other); PropertyFlags& operator|=(Enum flag); @@ -55,9 +62,15 @@ public: PropertyFlags& operator^=(PropertyFlags other); PropertyFlags& operator^=(Enum flag); + PropertyFlags& operator+=(PropertyFlags other); + PropertyFlags& operator+=(Enum flag); + PropertyFlags& operator-=(PropertyFlags other); PropertyFlags& operator-=(Enum flag); + PropertyFlags& operator<<=(PropertyFlags other); + PropertyFlags& operator<<=(Enum flag); + PropertyFlags operator|(PropertyFlags other) const; PropertyFlags operator|(Enum flag) const; @@ -67,25 +80,38 @@ public: PropertyFlags operator^(PropertyFlags other) const; PropertyFlags operator^(Enum flag) const; + PropertyFlags operator+(PropertyFlags other) const; + PropertyFlags operator+(Enum flag) const; + PropertyFlags operator-(PropertyFlags other) const; PropertyFlags operator-(Enum flag) const; + PropertyFlags operator<<(PropertyFlags other) const; + PropertyFlags operator<<(Enum flag) const; - /* - inline PropertyFlags operator~() const { return PropertyFlags(Enum(~i)); } - inline bool operator!() const { return !i; } - */ + + PropertyFlags operator~() const; + + void debugDumpBits(); private: void shinkIfNeeded(); - void debugDumpBits(); QBitArray _flags; int _maxFlag; int _minFlag; + bool _trailingFlipped; /// are the trailing properties flipping in their state (e.g. assumed true, instead of false) }; +template PropertyFlags& operator<<(PropertyFlags& out, const PropertyFlags& other) { + return out <<= other; +} + +template PropertyFlags& operator<<(PropertyFlags& out, Enum flag) { + return out <<= flag; +} + template inline void PropertyFlags::setHasProperty(Enum flag, bool value) { // keep track of our min flag @@ -111,7 +137,7 @@ template inline void PropertyFlags::setHasProperty(Enum fla template inline bool PropertyFlags::getHasProperty(Enum flag) { if (flag > _maxFlag) { - return false; + return _trailingFlipped; // usually false } return _flags.testBit(flag); } @@ -121,6 +147,11 @@ const int BITS_PER_BYTE = 8; template inline QByteArray PropertyFlags::encode() { const bool debug = false; QByteArray output; + + if (_maxFlag < _minFlag) { + output.fill(0, 1); + return output; // no flags... nothing to encode + } outputBufferBits((const unsigned char*)output.constData(), output.size()); @@ -200,21 +231,26 @@ template inline void PropertyFlags::decode(const QByteArray } template inline void PropertyFlags::debugDumpBits() { + qDebug() << "_minFlag=" << _minFlag; + qDebug() << "_maxFlag=" << _maxFlag; + qDebug() << "_trailingFlipped=" << _trailingFlipped; for(int i = 0; i < _flags.size(); i++) { qDebug() << "bit[" << i << "]=" << _flags.at(i); } } -template inline PropertyFlags& PropertyFlags::operator=(const PropertyFlags &other) { +template inline PropertyFlags& PropertyFlags::operator=(const PropertyFlags& other) { _flags = other._flags; _maxFlag = other._maxFlag; + _minFlag = other._minFlag; return *this; } template inline PropertyFlags& PropertyFlags::operator|=(PropertyFlags other) { _flags |= other._flags; _maxFlag = std::max(_maxFlag, other._maxFlag); + _minFlag = std::min(_minFlag, other._minFlag); return *this; } @@ -222,6 +258,7 @@ template inline PropertyFlags& PropertyFlags::operato PropertyFlags other(flag); _flags |= other._flags; _maxFlag = std::max(_maxFlag, other._maxFlag); + _minFlag = std::min(_minFlag, other._minFlag); return *this; } @@ -251,31 +288,45 @@ template inline PropertyFlags& PropertyFlags::operato return *this; } -template inline PropertyFlags& PropertyFlags::operator-=(PropertyFlags other) { - for(int flag = other.firstFlag(); flag <= other.lastFlag(); flag++) { - //qDebug() << "checking other.getHasProperty(flag) flag=" << flag; - if (other.getHasProperty(flag)) { - //qDebug() << "setting setHasProperty(flag) flag=" << flag; - setHasProperty(flag, false); +template inline PropertyFlags& PropertyFlags::operator+=(PropertyFlags other) { + for(int flag = (int)other.firstFlag(); flag <= (int)other.lastFlag(); flag++) { + if (other.getHasProperty((Enum)flag)) { + setHasProperty((Enum)flag, true); } } - return *this; } +template inline PropertyFlags& PropertyFlags::operator+=(Enum flag) { + setHasProperty(flag, true); + return *this; +} + +template inline PropertyFlags& PropertyFlags::operator-=(PropertyFlags other) { + for(int flag = (int)other.firstFlag(); flag <= (int)other.lastFlag(); flag++) { + if (other.getHasProperty((Enum)flag)) { + setHasProperty((Enum)flag, false); + } + } + return *this; +} + template inline PropertyFlags& PropertyFlags::operator-=(Enum flag) { - bool debug = false; - if (debug) { - qDebug() << "operator-=(Enum flag) flag=" << flag << "before..."; - debugDumpBits(); - } setHasProperty(flag, false); + return *this; +} - if (debug) { - qDebug() << "after..."; - debugDumpBits(); +template inline PropertyFlags& PropertyFlags::operator<<=(PropertyFlags other) { + for(int flag = (int)other.firstFlag(); flag <= (int)other.lastFlag(); flag++) { + if (other.getHasProperty((Enum)flag)) { + setHasProperty((Enum)flag, true); + } } + return *this; +} +template inline PropertyFlags& PropertyFlags::operator<<=(Enum flag) { + setHasProperty(flag, true); return *this; } @@ -318,6 +369,18 @@ template inline PropertyFlags PropertyFlags::operator return result; } +template inline PropertyFlags PropertyFlags::operator+(PropertyFlags other) const { + PropertyFlags result(*this); + result += other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator+(Enum flag) const { + PropertyFlags result(*this); + result.setHasProperty(flag, true); + return result; +} + template inline PropertyFlags PropertyFlags::operator-(PropertyFlags other) const { PropertyFlags result(*this); result -= other; @@ -330,6 +393,25 @@ template inline PropertyFlags PropertyFlags::operator return result; } +template inline PropertyFlags PropertyFlags::operator<<(PropertyFlags other) const { + PropertyFlags result(*this); + result <<= other; + return result; +} + +template inline PropertyFlags PropertyFlags::operator<<(Enum flag) const { + PropertyFlags result(*this); + result.setHasProperty(flag, true); + return result; +} + +template inline PropertyFlags PropertyFlags::operator~() const { + PropertyFlags result(*this); + result._flags = ~_flags; + result._trailingFlipped = !_trailingFlipped; + return result; +} + template inline void PropertyFlags::shinkIfNeeded() { bool maxFlagWas = _maxFlag; while (_maxFlag >= 0) { @@ -343,8 +425,6 @@ template inline void PropertyFlags::shinkIfNeeded() { } } - - /*** BitArr.resize(8*byteArr.count()); diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index 1a66a0b2ae..7143e6ca7a 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -66,7 +66,7 @@ void OctreeTests::propertyFlagsTests() { qDebug() << "OctreeTests::propertyFlagsTests()"; { - qDebug() << "Test 1: ModelProperties: PROP_VISIBLE, PROP_POSITION, PROP_RADIUS, PROP_MODEL_URL, PROP_ROTATION"; + qDebug() << "Test 1: ModelProperties: using setHasProperty()"; ModelPropertyFlags props; props.setHasProperty(PROP_VISIBLE); props.setHasProperty(PROP_POSITION); @@ -81,8 +81,7 @@ void OctreeTests::propertyFlagsTests() { } { - qDebug() << "Test 2: ParticlePropertyFlags: PROP_VISIBLE, PARTICLE_PROP_ANIMATION_URL, PARTICLE_PROP_ANIMATION_FPS, " - "PARTICLE_PROP_ANIMATION_FRAME_INDEX, PARTICLE_PROP_ANIMATION_PLAYING, PARTICLE_PROP_PAUSE_SIMULATION"; + qDebug() << "Test 2: ParticlePropertyFlags: using setHasProperty()"; ParticlePropertyFlags props2; props2.setHasProperty(PARTICLE_PROP_VISIBLE); props2.setHasProperty(PARTICLE_PROP_ANIMATION_URL); @@ -130,11 +129,245 @@ void OctreeTests::propertyFlagsTests() { qDebug() << "encoded="; outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 3c: ParticlePropertyFlags: using |= operator"; + ParticlePropertyFlags props; + + props |= PARTICLE_PROP_VISIBLE; + props |= PARTICLE_PROP_ANIMATION_URL; + props |= PARTICLE_PROP_ANIMATION_FPS; + props |= PARTICLE_PROP_ANIMATION_FRAME_INDEX; + props |= PARTICLE_PROP_ANIMATION_PLAYING; + props |= PARTICLE_PROP_PAUSE_SIMULATION; + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 4: ParticlePropertyFlags: using + operator"; + ParticlePropertyFlags props; + + props = ParticlePropertyFlags(PARTICLE_PROP_VISIBLE) + + ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_URL) + + ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FPS) + + ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FRAME_INDEX) + + ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_PLAYING) + + ParticlePropertyFlags(PARTICLE_PROP_PAUSE_SIMULATION); + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 4b: ParticlePropertyFlags: using += operator"; + ParticlePropertyFlags props; + + props += PARTICLE_PROP_VISIBLE; + props += PARTICLE_PROP_ANIMATION_URL; + props += PARTICLE_PROP_ANIMATION_FPS; + props += PARTICLE_PROP_ANIMATION_FRAME_INDEX; + props += PARTICLE_PROP_ANIMATION_PLAYING; + props += PARTICLE_PROP_PAUSE_SIMULATION; + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 5: ParticlePropertyFlags: using = ... << operator"; + ParticlePropertyFlags props; + + props = ParticlePropertyFlags(PARTICLE_PROP_VISIBLE) + << ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_URL) + << ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FPS) + << ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_FRAME_INDEX) + << ParticlePropertyFlags(PARTICLE_PROP_ANIMATION_PLAYING) + << ParticlePropertyFlags(PARTICLE_PROP_PAUSE_SIMULATION); + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 5b: ParticlePropertyFlags: using <<= operator"; + ParticlePropertyFlags props; + + props <<= PARTICLE_PROP_VISIBLE; + props <<= PARTICLE_PROP_ANIMATION_URL; + props <<= PARTICLE_PROP_ANIMATION_FPS; + props <<= PARTICLE_PROP_ANIMATION_FRAME_INDEX; + props <<= PARTICLE_PROP_ANIMATION_PLAYING; + props <<= PARTICLE_PROP_PAUSE_SIMULATION; + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 5c: ParticlePropertyFlags: using << enum operator"; + ParticlePropertyFlags props; + + props << PARTICLE_PROP_VISIBLE; + props << PARTICLE_PROP_ANIMATION_URL; + props << PARTICLE_PROP_ANIMATION_FPS; + props << PARTICLE_PROP_ANIMATION_FRAME_INDEX; + props << PARTICLE_PROP_ANIMATION_PLAYING; + props << PARTICLE_PROP_PAUSE_SIMULATION; + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 5d: ParticlePropertyFlags: using << flags operator "; + ParticlePropertyFlags props; + ParticlePropertyFlags props2; + + props << PARTICLE_PROP_VISIBLE; + props << PARTICLE_PROP_ANIMATION_URL; + props << PARTICLE_PROP_ANIMATION_FPS; + + props2 << PARTICLE_PROP_ANIMATION_FRAME_INDEX; + props2 << PARTICLE_PROP_ANIMATION_PLAYING; + props2 << PARTICLE_PROP_PAUSE_SIMULATION; + + props << props2; + + QByteArray encoded = props.encode(); + + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } + + { + qDebug() << "Test 6: ParticlePropertyFlags comparison"; + ParticlePropertyFlags propsA; + + qDebug() << "!propsA:" << (!propsA) << "{ expect true }"; + + propsA << PARTICLE_PROP_VISIBLE; + propsA << PARTICLE_PROP_ANIMATION_URL; + propsA << PARTICLE_PROP_ANIMATION_FPS; + propsA << PARTICLE_PROP_ANIMATION_FRAME_INDEX; + propsA << PARTICLE_PROP_ANIMATION_PLAYING; + propsA << PARTICLE_PROP_PAUSE_SIMULATION; + + qDebug() << "!propsA:" << (!propsA) << "{ expect false }"; + + ParticlePropertyFlags propsB; + qDebug() << "!propsB:" << (!propsB) << "{ expect true }"; + + + propsB << PARTICLE_PROP_VISIBLE; + propsB << PARTICLE_PROP_ANIMATION_URL; + propsB << PARTICLE_PROP_ANIMATION_FPS; + propsB << PARTICLE_PROP_ANIMATION_FRAME_INDEX; + propsB << PARTICLE_PROP_ANIMATION_PLAYING; + propsB << PARTICLE_PROP_PAUSE_SIMULATION; + + qDebug() << "!propsB:" << (!propsB) << "{ expect false }"; + + qDebug() << "propsA == propsB:" << (propsA == propsB) << "{ expect true }"; + qDebug() << "propsA != propsB:" << (propsA != propsB) << "{ expect false }"; + + + qDebug() << "AFTER propsB -= PARTICLE_PROP_PAUSE_SIMULATION..."; + propsB -= PARTICLE_PROP_PAUSE_SIMULATION; + + qDebug() << "propsA == propsB:" << (propsA == propsB) << "{ expect false }"; + qDebug() << "propsA != propsB:" << (propsA != propsB) << "{ expect true }"; + + qDebug() << "AFTER propsB = propsA..."; + propsB = propsA; + + qDebug() << "propsA == propsB:" << (propsA == propsB) << "{ expect true }"; + qDebug() << "propsA != propsB:" << (propsA != propsB) << "{ expect false }"; } + { + qDebug() << "Test 7: ParticlePropertyFlags testing individual properties"; + ParticlePropertyFlags props; + + qDebug() << "ParticlePropertyFlags props;"; + QByteArray encoded = props.encode(); + qDebug() << "props... encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + + qDebug() << "props.getHasProperty(PARTICLE_PROP_VISIBLE)" << (props.getHasProperty(PARTICLE_PROP_VISIBLE)) + << "{ expect false }"; + + qDebug() << "props << PARTICLE_PROP_VISIBLE;"; + props << PARTICLE_PROP_VISIBLE; + + encoded = props.encode(); + qDebug() << "props... encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + qDebug() << "props.getHasProperty(PARTICLE_PROP_VISIBLE)" << (props.getHasProperty(PARTICLE_PROP_VISIBLE)) + << "{ expect true }"; + + qDebug() << "props << PARTICLE_PROP_ANIMATION_URL;"; + props << PARTICLE_PROP_ANIMATION_URL; + + encoded = props.encode(); + qDebug() << "props... encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + qDebug() << "props.getHasProperty(PARTICLE_PROP_VISIBLE)" << (props.getHasProperty(PARTICLE_PROP_VISIBLE)) + << "{ expect true }"; + + qDebug() << "props << ... more ..."; + props << PARTICLE_PROP_ANIMATION_FPS; + props << PARTICLE_PROP_ANIMATION_FRAME_INDEX; + props << PARTICLE_PROP_ANIMATION_PLAYING; + props << PARTICLE_PROP_PAUSE_SIMULATION; + + encoded = props.encode(); + qDebug() << "props... encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + qDebug() << "props.getHasProperty(PARTICLE_PROP_VISIBLE)" << (props.getHasProperty(PARTICLE_PROP_VISIBLE)) + << "{ expect true }"; + + qDebug() << "ParticlePropertyFlags propsB = props & PARTICLE_PROP_VISIBLE;"; + ParticlePropertyFlags propsB = props & PARTICLE_PROP_VISIBLE; + + qDebug() << "propsB.getHasProperty(PARTICLE_PROP_VISIBLE)" << (propsB.getHasProperty(PARTICLE_PROP_VISIBLE)) + << "{ expect true }"; + + encoded = propsB.encode(); + qDebug() << "propsB... encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + + qDebug() << "propsB..."; + propsB.debugDumpBits(); + + qDebug() << "ParticlePropertyFlags propsC = ~propsB;"; + ParticlePropertyFlags propsC = ~propsB; + qDebug() << "propsC..."; + propsC.debugDumpBits(); + + qDebug() << "propsC.getHasProperty(PARTICLE_PROP_VISIBLE)" << (propsC.getHasProperty(PARTICLE_PROP_VISIBLE)) + << "{ expect false }"; + + encoded = propsC.encode(); + qDebug() << "propsC... encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + } - qDebug() << "******************************************************************************************"; } From 10f7eae7a0d44a344d9238b69cb7c0bd10efa8e9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 14:56:13 -0700 Subject: [PATCH 06/10] implemented decode --- libraries/shared/src/PropertyFlags.h | 60 +++++++++++++++++++++------- tests/octree/src/OctreeTests.cpp | 28 +++++++++++++ 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/libraries/shared/src/PropertyFlags.h b/libraries/shared/src/PropertyFlags.h index 4c4dc6b386..d19f52a846 100644 --- a/libraries/shared/src/PropertyFlags.h +++ b/libraries/shared/src/PropertyFlags.h @@ -10,7 +10,6 @@ // // // TODO: -// * implement decode // * iterator to enumerate the set values? #ifndef hifi_PropertyFlags_h @@ -50,7 +49,6 @@ public: bool operator!=(const PropertyFlags& other) const { return _flags != other._flags; } bool operator!() const { return _flags.size() == 0; } - PropertyFlags& operator=(const PropertyFlags& other); PropertyFlags& operator|=(PropertyFlags other); @@ -59,9 +57,6 @@ public: PropertyFlags& operator&=(PropertyFlags other); PropertyFlags& operator&=(Enum flag); - PropertyFlags& operator^=(PropertyFlags other); - PropertyFlags& operator^=(Enum flag); - PropertyFlags& operator+=(PropertyFlags other); PropertyFlags& operator+=(Enum flag); @@ -77,9 +72,6 @@ public: PropertyFlags operator&(PropertyFlags other) const; PropertyFlags operator&(Enum flag) const; - PropertyFlags operator^(PropertyFlags other) const; - PropertyFlags operator^(Enum flag) const; - PropertyFlags operator+(PropertyFlags other) const; PropertyFlags operator+(Enum flag) const; @@ -89,7 +81,13 @@ public: PropertyFlags operator<<(PropertyFlags other) const; PropertyFlags operator<<(Enum flag) const; - + // NOTE: due to the nature of the compact storage of these property flags, and the fact that the upper bound of the + // enum is not know, these operators will only perform their bitwise operations on the set of properties that have + // been previously set + PropertyFlags& operator^=(PropertyFlags other); + PropertyFlags& operator^=(Enum flag); + PropertyFlags operator^(PropertyFlags other) const; + PropertyFlags operator^(Enum flag) const; PropertyFlags operator~() const; void debugDumpBits(); @@ -227,7 +225,45 @@ template inline QByteArray PropertyFlags::encode() { return output; } -template inline void PropertyFlags::decode(const QByteArray& fromEncoded) { +template inline void PropertyFlags::decode(const QByteArray& fromEncodedBytes) { + + clear(); // we are cleared out! + + // first convert the ByteArray into a BitArray... + QBitArray encodedBits; + int bitCount = BITS_PER_BYTE * fromEncodedBytes.count(); + encodedBits.resize(bitCount); + + for(int byte = 0; byte < fromEncodedBytes.count(); byte++) { + char originalByte = fromEncodedBytes.at(byte); + for(int bit = 0; bit < BITS_PER_BYTE; bit++) { + int shiftBy = BITS_PER_BYTE - (bit + 1); + char maskBit = ( 1 << shiftBy); + bool bitValue = originalByte & maskBit; + encodedBits.setBit(byte * BITS_PER_BYTE + bit, bitValue); + } + } + + // next, read the leading bits to determine the correct number of bytes to decode (may not match the QByteArray) + int encodedByteCount = 0; + int bitAt; + for (bitAt = 0; bitAt < bitCount; bitAt++) { + if (encodedBits.at(bitAt)) { + encodedByteCount++; + } else { + break; + } + } + encodedByteCount++; // always at least one byte + int expectedBitCount = encodedByteCount * BITS_PER_BYTE; + + // Now, keep reading... + int flagsStartAt = bitAt + 1; + for (bitAt = flagsStartAt; bitAt < expectedBitCount; bitAt++) { + if (encodedBits.at(bitAt)) { + setHasProperty((Enum)(bitAt - flagsStartAt)); + } + } } template inline void PropertyFlags::debugDumpBits() { @@ -431,10 +467,6 @@ BitArr.resize(8*byteArr.count()); for(int i=0; i diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index 7143e6ca7a..d15b77a53a 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -367,6 +367,34 @@ void OctreeTests::propertyFlagsTests() { qDebug() << "propsC... encoded="; outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); } + + { + qDebug() << "Test 8: ParticlePropertyFlags: decode tests"; + ParticlePropertyFlags props; + + props << PARTICLE_PROP_VISIBLE; + props << PARTICLE_PROP_ANIMATION_URL; + props << PARTICLE_PROP_ANIMATION_FPS; + props << PARTICLE_PROP_ANIMATION_FRAME_INDEX; + props << PARTICLE_PROP_ANIMATION_PLAYING; + props << PARTICLE_PROP_PAUSE_SIMULATION; + + QByteArray encoded = props.encode(); + qDebug() << "encoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + + ParticlePropertyFlags propsDecoded; + + propsDecoded.decode(encoded); + + qDebug() << "propsDecoded == props:" << (propsDecoded == props) << "{ expect true }"; + + QByteArray encodedAfterDecoded = propsDecoded.encode(); + + qDebug() << "encodedAfterDecoded="; + outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + + } qDebug() << "******************************************************************************************"; } From 2066dbcec78903535384c5ef3dc47a48d312ab86 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 15:16:51 -0700 Subject: [PATCH 07/10] cleanup --- libraries/shared/src/PropertyFlags.h | 95 +--------------------------- tests/octree/src/OctreeTests.cpp | 5 -- 2 files changed, 1 insertion(+), 99 deletions(-) diff --git a/libraries/shared/src/PropertyFlags.h b/libraries/shared/src/PropertyFlags.h index d19f52a846..b9253379c6 100644 --- a/libraries/shared/src/PropertyFlags.h +++ b/libraries/shared/src/PropertyFlags.h @@ -10,7 +10,7 @@ // // // TODO: -// * iterator to enumerate the set values? +// * consider adding iterator to enumerate the properties that have been set? #ifndef hifi_PropertyFlags_h #define hifi_PropertyFlags_h @@ -143,7 +143,6 @@ template inline bool PropertyFlags::getHasProperty(Enum fla const int BITS_PER_BYTE = 8; template inline QByteArray PropertyFlags::encode() { - const bool debug = false; QByteArray output; if (_maxFlag < _minFlag) { @@ -151,77 +150,31 @@ template inline QByteArray PropertyFlags::encode() { return output; // no flags... nothing to encode } - outputBufferBits((const unsigned char*)output.constData(), output.size()); - - if (debug) qDebug() << "PropertyFlags::encode()"; - // we should size the array to the correct size. int lengthInBytes = (_maxFlag / (BITS_PER_BYTE - 1)) + 1; - if (debug) qDebug() << " lengthInBytes=" << lengthInBytes; - output.fill(0, lengthInBytes); - if (debug) outputBufferBits((const unsigned char*)output.constData(), output.size()); - // next pack the number of header bits in, the first N-1 to be set to 1, the last to be set to 0 for(int i = 0; i < lengthInBytes; i++) { int outputIndex = i; - if (debug) qDebug() << "outputIndex:" << outputIndex; int bitValue = (i < (lengthInBytes - 1) ? 1 : 0); - - if (debug) qDebug() << " length code bit["<< outputIndex << "]=" << bitValue; - char original = output.at(outputIndex / BITS_PER_BYTE); int shiftBy = BITS_PER_BYTE - ((outputIndex % BITS_PER_BYTE) + 1); char thisBit = ( bitValue << shiftBy); - - if (debug) { - qDebug() << "bitValue:" << bitValue; - qDebug() << "shiftBy:" << shiftBy; - qDebug() << "original:"; - outputBits(original); - - qDebug() << "thisBit:"; - outputBits(thisBit); - } - output[i / BITS_PER_BYTE] = (original | thisBit); } - if (debug) outputBufferBits((const unsigned char*)output.constData(), output.size()); - // finally pack the the actual bits from the bit array for(int i = lengthInBytes; i < (lengthInBytes + _maxFlag + 1); i++) { int flagIndex = i - lengthInBytes; int outputIndex = i; - if (debug) qDebug() << "flagIndex:" << flagIndex; - if (debug) qDebug() << "outputIndex:" << outputIndex; - - int bitValue = ( _flags[flagIndex] ? 1 : 0); - - if (debug) qDebug() << " encode bit["< inline void PropertyFlags::shinkIfNeeded() { } } -/*** - -BitArr.resize(8*byteArr.count()); -for(int i=0; i -class QFlags -{ - typedef void **Zero; - int i; -public: - typedef Enum enum_type; - Q_DECL_CONSTEXPR inline QFlags(const QFlags &f) : i(f.i) {} - Q_DECL_CONSTEXPR inline QFlags(Enum f) : i(f) {} - Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {} - inline QFlags(QFlag f) : i(f) {} - - inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; } - inline QFlags &operator&=(int mask) { i &= mask; return *this; } - inline QFlags &operator&=(uint mask) { i &= mask; return *this; } - inline QFlags &operator|=(QFlags f) { i |= f.i; return *this; } - inline QFlags &operator|=(Enum f) { i |= f; return *this; } - inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; } - inline QFlags &operator^=(Enum f) { i ^= f; return *this; } - - Q_DECL_CONSTEXPR inline operator int() const { return i; } - - Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); } - Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); } - Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(Enum(i ^ f.i)); } - Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(Enum(i ^ f)); } - Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(Enum(i & mask)); } - Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(Enum(i & mask)); } - Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(Enum(i & f)); } - Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(Enum(~i)); } - - Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } - - inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); } -}; - -***/ - #endif // hifi_PropertyFlags_h diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index d15b77a53a..436973ba52 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -352,13 +352,8 @@ void OctreeTests::propertyFlagsTests() { qDebug() << "propsB... encoded="; outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); - qDebug() << "propsB..."; - propsB.debugDumpBits(); - qDebug() << "ParticlePropertyFlags propsC = ~propsB;"; ParticlePropertyFlags propsC = ~propsB; - qDebug() << "propsC..."; - propsC.debugDumpBits(); qDebug() << "propsC.getHasProperty(PARTICLE_PROP_VISIBLE)" << (propsC.getHasProperty(PARTICLE_PROP_VISIBLE)) << "{ expect false }"; From c7a502e2c9437bf783dc551229a7517a5a7b1423 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 15:18:11 -0700 Subject: [PATCH 08/10] removed empty file --- libraries/shared/src/PropertyFlags.cpp | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 libraries/shared/src/PropertyFlags.cpp diff --git a/libraries/shared/src/PropertyFlags.cpp b/libraries/shared/src/PropertyFlags.cpp deleted file mode 100644 index 8413ce8172..0000000000 --- a/libraries/shared/src/PropertyFlags.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// -// PropertyFlags.cpp -// libraries/shared/src -// -// Created by Brad Hefta-Gaub on 6/3/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - From 152d99d8102fb34d95d007645678c8691d8287a0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 15:23:17 -0700 Subject: [PATCH 09/10] removed some old debug code and updated a comment --- libraries/models/src/ModelTreeElement.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index 3fc2537dc7..b0c7e125b4 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -50,6 +50,10 @@ ModelTreeElement* ModelTreeElement::addChildAtIndex(int index) { } +// TODO: This will attempt to store as many models as will fit in the packetData, if an individual model won't +// fit, but some models did fit, then the element outputs what can fit. Once the general Octree::encodeXXX() +// process supports partial encoding of an octree element, this will need to be updated to handle spanning its +// contents across multiple packets. bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const { bool success = true; // assume the best... @@ -89,7 +93,6 @@ bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBit actualNumberOfModels++; } if (!success) { - qDebug() << "ModelTreeElement::appendElementData()... model i=" << i << "didn't fit..."; packetData->discardLevel(modelLevel); break; } @@ -97,7 +100,6 @@ bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBit } if (!success) { - qDebug() << "ModelTreeElement::appendElementData()... updatePriorBytes()... actualNumberOfModels=" << actualNumberOfModels; success = packetData->updatePriorBytes(numberOfModelsOffset, (const unsigned char*)&actualNumberOfModels, sizeof(actualNumberOfModels)); } From b74676de0d5af68f634f8b90485b7b97f61f6778 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 4 Jun 2014 15:33:22 -0700 Subject: [PATCH 10/10] add more tests for decode --- tests/octree/src/OctreeTests.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index 436973ba52..ddc3f2c74d 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -378,8 +378,9 @@ void OctreeTests::propertyFlagsTests() { qDebug() << "encoded="; outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + qDebug() << "encoded.size()=" << encoded.size(); + ParticlePropertyFlags propsDecoded; - propsDecoded.decode(encoded); qDebug() << "propsDecoded == props:" << (propsDecoded == props) << "{ expect true }"; @@ -387,7 +388,23 @@ void OctreeTests::propertyFlagsTests() { QByteArray encodedAfterDecoded = propsDecoded.encode(); qDebug() << "encodedAfterDecoded="; - outputBufferBits((const unsigned char*)encoded.constData(), encoded.size()); + outputBufferBits((const unsigned char*)encodedAfterDecoded.constData(), encodedAfterDecoded.size()); + + qDebug() << "fill encoded byte array with extra garbage (as if it was bitstream with more content)"; + QByteArray extraContent; + extraContent.fill(0xba, 10); + encoded.append(extraContent); + qDebug() << "encoded.size()=" << encoded.size() << "includes extra garbage"; + + ParticlePropertyFlags propsDecodedExtra; + propsDecodedExtra.decode(encoded); + + qDebug() << "propsDecodedExtra == props:" << (propsDecodedExtra == props) << "{ expect true }"; + + QByteArray encodedAfterDecodedExtra = propsDecodedExtra.encode(); + + qDebug() << "encodedAfterDecodedExtra="; + outputBufferBits((const unsigned char*)encodedAfterDecodedExtra.constData(), encodedAfterDecodedExtra.size()); }