// function used to go from int distances to float and then back // when finding distance to an individual polygon Distance3i distance_trianglei(const int3 p, const int3* poly) { float3 poly_float3[3]; for (int i = 0; i < 3; ++i) { /* poly_float3[i] = (float3)(poly[i].x, poly[i].y, poly[i].z); */ poly_float3[i] = convert_float3(poly[i]); } Distance3f d = /* distance_trianglef((float3)(p.x, p.y, p.z), poly_float3); */ distance_trianglef(convert_float3(p), poly_float3); return make_dist3( // convert_int_rte(d.d), // convert_int3_rte(d.p)); convert_int(d.d), convert_int3(d.p)); }
Distance3i distance_geom3( const int3 p, global const int* geometry, global const int3* verts) { // Distance3i best = { INT_MAX, (int3)(0, 0, 0) }; Distance3i best = { INT_MAX, make_int3(0, 0, 0) }; const int num_tris = geometry[1]; const Triangle* tris = (Triangle*)(geometry+2); for (int j = 0; j < num_tris; ++j) { Triangle t = tris[j]; const int3 tri_verts[3] = { (verts[t.s[0]]), (verts[t.s[1]]), (verts[t.s[2]]) }; int3 set_verts[3]; const int num_unique = find_unique(tri_verts, set_verts); if (num_unique == 3) { best = min_pair3i(best, distance_trianglei(p, tri_verts)); } else { // Degenerate triangle if (num_unique == 1) { // Degenerate to a point int3 closest = tri_verts[0]; float3 closest_d = convert_float3(closest); float3 p_d = convert_float3(p); int dist = (int)(fast_length(p_d-closest_d)+0.5f); best = min_pair3i(best, make_dist3(dist, closest)); } else { // Degenerate to a line int3 a = set_verts[0]; int3 b = set_verts[1]; Distance3f dist = distance_line3(convert_float3(p), convert_float3(a), convert_float3(b)); Distance3i disti = make_dist3( // convert_int_rte(dist.d), // convert_int3_rte(dist.p)); convert_int(dist.d), convert_int3(dist.p)); best = min_pair3i(best, disti); } } } return best; }
kernel void interact(global float *one, global float *two, const uint work_size) { const int size = get_global_size(0); const int pos = get_global_id(0); int i, s; const float dt = 0.00001; // time step const float in = 1e1; // interaction magnitude const float rm = 0.2; // equillibrium distance const float el = 1e6; // boundaries elasticity const float em = 1e-4; // emission coefficient const float ms = 100.0; // maximal speed global float *src = one; global float *dst = two; global float *tmp; Particle p; if(pos < work_size) p = loadParticle(pos,src); for(s = 0; s < 200; ++s) { barrier(CLK_GLOBAL_MEM_FENCE); if(pos >= work_size) continue; float3 acc = (float3)(0.0); float3 frc; /* We use Lennard-Jones potential */ for(i = 0; i < work_size; ++i) { if(i == pos) continue; Particle p2 = loadParticle(i, src); float3 r = p2.pos - p.pos; float l2 = dot(r,r)/(rm*rm); if(l2 < 0.6) continue; float l4 = l2*l2; float l6 = l2*l4; float l8 = l4*l4; frc = r*in*12.0*(1.0 - 1.0/l6)/(l8*rm*rm); acc += frc*(1.0 - em*dot(frc, p.vel - p2.vel)); } /* Boundaries */ frc = el*convert_float3(isgreater(fabs(p.pos), (float3)(1.0)))*(fabs(p.pos) - (float3)(1.0))*sign(p.pos); acc += frc*(1.0 - em*dot(frc, p.vel)); p.vel += dt*acc; float spd = length(p.vel); if(spd > ms) p.vel *= ms/spd; p.pos += dt*p.vel; storeParticle(&p,pos,dst); tmp = src; src = dst; dst = tmp; } }