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, -3}) 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 world = ecs.World() -- update transforms world:addSystem{ filter=ecs.Filter.AND{"transform", "parent"}, update=function(entity, dt) recursiveComputeTransform(entity) end, priority=1, } world:addSystem{ filter=ecs.Filter.AND{"transform", "parent"}, update=function(entity, dt) entity._transform = nil entity._transformComputed = false end, priority=0, } -- render objects world:addSystem{ filter=ecs.Filter.AND{"mesh", "shader", "transform"}, update=function(entity, dt) entity.shader:use() entity.shader:setMatrix('model', entity._transform) entity.shader:setMatrix('view', camera.view) entity.shader:setMatrix('projection', camera.projection) entity.mesh:drawElements() end, priority=99, } 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] local tetraEntity = { parent=false, transform=Mat4.Identity(), mesh=tetra, shader=shader, } local cubeEntity = { parent=tetraEntity, transform=Mat4.Identity(), mesh=cube, shader=shader, } cubeEntity.transform:translate(Vec3{2, 0, 0}) local octaEntity = { parent=cubeEntity, transform=Mat4.Identity(), mesh=octa, shader=shader, } octaEntity.transform:translate(Vec3{2, 0, 0}) world:addEntity(tetraEntity) world:addEntity(cubeEntity) world:addEntity(octaEntity) local prevTime = 0 while not window:shouldClose() do local time = glfw.GetTime() local dt = time - prevTime prevTime = time tetraEntity.transform:identity() tetraEntity.transform:rotateY(0.5 * math.pi * time) tetraEntity.transform:rotateX(0.05 * math.pi * time) --model:scale(0.2 * Vec3{1, 1, 1}) cubeEntity.transform:identity() cubeEntity.transform:translate(Vec3{2, 0, 0}) cubeEntity.transform:rotateY(0.3 * math.pi * time) cubeEntity.transform:rotateX(0.08 * math.pi * time) gl.ClearColor(0.2, 0.4, 1.0, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT) world:update(dt) window:swapBuffers() glfw.PollEvents() end honey.terminate()