1 //
2 // Copyright (c) 2008-2017 the Urho3D project.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 //
22
23 #pragma once
24
25 #include "../Graphics/GraphicsDefs.h"
26 #include "../Math/BoundingBox.h"
27 #include "../Scene/Component.h"
28
29 namespace Urho3D
30 {
31
32 static const unsigned DRAWABLE_GEOMETRY = 0x1;
33 static const unsigned DRAWABLE_LIGHT = 0x2;
34 static const unsigned DRAWABLE_ZONE = 0x4;
35 static const unsigned DRAWABLE_GEOMETRY2D = 0x8;
36 static const unsigned DRAWABLE_ANY = 0xff;
37 static const unsigned DEFAULT_VIEWMASK = M_MAX_UNSIGNED;
38 static const unsigned DEFAULT_LIGHTMASK = M_MAX_UNSIGNED;
39 static const unsigned DEFAULT_SHADOWMASK = M_MAX_UNSIGNED;
40 static const unsigned DEFAULT_ZONEMASK = M_MAX_UNSIGNED;
41 static const int MAX_VERTEX_LIGHTS = 4;
42 static const float ANIMATION_LOD_BASESCALE = 2500.0f;
43
44 class Camera;
45 class File;
46 class Geometry;
47 class Light;
48 class Material;
49 class OcclusionBuffer;
50 class Octant;
51 class RayOctreeQuery;
52 class Zone;
53 struct RayQueryResult;
54 struct WorkItem;
55
56 /// Geometry update type.
57 enum UpdateGeometryType
58 {
59 UPDATE_NONE = 0,
60 UPDATE_MAIN_THREAD,
61 UPDATE_WORKER_THREAD
62 };
63
64 /// Rendering frame update parameters.
65 struct FrameInfo
66 {
67 /// Frame number.
68 unsigned frameNumber_;
69 /// Time elapsed since last frame.
70 float timeStep_;
71 /// Viewport size.
72 IntVector2 viewSize_;
73 /// Camera being used.
74 Camera* camera_;
75 };
76
77 /// Source data for a 3D geometry draw call.
78 struct URHO3D_API SourceBatch
79 {
80 /// Construct with defaults.
81 SourceBatch();
82 /// Copy-construct.
83 SourceBatch(const SourceBatch& batch);
84 /// Destruct.
85 ~SourceBatch();
86
87 /// Assignment operator.
88 SourceBatch& operator =(const SourceBatch& rhs);
89
90 /// Distance from camera.
91 float distance_;
92 /// Geometry.
93 Geometry* geometry_;
94 /// Material.
95 SharedPtr<Material> material_;
96 /// World transform(s). For a skinned model, these are the bone transforms.
97 const Matrix3x4* worldTransform_;
98 /// Number of world transforms.
99 unsigned numWorldTransforms_;
100 /// Per-instance data. If not null, must contain enough data to fill instancing buffer.
101 void* instancingData_;
102 /// %Geometry type.
103 GeometryType geometryType_;
104 };
105
106 /// Base class for visible components.
107 class URHO3D_API Drawable : public Component
108 {
109 URHO3D_OBJECT(Drawable, Component);
110
111 friend class Octant;
112 friend class Octree;
113 friend void UpdateDrawablesWork(const WorkItem* item, unsigned threadIndex);
114
115 public:
116 /// Construct.
117 Drawable(Context* context, unsigned char drawableFlags);
118 /// Destruct.
119 virtual ~Drawable();
120 /// Register object attributes. Drawable must be registered first.
121 static void RegisterObject(Context* context);
122
123 /// Handle enabled/disabled state change.
124 virtual void OnSetEnabled();
125 /// Process octree raycast. May be called from a worker thread.
126 virtual void ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results);
127 /// Update before octree reinsertion. Is called from a worker thread
Update(const FrameInfo & frame)128 virtual void Update(const FrameInfo& frame) { }
129 /// Calculate distance and prepare batches for rendering. May be called from worker thread(s), possibly re-entrantly.
130 virtual void UpdateBatches(const FrameInfo& frame);
131 /// Prepare geometry for rendering.
UpdateGeometry(const FrameInfo & frame)132 virtual void UpdateGeometry(const FrameInfo& frame) { }
133
134 /// Return whether a geometry update is necessary, and if it can happen in a worker thread.
GetUpdateGeometryType()135 virtual UpdateGeometryType GetUpdateGeometryType() { return UPDATE_NONE; }
136
137 /// Return the geometry for a specific LOD level.
138 virtual Geometry* GetLodGeometry(unsigned batchIndex, unsigned level);
139
140 /// Return number of occlusion geometry triangles.
GetNumOccluderTriangles()141 virtual unsigned GetNumOccluderTriangles() { return 0; }
142
143 /// Draw to occlusion buffer. Return true if did not run out of triangles.
144 virtual bool DrawOcclusion(OcclusionBuffer* buffer);
145 /// Visualize the component as debug geometry.
146 virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
147
148 /// Set draw distance.
149 void SetDrawDistance(float distance);
150 /// Set shadow draw distance.
151 void SetShadowDistance(float distance);
152 /// Set LOD bias.
153 void SetLodBias(float bias);
154 /// Set view mask. Is and'ed with camera's view mask to see if the object should be rendered.
155 void SetViewMask(unsigned mask);
156 /// Set light mask. Is and'ed with light's and zone's light mask to see if the object should be lit.
157 void SetLightMask(unsigned mask);
158 /// Set shadow mask. Is and'ed with light's light mask and zone's shadow mask to see if the object should be rendered to a shadow map.
159 void SetShadowMask(unsigned mask);
160 /// Set zone mask. Is and'ed with zone's zone mask to see if the object should belong to the zone.
161 void SetZoneMask(unsigned mask);
162 /// Set maximum number of per-pixel lights. Default 0 is unlimited.
163 void SetMaxLights(unsigned num);
164 /// Set shadowcaster flag.
165 void SetCastShadows(bool enable);
166 /// Set occlusion flag.
167 void SetOccluder(bool enable);
168 /// Set occludee flag.
169 void SetOccludee(bool enable);
170 /// Mark for update and octree reinsertion. Update is automatically queued when the drawable's scene node moves or changes scale.
171 void MarkForUpdate();
172
173 /// Return local space bounding box. May not be applicable or properly updated on all drawables.
GetBoundingBox()174 const BoundingBox& GetBoundingBox() const { return boundingBox_; }
175
176 /// Return world-space bounding box.
177 const BoundingBox& GetWorldBoundingBox();
178
179 /// Return drawable flags.
GetDrawableFlags()180 unsigned char GetDrawableFlags() const { return drawableFlags_; }
181
182 /// Return draw distance.
GetDrawDistance()183 float GetDrawDistance() const { return drawDistance_; }
184
185 /// Return shadow draw distance.
GetShadowDistance()186 float GetShadowDistance() const { return shadowDistance_; }
187
188 /// Return LOD bias.
GetLodBias()189 float GetLodBias() const { return lodBias_; }
190
191 /// Return view mask.
GetViewMask()192 unsigned GetViewMask() const { return viewMask_; }
193
194 /// Return light mask.
GetLightMask()195 unsigned GetLightMask() const { return lightMask_; }
196
197 /// Return shadow mask.
GetShadowMask()198 unsigned GetShadowMask() const { return shadowMask_; }
199
200 /// Return zone mask.
GetZoneMask()201 unsigned GetZoneMask() const { return zoneMask_; }
202
203 /// Return maximum number of per-pixel lights.
GetMaxLights()204 unsigned GetMaxLights() const { return maxLights_; }
205
206 /// Return shadowcaster flag.
GetCastShadows()207 bool GetCastShadows() const { return castShadows_; }
208
209 /// Return occluder flag.
IsOccluder()210 bool IsOccluder() const { return occluder_; }
211
212 /// Return occludee flag.
IsOccludee()213 bool IsOccludee() const { return occludee_; }
214
215 /// Return whether is in view this frame from any viewport camera. Excludes shadow map cameras.
216 bool IsInView() const;
217 /// Return whether is in view of a specific camera this frame. Pass in a null camera to allow any camera, including shadow map cameras.
218 bool IsInView(Camera* camera) const;
219
220 /// Return draw call source data.
GetBatches()221 const Vector<SourceBatch>& GetBatches() const { return batches_; }
222
223 /// Set new zone. Zone assignment may optionally be temporary, meaning it needs to be re-evaluated on the next frame.
224 void SetZone(Zone* zone, bool temporary = false);
225 /// Set sorting value.
226 void SetSortValue(float value);
227
228 /// Set view-space depth bounds.
SetMinMaxZ(float minZ,float maxZ)229 void SetMinMaxZ(float minZ, float maxZ)
230 {
231 minZ_ = minZ;
232 maxZ_ = maxZ;
233 }
234
235 /// Mark in view. Also clear the light list.
236 void MarkInView(const FrameInfo& frame);
237 /// Mark in view without specifying a camera. Used for shadow casters.
238 void MarkInView(unsigned frameNumber);
239 /// Sort and limit per-pixel lights to maximum allowed. Convert extra lights into vertex lights.
240 void LimitLights();
241 /// Sort and limit per-vertex lights to maximum allowed.
242 void LimitVertexLights(bool removeConvertedLights);
243
244 /// Set base pass flag for a batch.
SetBasePass(unsigned batchIndex)245 void SetBasePass(unsigned batchIndex) { basePassFlags_ |= (1 << batchIndex); }
246
247 /// Return octree octant.
GetOctant()248 Octant* GetOctant() const { return octant_; }
249
250 /// Return current zone.
GetZone()251 Zone* GetZone() const { return zone_; }
252
253 /// Return whether current zone is inconclusive or dirty due to the drawable moving.
IsZoneDirty()254 bool IsZoneDirty() const { return zoneDirty_; }
255
256 /// Return distance from camera.
GetDistance()257 float GetDistance() const { return distance_; }
258
259 /// Return LOD scaled distance from camera.
GetLodDistance()260 float GetLodDistance() const { return lodDistance_; }
261
262 /// Return sorting value.
GetSortValue()263 float GetSortValue() const { return sortValue_; }
264
265 /// Return whether is in view on the current frame. Called by View.
266 bool IsInView(const FrameInfo& frame, bool anyCamera = false) const;
267
268 /// Return whether has a base pass.
HasBasePass(unsigned batchIndex)269 bool HasBasePass(unsigned batchIndex) const { return (basePassFlags_ & (1 << batchIndex)) != 0; }
270
271 /// Return per-pixel lights.
GetLights()272 const PODVector<Light*>& GetLights() const { return lights_; }
273
274 /// Return per-vertex lights.
GetVertexLights()275 const PODVector<Light*>& GetVertexLights() const { return vertexLights_; }
276
277 /// Return the first added per-pixel light.
GetFirstLight()278 Light* GetFirstLight() const { return firstLight_; }
279
280 /// Return the minimum view-space depth.
GetMinZ()281 float GetMinZ() const { return minZ_; }
282
283 /// Return the maximum view-space depth.
GetMaxZ()284 float GetMaxZ() const { return maxZ_; }
285
286 /// Add a per-pixel light affecting the object this frame.
AddLight(Light * light)287 void AddLight(Light* light)
288 {
289 if (!firstLight_)
290 firstLight_ = light;
291
292 // Need to store into the light list only if the per-pixel lights are being limited
293 // Otherwise recording the first light is enough
294 if (maxLights_)
295 lights_.Push(light);
296 }
297
298 /// Add a per-vertex light affecting the object this frame.
AddVertexLight(Light * light)299 void AddVertexLight(Light* light)
300 {
301 vertexLights_.Push(light);
302 }
303
304 protected:
305 /// Handle node being assigned.
306 virtual void OnNodeSet(Node* node);
307 /// Handle scene being assigned.
308 virtual void OnSceneSet(Scene* scene);
309 /// Handle node transform being dirtied.
310 virtual void OnMarkedDirty(Node* node);
311 /// Recalculate the world-space bounding box.
312 virtual void OnWorldBoundingBoxUpdate() = 0;
313
314 /// Handle removal from octree.
OnRemoveFromOctree()315 virtual void OnRemoveFromOctree() { }
316
317 /// Add to octree.
318 void AddToOctree();
319 /// Remove from octree.
320 void RemoveFromOctree();
321
322 /// Move into another octree octant.
SetOctant(Octant * octant)323 void SetOctant(Octant* octant) { octant_ = octant; }
324
325 /// World-space bounding box.
326 BoundingBox worldBoundingBox_;
327 /// Local-space bounding box.
328 BoundingBox boundingBox_;
329 /// Draw call source data.
330 Vector<SourceBatch> batches_;
331 /// Drawable flags.
332 unsigned char drawableFlags_;
333 /// Bounding box dirty flag.
334 bool worldBoundingBoxDirty_;
335 /// Shadowcaster flag.
336 bool castShadows_;
337 /// Occluder flag.
338 bool occluder_;
339 /// Occludee flag.
340 bool occludee_;
341 /// Octree update queued flag.
342 bool updateQueued_;
343 /// Zone inconclusive or dirtied flag.
344 bool zoneDirty_;
345 /// Octree octant.
346 Octant* octant_;
347 /// Current zone.
348 Zone* zone_;
349 /// View mask.
350 unsigned viewMask_;
351 /// Light mask.
352 unsigned lightMask_;
353 /// Shadow mask.
354 unsigned shadowMask_;
355 /// Zone mask.
356 unsigned zoneMask_;
357 /// Last visible frame number.
358 unsigned viewFrameNumber_;
359 /// Current distance to camera.
360 float distance_;
361 /// LOD scaled distance.
362 float lodDistance_;
363 /// Draw distance.
364 float drawDistance_;
365 /// Shadow distance.
366 float shadowDistance_;
367 /// Current sort value.
368 float sortValue_;
369 /// Current minimum view space depth.
370 float minZ_;
371 /// Current maximum view space depth.
372 float maxZ_;
373 /// LOD bias.
374 float lodBias_;
375 /// Base pass flags, bit per batch.
376 unsigned basePassFlags_;
377 /// Maximum per-pixel lights.
378 unsigned maxLights_;
379 /// List of cameras from which is seen on the current frame.
380 PODVector<Camera*> viewCameras_;
381 /// First per-pixel light added this frame.
382 Light* firstLight_;
383 /// Per-pixel lights affecting this drawable.
384 PODVector<Light*> lights_;
385 /// Per-vertex lights affecting this drawable.
386 PODVector<Light*> vertexLights_;
387 };
388
CompareDrawables(Drawable * lhs,Drawable * rhs)389 inline bool CompareDrawables(Drawable* lhs, Drawable* rhs)
390 {
391 return lhs->GetSortValue() < rhs->GetSortValue();
392 }
393
394 URHO3D_API bool WriteDrawablesToOBJ(PODVector<Drawable*> drawables, File* outputFile, bool asZUp, bool asRightHanded, bool writeLightmapUV = false);
395
396 }
397