require 'honey.std' local glfw = honey.glfw local gl = honey.gl local Vec3 = honey.Vec3 local Mat4 = honey.Mat4 local ecs = honey.ecs -- camera matrices local camera = { view=Mat4.Identity(), projection=Mat4(), } camera.view:translate(Vec3{0, 0, -60}) camera.projection:perspective(math.rad(45), 640/480, 0.1, 100) function recursiveComputeTransform(entity) if entity._transformComputed then return entity._transform end if entity.parent == false then entity._transformComputed = true entity._transform = entity.transform return entity.transform end entity._transformComputed = true local parentTransform = recursiveComputeTransform(entity.parent) entity._transform = parentTransform * entity.transform return entity._transform end local level = ecs.Level() -- update transforms level:addSystem{ filter=ecs.Filter.AND{"transform", "parent"}, update=function(entity, dt) recursiveComputeTransform(entity) end, priority=1, } level:addSystem{ filter=ecs.Filter.AND{"transform", "parent"}, update=function(entity, dt) entity._transform = nil entity._transformComputed = false end, priority=0, } -- render objects level:addSystem{ filter=ecs.Filter.AND{"mesh", "shader", "transform"}, update=function(entity, dt) entity.shader:use() entity.shader:configure{ matrix={ model=entity._transform, view=camera.view, projection=camera.projection, }, } entity.mesh:drawElements() end, priority=99, } -- run custom scripts level:addSystem{ filter=ecs.Filter.AND{"update"}, update=function(entity, dt) entity.update(entity, dt) end, priority=50, } local window = honey.init() gl.Enable(gl.DEPTH_TEST) local vertexShaderSource = [[ #version 410 core layout (location = 0) in vec3 in_position; layout (location = 1) in vec3 in_normal; layout (location = 2) in vec2 in_tex; uniform mat4 model; uniform mat4 view; uniform mat4 projection; out vec3 position; out vec3 normal; out vec2 tex; void main() { gl_Position = projection * view * model * vec4(in_position, 1.0); position = in_position; //normal = vec3(model * vec4(in_normal, 1.0f)); normal = in_normal; tex = in_tex; } ]] local fragmentShaderSource = [[ #version 410 core out vec4 FragColor; in vec3 position; in vec3 normal; in vec2 tex; uniform sampler2D ourTexture; void main() { FragColor = vec4(normal, 1.0f); //FragColor = vec4(tex, 1.0f, 1.0f); //FragColor = texture(ourTexture, TexCoord); } ]] local shader = honey.Shader{ vertex = vertexShaderSource, fragment = fragmentShaderSource, } local tetra = honey.mesh.loadFile("assets/tetrahedron.obj")[1] local cube = honey.mesh.loadFile("assets/cube.obj")[1] 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] function updateTransform(self, dt) self.transform:rotateY(0.3 * math.pi * dt) self.transform:rotateX(0.1 * math.pi * dt) end function growLine(prev, depth) if depth == 0 then return prev end local entity = { transform=Mat4.Identity(), mesh=octa, shader=shader, update=updateTransform, } entity.transform:translate(Vec3{2, 0, 0}) prev.parent = entity level:addEntity(prev) return growLine(entity, depth-1) end local leaf = { transform=Mat4.Identity(), mesh=tetra, shader=shader, } local root = growLine(leaf, 24) root.parent = false level:addEntity(root) window:setKeyCallback(function(_, key) if key == glfw.KEY_ESCAPE then window:setShouldClose(true) end end) local prevTime = 0 while not window:shouldClose() do local time = glfw.GetTime() local dt = time - prevTime prevTime = time gl.ClearColor(0.2, 0.4, 1.0, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT) level:update(dt) window:swapBuffers() glfw.PollEvents() end honey.terminate()