1572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#pragma version(1)
2572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#pragma rs java_package_name(com.example.android.rs.balls)
3572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
4572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include "balls.rsh"
5572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
6572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsfloat2 gGravityVector = {0.f, 9.8f};
7572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
8572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsfloat2 gMinPos = {0.f, 0.f};
9572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsfloat2 gMaxPos = {1280.f, 700.f};
10572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
11572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic float2 touchPos[10];
12572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic float touchPressure[10];
13572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic const float gDT = 1.f / 30.f;
14572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
15572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsrs_allocation gGrid;
16572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsrs_allocation gGridCache;
17572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsrs_allocation gBalls;
18572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
19572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsfloat gScale = 1.f;
20572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
21572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsvoid touch(float x, float y, float pressure, int id) {
22572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (id >= 10) {
23572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        return;
24572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
25572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
26572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    touchPos[id].x = x;
27572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    touchPos[id].y = y;
28572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    touchPressure[id] = pressure;
29572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
30572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
31572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsvoid root(Ball_t *ball, uint32_t x) {
32572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    float2 fv = 0;
33572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    float pressure = 0;
34572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    float2 pos = ball->position;
35572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int2 gridPos[9];
36572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
37572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[0] = convert_int2((ball->position / 100.f) /*- 0.4999f*/);
38572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[1] = (int2){gridPos[0].x - 1, gridPos[0].y - 1};
39572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[2] = (int2){gridPos[0].x + 0, gridPos[0].y - 1};
40572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[3] = (int2){gridPos[0].x + 1, gridPos[0].y - 1};
41572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[4] = (int2){gridPos[0].x - 1, gridPos[0].y};
42572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[5] = (int2){gridPos[0].x + 1, gridPos[0].y};
43572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[6] = (int2){gridPos[0].x - 1, gridPos[0].y + 1};
44572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[7] = (int2){gridPos[0].x + 0, gridPos[0].y + 1};
45572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    gridPos[8] = (int2){gridPos[0].x + 1, gridPos[0].y + 1};
46572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
47572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    for (int gct=0; gct < 9; gct++) {
48572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if ((gridPos[gct].x >= rsAllocationGetDimX(gGrid)) ||
49572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            (gridPos[gct].x < 0) ||
50572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            (gridPos[gct].y >= rsAllocationGetDimY(gGrid)) ||
51572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            (gridPos[gct].y < 0)) {
52572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            continue;
53572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
54572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        //rsDebug("grid ", gridPos[gct]);
55572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        const BallGrid_t *bg = (const BallGrid_t *)rsGetElementAt(gGrid, gridPos[gct].x, gridPos[gct].y);
56572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
57572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        for (int cidx = 0; cidx < bg->count; cidx++) {
58572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            float2 bcptr = rsGetElementAt_float2(gGridCache, bg->cacheIdx + cidx);
59572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            float2 vec = bcptr - pos;
60572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            float2 vec2 = vec * vec;
61572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            float len2 = vec2.x + vec2.y;
62572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
63811fe009f3db9a7cdc7a8797d31d1a067406860dJason Sams            if ((len2 < 10000.f) && (len2 > 0.001f)) {
64811fe009f3db9a7cdc7a8797d31d1a067406860dJason Sams                float len = rsqrt(len2 + 4.f);
65811fe009f3db9a7cdc7a8797d31d1a067406860dJason Sams                float f = (len * len * len) * 20000.f;
66811fe009f3db9a7cdc7a8797d31d1a067406860dJason Sams                fv -= vec * f;
67811fe009f3db9a7cdc7a8797d31d1a067406860dJason Sams                pressure += f;
68572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            }
69572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
70572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
71572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
72572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    //fv /= ball->size * ball->size * ball->size;
73572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    fv -= gGravityVector * 4.f * gScale;
74572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    fv *= gDT;
75572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
76572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    for (int i=0; i < 10; i++) {
77572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if (touchPressure[i] > 0.1f) {
78572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            float2 vec = touchPos[i] - ball->position;
79572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            float2 vec2 = vec * vec;
80572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            float len2 = max(2.f, vec2.x + vec2.y);
81572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            float2 pfv = (vec / len2) * touchPressure[i] * 500.f * gScale;
82572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            pressure += length(pfv);
83572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            fv -= pfv;
84572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
85572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
86572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
87572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    ball->delta = (ball->delta * (1.f - 0.008f)) + fv;
88572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    ball->position = ball->position + (ball->delta * gDT);
89572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
90572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    const float wallForce = 400.f * gScale;
91572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (ball->position.x > (gMaxPos.x - 20.f)) {
92572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        float d = gMaxPos.x - ball->position.x;
93572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if (d < 0.f) {
94572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            if (ball->delta.x > 0) {
95572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams                ball->delta.x *= -0.7f;
96572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            }
97572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            ball->position.x = gMaxPos.x - 1.f;
98572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        } else {
99572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            ball->delta.x -= min(wallForce / (d * d), 10.f);
100572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
101572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
102572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
103572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (ball->position.x < (gMinPos.x + 20.f)) {
104572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        float d = ball->position.x - gMinPos.x;
105572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if (d < 0.f) {
106572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            if (ball->delta.x < 0) {
107572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams                ball->delta.x *= -0.7f;
108572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            }
109572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            ball->position.x = gMinPos.x + 1.f;
110572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        } else {
111572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            ball->delta.x += min(wallForce / (d * d), 10.f);
112572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
113572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
114572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
115572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (ball->position.y > (gMaxPos.y - 20.f)) {
116572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        float d = gMaxPos.y - ball->position.y;
117572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if (d < 0.f) {
118572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            if (ball->delta.y > 0) {
119572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams                ball->delta.y *= -0.7f;
120572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            }
121572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            ball->position.y = gMaxPos.y - 1.f;
122572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        } else {
123572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            ball->delta.y -= min(wallForce / (d * d), 10.f);
124572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
125572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
126572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
127572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (ball->position.y < (gMinPos.y + 20.f)) {
128572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        float d = ball->position.y - gMinPos.y;
129572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if (d < 0.f) {
130572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            if (ball->delta.y < 0) {
131572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams                ball->delta.y *= -0.7f;
132572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            }
133572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            ball->position.y = gMinPos.y + 1.f;
134572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        } else {
135572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            ball->delta.y += min(wallForce / (d * d * d), 10.f);
136572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
137572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
138572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
139572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    // low pressure ~500, high ~2500
140811fe009f3db9a7cdc7a8797d31d1a067406860dJason Sams    pressure *= 12.f;
141572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    ball->pressure = pressure;
142572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
143572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    //rsDebug("p ", pressure);
144572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
145572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    float4 color = 1.f;
146572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    color.r = pow(pressure, 0.25f) / 12.f;
147572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    color.b = 1.f - color.r;
148572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    color.g = sin(pressure / 1500.f * 3.14f);
149572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    color.rgb = max(color.rgb, (float3)0);
150572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    color.rgb = normalize(color.rgb);
151572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    ball->color = rsPackColorTo8888(color);
152572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
153572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    //rsDebug("physics pos out", ball->position);
154572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
155572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
156