Adding chipmunk implementation for physics adaptor
[platform/core/uifw/dali-toolkit.git] / dali-physics / internal / bullet-impl / bullet-physics-world-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/bullet-impl/bullet-physics-world-impl.h>
19
20 // External Headers
21 #include <BulletCollision/NarrowPhaseCollision/btRaycastCallback.h>
22 #include <btBulletCollisionCommon.h>
23 #include <memory>
24
25 // Internal Headers
26 #include <dali/dali.h>
27 #include <dali/devel-api/common/stage-devel.h>
28 #include <dali/devel-api/update/frame-callback-interface.h>
29
30 namespace Dali::Toolkit::Physics::Internal
31 {
32 std::unique_ptr<PhysicsWorld> BulletPhysicsWorld::New(Dali::Actor rootActor, Dali::CallbackBase* updateCallback)
33 {
34   std::unique_ptr<BulletPhysicsWorld> world = std::make_unique<BulletPhysicsWorld>(rootActor, updateCallback);
35   world->Initialize();
36   return world;
37 }
38
39 BulletPhysicsWorld::BulletPhysicsWorld(Dali::Actor rootActor, Dali::CallbackBase* updateCallback)
40 : PhysicsWorld(rootActor, updateCallback)
41 {
42 }
43
44 void BulletPhysicsWorld::OnInitialize(/*void* dynamicsWorld*/)
45 {
46   // @todo Should enable developer to supply their own created DynamicsWorld.
47
48   mCollisionConfiguration = new btDefaultCollisionConfiguration();
49   mDispatcher             = new btCollisionDispatcher(mCollisionConfiguration);
50   mBroadphase             = new btDbvtBroadphase();
51   mSolver                 = new btSequentialImpulseConstraintSolver;
52   mDynamicsWorld          = new btDiscreteDynamicsWorld(mDispatcher, mBroadphase, mSolver, mCollisionConfiguration);
53 }
54
55 BulletPhysicsWorld::~BulletPhysicsWorld()
56 {
57   Dali::Mutex::ScopedLock lock(mMutex);
58
59   if(mDynamicsWorld)
60   {
61     int i;
62     for(i = mDynamicsWorld->getNumConstraints() - 1; i >= 0; i--)
63     {
64       mDynamicsWorld->removeConstraint(mDynamicsWorld->getConstraint(i));
65     }
66     for(i = mDynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
67     {
68       btCollisionObject* obj  = mDynamicsWorld->getCollisionObjectArray()[i];
69       btRigidBody*       body = btRigidBody::upcast(obj);
70       if(body && body->getMotionState())
71       {
72         delete body->getMotionState();
73       }
74       mDynamicsWorld->removeCollisionObject(obj);
75       delete obj;
76     }
77   }
78
79   /*
80   for (int j = 0; j < m_collisionShapes.size(); j++)
81   {
82     btCollisionShape* shape = mCollisionShapes[j];
83     delete shape;
84   }
85   mCollisionShapes.clear();
86   */
87
88   delete mDynamicsWorld;
89   delete mSolver;
90   delete mBroadphase;
91   delete mDispatcher;
92   delete mCollisionConfiguration;
93 }
94
95 Dali::Any BulletPhysicsWorld::GetNative()
96 {
97   return mDynamicsWorld;
98 }
99
100 void BulletPhysicsWorld::Integrate(float timestep)
101 {
102   if(mPhysicsIntegrateState == Physics::PhysicsAdaptor::IntegrationState::ON)
103   {
104     mDynamicsWorld->stepSimulation(timestep);
105   }
106   if(mDynamicsWorld->getDebugDrawer() && mPhysicsDebugState == Physics::PhysicsAdaptor::DebugState::ON)
107   {
108     mDynamicsWorld->debugDrawWorld();
109   }
110 }
111
112 inline btVector3 ConvertVector(Dali::Vector3 vector)
113 {
114   return btVector3(vector.x, vector.y, vector.z);
115 }
116
117 Dali::Any BulletPhysicsWorld::HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Vector3& localPivot, float& distanceFromCamera)
118 {
119   btRigidBody* hitBody{nullptr};
120
121   btVector3                                  origin = ConvertVector(rayFromWorld);
122   btVector3                                  end    = ConvertVector(rayToWorld);
123   btCollisionWorld::ClosestRayResultCallback rayResultCallback(origin, end);
124   rayResultCallback.m_flags |= btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest;
125
126   mDynamicsWorld->rayTest(origin, end, rayResultCallback);
127   if(rayResultCallback.hasHit())
128   {
129     auto         pickPos = rayResultCallback.m_hitPointWorld;
130     btRigidBody* body    = (btRigidBody*)btRigidBody::upcast(rayResultCallback.m_collisionObject);
131     if(body)
132     {
133       if(!(body->isStaticObject() || body->isKinematicObject()))
134       {
135         hitBody            = body; // Found a dynamic body.
136         distanceFromCamera = (pickPos - origin).length();
137
138         btVector3 pivot = body->getCenterOfMassTransform().inverse() * pickPos;
139         localPivot.x    = pivot.x();
140         localPivot.y    = pivot.y();
141         localPivot.z    = pivot.z();
142       }
143     }
144   }
145   Dali::Any bodyPtr;
146   if(hitBody)
147   {
148     bodyPtr = hitBody;
149   }
150
151   return bodyPtr;
152 }
153
154 } // namespace Dali::Toolkit::Physics::Internal