Search code examples
macoscocoascenekitcaanimationscnnode

SceneKit get current SCNNode position form Animated SCNNode


I want to get a current node position form an animated SCNNode I am aware of presentationNode and I tried to extract position form there, but no Luck

Here is my Code

SCNNode * pelvis = [_unit childNodeWithName:@"Bip01_Pelvis" recursively:YES];
SCNNode * present = pelvis.presentationNode;



SCNVector3 position = [self convertPosition:present.position toNode:self.parentNode];

The position I have is the position of the SCNNode in the "rest" mode before the CAAnimation was applied.

How to get properties like position form the 'presentationNode'?

Edit

Class itself relevant parts:

@interface UndeadSimple : RepresentationNode <CAAnimationDelegate>
{
    //Animations
    SCNNode * _undead;

    CAAnimation * _currentAnimation;
    NSString    * _currAnimationkey;

    CAAnimation * _death1;
    ...

    SCNNode        * _audioNode;
    SCNAudioSource * _deathSource;
    SCNAudioPlayer * _player;
}

Init:

NSString * sceneName = @ZOMBIE;
SCNScene *scene2 = [SCNScene sceneNamed:sceneName];

_undead = [SCNNode node];
for(SCNNode * node in scene2.rootNode.childNodes)
{
    [_undead addChildNode:node];
    [node removeAllAnimations];
}
[_undead setScale:(SCNVector3Make(0.024, 0.02, 0.024))];

[self addChildNode:_undead];
[_undead removeAllAnimations];

_currentAnimation = _idleAnimation;
_currAnimationkey = @"resting";

[_undead addAnimation:_currentAnimation forKey:_currAnimationkey];

Animation and event:

SCNAnimationEvent * event2 = [SCNAnimationEvent animationEventWithKeyTime:0.9 block:^(CAAnimation * _Nonnull animation, id  _Nonnull animatedObject, BOOL playingBackward)
{
    [self.delegate finishedDeathAnimation];
}];

_death1 = anims.death1.mutableCopy;
[_death1 setDelegate:self];
[_death1 setFillMode:kCAFillModeForwards];
_death1.removedOnCompletion = NO;
[_death1 setAnimationEvents:@[event2]];

Animation Call:

- (void)die
{

    if([_currAnimationkey isEqualToString:@"dead"])
    {
        return;
    }

   [_undead removeAllAnimations];
   CAAnimation * death = nil;



    int anim = arc4random_uniform(3);
    if(anim < 1)
    {
        death = _death1;
    }
    else if(anim < 2)
    {
        death = _death2;
    }
    else
    {
        death = _death3;
    }

    _currAnimationkey = @"dead";
    _currentAnimation = death;

}

//Helper Method to get presentation Node

- (SCNNode *)getSnapNode
{
    SCNNode * repNode = [_undead presentationNode];
    _undead.transform = repNode.transform;
    repNode = _undead.clone;
    return repNode;
}

//On callback call and try to get position:

- (void)finishedDeathAnimation
{
    SCNPlane * bloodgeometry = [SCNPlane planeWithWidth:4 height:4];
    bloodgeometry.firstMaterial.diffuse.contents = [NSImage imageNamed:@"blood"];

    SCNNode * bloodNode = [SCNNode node];
    [bloodNode setEulerAngles:SCNVector3Make(-M_PI_2, 0, 0)];
    bloodNode.geometry = bloodgeometry;

    //Bip01_Pelvis
    SCNNode * deadBody = [_unit getSnapNode];

    SCNNode * pelvis = [deadBody childNodeWithName:@"Bip01_Pelvis" recursively:YES];

    SCNNode * present = pelvis.presentationNode;
    SCNVector3 position = [self convertPosition:present.position toNode:self.parentNode];

   NSLog(@"pelvis position %lf,%lf,%lf", present.position.x, present.position.y, present.position.z); //Always {0,0,0}


    bloodNode.position = SCNVector3Make(position.x, 0.0001, position.z);

    [self.parentNode addChildNode:bloodNode];

    [self removeFromParentNode];
}

Edit 2

I also tried to simplify it a bit:

another helper method:

//in undead/unit class

- (SCNVector3)getPosition
{
    SCNNode * repNode = [[_undead childNodeWithName:@"Bip01_Pelvis" recursively:YES] presentationNode];
    return repNode.position;
}

On callback:

- (void)finishedDeathAnimation
{
    position = [_unit getPosition];
    NSLog(@"pelvis position %lf,%lf,%lf", position.x, position.y, position.z); //Alway 0,0,0 as well :(
}

Solution

  • It is rare to find someone just like me still believe in Objective C rather than swift thats why i would like to offer full help.

    I was having this issue for an animation exported from Blender as a Collada but have succeeded to get the actual position after few tries.

    Using presentationNode is the correct way but you need to get it from the child while you making the animation for example this is how to run animation for a node Called _monkey notice that at the last Code i got the _present From the child.presentationNode Not from _monkey.presentationNode Also it have to be obtained during the enumeration not after

    so first i need to define

    NSNode * _present; 
    

    then i do play the animation

       [_monkey enumerateChildNodesUsingBlock:^(SCNNode *child, BOOL *stop)
         {
             for(NSString *key in child.animationKeys)
             {               // for every animation key
                 CAAnimation *animation = [child animationForKey:key]; // get the animation
                 animation.usesSceneTimeBase = NO;                     // make it system time based
                 animation.repeatCount = FLT_MAX;                      // make it repeat forever
                 animation.speed = 0.2;
                 [child addAnimation:animation forKey:key];            // animations are copied upon addition, so we have to replace the previous animation
             }
             _present = child.presentationNode;
         }];
    

    Then Under the render i can check the Results which is changing as the animation moves (Also if you have worked with iOS11 you can check worldPosition instead of position it gives great results too).

    - (void)renderer:(id <SCNSceneRenderer>)renderer didSimulatePhysicsAtTime:(NSTimeInterval)time
    {
         NSLog(@" Location X:%f Y:%f Z:%f", _present.position.x, _present.position.y, _present.position.z);
    
    }
    

    Finally Here Is The Results

    Y:-2.505034 Z:4.426160
    2017-10-11 04:42:19.700435+0200 monkey[547:137368]  Location X:-5.266642 Y:-2.480119 Z:4.427162
    2017-10-11 04:42:19.720763+0200 monkey[547:137368]  Location X:-5.215315 Y:-2.455228 Z:4.428163
    2017-10-11 04:42:19.740449+0200 monkey[547:137346]  Location X:-5.163589 Y:-2.430143 Z:4.429171
    2017-10-11 04:42:19.760397+0200 monkey[547:137368]  Location X:-5.112190 Y:-2.405216 Z:4.430173
    2017-10-11 04:42:19.780557+0200 monkey[547:137346]  Location X:-5.060925 Y:-2.380355 Z:4.431173
    2017-10-11 04:42:19.800418+0200 monkey[547:137342]  Location X:-5.008560 Y:-2.355031 Z:4.432024
    

    This Give Me Good Results. Hope it would work with you.