Last active
November 11, 2020 17:14
-
-
Save Heath123/12ff2437c7d5585a8dd94acf12d60f92 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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