Skip to content

Instantly share code, notes, and snippets.

@Heath123
Last active November 11, 2020 17:14
Show Gist options
  • Save Heath123/12ff2437c7d5585a8dd94acf12d60f92 to your computer and use it in GitHub Desktop.
Save Heath123/12ff2437c7d5585a8dd94acf12d60f92 to your computer and use it in GitHub Desktop.
package com.example;
public class HitData {
public float[] hit_pos;
public float[] hit_norm;
public boolean hit;
public HitData(float[] hit_pos, float[] hit_norm, boolean hit) {
this.hit_pos = hit_pos;
this.hit_norm = hit_norm;
this.hit = hit;
}
}
package com.example;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("Hello world!");
System.out.println(Arrays.toString(traceRay(new float[]{3,4,5}, new float[]{1,-1,-1}, 20).hit_pos));
}
private static final float Infinity = Float.POSITIVE_INFINITY;
private static boolean getVoxel(int x, int y, int z) {
// return a truthy value here for voxels that block the raycast
return y < 0;
}
private static HitData traceRay_impl(float px, float py, float pz,
float dx, float dy, float dz,
float max_d) {
float hit_pos[] = new float[3];
float hit_norm[] = new float[3];
// consider raycast vector to be parametrized by t
// vec = [px,py,pz] + t * [dx,dy,dz]
// algo below is as described by this paper:
// http://www.cse.chalmers.se/edu/year/2010/course/TDA361/grid.pdf
float t = 0;
int ix = (int) Math.floor(px);
int iy = (int) Math.floor(py);
int iz = (int) Math.floor(pz);
int stepx = (dx > 0) ? 1 : -1;
int stepy = (dy > 0) ? 1 : -1;
int stepz = (dz > 0) ? 1 : -1;
// dx,dy,dz are already normalized
float txDelta = Math.abs(1 / dx);
float tyDelta = Math.abs(1 / dy);
float tzDelta = Math.abs(1 / dz);
float xdist = (stepx > 0) ? (ix + 1 - px) : (px - ix);
float ydist = (stepy > 0) ? (iy + 1 - py) : (py - iy);
float zdist = (stepz > 0) ? (iz + 1 - pz) : (pz - iz);
// location of nearest voxel boundary, in units of t
float txMax = (txDelta < Infinity) ? txDelta * xdist : Infinity;
float tyMax = (tyDelta < Infinity) ? tyDelta * ydist : Infinity;
float tzMax = (tzDelta < Infinity) ? tzDelta * zdist : Infinity;
int steppedIndex = -1;
// main loop along raycast vector
while (t <= max_d) {
// exit check
boolean b = getVoxel(ix, iy, iz);
if (b) {
hit_pos[0] = px + t * dx;
hit_pos[1] = py + t * dy;
hit_pos[2] = pz + t * dz;
hit_norm[0] = hit_norm[1] = hit_norm[2] = 0;
if (steppedIndex == 0) hit_norm[0] = -stepx;
if (steppedIndex == 1) hit_norm[1] = -stepy;
if (steppedIndex == 2) hit_norm[2] = -stepz;
return new HitData(hit_pos, hit_norm, b);
}
// advance t to next nearest voxel boundary
if (txMax < tyMax) {
if (txMax < tzMax) {
ix += stepx;
t = txMax;
txMax += txDelta;
steppedIndex = 0;
} else {
iz += stepz;
t = tzMax;
tzMax += tzDelta;
steppedIndex = 2;
}
} else {
if (tyMax < tzMax) {
iy += stepy;
t = tyMax;
tyMax += tyDelta;
steppedIndex = 1;
} else {
iz += stepz;
t = tzMax;
tzMax += tzDelta;
steppedIndex = 2;
}
}
}
// no voxel hit found
hit_pos[0] = px + t * dx;
hit_pos[1] = py + t * dy;
hit_pos[2] = pz + t * dz;
hit_norm[0] = hit_norm[1] = hit_norm[2] = 0;
return new HitData(hit_pos, hit_norm, false);
}
// conform inputs
public static HitData traceRay(float[] origin, float[] direction, float max_d) throws Exception {
float px = origin[0];
float py = origin[1];
float pz = origin[2];
float dx = direction[0];
float dy = direction[1];
float dz = direction[2];
float ds = (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
if (ds == 0) {
throw new Exception("Can't raycast along a zero vector");
}
dx /= ds;
dy /= ds;
dz /= ds;
return traceRay_impl(px, py, pz, dx, dy, dz, max_d);
}
public static HitData traceRay(float[] origin, float[] direction) throws Exception {
return traceRay(origin, direction, 64);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment