2015-10-22 12 views
5

So habe ich ein bisschen von einem Projekt, das ich versuche zu tun. Ich versuche, die Geräte relativ zur Schwerkraft zu drehen, und die Übersetzung von dort, wo sie begonnen hat. Also im Grunde "Tracking" Daten für das Gerät. Ich plane, dies im Wesentlichen anzuwenden, indem ich einen 3D-Punkt mache, der die Daten nachahmt, die ich später vom Gerät aufnehme.Bitte helfen Sie mir, Gerätedrehdaten richtig anzuwenden

Um dies zu erreichen, dachte ich, es wäre am besten, mit Szenen-Kit zu arbeiten, so dass ich Dinge in 3 Dimensionen sehen kann, genau wie die Daten, die ich aufnehmen möchte. Gerade jetzt habe ich versucht, das Schiff zu drehen, so dass es immer wie seine folgende Schwerkraft aussieht (wie es auf dem Boden oder so etwas ist) egal was die Gerätedrehung ist. Ich denke, sobald ich das hier habe, wird es ein Sinn sein, dies auf einen Punkt anzuwenden. Also habe ich den folgenden Code gemacht:

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) 

    } 

Wenn Sie nur eine der Rotationslinien laufen dann ist alles perfekt. Es verhält sich auf dieser Achse richtig. Wenn ich jedoch alle drei Achsen auf einmal mache, wird es chaotisch und funktioniert mit Jitter und allem anderen als erwartet.

Ich denke, meine Frage ist: Weiß jemand, wie ich meinen Code oben beheben, so dass das Schiff richtig "aufrecht" bleibt, egal welche Ausrichtung.

+0

Diese Frage ist viel zu weit. – nhgrif

+1

@nhgrif Ich habe meine Hauptfragen oben notiert. Zugegeben, einige von ihnen sind mehr Theorie als Anwendung. Die erste Frage ist jedoch meiner Definition nach nicht weit gefasst. Ich habe klar gesagt, worauf ich gehofft hatte, und was schief gelaufen ist, als ich es getan habe. –

+0

Frage 1 selbst ist nicht zu breit, denke ich nicht. Sie sollten in Erwägung ziehen, den Umfang dieses Beitrags auf genau diese Frage zu beschränken, damit dieser Beitrag nicht wegen außergewöhnlich großer Breite geschlossen wird. – nhgrif

Antwort

8

J.Doe!

Zuerst gibt es einen kleinen Trick. Wenn Sie das iPhone als Standardposition verwenden möchten, müssen Sie beachten, dass die Achse, die in sceneKit verwendet wird, anders ist als die von DeviceMotion verwendete Achse. Schauen Sie sich die Achse:

deviceMotion axis sceneKit axis http://developer.apple.com/library/ios/documentation/SceneKit/Reference/SceneKit_Framework/Art/3d_coordinate_system_2x.png

Das erste, was Sie einstellen müssen, ist die Kameraposition. Wenn Sie ein SceneKit-Projekt starten, erstellt es Ihre Kamera in der Position (0, 0, 15). Es gibt ein Problem damit:

Die Werte von eulerAngles = (0,0,0) würden bedeuten, dass das Objekt in der Ebene xz wäre, aber solange du von Z aus schaust, siehst du es einfach von der Seite. Damit dies dem Iphone entspricht, müssen Sie die Kamera so einstellen, dass sie von oben aussieht. So wäre es wie man es aus dem Telefon gesucht haben (wie eine Kamera, 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 

Damit wir das Schiff von oben gehen, um zu sehen, so dass der erste Teil erfolgt. Jetzt müssen wir das Schiff mit der Gerätedrehung "still" (auf den Boden) bleiben lassen.

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

Dann auf 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; 
} 

Dann gehen wir auf die Update-Methode

Blick auf die Achse: die Achse Y und Z "eingeschaltet", wenn Sie die sceneKit Achse vergleichen und die Achse deviceMotion. Z ist auf dem Telefon, während es auf der Seite ist, und Y ist auf der Bühne, während auf der Seite auf dem Telefon. So werden die Nick-, Roll- und Gierbewegungen, die jeweils der X-, Y- und Z-Achse zugeordnet sind, als Nick-, Gier- und Rollwinkel angewendet.

Hinweis Ich habe den Roll-Wert positiv gesetzt, das liegt daran, dass da noch etwas "geschaltet" ist. Es ist ein bisschen schwer zu visualisieren. Sehen Sie, dass die Y-Achse der Gerätebewegung mit der Z-Achse der Szene korreliert ist.Stellen Sie sich nun eine Objektdrehung entlang dieser Achse in der gleichen Richtung vor (zum Beispiel im Uhrzeigersinn), würden sie aufgrund der Anordnung der Achse in entgegengesetzte Richtungen gehen. (Sie können die Rolle negativ einstellen, um zu sehen, wie es schief geht)

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); 
    } 

Hoffe, dass hilft! Tschüss!

+0

Vielen Dank für so eine gründliche Antwort! –

Verwandte Themen