From 45dbe47d17303050cbea7c2c51e838acfe21c2fb Mon Sep 17 00:00:00 2001 From: sanine-a Date: Tue, 28 Mar 2023 16:35:22 -0500 Subject: add cached mesh loading --- main.lua | 213 +++++++++++---------------------------------------------------- 1 file changed, 35 insertions(+), 178 deletions(-) (limited to 'main.lua') diff --git a/main.lua b/main.lua index 2463bdd..098a65b 100644 --- a/main.lua +++ b/main.lua @@ -1,28 +1,4 @@ require 'honey.std' -local paused = true -local balls = {} - -local function formatize(f) - return function(fmt, ...) - f(string.format(fmt, ...)) - end -end -local printf = formatize(print) -local log = honey.log -log.fatal = formatize(log.fatal) -log.error = formatize(log.error) -log.warn = formatize(log.warn) -log.info = formatize(log.info) -log.debug = formatize(log.debug) -log.trace = formatize(log.trace) - -log.info( - "honey v%d.%d.%d -- %s", - honey.version.major, - honey.version.minor, - honey.version.patch, - honey.version.string -) local glfw = honey.glfw local gl = honey.gl @@ -43,80 +19,14 @@ local vg = nvg.CreateContext() 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, -30}), projection=Mat4():perspective(math.rad(45), 640/480, 0.1, 100), } --- setup ecs -local level = ecs.Level() -level:addSystem(systems.transformCascade) -level:addSystem(systems.renderCam(camera)) -level:addSystem(systems.update) - --- physics system -local world = ode.WorldCreate() -local space = ode.HashSpaceCreate(ode.Space0) -level:addSystem{ - setup=function(self) - self.time = 0 - self.world=world - self.space=space - ode.WorldSetGravity(self.world, 0, -100, 0) - ode.WorldSetCFM(self.world, 1e-5) - self.contactgroup = ode.JointGroupCreate(200) - self.__gc = honey.util.gc_canary(function() - ode.WorldDestroy(self.world) - ode.SpaceDestroy(self.space) - end) - end, - filter = ecs.Filter.AND{"transform", "collisionShape", "physicsBody"}, - preUpdate = function(self) - self.dt = nil - if self.time > 0.01 then - self.time = self.time - 0.01 - ode.SpaceCollide(self.space, function(o1, o2) - local b1 = ode.GeomGetBody(o1) - local b2 = ode.GeomGetBody(o2) - local contact = ode.CreateContact{ - surface = { - mode = ode.ContactBounce + ode.ContactSoftCFM, - mu = ode.Infinity, - bounce = 0.90, - bounce_vel = 0.1, - soft_cfm = 0.001, - }, - } - local collisions = ode.Collide(o1, o2, 1) - if #collisions > 0 then - local e1 = ode.GeomGetData(o1) - local e2 = ode.GeomGetData(o2) - ode.ContactSetGeom(contact, collisions[1]) - local joint = ode.JointCreateContact(self.world, self.contactgroup, contact) - ode.JointAttach(joint, b1, b2) - end - end) - ode.WorldQuickStep(self.world, 0.01) - ode.JointGroupEmpty(self.contactgroup) - end - end, - update = function(self, entity, dt) - if not self.dt then - self.dt = dt - self.time = self.time + dt - end - local x, y, z = ode.BodyGetPosition(entity.physicsBody) - local d, a, b, c = ode.BodyGetQuaternion(entity.physicsBody) - entity.transform:identity():translate(Vec3{x, y, z}):mul(Quaternion{a, b, c, d}:toMat4()) - end, - onRemoveEntity = function(self, id, entity) - print("remove", id) - ode.GeomDestroy(entity.collisionShape) - ode.BodyDestroy(entity.physicsBody) - end, -} -- create shader local shader = honey.Shader{ @@ -132,97 +42,12 @@ local octa = honey.mesh.loadFile("assets/octahedron.obj")[1] local dodeca = honey.mesh.loadFile("assets/dodecahedron.obj")[1] local icosa = honey.mesh.loadFile("assets/icosahedron.obj")[1] --- update function for each entity -function updateTransform(self, dt) - self.transform:rotateY(0.3 * math.pi * dt) - self.transform:rotateX(0.1 * math.pi * dt) -end - --- create entities -function growLine(prev, depth) - if depth == 0 then return prev end - - local entity = { - transform=Mat4():identity():translate(Vec3{2, 0, 0}), - parent=false, - mesh=octa, - shader=shader, - update=updateTransform, - } - prev.parent = entity - level:addEntity(prev) - return growLine(entity, depth-1) -end - -local leaf = { - transform=Mat4():identity():translate(Vec3{2, 0, 0}), - parent=false, - mesh=tetra, - shader=shader, -} -local root = growLine(leaf, 24) -root.update = function(self, dt) - self.transform:rotateY(0.2 * math.pi * dt) -end -level:addEntity(root) - -local groundPlane = { - transform=Mat4():identity():translate(Vec3{0, -2, 0}):scale(Vec3{10, 10, 10}), - parent=false, - mesh=plane, - shader=shader, -} -level:addEntity(groundPlane) - - -local function createNewBall() - local ball = { - transform=Mat4():identity(), - parent=false, - mesh=icosa, - shader=shader, - collisionShape=ode.CreateSphere(space, 1.0), - physicsBody=ode.BodyCreate(world), - } - - local id = level:addEntity(ball) - ball.id = id - table.insert(balls, id) - if #balls > 200 then - level:removeEntity(table.remove(balls, 1)) - end - - local mass = ode.MassCreate() - ode.MassSetSphere(mass, 1, 0.5) - ode.BodySetMass(ball.physicsBody, mass) - local function tiny() return (6 * math.random()) - 3 end - local x, y, z = tiny(), tiny(), tiny() - ode.GeomSetBody(ball.collisionShape, ball.physicsBody) - ode.BodySetPosition(ball.physicsBody, x, y, z) - ode.BodySetLinearVel(ball.physicsBody, x, y, z) - ode.GeomSetData(ball.collisionShape, ball) -end -createNewBall() - -ode.CreatePlane(space, 0, 1, 0, -2) -- 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) - elseif key == glfw.KEY_SPACE then - paused = not paused - elseif - key == glfw.KEY_Z or - key == glfw.KEY_X or - key == glfw.KEY_C or - key == glfw.KEY_V or - key == glfw.KEY_B or - key == glfw.KEY_N or - key == glfw.KEY_M - then - createNewBall() end end end) @@ -248,15 +73,47 @@ function averager(memory) end local fpsAverage = averager(200) + +-- setup ecs +local edb = ecs.EntityDb() +local sdb = ecs.SystemDb() + +sdb:addSystem{ + update = function(self, dt) + local entities = self.db:queryComponent("renderMesh") + for entity, tbl in pairs(entities) do + tbl.shader:use() + tbl.shader:configure{matrix={ + view=camera.view, + projection=camera.projection, + model=Mat4():identity(), + }} + local mesh = honey.mesh.loadMesh(tbl.mesh.filename, tbl.mesh.index) + mesh:drawElements() + end + end, + db = edb, + priority = 99, +} + + +local id = edb:createEntity() +edb:addComponent(id, "renderMesh", { + shader = shader, + mesh = { filename="assets/icosahedron.obj", index=1 }, +}) + + + -- main loop honey.loop(window, function(dt) gl.ClearColor(0.2, 0.4, 1.0, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT + gl.STENCIL_BUFFER_BIT) - gl.UseProgram(0) gl.Enable(gl.DEPTH_TEST) + gl.Disable(gl.CULL_FACE) - level:update(dt, paused) + sdb:update(dt) nvg.BeginFrame(vg, vw, vh, 1.0) nvg.StrokeColor(vg, nvg.RGBf(1, 1, 1)) nvg.FontFace(vg, "November") -- cgit v1.2.1