Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Nanxia opened this issue Feb 26, 2018 · 10 comments
Open

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

Nanxia opened this issue Feb 26, 2018 · 10 comments
Assignees
Labels

Comments

@Nanxia
Copy link

Nanxia commented Feb 26, 2018

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 dmsurti self-assigned this Feb 26, 2018
@dmsurti
Copy link
Owner

dmsurti commented Feb 26, 2018

  • Please attach a model file that demonstrates the problem
  • Does your file contain multiple animations? e.g.; walk, run, jump
  • Does a single animation not play completely is what you mean when you say only a portion of the animation.
  • Please attach the relevant code that loads/plays these animations

@Nanxia
Copy link
Author

Nanxia commented Feb 27, 2018

  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
Copy link
Author

Nanxia commented Feb 27, 2018

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
Copy link
Owner

dmsurti commented Feb 27, 2018

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.

@dmsurti dmsurti added the bug label Feb 27, 2018
@Nanxia
Copy link
Author

Nanxia commented Feb 27, 2018

So AssimpKit loading FBX animation is a problem right?

The correct way is as follows:

  • (void)viewDidLoad
    {
    [super viewDidLoad];

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

    SCNAssimpScene *animScene =
    [SCNScene assimpSceneWithURL:[NSURL URLWithString:filePath]
    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.9f
                                             block:eventBlock];
      NSArray *animEvents =
      [[NSArray alloc] initWithObjects:animEvent, nil];
      settings.animationEvents = animEvents;
      settings.delegate = self;
      
      SCNScene *animation = [animScene animationSceneForKey:key];
      [animScene.modelScene.rootNode addAnimationScene:animation
                                            forKey:key
                                      withSettings:settings];
    

    }

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

    // set the scene to the view
    scnView.scene = animScene.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, -20);

    scnView.playing = YES;
    }

@dmsurti
Copy link
Owner

dmsurti commented Feb 27, 2018

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

@Nanxia
Copy link
Author

Nanxia commented Feb 27, 2018

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

@loringit
Copy link

Hi!
Any updates?

@johndpope
Copy link

johndpope commented Aug 10, 2020

I'm banging my head against the wall on similiar issue downstream with swift port
eugenebokhan/asset-import-kit#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
Copy link

johndpope commented Aug 12, 2020

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants