Skip to content

Commit

Permalink
Add OpenXR fb_render_model extension wrapper and OpenXRFBRenderModel …
Browse files Browse the repository at this point in the history
…node
  • Loading branch information
devloglogan committed Jan 25, 2024
1 parent 4962575 commit 2382758
Show file tree
Hide file tree
Showing 10 changed files with 639 additions and 8 deletions.
1 change: 1 addition & 0 deletions demo/export_presets.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,4 @@ meta_xr_features/quest_2_support=true
meta_xr_features/quest_3_support=true
meta_xr_features/quest_pro_support=true
meta_xr_features/use_anchor_api=true
meta_xr_features/render_model=1
13 changes: 13 additions & 0 deletions demo/main.gd
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
@uid("uid://b0vnbvovnw33f") # Generated automatically, do not modify.
extends Node3D

@onready var left_hand_mesh: MeshInstance3D = $XROrigin3D/LeftHand/LeftHandMesh
@onready var right_hand_mesh: MeshInstance3D = $XROrigin3D/RightHand/RightHandMesh

var xr_interface : XRInterface = null

# Called when the node enters the scene tree for the first time.
Expand All @@ -23,3 +27,12 @@ func _on_left_hand_button_pressed(name):
if name == "menu_button" and scene_capture:
print("Triggering scene capture")
scene_capture.request_scene_capture()


func _on_left_controller_fb_render_model_render_model_loaded() -> void:
left_hand_mesh.hide()


func _on_right_controller_fb_render_model_render_model_loaded() -> void:
right_hand_mesh.hide()

19 changes: 14 additions & 5 deletions demo/main.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[gd_scene load_steps=14 format=3 uid="uid://cqsodpswgup8w"]

[ext_resource type="Script" path="res://main.gd" id="1_fsva1"]
[ext_resource type="Script" uid="uid://b0vnbvovnw33f" path="res://main.gd" id="1_fsva1"]
[ext_resource type="PackedScene" uid="uid://c0uv4eu2yjm3b" path="res://viewport_2d_in_3d.tscn" id="2_7whgo"]
[ext_resource type="PackedScene" uid="uid://d4b4rllli6tqp" path="res://tablet_content.tscn" id="3_45w5g"]

Expand Down Expand Up @@ -56,17 +56,20 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.352791, 0)
[node name="LeftHand" type="XRController3D" parent="XROrigin3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.460909, 0.388594, -0.241118)
tracker = &"left_hand"
pose = &"aim"
pose = &"grip"

[node name="LeftHandMesh" type="MeshInstance3D" parent="XROrigin3D/LeftHand"]
mesh = SubResource("BoxMesh_3kt6b")

[node name="HandTablet" type="MeshInstance3D" parent="XROrigin3D/LeftHand/LeftHandMesh"]
transform = Transform3D(1, 0, 0, 0, 0.919876, 0.392209, 0, -0.392209, 0.919876, 0, 0.208883, -0.236189)
[node name="LeftControllerFbRenderModel" type="OpenXRFbRenderModel" parent="XROrigin3D/LeftHand"]
render_model_path = "/model_fb/controller/left"

[node name="HandTablet" type="MeshInstance3D" parent="XROrigin3D/LeftHand"]
transform = Transform3D(1, 0, 0, 0, -0.392209, 0.919876, 0, -0.919876, -0.392209, 0, -0.236189, -0.208883)
mesh = SubResource("QuadMesh_1oamj")
surface_material_override/0 = SubResource("StandardMaterial3D_pmc5p")

[node name="Viewport2Din3D" parent="XROrigin3D/LeftHand/LeftHandMesh/HandTablet" instance=ExtResource("2_7whgo")]
[node name="Viewport2Din3D" parent="XROrigin3D/LeftHand/HandTablet" instance=ExtResource("2_7whgo")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.005)
screen_size = Vector2(0.35, 0.25)
enabled = false
Expand All @@ -76,10 +79,14 @@ unshaded = true
[node name="RightHand" type="XRController3D" parent="XROrigin3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.478861, 0.468292, -0.241097)
tracker = &"right_hand"
pose = &"grip"

[node name="RightHandMesh" type="MeshInstance3D" parent="XROrigin3D/RightHand"]
mesh = SubResource("BoxMesh_ey3x4")

[node name="RightControllerFbRenderModel" type="OpenXRFbRenderModel" parent="XROrigin3D/RightHand"]
render_model_path = "/model_fb/controller/right"

[node name="EyeGaze" type="XRController3D" parent="XROrigin3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.977669, 0)
tracker = &"/user/eyes_ext"
Expand All @@ -92,3 +99,5 @@ mesh = SubResource("SphereMesh_5gcab")
mesh = SubResource("PlaneMesh_mjcgt")

[connection signal="button_pressed" from="XROrigin3D/LeftHand" to="." method="_on_left_hand_button_pressed"]
[connection signal="render_model_loaded" from="XROrigin3D/LeftHand/LeftControllerFbRenderModel" to="." method="_on_left_controller_fb_render_model_render_model_loaded"]
[connection signal="render_model_loaded" from="XROrigin3D/RightHand/RightControllerFbRenderModel" to="." method="_on_right_controller_fb_render_model_render_model_loaded"]
29 changes: 28 additions & 1 deletion godotopenxrmeta/src/main/cpp/export/meta_export_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ MetaEditorExportPlugin::MetaEditorExportPlugin() {
PASSTHROUGH_NONE_VALUE,
false
);
_render_model_option = _generate_export_option(
"meta_xr_features/render_model",
"",
Variant::Type::INT,
PROPERTY_HINT_ENUM,
"None,Optional,Required",
PROPERTY_USAGE_DEFAULT,
RENDER_MODEL_NONE_VALUE,
false
);
_use_anchor_api_option = _generate_export_option(
"meta_xr_features/use_anchor_api",
"",
Expand Down Expand Up @@ -167,6 +177,7 @@ TypedArray<Dictionary> MetaEditorExportPlugin::_get_export_options(const Ref<Edi
export_options.append(_hand_tracking_option);
export_options.append(_hand_tracking_frequency_option);
export_options.append(_passthrough_option);
export_options.append(_render_model_option);
export_options.append(_use_anchor_api_option);
export_options.append(_use_scene_api_option);
export_options.append(_support_quest_1_option);
Expand Down Expand Up @@ -243,6 +254,10 @@ String MetaEditorExportPlugin::_get_export_option_warning(const Ref<EditorExport
if (!openxr_enabled && _get_int_option(option, PASSTHROUGH_NONE_VALUE) > PASSTHROUGH_NONE_VALUE) {
return "\"Passthrough\" requires \"XR Mode\" to be \"OpenXR\".\n";
}
} else if (option == "meta_xr_features/render_model") {
if (!openxr_enabled && _get_int_option(option, RENDER_MODEL_NONE_VALUE) > RENDER_MODEL_NONE_VALUE) {
return "\"Render Model\" requires \"XR Mode\" to be \"OpenXR\".\n";
}
} else if (option == "meta_xr_features/use_anchor_api") {
if (!openxr_enabled && _get_bool_option(option)) {
return "\"Use anchor API\" is only valid when \"XR Mode\" is \"OpenXR\".\n";
Expand Down Expand Up @@ -294,6 +309,18 @@ String MetaEditorExportPlugin::_get_android_manifest_element_contents(const Ref<
contents += " <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.PASSTHROUGH\" android:required=\"true\" />\n";
}

// Check for render model
int render_model_value = _get_int_option("meta_xr_features/render_model", RENDER_MODEL_NONE_VALUE);
if (render_model_value > RENDER_MODEL_NONE_VALUE) {
contents += " <uses-permission android:name=\"com.oculus.permission.RENDER_MODEL\" />\n";

if (render_model_value == RENDER_MODEL_OPTIONAL_VALUE) {
contents += " <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.RENDER_MODEL\" android:required=\"false\" />\n";
} else if (render_model_value == RENDER_MODEL_REQUIRED_VALUE) {
contents += " <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.RENDER_MODEL\" android:required=\"true\" />\n";
}
}

// Check for anchor api
bool use_anchor_api = _get_bool_option("meta_xr_features/use_anchor_api");
if (use_anchor_api) {
Expand Down Expand Up @@ -348,4 +375,4 @@ String MetaEditorExportPlugin::_get_android_manifest_activity_element_contents(c
<category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD" />
</intent-filter>
)";
}
}
6 changes: 5 additions & 1 deletion godotopenxrmeta/src/main/cpp/export/meta_export_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ static const int PASSTHROUGH_NONE_VALUE = 0;
static const int PASSTHROUGH_OPTIONAL_VALUE = 1;
static const int PASSTHROUGH_REQUIRED_VALUE = 2;

static const int RENDER_MODEL_NONE_VALUE = 0;
static const int RENDER_MODEL_OPTIONAL_VALUE = 1;
static const int RENDER_MODEL_REQUIRED_VALUE = 2;

static const int HAND_TRACKING_NONE_VALUE = 0;
static const int HAND_TRACKING_OPTIONAL_VALUE = 1;
static const int HAND_TRACKING_REQUIRED_VALUE = 2;
Expand Down Expand Up @@ -82,6 +86,7 @@ class MetaEditorExportPlugin : public OpenXREditorExportPlugin {
Dictionary _hand_tracking_option;
Dictionary _hand_tracking_frequency_option;
Dictionary _passthrough_option;
Dictionary _render_model_option;
Dictionary _use_anchor_api_option;
Dictionary _use_scene_api_option;
Dictionary _support_quest_1_option;
Expand All @@ -102,5 +107,4 @@ class MetaEditorPlugin : public EditorPlugin {

private:
MetaEditorExportPlugin *meta_export_plugin = nullptr;

};
69 changes: 69 additions & 0 deletions godotopenxrmeta/src/main/cpp/include/openxr_fb_render_model.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**************************************************************************/
/* openxr_fb_render_model.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT XR */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */
/* */
/* Original contributed implementation: */
/* Copyright (c) 2022-2023 MattaKis Consulting Kft. (Migeran) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef OPENXR_FB_RENDER_MODEL_H
#define OPENXR_FB_RENDER_MODEL_H

#include <godot_cpp/classes/node3d.hpp>

namespace godot {

class OpenXRFbRenderModel : public Node3D {
GDCLASS(OpenXRFbRenderModel, Node3D)

private:
String render_model_path;
Node3D *render_model = nullptr;

void load_render_model();

protected:
void _notification(int p_what);

static void _bind_methods();

void _validate_property(PropertyInfo &p_property) const;

public:
PackedStringArray get_suggested_render_model_path_names() const;

void set_render_model_path(String p_render_model_path);
String get_render_model_path();

static TypedArray<String> get_valid_paths();
bool has_render_model();
Node3D *get_render_model();
};

} //namespace godot

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**************************************************************************/
/* openxr_fb_render_model_extension_wrapper.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT XR */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */
/* */
/* Original contributed implementation: */
/* Copyright (c) 2022-2023 MattaKis Consulting Kft. (Migeran) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef OPENXR_FB_RENDER_MODEL_EXTENSION_WRAPPER_H
#define OPENXR_FB_RENDER_MODEL_EXTENSION_WRAPPER_H

#include <openxr/openxr.h>
#include <godot_cpp/classes/open_xr_extension_wrapper_extension.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
#include <map>

#include "util.h"

using namespace godot;

// Wrapper for the set of Facebook render model extension.
class OpenXRFbRenderModelExtensionWrapper : public OpenXRExtensionWrapperExtension {
GDCLASS(OpenXRFbRenderModelExtensionWrapper, OpenXRExtensionWrapperExtension);

public:
uint64_t _set_system_properties_and_get_next_pointer(void *next_pointer) override;

godot::Dictionary _get_requested_extensions() override;

void _on_instance_created(uint64_t instance) override;

void _on_instance_destroyed() override;

void _on_state_stopping() override;

static OpenXRFbRenderModelExtensionWrapper *get_singleton();

bool is_enabled() const;
TypedArray<String> get_valid_paths();
PackedByteArray get_buffer(const String &p_path);

OpenXRFbRenderModelExtensionWrapper();
~OpenXRFbRenderModelExtensionWrapper();

protected:
static void _bind_methods();

private:
EXT_PROTO_XRRESULT_FUNC4(xrEnumerateRenderModelPathsFB,
(XrSession), session,
(uint32_t), pathCapacityInput,
(uint32_t *), pathCountOutput,
(XrRenderModelPathInfoFB *), path);

EXT_PROTO_XRRESULT_FUNC3(xrGetRenderModelPropertiesFB,
(XrSession), session,
(XrPath), path,
(XrRenderModelPropertiesFB *), properties);

EXT_PROTO_XRRESULT_FUNC3(xrLoadRenderModelFB,
(XrSession), session,
(const XrRenderModelLoadInfoFB *), info,
(XrRenderModelBufferFB *), buffer);

EXT_PROTO_XRRESULT_FUNC5(xrPathToString,
(XrInstance), instance,
(XrPath), path,
(uint32_t), bufferCapacityInput,
(uint32_t *), bufferCountOutput,
(char *), buffer);

EXT_PROTO_XRRESULT_FUNC3(xrStringToPath,
(XrInstance), instance,
(const char *), pathString,
(XrPath *), path);

bool initialize_fb_render_model_extension(const XrInstance instance);

void cleanup();

void populate_valid_paths();

String _xr_path_to_string(XrPath p_path);

XrPath _string_to_xr_path(const String &p_path);

static OpenXRFbRenderModelExtensionWrapper *singleton;

std::map<godot::String, bool *> request_extensions;
bool fb_render_model_ext = false;
TypedArray<String> valid_paths = TypedArray<String>();
XrSystemRenderModelPropertiesFB system_render_model_properties;
};

#endif // OPENXR_FB_RENDER_MODEL_EXTENSION_WRAPPER_H
Loading

0 comments on commit 2382758

Please sign in to comment.