Overte C++ Documentation
RenderableEntityItem.h
1 //
2 // RenderableEntityItem.h
3 // interface/src
4 //
5 // Created by Brad Hefta-Gaub on 12/6/13.
6 // Copyright 2013 High Fidelity, Inc.
7 // Copyright 2024 Overte e.V.
8 //
9 // Distributed under the Apache License, Version 2.0.
10 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11 //
12 
13 #ifndef hifi_RenderableEntityItem_h
14 #define hifi_RenderableEntityItem_h
15 
16 #include <render/Scene.h>
17 #include <render/HighlightStyle.h>
18 
19 #include <EntityItem.h>
20 #include <Sound.h>
21 #include "AbstractViewStateInterface.h"
22 #include "EntitiesRendererLogging.h"
23 #include <graphics-scripting/Forward.h>
24 #include <RenderHifi.h>
25 #include "EntityTreeRenderer.h"
26 #include "FadeObjectParams.shared.slh"
27 
28 class EntityTreeRenderer;
29 
30 namespace render { namespace entities {
31 
32 // Base class for all renderable entities
33 class EntityRenderer : public QObject, public std::enable_shared_from_this<EntityRenderer>, public PayloadProxyInterface, protected ReadWriteLockable, public scriptable::ModelProvider {
34  Q_OBJECT
35 
36  using Pointer = std::shared_ptr<EntityRenderer>;
37 
38 public:
39  static void initEntityRenderers();
40  static Pointer addToScene(EntityTreeRenderer& renderer, const EntityItemPointer& entity, const ScenePointer& scene, Transaction& transaction);
41 
42  // Allow classes to override this to interact with the user
43  virtual bool wantsHandControllerPointerEvents() const { return false; }
44  virtual bool wantsKeyboardFocus() const { return false; }
45  virtual void setProxyWindow(QWindow* proxyWindow) {}
46  virtual QObject* getEventHandler() { return nullptr; }
47  virtual void emitScriptEvent(const QVariant& message) {}
48  const EntityItemPointer& getEntity() const { return _entity; }
49  const ItemID& getRenderItemID() const { return _renderItemID; }
50 
51  const SharedSoundPointer& getCollisionSound() { return _collisionSound; }
52  void setCollisionSound(const SharedSoundPointer& sound) { _collisionSound = sound; }
53 
54  // Handlers for rendering events... executed on the main thread, only called by EntityTreeRenderer,
55  // cannot be overridden or accessed by subclasses
56  virtual void updateInScene(const ScenePointer& scene, Transaction& transaction) final;
57  virtual bool addToScene(const ScenePointer& scene, Transaction& transaction) final;
58  virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction);
59 
60  virtual void fade(render::Transaction& transaction, TransitionType type);
61 
62  const uint64_t& getUpdateTime() const { return _updateTime; }
63 
64  enum class Pipeline {
65  SIMPLE,
66  MATERIAL,
67  PROCEDURAL,
68  MIRROR
69  };
70  virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName);
71  virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName);
72  virtual graphics::MaterialPointer getTopMaterial();
73  Pipeline getPipelineType(const graphics::MultiMaterial& materials);
74  virtual gpu::TexturePointer getTexture() { return nullptr; }
75 
76  virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); }
77 
78  static glm::vec4 calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start);
79  static glm::vec3 calculatePulseColor(const glm::vec3& color, const PulsePropertyGroup& pulseProperties, quint64 start);
80 
81  virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override;
82  virtual Item::Bound getBound(RenderArgs* args) override;
83  bool passesZoneOcclusionTest(const std::unordered_set<QUuid>& containingZones) const override;
84  ItemID computeMirrorView(ViewFrustum& viewFrustum) const override;
85  static ItemID computeMirrorViewOperator(ViewFrustum& viewFrustum, const glm::vec3& inPropertiesPosition, const glm::quat& inPropertiesRotation,
86  MirrorMode mirrorMode, const QUuid& portalExitID);
87  virtual void renderSimulate(RenderArgs* args) override {}
88  virtual HighlightStyle getOutlineStyle(const ViewFrustum& viewFrustum, const size_t height) const override;
89 
90  virtual FadeProperties getFadeProperties(const TransitionType type) const override;
91  // Non-world layer entities do not currently support fading
92  virtual ComponentMode getFadeOutMode() const { return _renderLayer == RenderLayer::WORLD ? _fadeOutMode : ComponentMode::COMPONENT_MODE_DISABLED; }
93 
94 protected:
95  virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); }
96  virtual void onAddToScene(const EntityItemPointer& entity);
97  virtual void onRemoveFromScene(const EntityItemPointer& entity);
98 
99  EntityRenderer(const EntityItemPointer& entity);
100  ~EntityRenderer();
101 
102  // Implementing the PayloadProxyInterface methods
103  virtual ItemKey getKey() override;
104  virtual ShapeKey getShapeKey() override;
105  virtual void render(RenderArgs* args) override final;
106  virtual render::hifi::Tag getTagMask() const;
107  virtual render::hifi::Layer getHifiRenderLayer() const;
108 
109  // Returns true if the item in question needs to have updateInScene called because of internal rendering state changes
110  virtual bool needsRenderUpdate() const;
111 
112  // Returns true if the item in question needs to have updateInScene called because of changes in the entity
113  virtual bool needsRenderUpdateFromEntity(const EntityItemPointer& entity) const;
114 
115  // Will be called on the main thread from updateInScene. This can be used to fetch things like
116  // network textures or model geometry from resource caches
117  virtual void doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity);
118 
119  // Will be called by the lambda posted to the scene in updateInScene.
120  // This function will execute on the rendering thread, so you cannot use network caches to fetch
121  // data in this method if using multi-threaded rendering
122  virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity);
123 
124  // Called by the `render` method after `needsRenderUpdate`
125  virtual void doRender(RenderArgs* args) = 0;
126 
127  virtual void updateModelTransformAndBound(const EntityItemPointer& entity);
128  virtual bool isTransparent() const { return false; }
129  inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
130 
131  virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
132  virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
133  virtual void setCullWithParent(bool value) { _cullWithParent = value; }
134  virtual void setMirrorMode(MirrorMode value) { _mirrorMode = value; }
135  virtual void setPortalExitID(const QUuid& value) { _portalExitID = value; }
136 
137  template<typename T>
138  std::shared_ptr<T> asTypedEntity() { return std::static_pointer_cast<T>(_entity); }
139 
140  static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters);
141  const Transform& getModelTransform() const;
142 
143  Transform getTransformToCenterWithMaybeOnlyLocalRotation(const EntityItemPointer& entity, bool& success) const;
144 
145  FadeObjectParams getFadeParams(const render::ScenePointer& scene) const;
146 
147  // Shared methods for entities that support materials
148  using MaterialMap = std::unordered_map<std::string, graphics::MultiMaterial>;
149  bool needsRenderUpdateFromMaterials() const;
150  void updateMaterials(bool baseMaterialChanged = false);
151  bool materialsTransparent() const;
152  Item::Bound getMaterialBound(RenderArgs* args);
153  void updateItemKeyBuilderFromMaterials(ItemKey::Builder& builder);
154  void updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& builder);
155 
156  Item::Bound _bound;
157  SharedSoundPointer _collisionSound;
158  QUuid _changeHandlerId;
159  ItemID _renderItemID{ Item::INVALID_ITEM_ID };
160  uint64_t _updateTime{ usecTimestampNow() }; // used when sorting/throttling render updates
161  bool _prevIsTransparent { false };
162  bool _visible { false };
163  bool _isVisibleInSecondaryCamera { false };
164  bool _canCastShadow { false };
165  bool _cullWithParent { false };
166  RenderLayer _renderLayer { RenderLayer::WORLD };
167  PrimitiveMode _primitiveMode { PrimitiveMode::SOLID };
168  QVector<QUuid> _renderWithZones;
169  BillboardMode _billboardMode { BillboardMode::NONE };
170  bool _cauterized { false };
171  bool _moving { false };
172  MirrorMode _mirrorMode { MirrorMode::NONE };
173  QUuid _portalExitID;
174  Transform _renderTransform;
175  Transform _prevRenderTransform; // each subclass is responsible for updating this after they render because they all handle transforms differently
176 
177  FadeInPropertyGroup _fadeInProperties;
178  FadeOutPropertyGroup _fadeOutProperties;
179  ComponentMode _fadeInMode { COMPONENT_MODE_INHERIT };
180  ComponentMode _fadeOutMode { COMPONENT_MODE_INHERIT };
181 
182  MaterialMap _materials;
183  mutable std::mutex _materialsLock;
184 
185  quint64 _created;
186 
187  // The base class relies on comparing the model transform to the entity transform in order
188  // to trigger an update, so the member must not be visible to derived classes as a modifiable
189  // transform
190  Transform _modelTransform;
191  // The rendering code only gets access to the entity in very specific circumstances
192  // i.e. to see if the rendering code needs to update because of a change in state of the
193  // entity. This forces all the rendering code itself to be independent of the entity
194  const EntityItemPointer _entity;
195 
196  QUuid _entityID;
197 
198 signals:
199  void requestRenderUpdate();
200 };
201 
202 template <typename T>
203 class TypedEntityRenderer : public EntityRenderer {
204  using Parent = EntityRenderer;
205 
206 public:
207  TypedEntityRenderer(const EntityItemPointer& entity) : Parent(entity), _typedEntity(asTypedEntity<T>()) {}
208 
209 protected:
210  using TypedEntityPointer = std::shared_ptr<T>;
211 
212  virtual void onAddToScene(const EntityItemPointer& entity) override final {
213  Parent::onAddToScene(entity);
214  onAddToSceneTyped(_typedEntity);
215  }
216 
217  virtual void onRemoveFromScene(const EntityItemPointer& entity) override final {
218  Parent::onRemoveFromScene(entity);
219  onRemoveFromSceneTyped(_typedEntity);
220  }
221 
222  using Parent::needsRenderUpdateFromEntity;
223  // Returns true if the item in question needs to have updateInScene called because of changes in the entity
224  virtual bool needsRenderUpdateFromEntity(const EntityItemPointer& entity) const override final {
225  return Parent::needsRenderUpdateFromEntity(entity) || needsRenderUpdateFromTypedEntity(_typedEntity);
226  }
227 
228  virtual void doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) override final {
229  Parent::doRenderUpdateSynchronous(scene, transaction, entity);
230  doRenderUpdateSynchronousTyped(scene, transaction, _typedEntity);
231  }
232 
233  virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) override final {
234  Parent::doRenderUpdateAsynchronous(entity);
235  doRenderUpdateAsynchronousTyped(_typedEntity);
236  }
237 
238  virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { return false; }
239  virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { }
240  virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { }
241  virtual void onAddToSceneTyped(const TypedEntityPointer& entity) { }
242  virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) { }
243 
244 private:
245  const TypedEntityPointer _typedEntity;
246 };
247 
248 } } // namespace render::entities
249 
250 #endif // hifi_RenderableEntityItem_h