-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathindex.js
130 lines (108 loc) · 2.71 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"use strict"
function traceRay_impl( getVoxel,
px, py, pz,
dx, dy, dz,
max_d, hit_pos, hit_norm) {
// 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
var t = 0.0
, floor = Math.floor
, ix = floor(px) | 0
, iy = floor(py) | 0
, iz = floor(pz) | 0
, stepx = (dx > 0) ? 1 : -1
, stepy = (dy > 0) ? 1 : -1
, stepz = (dz > 0) ? 1 : -1
// dx,dy,dz are already normalized
, txDelta = Math.abs(1 / dx)
, tyDelta = Math.abs(1 / dy)
, tzDelta = Math.abs(1 / dz)
, xdist = (stepx > 0) ? (ix + 1 - px) : (px - ix)
, ydist = (stepy > 0) ? (iy + 1 - py) : (py - iy)
, zdist = (stepz > 0) ? (iz + 1 - pz) : (pz - iz)
// location of nearest voxel boundary, in units of t
, txMax = (txDelta < Infinity) ? txDelta * xdist : Infinity
, tyMax = (tyDelta < Infinity) ? tyDelta * ydist : Infinity
, tzMax = (tzDelta < Infinity) ? tzDelta * zdist : Infinity
, steppedIndex = -1
// main loop along raycast vector
while (t <= max_d) {
// exit check
var b = getVoxel(ix, iy, iz)
if (b) {
if (hit_pos) {
hit_pos[0] = px + t * dx
hit_pos[1] = py + t * dy
hit_pos[2] = pz + t * dz
}
if (hit_norm) {
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 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
if (hit_pos) {
hit_pos[0] = px + t * dx
hit_pos[1] = py + t * dy
hit_pos[2] = pz + t * dz
}
if (hit_norm) {
hit_norm[0] = hit_norm[1] = hit_norm[2] = 0
}
return 0
}
// conform inputs
function traceRay(getVoxel, origin, direction, max_d, hit_pos, hit_norm) {
var px = +origin[0]
, py = +origin[1]
, pz = +origin[2]
, dx = +direction[0]
, dy = +direction[1]
, dz = +direction[2]
, ds = Math.sqrt(dx * dx + dy * dy + dz * dz)
if (ds === 0) {
throw new Error("Can't raycast along a zero vector")
}
dx /= ds
dy /= ds
dz /= ds
if (typeof (max_d) === "undefined") {
max_d = 64.0
} else {
max_d = +max_d
}
return traceRay_impl(getVoxel, px, py, pz, dx, dy, dz, max_d, hit_pos, hit_norm)
}
module.exports = traceRay