SCNText rendering without curves, not font-like - ios

When I run this SceneKit code:
let txt = SCNText(string: "Hello", extrusionDepth: 0.2)
let textNode = SCNNode(geometry: txt)
scene.rootNode.addChildNode(textNode)
I get very angular text:
It seems to do this regardless of font and it behaves the same way on a device as in the simulator.
Here's the code in context:
// create a new scene
let scene = SCNScene()
// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 10, y: 0, z: 75)
// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLightTypeOmni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)
// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor.darkGrayColor()
scene.rootNode.addChildNode(ambientLightNode)
let txt = SCNText(string: "Hello", extrusionDepth: 0.2)
let textNode = SCNNode(geometry: txt)
scene.rootNode.addChildNode(textNode)
// retrieve the SCNView
let scnView = self.view as! SCNView
// set the scene to the view
scnView.scene = scene

SCNText subdivides the 2D Bézier path for your text just like Core Graphics would do if you were drawing it. You can always use the flatness property to make it smoother, but you won't get "sub-pixel smoothness".
To solve this issue you can use a bigger font size, so that the underlying Bézier path is bigger and more vertices are generated when discretization occurs.

My solution was using big font as #mnuages was suggested then using scale on the text node with
animatedTextNode.scale = SCNVector3(0.1, 0.1, 0.1)
to get what size I wanted.
In that case when you animate text and when it comes closer to the camera it looks smooth.

Related

How to use ScnNode as a ScnLight?

var sun = SCNNode(geometry: SCNSphere(radius:0.35))
sun.geometry?.firstMaterial?.diffuse.contents=#imageLiteral(resourceName: "Sun")
sun.position=SCNVector3(0,0,-1)
And i want to use the sun SCNSphere as a omni light source.
let OmniLight = SCNLight()
OmniLight.type = SCNLight.LightType.omni
OmniLight.color = UIColor.white
But if i run this code, the sun is full black.
add it to the scene:
scene.rootNode.addChildNode(sun)
Here's example playground code:
import UIKit
import SceneKit
import PlaygroundSupport
// create a scene view with an empty scene
var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 640, height: 480))
var scene = SCNScene()
sceneView.scene = scene
PlaygroundPage.current.liveView = sceneView
// default lighting
sceneView.autoenablesDefaultLighting = false
// a camera
var cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 3)
scene.rootNode.addChildNode(cameraNode)
// your code (minus the image)
var sun = SCNNode(geometry: SCNSphere(radius:0.35))
sun.geometry?.firstMaterial?.diffuse.contents = UIColor.orange
sun.position=SCNVector3(0,0,-1)
let OmniLight = SCNLight()
OmniLight.type = SCNLight.LightType.omni
OmniLight.color = UIColor.white
// add to scene
scene.rootNode.addChildNode(sun)

Scene Kit node not rotating

I am trying to rotate by scene kit node, however it is not rotating.
I want it to rotate around the y axis. It is a sphere.
let node = SCNNode()
node.geometry = SCNSphere(radius: 1)
node.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "diffuse.png")
node.geometry?.firstMaterial?.specular.contents = UIImage(named: "specular.png")
node.geometry?.firstMaterial?.emission.contents = UIImage(named: "emission.png")
scene.rootNode.addChildNode(node)
let action = SCNAction.rotate(by:360 * CGFloat((Double.pi)/180.0), around: SCNVector3(x: 0, y: 1, z: 0), duration: 8)
let repeatAction = SCNAction.repeatForever(action)
node.runAction(repeatAction)
Are you certain it isn't rotating? I'm not sure what your diffuse, specular and emission images are but maybe because it's a sphere it just doesn't really look like it is rotating because it looks the same from all sides.
Running the same action on a cube in viewDidAppear is working for me, so it could just be that you can't really notice the sphere rotating. I used this code:
let node = SCNNode()
node.geometry = SCNBox (width: 0.5, height: 0.5, length: 0.5, chamferRadius: 0.1)
node.position = SCNVector3Make(0, 0, -1)
sceneView.scene.rootNode.addChildNode(node)
let action = SCNAction.rotate(by:360 * CGFloat((Double.pi)/180.0), around: SCNVector3(x: 0, y: 1, z: 0), duration: 8)
let repeatAction = SCNAction.repeatForever(action)
node.runAction(repeatAction)
The cube is rotating fine with the way that you rotated the SCNNode.
Hope this helps

SceneKit With Vuforia AR library custom models

I am new in SceneKit, working with swift 3 and latest Vuforia library 6-2-9.
I have a problem with applying textures on custom 3D models.
fileprivate func createDefaultMarkerScene(with view: VuforiaEAGLView) -> SCNScene {
let scene = SCNScene()
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light?.type = .omni
lightNode.light?.color = UIColor.lightGray
lightNode.position = SCNVector3(x: 0, y: 0, z: 1000)
scene.rootNode.addChildNode(lightNode)
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light?.type = .ambient
ambientLightNode.light?.color = UIColor.darkGray
scene.rootNode.addChildNode(ambientLightNode)
let geoNode = SCNNode()
geoNode.name = "model_model"
let normalsSources = SCNGeometrySource(normals: normalsSCNVector3)
let verticesSources = SCNGeometrySource(vertices: verticesSCNVector3)
let texCoordsSources = SCNGeometrySource(textureCoordinates: texCoordCGPoint)
let indicesElements = SCNGeometryElement(indices: indices, primitiveType: SCNGeometryPrimitiveType.triangles)
geoNode.geometry = SCNGeometry(sources: [verticesSources, normalsSources, texCoordsSources], elements: [indicesElements])
geoNode.position = SCNVector3(x: 0, y: 0, z: 0)
geoNode.scale = SCNVector3(x: 50, y: 50, z: 50)
let material = SCNMaterial()
material.diffuse.contents = UIImage(named: "grad_ao.png")
geoNode.geometry?.firstMaterial = material
scene.rootNode.addChildNode(geoNode)
return scene
}
Model is properly rendered, but applied texture is completely messed up. I have tried with rotated image, also uv coordinates all ok [0..1].
Any ideas? Thank you
I have managed to fix an issue.
The key is in "texture.png" file.
I just need to flip the image for 180 degrees with:
material.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0)

Scenekit: Animating Camera Node While Using Constraints

I am attempting to animate the camera node in Scenekit while having the camera look at a specific point with a constraint. For some reason activating the constraint locks the camera position.
Is there a specific reason this does not work or what am I missing here?
cameraNode = SCNNode()
let camera = SCNCamera()
cameraNode.camera = camera
cameraNode.position = SCNVector3Make(5.0, 10.0, 5.0)
scene.rootNode.addChildNode(cameraNode)
let center = SCNNode()
center.position = SCNVector3Make(0, 0, 0)
let lookConstraint = SCNLookAtConstraint(target: center)
cameraNode.constraints = [lookConstraint]
let firstAnimation = SCNAction.move(to: SCNVector3Make(10, 10, 10), duration: 2.0)
let secondAnimation = SCNAction.move(by: SCNVector3Make(0, 5, 5), duration: 2.0)
let sequence = SCNAction.sequence([firstAnimation, secondAnimation])
cameraNode.runAction(sequence)

Create smoother edges or otherwise fix jagged edges on box in SCNView?

The code below generates a red box in a SCNView. However, the edges are jagged along the top and bottom of the side/element facing you (as illustrated by the attachment). The goal is to render smoother edges similar to Minecraft boxes. Changing the camera position reduces the pixelation of certain edges, so is this a camera angle issue? If yes, is it possible to render boxes with smooth edges no matter the camera angle?
For instance setting the camera position to SCNVector3(x: 0.0, y: 0.0, z: 10.0) renders the box effectively in 2D and with crisp edges (second attachment).
let sceneView = SCNView(frame: self.view.frame)
self.view.addSubview(sceneView)
let scene = SCNScene()
sceneView.scene = scene
let camera = SCNCamera()
let cameraNode = SCNNode()
cameraNode.camera = camera
cameraNode.position = SCNVector3(x: -3.0, y: 0.0, z: 10.0)
let ambientLight = SCNLight()
ambientLight.type = SCNLightTypeAmbient
ambientLight.color = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0)
cameraNode.light = ambientLight
let light = SCNLight()
light.type = SCNLightTypeOmni
let lightNode = SCNNode()
lightNode.light = light
lightNode.position = SCNVector3(x: 0, y: 20, z: 10)
let cubeGeometry = SCNBox(width: 3.0, height: 3.0, length: 3.0, chamferRadius: 0.0)
let cubeNode = SCNNode(geometry: cubeGeometry)
let planeGeometry = SCNPlane(width: 100.0, height: 100.0)
let planeNode = SCNNode(geometry: planeGeometry)
planeNode.eulerAngles = SCNVector3(x: GLKMathDegreesToRadians(-90), y: 0, z: 0)
planeNode.position = SCNVector3(x: 0, y: -0.5, z: 0)
let redMaterial = SCNMaterial()
redMaterial.diffuse.contents = UIColor.redColor()
cubeGeometry.materials = [redMaterial]
let greenMaterial = SCNMaterial()
greenMaterial.diffuse.contents = UIColor.greenColor()
planeGeometry.materials = [greenMaterial]
let constraint = SCNLookAtConstraint(target: cubeNode)
constraint.gimbalLockEnabled = true
cameraNode.constraints = [constraint]
lightNode.constraints = [constraint]
scene.rootNode.addChildNode(lightNode)
scene.rootNode.addChildNode(cameraNode)
scene.rootNode.addChildNode(cubeNode)
scene.rootNode.addChildNode(planeNode)
As mentioned in the comments, if you want to antialias every frame set the antialiasingMode. It doesn’t do as nice a job as CoreGraphics but it’s reasonably nice. However, it does increase the workload a ton, so you’re going to burn batteries and slow down your framerate.
On OS X the default is to 4x multisample every frame. On iOS the default is no multisampling, since it’s so expensive.
Luckily there’s a solution I much prefer, which is to turn on jittering. It’s kind of like multisampling but lazy. When objects are moving they are rendered normally (with jaggies), but when they stop moving the renderer runs like 96 more frames in the background and smooths out all the jaggies.
The final look is much better than antialiasing (because there’s no “96x antialiasing mode”) and on fast hardware most people I’ve shown it to don’t realize that the quality is changing when objects move.

Resources