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