Küre Hakkında Rastgele Dönme


12

Bir kullanıcının kürenin yüzeyi etrafında hareket etmesini sağlayan bir tamirciyi kodluyorum. Küre üzerindeki konum şu anda thetave olarak saklanır phi, burada thetamevcut konumun z ekseni ile xz çıkıntısı arasındaki açı (yani y ekseni etrafında dönüş) ve y ekseninden konuma phiaçıdır. Bunu kötü bir şekilde açıkladım, ama aslında theta = yaw,phi = pitch

Vector3 position = new Vector3(0,0,1);
position.X = (float)Math.Sin(phi) * (float)Math.Sin(theta);
position.Y = (float)Math.Sin(phi) * (float)Math.Cos(theta);
position.Z = (float)Math.Cos(phi);
position *= r;

Bunun doğru olduğuna inanıyorum, ancak yanlış olabilirim. Yarıçaplı dünya uzayının kökeninde bir kürenin yüzeyi etrafında rasgele iki boyutlu bir yönde hareket edebilmem gerekiyor r. Örneğin, tutma Woyuncunun yönüne göre küre etrafında yukarı doğru hareket etmelidir.

Kürenin konumunu / yönelimini temsil etmek için bir Kuaterniyon kullanmam gerektiğine inanıyorum, ama bunu yapmanın doğru yolunu düşünemiyorum. Küresel geometri benim güçlü elbisem değil.

Temel olarak, aşağıdaki bloğu doldurmam gerekiyor:

public void Move(Direction dir)
{   
    switch (dir)
    {
        case Direction.Left:
            // update quaternion to rotate left
            break;
        case Direction.Right:   
            // update quaternion to rotate right
            break;
        case Direction.Up:
            // update quaternion to rotate upward
            break;
        case Direction.Down:
            // update quaternion to rotate downward
            break;
    }
}

Oyuncu direklere ulaşırsa ne olur? "Yukarı doğru yön" yazdığınızı fark ettim, kelimenin tam anlamıyla "yukarı" mı (yani, kürenin yüzeyinden uzakta), "düz ileri" veya "kuzey kutbuna doğru" mı (son iki oyuncu aynı ise) yönlerini değiştiremez ve "önlerinde" veya "yukarı" her zaman kuzeydir)?
Martin Sojka

Belki de kötü ifade edilmişti. Oyuncu kürenin yüzeyini terk etmemeli ve kardinal eksenin farkında olmamalıdır. "Yukarı" hareket ettirdiğinizde, kürenin yüzeyi boyunca oynatıcının yönüne göre yukarı doğru hareket edersiniz. Örneğin (r, 0,0) konumundaysanız ve yukarı basarsanız, z + kutbuna doğru gidersiniz, ancak devam ederseniz etrafta sarılıp devam etmelisiniz.
azz

Hala bir soru var: Oyuncu yönünü değiştirebilir mi ("sola" ve "sağa" döndürün)?
Martin Sojka

Belki de ne istediğime daha iyi bir örnek: (1,1,1)Soldaki oyuncu kürenin etrafında dönerek (~1.2,0,~-1.2), sonra (-1,-1,-1), sonra (~-1.2,0,~1.2)ve sonra geri dönecekti (1,1,1).
azz

1
Her zaman pozisyonunuzu güncellemek thetave takip phietmek istiyorsanız, sorununuzu gereksiz yere karmaşık hale getiriyorsunuz. Her bir karenin (biri yalpalamayan) ve Vector3.Transormkürenin etrafındaki 2 dönüş eksenini hesaplamak çok daha kolaydır . Bu, sorununuzu basitleştirir ancak phi& ile bağlantıyı kesmenize neden olur theta.
Steve H

Yanıtlar:


5

Aslında, 'her iki yöne' sahip olamayacağınız ortaya çıkıyor: niyetiniz küre üzerinde herhangi bir 'mutlak yönelim' duygusu yoksa (yani, oyuncular her zaman örneğin direklere bakmıyorsa) ), oyuncu yönlendirmesi kavramına sahip olmanız gerekir. Sezgi önerebiliriz aksine, küre üzerinde hareket Bunun nedeni değil tam bir uçağa hareketi gibi, hatta lokal olarak (oldukça); kürenin kendine özgü eğriliği, oyuncuların kendilerini döndürecek eylemlerde bulunabileceği anlamına gelir!

Neden bahsettiğimin en uç örneği için, oyuncunun ekvatorda bir noktada başladığını düşünün (rahatlık için ekvatorda yukarıdan eşleştirilen bir saat yüzü hayal edeceğiz ve oynatıcıyı saat 6 yönünde koyacağız ), 'yukarıya' bakacak şekilde, yani Kuzey Kutbuna doğru. Diyelim ki oyuncu Kuzey Kutbuna kadar yürüyor; o zaman doğrudan saat 12 yönüne bakarlar. Şimdi, oyuncu Kuzey Kutbundan ekvatora doğrudan sağa hareket etsin; saat 3'te dönecekler - ama sağa doğru hareket ettiklerinde yüzleri değişmediği için(fikir şu ki, nasıl hareket ederlerse etsinler yüzleri değişmiyor), hala saat 12 yönünde karşı karşıya gelecekler - şimdi ekvator boyunca karşı karşıya kalıyorlar! Şimdi, 'geri' başlangıç ​​noktalarına geri dönmelerine izin verin; o zaman hala ekvator boyunca karşı karşıya kalacaklar, bu yüzden saat 3'e doğru bakacaklar - sadece 'kişisel' yönlerini değiştirmeden küre boyunca hareket etmeleri, kuzey kutbuna bakacak şekilde dönmelerine neden oldu. ekvator boyunca bakacak! Bir anlamda, bu eski bir avcının bir ayrıntısıdır, bir avcı bir mil güneye, bir mil batıya ve sonra bir mil kuzey'e doğru şaka - ama burada yön değişikliğini gerçekleştirmek için kürenin eğriliğinden yararlanıyoruz. Aynı etkinin çok daha küçük ölçeklerde bile devam ettiğini unutmayın;

Neyse ki, kuaterniyonlar (sizin belirttiğiniz gibi) bu durumu ele alır; bir kuaterniyon keyfi bir dönüşü temsil ettiğinden, küre üzerinde keyfi bir 'nokta artı yönelimi' etkin bir şekilde temsil eder: başlangıçta bir 'üç eksenli' ile başlayıp ona keyfi bir dönüş sağlayın, ardından bir birimi döndürülen eksenler hangi yönde hareket ettirdiğinizi hayal edin Z ekseni noktaları; küçük bir düşünce, bunun sizi ünite küresinde bir miktar 'yönelim' (yani, üç ekseninizin X ve Y eksenlerinin bazı düzenlemeleri) ile bir noktaya getirdiğine ve her noktaya + yönelime erişebileceğinize ikna edecektir. birim küre bu şekilde (sadece Z ekseninizi, başlangıç ​​noktasından küre üzerindeki noktaya doğru çizgi boyunca işaret edin, daha sonra üç eksenlerinizi bu satır boyunca başlangıç ​​noktasına geri taşıyın). Daha ne, Kuaterniyonların çarpımı rotasyon kompozisyonuna karşılık geldiğinden, tarif ettiğiniz işlemlerin her biri 'mevcut yönelemenizi' uygun şekilde seçilmiş bir kuaterniyon ile çarparak temsil edilebilir: özellikle, (birim) kuaterniyondan (qx, qy, qz, qw) "arkcos (qw) ile (qx, qy, qz) ekseni etrafında döndür" anlamına gelir, ardından (özel koordinat sistemi seçiminize bağlı olarak ve c_a'nın cos (alfa) ve s_a günah (alfa) olmasına izin vermek) üç quaternion M_x = (s_a, 0, 0, c_a), M_y = (0, s_a, 0, c_a) ve M_z = (0, 0, s_a, c_a) 'I yönünde döndürme (yani taşıma) 'şu anda alfa ile karşı karşıyayım' ve 'şu anda alfa ile karşı karşıya olduğum yönün ortogonal bir yönünde dön'. (Bu kuaterniyonların üçüncüsü 'karakterimi kendi ekseni etrafında döndür'Cur_q = M_x * Cur_qeğer oyuncu yukarı bastırdıysa veya Cur_q = M_y * Cur_qoyuncu sağa Cur_q = M_yinv * Cur_qbastıysa (veya oyuncu sola bastırmış gibi bir şey varsa, burada M_yinv M_y kuaterniyonunun 'tersidir, başka bir dönüşü temsil eder). İster premultiply ister postmultiply olsun, rotasyonu hangi 'tarafa uyguladığınıza dikkat etmeniz gerekir; açık söylemek gerekirse, bunu hem hata hem de deneme yöntemiyle çözmek, hata ve çarpımla çözmek en kolay yol olabilir.

Güncellenmiş kuaterniyonunuzdan küre üzerindeki bir noktaya (ve karakterinizin bir yönüne) gitmek de nispeten basittir: son paragrafın yazışmasına göre, yapmanız gereken tek şey kuaterniyonunuzu temel vektörlerde kullanmaktır (1, 0,0), (0,1,0) ve (0,0,1) karelerinizi 'vektörü kuaterniyona göre döndür' işlemi v → qvq -1 (burada çarpmaların kuaterniyon olduğu ve v = (x, y, z) 'dejenere kuaterniyon' (x, y, z, 0)) ile. Örneğin, birim küredeki konum sadece z vektörünü dönüştürerek elde edilir: pos = (qx, qy, qz, qw) * (0, 0, 1, 0) * (-qx, -qy, -qz, qw) = (qx, qy, qz, qw) * (qy, -qx, qw, qz) = (2 (qy * qw + qz * qx), 2 (qz * qy-qw * qx), (qz ^ 2 + qw ^ 2) - (qx ^ 2 + qy ^ 2), 0), yani(2(qy*qw+qz*qx), 2(qz*qy-qw*qx), (qz^2+qw^2)-(qx^2+qy^2))birim küredeki 'dönüştürülmüş' kullanıcının koordinatları olurdu (ve keyfi bir küredeki koordinatları elde etmek için, elbette, bunları kürenin yarıçapıyla çarpacaksınız); benzer hesaplamalar, örneğin kullanıcının yönünü tanımlamak için diğer eksenler için de kullanılabilir.


Tam olarak elde etmek istediğim şey. Oryantasyon kuaterniyonundan bir pozisyon almanın doğru yolunu düşünemedim. Sağladığınız şeyi kullanarak, Move()prosedürü yazabilirim , ancak normalleştirilmiş ekseni (yani konumum) elde etmek için, sadece alır mıydım (sin(qx),sin(qy),sin(qw)) * r?
azz

@Der tam olarak değil - Gönderiyi ayrıntılarla güncelleyeceğim, ancak kısa sürüm, dördüncülüğünüzü bir birim vektörü, örneğin (0,0,1), normal v -> qvq <sup> dönüştürmek için kullanmanızdır. -1 </sup> işlemi; basit bir vektörü dönüştürdüğünüz, burada (doğal olarak) bir kısayol olduğu anlamına gelir, ancak son koordinatlar, kuaterniyonunuzun değerlerinde lineer değil, ikinci derecedir.
Steven Stadnicki

1

Sanırım buna benzer bir şey istiyorsun http://www.youtube.com/watch?v=L2YRZbRSD1k

48 saatlik bir gamejam için kodu buradan yükleyebilirsiniz ... http://archive.globalgamejam.org/2011/evil-god

3D koordinatları elde etmek için kodunuza benzer bir şey kullandım ... ama gezegeni döndürdüm ve oyuncu aynı pozisyondaydı, sanırım yaratık hareketiyle ilgileniyorsunuz, bu:

    // To add movement
    protected override void LocalUpdate(float seconds)
    {
        Creature.Alfa += Direction.X * seconds * Speed;
        Creature.Beta += Direction.Y * seconds * Speed;            
    }


    // To calculate position
       World.Planet.GetCartesian(Alfa, Beta, out Position); // as you do
       Matrix PositionMatrix = Matrix.CreateTranslation(Position) * World.Planet.RotationMatrix;           
       LastPositionAbsolute = PositionAbsolute;
       Vector3 Up = PositionAbsolute = Vector3.Transform(Vector3.Zero, PositionMatrix);           
       Up.Normalize();
       // This is to add and offset to the creature model position
       PositionAbsolute += Up * 8;  
      // calculate new forward vector if needed

       if ((PositionAbsolute - LastPositionAbsolute).Length() > 0.1f) {
           Forward = PositionAbsolute - LastPositionAbsolute;
           Forward.Normalize();
       }

       // Calculate the world transform with position, forward vector and up vector
       Matrix LocalWorld = Matrix.CreateWorld(PositionAbsolute, Forward, Up); 

       Transform = Matrix.CreateScale(Scale * ScaleFactor) * LocalWorld;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.