diff options
author | sanine <sanine.not@pm.me> | 2022-10-03 14:20:47 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-10-03 14:20:47 -0500 |
commit | 94fbc0a7d62c5b48eeb056419bc841d4db8f91b4 (patch) | |
tree | ea4b7682d94df1a55f4140a02ab3abd487500f03 | |
parent | c5fc66ee58f2c60f2d226868bb1cf5b91badaf53 (diff) |
add basic bouncing ball
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | demo/bouncing_ball/ball.dae | 69 | ||||
-rw-r--r-- | demo/bouncing_ball/fragment.fs | 10 | ||||
-rw-r--r-- | demo/bouncing_ball/main.lua | 136 | ||||
-rw-r--r-- | demo/bouncing_ball/mesh.lua | 97 | ||||
-rw-r--r-- | demo/bouncing_ball/shader.lua | 65 | ||||
-rw-r--r-- | demo/bouncing_ball/vertex.vs | 15 | ||||
-rw-r--r-- | demo/fancy/container.jpg (renamed from demo/container.jpg) | bin | 184939 -> 184939 bytes | |||
-rw-r--r-- | demo/fancy/example_sound.ogg (renamed from demo/example_sound.ogg) | bin | 1089524 -> 1089524 bytes | |||
-rw-r--r-- | demo/fancy/honey.lua (renamed from demo/honey.lua) | 0 | ||||
-rw-r--r-- | demo/fancy/suzanne.dae (renamed from demo/suzanne.dae) | 0 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/ode/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/ode/ode_bindings.c | 563 | ||||
-rw-r--r-- | src/ode/ode_bindings.h | 8 |
15 files changed, 976 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 911b8ba..54d6771 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ add_subdirectory(${LIB_ROOT}/ode-0.16.1) set(HONEY_SOURCE ${SRC_ROOT}/main.c) add_executable(honey ${HONEY_SOURCE}) -set(LIBRARIES lua5.1 honeysuckle glfw cargs assimp cairo ode) +set(LIBRARIES lua5.1 honeysuckle glfw cargs assimp cairo ODE) if (WIN32) set(LIBRARIES ${LIBRARIES} opengl32) else() @@ -73,3 +73,4 @@ add_subdirectory(${SRC_ROOT}/options) add_subdirectory(${SRC_ROOT}/test) add_subdirectory(${SRC_ROOT}/util) add_subdirectory(${SRC_ROOT}/import) +add_subdirectory(${SRC_ROOT}/ode) diff --git a/demo/bouncing_ball/ball.dae b/demo/bouncing_ball/ball.dae new file mode 100644 index 0000000..3e87e7c --- /dev/null +++ b/demo/bouncing_ball/ball.dae @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <asset> + <contributor> + <author>Blender User</author> + <authoring_tool>Blender 2.82.7</authoring_tool> + </contributor> + <created>2022-10-02T00:43:40</created> + <modified>2022-10-02T00:43:40</modified> + <unit name="meter" meter="1"/> + <up_axis>Z_UP</up_axis> + </asset> + <library_images/> + <library_geometries> + <geometry id="Icosphere-mesh" name="Icosphere"> + <mesh> + <source id="Icosphere-mesh-positions"> + <float_array id="Icosphere-mesh-positions-array" count="126">0 0 -1 0.7236073 -0.5257253 -0.4472195 -0.276388 -0.8506492 -0.4472199 -0.8944262 0 -0.4472156 -0.276388 0.8506492 -0.4472199 0.7236073 0.5257253 -0.4472195 0.276388 -0.8506492 0.4472199 -0.7236073 -0.5257253 0.4472195 -0.7236073 0.5257253 0.4472195 0.276388 0.8506492 0.4472199 0.8944262 0 0.4472156 0 0 1 -0.1624555 -0.4999952 -0.8506544 0.4253227 -0.3090114 -0.8506542 0.2628688 -0.8090116 -0.5257377 0.8506479 0 -0.5257359 0.4253227 0.3090114 -0.8506542 -0.5257298 0 -0.8506517 -0.6881894 -0.4999969 -0.5257362 -0.1624555 0.4999952 -0.8506544 -0.6881894 0.4999969 -0.5257362 0.2628688 0.8090116 -0.5257377 0.9510579 -0.3090126 0 0.9510579 0.3090126 0 0 -1 0 0.5877856 -0.8090167 0 -0.9510579 -0.3090126 0 -0.5877856 -0.8090167 0 -0.5877856 0.8090167 0 -0.9510579 0.3090126 0 0.5877856 0.8090167 0 0 1 0 0.6881894 -0.4999969 0.5257362 -0.2628688 -0.8090116 0.5257377 -0.8506479 0 0.5257359 -0.2628688 0.8090116 0.5257377 0.6881894 0.4999969 0.5257362 0.1624555 -0.4999952 0.8506544 0.5257298 0 0.8506517 -0.4253227 -0.3090114 0.8506542 -0.4253227 0.3090114 0.8506542 0.1624555 0.4999952 0.8506544</float_array> + <technique_common> + <accessor source="#Icosphere-mesh-positions-array" count="42" stride="3"> + <param name="X" type="float"/> + <param name="Y" type="float"/> + <param name="Z" type="float"/> + </accessor> + </technique_common> + </source> + <source id="Icosphere-mesh-normals"> + <float_array id="Icosphere-mesh-normals-array" count="240">0.1023808 -0.3150898 -0.9435235 0.7002239 -0.2680318 -0.6616989 -0.2680341 -0.1947365 -0.9435229 -0.2680341 0.1947365 -0.9435229 0.1023808 0.3150898 -0.9435235 0.9049892 -0.2680314 -0.3303846 0.02474659 -0.9435213 -0.3303864 -0.8896974 -0.3150947 -0.3303847 -0.574602 0.7487835 -0.3303876 0.534576 0.7778645 -0.3303867 0.802609 -0.5831265 -0.1256273 -0.3065689 -0.9435216 -0.125629 -0.9920774 0 -0.1256283 -0.3065689 0.9435216 -0.125629 0.802609 0.5831265 -0.1256273 0.408946 -0.6284251 0.6616986 -0.4712998 -0.5831221 0.6616986 -0.7002239 0.2680318 0.6616989 0.03853034 0.7487791 0.6616988 0.7240421 0.1947361 0.6616955 0.2680341 0.1947365 0.9435229 0.4911195 0.356821 0.7946575 0.408946 0.6284253 0.6616986 -0.1023808 0.3150899 0.9435235 -0.1875938 0.5773454 0.7946577 -0.4712998 0.5831222 0.6616986 -0.3313045 0 0.9435239 -0.6070606 0 0.7946557 -0.7002239 -0.2680319 0.6616989 -0.1023808 -0.3150899 0.9435235 -0.1875939 -0.5773454 0.7946577 0.03853034 -0.7487791 0.6616988 0.2680341 -0.1947366 0.9435229 0.4911196 -0.356821 0.7946575 0.7240421 -0.1947361 0.6616955 0.8896973 0.3150947 0.3303848 0.7946557 0.5773479 0.187595 0.574602 0.7487835 0.3303875 -0.02474659 0.9435213 0.3303865 -0.3035309 0.9341715 0.1875973 -0.534576 0.7778646 0.3303866 -0.9049891 0.2680313 0.3303845 -0.9822458 0 0.1875985 -0.9049891 -0.2680313 0.3303845 -0.534576 -0.7778646 0.3303866 -0.3035309 -0.9341715 0.1875974 -0.02474659 -0.9435213 0.3303865 0.574602 -0.7487835 0.3303875 0.7946557 -0.5773479 0.1875951 0.8896973 -0.3150947 0.3303848 0.3065689 0.9435216 0.1256287 0.3035309 0.9341715 -0.1875974 0.02474659 0.9435213 -0.3303864 -0.802609 0.5831265 0.1256273 -0.7946557 0.5773479 -0.1875951 -0.8896974 0.3150947 -0.3303847 -0.802609 -0.5831265 0.1256273 -0.7946557 -0.5773479 -0.187595 -0.574602 -0.7487835 -0.3303875 0.3065689 -0.9435216 0.1256287 0.3035309 -0.9341715 -0.1875973 0.5345759 -0.7778645 -0.3303867 0.9920774 0 0.1256283 0.9822458 0 -0.1875985 0.9049891 0.2680313 -0.3303845 0.4712998 0.5831221 -0.6616986 0.1875942 0.5773454 -0.7946577 -0.03853058 0.7487792 -0.6616986 -0.408946 0.6284253 -0.6616986 -0.4911196 0.356821 -0.7946575 -0.7240421 0.1947361 -0.6616955 -0.7240421 -0.1947361 -0.6616955 -0.4911196 -0.356821 -0.7946575 -0.408946 -0.6284253 -0.6616986 0.7002239 0.2680319 -0.6616989 0.6070606 0 -0.7946556 0.3313045 0 -0.9435239 -0.03853058 -0.7487792 -0.6616986 0.1875942 -0.5773454 -0.7946577 0.4712998 -0.5831221 -0.6616986</float_array> + <technique_common> + <accessor source="#Icosphere-mesh-normals-array" count="80" stride="3"> + <param name="X" type="float"/> + <param name="Y" type="float"/> + <param name="Z" type="float"/> + </accessor> + </technique_common> + </source> + <source id="Icosphere-mesh-map-0"> + <float_array id="Icosphere-mesh-map-0-array" count="480">0.818181 0 0.7727265 0.07873046 0.8636355 0.07873046 0.727272 0.157461 0.6818175 0.07873046 0.636363 0.157461 0.090909 0 0.0454545 0.07873046 0.1363635 0.07873046 0.272727 0 0.2272725 0.07873046 0.3181815 0.07873046 0.454545 0 0.4090905 0.07873046 0.4999995 0.07873046 0.727272 0.157461 0.636363 0.157461 0.6818175 0.236191 0.90909 0.157461 0.818181 0.157461 0.8636355 0.236191 0.181818 0.157461 0.090909 0.157461 0.1363635 0.236191 0.363636 0.157461 0.272727 0.157461 0.3181815 0.236191 0.545454 0.157461 0.454545 0.157461 0.4999995 0.236191 0.727272 0.157461 0.6818175 0.236191 0.7727265 0.236191 0.90909 0.157461 0.8636355 0.236191 0.954545 0.236191 0.181818 0.157461 0.1363635 0.236191 0.2272725 0.236191 0.363636 0.157461 0.3181815 0.236191 0.4090905 0.236191 0.545454 0.157461 0.4999995 0.236191 0.5909085 0.236191 0.818181 0.314921 0.727272 0.314921 0.7727265 0.3936515 1 0.314921 0.9090905 0.314921 0.954545 0.3936515 0.272727 0.314921 0.181818 0.314921 0.2272725 0.3936515 0.454545 0.314921 0.363636 0.314921 0.4090905 0.3936515 0.636363 0.314921 0.545454 0.314921 0.5909085 0.3936515 0.5909085 0.3936515 0.4999995 0.3936515 0.545454 0.472382 0.5909085 0.3936515 0.545454 0.314921 0.4999995 0.3936515 0.545454 0.314921 0.454545 0.314921 0.4999995 0.3936515 0.4090905 0.3936515 0.3181815 0.3936515 0.363636 0.472382 0.4090905 0.3936515 0.363636 0.314921 0.3181815 0.3936515 0.363636 0.314921 0.272727 0.314921 0.3181815 0.3936515 0.2272725 0.3936515 0.1363635 0.3936515 0.181818 0.472382 0.2272725 0.3936515 0.181818 0.314921 0.1363635 0.3936515 0.181818 0.314921 0.090909 0.314921 0.1363635 0.3936515 0.954545 0.3936515 0.8636355 0.3936515 0.90909 0.472382 0.954545 0.3936515 0.9090905 0.314921 0.8636355 0.3936515 0.9090905 0.314921 0.818181 0.314921 0.8636355 0.3936515 0.7727265 0.3936515 0.6818175 0.3936515 0.727272 0.472382 0.7727265 0.3936515 0.727272 0.314921 0.6818175 0.3936515 0.727272 0.314921 0.636363 0.314921 0.6818175 0.3936515 0.5909085 0.236191 0.545454 0.314921 0.636363 0.314921 0.5909085 0.236191 0.4999995 0.236191 0.545454 0.314921 0.4999995 0.236191 0.454545 0.314921 0.545454 0.314921 0.4090905 0.236191 0.363636 0.314921 0.454545 0.314921 0.4090905 0.236191 0.3181815 0.236191 0.363636 0.314921 0.3181815 0.236191 0.272727 0.314921 0.363636 0.314921 0.2272725 0.236191 0.181818 0.314921 0.272727 0.314921 0.2272725 0.236191 0.1363635 0.236191 0.181818 0.314921 0.1363635 0.236191 0.090909 0.314921 0.181818 0.314921 0.954545 0.236191 0.9090905 0.314921 1 0.314921 0.954545 0.236191 0.8636355 0.236191 0.9090905 0.314921 0.8636355 0.236191 0.818181 0.314921 0.9090905 0.314921 0.7727265 0.236191 0.727272 0.314921 0.818181 0.314921 0.7727265 0.236191 0.6818175 0.236191 0.727272 0.314921 0.6818175 0.236191 0.636363 0.314921 0.727272 0.314921 0.4999995 0.236191 0.4090905 0.236191 0.454545 0.314921 0.4999995 0.236191 0.454545 0.157461 0.4090905 0.236191 0.454545 0.157461 0.363636 0.157461 0.4090905 0.236191 0.3181815 0.236191 0.2272725 0.236191 0.272727 0.314921 0.3181815 0.236191 0.272727 0.157461 0.2272725 0.236191 0.272727 0.157461 0.181818 0.157461 0.2272725 0.236191 0.1363635 0.236191 0.0454545 0.236191 0.090909 0.314921 0.1363635 0.236191 0.090909 0.157461 0.0454545 0.236191 0.090909 0.157461 0 0.157461 0.0454545 0.236191 0.8636355 0.236191 0.7727265 0.236191 0.818181 0.314921 0.8636355 0.236191 0.818181 0.157461 0.7727265 0.236191 0.818181 0.157461 0.727272 0.157461 0.7727265 0.236191 0.6818175 0.236191 0.5909085 0.236191 0.636363 0.314921 0.6818175 0.236191 0.636363 0.157461 0.5909085 0.236191 0.636363 0.157461 0.545454 0.157461 0.5909085 0.236191 0.4999995 0.07873046 0.454545 0.157461 0.545454 0.157461 0.4999995 0.07873046 0.4090905 0.07873046 0.454545 0.157461 0.4090905 0.07873046 0.363636 0.157461 0.454545 0.157461 0.3181815 0.07873046 0.272727 0.157461 0.363636 0.157461 0.3181815 0.07873046 0.2272725 0.07873046 0.272727 0.157461 0.2272725 0.07873046 0.181818 0.157461 0.272727 0.157461 0.1363635 0.07873046 0.090909 0.157461 0.181818 0.157461 0.1363635 0.07873046 0.0454545 0.07873046 0.090909 0.157461 0.0454545 0.07873046 0 0.157461 0.090909 0.157461 0.636363 0.157461 0.5909085 0.07873046 0.545454 0.157461 0.636363 0.157461 0.6818175 0.07873046 0.5909085 0.07873046 0.6818175 0.07873046 0.636363 0 0.5909085 0.07873046 0.8636355 0.07873046 0.818181 0.157461 0.90909 0.157461 0.8636355 0.07873046 0.7727265 0.07873046 0.818181 0.157461 0.7727265 0.07873046 0.727272 0.157461 0.818181 0.157461</float_array> + <technique_common> + <accessor source="#Icosphere-mesh-map-0-array" count="240" stride="2"> + <param name="S" type="float"/> + <param name="T" type="float"/> + </accessor> + </technique_common> + </source> + <vertices id="Icosphere-mesh-vertices"> + <input semantic="POSITION" source="#Icosphere-mesh-positions"/> + </vertices> + <triangles count="80"> + <input semantic="VERTEX" source="#Icosphere-mesh-vertices" offset="0"/> + <input semantic="NORMAL" source="#Icosphere-mesh-normals" offset="1"/> + <input semantic="TEXCOORD" source="#Icosphere-mesh-map-0" offset="2" set="0"/> + <p>0 0 0 13 0 1 12 0 2 1 1 3 13 1 4 15 1 5 0 2 6 12 2 7 17 2 8 0 3 9 17 3 10 19 3 11 0 4 12 19 4 13 16 4 14 1 5 15 15 5 16 22 5 17 2 6 18 14 6 19 24 6 20 3 7 21 18 7 22 26 7 23 4 8 24 20 8 25 28 8 26 5 9 27 21 9 28 30 9 29 1 10 30 22 10 31 25 10 32 2 11 33 24 11 34 27 11 35 3 12 36 26 12 37 29 12 38 4 13 39 28 13 40 31 13 41 5 14 42 30 14 43 23 14 44 6 15 45 32 15 46 37 15 47 7 16 48 33 16 49 39 16 50 8 17 51 34 17 52 40 17 53 9 18 54 35 18 55 41 18 56 10 19 57 36 19 58 38 19 59 38 20 60 41 20 61 11 20 62 38 21 63 36 21 64 41 21 65 36 22 66 9 22 67 41 22 68 41 23 69 40 23 70 11 23 71 41 24 72 35 24 73 40 24 74 35 25 75 8 25 76 40 25 77 40 26 78 39 26 79 11 26 80 40 27 81 34 27 82 39 27 83 34 28 84 7 28 85 39 28 86 39 29 87 37 29 88 11 29 89 39 30 90 33 30 91 37 30 92 33 31 93 6 31 94 37 31 95 37 32 96 38 32 97 11 32 98 37 33 99 32 33 100 38 33 101 32 34 102 10 34 103 38 34 104 23 35 105 36 35 106 10 35 107 23 36 108 30 36 109 36 36 110 30 37 111 9 37 112 36 37 113 31 38 114 35 38 115 9 38 116 31 39 117 28 39 118 35 39 119 28 40 120 8 40 121 35 40 122 29 41 123 34 41 124 8 41 125 29 42 126 26 42 127 34 42 128 26 43 129 7 43 130 34 43 131 27 44 132 33 44 133 7 44 134 27 45 135 24 45 136 33 45 137 24 46 138 6 46 139 33 46 140 25 47 141 32 47 142 6 47 143 25 48 144 22 48 145 32 48 146 22 49 147 10 49 148 32 49 149 30 50 150 31 50 151 9 50 152 30 51 153 21 51 154 31 51 155 21 52 156 4 52 157 31 52 158 28 53 159 29 53 160 8 53 161 28 54 162 20 54 163 29 54 164 20 55 165 3 55 166 29 55 167 26 56 168 27 56 169 7 56 170 26 57 171 18 57 172 27 57 173 18 58 174 2 58 175 27 58 176 24 59 177 25 59 178 6 59 179 24 60 180 14 60 181 25 60 182 14 61 183 1 61 184 25 61 185 22 62 186 23 62 187 10 62 188 22 63 189 15 63 190 23 63 191 15 64 192 5 64 193 23 64 194 16 65 195 21 65 196 5 65 197 16 66 198 19 66 199 21 66 200 19 67 201 4 67 202 21 67 203 19 68 204 20 68 205 4 68 206 19 69 207 17 69 208 20 69 209 17 70 210 3 70 211 20 70 212 17 71 213 18 71 214 3 71 215 17 72 216 12 72 217 18 72 218 12 73 219 2 73 220 18 73 221 15 74 222 16 74 223 5 74 224 15 75 225 13 75 226 16 75 227 13 76 228 0 76 229 16 76 230 12 77 231 14 77 232 2 77 233 12 78 234 13 78 235 14 78 236 13 79 237 1 79 238 14 79 239</p> + </triangles> + </mesh> + </geometry> + </library_geometries> + <library_visual_scenes> + <visual_scene id="Scene" name="Scene"> + <node id="Icosphere" name="Icosphere" type="NODE"> + <matrix sid="transform">1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</matrix> + <instance_geometry url="#Icosphere-mesh" name="Icosphere"/> + </node> + </visual_scene> + </library_visual_scenes> + <scene> + <instance_visual_scene url="#Scene"/> + </scene> +</COLLADA>
\ No newline at end of file diff --git a/demo/bouncing_ball/fragment.fs b/demo/bouncing_ball/fragment.fs new file mode 100644 index 0000000..a291d35 --- /dev/null +++ b/demo/bouncing_ball/fragment.fs @@ -0,0 +1,10 @@ +#version 330 core +in vec2 TexCoord; +out vec4 FragColor; + +uniform sampler2D ourTexture; + +void main() +{ + FragColor = vec4(TexCoord.x, TexCoord.y, 0, 1); +} diff --git a/demo/bouncing_ball/main.lua b/demo/bouncing_ball/main.lua new file mode 100644 index 0000000..ecbff7b --- /dev/null +++ b/demo/bouncing_ball/main.lua @@ -0,0 +1,136 @@ +local gl = honey.gl +local window = honey.window + +local Shader = require 'shader' +local Mesh = require 'mesh' + + +--====== initialize opengl ======-- + +gl.Init() +window.setHint(window.hintType.contextVersionMajor, 3) +window.setHint(window.hintType.contextVersionMinor, 3) +window.setHint(window.hintType.openGlProfile, window.profileType.openGlCoreProfile) + + +--====== create window ======-- + +local w = window.create(640, 480, 'bouncing ball demo') +window.makeContextCurrent(w) +gl.InitGlad() +gl.Enable(gl.DEPTH_TEST) + +window.setFramebufferSizeCallback(w, function(_, width, height) + print(string.format("resize: (%d, %d)", width, height)) + gl.setViewport(0, 0, width, height) +end) + + +--===== load mesh and shader =====-- + +local shader = Shader.Load('vertex.vs', 'fragment.fs') +local ball = Mesh.Load('ball.dae') + +--===== set up ode =====-- + +local ode = honey.ode +ode.InitODE() +local world = ode.WorldCreate() +local space = ode.HashSpaceCreate() +ode.WorldSetGravity(world, 0, -10, 0) +ode.WorldSetCFM(world, 1e-5) +ode.CreatePlane(space, 0, 1, 0, 0) +local contactgroup = ode.JointGroupCreate() +local body = ode.BodyCreate(world) +local geom = ode.CreateSphere(space, 0.5) +local mass = ode.MassCreate() +ode.MassSetSphere(mass, 1, 0.5) +ode.BodySetMass(body, mass) +ode.GeomSetBody(geom, body) +ode.BodySetPosition(body, 0, 3, 0) + +function physicsStep() + ode.SpaceCollide(space, function(o1, o2) + local b1 = ode.GeomGetBody(o1) + local b2 = ode.GeomGetBody(o2) + local contact = ode.ContactCreate() + ode.ContactSurfaceSetMode(contact, ode.ContactBounce + ode.ContactSoftCFM) + ode.ContactSurfaceSetMu(contact, ode.Infinity) + ode.ContactSurfaceSetBounce(contact, 0.9) + ode.ContactSurfaceSetBounceVel(contact, 0.1) + ode.ContactSurfaceSetSoftCFM(contact, 0.001) + local collisionCount = ode.Collide(o1, o2, contact) + if collisionCount > 0 then + local joint = ode.JointCreateContact(world, contactgroup, contact) + ode.JointAttach(joint, b1, b2) + end + end) + ode.WorldQuickStep(world, 0.01) + ode.JointGroupEmpty(contactgroup) +end + + +--====== matrices ======-- + +function setVector(vector, x, y, z) + honey.glm.vec3_set(vector, 0, x) + honey.glm.vec3_set(vector, 1, y) + honey.glm.vec3_set(vector, 2, z) +end + +local view = honey.glm.mat4() +honey.glm.mat4_identity(view) +local translation = honey.glm.vec3() +setVector(translation, 0, -1, -6) +honey.glm.translate(view, translation) + +local projection = honey.glm.mat4() +honey.glm.perspective(math.rad(45), 800/600, 0.1, 1000, projection) + + +--====== main loop ======-- + +local ballPosition = honey.glm.vec3() +setVector(ballPosition, ode.BodyGetPosition(body)) + +local time = 0 +local dtAverage = 0 +local dtCount = 0 + +while not window.shouldClose(w) do + local newTime = window.getTime() + local dt = newTime - time + dtAverage = dtAverage + dt + dtCount = dtCount + 1 + if dtCount > 60 then + local fps = dtCount/dtAverage + print(string.format('%0.2f fps', fps)) + dtAverage = 0 + dtCount = 0 + end + time = newTime + + physicsStep() + + gl.ClearColor(0.2, 0.3, 0.3, 1.0) + gl.Clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT) + + setVector(ballPosition, ode.BodyGetPosition(body)) + ball:SetPosition(ballPosition) + + shader:Use() + shader:SetMatrix('model', ball.transform) + shader:SetMatrix('view', view) + shader:SetMatrix('projection', projection) + + + ball:Draw() + + window.swapBuffers(w) + window.pollEvents() +end + +--===== shut down =====-- + +window.destroy(w) +gl.Terminate() diff --git a/demo/bouncing_ball/mesh.lua b/demo/bouncing_ball/mesh.lua new file mode 100644 index 0000000..cc957cd --- /dev/null +++ b/demo/bouncing_ball/mesh.lua @@ -0,0 +1,97 @@ +local Mesh = {} +local gl = honey.gl +setmetatable(Mesh, {__index=_G}) +setfenv(1, Mesh) + + +--===== creation =====-- + +local function loadScene(filename) + local scene = honey.import.importFile(filename) + local mesh = scene.meshes[1] + local vertices = {} + + for i=1,#mesh.vertices do + local position = mesh.vertices[i] + local uv = mesh.uvs[1][i] + table.insert(vertices, position.x) + table.insert(vertices, position.y) + table.insert(vertices, position.z) + table.insert(vertices, uv.x) + table.insert(vertices, uv.y) + end + + local elements = {} + for _, face in ipairs(mesh.faces) do + assert(#face == 3) + for _, i in ipairs(face) do + table.insert(elements, i) + end + end + + return vertices, elements +end + + +function Load(filename) + local self = {} + setmetatable(self, {__index=Mesh}) + + self.transform = honey.glm.mat4() + honey.glm.mat4_identity(self.transform) + + -- opengl mesh data + self.vertexArray = gl.GenVertexArrays() + self.vertexBuffer = gl.GenBuffers() + self.elementBuffer = gl.GenBuffers() + + -- load data + local vertices, elements = loadScene(filename) + self.elementCount = #elements + + -- buffer data + gl.BindVertexArray(self.vertexArray) + gl.BindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer) + gl.BufferData(gl.ARRAY_BUFFER, gl.FLOAT, vertices, gl.STATIC_DRAW) + + gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.elementBuffer) + gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.UNSIGNED_INT, elements, gl.STATIC_DRAW) + + -- set vertex attributes + -- position + gl.VertexAttribPointer(0, 3, false, 5, 0) + gl.EnableVertexAttribArray(0) + -- uvs + gl.VertexAttribPointer(1, 2, false, 5, 3) + gl.EnableVertexAttribArray(1) + + return self +end + + +--===== methods =====-- + +local function vectorToTable(v) + local tbl = { + x = honey.glm.vec3_get(v, 0), + y = honey.glm.vec3_get(v, 1), + z = honey.glm.vec3_get(v, 2), + } + return tbl +end + +function SetPosition(self, position) + honey.glm.mat4_identity(self.transform) + honey.glm.translate(self.transform, position) +end + + +function Draw(self) + gl.BindVertexArray(self.vertexArray) + gl.DrawElements(gl.TRIANGLES, self.elementCount, gl.UNSIGNED_INT, 0) +end + + +--===== fin =====-- + +return Mesh diff --git a/demo/bouncing_ball/shader.lua b/demo/bouncing_ball/shader.lua new file mode 100644 index 0000000..50d27ff --- /dev/null +++ b/demo/bouncing_ball/shader.lua @@ -0,0 +1,65 @@ +local Shader = {} +local gl = honey.gl +setmetatable(Shader, {__index=_G}) +setfenv(1, Shader) + + +--===== creation =====-- + +function Create(vertexSource, fragmentSource) + local self = {} + setmetatable(self, {__index=Shader}) + + -- vertex shader + local vertexShader = gl.CreateShader(gl.VERTEX_SHADER) + gl.ShaderSource(vertexShader, vertexSource) + gl.CompileShader(vertexShader) + + -- fragment shader + local fragmentShader = gl.CreateShader(gl.FRAGMENT_SHADER) + gl.ShaderSource(fragmentShader, fragmentSource) + gl.CompileShader(fragmentShader) + + -- link + self.program = gl.CreateProgram() + gl.AttachShader(self.program, vertexShader) + gl.AttachShader(self.program, fragmentShader) + gl.LinkProgram(self.program) + + -- clean up + gl.DeleteShader(vertexShader) + gl.DeleteShader(fragmentShader) + + return self +end + + +function Load(vertexFile, fragmentFile) + local vf = io.open(vertexFile) + local vsource = vf:read('*a') + vf:close() + + local ff = io.open(fragmentFile) + local fsource = ff:read('*a') + ff:close() + + return Create(vsource, fsource) +end + + +--===== methods =====-- + +function Use(self) + gl.UseProgram(self.program) +end + +function SetMatrix(self, name, matrix) + gl.UseProgram(self.program) + local location = gl.GetUniformLocation(self.program, name) + gl.UniformMatrix4fv(location, false, matrix) +end + + +--===== fin =====-- + +return Shader diff --git a/demo/bouncing_ball/vertex.vs b/demo/bouncing_ball/vertex.vs new file mode 100644 index 0000000..017f39c --- /dev/null +++ b/demo/bouncing_ball/vertex.vs @@ -0,0 +1,15 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoord; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +out vec2 TexCoord; + +void main() +{ + gl_Position = projection * view * model * vec4(aPos, 1.0); + TexCoord = aTexCoord; +} diff --git a/demo/container.jpg b/demo/fancy/container.jpg Binary files differindex d07bee4..d07bee4 100644 --- a/demo/container.jpg +++ b/demo/fancy/container.jpg diff --git a/demo/example_sound.ogg b/demo/fancy/example_sound.ogg Binary files differindex 5f97755..5f97755 100644 --- a/demo/example_sound.ogg +++ b/demo/fancy/example_sound.ogg diff --git a/demo/honey.lua b/demo/fancy/honey.lua index 4b1526f..4b1526f 100644 --- a/demo/honey.lua +++ b/demo/fancy/honey.lua diff --git a/demo/suzanne.dae b/demo/fancy/suzanne.dae index 0c70072..0c70072 100644 --- a/demo/suzanne.dae +++ b/demo/fancy/suzanne.dae @@ -9,6 +9,7 @@ #include "import/import.h" #include "logging/logging.h" #include "options/options.h" +#include "ode/ode_bindings.h" void print_load_error(lua_State *L, const char *script_file, int error_type); @@ -34,6 +35,7 @@ int main(int argc, char **argv) setup_import(L, honey_index); setup_logging(L, honey_index); setup_window(L, honey_index); + setup_ode(L, honey_index); lua_setglobal(L, "honey"); /* load main script */ diff --git a/src/ode/CMakeLists.txt b/src/ode/CMakeLists.txt new file mode 100644 index 0000000..83d517a --- /dev/null +++ b/src/ode/CMakeLists.txt @@ -0,0 +1,9 @@ +project(honey_engine) + +target_sources(honey PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/ode_bindings.c +) + + +target_sources(test PUBLIC +) diff --git a/src/ode/ode_bindings.c b/src/ode/ode_bindings.c new file mode 100644 index 0000000..116878a --- /dev/null +++ b/src/ode/ode_bindings.c @@ -0,0 +1,563 @@ +#include <lua.h> +#include <honeysuckle.h> +#include <ode/ode.h> + + +/* setup/teardown */ +int init_ode(lua_State *L); +int close_ode(lua_State *L); + +/* world functions */ +int world_create(lua_State *L); +int world_destroy(lua_State *L); +int world_set_gravity(lua_State *L); +int world_get_gravity(lua_State *L); +int world_set_cfm(lua_State *L); +int world_quickstep(lua_State *L); + +/* space functions */ +int hash_space_create(lua_State *L); +int space_destroy(lua_State *L); +int space_collide(lua_State *L); + +/* joint group functions */ +int joint_group_create(lua_State *L); +int joint_group_destroy(lua_State *L); +int joint_group_empty(lua_State *L); + +/* joint functions */ +int joint_create_contact(lua_State *L); +int joint_attach(lua_State *L); + +/* body functions */ +int body_create(lua_State *L); +int body_set_mass(lua_State *L); +int body_set_position(lua_State *L); +int body_get_position(lua_State *L); +int body_add_force(lua_State *L); +int body_get_force(lua_State *L); +int body_set_linear_vel(lua_State *L); + +/* geom functions */ +int create_sphere(lua_State *L); +int create_plane(lua_State *L); +int geom_get_class(lua_State *L); +int geom_set_body(lua_State *L); +int geom_get_body(lua_State *L); +int collide(lua_State *L); + +/* mass functions */ +int mass_create(lua_State *L); +int mass_set_sphere(lua_State *L); + + +/* contact functions */ +int contact_create(lua_State *L); +int contact_surface_set_mode(lua_State *L); +int contact_surface_set_mu(lua_State *L); +int contact_surface_set_bounce(lua_State *L); +int contact_surface_set_bounce_vel(lua_State *L); +int contact_surface_set_soft_cfm(lua_State *L); + + +#define NEW_METATABLE(name) luaL_newmetatable(L, name); lua_pop(L, 1); +static const char *world_tname = "ode.World"; +static const char *space_tname = "ode.Space"; +static const char *body_tname = "ode.Body"; +static const char *geom_tname = "ode.Geom"; +static const char *mass_tname = "ode.Mass"; +static const char *joint_group_tname = "ode.JointGroup"; +static const char *joint_tname = "ode.Joint"; +static const char *contact_tname = "ode.Contact"; + +void setup_ode(lua_State *L, int honey_tbl) +{ + /* setup metatables */ + NEW_METATABLE(world_tname); + NEW_METATABLE(space_tname); + NEW_METATABLE(body_tname); + NEW_METATABLE(geom_tname); + NEW_METATABLE(mass_tname); + NEW_METATABLE(joint_group_tname); + NEW_METATABLE(joint_tname); + NEW_METATABLE(contact_tname); + + + /* create main table */ + hs_create_table(L, + hs_str_cfunc("InitODE", init_ode), + hs_str_cfunc("CloseODE", close_ode), + + hs_str_cfunc("WorldCreate", world_create), + hs_str_cfunc("WorldDestroy", world_destroy), + hs_str_cfunc("WorldSetGravity", world_set_gravity), + hs_str_cfunc("WorldGetGravity", world_get_gravity), + hs_str_cfunc("WorldSetCFM", world_set_cfm), + hs_str_cfunc("WorldQuickStep", world_quickstep), + + hs_str_cfunc("HashSpaceCreate", hash_space_create), + hs_str_cfunc("SpaceDestroy", space_destroy), + hs_str_cfunc("SpaceCollide", space_collide), + + hs_str_cfunc("JointGroupCreate", joint_group_create), + hs_str_cfunc("JointGroupDestroy", joint_group_destroy), + hs_str_cfunc("JointGroupEmpty", joint_group_empty), + + hs_str_cfunc("JointCreateContact", joint_create_contact), + hs_str_cfunc("JointAttach", joint_attach), + + hs_str_cfunc("BodyCreate", body_create), + hs_str_cfunc("BodySetMass", body_set_mass), + hs_str_cfunc("BodySetPosition", body_set_position), + hs_str_cfunc("BodyGetPosition", body_get_position), + hs_str_cfunc("BodyAddForce", body_add_force), + hs_str_cfunc("BodyGetForce", body_get_force), + hs_str_cfunc("BodySetLinearVel", body_set_linear_vel), + + hs_str_cfunc("CreateSphere", create_sphere), + hs_str_cfunc("CreatePlane", create_plane), + hs_str_cfunc("GeomGetClass", geom_get_class), + hs_str_cfunc("GeomSetBody", geom_set_body), + hs_str_cfunc("GeomGetBody", geom_get_body), + hs_str_cfunc("Collide", collide), + + hs_str_cfunc("MassCreate", mass_create), + hs_str_cfunc("MassSetSphere", mass_set_sphere), + + hs_str_cfunc("ContactCreate", contact_create), + hs_str_cfunc("ContactSurfaceSetMode", contact_surface_set_mode), + hs_str_cfunc("ContactSurfaceSetMu", contact_surface_set_mu), + hs_str_cfunc("ContactSurfaceSetBounce", contact_surface_set_bounce), + hs_str_cfunc("ContactSurfaceSetBounceVel", contact_surface_set_bounce_vel), + hs_str_cfunc("ContactSurfaceSetSoftCFM", contact_surface_set_soft_cfm), + + /* contact surface mode enum */ + hs_str_int("ContactBounce", dContactBounce), + hs_str_int("ContactSoftCFM", dContactSoftCFM), + + /* helpful */ + hs_str_num("Infinity", dInfinity), + ); + + lua_setfield(L, honey_tbl, "ode"); +} + + +/* --===== setup/teardown =====-- */ + +int init_ode(lua_State *L) +{ + dInitODE(); + return 0; +} + + +int close_ode(lua_State *L) +{ + dCloseODE(); + return 0; +} + + +/* --===== world functions =====-- */ + +int world_create(lua_State *L) +{ + dWorldID *world = lua_newuserdata(L, sizeof(dWorldID *)); + *world = dWorldCreate(); + luaL_getmetatable(L, world_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int world_destroy(lua_State *L) +{ + dWorldID *world = luaL_checkudata(L, 1, world_tname); + dWorldDestroy(*world); + return 0; +} + + +int world_set_gravity(lua_State *L) +{ + dWorldID *world = luaL_checkudata(L, 1, world_tname); + double gx = luaL_checknumber(L, 2); + double gy = luaL_checknumber(L, 3); + double gz = luaL_checknumber(L, 4); + dWorldSetGravity(*world, gx, gy, gz); + return 0; +} + + +int world_get_gravity(lua_State *L) +{ + dWorldID *world = luaL_checkudata(L, 1, world_tname); + dVector3 result; + dWorldGetGravity(*world, result); + lua_pushnumber(L, result[0]); + lua_pushnumber(L, result[1]); + lua_pushnumber(L, result[2]); + return 3; +} + + +int world_set_cfm(lua_State *L) +{ + dWorldID *world = luaL_checkudata(L, 1, world_tname); + double cfm = luaL_checknumber(L, 2); + dWorldSetCFM(*world, cfm); + return 0; +} + + +int world_quickstep(lua_State *L) +{ + dWorldID *world = luaL_checkudata(L, 1, world_tname); + double stepsize = luaL_checknumber(L, 2); + dWorldQuickStep(*world, stepsize); + return 0; +} + + +/* --===== space functions =====-- */ + +int hash_space_create(lua_State *L) +{ + dSpaceID *space = lua_newuserdata(L, sizeof(dSpaceID *)); + *space = dHashSpaceCreate(NULL); + luaL_getmetatable(L, space_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int space_destroy(lua_State *L) +{ + dSpaceID *space = luaL_checkudata(L, 1, space_tname); + dSpaceDestroy(*space); + return 0; +} + + +static void near_callback(void *data, dGeomID o1, dGeomID o2) +{ + lua_State *L = data; + lua_pushvalue(L, 2); /* user callback should be at stack index 2 */ + + dGeomID *ptr1 = lua_newuserdata(L, sizeof(dGeomID *)); + *ptr1 = o1; + luaL_getmetatable(L, geom_tname); + lua_setmetatable(L, -2); + + dGeomID *ptr2 = lua_newuserdata(L, sizeof(dGeomID *)); + *ptr2 = o2; + luaL_getmetatable(L, geom_tname); + lua_setmetatable(L, -2); + + lua_call(L, 2, 0); +} + +int space_collide(lua_State *L) +{ + dSpaceID *space = luaL_checkudata(L, 1, space_tname); + luaL_argcheck(L, lua_type(L, 2) == LUA_TFUNCTION, 2, ""); + dSpaceCollide(*space, L, near_callback); + return 0; +} + + +/* --===== joint group functions =====-- */ + +int joint_group_create(lua_State *L) +{ + dJointGroupID *group = lua_newuserdata(L, sizeof(dJointGroupID *)); + *group = dJointGroupCreate(0); + luaL_getmetatable(L, joint_group_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int joint_group_destroy(lua_State *L) +{ + dJointGroupID *group = luaL_checkudata(L, 1, joint_group_tname); + dJointGroupDestroy(*group); + return 0; +} + + +int joint_group_empty(lua_State *L) +{ + dJointGroupID *group = luaL_checkudata(L, 1, joint_group_tname); + dJointGroupEmpty(*group); + return 0; +} + + +/* --===== joint functions =====-- */ + +int joint_create_contact(lua_State *L) +{ + dWorldID *world = luaL_checkudata(L, 1, world_tname); + dJointGroupID group = NULL; + if (lua_type(L, 2) != LUA_TNIL) { + dJointGroupID *ptr = luaL_checkudata(L, 2, joint_group_tname); + group = *ptr; + } + dContact *contact = luaL_checkudata(L, 3, contact_tname); + + dJointID *joint = lua_newuserdata(L, sizeof(dJointID *)); + *joint = dJointCreateContact(*world, group, contact); + luaL_getmetatable(L, joint_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int joint_attach(lua_State *L) +{ + dJointID *joint = luaL_checkudata(L, 1, joint_tname); + dBodyID *body1 = luaL_checkudata(L, 2, body_tname); + dBodyID *body2 = luaL_checkudata(L, 3, body_tname); + + dJointAttach(*joint, *body1, *body2); + return 0; +} + + + + +/* --===== body functions =====-- */ + +int body_create(lua_State *L) +{ + dWorldID *world = luaL_checkudata(L, 1, world_tname); + + dBodyID *body = lua_newuserdata(L, sizeof(dBodyID *)); + *body = dBodyCreate(*world); + luaL_getmetatable(L, body_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int body_set_mass(lua_State *L) +{ + dBodyID *body = luaL_checkudata(L, 1, body_tname); + dMass *mass = luaL_checkudata(L, 2, mass_tname); + + dBodySetMass(*body, mass); + return 0; +} + + +int body_set_position(lua_State *L) +{ + dBodyID *body = luaL_checkudata(L, 1, body_tname); + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + double z = luaL_checknumber(L, 4); + + dBodySetPosition(*body, x, y, z); + return 0; +} + + +int body_get_position(lua_State *L) +{ + dBodyID *body = luaL_checkudata(L, 1, body_tname); + const dReal *pos = dBodyGetPosition(*body); + + lua_pushnumber(L, pos[0]); + lua_pushnumber(L, pos[1]); + lua_pushnumber(L, pos[2]); + return 3; +} + + +int body_add_force(lua_State *L) +{ + dBodyID *body = luaL_checkudata(L, 1, body_tname); + double fx = luaL_checknumber(L, 2); + double fy = luaL_checknumber(L, 3); + double fz = luaL_checknumber(L, 4); + + dBodyAddForce(*body, fx, fy, fz); + return 0; +} + + +int body_get_force(lua_State *L) +{ + dBodyID *body = luaL_checkudata(L, 1, body_tname); + + const dReal *f = dBodyGetForce(*body); + lua_pushnumber(L, f[0]); + lua_pushnumber(L, f[1]); + lua_pushnumber(L, f[2]); + return 3; +} + + +int body_set_linear_vel(lua_State *L) +{ + dBodyID *body = luaL_checkudata(L, 1, body_tname); + double vx = luaL_checknumber(L, 2); + double vy = luaL_checknumber(L, 3); + double vz = luaL_checknumber(L, 4); + + dBodySetLinearVel(*body, vx, vy, vz); + return 0; +} + + +/* --===== geom functions =====-- */ + +int create_sphere(lua_State *L) +{ + dSpaceID *space = luaL_checkudata(L, 1, space_tname); + double radius = luaL_checknumber(L, 2); + + dGeomID *geom = lua_newuserdata(L, sizeof(dGeomID *)); + *geom = dCreateSphere(*space, radius); + luaL_getmetatable(L, geom_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int create_plane(lua_State *L) +{ + dSpaceID *space = luaL_checkudata(L, 1, space_tname); + double a = luaL_checknumber(L, 2); + double b = luaL_checknumber(L, 3); + double c = luaL_checknumber(L, 4); + double d = luaL_checknumber(L, 5); + + dGeomID *geom = lua_newuserdata(L, sizeof(dGeomID *)); + *geom = dCreatePlane(*space, a, b, c, d); + luaL_getmetatable(L, geom_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int geom_get_class(lua_State *L) +{ + dGeomID *geom = luaL_checkudata(L, 1, geom_tname); + int class = dGeomGetClass(*geom); + lua_pushinteger(L, class); + return 1; +} + + +int geom_set_body(lua_State *L) +{ + dGeomID *geom = luaL_checkudata(L, 1, geom_tname); + dBodyID *body = luaL_checkudata(L, 2, body_tname); + dGeomSetBody(*geom, *body); + return 0; +} + + +int geom_get_body(lua_State *L) +{ + dGeomID *geom = luaL_checkudata(L, 1, geom_tname); + + dBodyID *body = lua_newuserdata(L, sizeof(dBodyID *)); + *body = dGeomGetBody(*geom); + luaL_getmetatable(L, body_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int collide(lua_State *L) +{ + dGeomID *o1 = luaL_checkudata(L, 1, geom_tname); + dGeomID *o2 = luaL_checkudata(L, 2, geom_tname); + dContact *contact = luaL_checkudata(L, 3, contact_tname); + + int count = dCollide(*o1, *o2, 1, &(contact->geom), sizeof(dContactGeom)); + lua_pushinteger(L, count); + return 1; +} + + +/* --===== mass functions =====-- */ + +int mass_create(lua_State *L) +{ + lua_newuserdata(L, sizeof(dMass)); + luaL_getmetatable(L, mass_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int mass_set_sphere(lua_State *L) +{ + dMass *mass = luaL_checkudata(L, 1, mass_tname); + double density = luaL_checknumber(L, 2); + double radius = luaL_checknumber(L, 3); + + dMassSetSphere(mass, density, radius); + return 0; +} + + +/* --===== contact functions =====-- */ + +int contact_create(lua_State *L) +{ + lua_newuserdata(L, sizeof(dContact)); + luaL_getmetatable(L, contact_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int contact_surface_set_mode(lua_State *L) +{ + dContact *contact = luaL_checkudata(L, 1, contact_tname); + int mode = luaL_checkinteger(L, 2); + contact->surface.mode = mode; + return 0; +} + + +int contact_surface_set_mu(lua_State *L) +{ + dContact *contact = luaL_checkudata(L, 1, contact_tname); + double mu = luaL_checknumber(L, 2); + contact->surface.mu = mu; + return 0; +} + + +int contact_surface_set_bounce(lua_State *L) +{ + dContact *contact = luaL_checkudata(L, 1, contact_tname); + double bounce = luaL_checknumber(L, 2); + contact->surface.bounce = bounce; + return 0; +} + + +int contact_surface_set_bounce_vel(lua_State *L) +{ + dContact *contact = luaL_checkudata(L, 1, contact_tname); + double bounce_vel = luaL_checknumber(L, 2); + contact->surface.bounce_vel = bounce_vel; + return 0; +} + + +int contact_surface_set_soft_cfm(lua_State *L) +{ + dContact *contact = luaL_checkudata(L, 1, contact_tname); + double soft_cfm = luaL_checknumber(L, 2); + contact->surface.soft_cfm = soft_cfm; + return 0; +} diff --git a/src/ode/ode_bindings.h b/src/ode/ode_bindings.h new file mode 100644 index 0000000..ac1cc35 --- /dev/null +++ b/src/ode/ode_bindings.h @@ -0,0 +1,8 @@ +#ifndef HONEY_ODE_H +#define HONEY_ODE_H + +#include <lua.h> + +void setup_ode(lua_State *L, int honey_tbl); + +#endif |