Saya bekerja dengan beberapa teman di game berbasis browser tempat orang dapat bergerak di peta 2D. Sudah hampir 7 tahun dan masih ada orang yang memainkan game ini, jadi kami memikirkan cara untuk memberi mereka sesuatu yang baru. Sejak itu peta permainan adalah bidang terbatas dan orang-orang dapat bergerak dari (0, 0) ke (MAX_X, MAX_Y) dalam peningkatan X dan Y yang dikuantisasi (bayangkan saja sebagai papan catur besar).
Kami percaya ini saatnya untuk memberikan dimensi lain, jadi, hanya beberapa minggu yang lalu, kami mulai bertanya-tanya bagaimana permainan bisa terlihat dengan pemetaan lain:
- Pesawat tanpa batas dengan gerakan terus-menerus: ini bisa menjadi langkah maju tetapi saya masih tidak yakin.
- Dunia Toroidal (gerakan terus-menerus atau terkuantisasi): dengan tulus saya bekerja dengan torus sebelumnya, tetapi kali ini saya menginginkan sesuatu yang lebih ...
- Dunia bulat dengan gerakan terus-menerus: ini akan luar biasa!
Apa yang kita inginkan Browser pengguna diberi daftar koordinat seperti (lintang, bujur) untuk setiap objek pada peta permukaan bulat; browser kemudian harus menunjukkan ini di layar pengguna rendering mereka di dalam elemen web (kanvas mungkin? ini bukan masalah). Ketika orang mengklik pada pesawat, kami mengonversi (mouseX, mouseY) menjadi (lat, lng) dan mengirimkannya ke server yang harus menghitung rute antara posisi pengguna saat ini ke titik yang diklik.
Apa yang kami miliki. Kami mulai menulis perpustakaan Java dengan banyak matematika yang berguna untuk bekerja dengan Rotation Matrices, Quaternions, Euler Angles, Translations, dll. di dalam JPanel. Kami berhasil menangkap klik dan menerjemahkannya ke koordinat bola dan menyediakan beberapa fitur bermanfaat lainnya seperti rotasi tampilan, skala, terjemahan, dll. Apa yang kami miliki sekarang seperti mesin kecil (memang sangat sedikit) yang mensimulasikan interaksi klien dan server. Sisi klien menunjukkan titik di layar dan menangkap interaksi lain, sisi server membuat tampilan dan melakukan kalkulus lain seperti menginterpolasi rute antara posisi saat ini dan titik yang diklik.
Dimana masalahnya? Jelas kami ingin memiliki jalur terpendek untuk interpolasi antara dua titik rute . Kami menggunakan angka empat untuk menginterpolasi antara dua titik pada permukaan bola dan ini tampaknya bekerja dengan baik sampai saya perhatikan bahwa kami tidak mendapatkan jalur terpendek pada permukaan bola:
Kami berpikir masalahnya adalah bahwa rute dihitung sebagai jumlah dari dua rotasi tentang sumbu X dan Y. Jadi kami mengubah cara kami menghitung angka empat tujuan: Kami mendapatkan sudut ketiga (yang pertama adalah lintang, yang kedua adalah garis bujur, yang ketiga adalah rotasi tentang vektor yang menunjuk ke posisi kami saat ini) yang kami sebut orientasi. Sekarang kita memiliki sudut "orientasi" kita memutar sumbu Z dan kemudian menggunakan vektor hasil sebagai sumbu rotasi untuk angka empat tujuan (Anda dapat melihat sumbu rotasi berwarna abu-abu):
Apa yang kami dapatkan adalah rute yang benar (Anda dapat melihatnya berada pada lingkaran besar), tetapi kami HANYA jika titik rute awal adalah lintang, bujur (0, 0) yang berarti vektor awal adalah (sphereRadius, 0 , 0). Dengan versi sebelumnya (gambar 1) kita tidak mendapatkan hasil yang baik bahkan ketika titik awal adalah 0, 0, jadi saya pikir kita sedang bergerak menuju solusi, tetapi prosedur yang kita ikuti untuk mendapatkan rute ini sedikit "aneh " mungkin?
Pada gambar berikut ini Anda mendapatkan tampilan masalah yang kita dapatkan ketika titik awal bukan (0, 0), karena Anda dapat melihat titik awal bukan vektor (sphereRadius, 0, 0), dan seperti yang Anda lihat titik tujuan (yang digambar dengan benar!) tidak pada rute.
Titik magenta (titik yang terletak pada rute) adalah titik akhir rute yang diputar di sekitar pusat bola (-mulaiLatitude, 0, -mulaiLongitude). Ini berarti bahwa jika saya menghitung matriks rotasi dan menerapkannya ke setiap titik pada rute mungkin saya akan mendapatkan rute yang sebenarnya, tetapi saya mulai berpikir bahwa ada cara yang lebih baik untuk melakukan ini.
Mungkin saya harus mencoba untuk mendapatkan pesawat melalui pusat bola dan titik rute, memotongnya dengan bola dan mendapatkan geodesik? Tapi bagaimana caranya?
Maaf karena terlalu bertele-tele dan mungkin karena bahasa Inggris yang salah, tetapi hal ini mengejutkan saya!
EDIT: Kode di bawah ini berfungsi dengan baik! Terima kasih untuk semuanya:
public void setRouteStart(double srcLat, double srcLng, double destLat, destLng) {
//all angles are in radians
u = Choords.sphericalToNormalized3D(srcLat, srcLng);
v = Choords.sphericalToNormalized3D(destLat, destLng);
double cos = u.dotProduct(v);
angle = Math.acos(cos);
if (Math.abs(cos) >= 0.999999) {
u = new V3D(Math.cos(srcLat), -Math.sin(srcLng), 0);
} else {
v.subtract(u.scale(cos));
v.normalize();
}
}
public static V3D sphericalToNormalized3D( double radLat, double radLng) {
//angles in radians
V3D p = new V3D();
double cosLat = Math.cos(radLat);
p.x = cosLat*Math.cos(radLng);
p.y = cosLat*Math.sin(radLng);
p.z = Math.sin(radLat);
return p;
}
public void setRouteDest(double lat, double lng) {
EulerAngles tmp = new AngoliEulero(
Math.toRadians(lat), 0, -Math.toRadians(lng));
qtEnd.setInertialToObject(tmp);
//do other stuff like drawing dest point...
}
public V3D interpolate(double totalTime, double t) {
double _t = angle * t/totalTime;
double cosA = Math.cos(_t);
double sinA = Math.sin(_t);
V3D pR = u.scale(cosA);
pR.sum(
v.scale(sinA)
);
return pR;
}
sumber
Jawaban:
Masalah Anda murni dua dimensi, pada bidang yang dibentuk oleh pusat bola dan titik sumber dan tujuan Anda. Menggunakan angka empat sebenarnya membuat hal-hal lebih kompleks, karena selain posisi pada bola 3D, angka empat mengkodekan orientasi.
Anda mungkin sudah memiliki sesuatu untuk diinterpolasi pada lingkaran, tetapi untuk berjaga-jaga, berikut adalah beberapa kode yang seharusnya berfungsi.
sumber
t
mencapaitotalTime
? Juga jika Anda ingin mendapatkan lingkaran penuh, buatlah nilait
maks,2 * pi / angle * totalTime
bukan hanyatotalTime
.Pastikan kedua angka empat berada di belahan bumi yang sama di hypersphere. Jika produk-titik mereka kurang dari 0, maka tidak. Dalam hal itu negasikan salah satu dari mereka (negasikan masing-masing nomornya), sehingga mereka berada di belahan bumi yang sama dan akan memberi Anda jalan terpendek. Kodesemu:
Jawaban saya di sini menjelaskan secara rinci apa yang meniadakan setiap istilah angka empat dan mengapa orientasi masih sama, hanya di sisi lain dari hypersphere.
EDIT fungsi interpolasi akan terlihat seperti ini:
sumber
Karena Anda ingin
V3D
kembali dari interpolator Anda, pendekatan paling sederhana adalah dengan melewatkan angka empat seluruhnya. Konversikan titik awal dan akhir menjadiV3D
dan letakkan di antara keduanya.Jika Anda bersikeras menggunakan quaternions maka angka empat yang mewakili rotasi dari
P
keQ
memiliki arahP x Q
danw
dariP . Q
.sumber