iPhoneのサンプルプログラム その3

SATCHを用いたナビアプリ(2)

シナリオファイル(圧縮)

カメラなどのプロパティ

disp0.lua(SATCHのスクリプト)
local componentInterface = getComponentInterface()
local scene = getCurrentScene()
local tRoll = Text2D(scene:getObjectByName("txtRoll"))

--Data for compass
local boussole = Entity(scene:getObjectByName("Boussole"))
local fleche = Entity(scene:getObjectByName("Fleche"))
boussole:setVisible(true)
fleche:setVisible(true)

local isCommand = nil
local command = nil

repeat

	if componentInterface then
		isCommand, command = componentInterface:pullCommand()
		if isCommand then
			if command["CommandName"]=="sendGyro" then
				tRoll:setText("Roll:"..command["arg0"])
				fleche:setOrientationEuler(0,command["arg1"],0,boussole)
			end
		end
	end

until coroutine.yield()

AppDelegate.h
#import <Foundation/Foundation.h>
#import <CoreMotion/CoreMotion.h>
#import "satchARViewer.h"

@interface AppDelegate : UIResponder  {
    UIWindow *window;
    UIView *mRender;
    SatchARViewer *mPlayer;
    
    CMMotionManager *motionManager;
    CMAttitude *referenceAttitude;
    BOOL isCaptured;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UIView *mRender;

- (void)start;
- (void)stop;

@end

AppDelegeta.mm
#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window;
@synthesize mRender;

- (void)dealloc
{
    [self stop];

    if (mPlayer) {
        [mPlayer terminate];
        [mPlayer release];
        mPlayer = nil;
    }

    [motionManager release];
    [mRender release];
    [window release];
    [super dealloc];
}

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [SatchARViewer setDialogMessageLoading:@"ロ−ディング..."];
    [SatchARViewer
        setToastMessageNoNetworkConnection:@"ネットワークに接続されていません。"];
    [SatchARViewer setToastMessageNetworkError:@"通信中にエラーが発生しました。"];
    [SatchARViewer setToastMessageLicenceError:@"認証に失敗しました。"];

    mRender = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
    [window addSubview:mRender];

    mPlayer = [[[SatchARViewer alloc] init] initialize:mRender];
    [self.window makeKeyAndVisible];
    [self start];

    motionManager = [[CMMotionManager alloc] init];
    motionManager.deviceMotionUpdateInterval = 1.0f/4.0f; // ジャイロのサンプリング間隔[s]    
    isCaptured = NO;
    referenceAttitude = nil;
    [self startGyro];

    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    if (mPlayer != nil) {
        [mPlayer applicationWillResignActive];
    }
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    if (mPlayer != nil) {
        [mPlayer applicationDidEnterBackground];
    }
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    if (mPlayer != nil) {
        [mPlayer applicationWillEnterForeground];
    }
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if (mPlayer != nil) {
        [mPlayer applicationDidBecomeActive];
    }
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    if (mPlayer != nil) {
        [mPlayer applicationWillTerminate];
    }
}

- (void)callback:(NSNumber*)num
{
    switch ([num intValue]) {
        case LOAD_SCENARIO_STATUS_COMPLETE:
            [mPlayer playScenario];
            break;
    }
}

- (void)start
{
    if (mPlayer) {
        [mPlayer loadScenario:@"Gyro1_iphone/Gyro1.dpd"
                 callback:@selector(callback:)
                      obj:self];
    }
}

- (void)stop
{
    if (mPlayer && ![mPlayer isScenarioPaused]) {
        [mPlayer pauseScenario];
}
}

- (void)startGyro
{
    // デバイスのハードウェアチェック
    if (!motionManager.deviceMotionAvailable)
    {
        NSLog(@"DeviceMotion is not available.");
        return;
    }

    isCaptured = NO;

    // モーションデータ更新時のハンドラを作成
    void (^handler)(CMDeviceMotion *, NSError *) = ^(CMDeviceMotion *motion, NSError *error)
    {
        if (isCaptured == NO) {
            referenceAttitude = [motion.attitude retain];
            isCaptured = YES;
        }
        else {
            // ジャイロデータの記録
            [self recordGyroData:motion];
        }
    };

    // モーションデータの測定を開始
    NSOperationQueue *queue = [NSOperationQueue currentQueue];
    [motionManager startDeviceMotionUpdatesToQueue:queue withHandler:handler];
}

- (void)recordGyroData:(CMDeviceMotion *)motion
{
    if (!mPlayer) {
        return;
    }

    CMAttitude *currentAttitude = motion.attitude;

    if (referenceAttitude != nil) {
        [currentAttitude multiplyByInverseOfAttitude: referenceAttitude];
    }

    // 角度を度数に変換
    float rollDegree = 180 * currentAttitude.roll / M_PI;
    float roll2 = rollDegree;
    if (roll2 <= 0) {
        roll2 = -roll2;
    }
    else {
        roll2 = 360.0 - roll2;
    }
    
    NSString *_roll = [NSString stringWithFormat:@"%.4f", rollDegree];
    NSString *_roll2 = [NSString stringWithFormat:@"%.4f", roll2];

    NSArray *para = [NSArray arrayWithObjects:_roll, _roll2, nil];
    NSLog(@"roll=%f, roll2=%f", rollDegree, roll2);

    [mPlayer enqueueCommand:@"sendGyro" args:para];
}

@end