mesh_storage.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  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, bool p_use_indirect) {
  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, p_use_indirect);
  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_command_buffer_rd_rid(RID p_multimesh) const {
  185. return _multimesh_get_command_buffer_rd_rid(p_multimesh);
  186. }
  187. RID RendererMeshStorage::multimesh_get_buffer_rd_rid(RID p_multimesh) const {
  188. return _multimesh_get_buffer_rd_rid(p_multimesh);
  189. }
  190. Vector<float> RendererMeshStorage::multimesh_get_buffer(RID p_multimesh) const {
  191. return _multimesh_get_buffer(p_multimesh);
  192. }
  193. void RendererMeshStorage::multimesh_set_buffer_interpolated(RID p_multimesh, const Vector<float> &p_buffer, const Vector<float> &p_buffer_prev) {
  194. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  195. if (mmi) {
  196. 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()));
  197. 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()));
  198. // We are assuming that mmi->interpolated is the case. (Can possibly assert this?)
  199. // Even if this flag hasn't been set - just calling this function suggests interpolation is desired.
  200. mmi->_data_prev = p_buffer_prev;
  201. mmi->_data_curr = p_buffer;
  202. _multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
  203. #if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
  204. if (!Engine::get_singleton()->is_in_physics_frame()) {
  205. PHYSICS_INTERPOLATION_WARNING("MultiMesh interpolation is being triggered from outside physics process, this might lead to issues");
  206. }
  207. #endif
  208. }
  209. }
  210. void RendererMeshStorage::multimesh_set_physics_interpolated(RID p_multimesh, bool p_interpolated) {
  211. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  212. if (mmi) {
  213. mmi->interpolated = p_interpolated;
  214. }
  215. }
  216. void RendererMeshStorage::multimesh_set_physics_interpolation_quality(RID p_multimesh, RS::MultimeshPhysicsInterpolationQuality p_quality) {
  217. ERR_FAIL_COND((p_quality < 0) || (p_quality > 1));
  218. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  219. if (mmi) {
  220. mmi->quality = (int)p_quality;
  221. }
  222. }
  223. void RendererMeshStorage::multimesh_instance_reset_physics_interpolation(RID p_multimesh, int p_index) {
  224. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
  225. if (mmi) {
  226. ERR_FAIL_INDEX(p_index, mmi->_num_instances);
  227. float *w = mmi->_data_prev.ptrw();
  228. const float *r = mmi->_data_curr.ptr();
  229. int start = p_index * mmi->_stride;
  230. for (int n = 0; n < mmi->_stride; n++) {
  231. w[start + n] = r[start + n];
  232. }
  233. }
  234. }
  235. void RendererMeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
  236. return _multimesh_set_visible_instances(p_multimesh, p_visible);
  237. }
  238. int RendererMeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
  239. return _multimesh_get_visible_instances(p_multimesh);
  240. }
  241. AABB RendererMeshStorage::multimesh_get_aabb(RID p_multimesh) {
  242. return _multimesh_get_aabb(p_multimesh);
  243. }
  244. void RendererMeshStorage::_multimesh_add_to_interpolation_lists(RID p_multimesh, MultiMeshInterpolator &r_mmi) {
  245. if (!r_mmi.on_interpolate_update_list) {
  246. r_mmi.on_interpolate_update_list = true;
  247. _interpolation_data.multimesh_interpolate_update_list.push_back(p_multimesh);
  248. }
  249. if (!r_mmi.on_transform_update_list) {
  250. r_mmi.on_transform_update_list = true;
  251. _interpolation_data.multimesh_transform_update_list_curr->push_back(p_multimesh);
  252. }
  253. }
  254. void RendererMeshStorage::InterpolationData::notify_free_multimesh(RID p_rid) {
  255. // If the instance was on any of the lists, remove.
  256. multimesh_interpolate_update_list.erase_multiple_unordered(p_rid);
  257. multimesh_transform_update_lists[0].erase_multiple_unordered(p_rid);
  258. multimesh_transform_update_lists[1].erase_multiple_unordered(p_rid);
  259. }
  260. void RendererMeshStorage::update_interpolation_tick(bool p_process) {
  261. // Detect any that were on the previous transform list that are no longer active,
  262. // we should remove them from the interpolate list.
  263. for (unsigned int n = 0; n < _interpolation_data.multimesh_transform_update_list_prev->size(); n++) {
  264. const RID &rid = (*_interpolation_data.multimesh_transform_update_list_prev)[n];
  265. bool active = true;
  266. // No longer active? (Either the instance deleted or no longer being transformed.)
  267. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
  268. if (mmi && !mmi->on_transform_update_list) {
  269. active = false;
  270. mmi->on_interpolate_update_list = false;
  271. // Make sure the most recent transform is set...
  272. mmi->_data_interpolated = mmi->_data_curr; // TODO: Copy data rather than use Packed = function?
  273. // ... and that both prev and current are the same, just in case of any interpolations.
  274. mmi->_data_prev = mmi->_data_curr;
  275. }
  276. if (!mmi) {
  277. active = false;
  278. }
  279. if (!active) {
  280. _interpolation_data.multimesh_interpolate_update_list.erase(rid);
  281. }
  282. }
  283. if (p_process) {
  284. for (unsigned int i = 0; i < _interpolation_data.multimesh_transform_update_list_curr->size(); i++) {
  285. const RID &rid = (*_interpolation_data.multimesh_transform_update_list_curr)[i];
  286. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
  287. if (mmi) {
  288. // Reset for next tick.
  289. mmi->on_transform_update_list = false;
  290. mmi->_data_prev = mmi->_data_curr;
  291. }
  292. }
  293. }
  294. // If any have left the transform list, remove from the interpolate list.
  295. // We maintain a mirror list for the transform updates, so we can detect when an instance
  296. // is no longer being transformed, and remove it from the interpolate list.
  297. SWAP(_interpolation_data.multimesh_transform_update_list_curr, _interpolation_data.multimesh_transform_update_list_prev);
  298. // Prepare for the next iteration.
  299. _interpolation_data.multimesh_transform_update_list_curr->clear();
  300. }
  301. void RendererMeshStorage::update_interpolation_frame(bool p_process) {
  302. if (p_process) {
  303. // Only need 32 bits for interpolation, don't use real_t.
  304. float f = Engine::get_singleton()->get_physics_interpolation_fraction();
  305. for (unsigned int c = 0; c < _interpolation_data.multimesh_interpolate_update_list.size(); c++) {
  306. const RID &rid = _interpolation_data.multimesh_interpolate_update_list[c];
  307. // We could use the TransformInterpolator here to slerp transforms, but that might be too expensive,
  308. // so just using a Basis lerp for now.
  309. MultiMeshInterpolator *mmi = _multimesh_get_interpolator(rid);
  310. if (mmi) {
  311. // Make sure arrays are the correct size.
  312. DEV_ASSERT(mmi->_data_prev.size() == mmi->_data_curr.size());
  313. if (mmi->_data_interpolated.size() < mmi->_data_curr.size()) {
  314. mmi->_data_interpolated.resize(mmi->_data_curr.size());
  315. }
  316. DEV_ASSERT(mmi->_data_interpolated.size() >= mmi->_data_curr.size());
  317. DEV_ASSERT((mmi->_data_curr.size() % mmi->_stride) == 0);
  318. int num = mmi->_data_curr.size() / mmi->_stride;
  319. const float *pf_prev = mmi->_data_prev.ptr();
  320. const float *pf_curr = mmi->_data_curr.ptr();
  321. float *pf_int = mmi->_data_interpolated.ptrw();
  322. bool use_lerp = mmi->quality == 0;
  323. // Temporary transform (needed for swizzling).
  324. Transform3D tp, tc, tr; // (transform prev, curr and result)
  325. // Test for cache friendliness versus doing branchless.
  326. for (int n = 0; n < num; n++) {
  327. // Transform.
  328. if (use_lerp) {
  329. for (int i = 0; i < mmi->_vf_size_xform; i++) {
  330. pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
  331. }
  332. } else {
  333. // Silly swizzling, this will slow things down.
  334. // No idea why it is using this format...
  335. // ... maybe due to the shader.
  336. tp.basis.rows[0][0] = pf_prev[0];
  337. tp.basis.rows[0][1] = pf_prev[1];
  338. tp.basis.rows[0][2] = pf_prev[2];
  339. tp.basis.rows[1][0] = pf_prev[4];
  340. tp.basis.rows[1][1] = pf_prev[5];
  341. tp.basis.rows[1][2] = pf_prev[6];
  342. tp.basis.rows[2][0] = pf_prev[8];
  343. tp.basis.rows[2][1] = pf_prev[9];
  344. tp.basis.rows[2][2] = pf_prev[10];
  345. tp.origin.x = pf_prev[3];
  346. tp.origin.y = pf_prev[7];
  347. tp.origin.z = pf_prev[11];
  348. tc.basis.rows[0][0] = pf_curr[0];
  349. tc.basis.rows[0][1] = pf_curr[1];
  350. tc.basis.rows[0][2] = pf_curr[2];
  351. tc.basis.rows[1][0] = pf_curr[4];
  352. tc.basis.rows[1][1] = pf_curr[5];
  353. tc.basis.rows[1][2] = pf_curr[6];
  354. tc.basis.rows[2][0] = pf_curr[8];
  355. tc.basis.rows[2][1] = pf_curr[9];
  356. tc.basis.rows[2][2] = pf_curr[10];
  357. tc.origin.x = pf_curr[3];
  358. tc.origin.y = pf_curr[7];
  359. tc.origin.z = pf_curr[11];
  360. TransformInterpolator::interpolate_transform_3d(tp, tc, tr, f);
  361. pf_int[0] = tr.basis.rows[0][0];
  362. pf_int[1] = tr.basis.rows[0][1];
  363. pf_int[2] = tr.basis.rows[0][2];
  364. pf_int[4] = tr.basis.rows[1][0];
  365. pf_int[5] = tr.basis.rows[1][1];
  366. pf_int[6] = tr.basis.rows[1][2];
  367. pf_int[8] = tr.basis.rows[2][0];
  368. pf_int[9] = tr.basis.rows[2][1];
  369. pf_int[10] = tr.basis.rows[2][2];
  370. pf_int[3] = tr.origin.x;
  371. pf_int[7] = tr.origin.y;
  372. pf_int[11] = tr.origin.z;
  373. }
  374. pf_prev += mmi->_vf_size_xform;
  375. pf_curr += mmi->_vf_size_xform;
  376. pf_int += mmi->_vf_size_xform;
  377. // Color.
  378. if (mmi->_vf_size_color == 4) {
  379. for (int i = 0; i < 4; i++) {
  380. pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
  381. }
  382. pf_prev += 4;
  383. pf_curr += 4;
  384. pf_int += 4;
  385. }
  386. // Custom data.
  387. if (mmi->_vf_size_data == 4) {
  388. for (int i = 0; i < 4; i++) {
  389. pf_int[i] = Math::lerp(pf_prev[i], pf_curr[i], f);
  390. }
  391. pf_prev += 4;
  392. pf_curr += 4;
  393. pf_int += 4;
  394. }
  395. }
  396. _multimesh_set_buffer(rid, mmi->_data_interpolated);
  397. // TODO: Make sure AABBs are constantly up to date through the interpolation?
  398. // NYI.
  399. }
  400. }
  401. }
  402. }