Skip to content

Instantly share code, notes, and snippets.

@jungchris
Created November 20, 2020 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jungchris/61c71bd5f156cf7e072195e1891cf010 to your computer and use it in GitHub Desktop.
Save jungchris/61c71bd5f156cf7e072195e1891cf010 to your computer and use it in GitHub Desktop.
Detected Objects with Video Overlay
//
// ViewController.swift
// helloVideoOnObjectDetected
//
// Created by Chris Jungmann on 11/20/20.
//
import UIKit
import SceneKit
import ARKit
import AVFoundation
class ViewController: UIViewController, ARSCNViewDelegate {
// video player
var player : AVPlayer?
var playerLooper: AVPlayerLooper!
var queuePlayer: AVQueuePlayer!
// used for video node
let videoNode = SCNNode(geometry: SCNPlane())
@IBOutlet var sceneView: ARSCNView!
@IBOutlet weak var buttonStart: UIButton!
@IBOutlet weak var buttonStop: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
// Show statistics such as fps and timing information
sceneView.showsStatistics = true
// Create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!
// Set the scene to the view
sceneView.scene = scene
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingConfiguration()
// Object Detection
configuration.detectionObjects = ARReferenceObject.referenceObjects(inGroupNamed: "ARResourceGroup", bundle: Bundle.main)!
// Run the view's session
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
// MARK: - ARSCNViewDelegate
@IBAction func buttonStartTouch(_ sender: Any) {
// prepare the video reference
let fileURL = URL(fileURLWithPath: Bundle.main.path(forResource: "team-walking", ofType: "mp4")!)
player = AVPlayer(url: fileURL)
// let asset: AVAsset = AVAsset(url: fileURL)
let asset = AVAsset(url: fileURL)
let playerItem = AVPlayerItem(asset: asset)
self.queuePlayer = AVQueuePlayer(playerItem: playerItem)
self.playerLooper = AVPlayerLooper(player: queuePlayer, templateItem: playerItem)
// player = AVPlayer(url: fileURL)
videoNode.geometry?.firstMaterial?.diffuse.contents = player
player!.play()
}
@IBAction func buttonStopTouch(_ sender: Any) {
player!.pause()
}
func createTextNode(string: String) -> SCNNode {
let text = SCNText(string: string, extrusionDepth: 0.1)
text.font = UIFont.systemFont(ofSize: 1.0)
text.flatness = 0.01
text.firstMaterial?.diffuse.contents = UIColor.white
let textNode = SCNNode(geometry: text)
let fontSize = Float(0.04)
textNode.scale = SCNVector3(fontSize, fontSize, fontSize)
return textNode
}
func createNode(objectAnchor: ARObjectAnchor) -> SCNNode {
// set width & height
videoNode.geometry?.setValue(CGFloat(objectAnchor.referenceObject.extent.x), forKey: "width")
videoNode.geometry?.setValue(CGFloat(objectAnchor.referenceObject.extent.z), forKey: "height")
// now set node properties. The UIImage is a content placeholder, replaced by buttonStartTouch
videoNode.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "ocean.jpg")
videoNode.geometry?.firstMaterial?.isDoubleSided = true
videoNode.position = SCNVector3(objectAnchor.referenceObject.center.x, objectAnchor.referenceObject.center.y, objectAnchor.referenceObject.center.z)
// rotate 90 degrees about x axis <--x-->
videoNode.eulerAngles = SCNVector3(-90.degreesToRadians, 0, 0)
return videoNode
}
// Override to create and configure nodes for anchors added to the view's session.
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
print("SCNSceneRenderer")
print(anchor.name as Any)
print("........")
print(anchor.description as Any)
let node = SCNNode()
if let objectAnchor = anchor as? ARObjectAnchor {
print("if condition meets 'ARObjectAnchor'")
/*
let plane = SCNPlane(width: CGFloat(objectAnchor.referenceObject.extent.x * 0.8), height: CGFloat(objectAnchor.referenceObject.extent.y * 0.5))
plane.cornerRadius = plane.width / 8
plane.firstMaterial?.diffuse.contents = UIImage(named: "ocean.jpg")
plane.firstMaterial?.isDoubleSided = true
plane.firstMaterial?.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0)
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3Make(objectAnchor.referenceObject.center.x, objectAnchor.referenceObject.center.y + 0.1, objectAnchor.referenceObject.center.z)
*/
let childNode = createNode(objectAnchor: objectAnchor)
// node.addChildNode(planeNode)
node.addChildNode(childNode)
}
return node
}
func session(_ session: ARSession, didFailWithError error: Error) {
// Present an error message to the user
}
func sessionWasInterrupted(_ session: ARSession) {
// Inform the user that the session has been interrupted, for example, by presenting an overlay
}
func sessionInterruptionEnded(_ session: ARSession) {
// Reset tracking and/or remove existing anchors if consistent tracking is required
}
}
extension Int {
var degreesToRadians: Double { return Double(self) * .pi/180 }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment