468 lines · 13.3 KB · C
RawDownload
////  MetavoxelSystem.h//  interface/src////  Created by Andrzej Kapolka on 12/10/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_MetavoxelSystem_h#define hifi_MetavoxelSystem_h #include <QList>#include <QOpenGLBuffer>#include <QReadWriteLock>#include <QVector> #include <glm/glm.hpp> #include <MetavoxelClientManager.h> #include "renderer/ProgramObject.h" class HeightfieldBaseLayerBatch;class HeightfieldSplatBatch;class HermiteBatch;class Model;class VoxelBatch;class VoxelSplatBatch; /// Renders a metavoxel tree.class MetavoxelSystem : public MetavoxelClientManager {    Q_OBJECT public:     class NetworkSimulation {    public:        float dropRate;        float repeatRate;        int minimumDelay;        int maximumDelay;        int bandwidthLimit;                NetworkSimulation(float dropRate = 0.0f, float repeatRate = 0.0f, int minimumDelay = 0,            int maximumDelay = 0, int bandwidthLimit = 0);    };     virtual ~MetavoxelSystem();     virtual void init();     virtual MetavoxelLOD getLOD();     const Frustum& getFrustum() const { return _frustum; }        void setNetworkSimulation(const NetworkSimulation& simulation);    NetworkSimulation getNetworkSimulation();        const AttributePointer& getHeightfieldBufferAttribute() { return _heightfieldBufferAttribute; }    const AttributePointer& getVoxelBufferAttribute() { return _voxelBufferAttribute; }        void simulate(float deltaTime);    void render();     void renderHeightfieldCursor(const glm::vec3& position, float radius);     void renderVoxelCursor(const glm::vec3& position, float radius);     bool findFirstRayVoxelIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance);     Q_INVOKABLE void paintHeightfieldColor(const glm::vec3& position, float radius, const QColor& color);     Q_INVOKABLE void paintHeightfieldMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material);            Q_INVOKABLE void paintVoxelColor(const glm::vec3& position, float radius, const QColor& color);        Q_INVOKABLE void paintVoxelMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material);            Q_INVOKABLE void setVoxelColor(const SharedObjectPointer& spanner, const QColor& color);            Q_INVOKABLE void setVoxelMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material);        void addHeightfieldBaseBatch(const HeightfieldBaseLayerBatch& batch) { _heightfieldBaseBatches.append(batch); }    void addHeightfieldSplatBatch(const HeightfieldSplatBatch& batch) { _heightfieldSplatBatches.append(batch); }        void addVoxelBaseBatch(const VoxelBatch& batch) { _voxelBaseBatches.append(batch); }    void addVoxelSplatBatch(const VoxelSplatBatch& batch) { _voxelSplatBatches.append(batch); }        void addHermiteBatch(const HermiteBatch& batch) { _hermiteBatches.append(batch); }     Q_INVOKABLE void deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const;        signals:     void rendering(); public slots:     void refreshVoxelData(); protected:     Q_INVOKABLE void applyMaterialEdit(const MetavoxelEditMessage& message, bool reliable = false);     virtual MetavoxelClient* createClient(const SharedNodePointer& node); private:        void guideToAugmented(MetavoxelVisitor& visitor, bool render = false);        AttributePointer _heightfieldBufferAttribute;    AttributePointer _voxelBufferAttribute;        MetavoxelLOD _lod;    QReadWriteLock _lodLock;    Frustum _frustum;        NetworkSimulation _networkSimulation;    QReadWriteLock _networkSimulationLock;        QVector<HeightfieldBaseLayerBatch> _heightfieldBaseBatches;    QVector<HeightfieldSplatBatch> _heightfieldSplatBatches;    QVector<VoxelBatch> _voxelBaseBatches;    QVector<VoxelSplatBatch> _voxelSplatBatches;    QVector<HermiteBatch> _hermiteBatches;        ProgramObject _baseHeightfieldProgram;    int _baseHeightScaleLocation;    int _baseColorScaleLocation;        class SplatLocations {    public:        int heightScale;        int textureScale;        int splatTextureOffset;        int splatTextureScalesS;        int splatTextureScalesT;        int textureValueMinima;        int textureValueMaxima;        int materials;        int materialWeights;    };        ProgramObject _splatHeightfieldProgram;    SplatLocations _splatHeightfieldLocations;        int _splatHeightScaleLocation;    int _splatTextureScaleLocation;    int _splatTextureOffsetLocation;    int _splatTextureScalesSLocation;    int _splatTextureScalesTLocation;    int _splatTextureValueMinimaLocation;    int _splatTextureValueMaximaLocation;        ProgramObject _heightfieldCursorProgram;        ProgramObject _baseVoxelProgram;    ProgramObject _splatVoxelProgram;    SplatLocations _splatVoxelLocations;        ProgramObject _voxelCursorProgram;        static void loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations);}; /// Base class for heightfield batches.class HeightfieldBatch {public:    QOpenGLBuffer* vertexBuffer;    QOpenGLBuffer* indexBuffer;    glm::vec3 translation;    glm::quat rotation;    glm::vec3 scale;    int vertexCount;    int indexCount;    GLuint heightTextureID;    glm::vec4 heightScale;}; /// A batch containing a heightfield base layer. class HeightfieldBaseLayerBatch : public HeightfieldBatch {public:    GLuint colorTextureID;    glm::vec2 colorScale;}; /// A batch containing a heightfield splat.class HeightfieldSplatBatch : public HeightfieldBatch {public:    GLuint materialTextureID;    glm::vec2 textureScale;    glm::vec2 splatTextureOffset;    int splatTextureIDs[4];    glm::vec4 splatTextureScalesS;    glm::vec4 splatTextureScalesT;    int materialIndex;}; /// Base class for voxel batches.class VoxelBatch {public:    QOpenGLBuffer* vertexBuffer;    QOpenGLBuffer* indexBuffer;    int vertexCount;    int indexCount;}; /// A batch containing a voxel splat.class VoxelSplatBatch : public VoxelBatch {public:    int splatTextureIDs[4];    glm::vec4 splatTextureScalesS;    glm::vec4 splatTextureScalesT;    int materialIndex;}; /// A batch containing Hermite data for debugging.class HermiteBatch {public:    QOpenGLBuffer* vertexBuffer;    int vertexCount;}; /// Generic abstract base class for objects that handle a signal.class SignalHandler : public QObject {    Q_OBJECT    public slots:        virtual void handle() = 0;}; /// Simple throttle for limiting bandwidth on a per-second basis.class Throttle {public:        Throttle();        /// Sets the per-second limit.    void setLimit(int limit) { _limit = limit; }        /// Determines whether the message with the given size should be throttled (discarded).  If not, registers the message    /// as having been processed (i.e., contributing to later throttling).    bool shouldThrottle(int bytes); private:        int _limit;    int _total;        typedef QPair<qint64, int> Bucket;    QList<Bucket> _buckets;}; /// A client session associated with a single server.class MetavoxelSystemClient : public MetavoxelClient {    Q_OBJECT        public:        MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater);        Q_INVOKABLE void setAugmentedData(const MetavoxelData& data);        /// Returns a copy of the augmented data.  This function is thread-safe.    MetavoxelData getAugmentedData();        void setRenderedAugmentedData(const MetavoxelData& data) { _renderedAugmentedData = data; }     virtual int parseData(const QByteArray& packet);     Q_INVOKABLE void refreshVoxelData();    protected:        virtual void dataChanged(const MetavoxelData& oldData);    virtual void sendDatagram(const QByteArray& data); private:        MetavoxelData _augmentedData;    MetavoxelData _renderedAugmentedData;    QReadWriteLock _augmentedDataLock;        Throttle _sendThrottle;    Throttle _receiveThrottle;}; /// Base class for cached static buffers.class BufferData : public QSharedData {public:        virtual ~BufferData();     virtual void render(bool cursor = false) = 0;}; typedef QExplicitlySharedDataPointer<BufferData> BufferDataPointer; /// Describes contents of a vertex in a voxel buffer.class VoxelPoint {public:    glm::vec3 vertex;    quint8 color[3];    char normal[3];    quint8 materials[4];    quint8 materialWeights[4];        void setNormal(const glm::vec3& normal);}; /// A container for a coordinate within a voxel block.class VoxelCoord {public:    QRgb encoded;        VoxelCoord(QRgb encoded) : encoded(encoded) { }        bool operator==(const VoxelCoord& other) const { return encoded == other.encoded; }}; inline uint qHash(const VoxelCoord& coord, uint seed) {    // multiply by prime numbers greater than the possible size    return qHash(qRed(coord.encoded) + 257 * (qGreen(coord.encoded) + 263 * qBlue(coord.encoded)), seed);} /// Contains the information necessary to render a voxel block.class VoxelBuffer : public BufferData {public:        VoxelBuffer(const QVector<VoxelPoint>& vertices, const QVector<int>& indices, const QVector<glm::vec3>& hermite,        const QMultiHash<VoxelCoord, int>& quadIndices, int size, const QVector<SharedObjectPointer>& materials =            QVector<SharedObjectPointer>());     /// Finds the first intersection between the described ray and the voxel data.    /// \param entry the entry point of the ray in relative coordinates, from (0, 0, 0) to (1, 1, 1)    bool findFirstRayIntersection(const glm::vec3& entry, const glm::vec3& origin,        const glm::vec3& direction, float& distance) const;            virtual void render(bool cursor = false); private:        QVector<VoxelPoint> _vertices;    QVector<int> _indices;    QVector<glm::vec3> _hermite;    QMultiHash<VoxelCoord, int> _quadIndices;    int _size;    int _vertexCount;    int _indexCount;    int _hermiteCount;    QOpenGLBuffer _vertexBuffer;    QOpenGLBuffer _indexBuffer;    QOpenGLBuffer _hermiteBuffer;    QVector<SharedObjectPointer> _materials;    QVector<NetworkTexturePointer> _networkTextures;}; /// A client-side attribute that stores renderable buffers.class BufferDataAttribute : public InlineAttribute<BufferDataPointer> {    Q_OBJECT    public:        Q_INVOKABLE BufferDataAttribute(const QString& name = QString());        virtual bool merge(void*& parent, void* children[], bool postRead = false) const;        virtual AttributeValue inherit(const AttributeValue& parentValue) const;}; /// Renders metavoxels as points.class DefaultMetavoxelRendererImplementation : public MetavoxelRendererImplementation {    Q_OBJECT public:        Q_INVOKABLE DefaultMetavoxelRendererImplementation();        virtual void augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod);    virtual void simulate(MetavoxelData& data, float deltaTime, MetavoxelInfo& info, const MetavoxelLOD& lod);    virtual void render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod);}; /// Renders spheres.class SphereRenderer : public SpannerRenderer {    Q_OBJECT public:        Q_INVOKABLE SphereRenderer();        virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false);}; /// Renders cuboids.class CuboidRenderer : public SpannerRenderer {    Q_OBJECT public:        Q_INVOKABLE CuboidRenderer();        virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false);}; /// Renders static models.class StaticModelRenderer : public SpannerRenderer {    Q_OBJECT public:        Q_INVOKABLE StaticModelRenderer();        virtual void init(Spanner* spanner);    virtual void simulate(float deltaTime);    virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false);    virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; private slots:     void applyTranslation(const glm::vec3& translation);    void applyRotation(const glm::quat& rotation);    void applyScale(float scale);    void applyURL(const QUrl& url); private:        Model* _model;}; /// Renders heightfields.class HeightfieldRenderer : public SpannerRenderer {    Q_OBJECT public:        Q_INVOKABLE HeightfieldRenderer();        virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false);}; /// Renders a single quadtree node.class HeightfieldNodeRenderer : public AbstractHeightfieldNodeRenderer {public:        HeightfieldNodeRenderer();    virtual ~HeightfieldNodeRenderer();        void render(const HeightfieldNodePointer& node, const glm::vec3& translation,        const glm::quat& rotation, const glm::vec3& scale, bool cursor);    private:     GLuint _heightTextureID;    GLuint _colorTextureID;    GLuint _materialTextureID;    QVector<NetworkTexturePointer> _networkTextures;        typedef QPair<int, int> IntPair;        typedef QPair<QOpenGLBuffer, QOpenGLBuffer> BufferPair;    static QHash<IntPair, BufferPair> _bufferPairs;}; #endif // hifi_MetavoxelSystem_h