i am implementing an app for iPhone6S that helps disabled people to gain back their limbs control by training using a virtual trainer.
This virtual trainer performs simple movements such as raising and lowering an arm, raising and lowering a leg, and then combines them in various rhythmic patterns.
Due to the target platform, I cannot make use of the powerful ARKit, and therefore I have to have to rely on SceneeKit alone.
My code is currently able to load a dae, and applying multiple actions to the skeleton. However I am facing problems in understanding the behavior of SCNAction.rotateTo and SCNAction.rotateBy
let DegreesPerRadians = Float(Double.pi/180)
func convertToRadians(angle:Float) -> Float {
return angle * DegreesPerRadians
}
func convertToRadians(angle:CGFloat) -> CGFloat {
return CGFloat(CGFloat(angle) * CGFloat(DegreesPerRadians))
}
var x45 = SCNAction.rotateBy( x: convertToRadians(angle: 45), y: 0, z: 0, duration: 0.2)
var x45r = SCNAction.rotateBy( x: convertToRadians(angle: -45), y: 0, z: 0, duration: 0.2)
func FOL()->SCNAction! {
let human = getHuman()
let bodyOfHuman = human?.childNode(withName: "Body", recursively: true)
let bodyRealSkeleton = bodyOfHuman?.skinner?.skeleton
let leftLegBone = bodyRealSkeleton?.childNode(withName: "mixamorig_LeftLeg", recursively: true)
let leftLegKick = SCNAction.customAction(duration: 0.1) { [self]
(node, elapsedTime) in leftLegBone?.runAction(x45)
}
return leftLegKick
}
func FOLrev()->SCNAction! {
let human = getHuman()
let bodyOfHuman = human?.childNode(withName: "Body", recursively: true)
let bodyRealSkeleton = bodyOfHuman?.skinner?.skeleton
let leftLegBone = bodyRealSkeleton?.childNode(withName: "mixamorig_LeftLeg", recursively: true)
let leftLegKick = SCNAction.customAction(duration: 0.1) { [self]
(node, elapsedTime) in leftLegBone?.runAction(x45r)
}
return leftLegKick
}
var actionSequence=[FOL(),FOLrev()]
The above code is then called with
_scene?.rootNode.runAction(SCNAction.sequence(actionSequence))
It results into the model properly bending the left leg and straightening it.
However when using instead "rotateTo" it goes into the opposite direction and does not "come back".
I watched all DevCon SceneKit materials and sample code but could not find any explanation or guidance.
My real goal is to add more complex actions, such as clapping hands, and when the same approach is tried on those patterns (that require 3-4 rotations) then the results are less predictable.
The answer to this question is that when using rotateTo, in order to go "back" one should use the starting position of the specific angle.
In the specific example, using rotateTo means to use following code