summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--honey/ecs-systems.lua54
-rw-r--r--main.lua86
2 files changed, 107 insertions, 33 deletions
diff --git a/honey/ecs-systems.lua b/honey/ecs-systems.lua
index ed51e5d..cfd5675 100644
--- a/honey/ecs-systems.lua
+++ b/honey/ecs-systems.lua
@@ -1,6 +1,10 @@
local ecs = require 'honey.ecs'
+local glm = require 'honey.glm'
+local Vec3 = glm.Vec3
+local Quaternion = glm.Quaternion
local gl = honey.gl
local glfw = honey.glfw
+local ode = honey.ode
local module = {}
@@ -36,6 +40,8 @@ end
transform = function(params)
return {
db = params.db,
+
+ priority = 1,
update = function(self, dt)
local entities = self.db:queryComponent("transform")
@@ -66,7 +72,6 @@ transform = function(params)
recursiveTransform(transform)
end
end,
- priority = 0,
}
end
@@ -160,9 +165,50 @@ physics = function(params)
world=params.world,
contactGroup=ode.JointGroupCreate(groupSize),
time=interval,
+
+ priority=0,
update=function(self, dt)
local query = self.db:queryComponent("physics")
- -- TODO: create physics bodies
+ for id, physics in pairs(query) do
+ if not physics._body then
+ physics._body = ode.BodyCreate(self.world)
+ local mass = ode.MassCreate()
+ local class = physics.mass.class
+ if not class then
+ -- configure mass manually
+ elseif class == "sphere" then
+ ode.MassSetSphere(
+ mass,
+ physics.mass.density,
+ physics.mass.radius
+ )
+ end
+ ode.BodySetMass(physics._body, mass)
+ local m = self.db:getComponent(id, "transform").matrix
+ ode.BodySetPosition(
+ physics._body,
+ m[1][4], m[2][4], m[3][4]
+ )
+ ode.BodySetRotation(
+ physics._body,
+ m[1][1], m[1][2], m[1][3],
+ m[2][1], m[2][2], m[2][3],
+ m[3][1], m[3][2], m[3][3]
+ )
+ ode.BodySetLinearVel(
+ physics._body,
+ physics.velocity[1],
+ physics.velocity[2],
+ physics.velocity[3]
+ )
+ ode.BodySetAngularVel(
+ physics._body,
+ physics.angularVelocity[1],
+ physics.angularVelocity[2],
+ physics.angularVelocity[3]
+ )
+ end
+ end
self.time = self.time + dt
-- only run the update every [interval] seconds
@@ -204,7 +250,9 @@ physics = function(params)
for id, physics in pairs(query) do
local x,y,z = ode.BodyGetPosition(physics._body)
local d,a,b,c = ode.BodyGetQuaternion(physics._body)
- entity.transform
+ local transform = self.db:getComponent(id, "transform")
+ local q = Quaternion{a,b,c,d}
+ transform.matrix
:identity()
:translate(Vec3{x,y,z})
:mul(Quaternion{a,b,c,d}:toMat4())
diff --git a/main.lua b/main.lua
index a686daa..16e27e6 100644
--- a/main.lua
+++ b/main.lua
@@ -7,6 +7,7 @@ local Mat4 = honey.Mat4
local Quaternion = honey.Quaternion
local ecs = honey.ecs
local sys = honey.standardSystems
+local dispatch = sys.dispatch
local ode = honey.ode
local nvg = honey.nvg
@@ -19,6 +20,16 @@ local vg = nvg.CreateContext()
local november = nvg.CreateFont(vg, "November", "assets/november.regular.ttf")
local vw, vh = 640, 480
+-- setup physics
+local space = ode.HashSpaceCreate(ode.Space0)
+local world = ode.WorldCreate()
+ode.WorldSetGravity(world, 0, -10, 0)
+ode.WorldSetCFM(world, 1e-5)
+local physicsGc = honey.util.gc_canary(function()
+ ode.SpaceDestroy(space)
+ ode.WorldDestroy(world)
+end)
+
-- setup ecs
local entities = ecs.EntityDb()
@@ -32,63 +43,78 @@ entities:addComponents(camera, {
transform={
matrix=Mat4():identity():translate(Vec3{0, 0, -6}),
},
+ z = {value=-6},
script={
script="cameraRotationScript",
},
+ onKey = {
+ script="cameraKeyHandler",
+ },
})
---entities:addComponent(camera, "camera", {
--- projection=Mat4():perspective(math.rad(45), 640/480, 0.1, 100),
---})
---entities:addComponent(camera, "transform", {
--- matrix=Mat4():identity():translate(Vec3{0, 0, -6}),
---})
---entities:addComponent(camera, "script", {
--- name = "cameraRotationScript",
---})
---
systems:addSystem(sys.transform)
systems:addSystem(sys.renderCamera, {camera=camera})
systems:addSystem(sys.script)
+systems:addSystem(sys.physics, {space=space, world=world})
package.loaded['baseRotationScript'] = function(entities, id, dt)
local transform = entities:getComponent(id, "transform")
transform.matrix:rotateZ(math.pi * dt)
end
package.loaded['cameraRotationScript'] = function(entities, id, dt)
local transform = entities:getComponent(id, "transform")
- transform.matrix:identity():translate(Vec3{0, 0, -6 + math.sin(math.pi * glfw.GetTime())})
+ local z = entities:getComponent(id, "z")
+ transform.matrix
+ :identity()
+ :translate(Vec3{0, 0, z.value + math.sin(math.pi * glfw.GetTime())})
+end
+package.loaded['cameraKeyHandler'] = function(entities, id, data)
+ local z = entities:getComponent(id, "z")
+ if data.key == glfw.KEY_W then
+ z.value = z.value + 1
+ elseif data.key == glfw.KEY_S then
+ z.value = z.value - 1
+ end
end
local id = entities:createEntity()
-entities:addComponent(id, "renderMesh", {
- textures = {
- ourTexture={ filename="77155.png" },
+entities:addComponents(id, {
+ renderMesh = {
+ textures = { ourTexture={ filename="77155.png" } },
+ shader = { vertex="vertex.glsl", fragment="fragment.glsl" },
+ mesh = { filename="assets/icosahedron.obj", index=1 },
+ },
+ transform = {
+ matrix = Mat4():identity():rotateZ(math.rad(45)),
+ },
+ physics = {
+ mass = {
+ class = "sphere",
+ density = 1,
+ radius = 1,
+ },
+ velocity = Vec3{ 0, 0, 0 },
+ angularVelocity = Vec3{ 0, 0, 0 },
},
- shader = { vertex="vertex.glsl", fragment="fragment.glsl" },
- mesh = { filename="assets/icosahedron.obj", index=1 },
-})
-entities:addComponent(id, "transform", {
- matrix = Mat4():identity():rotateZ(math.rad(45)),
-})
-entities:addComponent(id, "script", {
- script = "baseRotationScript",
})
local id2 = entities:createEntity()
-entities:addComponent(id2, "renderMesh", {
- shader = { vertex="vertex.glsl", fragment="fragment.glsl" },
- mesh = { filename="assets/tetrahedron.obj", index=1 },
-})
-entities:addComponent(id2, "transform", {
- parent=id,
- matrix=Mat4():identity():translate(Vec3{0, 2, 0}),
+entities:addComponents(id2, {
+ renderMesh = {
+ shader = { vertex="vertex.glsl", fragment="fragment.glsl" },
+ mesh = { filename="assets/tetrahedron.obj", index=1 },
+ },
+ transform = {
+ parent=id,
+ matrix=Mat4():identity():translate(Vec3{0, 2, 0}),
+ },
})
-- close window on ESCAPE key
window:setKeyCallback(function(_, key, scancode, action)
+ dispatch(entities, "onKey", {key=key, scancode=scancode, action=action})
if action == glfw.PRESS then
if key == glfw.KEY_ESCAPE then
window:setShouldClose(true)
@@ -100,7 +126,7 @@ end)
window:setFramebufferSizeCallback(function(_, width, height)
gl.Viewport(0, 0, width, height)
vw, vh = width, height
- sys.dispatch(entities, "onWindowResize", { width=width, height=height })
+ dispatch(entities, "onWindowResize", { width=width, height=height })
end)
package.loaded["cameraHandleResize"] = function(entities, id, data)