iPhoneシェルピンスキー四面体

シェルピンスキー四面体を表示するiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@interface ViewController ()

@property (nonatomic, weak) SCNView *sceneView;

@property (nonatomic ,weak) SCNNode *current;

@property (nonatomic) int count;

@end

@implementation ViewController

#define TriLength 1

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createTetrahedron];

    [self createCamera];

    [self createLight];

}

– (void)setupScene {

    SCNView *sv = [[SCNView alloc] initWithFrame:self.view.bounds];

    sv.backgroundColor = [UIColor colorWithHue:0.25 saturation:0.2 brightness:1 alpha:1];

    sv.scene = [SCNScene scene];

    sv.allowsCameraControl = YES;

    [self.view addSubview:sv];

    

    self.sceneView = sv;

}

– (void)createTetrahedron {

    SCNNode *o = [SCNNode node];

    [self.sceneView.scene.rootNode addChildNode:o];

    float dw = atan2f(sqrt(2.0) / 2.0, 1.0);

    for (int i=0; i<4; i++) {

        SCNNode *t = [self createTriangle];

        if (i > 1) {

            [t runAction:[SCNAction rotateByX:(i%2) ? dw : -dw y:0 z:0 duration:0.0]];

        } else {

            [t runAction:[SCNAction sequence:@[

               [SCNAction rotateByX:0 y:M_PI * 0.5 z:0 duration:0],

               [SCNAction rotateByX:0 y:0 z:M_PI duration:0],

               [SCNAction moveByX:0 y:TriLength / sqrt(2.0) z:0 duration:0],

               [SCNAction rotateByX:(i%2) ? dw : -dw y:0 z:0 duration:0.0]]]];

        }

        [o addChildNode:t];

    }

    [o runAction:[SCNAction rotateByX:(M_PI * 0.5 – dw) y:0 z:0 duration:0]];

    self.current = o;

}

– (void)addTetrahedron {

    

    SCNNode *o = [SCNNode node];

    [self.sceneView.scene.rootNode addChildNode:o];

    

    [o addChildNode:self.current];

    

    int l = pow(2.0, self.count) * TriLength;

    for (int i=0; i<3; i++) {

        SCNNode *c = [self.current clone];

        c.position =

              (i == 0) ? SCNVector3Make(l * 0.5, -l * sin(M_PI/3.0), -l*0.29)

            : (i == 1) ? SCNVector3Make(-l * 0.5, -l * sin(M_PI/3.0), -l * 0.29)

            : SCNVector3Make(0, -l * sin(M_PI/3.0), l * 0.52);

        [o addChildNode:c];

    }

    

    self.current = o;

    self.count++;

}

– (SCNNode *)createTriangle {

    float r = TriLength * 0.5;

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:CGPointMake(-r, 0)];

    [path addLineToPoint:CGPointMake(0, r * sqrt(3.0))];

    [path addLineToPoint:CGPointMake(r, 0)];

    [path closePath];

    

    SCNShape *triangle = [SCNShape shapeWithPath:path extrusionDepth:0.01];

    SCNNode *triangleNode = [SCNNode nodeWithGeometry:triangle];

    return triangleNode;

}

– (void)createCamera {

    SCNNode *camera = [SCNNode node];

    camera.camera = [SCNCamera camera];

    camera.position = SCNVector3Make(0, –4, 10);

    [self.sceneView.scene.rootNode addChildNode:camera];

}

– (void)createLight {

    SCNLight *light = [SCNLight light];

    light.type = SCNLightTypeOmni;

    light.color = [UIColor colorWithHue:0.5 saturation:0.1 brightness:0.4 alpha:1];

    

    SCNNode *lightNode = [SCNNode node];

    lightNode.light = light;

    lightNode.position = SCNVector3Make(0, 0, 40);

    [self.sceneView.scene.rootNode addChildNode:lightNode];

}

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    if (self.count > 4) {

        return;

    }

    [self addTetrahedron];

}

@end