Skip to content

Instantly share code, notes, and snippets.

@cenkbilgen
Created March 12, 2019 17:38
Show Gist options
  • Save cenkbilgen/ba5da0b80f10dc69c10ee59d4ccbbda6 to your computer and use it in GitHub Desktop.
Save cenkbilgen/ba5da0b80f10dc69c10ee59d4ccbbda6 to your computer and use it in GitHub Desktop.
A SceneKit node showing the world origin and axis directions. Helpful in ARKit, to know where exactly the session started and relative node locations.
//
// OriginAxis.swift
//
// Created by abc on 2019-03-07.
// Copyright © 2019 Cenk Bilgen. All rights reserved.
//
import Foundation
import SceneKit
class Origin: SCNNode {
// see: https://developer.apple.com/documentation/arkit/arsessionconfiguration/worldalignment/gravityandheading
// if ar session configured with gravity and heading, then +x is east, +y is up, +z is south
private enum Axis {
case x, y, z
var normal: float3 {
switch self {
case .x: return simd_float3(1, 0, 0)
case .y: return simd_float3(0, 1, 0)
case .z: return simd_float3(0, 0, 1)
}
}
}
// TODO: Set pivot to origin and redo tranforms, it'll make it easier to place additional nodes
init(length: CGFloat = 0.1, radiusRatio ratio: CGFloat = 0.04, color: (x: UIColor, y: UIColor, z: UIColor, origin: UIColor) = (.blue, .green, .red, .cyan)) {
// x-axis
let xAxis = SCNCylinder(radius: length*ratio, height: length)
xAxis.firstMaterial?.diffuse.contents = color.x
let xAxisNode = SCNNode(geometry: xAxis)
// by default the middle of the cylinder will be at the origin aligned to the y-axis
// need to spin around to align with respective axes and shift position so they start at the origin
xAxisNode.simdWorldOrientation = simd_quatf.init(angle: .pi/2, axis: Axis.z.normal)
xAxisNode.simdWorldPosition = simd_float1(length)/2 * Axis.x.normal
// y-axis
let yAxis = SCNCylinder(radius: length*ratio, height: length)
yAxis.firstMaterial?.diffuse.contents = color.y
let yAxisNode = SCNNode(geometry: yAxis)
yAxisNode.simdWorldPosition = simd_float1(length)/2 * Axis.y.normal // just shift
// z-axis
let zAxis = SCNCylinder(radius: length*ratio, height: length)
zAxis.firstMaterial?.diffuse.contents = color.z
let zAxisNode = SCNNode(geometry: zAxis)
zAxisNode.simdWorldOrientation = simd_quatf(angle: -.pi/2, axis: Axis.x.normal)
zAxisNode.simdWorldPosition = simd_float1(length)/2 * Axis.z.normal
// dot at origin
let origin = SCNSphere(radius: length*ratio)
origin.firstMaterial?.diffuse.contents = color.origin
let originNode = SCNNode(geometry: origin)
super.init()
self.addChildNode(originNode)
self.addChildNode(xAxisNode)
self.addChildNode(yAxisNode)
self.addChildNode(zAxisNode)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
@aheze
Copy link

aheze commented Apr 12, 2021

Thank you so much! Exactly what I was looking for.

@Maxsix74
Copy link

Thank you so much! Good job

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment