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