Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 :(
}
like image 949
ColdSteel Avatar asked Nov 30 '16 19:11

ColdSteel


2 Answers

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.

like image 151
Ahmed El-Bermawy Avatar answered Oct 06 '22 17:10

Ahmed El-Bermawy


There's no animation running, at least not in the code you've shown us. Check the presentation node's position while the animation is playing, perhaps in renderer:updateAtTime: (see SCNRendererDelegate).

like image 1
Hal Mueller Avatar answered Oct 06 '22 17:10

Hal Mueller