const float& nearClippingPlane,
const float& farClippingPlane,
HitTestInterface& hitCheck,
- const RayTest& rayTest,
+ RayTest& rayTest,
const Integration::Point& point,
const uint32_t eventTime,
bool clippingActor,
Vector2 hitPointLocal;
float distance;
+ Vector3 hitPointLocal3D;
+ Dali::Layer::Behavior layerBehavior = actor.GetLayer().GetProperty<Dali::Layer::Behavior>(Dali::Layer::Property::BEHAVIOR);
+
+ bool isHitted = false;
+ if(layerBehavior == Dali::Layer::Behavior::LAYER_3D)
+ {
+ isHitted = rayTest.ActorBoundingBoxTest(actor, rayOrigin, rayDir, hitPointLocal3D, distance);
+ }
+ else
+ {
+ isHitted = rayTest.ActorTest(actor, rayOrigin, rayDir, hitPointLocal, distance);
+ }
+
// Finally, perform a more accurate ray test to see if our ray actually hits the actor.
- if(rayTest.ActorTest(actor, rayOrigin, rayDir, hitPointLocal, distance))
+ if(isHitted)
{
// Calculate z coordinate value in Camera Space.
const Matrix& viewMatrix = renderTask.GetCameraActor()->GetViewMatrix();
const bool& overlayed,
bool& overlayHit,
bool layerIs3d,
- const RayTest& rayTest,
+ RayTest& rayTest,
const Integration::Point& point,
const uint32_t eventTime)
{
Vector2 screenCoordinates,
Results& results,
HitTestInterface& hitCheck,
- const RayTest& rayTest)
+ RayTest& rayTest)
{
if(renderTask.IsHittable(screenCoordinates))
{
return hit;
}
+bool RayTest::ActorBoundingBoxTest(const Internal::Actor& actor, const Vector4& rayOrigin, const Vector4& rayDir, Vector3& hitPointLocal, float& distance)
+{
+ bool hit = false;
+
+ if(actor.OnScene())
+ {
+ const Node& node = actor.GetNode();
+
+ // Transforms the ray to the local reference system.
+ // Calculate the inverse of Model matrix
+ Matrix modelMatrix(false /*don't init*/);
+ modelMatrix = node.GetWorldMatrix(0);
+ Matrix invModelMatrix = modelMatrix;
+ invModelMatrix.Invert();
+
+ Vector4 rayOriginLocal(invModelMatrix * rayOrigin);
+ Vector4 rayDirVector = rayDir;
+ rayDirVector.w = 0.0f; // Make it Vector.
+ Vector4 rayDirLocal(invModelMatrix * rayDirVector);
+ rayDirLocal.Normalize();
+
+ Vector3 currentSize = node.GetSize(EventThreadServices::Get().GetEventBufferIndex());
+ Vector3 AABBMin = Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f);
+ Vector3 AABBMax = Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f);
+
+ float distanceMin = 0.0f;
+ float distanceMax = std::numeric_limits<float>::infinity();
+ for(uint32_t i = 0; i < 3u; ++i)
+ {
+ float rayOriginScalar = (i == 0) ? rayOriginLocal.x : ((i == 1) ? rayOriginLocal.y : rayOriginLocal.z);
+ float rayDirectionScalar = (i == 0) ? rayDirLocal.x : ((i == 1) ? rayDirLocal.y : rayDirLocal.z);
+ float boxMin = (i == 0) ? AABBMin.x : ((i == 1) ? AABBMin.y : AABBMin.z);
+ float boxMax = (i == 0) ? AABBMax.x : ((i == 1) ? AABBMax.y : AABBMax.z);
+
+ // Check the ray is parallel to an axis.
+ if(std::abs(rayDirectionScalar) < Math::MACHINE_EPSILON_1)
+ {
+ // If the ray is parallel to an axis and the ray's origin along that axis lies outside the
+ // corresponding minimum and maximum bounds of the AABB, there can be no intersection
+ // between the ray and the AABB.
+ if(rayOriginScalar < boxMin || rayOriginScalar > boxMax)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ float hit1 = (boxMin - rayOriginScalar) / rayDirectionScalar;
+ float hit2 = (boxMax - rayOriginScalar) / rayDirectionScalar;
+
+ if(hit1 > hit2)
+ {
+ std::swap(hit1, hit2);
+ }
+
+ distanceMin = std::max(distanceMin, hit1);
+ distanceMax = std::min(distanceMax, hit2);
+
+ if(distanceMin > distanceMax)
+ {
+ return false;
+ }
+ }
+ }
+
+ Vector4 hitPointLocalVector4 = rayOriginLocal + rayDirLocal * distanceMin;
+ hitPointLocalVector4.w = 1.0f; // Make it Position
+ distance = Vector3(rayOrigin - (modelMatrix * hitPointLocalVector4)).Length();
+ hitPointLocal = Vector3(hitPointLocalVector4);
+ hitPointLocal.x += currentSize.x * 0.5f;
+ hitPointLocal.y = currentSize.y * 0.5f - hitPointLocal.y;
+
+ hit = true;
+ }
+
+ return hit;
+}
+
} // namespace Internal
} // namespace Dali
*/
bool ActorTest(const Internal::Actor& actor, const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance) const;
+ /**
+ * Performs a ray-actor test with the given pick-ray and the given actor's Bounding Box.
+ *
+ * @param[in] actor The actor to perform the ray-sphere test on
+ * @param[in] rayOrigin The ray origin in the world's reference system.
+ * @param[in] rayDir The ray director vector in the world's reference system.
+ * @param[out] hitPointLocal The hit point in the Actor's local reference system.
+ * @param[out] distance The distance from the hit point to the camera.
+ * @return True if the ray intersects the actor's Bounding Box.
+ *
+ * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5)
+ */
+ bool ActorBoundingBoxTest(const Internal::Actor& actor, const Vector4& rayOrigin, const Vector4& rayDir, Vector3& hitPointLocal, float& distance);
+
private:
const EventThreadServices& mEventThreadServices;
};