SET( ENABLE_SCENE3D "ON" )
ENDIF()
+ pkg_check_modules(DALI_PHYSICS_2D dali2-physics-2d)
+ IF( DALI_PHYSICS_2D_FOUND )
+ FOREACH(flag ${DALI_PHYSICS_2D_CFLAGS})
+ SET(REQUIRED_CFLAGS "${REQUIRED_CFLAGS} ${flag}")
+ ENDFOREACH(flag)
+
+ SET( REQUIRED_CFLAGS "${REQUIRED_CFLAGS} -DDALI_PHYSICS_2D_AVAILABLE" )
+
+ FOREACH(flag ${DALI_PHYSICS_2D_LDFLAGS})
+ SET(REQUIRED_PKGS_LDFLAGS "${REQUIRED_PKGS_LDFLAGS} ${flag}")
+ ENDFOREACH(flag)
+
+ SET( ENABLE_PHYSICS_2D "ON" )
+ ENDIF()
+
# if build as tizen platform, use capi-appfw-app-control
IF( TIZEN )
pkg_check_modules(CAPI_APPFW_APP_CONTROL capi-appfw-app-control)
FIND_PACKAGE( dali2-scene3d )
+ FIND_PACKAGE( chipmunk )
+
# Set up the include dir
SET( INCLUDE_DIR $ENV{includedir} )
IF( NOT INCLUDE_DIR )
)
SET( ENABLE_SCENE3D "ON" )
ENDIF()
+
+ IF (chipmunk_FOUND)
+ SET(REQUIRED_LIBS
+ ${REQUIRED_LIBS}
+ -lchipmunk
+ )
+ SET( ENABLE_PHYSICS_2D "ON" )
+ ENDIF()
+
ELSEIF( UNIX )
SET( REQUIRED_LIBS
${REQUIRED_PKGS_LDFLAGS}
SET(DALI_DEMO_CFLAGS "${DALI_DEMO_CFLAGS} -DDALI_SCENE3D_AVAILABLE")
ENDIF()
+IF( ENABLE_PHYSICS_2D )
+ SET(DALI_DEMO_CFLAGS "${DALI_DEMO_CFLAGS} -DDALI_PHYSICS_2D_AVAILABLE")
+ENDIF()
+
IF( UNIX )
IF( NOT ${ENABLE_EXPORTALL} )
ADD_DEFINITIONS( "-DHIDE_DALI_INTERNALS" )
MESSAGE( " Current Build Platform : [" ${CURRENT_BUILD_PLATFORM} "]" )
MESSAGE( " Build example name : [" ${CURRENT_BUILD_EXAMPLE_NAME} "]" )
MESSAGE( " Scene3D Enabled : [" ${ENABLE_SCENE3D} "]" )
+MESSAGE( " Physics 2D Enabled : [" ${ENABLE_PHYSICS_2D} "]" )
ENDIF()
ENDIF()
+SET(PHYSICS_2D_DIR "chipmunk")
+IF (NOT "${ENABLE_PHYSICS_2D}" )
+ IF ( ${PHYSICS_2D_DIR} IN_LIST SUBDIRS )
+ LIST( REMOVE_ITEM SUBDIRS ${PHYSICS_2D_DIR} )
+ ENDIF()
+ENDIF()
+
FIND_PROGRAM( SHADER_GENERATOR "dali-shader-generator" )
IF( NOT SHADER_GENERATOR )
MESSAGE( FATAL_ERROR "dali-shader-generator not found!" )
<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">
<label>Canvas View</label>
</ui-application>
+ <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">
+ <label>Chipmunk Physics</label>
+ </ui-application>
<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">
<label>Clipping Draw Order</label>
</ui-application>
demo.AddExample(Example("builder.example", DALI_DEMO_STR_TITLE_SCRIPT_BASED_UI));
demo.AddExample(Example("buttons.example", DALI_DEMO_STR_TITLE_BUTTONS));
demo.AddExample(Example("canvas-view.example", DALI_DEMO_STR_TITLE_CANVAS_VIEW));
+ demo.AddExample(Example("chipmunk-physics.example", DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS));
demo.AddExample(Example("clipping.example", DALI_DEMO_STR_TITLE_CLIPPING));
demo.AddExample(Example("clipping-draw-order.example", DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER));
demo.AddExample(Example("color-transition.example", DALI_DEMO_STR_TITLE_COLOR_TRANSITION));
--- /dev/null
+# Chipmunk Physics Example
+
+This is an example showing how to use Chipmunk2D physics library to create and control physics objects in DALi.
+It creates a ball and a pyramid brick wall which can be moved using touch and key events.
+
+![](./chipmunk.gif)
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "frame-callback.h"
+#include "physics-impl.h"
+#include <dali/public-api/math/vector3.h>
+#include <dali/devel-api/update/update-proxy.h>
+#include <dali/devel-api/threading/mutex.h>
+
+using Dali::Vector3;
+using Dali::Quaternion;
+
+FrameCallback::FrameCallback(PhysicsImpl& physicsImpl)
+: mPhysicsImpl(physicsImpl)
+{
+}
+
+bool FrameCallback::Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds)
+{
+ Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex);
+ static float frameTime=0;
+ frameTime+=elapsedSeconds;
+ do
+ {
+ mPhysicsImpl.Integrate(mPhysicsTimeStep);
+ frameTime-=mPhysicsTimeStep;
+ } while (frameTime>0);
+
+ for(auto&& actor : mPhysicsImpl.mPhysicsActors)
+ {
+ // Get position, orientation from physics world.
+ Vector3 position = actor.second.GetActorPosition();
+ updateProxy.BakePosition(actor.first, position);
+ Quaternion rotation = actor.second.GetActorRotation();
+ updateProxy.BakeOrientation(actor.first, rotation);
+ }
+
+ return true;
+}
--- /dev/null
+#ifndef PHYSICS_DEMO_FRAME_CALLBACK_H
+#define PHYSICS_DEMO_FRAME_CALLBACK_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/adaptor-framework/window.h>
+#include <dali/devel-api/update/frame-callback-interface.h>
+#include <map>
+#include <chrono>
+
+class PhysicsImpl;
+
+class FrameCallback : public Dali::FrameCallbackInterface
+{
+public:
+ /**
+ * Constructor
+ */
+ explicit FrameCallback(PhysicsImpl& physicsImpl);
+
+ /**
+ * Set the physics time step
+ * @param timeStep (in seconds)
+ */
+ void SetPhysicsTimeStep(float timeStep)
+ {
+ mPhysicsTimeStep = timeStep;
+ }
+
+private:
+ /**
+ * Called each frame.
+ * @param[in] updateProxy Used to set world matrix and size
+ * @param[in] elapsedSeconds Time since last frame
+ * @return Whether we should keep rendering.
+ */
+ bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) override;
+
+private: // Member variables
+ PhysicsImpl& mPhysicsImpl;
+ float mPhysicsTimeStep{1.0/180.0};
+};
+
+#endif //PHYSICS_DEMO_FRAME_CALLBACK_H
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "physics-actor.h"
+#include "physics-impl.h"
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/quaternion.h>
+
+using Dali::Vector3;
+using Dali::Quaternion;
+using Dali::Radian;
+
+void PhysicsActor::ClearForces()
+{
+ printf("Not Implemented\n");
+ //mBody->clearForces();
+ // No similar API
+}
+
+Dali::Vector3 PhysicsActor::GetPhysicsPosition()
+{
+ cpVect cpPosition = cpBodyGetPosition(mBody);
+ return Vector3(cpPosition.x, cpPosition.y, 0.0f);
+}
+
+void PhysicsActor::SetPhysicsPosition(Dali::Vector3 actorPosition)
+{
+ Dali::Mutex::ScopedLock lock(mImpl->mMutex);
+ Vector3 physicsPosition = mImpl->TranslateToPhysicsSpace(actorPosition);
+ cpBodySetPosition(mBody, cpv(physicsPosition.x, physicsPosition.y));
+}
+
+void PhysicsActor::SetPhysicsVelocity(Dali::Vector3 actorVelocity)
+{
+ Dali::Mutex::ScopedLock lock(mImpl->mMutex);
+ Vector3 physicsVelocity = mImpl->ConvertVectorToPhysicsSpace(actorVelocity);
+ cpBodySetVelocity(mBody, cpv(physicsVelocity.x, physicsVelocity.y));
+}
+
+void PhysicsActor::SetPhysicsAngularVelocity(Dali::Vector3 velocity)
+{
+ Dali::Mutex::ScopedLock lock(mImpl->mMutex);
+ printf("Not Implemented\n");
+ //mBody->setAngularVelocity(btVector3(velocity.x, velocity.y, velocity.z));
+}
+
+Quaternion PhysicsActor::GetPhysicsRotation()
+{
+ return Quaternion{};
+}
+
+void PhysicsActor::SetPhysicsRotation(Dali::Quaternion rotation)
+{
+ Dali::Mutex::ScopedLock lock(mImpl->mMutex);
+
+ Vector3 axis;
+ Radian angle;
+ rotation.ToAxisAngle(axis, angle);
+
+ //btQuaternion orn = btQuaternion(btVector3(axis.x, -axis.y, axis.z), btScalar(float(-angle)));
+ //btTransform& transform = mBody->getWorldTransform();
+ //transform.setRotation(orn);
+ printf("Not Implemented\n");
+}
+
+
+Vector3 PhysicsActor::GetActorPosition()
+{
+ cpVect cpPosition = cpBodyGetPosition(mBody);
+ return mImpl->TranslateFromPhysicsSpace(Vector3(cpPosition.x, cpPosition.y, 0.0f));
+}
+
+Vector3 PhysicsActor::GetActorVelocity()
+{
+ cpVect cpVelocity = cpBodyGetVelocity(mBody);
+ return mImpl->ConvertVectorFromPhysicsSpace(Vector3(cpVelocity.x, cpVelocity.y, 0.0f));
+}
+
+Quaternion PhysicsActor::GetActorRotation()
+{
+ cpFloat angle = cpBodyGetAngle(mBody);
+ return Quaternion(Radian(angle), -Vector3::ZAXIS);
+}
--- /dev/null
+#ifndef DALI_PHYSICS_DEMO_PHYSICS_ACTOR_H
+#define DALI_PHYSICS_DEMO_PHYSICS_ACTOR_H
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <chipmunk/chipmunk.h>
+#include <cstdint>
+#include <dali/dali.h>
+#include <iosfwd>
+
+// Forward declarations
+class PhysicsImpl;
+
+/**
+ * Class that associates an actor with a physics body. (Initially, rigid body)
+ */
+class PhysicsActor
+{
+public:
+ PhysicsActor() = default;
+ PhysicsActor(Dali::Actor& actor, cpBody* body, PhysicsImpl* impl, Dali::Property::Index brightnessId)
+ : mImpl(impl),
+ mActorId(actor.GetProperty<int>(Dali::Actor::Property::ID)),
+ mBody(body),
+ mBrightnessIndex(brightnessId)
+ {
+ cpBodySetUserData(mBody, this);
+ }
+
+ PhysicsActor(const PhysicsActor& rhs)=delete;
+ PhysicsActor& operator=(const PhysicsActor& rhs)=delete;
+
+ PhysicsActor(const PhysicsActor&& rhs)
+ {
+ if(this != &rhs)
+ {
+ mImpl = rhs.mImpl;
+ mActorId = rhs.mActorId;
+ mBody = rhs.mBody;
+ cpBodySetUserData(mBody, this);
+ mBrightnessIndex = rhs.mBrightnessIndex;
+ }
+ }
+
+ PhysicsActor& operator=(const PhysicsActor&& rhs)
+ {
+ if(this != &rhs)
+ {
+ mActorId = rhs.mActorId;
+ mBody = rhs.mBody;
+ mImpl = rhs.mImpl;
+ mBrightnessIndex = rhs.mBrightnessIndex;
+ cpBodySetUserData(mBody, this);
+ }
+ return *this;
+ }
+
+ uint32_t GetId()
+ {
+ return mActorId;
+ }
+
+ cpBody* GetBody()
+ {
+ return mBody;
+ }
+
+ Dali::Property::Index GetBrightnessIndex()
+ {
+ return mBrightnessIndex;
+ }
+
+ Dali::Vector3 GetPhysicsPosition();
+ Dali::Quaternion GetPhysicsRotation();
+
+ void SetPhysicsPosition(Dali::Vector3 actorPosition);
+ void SetPhysicsVelocity(Dali::Vector3 actorVelocity);
+ void SetPhysicsAngularVelocity(Dali::Vector3 actorVelocity);
+ void SetPhysicsRotation(Dali::Quaternion actorRotation);
+ Dali::Vector3 GetActorPosition();
+ Dali::Vector3 GetActorVelocity();
+ Dali::Quaternion GetActorRotation();
+ void ClearForces();
+
+private:
+ PhysicsImpl* mImpl{nullptr};
+ uint32_t mActorId{0};
+ cpBody* mBody{nullptr};
+ Dali::Property::Index mBrightnessIndex{Dali::Property::INVALID_INDEX};
+};
+
+#endif // DALI_PHYSICS_DEMO_PHYSICS_ACTOR_H
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali/dali.h>
+
+#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
+#include <dali/devel-api/adaptor-framework/key-devel.h>
+#include <dali/devel-api/events/hit-test-algorithm.h>
+
+#include <iostream>
+#include <string>
+
+#include "generated/rendering-textured-shape-frag.h"
+#include "generated/rendering-textured-shape-vert.h"
+#include "physics-actor.h"
+#include "physics-impl.h"
+
+using namespace Dali;
+
+namespace KeyModifier
+{
+enum Key
+{
+ CONTROL_L = DevelKey::DALI_KEY_CONTROL_LEFT,
+ CONTROL_R = DevelKey::DALI_KEY_CONTROL_RIGHT,
+ SHIFT_L = 50,
+ SHIFT_R = 62,
+ ALT_L = 64,
+ ALT_R = 108,
+ SUPER_L = 133,
+ SUPER_R = 134,
+ MENU = 135,
+};
+}
+
+const std::string BRICK_WALL = DEMO_IMAGE_DIR "/brick-wall.jpg";
+const std::string BALL_IMAGE = DEMO_IMAGE_DIR "/blocks-ball.png";
+const std::string BRICK_URIS[4] = {
+ 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"};
+
+/**
+ * @brief The physics demo using Chipmunk2D APIs.
+ */
+class PhysicsDemoController : public ConnectionTracker
+{
+public:
+ PhysicsDemoController(Application& app)
+ : mApplication(app)
+ {
+ app.InitSignal().Connect(this, &PhysicsDemoController::OnInit);
+ app.TerminateSignal().Connect(this, &PhysicsDemoController::OnTerminate);
+ }
+
+ ~PhysicsDemoController() override
+ {
+ }
+
+ void OnInit(Application& application)
+ {
+ mWindow = application.GetWindow();
+ mWindow.ResizeSignal().Connect(this, &PhysicsDemoController::OnWindowResize);
+ mWindow.KeyEventSignal().Connect(this, &PhysicsDemoController::OnKeyEv);
+ Stage::GetCurrent().KeepRendering(30);
+ mWindow.SetBackgroundColor(Color::DARK_SLATE_GRAY);
+ Window::WindowSize windowSize = mWindow.GetSize();
+
+ mPhysicsRoot = mPhysicsImpl.Initialize(mWindow);
+ mPhysicsRoot.TouchedSignal().Connect(this, &PhysicsDemoController::OnTouched);
+
+ mWindow.Add(mPhysicsRoot);
+
+ CreateBall();
+ CreateBrickPyramid(windowSize);
+
+ // For funky mouse drag
+ mMouseBody = mPhysicsImpl.AddMouseBody();
+ }
+
+ void CreateBall()
+ {
+ const float BALL_MASS = 10.0f;
+ const float BALL_RADIUS = 26.0f;
+ const float BALL_ELASTICITY = 0.5f;
+ const float BALL_FRICTION = 0.5f;
+
+ Property::Value v{std::string{SHADER_RENDERING_TEXTURED_SHAPE_VERT}};
+ Property::Value f{std::string{SHADER_RENDERING_TEXTURED_SHAPE_FRAG}};
+
+ auto image = Property::Map{{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
+ {Toolkit::ImageVisual::Property::URL, BALL_IMAGE},
+ {Toolkit::Visual::Property::SHADER, {{Toolkit::Visual::Shader::Property::FRAGMENT_SHADER, f}}}};
+
+ auto ball = Toolkit::ImageView::New();
+ ball[Toolkit::ImageView::Property::IMAGE] = image;
+ mPhysicsImpl.AddBall(ball, BALL_MASS, BALL_RADIUS, BALL_ELASTICITY, BALL_FRICTION);
+ }
+
+ void CreateBrickPyramid(Dali::Window::WindowSize windowSize)
+ {
+ const float BRICK_MASS = 30.0f;
+ const float BRICK_ELASTICITY = 0.0f;
+ const float BRICK_FRICTION = 0.9f;
+ const int BRICK_WIDTH = 128;
+ const int BRICK_HEIGHT = 64;
+ const int BRICK_GAP = 8;
+
+ Property::Value v{std::string{SHADER_RENDERING_TEXTURED_SHAPE_VERT}};
+ Property::Value f{std::string{SHADER_RENDERING_TEXTURED_SHAPE_FRAG}};
+
+ int uriIndex = 0;
+ int numberOfRows = windowSize.GetWidth() / (BRICK_WIDTH + BRICK_GAP) - 2;
+ int oY = windowSize.GetHeight() - (1 + numberOfRows) * BRICK_HEIGHT;
+ for(int i = 0; i < numberOfRows; ++i)
+ {
+ // Row start: i+1 is brick number. i is gap#
+ int w = (i + 1) * BRICK_WIDTH + i * BRICK_GAP;
+ int oX = (windowSize.GetWidth() - w) / 2;
+ for(int j = 0; j < i + 1; ++j)
+ {
+ auto image = Property::Map{{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
+ {Toolkit::ImageVisual::Property::URL, BRICK_URIS[uriIndex]},
+ {Toolkit::Visual::Property::SHADER, {{Toolkit::Visual::Shader::Property::FRAGMENT_SHADER, f}}}};
+
+ auto brick = Toolkit::ImageView::New();
+ brick[Toolkit::ImageView::Property::IMAGE] = image;
+ auto& physicsActor = mPhysicsImpl.AddBrick(brick, BRICK_MASS, BRICK_ELASTICITY, BRICK_FRICTION, Vector3(BRICK_WIDTH, BRICK_HEIGHT, BRICK_HEIGHT));
+ physicsActor.SetPhysicsPosition(Vector3(oX + j * (BRICK_WIDTH + BRICK_GAP), oY + i * BRICK_HEIGHT, 0.0f));
+ uriIndex += 1;
+ uriIndex %= 4;
+ }
+ }
+ }
+ void OnTerminate(Application& application)
+ {
+ UnparentAndReset(mPhysicsRoot);
+ }
+
+ void OnWindowResize(Window window, Window::WindowSize newSize)
+ {
+ mPhysicsImpl.CreateWorldBounds(newSize);
+ }
+
+ bool OnTouched(Dali::Actor actor, const Dali::TouchEvent& touch)
+ {
+ static enum {
+ None,
+ MoveCameraXZ,
+ MovePivot,
+ } state = None;
+
+ auto renderTask = mWindow.GetRenderTaskList().GetTask(0);
+ auto screenCoords = touch.GetScreenPosition(0);
+ Vector3 origin, direction;
+ Dali::HitTestAlgorithm::BuildPickingRay(renderTask, screenCoords, origin, direction);
+
+ switch(state)
+ {
+ case None:
+ {
+ if(touch.GetState(0) == Dali::PointState::STARTED)
+ {
+ if(mCtrlDown)
+ {
+ state = MoveCameraXZ;
+ // local to top left
+ //cameraY = touch.GetLocalPosition(0).y;
+ // Could move on fixed plane, e.g. y=0.
+ // position.Y corresponds to a z value depending on perspective
+ // position.X scales to an x value depending on perspective
+ }
+ else
+ {
+ state = MovePivot;
+ Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex);
+
+ Vector3 localPivot;
+ float pickingDistance;
+ auto body = mPhysicsImpl.HitTest(screenCoords, origin, direction, localPivot, pickingDistance);
+ if(body)
+ {
+ mPickedBody = body;
+ mPhysicsImpl.HighlightBody(mPickedBody, true);
+ mPickedSavedState = mPhysicsImpl.ActivateBody(mPickedBody);
+ mPickedConstraint = mPhysicsImpl.AddPivotJoint(mPickedBody, mMouseBody, localPivot);
+ }
+ }
+ }
+ break;
+ }
+ case MovePivot:
+ {
+ if(touch.GetState(0) == Dali::PointState::MOTION)
+ {
+ if(mPickedBody && mPickedConstraint)
+ {
+ if(!mShiftDown)
+ {
+ // Move point in XY plane, projected into scene
+ Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex);
+
+ Vector3 position = mPhysicsImpl.TranslateToPhysicsSpace(Vector3(screenCoords));
+ mPhysicsImpl.MoveMouseBody(mMouseBody, position);
+ }
+ else
+ {
+ // Move point in XZ plane
+ // Above vanishing pt, it's on top plane of frustum; below vanishing pt it's on bottom plane.
+ // Kind of want to project onto the plane using initial touch xy, rather than top/bottom.
+ // Whole new projection code needed.
+
+ // Cheat!
+ }
+ }
+ }
+ else if(touch.GetState(0) == Dali::PointState::FINISHED ||
+ touch.GetState(0) == Dali::PointState::INTERRUPTED)
+ {
+ if(mPickedConstraint)
+ {
+ mPhysicsImpl.HighlightBody(mPickedBody, false);
+
+ Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex);
+ mPhysicsImpl.RestoreBodyState(mPickedBody, mPickedSavedState);
+ mPhysicsImpl.ReleaseConstraint(mPickedConstraint);
+ mPickedConstraint = nullptr;
+ mPickedBody = nullptr;
+ }
+ state = None;
+ }
+ break;
+ }
+ case MoveCameraXZ:
+ {
+ if(touch.GetState(0) == Dali::PointState::MOTION)
+ {
+ // Move camera in XZ plane
+ //float y = cameraY; // touch point in Y. Move camera in an XZ plane on this point.
+ }
+ else if(touch.GetState(0) == Dali::PointState::FINISHED ||
+ touch.GetState(0) == Dali::PointState::INTERRUPTED)
+ {
+ state = None;
+ }
+ break;
+ }
+ }
+
+ //std::cout<<"Touch State: "<<state<<std::endl;
+ Stage::GetCurrent().KeepRendering(30.0f);
+
+ return true;
+ }
+
+ void OnKeyEv(const Dali::KeyEvent& event)
+ {
+ if(event.GetState() == KeyEvent::DOWN)
+ {
+ switch(event.GetKeyCode())
+ {
+ case KeyModifier::CONTROL_L:
+ case KeyModifier::CONTROL_R:
+ {
+ mCtrlDown = true;
+ break;
+ }
+ case KeyModifier::ALT_L:
+ case KeyModifier::ALT_R:
+ {
+ mAltDown = true;
+ break;
+ }
+ case KeyModifier::SHIFT_L:
+ case KeyModifier::SHIFT_R:
+ {
+ mShiftDown = true;
+ break;
+ }
+ default:
+ {
+ if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
+ {
+ mApplication.Quit();
+ }
+ else if(!event.GetKeyString().compare(" "))
+ {
+ mPhysicsImpl.ToggleIntegrateState();
+ }
+ else if(!event.GetKeyString().compare("m"))
+ {
+ mPhysicsImpl.ToggleDebugState();
+ }
+ break;
+ }
+ }
+ }
+ else if(event.GetState() == KeyEvent::UP)
+ {
+ switch(event.GetKeyCode())
+ {
+ case KeyModifier::CONTROL_L:
+ case KeyModifier::CONTROL_R:
+ {
+ mCtrlDown = false;
+ break;
+ }
+ case KeyModifier::ALT_L:
+ case KeyModifier::ALT_R:
+ {
+ mAltDown = false;
+ break;
+ }
+ case KeyModifier::SHIFT_L:
+ case KeyModifier::SHIFT_R:
+ {
+ mShiftDown = false;
+ break;
+ }
+ }
+ }
+ }
+
+private:
+ Application& mApplication;
+ Window mWindow;
+
+ PhysicsImpl mPhysicsImpl;
+ Actor mPhysicsRoot;
+ cpBody* mMouseBody{nullptr};
+ cpBody* mPickedBody{nullptr};
+ cpConstraint* mPickedConstraint{nullptr};
+ int mPickedSavedState = -1; /// 0 : Active, 1 : Sleeping
+
+ bool mCtrlDown{false};
+ bool mAltDown{false};
+ bool mShiftDown{false};
+};
+
+int DALI_EXPORT_API main(int argc, char** argv)
+{
+ Application application = Application::New(&argc, &argv);
+ PhysicsDemoController controller(application);
+ application.MainLoop();
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "physics-impl.h"
+#include "physics-actor.h"
+
+#include <devel-api/common/stage.h>
+#include <map>
+#include <utility>
+#include <iostream>
+
+using Dali::Layer;
+using Dali::Actor;
+using Dali::Window;
+using Dali::Vector2;
+using Dali::Vector3;
+using Dali::Stage;
+using namespace Dali::DevelStage;
+
+#define GRABBABLE_MASK_BIT (1u<<31)
+cpShapeFilter GRAB_FILTER = {CP_NO_GROUP, GRABBABLE_MASK_BIT, GRABBABLE_MASK_BIT};
+cpShapeFilter NOT_GRABBABLE_FILTER = {CP_NO_GROUP, ~GRABBABLE_MASK_BIT, ~GRABBABLE_MASK_BIT};
+
+Actor PhysicsImpl::Initialize(Window window)
+{
+ mWindow = window;
+ mSpace = cpSpaceNew();
+ cpSpaceSetIterations(mSpace, 30);
+ cpSpaceSetSleepTimeThreshold(mSpace, 0.5f);
+ cpSpaceSetGravity(mSpace, cpv(0, -200));
+
+ auto windowSize = window.GetSize();
+ CreateWorldBounds(windowSize);
+
+ // Create an actor that can handle mouse events.
+ mPhysicsRoot = Layer::New();
+ mPhysicsRoot[Actor::Property::SIZE] = Vector2(windowSize.GetWidth(), windowSize.GetHeight());
+ mPhysicsRoot[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER;
+ mPhysicsRoot[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER;
+
+ mFrameCallback = new FrameCallback(*this);
+ AddFrameCallback(Stage::GetCurrent(), *mFrameCallback, window.GetRootLayer());
+ Stage::GetCurrent().KeepRendering(30);
+
+
+ return mPhysicsRoot;
+}
+
+Layer PhysicsImpl::CreateDebug(Vector2 windowSize)
+{
+ return Layer();
+}
+
+void PhysicsImpl::CreateWorldBounds(Window::WindowSize size)
+{
+ // Physics origin is 0,0,0 in DALi coords.
+ // But, Y is inverted, so bottom is -ve, top is +ve.
+ // Perform this correction when applying position to actor.
+ // But, can't use actors in update, so cache transform.
+ SetTransform(Vector2(size.GetWidth(), size.GetHeight()));
+
+ int xBound=size.GetWidth()/2;
+ int yBound=size.GetHeight()/2;
+
+ cpBody *staticBody = cpSpaceGetStaticBody(mSpace);
+
+ if(mLeftBound)
+ {
+ cpSpaceRemoveShape(mSpace, mLeftBound);
+ cpSpaceRemoveShape(mSpace, mRightBound);
+ cpSpaceRemoveShape(mSpace, mTopBound);
+ cpSpaceRemoveShape(mSpace, mBottomBound);
+ cpShapeFree(mLeftBound);
+ cpShapeFree(mRightBound);
+ cpShapeFree(mTopBound);
+ cpShapeFree(mBottomBound);
+ }
+ mLeftBound = AddBound(staticBody, cpv(-xBound, -yBound), cpv(-xBound, yBound));
+ mRightBound = AddBound(staticBody, cpv( xBound, -yBound), cpv( xBound, yBound));
+ mTopBound = AddBound(staticBody, cpv(-xBound, -yBound), cpv( xBound, -yBound));
+ mBottomBound = AddBound(staticBody, cpv(-xBound, yBound), cpv( xBound, yBound));
+}
+
+void PhysicsImpl::SetTransform(Vector2 worldSize)
+{
+ mWorldOffset.x = worldSize.x * 0.5f;
+ mWorldOffset.y = worldSize.y * 0.5f;
+ // y is always inverted.
+}
+
+cpShape* PhysicsImpl::AddBound(cpBody* staticBody, cpVect start, cpVect end)
+{
+ cpShape* shape = cpSpaceAddShape(mSpace, cpSegmentShapeNew(staticBody,start, end,0.0f));
+ cpShapeSetElasticity(shape, 1.0f);
+ cpShapeSetFriction(shape, 1.0f);
+ cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER);
+ return shape;
+}
+
+PhysicsActor& PhysicsImpl::AddBall(::Actor actor, float mass, float radius, float elasticity, float friction)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+ cpBody* body = cpSpaceAddBody(mSpace, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
+ cpBodySetPosition(body, cpv(0, 0));
+ cpBodySetVelocity(body, cpv(0, 0));
+
+ cpShape* shape = cpSpaceAddShape(mSpace, cpCircleShapeNew(body, radius, cpvzero));
+ cpShapeSetElasticity(shape, elasticity);
+ cpShapeSetFriction(shape, friction);
+
+ int id = actor[Actor::Property::ID];
+ Dali::Property::Index index = actor.RegisterProperty("uBrightness", 0.0f);
+ mPhysicsActors.insert(std::make_pair(id, PhysicsActor{actor, body, this, index}));
+ actor[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::TOP_LEFT;
+ actor[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER;
+ mPhysicsRoot.Add(actor);
+ return mPhysicsActors.at(id);
+}
+
+PhysicsActor& PhysicsImpl::AddBrick(Dali::Actor actor, float mass, float elasticity, float friction, Vector3 size)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+ cpBody* body = cpSpaceAddBody(mSpace, cpBodyNew(mass, cpMomentForBox(mass, size.width, size.height)));
+ cpBodySetPosition(body, cpv(0, 0));
+ cpBodySetVelocity(body, cpv(0, 0));
+
+ cpShape* shape = cpSpaceAddShape(mSpace, cpBoxShapeNew(body, size.width, size.height, 0.0f));
+ cpShapeSetFriction(shape, friction);
+ cpShapeSetElasticity(shape, elasticity);
+
+ int id = actor[Actor::Property::ID];
+ Dali::Property::Index index = actor.RegisterProperty("uBrightness", 0.0f);
+ mPhysicsActors.insert(std::make_pair(id, PhysicsActor{actor, body, this, index}));
+ actor[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::TOP_LEFT;
+ actor[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER;
+ mPhysicsRoot.Add(actor);
+ return mPhysicsActors.at(id);
+}
+
+cpBody* PhysicsImpl::AddMouseBody()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+ auto kinematicBody = cpBodyNewKinematic(); // Mouse actor is a kinematic body that is not integrated
+ return kinematicBody;
+}
+
+PhysicsActor* PhysicsImpl::GetPhysicsActor(cpBody* body)
+{
+ return reinterpret_cast<PhysicsActor*>(cpBodyGetUserData(body));
+}
+
+void PhysicsImpl::HighlightBody(cpBody* body, bool highlight)
+{
+ auto physicsActor = GetPhysicsActor(body);
+ if(physicsActor)
+ {
+ Actor actor = mPhysicsRoot.FindChildById(physicsActor->GetId());
+ if(actor)
+ {
+ actor[physicsActor->GetBrightnessIndex()] = highlight?1.0f:0.0f;
+ }
+ }
+}
+
+// Convert from root actor local space to physics space
+Vector3 PhysicsImpl::TranslateToPhysicsSpace(Vector3 vector)
+{
+ // root actor origin is top left, DALi Y is inverted.
+ // Physics origin is center. Y: 0->1 => 0.5=>-0.5
+ return Vector3(vector.x-mWorldOffset.x, mWorldOffset.y-vector.y, vector.z);
+}
+
+// Convert from physics space to root actor local space
+Vector3 PhysicsImpl::TranslateFromPhysicsSpace(Vector3 vector)
+{
+ return Vector3(vector.x+mWorldOffset.x, mWorldOffset.y-vector.y, vector.z);
+}
+
+// Convert a vector from dali space to physics space
+Vector3 PhysicsImpl::ConvertVectorToPhysicsSpace(Vector3 vector)
+{
+ // root actor origin is top left, DALi Y is inverted.
+ // @todo Add space config scale.
+ return Vector3(vector.x, -vector.y, vector.z);
+}
+
+// Convert a vector physics space to root actor local space
+Vector3 PhysicsImpl::ConvertVectorFromPhysicsSpace(Vector3 vector)
+{
+ return Vector3(vector.x, -vector.y, vector.z);
+}
+
+void PhysicsImpl::Integrate(float timestep)
+{
+ if(mPhysicsIntegrateState)
+ {
+ cpSpaceStep(mSpace, timestep);
+ }
+// if(mDynamicsWorld->getDebugDrawer() && mPhysicsDebugState)
+// {
+// mDynamicsWorld->debugDrawWorld();
+// }
+}
+
+cpBody* PhysicsImpl::HitTest(Vector2 screenCoords, Vector3 origin, Vector3 direction, Vector3& localPivot, float& distanceFromCamera)
+{
+ Vector3 spacePosition = TranslateToPhysicsSpace(Vector3{screenCoords});
+ cpVect mousePosition = cpv(spacePosition.x, spacePosition.y);
+ cpFloat radius = 5.0f;
+ cpPointQueryInfo info = {0};
+ cpShape *shape = cpSpacePointQueryNearest(mSpace, mousePosition, radius, GRAB_FILTER, &info);
+
+ cpBody *body{nullptr};
+
+ if(shape && cpBodyGetMass(cpShapeGetBody(shape)) < INFINITY)
+ {
+ // Use the closest point on the surface if the click is outside the shape.
+ cpVect nearest = (info.distance > 0.0f ? info.point : mousePosition);
+ body = cpShapeGetBody(shape);
+ cpVect local = cpBodyWorldToLocal(body, nearest);
+ localPivot.x = local.x;
+ localPivot.y = local.y;
+ localPivot.z = 0.0;
+ }
+ return body;
+}
+
+
+cpConstraint* PhysicsImpl::AddPivotJoint(cpBody* body1, cpBody* body2, Vector3 localPivot)
+{
+ cpVect pivot{localPivot.x, localPivot.y};
+ cpConstraint* joint = cpPivotJointNew2(body2, body1, cpvzero, pivot);
+ cpConstraintSetMaxForce(joint, 50000.0f); // Magic numbers for mouse feedback.
+ cpConstraintSetErrorBias(joint, cpfpow(1.0f - 0.15f, 60.0f));
+ cpConstraint* constraint = cpSpaceAddConstraint(mSpace, joint);
+ return constraint; // Constraint & joint are the same...
+}
+
+void PhysicsImpl::MoveMouseBody(cpBody* mouseBody, Vector3 position)
+{
+ cpVect cpPosition = cpv(position.x, position.y);
+ cpVect newPoint = cpvlerp(cpBodyGetPosition(mouseBody), cpPosition, 0.25f);
+ cpBodySetVelocity(mouseBody, cpvmult(cpvsub(newPoint, cpBodyGetPosition(mouseBody)), 60.0f));
+ // Normally, kinematic body's position would be calculated by engine.
+ // For mouse, though, we want to set it.
+ cpBodySetPosition(mouseBody, newPoint);
+}
+
+void PhysicsImpl::MoveConstraint(cpConstraint* constraint, Vector3 newPosition)
+{
+}
+
+void PhysicsImpl::ReleaseConstraint(cpConstraint* constraint)
+{
+ cpSpaceRemoveConstraint(mSpace, constraint);
+ cpConstraintFree(constraint);
+}
+
+int PhysicsImpl::ActivateBody(cpBody* body)
+{
+ int oldState = cpBodyIsSleeping(body);
+ cpBodyActivate(body);
+
+ return oldState;
+}
+
+void PhysicsImpl::RestoreBodyState(cpBody* body, int oldState)
+{
+ if(oldState)
+ {
+ cpBodyActivate(body);
+ }
+ else
+ {
+ cpBodySleep(body);
+ }
+}
--- /dev/null
+#ifndef DALI_PHYSICS_DEMO_PHYSICS_IMPL_H
+#define DALI_PHYSICS_DEMO_PHYSICS_IMPL_H
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/dali.h>
+#include <dali/devel-api/threading/mutex.h>
+#include <dali/devel-api/common/stage-devel.h>
+
+#include <map>
+#include <chipmunk/chipmunk.h>
+
+#include "physics-actor.h"
+#include "frame-callback.h"
+
+
+class PhysicsImpl : public Dali::ConnectionTracker
+{
+public:
+ Dali::Actor Initialize(Dali::Window window);
+
+ /**
+ * Create a layer & debug renderer
+ */
+ Dali::Layer CreateDebug(Dali::Vector2 windowSize);
+
+ /**
+ * Converts a point in RootActor local coords (e.g. gesture)
+ * into physics space coords.
+ * @param vector The point to convert
+ * @return The converted point
+ */
+ Dali::Vector3 TranslateToPhysicsSpace(Dali::Vector3 vector);
+
+ /**
+ * Converts a point in physics space coords.
+ * into RootActor local coords
+ * @param vector The point to convert
+ * @return The converted point
+ */
+ Dali::Vector3 TranslateFromPhysicsSpace(Dali::Vector3 vector);
+
+ /**
+ * Converts a vector in DALi space into physics space.
+ * @param vector The vector to convert
+ * @return The converted vector
+ */
+ Dali::Vector3 ConvertVectorToPhysicsSpace(Dali::Vector3 vector);
+
+ /**
+ * Converts a vector in physics space to DALi space
+ * @param vector The vector to convert
+ * @return The converted vector
+ */
+ Dali::Vector3 ConvertVectorFromPhysicsSpace(Dali::Vector3 vector);
+
+ /**
+ * Set up the transform from world space to physics space
+ * @param[in] worldSize The 2d bounding box of the world in screen space
+ */
+ void SetTransform(Dali::Vector2 worldSize);
+
+ /**
+ * Run the physics integration over the given timestep.
+ * @param timeStep
+ */
+ void Integrate(float timeStep);
+
+ /**
+ * Toggle the integration state. If it's turned on, physics will run
+ * during the frame callback.
+ */
+ void ToggleIntegrateState()
+ {
+ mPhysicsIntegrateState ^= true;
+ }
+
+ /**
+ * Toggle the debug state. If debug is turned on, use the physics engine
+ * debug to show wireframes.
+ */
+ void ToggleDebugState()
+ {
+ mPhysicsDebugState ^= true;
+ }
+
+ void CreateWorldBounds(Dali::Window::WindowSize size);
+ cpShape* AddBound(cpBody* staticBody, cpVect start, cpVect end);
+ PhysicsActor& AddBall(Dali::Actor actor, float mass, float radius, float elasticity, float friction);
+ PhysicsActor& AddBrick(Dali::Actor actor,float mass, float elasticity, float friction, Dali::Vector3 size);
+
+ cpBody* AddMouseBody();
+
+ /**
+ * @param[in] screenCoords The touch point in screen coordinates
+ * @param[in] origin The camera origin in DALi world space
+ * @param[in] direction The ray direction in DALi world space
+ * @param[out] localPivot The hit point local to the body
+ * @param[out] distanceFromCamera The distance of the pick point from the camera
+ * @return nullptr if no dynamic body found, otherwise a valid ptr to the hit body.
+ */
+ cpBody* HitTest(Dali::Vector2 screenCoords, Dali::Vector3 origin, Dali::Vector3 direction,
+ Dali::Vector3& localPivot, float& distanceFromCamera);
+
+ cpConstraint* AddPivotJoint(cpBody* body1, cpBody* body2, Dali::Vector3 localPivot);
+
+ void MoveMouseBody(cpBody* mouseBody, Dali::Vector3 position);
+
+ void MoveConstraint(cpConstraint* constraint, Dali::Vector3 newPosition);
+
+ void ReleaseConstraint(cpConstraint* constraint);
+
+ /**
+ * Ensure that the physics body does not go to sleep
+ * @param[in] body The physics body
+ * @return The old state
+ */
+ int ActivateBody(cpBody* body);
+
+ /**
+ * Restore the state of the physics body
+ * @param[in] body The physics body
+ * @param[in] oldState The previous state to restore
+ */
+ void RestoreBodyState(cpBody* body, int oldState);
+
+ /**
+ * Get the physics actor associated with the given body
+ * @param[in] body The physics body
+ * @return the associated physics actor
+ */
+ PhysicsActor* GetPhysicsActor(cpBody* body);
+
+ /**
+ * Set the highlight state of the actor associated with the physics body
+ * @param[in] body The physics body
+ * @param[in] highlight Whether to turn the highlight on or off.
+ */
+ void HighlightBody(cpBody* body, bool highlight);
+
+
+public:
+ std::map<uint32_t, PhysicsActor> mPhysicsActors;
+ bool mPhysicsIntegrateState{true};
+ bool mPhysicsDebugState{true};
+
+ cpSpace* mSpace{nullptr};
+ cpShape* mLeftBound{nullptr};
+ cpShape* mRightBound{nullptr};
+ cpShape* mTopBound{nullptr};
+ cpShape* mBottomBound{nullptr};
+
+ Dali::Window mWindow;
+ Dali::Mutex mMutex;
+
+ Dali::Actor mPhysicsRoot;
+ Dali::Vector2 mWorldOffset;
+ FrameCallback* mFrameCallback{nullptr};
+};
+
+#endif // DALI_PHYSICS_DEMO_PHYSICS_IMPL_H
--- /dev/null
+uniform sampler2D uTexture;
+uniform mediump float uBrightness;
+varying mediump vec2 vTexCoord;
+varying mediump vec3 vIllumination;
+
+mediump vec3 redistribute_rgb(mediump vec3 color)
+{
+ mediump float threshold = 0.9999999;
+ mediump float m = max(max(color.r, color.g), color.b);
+ if(m <= threshold)
+ {
+ return color;
+ }
+ mediump float total = color.r + color.g + color.b;
+ if( total >= 3.0 * threshold)
+ {
+ return vec3(threshold);
+ }
+ mediump float x = (3.0 * threshold - total) / (3.0 * m - total);
+ mediump float gray = threshold - x * m;
+ return vec3(gray) + vec3(x)*color;
+}
+
+void main()
+{
+ mediump vec4 texColor = texture2D( uTexture, vTexCoord );
+ mediump vec3 pcol=texColor.rgb*(1.0+uBrightness);
+ gl_FragColor = vec4( redistribute_rgb(pcol), texColor.a);
+}
\ No newline at end of file
--- /dev/null
+attribute mediump vec3 aPosition; // DALi shader builtin
+//attribute mediump vec2 aTexCoord; // DALi shader builtin
+uniform mediump mat4 uMvpMatrix; // DALi shader builtin
+uniform mediump mat4 uViewMatrix; // DALi shader builtin
+uniform mediump mat4 uModelView; // DALi shader builtin
+uniform mediump vec3 uSize; // DALi shader builtin
+varying mediump vec3 vIllumination;
+varying mediump vec2 vTexCoord;
+
+void main()
+{
+ mediump vec4 vertexPosition = vec4(aPosition, 1.0);
+ mediump vec3 normal = normalize(vertexPosition.xyz);
+
+ vertexPosition.xyz *= uSize;
+ vec4 pos = uModelView * vertexPosition;
+
+ vec4 lightPosition = vec4(400.0, 0.0, 100.0, 1.0);
+ vec4 mvLightPos = uViewMatrix * lightPosition;
+ vec3 vectorToLight = normalize(mvLightPos.xyz - pos.xyz);
+ float lightDiffuse = max(dot(vectorToLight, normal), 0.0);
+
+ vIllumination = vec3(lightDiffuse * 0.5 + 0.5);
+ vTexCoord = aPosition.xy*2.0;
+ gl_Position = uMvpMatrix * vertexPosition;
+}
\ No newline at end of file
Name: com.samsung.dali-demo
Summary: The OpenGLES Canvas Core Demo
-Version: 2.2.37
+Version: 2.2.38
Release: 1
Group: System/Libraries
License: Apache-2.0
BuildRequires: pkgconfig(dali2-adaptor)
BuildRequires: pkgconfig(dali2-toolkit)
BuildRequires: pkgconfig(dali2-scene3d)
+BuildRequires: pkgconfig(dali2-physics-2d)
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(gles20)
BuildRequires: pkgconfig(glesv2)
msgid "DALI_DEMO_STR_TITLE_COMPRESSED_TEXTURE_FORMATS"
msgstr "Compressed Texture Formats"
+msgid "DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS"
+msgstr "Chipmunk Physics"
+
msgid "DALI_DEMO_STR_TITLE_CLIPPING"
msgstr "Clipping"
msgid "DALI_DEMO_STR_TITLE_COMPRESSED_TEXTURE_FORMATS"
msgstr "Compressed Texture Formats"
+msgid "DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS"
+msgstr "Chipmunk Physics"
+
msgid "DALI_DEMO_STR_TITLE_CLIPPING"
msgstr "Clipping"
#define DALI_DEMO_STR_TITLE_CANVAS_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CANVAS_VIEW")
#define DALI_DEMO_STR_TITLE_CALL_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CALL_ACTIVE")
#define DALI_DEMO_STR_TITLE_CARD_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CARD_ACTIVE")
+#define DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS")
#define DALI_DEMO_STR_TITLE_CLIPPING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING")
#define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER")
#define DALI_DEMO_STR_TITLE_COLOR_TRANSITION dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_TRANSITION")
#define DALI_DEMO_STR_TITLE_CANVAS_VIEW "Canvas View"
#define DALI_DEMO_STR_TITLE_CALL_ACTIVE "Call Active"
#define DALI_DEMO_STR_TITLE_CARD_ACTIVE "Card Active"
+#define DALI_DEMO_STR_TITLE_CHIPMUNK_PHYSICS "Chipmunk Physics"
#define DALI_DEMO_STR_TITLE_CLIPPING "Clipping"
#define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER "Clipping Draw Order"
#define DALI_DEMO_STR_TITLE_COLOR_TRANSITION "Color Transition"