Skip to content

Instantly share code, notes, and snippets.

@lfarah
Created April 29, 2018 07:36
Show Gist options
  • Save lfarah/e4fecaa696edc36c58a717686d6f8a1e to your computer and use it in GitHub Desktop.
Save lfarah/e4fecaa696edc36c58a717686d6f8a1e to your computer and use it in GitHub Desktop.
/*
See LICENSE folder for this sample’s licensing information.
Abstract:
Wrapper SceneKit node for virtual objects placed into the AR scene.
*/
import Foundation
import SceneKit
import ARKit
class VirtualObject: SCNNode {
var modelName: String = ""
var fileExtension: String = ""
var thumbImage: UIImage!
var title: String = ""
var modelLoaded: Bool = false
var viewController: ViewController?
override init() {
super.init()
self.name = "Virtual object root node"
}
init(geometry: SCNGeometry?) {
super.init()
self.geometry = geometry
self.name = "Virtual object root node"
self.modelName = "modelName"
self.fileExtension = "fileExtension"
self.thumbImage = #imageLiteral(resourceName: "tom")
self.title = "Tom"
}
init(modelName: String, fileExtension: String, thumbImageFilename: String, title: String) {
super.init()
self.name = "Virtual object root node"
self.modelName = modelName
self.fileExtension = fileExtension
self.thumbImage = UIImage(named: thumbImageFilename)
self.title = title
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func loadModel() {
guard let virtualObjectScene = SCNScene(named: "\(modelName).\(fileExtension)", inDirectory: "Models.scnassets/\(modelName)") else {
return
}
let wrapperNode = SCNNode()
for child in virtualObjectScene.rootNode.childNodes {
child.geometry?.firstMaterial?.lightingModel = .physicallyBased
child.movabilityHint = .movable
wrapperNode.addChildNode(child)
}
self.addChildNode(wrapperNode)
modelLoaded = true
}
func unloadModel() {
for child in self.childNodes {
child.removeFromParentNode()
}
modelLoaded = false
}
func translateBasedOnScreenPos(_ pos: CGPoint, instantly: Bool, infinitePlane: Bool) {
guard let controller = viewController else {
return
}
let result = controller.worldPositionFromScreenPosition(pos, objectPos: self.position, infinitePlane: infinitePlane)
controller.moveVirtualObjectToPosition(result.position, instantly, !result.hitAPlane)
}
}
extension VirtualObject {
static func isNodePartOfVirtualObject(_ node: SCNNode) -> Bool {
if node.name == "Virtual object root node" {
return true
}
if node.parent != nil {
return isNodePartOfVirtualObject(node.parent!)
}
return false
}
}
// MARK: - Protocols for Virtual Objects
protocol ReactsToScale {
func reactToScale()
}
extension SCNNode {
func reactsToScale() -> ReactsToScale? {
if let canReact = self as? ReactsToScale {
return canReact
}
if parent != nil {
return parent!.reactsToScale()
}
return nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment