Convert UIKit coordinates to SpriteKit coordinates - ios

I am trying to convert normal uikit coordinates (top left origin, width and height go right and down) to Sprite Kit coordinates (origin is at center of node, left and down are negative, right and up are positive).
Does anyone know how to do this? Unfortunately I can't work around this to my knowledge because I am using QuartzCore for drawing on a SKNode. Without converting, I am getting really off drawings.

According to the docs, SKView has methods for Converting Between View and Scene Coordinates.
Remember the scene is itself an SKNode, so if you need to get from scene coordinates to a particular node coordinate system there's also the methods in Converting to and from the Node’s Coordinate System.

Related

ARKit how position nodes base on horizon and not the camera orientation?

When I add a new node with ARKit (ARSKView), the object is positioned base on the device camera. So if your phone is facing down or tilted, the object will be in that direction as well. How can I instead place the object base on the horizon?
For that, right after a new node's creation, use a worldOrientation instance property that controls the node's orientation relative to the scene's world coordinate space.
var worldOrientation: SCNQuaternion { get set }
This quaternion isolates the rotational aspect of the node's worldTransform matrix, which in turn is the conversion of the node's transform from local space to the scene's world coordinate space. That is, it expresses the difference in axis and angle of rotation between the node and the scene's rootNode.
let worldOrientation = sceneView.scene.rootNode.worldOrientation
yourNode.rotation = worldOrientation /* X, Y, Z, W components */
P.S. (as you updated your question) :
If you're using SpriteKit, 2D sprites you spawn in ARSKView are always face the camera. So, if the camera moves around a definite point of real scene, all the sprites must be rotated about their pivot point, still facing a camera.
Nothing can prevent you from using SceneKit and SpriteKit together.

How do you get the UIKit coordinates of an ARKit feature point?

I have an ARSCNView and I am tracking feature points in the scene. How would I get the 2D coordinates of the feature points (as in the coordinates of that point in the screen) from the 3D world coordinates of the feature point?
(Essentially the opposite of sceneView.hitTest)
Converting a point from 3D space (usually camera or world space) to 2D view (pixel) space is called projecting that point. (Because it involves a projection transform that defines how to flatten the third dimension.)
ARKit and SceneKit both offer methods for projecting points (and unprojecting points, the reverse transform that requires extra input on how to extrapolate the third dimension).
Since you're working with ARSCNView, you can just use the projectPoint method. (That's inherited from the superclass SCNView and defined in the SCNSceneRenderer protocol, but still applies in AR because ARKit world space is the same as SceneKit world/scene/rootNode space.) Note you'll need to convert back and forth between float3 and SCNVector3 for that method.
Also note the returned "2D" point is still a 3D vector — the x and y coordinates are screen pixels (well, "points" as in UIKit layout units), and the third is a relative depth value. Just make a CGPoint from the first two coordinates for something you can use with other UIKit API.
BTW, if you're using ARKit without SceneKit, there's also a projectPoint method on ARCamera.

Why is "convertPosition" called to project a point found in SceneKit?

I am working on 3D project/unproject logic and I am learning some of the fundamentals. I went over this question:
Scene Kit: projectPoint calculated is displaced
In that question part of the shown code is:
//world coordinates
let v1w = topSphereNode.convertPosition(v1, toNode: scene.rootNode)
let v2w = topSphereNode.convertPosition(v2, toNode: scene.rootNode)
My question is, why is that needed? Why not just use v1 and v2 as points since they are already valid points 3D points in the scene? Why does the top sphere node's position need to be converted with respect to the root node's position?
since they are already valid points 3D points in the scene?
They are not necessarily valid 3D points in the scene, but 3D points in the local space of the sphere. The code you showed converts them to the world space, i.e. the scene space. This is important when the sphere is a child object, rotated, scaled, and/or simply not in the center of the scene.
Rather then using code from a question, check out the answers here:
How to use iOS (Swift) SceneKit SCNSceneRenderer unprojectPoint properly

Scenekit object that stays in the center of the camera view (Swift)

So I have a camera in my SceneKit project that is able to rotate and move around freely, and I have an object that, in some cases, needs to stay at a constant distance away from the camera and always be in the center of its view no matter how the camera rotates. Unfortunately, I'm new to SceneKit and don't know how to accomplish this.
So the key things I'm looking for are:
How to have the object always at the same distance from the camera
How to have the object always be in the center of the camera's view no matter what direction it's looking
At the moment, both the camera and the object (an SCNNode with a box geometry) are children of the same scene.
I'm coding in swift so I'd prefer an answer using that, but if you have a solution in objective-c, that works too.
Thanks a bunch!
Think about how you might solve this in the real world. Grab a two by four of the appropriate length. Use duct tape to attach the ball to one end, and to attach the camera (aimed at the ball) to the other end.
Now you can carry that rig around with you. The ball will always be in the center of the camera view, and will be a constant distance away from the camera.
You can build the same rig, virtually, in SceneKit. Create a new SCNNode to be the rig (taking the place of the two by four). Add the ball as a child node, at (0, 0, 0). Add the camera as a child node too, at (0, 0, 5) (camera looks down the -Z axis, so this position should put the ball in the center of the view). Now you can move the rig node anywhere in the scene you want, and you'll have a consistent ball position.

Recreate the 3D outlines of a City street in iOS SceneKit with OSM XML data

What is best strategy to recreate part of a street in iOS SceneKit using .osm XML data?
Please assume part of a street is offered in the OSM XML data and contains the necessary geopoints with latitude and longitude denoting the Nodes to describe the paths/footprints of 6 buildings (i.e. ground floor plans that line the side of a street).
Specifically, what's the best strategy to convert latitude and longitude Nodes in order to locate these building footprints/polygons on the ground floor in a scene within SceneKit iOS? (i.e. running through position 0,0,0)? Thank you.
Very roughly and briefly, based on my own experience with 3D map rendering:
Transform the XML data from lat/long to appropriate coordinates for a 2D map (that is, project it to a plane using a map projection, then apply a 2D affine transform to get it into screen pixel coordinates). Create a 2D map that's wider and taller than the actual screen, because of what's going to happen in step 2:
Using a 3D coordinate system with your map vertical (i.e., set all the Z coordinates to zero), rotate the map so that it reclines at an appropriate shallow angle, as if you're in an aeroplane looking down on it; the angle might be 30 degrees from horizontal. To rotate the map you'll need to create a 3D rotation matrix. The axis of rotation will be the X axis: that is, the horizontal line that is the bottom border of your 2D map. The rotation is exactly the same as what happens when you rotate your laptop screen away from you.
Supply the new 3D coordinates to your rendering system. I haven't used SceneKit but I had a quick look at the documentation and you can use any coordinate system you like, so you will be able to use one that is convenient for the process I have just described: something that uses units the size of a screen pixel at the viewing plane, with Y going upwards, X going right, and Z going away from the viewer.
One final caveat: if you want to add extrusions giving a rough approximation of the 3D building shapes (such data is available in OSM for some areas) note that my scheme requires the tops of buildings, and indeed anything above ground level, to have negative Z coordinates.
Pretty simple. First, convert Your CLLocationCoordinate2D to a MKMapPoint, which is exactly the same as a CGRect. Second, scale down the MKMapPoint by some arbitrary number so it fits in with how you want it on your scene graph, let's say by 200. Since scenekit's coordinate system is centered at (0,0), you'll need to make sure your location is correct. Then just create your scnvector3's with the x/y of he MKMapPoint, and you will be locked to coordinates.

Resources