-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.lua
165 lines (127 loc) · 4.18 KB
/
main.lua
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
---@diagnostic disable: unused-function
local LOVE_SIM = false
if _G["love"] ~= nil then
LOVE_SIM = true
end
--
-- Load Libraries
--
if LOVE_SIM then
require "class"
require "cpml"
require "materials"
require "ray"
require "lovescreen"
require "shapes"
else
os.loadAPI("lib/class")
Class = class.Class
os.loadAPI("lib/cpml")
vec3 = cpml.vec3
vec2 = cpml.vec2
mat4 = cpml.mat4
quat = cpml.quat
intersect = cpml.intersect
os.loadAPI("ray")
Ray = ray.Ray
os.loadAPI("shapes")
Sphere = shapes.Sphere
Plane = shapes.Plane
os.loadAPI("ccscreen")
Screen = ccscreen.Screen
end
--
-- Main part of the program
--
-- Draw Parameters
local cameraYaw = math.pi / 32
local cameraPitch = math.pi / 32
local cameraPos = vec3(0, -2, 8) -- vec3(0, -2, 0)
local cameraRotSpeed = math.pi / 32
local viewRotMatrix = mat4()
local viewTransMatrix = mat4()
-- Call this every time the camera moves
local function updateViewMatrix()
local yawRot = quat.from_angle_axis(cameraYaw, vec3(0, -1, 0))
local pitchRot = quat.from_angle_axis(cameraPitch, vec3(1, 0, 0))
viewRotMatrix = yawRot * pitchRot
viewTransMatrix:translate(mat4.identity(viewTransMatrix), cameraPos)
end
updateViewMatrix()
-- Scene Objects
-- X left-right negative-positive
-- Y top-bottom negative-positive
-- Z front-back negative-positive
local lightPosition = vec3(100.0, -100.0, 100.0)
local objects = {
Plane(vec3(0, 1, 0), vec3(0, -1, 0)):with_colour(colours.lime, colours.green),
Sphere(vec3(-2, -1.1, -5), 1):with_colour(colours.red, colours.brown),
Sphere(vec3(1, 0, -8), 1):with_colour(colours.blue, colours.cyan),
Sphere(vec3(2, -1.5, 2), 1),
}
local function castRay(ray, objects)
local closestPoint = false
local closestDist = INFINITY
local closestObject = nil
for _, object in ipairs(objects) do
local point, dist = object:intersect_ray(ray)
if point and dist < closestDist then
closestDist = dist
closestPoint = point
closestObject = object
end
end
return closestPoint, closestDist, closestObject
end
local function renderFrame(screen)
for y=0,screen.resolution.y do
for x=0,screen.resolution.x do
-- Shoot the ray in the scene and search for intersection
local ray = Ray:fromPixel(vec2(x, y), screen.resolution)
ray.direction = viewRotMatrix * ray.direction
ray.position = cameraPos
local point, dist, object = castRay(ray, objects)
local pxColour = colours.black -- background
if point then
pxColour = object:pointColour(point, {{position = lightPosition}}, objects)
end
screen:setPx(x, y, pxColour)
end
end
end
if LOVE_SIM then
local loveScreen = Screen:new()
function love.draw()
love.graphics.setColor(1, 1, 1)
love.graphics.print("Hello, world!", 400, 300)
renderFrame(loveScreen)
end
else -- NOT LOVE_SIM
local function main()
local screen = Screen()
while(true) do
renderFrame(screen)
os.sleep(0)
end
end
main()
end -- END NOT LOVE_SIM
--
-- Movement
--
if LOVE_SIM then
function love.keypressed(key, scancode, isrepeat)
if scancode == "left" then cameraYaw = cameraYaw - cameraRotSpeed end
if scancode == "right" then cameraYaw = cameraYaw + cameraRotSpeed end
if scancode == "up" then cameraPitch = cameraPitch + cameraRotSpeed end
if scancode == "down" then cameraPitch = cameraPitch - cameraRotSpeed end
if scancode == "r" then cameraPos.y = cameraPos.y + 0.5 end
if scancode == "f" then cameraPos.y = cameraPos.y - 0.5 end
if scancode == "d" then cameraPos.x = cameraPos.x + 0.5 end
if scancode == "a" then cameraPos.x = cameraPos.x - 0.5 end
if scancode == "s" then cameraPos.z = cameraPos.z + 0.5 end
if scancode == "w" then cameraPos.z = cameraPos.z - 0.5 end
updateViewMatrix()
end
else -- NOT LOVE_SIM
end -- END NOT LOVE_SIM