openxr_render_model_extension.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. /**************************************************************************/
  2. /* openxr_render_model_extension.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 "openxr_render_model_extension.h"
  31. #ifdef MODULE_GLTF_ENABLED
  32. #include "../openxr_api.h"
  33. #include "../openxr_interface.h"
  34. #include "core/config/project_settings.h"
  35. #include "core/string/print_string.h"
  36. #include "servers/xr/xr_server.h"
  37. OpenXRRenderModelExtension *OpenXRRenderModelExtension::singleton = nullptr;
  38. OpenXRRenderModelExtension *OpenXRRenderModelExtension::get_singleton() {
  39. return singleton;
  40. }
  41. void OpenXRRenderModelExtension::_bind_methods() {
  42. ClassDB::bind_method(D_METHOD("is_active"), &OpenXRRenderModelExtension::is_active);
  43. ClassDB::bind_method(D_METHOD("render_model_create", "render_model_id"), &OpenXRRenderModelExtension::render_model_create);
  44. ClassDB::bind_method(D_METHOD("render_model_destroy", "render_model"), &OpenXRRenderModelExtension::render_model_destroy);
  45. ClassDB::bind_method(D_METHOD("render_model_get_all"), &OpenXRRenderModelExtension::render_model_get_all);
  46. ClassDB::bind_method(D_METHOD("render_model_new_scene_instance", "render_model"), &OpenXRRenderModelExtension::render_model_new_scene_instance);
  47. ClassDB::bind_method(D_METHOD("render_model_get_subaction_paths", "render_model"), &OpenXRRenderModelExtension::render_model_get_subaction_paths);
  48. ClassDB::bind_method(D_METHOD("render_model_get_top_level_path", "render_model"), &OpenXRRenderModelExtension::render_model_get_top_level_path_as_string);
  49. ClassDB::bind_method(D_METHOD("render_model_get_confidence", "render_model"), &OpenXRRenderModelExtension::render_model_get_confidence);
  50. ClassDB::bind_method(D_METHOD("render_model_get_root_transform", "render_model"), &OpenXRRenderModelExtension::render_model_get_root_transform);
  51. ClassDB::bind_method(D_METHOD("render_model_get_animatable_node_count", "render_model"), &OpenXRRenderModelExtension::render_model_get_animatable_node_count);
  52. ClassDB::bind_method(D_METHOD("render_model_get_animatable_node_name", "render_model", "index"), &OpenXRRenderModelExtension::render_model_get_animatable_node_name);
  53. ClassDB::bind_method(D_METHOD("render_model_is_animatable_node_visible", "render_model", "index"), &OpenXRRenderModelExtension::render_model_is_animatable_node_visible);
  54. ClassDB::bind_method(D_METHOD("render_model_get_animatable_node_transform", "render_model", "index"), &OpenXRRenderModelExtension::render_model_get_animatable_node_transform);
  55. ADD_SIGNAL(MethodInfo("render_model_added", PropertyInfo(Variant::RID, "render_model")));
  56. ADD_SIGNAL(MethodInfo("render_model_removed", PropertyInfo(Variant::RID, "render_model")));
  57. ADD_SIGNAL(MethodInfo("render_model_top_level_path_changed", PropertyInfo(Variant::RID, "render_model")));
  58. }
  59. OpenXRRenderModelExtension::OpenXRRenderModelExtension() {
  60. singleton = this;
  61. }
  62. OpenXRRenderModelExtension::~OpenXRRenderModelExtension() {
  63. singleton = nullptr;
  64. }
  65. HashMap<String, bool *> OpenXRRenderModelExtension::get_requested_extensions(XrVersion p_version) {
  66. HashMap<String, bool *> request_extensions;
  67. if (GLOBAL_GET("xr/openxr/extensions/render_model")) {
  68. if (p_version < XR_API_VERSION_1_1_0) {
  69. // Extension was promoted in OpenXR 1.1, only include it in OpenXR 1.0.
  70. request_extensions[XR_EXT_UUID_EXTENSION_NAME] = &uuid_ext;
  71. }
  72. request_extensions[XR_EXT_RENDER_MODEL_EXTENSION_NAME] = &render_model_ext;
  73. request_extensions[XR_EXT_INTERACTION_RENDER_MODEL_EXTENSION_NAME] = &interaction_render_model_ext;
  74. }
  75. return request_extensions;
  76. }
  77. void OpenXRRenderModelExtension::on_instance_created(const XrInstance p_instance) {
  78. // Standard entry points we use.
  79. EXT_INIT_XR_FUNC(xrLocateSpace);
  80. EXT_INIT_XR_FUNC(xrDestroySpace);
  81. EXT_INIT_XR_FUNC(xrPathToString);
  82. if (render_model_ext) {
  83. EXT_INIT_XR_FUNC(xrCreateRenderModelEXT);
  84. EXT_INIT_XR_FUNC(xrDestroyRenderModelEXT);
  85. EXT_INIT_XR_FUNC(xrGetRenderModelPropertiesEXT);
  86. EXT_INIT_XR_FUNC(xrCreateRenderModelSpaceEXT);
  87. EXT_INIT_XR_FUNC(xrCreateRenderModelAssetEXT);
  88. EXT_INIT_XR_FUNC(xrDestroyRenderModelAssetEXT);
  89. EXT_INIT_XR_FUNC(xrGetRenderModelAssetDataEXT);
  90. EXT_INIT_XR_FUNC(xrGetRenderModelAssetPropertiesEXT);
  91. EXT_INIT_XR_FUNC(xrGetRenderModelStateEXT);
  92. }
  93. if (interaction_render_model_ext) {
  94. EXT_INIT_XR_FUNC(xrEnumerateInteractionRenderModelIdsEXT);
  95. EXT_INIT_XR_FUNC(xrEnumerateRenderModelSubactionPathsEXT);
  96. EXT_INIT_XR_FUNC(xrGetRenderModelPoseTopLevelUserPathEXT);
  97. }
  98. }
  99. void OpenXRRenderModelExtension::on_session_created(const XrSession p_session) {
  100. _interaction_data_dirty = true;
  101. }
  102. void OpenXRRenderModelExtension::on_instance_destroyed() {
  103. xrCreateRenderModelEXT_ptr = nullptr;
  104. xrDestroyRenderModelEXT_ptr = nullptr;
  105. xrGetRenderModelPropertiesEXT_ptr = nullptr;
  106. xrCreateRenderModelSpaceEXT_ptr = nullptr;
  107. xrCreateRenderModelAssetEXT_ptr = nullptr;
  108. xrDestroyRenderModelAssetEXT_ptr = nullptr;
  109. xrGetRenderModelAssetDataEXT_ptr = nullptr;
  110. xrGetRenderModelAssetPropertiesEXT_ptr = nullptr;
  111. xrGetRenderModelStateEXT_ptr = nullptr;
  112. xrEnumerateInteractionRenderModelIdsEXT_ptr = nullptr;
  113. xrEnumerateRenderModelSubactionPathsEXT_ptr = nullptr;
  114. xrGetRenderModelPoseTopLevelUserPathEXT_ptr = nullptr;
  115. uuid_ext = false;
  116. render_model_ext = false;
  117. interaction_render_model_ext = false;
  118. }
  119. void OpenXRRenderModelExtension::on_session_destroyed() {
  120. _clear_interaction_data();
  121. _clear_render_model_data();
  122. // We no longer have valid sync data.
  123. xr_sync_has_run = false;
  124. }
  125. bool OpenXRRenderModelExtension::on_event_polled(const XrEventDataBuffer &event) {
  126. if (event.type == XR_TYPE_EVENT_DATA_INTERACTION_RENDER_MODELS_CHANGED_EXT) {
  127. // Mark interaction data as dirty so that we update it on sync.
  128. _interaction_data_dirty = true;
  129. return true;
  130. } else if (event.type == XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) {
  131. // If our controller bindings changed, its likely our render models change too.
  132. // We should be getting a XR_TYPE_EVENT_DATA_INTERACTION_RENDER_MODELS_CHANGED_EXT
  133. // but checking for this scenario just in case.
  134. _interaction_data_dirty = true;
  135. // Do not consider this handled, we simply do additional logic.
  136. return false;
  137. }
  138. return false;
  139. }
  140. void OpenXRRenderModelExtension::on_sync_actions() {
  141. if (!is_active()) {
  142. return;
  143. }
  144. OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
  145. ERR_FAIL_NULL(openxr_api);
  146. // Mark sync as run
  147. xr_sync_has_run = true;
  148. // Update our interaction data if needed
  149. if (_interaction_data_dirty) {
  150. _update_interaction_data();
  151. }
  152. // Loop through all of our render models to update our space and state info
  153. LocalVector<RID> owned = render_model_owner.get_owned_list();
  154. for (const RID &rid : owned) {
  155. RenderModel *render_model = render_model_owner.get_or_null(rid);
  156. if (render_model && render_model->xr_space != XR_NULL_HANDLE) {
  157. XrSpaceLocation render_model_location = {
  158. XR_TYPE_SPACE_LOCATION, // type
  159. nullptr, // next
  160. 0, // locationFlags
  161. { { 0.0, 0.0, 0.0, 1.0 }, { 0.0, 0.0, 0.0 } }, // pose
  162. };
  163. XrResult result = xrLocateSpace(render_model->xr_space, openxr_api->get_play_space(), openxr_api->get_predicted_display_time(), &render_model_location);
  164. ERR_CONTINUE_MSG(XR_FAILED(result), "OpenXR: Failed to locate render model space [" + openxr_api->get_error_string(result) + "]");
  165. render_model->confidence = openxr_api->transform_from_location(render_model_location, render_model->root_transform);
  166. if (!render_model->node_states.is_empty()) {
  167. // Get node states.
  168. XrRenderModelStateGetInfoEXT get_state_info = {
  169. XR_TYPE_RENDER_MODEL_STATE_GET_INFO_EXT, // type
  170. nullptr, // next
  171. openxr_api->get_predicted_display_time() // displayTime
  172. };
  173. XrRenderModelStateEXT state = {
  174. XR_TYPE_RENDER_MODEL_STATE_EXT, // type
  175. nullptr, // next
  176. render_model->animatable_node_count, // nodeStateCount
  177. render_model->node_states.ptr(), // nodeStates
  178. };
  179. result = xrGetRenderModelStateEXT(render_model->xr_render_model, &get_state_info, &state);
  180. if (XR_FAILED(result)) {
  181. ERR_PRINT("OpenXR: Failed to update node states [" + openxr_api->get_error_string(result) + "]");
  182. }
  183. }
  184. XrPath new_path = XR_NULL_PATH;
  185. if (toplevel_paths.is_empty()) {
  186. // Set this up just once with paths we support here.
  187. toplevel_paths.push_back(openxr_api->get_xr_path("/user/hand/left"));
  188. toplevel_paths.push_back(openxr_api->get_xr_path("/user/hand/right"));
  189. }
  190. XrInteractionRenderModelTopLevelUserPathGetInfoEXT info = {
  191. XR_TYPE_INTERACTION_RENDER_MODEL_TOP_LEVEL_USER_PATH_GET_INFO_EXT, // type
  192. nullptr, // next
  193. (uint32_t)toplevel_paths.size(), // topLevelUserPathCount
  194. toplevel_paths.ptr() // topLevelUserPaths
  195. };
  196. result = xrGetRenderModelPoseTopLevelUserPathEXT(render_model->xr_render_model, &info, &new_path);
  197. if (XR_FAILED(result)) {
  198. ERR_PRINT("OpenXR: Failed to update the top level path for render models [" + openxr_api->get_error_string(result) + "]");
  199. } else if (new_path != render_model->top_level_path) {
  200. print_verbose("OpenXR: Render model top level path changed to " + openxr_api->get_xr_path_name(new_path));
  201. // Set the new path
  202. render_model->top_level_path = new_path;
  203. // And broadcast it
  204. // Note, converting an XrPath to a String has overhead, so we won't do this automatically.
  205. emit_signal(SNAME("render_model_top_level_path_changed"), rid);
  206. }
  207. }
  208. }
  209. }
  210. bool OpenXRRenderModelExtension::is_active() const {
  211. return render_model_ext && interaction_render_model_ext;
  212. }
  213. void OpenXRRenderModelExtension::_clear_interaction_data() {
  214. for (const KeyValue<XrRenderModelIdEXT, RID> &e : interaction_render_models) {
  215. render_model_destroy(e.value);
  216. }
  217. interaction_render_models.clear();
  218. }
  219. bool OpenXRRenderModelExtension::_update_interaction_data() {
  220. ERR_FAIL_COND_V_MSG(!interaction_render_model_ext, false, "Interaction render model extension hasn't been enabled.");
  221. OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
  222. ERR_FAIL_NULL_V(openxr_api, false);
  223. XrSession session = openxr_api->get_session();
  224. ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
  225. // Check if syncActions has been run at least once or there is no point in getting data.
  226. if (!xr_sync_has_run) {
  227. // Do not treat this as an error.
  228. return true;
  229. }
  230. // If we get this far, no longer mark as dirty.
  231. // Else we just repeat the same error over and over again.
  232. _interaction_data_dirty = false;
  233. // Obtain interaction info.
  234. XrInteractionRenderModelIdsEnumerateInfoEXT interaction_info = {
  235. XR_TYPE_INTERACTION_RENDER_MODEL_IDS_ENUMERATE_INFO_EXT, // type
  236. nullptr, // next
  237. };
  238. // Obtain count.
  239. uint32_t interaction_count = 0;
  240. XrResult result = xrEnumerateInteractionRenderModelIdsEXT(session, &interaction_info, 0, &interaction_count, nullptr);
  241. if (XR_FAILED(result)) {
  242. // not successful? then we do nothing.
  243. ERR_FAIL_V_MSG(false, "OpenXR: Failed to obtain render model interaction id count [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  244. }
  245. // Create some storage
  246. LocalVector<XrRenderModelIdEXT> render_model_interaction_ids;
  247. render_model_interaction_ids.resize(interaction_count);
  248. // Only need to fetch data if there is something to fetch (/we've got storage).
  249. if (!render_model_interaction_ids.is_empty()) {
  250. // Obtain interaction ids
  251. result = xrEnumerateInteractionRenderModelIdsEXT(session, &interaction_info, render_model_interaction_ids.size(), &interaction_count, render_model_interaction_ids.ptr());
  252. if (XR_FAILED(result)) {
  253. ERR_FAIL_V_MSG(false, "OpenXR: Failed to obtain render model interaction ids [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  254. }
  255. }
  256. // Remove render models that are no longer tracked
  257. LocalVector<XrRenderModelIdEXT> erase_ids;
  258. for (const KeyValue<XrRenderModelIdEXT, RID> &e : interaction_render_models) {
  259. if (!render_model_interaction_ids.has(e.key)) {
  260. if (e.value.is_valid()) {
  261. render_model_destroy(e.value);
  262. }
  263. erase_ids.push_back(e.key);
  264. }
  265. }
  266. // Remove these from our hashmap
  267. for (const XrRenderModelIdEXT &id : erase_ids) {
  268. interaction_render_models.erase(id);
  269. }
  270. // Now update our models
  271. for (const XrRenderModelIdEXT &id : render_model_interaction_ids) {
  272. if (!interaction_render_models.has(id)) {
  273. // Even if this fails we add it so we don't repeat trying to create it
  274. interaction_render_models[id] = render_model_create(id);
  275. }
  276. }
  277. return true;
  278. }
  279. bool OpenXRRenderModelExtension::has_render_model(RID p_render_model) const {
  280. return render_model_owner.owns(p_render_model);
  281. }
  282. RID OpenXRRenderModelExtension::render_model_create(XrRenderModelIdEXT p_render_model_id) {
  283. ERR_FAIL_COND_V_MSG(!render_model_ext, RID(), "Render model extension hasn't been enabled.");
  284. OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
  285. ERR_FAIL_NULL_V(openxr_api, RID());
  286. XrSession session = openxr_api->get_session();
  287. ERR_FAIL_COND_V(session == XR_NULL_HANDLE, RID());
  288. RenderModel render_model;
  289. render_model.xr_render_model_id = p_render_model_id;
  290. // Get a list of supported glTF extensions.
  291. const HashSet<String> supported_gltf_extensions_hash_set = GLTFDocument::get_supported_gltf_extensions_hashset();
  292. Vector<CharString> supported_gltf_extensions_char_string; // Just for temp storage of our c-strings.
  293. supported_gltf_extensions_char_string.resize(supported_gltf_extensions_hash_set.size());
  294. int64_t supported_gltf_extension_index = 0;
  295. for (const String &ext : supported_gltf_extensions_hash_set) {
  296. supported_gltf_extensions_char_string.set(supported_gltf_extension_index, ext.utf8());
  297. supported_gltf_extension_index++;
  298. }
  299. // Now we can convert them to the `const char *` format.
  300. Vector<const char *> supported_gltf_extensions;
  301. supported_gltf_extensions.resize(supported_gltf_extensions_char_string.size());
  302. for (int64_t i = 0; i < supported_gltf_extensions_char_string.size(); i++) {
  303. supported_gltf_extensions.write[i] = supported_gltf_extensions_char_string[i].get_data();
  304. }
  305. XrRenderModelCreateInfoEXT create_info = {
  306. XR_TYPE_RENDER_MODEL_CREATE_INFO_EXT, // type
  307. nullptr, // next
  308. p_render_model_id, // renderModelId
  309. uint32_t(supported_gltf_extensions.size()), // gltfExtensionCount
  310. supported_gltf_extensions.ptr(), // gltfExtensions
  311. };
  312. XrResult result = xrCreateRenderModelEXT(session, &create_info, &render_model.xr_render_model);
  313. if (XR_FAILED(result)) {
  314. ERR_FAIL_V_MSG(RID(), "OpenXR: Failed to create render model [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  315. }
  316. XrRenderModelPropertiesGetInfoEXT properties_info = {
  317. XR_TYPE_RENDER_MODEL_PROPERTIES_GET_INFO_EXT, // type
  318. nullptr, // next
  319. };
  320. XrRenderModelPropertiesEXT properties = {
  321. XR_TYPE_RENDER_MODEL_PROPERTIES_EXT, // type
  322. nullptr, // next
  323. {}, // cacheId
  324. 0, // animatableNodeCount
  325. };
  326. result = xrGetRenderModelPropertiesEXT(render_model.xr_render_model, &properties_info, &properties);
  327. if (XR_FAILED(result)) {
  328. ERR_PRINT("OpenXR: Failed to get render model properties [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  329. } else {
  330. render_model.animatable_node_count = properties.animatableNodeCount;
  331. render_model.render_model_data = _get_render_model_data(properties.cacheId, properties.animatableNodeCount);
  332. }
  333. // Create space for positioning our asset.
  334. XrRenderModelSpaceCreateInfoEXT space_create_info = {
  335. XR_TYPE_RENDER_MODEL_SPACE_CREATE_INFO_EXT, // type
  336. nullptr, // next
  337. render_model.xr_render_model // renderModel
  338. };
  339. result = xrCreateRenderModelSpaceEXT(session, &space_create_info, &render_model.xr_space);
  340. if (XR_FAILED(result)) {
  341. ERR_PRINT("OpenXR: Failed to create render model space [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  342. }
  343. if (render_model.animatable_node_count > 0) {
  344. render_model.node_states.resize(render_model.animatable_node_count);
  345. }
  346. RID new_rid = render_model_owner.make_rid(render_model);
  347. emit_signal(SNAME("render_model_added"), new_rid);
  348. return new_rid;
  349. }
  350. RID OpenXRRenderModelExtension::_render_model_create(uint64_t p_render_model_id) {
  351. RID ret;
  352. ERR_FAIL_COND_V(p_render_model_id == XR_NULL_RENDER_MODEL_ID_EXT, ret);
  353. if (is_active()) {
  354. ret = render_model_create(XrRenderModelIdEXT(p_render_model_id));
  355. }
  356. return ret;
  357. }
  358. void OpenXRRenderModelExtension::render_model_destroy(RID p_render_model) {
  359. ERR_FAIL_COND_MSG(!render_model_ext, "Render model extension hasn't been enabled.");
  360. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  361. ERR_FAIL_NULL(render_model);
  362. emit_signal(SNAME("render_model_removed"), p_render_model);
  363. // Clean up.
  364. if (render_model->xr_space != XR_NULL_HANDLE) {
  365. xrDestroySpace(render_model->xr_space);
  366. }
  367. render_model->node_states.clear();
  368. // And destroy our model.
  369. XrResult result = xrDestroyRenderModelEXT(render_model->xr_render_model);
  370. if (XR_FAILED(result)) {
  371. ERR_PRINT("OpenXR: Failed to destroy render model [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  372. }
  373. render_model_owner.free(p_render_model);
  374. }
  375. TypedArray<RID> OpenXRRenderModelExtension::render_model_get_all() {
  376. TypedArray<RID> ret;
  377. LocalVector<RID> rids = render_model_owner.get_owned_list();
  378. for (const RID &rid : rids) {
  379. ret.push_back(rid);
  380. }
  381. return ret;
  382. }
  383. Node3D *OpenXRRenderModelExtension::render_model_new_scene_instance(RID p_render_model) const {
  384. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  385. ERR_FAIL_NULL_V(render_model, nullptr);
  386. if (render_model->render_model_data.is_null()) {
  387. // We never loaded it (don't spam errors here).
  388. return nullptr;
  389. }
  390. return render_model->render_model_data->new_scene_instance();
  391. }
  392. PackedStringArray OpenXRRenderModelExtension::render_model_get_subaction_paths(RID p_render_model) {
  393. OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
  394. ERR_FAIL_NULL_V(openxr_api, PackedStringArray());
  395. XrInstance instance = openxr_api->get_instance();
  396. ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, PackedStringArray());
  397. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  398. ERR_FAIL_NULL_V(render_model, PackedStringArray());
  399. PackedStringArray subaction_paths;
  400. XrInteractionRenderModelSubactionPathInfoEXT subaction_info = {
  401. XR_TYPE_INTERACTION_RENDER_MODEL_SUBACTION_PATH_INFO_EXT, // type
  402. nullptr, // next
  403. };
  404. uint32_t capacity;
  405. XrResult result = xrEnumerateRenderModelSubactionPathsEXT(render_model->xr_render_model, &subaction_info, 0, &capacity, nullptr);
  406. if (XR_FAILED(result)) {
  407. ERR_FAIL_V_MSG(PackedStringArray(), "OpenXR: Failed to obtain render model subaction path count [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  408. }
  409. if (capacity > 0) {
  410. LocalVector<XrPath> paths;
  411. paths.resize(capacity);
  412. result = xrEnumerateRenderModelSubactionPathsEXT(render_model->xr_render_model, &subaction_info, capacity, &capacity, paths.ptr());
  413. if (XR_FAILED(result)) {
  414. ERR_FAIL_V_MSG(PackedStringArray(), "OpenXR: Failed to obtain render model subaction paths [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  415. }
  416. for (uint32_t i = 0; i < capacity; i++) {
  417. char buffer[1024];
  418. uint32_t size = 0;
  419. xrPathToString(instance, paths[i], 1024, &size, buffer);
  420. if (size > 0) {
  421. subaction_paths.push_back(String(buffer));
  422. }
  423. }
  424. }
  425. return subaction_paths;
  426. }
  427. XrPath OpenXRRenderModelExtension::render_model_get_top_level_path(RID p_render_model) const {
  428. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  429. ERR_FAIL_NULL_V(render_model, XRPose::TrackingConfidence::XR_TRACKING_CONFIDENCE_NONE);
  430. return render_model->top_level_path;
  431. }
  432. String OpenXRRenderModelExtension::render_model_get_top_level_path_as_string(RID p_render_model) const {
  433. String ret;
  434. OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
  435. ERR_FAIL_NULL_V(openxr_api, ret);
  436. if (is_active() && has_render_model(p_render_model)) {
  437. XrPath path = render_model_get_top_level_path(p_render_model);
  438. if (path == XR_NULL_PATH) {
  439. return "None";
  440. } else {
  441. return openxr_api->get_xr_path_name(path);
  442. }
  443. }
  444. return ret;
  445. }
  446. XRPose::TrackingConfidence OpenXRRenderModelExtension::render_model_get_confidence(RID p_render_model) const {
  447. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  448. ERR_FAIL_NULL_V(render_model, XRPose::TrackingConfidence::XR_TRACKING_CONFIDENCE_NONE);
  449. return render_model->confidence;
  450. }
  451. Transform3D OpenXRRenderModelExtension::render_model_get_root_transform(RID p_render_model) const {
  452. XRServer *xr_server = XRServer::get_singleton();
  453. ERR_FAIL_NULL_V(xr_server, Transform3D());
  454. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  455. ERR_FAIL_NULL_V(render_model, Transform3D());
  456. // Scale our root transform
  457. real_t world_scale = xr_server->get_world_scale();
  458. Transform3D root_transform = render_model->root_transform.scaled(Vector3(world_scale, world_scale, world_scale));
  459. return xr_server->get_reference_frame() * root_transform;
  460. }
  461. uint32_t OpenXRRenderModelExtension::render_model_get_animatable_node_count(RID p_render_model) const {
  462. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  463. ERR_FAIL_NULL_V(render_model, 0);
  464. return render_model->animatable_node_count;
  465. }
  466. String OpenXRRenderModelExtension::render_model_get_animatable_node_name(RID p_render_model, uint32_t p_index) const {
  467. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  468. ERR_FAIL_NULL_V(render_model, String());
  469. if (render_model->render_model_data.is_null()) {
  470. // We never loaded it (don't spam errors here).
  471. return String();
  472. }
  473. return render_model->render_model_data->get_node_name(p_index);
  474. }
  475. bool OpenXRRenderModelExtension::render_model_is_animatable_node_visible(RID p_render_model, uint32_t p_index) const {
  476. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  477. ERR_FAIL_NULL_V(render_model, false);
  478. ERR_FAIL_UNSIGNED_INDEX_V(p_index, render_model->animatable_node_count, false);
  479. if (render_model->node_states.is_empty()) {
  480. // Never allocated (don't spam errors here).
  481. return false;
  482. }
  483. return render_model->node_states[p_index].isVisible;
  484. }
  485. Transform3D OpenXRRenderModelExtension::render_model_get_animatable_node_transform(RID p_render_model, uint32_t p_index) const {
  486. OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
  487. ERR_FAIL_NULL_V(openxr_api, Transform3D());
  488. RenderModel *render_model = render_model_owner.get_or_null(p_render_model);
  489. ERR_FAIL_NULL_V(render_model, Transform3D());
  490. ERR_FAIL_UNSIGNED_INDEX_V(p_index, render_model->animatable_node_count, Transform3D());
  491. if (render_model->node_states.is_empty()) {
  492. // Never allocated (don't spam errors here).
  493. return Transform3D();
  494. }
  495. return openxr_api->transform_from_pose(render_model->node_states[p_index].nodePose);
  496. }
  497. Ref<OpenXRRenderModelData> OpenXRRenderModelExtension::_get_render_model_data(XrUuidEXT p_cache_id, uint32_t p_animatable_node_count) {
  498. if (render_model_data_cache.has(p_cache_id)) {
  499. return render_model_data_cache[p_cache_id];
  500. }
  501. // We don't have this cached, lets load it up
  502. OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
  503. ERR_FAIL_NULL_V(openxr_api, nullptr);
  504. XrSession session = openxr_api->get_session();
  505. ERR_FAIL_COND_V(session == XR_NULL_HANDLE, nullptr);
  506. XrRenderModelAssetEXT asset;
  507. XrRenderModelAssetCreateInfoEXT create_info = {
  508. XR_TYPE_RENDER_MODEL_ASSET_CREATE_INFO_EXT, // type
  509. nullptr, // next
  510. p_cache_id // cacheId
  511. };
  512. XrResult result = xrCreateRenderModelAssetEXT(session, &create_info, &asset);
  513. if (XR_FAILED(result)) {
  514. ERR_FAIL_V_MSG(nullptr, "OpenXR: Failed to create render model asset [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  515. }
  516. Ref<OpenXRRenderModelData> render_model_data = _load_asset(asset, p_animatable_node_count);
  517. // We're done with this :)
  518. result = xrDestroyRenderModelAssetEXT(asset);
  519. if (XR_FAILED(result)) {
  520. ERR_PRINT("OpenXR: Failed to destroy render model asset [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  521. }
  522. // And cache it
  523. render_model_data_cache[p_cache_id] = render_model_data;
  524. return render_model_data;
  525. }
  526. Ref<OpenXRRenderModelData> OpenXRRenderModelExtension::_load_asset(XrRenderModelAssetEXT p_asset, uint32_t p_animatable_node_count) {
  527. XrRenderModelAssetDataGetInfoEXT get_info = {
  528. XR_TYPE_RENDER_MODEL_ASSET_DATA_GET_INFO_EXT, // type
  529. nullptr, // next
  530. };
  531. XrRenderModelAssetDataEXT asset_data = {
  532. XR_TYPE_RENDER_MODEL_ASSET_DATA_EXT, // type
  533. nullptr, // next
  534. 0, // bufferCapacityInput;
  535. 0, // bufferCountOutput;
  536. nullptr // buffer;
  537. };
  538. // Obtain required size for the buffer.
  539. XrResult result = xrGetRenderModelAssetDataEXT(p_asset, &get_info, &asset_data);
  540. if (XR_FAILED(result)) {
  541. ERR_FAIL_V_MSG(nullptr, "OpenXR: Failed to get render model buffer size [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  542. }
  543. ERR_FAIL_COND_V(asset_data.bufferCountOutput == 0, nullptr);
  544. // Allocate data
  545. PackedByteArray buffer;
  546. buffer.resize(asset_data.bufferCountOutput);
  547. asset_data.buffer = buffer.ptrw();
  548. asset_data.bufferCapacityInput = asset_data.bufferCountOutput;
  549. // Now get our actual data.
  550. result = xrGetRenderModelAssetDataEXT(p_asset, &get_info, &asset_data);
  551. if (XR_FAILED(result)) {
  552. ERR_FAIL_V_MSG(nullptr, "OpenXR: Failed to get render model buffer [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  553. }
  554. // Get the names of any animatable nodes
  555. PackedStringArray node_names;
  556. if (p_animatable_node_count > 0) {
  557. Vector<XrRenderModelAssetNodePropertiesEXT> node_properties;
  558. node_properties.resize(p_animatable_node_count);
  559. XrRenderModelAssetPropertiesGetInfoEXT properties_info = {
  560. XR_TYPE_RENDER_MODEL_ASSET_PROPERTIES_GET_INFO_EXT, // type
  561. nullptr, // next
  562. };
  563. XrRenderModelAssetPropertiesEXT asset_properties = {
  564. XR_TYPE_RENDER_MODEL_ASSET_PROPERTIES_EXT, // type
  565. nullptr, // next
  566. uint32_t(node_properties.size()), // nodePropertyCount
  567. node_properties.ptrw(), // nodeProperties
  568. };
  569. result = xrGetRenderModelAssetPropertiesEXT(p_asset, &properties_info, &asset_properties);
  570. if (XR_FAILED(result)) {
  571. ERR_FAIL_V_MSG(nullptr, "OpenXR: Failed to get render model property info [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
  572. }
  573. node_names.resize(p_animatable_node_count);
  574. String *node_names_ptrw = node_names.ptrw();
  575. for (uint32_t i = 0; i < p_animatable_node_count; i++) {
  576. node_names_ptrw[i] = String(node_properties[i].uniqueName);
  577. }
  578. }
  579. Ref<OpenXRRenderModelData> render_model_data;
  580. render_model_data.instantiate();
  581. render_model_data->parse_gltf_document(buffer);
  582. render_model_data->set_node_names(node_names);
  583. return render_model_data;
  584. }
  585. void OpenXRRenderModelExtension::_clear_render_model_data() {
  586. // Clear our toplevel paths filter.
  587. toplevel_paths.clear();
  588. // Clear our render model cache.
  589. render_model_data_cache.clear();
  590. // Loop through all of our render models and destroy them.
  591. LocalVector<RID> owned = render_model_owner.get_owned_list();
  592. for (const RID &rid : owned) {
  593. render_model_destroy(rid);
  594. }
  595. }
  596. bool OpenXRRenderModelData::parse_gltf_document(const PackedByteArray &p_bytes) {
  597. // State holds our data, document parses GLTF
  598. Ref<GLTFState> new_state;
  599. new_state.instantiate();
  600. Ref<GLTFDocument> new_gltf_document;
  601. new_gltf_document.instantiate();
  602. Error err = new_gltf_document->append_from_buffer(p_bytes, "", new_state);
  603. if (err != OK) {
  604. ERR_FAIL_V_MSG(false, "OpenXR: Failed to parse GLTF data.");
  605. }
  606. gltf_document = new_gltf_document;
  607. gltf_state = new_state;
  608. return true;
  609. }
  610. Node3D *OpenXRRenderModelData::new_scene_instance() {
  611. ERR_FAIL_COND_V(gltf_document.is_null(), nullptr);
  612. ERR_FAIL_COND_V(gltf_state.is_null(), nullptr);
  613. return Object::cast_to<Node3D>(gltf_document->generate_scene(gltf_state));
  614. }
  615. void OpenXRRenderModelData::set_node_names(const PackedStringArray &p_node_names) {
  616. node_names = p_node_names;
  617. }
  618. PackedStringArray OpenXRRenderModelData::get_node_names() const {
  619. return node_names;
  620. }
  621. const String OpenXRRenderModelData::get_node_name(uint32_t p_node_index) const {
  622. ERR_FAIL_UNSIGNED_INDEX_V(p_node_index, node_names.size(), String());
  623. return node_names[p_node_index];
  624. }
  625. OpenXRRenderModelData::OpenXRRenderModelData() {
  626. }
  627. OpenXRRenderModelData::~OpenXRRenderModelData() {
  628. }
  629. #endif // MODULE_GLTF_ENABLED