[Tizen] Added integration api to physics
[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   Lock();
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   Unlock();
95 }
96
97 Dali::Any BulletPhysicsWorld::GetNative()
98 {
99   return mDynamicsWorld;
100 }
101
102 void BulletPhysicsWorld::Integrate(float timestep)
103 {
104   if(mPhysicsIntegrateState == Physics::PhysicsAdaptor::IntegrationState::ON)
105   {
106     mDynamicsWorld->stepSimulation(timestep);
107   }
108   if(mDynamicsWorld->getDebugDrawer() && mPhysicsDebugState == Physics::PhysicsAdaptor::DebugState::ON)
109   {
110     mDynamicsWorld->debugDrawWorld();
111   }
112 }
113
114 inline btVector3 ConvertVector(Dali::Vector3 vector)
115 {
116   return btVector3(vector.x, vector.y, vector.z);
117 }
118
119 Dali::Any BulletPhysicsWorld::HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Any nativeFilter, Dali::Vector3& localPivot, float& distanceFromCamera)
120 {
121   btRigidBody* hitBody{nullptr};
122
123   btVector3                                  origin = ConvertVector(rayFromWorld);
124   btVector3                                  end    = ConvertVector(rayToWorld);
125   btCollisionWorld::ClosestRayResultCallback rayResultCallback(origin, end);
126   rayResultCallback.m_flags |= btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest;
127
128   mDynamicsWorld->rayTest(origin, end, rayResultCallback);
129   if(rayResultCallback.hasHit())
130   {
131     auto         pickPos = rayResultCallback.m_hitPointWorld;
132     btRigidBody* body    = (btRigidBody*)btRigidBody::upcast(rayResultCallback.m_collisionObject);
133     if(body)
134     {
135       if(!(body->isStaticObject() || body->isKinematicObject()))
136       {
137         hitBody            = body; // Found a dynamic body.
138         distanceFromCamera = (pickPos - origin).length();
139
140         btVector3 pivot = body->getCenterOfMassTransform().inverse() * pickPos;
141         localPivot.x    = pivot.x();
142         localPivot.y    = pivot.y();
143         localPivot.z    = pivot.z();
144       }
145     }
146   }
147   Dali::Any bodyPtr;
148   if(hitBody)
149   {
150     bodyPtr = hitBody;
151   }
152
153   return bodyPtr;
154 }
155
156 } // namespace Dali::Toolkit::Physics::Internal