2015-10-22 11 views
5

Mam więc trochę projektu, który próbuję wykonać. Próbuję uzyskać obrót urządzeń względem grawitacji i tłumaczenie od miejsca, w którym się zaczęło. Więc w zasadzie otrzymuję dane "śledzenia" dla urządzenia. Planuję zasadniczo zastosować to, tworząc 3d pt, który będzie naśladować dane, które nagrywam z urządzenia później.Proszę, pomóżcie mi poprawnie zastosować dane o rotacji urządzenia

W każdym razie, próbując to osiągnąć, pomyślałem, że najlepiej będzie pracować z zestawem scen w ten sposób, że widzę rzeczy w 3 wymiarach, podobnie jak dane, które próbuję nagrać. W tej chwili staram się zmusić statek do rotacji, aby zawsze wyglądał jak jego grawitacja (jak na ziemi lub coś w tym rodzaju), bez względu na rotację urządzenia. Sądzę, że gdy już to zrobię, będzie to grzechotka, aby zastosować to do pewnego punktu. Tak więc stworzyłem następujący kod:

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) 

    } 

Gdy uruchamiasz tylko jedną z linii obrotu, wszystko jest idealnie. Zachowuje się prawidłowo na tej osi. Jednak kiedy robię wszystkie trzy osie "od razu staje się chaotyczna i działa daleko od oczekiwanego z jitterem i wszystkim.

Domyślam się, że moje pytanie brzmi: Czy ktoś wie, jak poprawić powyższy kod, aby statek prawidłowo pozostał "w pionie" bez względu na orientację.

+0

To pytanie jest zbyt obszerne. – nhgrif

+1

@nhgrif Zapisałem moje główne pytania powyżej. Niektóre z nich to więcej teorii niż aplikacji. Jednak moja definicja nie jest szeroka. Wyraźnie stwierdziłem, czego oczekiwałem i co poszło źle, kiedy to zrobiłem. –

+0

Pytanie 1 samo w sobie nie jest zbyt szerokie, nie sądzę. Powinieneś rozważyć zawężenie zakresu tego posta do tego samego pytania, aby ten post nie był zamknięty z powodu wyjątkowo szerokiego zakresu. – nhgrif

Odpowiedz

8

J.Doe!

Najpierw jest niewielka sztuczka. Jeśli chcesz użyć iPhone'a jako domyślnej pozycji, musisz zauważyć, że oś używana w scenieKit różni się od osi używanej przez DeviceMotion. Sprawdź oś:

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

Pierwszą rzeczą, którą trzeba ustawić jest położenie kamery. Po uruchomieniu projektu SceneKit tworzy on swoją kamerę w pozycji (0, 0, 15). Wystąpił problem z tym:

Wartości EulerAngles = (0,0,0) oznaczałyby, że obiekt znajdowałby się w płaszczyźnie xz, ale tak długo, jak patrzysz na Z, po prostu widzisz go z bok. Aby było to równoważne z układaniem iPhone'a, musisz ustawić kamerę tak, aby wyglądała z góry. Więc byłoby jakbyś patrząc na niego z telefonu (takich jak 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 

Dzięki temu mamy zamiar zobaczyć statek z góry, więc pierwsza część jest wykonywana. Teraz musimy sprawić, aby statek pozostał "nieruchomy" (twarzą do ziemi) przy obrocie urządzenia.

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

Następnie na 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; 
} 

Potem idziemy do sposobu aktualizacji

Spójrz na osi: osi Y i Z są „włączane” Jeśli porównać oś sceneKit i oś deviceMotion. Z jest podniesiony do góry, a jednocześnie znajduje się z boku sceny, a Y jest na scenie, a jednocześnie z boku telefonu. Tak więc pitch, roll i yaw, odpowiednio związane z osiami X, Y i Z, będą stosowane jako pitch, yaw and roll.

Uwaga Złożyłem wartość przechyłu pozytywną, ponieważ jest coś innego "przełączonego". Trudno to sobie wyobrazić. Zobacz oś Y ruchu urządzenia jest skorelowana z osią Z sceny.Teraz wyobraźmy sobie obrót obiektu wzdłuż tej osi, w tym samym kierunku (na przykład w kierunku zgodnym z ruchem wskazówek zegara), zmierzałyby one w przeciwnych kierunkach z powodu rozmieszczenia osi. (możesz ustawić negatywny wynik rolki, aby zobaczyć, jak działa źle)

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

Nadzieję, że pomaga! Do zobaczenia!

+0

Dziękuję bardzo za tak dokładną odpowiedź! –

Powiązane problemy