1 #ifndef DALI_TOOLKIT_PHYSICS_ADAPTOR_H
2 #define DALI_TOOLKIT_PHYSICS_ADAPTOR_H
5 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
27 #include <dali-toolkit/public-api/dali-toolkit-common.h>
29 namespace Dali::Toolkit::Physics
37 } // namespace Internal
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.
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.
46 class DALI_TOOLKIT_API PhysicsAdaptor : public BaseHandle
49 enum class IntegrationState
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.
66 * When it goes out of scope, the mutex is unlocked, and the integration step
69 struct ScopedPhysicsAccessor
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*>();
79 Dali::Any GetNative();
82 * Hit test the physics world and return the nearest body.
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.
90 Dali::Any HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Vector3& localPivot, float& distanceFromCamera);
93 ScopedPhysicsAccessor(ScopedPhysicsAccessor&) = delete;
94 const ScopedPhysicsAccessor& operator=(const ScopedPhysicsAccessor&) = delete;
99 ~ScopedPhysicsAccessor();
102 ScopedPhysicsAccessor(Internal::PhysicsWorld& world);
103 friend Internal::PhysicsAdaptor;
111 PhysicsAdaptor(const PhysicsAdaptor& handle);
112 PhysicsAdaptor(PhysicsAdaptor&& rhs) noexcept;
113 PhysicsAdaptor& operator=(const PhysicsAdaptor& handle);
114 PhysicsAdaptor& operator=(PhysicsAdaptor&& handle) noexcept;
117 * Initialize the physics system.
119 * @todo Consider allowing developer to create the physics world and pass it in here.
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
124 static PhysicsAdaptor New(const Dali::Matrix& transform, Uint16Pair size);
127 * @brief Downcasts a handle to PhysicsAdaptor handle.
129 * If handle points to an PhysicsAdaptor object, the downcast produces valid handle.
130 * If not, the returned handle is left uninitialized.
133 * @param[in] handle to an object
134 * @return handle to a PhysicsAdaptor object or an uninitialized handle
136 static PhysicsAdaptor DownCast(BaseHandle handle);
139 * Set how long the integration should take.
140 * @param[in] timestep The length of time that the physics integration should take.
142 void SetTimestep(float timestep);
145 * Get the current physics integration timestep
146 * @return the current physics integration timestep
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.
154 * When the pointer goes out of scope, the mutex is unlocked and the physics world
157 using ScopedPhysicsAccessorPtr = std::unique_ptr<PhysicsAdaptor::ScopedPhysicsAccessor>;
158 ScopedPhysicsAccessorPtr GetPhysicsAccessor();
161 * Create a layer & debug renderer
162 * The debug renderer may utilize the debug features of the native physics
165 * @param[in] window The window to draw in (requires camera)
167 Dali::Layer CreateDebugLayer(Dali::Window window);
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
175 Dali::Vector3 TranslateToPhysicsSpace(Dali::Vector3 vector);
178 * Convert a rotation in DALi coordinate system into physics space.
179 * @param[in] rotation The rotation to convert
180 * @return the converted rotation.
182 Dali::Quaternion TranslateToPhysicsSpace(Dali::Quaternion rotation);
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
190 Dali::Vector3 TranslateFromPhysicsSpace(Dali::Vector3 vector);
193 * Convert a rotation in physics coordinate system into DALi space.
194 * @param[in] rotation The rotation to convert
195 * @return the converted rotation.
197 Dali::Quaternion TranslateFromPhysicsSpace(Dali::Quaternion rotation);
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
204 Dali::Vector3 ConvertVectorToPhysicsSpace(Dali::Vector3 vector);
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
211 Dali::Vector3 ConvertVectorFromPhysicsSpace(Dali::Vector3 vector);
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
218 void SetTransformAndSize(const Dali::Matrix& transform, Uint16Pair size);
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
226 void SetIntegrationState(IntegrationState state);
229 * Get the integration state.
230 * @return the new integration state
232 IntegrationState GetIntegrationState();
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
240 void SetDebugState(DebugState state);
243 * Get the debug state.
244 * @return the new debug state
246 DebugState GetDebugState();
249 * Add an actor / body pair.
250 * @pre It's expected that the client has added the body to the physics world.
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.
256 PhysicsActor AddActorBody(Dali::Actor actor, Dali::Any body);
259 * Get the physics actor associated with the given body
260 * @param[in] body The physics body
261 * @return the associated physics actor
263 PhysicsActor GetPhysicsActor(Dali::Any body);
266 * Get the root actor (which holds all the actor/body pairs)
268 Dali::Actor GetRootActor();
271 * Convert DALi touch point into a picking ray in the physics world.
273 * These can then be used to hit test the PhysicsWorld
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
282 * OnTouched(Dali::Actor actor, Dali::TouchEvent& touch)
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, ..);
293 void BuildPickingRay(Dali::Vector3 origin, Dali::Vector3 direction, Dali::Vector3& rayFromWorld, Dali::Vector3& rayToWorld);
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.
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.
305 Dali::Vector3 ProjectPoint(Dali::Vector3 origin, Dali::Vector3 direction, float distance);
308 * Queue a function to be executed before the physics integration in the update thread.
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.
314 void Queue(std::function<void(void)> function);
317 * Create a sync point for queued functions.
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.
326 void CreateSyncPoint();
328 public: // Not intended for developer use
331 * @note Not intented for application developers
333 explicit DALI_INTERNAL PhysicsAdaptor(Internal::PhysicsAdaptor* impl);
337 } // namespace Dali::Toolkit::Physics
339 #endif //DALI_TOOLKIT_PHYSICS_ADAPTOR_H