|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: AknPhysics engine |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <e32debug.h> |
|
19 #include <aknphysics.h> |
|
20 #include <eikenv.h> |
|
21 #include <eikappui.h> |
|
22 #include <eikapp.h> |
|
23 #include <alf/alfdirectclient.h> |
|
24 |
|
25 #include "aknphysicsconstants.h" |
|
26 #include "aknphysicsengine.h" |
|
27 |
|
28 // ======== MEMBER FUNCTIONS ======== |
|
29 |
|
30 // --------------------------------------------------------------------------- |
|
31 // CAknPhysicsEngine::NewL |
|
32 // --------------------------------------------------------------------------- |
|
33 // |
|
34 CAknPhysicsEngine* CAknPhysicsEngine::NewL( CAknPhysics* aPhysics ) |
|
35 { |
|
36 CAknPhysicsEngine* self = CAknPhysicsEngine::NewLC( aPhysics ); |
|
37 CleanupStack::Pop( self ); |
|
38 return self; |
|
39 } |
|
40 |
|
41 |
|
42 // --------------------------------------------------------------------------- |
|
43 // CAknPhysicsEngine::NewLC |
|
44 // --------------------------------------------------------------------------- |
|
45 // |
|
46 CAknPhysicsEngine* CAknPhysicsEngine::NewLC( CAknPhysics* aPhysics ) |
|
47 { |
|
48 CAknPhysicsEngine* self = |
|
49 new ( ELeave ) CAknPhysicsEngine( aPhysics ); |
|
50 CleanupStack::PushL( self ); |
|
51 self->ConstructL(); |
|
52 return self; |
|
53 } |
|
54 |
|
55 |
|
56 // --------------------------------------------------------------------------- |
|
57 // CAknPhysicsEngine::~CAknPhysicsEngine |
|
58 // --------------------------------------------------------------------------- |
|
59 // |
|
60 CAknPhysicsEngine::~CAknPhysicsEngine() |
|
61 { |
|
62 DeletePhysics(); |
|
63 delete iAlfClient; |
|
64 } |
|
65 |
|
66 |
|
67 // --------------------------------------------------------------------------- |
|
68 // CAknPhysicsEngine::WorldExists |
|
69 // --------------------------------------------------------------------------- |
|
70 // |
|
71 TBool CAknPhysicsEngine::WorldExists() const |
|
72 { |
|
73 return iWorldId != NULL; |
|
74 } |
|
75 |
|
76 |
|
77 // --------------------------------------------------------------------------- |
|
78 // CAknPhysicsEngine::CreateWorld |
|
79 // --------------------------------------------------------------------------- |
|
80 // |
|
81 void CAknPhysicsEngine::CreateWorld( const TInt& aGravity ) |
|
82 { |
|
83 dInitODE(); |
|
84 iWorldId = dWorldCreate(); |
|
85 dWorldSetERP( iWorldId, REAL( KErpFactor ) ); |
|
86 dWorldSetCFM( iWorldId, REAL( KCfmFactor ) ); |
|
87 dWorldSetGravity( iWorldId, 0, 0, -REAL( aGravity ) ); |
|
88 dWorldSetAutoDisableFlag(iWorldId, 1); |
|
89 iSpace = dSimpleSpaceCreate(0); |
|
90 } |
|
91 |
|
92 |
|
93 // --------------------------------------------------------------------------- |
|
94 // CAknPhysicsEngine::CreatePlanes |
|
95 // --------------------------------------------------------------------------- |
|
96 // |
|
97 void CAknPhysicsEngine::CreatePlanes( const TInt64& aIh, |
|
98 const TInt64& aX, |
|
99 const TInt64& aY, |
|
100 const TInt64& aR ) |
|
101 { |
|
102 // Create bounding planes |
|
103 iPlaneTop = dCreatePlane( iSpace, REAL( aX ), REAL( aY ), 0, REAL( 0 ) ); |
|
104 iPlaneBottom = dCreatePlane( iSpace, REAL( -aX ), REAL( -aY ), 0, REAL( -aIh ) ); |
|
105 iPlaneLeft = dCreatePlane( iSpace, REAL( aY ), REAL( aX ), 0, REAL( 0 ) ); |
|
106 iPlaneRight = dCreatePlane( iSpace, REAL( -aY ), REAL( -aX ), 0, REAL( -aR ) ); |
|
107 |
|
108 // create z-plane to apply friction |
|
109 // bottom, z axle |
|
110 iPlaneFriction = dCreatePlane( iSpace, 0, 0, REAL( 1 ), REAL( -KZDepth ) ); |
|
111 } |
|
112 |
|
113 |
|
114 |
|
115 // --------------------------------------------------------------------------- |
|
116 // CAknPhysicsEngine::CreateViewBody |
|
117 // --------------------------------------------------------------------------- |
|
118 // |
|
119 void CAknPhysicsEngine::CreateViewBody( |
|
120 const TInt64& aWidth, const TInt64& aHeight, const TInt64& aMass ) |
|
121 { |
|
122 // create viewbox |
|
123 iViewBox = dCreateBox( iSpace, REAL( aWidth ), REAL( aHeight ), REAL( KZDepth ) ); |
|
124 iViewBody = dBodyCreate( iWorldId ); |
|
125 |
|
126 dBodySetAutoDisableFlag( iViewBody, 1 ); |
|
127 dGeomSetBody( iViewBox, iViewBody ); |
|
128 |
|
129 // Set mass for body |
|
130 dMass mass; |
|
131 dMassSetBoxTotal( &mass, |
|
132 REAL( aMass ), REAL( aWidth ), REAL( aHeight ), REAL( KZDepth ) ); |
|
133 dBodySetMass( iViewBody, &mass ); |
|
134 |
|
135 // Create JointGroup to handle contacts |
|
136 iContactGroup = dJointGroupCreate( 0 ); |
|
137 } |
|
138 |
|
139 |
|
140 // --------------------------------------------------------------------------- |
|
141 // CAknPhysicsEngine::SetViewBodyPosition |
|
142 // --------------------------------------------------------------------------- |
|
143 // |
|
144 void CAknPhysicsEngine::SetViewBodyPosition( const TPoint& aPosition ) |
|
145 { |
|
146 if ( iViewBody ) |
|
147 { |
|
148 iViewPosition = aPosition; |
|
149 TInt64 x, y; |
|
150 x = iViewPosition.iX; |
|
151 y = iViewPosition.iY; |
|
152 dBodySetPosition( |
|
153 iViewBody, |
|
154 REAL( x ), |
|
155 REAL( y ), |
|
156 REAL( -KZDepth/2 ) ); |
|
157 } |
|
158 } |
|
159 |
|
160 |
|
161 // --------------------------------------------------------------------------- |
|
162 // CAknPhysicsEngine::GetViewBodyPosition |
|
163 // --------------------------------------------------------------------------- |
|
164 // |
|
165 void CAknPhysicsEngine::GetViewBodyPosition( TPoint& aPosition ) |
|
166 { |
|
167 const dReal *pos = dBodyGetPosition( iViewBody ); |
|
168 iViewPosition.iX = dFLOAT( pos[0] ); |
|
169 iViewPosition.iY = dFLOAT( pos[1] ); |
|
170 aPosition = iViewPosition; |
|
171 } |
|
172 |
|
173 |
|
174 // --------------------------------------------------------------------------- |
|
175 // CAknPhysicsEngine::ResetViewBodyForceAndVelocity |
|
176 // --------------------------------------------------------------------------- |
|
177 // |
|
178 void CAknPhysicsEngine::ResetViewBodyForceAndVelocity() |
|
179 { |
|
180 if ( iViewBody ) |
|
181 { |
|
182 dBodySetForce( iViewBody, 0, 0, 0); |
|
183 dBodySetLinearVel( iViewBody, 0, 0, 0 ); |
|
184 } |
|
185 } |
|
186 |
|
187 |
|
188 |
|
189 // --------------------------------------------------------------------------- |
|
190 // CAknPhysicsEngine::EnableViewBody |
|
191 // --------------------------------------------------------------------------- |
|
192 // |
|
193 void CAknPhysicsEngine::EnableViewBody() |
|
194 { |
|
195 if ( iViewBody ) |
|
196 { |
|
197 dBodyEnable( iViewBody ); |
|
198 } |
|
199 } |
|
200 |
|
201 |
|
202 // --------------------------------------------------------------------------- |
|
203 // CAknPhysicsEngine::IsViewBodyEnabled |
|
204 // --------------------------------------------------------------------------- |
|
205 // |
|
206 TBool CAknPhysicsEngine::IsViewBodyEnabled() const |
|
207 { |
|
208 if ( iViewBody ) |
|
209 { |
|
210 return dBodyIsEnabled( iViewBody ); |
|
211 } |
|
212 return EFalse; |
|
213 } |
|
214 |
|
215 |
|
216 // --------------------------------------------------------------------------- |
|
217 // CAknPhysicsEngine::ApplyDragForce |
|
218 // --------------------------------------------------------------------------- |
|
219 // |
|
220 void CAknPhysicsEngine::ApplyDragForce( |
|
221 const TPoint& aDrag, const TInt& aMoveTime ) |
|
222 { |
|
223 if ( iViewBody ) |
|
224 { |
|
225 TReal step = aMoveTime * KStepFactor; |
|
226 // calculate and apply force from drag |
|
227 dVector3 force; |
|
228 dWorldImpulseToForce( |
|
229 iWorldId, |
|
230 REAL( step ), |
|
231 REAL( TInt64( aDrag.iX / 3 ) ), |
|
232 REAL( TInt64( aDrag.iY / 3 ) ), |
|
233 0, |
|
234 force ); |
|
235 dBodyAddForce( iViewBody, force[0], force[1], force[2] ); |
|
236 } |
|
237 } |
|
238 |
|
239 |
|
240 // --------------------------------------------------------------------------- |
|
241 // CAknPhysicsEngine::CollisionState |
|
242 // --------------------------------------------------------------------------- |
|
243 // |
|
244 const CAknPhysicsEngine::TAknPhysicsCollision& CAknPhysicsEngine::CollisionState() |
|
245 { |
|
246 return iCollision; |
|
247 } |
|
248 |
|
249 |
|
250 // --------------------------------------------------------------------------- |
|
251 // CAknPhysicsEngine::ResetCollisionState |
|
252 // --------------------------------------------------------------------------- |
|
253 // |
|
254 void CAknPhysicsEngine::ResetCollisionState() |
|
255 { |
|
256 iCollision = EAknPhysicsNoCollision; |
|
257 } |
|
258 |
|
259 |
|
260 // --------------------------------------------------------------------------- |
|
261 // CAknPhysicsEngine::TakePhysicsStep |
|
262 // --------------------------------------------------------------------------- |
|
263 // |
|
264 void CAknPhysicsEngine::TakePhysicsStep() |
|
265 { |
|
266 // Call collision detection (step |
|
267 dSpaceCollide ( iSpace, this , &CAknPhysicsEngine::CallbackFunc ); |
|
268 |
|
269 // Take a simulation step |
|
270 dWorldQuickStep( iWorldId, REAL( 0.1 ) ); |
|
271 |
|
272 // Remove all joints in the contact |
|
273 dJointGroupEmpty( iContactGroup ); |
|
274 } |
|
275 |
|
276 |
|
277 // --------------------------------------------------------------------------- |
|
278 // CAknPhysicsEngine::DeletePhysics |
|
279 // --------------------------------------------------------------------------- |
|
280 // |
|
281 void CAknPhysicsEngine::DeletePhysics() |
|
282 { |
|
283 if(iWorldId) |
|
284 { |
|
285 // Remove all joints in the contact |
|
286 dJointGroupEmpty( iContactGroup ); |
|
287 |
|
288 dJointGroupDestroy( iContactGroup ); |
|
289 iContactGroup = NULL; |
|
290 dBodyDestroy( iViewBody ); |
|
291 iViewBody = NULL; |
|
292 |
|
293 dGeomDestroy( iPlaneTop ); |
|
294 iPlaneTop = NULL; |
|
295 dGeomDestroy( iPlaneBottom ); |
|
296 iPlaneBottom = NULL; |
|
297 dGeomDestroy( iPlaneLeft ); |
|
298 iPlaneLeft = NULL; |
|
299 dGeomDestroy( iPlaneRight ); |
|
300 iPlaneRight = NULL; |
|
301 dGeomDestroy( iPlaneFriction ); |
|
302 iPlaneFriction = NULL; |
|
303 dGeomDestroy( iViewBox ); |
|
304 iViewBox = NULL; |
|
305 |
|
306 dSpaceDestroy( iSpace ); |
|
307 iSpace = NULL; |
|
308 dWorldDestroy( iWorldId ); |
|
309 iWorldId = NULL; |
|
310 dCloseODE(); // final clean-up; |
|
311 } |
|
312 } |
|
313 |
|
314 |
|
315 // --------------------------------------------------------------------------- |
|
316 // CAknPhysicsEngine::SetFriction |
|
317 // --------------------------------------------------------------------------- |
|
318 // |
|
319 void CAknPhysicsEngine::SetFriction( TReal aFriction ) |
|
320 { |
|
321 iFriction = aFriction; |
|
322 } |
|
323 |
|
324 |
|
325 // --------------------------------------------------------------------------- |
|
326 // CAknPhysicsEngine::ResetFriction |
|
327 // --------------------------------------------------------------------------- |
|
328 // |
|
329 void CAknPhysicsEngine::ResetFriction() |
|
330 { |
|
331 iFriction = KDefaultFriction; |
|
332 } |
|
333 |
|
334 |
|
335 // --------------------------------------------------------------------------- |
|
336 // CAknPhysicsEngine::StartFpsLogging |
|
337 // --------------------------------------------------------------------------- |
|
338 // |
|
339 void CAknPhysicsEngine::StartFpsLogging() |
|
340 { |
|
341 if ( !iAlfClient ) |
|
342 { |
|
343 TRAP_IGNORE( iAlfClient = new ( ELeave ) RAlfDirectClient ); |
|
344 } |
|
345 |
|
346 if ( iAlfClient ) |
|
347 { |
|
348 if ( iLogUid == KNullUid ) |
|
349 { |
|
350 CEikonEnv* env = CEikonEnv::Static(); |
|
351 |
|
352 if ( env ) |
|
353 { |
|
354 CEikAppUi* appUi = static_cast<CEikAppUi*>( env->AppUi() ); |
|
355 |
|
356 if ( appUi && appUi->Application() ) |
|
357 { |
|
358 iLogUid = appUi->Application()->AppDllUid(); |
|
359 } |
|
360 } |
|
361 } |
|
362 |
|
363 iAlfClient->MeasureFPS( iLogUid.iUid, ETrue ); |
|
364 } |
|
365 } |
|
366 |
|
367 |
|
368 // --------------------------------------------------------------------------- |
|
369 // CAknPhysicsEngine::StopFpsLogging |
|
370 // --------------------------------------------------------------------------- |
|
371 // |
|
372 void CAknPhysicsEngine::StopFpsLogging() |
|
373 { |
|
374 if ( iAlfClient ) |
|
375 { |
|
376 iAlfClient->MeasureFPS( iLogUid.iUid, EFalse ); |
|
377 } |
|
378 } |
|
379 |
|
380 |
|
381 // --------------------------------------------------------------------------- |
|
382 // CAknPhysicsEngine::CAknPhysicsEngine |
|
383 // --------------------------------------------------------------------------- |
|
384 // |
|
385 CAknPhysicsEngine::CAknPhysicsEngine( CAknPhysics* aPhysics ) |
|
386 : iWorldId( NULL ), |
|
387 iFriction( KDefaultFriction ), |
|
388 iPhysics( aPhysics ), |
|
389 iLogUid( KNullUid ) |
|
390 { |
|
391 } |
|
392 |
|
393 |
|
394 // --------------------------------------------------------------------------- |
|
395 // CAknPhysicsEngine::ConstructL |
|
396 // --------------------------------------------------------------------------- |
|
397 // |
|
398 void CAknPhysicsEngine::ConstructL() |
|
399 { |
|
400 } |
|
401 |
|
402 |
|
403 // ----------------------------------------------------------------------------- |
|
404 // CAknPhysicsEngine::CallbackFunc() |
|
405 // ----------------------------------------------------------------------------- |
|
406 // |
|
407 void CAknPhysicsEngine::CallbackFunc( void* aData, dGeomID o0, dGeomID o1 ) |
|
408 { |
|
409 static_cast<CAknPhysicsEngine*>( aData )->HandleCollisionBetween( o0,o1 ); |
|
410 } |
|
411 |
|
412 |
|
413 // ----------------------------------------------------------------------------- |
|
414 // CAknPhysicsEngine::HandleCollisionBetween() |
|
415 // ----------------------------------------------------------------------------- |
|
416 // |
|
417 void CAknPhysicsEngine::HandleCollisionBetween( |
|
418 dGeomID aObject1, dGeomID aObject2 ) |
|
419 { |
|
420 |
|
421 TSize viewSize( iPhysics->ViewSize() ); |
|
422 TSize worldSize( iPhysics->WorldSize() ); |
|
423 TInt surfaceErp( iPhysics->SurfaceErp() ); |
|
424 TInt surfaceCfm( iPhysics->SurfaceCfm() ); |
|
425 |
|
426 |
|
427 dBodyID b1 = dGeomGetBody(aObject1); |
|
428 dBodyID b2 = dGeomGetBody(aObject2); |
|
429 dContact contacts[KMaxContacts]; |
|
430 TInt numc = dCollide(aObject1, |
|
431 aObject2, |
|
432 KMaxContacts, |
|
433 &contacts[0].geom, |
|
434 sizeof(dContact)); |
|
435 |
|
436 for (TInt i = 0 ; i < numc; i++) |
|
437 { |
|
438 contacts[i].surface.mode = dContactApprox1; |
|
439 |
|
440 if(aObject1 == iPlaneFriction || aObject2 == iPlaneFriction) |
|
441 { |
|
442 if( iCollision == EAknPhysicsNoCollision ) |
|
443 { |
|
444 contacts[i].surface.mu = REAL( iFriction ); |
|
445 } |
|
446 else |
|
447 { |
|
448 contacts[i].surface.mu = 0; |
|
449 } |
|
450 } |
|
451 else if(aObject1 == iPlaneTop |
|
452 || aObject2 == iPlaneTop) |
|
453 { |
|
454 contacts[i].surface.mu = 0; // No friction |
|
455 TInt offScreen = 0; |
|
456 if( iPhysics->Landscape() ) |
|
457 { |
|
458 offScreen = -(iViewPosition.iX - viewSize.iWidth/2); |
|
459 offScreen = |
|
460 offScreen > viewSize.iWidth ? viewSize.iWidth : offScreen; |
|
461 } |
|
462 else |
|
463 { |
|
464 offScreen = -(iViewPosition.iY - viewSize.iHeight/2); |
|
465 offScreen = |
|
466 offScreen > viewSize.iHeight ? viewSize.iHeight : offScreen; |
|
467 } |
|
468 if( offScreen ) |
|
469 { |
|
470 contacts[i].surface.mode |= dContactSoftCFM | dContactSoftERP; |
|
471 contacts[i].surface.soft_erp = |
|
472 REAL( TReal( surfaceErp )/offScreen ); |
|
473 contacts[i].surface.soft_cfm = |
|
474 REAL( TReal( surfaceCfm )/offScreen); |
|
475 iCollision = EAknPhysicsTopCollision; |
|
476 } |
|
477 else |
|
478 iCollision = EAknPhysicsNoCollision; |
|
479 |
|
480 RDebug::Print(_L("TOP COLLISION")); |
|
481 } |
|
482 else if(aObject1 == iPlaneBottom |
|
483 || aObject2 == iPlaneBottom ) |
|
484 { |
|
485 contacts[i].surface.mu = 0; // No friction |
|
486 TInt offScreen = 0; |
|
487 if(iPhysics->Landscape()) |
|
488 { |
|
489 offScreen = |
|
490 (iViewPosition.iX + viewSize.iWidth/2) - viewSize.iWidth; |
|
491 offScreen = |
|
492 offScreen > viewSize.iWidth ? viewSize.iWidth : offScreen; |
|
493 } |
|
494 else |
|
495 { |
|
496 offScreen = |
|
497 (iViewPosition.iY + viewSize.iHeight/2) - worldSize.iHeight; |
|
498 offScreen = |
|
499 offScreen > viewSize.iHeight ? viewSize.iHeight : offScreen; |
|
500 } |
|
501 |
|
502 if( offScreen ) |
|
503 { |
|
504 contacts[i].surface.mode |= dContactSoftCFM | dContactSoftERP; |
|
505 contacts[i].surface.soft_erp = |
|
506 REAL( TReal( surfaceErp )/offScreen ); |
|
507 contacts[i].surface.soft_cfm = |
|
508 REAL( TReal( surfaceCfm )/offScreen); |
|
509 iCollision = EAknPhysicsBottomCollision; |
|
510 } |
|
511 else |
|
512 iCollision = EAknPhysicsNoCollision; |
|
513 |
|
514 RDebug::Print(_L("BOTTOM COLLISION")); |
|
515 } |
|
516 else |
|
517 { |
|
518 iCollision = EAknPhysicsNoCollision; |
|
519 contacts[i].surface.mu = 0; // No friction |
|
520 contacts[i].surface.mode |= |
|
521 dContactBounce | dContactSoftCFM | dContactSoftERP; |
|
522 contacts[i].surface.soft_cfm = REAL(KCfmSoftFactor); |
|
523 contacts[i].surface.soft_erp = REAL(KErpFactor); |
|
524 contacts[i].surface.bounce = REAL(KBounceFactor); // small bounce |
|
525 } |
|
526 |
|
527 dJointID c = dJointCreateContact(iWorldId, iContactGroup, &contacts[i]); |
|
528 dJointAttach(c,b1,b2); |
|
529 } |
|
530 } |