ios - Swift : ARKit Save ARPlaneAnchor for next session -
arkit
quite new , quite new in swift... i'm having troubles...
i'd save arplaneanchor
detected during session , reload them when relaunch app. phone @ same place , i'd scan room 1 time. , remembering anchor found in room everytime launch app.
i tried several solutions :
solution1 : save arplaneanchor using : nskeyedarchiver.archiverootobject(plane, tofile: filepath)
i got error :
terminating app due uncaught exception 'nsinvalidargumentexception', reason: '-[arplaneanchor encodewithcoder:]: unrecognized selector sent instance
i think maybe can't save kind of data locally
solution2 : store datas of arplaneanchor
intantiate them when launch app. datas float. creat aranchor
easily, cast them arplaneanchor
, not modify "center" , "extend" parameter of arplaneanchor
because have getter , not setter. can't create anchors.
i open anysolution. think need store aranchor object, not find way without crash! if can me grateful.
first... if app restricted situation device permanently installed , user can never move or rotate it, using arkit display overlay content on camera feed sort of "killing mosquitos cannon" kind of situation. work out @ development time kind of camera projection 3d engine needs, use "dumb" camera feed 3d engine running on top, , not need ios 11 or arkit-capable device.
so might want think use case or technology stack more before commit specific solutions , workarounds.
as more specific problem...
arplaneanchor
entirely read-only class, because use case entirely read-only. exists sole purpose of giving arkit way give information detected planes. however, once have information, can whatever want. , there on, don't need keep arplaneanchor
in equation anymore.
perhaps you're confused because of typical use case plane detection (and scenekit-based display):
- turn on plane detection
- respond
renderer(_:didadd:for:)
receivearplaneanchor
objects - in method, return virtual content associate plane anchor
- let
arscnview
automatically position content follows plane's position
if plane's position static respect camera, though, don't need that.
you need arkit handle placement of content within scene if placement needs ongoing management, case when plane detection live (arkit refines estimates of plane location , extent , updates anchor accordingly). if did plane-finding ahead of time, won't getting updates, don't need arkit manage updates.
instead steps can more this:
- know plane (position in world space).
- set position of virtual content position of plane.
- add content scene directly.
in other words, "solution 2" step in right direction, not far enough. want archive not arplaneanchor
instance itself, information contains — , when unarchiving, don't need re-create arplaneanchor
instance, need use information.
so, if place content "live" plane detection:
func renderer(_ renderer: scnscenerenderer, didadd node: scnnode, anchor: aranchor) { guard let planeanchor = anchor as? arplaneanchor else { return } let extent = planeanchor.extent let center = planeanchor.center // planeanchor.transform not used, because arscnview automatically applies // container node, , make child of container node let plane = scnplane(width: cgfloat(extent.x), height: cgfloat(extent.z)) let planenode = scnnode(geometry: plane) planenode.eulerangles.x = .pi / 2 planenode.simdposition = center node.addchildnode(planenode) }
then can static content placement:
struct planeinfo { // save , restore arplaneanchor data let transform: float4x4 let center: float3 let extent: float3 } func makeplane(from planeinfo: planeinfo) { // call when place content let extent = planeinfo.extent let center = float4(planeinfo.center, 1) * planeinfo.transform // we're positioning content in world space, center // offset relative transform let plane = scnplane(width: cgfloat(extent.x), height: cgfloat(extent.z)) let planenode = scnnode(geometry: plane) planenode.eulerangles.x = .pi / 2 planenode.simdposition = center.xyz view.scene.rootnode.addchildnode(planenode) } // convenience vector-width conversions used above extension float4 { init(_ xyz: float3, _ w: float) { self.init(xyz.x, xyz.y, xyz.z, 1) } var xyz: float3 { return float3(self.x, self.y, self.z) } }
Comments
Post a Comment