Browse Source

Refactoring of Drawable::IsInView() functions and drawable view tracking.
- Call Drawable::IsInView() to check whether in view of any viewport camera. Does not include shadow map cameras.
- Call Drawable::IsInView(Camera*) to check whether in view of a specific camera. Pass null camera pointer here to allow any camera, including shadow maps.
Removed Drawable Lua exposed functions which do not have exposed counterparts in AngelScript, but are rather meant for internal C++ use only by the Renderer / View classes.
Closes #207.

Lasse Öörni 11 years ago
parent
commit
4bd2eb0356

+ 41 - 13
Source/Engine/Graphics/Drawable.cpp

@@ -28,6 +28,7 @@
 #include "Log.h"
 #include "Material.h"
 #include "Octree.h"
+#include "Renderer.h"
 #include "Scene.h"
 #include "Sort.h"
 #include "Zone.h"
@@ -80,8 +81,6 @@ Drawable::Drawable(Context* context, unsigned char drawableFlags) :
     firstLight_(0),
     zone_(0),
     lastZone_(0),
-    viewFrame_(0),
-    viewCamera_(0),
     zoneDirty_(false)
 {
 }
@@ -251,6 +250,31 @@ const BoundingBox& Drawable::GetWorldBoundingBox()
     return worldBoundingBox_;
 }
 
+bool Drawable::IsInView() const
+{
+    // Note: in headless mode there is no renderer subsystem and no view frustum tests are performed, so return
+    // always false in that case
+    Renderer* renderer = GetSubsystem<Renderer>();
+    if (renderer)
+        return viewFrameNumber_ == renderer->GetFrameInfo().frameNumber_ && !viewCameras_.Empty();
+    else
+        return false;
+}
+
+bool Drawable::IsInView(Camera* camera) const
+{
+    Renderer* renderer = GetSubsystem<Renderer>();
+    if (renderer)
+        return viewFrameNumber_ == renderer->GetFrameInfo().frameNumber_ && (!camera || viewCameras_.Contains(camera));
+    else
+        return false;
+}
+
+bool Drawable::IsInView(const FrameInfo& frame, bool anyCamera) const
+{
+    return viewFrameNumber_ == frame.frameNumber_ && (anyCamera || viewCameras_.Contains(frame.camera_));
+}
+
 void Drawable::SetZone(Zone* zone, bool temporary)
 {
     zone_ = zone;
@@ -271,23 +295,27 @@ void Drawable::SetMinMaxZ(float minZ, float maxZ)
     maxZ_ = maxZ;
 }
 
-void Drawable::MarkInView(const FrameInfo& frame, bool mainView)
+void Drawable::MarkInView(const FrameInfo& frame)
 {
-    if (mainView)
+    if (frame.frameNumber_ != viewFrameNumber_)
     {
         viewFrameNumber_ = frame.frameNumber_;
-        viewFrame_ = &frame;
-        viewCamera_ = frame.camera_;
+        viewCameras_.Clear();
     }
-    else
+    
+    viewCameras_.Insert(frame.camera_);
+}
+
+void Drawable::MarkInView(unsigned frameNumber, Camera* camera)
+{
+    if (frameNumber != viewFrameNumber_)
     {
-        if (viewFrameNumber_ != frame.frameNumber_ || viewFrame_ != &frame)
-        {
-            viewFrameNumber_ = frame.frameNumber_;
-            viewFrame_ = &frame;
-            viewCamera_ = 0;
-        }
+        viewFrameNumber_ = frameNumber;
+        viewCameras_.Clear();
     }
+    
+    if (camera)
+        viewCameras_.Insert(camera);
 }
 
 void Drawable::LimitLights()

+ 13 - 10
Source/Engine/Graphics/Drawable.h

@@ -25,6 +25,7 @@
 #include "BoundingBox.h"
 #include "Component.h"
 #include "GraphicsDefs.h"
+#include "HashSet.h"
 
 namespace Urho3D
 {
@@ -187,6 +188,10 @@ public:
     bool IsOccluder() const { return occluder_; }
     /// Return occludee flag.
     bool IsOccludee() const { return occludee_; }
+    /// Return whether is in view this frame from any viewport camera. Excludes shadow map cameras.
+    bool IsInView() const;
+    /// Return whether is in view of a specific camera this frame. Pass in a null camera to allow any camera, including shadow map cameras.
+    bool IsInView(Camera* camera) const;
     /// Return draw call source data.
     const Vector<SourceBatch>& GetBatches() const { return batches_; }
     
@@ -196,8 +201,10 @@ public:
     void SetSortValue(float value);
     /// Set view-space depth bounds.
     void SetMinMaxZ(float minZ, float maxZ);
-    /// Mark in view (either the main camera, or a shadow camera view) this frame.
-    void MarkInView(const FrameInfo& frame, bool mainView = true);
+    /// Mark in view.
+    void MarkInView(const FrameInfo& frame);
+    /// Mark in view of a specific camera. Specify null camera to update just the frame number.
+    void MarkInView(unsigned frameNumber, Camera* camera);
     /// Sort and limit per-pixel lights to maximum allowed. Convert extra lights into vertex lights.
     void LimitLights();
     /// Sort and limit per-vertex lights to maximum allowed.
@@ -218,10 +225,8 @@ public:
     float GetLodDistance() const { return lodDistance_; }
     /// Return sorting value.
     float GetSortValue() const { return sortValue_; }
-    /// Return whether is in view this frame.
-    bool IsInView(unsigned frameNumber) const { return viewFrameNumber_ == frameNumber; }
-    /// Return whether is visible in a specific view this frame.
-    bool IsInView(const FrameInfo& frame, bool mainView = true) const { return viewFrameNumber_ == frame.frameNumber_ && viewFrame_ == &frame && (!mainView || viewCamera_ == frame.camera_); }
+    /// Return whether is in view on the current frame. Called by View.
+    bool IsInView(const FrameInfo& frame, bool anyCamera = false) const;
     /// Return whether has a base pass.
     bool HasBasePass(unsigned batchIndex) const { return (basePassFlags_ & (1 << batchIndex)) != 0; }
     /// Return per-pixel lights.
@@ -332,12 +337,10 @@ protected:
     Zone* zone_;
     /// Previous zone.
     Zone* lastZone_;
-    /// Last view's frameinfo. Not safe to dereference.
-    const FrameInfo* viewFrame_;
-    /// Last view's camera. Not safe to dereference.
-    Camera* viewCamera_;
     /// Zone assignment dirty flag.
     bool zoneDirty_;
+    /// Set of cameras from which is seen on the current frame.
+    HashSet<Camera*> viewCameras_;
 };
 
 inline bool CompareDrawables(Drawable* lhs, Drawable* rhs)

+ 6 - 4
Source/Engine/Graphics/View.cpp

@@ -851,9 +851,11 @@ void View::GetBatches()
                         k < query.shadowCasters_.Begin() + query.shadowCasterEnd_[j]; ++k)
                     {
                         Drawable* drawable = *k;
-                        if (!drawable->IsInView(frame_, false))
+                        if (!drawable->IsInView(frame_, true))
                         {
-                            drawable->MarkInView(frame_, false);
+                            // May be called from multiple threads, so don't manipulate the Drawable's viewCameras set,
+                            // just update the frame number
+                            drawable->MarkInView(frame_.frameNumber_, 0);
                             shadowGeometries_.Push(drawable);
                         }
                         
@@ -1878,7 +1880,7 @@ void View::UpdateOccluders(PODVector<Drawable*>& occluders, Camera* camera)
         Drawable* occluder = *i;
         bool erase = false;
         
-        if (!occluder->IsInView(frame_, false))
+        if (!occluder->IsInView(frame_, true))
             occluder->UpdateBatches(frame_);
         
         // Check occluder's draw distance (in main camera view)
@@ -2090,7 +2092,7 @@ void View::ProcessShadowCasters(LightQueryResult& query, const PODVector<Drawabl
         // Check shadow distance
         float maxShadowDistance = drawable->GetShadowDistance();
         float drawDistance = drawable->GetDrawDistance();
-        bool batchesUpdated = drawable->IsInView(frame_, false);
+        bool batchesUpdated = drawable->IsInView(frame_, true);
         if (drawDistance > 0.0f && (maxShadowDistance <= 0.0f || drawDistance < maxShadowDistance))
             maxShadowDistance = drawDistance;
         if (maxShadowDistance > 0.0f)

+ 6 - 61
Source/Engine/LuaScript/pkgs/Graphics/Drawable.pkg

@@ -11,13 +11,6 @@ static const unsigned DEFAULT_ZONEMASK;
 static const int MAX_VERTEX_LIGHTS;
 static const float ANIMATION_LOD_BASESCALE;
 
-enum UpdateGeometryType
-{
-    UPDATE_NONE = 0,
-    UPDATE_MAIN_THREAD,
-    UPDATE_WORKER_THREAD
-};
-
 class Drawable : public Component
 {
     void SetDrawDistance(float distance);
@@ -47,30 +40,11 @@ class Drawable : public Component
     bool GetCastShadows() const;
     bool IsOccluder() const;
     bool IsOccludee() const;
-    
-    void SetZone(Zone* zone, bool temporary = false);
-    void SetSortValue(float value);
-    void SetMinMaxZ(float minZ, float maxZ);
-    void MarkInView(const FrameInfo& frame, bool mainView = true);
-    void ClearLights();
-    void AddLight(Light* light);
-    void AddVertexLight(Light* light);
-    void LimitLights();
-    void LimitVertexLights();
-    void SetBasePass(unsigned batchIndex);
-    Octant* GetOctant() const;
+    bool IsInView() const;
+    bool IsInView(Camera*) const;
+
     Zone* GetZone() const;
-    Zone* GetLastZone() const;
-    bool IsZoneDirty() const;
-    float GetDistance() const;
-    float GetLodDistance() const;
-    float GetSortValue() const;
-    bool HasBasePass(unsigned batchIndex) const;
-    Light* GetFirstLight() const;
-    float GetMinZ() const;
-    float GetMaxZ() const;
-    
-    tolua_readonly tolua_property__is_set bool inView;
+
     tolua_readonly tolua_property__get_set BoundingBox& worldBoundingBox;
     tolua_readonly tolua_property__get_set unsigned char drawableFlags;
     tolua_property__get_set float drawDistance;
@@ -84,36 +58,7 @@ class Drawable : public Component
     tolua_property__get_set bool castShadows;
     tolua_property__is_set bool occluder;
     tolua_property__is_set bool occludee;
-    tolua_readonly tolua_property__get_set Octant* octant;
-    tolua_property__get_set Zone* zone;
-    tolua_readonly tolua_property__get_set Zone* lastZone;
-    tolua_readonly tolua_property__is_set bool zoneDirty;
-    tolua_readonly tolua_property__get_set float distance;
-    tolua_readonly tolua_property__get_set float lodDistance;
-    tolua_property__get_set float sortValue;
-    tolua_readonly tolua_property__get_set Light* firstLight;
-    tolua_readonly tolua_property__get_set float minZ;
-    tolua_readonly tolua_property__get_set float maxZ;
+    tolua_readonly tolua_property__is_set bool inView;
+    tolua_readonly tolua_property__get_set Zone* zone;
 };
 
-${
-static bool DrawableIsInView(Drawable* drawable)
-{
-    // Get the last frame number processed by the Renderer to be able to check
-    Renderer* renderer = drawable->GetContext()->GetSubsystem<Renderer>();
-    if (!renderer)
-        return false;
-    const FrameInfo& frame = renderer->GetFrameInfo();
-    return drawable->IsInView(frame.frameNumber_);
-}
-#define TOLUA_DISABLE_tolua_get_Drawable_inView
-static int tolua_get_Drawable_inView(lua_State* tolua_S)
-{
-  Drawable* self = (Drawable*)  tolua_tousertype(tolua_S,1,0);
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'inView'",NULL);
-#endif
- tolua_pushboolean(tolua_S,(bool)DrawableIsInView(self));
- return 1;
-}
-$}

+ 4 - 12
Source/Engine/Script/APITemplates.h

@@ -30,7 +30,6 @@
 #include "HashSet.h"
 #include "Log.h"
 #include "Node.h"
-#include "Renderer.h"
 #include "Resource.h"
 #include "Script.h"
 #include "ScriptInstance.h"
@@ -45,6 +44,8 @@
 namespace Urho3D
 {
 
+class Camera;
+
 /// Template function for dynamic cast between two script classes.
 template <class T, class U> U* RefCast(T* t)
 {
@@ -677,22 +678,13 @@ template <class T> void RegisterResource(asIScriptEngine* engine, const char* cl
     engine->RegisterObjectMethod(className, "uint get_useTimer()" ,asMETHODPR(T, GetUseTimer, (), unsigned), asCALL_THISCALL);
 }
 
-static bool DrawableIsInView(Drawable* ptr)
-{
-    // Get the last frame number processed by the Renderer to be able to check
-    Renderer* renderer = GetScriptContext()->GetSubsystem<Renderer>();
-    if (!renderer)
-        return false;
-    const FrameInfo& frame = renderer->GetFrameInfo();
-    return ptr->IsInView(frame.frameNumber_);
-}
-
 /// Template function for registering a class derived from Drawable.
 template <class T> void RegisterDrawable(asIScriptEngine* engine, const char* className)
 {
     RegisterComponent<T>(engine, className);
     RegisterSubclass<Drawable, T>(engine, "Drawable", className);
-    engine->RegisterObjectMethod(className, "bool get_inView() const", asFUNCTION(DrawableIsInView), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod(className, "bool IsInView(Camera@+) const", asMETHODPR(Drawable, IsInView, (Camera*) const, bool), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_inView() const", asMETHODPR(Drawable, IsInView, () const, bool), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_castShadows(bool)", asMETHOD(T, SetCastShadows), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_castShadows() const", asMETHOD(T, GetCastShadows), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_occluder(bool)", asMETHOD(T, SetOccluder), asCALL_THISCALL);

+ 1 - 0
Source/Engine/Script/GraphicsAPI.cpp

@@ -35,6 +35,7 @@
 #include "Material.h"
 #include "Octree.h"
 #include "ParticleEmitter.h"
+#include "Renderer.h"
 #include "RenderPath.h"
 #include "Scene.h"
 #include "SmoothedTransform.h"