world view ray casting
This commit is contained in:
@ -35,3 +35,54 @@ var DirectionVecd = [6]Vec3d{
|
||||
ZPlus: {0, 0, 1},
|
||||
ZMinus: {0, 0, -1},
|
||||
}
|
||||
var DirectionName = [6]string{
|
||||
"X+",
|
||||
"X-",
|
||||
"Y+",
|
||||
"Y-",
|
||||
"Z+",
|
||||
"Z-",
|
||||
}
|
||||
|
||||
func (d Direction) Opposite() Direction {
|
||||
switch d {
|
||||
case XPlus:
|
||||
return XMinus
|
||||
case XMinus:
|
||||
return XPlus
|
||||
case YPlus:
|
||||
return YMinus
|
||||
case YMinus:
|
||||
return YPlus
|
||||
case ZPlus:
|
||||
return ZMinus
|
||||
case ZMinus:
|
||||
return ZPlus
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// DirectionIs returns X/Y/Z for 0/1/2, and +/- for #pos/neg.
|
||||
func DirectionIs(index int, positive bool) Direction {
|
||||
switch index {
|
||||
case 0:
|
||||
if positive {
|
||||
return XPlus
|
||||
} else {
|
||||
return XMinus
|
||||
}
|
||||
case 1:
|
||||
if positive {
|
||||
return YPlus
|
||||
} else {
|
||||
return YMinus
|
||||
}
|
||||
case 2:
|
||||
if positive {
|
||||
return ZPlus
|
||||
} else {
|
||||
return ZMinus
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
@ -155,3 +155,51 @@ func (box1 Boxd) Intersect(box2 Boxd) (ok bool, intersect Boxd) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func between(val, min, max float64) bool {
|
||||
return min <= val && val <= max
|
||||
}
|
||||
|
||||
// IntersectRay computes if a Box intersects with a ray.
|
||||
// #dir must be normalized, otherwise it's garbage-in garbage-out.
|
||||
func (box Boxd) IntersectRay(start, dir Vec3d, length float64) (ok bool, hitface Direction, where Vec3d, dist float64) {
|
||||
// https://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms
|
||||
if box.Contains(start) {
|
||||
return true, XPlus, start, 0
|
||||
}
|
||||
|
||||
min, max := box.MinPoint(), box.MaxPoint()
|
||||
|
||||
var t Vec3d
|
||||
for i := 0; i < 3; i++ {
|
||||
if dir[i] > 0 {
|
||||
t[i] = (min[i] - start[i]) / dir[i]
|
||||
} else {
|
||||
t[i] = (max[i] - start[i]) / dir[i]
|
||||
}
|
||||
}
|
||||
|
||||
maxi := 0
|
||||
for i, ti := range t {
|
||||
if ti > t[maxi] {
|
||||
maxi = i
|
||||
}
|
||||
}
|
||||
|
||||
if between(t[maxi], 0, length) {
|
||||
pt := start.Add(dir.Multiply(t[maxi]))
|
||||
|
||||
o1 := (maxi + 1) % 3
|
||||
o2 := (maxi + 1) % 3
|
||||
|
||||
if between(pt[o1], min[o1], max[o1]) && between(pt[o2], min[o2], max[o2]) {
|
||||
ok = true
|
||||
hitface = DirectionIs(maxi, dir[maxi] < 0)
|
||||
where = pt
|
||||
dist = t[maxi]
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user