Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ google-services.json

# IDE
.vscode

# Godot
*.uid
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,26 @@ directory to initialize the `godot-cpp` submodule:
git submodule update --init
```

### Prerequisites

- OpenJDK: NEEDS version 17
- Gradle: 8.9 (NEEDS pre 9.0)
- Make sure the ANDROID_HOME env var is set (usually /home/<username>/Android/Sdk). NOTE: don't use tilde path ("~/Android/Sdk") as it may fail the python `os.path.exists` call
- Make sure that $ANDROID_HOME/platform-tools is in your PATH variable (and that platform tools are installed in Android Studio)
- Make sure that the NDKROOT env var is set (should be $ANDROID_HOME/ndk/<version>)
- Use Ndk versions 25.1.8937393 (in your path above), and also download version 23.2.8568313

You are now ready to build the bindings :)



### Building the C++ bindings
Build the Android C++ bindings using the following commands. To speed up compilation, add `-jN` at
the end of the SCons command line where `N` is the number of CPU threads you have on your system.
The example below uses 4 threads.
```
cd godot-cpp
git checkout 4.4
scons platform=android target=template_debug -j4
scons platform=android target=template_release -j4
```
Expand Down
42 changes: 42 additions & 0 deletions plugin/demo/Camera.gdshader
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
shader_type sky;

uniform samplerExternalOES camera_y : source_color, repeat_disable;
uniform samplerExternalOES camera_CbCr : source_color, repeat_disable;

uniform vec2 viewport_size = vec2(512,512);
uniform vec2 feed_transform_basis_x = vec2(1,0);
uniform vec2 feed_transform_basis_y = vec2(0,1);
uniform vec2 feed_transform_origin = vec2(0,0);

void sky() {
if (AT_CUBEMAP_PASS){
COLOR = vec3(0);
}
else{
vec2 uv = FRAGCOORD.xy / viewport_size;

// Very hacky, from trial and error
uv.y = 1.0 - uv.y;
mat2 feed_transform_basis = mat2(feed_transform_basis_x, feed_transform_basis_y);
uv = feed_transform_origin + feed_transform_basis * uv;
//uv = (inverse(feed_transform) * vec4(uv,0,1)).xy;

// If the camera has YCbCr, use the commented block below
// vec3 color;
// color.r = texture(camera_y, uv).r;
// color.gb = texture(camera_CbCr, uv).rg - vec2(0.5, 0.5);

// // YCbCr -> SRGB conversion
// // Using BT.709 which is the standard for HDTV
// color.rgb = mat3(
// vec3(1.00000, 1.00000, 1.00000),
// vec3(0.00000, -0.18732, 1.85560),
// vec3(1.57481, -0.46813, 0.00000)) *
// color.rgb;

COLOR.rgb = texture(camera_y, uv).rgb;
//COLOR.rgb += vec3(uv-0.5,0);
// Because of background canvas
//COLOR = pow(COLOR, vec4(2.2));
}
}
63 changes: 63 additions & 0 deletions plugin/demo/ImageTrackedComponent.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
extends Node

var target: Node3D

@export var trackedImage: Image

@export_group("Transform")
@export var position_offset: Vector3 = Vector3(0,0,0)

@export var maxDistanceRender: float = 2

enum ROTATION_MIX {ABSOLUTE, RELATIVE}

@export var x_rotation_mix: ROTATION_MIX = ROTATION_MIX.RELATIVE
@export var x_rotation_val: float = 0.0

@export var y_rotation_mix: ROTATION_MIX = ROTATION_MIX.RELATIVE
@export var y_rotation_val: float = 0.0

@export var z_rotation_mix: ROTATION_MIX = ROTATION_MIX.RELATIVE
@export var z_rotation_val: float = 0.0

func _ready():
target = get_parent()
ARCoreInterfaceInstance.image_tracker_database_add_image(trackedImage, trackedImage.resource_name)

func _process(_delta: float):

var trackedTrsfrm: Transform3D = ARCoreInterfaceInstance.image_tracker_get_tracked_transform(trackedImage.resource_name)
target.position = trackedTrsfrm.origin + position_offset


var cam = get_viewport().get_camera_3d()
var distToCam = target.global_position.distance_to(cam.global_position)
print("Cam global position, ", cam.global_position)
print("Cam rotation (deg), ", cam.global_rotation_degrees)
print("tracked obj position, ", target.global_position)
print("Distance cam to tracked image: ", distToCam)
if distToCam > maxDistanceRender:
target.visible = false
return
else:
target.visible = true


var imgRot = trackedTrsfrm.basis.get_euler()

var rot_x = x_rotation_val
if x_rotation_mix == ROTATION_MIX.RELATIVE:
rot_x += imgRot.x
target.rotation.x = rot_x


var rot_y = y_rotation_val
if y_rotation_mix == ROTATION_MIX.RELATIVE:
rot_y += imgRot.y
target.rotation.y = rot_y


var rot_z = z_rotation_val
if z_rotation_mix == ROTATION_MIX.RELATIVE:
rot_z += imgRot.z
target.rotation.z = rot_z
4 changes: 4 additions & 0 deletions plugin/demo/LogTransform.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
extends Node3D

func _process(delta: float) -> void:
print(name, " Transform is ", transform)
12 changes: 12 additions & 0 deletions plugin/demo/StickNode.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[gd_scene load_steps=3 format=3 uid="uid://c64yix7y4oc2d"]

[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jeq64"]
albedo_color = Color(1, 1, 0, 1)

[sub_resource type="TorusMesh" id="TorusMesh_cm40d"]
material = SubResource("StandardMaterial3D_jeq64")

[node name="Node3D" type="Node3D"]

[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("TorusMesh_cm40d")
15 changes: 15 additions & 0 deletions plugin/demo/click_detect.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
extends Control

signal onScreenTouchDown(pos: Vector2)

var isTouchDown: bool = false


func _on_gui_input(event: InputEvent) -> void:
#print("Control detected event")
if event is InputEventScreenTouch and event.pressed == true:
if not isTouchDown:
onScreenTouchDown.emit(event.position)
isTouchDown = true
else:
isTouchDown = false
14 changes: 14 additions & 0 deletions plugin/demo/export_presets.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,29 @@
name="Android"
platform="Android"
runnable=true
advanced_options=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="./GDExtension Android Plugin Demo.apk"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2

[preset.0.options]

custom_template/debug=""
custom_template/release=""
gradle_build/use_gradle_build=true
gradle_build/gradle_build_directory=""
gradle_build/android_source_template="/home/tom/Documents/GodotFork/godot/bin/android_source.zip"
gradle_build/compress_native_libraries=false
gradle_build/export_format=0
gradle_build/min_sdk="31"
gradle_build/target_sdk="31"
Expand All @@ -40,8 +47,10 @@ package/show_as_launcher_app=false
launcher_icons/main_192x192=""
launcher_icons/adaptive_foreground_432x432=""
launcher_icons/adaptive_background_432x432=""
launcher_icons/adaptive_monochrome_432x432=""
graphics/opengl_debug=false
xr_features/xr_mode=0
gesture/swipe_to_dismiss=false
screen/immersive_mode=true
screen/support_small=true
screen/support_normal=true
Expand All @@ -57,6 +66,7 @@ permissions/access_checkin_properties=false
permissions/access_coarse_location=false
permissions/access_fine_location=false
permissions/access_location_extra_commands=false
permissions/access_media_location=false
permissions/access_mock_location=false
permissions/access_network_state=false
permissions/access_surface_flinger=false
Expand Down Expand Up @@ -144,6 +154,10 @@ permissions/read_frame_buffer=false
permissions/read_history_bookmarks=false
permissions/read_input_state=false
permissions/read_logs=false
permissions/read_media_audio=false
permissions/read_media_images=false
permissions/read_media_video=false
permissions/read_media_visual_user_selected=false
permissions/read_phone_state=false
permissions/read_profile=false
permissions/read_sms=false
Expand Down
2 changes: 1 addition & 1 deletion plugin/demo/main.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://cg3hylang5fxn"]

[ext_resource type="Script" path="res://main.gd" id="1_j0gfq"]
[ext_resource type="Script" uid="uid://bitq5ot864ym3" path="res://main.gd" id="1_j0gfq"]

[node name="Main" type="Node2D"]
script = ExtResource("1_j0gfq")
Expand Down
81 changes: 80 additions & 1 deletion plugin/demo/main3D.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@ extends Node3D
var _plugin_name = "ARCorePlugin"
var _android_plugin

@export var trackedPlaneScene: PackedScene
var allPlanesShowed: Dictionary

var is_estimating_light = false
var original_light_trsf: Transform3D;

@export var skyCamMaterial: ShaderMaterial
var camFeed: CameraFeed

# Called when the node enters the scene tree for the first time.
func _ready():
func _enter_tree() -> void:
XRServer.tracker_added.connect(func(tracker_name, type):
print("New XRServer Tracker ", tracker_name))

for s in Engine.get_singleton_list():
print("MCT " + s.get_basename())
if Engine.has_singleton(_plugin_name):
Expand All @@ -28,12 +37,70 @@ func _ready():
ARCoreInterfaceInstance.start()

original_light_trsf = $DirectionalLight3D.transform

ARCoreInterfaceInstance.enable_images_detection(true)
ARCoreInterfaceInstance.create_image_tracker_database()

camFeed = ARCoreInterfaceInstance.get_camera_feed()
if camFeed:
_setup_skyshader_camera_params()
else:
print("NO CAMERA FEED ON ENTER TREE")
ARCoreInterfaceInstance.enable_vertical_plane_detection(true)
ARCoreInterfaceInstance.enable_horizontal_plane_detection(true)

#ARCoreInterfaceInstance.image_tracker_database_add_image(imageToTrack.get_image(), "base")
#ARCoreInterfaceInstance.track_nodes_to_images({
# imageToTrack.get_image(): nodeToStick
#})

func _exit_tree():
_android_plugin.uninitializeEnvironment()

func _setup_skyshader_camera_params():
var ytex: CameraTexture = skyCamMaterial.get_shader_parameter("camera_y")
if not ytex:
ytex = CameraTexture.new()
var ctex: CameraTexture = skyCamMaterial.get_shader_parameter("camera_CbCr")
if not ctex:
ctex = CameraTexture.new()
ytex.camera_feed_id = camFeed.get_id()
ctex.camera_feed_id = camFeed.get_id()
print("Setting up camera shader, id is ", camFeed.get_id())
skyCamMaterial.set_shader_parameter("camera_y", ytex)
skyCamMaterial.set_shader_parameter("camera_CbCr", ctex)

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):

var allIds = ARCoreInterfaceInstance.plane_tracker_get_all_plane_ids()
print("All tracked plane ids: ", allIds)
for id in allIds:
var plane
if allPlanesShowed.has(id):
plane = allPlanesShowed[id]
else:
plane = trackedPlaneScene.instantiate()
allPlanesShowed[id] = plane
add_child(plane)
plane.global_transform = ARCoreInterfaceInstance.plane_tracker_get_plane_transform(id)
print("Plane ", id, " position is ", plane.global_position)

if camFeed == null:
print("STILL NO CAMERA FEED")
camFeed = ARCoreInterfaceInstance.get_camera_feed()
if camFeed:
_setup_skyshader_camera_params()

if camFeed:
#print("Camera feed transform: ", camFeed.feed_transform)
skyCamMaterial.set_shader_parameter("feed_transform_basis_x", camFeed.feed_transform.x)
skyCamMaterial.set_shader_parameter("feed_transform_basis_y", camFeed.feed_transform.y)
skyCamMaterial.set_shader_parameter("feed_transform_origin", camFeed.feed_transform.origin)
var vpSize = get_viewport().size
skyCamMaterial.set_shader_parameter("viewport_size", vpSize)
#var imgTrsfm: Transform3D = ARCoreInterfaceInstance.image_tracker_get_tracked_transform("base")
#nodeToStick.position = imgTrsfm.origin
if (is_estimating_light):
var light_dir = ARCoreInterfaceInstance.get_light_main_hdr_direction()
$DirectionalLight3D.rotation = light_dir
Expand Down Expand Up @@ -73,3 +140,15 @@ func _on_node_2d_point_cloud_detection_toggled(toggled):

func _on_node_2d_switch_orientation(vertical):
ARCoreInterfaceInstance.switch_orientation(vertical)


func _on_screen_touch_down(pos: Vector2) -> void:
#print("Detected click at ", pos)
#var cam = get_viewport().get_camera_3d()
#var orig = cam.project_ray_origin(pos)
#var dir = cam.project_ray_normal(pos)
#print("Resulting ray is ", orig, dir)
#
#var trsfm = ARCoreInterfaceInstance.raycast(orig, dir)
var trsfm = ARCoreInterfaceInstance.screenRayCast(pos.x, pos.y)
print("Resulting raycast hit transform is ", trsfm)
Loading