// // OctreeSceneStats.h // libraries/octree/src // // Created by Brad Hefta-Gaub on 7/18/13. // Copyright 2013 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_OctreeSceneStats_h #define hifi_OctreeSceneStats_h #include #include #include #include "JurisdictionMap.h" #include "OctreePacketData.h" #define GREENISH 0x40ff40d0 #define YELLOWISH 0xffef40c0 #define GREYISH 0xd0d0d0a0 class OctreeElement; /// Collects statistics for calculating and sending a scene from a octree server to an interface client class OctreeSceneStats { public: OctreeSceneStats(); ~OctreeSceneStats(); void reset(); OctreeSceneStats(const OctreeSceneStats& other); // copy constructor OctreeSceneStats& operator= (const OctreeSceneStats& other); // copy assignment /// Call when beginning the computation of a scene. Initializes internal structures void sceneStarted(bool fullScene, bool moving, OctreeElement* root, JurisdictionMap* jurisdictionMap); bool getIsSceneStarted() const { return _isStarted; } /// Call when the computation of a scene is completed. Finalizes internal structures void sceneCompleted(); void printDebugDetails(); /// Track that a packet was sent as part of the scene. void packetSent(int bytes); /// Tracks the beginning of an encode pass during scene calculation. void encodeStarted(); /// Tracks the ending of an encode pass during scene calculation. void encodeStopped(); /// Track that a element was traversed as part of computation of a scene. void traversed(const OctreeElement* element); /// Track that a element was skipped as part of computation of a scene due to being beyond the LOD distance. void skippedDistance(const OctreeElement* element); /// Track that a element was skipped as part of computation of a scene due to being out of view. void skippedOutOfView(const OctreeElement* element); /// Track that a element was skipped as part of computation of a scene due to previously being in view while in delta sending void skippedWasInView(const OctreeElement* element); /// Track that a element was skipped as part of computation of a scene due to not having changed since last full scene sent void skippedNoChange(const OctreeElement* element); /// Track that a element was skipped as part of computation of a scene due to being occluded void skippedOccluded(const OctreeElement* element); /// Track that a element's color was was sent as part of computation of a scene void colorSent(const OctreeElement* element); /// Track that a element was due to be sent, but didn't fit in the packet and was moved to next packet void didntFit(const OctreeElement* element); /// Track that the color bitmask was was sent as part of computation of a scene void colorBitsWritten(); /// Track that the exists in tree bitmask was was sent as part of computation of a scene void existsBitsWritten(); /// Track that the exists in packet bitmask was was sent as part of computation of a scene void existsInPacketBitsWritten(); /// Fix up tracking statistics in case where bitmasks were removed for some reason void childBitsRemoved(bool includesExistsBits, bool includesColors); /// Pack the details of the statistics into a buffer for sending as a network packet int packIntoMessage(unsigned char* destinationBuffer, int availableBytes); /// Unpack the details of the statistics from a buffer typically received as a network packet int unpackFromMessage(const unsigned char* sourceBuffer, int availableBytes); /// Indicates that a scene has been completed and the statistics are ready to be sent bool isReadyToSend() const { return _isReadyToSend; } /// Mark that the scene statistics have been sent void markAsSent() { _isReadyToSend = false; } unsigned char* getStatsMessage() { return &_statsMessage[0]; } int getStatsMessageLength() const { return _statsMessageLength; } /// List of various items tracked by OctreeSceneStats which can be accessed via getItemInfo() and getItemValue() enum Item { ITEM_ELAPSED, ITEM_ENCODE, ITEM_PACKETS, ITEM_VOXELS_SERVER, ITEM_VOXELS, ITEM_COLORS, ITEM_BITS, ITEM_TRAVERSED, ITEM_SKIPPED, ITEM_SKIPPED_DISTANCE, ITEM_SKIPPED_OUT_OF_VIEW, ITEM_SKIPPED_WAS_IN_VIEW, ITEM_SKIPPED_NO_CHANGE, ITEM_SKIPPED_OCCLUDED, ITEM_DIDNT_FIT, ITEM_MODE, ITEM_COUNT }; /// Meta information about each stats item struct ItemInfo { char const* const caption; unsigned colorRGBA; int detailsCount; const char* detailsLabels; }; /// Returns details about items tracked by OctreeSceneStats /// \param Item item The item from the stats you're interested in. ItemInfo& getItemInfo(Item item) { return _ITEMS[item]; } /// Returns a UI formatted value of an item tracked by OctreeSceneStats /// \param Item item The item from the stats you're interested in. const char* getItemValue(Item item); /// Returns OctCode for root element of the jurisdiction of this particular octree server unsigned char* getJurisdictionRoot() const { return _jurisdictionRoot; } /// Returns list of OctCodes for end elements of the jurisdiction of this particular octree server const std::vector& getJurisdictionEndNodes() const { return _jurisdictionEndNodes; } bool isMoving() const { return _isMoving; }; quint64 getTotalElements() const { return _totalElements; } quint64 getTotalInternal() const { return _totalInternal; } quint64 getTotalLeaves() const { return _totalLeaves; } quint64 getTotalEncodeTime() const { return _totalEncodeTime; } quint64 getElapsedTime() const { return _elapsed; } quint64 getLastFullElapsedTime() const { return _lastFullElapsed; } quint64 getLastFullTotalEncodeTime() const { return _lastFullTotalEncodeTime; } quint32 getLastFullTotalPackets() const { return _lastFullTotalPackets; } quint64 getLastFullTotalBytes() const { return _lastFullTotalBytes; } // Used in client implementations to track individual octree packets void trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec); quint32 getIncomingPackets() const { return _incomingPacket; } quint64 getIncomingBytes() const { return _incomingBytes; } quint64 getIncomingWastedBytes() const { return _incomingWastedBytes; } quint32 getIncomingOutOfOrder() const { return _incomingLate + _incomingEarly; } quint32 getIncomingLikelyLost() const { return _incomingLikelyLost; } quint32 getIncomingRecovered() const { return _incomingRecovered; } quint32 getIncomingEarly() const { return _incomingEarly; } quint32 getIncomingLate() const { return _incomingLate; } quint32 getIncomingReallyLate() const { return _incomingReallyLate; } quint32 getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; } float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); } const QSet& getMissingSequenceNumbers() const { return _missingSequenceNumbers; } private: void copyFromOther(const OctreeSceneStats& other); bool _isReadyToSend; unsigned char _statsMessage[MAX_PACKET_SIZE]; qint32 _statsMessageLength; // scene timing data in usecs bool _isStarted; quint64 _start; quint64 _end; quint64 _elapsed; quint64 _lastFullElapsed; quint64 _lastFullTotalEncodeTime; quint32 _lastFullTotalPackets; quint64 _lastFullTotalBytes; SimpleMovingAverage _elapsedAverage; SimpleMovingAverage _bitsPerOctreeAverage; quint64 _totalEncodeTime; quint64 _encodeStart; // scene octree related data quint64 _totalElements; quint64 _totalInternal; quint64 _totalLeaves; quint64 _traversed; quint64 _internal; quint64 _leaves; quint64 _skippedDistance; quint64 _internalSkippedDistance; quint64 _leavesSkippedDistance; quint64 _skippedOutOfView; quint64 _internalSkippedOutOfView; quint64 _leavesSkippedOutOfView; quint64 _skippedWasInView; quint64 _internalSkippedWasInView; quint64 _leavesSkippedWasInView; quint64 _skippedNoChange; quint64 _internalSkippedNoChange; quint64 _leavesSkippedNoChange; quint64 _skippedOccluded; quint64 _internalSkippedOccluded; quint64 _leavesSkippedOccluded; quint64 _colorSent; quint64 _internalColorSent; quint64 _leavesColorSent; quint64 _didntFit; quint64 _internalDidntFit; quint64 _leavesDidntFit; quint64 _colorBitsWritten; quint64 _existsBitsWritten; quint64 _existsInPacketBitsWritten; quint64 _treesRemoved; // Accounting Notes: // // 1) number of octrees sent can be calculated as _colorSent + _colorBitsWritten. This works because each internal // element in a packet will have a _colorBitsWritten included for it and each "leaf" in the packet will have a // _colorSent written for it. Note that these "leaf" elements in the packets may not be actual leaves in the full // tree, because LOD may cause us to send an average color for an internal element instead of recursing deeper to // the leaves. // // 2) the stats balance if: (working assumption) // if _colorSent > 0 // _traversed = all skipped + _colorSent + _colorBitsWritten // else // _traversed = all skipped + _colorSent + _colorBitsWritten + _treesRemoved // // scene network related data quint32 _packets; quint64 _bytes; quint32 _passes; // incoming packets stats quint32 _incomingPacket; quint64 _incomingBytes; quint64 _incomingWastedBytes; quint16 _incomingLastSequence; /// last incoming sequence number quint32 _incomingLikelyLost; /// count of packets likely lost, may be off by _incomingReallyLate count quint32 _incomingRecovered; /// packets that were late, and we had in our missing list, we consider recovered quint32 _incomingEarly; /// out of order earlier than expected quint32 _incomingLate; /// out of order later than expected quint32 _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late quint32 _incomingPossibleDuplicate; /// out of order possibly a duplicate QSet _missingSequenceNumbers; SimpleMovingAverage _incomingFlightTimeAverage; // features related items bool _isMoving; bool _isFullScene; static ItemInfo _ITEMS[]; static const int MAX_ITEM_VALUE_LENGTH = 128; char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH]; unsigned char* _jurisdictionRoot; std::vector _jurisdictionEndNodes; }; /// Map between element IDs and their reported OctreeSceneStats. Typically used by classes that need to know which elements sent /// which octree stats typedef std::map NodeToOctreeSceneStats; typedef std::map::iterator NodeToOctreeSceneStatsIterator; #endif // hifi_OctreeSceneStats_h