diff options
author | sanine <sanine.not@pm.me> | 2023-03-29 00:46:16 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2023-03-29 00:46:16 -0500 |
commit | ee3b19aa4f0ec65c159a31d589bbafd4a644610e (patch) | |
tree | c8052c53c0e486daeaec241f3463e4582a68b8d6 /main.lua | |
parent | 5a93fb6f6a8fb6f1dad821b407b4f4531bc23783 (diff) |
re-implement recursive transform system
Diffstat (limited to 'main.lua')
-rw-r--r-- | main.lua | 150 |
1 files changed, 113 insertions, 37 deletions
@@ -20,51 +20,74 @@ local november = nvg.CreateFont(vg, "November", "assets/november.regular.ttf") local vw, vh = 640, 480 --- create camera matrices -local camera = { - view=Mat4():identity():translate(Vec3{0, 0, -3}), +-- setup ecs +local edb = ecs.EntityDb() +local sdb = ecs.SystemDb() + +local camera = edb:createEntity() +edb:addComponent(camera, "camera", { projection=Mat4():perspective(math.rad(45), 640/480, 0.1, 100), +}) +edb:addComponent(camera, "transform", { + matrix=Mat4():identity():translate(Vec3{0, 0, -6}), +}) + + +sdb:addSystem{ + update = function(self, dt) + local transform = edb:getComponent(camera, "transform") + transform.matrix:translate(Vec3{0, 0, -0.2*math.sin(math.pi * glfw.GetTime())}) + end } +sdb:addSystem{ + update = function(self, dt) + local entities = self.db:queryComponent("transform") --- close window on ESCAPE key -window:setKeyCallback(function(_, key, scancode, action) - if action == glfw.PRESS then - if key == glfw.KEY_ESCAPE then - window:setShouldClose(true) + -- prepare transforms + for id, transform in pairs(entities) do + transform._visited = false end - end -end) --- resize window correctly -window:setFramebufferSizeCallback(function(_, width, height) - gl.Viewport(0, 0, width, height) - camera.projection:perspectiveResize(width/height) - vw, vh = width, height -end) - --- averager (for fps) -function averager(memory) - local buf = {} - local avg = 0 - for i=1,memory do table.insert(buf, 0) end - return function(value) - table.insert(buf, value) - local val = table.remove(buf, 1) - avg = avg + value - val - return avg / memory - end -end -local fpsAverage = averager(200) + -- helper function + local function recursiveTransform(transform) + if transform._visited then + return transform._matrix + end + if not transform.parent then + transform._matrix = transform.matrix + else + local parentTransform = self.db:getComponent(transform.parent, "transform") + local parentMatrix = recursiveTransform(parentTransform) + transform._matrix = parentMatrix * transform.matrix + end + transform._visited = true + return transform._matrix + end --- setup ecs -local edb = ecs.EntityDb() -local sdb = ecs.SystemDb() + -- compute transforms + for id, transform in pairs(entities) do + recursiveTransform(transform) + end + end, + db = edb, + priority = 0, +} sdb:addSystem{ + camera = camera, update = function(self, dt) + local cameraParams = self.db:getComponent(camera, "camera") + local cameraTransform = self.db:getComponent(camera, "transform") + local view + if cameraTransform then + view = cameraTransform._matrix + else + view = Mat4():identity() + end + local entities = self.db:queryComponent("renderMesh") for entity, tbl in pairs(entities) do -- get shader @@ -73,7 +96,7 @@ sdb:addSystem{ -- bind textures local texOffset = 0 - for name, texTbl in pairs(tbl.textures) do + for name, texTbl in pairs(tbl.textures or {}) do local texture = honey.image.loadImage(texTbl.filename, texTbl.params) gl.BindTexture(gl.TEXTURE_2D + texOffset, texture.texture) shader:setInt(name, texOffset) @@ -81,14 +104,16 @@ sdb:addSystem{ end -- configure default uniforms + local query = self.db:getComponent(entity, "transform") + local model = (query and query._matrix) or Mat4():identity() shader:configure{ float={ time=glfw.GetTime(), }, matrix={ - view=camera.view, - projection=camera.projection, - model=Mat4():identity(), + view=view, + projection=cameraParams.projection, + model=model, }, } @@ -115,7 +140,58 @@ edb:addComponent(id, "renderMesh", { shader = { vertex="vertex.glsl", fragment="fragment.glsl" }, mesh = { filename="assets/icosahedron.obj", index=1 }, }) +edb:addComponent(id, "transform", { + matrix = Mat4():identity():rotateZ(math.rad(45)), +}) +sdb:addSystem{ + update = function(self, dt) + local transform = edb:getComponent(id, "transform") + transform.matrix:rotateZ(math.pi * dt) + end, +} +local id2 = edb:createEntity() +edb:addComponent(id2, "renderMesh", { + shader = { vertex="vertex.glsl", fragment="fragment.glsl" }, + mesh = { filename="assets/tetrahedron.obj", index=1 }, +}) +edb:addComponent(id2, "transform", { + parent=id, + matrix=Mat4():identity():translate(Vec3{0, 2, 0}), +}) + + + +-- close window on ESCAPE key +window:setKeyCallback(function(_, key, scancode, action) + if action == glfw.PRESS then + if key == glfw.KEY_ESCAPE then + window:setShouldClose(true) + end + end +end) + +-- resize window correctly +window:setFramebufferSizeCallback(function(_, width, height) + gl.Viewport(0, 0, width, height) + local cameraParams = edb:getComponent(camera, "camera") + cameraParams.projection:perspectiveResize(width/height) + vw, vh = width, height +end) + +-- averager (for fps) +function averager(memory) + local buf = {} + local avg = 0 + for i=1,memory do table.insert(buf, 0) end + return function(value) + table.insert(buf, value) + local val = table.remove(buf, 1) + avg = avg + value - val + return avg / memory + end +end +local fpsAverage = averager(200) -- main loop |