Actor's Transformation API Cleanup
[platform/core/uifw/dali-core.git] / dali / internal / update / dynamics / scene-graph-dynamics-body.cpp
1 /*
2  * Copyright (c) 2014 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
18 // CLASS HEADER
19 #include <dali/internal/update/dynamics/scene-graph-dynamics-body.h>
20
21 // INTERNAL HEADERS
22 #include <dali/integration-api/dynamics/dynamics-body-intf.h>
23 #include <dali/integration-api/dynamics/dynamics-body-settings.h>
24 #include <dali/integration-api/dynamics/dynamics-factory-intf.h>
25 #include <dali/integration-api/dynamics/dynamics-shape-intf.h>
26 #include <dali/internal/update/dynamics/scene-graph-dynamics-shape.h>
27 #include <dali/internal/update/dynamics/scene-graph-dynamics-mesh-shape.h>
28 #include <dali/internal/update/dynamics/scene-graph-dynamics-world.h>
29 #include <dali/internal/update/modeling/scene-graph-mesh.h>
30 #include <dali/internal/update/modeling/internal-mesh-data.h>
31 #include <dali/internal/update/nodes/node.h>
32
33 namespace Dali
34 {
35
36 namespace Internal
37 {
38
39 namespace SceneGraph
40 {
41
42 DynamicsBody::DynamicsBody(DynamicsWorld& world, Node& node )
43 : mBody(NULL),
44   mNode(node),
45   mWorld(world),
46   mLinearVelocity(),
47   mAngularVelocity()
48 {
49   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
50 }
51
52 DynamicsBody::~DynamicsBody()
53 {
54   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__ );
55
56   delete mBody;
57 }
58
59
60 void DynamicsBody::Initialize( Integration::DynamicsBodySettings* settings, DynamicsShape* shape )
61 {
62   DALI_ASSERT_DEBUG( shape && "NULL shape passed into DynamicsBody" );
63
64   mBody = mWorld.GetDynamicsFactory().CreateDynamicsBody();
65
66   if( Dali::DynamicsBodyConfig::SOFT == settings->type )
67   {
68     Mesh* mesh( static_cast<DynamicsMeshShape&>(*shape).GetMesh() );
69     DALI_ASSERT_DEBUG( mesh );
70     mMesh = mesh;
71   }
72
73   Vector3 position;
74   Quaternion rotation;
75   GetNodePositionAndRotation( position, rotation );
76   mBody->Initialize( *settings, shape->GetShape(), mWorld.GetDynamicsWorld(), position, rotation );
77   delete settings;
78 }
79
80 void DynamicsBody::SetMass(const float mass)
81 {
82   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - mass:%.2f\n", __PRETTY_FUNCTION__, mass);
83
84   mBody->SetMass( mass );
85 }
86
87 void DynamicsBody::SetElasticity(const float elasticity)
88 {
89   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - elasticity:%.1f\n", __PRETTY_FUNCTION__, elasticity);
90
91   mBody->SetElasticity( elasticity );
92 }
93
94 void DynamicsBody::SetLinearVelocity(const Vector3& velocity)
95 {
96   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (velocity:%f %f %f)\n", __PRETTY_FUNCTION__, velocity.x, velocity.y, velocity.z);
97
98   mBody->SetLinearVelocity( velocity / mWorld.GetWorldScale() );
99   mLinearVelocity[ mWorld.GetBufferIndex() ] = velocity;
100 }
101
102 Vector3 DynamicsBody::GetLinearVelocity( BufferIndex bufferIndex ) const
103 {
104   const Vector3& velocity( mLinearVelocity[ bufferIndex ] );
105
106   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (velocity:%f %f %f)\n", __PRETTY_FUNCTION__,
107                 velocity.x, velocity.y, velocity.z);
108
109   return velocity;
110 }
111
112 void DynamicsBody::SetAngularVelocity(const Vector3& velocity)
113 {
114   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (velocity:%f %f %f)\n", __PRETTY_FUNCTION__, velocity.x, velocity.y, velocity.z);
115
116   mBody->SetAngularVelocity( velocity );
117
118   mAngularVelocity[ mWorld.GetBufferIndex() ] = velocity;
119 }
120
121 Vector3 DynamicsBody::GetAngularVelocity( BufferIndex bufferIndex ) const
122 {
123   const Vector3& velocity( mAngularVelocity[ bufferIndex ] );
124
125   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (velocity:%f %f %f)\n", __PRETTY_FUNCTION__,
126                 velocity.x, velocity.y, velocity.z);
127
128   return velocity;
129 }
130
131 void DynamicsBody::SetKinematic(const bool flag)
132 {
133   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - %s\n", __PRETTY_FUNCTION__, flag ? "true" : "false" );
134
135   mBody->SetKinematic( flag );
136 }
137
138 bool DynamicsBody::IsKinematic() const
139 {
140   return mBody->IsKinematic();
141 }
142
143 void DynamicsBody::SetSleepEnabled( const bool flag)
144 {
145   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - %s\n", __PRETTY_FUNCTION__, flag ? "true" : "false" );
146
147   mBody->SetSleepEnabled( flag );
148 }
149
150 void DynamicsBody::WakeUp()
151 {
152   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
153
154   mBody->WakeUp();
155 }
156
157 void DynamicsBody::AddAnchor( const unsigned int index, const DynamicsBody* anchorBody, const bool collisions )
158 {
159   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (index: %d)\n", __PRETTY_FUNCTION__, index);
160   DALI_ASSERT_DEBUG( NULL != mBody );
161   DALI_ASSERT_DEBUG( Dali::DynamicsBodyConfig::SOFT == mBody->GetType() );
162   DALI_ASSERT_DEBUG( NULL != anchorBody && NULL != anchorBody->mBody );
163   DALI_ASSERT_DEBUG( Dali::DynamicsBodyConfig::RIGID == anchorBody->GetType() );
164
165   mBody->AddAnchor( index, anchorBody->GetBody(), collisions );
166 }
167
168 void DynamicsBody::ConserveVolume( const bool flag )
169 {
170   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (%s)\n", __PRETTY_FUNCTION__, flag ? "yes" : "no" );
171
172   mBody->ConserveVolume( flag );
173 }
174
175 void DynamicsBody::ConserveShape( const bool flag )
176 {
177   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (%s)\n", __PRETTY_FUNCTION__, flag ? "yes" : "no" );
178
179   mBody->ConserveShape( flag );
180 }
181
182 short int DynamicsBody::GetCollisionGroup() const
183 {
184   return mBody->GetCollisionGroup();
185 }
186
187 void DynamicsBody::SetCollisionGroup( const short int collisionGroup )
188 {
189   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (0x%04X)\n", __PRETTY_FUNCTION__, collisionGroup );
190   mBody->SetCollisionGroup( collisionGroup );
191 }
192
193 short int DynamicsBody::GetCollisionMask() const
194 {
195   return mBody->GetCollisionMask();
196 }
197
198 void DynamicsBody::SetCollisionMask( const short int collisionMask )
199 {
200   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s - (0x%04X)\n", __PRETTY_FUNCTION__, collisionMask );
201   mBody->SetCollisionMask( collisionMask );
202 }
203
204 int DynamicsBody::GetType() const
205 {
206   return mBody->GetType();
207 }
208
209 Integration::DynamicsBody* DynamicsBody::GetBody() const
210 {
211   return mBody;
212 }
213
214 void DynamicsBody::Connect()
215 {
216   int bodyType( mBody->GetType() );
217   if( Dali::DynamicsBodyConfig::RIGID == bodyType )
218   {
219 //    SetMotionState();
220   }
221   else if( Dali::DynamicsBodyConfig::SOFT == bodyType )
222   {
223     /*
224      * Soft body vertices get local transformation applied twice due to
225      * physics engine directly transforming all the points in a soft body's mesh
226      * then the vertices getting the transformation applied again in the shader
227      */
228     mNode.SetInhibitLocalTransform(true);
229   }
230
231   RefreshDynamics();
232
233   mWorld.AddBody(*this);
234 }
235
236 void DynamicsBody::Disconnect()
237 {
238   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::General, "%s (body: %p)\n", __PRETTY_FUNCTION__, mBody);
239
240   if( Dali::DynamicsBodyConfig::SOFT == GetType() )
241   {
242     /*
243      * Soft body vertices get local transformation applied twice due to
244      * physics engine directly transforming all the points in a soft body's mesh
245      * then the vertices getting the transformation applied again in the shader
246      */
247     mNode.SetInhibitLocalTransform(false);
248   }
249
250   mWorld.RemoveBody(*this);
251 }
252
253 void DynamicsBody::Delete()
254 {
255   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::General, "%s (body: %p)\n", __PRETTY_FUNCTION__, mBody);
256
257   mWorld.DeleteBody(*this);
258 }
259
260 void DynamicsBody::SetMotionState()
261 {
262   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
263 }
264
265 void DynamicsBody::GetNodePositionAndRotation(Vector3& position, Quaternion& rotation)
266 {
267   const BufferIndex bufferIndex = mWorld.GetBufferIndex();
268   position = mNode.GetPosition(bufferIndex) / mWorld.GetWorldScale();
269   rotation = mNode.GetRotation(bufferIndex);
270 }
271
272 void DynamicsBody::SetNodePositionAndRotation(const Vector3& position, const Quaternion& rotation)
273 {
274   const Vector3 scaledPosition(position * mWorld.GetWorldScale());
275
276   const BufferIndex bufferIndex( mWorld.GetBufferIndex() );
277   mNode.BakePosition(bufferIndex, scaledPosition);
278   mNode.BakeOrientation(bufferIndex, rotation);
279
280   if( Dali::DynamicsBodyConfig::RIGID == mBody->GetType() )
281   {
282     mLinearVelocity[bufferIndex] = mBody->GetLinearVelocity();
283     mAngularVelocity[bufferIndex] = mBody->GetAngularVelocity();
284   }
285 }
286
287 void DynamicsBody::RefreshDynamics()
288 {
289   // get node's world position and rotation
290   Vector3 position;
291   Quaternion rotation;
292   GetNodePositionAndRotation(position, rotation);
293
294   mBody->SetTransform( position, rotation );
295 }
296
297 bool DynamicsBody::RefreshNode(BufferIndex updateBufferIndex)
298 {
299   // get updated parameters
300   if( Dali::DynamicsBodyConfig::SOFT == mBody->GetType() )
301   {
302     RefreshMesh(updateBufferIndex);
303   }
304   else
305   {
306     if( !mBody->IsKinematic() )
307     {
308       // get updated parameters
309       Vector3 position;
310       Quaternion rotation;
311       mBody->GetTransform( position, rotation );
312       SetNodePositionAndRotation( position, rotation );
313     }
314   }
315
316   // TODO: Add activation state change notification
317   // interrogate dynamics body for it's activation state
318   bool activationState( mBody->IsActive() );
319
320   return activationState;
321 }
322
323 void DynamicsBody::RefreshMesh(BufferIndex updateBufferIndex)
324 {
325   Internal::MeshData& meshData( mMesh->GetMeshData( Mesh::UPDATE_THREAD ) );
326
327   mBody->GetSoftVertices( meshData.GetVertices() );
328
329   mMesh->MeshDataUpdated( updateBufferIndex, Mesh::UPDATE_THREAD, NULL );
330 }
331
332 } // namespace SceneGraph
333
334 } // namespace Internal
335
336 } // namespace Dali