portal_resources.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /**************************************************************************/
  2. /* portal_resources.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 "portal_resources.h"
  31. OccluderResourceHandle PortalResources::occluder_resource_create() {
  32. uint32_t pool_id = 0;
  33. VSOccluder_Resource *occ = _occluder_resource_pool.request(pool_id);
  34. occ->create();
  35. OccluderResourceHandle handle = pool_id + 1;
  36. return handle;
  37. }
  38. void PortalResources::occluder_resource_destroy(OccluderResourceHandle p_handle) {
  39. p_handle--;
  40. // Depending on the occluder resource type, remove the spheres, polys, holes etc
  41. // We can reuse the update methods for this.
  42. VSOccluder_Resource &occ = _occluder_resource_pool[p_handle];
  43. switch (occ.type) {
  44. case VSOccluder_Instance::OT_SPHERE: {
  45. occluder_resource_update_spheres(p_handle + 1, Vector<Plane>());
  46. } break;
  47. case VSOccluder_Instance::OT_MESH: {
  48. occluder_resource_update_mesh(p_handle + 1, Geometry::OccluderMeshData());
  49. } break;
  50. default: {
  51. } break;
  52. }
  53. // This also clears the occluder
  54. occ.create();
  55. _occluder_resource_pool.free(p_handle);
  56. }
  57. void PortalResources::occluder_resource_prepare(OccluderResourceHandle p_handle, VSOccluder_Instance::Type p_type) {
  58. p_handle--;
  59. // depending on the occluder type, remove the spheres etc
  60. VSOccluder_Resource &occ = _occluder_resource_pool[p_handle];
  61. if (occ.type != VSOccluder_Instance::OT_UNDEFINED) {
  62. ERR_PRINT_ONCE("occluder_resource_prepare should be called only once.");
  63. }
  64. occ.type = p_type;
  65. ERR_FAIL_COND(p_type == VSOccluder_Instance::OT_UNDEFINED);
  66. }
  67. void PortalResources::occluder_resource_update_spheres(OccluderResourceHandle p_handle, const Vector<Plane> &p_spheres) {
  68. p_handle--;
  69. VSOccluder_Resource &occ = _occluder_resource_pool[p_handle];
  70. ERR_FAIL_COND(occ.type != VSOccluder_Resource::OT_SPHERE);
  71. // first deal with the situation where the number of spheres has changed (rare)
  72. if (occ.list_ids.size() != p_spheres.size()) {
  73. // not the most efficient, but works...
  74. // remove existing
  75. for (int n = 0; n < occ.list_ids.size(); n++) {
  76. uint32_t id = occ.list_ids[n];
  77. _occluder_local_sphere_pool.free(id);
  78. }
  79. occ.list_ids.clear();
  80. // create new
  81. for (int n = 0; n < p_spheres.size(); n++) {
  82. uint32_t id;
  83. VSOccluder_Sphere *sphere = _occluder_local_sphere_pool.request(id);
  84. sphere->create();
  85. occ.list_ids.push_back(id);
  86. }
  87. }
  88. // new positions
  89. for (int n = 0; n < occ.list_ids.size(); n++) {
  90. uint32_t id = occ.list_ids[n];
  91. VSOccluder_Sphere &sphere = _occluder_local_sphere_pool[id];
  92. sphere.from_plane(p_spheres[n]);
  93. }
  94. // mark as dirty as the world space spheres will be out of date next time this resource is used
  95. occ.revision += 1;
  96. }
  97. void PortalResources::occluder_resource_update_mesh(OccluderResourceHandle p_handle, const Geometry::OccluderMeshData &p_mesh_data) {
  98. p_handle--;
  99. VSOccluder_Resource &occ = _occluder_resource_pool[p_handle];
  100. ERR_FAIL_COND(occ.type != VSOccluder_Resource::OT_MESH);
  101. // mark as dirty, needs world points updating next time this resource is used
  102. occ.revision += 1;
  103. const LocalVectori<Geometry::OccluderMeshData::Face> &faces = p_mesh_data.faces;
  104. const LocalVectori<Vector3> &vertices = p_mesh_data.vertices;
  105. // first deal with the situation where the number of polys has changed (rare)
  106. if (occ.list_ids.size() != faces.size()) {
  107. // not the most efficient, but works...
  108. // remove existing
  109. for (int n = 0; n < occ.list_ids.size(); n++) {
  110. uint32_t id = occ.list_ids[n];
  111. // must also free the holes
  112. VSOccluder_Poly &opoly = _occluder_local_poly_pool[id];
  113. for (int h = 0; h < opoly.num_holes; h++) {
  114. _occluder_local_hole_pool.free(opoly.hole_pool_ids[h]);
  115. // perhaps debug only
  116. opoly.hole_pool_ids[h] = UINT32_MAX;
  117. }
  118. _occluder_local_poly_pool.free(id);
  119. }
  120. occ.list_ids.clear();
  121. // create new
  122. for (int n = 0; n < faces.size(); n++) {
  123. uint32_t id;
  124. VSOccluder_Poly *poly = _occluder_local_poly_pool.request(id);
  125. poly->create();
  126. occ.list_ids.push_back(id);
  127. }
  128. }
  129. // new data
  130. for (int n = 0; n < occ.list_ids.size(); n++) {
  131. uint32_t id = occ.list_ids[n];
  132. VSOccluder_Poly &opoly = _occluder_local_poly_pool[id];
  133. Occlusion::PolyPlane &poly = opoly.poly;
  134. // source face
  135. const Geometry::OccluderMeshData::Face &face = faces[n];
  136. opoly.two_way = face.two_way;
  137. // make sure the number of holes is correct
  138. if (face.holes.size() != opoly.num_holes) {
  139. // slow but hey ho
  140. // delete existing holes
  141. for (int i = 0; i < opoly.num_holes; i++) {
  142. _occluder_local_hole_pool.free(opoly.hole_pool_ids[i]);
  143. opoly.hole_pool_ids[i] = UINT32_MAX;
  144. }
  145. // create any new holes
  146. opoly.num_holes = face.holes.size();
  147. for (int i = 0; i < opoly.num_holes; i++) {
  148. uint32_t hole_id;
  149. VSOccluder_Hole *hole = _occluder_local_hole_pool.request(hole_id);
  150. opoly.hole_pool_ids[i] = hole_id;
  151. hole->create();
  152. }
  153. }
  154. // set up the poly basics, plane and verts
  155. poly.plane = face.plane;
  156. poly.num_verts = MIN(face.indices.size(), Occlusion::PolyPlane::MAX_POLY_VERTS);
  157. for (int c = 0; c < poly.num_verts; c++) {
  158. int vert_index = face.indices[c];
  159. if (vert_index < vertices.size()) {
  160. poly.verts[c] = vertices[vert_index];
  161. } else {
  162. WARN_PRINT_ONCE("occluder_update_mesh : poly index out of range");
  163. }
  164. }
  165. // set up any holes that are present
  166. for (int h = 0; h < opoly.num_holes; h++) {
  167. VSOccluder_Hole &dhole = get_pool_occluder_local_hole(opoly.hole_pool_ids[h]);
  168. const Geometry::OccluderMeshData::Hole &shole = face.holes[h];
  169. dhole.num_verts = shole.indices.size();
  170. dhole.num_verts = MIN(dhole.num_verts, Occlusion::Poly::MAX_POLY_VERTS);
  171. for (int c = 0; c < dhole.num_verts; c++) {
  172. int vert_index = shole.indices[c];
  173. if (vert_index < vertices.size()) {
  174. dhole.verts[c] = vertices[vert_index];
  175. } else {
  176. WARN_PRINT_ONCE("occluder_update_mesh : hole index out of range");
  177. }
  178. } // for c through hole verts
  179. } // for h through holes
  180. } // for n through occluders
  181. }