e39945b08dc59057be73d71dc30f90ee1c3c91d9
[platform/core/uifw/dali-toolkit.git] / dali-physics / public-api / physics-adaptor.h
1 #ifndef DALI_TOOLKIT_PHYSICS_ADAPTOR_H
2 #define DALI_TOOLKIT_PHYSICS_ADAPTOR_H
3
4 /*
5  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or adaptoried.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <dali/public-api/actors/actor.h>
22 #include <dali/public-api/adaptor-framework/window.h>
23 #include <dali/public-api/object/any.h>
24 #include <dali/public-api/object/base-handle.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/public-api/dali-toolkit-common.h>
28
29 namespace Dali::Toolkit::Physics
30 {
31 class PhysicsActor;
32
33 namespace Internal
34 {
35 class PhysicsAdaptor;
36 class PhysicsWorld;
37 } // namespace Internal
38
39 /**
40  * Adaptor to manage access to the physics world and pairing actors and physics
41  * bodies, plus some translation methods to/from the physics space and dali space.
42  *
43  * Also manages a debug renderer that may utilize the physics engine debug.
44  * It is up to the developer to retrieve the root actor and parent it into the scene.
45  */
46 class DALI_TOOLKIT_API PhysicsAdaptor : public BaseHandle
47 {
48 public:
49   enum class IntegrationState
50   {
51     OFF,
52     ON
53   };
54   enum class DebugState
55   {
56     OFF,
57     ON
58   };
59
60   /**
61    * Scoped accessor to the physics world. Automatically locks the physics world
62    * with a mutex to prevent the integration step from running whilst the
63    * developer is accessing the world, e.g. to add/remove bodies or constraints,
64    * or to perform hit-test.
65    *
66    * When it goes out of scope, the mutex is unlocked, and the integration step
67    * can resume.
68    */
69   struct ScopedPhysicsAccessor
70   {
71   public:
72     /**
73      * Get a pointer to the native world. This uses DALi::Any wrapper to ensure
74      * that the same interface can be used for both 2d and 3d physics. It can be
75      * cast to the right type using the following construct:
76      *   auto accessor = PhysicsAdaptor.GetPhysicsAccessor();
77      *   auto bulletWorld = accessor->GetNative().Get<btDiscreteDynamiscWorld*>();
78      */
79     Dali::Any GetNative();
80
81     /**
82      * Hit test the physics world and return the nearest body.
83      *
84      * @param[in] rayFromWorld The origin in physics world space
85      * @param[in] rayToWorld A point along the direction on the far side of the physics world
86      * @param[out] localPivot The hit point local to the body
87      * @param[out] distanceFromCamera The distance of the pick point from the camera
88      * @return Empty value if no dynamic body found, otherwise a valid ptr to the hit body.
89      */
90     Dali::Any HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Vector3& localPivot, float& distanceFromCamera);
91
92     // Not copyable
93     ScopedPhysicsAccessor(ScopedPhysicsAccessor&) = delete;
94     const ScopedPhysicsAccessor& operator=(const ScopedPhysicsAccessor&) = delete;
95
96     /**
97      * Destructor
98      */
99     ~ScopedPhysicsAccessor();
100
101   private:
102     ScopedPhysicsAccessor(Internal::PhysicsWorld& world);
103     friend Internal::PhysicsAdaptor;
104
105     struct Impl;
106     Impl* mImpl;
107   };
108
109   PhysicsAdaptor();
110   ~PhysicsAdaptor();
111   PhysicsAdaptor(const PhysicsAdaptor& handle);
112   PhysicsAdaptor(PhysicsAdaptor&& rhs) noexcept;
113   PhysicsAdaptor& operator=(const PhysicsAdaptor& handle);
114   PhysicsAdaptor& operator=(PhysicsAdaptor&& handle) noexcept;
115
116   /**
117    * Initialize the physics system.
118    *
119    * @todo Consider allowing developer to create the physics world and pass it in here.
120    *
121    * @param[in] transform The transform matrix for DALi to Physics world space
122    * @param[in] size The size of the layer the physics actors will be drawn in
123    */
124   static PhysicsAdaptor New(const Dali::Matrix& transform, Uint16Pair size);
125
126   /**
127    * @brief Downcasts a handle to PhysicsAdaptor handle.
128    *
129    * If handle points to an PhysicsAdaptor object, the downcast produces valid handle.
130    * If not, the returned handle is left uninitialized.
131    *
132    * @SINCE_2.2.40
133    * @param[in] handle to an object
134    * @return handle to a PhysicsAdaptor object or an uninitialized handle
135    */
136   static PhysicsAdaptor DownCast(BaseHandle handle);
137
138   /**
139    * Set how long the integration should take.
140    * @param[in] timestep The length of time that the physics integration should take.
141    */
142   void SetTimestep(float timestep);
143
144   /**
145    * Get the current physics integration timestep
146    * @return the current physics integration timestep
147    */
148   float GetTimestep();
149
150   /**
151    * Returns an accessor pointer to the physics world. It automatically locks a mutex
152    * to prevent the integration step from running whilst the world is being modified.
153    *
154    * When the pointer goes out of scope, the mutex is unlocked and the physics world
155    * can run again.
156    */
157   using ScopedPhysicsAccessorPtr = std::unique_ptr<PhysicsAdaptor::ScopedPhysicsAccessor>;
158   ScopedPhysicsAccessorPtr GetPhysicsAccessor();
159
160   /**
161    * Create a layer & debug renderer
162    * The debug renderer may utilize the debug features of the native physics
163    * engine.
164    *
165    * @param[in] window The window to draw in (requires camera)
166    */
167   Dali::Layer CreateDebugLayer(Dali::Window window);
168
169   /**
170    * Converts a point in RootActor local coords (e.g. gesture)
171    * into physics space coords.
172    * @param vector The point to convert
173    * @return The converted point
174    */
175   Dali::Vector3 TranslateToPhysicsSpace(Dali::Vector3 vector);
176
177   /**
178    * Convert a rotation in DALi coordinate system into physics space.
179    * @param[in] rotation The rotation to convert
180    * @return the converted rotation.
181    */
182   Dali::Quaternion TranslateToPhysicsSpace(Dali::Quaternion rotation);
183
184   /**
185    * Converts a point in physics space coords.
186    * into RootActor local coords
187    * @param vector The point to convert
188    * @return The converted point
189    */
190   Dali::Vector3 TranslateFromPhysicsSpace(Dali::Vector3 vector);
191
192   /**
193    * Convert a rotation in physics coordinate system into DALi space.
194    * @param[in] rotation The rotation to convert
195    * @return the converted rotation.
196    */
197   Dali::Quaternion TranslateFromPhysicsSpace(Dali::Quaternion rotation);
198
199   /**
200    * Converts a vector (not a point) in DALi space into physics space.
201    * @param vector The vector to convert
202    * @return The converted vector
203    */
204   Dali::Vector3 ConvertVectorToPhysicsSpace(Dali::Vector3 vector);
205
206   /**
207    * Converts a vector (not a point) in physics space to DALi space
208    * @param vector The vector to convert
209    * @return The converted vector
210    */
211   Dali::Vector3 ConvertVectorFromPhysicsSpace(Dali::Vector3 vector);
212
213   /**
214    * Set up the transform from world space to physics space
215    * @param[in] transform The transform matrix for DALi to Physics world space
216    * @param[in] size The size of the layer the physics actors will be drawn in
217    */
218   void SetTransformAndSize(const Dali::Matrix& transform, Uint16Pair size);
219
220   /**
221    * Set the integration state. If it's turned on, physics will run
222    * during the update frame callback.
223    * @note This is ON by default
224    * @param[in] state the new integration state
225    */
226   void SetIntegrationState(IntegrationState state);
227
228   /**
229    * Get the integration state.
230    * @return the new integration state
231    */
232   IntegrationState GetIntegrationState();
233
234   /**
235    * Set the debug state. If debug is turned on, use the physics engine
236    * debug to show wireframes in a layer above the root actor.
237    * @note This is OFF by default
238    * @param[in] state the new debug state
239    */
240   void SetDebugState(DebugState state);
241
242   /**
243    * Get the debug state.
244    * @return the new debug state
245    */
246   DebugState GetDebugState();
247
248   /**
249    * Add an actor / body pair.
250    * @pre It's expected that the client has added the body to the physics world.
251    *
252    * @param[in] actor The actor used for rendering the physics object
253    * @param[in] body The physics object
254    * @return a handle to the actor / body pair.
255    */
256   PhysicsActor AddActorBody(Dali::Actor actor, Dali::Any body);
257
258   /**
259    * Get the physics actor associated with the given body
260    * @param[in] body The physics body
261    * @return the associated physics actor
262    */
263   PhysicsActor GetPhysicsActor(Dali::Any body);
264
265   /**
266    * Get the root actor (which holds all the actor/body pairs)
267    */
268   Dali::Actor GetRootActor();
269
270   /**
271    * Convert DALi touch point into a picking ray in the physics world.
272    *
273    * These can then be used to hit test the PhysicsWorld
274    *
275    * @param[in] origin The origin in DALi world space
276    * @param[in] direction The direction of the picking ray
277    * @param[out] rayFromWorld The origin in physics world space
278    * @param[out] rayToWorld A point along the direction on the far side of the
279    * physics world
280    *
281    * Example:
282    *   OnTouched(Dali::Actor actor, Dali::TouchEvent& touch)
283    *   {
284    *     ..
285    *     Vector3 origin, direction;
286    *     Dali::HitTestAlgorithm::BuildPickingRay(renderTask, touch.GetScreenPosition(0), origin, direction);
287    *     btVector3 rayFromWorld, rayToWorld;
288    *     physicsAdaptor.BuildPickingRay(origin, direction, rayFromWorld, rayToWorld);
289    *     auto scopedAccessor = physicsAdaptor.GetPhysicsAccessor();
290    *     body = scopedAccessor->Get().HitTest(rayFromWorld, rayToWorld, ..);
291    *   }
292    */
293   void BuildPickingRay(Dali::Vector3 origin, Dali::Vector3 direction, Dali::Vector3& rayFromWorld, Dali::Vector3& rayToWorld);
294
295   /**
296    * Project a point from the origin (in DALi space) a distance along
297    * the direction vector (in DALi space), and return the projected
298    * point in Physics space.
299    *
300    * @param[in] origin    Origin in DALi world space
301    * @param[in] direction Direction in DALi world space
302    * @param[in] distance  Distance along the direction vector
303    * @return the projected point, converted to the Physics space.
304    */
305   Dali::Vector3 ProjectPoint(Dali::Vector3 origin, Dali::Vector3 direction, float distance);
306
307   /**
308    * Queue a function to be executed before the physics integration in the update thread.
309    *
310    * @param[in] function to execute. This can be any method, and it can work fine with
311    * physics bodies etc, but it must not be used with DALI event side objects, as this
312    * will very likely cause the update thread to crash.
313    */
314   void Queue(std::function<void(void)> function);
315
316   /**
317    * Create a sync point for queued functions.
318    *
319    * Ensures that any queued functions are processed after this sync
320    * point is seen in the Update::FrameCallback, which will be in the
321    * same frame as any other DALi properties set during this event
322    * handler invocation.
323    *
324    * @param[in] None
325    */
326   void CreateSyncPoint();
327
328 public: // Not intended for developer use
329   /// @cond internal
330   /**
331    * @note Not intented for application developers
332    */
333   explicit DALI_INTERNAL PhysicsAdaptor(Internal::PhysicsAdaptor* impl);
334   /// @endcond
335 };
336
337 } // namespace Dali::Toolkit::Physics
338
339 #endif //DALI_TOOLKIT_PHYSICS_ADAPTOR_H