dmsurti / AssimpKit

A library (macOS, iOS) that converts the files supported by Assimp to Scene Kit scenes.
http://assimpkit.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
477 stars 54 forks source link

AssimpKit can not display all the animations of the FBX model #101

Open Nanxia opened 6 years ago

Nanxia commented 6 years ago

AssimpKit can not display all the animations of the FBX model, only a portion of the animation. I would like to ask what is the reason for such a result

dmsurti commented 6 years ago
Nanxia commented 6 years ago
  1. This is a demonstration model. duilian.FBX.zip
  2. This model is a swinging couplet, but this model is only swingable by the left pair.
  3. The sample code is as follows: (void)viewDidLoad { [super viewDidLoad];

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"duilian" ofType:@"FBX"];

self.modelFilePath = filePath; self.animFilePath = self.modelFilePath;

SCNAssimpScene *scene = [SCNScene assimpSceneWithURL:[NSURL URLWithString:self.modelFilePath] postProcessFlags:AssimpKit_Process_FlipUVs | AssimpKit_Process_Triangulate];

// Load the animation scene if (self.animFilePath) { SCNAssimpScene animScene = [SCNScene assimpSceneWithURL:[NSURL URLWithString:self.animFilePath] postProcessFlags:AssimpKit_Process_FlipUVs | AssimpKit_Process_Triangulate]; NSArray animationKeys = animScene.animationKeys; // If multiple animations exist, load the first animation if (animationKeys.count > 0) { SCNAssimpAnimSettings *settings = [[SCNAssimpAnimSettings alloc] init]; settings.repeatCount = 3;

  NSString *key = [animationKeys objectAtIndex:0];
  SCNAnimationEventBlock eventBlock =
  ^(CAAnimation *animation, id animatedObject,
    BOOL playingBackward) {
      NSLog(@" Animation Event triggered ");

      // To test removing animation uncomment
      // Then the animation wont repeat 3 times
      // as it will be removed after 90% of the first loop
      // is completed, as event key time is 0.9
      // [scene.rootNode removeAnimationSceneForKey:key
      //                            fadeOutDuration:0.3];
      // [scene.rootNode pauseAnimationSceneForKey:key];
      // [scene.rootNode resumeAnimationSceneForKey:key];
  };
  SCNAnimationEvent *animEvent =
  [SCNAnimationEvent animationEventWithKeyTime:0.1f
                                         block:eventBlock];
  NSArray *animEvents =
  [[NSArray alloc] initWithObjects:animEvent, nil];
  settings.animationEvents = animEvents;
  settings.delegate = self;

  SCNScene *animation = [animScene animationSceneForKey:key];
  [scene.modelScene.rootNode addAnimationScene:animation
                                        forKey:key
                                  withSettings:settings];

} }

// retrieve the SCNView SCNView scnView = (SCNView )self.view;

// set the scene to the view scnView.scene = scene.modelScene;

// allows the user to manipulate the camera scnView.allowsCameraControl = YES;

// show statistics such as fps and timing information scnView.showsStatistics = YES;

// configure the view scnView.backgroundColor = [UIColor blackColor];

scnView.scene.rootNode.position = SCNVector3Make(0, 0, -50);

scnView.playing = YES; }

Nanxia commented 6 years ago

After I tried to change the AssimpKit source code, I solved the animation problem but did not know if it was correct and the changes were as follows:

No change before : 1

After the change : 1

dmsurti commented 6 years ago

Thanks for providing the file. Comparing it with FBX review tool, I can see only 1 vertical block on the left is animated using AssimpKit.

Btw, your code change is wrong and unnecessary. You should probably read how to load animations.

The gist is: you load the model scene, then load the animations (from the scene you just loaded or another scene if they are defined externally) and add the animation to the model scene. The above docs referred to use the same scenarios.

Nanxia commented 6 years ago

So AssimpKit loading FBX animation is a problem right?

The correct way is as follows:

dmsurti commented 6 years ago

Yes, hence I have labeled this issue as a bug.

Nanxia commented 6 years ago

Thank you @dmsurti for sharing, looking forward to your update

loringit commented 4 years ago

Hi! Any updates?

johndpope commented 4 years ago

I'm banging my head against the wall on similiar issue downstream with swift port https://github.com/eugenebokhan/AssetImportKit/issues/14

failed attempts to get my fbx import to animate in swift. @Nanxia - I followed your instructions but no joy. https://github.com/johndpope/demo-unistroy

if let pathToObject = Bundle.main.path(forResource: "ely", ofType: "fbx") {

            let scaleFactor:Float = 0.0025

            do {
                // 1. you load the model scene
                let assimpScene = try SCNScene.assimpScene(filePath: pathToObject, postProcessSteps:[.defaultQuality]) //realtimeFast realtimeQuality realtimeMaxQuality  [.optimizeGraph,

                // ( add the model to the scene / scale it down / is this wrong?)
                let modelScene = assimpScene.modelScene!
                modelScene.rootNode.childNodes.forEach {
                    $0.position =   $0.position * scaleFactor
                    $0.scale = $0.scale * scaleFactor
                    sceneView.scene.rootNode.addChildNode($0) // the robot is added - it has a root - below it fails to add animation due to  no root: nil nil
                    self.robotNode = $0
                }

//                print("skeletonNode:",assimpScene.skeletonNode)
//                print("animations:",assimpScene.animations)
//                print("animationKeys:",assimpScene.animationScenes.allKeys)
                //assimpScene.makeAnimationScenes()
//                for animSceneKey in assimpScene.animations.allKeys {
//                    if let animSceneKey = animSceneKey as? String {
//                        if let assimpAnim = assimpScene.animations.value(forKey: animSceneKey) as? AssetImporterAnimation {
//                            let animScene = SCNScene()
//                            animScene.rootNode.addChildNode(assimpScene.skeletonNode.clone())
//                            assimpScene.addAnimation(assimpAnimation: assimpAnim,to: assimpScene.modelScene!)
//                            assimpScene.animationScenes.setValue( assimpScene.modelScene!,forKey: animSceneKey)
//                        }
//                    }
//                }
//
                // 2. then load the animations
                // either these lines are wrong... OR
                for (_,animScene) in assimpScene.animationScenes{
                    print("animScene:",animScene)
                    if animScene is SCNScene{
                        let animation = assimpScene.animations["ely-1"] as! AssetImporterAnimation
                         print("animation:",animation)
//                        3. and add the animation to the model scene.
//                        assimpScene.modelScene!.rootNode.addAnimationScene(animation, forKey: "ely-1", with: settings) // FAILS
//                        self.robotNode?.parent?.addAnimationScene(animation, forKey: "ely-1", with: settings) // FAILS
//                        self.robotNode?.addAnimationScene(animation, forKey: "ely-1", with: settings) // FAILS
//                        sceneView.scene.rootNode.addAnimationScene(animation, forKey: "ely-1", with: settings) // FAILS

                        // just attempt to hijack view and coerce the animation scene to sceneView.scene
                        sceneView.scene = animScene as! SCNScene // FAILS

                    }

                }

                sceneView.isPlaying = true
                sceneView.showsStatistics = true

            }catch let error{
                print("error:",error)
            }
        }
johndpope commented 4 years ago

UPDATE - I got the library loading fbx + animations with swift / via carthage. The eugenebokhan/AssetImportKit seems to not work. https://github.com/johndpope/swift-2

if anyone knows how to pass the flags in swift - would like to know.

  let flipUVs = AssimpKitPostProcessSteps.process_FlipUVs
    let trianglulate = AssimpKitPostProcessSteps.process_Triangulate
    //        let flags = [flipUVs,trianglulate] // passing this doesn't work.
    let scene = SCNScene.assimpScene(with: modelFileURL,postProcessFlags:trianglulate)