Modules: update modules to be built for iOS

Using 'available' checks to fix deprecation compilation errors
Additional checks for simulator
This commit is contained in:
Sergey Minakov
2020-07-15 19:03:01 +03:00
parent 33038be5ed
commit 66be375eb0
4 changed files with 276 additions and 214 deletions

View File

@ -60,8 +60,8 @@ private:
float eye_height, z_near, z_far; float eye_height, z_near, z_far;
Ref<CameraFeed> feed; Ref<CameraFeed> feed;
int image_width[2]; size_t image_width[2];
int image_height[2]; size_t image_height[2];
Vector<uint8_t> img_data[2]; Vector<uint8_t> img_data[2];
struct anchor_map { struct anchor_map {
@ -84,9 +84,9 @@ public:
void start_session(); void start_session();
void stop_session(); void stop_session();
bool get_anchor_detection_is_enabled() const; bool get_anchor_detection_is_enabled() const override;
void set_anchor_detection_is_enabled(bool p_enable); void set_anchor_detection_is_enabled(bool p_enable) override;
virtual int get_camera_feed_id(); virtual int get_camera_feed_id() override;
bool get_light_estimation_is_enabled() const; bool get_light_estimation_is_enabled() const;
void set_light_estimation_is_enabled(bool p_enable); void set_light_estimation_is_enabled(bool p_enable);
@ -97,22 +97,22 @@ public:
/* while Godot has its own raycast logic this takes ARKits camera into account and hits on any ARAnchor */ /* while Godot has its own raycast logic this takes ARKits camera into account and hits on any ARAnchor */
Array raycast(Vector2 p_screen_coord); Array raycast(Vector2 p_screen_coord);
void notification(int p_what); virtual void notification(int p_what) override;
virtual StringName get_name() const; virtual StringName get_name() const override;
virtual int get_capabilities() const; virtual int get_capabilities() const override;
virtual bool is_initialized() const; virtual bool is_initialized() const override;
virtual bool initialize(); virtual bool initialize() override;
virtual void uninitialize(); virtual void uninitialize() override;
virtual Size2 get_render_targetsize(); virtual Size2 get_render_targetsize() override;
virtual bool is_stereo(); virtual bool is_stereo() override;
virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform); virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) override;
virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far); virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect); virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process(); virtual void process() override;
// called by delegate (void * because C++ and Obj-C don't always mix, should really change all platform/iphone/*.cpp files to .mm) // called by delegate (void * because C++ and Obj-C don't always mix, should really change all platform/iphone/*.cpp files to .mm)
void _add_or_update_anchor(void *p_anchor); void _add_or_update_anchor(void *p_anchor);

View File

@ -42,7 +42,9 @@
#include "arkit_session_delegate.h" #include "arkit_session_delegate.h"
// just a dirty workaround for now, declare these as globals. I'll probably encapsulate ARSession and associated logic into an mm object and change ARKitInterface to a normal cpp object that consumes it. // just a dirty workaround for now, declare these as globals. I'll probably encapsulate ARSession and associated logic into an mm object and change ARKitInterface to a normal cpp object that consumes it.
API_AVAILABLE(ios(11.0))
ARSession *ar_session; ARSession *ar_session;
ARKitSessionDelegate *ar_delegate; ARKitSessionDelegate *ar_delegate;
NSTimeInterval last_timestamp; NSTimeInterval last_timestamp;
@ -55,22 +57,28 @@ void ARKitInterface::start_session() {
if (initialized) { if (initialized) {
print_line("Starting ARKit session"); print_line("Starting ARKit session");
Class ARWorldTrackingConfigurationClass = NSClassFromString(@"ARWorldTrackingConfiguration"); if (@available(iOS 11, *)) {
ARWorldTrackingConfiguration *configuration = [ARWorldTrackingConfigurationClass new]; Class ARWorldTrackingConfigurationClass = NSClassFromString(@"ARWorldTrackingConfiguration");
ARWorldTrackingConfiguration *configuration = [ARWorldTrackingConfigurationClass new];
configuration.lightEstimationEnabled = light_estimation_is_enabled; configuration.lightEstimationEnabled = light_estimation_is_enabled;
if (plane_detection_is_enabled) { if (plane_detection_is_enabled) {
configuration.planeDetection = ARPlaneDetectionVertical | ARPlaneDetectionHorizontal; if (@available(iOS 11.3, *)) {
} else { configuration.planeDetection = ARPlaneDetectionVertical | ARPlaneDetectionHorizontal;
configuration.planeDetection = 0; } else {
configuration.planeDetection = ARPlaneDetectionHorizontal;
}
} else {
configuration.planeDetection = 0;
}
// make sure our camera is on
if (feed.is_valid()) {
feed->set_active(true);
}
[ar_session runWithConfiguration:configuration];
} }
// make sure our camera is on
if (feed.is_valid()) {
feed->set_active(true);
}
[ar_session runWithConfiguration:configuration];
} }
} }
@ -84,7 +92,9 @@ void ARKitInterface::stop_session() {
feed->set_active(false); feed->set_active(false);
} }
[ar_session pause]; if (@available(iOS 11.0, *)) {
[ar_session pause];
}
} }
} }
@ -92,12 +102,12 @@ void ARKitInterface::notification(int p_what) {
// TODO, this is not being called, need to find out why, possibly because this is not a node. // TODO, this is not being called, need to find out why, possibly because this is not a node.
// in that case we need to find a way to get these notifications! // in that case we need to find a way to get these notifications!
switch (p_what) { switch (p_what) {
case MainLoop::NOTIFICATION_WM_FOCUS_IN: { case DisplayServer::WINDOW_EVENT_FOCUS_IN: {
print_line("Focus in"); print_line("Focus in");
start_session(); start_session();
}; break; }; break;
case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { case DisplayServer::WINDOW_EVENT_FOCUS_OUT: {
print_line("Focus out"); print_line("Focus out");
stop_session(); stop_session();
@ -162,37 +172,42 @@ int ARKitInterface::get_capabilities() const {
} }
Array ARKitInterface::raycast(Vector2 p_screen_coord) { Array ARKitInterface::raycast(Vector2 p_screen_coord) {
Array arr; if (@available(iOS 11, *)) {
Size2 screen_size = OS::get_singleton()->get_window_size(); Array arr;
CGPoint point; Size2 screen_size = DisplayServer::get_singleton()->screen_get_size();
point.x = p_screen_coord.x / screen_size.x; CGPoint point;
point.y = p_screen_coord.y / screen_size.y; point.x = p_screen_coord.x / screen_size.x;
point.y = p_screen_coord.y / screen_size.y;
///@TODO maybe give more options here, for now we're taking just ARAchors into account that were found during plane detection keeping their size into account ///@TODO maybe give more options here, for now we're taking just ARAchors into account that were found during plane detection keeping their size into account
NSArray<ARHitTestResult *> *results = [ar_session.currentFrame hittest:point types:ARHitTestResultTypeExistingPlaneUsingExtent];
for (ARHitTestResult *result in results) { NSArray<ARHitTestResult *> *results = [ar_session.currentFrame hitTest:point types:ARHitTestResultTypeExistingPlaneUsingExtent];
Transform transform;
matrix_float4x4 m44 = result.worldTransform; for (ARHitTestResult *result in results) {
transform.basis.elements[0].x = m44.columns[0][0]; Transform transform;
transform.basis.elements[1].x = m44.columns[0][1];
transform.basis.elements[2].x = m44.columns[0][2];
transform.basis.elements[0].y = m44.columns[1][0];
transform.basis.elements[1].y = m44.columns[1][1];
transform.basis.elements[2].y = m44.columns[1][2];
transform.basis.elements[0].z = m44.columns[2][0];
transform.basis.elements[1].z = m44.columns[2][1];
transform.basis.elements[2].z = m44.columns[2][2];
transform.origin.x = m44.columns[3][0];
transform.origin.y = m44.columns[3][1];
transform.origin.z = m44.columns[3][2];
/* important, NOT scaled to world_scale !! */ matrix_float4x4 m44 = result.worldTransform;
arr.push_back(transform); transform.basis.elements[0].x = m44.columns[0][0];
transform.basis.elements[1].x = m44.columns[0][1];
transform.basis.elements[2].x = m44.columns[0][2];
transform.basis.elements[0].y = m44.columns[1][0];
transform.basis.elements[1].y = m44.columns[1][1];
transform.basis.elements[2].y = m44.columns[1][2];
transform.basis.elements[0].z = m44.columns[2][0];
transform.basis.elements[1].z = m44.columns[2][1];
transform.basis.elements[2].z = m44.columns[2][2];
transform.origin.x = m44.columns[3][0];
transform.origin.y = m44.columns[3][1];
transform.origin.z = m44.columns[3][2];
/* important, NOT scaled to world_scale !! */
arr.push_back(transform);
}
return arr;
} else {
return Array();
} }
return arr;
} }
void ARKitInterface::_bind_methods() { void ARKitInterface::_bind_methods() {
@ -221,51 +236,55 @@ bool ARKitInterface::initialize() {
XRServer *xr_server = XRServer::get_singleton(); XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, false); ERR_FAIL_NULL_V(xr_server, false);
if (!initialized) { if (@available(iOS 11, *)) {
print_line("initializing ARKit"); if (!initialized) {
print_line("initializing ARKit");
// create our ar session and delegate // create our ar session and delegate
Class ARSessionClass = NSClassFromString(@"ARSession"); Class ARSessionClass = NSClassFromString(@"ARSession");
if (ARSessionClass == Nil) { if (ARSessionClass == Nil) {
void *arkit_handle = dlopen("/System/Library/Frameworks/ARKit.framework/ARKit", RTLD_NOW); void *arkit_handle = dlopen("/System/Library/Frameworks/ARKit.framework/ARKit", RTLD_NOW);
if (arkit_handle) { if (arkit_handle) {
ARSessionClass = NSClassFromString(@"ARSession"); ARSessionClass = NSClassFromString(@"ARSession");
} else { } else {
print_line("ARKit init failed"); print_line("ARKit init failed");
return false; return false;
}
} }
} ar_session = [ARSessionClass new];
ar_session = [ARSessionClass new]; ar_delegate = [ARKitSessionDelegate new];
ar_delegate = [ARKitSessionDelegate new]; ar_delegate.arkit_interface = this;
ar_delegate.arkit_interface = this; ar_session.delegate = ar_delegate;
ar_session.delegate = ar_delegate;
// reset our transform // reset our transform
transform = Transform(); transform = Transform();
// make this our primary interface // make this our primary interface
xr_server->set_primary_interface(this); xr_server->set_primary_interface(this);
// make sure we have our feed setup // make sure we have our feed setup
if (feed.is_null()) { if (feed.is_null()) {
feed.instance(); feed.instance();
feed->set_name("ARKit"); feed->set_name("ARKit");
CameraServer *cs = CameraServer::get_singleton(); CameraServer *cs = CameraServer::get_singleton();
if (cs != NULL) { if (cs != NULL) {
cs->add_feed(feed); cs->add_feed(feed);
}
} }
feed->set_active(true);
// yeah!
initialized = true;
// Start our session...
start_session();
} }
feed->set_active(true);
// yeah! return true;
initialized = true; } else {
return false;
// Start our session...
start_session();
} }
return true;
} }
void ARKitInterface::uninitialize() { void ARKitInterface::uninitialize() {
@ -286,9 +305,12 @@ void ARKitInterface::uninitialize() {
remove_all_anchors(); remove_all_anchors();
[ar_session release]; if (@available(iOS 11.0, *)) {
[ar_session release];
ar_session = NULL;
}
[ar_delegate release]; [ar_delegate release];
ar_session = NULL;
ar_delegate = NULL; ar_delegate = NULL;
initialized = false; initialized = false;
session_was_started = false; session_was_started = false;
@ -296,15 +318,15 @@ void ARKitInterface::uninitialize() {
} }
Size2 ARKitInterface::get_render_targetsize() { Size2 ARKitInterface::get_render_targetsize() {
_THREAD_SAFE_METHOD_ // _THREAD_SAFE_METHOD_
Size2 target_size = OS::get_singleton()->get_window_size(); Size2 target_size = DisplayServer::get_singleton()->screen_get_size();
return target_size; return target_size;
} }
Transform ARKitInterface::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) { Transform ARKitInterface::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {
_THREAD_SAFE_METHOD_ // _THREAD_SAFE_METHOD_
Transform transform_for_eye; Transform transform_for_eye;
@ -336,7 +358,7 @@ CameraMatrix ARKitInterface::get_projection_for_eye(XRInterface::Eyes p_eye, rea
} }
void ARKitInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { void ARKitInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
_THREAD_SAFE_METHOD_ // _THREAD_SAFE_METHOD_
// We must have a valid render target // We must have a valid render target
ERR_FAIL_COND(!p_render_target.is_valid()); ERR_FAIL_COND(!p_render_target.is_valid());
@ -345,15 +367,15 @@ void ARKitInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target
ERR_FAIL_COND(p_screen_rect == Rect2()); ERR_FAIL_COND(p_screen_rect == Rect2());
// get the size of our screen // get the size of our screen
Rect2 screen_rect = p_screen_rect; // Rect2 screen_rect = p_screen_rect;
// screen_rect.position.x += screen_rect.size.x; // screen_rect.position.x += screen_rect.size.x;
// screen_rect.size.x = -screen_rect.size.x; // screen_rect.size.x = -screen_rect.size.x;
// screen_rect.position.y += screen_rect.size.y; // screen_rect.position.y += screen_rect.size.y;
// screen_rect.size.y = -screen_rect.size.y; // screen_rect.size.y = -screen_rect.size.y;
VSG::rasterizer->set_current_render_target(RID()); // VSG::rasterizer->set_current_render_target(RID());
VSG::rasterizer->blit_render_target_to_screen(p_render_target, screen_rect, 0); // VSG::rasterizer->blit_render_target_to_screen(p_render_target, screen_rect, 0);
} }
XRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *p_uuid) { XRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *p_uuid) {
@ -432,7 +454,7 @@ void ARKitInterface::remove_all_anchors() {
} }
void ARKitInterface::process() { void ARKitInterface::process() {
_THREAD_SAFE_METHOD_ // _THREAD_SAFE_METHOD_
if (@available(iOS 11.0, *)) { if (@available(iOS 11.0, *)) {
if (initialized) { if (initialized) {
@ -443,8 +465,16 @@ void ARKitInterface::process() {
last_timestamp = current_frame.timestamp; last_timestamp = current_frame.timestamp;
// get some info about our screen and orientation // get some info about our screen and orientation
Size2 screen_size = OS::get_singleton()->get_window_size(); Size2 screen_size = DisplayServer::get_singleton()->screen_get_size();
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown;
if (@available(iOS 13, *)) {
orientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation;
#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR
} else {
orientation = [[UIApplication sharedApplication] statusBarOrientation];
#endif
}
// Grab our camera image for our backbuffer // Grab our camera image for our backbuffer
CVPixelBufferRef pixelBuffer = current_frame.capturedImage; CVPixelBufferRef pixelBuffer = current_frame.capturedImage;
@ -475,27 +505,27 @@ void ARKitInterface::process() {
{ {
// do Y // do Y
int new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0); size_t new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0);
int new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0); size_t new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0);
int bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0); size_t bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
if ((image_width[0] != new_width) || (image_height[0] != new_height)) { if ((image_width[0] != new_width) || (image_height[0] != new_height)) {
printf("- Camera padding l:%lu r:%lu t:%lu b:%lu\n", extraLeft, extraRight, extraTop, extraBottom); printf("- Camera padding l:%lu r:%lu t:%lu b:%lu\n", extraLeft, extraRight, extraTop, extraBottom);
printf("- Camera Y plane size: %i, %i - %i\n", new_width, new_height, bytes_per_row); printf("- Camera Y plane size: %lu, %lu - %lu\n", new_width, new_height, bytes_per_row);
image_width[0] = new_width; image_width[0] = new_width;
image_height[0] = new_height; image_height[0] = new_height;
img_data[0].resize(new_width * new_height); img_data[0].resize(new_width * new_height);
} }
uint8_t *w = img_data[0].write(); uint8_t *w = img_data[0].ptrw();
if (new_width == bytes_per_row) { if (new_width == bytes_per_row) {
memcpy(w.ptr(), dataY, new_width * new_height); memcpy(w, dataY, new_width * new_height);
} else { } else {
int offset_a = 0; size_t offset_a = 0;
int offset_b = extraLeft + (extraTop * bytes_per_row); size_t offset_b = extraLeft + (extraTop * bytes_per_row);
for (int r = 0; r < new_height; r++) { for (size_t r = 0; r < new_height; r++) {
memcpy(w.ptr() + offset_a, dataY + offset_b, new_width); memcpy(w + offset_a, dataY + offset_b, new_width);
offset_a += new_width; offset_a += new_width;
offset_b += bytes_per_row; offset_b += bytes_per_row;
} }
@ -507,26 +537,26 @@ void ARKitInterface::process() {
{ {
// do CbCr // do CbCr
int new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1); size_t new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1);
int new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1); size_t new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1);
int bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0); size_t bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
if ((image_width[1] != new_width) || (image_height[1] != new_height)) { if ((image_width[1] != new_width) || (image_height[1] != new_height)) {
printf("- Camera CbCr plane size: %i, %i - %i\n", new_width, new_height, bytes_per_row); printf("- Camera CbCr plane size: %lu, %lu - %lu\n", new_width, new_height, bytes_per_row);
image_width[1] = new_width; image_width[1] = new_width;
image_height[1] = new_height; image_height[1] = new_height;
img_data[1].resize(2 * new_width * new_height); img_data[1].resize(2 * new_width * new_height);
} }
uint8_t *w = img_data[1].write(); uint8_t *w = img_data[1].ptrw();
if ((2 * new_width) == bytes_per_row) { if ((2 * new_width) == bytes_per_row) {
memcpy(w.ptr(), dataCbCr, 2 * new_width * new_height); memcpy(w, dataCbCr, 2 * new_width * new_height);
} else { } else {
int offset_a = 0; size_t offset_a = 0;
int offset_b = extraLeft + (extraTop * bytes_per_row); size_t offset_b = extraLeft + (extraTop * bytes_per_row);
for (int r = 0; r < new_height; r++) { for (size_t r = 0; r < new_height; r++) {
memcpy(w.ptr() + offset_a, dataCbCr + offset_b, 2 * new_width); memcpy(w + offset_a, dataCbCr + offset_b, 2 * new_width);
offset_a += 2 * new_width; offset_a += 2 * new_width;
offset_b += bytes_per_row; offset_b += bytes_per_row;
} }
@ -658,69 +688,78 @@ void ARKitInterface::process() {
} }
void ARKitInterface::_add_or_update_anchor(void *p_anchor) { void ARKitInterface::_add_or_update_anchor(void *p_anchor) {
_THREAD_SAFE_METHOD_ // _THREAD_SAFE_METHOD_
ARAnchor *anchor = (ARAnchor *)p_anchor; if (@available(iOS 11.0, *)) {
ARAnchor *anchor = (ARAnchor *)p_anchor;
unsigned char uuid[16]; unsigned char uuid[16];
[anchor.identifier getUUIDBytes:uuid]; [anchor.identifier getUUIDBytes:uuid];
XRPositionalTracker *tracker = get_anchor_for_uuid(uuid); XRPositionalTracker *tracker = get_anchor_for_uuid(uuid);
if (tracker != NULL) { if (tracker != NULL) {
// lets update our mesh! (using Arjens code as is for now) // lets update our mesh! (using Arjens code as is for now)
// we should also probably limit how often we do this... // we should also probably limit how often we do this...
// can we safely cast this? // can we safely cast this?
ARPlaneAnchor *planeAnchor = (ARPlaneAnchor *)anchor; ARPlaneAnchor *planeAnchor = (ARPlaneAnchor *)anchor;
if (planeAnchor.geometry.triangleCount > 0) { if (@available(iOS 11.3, *)) {
Ref<SurfaceTool> surftool; if (planeAnchor.geometry.triangleCount > 0) {
surftool.instance(); Ref<SurfaceTool> surftool;
surftool->begin(Mesh::PRIMITIVE_TRIANGLES); surftool.instance();
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
for (int j = planeAnchor.geometry.triangleCount * 3 - 1; j >= 0; j--) { for (int j = planeAnchor.geometry.triangleCount * 3 - 1; j >= 0; j--) {
int16_t index = planeAnchor.geometry.triangleIndices[j]; int16_t index = planeAnchor.geometry.triangleIndices[j];
simd_float3 vrtx = planeAnchor.geometry.vertices[index]; simd_float3 vrtx = planeAnchor.geometry.vertices[index];
simd_float2 textcoord = planeAnchor.geometry.textureCoordinates[index]; simd_float2 textcoord = planeAnchor.geometry.textureCoordinates[index];
surftool->add_uv(Vector2(textcoord[0], textcoord[1])); surftool->add_uv(Vector2(textcoord[0], textcoord[1]));
surftool->add_color(Color(0.8, 0.8, 0.8)); surftool->add_color(Color(0.8, 0.8, 0.8));
surftool->add_vertex(Vector3(vrtx[0], vrtx[1], vrtx[2])); surftool->add_vertex(Vector3(vrtx[0], vrtx[1], vrtx[2]));
}
surftool->generate_normals();
tracker->set_mesh(surftool->commit());
} else {
Ref<Mesh> nomesh;
tracker->set_mesh(nomesh);
}
} else {
Ref<Mesh> nomesh;
tracker->set_mesh(nomesh);
} }
surftool->generate_normals(); // Note, this also contains a scale factor which gives us an idea of the size of the anchor
tracker->set_mesh(surftool->commit()); // We may extract that in our XRAnchor class
} else { Basis b;
Ref<Mesh> nomesh; matrix_float4x4 m44 = anchor.transform;
tracker->set_mesh(nomesh); b.elements[0].x = m44.columns[0][0];
b.elements[1].x = m44.columns[0][1];
b.elements[2].x = m44.columns[0][2];
b.elements[0].y = m44.columns[1][0];
b.elements[1].y = m44.columns[1][1];
b.elements[2].y = m44.columns[1][2];
b.elements[0].z = m44.columns[2][0];
b.elements[1].z = m44.columns[2][1];
b.elements[2].z = m44.columns[2][2];
tracker->set_orientation(b);
tracker->set_rw_position(Vector3(m44.columns[3][0], m44.columns[3][1], m44.columns[3][2]));
} }
// Note, this also contains a scale factor which gives us an idea of the size of the anchor
// We may extract that in our XRAnchor class
Basis b;
matrix_float4x4 m44 = anchor.transform;
b.elements[0].x = m44.columns[0][0];
b.elements[1].x = m44.columns[0][1];
b.elements[2].x = m44.columns[0][2];
b.elements[0].y = m44.columns[1][0];
b.elements[1].y = m44.columns[1][1];
b.elements[2].y = m44.columns[1][2];
b.elements[0].z = m44.columns[2][0];
b.elements[1].z = m44.columns[2][1];
b.elements[2].z = m44.columns[2][2];
tracker->set_orientation(b);
tracker->set_rw_position(Vector3(m44.columns[3][0], m44.columns[3][1], m44.columns[3][2]));
} }
} }
void ARKitInterface::_remove_anchor(void *p_anchor) { void ARKitInterface::_remove_anchor(void *p_anchor) {
_THREAD_SAFE_METHOD_ // _THREAD_SAFE_METHOD_
ARAnchor *anchor = (ARAnchor *)p_anchor; if (@available(iOS 11.0, *)) {
ARAnchor *anchor = (ARAnchor *)p_anchor;
unsigned char uuid[16]; unsigned char uuid[16];
[anchor.identifier getUUIDBytes:uuid]; [anchor.identifier getUUIDBytes:uuid];
remove_anchor_for_uuid(uuid); remove_anchor_for_uuid(uuid);
}
} }
ARKitInterface::ARKitInterface() { ARKitInterface::ARKitInterface() {
@ -728,7 +767,9 @@ ARKitInterface::ARKitInterface() {
session_was_started = false; session_was_started = false;
plane_detection_is_enabled = false; plane_detection_is_enabled = false;
light_estimation_is_enabled = false; light_estimation_is_enabled = false;
ar_session = NULL; if (@available(iOS 11.0, *)) {
ar_session = NULL;
}
z_near = 0.01; z_near = 0.01;
z_far = 1000.0; z_far = 1000.0;
projection.set_perspective(60.0, 1.0, z_near, z_far, false); projection.set_perspective(60.0, 1.0, z_near, z_far, false);

View File

@ -42,9 +42,9 @@ class ARKitInterface;
@property(nonatomic) ARKitInterface *arkit_interface; @property(nonatomic) ARKitInterface *arkit_interface;
- (void)session:(ARSession *)session didAddAnchors:(NSArray<ARAnchor *> *)anchors; - (void)session:(ARSession *)session didAddAnchors:(NSArray<ARAnchor *> *)anchors API_AVAILABLE(ios(11.0));
- (void)session:(ARSession *)session didRemoveAnchors:(NSArray<ARAnchor *> *)anchors; - (void)session:(ARSession *)session didRemoveAnchors:(NSArray<ARAnchor *> *)anchors API_AVAILABLE(ios(11.0));
- (void)session:(ARSession *)session didUpdateAnchors:(NSArray<ARAnchor *> *)anchors; - (void)session:(ARSession *)session didUpdateAnchors:(NSArray<ARAnchor *> *)anchors API_AVAILABLE(ios(11.0));
@end @end
#endif /* !ARKIT_SESSION_DELEGATE_H */ #endif /* !ARKIT_SESSION_DELEGATE_H */

View File

@ -158,25 +158,31 @@
} else if (dataCbCr == NULL) { } else if (dataCbCr == NULL) {
print_line("Couldn't access CbCr pixel buffer data"); print_line("Couldn't access CbCr pixel buffer data");
} else { } else {
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown;
if (@available(iOS 13, *)) {
orientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation;
#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR
} else {
orientation = [[UIApplication sharedApplication] statusBarOrientation];
#endif
}
Ref<Image> img[2]; Ref<Image> img[2];
{ {
// do Y // do Y
int new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0); size_t new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0);
int new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0); size_t new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0);
int _bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
if ((width[0] != new_width) || (height[0] != new_height)) { if ((width[0] != new_width) || (height[0] != new_height)) {
// printf("Camera Y plane %i, %i - %i\n", new_width, new_height, bytes_per_row);
width[0] = new_width; width[0] = new_width;
height[0] = new_height; height[0] = new_height;
img_data[0].resize(new_width * new_height); img_data[0].resize(new_width * new_height);
} }
uint8_t *w = img_data[0].ptrw(); uint8_t *w = img_data[0].ptrw();
memcpy(w.ptr(), dataY, new_width * new_height); memcpy(w, dataY, new_width * new_height);
img[0].instance(); img[0].instance();
img[0]->create(new_width, new_height, 0, Image::FORMAT_R8, img_data[0]); img[0]->create(new_width, new_height, 0, Image::FORMAT_R8, img_data[0]);
@ -184,20 +190,17 @@
{ {
// do CbCr // do CbCr
int new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1); size_t new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1);
int new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1); size_t new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1);
int bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
if ((width[1] != new_width) || (height[1] != new_height)) { if ((width[1] != new_width) || (height[1] != new_height)) {
// printf("Camera CbCr plane %i, %i - %i\n", new_width, new_height, bytes_per_row);
width[1] = new_width; width[1] = new_width;
height[1] = new_height; height[1] = new_height;
img_data[1].resize(2 * new_width * new_height); img_data[1].resize(2 * new_width * new_height);
} }
uint8_t *w = img_data[1].ptrw(); uint8_t *w = img_data[1].ptrw();
memcpy(w.ptr(), dataCbCr, 2 * new_width * new_height); memcpy(w, dataCbCr, 2 * new_width * new_height);
///TODO GLES2 doesn't support FORMAT_RG8, need to do some form of conversion ///TODO GLES2 doesn't support FORMAT_RG8, need to do some form of conversion
img[1].instance(); img[1].instance();
@ -359,41 +362,59 @@ void CameraIOS::update_feeds() {
// this way of doing things is deprecated but still works, // this way of doing things is deprecated but still works,
// rewrite to using AVCaptureDeviceDiscoverySession // rewrite to using AVCaptureDeviceDiscoverySession
AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:[NSArray arrayWithObjects:AVCaptureDeviceTypeBuiltInTelephotoCamera, AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInTrueDepthCamera, AVCaptureDeviceTypeBuiltInWideAngleCamera, nil] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; NSMutableArray *deviceTypes = [NSMutableArray array];
// remove devices that are gone.. if (@available(iOS 10, *)) {
for (int i = feeds.size() - 1; i >= 0; i--) { [deviceTypes addObject:AVCaptureDeviceTypeBuiltInWideAngleCamera];
Ref<CameraFeedIOS> feed(feeds[i]); [deviceTypes addObject:AVCaptureDeviceTypeBuiltInTelephotoCamera];
if (feed.is_null()) { if (@available(iOS 10.2, *)) {
// feed not managed by us [deviceTypes addObject:AVCaptureDeviceTypeBuiltInDualCamera];
} else if (![session.devices containsObject:feed->get_device()]) { }
// remove it from our array, this will also destroy it ;)
remove_feed(feed);
};
};
// add new devices.. if (@available(iOS 11.1, *)) {
for (AVCaptureDevice *device in session.devices) { [deviceTypes addObject:AVCaptureDeviceTypeBuiltInTrueDepthCamera];
bool found = false; }
for (int i = 0; i < feeds.size() && !found; i++) { AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession
discoverySessionWithDeviceTypes:deviceTypes
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionUnspecified];
// remove devices that are gone..
for (int i = feeds.size() - 1; i >= 0; i--) {
Ref<CameraFeedIOS> feed(feeds[i]); Ref<CameraFeedIOS> feed(feeds[i]);
if (feed.is_null()) { if (feed.is_null()) {
// feed not managed by us // feed not managed by us
} else if (feed->get_device() == device) { } else if (![session.devices containsObject:feed->get_device()]) {
found = true; // remove it from our array, this will also destroy it ;)
remove_feed(feed);
}; };
}; };
if (!found) { // add new devices..
Ref<CameraFeedIOS> newfeed; for (AVCaptureDevice *device in session.devices) {
newfeed.instance(); bool found = false;
newfeed->set_device(device);
add_feed(newfeed); for (int i = 0; i < feeds.size() && !found; i++) {
Ref<CameraFeedIOS> feed(feeds[i]);
if (feed.is_null()) {
// feed not managed by us
} else if (feed->get_device() == device) {
found = true;
};
};
if (!found) {
Ref<CameraFeedIOS> newfeed;
newfeed.instance();
newfeed->set_device(device);
add_feed(newfeed);
};
}; };
}; }
}; };
CameraIOS::CameraIOS() { CameraIOS::CameraIOS() {