Tôi đang làm việc với một số người bạn trên một trò chơi dựa trên trình duyệt nơi mọi người có thể di chuyển trên bản đồ 2D. Đã gần 7 năm và mọi người vẫn chơi trò chơi này, vì vậy chúng tôi đang nghĩ cách để cung cấp cho họ một cái gì đó mới. Kể từ đó, bản đồ trò chơi là một mặt phẳng giới hạn và mọi người có thể di chuyển từ (0, 0) đến (MAX_X, MAX_Y) theo gia số X và Y được lượng tử hóa (chỉ cần tưởng tượng nó như một bàn cờ lớn).
Chúng tôi tin rằng đã đến lúc cung cấp cho nó một chiều không gian khác, vì vậy chỉ một vài tuần trước, chúng tôi bắt đầu tự hỏi làm thế nào trò chơi có thể nhìn với các ánh xạ khác:
- Máy bay không giới hạn với chuyển động liên tục: đây có thể là một bước tiến nhưng tôi vẫn không bị thuyết phục.
- Thế giới hình xuyến (chuyển động liên tục hoặc lượng tử hóa): chân thành tôi đã làm việc với hình xuyến trước đây nhưng lần này tôi muốn một cái gì đó nhiều hơn ...
- Thế giới hình cầu với sự chuyển động liên tục: điều này sẽ rất tuyệt!
Những gì chúng tôi muốn Trình duyệt người dùng được cung cấp một danh sách các tọa độ như (vĩ độ, kinh độ) cho từng đối tượng trên bản đồ bề mặt hình cầu; Các trình duyệt sau đó phải hiển thị điều này trong màn hình của người dùng hiển thị chúng bên trong một thành phần web (có thể là canvas? đây không phải là vấn đề). Khi mọi người nhấp vào mặt phẳng, chúng tôi chuyển đổi (mouseX, mouseY) thành (lat, lng) và gửi nó đến máy chủ để tính toán tuyến đường giữa vị trí của người dùng hiện tại đến điểm được nhấp.
Những gì chúng tôi có Chúng tôi đã bắt đầu viết một thư viện Java với nhiều toán học hữu ích để làm việc với Ma trận Xoay, Đệ tứ, Euler Angles, Dịch thuật, v.v. Chúng tôi kết hợp tất cả lại và tạo ra một chương trình tạo các điểm hình cầu, hiển thị chúng và hiển thị cho người dùng bên trong một JPanel. Chúng tôi đã quản lý để bắt các nhấp chuột và dịch chúng sang các hợp đồng hình cầu và cung cấp một số tính năng hữu ích khác như xoay chế độ xem, tỷ lệ, dịch, v.v. Những gì chúng tôi có bây giờ giống như một công cụ nhỏ (thực sự rất nhỏ) mô phỏng tương tác giữa máy khách và máy chủ. Phía máy khách hiển thị các điểm trên màn hình và bắt các tương tác khác, phía máy chủ hiển thị chế độ xem và thực hiện các phép tính khác như nội suy tuyến đường giữa vị trí hiện tại và điểm được nhấp.
Vấn đề ở đâu? Rõ ràng chúng ta muốn có con đường ngắn nhất để nội suy giữa hai điểm tuyến . Chúng tôi sử dụng tứ phương để nội suy giữa hai điểm trên bề mặt của hình cầu và điều này dường như hoạt động tốt cho đến khi tôi nhận thấy rằng chúng tôi không đi được con đường ngắn nhất trên bề mặt hình cầu:
Chúng tôi mặc dù vấn đề là tuyến đường được tính bằng tổng hai lần quay quanh trục X và Y. Vì vậy, chúng tôi đã thay đổi cách tính toán bậc bốn đích: Chúng ta có góc thứ ba (thứ nhất là vĩ độ, thứ hai là kinh độ, thứ ba là xoay quanh vectơ chỉ về vị trí hiện tại của chúng ta) mà chúng ta gọi là định hướng. Bây giờ chúng ta có góc "định hướng", chúng ta xoay trục Z và sau đó sử dụng vectơ kết quả làm trục xoay cho phần tư đích (bạn có thể thấy trục xoay có màu xám):
Những gì chúng ta có là tuyến đường chính xác (bạn có thể thấy nó nằm trên một vòng tròn lớn), nhưng chúng ta chỉ có CHỈ này nếu điểm tuyến đường bắt đầu ở vĩ độ, kinh độ (0, 0) có nghĩa là vectơ bắt đầu là (sphereRadius, 0 , 0). Với phiên bản trước (hình 1), chúng tôi không có kết quả tốt ngay cả khi điểm bắt đầu là 0, 0, vì vậy tôi nghĩ rằng chúng tôi đang hướng tới một giải pháp, nhưng quy trình chúng tôi thực hiện để có lộ trình này hơi "lạ" " có lẽ?
Trong hình ảnh sau, bạn có được cái nhìn về vấn đề chúng ta gặp phải khi điểm bắt đầu không phải là (0, 0), vì bạn có thể thấy điểm bắt đầu không phải là vectơ (sphereRadius, 0, 0) và như bạn có thể thấy điểm đích (được vẽ chính xác!) không nằm trên tuyến đường.
Điểm màu đỏ tươi (điểm nằm trên tuyến đường) là điểm kết thúc của tuyến đường xoay quanh tâm của hình cầu (-startLatitude, 0, -startLongitude). Điều này có nghĩa là nếu tôi tính toán một ma trận xoay và áp dụng nó cho mọi điểm trên tuyến đường thì có thể tôi sẽ có được tuyến đường thực sự, nhưng tôi bắt đầu nghĩ rằng có một cách tốt hơn để làm điều này.
Có lẽ tôi nên cố gắng đưa máy bay qua tâm của quả cầu và các điểm tuyến đường, giao nó với quả cầu và lấy trắc địa? Nhưng bằng cách nào?
Xin lỗi vì cách quá dài dòng và có thể vì tiếng Anh không chính xác nhưng điều này đang thổi vào tâm trí của tôi!
EDIT: Mã dưới đây hoạt động tốt! Cảm ơn tất cả mọi người:
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;
}