Skip to content

Instantly share code, notes, and snippets.

@wizard1066
Last active January 20, 2023 09:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wizard1066/08046c5aafe91ca9f9f0aca45fb1e1b7 to your computer and use it in GitHub Desktop.
Save wizard1066/08046c5aafe91ca9f9f0aca45fb1e1b7 to your computer and use it in GitHub Desktop.
//
// ContentView.swift
// ARKit3
//
// Created by localuser on 25.12.22.
//
import SwiftUI
import ARKit
import Combine
import Foundation
import CoreML
let feedback = PassthroughSubject<CGPoint,Never>()
let screenSize: CGRect = UIScreen.main.bounds
let screenWidth: CGFloat = UIScreen.main.bounds.width
let screenHeight: CGFloat = UIScreen.main.bounds.height
struct Fonts {
static func avenirNextCondensedBold (size: CGFloat) -> Font {
return Font.custom("AvenirNextCondensed-Bold", size: size)
}
static func neutonRegular (size: CGFloat) -> Font {
return Font.custom("Neuton-Regular", size: size)
}
}
class Looker: ObservableObject {
static var shared = Looker()
@Published var paused = false
@Published var gazeX = ""
@Published var gazeY = ""
@Published var gazeA = ""
@Published var outOfRange = false
@Published var leftIn = "0"
@Published var leftOut = "0"
@Published var rightIn = "0"
@Published var rightOut = "0"
@Published var leftUp = "0"
@Published var leftDown = "0"
@Published var rightUp = "0"
@Published var rightDown = "0"
}
extension Text {
init(_ string: String, configure: ((inout AttributedString) -> Void)) {
var attributedString = AttributedString(string) /// create an `AttributedString`
configure(&attributedString)
self.init(attributedString)
}
}
struct ContentView: View {
@State var arview = ARSCNView()
@State var gaze = CGPoint.zero
@ObservedObject var looked = Looker.shared
var body: some View {
ZStack {
CustomARView(view: arview)
Circle()
.stroke(looked.outOfRange ? .red : .green, lineWidth: looked.outOfRange ? 4 : 1)
.frame(width: 312, height: 312)
VStack(spacing:0) {
HStack {
Text("LI \(looked.leftIn)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Double(looked.leftIn)! > 0 ? Color.green: Color.clear)
.background(Double(looked.leftIn)! > 0 ? Color.white: Color.clear)
Text("LO \(looked.leftOut)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Double(looked.leftOut)! > 0 ? Color.green: Color.clear)
.background(Double(looked.leftOut)! > 0 ? Color.white: Color.clear)
Text("RI \(looked.rightIn)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Double(looked.rightIn)! > 0 ? Color.green: Color.clear)
.background(Double(looked.rightIn)! > 0 ? Color.white: Color.clear)
Text("RO \(looked.rightOut)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Double(looked.rightOut)! > 0 ? Color.green: Color.clear)
.background(Double(looked.rightOut)! > 0 ? Color.white: Color.clear)
VStack {
Spacer()
HStack {
Text("\(looked.gazeY)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Color.blue)
.background(Color.white)
Text("\(looked.gazeA)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Color.red)
.background(Color.white)
Text("\(looked.gazeX)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Color.blue)
.background(Color.white)
}
}
Text("LU \(looked.leftUp)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Double(looked.leftUp)! > 0 ? Color.green: Color.clear)
.background(Double(looked.leftUp)! > 0 ? Color.white: Color.clear)
Text("LD \(looked.leftDown)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Double(looked.leftDown)! > 0 ? Color.green: Color.clear)
.background(Double(looked.leftDown)! > 0 ? Color.white: Color.clear)
Text("RU \(looked.rightUp)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Double(looked.rightUp)! > 0 ? Color.green: Color.clear)
.background(Double(looked.rightUp)! > 0 ? Color.white: Color.clear)
Text("RD \(looked.rightDown)")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(Double(looked.rightDown)! > 0 ? Color.green: Color.clear)
.background(Double(looked.rightDown)! > 0 ? Color.white: Color.clear)
}
}
VStack {
Text("paused")
.font(Fonts.avenirNextCondensedBold(size: 24))
.foregroundColor(looked.paused ? Color.white:Color.clear)
.background(looked.paused ? Color.red:Color.clear)
.onTapGesture {
looked.paused.toggle()
}
Spacer()
}
// Circle()
// .stroke(Color.green, lineWidth: 2)
// .frame(width: 16, height: 16)
// .position(looked.lookPoint)
// VStack {
// Circle()
// .fill(looked.lookUp ? Color.white: Color.red)
// .frame(width: 32, height: 32)
// .padding(.bottom,36)
// HStack {
// Circle()
// .fill(looked.lookLeft ? Color.white: Color.red)
// .frame(width: 32, height: 32)
// .padding(.trailing, 36)
// Circle()
// .stroke(Color.white, lineWidth: 8)
// .frame(width: 64, height: 64)
// .padding()
// .onTapGesture {
// print("reste")
// looked.lookUp = false
// looked.lookDown = false
// looked.lookRight = false
// looked.lookLeft = false
// }
// Circle()
// .fill(looked.lookRight ? Color.white: Color.red)
// .frame(width: 32, height: 32)
// .padding(.leading, 36)
// }
// Circle()
// .fill(looked.lookDown ? Color.white: Color.red)
// .frame(width: 32, height: 32)
// .padding(.top,36)
// }
}
}
}
struct CustomARView: UIViewRepresentable {
typealias UIViewType = ARSCNView
var view:ARSCNView
var options: [Any] = []
func makeUIView(context: Context) -> ARSCNView {
view.session.delegate = context.coordinator
return view
}
func updateUIView(_ view: ARSCNView, context: Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self.view)
}
}
class Coordinator: NSObject, ARSCNViewDelegate, ARSessionDelegate {
private var trackingView:ARSCNView
private var sphereNode: SCNNode!
private var cubeNode: SCNNode!
private var satelliteNode: SCNNode!
private var satelliteNodeY: SCNNode!
private var blinked = false
private var config = MLModelConfiguration()
@ObservedObject var looked = Looker.shared
init(_ view: ARSCNView) {
self.trackingView = view
super.init()
guard ARFaceTrackingConfiguration.isSupported else {
fatalError("Face tracking not available on this on this device model!")
}
let connectSession = MultipeerSession.shared
let configuration = ARFaceTrackingConfiguration()
self.trackingView.session.run(configuration)
self.trackingView.delegate = self
let geo3 = SCNSphere(radius: 0.5)
geo3.segmentCount = 16
sphereNode = SCNNode(geometry: geo3)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.white.withAlphaComponent(1)
sphereNode.geometry?.firstMaterial?.fillMode = .fill
sphereNode.simdPosition = SIMD3(x: 0, y: 1, z: -6)
self.trackingView.scene.rootNode.addChildNode(sphereNode)
let geo = SCNSphere(radius: 0.5)
satelliteNode = SCNNode(geometry: geo)
satelliteNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue.withAlphaComponent(1)
satelliteNode.position = SCNVector3(x: 0, y: 0, z: 24)
// satelliteNodeY = SCNNode(geometry: geo)
// satelliteNodeY.geometry?.firstMaterial?.diffuse.contents = UIColor.red.withAlphaComponent(0.8)
// satelliteNodeY.position = SCNVector3(x: 0, y: 0, z: -6)
let colorNames:[UIColor] = [UIColor.red, .blue, .green, .purple, .orange, .brown]
var colorMaterials:[SCNMaterial] = []
for colors in colorNames {
let newMaterial = SCNMaterial()
newMaterial.diffuse.contents = colors
colorMaterials.append(newMaterial)
}
let geo2 = SCNBox(width: 0.25, height: 0.25, length: 0.25, chamferRadius: 0)
cubeNode = SCNNode(geometry: geo2)
// cubeNode.geometry?.materials = colorMaterials
cubeNode.position = SCNVector3(x: 0, y: 0, z: -10)
cubeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.clear
cubeNode.addChildNode(satelliteNode)
// cubeNode.addChildNode(satelliteNodeY)
self.trackingView.scene.rootNode.addChildNode(cubeNode)
}
var xCords:[Float] = []
var yCords:[Float] = []
var spawnTime:TimeInterval = 0
var lastTime:TimeInterval? = nil
var faceAnchor: ARFaceAnchor? = nil
var changeX:Float = 0
var changeY:Float = 0
struct Regard {
let direct:String!
let eyeLookIn_L:Double!
let eyeLookOut_R:Double!
let eyeLookIn_R:Double!
let eyeLookOut_L:Double!
let eyeLookDown_L:Double!
let eyeLookDown_R:Double!
let eyeLookUp_L:Double!
let eyeLookUp_R:Double!
let angleX:Double!
let angleY:Double!
}
var looks:[ARFaceAnchor.BlendShapeLocation:Double] = [:]
var log:[Regard] = []
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
lastTime = time
if time > spawnTime {
if faceAnchor != nil && !looked.paused {
DispatchQueue.main.async { [self] in
self.cubeNode.simdOrientation = faceAnchor!.leftEyeTransform.orientation
let angleX = rad2deg(Double(self.cubeNode.eulerAngles.x))
let angleY = rad2deg(Double(self.cubeNode.eulerAngles.y))
let eyeLookIn_L = (faceAnchor?.blendShapes[.eyeLookInLeft]!.doubleValue)!
let eyeLookIn_R = (faceAnchor?.blendShapes[.eyeLookInRight]?.doubleValue)!
let eyeLookOut_R = (faceAnchor?.blendShapes[.eyeLookOutRight]?.doubleValue)!
let eyeLookOut_L = (faceAnchor?.blendShapes[.eyeLookOutLeft]?.doubleValue)!
let eyeLookDown_L = (faceAnchor?.blendShapes[.eyeLookDownLeft]?.doubleValue)!
let eyeLookUp_L = (faceAnchor?.blendShapes[.eyeLookUpLeft]?.doubleValue)!
let eyeLookDown_R = (faceAnchor?.blendShapes[.eyeLookDownRight]?.doubleValue)!
let eyeLookUp_R = (faceAnchor?.blendShapes[.eyeLookUpRight]?.doubleValue)!
var modelName:String!
do {
let model = try
eyesClassifier48(configuration: config)
let prediction = try model.prediction(eyeLookIn_L: eyeLookIn_L, eyeLookOut_L: eyeLookOut_L, eyeLookIn_R: eyeLookIn_R, eyeLookOut_R: eyeLookOut_R, eyeLookDown_L: eyeLookDown_L, eyeLookDown_R: eyeLookDown_R, eyeLookUp_L: eyeLookUp_L, eyeLookUp_R: eyeLookUp_L, faceX: 0, faceY: 0)
modelName = prediction.direction
} catch {
print("model error")
}
let eyesLookDown = (eyeLookDown_R + eyeLookUp_R) / 2
let eyesLookUp = (eyeLookUp_L + eyeLookUp_R) / 2
let eyesLookLeft = (eyeLookOut_L + eyeLookIn_R) / 2
let eyesLookRight = (eyeLookOut_R + eyeLookIn_L) / 2
let eyesLookSide = (eyesLookLeft + eyesLookRight) / 2
let eyesTrue = (faceAnchor?.blendShapes[.browOuterUpLeft]!.doubleValue)! > 0.1
let talk = Speaking()
if eyesTrue {
let foo = log.filter({$0.direct == "eyesLeft"})
let foo2 = foo.filter({$0.eyeLookIn_L > 0})
let minValue = foo2.min { $0.eyeLookIn_L < $1.eyeLookIn_L }?.eyeLookIn_L
let maxValue = foo2.max { $0.eyeLookIn_L < $1.eyeLookIn_L }?.eyeLookIn_L
let sortedValues = foo2.sorted(by: { $0.eyeLookIn_L > $1.eyeLookIn_L} )
for foos in foo2 {
print("\(foos.eyeLookIn_L!)")
}
print("lookLeft \(minValue) \(maxValue)")
}
let angle = rad2deg(Double(faceAnchor!.transform.orientation.angle.binade))
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
//
let number = NSNumber(value: angleY)
let formattedValue = formatter.string(from: number)!
looked.gazeY = formattedValue.description
let number2 = NSNumber(value: angleX)
let formattedValue2 = formatter.string(from: number2)!
looked.gazeX = formattedValue2.description
let number3 = NSNumber(value: angle)
let formattedValue3 = formatter.string(from: number3)!
looked.gazeA = formattedValue3.description
var divisor = 0.3
var height:Float = 0.5
// if eyesLookLeft < 0.1 && eyesLookRight < 0.1 && eyesLookDown < 0.1 && eyesLookUp < 0.1 {
// sphereNode.simdPosition = SIMD3(x: 0, y: height, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.green.withAlphaComponent(0.8)
// //looked.gazeA = ""
// return
// }
if angle < 8 && !looked.paused {
looked.outOfRange = false
switch modelName {
case "eyesLeft":
//talk.speaker(words: ["left"])
sphereNode.simdPosition = SIMD3(x: -1, y: height, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue.withAlphaComponent(1)
//looked.paused = true
logEyes(look: "eyesLeft")
case "eyesRight":
//talk.speaker(words: ["right"])
sphereNode.simdPosition = SIMD3(x: 1, y: height, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue.withAlphaComponent(1)
//looked.paused = true
logEyes(look: "eyesRight")
case "eyesDown":
//talk.speaker(words: ["down"])
sphereNode.simdPosition = SIMD3(x: 0, y: height - 1, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red.withAlphaComponent(1)
//looked.paused = true
logEyes(look: "eyesDown")
case "eyesUp":
//talk.speaker(words: ["up"])
sphereNode.simdPosition = SIMD3(x: 0, y: height + 1, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red.withAlphaComponent(1)
//looked.paused = true
logEyes(look: "eyesUp")
case "eyesLeftUp":
//talk.speaker(words: ["high left"])
sphereNode.simdPosition = SIMD3(x: -1, y: height + 1, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.orange.withAlphaComponent(1)
//looked.paused = true
logEyes(look: "eyesLeftUp")
case "eyesRightUp":
//talk.speaker(words: ["high right"])
sphereNode.simdPosition = SIMD3(x: 1, y: height + 1, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.orange.withAlphaComponent(1)
//looked.paused = true
logEyes(look: "eyesRightUp")
case "eyesLeftDown":
//talk.speaker(words: ["low left"])
sphereNode.simdPosition = SIMD3(x: -1, y: height - 1, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.yellow.withAlphaComponent(1)
//looked.paused = true
logEyes(look: "eyesLeftDown")
case "eyesRightDown":
//talk.speaker(words: ["low right"])
sphereNode.simdPosition = SIMD3(x: 1, y: height - 1, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.yellow.withAlphaComponent(1)
//looked.paused = true
logEyes(look: "eyesRightDown")
default:
sphereNode.simdPosition = SIMD3(x: 0, y: height, z: -6)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.green.withAlphaComponent(0.8)
logEyes(look: "eyesCentre")
}
// if (eyesLookDown > 0.09) || (eyesLookUp > 0.09) {
// if eyesLookDown > 0.2 && eyesLookLeft > 0.2 {
// talk.speaker(words: ["southEast"])
// sphereNode.simdPosition = SIMD3(x: 1, y: height - 1, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.yellow.withAlphaComponent(1)
// looked.paused = true
// }
// if eyesLookDown > 0.2 && eyesLookRight > 0.2 {
// talk.speaker(words: ["southWest"])
// sphereNode.simdPosition = SIMD3(x: -1, y: height - 1, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.orange.withAlphaComponent(1)
// looked.paused = true
// }
// if eyesLookDown > 0.2 && eyesLookSide < 0.3 && eyesLookUp < 0.1 {
// talk.speaker(words: ["south"])
// sphereNode.simdPosition = SIMD3(x: 0, y: height - 1, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red.withAlphaComponent(1)
// looked.paused = true
// }
// if eyesLookUp > 0.2 && eyesLookRight > 0.2 {
// talk.speaker(words: ["northEast"])
// sphereNode.simdPosition = SIMD3(x: 1, y: height + 1, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.yellow.withAlphaComponent(1)
// looked.paused = true
// }
// if eyesLookUp > 0.2 && eyesLookLeft > 0.2 {
// talk.speaker(words: ["northWest"])
// sphereNode.simdPosition = SIMD3(x: -1, y: height + 1, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.orange.withAlphaComponent(1)
// looked.paused = true
// }
// if eyesLookUp > 0.2 && eyesLookSide < 0.3 && eyesLookDown < 0.1 {
// talk.speaker(words: ["north"])
// sphereNode.simdPosition = SIMD3(x: 0, y: height + 1, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red.withAlphaComponent(1)
// looked.paused = true
// }
// }
// if eyesLookLeft > 0.2 && eyesLookUp < 0.1 && eyesLookDown < 0.1 {
// talk.speaker(words: ["east"])
// sphereNode.simdPosition = SIMD3(x: 1, y: height, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue.withAlphaComponent(1)
// looked.paused = true
// }
// if eyesLookRight > 0.2 && eyesLookUp < 0.1 && eyesLookDown < 0.1 {
// talk.speaker(words: ["west"])
// sphereNode.simdPosition = SIMD3(x: -1, y: height, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue.withAlphaComponent(1)
// looked.paused = true
//
// }
} else {
looked.outOfRange = true
}
// let newX = (satelliteNode.worldPosition.x * 100).rounded() / 100
// let newY = (satelliteNode.worldPosition.y * 100).rounded() / 100
//
// let formatter = NumberFormatter()
// formatter.numberStyle = .decimal
// formatter.maximumFractionDigits = 2
//
// let number = NSNumber(value: newX)
// let formattedValue = formatter.string(from: number)!
//
// let number2 = NSNumber(value: newY)
// let formattedValue2 = formatter.string(from: number2)!
//
// looked.gazeX = formattedValue
// looked.gazeY = formattedValue2
// if newX < 1.5 && newY < 1.5 {
// sphereNode.simdPosition = SIMD3(x: 0, y: 0, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red.withAlphaComponent(0.90)
// }
// if (newX > 0.7 || newX < -0.7) {
// changeX = newX > 0 ? 2.0 : -2.0
// sphereNode.simdPosition = SIMD3(x: changeX, y: 0, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue.withAlphaComponent(0.90)
// }
// if (newY > 0.45 || newY < -0.9) {
// changeY = newY > 0 ? 1.0 : -1.0
// sphereNode.simdPosition = SIMD3(x: 0, y: changeY, z: -6)
// sphereNode.geometry?.firstMaterial?.diffuse.§ contents = UIColor.green.withAlphaComponent(0.90)
// }
}
}
spawnTime = time + TimeInterval(0.1)
showFaces()
}
func logEyes(look:String) {
let eyeLookIn_L = faceAnchor?.blendShapes[.eyeLookInLeft]?.doubleValue
let eyeLookIn_R = faceAnchor?.blendShapes[.eyeLookInRight]?.doubleValue
let eyeLookOut_R = faceAnchor?.blendShapes[.eyeLookOutRight]?.doubleValue
let eyeLookOut_L = faceAnchor?.blendShapes[.eyeLookOutLeft]?.doubleValue
let eyeLookDown_L = faceAnchor?.blendShapes[.eyeLookDownLeft]?.doubleValue
let eyeLookUp_L = faceAnchor?.blendShapes[.eyeLookUpLeft]?.doubleValue
let eyeLookDown_R = faceAnchor?.blendShapes[.eyeLookDownRight]?.doubleValue
let eyeLookUp_R = faceAnchor?.blendShapes[.eyeLookUpRight]?.doubleValue
let angleX = rad2deg(Double(self.cubeNode.eulerAngles.x))
let angleY = rad2deg(Double(self.cubeNode.eulerAngles.y))
let rec = Regard(direct: look, eyeLookIn_L: eyeLookIn_L, eyeLookOut_R: eyeLookOut_R, eyeLookIn_R: eyeLookIn_R, eyeLookOut_L: eyeLookOut_L, eyeLookDown_L: eyeLookDown_L, eyeLookDown_R: eyeLookDown_R, eyeLookUp_L: eyeLookUp_L, eyeLookUp_R: eyeLookUp_R, angleX: angleX, angleY: angleY)
log.append(rec)
}
}
func return2D(figure: Double) -> String {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
//
let number = NSNumber(value: figure)
let formattedValue = formatter.string(from: number)!
return formattedValue
}
func showFaces() {
for faces in [ARFaceAnchor.BlendShapeLocation.eyeLookOutRight, .eyeLookOutLeft, .eyeLookInRight, .eyeLookInLeft, .eyeLookUpLeft, .eyeLookUpRight, .eyeLookDownRight, .eyeLookDownLeft] {
//print("looks \(faces) \(looks[faces])")
}
// if looks[.cheekPuff] != 0 {
// DispatchQueue.main.async {
// self.looked.paused = true
// print("paused true")
// }
// }
// if looks[.cheekPuff] != 0 {
// DispatchQueue.main.async {
// self.looked.paused = false
// print("paused false")
// }
// }
DispatchQueue.main.async {
if !self.looked.outOfRange && !self.looked.paused {
if self.looks[.eyeLookInLeft] != nil {
self.looked.leftIn = self.return2D(figure: self.looks[.eyeLookInLeft] ?? 0)
self.looked.leftOut = self.return2D(figure: self.looks[.eyeLookOutLeft] ?? 0)
self.looked.rightIn = self.return2D(figure: self.looks[.eyeLookInRight] ?? 0)
self.looked.rightOut = self.return2D(figure: self.looks[.eyeLookOutRight] ?? 0)
self.looked.leftDown = self.return2D(figure: self.looks[.eyeLookDownLeft] ?? 0)
self.looked.leftUp = self.return2D(figure: self.looks[.eyeLookUpLeft] ?? 0)
self.looked.rightDown = self.return2D(figure: self.looks[.eyeLookDownRight] ?? 0)
self.looked.rightUp = self.return2D(figure: self.looks[.eyeLookUpRight] ?? 0)
}
}
}
}
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let faceAnchor = anchor as? ARFaceAnchor else { return }
self.faceAnchor = faceAnchor
looks.removeAll()
for faces in faceAnchor.blendShapes {
if looks[faces.key] != nil {
looks[faces.key]! = 0
} else {
looks[faces.key] = faceAnchor.blendShapes[faces.key]!.doubleValue
}
}
}
func dummy(_ anchor: ARAnchor) {
guard let faceAnchor = anchor as? ARFaceAnchor else { return }
DispatchQueue.main.async { [self] in
self.cubeNode.simdOrientation = faceAnchor.leftEyeTransform.orientation
// self.cubeNode.simdPosition = faceAnchor.leftEyeTransform.translation
// self.cubeNode.simdPosition.z = -10
// let foo = rad2deg(Double(quatToEulerAngles(self.cubeNode.simdOrientation).y))
//print("simdOrientation \(foo) \(satelliteNode.simdPosition.x) lnik \(link)")
// if (foo > 2) && (foo < 6) {
// SCNTransaction.begin()
// SCNTransaction.animationDuration = 1.0
// sphereNode.simdPosition = SIMD3(x: -1, y: 1, z: -6)
// SCNTransaction.commit()
// }
// if (foo > 6) && (foo < 12) {
// SCNTransaction.begin()
// SCNTransaction.animationDuration = 1.0
// sphereNode.simdPosition = SIMD3(x: -2, y: 1, z: -6)
// SCNTransaction.commit()
// }
// if foo > 18 && foo < 24 {
// SCNTransaction.begin()
// SCNTransaction.animationDuration = 1.0
// sphereNode.simdPosition = SIMD3(x: -3, y: 1, z: -6)
// SCNTransaction.commit()
// }
// if foo < -2 && foo > -6 {
// SCNTransaction.begin()
// SCNTransaction.animationDuration = 1.0
// sphereNode.simdPosition = SIMD3(x: 1, y: 1, z: -6)
// SCNTransaction.commit()
// }
// if foo < -6 && foo > -12 {
// SCNTransaction.begin()
// SCNTransaction.animationDuration = 1.0
// sphereNode.simdPosition = SIMD3(x: 2, y: 1, z: -6)
// SCNTransaction.commit()
// }
// if foo < -12 && foo > -24 {
// SCNTransaction.begin()
// SCNTransaction.animationDuration = 1.0
// sphereNode.simdPosition = SIMD3(x: 3, y: 1, z: -6)
// SCNTransaction.commit()
// }
// if foo > -3 && foo < 3 {
// SCNTransaction.begin()
// SCNTransaction.animationDuration = 1.0
// sphereNode.simdPosition = SIMD3(x: 0, y: 1, z: -6)
// SCNTransaction.commit()
// }
// print("BlendShapes ",faceAnchor.blendShapes.count)
if faceAnchor.blendShapes[.eyeLookInLeft]!.doubleValue < 0.3 &&
faceAnchor.blendShapes[.eyeLookInRight]!.doubleValue < 0.3 &&
faceAnchor.blendShapes[.eyeLookUpLeft]!.doubleValue < 0.3 &&
faceAnchor.blendShapes[.eyeLookDownLeft]!.doubleValue < 0.3 {
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.0
//sphereNode.simdPosition = SIMD3(x: 0, y: 0, z: -6)
SCNTransaction.commit()
}
if faceAnchor.blendShapes[.eyeLookInLeft]!.doubleValue > 0.3 {
//self.looked.lookRight = true
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.0
//sphereNode.simdPosition = SIMD3(x: -3, y: 0, z: -6)
SCNTransaction.commit()
}
if faceAnchor.blendShapes[.eyeLookInRight]!.doubleValue > 0.3 {
//self.looked.lookLeft = true
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.0
//sphereNode.simdPosition = SIMD3(x: 3, y: 0, z: -6)
SCNTransaction.commit()
}
if faceAnchor.blendShapes[.eyeLookUpLeft]!.doubleValue > 0.3 {
//self.looked.lookUp = true
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.0
//sphereNode.simdPosition = SIMD3(x: 0, y: 1, z: -6)
SCNTransaction.commit()
}
if faceAnchor.blendShapes[.eyeLookDownLeft]!.doubleValue > 0.3 {
//self.looked.lookDown = true
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.0
//sphereNode.simdPosition = SIMD3(x: 0, y: -1, z: -6)
SCNTransaction.commit()
}
if faceAnchor.blendShapes[.eyeLookInLeft]!.doubleValue > 0.2 &&
faceAnchor.blendShapes[.eyeLookDownLeft]!.doubleValue > 0.2 {
//self.looked.lookRight = true
//sphereNode.simdPosition = SIMD3(x: -2, y: -1, z: -6)
}
if faceAnchor.blendShapes[.eyeLookInLeft]!.doubleValue > 0.2 &&
faceAnchor.blendShapes[.eyeLookUpLeft]!.doubleValue > 0.2 {
//self.looked.lookLeft = true
//sphereNode.simdPosition = SIMD3(x: -2, y: 1, z: -6)
}
if faceAnchor.blendShapes[.eyeLookInRight]!.doubleValue > 0.2 &&
faceAnchor.blendShapes[.eyeLookDownLeft]!.doubleValue > 0.2 {
//self.looked.lookDown = true
//sphereNode.simdPosition = SIMD3(x: 2, y: -1, z: -6)
}
if faceAnchor.blendShapes[.eyeLookInRight]!.doubleValue > 0.2 &&
faceAnchor.blendShapes[.eyeLookUpLeft]!.doubleValue > 0.2 {
//self.looked.lookUp = true
//sphereNode.simdPosition = SIMD3(x: 2, y: 1, z: -6)
}
//var newX = Float(faceAnchor.lookAtPoint.x) * 8
//let newY = Float(faceAnchor.lookAtPoint.y) * 4
//let newXR = (newX * 100).rounded() / 100
//let newYR = (newY * 100).rounded() / 100
if faceAnchor.blendShapes[.cheekPuff]!.doubleValue > 0.5 {
blinked.toggle()
//print("blink")
}
let newX = (satelliteNode.worldPosition.x * 100).rounded() / 100
let newY = (satelliteNodeY.worldPosition.y * 100).rounded() / 100
let newXR = (newX * 100).rounded() / 100
let newYR = (newY * 100).rounded() / 100
xCords.append(newX)
yCords.append(newY)
//print("satX \(blinked) \(xCords.min()) \(xCords.max()) satY \(yCords.min()) \(yCords.max()) X \(newX) Y \(newY)")
SCNTransaction.begin()
SCNTransaction.animationDuration = 1
//sphereNode.simdPosition = SIMD3(x: newX, y: newY, z: -6)
if (newX > 1.0 && newX < -1.0) && blinked {
sphereNode.simdPosition = SIMD3(x: newX, y: newY, z: -6)
}
if (newY > 1.0 || newY < -1.0) && blinked {
sphereNode.simdPosition = SIMD3(x: newX, y: newY, z: -6)
}
if (newX > 1.0 || newX < -1.0) && !blinked {
sphereNode.simdPosition = SIMD3(x: newX, y: 0, z: -6)
}
if (newY > 1.0 || newY < -1.0) && !blinked {
sphereNode.simdPosition = SIMD3(x: 0, y: newY, z: -6)
}
SCNTransaction.commit()
// self.looked.lookPoint.x += CGFloat(faceAnchor.lookAtPoint.x) * -1
// self.looked.lookPoint.y += CGFloat(faceAnchor.lookAtPoint.y) * 1
//
// if self.sphereNode.simdPosition.x > -2 && self.sphereNode.simdPosition.x < 2 {
// self.sphereNode.simdPosition.x += faceAnchor.lookAtPoint.x * 0.25
// } else {
// if self.sphereNode.simdPosition.x > 0 {
// self.sphereNode.simdPosition.x = 1.99
// } else {
// self.sphereNode.simdPosition.x = -1.99
// }
// }
// if self.sphereNode.simdPosition.y > -2 {
// self.sphereNode.simdPosition.y += faceAnchor.lookAtPoint.y * 0.25
// } else {
// self.sphereNode.simdPosition.y = -1.99
// }
}
}
func quatToEulerAngles(_ quat: simd_quatf) -> SIMD3<Float>{
let n = SCNNode()
n.simdOrientation = quat
return n.simdEulerAngles
}
func rad2deg(_ number: Double) -> Double {
return number * 180 / .pi
}
}
extension float4x4 {
var translation: SIMD3<Float> {
let translation = columns.3
return SIMD3<Float>(translation.x, translation.y, translation.z)
}
/**
Factors out the orientation component of the transform.
*/
var orientation: simd_quatf {
return simd_quaternion(self)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment