5

それで、私がやろうとしているプロジェクトが少しあります。重力に対するデバイスの回転と、開始位置からの移動を取得しようとしています。基本的に、デバイスの「追跡」データを取得します。後でデバイスから記録したデータを模倣する 3d pt を作成することで、基本的にこれを適用する予定です。

とにかくこれを達成するためには、シーン キットを使用して、記録しようとしているデータと同じように 3 次元で物事を見ることができるようにするのが最善だと考えました。現在、私は船を回転させようとしており、デバイスの回転に関係なく、常に次の重力 (地面にあるものなど) のように見えます。これを下に置いたら、これをポイントに適用するのは面倒だと思います. そこで、次のコードを作成しました。

if let attitude = motionManager.deviceMotion?.attitude {
        print(attitude)


        ship.eulerAngles.y = -Float(attitude.roll)
        ship.eulerAngles.z = -Float(attitude.yaw)
        ship.eulerAngles.x = -Float(attitude.pitch)

    }

回転ラインの 1 つだけを実行すると、すべてが完璧になります。その軸で適切に動作します。しかし、一度に 3 つの軸すべてを実行すると、混沌としてしまい、ジッターやすべてが予想とはかけ離れたパフォーマンスを発揮します。

私の質問は次のとおりだと思います:船がどの向きであっても適切に「直立」したままになるように、上記のコードを修正する方法を知っている人はいますか?

4

1 に答える 1

12

J.ドウ!

最初にちょっとしたコツがあります。デフォルトの位置として横になっている iPhone を使用する場合は、sceneKit で使用される軸が DeviceMotion で使用される軸と異なることに注意する必要があります。軸を確認します。

デバイス運動軸 シーンキット軸
(出典:apple.com

最初に設定する必要があるのは、カメラの位置です。SceneKit プロジェクトを開始すると、位置 (0、0、15) にカメラが作成されます。それには問題があります:

eulerAngles = (0,0,0) の値は、オブジェクトが平面 xz にあることを意味しますが、Z から見ている限り、横から見るだけです。iPhone が横になっているのと同じようにするには、カメラを上から見るように設定する必要があります。つまり、電話から見ているようなものになります(カメラのように、idk)

// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)

// place the camera
cameraNode.position = SCNVector3(x: 0, y: 15, z: 0)
// but then you need to make the cameraNode face the ship (the origin of the axis), rotating it
cameraNode.eulerAngles.x = -Float(M_PI)*0.5 //or Float(M_PI)*1.5

これで船を上から見ることができるので、最初の部分は完了です。次に、デバイスの回転で船を「静止」(地面に面した状態) に保つ必要があります。

//First we need to use SCNRendererDelegate
class GameViewController : UIViewController SCNSceneRendererDelegate{
    private let motion = CMMotionManager();
...

次にviewDidLoadで:

//important if you remove the sceneKit initial action from the ship.
//The scene would be static, and static scenes do not trigger the renderer update, setting the playing property to true forces that:
scnView.playing = true;
if(motion.deviceMotionAvailable){
    motion.startDeviceMotionUpdates();
    motion.deviceMotionUpdateInterval = 1.0/60.0;
}

次に、更新メソッドに移動します

軸を見てください。sceneKit 軸と deviceMotion 軸を比較すると、Y 軸と Z 軸が「入れ替わっています」。Z は電話で上を向いていますが、 はシーンの横にあり、Y はシーンで上を向いていますが、電話では横になっています。したがって、それぞれ X 軸、Y 軸、Z 軸に関連付けられているピッチ、ロール、ヨーは、ピッチ、ヨー、ロールとして適用されます。

ロール値を正にしたことに注意してください。これは、「切り替えられた」何かがあるためです。視覚化するのはちょっと難しいです。デバイスの動きの Y 軸がシーンの Z 軸に相関していることを確認してください。この軸に沿って同じ方向 (たとえば時計回り) にオブジェクトを回転させると、軸の配置により反対方向に回転することになります。(ロールを負に設定して、それがどのようにうまくいかないかを確認できます)

func renderer(renderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {
    if let rot = motion.deviceMotion?.attitude{
        print("\(rot.pitch) \(rot.roll) \(rot.yaw)")
        ship.eulerAngles.x = -Float(rot.pitch);
        ship.eulerAngles.y = -Float(rot.yaw);
        ship.eulerAngles.z = Float(rot.roll);
    }

それが役立つことを願っています! じゃあ!

于 2015-10-23T01:58:18.650 に答える