-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcamera.nelua
86 lines (81 loc) · 2.35 KB
/
camera.nelua
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
global Camera = @record{
lower_left_corner: vec3,
lower_left_corner_direction: vec3,
horizontal: vec3,
vertical: vec3,
origin: vec3,
lookat: vec3,
vup: vec3,
u: vec3,
v: vec3,
w: vec3,
lensradius: number,
vfov: number,
aspect: number,
aperture: number,
focusdist: number,
}
function Camera:update()
local theta = self.vfov*math.pi/180
local half_height = math.tan(theta/2)
local half_width = self.aspect * half_height
self.w = vec3.unit(self.origin - self.lookat)
self.u = vec3.unit(vec3.cross(self.vup, self.w))
self.v = vec3.cross(self.w, self.u)
self.lower_left_corner =
self.origin - (
self.u * (half_width*self.focusdist) +
self.v * (half_height*self.focusdist) +
self.w * self.focusdist)
self.lower_left_corner_direction = self.lower_left_corner - self.origin
self.horizontal = self.u * (2*half_width*self.focusdist)
self.vertical = self.v * (2*half_height*self.focusdist)
self.lensradius = self.aperture / 2
end
function Camera.create(lookfrom: vec3, lookat: vec3, vup: vec3,
vfov: number, aspect: number, aperture: number, focusdist: number): Camera
if aperture == 0 then
focusdist = 1
end
local self = Camera{
origin = lookfrom,
lookat = lookat,
vup = vup,
vfov = vfov,
aspect = aspect,
aperture = aperture,
focusdist = focusdist,
}
self:update()
return self
end
function Camera:getray(u: number, v: number)
local r: Ray
if self.aperture ~= 0 then
local rd = vec3.random_in_disk(self.lensradius)
local offset = self.u * rd.x + self.v * rd.y
r.origin = self.origin + offset
r.direction = (self.lower_left_corner + self.horizontal * u + self.vertical * v) - r.origin
else
r.origin = self.origin
r.direction = self.lower_left_corner_direction + self.horizontal * u + self.vertical * v
end
r.direction = r.direction:unit()
return r
end
function Camera:rotate(x: number, y: number)
local dir = self.lookat - self.origin
dir = vec3.rotvec(dir, self.u, x)
dir = vec3.rotvec(dir, self.v, y)
self.lookat = self.origin + dir
self:update()
end
function Camera:translate(x: number, y: number, z: number)
local trans = vec3{0,0,0}
trans = trans + self.u * x
trans = trans + self.w * -z
trans = trans + self.v * y
self.origin = self.origin + trans
self.lookat = self.lookat + trans
self:update()
end