>>61416003Wrote a new and improved ray tracer for my minecraft clone.

void finite_pick_ll(finiteworld * f, float x, float y, float z, float dx, float dy, float dz, int distance, int * output) {

block * b = finite_getblock(f, x, y, z); //Quick test to see if ray is already in a block

if(b->type != AIR) {

output[0] = 1;

output[1] = x;

output[2] = y;

output[3] = z;

return;

}

vec3 const p = { x, y, z };

vec3 const d = { dx, dy, dz};

int cur[3] = { lrint(floor(x)), lrint(floor(y)), lrint(floor(z)) };

int signs[3] = { (dx > 0) ? 1 : -1, (dy > 0) ? 1 : -1, (dz > 0) ? 1 : -1 };

vec3 corner = { x, y, z };

for(int i = 0; i < 3; i++) {

corner[i] = (signs[i] > 0) ? ceil(corner[i]) : floor(corner[i]);

}

vec3 tmp;

float ndotd;

for(int k = 0; k < distance; k++) { //TODO better distance measure

vec3_sub(tmp, corner, p);

float smallest = INFINITY;

int coord;

for(int j = 0; j < 3; j++) { //TODO avoid recomputation

ndotd = d[j];

float t = fabs(tmp[j] / ndotd); //Don't be afraid!

if(t < smallest) {

smallest = t;

coord = j;

}

}

cur[coord] += signs[coord];

corner[coord] += signs[coord];

b = finite_getblock(f, cur[0], cur[1], cur[2]);

if(b->type != AIR) {

output[0] = 1;

output[1] = cur[0];

output[2] = cur[1];

output[3] = cur[2];

return;

}

}

output[0] = 0;

//let n = normal of plane

//let d = direction of player

//let a = position of player

//let b = point on plane

//t = (n dot (b - a)) / (n dot d)

//where intersection i = t * d + a

}

The old brainlet version used iterative Euler integration and did a lookup at each step. It was simpler and the math was faster, but having to do lookups 50x more murdered performance.