From: David Steele Date: Mon, 4 Sep 2023 17:42:49 +0000 (+0100) Subject: Adding dali letters to 2d phys demo X-Git-Tag: dali_2.2.44~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=549cce45e261fa60e50858841468bd7affe0f003;p=platform%2Fcore%2Fuifw%2Fdali-demo.git Adding dali letters to 2d phys demo Added "hanging" letters that can pivot about some point Now, the balls interact with the letters, and fire off with a huge impulse periodically to bring some life to the demo! Change-Id: Ieecacc3b27e4e55174cb86d1075c9b1739ae0bc3 --- diff --git a/examples/bullet-physics/physics-demo-controller.cpp b/examples/bullet-physics/physics-demo-controller.cpp index 93ec771..40fdc59 100644 --- a/examples/bullet-physics/physics-demo-controller.cpp +++ b/examples/bullet-physics/physics-demo-controller.cpp @@ -303,8 +303,9 @@ public: Vector3 localPivot; Vector3 rayPhysicsOrigin; Vector3 rayPhysicsEnd; + Dali::Any nullFilter; mPhysicsAdaptor.BuildPickingRay(origin, direction, rayPhysicsOrigin, rayPhysicsEnd); - auto body = scopedAccessor->HitTest(rayPhysicsOrigin, rayPhysicsEnd, localPivot, mOldPickingDistance); + auto body = scopedAccessor->HitTest(rayPhysicsOrigin, rayPhysicsEnd, nullFilter, localPivot, mOldPickingDistance); if(!body.Empty()) { mPickedBody = body.Get(); diff --git a/examples/chipmunk-physics/README.md b/examples/chipmunk-physics/README.md index 287fa27..897d948 100644 --- a/examples/chipmunk-physics/README.md +++ b/examples/chipmunk-physics/README.md @@ -1,7 +1,9 @@ # 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 set of balls which act under gravity +It creates a set of balls which act under gravity, and the letters of the DALi logo that are each "suspended" from +a fixed pivot. Every 7 seconds, a random number of the balls are given a high impulse to bring the whole demo back +to life. ![](./chipmunk.gif) @@ -9,3 +11,4 @@ It creates a set of balls which act under gravity "qe" keys rotate the last touched actor in Z axis "p" key resets the position/forces on the last touched actor to the origin Space key toggles the integration state. +"m" key toggles the debug state diff --git a/examples/chipmunk-physics/dletter.blend b/examples/chipmunk-physics/dletter.blend new file mode 100755 index 0000000..1d5c23a Binary files /dev/null and b/examples/chipmunk-physics/dletter.blend differ diff --git a/examples/chipmunk-physics/letter-a.h b/examples/chipmunk-physics/letter-a.h new file mode 100755 index 0000000..cbac134 --- /dev/null +++ b/examples/chipmunk-physics/letter-a.h @@ -0,0 +1,62 @@ +double letter_a[] = { +0.080334, -0.445639, +-0.050940, -0.447993, +-0.175007, -0.428650, +-0.275208, -0.394296, +-0.349133, -0.348910, +-0.399168, -0.296059, +-0.429146, -0.239705, +-0.444190, -0.184144, +-0.449309, -0.133031, +-0.447807, -0.088260, +-0.441110, -0.049854, +-0.429090, -0.016322, +-0.411267, 0.013977, +-0.387297, 0.042290, +-0.356968, 0.069448, +-0.320038, 0.095734, +-0.276016, 0.120705, +-0.224141, 0.143171, +-0.163786, 0.161366, +-0.096207, 0.173662, +-0.025351, 0.178901, +0.042247, 0.176440, +0.099742, 0.166799, +0.143348, 0.152616, +0.172828, 0.138790, +0.191163, 0.131669, +0.202876, 0.135037, +0.213151, 0.148009, +0.227734, 0.165069, +0.251264, 0.178894, +0.284487, 0.185042, +0.323773, 0.182775, +0.361894, 0.174502, +0.392529, 0.162594, +0.412959, 0.147477, +0.424129, 0.127583, +0.429248, 0.100184, +0.431109, 0.063005, +0.431556, 0.014540, +0.431537, -0.045757, +0.431509, -0.116220, +0.431712, -0.192109, +0.432178, -0.265634, +0.432602, -0.328082, +0.432049, -0.374457, +0.428895, -0.404558, +0.420987, -0.422551, +0.406962, -0.433552, +0.387266, -0.440988, +0.364196, -0.446436, +0.341061, -0.450080, +0.320084, -0.451858, +0.301841, -0.451758, +0.285388, -0.449827, +0.269461, -0.446152, +0.253532, -0.440856, +0.237876, -0.434095, +0.222830, -0.426206, +0.206674, -0.418119, +0.184985, -0.411483, +}; diff --git a/examples/chipmunk-physics/letter-d.h b/examples/chipmunk-physics/letter-d.h new file mode 100755 index 0000000..29f0208 --- /dev/null +++ b/examples/chipmunk-physics/letter-d.h @@ -0,0 +1,64 @@ +double letter_d[] = { +0.131136, -0.445716, +0.210390, -0.423237, +0.262577, -0.399065, +0.303066, -0.375918, +0.337334, -0.354157, +0.351012, -0.340831, +0.375016, -0.322534, +0.396490, -0.293488, +0.416732, -0.270408, +0.434497, -0.237234, +0.452636, -0.199979, +0.462341, -0.155056, +0.466712, -0.072655, +0.468917, 0.030611, +0.469557, 0.141277, +0.468970, 0.241971, +0.466592, 0.321481, +0.463973, 0.370117, +0.449290, 0.412602, +0.430514, 0.435231, +0.405080, 0.449557, +0.375657, 0.458505, +0.345982, 0.463514, +0.318714, 0.465354, +0.294957, 0.464321, +0.274400, 0.460291, +0.256365, 0.453172, +0.240564, 0.443229, +0.227141, 0.431093, +0.216465, 0.417345, +0.208675, 0.401603, +0.203567, 0.382294, +0.200628, 0.356920, +0.199298, 0.324164, +0.199170, 0.285514, +0.200000, 0.245338, +0.201478, 0.209592, +0.202679, 0.182716, +0.201921, 0.166840, +0.196805, 0.161833, +0.184565, 0.165839, +0.162353, 0.175720, +0.127279, 0.187103, +0.077452, 0.195250, +0.014636, 0.197297, +-0.055010, 0.192870, +-0.121485, 0.183899, +-0.176149, 0.172829, +-0.216299, 0.161038, +-0.245481, 0.148720, +-0.271343, 0.135014, +-0.299749, 0.118339, +-0.333036, 0.096502, +-0.370072, 0.066624, +-0.407117, 0.024452, +-0.438623, -0.036298, +-0.457155, -0.123895, +-0.443017, -0.239761, +-0.333914, -0.370416, +-0.238509, -0.415552, +-0.143103, -0.447210, +-0.015264, -0.458859, +}; diff --git a/examples/chipmunk-physics/letter-i.h b/examples/chipmunk-physics/letter-i.h new file mode 100755 index 0000000..974e1ca --- /dev/null +++ b/examples/chipmunk-physics/letter-i.h @@ -0,0 +1,62 @@ +double letter_i[] = { +0.064721, 0.397047, +0.084359, 0.392005, +0.106181, 0.384591, +0.125922, 0.375744, +0.142219, 0.366343, +0.154761, 0.356927, +0.163984, 0.347651, +0.170804, 0.338367, +0.175946, 0.328809, +0.179775, 0.318644, +0.182339, 0.307542, +0.177591, 0.258003, +0.148165, 0.224480, +0.111786, 0.209128, +0.092304, 0.197781, +0.091241, 0.194700, +0.110808, 0.181851, +0.144725, 0.163438, +0.168692, 0.140330, +0.174015, 0.027886, +0.174833, -0.060661, +0.175642, -0.162698, +0.176388, -0.255385, +0.176999, -0.322609, +0.177447, -0.361523, +0.176470, -0.404438, +0.156498, -0.440912, +0.128113, -0.461851, +0.079571, -0.474461, +0.032029, -0.476380, +-0.006020, -0.470540, +-0.051020, -0.453217, +-0.078452, -0.436259, +-0.088338, -0.425531, +-0.099007, -0.405238, +-0.104707, -0.324290, +-0.104555, -0.251683, +-0.104249, -0.160428, +-0.103978, -0.069679, +-0.103846, 0.002851, +-0.103784, 0.050585, +-0.103546, 0.078313, +-0.101804, 0.106063, +-0.086488, 0.143888, +-0.047079, 0.166131, +-0.007868, 0.197018, +-0.056347, 0.222110, +-0.084005, 0.244999, +-0.094406, 0.286331, +-0.090557, 0.322635, +-0.086423, 0.332826, +-0.081092, 0.342019, +-0.074727, 0.350617, +-0.067183, 0.359181, +-0.057354, 0.368154, +-0.043032, 0.377802, +-0.021385, 0.387927, +0.009406, 0.396920, +0.051950, 0.399662, + +}; diff --git a/examples/chipmunk-physics/letter-l.h b/examples/chipmunk-physics/letter-l.h new file mode 100755 index 0000000..6abff43 --- /dev/null +++ b/examples/chipmunk-physics/letter-l.h @@ -0,0 +1,37 @@ +double letter_l[] = { +-0.105263, -0.207440, +-0.108182, 0.173937, +-0.109280, 0.299948, +-0.109283, 0.340490, +-0.105907, 0.372182, +-0.104059, 0.380107, +-0.091231, 0.409253, +-0.069112, 0.431754, +-0.039130, 0.446449, +-0.005093, 0.454614, +0.029018, 0.457917, +0.060424, 0.457140, +0.087614, 0.452122, +0.110104, 0.442246, +0.127851, 0.427662, +0.141076, 0.409636, +0.150263, 0.390488, +0.156066, 0.372701, +0.159670, 0.354752, +0.160219, 0.303937, +0.160569, 0.152952, +0.160810, 0.034914, +0.160790, -0.095764, +0.160217, -0.214607, +0.158889, -0.304397, +0.156737, -0.360039, +0.150208, -0.401271, +0.124974, -0.427020, +0.078909, -0.447270, +0.052876, -0.452784, +0.038706, -0.454157, +-0.024785, -0.446256, +-0.075312, -0.415388, +-0.091657, -0.396699, +-0.103874, -0.371529, +}; diff --git a/examples/chipmunk-physics/physics-demo-controller.cpp b/examples/chipmunk-physics/physics-demo-controller.cpp index 6baf71b..23d6499 100644 --- a/examples/chipmunk-physics/physics-demo-controller.cpp +++ b/examples/chipmunk-physics/physics-demo-controller.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -#include #include +#include #include #include @@ -23,9 +23,14 @@ #include #include +#include #include #include -#include +#include "letter-a.h" +#include "letter-d.h" +#include "letter-i.h" +#include "letter-l.h" +#include "split-letter-d.h" using namespace Dali; using namespace Dali::Toolkit::Physics; @@ -34,8 +39,7 @@ using namespace Dali::Toolkit::Physics; Debug::Filter* gPhysicsDemo = Debug::Filter::New(Debug::Concise, false, "LOG_PHYSICS_EXAMPLE"); #endif -#define GRABBABLE_MASK_BIT (1u << 31) -cpShapeFilter NOT_GRABBABLE_FILTER = {CP_NO_GROUP, ~GRABBABLE_MASK_BIT, ~GRABBABLE_MASK_BIT}; +const bool DEBUG_STATE{false}; namespace KeyModifier { @@ -53,10 +57,69 @@ enum Key }; } -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 LETTER_IMAGES[4] = { + DEMO_IMAGE_DIR "/dali-logo-d.png", + DEMO_IMAGE_DIR "/dali-logo-a.png", + DEMO_IMAGE_DIR "/dali-logo-l.png", + DEMO_IMAGE_DIR "/dali-logo-i.png"}; + +const std::string BRICK_WALL = DEMO_IMAGE_DIR "/brick-wall.jpg"; +const std::string BALL_IMAGE = DEMO_IMAGE_DIR "/blocks-ball.png"; + +#if defined(_ARCH_ARM_) +#define DEMO_ICON_DIR "/usr/share/icons" +#else +#define DEMO_ICON_DIR DEMO_IMAGE_DIR +#endif + +const std::string BALL_IMAGES[] = {DEMO_IMAGE_DIR "/blocks-ball.png", + DEMO_ICON_DIR "/dali-tests.png", + DEMO_ICON_DIR "/dali-examples.png", + DEMO_ICON_DIR "/com.samsung.dali-demo.png"}; + +const std::string LOGO = DEMO_IMAGE_DIR "/Logo-for-demo.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"}; + 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"}; + +using Verts = double*; + +const Verts LETTER_VERTICES[] = {&letter_d0[0], &letter_d1[0], &letter_a[0], &letter_l[0], &letter_i[0]}; +//const Verts LETTER_VERTS[4] = {&letter_d[0], &letter_a[0], &letter_l[0], &letter_i[0]}; +const size_t NUMBER_OF_VERTICES[] = { + sizeof(letter_d0) / (2 * sizeof(double)), + sizeof(letter_d1) / (2 * sizeof(double)), + sizeof(letter_a) / (2 * sizeof(double)), + sizeof(letter_l) / (2 * sizeof(double)), + sizeof(letter_i) / (2 * sizeof(double))}; + +// Indexed by letter - index into VERTICES / NUMBER_OF_VERTICES arrays +const std::vector LETTER_SHAPE_INDEXES[]{{0, 1}, {2}, {3}, {4}}; + +// Groups that can collide with each other: +const cpGroup BALL_GROUP{1 << 0}; +const cpGroup LETTER_GROUP_1{1 << 1}; +const cpGroup LETTER_GROUP_2{1 << 2}; +const cpGroup LETTER_GROUP_3{1 << 3}; +const cpGroup LETTER_GROUP_4{1 << 4}; +const cpGroup BOUNDS_GROUP{1 << 5}; + +const cpBitmask COLLISION_MASK{0x3F}; + +const cpBitmask BALL_COLLIDES_WITH{BALL_GROUP | LETTER_GROUP_1 | LETTER_GROUP_2 | LETTER_GROUP_3 | LETTER_GROUP_4 | BOUNDS_GROUP}; +const cpBitmask LETTER_1_COLLIDES_WITH{BALL_GROUP | LETTER_GROUP_2 | BOUNDS_GROUP}; +const cpBitmask LETTER_2_COLLIDES_WITH{BALL_GROUP | LETTER_GROUP_1 | LETTER_GROUP_3}; +const cpBitmask LETTER_3_COLLIDES_WITH{BALL_GROUP | LETTER_GROUP_2 | LETTER_GROUP_4}; +const cpBitmask LETTER_4_COLLIDES_WITH{BALL_GROUP | LETTER_GROUP_3 | BOUNDS_GROUP}; + +static cpFloat SpringForce(cpConstraint* spring, cpFloat distance) +{ + cpFloat clamp = 20.0f; + return cpfclamp(cpDampedSpringGetRestLength(spring) - distance, -clamp, clamp) * + cpDampedSpringGetStiffness(spring); +} /** * @brief The physics demo using Chipmunk2D APIs. @@ -92,61 +155,189 @@ public: 0.0f)); mPhysicsAdaptor = PhysicsAdaptor::New(mPhysicsTransform, windowSize); - mPhysicsRoot = mPhysicsAdaptor.GetRootActor(); + mPhysicsRoot = mPhysicsAdaptor.GetRootActor(); mPhysicsRoot.TouchedSignal().Connect(this, &PhysicsDemoController::OnTouched); mWindow.Add(mPhysicsRoot); + mPopcornTimer = Timer::New(7000); + mPopcornTimer.TickSignal().Connect(this, &PhysicsDemoController::OnPopcornTick); + mPopcornTimer.Start(); - auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); - cpSpace* space = scopedAccessor->GetNative().Get(); + auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); + cpSpace* space = scopedAccessor->GetNative().Get(); CreateBounds(space, windowSize); + // Ball area = 2*PI*26^2 ~= 6.28*26*26 ~= 5400 - // Fill quarter of the screen... + // Fill top quarter of the screen... int numBalls = 10 + windowSize.GetWidth() * windowSize.GetHeight() / 20000; for(int i = 0; i < numBalls; ++i) { - CreateBall(space); + mBalls.push_back(CreateBall(space)); } + //AddSprings(space); + //CreateLogo(space); + CreateLetters(space); // For funky mouse drag mMouseBody = cpBodyNewKinematic(); // Mouse actor is a kinematic body that is not integrated // Process any async queued methods next frame mPhysicsAdaptor.CreateSyncPoint(); + + if(DEBUG_STATE) + { + mPhysicsDebugLayer = mPhysicsAdaptor.CreateDebugLayer(mWindow); + mPhysicsAdaptor.SetDebugState(PhysicsAdaptor::DebugState::ON); + } } - void CreateBall(cpSpace* space) + PhysicsActor CreateBall(cpSpace* space) { const float BALL_MASS = 10.0f; - const float BALL_RADIUS = 26.0f; + const float BALL_RADIUS = 13.0f; const float BALL_ELASTICITY = 0.5f; const float BALL_FRICTION = 0.5f; - auto ball = Toolkit::ImageView::New(BALL_IMAGE); - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(BALL_MASS, cpMomentForCircle(BALL_MASS, 0.0f, BALL_RADIUS, cpvzero))); + auto ball = Toolkit::ImageView::New(BALL_IMAGES[rand() % 4]); + ball[Actor::Property::NAME] = "Ball"; + ball[Actor::Property::SIZE] = Vector2(26, 26); // Halve the image size + cpBody* body = cpSpaceAddBody(space, cpBodyNew(BALL_MASS, cpMomentForCircle(BALL_MASS, 0.0f, BALL_RADIUS, cpvzero))); cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, BALL_RADIUS, cpvzero)); cpShapeSetElasticity(shape, BALL_ELASTICITY); cpShapeSetFriction(shape, BALL_FRICTION); - + //cpShapeSetFilter(shape, cpShapeFilterNew(BALL_GROUP, BALL_COLLIDES_WITH, COLLISION_MASK)); ball.RegisterProperty("uBrightness", 0.0f); PhysicsActor physicsBall = mPhysicsAdaptor.AddActorBody(ball, body); - Window::WindowSize windowSize = mWindow.GetSize(); + Window::WindowSize windowSize = mWindow.GetSize(); - const float fw = 0.5f*(windowSize.GetWidth() - BALL_RADIUS); - const float fh = 0.5f*(windowSize.GetHeight() - BALL_RADIUS); + const float fw = 0.5f * (windowSize.GetWidth() - BALL_RADIUS); + const float fh = 0.5f * (windowSize.GetHeight() - BALL_RADIUS); // Example of setting physics property on update thread - physicsBall.AsyncSetPhysicsPosition(Vector3(Random::Range(-fw, fw), Random::Range(-fh, fh), 0.0f)); + physicsBall.AsyncSetPhysicsPosition(Vector3(Random::Range(-fw, fw), Random::Range(-fh, -fh * 0.5), 0.0f)); // Example of queuing a chipmunk method to run on the update thread - mPhysicsAdaptor.Queue([body](){ + mPhysicsAdaptor.Queue([body]() { cpBodySetVelocity(body, cpv(Random::Range(-100.0, 100.0), Random::Range(-100.0, 100.0))); }); + return physicsBall; + } + + void CreateLogo(cpSpace* space) + { + const float MASS = 20.0f; + auto logo = Toolkit::ImageView::New(LOGO); + Vector2 logoSize{368, 208}; + logo[Actor::Property::SIZE] = logoSize; // Double in size + + cpBody* logoBody = cpSpaceAddBody(space, cpBodyNew(MASS, cpMomentForBox(MASS, logoSize.width, logoSize.height))); + cpShape* logoShape = cpSpaceAddShape(space, cpBoxShapeNew(logoBody, logoSize.width, logoSize.height, 0.0)); + PhysicsActor logoActor = mPhysicsAdaptor.AddActorBody(logo, logoBody); + + cpShapeSetFriction(logoShape, 0.9); + cpShapeSetElasticity(logoShape, 0.0); + Window::WindowSize windowSize = mWindow.GetSize(); + Vector3 daliPos(0, -windowSize.GetHeight() / 2 + logoSize.height * 1.3, 0); + Vector3 physPos = mPhysicsAdaptor.TranslateToPhysicsSpace(daliPos); + cpBodySetPosition(logoBody, cpv(physPos.x, physPos.y)); + + cpBody* staticBody = cpSpaceGetStaticBody(space); + cpConstraint* spring = NewSpring(staticBody, logoBody, cpv(0, 0), cpv(0, logoSize.height / 2)); + cpSpaceAddConstraint(space, spring); + } + + void CreateLetters(cpSpace* space) + { + const float LETTER_MASS = 10.0f; + const float RADIUS = 85.0f; + const float ELASTICITY = 0.0f; + const float FRICTION = 0.9f; + + static const cpShapeFilter FILTERS[4] = { + cpShapeFilterNew(LETTER_GROUP_1, LETTER_1_COLLIDES_WITH, COLLISION_MASK), + cpShapeFilterNew(LETTER_GROUP_2, LETTER_2_COLLIDES_WITH, COLLISION_MASK), + cpShapeFilterNew(LETTER_GROUP_3, LETTER_3_COLLIDES_WITH, COLLISION_MASK), + cpShapeFilterNew(LETTER_GROUP_4, LETTER_4_COLLIDES_WITH, COLLISION_MASK)}; + + static const std::string NAME[4] = {"d", "a", "l", "i"}; + for(int index = 0; index < 4; ++index) + { + auto letter = Toolkit::ImageView::New(LETTER_IMAGES[index]); + letter[Actor::Property::NAME] = NAME[index]; + + cpBody* body = cpSpaceAddBody(space, cpBodyNew(LETTER_MASS, cpMomentForCircle(LETTER_MASS, 0.0f, RADIUS, cpvzero))); + + for(size_t letterShapeIndex = 0; letterShapeIndex < LETTER_SHAPE_INDEXES[index].size(); ++letterShapeIndex) + { + size_t shapeIndex = LETTER_SHAPE_INDEXES[index][letterShapeIndex]; + + std::vector scaledVerts; + size_t numberOfElements = NUMBER_OF_VERTICES[shapeIndex]; + scaledVerts.resize(numberOfElements); + for(size_t i = 0; i < numberOfElements; ++i) + { + double x = LETTER_VERTICES[shapeIndex][i * 2 + 0]; + double y = LETTER_VERTICES[shapeIndex][i * 2 + 1]; + scaledVerts[i] = cpv(x * 122.0f, y * 171.0f); // Verts are normalized to +-0.5 + } + cpFloat bevel = 1.0; + + cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew(body, numberOfElements, &scaledVerts[0], cpTransformIdentity, bevel)); + cpShapeSetElasticity(shape, ELASTICITY); + cpShapeSetFriction(shape, FRICTION); + cpShapeSetFilter(shape, FILTERS[index]); + } + + PhysicsActor physicsLetter = mPhysicsAdaptor.AddActorBody(letter, body); + + Window::WindowSize windowSize = mWindow.GetSize(); + + // Image is 326x171; center of letter is guessed; each image contains only 1 image. + // Position the letters into the window + + float cellW = (windowSize.GetWidth() - 170) / 4; + float cellC = -windowSize.GetWidth() * 0.5f + cellW * (0.5f + index); + float x = 85 + cellC; // - 61.0f; + Vector3 physPos = mPhysicsAdaptor.TranslateToPhysicsSpace(Vector3(x, 0, 0.0f)); + + // Have to set position before setting constraint + cpBodySetPosition(body, cpv(physPos.x, physPos.y)); + + // Add a fixed pivot at top of shape + cpBody* staticBody = cpSpaceGetStaticBody(space); + + Vector3 localPivot(x, -70.0f, 0.0f); + Vector3 pivotPhys = mPhysicsAdaptor.TranslateToPhysicsSpace(localPivot); + cpSpaceAddConstraint(space, cpPivotJointNew(staticBody, body, cpv(pivotPhys.x, pivotPhys.y))); + } + } + + cpConstraint* NewSpring(cpBody* body1, cpBody* body2, cpVect anchor1, cpVect anchor2) + { + const cpFloat STIFFNESS{100.0f}; + const cpFloat DAMPING{0.5f}; + cpConstraint* spring = cpDampedSpringNew(body1, body2, anchor1, anchor2, 0.0f, STIFFNESS, DAMPING); + cpDampedSpringSetSpringForceFunc(spring, SpringForce); + return spring; + } + + void AddSprings(cpSpace* space) + { + int N = mBalls.size(); + int randValue = 3 + rand() % (N / 4); // Some number of pairs + for(int i = 0; i < randValue; ++i) + { + int randIndex = rand() % N; + cpBody* body1 = mBalls[randIndex].GetBody().Get(); + cpBody* body2 = mBalls[(randIndex + 1) % N].GetBody().Get(); + + cpConstraint* spring = NewSpring(body1, body2, cpv(25, 0), cpv(-25, 0)); + cpSpaceAddConstraint(space, spring); + } } void CreateBounds(cpSpace* space, Window::WindowSize size) @@ -180,7 +371,7 @@ public: cpShapeSetElasticity(shape, 1.0f); cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); + cpShapeSetFilter(shape, cpShapeFilterNew(BOUNDS_GROUP, COLLISION_MASK, COLLISION_MASK)); return shape; } @@ -209,12 +400,30 @@ public: void OnWindowResize(Window window, Window::WindowSize newSize) { - auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); - cpSpace* space = scopedAccessor->GetNative().Get(); + auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); + cpSpace* space = scopedAccessor->GetNative().Get(); CreateBounds(space, newSize); } + bool OnPopcornTick() + { + auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); + + // fire off N random balls upwards with a high impulse + int N = mBalls.size(); + int randValue = 10 + rand() % (N / 2); + + for(int i = 0; i < randValue; ++i) + { + int randIndex = rand() % N; + cpBody* body = mBalls[randIndex].GetBody().Get(); + cpBodyActivate(body); + cpBodyApplyImpulseAtLocalPoint(body, cpv(rand() % 200 - 100, -10000), cpv(0, 25)); + } + return true; + } + bool OnTouched(Dali::Actor actor, const Dali::TouchEvent& touch) { static enum { @@ -225,7 +434,7 @@ public: auto renderTask = mWindow.GetRenderTaskList().GetTask(0); auto screenCoords = touch.GetScreenPosition(0); // In this demo, physics space is equivalent to screen space with y inverted - auto windowSize = mWindow.GetSize(); + auto windowSize = mWindow.GetSize(); Vector3 rayPhysicsOrigin(screenCoords.x, windowSize.GetHeight() - screenCoords.y, 0.0f); switch(state) @@ -236,17 +445,24 @@ public: { state = MovePivot; - auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); - cpSpace* space = scopedAccessor->GetNative().Get(); + auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); + cpSpace* space = scopedAccessor->GetNative().Get(); Vector3 localPivot; float pickingDistance; - auto body = scopedAccessor->HitTest(rayPhysicsOrigin, rayPhysicsOrigin, localPivot, pickingDistance); + cpShapeFilter ballFilter{CP_NO_GROUP, 1u << 31, 1u << 31}; + auto body = scopedAccessor->HitTest(rayPhysicsOrigin, rayPhysicsOrigin, ballFilter, localPivot, pickingDistance); + if(body.Empty()) + { + cpShapeFilter letterFilter{CP_NO_GROUP, COLLISION_MASK, COLLISION_MASK}; + body = scopedAccessor->HitTest(rayPhysicsOrigin, rayPhysicsOrigin, letterFilter, localPivot, pickingDistance); + } if(!body.Empty()) { - mPickedBody = body.Get(); + mPickedBody = body.Get(); mSelectedActor = mPhysicsAdaptor.GetPhysicsActor(mPickedBody); + std::cout << "PhysicsActor: " << mPhysicsAdaptor.GetRootActor().FindChildById(mSelectedActor.GetId()).GetProperty(Actor::Property::NAME) << std::endl; mPickedSavedState = cpBodyIsSleeping(mPickedBody); cpBodyActivate(mPickedBody); @@ -273,8 +489,8 @@ public: { if(mPickedConstraint) { - auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); - cpSpace* space = scopedAccessor->GetNative().Get(); + auto scopedAccessor = mPhysicsAdaptor.GetPhysicsAccessor(); + cpSpace* space = scopedAccessor->GetNative().Get(); if(mPickedSavedState) { @@ -296,7 +512,6 @@ public: } } - Stage::GetCurrent().KeepRendering(30.0f); return true; @@ -305,6 +520,7 @@ public: void OnKeyEv(const Dali::KeyEvent& event) { static bool integrateState{true}; + static bool debugState{DEBUG_STATE}; if(event.GetState() == KeyEvent::DOWN) { @@ -336,11 +552,17 @@ public: } else if(!event.GetKeyString().compare(" ")) { - integrateState = true^integrateState; - mPhysicsAdaptor.SetIntegrationState(integrateState? - PhysicsAdaptor::IntegrationState::ON: - PhysicsAdaptor::IntegrationState::OFF); - + integrateState = true ^ integrateState; + mPhysicsAdaptor.SetIntegrationState(integrateState ? PhysicsAdaptor::IntegrationState::ON : PhysicsAdaptor::IntegrationState::OFF); + } + else if(!event.GetKeyString().compare("m")) + { + debugState = true ^ debugState; + if(debugState && !mPhysicsDebugLayer) + { + mPhysicsDebugLayer = mPhysicsAdaptor.CreateDebugLayer(mWindow); + } + mPhysicsAdaptor.SetDebugState(debugState ? PhysicsAdaptor::DebugState::ON : PhysicsAdaptor::DebugState::OFF); } else if(!event.GetKeyString().compare("w")) { @@ -391,10 +613,13 @@ public: // Rotate anti-clockwise if(mSelectedActor) { - Quaternion quaternion = mSelectedActor.GetActorRotation(); - quaternion *= Quaternion(Degree(-15.0f), Vector3::ZAXIS); - mSelectedActor.AsyncSetPhysicsRotation(quaternion); - cpBody* body = mSelectedActor.GetBody().Get(); + // A negative angle should rotate anti-clockwise, which it does, + // BUT, we mirror in Y axis, so actually, it LOOKS like it rotates clockwise. + // So, we have to invert angle. + + cpBody* body = mSelectedActor.GetBody().Get(); + float angle = cpBodyGetAngle(body); + mPhysicsAdaptor.Queue([body, angle]() { cpBodySetAngle(body, angle + Math::PI / 12.0f); }); mPhysicsAdaptor.Queue([body]() { cpBodyActivate(body); }); mPhysicsAdaptor.CreateSyncPoint(); } @@ -404,9 +629,9 @@ public: // Rotate clockwise using native physics APIs if(mSelectedActor) { - cpBody* body = mSelectedActor.GetBody().Get(); - float angle = cpBodyGetAngle(body); - mPhysicsAdaptor.Queue([body, angle]() { cpBodySetAngle(body, angle-Math::PI/12.0f); }); + cpBody* body = mSelectedActor.GetBody().Get(); + float angle = cpBodyGetAngle(body); + mPhysicsAdaptor.Queue([body, angle]() { cpBodySetAngle(body, angle - Math::PI / 12.0f); }); mPhysicsAdaptor.Queue([body]() { cpBodyActivate(body); }); mPhysicsAdaptor.CreateSyncPoint(); } @@ -445,14 +670,19 @@ private: Application& mApplication; Window mWindow; - PhysicsAdaptor mPhysicsAdaptor; - PhysicsActor mSelectedActor; - Matrix mPhysicsTransform; - Actor mPhysicsRoot; - cpBody* mMouseBody{nullptr}; - cpBody* mPickedBody{nullptr}; - cpConstraint* mPickedConstraint{nullptr}; - int mPickedSavedState = -1; /// 0 : Active, 1 : Sleeping + PhysicsAdaptor mPhysicsAdaptor; + PhysicsActor mSelectedActor; + std::vector mBalls; + Matrix mPhysicsTransform; + Actor mPhysicsRoot; + Layer mPhysicsDebugLayer; + cpBody* mMouseBody{nullptr}; + cpBody* mPickedBody{nullptr}; + cpConstraint* mPickedConstraint{nullptr}; + int mPickedSavedState = -1; /// 0 : Active, 1 : Sleeping + Timer mPopcornTimer; + + PhysicsAdaptor::DebugState mDebugState{PhysicsAdaptor::DebugState::OFF}; cpShape* mLeftBound{nullptr}; cpShape* mRightBound{nullptr}; diff --git a/examples/chipmunk-physics/split-letter-d.h b/examples/chipmunk-physics/split-letter-d.h new file mode 100644 index 0000000..ab0572d --- /dev/null +++ b/examples/chipmunk-physics/split-letter-d.h @@ -0,0 +1,68 @@ +double letter_d0[] = { +0.131136, -0.445716, +0.210390, -0.423237, +0.262577, -0.399065, +0.303066, -0.375918, +0.337334, -0.354157, +0.351012, -0.340831, +0.375016, -0.322534, +0.396490, -0.293488, +0.416732, -0.270408, +0.434497, -0.237234, +0.201921, 0.161833, +0.184565, 0.165839, +0.162353, 0.175720, +0.127279, 0.187103, +0.077452, 0.195250, +0.014636, 0.197297, +-0.055010, 0.192870, +-0.121485, 0.183899, +-0.176149, 0.172829, +-0.216299, 0.161038, +-0.245481, 0.148720, +-0.271343, 0.135014, +-0.299749, 0.118339, +-0.333036, 0.096502, +-0.370072, 0.066624, +-0.407117, 0.024452, +-0.438623, -0.036298, +-0.457155, -0.123895, +-0.443017, -0.239761, +-0.333914, -0.370416, +-0.238509, -0.415552, +-0.143103, -0.447210, +-0.015264, -0.458859, +}; +double letter_d1[] = { +0.201921, 0.166840, +0.202679, 0.182716, +0.201478, 0.209592, +0.200000, 0.245338, +0.199170, 0.285514, +0.199298, 0.324164, +0.200628, 0.356920, +0.203567, 0.382294, +0.208675, 0.401603, +0.216465, 0.417345, +0.227141, 0.431093, +0.240564, 0.443229, +0.256365, 0.453172, +0.274400, 0.460291, +0.294957, 0.464321, +0.318714, 0.465354, +0.345982, 0.463514, +0.375657, 0.458505, +0.405080, 0.449557, +0.430514, 0.435231, +0.449290, 0.412602, +0.463973, 0.370117, +0.466592, 0.321481, +0.468970, 0.241971, +0.469557, 0.141277, +0.468917, 0.030611, +0.466712, -0.072655, +0.462341, -0.155056, +0.452636, -0.199979, +0.434497, -0.237234, +0.201921, 0.161833, +}; diff --git a/resources/images/dali-logo-a.png b/resources/images/dali-logo-a.png new file mode 100644 index 0000000..3e8a377 Binary files /dev/null and b/resources/images/dali-logo-a.png differ diff --git a/resources/images/dali-logo-d.png b/resources/images/dali-logo-d.png new file mode 100644 index 0000000..0153a93 Binary files /dev/null and b/resources/images/dali-logo-d.png differ diff --git a/resources/images/dali-logo-i.png b/resources/images/dali-logo-i.png new file mode 100644 index 0000000..3f5afa5 Binary files /dev/null and b/resources/images/dali-logo-i.png differ diff --git a/resources/images/dali-logo-l.png b/resources/images/dali-logo-l.png new file mode 100644 index 0000000..d57ad58 Binary files /dev/null and b/resources/images/dali-logo-l.png differ