Browse Source

Add screen to world convert functions, PhysicsWorld2D use these function to pick rigid body.

aster 11 years ago
parent
commit
85bcdaecf4

+ 2 - 2
Bin/Data/Scripts/32_Urho2DConstraints.as

@@ -390,7 +390,7 @@ void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
 void HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)
 void HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)
 {
 {
     PhysicsWorld2D@ physicsWorld = scene_.GetComponent("PhysicsWorld2D");
     PhysicsWorld2D@ physicsWorld = scene_.GetComponent("PhysicsWorld2D");
-    RigidBody2D@ rigidBody = physicsWorld.GetRigidBody(input.mousePosition.x, input.mousePosition.y, M_MAX_UNSIGNED ,camera); // Raycast for RigidBody2Ds to pick
+    RigidBody2D@ rigidBody = physicsWorld.GetRigidBody(input.mousePosition.x, input.mousePosition.y, M_MAX_UNSIGNED); // Raycast for RigidBody2Ds to pick
     if (rigidBody !is null)
     if (rigidBody !is null)
     {
     {
         pickedNode = rigidBody.node;
         pickedNode = rigidBody.node;
@@ -442,7 +442,7 @@ void HandleMouseMove(StringHash eventType, VariantMap& eventData)
 void HandleTouchBegin3(StringHash eventType, VariantMap& eventData)
 void HandleTouchBegin3(StringHash eventType, VariantMap& eventData)
 {
 {
     PhysicsWorld2D@ physicsWorld = scene_.GetComponent("PhysicsWorld2D");
     PhysicsWorld2D@ physicsWorld = scene_.GetComponent("PhysicsWorld2D");
-    RigidBody2D@ rigidBody = physicsWorld.GetRigidBody(eventData["X"].GetInt(), eventData["Y"].GetInt(), M_MAX_UNSIGNED ,camera); // Raycast for RigidBody2Ds to pick
+    RigidBody2D@ rigidBody = physicsWorld.GetRigidBody(eventData["X"].GetInt(), eventData["Y"].GetInt(), M_MAX_UNSIGNED); // Raycast for RigidBody2Ds to pick
     if (rigidBody !is null)
     if (rigidBody !is null)
     {
     {
         pickedNode = rigidBody.node;
         pickedNode = rigidBody.node;

+ 70 - 0
Source/Engine/Graphics/Viewport.cpp

@@ -114,4 +114,74 @@ RenderPath* Viewport::GetRenderPath() const
     return renderPath_;
     return renderPath_;
 }
 }
 
 
+Ray Viewport::GetScreenRay(int x, int y) const
+{
+    if (!camera_)
+        return Ray();
+
+    float screenX;
+    float screenY;
+
+    if (rect_ == IntRect::ZERO)
+    {
+        Graphics* graphics = GetSubsystem<Graphics>();
+        screenX = (float)x / (float)graphics->GetWidth();
+        screenY = (float)y / (float)graphics->GetHeight();
+    }
+    else
+    {
+        screenX = float(x - rect_.left_) / (float)rect_.Width();
+        screenY = float(y - rect_.top_) / (float)rect_.Height();
+    }
+
+    return camera_->GetScreenRay(screenX, screenY);
+}
+
+IntVector2 Viewport::WorldToScreenPoint(const Vector3& worldPos) const
+{
+    if (!camera_)
+        return IntVector2::ZERO;
+
+    Vector2 screenPoint = camera_->WorldToScreenPoint(worldPos);
+
+    int x;
+    int y;
+    if (rect_ == IntRect::ZERO)
+    {
+        Graphics* graphics = GetSubsystem<Graphics>();
+        x = (int)(screenPoint.x_ * graphics->GetWidth());
+        y = (int)(screenPoint.y_ * graphics->GetHeight());
+    }
+    else
+    {
+        x = (int)(rect_.left_ + screenPoint.x_ * rect_.Width());
+        y = (int)(rect_.top_ + screenPoint.y_ * rect_.Height());
+    }
+    
+    return IntVector2(x, y);
+}
+
+Vector3 Viewport::ScreenToWorldPoint(int x, int y, float depth) const
+{
+    if (!camera_)
+        return Vector3::ZERO;
+
+    float screenX;
+    float screenY;
+
+    if (rect_ == IntRect::ZERO)
+    {
+        Graphics* graphics = GetSubsystem<Graphics>();
+        screenX = (float)x / (float)graphics->GetWidth();
+        screenY = (float)y / (float)graphics->GetHeight();
+    }
+    else
+    {
+        screenX = float(x - rect_.left_) / (float)rect_.Width();
+        screenY = float(y - rect_.top_) / (float)rect_.Height();
+    }
+
+    return camera_->ScreenToWorldPoint(Vector3(screenX, screenY, depth));
+}
+
 }
 }

+ 8 - 0
Source/Engine/Graphics/Viewport.h

@@ -24,7 +24,9 @@
 
 
 #include "Object.h"
 #include "Object.h"
 #include "Ptr.h"
 #include "Ptr.h"
+#include "Ray.h"
 #include "Rect.h"
 #include "Rect.h"
+#include "Vector2.h"
 
 
 namespace Urho3D
 namespace Urho3D
 {
 {
@@ -68,6 +70,12 @@ public:
     const IntRect& GetRect() const { return rect_; }
     const IntRect& GetRect() const { return rect_; }
     /// Return rendering path.
     /// Return rendering path.
     RenderPath* GetRenderPath() const;
     RenderPath* GetRenderPath() const;
+    /// Return ray corresponding to normalized screen coordinates.
+    Ray GetScreenRay(int x, int y) const;
+    // Convert a world space point to normalized screen coordinates.
+    IntVector2 WorldToScreenPoint(const Vector3& worldPos) const;
+    // Convert screen coordinates and depth to a world space point.
+    Vector3 ScreenToWorldPoint(int x, int y, float depth) const;
     
     
 private:
 private:
     /// Scene pointer.
     /// Scene pointer.

+ 4 - 0
Source/Engine/LuaScript/pkgs/Graphics/Viewport.pkg

@@ -17,6 +17,10 @@ class Viewport
     Camera* GetCamera() const;
     Camera* GetCamera() const;
     const IntRect& GetRect() const;
     const IntRect& GetRect() const;
     RenderPath* GetRenderPath() const;
     RenderPath* GetRenderPath() const;
+    Ray GetScreenRay(int x, int y) const;
+    IntVector2 WorldToScreenPoint(const Vector3& worldPos) const;
+    Vector3 ScreenToWorldPoint(int x, int y, float depth) const;
+    
     
     
     tolua_property__get_set Scene* scene;
     tolua_property__get_set Scene* scene;
     tolua_property__get_set Camera* camera;
     tolua_property__get_set Camera* camera;

+ 1 - 1
Source/Engine/LuaScript/pkgs/Urho2D/PhysicsWorld2D.pkg

@@ -33,7 +33,7 @@ class PhysicsWorld2D : Component
     // void RaycastSingle(PhysicsRaycastResult2D& result, const Vector2& startPoint, const Vector2& endPoint, unsigned collisionMask = M_MAX_UNSIGNED);
     // void RaycastSingle(PhysicsRaycastResult2D& result, const Vector2& startPoint, const Vector2& endPoint, unsigned collisionMask = M_MAX_UNSIGNED);
     tolua_outside PhysicsRaycastResult2D PhysicsWorld2DRaycastSingle @ RaycastSingle(const Vector2& startPoint, const Vector2& endPoint, unsigned collisionMask = M_MAX_UNSIGNED);
     tolua_outside PhysicsRaycastResult2D PhysicsWorld2DRaycastSingle @ RaycastSingle(const Vector2& startPoint, const Vector2& endPoint, unsigned collisionMask = M_MAX_UNSIGNED);
     RigidBody2D* GetRigidBody(const Vector2& point, unsigned collisionMask = M_MAX_UNSIGNED);
     RigidBody2D* GetRigidBody(const Vector2& point, unsigned collisionMask = M_MAX_UNSIGNED);
-    RigidBody2D* GetRigidBody(int screenX, int screenY, unsigned collisionMask = M_MAX_UNSIGNED, Camera* camera = 0);
+    RigidBody2D* GetRigidBody(int screenX, int screenY, unsigned collisionMask = M_MAX_UNSIGNED);
     // void GetRigidBodies(PODVector<RigidBody2D*>& result, const Rect& aabb, unsigned collisionMask = M_MAX_UNSIGNED);
     // void GetRigidBodies(PODVector<RigidBody2D*>& result, const Rect& aabb, unsigned collisionMask = M_MAX_UNSIGNED);
     tolua_outside const PODVector<RigidBody2D*>& PhysicsWorld2DGetRigidBodies @ GetRigidBodies(const Rect& aabb, unsigned collisionMask = M_MAX_UNSIGNED);
     tolua_outside const PODVector<RigidBody2D*>& PhysicsWorld2DGetRigidBodies @ GetRigidBodies(const Rect& aabb, unsigned collisionMask = M_MAX_UNSIGNED);
 
 

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

@@ -424,6 +424,9 @@ static void RegisterTextures(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Viewport", "RenderPath@+ get_renderPath() const", asMETHOD(Viewport, GetRenderPath), asCALL_THISCALL);
     engine->RegisterObjectMethod("Viewport", "RenderPath@+ get_renderPath() const", asMETHOD(Viewport, GetRenderPath), asCALL_THISCALL);
     engine->RegisterObjectMethod("Viewport", "void set_rect(const IntRect&in)", asMETHOD(Viewport, SetRect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Viewport", "void set_rect(const IntRect&in)", asMETHOD(Viewport, SetRect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Viewport", "const IntRect& get_rect() const", asMETHOD(Viewport, GetRect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Viewport", "const IntRect& get_rect() const", asMETHOD(Viewport, GetRect), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Viewport", "Ray GetScreenRay(int, int) const", asMETHOD(Viewport, GetScreenRay), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Viewport", "Vector2 WorldToScreenPoint(const Vector3&in) const", asMETHOD(Viewport, WorldToScreenPoint), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Viewport", "Vector3 ScreenToWorldPoint(int, int, float) const", asMETHOD(Viewport, ScreenToWorldPoint), asCALL_THISCALL);
     
     
     engine->RegisterObjectType("RenderSurface", 0, asOBJ_REF);
     engine->RegisterObjectType("RenderSurface", 0, asOBJ_REF);
     engine->RegisterObjectBehaviour("RenderSurface", asBEHAVE_ADDREF, "void f()", asMETHOD(RenderSurface, AddRef), asCALL_THISCALL);
     engine->RegisterObjectBehaviour("RenderSurface", asBEHAVE_ADDREF, "void f()", asMETHOD(RenderSurface, AddRef), asCALL_THISCALL);

+ 1 - 1
Source/Engine/Script/Urho2DAPI.cpp

@@ -295,7 +295,7 @@ static void RegisterPhysicsWorld2D(asIScriptEngine* engine)
     engine->RegisterObjectMethod("PhysicsWorld2D", "Array<PhysicsRaycastResult2D>@ Raycast(const Vector2&, const Vector2&, uint collisionMask = 0xffff)", asFUNCTION(PhysicsWorld2DRaycast), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("PhysicsWorld2D", "Array<PhysicsRaycastResult2D>@ Raycast(const Vector2&, const Vector2&, uint collisionMask = 0xffff)", asFUNCTION(PhysicsWorld2DRaycast), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("PhysicsWorld2D", "PhysicsRaycastResult2D RaycastSingle(const Vector2&, const Vector2&, uint collisionMask = 0xffff)", asFUNCTION(PhysicsWorld2DRaycastSingle), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("PhysicsWorld2D", "PhysicsRaycastResult2D RaycastSingle(const Vector2&, const Vector2&, uint collisionMask = 0xffff)", asFUNCTION(PhysicsWorld2DRaycastSingle), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("PhysicsWorld2D", "RigidBody2D@+ GetRigidBody(const Vector2&, uint collisionMask = 0xffff)", asMETHODPR(PhysicsWorld2D, GetRigidBody, (const Vector2&, unsigned), RigidBody2D*), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld2D", "RigidBody2D@+ GetRigidBody(const Vector2&, uint collisionMask = 0xffff)", asMETHODPR(PhysicsWorld2D, GetRigidBody, (const Vector2&, unsigned), RigidBody2D*), asCALL_THISCALL);
-    engine->RegisterObjectMethod("PhysicsWorld2D", "RigidBody2D@+ GetRigidBody(int, int, uint collisionMask = 0xffff, Camera@+ = 0)", asMETHODPR(PhysicsWorld2D, GetRigidBody, (int, int, unsigned, Camera*), RigidBody2D*), asCALL_THISCALL);
+    engine->RegisterObjectMethod("PhysicsWorld2D", "RigidBody2D@+ GetRigidBody(int, int, uint collisionMask = 0xffff)", asMETHODPR(PhysicsWorld2D, GetRigidBody, (int, int, unsigned), RigidBody2D*), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld2D", "Array<RigidBody2D@>@ GetRigidBodies(const Rect&in, uint collisionMask = 0xffff)", asFUNCTION(PhysicsWorld2DGetRigidBodies), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("PhysicsWorld2D", "Array<RigidBody2D@>@ GetRigidBodies(const Rect&in, uint collisionMask = 0xffff)", asFUNCTION(PhysicsWorld2DGetRigidBodies), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("PhysicsWorld2D", "void set_drawShape(bool)", asMETHOD(PhysicsWorld2D, SetDrawShape), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld2D", "void set_drawShape(bool)", asMETHOD(PhysicsWorld2D, SetDrawShape), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld2D", "bool get_drawShape() const", asMETHOD(PhysicsWorld2D, GetDrawShape), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld2D", "bool get_drawShape() const", asMETHOD(PhysicsWorld2D, GetDrawShape), asCALL_THISCALL);

+ 13 - 18
Source/Engine/Urho2D/PhysicsWorld2D.cpp

@@ -21,7 +21,6 @@
 //
 //
 
 
 #include "Precompiled.h"
 #include "Precompiled.h"
-#include "Camera.h"
 #include "Context.h"
 #include "Context.h"
 #include "DebugRenderer.h"
 #include "DebugRenderer.h"
 #include "Graphics.h"
 #include "Graphics.h"
@@ -30,9 +29,11 @@
 #include "PhysicsUtils2D.h"
 #include "PhysicsUtils2D.h"
 #include "PhysicsWorld2D.h"
 #include "PhysicsWorld2D.h"
 #include "Profiler.h"
 #include "Profiler.h"
+#include "Renderer.h"
 #include "RigidBody2D.h"
 #include "RigidBody2D.h"
 #include "Scene.h"
 #include "Scene.h"
 #include "SceneEvents.h"
 #include "SceneEvents.h"
+#include "Viewport.h"
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
@@ -517,27 +518,21 @@ RigidBody2D* PhysicsWorld2D::GetRigidBody(const Vector2& point, unsigned collisi
     return callback.GetRigidBody();
     return callback.GetRigidBody();
 }
 }
 
 
-RigidBody2D* PhysicsWorld2D::GetRigidBody(int screenX, int screenY, unsigned collisionMask, Camera* camera)
+RigidBody2D* PhysicsWorld2D::GetRigidBody(int screenX, int screenY, unsigned collisionMask)
 {
 {
-    if (!camera)
+    Renderer* renderer = GetSubsystem<Renderer>();
+    for (unsigned i = 0; i  < renderer->GetNumViewports(); ++i)
     {
     {
-        PODVector<Camera*> cameras;
-        GetScene()->GetComponents<Camera>(cameras, true);
-        if (!cameras.Empty())
-            camera = cameras[0];
-    }
-
-    if (!camera)
-    {
-        LOGWARNING("Could not find camera in scene");
-        return 0;
+        Viewport* viewport = renderer->GetViewport(i);
+        // Find a viewport with same scene
+        if (viewport && viewport->GetScene() == GetScene())
+        {
+            Vector3 worldPoint = viewport->ScreenToWorldPoint(screenX, screenY, 0.0f);
+            return GetRigidBody(Vector2(worldPoint.x_, worldPoint.y_), collisionMask);
+        }
     }
     }
 
 
-    Graphics* graphics = GetSubsystem<Graphics>();
-    Vector3 screenPoint((float)screenX / graphics->GetWidth(), (float)screenY / graphics->GetHeight(), 0.0f);
-    Vector3 worldPoint = camera->ScreenToWorldPoint(screenPoint);
-
-    return GetRigidBody(Vector2(worldPoint.x_, worldPoint.y_), collisionMask);
+    return 0;
 }
 }
 
 
 // Aabb query callback class.
 // Aabb query callback class.

+ 2 - 2
Source/Engine/Urho2D/PhysicsWorld2D.h

@@ -129,8 +129,8 @@ public:
     void RaycastSingle(PhysicsRaycastResult2D& result, const Vector2& startPoint, const Vector2& endPoint, unsigned collisionMask = M_MAX_UNSIGNED);
     void RaycastSingle(PhysicsRaycastResult2D& result, const Vector2& startPoint, const Vector2& endPoint, unsigned collisionMask = M_MAX_UNSIGNED);
     /// Return rigid body at point.
     /// Return rigid body at point.
     RigidBody2D* GetRigidBody(const Vector2& point, unsigned collisionMask = M_MAX_UNSIGNED);
     RigidBody2D* GetRigidBody(const Vector2& point, unsigned collisionMask = M_MAX_UNSIGNED);
-    /// Return rigid body at screen point, if camera is 0, it will use first camera in scene. when viewport size was not equal to window size it may have problem.
-    RigidBody2D* GetRigidBody(int screenX, int screenY, unsigned collisionMask = M_MAX_UNSIGNED, Camera* camera = 0);
+    /// Return rigid body at screen point.
+    RigidBody2D* GetRigidBody(int screenX, int screenY, unsigned collisionMask = M_MAX_UNSIGNED);
     /// Return rigid bodies by a box query.
     /// Return rigid bodies by a box query.
     void GetRigidBodies(PODVector<RigidBody2D*>& result, const Rect& aabb, unsigned collisionMask = M_MAX_UNSIGNED);
     void GetRigidBodies(PODVector<RigidBody2D*>& result, const Rect& aabb, unsigned collisionMask = M_MAX_UNSIGNED);
 
 

+ 1 - 1
Source/Samples/32_Urho2DConstraints/Urho2DConstraints.cpp

@@ -505,7 +505,7 @@ void Urho2DConstraints::HandleMouseButtonDown(StringHash eventType, VariantMap&
 {
 {
     Input* input = GetSubsystem<Input>();
     Input* input = GetSubsystem<Input>();
     PhysicsWorld2D* physicsWorld = scene_->GetComponent<PhysicsWorld2D>();
     PhysicsWorld2D* physicsWorld = scene_->GetComponent<PhysicsWorld2D>();
-    RigidBody2D* rigidBody = physicsWorld->GetRigidBody(input->GetMousePosition().x_, input->GetMousePosition().y_, M_MAX_UNSIGNED, camera_); // Raycast for RigidBody2Ds to pick
+    RigidBody2D* rigidBody = physicsWorld->GetRigidBody(input->GetMousePosition().x_, input->GetMousePosition().y_, M_MAX_UNSIGNED); // Raycast for RigidBody2Ds to pick
     if (rigidBody)
     if (rigidBody)
     {
     {
         pickedNode = rigidBody->GetNode();
         pickedNode = rigidBody->GetNode();