3D 空间中的 scenekit 节点旋转和移动

Has*_*lil 3 3d ios scenekit

假设我们有一个SCNNode,我们想要旋转、改变飞行方向并在没有重力的空间中移动。目前该节点只是一个相机。实际上它应该对陀螺仪加速度计数据做出反应。我认为场景更新可以在- (void)renderer:(id <SCNSceneRenderer>)aRenderer didSimulatePhysicsAtTime:(NSTimeInterval)time.

我面临的问题是如何利用陀螺仪和加速度计数据来计算飞行方向,以及如何计算旋转方向和运动。我刷新了关于每个轴(x,y,z)的 3D 旋转矩阵的记忆,但仍然缺少上述部分来解决这个问题。可能想法很复杂,解决办法却很简单。

- (void)viewDidLoad
{

SCNView *scnView = (SCNView *) self.view;
SCNScene *scene = [SCNScene scene];
scnView.scene = scene;

_cameraNode = [[SCNNode alloc] init];
_cameraNode.camera = [SCNCamera camera];
_cameraNode.camera.zFar = 500;
_cameraNode.position = SCNVector3Make(0, 60, 50);
_cameraNode.rotation  = SCNVector4Make(1, 0, 0, -M_PI_4*0.75);
[scene.rootNode addChildNode:_cameraNode];

scnView.pointOfView = _cameraNode;
[self setupAccelerometer];
}

- (void)setupAccelerometer
{
_motionManager = [[CMMotionManager alloc] init];
GameViewController * __weak weakSelf = self;

if ([[GCController controllers] count] == 0 && [_motionManager isAccelerometerAvailable] == YES) {
    [_motionManager setAccelerometerUpdateInterval:1/60.0];
    [_motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
        [weakSelf accelerometerDidChange:accelerometerData.acceleration];
    }];
}
}

- (void)accelerometerDidChange:(CMAcceleration)acceleration
{
 //acceleration.x
 //acceleration.y
 //acceleration.z
 // now we have the data and saved somewhere

}
Run Code Online (Sandbox Code Playgroud)

ric*_*ter 5

如果您想结合陀螺仪和加速计数据来获得方向,您最好让 CoreMotion 为您做到这一点。文档中管理设备运动更新下列出的方法可以获取CMDeviceMotion对象;从其中一个您可以获得CMAttitude代表方向的 ,并从中您可以获得可以应用于场景中的节点的旋转矩阵或四元数。(可能在进一步对其进行转换之后,以便中性方向按照您想要的方式适合您的场景。)

按照您想要的方式定位节点后,从中获取飞行方向应该非常简单:

  1. 根据节点的局部坐标空间选择一个飞行方向,并生成一个指向该方向的向量;例如,相机朝其节点的 -z 方向查看,因此如果您希望相机节点沿着其飞行路径查看,您将使用类似 {0, 0, -1} 的向量。

  2. convertPosition:toNode:使用和 场景的将该向量转换为场景空间rootNode。考虑到节点的方向,这将为您提供场景中的飞行方向。

  3. 使用转换后的矢量来移动节点,方法是将其指定为节点物理体的速度,或者使用它来得出新位置并通过动作或动画将节点移动到那里。