Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use a PNG sequence as an animated material on a SceneKit object?

I'd like to programmatically change the material of an object rendered using SceneKit in iOS. But I would like to use animated image files. PNG sequences work great in iOS for stuff like UIImageViews -- how do I use them as a material in SceneKit?

Something like this doesn't work:

floor.firstMaterial.diffuse.contents = [UIImage animatedImageNamed:@"ANIMATION_" duration:6.0f];

Thanks!

like image 570
Josh Knowles Avatar asked Jan 28 '15 19:01

Josh Knowles


2 Answers

There is a much simpler solution (or at least I think it's simpler) though I can't attest to whether it's more efficient. I've tested this on an iPad mini (1st gen) and it works fine.

Rather than place a texture that is a spritesheet into the material's contents (and fiddle with the shader), you can place an SKScene object there instead.

That way you can just use SKSpriteNode objects within the SKScene and animate them using SCNAction objects. All of the animation can then be controlled easily and more powerfully without having to touch shader code.

    NSArray<SKTexture*> *cursorTextures =
    @[
      [SKTexture textureWithImageNamed:@"tilecursor1.png"],
      [SKTexture textureWithImageNamed:@"tilecursor2.png"],
      [SKTexture textureWithImageNamed:@"tilecursor3.png"],
      [SKTexture textureWithImageNamed:@"tilecursor4.png"],
      [SKTexture textureWithImageNamed:@"tilecursor5.png"]
      ];

    SKSpriteNode *cursorSprite = [SKSpriteNode spriteNodeWithTexture:cursorTextures[0]];
    cursorSprite.position = CGPointMake(cursorSprite.size.width/2.0, cursorSprite.size.height/2.0);
    [cursorSprite runAction:[SKAction repeatActionForever:[SKAction animateWithTextures:cursorTextures timePerFrame:0.1]]];

    SKScene *cursorScene = [SKScene sceneWithSize:cursorSprite.size];
    cursorScene.backgroundColor = [UIColor clearColor];
    [cursorScene addChild:cursorSprite];

    ...

    self.cursor.material.diffuse.contents = cursorScene;
like image 200
PKCLsoft Avatar answered Nov 08 '22 16:11

PKCLsoft


there is nothing that you can use out of the box.

I would do this using shader modifiers. If you pack all your images in a single image, you can use a modifier (at the SCNShaderModifierEntryPointGeometry entry point) to update the object's texture coordinates according to u_time so that every t ms another image (or sub-image of the atlas) is used.

like image 4
mnuages Avatar answered Nov 08 '22 15:11

mnuages