| #pragma version(1) |
| #pragma rs java_package_name(com.example.android.rs.balls) |
| |
| #include "balls.rsh" |
| |
| float2 gGravityVector = {0.f, 9.8f}; |
| |
| float2 gMinPos = {0.f, 0.f}; |
| float2 gMaxPos = {1280.f, 700.f}; |
| |
| static float2 touchPos[10]; |
| static float touchPressure[10]; |
| |
| void touch(float x, float y, float pressure, int id) { |
| if (id >= 10) { |
| return; |
| } |
| |
| touchPos[id].x = x; |
| touchPos[id].y = y; |
| touchPressure[id] = pressure; |
| } |
| |
| void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint32_t x) { |
| float2 fv = {0, 0}; |
| float2 pos = ballIn->position; |
| |
| int arcID = -1; |
| float arcInvStr = 100000; |
| |
| const Ball_t * bPtr = rsGetElementAt(ctl->ain, 0); |
| for (uint32_t xin = 0; xin < ctl->dimX; xin++) { |
| float2 vec = bPtr[xin].position - pos; |
| float2 vec2 = vec * vec; |
| float len2 = vec2.x + vec2.y; |
| |
| if (len2 < 10000) { |
| //float minDist = ballIn->size + bPtr[xin].size; |
| float forceScale = ballIn->size * bPtr[xin].size; |
| forceScale *= forceScale; |
| |
| if (len2 > 16 /* (minDist*minDist)*/) { |
| // Repulsion |
| float len = sqrt(len2); |
| fv -= (vec / (len * len * len)) * 20000.f * forceScale; |
| } else { |
| if (len2 < 1) { |
| if (xin == x) { |
| continue; |
| } |
| ballOut->delta = 0.f; |
| ballOut->position = ballIn->position; |
| if (xin > x) { |
| ballOut->position.x += 1.f; |
| } else { |
| ballOut->position.x -= 1.f; |
| } |
| //ballOut->color.rgb = 1.f; |
| //ballOut->arcID = -1; |
| //ballOut->arcStr = 0; |
| return; |
| } |
| // Collision |
| float2 axis = normalize(vec); |
| float e1 = dot(axis, ballIn->delta); |
| float e2 = dot(axis, bPtr[xin].delta); |
| float e = (e1 - e2) * 0.45f; |
| if (e1 > 0) { |
| fv -= axis * e; |
| } else { |
| fv += axis * e; |
| } |
| } |
| } |
| } |
| |
| fv /= ballIn->size * ballIn->size * ballIn->size; |
| fv -= gGravityVector * 4.f; |
| fv *= ctl->dt; |
| |
| for (int i=0; i < 10; i++) { |
| if (touchPressure[i] > 0.1f) { |
| float2 vec = touchPos[i] - ballIn->position; |
| float2 vec2 = vec * vec; |
| float len2 = max(2.f, vec2.x + vec2.y); |
| fv -= (vec / len2) * touchPressure[i] * 300.f; |
| } |
| } |
| |
| ballOut->delta = (ballIn->delta * (1.f - 0.004f)) + fv; |
| ballOut->position = ballIn->position + (ballOut->delta * ctl->dt); |
| |
| const float wallForce = 400.f; |
| if (ballOut->position.x > (gMaxPos.x - 20.f)) { |
| float d = gMaxPos.x - ballOut->position.x; |
| if (d < 0.f) { |
| if (ballOut->delta.x > 0) { |
| ballOut->delta.x *= -0.7; |
| } |
| ballOut->position.x = gMaxPos.x; |
| } else { |
| ballOut->delta.x -= min(wallForce / (d * d), 10.f); |
| } |
| } |
| |
| if (ballOut->position.x < (gMinPos.x + 20.f)) { |
| float d = ballOut->position.x - gMinPos.x; |
| if (d < 0.f) { |
| if (ballOut->delta.x < 0) { |
| ballOut->delta.x *= -0.7; |
| } |
| ballOut->position.x = gMinPos.x + 1.f; |
| } else { |
| ballOut->delta.x += min(wallForce / (d * d), 10.f); |
| } |
| } |
| |
| if (ballOut->position.y > (gMaxPos.y - 20.f)) { |
| float d = gMaxPos.y - ballOut->position.y; |
| if (d < 0.f) { |
| if (ballOut->delta.y > 0) { |
| ballOut->delta.y *= -0.7; |
| } |
| ballOut->position.y = gMaxPos.y; |
| } else { |
| ballOut->delta.y -= min(wallForce / (d * d), 10.f); |
| } |
| } |
| |
| if (ballOut->position.y < (gMinPos.y + 20.f)) { |
| float d = ballOut->position.y - gMinPos.y; |
| if (d < 0.f) { |
| if (ballOut->delta.y < 0) { |
| ballOut->delta.y *= -0.7; |
| } |
| ballOut->position.y = gMinPos.y + 1.f; |
| } else { |
| ballOut->delta.y += min(wallForce / (d * d * d), 10.f); |
| } |
| } |
| |
| ballOut->size = ballIn->size; |
| |
| //rsDebug("physics pos out", ballOut->position); |
| } |
| |