iPhoneネッカーキューブ

ネッカーキューブという錯視をためしてみるiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@interface ViewController ()

@property (nonatomic, weak) SCNScene *scene;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor colorWithHue:0.7 saturation:0.8 brightness:0.5 alpha:1];

    [self createTitle];

    

    [self setupScene];

    [self createCamera];

    [self createCube];

}

– (void)createTitle {

    UILabel *title = [[UILabel alloc] init];

    title.text = @”Necker Cube”;

    title.font = [UIFont fontWithName:@”ChalkboardSE-Light” size:40];

    title.textColor = [UIColor whiteColor];

    [title sizeToFit];

    title.center = CGPointMake(CGRectGetMidX(self.view.bounds), 80);

    [self.view addSubview:title];

}

– (void)setupScene {

    float w = CGRectGetMaxX(self.view.bounds);

    SCNView *sceneView = [[SCNView alloc] initWithFrame:CGRectMake(0, 0, w, w)];

    sceneView.scene = [SCNScene scene];

    sceneView.backgroundColor = [UIColor colorWithHue:0.7 saturation:0.2 brightness:1 alpha:1];

    sceneView.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));

    [self.view addSubview:sceneView];

    

    self.scene = sceneView.scene;

}

– (void)createCamera {

    SCNNode *camera = [SCNNode node];

    camera.name = @”camera”;

    camera.position = SCNVector3Make(0, 10, 20);

    

    camera.camera = [SCNCamera camera];

    camera.camera.usesOrthographicProjection = YES;

    camera.camera.orthographicScale = 15.0;

    

    [self.scene.rootNode addChildNode:camera];

}

– (void)createCube {

    float l = 5;

    SCNNode *cube = [SCNNode node];

    cube.name = @”cube”;

    cube.position = SCNVector3Make(0, 5.5, 0);

    [self.scene.rootNode addChildNode:cube];

    

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

        SCNBox *bar = [SCNBox boxWithWidth:l height:0.2 length:0.2 chamferRadius:0];

        bar.firstMaterial.diffuse.contents = [UIColor grayColor];

        SCNNode *barNode = [SCNNode nodeWithGeometry:bar];

        [cube addChildNode:barNode];

        

        barNode.position = SCNVector3Make(0, l/2.0, 0);

        if (i < 4) {

            barNode.transform = SCNMatrix4Rotate(barNode.transform, i * M_PI/2.0, 0, 0, 1);

            barNode.transform = SCNMatrix4Translate(barNode.transform, 0, 0, -l/2.0);

        } else if (i < 8) {

            barNode.transform = SCNMatrix4Rotate(barNode.transform, i * M_PI/2.0, 0, 0, 1);

            barNode.transform = SCNMatrix4Translate(barNode.transform, 0, 0, l/2.0);

        } else {

            barNode.transform = SCNMatrix4Rotate(barNode.transform, M_PI/2.0, 0, 1, 0);

            barNode.transform = SCNMatrix4Translate(barNode.transform, l/2.0, 0, 0);

            barNode.transform = SCNMatrix4Rotate(barNode.transform, i * M_PI/2.0, 0, 0, 1);

        }

    }

    

    // camera

    SCNNode *camera = [self.scene.rootNode childNodeWithName:@”camera” recursively:NO];

    camera.constraints = @[[SCNLookAtConstraint lookAtConstraintWithTarget:cube]];

    

}

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

    

    SCNNode *cube = [self.scene.rootNode childNodeWithName:@”cube” recursively:NO];

    

    CABasicAnimation *boxRotation =

    [CABasicAnimation animationWithKeyPath:@”transform”];

    boxRotation.toValue =

    [NSValue valueWithSCNMatrix4:SCNMatrix4Rotate(cube.transform, M_PI,

                                                  0, 1, 0)];

    boxRotation.timingFunction =

    [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

    boxRotation.repeatCount = INFINITY;

    boxRotation.duration = 2.0;

    

    [cube addAnimation:boxRotation

                forKey:@”RotateTheBox”];

}

@end