#version 450 #extension GL_GOOGLE_include_directive : require layout(local_size_x = 64) in; #include "rigid_common.glsl" // Once per frame: sleeping (resting bodies stop being simulated, sleeping ones re-check their support), and the entity's position and angle. layout(std430, set = 0, binding = 27) buffer Edits { ivec4 ehead; vec4 ee[512]; }; // cell edits: the flames of a burning corpse void main() { uint bi = gl_GlobalInvocationID.x; if (int(bi) >= bhdr.x) return; Body B = bodies[bi]; if ((B.i.z & B_REMOVED) != 0) return; int s = B.i.x; int nS = shi(s, 4); vec2 com = vec2(shf(s, 5), shf(s, 6)); float c = cos(B.p.z), sn = sin(B.p.z); if ((B.i.z & 8) != 0) { // simulated on the CPU (src/phys): the sleep state comes from there } else if ((B.i.z & B_ASLEEP) != 0) { B.q.w += 1.0; if (B.q.w >= 12.0) { // re-check the support now and then B.q.w = 0.0; bool supported = false; for (int k = 0; k < nS && !supported; ++k) { vec2 r = rot2(c, sn, sample_of(s, k)); supported = solid_at(ivec2(floor(B.p.x + r.x), floor(B.p.y + r.y + 1.5))); } if (!supported) { B.i.z &= ~B_ASLEEP; B.i.w = 0; } } } else { // 009be020: the sleep timer counts while the velocity stays under the tolerances (0.01 units per second linear, 2 degrees per second angular; pixels per frame at scale 10); a body // sleeps when it has been quiet for half a second AND every body joined to it has too (the island's minimum timer) const bool quiet = length(B.v.xy) < 0.01 * 10.0 / 60.0 && abs(B.p.w) < 0.034906585 / 60.0; B.i.w = quiet ? B.i.w + 1 : 0; if (B.i.w >= 30) { bool island = true; for (int k = 0; k < 4 && island; ++k) { const int j = B.jn[k]; if (j < 0) continue; const Body C = bodies[j]; if ((C.i.z & B_REMOVED) != 0 || (C.i.z & B_ASLEEP) != 0) continue; island = C.i.w >= 30; } if (island) { B.i.z |= B_ASLEEP; B.v.xy = vec2(0.0); B.p.w = 0.0; B.i.w = 0; } } B.l = vec4(B.p.xy, B.p.z, 0.0); } if (B.m.z > 0.0) { // a burning corpse part: flames now and then, water puts it out (the pixels of burnable props burn in rigid_burn.comp) B.m.z -= 1.0; ivec2 cc = ivec2(floor(B.p.xy)) - ivec2(pc.view_x, pc.view_y); if (cc.x >= 0 && cc.y >= 0 && cc.x < pc.gw && cc.y < pc.gh) { uint cm = cell_mat(cells[cc.y * pc.gw + cc.x]); if (cm != 0u && ((mats[3u * cm + 2u].z >> 18) & 1u) != 0u) B.m.z = 0.0; } if (B.m.z > 0.0 && (hash3(bi, uint(pc.frame), 17u) & 3u) == 0u) { uint ei = uint(atomicAdd(ehead.x, 1)); vec2 fp = B.p.xy + vec2(0.0, -1.0); if (ei < 256u) { ee[2u * ei] = vec4(fp, 1.5, 0.0); ee[2u * ei + 1u] = vec4(1.0, float(mats[mats.length() - 1u].x), 0.45, 0.0); } } } bodies[bi] = B; if (B.i.y >= 0) { vec2 d = rot2(c, sn, B.q.xy - com); ents[B.i.y].a = vec4(B.p.xy + d, B.p.z, 0.0); } }