2015-10-22 35 views
5

Quindi ho un po 'di un progetto che sto cercando di fare. Sto cercando di ottenere la rotazione dei dispositivi relativa alla gravità e la traduzione da dove è iniziata. Quindi fondamentalmente ricevendo dati di "tracciamento" per il dispositivo. Ho intenzione di applicare sostanzialmente questo facendo un 3d pt che imiterà i dati che registro dal dispositivo in seguito.Per favore aiutami ad applicare correttamente i dati di rotazione del dispositivo

In ogni caso, per tentare di ottenere ciò, ho pensato che sarebbe stato meglio lavorare con il kit di scena in modo da poter vedere le cose in 3 dimensioni proprio come i dati che sto cercando di registrare. In questo momento ho cercato di far ruotare la nave in modo che assomigli sempre alla sua gravità successiva (come la sua sul terreno o qualcosa del genere), non importa quale sia la rotazione del dispositivo. Immagino che una volta che avrò questo giù sarà un peccato applicare questo a un punto. Così ho fatto il seguente codice:

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) 

    } 

Quando si esegue solo una delle linee di rotazione, allora tutto è perfettamente. Funziona correttamente su quell'asse. Tuttavia quando faccio tutti e tre gli assi 'subito diventa caotico e si esibisce lontano dal previsto con jitter e tutto il resto.

Suppongo che la mia domanda sia: Qualcuno sa come risolvere il mio codice sopra in modo che la nave rimanga correttamente "verticale" indipendentemente dall'orientamento.

+0

Questa domanda è molto, troppo ampia. – nhgrif

+1

@nhgrif Ho scritto le mie domande principali sopra. Concessi alcuni di loro sono più teoria quindi applicazione. Comunque la domanda uno non è affatto ampia secondo la mia definizione. Ho dichiarato chiaramente cosa speravo e cosa è andato storto quando l'ho fatto. –

+0

La prima domanda non è troppo ampia, non credo. Dovresti considerare di restringere la portata di questo post fino a quella domanda in modo che questo post non sia chiuso per essere straordinariamente ampio. – nhgrif

risposta

8

J.Doe!

Prima c'è un piccolo trucco. Se si desidera utilizzare l'iphone come posizione predefinita, è necessario notare che gli assi utilizzati su SceneKit sono diversi da quelli utilizzati da DeviceMotion. Controllare l'asse:

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

La prima cosa è necessario impostare è la posizione della telecamera. Quando avvii un progetto SceneKit, crea la tua fotocamera nella posizione (0, 0, 15). C'è un problema:

I valori di eulerAngles = (0,0,0) significherebbe che l'oggetto si troverebbe nel piano xz, ma finché si guarda da Z, lo si vede dal lato. Affinché ciò sia equivalente all'iPhone, è necessario impostare la fotocamera per guardare dall'alto. Quindi sarebbe come se stessi guardando dal telefono cellulare (come una macchina fotografica, 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 

Con questo stiamo andando a vedere la nave dall'alto, in modo che la prima parte è fatta. Ora dobbiamo fare in modo che la nave rimanga "immobile" (rivolta verso terra) con la rotazione del dispositivo.

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

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

Poi andiamo al metodo di aggiornamento

Guardate l'asse: l'asse Y e Z sono "accesi" se si confronta l'asse di sceneKit e l'asse deviceMotion. Z è sul telefono, mentre è di lato sulla scena, e Y è in alto sulla scena, mentre sul lato del telefono. Quindi il pitch, il roll e l'imbardata, rispettivamente associati all'asse X, Y e Z, saranno applicati come pitch, imbardata e roll.

Avviso Ho inserito il valore di roll positivo, perché c'è qualcos'altro "commutato". È piuttosto difficile da visualizzare. Vedere l'asse Y del movimento del dispositivo è correlato all'asse Z della scena.Ora immagina una rotazione dell'oggetto lungo questo asse, nella stessa direzione (ad esempio in senso orario), andrebbero in direzioni opposte a causa della disposizione dell'asse. (puoi anche impostare il negativo del rotolo vedi come va male)

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

Spero che ti aiuti! Ci vediamo!

+0

Grazie mille per una risposta così completa! –