Adding chipmunk implementation for physics adaptor
[platform/core/uifw/dali-toolkit.git] / dali-physics / internal / chipmunk-impl / chipmunk-physics-adaptor-impl.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // Class Header
18 #include <dali-physics/internal/chipmunk-impl/chipmunk-physics-adaptor-impl.h>
19
20 // External Headers
21 #include <utility>
22
23 // Internal Headers
24 #include <dali-physics/internal/chipmunk-impl/chipmunk-physics-world-impl.h>
25 #include <dali/dali.h>
26 #include <dali/integration-api/debug.h>
27
28 namespace
29 {
30 #if defined(DEBUG_ENABLED)
31 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_PHYSICS");
32 #endif
33
34 inline cpVect ConvertVector(Dali::Vector3 vector)
35 {
36   return cpv(vector.x, vector.y);
37 }
38
39 } // namespace
40
41 namespace Dali::Toolkit::Physics::Internal
42 {
43 PhysicsAdaptorPtr CreateNewPhysicsAdaptor(const Dali::Matrix& transform, Uint16Pair worldSize)
44 {
45   PhysicsAdaptorPtr adaptor(new ChipmunkPhysicsAdaptor());
46   adaptor->Initialize(transform, worldSize);
47   return adaptor;
48 }
49
50 ChipmunkPhysicsAdaptor::ChipmunkPhysicsAdaptor()
51 : PhysicsAdaptor()
52 {
53 }
54
55 ChipmunkPhysicsAdaptor::~ChipmunkPhysicsAdaptor()
56 {
57   // @todo Ensure physics bodies don't leak
58 }
59
60 void ChipmunkPhysicsAdaptor::OnInitialize(const Dali::Matrix& transform, Uint16Pair worldSize)
61 {
62   mTransform        = transform;
63   mInverseTransform = transform;
64   mInverseTransform.Invert();
65   mSize = worldSize;
66
67   mPhysicsWorld = ChipmunkPhysicsWorld::New(mRootActor,
68                                             Dali::MakeCallback(mSlotDelegate.GetSlot(),
69                                                                &PhysicsAdaptor::OnUpdateActors));
70 }
71
72 Layer ChipmunkPhysicsAdaptor::CreateDebugLayer(Dali::Window window)
73 {
74   return Layer();
75 }
76
77 void ChipmunkPhysicsAdaptor::SetTransformAndSize(const Dali::Matrix& transform, Uint16Pair worldSize)
78 {
79   mTransform        = transform;
80   mInverseTransform = transform;
81   mInverseTransform.Invert();
82   mSize = worldSize;
83
84   GetRootActor()[Actor::Property::SIZE] = Vector3(worldSize.GetWidth(), worldSize.GetHeight(), 0);
85 }
86
87 PhysicsActorPtr ChipmunkPhysicsAdaptor::AddActorBody(Dali::Actor actor, Dali::Any body)
88 {
89   uint32_t id    = static_cast<uint32_t>(actor.GetProperty<int>(Actor::Property::ID));
90   cpBody*  cBody = body.Get<cpBody*>();
91   cpBodySetUserData(cBody, this);
92
93   mPhysicsActors.insert(std::make_pair(id, PhysicsActor::New(actor, body, *this)));
94   actor[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER;
95   actor[Actor::Property::ANCHOR_POINT]  = Dali::AnchorPoint::CENTER;
96   mRootActor.Add(actor);
97   return mPhysicsActors.at(id);
98 }
99
100 void ChipmunkPhysicsAdaptor::RemoveActorBody(PhysicsActor& physicsActor)
101 {
102   auto iter = mPhysicsActors.find(physicsActor.GetId());
103   if(iter != mPhysicsActors.end())
104   {
105     mPhysicsActors.erase(iter);
106   }
107   Dali::Actor actor = mRootActor.FindChildById(physicsActor.GetId());
108   if(actor)
109   {
110     actor.Unparent();
111   }
112   auto    body  = physicsActor.GetBody();
113   cpBody* cBody = body.Get<cpBody*>();
114   if(cBody)
115   {
116     cpBodySetUserData(cBody, nullptr);
117   }
118 }
119
120 PhysicsActorPtr ChipmunkPhysicsAdaptor::GetPhysicsActor(Dali::Any body) const
121 {
122   cpBody* cBody = body.Get<cpBody*>();
123   if(cBody)
124   {
125     return reinterpret_cast<PhysicsActor*>(cpBodyGetUserData(cBody));
126   }
127   DALI_LOG_ERROR("Body not found in physics actors");
128   return nullptr;
129 }
130
131 // Convert a position from root actor local space to physics space
132 Vector3 ChipmunkPhysicsAdaptor::TranslateToPhysicsSpace(Vector3 vector) const
133 {
134   Vector4 position = mTransform * Vector4(vector.x, vector.y, vector.z, 1.0f);
135   return Vector3(position);
136 }
137
138 // Convert a position from physics space to root actor local space
139 Vector3 ChipmunkPhysicsAdaptor::TranslateFromPhysicsSpace(Vector3 vector) const
140 {
141   Vector4 position = mInverseTransform * Vector4(vector.x, vector.y, vector.z, 1.0f);
142   return Vector3(position);
143 }
144
145 Quaternion ChipmunkPhysicsAdaptor::TranslateToPhysicsSpace(Quaternion orientation) const
146 {
147   // It's complicated.
148   return orientation;
149 }
150
151 Quaternion ChipmunkPhysicsAdaptor::TranslateFromPhysicsSpace(Quaternion orientation) const
152 {
153   // Mirroring conversion is identical in both transforms
154   return TranslateToPhysicsSpace(orientation);
155 }
156
157 // Convert a vector from dali space to physics space
158 Vector3 ChipmunkPhysicsAdaptor::ConvertVectorToPhysicsSpace(Vector3 vector) const
159 {
160   Vector4 otherVector(mTransform * Vector4(vector.x, vector.y, vector.z, 0.0f));
161   return Vector3(otherVector);
162 }
163
164 // Convert a vector from physics space to root actor local space
165 Vector3 ChipmunkPhysicsAdaptor::ConvertVectorFromPhysicsSpace(Vector3 vector) const
166 {
167   Vector4 otherVector(mInverseTransform * Vector4(vector.x, vector.y, vector.z, 0.0f));
168   return Vector3(otherVector);
169 }
170
171 void ChipmunkPhysicsAdaptor::BuildPickingRay(Vector3 origin, Vector3 direction, Dali::Vector3& rayFromWorld, Dali::Vector3& rayToWorld)
172 {
173   rayFromWorld = TranslateToPhysicsSpace(origin);
174   rayToWorld   = TranslateToPhysicsSpace(origin); // rayToWorld is identical - there's no depth
175 }
176
177 Vector3 ChipmunkPhysicsAdaptor::ProjectPoint(Vector3 origin, Vector3 direction, float distance)
178 {
179   // Ignore direction & distance.
180   return TranslateToPhysicsSpace(origin);
181 }
182
183 } // namespace Dali::Toolkit::Physics::Internal