Хотя контекст этого вопроса касается создания 2D / 3D-игры, проблема, с которой я столкнулся, сводится к некоторой математике. Хотя это 2,5-мерный мир, давайте притворимся, что это всего лишь 2-мерный мир для этого вопроса.
// xa: x-accent, the x coordinate of the projection
// mapP: a coordinate on a map which need to be projected
// _Dist_ values are constants for the projection, choosing them correctly will result in i.e. an isometric projection
xa = mapP.x * xDistX + mapP.y * xDistY;
ya = mapP.x * yDistX + mapP.y * yDistY;
xDistX и yDistX определяют угол оси x, а xDistY и yDistY определяют угол оси y на проекции (а также размер сетки, но для простоты предположим, что это 1 пиксель).
x-axis-angle = atan(yDistX/xDistX)
y-axis-angle = atan(yDistY/yDistY)
такая "нормальная" система координат
--------------- x
|
|
|
|
|
y
has values like this:
xDistX = 1;
yDistX = 0;
xDistY = 0;
YDistY = 1;
Таким образом, каждый шаг в направлении x приведет к проекции на 1 пиксель вправо на 0 пикселей вниз. Каждый шаг в направлении y проекции приведет к 0 шагам вправо и 1 пикселю вниз. При правильном выборе xDistX, yDistX, xDistY, yDistY вы можете спроецировать любую триметрическую или диметрическую систему (поэтому я выбрал эту).
Пока все хорошо, когда это нарисовано, все оказывается в порядке. Если «моя система» и мышление понятны, давайте перейдем к перспективе. Я хотел добавить некоторую перспективу к этой сетке, поэтому я добавил несколько дополнительных элементов, например:
camera = new MapPoint(60, 60);
dx = mapP.x - camera.x; // delta x
dy = mapP.y - camera.y; // delta y
dist = Math.sqrt(dx * dx + dy * dy); // dist is the distance to the camera, Pythagoras etc.. all objects must be in front of the camera
fac = 1 - dist / 100; // this formula determines the amount of perspective
xa = fac * (mapP.x * xDistX + mapP.y * xDistY) ;
ya = fac * (mapP.x * yDistX + mapP.y * yDistY );
Теперь самое сложное... что, если вы получили точку (xa,ya) на проекции и хотите вычислить исходную точку (x,y). Для первого случая (без перспективы) я нашел обратную функцию, но как это сделать для формулы с перспективой. Майские математические способности не совсем подходят для решения этой задачи.
(Я смутно помню, что давным-давно mathematica могла создать обратную функцию для некоторых особых случаев... может ли это решить эту проблему? Может кто-нибудь попробовать?)
fac
? Какова величина перспективы? Какое отношение имеет 100 к чему-либо? Предназначен лиfac
для реализации кажущегося сжатия объектов из-за перспективы. Это делает объект на расстоянии 100 нулевым размером, так что это не имеет смысла? - person sigfpe   schedule 21.05.2010