[英]How to split out multiple animations from Collada file in SceneKit
我將第三方.dae Collada文件作為場景加載到SceneKit項目中。
.dae文件中有許多不同的動畫,設置在不同的時間/幀。 我試圖弄清楚如何將這些分開並通過引用名稱引用每個單獨的動畫。 dae文件中沒有可理解的引用名稱 - 動畫都設置為單個動畫。
我能夠將動畫解析為CAAnimation對象,並使用以下代碼驗證我是否成功完成了此操作:
SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/man.dae"];
SCNNode *man = [scene.rootNode childNodeWithName:@"Bip01" recursively:YES];
CAAnimation *animation = [man animationForKey:@"test_Collada_DAE-1"];
[man removeAllAnimations];
[man addAnimation:animation forKey:@"animation"];
有沒有辦法為我的CAAnimation對象設置開始和結束幀或時間? 解析各種動畫的最佳方法是什么? 我希望我不必手動將dae文件拆分成多個並單獨加載每個文件。
3d工具通常將多個動畫導出為具有子動畫的單個動畫。 在這種情況下,SceneKit會將這些動畫加載為具有子動畫的CAAnimationGroup。 因此,一個選項是“解析”動畫組的子動畫並檢索所需的動畫。 另一種選擇是使用SCNSceneSource按名稱檢索(子)動畫(但這僅在您的3d工具導出DAE時導出名稱時才有效)。
如果您需要“裁剪”動畫(即從較長的動畫中提取以t0開頭且持續時間為D的動畫),CoreAnimation有一個API:
創建一個動畫組以“裁剪”持續時間D.
將要裁剪的動畫添加為子動畫,並將其timeOffset設置為t0。
正如Toyos在他的回答中提到的,使用SCNSceneSource
枚舉CAAnimationGroup
並檢索CAAnimation
對象,如下所示:
NSURL *daeURL = [[NSBundle mainBundle] URLForResource:@"exportedFilename" withExtension:@"dae"];
SCNSceneSource *sceneSource = [SCNSceneSource sceneSourceWithURL:daeURL options:nil];
NSMutableArray *myAnimations = [@[] mutableCopy];
for (NSString *singleAnimationName in [sceneSource identifiersOfEntriesWithClass:[CAAnimation class]]) {
CAAnimation *thisAnimation = [sceneSource entryWithIdentifier:singleAnimationName withClass:[CAAnimation class]];
[myAnimations addObject:thisAnimation];
}
下面是將幀數轉換為時間的代碼,然后通過使用CAAnimationGroup
作為@Toyos描述,僅播放動畫的那部分。 此示例代碼通過重復fullAnimation
10幀到第160幀來播放“空閑”動畫:
func playIdleAnimation() {
let animation = subAnimation(of:fullAnimation, startFrame: 10, endFrame: 160)
animation.repeatCount = .greatestFiniteMagnitude
addAnimation(animation, forKey: "animation")
}
func subAnimation(of fullAnimation:CAAnimation, startFrame:Int, endFrame:Int) -> CAAnimation {
let (startTime, duration) = timeRange(startFrame:startFrame, endFrame:endFrame)
let animation = subAnimation(of: fullAnimation, offset: startTime, duration: duration)
return animation
}
func subAnimation(of fullAnimation:CAAnimation, offset timeOffset:CFTimeInterval, duration:CFTimeInterval) -> CAAnimation {
fullAnimation.timeOffset = timeOffset
let container = CAAnimationGroup()
container.animations = [fullAnimation]
container.duration = duration
return container
}
func timeRange(startFrame:Int, endFrame:Int) -> (startTime:CFTimeInterval, duration:CFTimeInterval) {
let startTime = timeOf(frame:startFrame)
let endTime = timeOf(frame:endFrame)
let duration = endTime - startTime
return (startTime, duration)
}
func timeOf(frame:Int) -> CFTimeInterval {
return CFTimeInterval(frame) / framesPerSecond()
}
func framesPerSecond() -> CFTimeInterval {
// number of frames per second the model was designed with
return 30.0
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.