#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 <dali/integration-api/debug.h>
#include <iostream>
#include <string>
using namespace Dali;
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gPhysicsDemo = Debug::Filter::New(Debug::Concise, false, "LOG_PHYSICS_EXAMPLE");
+#endif
+
namespace KeyModifier
{
enum Key
mWindow.Add(mPhysicsRoot);
- CreateBall();
- CreateBrickPyramid(windowSize);
+ // Ball area = 2*PI*26^2 ~= 6.28*26*26 ~= 5400
+ // Fill quarter of the screen...
+ int numBalls = 10 + windowSize.GetWidth() * windowSize.GetHeight() / 20000;
+
+ for(int i = 0; i < numBalls; ++i)
+ {
+ CreateBall();
+ }
// For funky mouse drag
mMouseBody = mPhysicsImpl.AddMouseBody();
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_IMAGE);
- auto ball = Toolkit::ImageView::New();
- ball[Toolkit::ImageView::Property::IMAGE] = image;
- mPhysicsImpl.AddBall(ball, BALL_MASS, BALL_RADIUS, BALL_ELASTICITY, BALL_FRICTION);
+ auto& physicsBall = mPhysicsImpl.AddBall(ball, BALL_MASS, BALL_RADIUS, BALL_ELASTICITY, BALL_FRICTION);
+ Window::WindowSize windowSize = mWindow.GetSize();
+ const float s = BALL_RADIUS;
+ const float fw = windowSize.GetWidth() - BALL_RADIUS;
+ const float fh = windowSize.GetHeight() - BALL_RADIUS;
+ physicsBall.SetPhysicsPosition(Vector3(Random::Range(s, fw), Random::Range(s, fh), 0.0f));
+ physicsBall.SetPhysicsVelocity(Vector3(Random::Range(-100.0, 100.0), Random::Range(-100.0, 100.0), 0.0f));
}
- 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);
#include "physics-actor.h"
#include <devel-api/common/stage.h>
+#include <iostream>
#include <map>
#include <utility>
-#include <iostream>
-using Dali::Layer;
using Dali::Actor;
-using Dali::Window;
+using Dali::Layer;
+using Dali::Stage;
using Dali::Vector2;
using Dali::Vector3;
-using Dali::Stage;
+using Dali::Window;
using namespace Dali::DevelStage;
-#define GRABBABLE_MASK_BIT (1u<<31)
-cpShapeFilter GRAB_FILTER = {CP_NO_GROUP, GRABBABLE_MASK_BIT, GRABBABLE_MASK_BIT};
+#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();
+ mSpace = cpSpaceNew();
cpSpaceSetIterations(mSpace, 30);
cpSpaceSetSleepTimeThreshold(mSpace, 0.5f);
cpSpaceSetGravity(mSpace, cpv(0, -200));
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 = 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;
}
// 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;
+ int xBound = size.GetWidth() / 2;
+ int yBound = size.GetHeight() / 2;
- cpBody *staticBody = cpSpaceGetStaticBody(mSpace);
+ cpBody* staticBody = cpSpaceGetStaticBody(mSpace);
if(mLeftBound)
{
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));
+ 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)
cpShape* PhysicsImpl::AddBound(cpBody* staticBody, cpVect start, cpVect end)
{
- cpShape* shape = cpSpaceAddShape(mSpace, cpSegmentShapeNew(staticBody,start, end,0.0f));
+ cpShape* shape = cpSpaceAddShape(mSpace, cpSegmentShapeNew(staticBody, start, end, 0.0f));
cpShapeSetElasticity(shape, 1.0f);
cpShapeSetFriction(shape, 1.0f);
cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER);
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)));
+ cpBody* body = cpSpaceAddBody(mSpace, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
cpBodySetPosition(body, cpv(0, 0));
cpBodySetVelocity(body, cpv(0, 0));
cpShapeSetElasticity(shape, elasticity);
cpShapeSetFriction(shape, friction);
- int id = actor[Actor::Property::ID];
+ 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;
+ 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)));
+ cpBody* body = cpSpaceAddBody(mSpace, cpBodyNew(mass, cpMomentForBox(mass, size.width, size.height)));
cpBodySetPosition(body, cpv(0, 0));
cpBodySetVelocity(body, cpv(0, 0));
cpShapeSetFriction(shape, friction);
cpShapeSetElasticity(shape, elasticity);
- int id = actor[Actor::Property::ID];
+ 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;
+ 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
+ auto kinematicBody = cpBodyNewKinematic(); // Mouse actor is a kinematic body that is not integrated
return kinematicBody;
}
Actor actor = mPhysicsRoot.FindChildById(physicsActor->GetId());
if(actor)
{
- actor[physicsActor->GetBrightnessIndex()] = highlight?1.0f:0.0f;
+ actor[physicsActor->GetBrightnessIndex()] = highlight ? 1.0f : 0.0f;
}
}
}
{
// 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);
+ 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);
+ return Vector3(vector.x + mWorldOffset.x, mWorldOffset.y - vector.y, vector.z);
}
// Convert a vector from dali space to physics space
{
cpSpaceStep(mSpace, timestep);
}
-// if(mDynamicsWorld->getDebugDrawer() && mPhysicsDebugState)
-// {
-// mDynamicsWorld->debugDrawWorld();
-// }
+ // 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);
+ 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};
+ 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;
+ 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};
+ 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));
void PhysicsImpl::MoveMouseBody(cpBody* mouseBody, Vector3 position)
{
cpVect cpPosition = cpv(position.x, position.y);
- cpVect newPoint = cpvlerp(cpBodyGetPosition(mouseBody), cpPosition, 0.25f);
+ 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.