This repository has been archived on 2023-08-08. You can view files and clone it, but cannot push or open issues or pull requests.
tomo-old/examples/raycaster/ray.go

91 lines
1.9 KiB
Go
Raw Normal View History

package main
import "math"
import "image"
type World interface {
At (image.Point) int
}
type DefaultWorld struct {
Data []int
Stride int
}
func (world DefaultWorld) At (position image.Point) int {
if position.X < 0 { return 0 }
if position.Y < 0 { return 0 }
if position.X >= world.Stride { return 0 }
index := position.X + position.Y * world.Stride
if index >= len(world.Data) { return 0 }
return world.Data[index]
}
type Camera struct {
X, Y float64
Angle float64
Fov float64
}
func (camera *Camera) Point () (image.Point) {
return image.Pt(int(camera.X), int(camera.Y))
}
func (camera *Camera) Rotate (by float64) {
camera.Angle += by
if camera.Angle < 0 { camera.Angle += math.Pi * 2 }
if camera.Angle > math.Pi * 2 { camera.Angle = 0 }
}
func (camera *Camera) Walk (by float64) {
dx, dy := camera.Delta()
camera.X += dx * by
camera.Y += dy * by
}
func (camera *Camera) Strafe (by float64) {
dx, dy := camera.OffsetDelta()
camera.X += dx * by
camera.Y += dy * by
}
func (camera *Camera) Delta () (x float64, y float64) {
return math.Cos(camera.Angle), math.Sin(camera.Angle)
}
func (camera *Camera) OffsetDelta () (x float64, y float64) {
offset := math.Pi / 2
return math.Cos(camera.Angle + offset), math.Sin(camera.Angle + offset)
}
type Ray struct {
X, Y float64
Angle float64
Precision int
}
func (ray *Ray) Cast (world World, max int) (distance float64) {
precision := 64
dX := math.Cos(ray.Angle) / float64(precision)
dY := math.Sin(ray.Angle) / float64(precision)
origX, origY := ray.X, ray.Y
wall := 0
depth := 0
for wall == 0 && depth < max * precision {
ray.X += dX
ray.Y += dY
wall = world.At(ray.Point())
depth ++
}
distanceX := origX - ray.X
distanceY := origY - ray.Y
return math.Sqrt(distanceX * distanceX + distanceY * distanceY)
}
func (ray *Ray) Point () (image.Point) {
return image.Pt(int(ray.X), int(ray.Y))
}