// // RenderablePolyVoxEntityItem.h // libraries/entities-renderer/src/ // // Created by Seth Alves on 5/19/15. // Copyright 2015 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_RenderablePolyVoxEntityItem_h #define hifi_RenderablePolyVoxEntityItem_h #include #include #include #include #include #include #include #include #include #include #include "RenderableEntityItem.h" namespace render { namespace entities { class PolyVoxEntityRenderer; } } class RenderablePolyVoxEntityItem : public PolyVoxEntityItem { friend class render::entities::PolyVoxEntityRenderer; public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderablePolyVoxEntityItem(const EntityItemID& entityItemID); virtual ~RenderablePolyVoxEntityItem(); void initializePolyVox(); using PolyVoxEntityItem::getVoxel; virtual uint8_t getVoxel(const ivec3& v) const override; using PolyVoxEntityItem::setVoxel; virtual bool setVoxel(const ivec3& v, uint8_t toValue) override; int getOnCount() const override { return _onCount; } virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const override; virtual void setVoxelData(const QByteArray& voxelData) override; virtual void setVoxelVolumeSize(const glm::vec3& voxelVolumeSize) override; virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) override; glm::vec3 getSurfacePositionAdjustment() const; glm::mat4 voxelToWorldMatrix() const; glm::mat4 worldToVoxelMatrix() const; glm::mat4 voxelToLocalMatrix() const; glm::mat4 localToVoxelMatrix() const; virtual ShapeType getShapeType() const override; virtual bool shouldBePhysical() const override { return !isDead(); } virtual bool isReadyToComputeShape() const override; virtual void computeShapeInfo(ShapeInfo& info) override; // coords are in voxel-volume space virtual bool setSphereInVolume(const vec3& center, float radius, uint8_t toValue) override; virtual bool setVoxelInVolume(const vec3& position, uint8_t toValue) override; // coords are in world-space virtual bool setSphere(const vec3& center, float radius, uint8_t toValue) override; virtual bool setCapsule(const vec3& startWorldCoords, const vec3& endWorldCoords, float radiusWorldCoords, uint8_t toValue) override; virtual bool setAll(uint8_t toValue) override; virtual bool setCuboid(const vec3& lowPosition, const vec3& cuboidSize, int toValue) override; virtual void setXNNeighborID(const EntityItemID& xNNeighborID) override; virtual void setYNNeighborID(const EntityItemID& yNNeighborID) override; virtual void setZNNeighborID(const EntityItemID& zNNeighborID) override; virtual void setXPNeighborID(const EntityItemID& xPNeighborID) override; virtual void setYPNeighborID(const EntityItemID& yPNeighborID) override; virtual void setZPNeighborID(const EntityItemID& zPNeighborID) override; std::shared_ptr getXNNeighbor(); std::shared_ptr getYNNeighbor(); std::shared_ptr getZNNeighbor(); std::shared_ptr getXPNeighbor(); std::shared_ptr getYPNeighbor(); std::shared_ptr getZPNeighbor(); virtual void setRegistrationPoint(const glm::vec3& value) override; void setVoxelsFromData(QByteArray uncompressedData, quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize); void forEachVoxelValue(const ivec3& voxelSize, std::function thunk); QByteArray volDataToArray(quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize) const; void setMesh(model::MeshPointer mesh); void setCollisionPoints(ShapeInfo::PointCollection points, AABox box); PolyVox::SimpleVolume* getVolData() { return _volData.get(); } uint8_t getVoxelInternal(const ivec3& v) const; bool setVoxelInternal(const ivec3& v, uint8_t toValue); void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); } bool getMeshes(MeshProxyList& result) override; private: bool updateOnCount(const ivec3& v, uint8_t toValue); PolyVox::RaycastResult doRayCast(glm::vec4 originInVoxel, glm::vec4 farInVoxel, glm::vec4& result) const; void recomputeMesh(); void cacheNeighbors(); void copyUpperEdgesFromNeighbors(); void bonkNeighbors(); bool updateDependents(); // these are run off the main thread void decompressVolumeData(); void compressVolumeDataAndSendEditPacket(); void computeShapeInfoWorker(); // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // may not match _voxelVolumeSize. bool _meshDirty { true }; // does collision-shape need to be recomputed? bool _meshReady{ false }; model::MeshPointer _mesh; ShapeInfo _shapeInfo; std::shared_ptr> _volData; bool _voxelDataDirty{ true }; bool _volDataDirty { false }; // does recomputeMesh need to be called? int _onCount; // how many non-zero voxels are in _volData bool _neighborsNeedUpdate { false }; // these are cached lookups of _xNNeighborID, _yNNeighborID, _zNNeighborID, _xPNeighborID, _yPNeighborID, _zPNeighborID EntityItemWeakPointer _xNNeighbor; // neighbor found by going along negative X axis EntityItemWeakPointer _yNNeighbor; EntityItemWeakPointer _zNNeighbor; EntityItemWeakPointer _xPNeighbor; // neighbor found by going along positive X axis EntityItemWeakPointer _yPNeighbor; EntityItemWeakPointer _zPNeighbor; }; namespace render { namespace entities { class PolyVoxEntityRenderer : public TypedEntityRenderer { using Parent = TypedEntityRenderer; friend class EntityRenderer; public: PolyVoxEntityRenderer(const EntityItemPointer& entity); protected: virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape(); } virtual ShapeKey getShapeKey() override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override { return false; } private: #ifdef POLYVOX_ENTITY_USE_FADE_EFFECT bool _hasTransitioned{ false }; #endif model::MeshPointer _mesh; std::array _xyzTextures; glm::vec3 _lastVoxelVolumeSize; glm::mat4 _lastVoxelToWorldMatrix; PolyVoxEntityItem::PolyVoxSurfaceStyle _lastSurfaceStyle { PolyVoxEntityItem::SURFACE_MARCHING_CUBES }; std::array _xyzTextureUrls; bool _neighborsNeedUpdate{ false }; }; } } #endif // hifi_RenderablePolyVoxEntityItem_h