#include <cuda_runtime.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "naive_update.h"
#include "main.h"
#include "utils.h"
__global__ void
update(Projectile* projs, Projectile* projs_snapshot, float delta_t)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i >= MAX_PROJS)
{
return;
}
/* intentionally not a pointer */
Projectile p = projs_snapshot[i];
if (!p.active)
{
return;
}
float normalized_dt = delta_t * 60.0f;
/* Gravity from all other projectiles */
float grav_x = 0.0f;
float grav_y = 0.0f;
/* gravity computation: */
for (int j = 0; j < MAX_PROJS; j++)
{
/* don't apply gravity to itself; */
Projectile pj = projs_snapshot[j];
if (j == i)
{
continue;
}
/* if it has no gravity, it can be
* ignored */
if (!pj.active || pj.gravity == 0)
{
continue;
}
float dx = pj.pos.x - p.pos.x;
float dy = pj.pos.y - p.pos.y;
float dist_sq = dx * dx + dy * dy;
/* avoid singularity if the projectiles are nearly on top of each other
*/
if (dist_sq < 1.0f)
{
continue;
}
/* strength of gravity should fall off with distance, scaled by the
* other projectile's gravity, per the inverse square law */
float dist = sqrtf(dist_sq);
float force = pj.gravity / dist_sq;
grav_x += (dx / dist) * force;
grav_y += (dy / dist) * force;
// projs_snapshot[j] = pj;
}
update_standard_projectile_velocity(&p, grav_x, grav_y, delta_t,
normalized_dt);
/* update the projectile in the global array */
projs[i] = p;
}
void
update_cpu(Projectile* h_projs, float delta_t)
{
/* needs a read-only buffer to avoid race conditions when updating position,
* etc. */
Projectile snapshot[MAX_PROJS];
memcpy(snapshot, h_projs, MAX_PROJS * sizeof(Projectile));
for (int i = 0; i < MAX_PROJS; i++)
{
if (!snapshot[i].active)
{
continue;
}
Projectile p = snapshot[i];
float normalized_dt = delta_t * 60.0f;
float grav_x = 0.0f;
float grav_y = 0.0f;
/* gravity computation */
for (int j = 0; j < MAX_PROJS; j++)
{
if (j == i || !snapshot[j].active || snapshot[j].gravity == 0)
{
continue;
}
float dx = snapshot[j].pos.x - p.pos.x;
float dy = snapshot[j].pos.y - p.pos.y;
float dist_sq = dx * dx + dy * dy;
if (dist_sq < 1.0f)
{
continue;
}
float dist = sqrtf(dist_sq);
float force = snapshot[j].gravity / dist_sq;
grav_x += (dx / dist) * force;
grav_y += (dy / dist) * force;
}
update_standard_projectile_velocity(&p, grav_x, grav_y, delta_t,
normalized_dt);
h_projs[i] = p;
}
}