iPhoneデジタル秤

秤のプレートに箱を落とすiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@interface ViewController () <SCNSceneRendererDelegate>

@property (nonatomic, weak) SCNView *sceneView;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createPlate];

    [self createLabel];

    [self createCamera];

}

– (void)setupScene {

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

    sv.delegate = self;

    sv.scene = [SCNScene scene];

    sv.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1];

    sv.autoenablesDefaultLighting = YES;

    [self.view addSubview:sv];

    self.sceneView = sv;

}

– (void)createPlate {

    SCNCylinder *plate = [SCNCylinder cylinderWithRadius:20 height:1];

    plate.firstMaterial.diffuse.contents = [UIColor colorWithWhite:0.4 alpha:1];

    SCNNode *plateNode = [SCNNode nodeWithGeometry:plate];

    plateNode.name = @”plate”;

    plateNode.physicsBody = [SCNPhysicsBody staticBody];

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

}

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

    SCNBox *box = [SCNBox boxWithWidth:3 height:3 length:3 chamferRadius:0];

    box.firstMaterial.diffuse.contents = [UIColor colorWithHue:arc4random_uniform(10) * 0.1 saturation:0.5 brightness:1 alpha:1];

    SCNNode *boxNode = [SCNNode nodeWithGeometry:box];

    boxNode.name = @”box”;

    boxNode.position = SCNVector3Make(((int)arc4random() % 8) – 4, 20, ((int)arc4random() % 8) – 4);

    boxNode.physicsBody = [SCNPhysicsBody dynamicBody];

    boxNode.physicsBody.restitution = 0.6;

    

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

}

– (void)createLabel {

    SCNText *text = [SCNText textWithString:@”0kg” extrusionDepth:1];

    text.firstMaterial.diffuse.contents = [UIColor orangeColor];

    text.alignmentMode = kCAAlignmentCenter;

    text.font = [UIFont systemFontOfSize:5];

    SCNNode *textNode = [SCNNode nodeWithGeometry:text];

    textNode.name = @”text”;

    textNode.position = SCNVector3Make(0, –5, 20);

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

}

– (void)createCamera {

    SCNNode *camera = [SCNNode node];

    camera.camera = [SCNCamera camera];

    camera.position = SCNVector3Make(0, 5, 70);

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

}

– (void)renderer:(id<SCNSceneRenderer>)aRenderer updateAtTime:(NSTimeInterval)time {

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

    float weight = 0;

    

    NSMutableArray *sortedBox = [[[[self.sceneView.scene.rootNode childNodes] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@”name == %@”, @”box”]] sortedArrayUsingComparator:^NSComparisonResult(SCNNode *n1, SCNNode *n2) {

        return n1.presentationNode.position.y > n2.presentationNode.position.y;

    }] mutableCopy];

    

    NSMutableArray *hits = [NSMutableArray array];

    [hits addObject:plate];

    for (SCNNode *n in sortedBox) {

        NSArray *contacts = [self.sceneView.scene.physicsWorld contactTestWithBody:n.physicsBody options:@{SCNPhysicsTestSearchModeKey : SCNPhysicsTestSearchModeAll}];

        for (SCNPhysicsContact *c in contacts) {

            if (c && [hits containsObject:c.nodeB]) {

                weight += n.physicsBody.mass;

                [hits addObject:n];

                break;

            }

        }

    }

    

    NSString *s = [NSString stringWithFormat:@”%.0fkg”, weight];

    SCNText *t = (SCNText *)[self.sceneView.scene.rootNode childNodeWithName:@”text” recursively:NO].geometry;

    if (![t.string isEqual:s]) {

        t.string = s;

    }

}

@end