260 lines
8.7 KiB
C++
260 lines
8.7 KiB
C++
#pragma once
|
|
|
|
#include <Cesium3DTilesSelection/TileLoadRequester.h>
|
|
#include <Cesium3DTilesSelection/TileLoadTask.h>
|
|
#include <Cesium3DTilesSelection/TileSelectionState.h>
|
|
#include <Cesium3DTilesSelection/ViewUpdateResult.h>
|
|
#include <CesiumUtility/CreditReferencer.h>
|
|
#include <CesiumUtility/IntrusivePointer.h>
|
|
#include <CesiumUtility/TreeTraversalState.h>
|
|
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace Cesium3DTilesSelection {
|
|
|
|
class GltfModifier;
|
|
class Tile;
|
|
class Tileset;
|
|
class TilesetContentManager;
|
|
class TilesetFrameState;
|
|
|
|
/**
|
|
* @brief Represents a group of views that collectively select tiles from a
|
|
* particular {@link Tileset}.
|
|
*
|
|
* Create an instance of this class and pass it repeatedly to
|
|
* {@link Tileset::updateViewGroup} to select tiles suitable for rendering the
|
|
* tileset from a given view or set of views.
|
|
*
|
|
* This class is intentionally decoupled from {@link ViewState}, such that
|
|
* clients are responsible for managing which views are represented by
|
|
* any particular group.
|
|
*/
|
|
class CESIUM3DTILESSELECTION_API TilesetViewGroup final
|
|
: public TileLoadRequester {
|
|
public:
|
|
/**
|
|
* @brief The type of the {@link CesiumUtility::TreeTraversalState}
|
|
* used to track tile selection states for this view group.
|
|
*/
|
|
using TraversalState =
|
|
CesiumUtility::TreeTraversalState<Tile::Pointer, TileSelectionState>;
|
|
|
|
/**
|
|
* @brief Constructs a new instance.
|
|
*/
|
|
TilesetViewGroup() noexcept;
|
|
|
|
/**
|
|
* @brief Constructs a new instance as a copy of an existing one.
|
|
*
|
|
* The new instance will be equivalent to the existing one, but it will not be
|
|
* registered with the {@link Cesium3DTilesSelection::Tileset}.
|
|
*
|
|
* @param rhs The view group to copy.
|
|
*/
|
|
TilesetViewGroup(const TilesetViewGroup& rhs) noexcept;
|
|
|
|
/**
|
|
* @brief Moves an existing view group into a new one.
|
|
*
|
|
* The new instance will be registered with the
|
|
* {@link Cesium3DTilesSelection::Tileset}, and the old one will be
|
|
* unregistered.
|
|
*
|
|
* @param rhs The view group to move from.
|
|
*/
|
|
TilesetViewGroup(TilesetViewGroup&& rhs) noexcept;
|
|
virtual ~TilesetViewGroup() noexcept;
|
|
|
|
/**
|
|
* @brief Gets the result from the last time this view group was updated by
|
|
* calling {@link Tileset::updateViewGroup}.
|
|
*/
|
|
const ViewUpdateResult& getViewUpdateResult() const;
|
|
|
|
/** @copydoc getViewUpdateResult */
|
|
ViewUpdateResult& getViewUpdateResult();
|
|
|
|
/**
|
|
* @brief Gets an object used to track the selection state of tiles as they
|
|
* are traversed for this view group.
|
|
*/
|
|
TraversalState& getTraversalState() noexcept { return this->_traversalState; }
|
|
|
|
/** @copydoc getTraversalState */
|
|
const TraversalState& getTraversalState() const noexcept {
|
|
return this->_traversalState;
|
|
}
|
|
|
|
/**
|
|
* @brief Adds a tile load task to this view group's load queue.
|
|
*
|
|
* Each tile may only be added once per call to {@link startNewFrame}. Adding
|
|
* a tile multiple times will lead to an assertion in debug builds and
|
|
* undefined behavior in release builds.
|
|
*
|
|
* @param task The tile load task to add to the queue.
|
|
* @param pModifier The optional glTF modifier. If not `nullptr`, this method
|
|
* will also add the tile to load queue if it needs glTF modification. See
|
|
* {@link TilesetExternals::pGltfModifier}.
|
|
*/
|
|
void addToLoadQueue(
|
|
const TileLoadTask& task,
|
|
const std::shared_ptr<GltfModifier>& pModifier = nullptr);
|
|
|
|
/**
|
|
* @brief A checkpoint within this view group's load queue.
|
|
*
|
|
* A checkpoint can be created by calling {@link saveTileLoadQueueCheckpoint}.
|
|
* Later, calling {@link restoreTileLoadQueueCheckpoint} will remove all
|
|
* tiles from the queue that were added since the checkpoint was saved.
|
|
*/
|
|
struct LoadQueueCheckpoint {
|
|
private:
|
|
size_t mainThread;
|
|
size_t workerThread;
|
|
friend class TilesetViewGroup;
|
|
};
|
|
|
|
/**
|
|
* @brief Saves a checkpoint of the tile load queue associated with this view
|
|
* group.
|
|
*
|
|
* The saved checkpoint can later be restored by calling
|
|
* {@link restoreTileLoadQueueCheckpoint}.
|
|
*
|
|
* This method should only be called in between calls to {@link startNewFrame}
|
|
* and {@link finishFrame}.
|
|
*
|
|
* @return The checkpoint.
|
|
*/
|
|
LoadQueueCheckpoint saveTileLoadQueueCheckpoint();
|
|
|
|
/**
|
|
* @brief Restores a previously-saved checkpoint of the tile load queue
|
|
* associated with this view group.
|
|
*
|
|
* Restoring a checkpoint discards all tiles from the queue that were
|
|
* requested, with a call to {@link addToLoadQueue}, since the checkpoint was
|
|
* created.
|
|
*
|
|
* This method should only be called in between calls to {@link startNewFrame}
|
|
* and {@link finishFrame}.
|
|
*
|
|
* @param checkpoint The previously-created checkpoint.
|
|
* @return The number of tiles that were discarded from the queue as a result
|
|
* of restoring the checkpoint.
|
|
*/
|
|
size_t restoreTileLoadQueueCheckpoint(const LoadQueueCheckpoint& checkpoint);
|
|
|
|
/**
|
|
* @brief Gets the number of tiles that are currently in the queue waiting to
|
|
* be loaded in the worker thread.
|
|
*/
|
|
size_t getWorkerThreadLoadQueueLength() const;
|
|
|
|
/**
|
|
* @brief Gets the number of tiles that are currently in the queue waiting to
|
|
* be loaded in the main thread.
|
|
*/
|
|
size_t getMainThreadLoadQueueLength() const;
|
|
|
|
/**
|
|
* @brief Starts a new frame.
|
|
*
|
|
* This method clears the set of tiles to be loaded so that a new set can be
|
|
* selected. It also makes the current tile selection state the previous one
|
|
* and releases references to tiles in the old previous one.
|
|
*
|
|
* @param tileset The tileset that is starting the new frame.
|
|
* @param frameState The state of the new frame.
|
|
*/
|
|
void
|
|
startNewFrame(const Tileset& tileset, const TilesetFrameState& frameState);
|
|
|
|
/**
|
|
* @brief Finishes the current frame.
|
|
*
|
|
* This method updates the load progress percentage returned by
|
|
* {@link getPreviousLoadProgressPercentage} and makes sure credits used by
|
|
* this view group have been referenced on the
|
|
* {@link CesiumUtility::CreditSystem}.
|
|
*
|
|
* @param tileset The tileset that is finishing the current frame.
|
|
* @param frameState The state of the frame.
|
|
*/
|
|
void finishFrame(const Tileset& tileset, const TilesetFrameState& frameState);
|
|
|
|
/**
|
|
* @brief Gets the previous load progress percentage for this view group as
|
|
* of the last time it was updated.
|
|
*
|
|
* This method reports the progress as of the last call to {@link finishFrame}.
|
|
*
|
|
* The reported percentage is computed as:
|
|
*
|
|
* \f$100.0\frac{totalTilesVisited - tilesNeedingLoading}{totalTilesVisited}\f$
|
|
*
|
|
* When loading is complete, this method will return exactly 100.0.
|
|
*/
|
|
float getPreviousLoadProgressPercentage() const;
|
|
|
|
/** @inheritdoc */
|
|
double getWeight() const override;
|
|
|
|
/**
|
|
* @brief Sets the weight of this view group relative to other tile
|
|
* requesters.
|
|
*
|
|
* See {@link getWeight} for an explanation of the meaning of the weight.
|
|
*
|
|
* @param weight The new weight for this view group.
|
|
*/
|
|
void setWeight(double weight) noexcept;
|
|
|
|
/** @inheritdoc */
|
|
bool hasMoreTilesToLoadInWorkerThread() const override;
|
|
/** @inheritdoc */
|
|
const Tile* getNextTileToLoadInWorkerThread() override;
|
|
|
|
/** @inheritdoc */
|
|
bool hasMoreTilesToLoadInMainThread() const override;
|
|
/** @inheritdoc */
|
|
const Tile* getNextTileToLoadInMainThread() override;
|
|
|
|
/**
|
|
* @brief Checks if a given credit is referenced in the most recently
|
|
* completed frame.
|
|
*
|
|
* Note that this method checks the most recently _completed_ frame. So, after
|
|
* a call to @ref finishFrame (the common case), this method will check the
|
|
* frame that was just finished. If called in between calls to @ref
|
|
* startNewFrame and @ref finishFrame (i.e., during the course of a call to
|
|
* @ref Tileset::updateViewGroup), it will check the frame prior to the
|
|
* current, in-progress one, because the current one has not yet been
|
|
* completed.
|
|
*
|
|
* @param credit The credit to test.
|
|
* @return True if the credit was referenced in this view group's most
|
|
* recently completed frame.
|
|
*/
|
|
bool isCreditReferenced(CesiumUtility::Credit credit) const noexcept;
|
|
|
|
private:
|
|
double _weight = 1.0;
|
|
std::vector<TileLoadTask> _mainThreadLoadQueue;
|
|
std::vector<TileLoadTask> _workerThreadLoadQueue;
|
|
size_t _tilesAlreadyLoadingOrUnloading = 0;
|
|
float _loadProgressPercentage = 0.0f;
|
|
ViewUpdateResult _updateResult;
|
|
TraversalState _traversalState;
|
|
CesiumUtility::CreditReferencer _previousFrameCredits;
|
|
CesiumUtility::CreditReferencer _currentFrameCredits;
|
|
};
|
|
|
|
} // namespace Cesium3DTilesSelection
|