How to map SceneKit sizes to artwork pixel sizes? - ios

Related to this question about creating static scenes in SceneKit, how are you supposed to map node sizes to artwork size?
Let's say you have a SCNSphere with a radius of 1. And inside the sphere you want to present a character sprite.
How do you decide how large the sprite artwork should be, that is, what is the relationship between the artwork pixel size and the SCNNode size?
For SpriteKit, this is done automatically as the nodes assume the size of the sprite textures by default.
Right now, the only solution seems to be a trial-and-error process where you try different sized artwork until one "fits" properly (i.e., not too small, not too big) inside the sphere, but surely there must be a more elegant approach?

Related

SceneKit: Transform texture to fill only part of a sphere

I'm developing an application that uses SceneKit API and I faced the problem that I basically cannot apply a texture to a sphere object and keep texture's pre-defined size. I'm able to either scale the texture up to the object's surface (default SceneKit's behavior) or repeat it. But what I want to achieve is similar to the billiard ball:
Let's say I have a a .png image of a white circle with the number "13" at the center of it. I want to put it like the one on the picture. Generally, I want it to be scaled up to a fixed size, not the whole surface.
I use material.diffuse.contents property of SCNGeometry to set the texture and I found contentsTransform property in the documentation which can probably help me sort it out but I didn't find an explanation how to use it with the sphere object.
Is it something that is possible with pure SceneKit? Any help would be very appreciated.
You need a preliminarily modelled geometry (polygonal sphere in your case) and its UV Mapped texture that's made in 3D modelling software (Autodesk Maya for instance).
Watch this short movie to find out how to get UV-mapped texture.

Can I change anchors or move images with ARKit and ARSK View?

I am trying to build a compass with ARKit, but I am having trouble with moving images. The compass is made up of 4 sprites for each of the cardinal directions, and they each hover one meter away from the camera in their specific locations. I would like the compass to surround the camera, so that even when the user moves, the compass still surrounds them. However, I do not know how to move the positions of these images after they are set for the first time.
I know it is possible to move nodes in an ARSCN View, but I am using an ARSK View, and as far as I know, it is impossible to move an anchor. In what way could I change the positions of the images if I do not move the anchor? Is this even possible with ARSK View, or should I give up and switch to ARSCN View?
Your use case suggests you don't really need elements that "move" in 3D, but elements whose 3D position is fixed relative to the camera. This sort of thing is trivial in a 3D framework like SceneKit, but much harder when you're trying to work in the space between ARKit (which mostly is concerned with world-relative positions) and a 2D framework that "fakes" a 3D effect for 2D content.
In SceneKit, you can make nodes follow the camera by making them children of the pointOfView node. Of course, that'll make them follow not just the camera's position but also orientation. If you want to selectively follow some aspects of the camera's transform but not others, you'd do well to combine node hierarchy with constraints — for example, a child of the camera node with a world space orientation constraint always returning identity, so that the node follows the camera's position but not its orientation.

Drawing on a plane in SceneKit

I created a SCNPlane in my scene. I set the diffuse content of the SCNPlane to an image. Now I need to display other details on the plane (e.g. the name of the plane, and other simple drawings like an arrow).
This seems like a simple task but I could not find any relevant information. Should I create other geometries and attach them to the plane? If so, how do I do that without z-fighting occurring?
Materials in SceneKit are very flexible. When you are assigning something to the diffuse or ambient property you are assigning a SCNMaterialProperty. From Apples docs you can assign:
An image object, or a path or URL to an image file
A specially formatted image or array of six images to be used as a cube map
A Core Animation layer or layer hierarchy, which itself may contain animated content
A SpriteKit texture providing a static image, or an entire SpriteKit scene rendering animated 2D content.
I haven't got the Core Animations layers to work properly, maybe someone else can give more information on it, but I have been using SpriteKit and it is really easy to set up.
Create a SKScene and add animate it as much as you want
Set the size of your scene. SceneKit will scale this up if your plane is bigger than your size.
Add it to your materials diffuse property

iOS - Adding a 2D image to a scenekit game

Hello i can't for the life of me work out how to add a 2D image in the scene using scenekit is it even possible? What I'm trying to accomplish is have a 3D flying plane over a 2D background image but the background image can't cover the whole screen. Thanks to anyone that can help
Others have said plenty good suggestions above.
Let me summarize each solution with different scenarios:
Using scnScene.background: Easiest, but fullscreen and static. You cannot display in a smaller area of the scene, nor can you customize the transformations.
Using scnScene.overlaySKScene to display a 2D SKScene and adding image sprite. This is probably what fits your scenario. If you want static but with configurable transformations, this is a good choice. Notably overlaySKScene is recommended by Apple to create HUD in your 3D scene.
However, if you want the 2D content to track the 3D movement, you need to do some coordinate conversion from 3D space to 2D space every frame. Bad news is the job is done by CPU, which will add performance drag. (Believe me, this frustrate me too!)
Using SCNNode with SCNPlane geometry and set the diffuse.content with the image; add SCNBillBoardConstraint to the node to ensure it's always facing the camera.
Most flexible. However if your camera is not orthographic, the picture is going to zoom as the fov of camera changes, which doesn't look 2D but rather a hanging 3D billboard.
SceneKit and SpriteKit play very nicely together.
Implement the background 2D image as a SceneKit node with SCNPlane geometry, using your image as the plane's material. If you want to get fancier, use a full, live SpriteKit scene as the SCNPlane's material. Place that node at the far end of your camera's frustum, with your 3D aircraft in front of it.
You might also consider providing a cube map (skybox) as your scene's background. See SCNScene.background.
You can use the background property on SCNScene to set a background image.
scnScene.background.contents = UIImage(named: "myImage")
Contents
You can set a value for this property using any of the following
types:
A color (NSColor/UIColor or CGColorRef), specifying a constant color
across the material’s surface
An image (NSImage/UIImage or CGImageRef), specifying a texture to be
mapped across the material’s surface
An NSString or NSURL object specifying the location of an image file
An array of six images (NSArray), specifying the faces of a cube map
A Core Animation layer (CALayer)
A texture (SKTexture, MDLTexture, MTLTexture, or GLKTextureInfo)
A Sprite Kit scene (SKScene)

How can I add a texture to a joint in SpriteKit?

Maybe I could do it with the anchor points, but I don't really understand how I should do that.
The solution I'm building needs to have a SKSpriteNode with a texture for the joint, then add it as a child of one of the conjoining nodes, such that it covers the area the SKPhysicsJoint is operating on. Anytime I rotate the joint the texture rotates with it. I got the idea from action figures with hidden joints, basically, you're just putting something over the mechanical joint, in order to make for more pleasing aesthetics.
I don't know if this will work for you, but you could also define a texture using the centerRect of an existing texture and then define the part you want to paint on the joint node. This is more work than I wanted to put in, depending on your artwork assets this may be a good way to get around having another image in your bundle. I'm the artist as well as the programmer, so its faster for me to just create a joint image and add another node over the upper and lower nodes in the joint.
Joints can't have a texture. You can estimate or for some joints calculate where the connection point is by using the two connected body's positions and then put a sprite there (and continue to update the sprite's position).

Resources