-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.nelua
300 lines (253 loc) · 8.07 KB
/
main.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
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
require "iterators"
require "string"
require "os"
local World = require "entropy.world"
local Storage = require "entropy.world.storage"
local P = require "entropy.world.pointer"
local Vec2 = require "entropy.math.vec2"
local Vec3 = require "entropy.math.vec3"
local Mat4 = require "entropy.math.mat4"
local world: World
-- register components
World.r("positions", Vec2)
World.r("velocities", Vec2)
##[[
function unroll(count, block)
for i=1,count do
block(i)
end
end
]]
## unroll(10, function(i)
World.r(#["_" .. tostring(i)]#, usize)
## end)
local Entity = @record{
pos: P(Vec2),
vel: P(Vec2),
}
World.r("entities", Entity)
local positions = world:s("positions", Vec2)
positions:reserve(10010)
local velocities = world:s("velocities", Vec2)
velocities:reserve(10010)
local entities = world:s("entities", Entity)
entities:reserve(10010)
for i=0,<10 do
local pos = positions:create({ x = i, y = i })
local vel = velocities:create({ x = i, y = i })
local entity = entities:create({
pos = pos,
vel = vel,
})
end
-- Initial State
print("===== Initial State =====")
for id, e in mpairs(entities) do
print(id, e, positions[e.pos], velocities[e.vel])
end
-- Run "System"
for _, e in mpairs(entities) do
positions[e.pos] = positions[e.pos] + velocities[e.vel]
end
-- Final State
print("===== Final State =====")
for id, e in mpairs(entities) do
print(id, e, positions[e.pos], velocities[e.vel])
end
-- Benchmark
print("===== Benching with 10,000 Entities =====")
local now = os.now()
for i=0,<10000 do
if i % 10 == 0 then
entities:create({
pos = positions:create({ x = i, y = i }),
vel = velocities:create({ x = i, y = i }),
})
else
entities:create({
pos = positions:create({ x = i, y = i }),
})
end
end
print("Creation: ", (os.now() - now) * 1000000)
require "vector"
local times: vector(float64)
for i=0,<1000 do
now = os.now()
for id, e in mpairs(entities) do
positions[e.pos] = positions[e.pos] + velocities[e.vel]
end
local time = os.now() - now
times:push(time)
end
local avg: float64 = 0.0
for _, time in ipairs(times) do
avg = avg + time
end
avg = avg / #times
print("Avg Iteration: ", avg * 1000000)
-- renderer
require "wgpu"
wgpuSetLogCallback((@WGPULogCallback)(function(level: WGPULogLevel, msg: cstring, ptr: pointer): void
print("WGPU" .. level .. ": " .. msg)
end))
wgpuSetLogLevel(WGPULogLevel_Info)
local Render = require 'entropy.render'
local Context = require 'entropy.render.context.glfw'
local Renderer = require "entropy.render.renderer"
local MeshImpl = require "entropy.render.impl.mesh"
require "entropy.render.impl.compose"
local Camera = require "entropy.scene.camera"
local Mesh = require "entropy.scene.mesh"
local Event = require "entropy.defs.event"
local render: Render
render:init_default()
local context: Context
context:init("testing", 512, 512, true, render)
##[[
local Impl = ComposeImpl({
MeshImpl,
})
]]
local ImplT = #[Impl]#
local renderer: Renderer(ImplT)
renderer:init(context.device, context.surface_config.format, context.surface_config.width, context.surface_config.height)
-- setup resize callback
context.user_pointer = &renderer
context.resize_callback = function(user: pointer, width: uint32, height: uint32): void
local crenderer = (@*Renderer(ImplT))(user)
crenderer:resize(width, height)
end
-- setup camera
local cameras = world:s("entropy.scene.cameras", Camera)
local camera_idx = cameras:create({
pos = { 10, 10, 10 },
rot = { 0, 0, 0 },
fov = 90,
z_near = 0.1,
z_far = 10000,
})
cameras[camera_idx]:look_at({ 0, 0, 0 })
-- load meshes
local meshes = world:s("entropy.scene.meshes", Mesh)
local cube_mesh_idx = meshes:create(Mesh.load_from_obj_comptime("./cube.obj"))
local cube_mesh = &meshes[cube_mesh_idx]
cube_mesh:init(world, "cube")
local count: isize <const> = 20
local instances = world:s("entropy.scene.meshes.cube", Mesh.Instance)
for y=-count,<count do
for x=-count,<count do
for z=-count,<count do
local instance_idx = instances:create(cube_mesh:instance())
instances[instance_idx].transform = Mat4.from_pos({ x * 5, z * 5, y * 5 }) * Mat4.from_scl({ 2, 2, 2 })
end
end
end
print("Total Instances: " .. tostring(#instances))
cube_mesh:prepare(renderer)
local fps_list: vector(float64)
local is_forward_pressed = false
local is_backward_pressed = false
local is_left_pressed = false
local is_right_pressed = false
local is_up_pressed = false
local is_down_pressed = false
local is_speed_pressed = false
local camera_yaw = 0.0
local camera_pitch = 0.0
local last_mouse_x = 0.0
local last_mouse_y = 0.0
while not context:should_close() do
local now = world:now()
-- get input
local has_event, event_queue = context:poll_event()
if has_event then
while not event_queue:empty() do
local event = event_queue:popfront()
if event.type == Event.Type.Key then
if event.data.Key.action == Event.Data.Key.Action.Press then
if event.data.Key.key == 256 then
context:close();
end
end
local state: boolean = false
if event.data.Key.action == Event.Data.Key.Action.Press or event.data.Key.action == Event.Data.Key.Action.Repeat then
state = true
elseif event.data.Key.action == Event.Data.Key.Action.Release then
state = false
end
if event.data.Key.key == 87 then
is_forward_pressed = state
elseif event.data.Key.key == 83 then
is_backward_pressed = state
elseif event.data.Key.key == 65 then
is_left_pressed = state
elseif event.data.Key.key == 68 then
is_right_pressed = state
elseif event.data.Key.key == 32 then
is_up_pressed = state
elseif event.data.Key.key == 340 then
is_down_pressed = state
elseif event.data.Key.key == 341 then
is_speed_pressed = state
end
elseif event.type == Event.Type.MouseMotion then
local mouse_dx = event.data.MouseMotion.x - last_mouse_x
local mouse_dy = event.data.MouseMotion.y - last_mouse_y
local sensitivity = 0.2
camera_yaw = camera_yaw + math.rad(mouse_dx) * sensitivity
camera_pitch = math.clamp(camera_pitch + math.rad(mouse_dy) * sensitivity, (-math.pi / 2) + 0.0001, (math.pi / 2) - 0.0001)
local camera = &cameras[camera_idx]
camera.rot = (@Vec3)({ math.cos(camera_yaw) * math.cos(camera_pitch), -math.sin(camera_pitch), math.sin(camera_yaw) * math.cos(camera_pitch) }):norm()
last_mouse_x = event.data.MouseMotion.x
last_mouse_y = event.data.MouseMotion.y
end
end
end
-- update
local speed = 1
if is_speed_pressed then
speed = 10
end
if is_forward_pressed then
cameras[camera_idx].pos = cameras[camera_idx].pos + cameras[camera_idx].rot * speed
end
if is_backward_pressed then
cameras[camera_idx].pos = cameras[camera_idx].pos - cameras[camera_idx].rot * speed
end
if is_left_pressed then
cameras[camera_idx].pos = cameras[camera_idx].pos - cameras[camera_idx].rot:cross({0, 1, 0}):norm() * speed
end
if is_right_pressed then
cameras[camera_idx].pos = cameras[camera_idx].pos + cameras[camera_idx].rot:cross({0, 1, 0}):norm() * speed
end
if is_up_pressed then
cameras[camera_idx].pos = cameras[camera_idx].pos + {0, speed, 0}
end
if is_down_pressed then
cameras[camera_idx].pos = cameras[camera_idx].pos - {0, speed, 0}
end
for _, instance in mpairs(instances) do
instance.transform = instance.transform * Mat4.from_pos({ (math.random() - 0.5) * speed, (math.random() - 0.5) * speed, (math.random() - 0.5) * speed }) * Mat4.from_rot(math.random() / 10, { math.random(), math.random(), math.random() })
end
for _, mesh in mpairs(meshes) do
mesh:update(renderer)
end
-- render
local view = context:view()
renderer:render(view, &world)
context:present()
fps_list:push(1 / (world:now() - now))
if #fps_list > 30 then
local avg: float64 = 0.0
for _, time in ipairs(fps_list) do
avg = avg + time
end
avg = avg / #fps_list
print("FPS: ", avg)
fps_list:clear()
end
end
renderer:cleanup()
context:cleanup()
render:cleanup()