From 3d0d22312c835f6348dfcfea5b098b2df024c70c Mon Sep 17 00:00:00 2001 From: David Steele Date: Thu, 3 Aug 2023 17:57:22 +0100 Subject: [PATCH] Fixed physics demo on target and made it more interesting Change-Id: I3a03ccc0e410e279061e08ec82a82a071bb87b78 --- examples/chipmunk-physics/frame-callback.cpp | 29 +++++-- .../chipmunk-physics/physics-demo-controller.cpp | 67 +++++----------- examples/chipmunk-physics/physics-impl.cpp | 92 +++++++++++----------- 3 files changed, 87 insertions(+), 101 deletions(-) diff --git a/examples/chipmunk-physics/frame-callback.cpp b/examples/chipmunk-physics/frame-callback.cpp index c6ef8a3..129b6d7 100644 --- a/examples/chipmunk-physics/frame-callback.cpp +++ b/examples/chipmunk-physics/frame-callback.cpp @@ -15,13 +15,18 @@ */ #include "frame-callback.h" -#include "physics-impl.h" -#include -#include #include +#include +#include +#include +#include "physics-impl.h" -using Dali::Vector3; using Dali::Quaternion; +using Dali::Vector3; + +#if defined(DEBUG_ENABLED) +extern Debug::Filter* gPhysicsDemo; +#endif FrameCallback::FrameCallback(PhysicsImpl& physicsImpl) : mPhysicsImpl(physicsImpl) @@ -30,14 +35,22 @@ FrameCallback::FrameCallback(PhysicsImpl& physicsImpl) bool FrameCallback::Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) { + static int numCalls = 0; + + numCalls++; + if(numCalls % 30 == 0) + { + DALI_LOG_INFO(gPhysicsDemo, Debug::Concise, "Physics frame update\n"); + } + Dali::Mutex::ScopedLock lock(mPhysicsImpl.mMutex); - static float frameTime=0; - frameTime+=elapsedSeconds; + static float frameTime = 0; + frameTime += elapsedSeconds; do { mPhysicsImpl.Integrate(mPhysicsTimeStep); - frameTime-=mPhysicsTimeStep; - } while (frameTime>0); + frameTime -= mPhysicsTimeStep; + } while(frameTime > 0); for(auto&& actor : mPhysicsImpl.mPhysicsActors) { diff --git a/examples/chipmunk-physics/physics-demo-controller.cpp b/examples/chipmunk-physics/physics-demo-controller.cpp index 14a9b0f..377322a 100644 --- a/examples/chipmunk-physics/physics-demo-controller.cpp +++ b/examples/chipmunk-physics/physics-demo-controller.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,10 @@ using namespace Dali; +#if defined(DEBUG_ENABLED) +Debug::Filter* gPhysicsDemo = Debug::Filter::New(Debug::Concise, false, "LOG_PHYSICS_EXAMPLE"); +#endif + namespace KeyModifier { enum Key @@ -84,8 +89,14 @@ public: 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(); @@ -98,53 +109,17 @@ public: 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); diff --git a/examples/chipmunk-physics/physics-impl.cpp b/examples/chipmunk-physics/physics-impl.cpp index 12e94a8..1916ee0 100644 --- a/examples/chipmunk-physics/physics-impl.cpp +++ b/examples/chipmunk-physics/physics-impl.cpp @@ -19,26 +19,26 @@ #include "physics-actor.h" #include +#include #include #include -#include -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)); @@ -47,16 +47,15 @@ Actor PhysicsImpl::Initialize(Window window) 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; } @@ -73,10 +72,10 @@ void PhysicsImpl::CreateWorldBounds(Window::WindowSize size) // 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) { @@ -89,10 +88,10 @@ void PhysicsImpl::CreateWorldBounds(Window::WindowSize size) 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) @@ -104,7 +103,7 @@ 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); @@ -114,7 +113,7 @@ cpShape* PhysicsImpl::AddBound(cpBody* staticBody, cpVect start, cpVect end) 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)); @@ -122,11 +121,11 @@ PhysicsActor& PhysicsImpl::AddBall(::Actor actor, float mass, float radius, floa 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); } @@ -134,7 +133,7 @@ PhysicsActor& PhysicsImpl::AddBall(::Actor actor, float mass, float radius, floa 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)); @@ -142,11 +141,11 @@ PhysicsActor& PhysicsImpl::AddBrick(Dali::Actor actor, float mass, float elastic 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); } @@ -154,7 +153,7 @@ PhysicsActor& PhysicsImpl::AddBrick(Dali::Actor actor, float mass, float elastic 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; } @@ -171,7 +170,7 @@ void PhysicsImpl::HighlightBody(cpBody* body, bool highlight) Actor actor = mPhysicsRoot.FindChildById(physicsActor->GetId()); if(actor) { - actor[physicsActor->GetBrightnessIndex()] = highlight?1.0f:0.0f; + actor[physicsActor->GetBrightnessIndex()] = highlight ? 1.0f : 0.0f; } } } @@ -181,13 +180,13 @@ 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); + 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 @@ -210,39 +209,38 @@ void PhysicsImpl::Integrate(float timestep) { 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)); @@ -253,7 +251,7 @@ cpConstraint* PhysicsImpl::AddPivotJoint(cpBody* body1, cpBody* body2, Vector3 l 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. -- 2.7.4