[dali_2.3.21] Merge branch 'devel/master'
[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 #include <functional> ///< for std::function
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/public-api/dali-toolkit-common.h>
29
30 namespace Dali::Toolkit::Physics
31 {
32 class PhysicsActor;
33
34 namespace Internal
35 {
36 class PhysicsAdaptor;
37 class PhysicsWorld;
38 } // namespace Internal
39
40 /**
41  * Adaptor to manage access to the physics world and pairing actors and physics
42  * bodies, plus some translation methods to/from the physics space and dali space.
43  *
44  * Also manages a debug renderer that may utilize the physics engine debug.
45  * It is up to the developer to retrieve the root actor and parent it into the scene.
46  */
47 class DALI_TOOLKIT_API PhysicsAdaptor : public BaseHandle
48 {
49 public:
50   /**
51    * @brief Enumeration to turn the integration step on or off.
52    */
53   enum class IntegrationState
54   {
55     OFF,
56     ON
57   };
58
59   /**
60    * @brief Enumeration to turn the debug rendering on or off
61    */
62   enum class DebugState
63   {
64     OFF,
65     ON
66   };
67
68   /**
69    * @brief Scoped accessor to the physics world.
70    *
71    * @SINCE_2_2.43
72    * Automatically locks the physics world with a mutex to prevent the
73    * integration step from running whilst the developer is accessing
74    * the world, e.g. to add/remove bodies or constraints, or to
75    * perform hit-test.
76    *
77    * When it goes out of scope, the mutex is unlocked, and the integration step
78    * can resume.
79    */
80   struct ScopedPhysicsAccessor
81   {
82   public:
83     /**
84      * @brief Get a pointer to the native world.
85      *
86      * @SINCE_2_2.43
87      * This uses DALi::Any wrapper to ensure that the same interface can be used
88      * for both 2d and 3d physics. It can be cast to the right type using the
89      * following construct:
90      *   auto accessor = PhysicsAdaptor.GetPhysicsAccessor();
91      *   auto bulletWorld = accessor->GetNative().Get<btDiscreteDynamiscWorld*>();
92      */
93     Dali::Any GetNative();
94
95     /**
96      * @brief Hit test the physics world and return the nearest body.
97      *
98      * @SINCE_2_2.43
99      * @param[in] rayFromWorld The origin in physics world space
100      * @param[in] rayToWorld A point along the direction on the far side of the physics world
101      * @param[in] nativeFilter a native body / shape filter
102      * @param[out] localPivot The hit point local to the body
103      * @param[out] distanceFromCamera The distance of the pick point from the camera
104      * @return Empty value if no dynamic body found, otherwise a valid ptr to the hit body.
105      */
106     Dali::Any HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Any nativeFilter, Dali::Vector3& localPivot, float& distanceFromCamera);
107
108     // Not copyable
109     ScopedPhysicsAccessor(ScopedPhysicsAccessor&) = delete;
110     const ScopedPhysicsAccessor& operator=(const ScopedPhysicsAccessor&) = delete;
111
112     /**
113      * @brief Destructor.
114      *
115      * On leaving scope, the mutex is unlocked and the physics integration step
116      * can resume.
117      */
118     ~ScopedPhysicsAccessor();
119
120   private:
121     /**
122      * @brief Private constructor.
123      *
124      * It is created by the physics adaptor.
125      */
126     ScopedPhysicsAccessor(Internal::PhysicsWorld& world);
127     friend Internal::PhysicsAdaptor;
128
129     struct Impl; ///< Opaque implementation structure
130     Impl* mImpl;
131   };
132
133   /**
134    * @brief Creates an uninitalized PhysicsAdaptor, this can be initialized with PhysicsAdaptor::New().
135    *
136    * @SINCE_2_2.43
137    * Calling member functions with an uninitialized PhysicsAdaptor handle is not allowed.
138    */
139   PhysicsAdaptor();
140
141   /**
142    * @brief Destructor
143    *
144    * This is non-virtual since derived Handle types must not contain data or virtual methods.
145    * @SINCE_2_2.43
146    */
147   ~PhysicsAdaptor();
148
149   /**
150    * @brief Copy Constructor.
151    *
152    * @SINCE_2_2.43
153    * @param[in] handle The handle to copy
154    * @note This creates a new handle, but does not create a new implementation object.
155    */
156   PhysicsAdaptor(const PhysicsAdaptor& handle);
157
158   /**
159    * @brief Move Constructor.
160    *
161    * @SINCE_2_2.43
162    * @param[in] handle A reference to the handle to move
163    */
164   PhysicsAdaptor(PhysicsAdaptor&& rhs) noexcept;
165
166   /**
167    * @brief Assignment operator.
168    *
169    * @SINCE_2_2.43
170    * @param[in] handle A reference to the handle to move
171    * @return a reference to this handle
172    */
173   PhysicsAdaptor& operator=(const PhysicsAdaptor& handle);
174
175   /**
176    * @brief Move Assignment operator.
177    *
178    * @SINCE_2_2.43
179    * @param[in] handle A reference to the handle to move
180    * @return a reference to this handle
181    */
182   PhysicsAdaptor& operator=(PhysicsAdaptor&& handle) noexcept;
183
184   /**
185    * @brief Initialize the physics system.
186    *
187    * @SINCE_2_2.43
188    * @param[in] transform The transform matrix for DALi to Physics world space
189    * @param[in] size The size of the layer the physics actors will be drawn in
190    */
191   static PhysicsAdaptor New(const Dali::Matrix& transform, Uint16Pair size);
192
193   /**
194    * @brief Downcasts a handle to PhysicsAdaptor handle.
195    *
196    * If handle points to an PhysicsAdaptor object, the downcast produces valid handle.
197    * If not, the returned handle is left uninitialized.
198    *
199    * @SINCE_2_2.43
200    * @param[in] handle to an object
201    * @return handle to a PhysicsAdaptor object or an uninitialized handle
202    */
203   static PhysicsAdaptor DownCast(BaseHandle handle);
204
205   /**
206    * @brief Set how long the integration should take.
207    *
208    * @SINCE_2_2.43
209    * @param[in] timestep The length of time that the physics integration should take.
210    */
211   void SetTimestep(float timestep);
212
213   /**
214    * @brief Get the current physics integration timestep.
215    *
216    * @SINCE_2_2.43
217    * @return the current physics integration timestep
218    */
219   float GetTimestep() const;
220
221   /**
222    * @brief Type to represent a pointer to a scoped accessor.
223    *
224    * @SINCE_2_2.43
225    */
226   using ScopedPhysicsAccessorPtr = std::unique_ptr<PhysicsAdaptor::ScopedPhysicsAccessor>;
227
228   /**
229    * @brief Returns an accessor to the physics world.
230    *
231    * @SINCE_2_2.43
232    * It automatically locks a mutex to prevent the integration step
233    * from running whilst the world is being modified.
234    *
235    * When the pointer goes out of scope, the mutex is unlocked and the physics world
236    * can run again.
237    * @return the scoped accessor
238    */
239   ScopedPhysicsAccessorPtr GetPhysicsAccessor();
240
241   /**
242    * @brief Create a layer & debug renderer.
243    *
244    * @SINCE_2_2.43
245    * The debug renderer may utilize the debug features of the native physics
246    * engine.
247    *
248    * @param[in] window The window to draw in (requires camera)
249    * @return The debug layer
250    */
251   Dali::Layer CreateDebugLayer(Dali::Window window);
252
253   /**
254    * @brief Converts a point in RootActor local coords (e.g. gesture)
255    * into physics space coords.
256    *
257    * @SINCE_2_2.43
258    * @param vector The point to convert
259    * @return The converted point
260    */
261   Dali::Vector3 TranslateToPhysicsSpace(Dali::Vector3 vector) const;
262
263   /**
264    * @brief Convert a rotation in DALi coordinate system into physics space.
265    *
266    * @SINCE_2_2.43
267    * @param[in] rotation The rotation to convert
268    * @return the converted rotation.
269    */
270   Dali::Quaternion TranslateToPhysicsSpace(Dali::Quaternion rotation) const;
271
272   /**
273    * @brief Converts a point in physics space coords into RootActor local coords.
274    *
275    * @SINCE_2_2.43
276    * @param vector The point to convert
277    * @return The converted point
278    */
279   Dali::Vector3 TranslateFromPhysicsSpace(Dali::Vector3 vector) const;
280
281   /**
282    * @brief Convert a rotation in physics coordinate system into DALi space.
283    *
284    * @SINCE_2_2.43
285    * @param[in] rotation The rotation to convert
286    * @return the converted rotation.
287    */
288   Dali::Quaternion TranslateFromPhysicsSpace(Dali::Quaternion rotation) const;
289
290   /**
291    * @brief Converts a vector (not a point) in DALi space into physics space.
292    *
293    * @SINCE_2_2.43
294    * @param vector The vector to convert
295    * @return The converted vector
296    */
297   Dali::Vector3 ConvertVectorToPhysicsSpace(Dali::Vector3 vector) const;
298
299   /**
300    * @brief Converts a vector (not a point) in physics space to DALi space.
301    *
302    * @SINCE_2_2.43
303    * @param vector The vector to convert
304    * @return The converted vector
305    */
306   Dali::Vector3 ConvertVectorFromPhysicsSpace(Dali::Vector3 vector) const;
307
308   /**
309    * @brief Set up the transform from world space to physics space.
310    *
311    * @SINCE_2_2.43
312    * @param[in] transform The transform matrix for DALi to Physics world space
313    * @param[in] size The size of the layer the physics actors will be drawn in
314    */
315   void SetTransformAndSize(const Dali::Matrix& transform, Uint16Pair size);
316
317   /**
318    * @brief Set the integration state.
319    *
320    * @SINCE_2_2.43
321    * If it's turned off, physics will be paused.
322    * @note This is ON by default
323    * @param[in] state the new integration state
324    */
325   void SetIntegrationState(IntegrationState state);
326
327   /**
328    * @brief Get the integration state.
329    *
330    * @SINCE_2_2.43
331    * @return the new integration state
332    */
333   IntegrationState GetIntegrationState() const;
334
335   /**
336    * @brief Set the debug state.
337    *
338    * @SINCE_2_2.43
339    * If debug is turned on, use the physics engine
340    * debug to show wireframes in a layer above the root actor.
341    * @note This is OFF by default
342    * @param[in] state the new debug state
343    */
344   void SetDebugState(DebugState state);
345
346   /**
347    * @brief Get the debug state.
348    *
349    * @SINCE_2_2.43
350    * @return the new debug state
351    */
352   DebugState GetDebugState() const;
353
354   /**
355    * @brief Add an actor / body pair.
356    * @pre It's expected that the client has added the body to the physics world.
357    *
358    * The adaptor does not "take ownership" of the actor or the physics body.
359    * @SINCE_2_2.43
360    * @param[in] actor The actor used for rendering the physics object
361    * @param[in] body The physics object
362    * @return a handle to the actor / body pair.
363    */
364   PhysicsActor AddActorBody(Dali::Actor actor, Dali::Any body);
365
366   /**
367    * @brief Remove the actor / body.
368    *
369    * This will unparent the actor from the root actor and disassociate it from
370    * the body.
371    *
372    * It is the responsibility of the client to remove the body from the physics world
373    * and destroy it at an appropriate time. Create a scoped accessor to ensure
374    * that the integration step isn't being run when doing so.
375    *
376    * If the root actor is holding the last reference to the actor, it will be
377    * destroyed automatically, otherwise it is the responsibility of the client to
378    * dereference the actor.
379    *
380    * @SINCE_2_2.43
381    * @param[in] physicsActor The actor / body pair to remove.
382    */
383   void RemoveActorBody(PhysicsActor physicsActor);
384
385   /**
386    * @brief Get the physics actor associated with the given body.
387    *
388    * @SINCE_2_2.43
389    * @param[in] body The physics body
390    * @return the associated physics actor
391    */
392   PhysicsActor GetPhysicsActor(Dali::Any body) const;
393
394   /**
395    * @brief Get the root actor (which holds all the actor/body pairs).
396    *
397    * @SINCE_2_2.43
398    * @return the root actor.
399    */
400   Dali::Actor GetRootActor() const;
401
402   /**
403    * @brief Convert DALi touch point into a picking ray in the physics world.
404    *
405    * These can then be used to hit test the PhysicsWorld
406    *
407    * @SINCE_2_2.43
408    * @param[in] origin The origin in DALi world space
409    * @param[in] direction The direction of the picking ray
410    * @param[out] rayFromWorld The origin in physics world space
411    * @param[out] rayToWorld A point along the direction on the far side of the physics world
412    *
413    * Example:
414    *   OnTouched(Dali::Actor actor, Dali::TouchEvent& touch)
415    *   {
416    *     ..
417    *     Vector3 origin, direction;
418    *     Dali::HitTestAlgorithm::BuildPickingRay(renderTask, touch.GetScreenPosition(0), origin, direction);
419    *     btVector3 rayFromWorld, rayToWorld;
420    *     physicsAdaptor.BuildPickingRay(origin, direction, rayFromWorld, rayToWorld);
421    *     auto scopedAccessor = physicsAdaptor.GetPhysicsAccessor();
422    *     Dali::Any nativeFilter;
423    *     body = scopedAccessor->Get().HitTest(rayFromWorld, rayToWorld, nativeFilter, ..);
424    *   }
425    */
426   void BuildPickingRay(Dali::Vector3 origin, Dali::Vector3 direction, Dali::Vector3& rayFromWorld, Dali::Vector3& rayToWorld);
427
428   /**
429    * @brief Project a point from the origin (in DALi space) a distance along
430    * the direction vector (in DALi space), and return the projected
431    * point in Physics space.
432    *
433    * @SINCE_2_2.43
434    * @param[in] origin    Origin in DALi world space
435    * @param[in] direction Direction in DALi world space
436    * @param[in] distance  Distance along the direction vector
437    * @return the projected point, converted to the Physics space.
438    */
439   Dali::Vector3 ProjectPoint(Dali::Vector3 origin, Dali::Vector3 direction, float distance);
440
441   /**
442    * @brief Queue a function to be executed before the physics integration in the update thread.
443    *
444    * @SINCE_2_2.43
445    * Multiple functions can be queued up. They are executed in the update frame
446    * callback when the next sync point is seen, so CreateSyncPoint() should be called
447    * afterwards for this to be executed.
448    *
449    * @param[in] function to execute. This can be any method, and it can work fine with
450    * physics bodies etc, but it must not be used with DALI event side objects, as this
451    * will very likely cause the update thread to crash.
452    */
453   void Queue(std::function<void(void)> function);
454
455   /**
456    * @brief Create a sync point for queued functions.
457    *
458    * @SINCE_2_2.43
459    * Ensures that any previously queued functions are processed
460    * in the Update::FrameCallback during the same frame as other
461    * DALi properties set during this event handler invocation.
462    * For example,
463    *   boxActor = Actor::New();
464    *   //... Create box actor renderer ...
465    *   btRigidBodyConstructionInfo info;
466    *   //... set construction properties
467    *   boxBody = new btRigidBody(info);
468    *   auto boxPhysicsActor = physicsAdaptor.AddActorBody(boxActor, boxBody);
469    *   boxActor.SetProperty(Actor::Property::VISIBLE, true);
470    *   boxActor.SetProperty(Actor::Property::OPACITY, 0.5f);
471    *   physicsAdaptor.Queue([boxBody](){ boxBody->activate(true);});
472    *   btVector3 impulse(4, 5, 6);
473    *   btVector3 position();
474    *   physicsAdaptor.Queue([boxBody](){ boxBody->applyImpulse(impulse, position);});
475    *   physicsAdaptor.CreateSyncPoint();
476    *
477    * Ensures that the box has both render properties and physics properties applied
478    * during the same frame.
479    */
480   void CreateSyncPoint();
481
482 public: // Not intended for developer use
483   /// @cond internal
484   /**
485    * @brief This constructor is used by PhysicsAdaptor::New() methods.
486    *
487    * @SINCE_2_2.43
488    * @param[in] impl A pointer to a newly allocated Dali resource.
489    * @note Not intended for application developers
490    */
491   explicit DALI_INTERNAL PhysicsAdaptor(Internal::PhysicsAdaptor* impl);
492   /// @endcond
493 };
494
495 } // namespace Dali::Toolkit::Physics
496
497 #endif //DALI_TOOLKIT_PHYSICS_ADAPTOR_H