Finding normal vector to iOS device

前端 未结 2 1126
长情又很酷
长情又很酷 2020-12-13 01:11

I would like to use CMAttitude to know the vector normal to the glass of the iPad/iPhone\'s screen (relative to the ground). As such, I would get vectors like the following:

2条回答
  •  有刺的猬
    2020-12-13 01:14

    Thanks to Kay for the starting point on the solution. Here is my implementation for anyone that needs it. I made a couple of small tweeks to Kay's advice for my situation. As a heads up, I'm using a landscape only presentation. I have code that updates a variable _isLandscapeLeft to make the necessary adjustment to the direction of the vector.

    Quaternion.h

        @interface Quaternion : NSObject{
        //double w;
        //double x;
        //double y;
        //double z;
    }
    
    @property(readwrite, assign)double w;
    @property(readwrite, assign)double x;
    @property(readwrite, assign)double y;
    @property(readwrite, assign)double z;
    
    - (id) initWithValues:(double)w2 x:(double)x2 y:(double)y2 z:(double)z2;
    - (Quaternion*) multiplyWithRight:(Quaternion*)q;
    @end
    

    Quaternion.m

    #import "Quaternion.h"
    
    @implementation Quaternion
    
    
    - (Quaternion*) multiplyWithRight:(Quaternion*)q {
        double newW = _w*q.w - _x*q.x - _y*q.y - _z*q.z;
        double newX = _w*q.x + _x*q.w + _y*q.z - _z*q.y;
        double newY = _w*q.y + _y*q.w + _z*q.x - _x*q.z;
        double newZ = _w*q.z + _z*q.w + _x*q.y - _y*q.x;
        _w = newW;
        _x = newX;
        _y = newY;
        _z = newZ;
        // one multiplication won't denormalise but when multipling again and again
        // we should assure that the result is normalised
        return self;
    }
    
    - (id) initWithValues:(double)w2 x:(double)x2 y:(double)y2 z:(double)z2 {
        if ((self = [super init])) {
            _x = x2; _y = y2; _z = z2; _w = w2;
        }
        return self;
    }
    
    
    @end
    

    And my game class that uses the quaternion for shooting:

    -(void)fireWeapon{
        ProjectileBaseClass *bullet = [[ProjectileBaseClass alloc] init];
        bullet.position = SCNVector3Make(0, 1, 0);
        [self.rootNode addChildNode:bullet];
    
        Quaternion *e = [[Quaternion alloc] initWithValues:0 x:0 y:0 z:1];
        CMQuaternion cm = _currentAttitude.quaternion;
        Quaternion *quat = [[Quaternion alloc] initWithValues:cm.w x:cm.x y:cm.y z:cm.z];
        Quaternion *quatConjugate = [[Quaternion alloc] initWithValues:cm.w x:-cm.x y:-cm.y z:-cm.z];
        quat = [quat multiplyWithRight:e];
        quat = [quat multiplyWithRight:quatConjugate];
        SCNVector3 directionToShoot;
        if (_isLandscapeLeft) {
            directionToShoot = SCNVector3Make(quat.y, -quat.x, -quat.z);
    
        }else{
            directionToShoot = SCNVector3Make(-quat.y, quat.x, -quat.z);
    
        }
    
        SCNAction *shootBullet = [SCNAction moveBy:directionToShoot duration:.1];
        [bullet runAction:[SCNAction repeatActionForever:shootBullet]];
    }
    

提交回复
热议问题