mesh_storage.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /**************************************************************************/
  2. /* mesh_storage.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "mesh_storage.h"
  31. #include "core/math/transform_interpolator.h"
  32. #if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
  33. #include "core/config/project_settings.h"
  34. #endif
  35. RID RendererMeshStorage::multimesh_allocate() {
  36. return _multimesh_allocate();
  37. }
  38. void RendererMeshStorage::multimesh_initialize(RID p_rid) {
  39. _multimesh_initialize(p_rid);
  40. }
  41. void RendererMeshStorage::multimesh_free(RID p_rid) {
  42. _multimesh_free(p_rid);
  43. }
  44. void RendererMeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
  45. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  46. if (mmi) {
  47. mmi->_transform_format = p_transform_format;
  48. mmi->_use_colors = p_use_colors;
  49. mmi->_use_custom_data = p_use_custom_data;
  50. mmi->_num_instances = p_instances;
  51. mmi->_vf_size_xform = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
  52. mmi->_vf_size_color = p_use_colors ? 4 : 0;
  53. mmi->_vf_size_data = p_use_custom_data ? 4 : 0;
  54. mmi->_stride = mmi->_vf_size_xform + mmi->_vf_size_color + mmi->_vf_size_data;
  55. int size_in_floats = p_instances * mmi->_stride;
  56. mmi->_data_curr.resize_zeroed(size_in_floats);
  57. mmi->_data_prev.resize_zeroed(size_in_floats);
  58. mmi->_data_interpolated.resize_zeroed(size_in_floats);
  59. }
  60. _multimesh_allocate_data(p_multimesh, p_instances, p_transform_format, p_use_colors, p_use_custom_data);
  61. }
  62. int RendererMeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
  63. return _multimesh_get_instance_count(p_multimesh);
  64. }
  65. void RendererMeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
  66. _multimesh_set_mesh(p_multimesh, p_mesh);
  67. }
  68. void RendererMeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
  69. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  70. if (mmi && mmi->interpolated) {
  71. ERR_FAIL_COND(p_index >= mmi->_num_instances);
  72. ERR_FAIL_COND(mmi->_vf_size_xform != 12);
  73. int start = p_index * mmi->_stride;
  74. float *ptr = mmi->_data_curr.ptrw();
  75. ptr += start;
  76. const Transform3D &t = p_transform;
  77. ptr[0] = t.basis.rows[0][0];
  78. ptr[1] = t.basis.rows[0][1];
  79. ptr[2] = t.basis.rows[0][2];
  80. ptr[3] = t.origin.x;
  81. ptr[4] = t.basis.rows[1][0];
  82. ptr[5] = t.basis.rows[1][1];
  83. ptr[6] = t.basis.rows[1][2];
  84. ptr[7] = t.origin.y;
  85. ptr[8] = t.basis.rows[2][0];
  86. ptr[9] = t.basis.rows[2][1];
  87. ptr[10] = t.basis.rows[2][2];
  88. ptr[11] = t.origin.z;
  89. _multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
  90. #if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
  91. if (!Engine::get_singleton()->is_in_physics_frame()) {
  92. PHYSICS_INTERPOLATION_WARNING("MultiMesh interpolation is being triggered from outside physics process, this might lead to issues");
  93. }
  94. #endif
  95. return;
  96. }
  97. _multimesh_instance_set_transform(p_multimesh, p_index, p_transform);
  98. }
  99. void RendererMeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
  100. _multimesh_instance_set_transform_2d(p_multimesh, p_index, p_transform);
  101. }
  102. void RendererMeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
  103. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  104. if (mmi && mmi->interpolated) {
  105. ERR_FAIL_COND(p_index >= mmi->_num_instances);
  106. ERR_FAIL_COND(mmi->_vf_size_color == 0);
  107. int start = (p_index * mmi->_stride) + mmi->_vf_size_xform;
  108. float *ptr = mmi->_data_curr.ptrw();
  109. ptr += start;
  110. if (mmi->_vf_size_color == 4) {
  111. for (int n = 0; n < 4; n++) {
  112. ptr[n] = p_color.components[n];
  113. }
  114. } else {
  115. #ifdef DEV_ENABLED
  116. // The options are currently 4 or zero, but just in case this changes in future...
  117. ERR_FAIL_COND(mmi->_vf_size_color != 0);
  118. #endif
  119. }
  120. _multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
  121. return;
  122. }
  123. _multimesh_instance_set_color(p_multimesh, p_index, p_color);
  124. }
  125. void RendererMeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
  126. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  127. if (mmi && mmi->interpolated) {
  128. ERR_FAIL_COND(p_index >= mmi->_num_instances);
  129. ERR_FAIL_COND(mmi->_vf_size_data == 0);
  130. int start = (p_index * mmi->_stride) + mmi->_vf_size_xform + mmi->_vf_size_color;
  131. float *ptr = mmi->_data_curr.ptrw();
  132. ptr += start;
  133. if (mmi->_vf_size_data == 4) {
  134. for (int n = 0; n < 4; n++) {
  135. ptr[n] = p_color.components[n];
  136. }
  137. } else {
  138. #ifdef DEV_ENABLED
  139. // The options are currently 4 or zero, but just in case this changes in future...
  140. ERR_FAIL_COND(mmi->_vf_size_data != 0);
  141. #endif
  142. }
  143. _multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
  144. return;
  145. }
  146. _multimesh_instance_set_custom_data(p_multimesh, p_index, p_color);
  147. }
  148. void RendererMeshStorage::multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) {
  149. _multimesh_set_custom_aabb(p_multimesh, p_aabb);
  150. }
  151. AABB RendererMeshStorage::multimesh_get_custom_aabb(RID p_multimesh) const {
  152. return _multimesh_get_custom_aabb(p_multimesh);
  153. }
  154. RID RendererMeshStorage::multimesh_get_mesh(RID p_multimesh) const {
  155. return _multimesh_get_mesh(p_multimesh);
  156. }
  157. Transform3D RendererMeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
  158. return _multimesh_instance_get_transform(p_multimesh, p_index);
  159. }
  160. Transform2D RendererMeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
  161. return _multimesh_instance_get_transform_2d(p_multimesh, p_index);
  162. }
  163. Color RendererMeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
  164. return _multimesh_instance_get_color(p_multimesh, p_index);
  165. }
  166. Color RendererMeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
  167. return _multimesh_instance_get_custom_data(p_multimesh, p_index);
  168. }
  169. void RendererMeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
  170. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  171. if (mmi && mmi->interpolated) {
  172. ERR_FAIL_COND_MSG(p_buffer.size() != mmi->_data_curr.size(), vformat("Buffer should have %d elements, got %d instead.", mmi->_data_curr.size(), p_buffer.size()));
  173. mmi->_data_curr = p_buffer;
  174. _multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
  175. #if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
  176. if (!Engine::get_singleton()->is_in_physics_frame()) {
  177. PHYSICS_INTERPOLATION_WARNING("MultiMesh interpolation is being triggered from outside physics process, this might lead to issues");
  178. }
  179. #endif
  180. return;
  181. }
  182. _multimesh_set_buffer(p_multimesh, p_buffer);
  183. }
  184. RID RendererMeshStorage::multimesh_get_buffer_rd_rid(RID p_multimesh) const {
  185. return _multimesh_get_buffer_rd_rid(p_multimesh);
  186. }
  187. Vector<float> RendererMeshStorage::multimesh_get_buffer(RID p_multimesh) const {
  188. return _multimesh_get_buffer(p_multimesh);
  189. }
  190. void RendererMeshStorage::multimesh_set_buffer_interpolated(RID p_multimesh, const Vector<float> &p_buffer, const Vector<float> &p_buffer_prev) {
  191. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  192. if (mmi) {
  193. ERR_FAIL_COND_MSG(p_buffer.size() != mmi->_data_curr.size(), vformat("Buffer for current frame should have %d elements, got %d instead.", mmi->_data_curr.size(), p_buffer.size()));
  194. ERR_FAIL_COND_MSG(p_buffer_prev.size() != mmi->_data_prev.size(), vformat("Buffer for previous frame should have %d elements, got %d instead.", mmi->_data_prev.size(), p_buffer_prev.size()));
  195. // We are assuming that mmi->interpolated is the case. (Can possibly assert this?)
  196. // Even if this flag hasn't been set - just calling this function suggests interpolation is desired.
  197. mmi->_data_prev = p_buffer_prev;
  198. mmi->_data_curr = p_buffer;
  199. _multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
  200. #if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
  201. if (!Engine::get_singleton()->is_in_physics_frame()) {
  202. PHYSICS_INTERPOLATION_WARNING("MultiMesh interpolation is being triggered from outside physics process, this might lead to issues");
  203. }
  204. #endif
  205. }
  206. }
  207. void RendererMeshStorage::multimesh_set_physics_interpolated(RID p_multimesh, bool p_interpolated) {
  208. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  209. if (mmi) {
  210. mmi->interpolated = p_interpolated;
  211. }
  212. }
  213. void RendererMeshStorage::multimesh_set_physics_interpolation_quality(RID p_multimesh, RS::MultimeshPhysicsInterpolationQuality p_quality) {
  214. ERR_FAIL_COND((p_quality < 0) || (p_quality > 1));
  215. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  216. if (mmi) {
  217. mmi->quality = (int)p_quality;
  218. }
  219. }
  220. void RendererMeshStorage::multimesh_instance_reset_physics_interpolation(RID p_multimesh, int p_index) {
  221. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  222. if (mmi) {
  223. ERR_FAIL_INDEX(p_index, mmi->_num_instances);
  224. float *w = mmi->_data_prev.ptrw();
  225. const float *r = mmi->_data_curr.ptr();
  226. int start = p_index * mmi->_stride;
  227. for (int n = 0; n < mmi->_stride; n++) {
  228. w[start + n] = r[start + n];
  229. }
  230. }
  231. }
  232. void RendererMeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
  233. return _multimesh_set_visible_instances(p_multimesh, p_visible);
  234. }
  235. int RendererMeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
  236. return _multimesh_get_visible_instances(p_multimesh);
  237. }
  238. AABB RendererMeshStorage::multimesh_get_aabb(RID p_multimesh) {
  239. return _multimesh_get_aabb(p_multimesh);
  240. }
  241. void RendererMeshStorage::_multimesh_add_to_interpolation_lists(RID p_multimesh, MultiMeshInterpolator &r_mmi) {
  242. if (!r_mmi.on_interpolate_update_list) {
  243. r_mmi.on_interpolate_update_list = true;
  244. _interpolation_data.multimesh_interpolate_update_list.push_back(p_multimesh);
  245. }
  246. if (!r_mmi.on_transform_update_list) {
  247. r_mmi.on_transform_update_list = true;
  248. _interpolation_data.multimesh_transform_update_list_curr->push_back(p_multimesh);
  249. }
  250. }
  251. void RendererMeshStorage::InterpolationData::notify_free_multimesh(RID p_rid) {
  252. // If the instance was on any of the lists, remove.
  253. multimesh_interpolate_update_list.erase_multiple_unordered(p_rid);
  254. multimesh_transform_update_lists[0].erase_multiple_unordered(p_rid);
  255. multimesh_transform_update_lists[1].erase_multiple_unordered(p_rid);
  256. }
  257. void RendererMeshStorage::update_interpolation_tick(bool p_process) {
  258. // Detect any that were on the previous transform list that are no longer active,
  259. // we should remove them from the interpolate list.
  260. for (unsigned int n = 0; n < _interpolation_data.multimesh_transform_update_list_prev->size(); n++) {
  261. const RID &rid = (*_interpolation_data.multimesh_transform_update_list_prev)[n];
  262. bool active = true;
  263. // No longer active? (Either the instance deleted or no longer being transformed.)
  264. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
  265. if (mmi && !mmi->on_transform_update_list) {
  266. active = false;
  267. mmi->on_interpolate_update_list = false;
  268. // Make sure the most recent transform is set...
  269. mmi->_data_interpolated = mmi->_data_curr; // TODO: Copy data rather than use Packed = function?
  270. // ... and that both prev and current are the same, just in case of any interpolations.
  271. mmi->_data_prev = mmi->_data_curr;
  272. }
  273. if (!mmi) {
  274. active = false;
  275. }
  276. if (!active) {
  277. _interpolation_data.multimesh_interpolate_update_list.erase(rid);
  278. }
  279. }
  280. if (p_process) {
  281. for (unsigned int i = 0; i < _interpolation_data.multimesh_transform_update_list_curr->size(); i++) {
  282. const RID &rid = (*_interpolation_data.multimesh_transform_update_list_curr)[i];
  283. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
  284. if (mmi) {
  285. // Reset for next tick.
  286. mmi->on_transform_update_list = false;
  287. mmi->_data_prev = mmi->_data_curr;
  288. }
  289. }
  290. }
  291. // If any have left the transform list, remove from the interpolate list.
  292. // We maintain a mirror list for the transform updates, so we can detect when an instance
  293. // is no longer being transformed, and remove it from the interpolate list.
  294. SWAP(_interpolation_data.multimesh_transform_update_list_curr, _interpolation_data.multimesh_transform_update_list_prev);
  295. // Prepare for the next iteration.
  296. _interpolation_data.multimesh_transform_update_list_curr->clear();
  297. }
  298. void RendererMeshStorage::update_interpolation_frame(bool p_process) {
  299. if (p_process) {
  300. // Only need 32 bits for interpolation, don't use real_t.
  301. float f = Engine::get_singleton()->get_physics_interpolation_fraction();
  302. for (unsigned int c = 0; c < _interpolation_data.multimesh_interpolate_update_list.size(); c++) {
  303. const RID &rid = _interpolation_data.multimesh_interpolate_update_list[c];
  304. // We could use the TransformInterpolator here to slerp transforms, but that might be too expensive,
  305. // so just using a Basis lerp for now.
  306. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
  307. if (mmi) {
  308. // Make sure arrays are the correct size.
  309. DEV_ASSERT(mmi->_data_prev.size() == mmi->_data_curr.size());
  310. if (mmi->_data_interpolated.size() < mmi->_data_curr.size()) {
  311. mmi->_data_interpolated.resize(mmi->_data_curr.size());
  312. }
  313. DEV_ASSERT(mmi->_data_interpolated.size() >= mmi->_data_curr.size());
  314. DEV_ASSERT((mmi->_data_curr.size() % mmi->_stride) == 0);
  315. int num = mmi->_data_curr.size() / mmi->_stride;
  316. const float *pf_prev = mmi->_data_prev.ptr();
  317. const float *pf_curr = mmi->_data_curr.ptr();
  318. float *pf_int = mmi->_data_interpolated.ptrw();
  319. bool use_lerp = mmi->quality == 0;
  320. // Temporary transform (needed for swizzling).
  321. Transform3D tp, tc, tr; // (transform prev, curr and result)
  322. // Test for cache friendliness versus doing branchless.
  323. for (int n = 0; n < num; n++) {
  324. // Transform.
  325. if (use_lerp) {
  326. for (int i = 0; i < mmi->_vf_size_xform; i++) {
  327. pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
  328. }
  329. } else {
  330. // Silly swizzling, this will slow things down.
  331. // No idea why it is using this format...
  332. // ... maybe due to the shader.
  333. tp.basis.rows[0][0] = pf_prev[0];
  334. tp.basis.rows[0][1] = pf_prev[1];
  335. tp.basis.rows[0][2] = pf_prev[2];
  336. tp.basis.rows[1][0] = pf_prev[4];
  337. tp.basis.rows[1][1] = pf_prev[5];
  338. tp.basis.rows[1][2] = pf_prev[6];
  339. tp.basis.rows[2][0] = pf_prev[8];
  340. tp.basis.rows[2][1] = pf_prev[9];
  341. tp.basis.rows[2][2] = pf_prev[10];
  342. tp.origin.x = pf_prev[3];
  343. tp.origin.y = pf_prev[7];
  344. tp.origin.z = pf_prev[11];
  345. tc.basis.rows[0][0] = pf_curr[0];
  346. tc.basis.rows[0][1] = pf_curr[1];
  347. tc.basis.rows[0][2] = pf_curr[2];
  348. tc.basis.rows[1][0] = pf_curr[4];
  349. tc.basis.rows[1][1] = pf_curr[5];
  350. tc.basis.rows[1][2] = pf_curr[6];
  351. tc.basis.rows[2][0] = pf_curr[8];
  352. tc.basis.rows[2][1] = pf_curr[9];
  353. tc.basis.rows[2][2] = pf_curr[10];
  354. tc.origin.x = pf_curr[3];
  355. tc.origin.y = pf_curr[7];
  356. tc.origin.z = pf_curr[11];
  357. TransformInterpolator::interpolate_transform_3d(tp, tc, tr, f);
  358. pf_int[0] = tr.basis.rows[0][0];
  359. pf_int[1] = tr.basis.rows[0][1];
  360. pf_int[2] = tr.basis.rows[0][2];
  361. pf_int[4] = tr.basis.rows[1][0];
  362. pf_int[5] = tr.basis.rows[1][1];
  363. pf_int[6] = tr.basis.rows[1][2];
  364. pf_int[8] = tr.basis.rows[2][0];
  365. pf_int[9] = tr.basis.rows[2][1];
  366. pf_int[10] = tr.basis.rows[2][2];
  367. pf_int[3] = tr.origin.x;
  368. pf_int[7] = tr.origin.y;
  369. pf_int[11] = tr.origin.z;
  370. }
  371. pf_prev += mmi->_vf_size_xform;
  372. pf_curr += mmi->_vf_size_xform;
  373. pf_int += mmi->_vf_size_xform;
  374. // Color.
  375. if (mmi->_vf_size_color == 4) {
  376. for (int i = 0; i < 4; i++) {
  377. pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
  378. }
  379. pf_prev += 4;
  380. pf_curr += 4;
  381. pf_int += 4;
  382. }
  383. // Custom data.
  384. if (mmi->_vf_size_data == 4) {
  385. for (int i = 0; i < 4; i++) {
  386. pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
  387. }
  388. pf_prev += 4;
  389. pf_curr += 4;
  390. pf_int += 4;
  391. }
  392. }
  393. _multimesh_set_buffer(rid, mmi->_data_interpolated);
  394. // TODO: Make sure AABBs are constantly up to date through the interpolation?
  395. // NYI.
  396. }
  397. }
  398. }
  399. }