JSGraphics.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "JSMath.h"
  23. #include "JSGraphics.h"
  24. #include <Atomic/Graphics/Material.h>
  25. #include <Atomic/Graphics/Light.h>
  26. #include <Atomic/Graphics/Octree.h>
  27. #include <Atomic/Graphics/Camera.h>
  28. #include <Atomic/Scene/Node.h>
  29. namespace Atomic
  30. {
  31. static int Light_SetShadowCascade(duk_context* ctx)
  32. {
  33. //CascadeParameters(float split1, float split2, float split3, float split4, float fadeStart, float biasAutoAdjust = 1.0f) :
  34. int numargs = duk_get_top(ctx);
  35. float split1;
  36. float split2;
  37. float split3;
  38. float split4;
  39. float fadeStart;
  40. float biasAutoAdjust = 1.0f;
  41. split1 = (float) duk_to_number(ctx, 0);
  42. split2 = (float) duk_to_number(ctx, 1);
  43. split3 = (float) duk_to_number(ctx, 2);
  44. split4 = (float) duk_to_number(ctx, 3);
  45. fadeStart = (float) duk_to_number(ctx, 4);
  46. if (numargs == 6)
  47. biasAutoAdjust = (float) duk_to_number(ctx, 5);
  48. CascadeParameters cparms(split1, split2, split3, split4, fadeStart, biasAutoAdjust);
  49. duk_push_this(ctx);
  50. Light* light = js_to_class_instance<Light>(ctx, -1, 0);
  51. light->SetShadowCascade(cparms);
  52. return 0;
  53. }
  54. static int Light_SetShadowCascadeParameter(duk_context* ctx)
  55. {
  56. int index = (int) duk_require_number(ctx, 0);
  57. float value = (float) duk_require_number(ctx, 1);
  58. duk_push_this(ctx);
  59. Light* light = js_to_class_instance<Light>(ctx, -1, 0);
  60. CascadeParameters parms = light->GetShadowCascade();
  61. switch (index)
  62. {
  63. case 0:
  64. parms.splits_[0] = value;
  65. break;
  66. case 1:
  67. parms.splits_[1] = value;
  68. break;
  69. case 2:
  70. parms.splits_[2] = value;
  71. break;
  72. case 3:
  73. parms.splits_[3] = value;
  74. break;
  75. case 4:
  76. parms.fadeStart_ = value;
  77. break;
  78. case 5:
  79. parms.biasAutoAdjust_ = value;
  80. break;
  81. }
  82. light->SetShadowCascade(parms);
  83. return 0;
  84. }
  85. static int Light_GetShadowCascade(duk_context* ctx)
  86. {
  87. duk_push_this(ctx);
  88. Light* light = js_to_class_instance<Light>(ctx, -1, 0);
  89. const CascadeParameters& parms = light->GetShadowCascade();
  90. duk_push_array(ctx);
  91. duk_push_number(ctx, parms.splits_[0]);
  92. duk_put_prop_index(ctx, -2, 0);
  93. duk_push_number(ctx, parms.splits_[1]);
  94. duk_put_prop_index(ctx, -2, 1);
  95. duk_push_number(ctx, parms.splits_[2]);
  96. duk_put_prop_index(ctx, -2, 2);
  97. duk_push_number(ctx, parms.splits_[3]);
  98. duk_put_prop_index(ctx, -2, 3);
  99. duk_push_number(ctx, parms.fadeStart_);
  100. duk_put_prop_index(ctx, -2, 4);
  101. duk_push_number(ctx, parms.biasAutoAdjust_);
  102. duk_put_prop_index(ctx, -2, 5);
  103. return 1;
  104. }
  105. static int Light_SetShadowBias(duk_context* ctx)
  106. {
  107. float constantBias = (float) duk_to_number(ctx, 0);
  108. float slopeScaledBias = (float) duk_to_number(ctx, 1);
  109. BiasParameters bparms(constantBias, slopeScaledBias);
  110. duk_push_this(ctx);
  111. Light* light = js_to_class_instance<Light>(ctx, -1, 0);
  112. light->SetShadowBias(bparms);
  113. return 0;
  114. }
  115. // Material
  116. static int Material_SetShaderParameter(duk_context* ctx)
  117. {
  118. duk_push_this(ctx);
  119. Material* material = js_to_class_instance<Material>(ctx, -1, 0);
  120. const char* name = duk_require_string(ctx, 0);
  121. String value = duk_require_string(ctx, 1);
  122. const Variant& v = material->GetShaderParameter(name);
  123. if (v == Variant::EMPTY)
  124. return 0;
  125. Variant vset;
  126. vset.FromString(v.GetType(), value);
  127. material->SetShaderParameter(name, vset);
  128. return 0;
  129. }
  130. static int Material_GetShaderParameters(duk_context* ctx)
  131. {
  132. duk_push_this(ctx);
  133. Material* material = js_to_class_instance<Material>(ctx, -1, 0);
  134. const HashMap<StringHash, MaterialShaderParameter>& params = material->GetShaderParameters();
  135. duk_push_array(ctx);
  136. unsigned j = 0;
  137. for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator i = params.Begin(); i != params.End(); ++i)
  138. {
  139. duk_push_object(ctx);
  140. duk_push_string(ctx, i->second_.name_.CString());
  141. duk_put_prop_string(ctx, -2, "name");
  142. js_push_variant(ctx, i->second_.value_);
  143. duk_put_prop_string(ctx, -2, "value");
  144. duk_push_string(ctx, i->second_.value_.ToString().CString());
  145. duk_put_prop_string(ctx, -2, "valueString");
  146. duk_push_string(ctx, i->second_.value_.GetTypeName().CString());
  147. duk_put_prop_string(ctx, -2, "typeName");
  148. duk_push_number(ctx, (double) i->second_.value_.GetType());
  149. duk_put_prop_string(ctx, -2, "type");
  150. duk_put_prop_index(ctx, -2, j++);
  151. }
  152. return 1;
  153. }
  154. static int Material_GetTextureUnitName(duk_context* ctx)
  155. {
  156. duk_push_string(ctx, Material::GetTextureUnitName((TextureUnit) ((int) duk_get_number(ctx, 0))).CString());
  157. return 1;
  158. }
  159. static int Camera_GetScreenRay(duk_context* ctx)
  160. {
  161. float x = (float) duk_to_number(ctx, 0);
  162. float y = (float) duk_to_number(ctx, 1);
  163. duk_push_this(ctx);
  164. Camera* camera = js_to_class_instance<Camera>(ctx, -1, 0);
  165. Ray ray = camera->GetScreenRay(x, y);
  166. duk_push_new_ray(ctx, ray);
  167. return 1;
  168. }
  169. // Octree Queries
  170. static duk_int_t DUK_MAGIC_RAYCAST = 1;
  171. static duk_int_t DUK_MAGIC_RAYCAST_SINGLE = 2;
  172. static void duk_push_rayqueryresult(duk_context* ctx, const RayQueryResult& result)
  173. {
  174. duk_push_object(ctx);
  175. duk_push_new_vector3(ctx, result.position_);
  176. duk_put_prop_string(ctx, -2, "position");
  177. duk_push_new_vector3(ctx, result.normal_);
  178. duk_put_prop_string(ctx, -2, "normal");
  179. duk_push_new_vector2(ctx, result.textureUV_);
  180. duk_put_prop_string(ctx, -2, "textureUV");
  181. duk_push_number(ctx, result.distance_);
  182. duk_put_prop_string(ctx, -2, "distance");
  183. js_push_class_object_instance(ctx, result.drawable_, "Drawable");
  184. duk_put_prop_string(ctx, -2, "drawable");
  185. js_push_class_object_instance(ctx, result.node_, "Node");
  186. duk_put_prop_string(ctx, -2, "node");
  187. duk_push_number(ctx, (duk_double_t) result.subObject_);
  188. duk_put_prop_string(ctx, -2, "subObject");
  189. }
  190. static int Octree_Raycast(duk_context* ctx)
  191. {
  192. bool single = duk_get_current_magic(ctx) == DUK_MAGIC_RAYCAST_SINGLE;
  193. duk_idx_t nargs = duk_get_top(ctx);
  194. // require at least the ray
  195. if (nargs < 1)
  196. {
  197. duk_push_undefined(ctx);
  198. return 1;
  199. }
  200. Ray ray;
  201. if (!duk_get_ray(ctx, 0, ray))
  202. {
  203. duk_push_undefined(ctx);
  204. return 1;
  205. }
  206. RayQueryLevel level = RAY_TRIANGLE;
  207. if (nargs > 1)
  208. {
  209. unsigned _level = (unsigned) duk_to_number(ctx, 1);
  210. if (_level > (unsigned) RAY_TRIANGLE_UV)
  211. {
  212. duk_push_undefined(ctx);
  213. return 1;
  214. }
  215. level = (RayQueryLevel) _level;
  216. }
  217. float maxDistance = M_INFINITY;
  218. if (nargs > 2)
  219. {
  220. maxDistance = (float) duk_to_number(ctx, 2);
  221. }
  222. unsigned char drawableFlags = DRAWABLE_ANY;
  223. if (nargs > 3)
  224. {
  225. drawableFlags = (unsigned char) duk_to_number(ctx, 3);
  226. }
  227. unsigned viewMask = DEFAULT_VIEWMASK;
  228. if (nargs > 4)
  229. {
  230. viewMask = (unsigned) duk_to_number(ctx, 4);
  231. }
  232. duk_push_this(ctx);
  233. Octree* octree = js_to_class_instance<Octree>(ctx, -1, 0);
  234. PODVector<RayQueryResult> result;
  235. RayOctreeQuery query(result, ray, level, maxDistance, drawableFlags, viewMask);
  236. single ? octree->RaycastSingle(query) : octree->Raycast(query);
  237. // handle case of nothing hit
  238. if (!result.Size())
  239. {
  240. if (single)
  241. duk_push_null(ctx);
  242. else
  243. duk_push_array(ctx);
  244. return 1;
  245. }
  246. else
  247. {
  248. if (single)
  249. {
  250. duk_push_rayqueryresult(ctx, result[0]);
  251. }
  252. else
  253. {
  254. duk_push_array(ctx);
  255. for (unsigned i = 0; i < result.Size(); i++)
  256. {
  257. duk_push_rayqueryresult(ctx, result[i]);
  258. duk_put_prop_index(ctx, -2, i);
  259. }
  260. }
  261. }
  262. return 1;
  263. }
  264. void jsapi_init_graphics(JSVM* vm)
  265. {
  266. duk_context* ctx = vm->GetJSContext();
  267. js_class_get_prototype(ctx, "Atomic", "Light");
  268. duk_push_c_function(ctx, Light_SetShadowCascade, DUK_VARARGS);
  269. duk_put_prop_string(ctx, -2, "setShadowCascade");
  270. duk_push_c_function(ctx, Light_SetShadowCascadeParameter, 2);
  271. duk_put_prop_string(ctx, -2, "setShadowCascadeParameter");
  272. duk_push_c_function(ctx, Light_GetShadowCascade, 0);
  273. duk_put_prop_string(ctx, -2, "getShadowCascade");
  274. duk_push_c_function(ctx, Light_SetShadowBias, 2);
  275. duk_put_prop_string(ctx, -2, "setShadowBias");
  276. duk_pop(ctx);
  277. js_class_get_prototype(ctx, "Atomic", "Material");
  278. duk_push_c_function(ctx, Material_GetShaderParameters, 0);
  279. duk_put_prop_string(ctx, -2, "getShaderParameters");
  280. duk_push_c_function(ctx, Material_SetShaderParameter, 2);
  281. duk_put_prop_string(ctx, -2, "setShaderParameter");
  282. duk_pop(ctx);
  283. js_class_get_prototype(ctx, "Atomic", "Octree");
  284. duk_push_c_function(ctx, Octree_Raycast, DUK_VARARGS);
  285. duk_set_magic(ctx, -1, (unsigned) DUK_MAGIC_RAYCAST);
  286. duk_put_prop_string(ctx, -2, "rayCast");
  287. duk_push_c_function(ctx, Octree_Raycast, DUK_VARARGS);
  288. duk_set_magic(ctx, -1, (unsigned) DUK_MAGIC_RAYCAST_SINGLE);
  289. duk_put_prop_string(ctx, -2, "rayCastSingle");
  290. duk_pop(ctx);
  291. js_class_get_prototype(ctx, "Atomic", "Camera");
  292. duk_push_c_function(ctx, Camera_GetScreenRay, 2);
  293. duk_put_prop_string(ctx, -2, "getScreenRay");
  294. duk_pop(ctx);
  295. // static methods
  296. js_class_get_constructor(ctx, "Atomic", "Material");
  297. duk_push_c_function(ctx, Material_GetTextureUnitName, 1);
  298. duk_put_prop_string(ctx, -2, "getTextureUnitName");
  299. duk_pop(ctx);
  300. }
  301. }