struct Agent { float x; float y; float direction; }; static struct Agent *agents; static float *ground; static float *working_ground; static int2 ground_dimensions; uint hash(uint input) { input ^= 2747636419u; input *= 2654435769u; input ^= input >> 16; input *= 2654435769u; input ^= input >> 16; input *= 2654435769u; return input; } void kernel initialize_globals(global struct Agent *new_agents, global float *new_ground, global float *new_working_ground, global int* new_ground_dimensions) { agents = new_agents; ground = new_ground; working_ground = new_working_ground; ground_dimensions[0] = new_ground_dimensions[0]; ground_dimensions[1] = new_ground_dimensions[1]; } void kernel update_ground() { int current_index = get_global_id(0); int cx = current_index % ground_dimensions[0]; int cy = current_index / ground_dimensions[0]; float sum = 0.0f; for (int i = cx-1; i <= cx+1; i++) { if (i < 0 || i >= ground_dimensions[0]) { continue; } for(int j = cy-1; j <= cy+1; j++) { if (j < 0 || j >= ground_dimensions[1]) { continue; } sum += ground[i+j*ground_dimensions[0]]; } } working_ground[current_index] = sum/9.0f-0.005f; if (working_ground[current_index] < 0) { working_ground[current_index] = 0.0f; } } void kernel iterate_ground() { ground[get_global_id(0)] = working_ground[get_global_id(0)]; } void kernel move_agents() { int current_index = get_global_id(0); uint psuedorandom_int = hash(agents[current_index].x+agents[current_index].y*ground_dimensions[0]); if (psuedorandom_int % 100 < 12) { psuedorandom_int = hash(psuedorandom_int); agents[current_index].direction += (float)(psuedorandom_int%1000)*M_PI_F/3.0f/1000.0f-M_PI_F/6.0f; } else { float lsense = ground[(int)(agents[current_index].x+2.0f*cos(agents[current_index].direction+M_PI_F/6.0f)) + (int)(agents[current_index].y+2.0f*sin(agents[current_index].direction+M_PI_F/6.0f)) * ground_dimensions[0]]; float ssense = ground[(int)(agents[current_index].x+2.0f*cos(agents[current_index].direction)) + (int)(agents[current_index].y+2.0f*sin(agents[current_index].direction)) * ground_dimensions[0]]; float rsense = ground[(int)(agents[current_index].x+2.0f*cos(agents[current_index].direction-M_PI_F/6.0f)) + (int)(agents[current_index].y+2.0f*sin(agents[current_index].direction-M_PI_F/6.0f)) * ground_dimensions[0]]; if (lsense > ssense && lsense > rsense) { agents[current_index].direction += M_PI_F/6.0f; } if (rsense > ssense && rsense > lsense) { agents[current_index].direction += -M_PI_F/6.0f; } } float nx = agents[current_index].x + cos(agents[current_index].direction); float ny = agents[current_index].y + sin(agents[current_index].direction); if(nx < 0.0f || nx >= ground_dimensions[0] || ny < 0.0f || ny >= ground_dimensions[1]) { nx = (nx<0.0f)?0.0f:((nx>=ground_dimensions[0])?(ground_dimensions[0]-1.0f):nx); ny = (ny<0.0f)?0.0f:((ny>=ground_dimensions[1])?(ground_dimensions[1]-1.0f):ny); psuedorandom_int = hash(psuedorandom_int); agents[current_index].direction = (float)(psuedorandom_int%1000)*2.0f*M_PI_F/1000.0f; } agents[current_index].x = nx; agents[current_index].y = ny; } void kernel emit_agent_pheromones() { int current_index = get_global_id(0); int x = agents[current_index].x; int y = agents[current_index].y; int ground_index = x+y*ground_dimensions[0]; ground[ground_index] = 1.0f; } void kernel fill_draw_data(global uchar* draw_data) { int index = get_global_id(0); uchar val = (uchar)(255.0f*ground[index]); draw_data[4*index] = val; draw_data[4*index+1] = val; draw_data[4*index+2] = val; draw_data[4*index+3] = 255; }