Commit 606bbd44cf947c8f347e70cddb169d22531638a6

Authored by Richard Huang
1 parent 08a1f2fb

Add physics demo using chipmunk

Change-Id: I40d9fb813bbb7f6360bf1bbadcff4b976e9c47bb
build/tizen/CMakeLists.txt
... ... @@ -243,6 +243,21 @@ IF( ENABLE_PKG_CONFIGURE )
243 243 SET( ENABLE_SCENE3D "ON" )
244 244 ENDIF()
245 245  
  246 + pkg_check_modules(DALI_PHYSICS_2D dali2-physics-2d)
  247 + IF( DALI_PHYSICS_2D_FOUND )
  248 + FOREACH(flag ${DALI_PHYSICS_2D_CFLAGS})
  249 + SET(REQUIRED_CFLAGS "${REQUIRED_CFLAGS} ${flag}")
  250 + ENDFOREACH(flag)
  251 +
  252 + SET( REQUIRED_CFLAGS "${REQUIRED_CFLAGS} -DDALI_PHYSICS_2D_AVAILABLE" )
  253 +
  254 + FOREACH(flag ${DALI_PHYSICS_2D_LDFLAGS})
  255 + SET(REQUIRED_PKGS_LDFLAGS "${REQUIRED_PKGS_LDFLAGS} ${flag}")
  256 + ENDFOREACH(flag)
  257 +
  258 + SET( ENABLE_PHYSICS_2D "ON" )
  259 + ENDIF()
  260 +
246 261 # if build as tizen platform, use capi-appfw-app-control
247 262 IF( TIZEN )
248 263 pkg_check_modules(CAPI_APPFW_APP_CONTROL capi-appfw-app-control)
... ... @@ -292,6 +307,8 @@ IF( WIN32 OR APPLE ) # WIN32 includes x64 as well according to the cmake doc.
292 307  
293 308 FIND_PACKAGE( dali2-scene3d )
294 309  
  310 + FIND_PACKAGE( chipmunk )
  311 +
295 312 # Set up the include dir
296 313 SET( INCLUDE_DIR $ENV{includedir} )
297 314 IF( NOT INCLUDE_DIR )
... ... @@ -346,6 +363,15 @@ IF( WIN32 OR APPLE ) # WIN32 includes x64 as well according to the cmake doc.
346 363 )
347 364 SET( ENABLE_SCENE3D "ON" )
348 365 ENDIF()
  366 +
  367 + IF (chipmunk_FOUND)
  368 + SET(REQUIRED_LIBS
  369 + ${REQUIRED_LIBS}
  370 + -lchipmunk
  371 + )
  372 + SET( ENABLE_PHYSICS_2D "ON" )
  373 + ENDIF()
  374 +
349 375 ELSEIF( UNIX )
350 376 SET( REQUIRED_LIBS
351 377 ${REQUIRED_PKGS_LDFLAGS}
... ... @@ -374,6 +400,10 @@ IF( ENABLE_SCENE3D )
374 400 SET(DALI_DEMO_CFLAGS "${DALI_DEMO_CFLAGS} -DDALI_SCENE3D_AVAILABLE")
375 401 ENDIF()
376 402  
  403 +IF( ENABLE_PHYSICS_2D )
  404 + SET(DALI_DEMO_CFLAGS "${DALI_DEMO_CFLAGS} -DDALI_PHYSICS_2D_AVAILABLE")
  405 +ENDIF()
  406 +
377 407 IF( UNIX )
378 408 IF( NOT ${ENABLE_EXPORTALL} )
379 409 ADD_DEFINITIONS( "-DHIDE_DALI_INTERNALS" )
... ... @@ -491,3 +521,4 @@ MESSAGE( " Folder DEMO_LANG : [" ${DEMO_LANG} "]" )
491 521 MESSAGE( " Current Build Platform : [" ${CURRENT_BUILD_PLATFORM} "]" )
492 522 MESSAGE( " Build example name : [" ${CURRENT_BUILD_EXAMPLE_NAME} "]" )
493 523 MESSAGE( " Scene3D Enabled : [" ${ENABLE_SCENE3D} "]" )
  524 +MESSAGE( " Physics 2D Enabled : [" ${ENABLE_PHYSICS_2D} "]" )
... ...
build/tizen/examples/CMakeLists.txt
... ... @@ -20,6 +20,13 @@ IF (NOT "${ENABLE_SCENE3D}" )
20 20 ENDIF()
21 21 ENDIF()
22 22  
  23 +SET(PHYSICS_2D_DIR "chipmunk")
  24 +IF (NOT "${ENABLE_PHYSICS_2D}" )
  25 + IF ( ${PHYSICS_2D_DIR} IN_LIST SUBDIRS )
  26 + LIST( REMOVE_ITEM SUBDIRS ${PHYSICS_2D_DIR} )
  27 + ENDIF()
  28 +ENDIF()
  29 +
23 30 FIND_PROGRAM( SHADER_GENERATOR "dali-shader-generator" )
24 31 IF( NOT SHADER_GENERATOR )
25 32 MESSAGE( FATAL_ERROR "dali-shader-generator not found!" )
... ...
com.samsung.dali-demo.xml
... ... @@ -67,6 +67,9 @@
67 67 <ui-application appid="canvas-view.example" exec="/usr/apps/com.samsung.dali-demo/bin/canvas-view.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
68 68 <label>Canvas View</label>
69 69 </ui-application>
  70 + <ui-application appid="chipmunk-physics.example" exec="/usr/apps/com.samsung.dali-demo/bin/chipmunk-physics.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
  71 + <label>Chipmunk Physics</label>
  72 + </ui-application>
70 73 <ui-application appid="clipping-draw-order.example" exec="/usr/apps/com.samsung.dali-demo/bin/clipping-draw-order.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
71 74 <label>Clipping Draw Order</label>
72 75 </ui-application>
... ...
examples-reel/dali-examples-reel.cpp
... ... @@ -47,6 +47,7 @@ int DALI_EXPORT_API main(int argc, char** argv)
47 47 demo.AddExample(Example("builder.example", DALI_DEMO_STR_TITLE_SCRIPT_BASED_UI));
48 48 demo.AddExample(Example("buttons.example", DALI_DEMO_STR_TITLE_BUTTONS));
49 49 demo.AddExample(Example("canvas-view.example", DALI_DEMO_STR_TITLE_CANVAS_VIEW));
  50 + demo.AddExample(Example("chipmunk-physics.example", DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS));
50 51 demo.AddExample(Example("clipping.example", DALI_DEMO_STR_TITLE_CLIPPING));
51 52 demo.AddExample(Example("clipping-draw-order.example", DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER));
52 53 demo.AddExample(Example("color-transition.example", DALI_DEMO_STR_TITLE_COLOR_TRANSITION));
... ...
examples/chipmunk-physics/frame-callback.cpp 0 → 100644
  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 +#include "frame-callback.h"
  18 +#include "physics-impl.h"
  19 +#include <dali/public-api/math/vector3.h>
  20 +#include <dali/devel-api/update/update-proxy.h>
  21 +#include <dali/devel-api/threading/mutex.h>
  22 +
  23 +using Dali::Vector3;
  24 +using Dali::Quaternion;
  25 +
  26 +FrameCallback::FrameCallback(PhysicsImpl& physicsImpl)
  27 +: mPhysicsImpl(physicsImpl)
  28 +{
  29 +}
  30 +
  31 +bool FrameCallback::Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds)
  32 +{
  33 + Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex);
  34 + static float frameTime=0;
  35 + frameTime+=elapsedSeconds;
  36 + do
  37 + {
  38 + mPhysicsImpl.Integrate(mPhysicsTimeStep);
  39 + frameTime-=mPhysicsTimeStep;
  40 + } while (frameTime>0);
  41 +
  42 + for(auto&& actor : mPhysicsImpl.mPhysicsActors)
  43 + {
  44 + // Get position, orientation from physics world.
  45 + Vector3 position = actor.second.GetActorPosition();
  46 + updateProxy.BakePosition(actor.first, position);
  47 + Quaternion rotation = actor.second.GetActorRotation();
  48 + updateProxy.BakeOrientation(actor.first, rotation);
  49 + }
  50 +
  51 + return true;
  52 +}
... ...
examples/chipmunk-physics/frame-callback.h 0 → 100644
  1 +#ifndef PHYSICS_DEMO_FRAME_CALLBACK_H
  2 +#define PHYSICS_DEMO_FRAME_CALLBACK_H
  3 +
  4 +/*
  5 + * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  6 + *
  7 + * Licensed under the Apache License, Version 2.0 (the "License");
  8 + * you may not use this file except in compliance with the License.
  9 + * You may obtain a copy of the License at
  10 + *
  11 + * http://www.apache.org/licenses/LICENSE-2.0
  12 + *
  13 + * Unless required by applicable law or agreed to in writing, software
  14 + * distributed under the License is distributed on an "AS IS" BASIS,
  15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16 + * See the License for the specific language governing permissions and
  17 + * limitations under the License.
  18 + */
  19 +
  20 +#include <dali/public-api/adaptor-framework/window.h>
  21 +#include <dali/devel-api/update/frame-callback-interface.h>
  22 +#include <map>
  23 +#include <chrono>
  24 +
  25 +class PhysicsImpl;
  26 +
  27 +class FrameCallback : public Dali::FrameCallbackInterface
  28 +{
  29 +public:
  30 + /**
  31 + * Constructor
  32 + */
  33 + explicit FrameCallback(PhysicsImpl& physicsImpl);
  34 +
  35 + /**
  36 + * Set the physics time step
  37 + * @param timeStep (in seconds)
  38 + */
  39 + void SetPhysicsTimeStep(float timeStep)
  40 + {
  41 + mPhysicsTimeStep = timeStep;
  42 + }
  43 +
  44 +private:
  45 + /**
  46 + * Called each frame.
  47 + * @param[in] updateProxy Used to set world matrix and size
  48 + * @param[in] elapsedSeconds Time since last frame
  49 + * @return Whether we should keep rendering.
  50 + */
  51 + bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) override;
  52 +
  53 +private: // Member variables
  54 + PhysicsImpl& mPhysicsImpl;
  55 + float mPhysicsTimeStep{1.0/180.0};
  56 +};
  57 +
  58 +#endif //PHYSICS_DEMO_FRAME_CALLBACK_H
... ...
examples/chipmunk-physics/physics-actor.cpp 0 → 100644
  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 +
  18 +#include "physics-actor.h"
  19 +#include "physics-impl.h"
  20 +#include <dali/public-api/common/constants.h>
  21 +#include <dali/public-api/math/vector3.h>
  22 +#include <dali/public-api/math/quaternion.h>
  23 +
  24 +using Dali::Vector3;
  25 +using Dali::Quaternion;
  26 +using Dali::Radian;
  27 +
  28 +void PhysicsActor::ClearForces()
  29 +{
  30 + printf("Not Implemented\n");
  31 + //mBody->clearForces();
  32 + // No similar API
  33 +}
  34 +
  35 +Dali::Vector3 PhysicsActor::GetPhysicsPosition()
  36 +{
  37 + cpVect cpPosition = cpBodyGetPosition(mBody);
  38 + return Vector3(cpPosition.x, cpPosition.y, 0.0f);
  39 +}
  40 +
  41 +void PhysicsActor::SetPhysicsPosition(Dali::Vector3 actorPosition)
  42 +{
  43 + Dali::Mutex::ScopedLock lock(mImpl->mMutex);
  44 + Vector3 physicsPosition = mImpl->TranslateToPhysicsSpace(actorPosition);
  45 + cpBodySetPosition(mBody, cpv(physicsPosition.x, physicsPosition.y));
  46 +}
  47 +
  48 +void PhysicsActor::SetPhysicsVelocity(Dali::Vector3 actorVelocity)
  49 +{
  50 + Dali::Mutex::ScopedLock lock(mImpl->mMutex);
  51 + Vector3 physicsVelocity = mImpl->ConvertVectorToPhysicsSpace(actorVelocity);
  52 + cpBodySetVelocity(mBody, cpv(physicsVelocity.x, physicsVelocity.y));
  53 +}
  54 +
  55 +void PhysicsActor::SetPhysicsAngularVelocity(Dali::Vector3 velocity)
  56 +{
  57 + Dali::Mutex::ScopedLock lock(mImpl->mMutex);
  58 + printf("Not Implemented\n");
  59 + //mBody->setAngularVelocity(btVector3(velocity.x, velocity.y, velocity.z));
  60 +}
  61 +
  62 +Quaternion PhysicsActor::GetPhysicsRotation()
  63 +{
  64 + return Quaternion{};
  65 +}
  66 +
  67 +void PhysicsActor::SetPhysicsRotation(Dali::Quaternion rotation)
  68 +{
  69 + Dali::Mutex::ScopedLock lock(mImpl->mMutex);
  70 +
  71 + Vector3 axis;
  72 + Radian angle;
  73 + rotation.ToAxisAngle(axis, angle);
  74 +
  75 + //btQuaternion orn = btQuaternion(btVector3(axis.x, -axis.y, axis.z), btScalar(float(-angle)));
  76 + //btTransform& transform = mBody->getWorldTransform();
  77 + //transform.setRotation(orn);
  78 + printf("Not Implemented\n");
  79 +}
  80 +
  81 +
  82 +Vector3 PhysicsActor::GetActorPosition()
  83 +{
  84 + cpVect cpPosition = cpBodyGetPosition(mBody);
  85 + return mImpl->TranslateFromPhysicsSpace(Vector3(cpPosition.x, cpPosition.y, 0.0f));
  86 +}
  87 +
  88 +Vector3 PhysicsActor::GetActorVelocity()
  89 +{
  90 + cpVect cpVelocity = cpBodyGetVelocity(mBody);
  91 + return mImpl->ConvertVectorFromPhysicsSpace(Vector3(cpVelocity.x, cpVelocity.y, 0.0f));
  92 +}
  93 +
  94 +Quaternion PhysicsActor::GetActorRotation()
  95 +{
  96 + cpFloat angle = cpBodyGetAngle(mBody);
  97 + return Quaternion(Radian(angle), -Vector3::ZAXIS);
  98 +}
... ...
examples/chipmunk-physics/physics-actor.h 0 → 100644
  1 +#ifndef DALI_PHYSICS_DEMO_PHYSICS_ACTOR_H
  2 +#define DALI_PHYSICS_DEMO_PHYSICS_ACTOR_H
  3 +/*
  4 + * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  5 + *
  6 + * Licensed under the Apache License, Version 2.0 (the "License");
  7 + * you may not use this file except in compliance with the License.
  8 + * You may obtain a copy of the License at
  9 + *
  10 + * http://www.apache.org/licenses/LICENSE-2.0
  11 + *
  12 + * Unless required by applicable law or agreed to in writing, software
  13 + * distributed under the License is distributed on an "AS IS" BASIS,
  14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15 + * See the License for the specific language governing permissions and
  16 + * limitations under the License.
  17 + *
  18 + */
  19 +
  20 +#include <chipmunk/chipmunk.h>
  21 +#include <cstdint>
  22 +#include <dali/dali.h>
  23 +#include <iosfwd>
  24 +
  25 +// Forward declarations
  26 +class PhysicsImpl;
  27 +
  28 +/**
  29 + * Class that associates an actor with a physics body. (Initially, rigid body)
  30 + */
  31 +class PhysicsActor
  32 +{
  33 +public:
  34 + PhysicsActor() = default;
  35 + PhysicsActor(Dali::Actor& actor, cpBody* body, PhysicsImpl* impl, Dali::Property::Index brightnessId)
  36 + : mImpl(impl),
  37 + mActorId(actor.GetProperty<int>(Dali::Actor::Property::ID)),
  38 + mBody(body),
  39 + mBrightnessIndex(brightnessId)
  40 + {
  41 + cpBodySetUserData(mBody, this);
  42 + }
  43 +
  44 + PhysicsActor(const PhysicsActor& rhs)=delete;
  45 + PhysicsActor& operator=(const PhysicsActor& rhs)=delete;
  46 +
  47 + PhysicsActor(const PhysicsActor&& rhs)
  48 + {
  49 + if(this != &rhs)
  50 + {
  51 + mImpl = rhs.mImpl;
  52 + mActorId = rhs.mActorId;
  53 + mBody = rhs.mBody;
  54 + cpBodySetUserData(mBody, this);
  55 + mBrightnessIndex = rhs.mBrightnessIndex;
  56 + }
  57 + }
  58 +
  59 + PhysicsActor& operator=(const PhysicsActor&& rhs)
  60 + {
  61 + if(this != &rhs)
  62 + {
  63 + mActorId = rhs.mActorId;
  64 + mBody = rhs.mBody;
  65 + mImpl = rhs.mImpl;
  66 + mBrightnessIndex = rhs.mBrightnessIndex;
  67 + cpBodySetUserData(mBody, this);
  68 + }
  69 + return *this;
  70 + }
  71 +
  72 + uint32_t GetId()
  73 + {
  74 + return mActorId;
  75 + }
  76 +
  77 + cpBody* GetBody()
  78 + {
  79 + return mBody;
  80 + }
  81 +
  82 + Dali::Property::Index GetBrightnessIndex()
  83 + {
  84 + return mBrightnessIndex;
  85 + }
  86 +
  87 + Dali::Vector3 GetPhysicsPosition();
  88 + Dali::Quaternion GetPhysicsRotation();
  89 +
  90 + void SetPhysicsPosition(Dali::Vector3 actorPosition);
  91 + void SetPhysicsVelocity(Dali::Vector3 actorVelocity);
  92 + void SetPhysicsAngularVelocity(Dali::Vector3 actorVelocity);
  93 + void SetPhysicsRotation(Dali::Quaternion actorRotation);
  94 + Dali::Vector3 GetActorPosition();
  95 + Dali::Vector3 GetActorVelocity();
  96 + Dali::Quaternion GetActorRotation();
  97 + void ClearForces();
  98 +
  99 +private:
  100 + PhysicsImpl* mImpl{nullptr};
  101 + uint32_t mActorId{0};
  102 + cpBody* mBody{nullptr};
  103 + Dali::Property::Index mBrightnessIndex{Dali::Property::INVALID_INDEX};
  104 +};
  105 +
  106 +#endif // DALI_PHYSICS_DEMO_PHYSICS_ACTOR_H
... ...
examples/chipmunk-physics/physics-demo-controller.cpp 0 → 100644
  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 +#include <dali-toolkit/dali-toolkit.h>
  18 +#include <dali/dali.h>
  19 +
  20 +#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
  21 +#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
  22 +#include <dali/devel-api/adaptor-framework/key-devel.h>
  23 +#include <dali/devel-api/events/hit-test-algorithm.h>
  24 +
  25 +#include <iostream>
  26 +#include <string>
  27 +
  28 +#include "generated/rendering-textured-shape-frag.h"
  29 +#include "generated/rendering-textured-shape-vert.h"
  30 +#include "physics-actor.h"
  31 +#include "physics-impl.h"
  32 +
  33 +using namespace Dali;
  34 +
  35 +namespace KeyModifier
  36 +{
  37 +enum Key
  38 +{
  39 + CONTROL_L = DevelKey::DALI_KEY_CONTROL_LEFT,
  40 + CONTROL_R = DevelKey::DALI_KEY_CONTROL_RIGHT,
  41 + SHIFT_L = 50,
  42 + SHIFT_R = 62,
  43 + ALT_L = 64,
  44 + ALT_R = 108,
  45 + SUPER_L = 133,
  46 + SUPER_R = 134,
  47 + MENU = 135,
  48 +};
  49 +}
  50 +
  51 +const std::string BRICK_WALL = DEMO_IMAGE_DIR "/brick-wall.jpg";
  52 +const std::string BALL_IMAGE = DEMO_IMAGE_DIR "/blocks-ball.png";
  53 +const std::string BRICK_URIS[4] = {
  54 + DEMO_IMAGE_DIR "/blocks-brick-1.png", DEMO_IMAGE_DIR "/blocks-brick-2.png", DEMO_IMAGE_DIR "/blocks-brick-3.png", DEMO_IMAGE_DIR "/blocks-brick-4.png"};
  55 +
  56 +/**
  57 + * @brief The physics demo using Chipmunk2D APIs.
  58 + */
  59 +class PhysicsDemoController : public ConnectionTracker
  60 +{
  61 +public:
  62 + PhysicsDemoController(Application& app)
  63 + : mApplication(app)
  64 + {
  65 + app.InitSignal().Connect(this, &PhysicsDemoController::OnInit);
  66 + app.TerminateSignal().Connect(this, &PhysicsDemoController::OnTerminate);
  67 + }
  68 +
  69 + ~PhysicsDemoController() override
  70 + {
  71 + }
  72 +
  73 + void OnInit(Application& application)
  74 + {
  75 + mWindow = application.GetWindow();
  76 + mWindow.ResizeSignal().Connect(this, &PhysicsDemoController::OnWindowResize);
  77 + mWindow.KeyEventSignal().Connect(this, &PhysicsDemoController::OnKeyEv);
  78 + Stage::GetCurrent().KeepRendering(30);
  79 + mWindow.SetBackgroundColor(Color::DARK_SLATE_GRAY);
  80 + Window::WindowSize windowSize = mWindow.GetSize();
  81 +
  82 + mPhysicsRoot = mPhysicsImpl.Initialize(mWindow);
  83 + mPhysicsRoot.TouchedSignal().Connect(this, &PhysicsDemoController::OnTouched);
  84 +
  85 + mWindow.Add(mPhysicsRoot);
  86 +
  87 + CreateBall();
  88 + CreateBrickPyramid(windowSize);
  89 +
  90 + // For funky mouse drag
  91 + mMouseBody = mPhysicsImpl.AddMouseBody();
  92 + }
  93 +
  94 + void CreateBall()
  95 + {
  96 + const float BALL_MASS = 10.0f;
  97 + const float BALL_RADIUS = 26.0f;
  98 + const float BALL_ELASTICITY = 0.5f;
  99 + const float BALL_FRICTION = 0.5f;
  100 +
  101 + Property::Value v{std::string{SHADER_RENDERING_TEXTURED_SHAPE_VERT}};
  102 + Property::Value f{std::string{SHADER_RENDERING_TEXTURED_SHAPE_FRAG}};
  103 +
  104 + auto image = Property::Map{{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
  105 + {Toolkit::ImageVisual::Property::URL, BALL_IMAGE},
  106 + {Toolkit::Visual::Property::SHADER, {{Toolkit::Visual::Shader::Property::FRAGMENT_SHADER, f}}}};
  107 +
  108 + auto ball = Toolkit::ImageView::New();
  109 + ball[Toolkit::ImageView::Property::IMAGE] = image;
  110 + mPhysicsImpl.AddBall(ball, BALL_MASS, BALL_RADIUS, BALL_ELASTICITY, BALL_FRICTION);
  111 + }
  112 +
  113 + void CreateBrickPyramid(Dali::Window::WindowSize windowSize)
  114 + {
  115 + const float BRICK_MASS = 30.0f;
  116 + const float BRICK_ELASTICITY = 0.0f;
  117 + const float BRICK_FRICTION = 0.9f;
  118 + const int BRICK_WIDTH = 128;
  119 + const int BRICK_HEIGHT = 64;
  120 + const int BRICK_GAP = 8;
  121 +
  122 + Property::Value v{std::string{SHADER_RENDERING_TEXTURED_SHAPE_VERT}};
  123 + Property::Value f{std::string{SHADER_RENDERING_TEXTURED_SHAPE_FRAG}};
  124 +
  125 + int uriIndex = 0;
  126 + int numberOfRows = windowSize.GetWidth() / (BRICK_WIDTH + BRICK_GAP) - 2;
  127 + int oY = windowSize.GetHeight() - (1 + numberOfRows) * BRICK_HEIGHT;
  128 + for(int i = 0; i < numberOfRows; ++i)
  129 + {
  130 + // Row start: i+1 is brick number. i is gap#
  131 + int w = (i + 1) * BRICK_WIDTH + i * BRICK_GAP;
  132 + int oX = (windowSize.GetWidth() - w) / 2;
  133 + for(int j = 0; j < i + 1; ++j)
  134 + {
  135 + auto image = Property::Map{{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
  136 + {Toolkit::ImageVisual::Property::URL, BRICK_URIS[uriIndex]},
  137 + {Toolkit::Visual::Property::SHADER, {{Toolkit::Visual::Shader::Property::FRAGMENT_SHADER, f}}}};
  138 +
  139 + auto brick = Toolkit::ImageView::New();
  140 + brick[Toolkit::ImageView::Property::IMAGE] = image;
  141 + auto& physicsActor = mPhysicsImpl.AddBrick(brick, BRICK_MASS, BRICK_ELASTICITY, BRICK_FRICTION, Vector3(BRICK_WIDTH, BRICK_HEIGHT, BRICK_HEIGHT));
  142 + physicsActor.SetPhysicsPosition(Vector3(oX + j * (BRICK_WIDTH + BRICK_GAP), oY + i * BRICK_HEIGHT, 0.0f));
  143 + uriIndex += 1;
  144 + uriIndex %= 4;
  145 + }
  146 + }
  147 + }
  148 + void OnTerminate(Application& application)
  149 + {
  150 + UnparentAndReset(mPhysicsRoot);
  151 + }
  152 +
  153 + void OnWindowResize(Window window, Window::WindowSize newSize)
  154 + {
  155 + mPhysicsImpl.CreateWorldBounds(newSize);
  156 + }
  157 +
  158 + bool OnTouched(Dali::Actor actor, const Dali::TouchEvent& touch)
  159 + {
  160 + static enum {
  161 + None,
  162 + MoveCameraXZ,
  163 + MovePivot,
  164 + } state = None;
  165 +
  166 + auto renderTask = mWindow.GetRenderTaskList().GetTask(0);
  167 + auto screenCoords = touch.GetScreenPosition(0);
  168 + Vector3 origin, direction;
  169 + Dali::HitTestAlgorithm::BuildPickingRay(renderTask, screenCoords, origin, direction);
  170 +
  171 + switch(state)
  172 + {
  173 + case None:
  174 + {
  175 + if(touch.GetState(0) == Dali::PointState::STARTED)
  176 + {
  177 + if(mCtrlDown)
  178 + {
  179 + state = MoveCameraXZ;
  180 + // local to top left
  181 + //cameraY = touch.GetLocalPosition(0).y;
  182 + // Could move on fixed plane, e.g. y=0.
  183 + // position.Y corresponds to a z value depending on perspective
  184 + // position.X scales to an x value depending on perspective
  185 + }
  186 + else
  187 + {
  188 + state = MovePivot;
  189 + Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex);
  190 +
  191 + Vector3 localPivot;
  192 + float pickingDistance;
  193 + auto body = mPhysicsImpl.HitTest(screenCoords, origin, direction, localPivot, pickingDistance);
  194 + if(body)
  195 + {
  196 + mPickedBody = body;
  197 + mPhysicsImpl.HighlightBody(mPickedBody, true);
  198 + mPickedSavedState = mPhysicsImpl.ActivateBody(mPickedBody);
  199 + mPickedConstraint = mPhysicsImpl.AddPivotJoint(mPickedBody, mMouseBody, localPivot);
  200 + }
  201 + }
  202 + }
  203 + break;
  204 + }
  205 + case MovePivot:
  206 + {
  207 + if(touch.GetState(0) == Dali::PointState::MOTION)
  208 + {
  209 + if(mPickedBody && mPickedConstraint)
  210 + {
  211 + if(!mShiftDown)
  212 + {
  213 + // Move point in XY plane, projected into scene
  214 + Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex);
  215 +
  216 + Vector3 position = mPhysicsImpl.TranslateToPhysicsSpace(Vector3(screenCoords));
  217 + mPhysicsImpl.MoveMouseBody(mMouseBody, position);
  218 + }
  219 + else
  220 + {
  221 + // Move point in XZ plane
  222 + // Above vanishing pt, it's on top plane of frustum; below vanishing pt it's on bottom plane.
  223 + // Kind of want to project onto the plane using initial touch xy, rather than top/bottom.
  224 + // Whole new projection code needed.
  225 +
  226 + // Cheat!
  227 + }
  228 + }
  229 + }
  230 + else if(touch.GetState(0) == Dali::PointState::FINISHED ||
  231 + touch.GetState(0) == Dali::PointState::INTERRUPTED)
  232 + {
  233 + if(mPickedConstraint)
  234 + {
  235 + mPhysicsImpl.HighlightBody(mPickedBody, false);
  236 +
  237 + Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex);
  238 + mPhysicsImpl.RestoreBodyState(mPickedBody, mPickedSavedState);
  239 + mPhysicsImpl.ReleaseConstraint(mPickedConstraint);
  240 + mPickedConstraint = nullptr;
  241 + mPickedBody = nullptr;
  242 + }
  243 + state = None;
  244 + }
  245 + break;
  246 + }
  247 + case MoveCameraXZ:
  248 + {
  249 + if(touch.GetState(0) == Dali::PointState::MOTION)
  250 + {
  251 + // Move camera in XZ plane
  252 + //float y = cameraY; // touch point in Y. Move camera in an XZ plane on this point.
  253 + }
  254 + else if(touch.GetState(0) == Dali::PointState::FINISHED ||
  255 + touch.GetState(0) == Dali::PointState::INTERRUPTED)
  256 + {
  257 + state = None;
  258 + }
  259 + break;
  260 + }
  261 + }
  262 +
  263 + //std::cout<<"Touch State: "<<state<<std::endl;
  264 + Stage::GetCurrent().KeepRendering(30.0f);
  265 +
  266 + return true;
  267 + }
  268 +
  269 + void OnKeyEv(const Dali::KeyEvent& event)
  270 + {
  271 + if(event.GetState() == KeyEvent::DOWN)
  272 + {
  273 + switch(event.GetKeyCode())
  274 + {
  275 + case KeyModifier::CONTROL_L:
  276 + case KeyModifier::CONTROL_R:
  277 + {
  278 + mCtrlDown = true;
  279 + break;
  280 + }
  281 + case KeyModifier::ALT_L:
  282 + case KeyModifier::ALT_R:
  283 + {
  284 + mAltDown = true;
  285 + break;
  286 + }
  287 + case KeyModifier::SHIFT_L:
  288 + case KeyModifier::SHIFT_R:
  289 + {
  290 + mShiftDown = true;
  291 + break;
  292 + }
  293 + default:
  294 + {
  295 + if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
  296 + {
  297 + mApplication.Quit();
  298 + }
  299 + else if(!event.GetKeyString().compare(" "))
  300 + {
  301 + mPhysicsImpl.ToggleIntegrateState();
  302 + }
  303 + else if(!event.GetKeyString().compare("m"))
  304 + {
  305 + mPhysicsImpl.ToggleDebugState();
  306 + }
  307 + break;
  308 + }
  309 + }
  310 + }
  311 + else if(event.GetState() == KeyEvent::UP)
  312 + {
  313 + switch(event.GetKeyCode())
  314 + {
  315 + case KeyModifier::CONTROL_L:
  316 + case KeyModifier::CONTROL_R:
  317 + {
  318 + mCtrlDown = false;
  319 + break;
  320 + }
  321 + case KeyModifier::ALT_L:
  322 + case KeyModifier::ALT_R:
  323 + {
  324 + mAltDown = false;
  325 + break;
  326 + }
  327 + case KeyModifier::SHIFT_L:
  328 + case KeyModifier::SHIFT_R:
  329 + {
  330 + mShiftDown = false;
  331 + break;
  332 + }
  333 + }
  334 + }
  335 + }
  336 +
  337 +private:
  338 + Application& mApplication;
  339 + Window mWindow;
  340 +
  341 + PhysicsImpl mPhysicsImpl;
  342 + Actor mPhysicsRoot;
  343 + cpBody* mMouseBody;
  344 + cpBody* mPickedBody;
  345 + int mPickedSavedState;
  346 + cpConstraint* mPickedConstraint;
  347 +
  348 + bool mCtrlDown{false};
  349 + bool mAltDown{false};
  350 + bool mShiftDown{false};
  351 +};
  352 +
  353 +int DALI_EXPORT_API main(int argc, char** argv)
  354 +{
  355 + Application application = Application::New(&argc, &argv);
  356 + PhysicsDemoController controller(application);
  357 + application.MainLoop();
  358 + return 0;
  359 +}
... ...
examples/chipmunk-physics/physics-impl.cpp 0 → 100644
  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 +
  18 +#include "physics-impl.h"
  19 +#include "physics-actor.h"
  20 +
  21 +#include <devel-api/common/stage.h>
  22 +#include <map>
  23 +#include <utility>
  24 +#include <iostream>
  25 +
  26 +using Dali::Layer;
  27 +using Dali::Actor;
  28 +using Dali::Window;
  29 +using Dali::Vector2;
  30 +using Dali::Vector3;
  31 +using Dali::Stage;
  32 +using namespace Dali::DevelStage;
  33 +
  34 +#define GRABBABLE_MASK_BIT (1u<<31)
  35 +cpShapeFilter GRAB_FILTER = {CP_NO_GROUP, GRABBABLE_MASK_BIT, GRABBABLE_MASK_BIT};
  36 +cpShapeFilter NOT_GRABBABLE_FILTER = {CP_NO_GROUP, ~GRABBABLE_MASK_BIT, ~GRABBABLE_MASK_BIT};
  37 +
  38 +Actor PhysicsImpl::Initialize(Window window)
  39 +{
  40 + mWindow = window;
  41 + mSpace = cpSpaceNew();
  42 + cpSpaceSetIterations(mSpace, 30);
  43 + cpSpaceSetSleepTimeThreshold(mSpace, 0.5f);
  44 + cpSpaceSetGravity(mSpace, cpv(0, -200));
  45 +
  46 + auto windowSize = window.GetSize();
  47 + CreateWorldBounds(windowSize);
  48 +
  49 + // Create an actor that can handle mouse events.
  50 + mPhysicsRoot = Layer::New();
  51 + mPhysicsRoot[Actor::Property::SIZE] = Vector2(windowSize.GetWidth(), windowSize.GetHeight());
  52 + mPhysicsRoot[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER;
  53 + mPhysicsRoot[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER;
  54 +
  55 + mFrameCallback = new FrameCallback(*this);
  56 + AddFrameCallback(Stage::GetCurrent(), *mFrameCallback, window.GetRootLayer());
  57 + Stage::GetCurrent().KeepRendering(30);
  58 +
  59 +
  60 + return mPhysicsRoot;
  61 +}
  62 +
  63 +Layer PhysicsImpl::CreateDebug(Vector2 windowSize)
  64 +{
  65 + return Layer();
  66 +}
  67 +
  68 +void PhysicsImpl::CreateWorldBounds(Window::WindowSize size)
  69 +{
  70 + // Physics origin is 0,0,0 in DALi coords.
  71 + // But, Y is inverted, so bottom is -ve, top is +ve.
  72 + // Perform this correction when applying position to actor.
  73 + // But, can't use actors in update, so cache transform.
  74 + SetTransform(Vector2(size.GetWidth(), size.GetHeight()));
  75 +
  76 + int xBound=size.GetWidth()/2;
  77 + int yBound=size.GetHeight()/2;
  78 +
  79 + cpBody *staticBody = cpSpaceGetStaticBody(mSpace);
  80 +
  81 + if(mLeftBound)
  82 + {
  83 + cpSpaceRemoveShape(mSpace, mLeftBound);
  84 + cpSpaceRemoveShape(mSpace, mRightBound);
  85 + cpSpaceRemoveShape(mSpace, mTopBound);
  86 + cpSpaceRemoveShape(mSpace, mBottomBound);
  87 + cpShapeFree(mLeftBound);
  88 + cpShapeFree(mRightBound);
  89 + cpShapeFree(mTopBound);
  90 + cpShapeFree(mBottomBound);
  91 + }
  92 + mLeftBound = AddBound(staticBody, cpv(-xBound, -yBound), cpv(-xBound, yBound));
  93 + mRightBound = AddBound(staticBody, cpv( xBound, -yBound), cpv( xBound, yBound));
  94 + mTopBound = AddBound(staticBody, cpv(-xBound, -yBound), cpv( xBound, -yBound));
  95 + mBottomBound = AddBound(staticBody, cpv(-xBound, yBound), cpv( xBound, yBound));
  96 +}
  97 +
  98 +void PhysicsImpl::SetTransform(Vector2 worldSize)
  99 +{
  100 + mWorldOffset.x = worldSize.x * 0.5f;
  101 + mWorldOffset.y = worldSize.y * 0.5f;
  102 + // y is always inverted.
  103 +}
  104 +
  105 +cpShape* PhysicsImpl::AddBound(cpBody* staticBody, cpVect start, cpVect end)
  106 +{
  107 + cpShape* shape = cpSpaceAddShape(mSpace, cpSegmentShapeNew(staticBody,start, end,0.0f));
  108 + cpShapeSetElasticity(shape, 1.0f);
  109 + cpShapeSetFriction(shape, 1.0f);
  110 + cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER);
  111 + return shape;
  112 +}
  113 +
  114 +PhysicsActor& PhysicsImpl::AddBall(::Actor actor, float mass, float radius, float elasticity, float friction)
  115 +{
  116 + Dali::Mutex::ScopedLock lock(mMutex);
  117 + cpBody* body = cpSpaceAddBody(mSpace, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
  118 + cpBodySetPosition(body, cpv(0, 0));
  119 + cpBodySetVelocity(body, cpv(0, 0));
  120 +
  121 + cpShape* shape = cpSpaceAddShape(mSpace, cpCircleShapeNew(body, radius, cpvzero));
  122 + cpShapeSetElasticity(shape, elasticity);
  123 + cpShapeSetFriction(shape, friction);
  124 +
  125 + int id = actor[Actor::Property::ID];
  126 + Dali::Property::Index index = actor.RegisterProperty("uBrightness", 0.0f);
  127 + mPhysicsActors.insert(std::make_pair(id, PhysicsActor{actor, body, this, index}));
  128 + actor[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::TOP_LEFT;
  129 + actor[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER;
  130 + mPhysicsRoot.Add(actor);
  131 + return mPhysicsActors.at(id);
  132 +}
  133 +
  134 +PhysicsActor& PhysicsImpl::AddBrick(Dali::Actor actor, float mass, float elasticity, float friction, Vector3 size)
  135 +{
  136 + Dali::Mutex::ScopedLock lock(mMutex);
  137 + cpBody* body = cpSpaceAddBody(mSpace, cpBodyNew(mass, cpMomentForBox(mass, size.width, size.height)));
  138 + cpBodySetPosition(body, cpv(0, 0));
  139 + cpBodySetVelocity(body, cpv(0, 0));
  140 +
  141 + cpShape* shape = cpSpaceAddShape(mSpace, cpBoxShapeNew(body, size.width, size.height, 0.0f));
  142 + cpShapeSetFriction(shape, friction);
  143 + cpShapeSetElasticity(shape, elasticity);
  144 +
  145 + int id = actor[Actor::Property::ID];
  146 + Dali::Property::Index index = actor.RegisterProperty("uBrightness", 0.0f);
  147 + mPhysicsActors.insert(std::make_pair(id, PhysicsActor{actor, body, this, index}));
  148 + actor[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::TOP_LEFT;
  149 + actor[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER;
  150 + mPhysicsRoot.Add(actor);
  151 + return mPhysicsActors.at(id);
  152 +}
  153 +
  154 +cpBody* PhysicsImpl::AddMouseBody()
  155 +{
  156 + Dali::Mutex::ScopedLock lock(mMutex);
  157 + auto kinematicBody = cpBodyNewKinematic(); // Mouse actor is a kinematic body that is not integrated
  158 + return kinematicBody;
  159 +}
  160 +
  161 +PhysicsActor* PhysicsImpl::GetPhysicsActor(cpBody* body)
  162 +{
  163 + return reinterpret_cast<PhysicsActor*>(cpBodyGetUserData(body));
  164 +}
  165 +
  166 +void PhysicsImpl::HighlightBody(cpBody* body, bool highlight)
  167 +{
  168 + auto physicsActor = GetPhysicsActor(body);
  169 + if(physicsActor)
  170 + {
  171 + Actor actor = mPhysicsRoot.FindChildById(physicsActor->GetId());
  172 + if(actor)
  173 + {
  174 + actor[physicsActor->GetBrightnessIndex()] = highlight?1.0f:0.0f;
  175 + }
  176 + }
  177 +}
  178 +
  179 +// Convert from root actor local space to physics space
  180 +Vector3 PhysicsImpl::TranslateToPhysicsSpace(Vector3 vector)
  181 +{
  182 + // root actor origin is top left, DALi Y is inverted.
  183 + // Physics origin is center. Y: 0->1 => 0.5=>-0.5
  184 + return Vector3(vector.x-mWorldOffset.x, mWorldOffset.y-vector.y, vector.z);
  185 +}
  186 +
  187 +// Convert from physics space to root actor local space
  188 +Vector3 PhysicsImpl::TranslateFromPhysicsSpace(Vector3 vector)
  189 +{
  190 + return Vector3(vector.x+mWorldOffset.x, mWorldOffset.y-vector.y, vector.z);
  191 +}
  192 +
  193 +// Convert a vector from dali space to physics space
  194 +Vector3 PhysicsImpl::ConvertVectorToPhysicsSpace(Vector3 vector)
  195 +{
  196 + // root actor origin is top left, DALi Y is inverted.
  197 + // @todo Add space config scale.
  198 + return Vector3(vector.x, -vector.y, vector.z);
  199 +}
  200 +
  201 +// Convert a vector physics space to root actor local space
  202 +Vector3 PhysicsImpl::ConvertVectorFromPhysicsSpace(Vector3 vector)
  203 +{
  204 + return Vector3(vector.x, -vector.y, vector.z);
  205 +}
  206 +
  207 +void PhysicsImpl::Integrate(float timestep)
  208 +{
  209 + if(mPhysicsIntegrateState)
  210 + {
  211 + cpSpaceStep(mSpace, timestep);
  212 + }
  213 +// if(mDynamicsWorld->getDebugDrawer() && mPhysicsDebugState)
  214 +// {
  215 +// mDynamicsWorld->debugDrawWorld();
  216 +// }
  217 +}
  218 +
  219 +cpBody* PhysicsImpl::HitTest(Vector2 screenCoords, Vector3 origin, Vector3 direction, Vector3& localPivot, float& distanceFromCamera)
  220 +{
  221 + Vector3 spacePosition = TranslateToPhysicsSpace(Vector3{screenCoords});
  222 + cpVect mousePosition = cpv(spacePosition.x, spacePosition.y);
  223 + cpFloat radius = 5.0f;
  224 + cpPointQueryInfo info = {0};
  225 + cpShape *shape = cpSpacePointQueryNearest(mSpace, mousePosition, radius, GRAB_FILTER, &info);
  226 +
  227 + cpBody *body{nullptr};
  228 +
  229 + if(shape && cpBodyGetMass(cpShapeGetBody(shape)) < INFINITY)
  230 + {
  231 + // Use the closest point on the surface if the click is outside the shape.
  232 + cpVect nearest = (info.distance > 0.0f ? info.point : mousePosition);
  233 + body = cpShapeGetBody(shape);
  234 + cpVect local = cpBodyWorldToLocal(body, nearest);
  235 + localPivot.x = local.x;
  236 + localPivot.y = local.y;
  237 + localPivot.z = 0.0;
  238 + }
  239 + return body;
  240 +}
  241 +
  242 +
  243 +cpConstraint* PhysicsImpl::AddPivotJoint(cpBody* body1, cpBody* body2, Vector3 localPivot)
  244 +{
  245 + cpVect pivot{localPivot.x, localPivot.y};
  246 + cpConstraint* joint = cpPivotJointNew2(body2, body1, cpvzero, pivot);
  247 + cpConstraintSetMaxForce(joint, 50000.0f); // Magic numbers for mouse feedback.
  248 + cpConstraintSetErrorBias(joint, cpfpow(1.0f - 0.15f, 60.0f));
  249 + cpConstraint* constraint = cpSpaceAddConstraint(mSpace, joint);
  250 + return constraint; // Constraint & joint are the same...
  251 +}
  252 +
  253 +void PhysicsImpl::MoveMouseBody(cpBody* mouseBody, Vector3 position)
  254 +{
  255 + cpVect cpPosition = cpv(position.x, position.y);
  256 + cpVect newPoint = cpvlerp(cpBodyGetPosition(mouseBody), cpPosition, 0.25f);
  257 + cpBodySetVelocity(mouseBody, cpvmult(cpvsub(newPoint, cpBodyGetPosition(mouseBody)), 60.0f));
  258 + // Normally, kinematic body's position would be calculated by engine.
  259 + // For mouse, though, we want to set it.
  260 + cpBodySetPosition(mouseBody, newPoint);
  261 +}
  262 +
  263 +void PhysicsImpl::MoveConstraint(cpConstraint* constraint, Vector3 newPosition)
  264 +{
  265 +}
  266 +
  267 +void PhysicsImpl::ReleaseConstraint(cpConstraint* constraint)
  268 +{
  269 + cpSpaceRemoveConstraint(mSpace, constraint);
  270 + cpConstraintFree(constraint);
  271 +}
  272 +
  273 +int PhysicsImpl::ActivateBody(cpBody* body)
  274 +{
  275 + int oldState = cpBodyIsSleeping(body);
  276 + cpBodyActivate(body);
  277 +
  278 + return oldState;
  279 +}
  280 +
  281 +void PhysicsImpl::RestoreBodyState(cpBody* body, int oldState)
  282 +{
  283 + if(oldState)
  284 + {
  285 + cpBodyActivate(body);
  286 + }
  287 + else
  288 + {
  289 + cpBodySleep(body);
  290 + }
  291 +}
... ...
examples/chipmunk-physics/physics-impl.h 0 → 100644
  1 +#ifndef DALI_PHYSICS_DEMO_PHYSICS_IMPL_H
  2 +#define DALI_PHYSICS_DEMO_PHYSICS_IMPL_H
  3 +/*
  4 + * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  5 + *
  6 + * Licensed under the Apache License, Version 2.0 (the "License");
  7 + * you may not use this file except in compliance with the License.
  8 + * You may obtain a copy of the License at
  9 + *
  10 + * http://www.apache.org/licenses/LICENSE-2.0
  11 + *
  12 + * Unless required by applicable law or agreed to in writing, software
  13 + * distributed under the License is distributed on an "AS IS" BASIS,
  14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15 + * See the License for the specific language governing permissions and
  16 + * limitations under the License.
  17 + *
  18 + */
  19 +
  20 +#include <dali/dali.h>
  21 +#include <dali/devel-api/threading/mutex.h>
  22 +#include <dali/devel-api/common/stage-devel.h>
  23 +
  24 +#include <map>
  25 +#include <chipmunk/chipmunk.h>
  26 +
  27 +#include "physics-actor.h"
  28 +#include "frame-callback.h"
  29 +
  30 +
  31 +class PhysicsImpl : public Dali::ConnectionTracker
  32 +{
  33 +public:
  34 + Dali::Actor Initialize(Dali::Window window);
  35 +
  36 + /**
  37 + * Create a layer & debug renderer
  38 + */
  39 + Dali::Layer CreateDebug(Dali::Vector2 windowSize);
  40 +
  41 + /**
  42 + * Converts a point in RootActor local coords (e.g. gesture)
  43 + * into physics space coords.
  44 + * @param vector The point to convert
  45 + * @return The converted point
  46 + */
  47 + Dali::Vector3 TranslateToPhysicsSpace(Dali::Vector3 vector);
  48 +
  49 + /**
  50 + * Converts a point in physics space coords.
  51 + * into RootActor local coords
  52 + * @param vector The point to convert
  53 + * @return The converted point
  54 + */
  55 + Dali::Vector3 TranslateFromPhysicsSpace(Dali::Vector3 vector);
  56 +
  57 + /**
  58 + * Converts a vector in DALi space into physics space.
  59 + * @param vector The vector to convert
  60 + * @return The converted vector
  61 + */
  62 + Dali::Vector3 ConvertVectorToPhysicsSpace(Dali::Vector3 vector);
  63 +
  64 + /**
  65 + * Converts a vector in physics space to DALi space
  66 + * @param vector The vector to convert
  67 + * @return The converted vector
  68 + */
  69 + Dali::Vector3 ConvertVectorFromPhysicsSpace(Dali::Vector3 vector);
  70 +
  71 + /**
  72 + * Set up the transform from world space to physics space
  73 + * @param[in] worldSize The 2d bounding box of the world in screen space
  74 + */
  75 + void SetTransform(Dali::Vector2 worldSize);
  76 +
  77 + /**
  78 + * Run the physics integration over the given timestep.
  79 + * @param timeStep
  80 + */
  81 + void Integrate(float timeStep);
  82 +
  83 + /**
  84 + * Toggle the integration state. If it's turned on, physics will run
  85 + * during the frame callback.
  86 + */
  87 + void ToggleIntegrateState()
  88 + {
  89 + mPhysicsIntegrateState ^= true;
  90 + }
  91 +
  92 + /**
  93 + * Toggle the debug state. If debug is turned on, use the physics engine
  94 + * debug to show wireframes.
  95 + */
  96 + void ToggleDebugState()
  97 + {
  98 + mPhysicsDebugState ^= true;
  99 + }
  100 +
  101 + void CreateWorldBounds(Dali::Window::WindowSize size);
  102 + cpShape* AddBound(cpBody* staticBody, cpVect start, cpVect end);
  103 + PhysicsActor& AddBall(Dali::Actor actor, float mass, float radius, float elasticity, float friction);
  104 + PhysicsActor& AddBrick(Dali::Actor actor,float mass, float elasticity, float friction, Dali::Vector3 size);
  105 +
  106 + cpBody* AddMouseBody();
  107 +
  108 + /**
  109 + * @param[in] screenCoords The touch point in screen coordinates
  110 + * @param[in] origin The camera origin in DALi world space
  111 + * @param[in] direction The ray direction in DALi world space
  112 + * @param[out] localPivot The hit point local to the body
  113 + * @param[out] distanceFromCamera The distance of the pick point from the camera
  114 + * @return nullptr if no dynamic body found, otherwise a valid ptr to the hit body.
  115 + */
  116 + cpBody* HitTest(Dali::Vector2 screenCoords, Dali::Vector3 origin, Dali::Vector3 direction,
  117 + Dali::Vector3& localPivot, float& distanceFromCamera);
  118 +
  119 + cpConstraint* AddPivotJoint(cpBody* body1, cpBody* body2, Dali::Vector3 localPivot);
  120 +
  121 + void MoveMouseBody(cpBody* mouseBody, Dali::Vector3 position);
  122 +
  123 + void MoveConstraint(cpConstraint* constraint, Dali::Vector3 newPosition);
  124 +
  125 + void ReleaseConstraint(cpConstraint* constraint);
  126 +
  127 + /**
  128 + * Ensure that the physics body does not go to sleep
  129 + * @param[in] body The physics body
  130 + * @return The old state
  131 + */
  132 + int ActivateBody(cpBody* body);
  133 +
  134 + /**
  135 + * Restore the state of the physics body
  136 + * @param[in] body The physics body
  137 + * @param[in] oldState The previous state to restore
  138 + */
  139 + void RestoreBodyState(cpBody* body, int oldState);
  140 +
  141 + /**
  142 + * Get the physics actor associated with the given body
  143 + * @param[in] body The physics body
  144 + * @return the associated physics actor
  145 + */
  146 + PhysicsActor* GetPhysicsActor(cpBody* body);
  147 +
  148 + /**
  149 + * Set the highlight state of the actor associated with the physics body
  150 + * @param[in] body The physics body
  151 + * @param[in] highlight Whether to turn the highlight on or off.
  152 + */
  153 + void HighlightBody(cpBody* body, bool highlight);
  154 +
  155 +
  156 +public:
  157 + std::map<uint32_t, PhysicsActor> mPhysicsActors;
  158 + bool mPhysicsIntegrateState{true};
  159 + bool mPhysicsDebugState{true};
  160 +
  161 + cpSpace* mSpace;
  162 + cpShape* mLeftBound{nullptr};
  163 + cpShape* mRightBound{nullptr};
  164 + cpShape* mTopBound{nullptr};
  165 + cpShape* mBottomBound{nullptr};
  166 +
  167 + Dali::Window mWindow;
  168 + Dali::Mutex mMutex;
  169 +
  170 + Dali::Actor mPhysicsRoot;
  171 + Dali::Vector2 mWorldOffset;
  172 + FrameCallback* mFrameCallback;
  173 +};
  174 +
  175 +#endif // DALI_PHYSICS_DEMO_PHYSICS_IMPL_H
... ...
examples/chipmunk-physics/shaders/rendering-textured-shape.frag 0 → 100644
  1 +uniform sampler2D uTexture;
  2 +uniform mediump float uBrightness;
  3 +varying mediump vec2 vTexCoord;
  4 +varying mediump vec3 vIllumination;
  5 +
  6 +mediump vec3 redistribute_rgb(mediump vec3 color)
  7 +{
  8 + mediump float threshold = 0.9999999;
  9 + mediump float m = max(max(color.r, color.g), color.b);
  10 + if(m <= threshold)
  11 + {
  12 + return color;
  13 + }
  14 + mediump float total = color.r + color.g + color.b;
  15 + if( total >= 3.0 * threshold)
  16 + {
  17 + return vec3(threshold);
  18 + }
  19 + mediump float x = (3.0 * threshold - total) / (3.0 * m - total);
  20 + mediump float gray = threshold - x * m;
  21 + return vec3(gray) + vec3(x)*color;
  22 +}
  23 +
  24 +void main()
  25 +{
  26 + mediump vec4 texColor = texture2D( uTexture, vTexCoord );
  27 + mediump vec3 pcol=texColor.rgb*(1.0+uBrightness);
  28 + gl_FragColor = vec4( redistribute_rgb(pcol), texColor.a);
  29 +}
0 30 \ No newline at end of file
... ...
examples/chipmunk-physics/shaders/rendering-textured-shape.vert 0 → 100644
  1 +attribute mediump vec3 aPosition; // DALi shader builtin
  2 +//attribute mediump vec2 aTexCoord; // DALi shader builtin
  3 +uniform mediump mat4 uMvpMatrix; // DALi shader builtin
  4 +uniform mediump mat4 uViewMatrix; // DALi shader builtin
  5 +uniform mediump mat4 uModelView; // DALi shader builtin
  6 +uniform mediump vec3 uSize; // DALi shader builtin
  7 +varying mediump vec3 vIllumination;
  8 +varying mediump vec2 vTexCoord;
  9 +
  10 +void main()
  11 +{
  12 + mediump vec4 vertexPosition = vec4(aPosition, 1.0);
  13 + mediump vec3 normal = normalize(vertexPosition.xyz);
  14 +
  15 + vertexPosition.xyz *= uSize;
  16 + vec4 pos = uModelView * vertexPosition;
  17 +
  18 + vec4 lightPosition = vec4(400.0, 0.0, 100.0, 1.0);
  19 + vec4 mvLightPos = uViewMatrix * lightPosition;
  20 + vec3 vectorToLight = normalize(mvLightPos.xyz - pos.xyz);
  21 + float lightDiffuse = max(dot(vectorToLight, normal), 0.0);
  22 +
  23 + vIllumination = vec3(lightDiffuse * 0.5 + 0.5);
  24 + vTexCoord = aPosition.xy*2.0;
  25 + gl_Position = uMvpMatrix * vertexPosition;
  26 +}
0 27 \ No newline at end of file
... ...
packaging/com.samsung.dali-demo.spec
... ... @@ -23,6 +23,7 @@ BuildRequires: pkgconfig(dali2-core)
23 23 BuildRequires: pkgconfig(dali2-adaptor)
24 24 BuildRequires: pkgconfig(dali2-toolkit)
25 25 BuildRequires: pkgconfig(dali2-scene3d)
  26 +BuildRequires: pkgconfig(dali2-physics-2d)
26 27 BuildRequires: pkgconfig(libtzplatform-config)
27 28 BuildRequires: pkgconfig(gles20)
28 29 BuildRequires: pkgconfig(glesv2)
... ...
resources/po/en_GB.po
... ... @@ -43,6 +43,9 @@ msgstr &quot;Card Active&quot;
43 43 msgid "DALI_DEMO_STR_TITLE_COMPRESSED_TEXTURE_FORMATS"
44 44 msgstr "Compressed Texture Formats"
45 45  
  46 +msgid "DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS"
  47 +msgstr "Chipmunk Physics"
  48 +
46 49 msgid "DALI_DEMO_STR_TITLE_CLIPPING"
47 50 msgstr "Clipping"
48 51  
... ...
resources/po/en_US.po
... ... @@ -46,6 +46,9 @@ msgstr &quot;Card Active&quot;
46 46 msgid "DALI_DEMO_STR_TITLE_COMPRESSED_TEXTURE_FORMATS"
47 47 msgstr "Compressed Texture Formats"
48 48  
  49 +msgid "DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS"
  50 +msgstr "Chipmunk Physics"
  51 +
49 52 msgid "DALI_DEMO_STR_TITLE_CLIPPING"
50 53 msgstr "Clipping"
51 54  
... ...
shared/dali-demo-strings.h
... ... @@ -50,6 +50,7 @@ extern &quot;C&quot;
50 50 #define DALI_DEMO_STR_TITLE_CANVAS_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CANVAS_VIEW")
51 51 #define DALI_DEMO_STR_TITLE_CALL_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CALL_ACTIVE")
52 52 #define DALI_DEMO_STR_TITLE_CARD_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CARD_ACTIVE")
  53 +#define DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS")
53 54 #define DALI_DEMO_STR_TITLE_CLIPPING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING")
54 55 #define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER")
55 56 #define DALI_DEMO_STR_TITLE_COLOR_TRANSITION dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_TRANSITION")
... ... @@ -169,6 +170,7 @@ extern &quot;C&quot;
169 170 #define DALI_DEMO_STR_TITLE_CANVAS_VIEW "Canvas View"
170 171 #define DALI_DEMO_STR_TITLE_CALL_ACTIVE "Call Active"
171 172 #define DALI_DEMO_STR_TITLE_CARD_ACTIVE "Card Active"
  173 +#define DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS "Chipmunk Physics"
172 174 #define DALI_DEMO_STR_TITLE_CLIPPING "Clipping"
173 175 #define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER "Clipping Draw Order"
174 176 #define DALI_DEMO_STR_TITLE_COLOR_TRANSITION "Color Transition"
... ...