wrap_Math.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /**
  2. * Copyright (c) 2006-2013 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "wrap_Math.h"
  21. #include "wrap_RandomGenerator.h"
  22. #include "wrap_BezierCurve.h"
  23. #include "MathModule.h"
  24. #include "BezierCurve.h"
  25. #include <cmath>
  26. #include <iostream>
  27. namespace love
  28. {
  29. namespace math
  30. {
  31. int w_setRandomSeed(lua_State *L)
  32. {
  33. EXCEPT_GUARD(Math::instance.setRandomSeed(luax_checkrandomseed(L, 1));)
  34. return 0;
  35. }
  36. int w_getRandomSeed(lua_State *L)
  37. {
  38. uint32 low = 0, high = 0;
  39. Math::instance.getRandomSeed(low, high);
  40. lua_pushnumber(L, (lua_Number) low);
  41. lua_pushnumber(L, (lua_Number) high);
  42. return 2;
  43. }
  44. int w_random(lua_State *L)
  45. {
  46. return luax_getrandom(L, 1, Math::instance.random());
  47. }
  48. int w_randomNormal(lua_State *L)
  49. {
  50. double stddev = luaL_optnumber(L, 1, 1.0);
  51. double mean = luaL_optnumber(L, 2, 0.0);
  52. double r = Math::instance.randomNormal(stddev);
  53. lua_pushnumber(L, r + mean);
  54. return 1;
  55. }
  56. int w_newRandomGenerator(lua_State *L)
  57. {
  58. RandomGenerator::Seed s;
  59. if (lua_gettop(L) > 0)
  60. s = luax_checkrandomseed(L, 1);
  61. RandomGenerator *t = Math::instance.newRandomGenerator();
  62. if (lua_gettop(L) > 0)
  63. {
  64. bool should_error = false;
  65. try
  66. {
  67. t->setSeed(s);
  68. }
  69. catch (love::Exception &e)
  70. {
  71. t->release();
  72. should_error = true;
  73. lua_pushstring(L, e.what());
  74. }
  75. if (should_error)
  76. return luaL_error(L, "%s", lua_tostring(L, -1));
  77. }
  78. luax_pushtype(L, "RandomGenerator", MATH_RANDOM_GENERATOR_T, t);
  79. return 1;
  80. }
  81. int w_newBezierCurve(lua_State *L)
  82. {
  83. std::vector<Vector> points;
  84. if (lua_istable(L, 1))
  85. {
  86. size_t top = lua_objlen(L, 1);
  87. points.reserve(top / 2);
  88. for (size_t i = 1; i <= top; i += 2)
  89. {
  90. lua_rawgeti(L, 1, i);
  91. lua_rawgeti(L, 1, i+1);
  92. Vector v;
  93. v.x = (float) luaL_checknumber(L, -2);
  94. v.y = (float) luaL_checknumber(L, -1);
  95. points.push_back(v);
  96. lua_pop(L, 2);
  97. }
  98. }
  99. else
  100. {
  101. size_t top = lua_gettop(L);
  102. points.reserve(top / 2);
  103. for (size_t i = 1; i <= top; i += 2)
  104. {
  105. Vector v;
  106. v.x = (float) luaL_checknumber(L, i);
  107. v.y = (float) luaL_checknumber(L, i+1);
  108. points.push_back(v);
  109. }
  110. }
  111. BezierCurve *curve = Math::instance.newBezierCurve(points);
  112. luax_pushtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, curve);
  113. return 1;
  114. }
  115. int w_triangulate(lua_State *L)
  116. {
  117. std::vector<Vertex> vertices;
  118. if (lua_istable(L, 1))
  119. {
  120. size_t top = lua_objlen(L, 1);
  121. vertices.reserve(top / 2);
  122. for (size_t i = 1; i <= top; i += 2)
  123. {
  124. lua_rawgeti(L, 1, i);
  125. lua_rawgeti(L, 1, i+1);
  126. Vertex v;
  127. v.x = (float) luaL_checknumber(L, -2);
  128. v.y = (float) luaL_checknumber(L, -1);
  129. vertices.push_back(v);
  130. lua_pop(L, 2);
  131. }
  132. }
  133. else
  134. {
  135. size_t top = lua_gettop(L);
  136. vertices.reserve(top / 2);
  137. for (size_t i = 1; i <= top; i += 2)
  138. {
  139. Vertex v;
  140. v.x = (float) luaL_checknumber(L, i);
  141. v.y = (float) luaL_checknumber(L, i+1);
  142. vertices.push_back(v);
  143. }
  144. }
  145. if (vertices.size() < 3)
  146. return luaL_error(L, "Need at least 3 vertices to triangulate");
  147. std::vector<Triangle> triangles;
  148. EXCEPT_GUARD(
  149. if (vertices.size() == 3)
  150. triangles.push_back(Triangle(vertices[0], vertices[1], vertices[2]));
  151. else
  152. triangles = Math::instance.triangulate(vertices);
  153. )
  154. lua_createtable(L, triangles.size(), 0);
  155. for (size_t i = 0; i < triangles.size(); ++i)
  156. {
  157. const Triangle &tri = triangles[i];
  158. lua_createtable(L, 6, 0);
  159. lua_pushnumber(L, tri.a.x);
  160. lua_rawseti(L, -2, 1);
  161. lua_pushnumber(L, tri.a.y);
  162. lua_rawseti(L, -2, 2);
  163. lua_pushnumber(L, tri.b.x);
  164. lua_rawseti(L, -2, 3);
  165. lua_pushnumber(L, tri.b.y);
  166. lua_rawseti(L, -2, 4);
  167. lua_pushnumber(L, tri.c.x);
  168. lua_rawseti(L, -2, 5);
  169. lua_pushnumber(L, tri.c.y);
  170. lua_rawseti(L, -2, 6);
  171. lua_rawseti(L, -2, i+1);
  172. }
  173. return 1;
  174. }
  175. int w_isConvex(lua_State *L)
  176. {
  177. std::vector<Vertex> vertices;
  178. if (lua_istable(L, 1))
  179. {
  180. size_t top = lua_objlen(L, 1);
  181. vertices.reserve(top / 2);
  182. for (size_t i = 1; i <= top; i += 2)
  183. {
  184. lua_rawgeti(L, 1, i);
  185. lua_rawgeti(L, 1, i+1);
  186. Vertex v;
  187. v.x = (float) luaL_checknumber(L, -2);
  188. v.y = (float) luaL_checknumber(L, -1);
  189. vertices.push_back(v);
  190. lua_pop(L, 2);
  191. }
  192. }
  193. else
  194. {
  195. size_t top = lua_gettop(L);
  196. vertices.reserve(top / 2);
  197. for (size_t i = 1; i <= top; i += 2)
  198. {
  199. Vertex v;
  200. v.x = (float) luaL_checknumber(L, i);
  201. v.y = (float) luaL_checknumber(L, i+1);
  202. vertices.push_back(v);
  203. }
  204. }
  205. lua_pushboolean(L, Math::instance.isConvex(vertices));
  206. return 1;
  207. }
  208. int w_noise(lua_State *L)
  209. {
  210. float w, x, y, z;
  211. float val;
  212. switch (lua_gettop(L))
  213. {
  214. case 1:
  215. x = (float) luaL_checknumber(L, 1);
  216. val = Math::instance.noise(x);
  217. break;
  218. case 2:
  219. x = (float) luaL_checknumber(L, 1);
  220. y = (float) luaL_checknumber(L, 2);
  221. val = Math::instance.noise(x, y);
  222. break;
  223. case 3:
  224. x = (float) luaL_checknumber(L, 1);
  225. y = (float) luaL_checknumber(L, 2);
  226. z = (float) luaL_checknumber(L, 3);
  227. val = Math::instance.noise(x, y, z);
  228. break;
  229. case 4:
  230. default:
  231. x = (float) luaL_checknumber(L, 1);
  232. y = (float) luaL_checknumber(L, 2);
  233. z = (float) luaL_checknumber(L, 3);
  234. w = (float) luaL_checknumber(L, 4);
  235. val = Math::instance.noise(x, y, z, w);
  236. break;
  237. }
  238. lua_pushnumber(L, (lua_Number) val);
  239. return 1;
  240. }
  241. // List of functions to wrap.
  242. static const luaL_Reg functions[] =
  243. {
  244. { "setRandomSeed", w_setRandomSeed },
  245. { "getRandomSeed", w_getRandomSeed },
  246. { "random", w_random },
  247. { "randomNormal", w_randomNormal },
  248. { "newRandomGenerator", w_newRandomGenerator },
  249. { "newBezierCurve", w_newBezierCurve },
  250. { "triangulate", w_triangulate },
  251. { "isConvex", w_isConvex },
  252. { "noise", w_noise },
  253. { 0, 0 }
  254. };
  255. static const lua_CFunction types[] =
  256. {
  257. luaopen_randomgenerator,
  258. luaopen_beziercurve,
  259. 0
  260. };
  261. extern "C" int luaopen_love_math(lua_State *L)
  262. {
  263. Math::instance.retain();
  264. WrappedModule w;
  265. w.module = &Math::instance;
  266. w.name = "math";
  267. w.flags = MODULE_T;
  268. w.functions = functions;
  269. w.types = types;
  270. int n = luax_register_module(L, w);
  271. return n;
  272. }
  273. } // math
  274. } // love