То, как вы отображаете (или нет, в зависимости от обстоятельств) координаты текстуры, работает не так, как задумано.
Я ищу математику, используемую для создания псевдо-3D-эффекта с использованием 2D-лучевого вещания
Запись в Википедии для наложения текстур содержит хороший раздел с описанием того, как Doom выполняет наложение текстур. Из записи:
Движок Doom ограничил мир вертикальными стенами и горизонтальными полами / потолками с камерой, которая могла вращаться только вокруг вертикальной оси. Это означало, что стены будут иметь постоянную глубину по вертикальной линии, а полы / потолки будут иметь постоянную глубину по горизонтальной линии. Быстрое аффинное отображение может быть использовано по этим направлениям, потому что это будет правильно.
«Быстрое аффинное отображение» - это просто простая 2D-интерполяция координат текстуры, и она будет подходящей операцией для того, что вы пытаетесь. Ограничением Doom было также то, что
Doom визуализирует вертикальные и горизонтальные пролеты с аффинным наложением текстур и поэтому не может рисовать наклонные полы или наклонные стены.
Не похоже, что ваша логика содержит какой-либо код для преобразования координат между различными координатными пространствами. Вам нужно будет применить преобразования между заданными координатами трассировки лучей и координатными пространствами текстуры как минимум. Это обычно включает в себя матричную математику и является очень распространенным и может также упоминаться как Проекция , как при проецировании точек из одного пространства / поверхности в другое. С помощью аффинных преобразований вы можете избежать использования матриц в пользу линейной интерполяции.
Уравнение координат для этого, адаптированного к вашим переменным (см. Выше), может выглядеть следующим образом:
u = (1 - a) * wallStart + a * wallEnd
where 0 <= *a* <= 1
В качестве альтернативы, вы можете использовать Weak Perspective projection , так как большая часть данных уже рассчитана. Снова из википедии:
To determine which screen x-coordinate corresponds to a point at
A_x_,A_z_
multiply the point coordinates by:
B_x = A_x * B_z / A_z
where
B_x
is the screen x coordinate
A_x
is the model x coordinate
B_z
is the focal length—the axial distance from the camera center *to the image plane*
A_z
is the subject distance.
Because the camera is in 3D, the same works for the screen y-coordinate, substituting y for x in the above diagram and equation.
В вашем случае A_x
- это местоположение стены в мировом пространстве. B_z
- это фокусное расстояние, которое будет 1
. A_z
- это расстояние, которое вы рассчитали, используя трассировку лучей. Результатом является координата x или y, представляющая перевод в область просмотра.
Процедура основного рисования для W3D документирует методы, используемые для трассировки лучей и преобразования координат при рендеринге игры. Код вполне читабелен, даже если вы не знакомы с C / ASM, и это отличный способ узнать больше о ваших интересных темах. Для дальнейшего чтения я бы предложил выполнить поиск в выбранном вами движке для таких вещей, как «матричное преобразование координат для наложения текстур», или поищите на сайте GameDev SE аналогичные.
Конкретная область этого файла, на которую нужно установить ноль, - это раздел, начинающийся с 267:
> ========================
> =
> = TransformTile
> =
> = Takes paramaters:
> = tx,ty : tile the object is centered in
> =
> = globals:
> = viewx,viewy : point of view
> = viewcos,viewsin : sin/cos of viewangle
> = scale : conversion from global value to screen value
> =
> = sets:
> = screenx,transx,transy,screenheight: projected edge location and size
> =
> = Returns true if the tile is withing getting distance
> =
Великолепная книга по "математике" - это эта - я очень рекомендую ее всем, кто хочет создать или улучшить эти навыки.
Обновление:
По сути, вы будете отображать пиксели (точки) изображения на точки на вашей прямоугольной настенной плитке, как показано трассировкой лучей.
Псевдо (МОГ) -кода:
var image = getImage(someImage); // get the image however you want. make sure it finishes loading before drawing
var iWidth = image.width, iHeight = image.height;
var sX = 0, sY = 0; // top-left corner of image. Adjust when using e.g., sprite sheets
for(var i=0;i<scene.length;++i){
var c = scene[i] == Infinity ? 500 : scene[i];
var s = map(c,0,500,255,0);// how dark/bright the wall should be
var h = map(c,0,500,scene_height,10); // relative height of wall (farther the smaller)
var wX = i*w, wY = 200 - h * 0.5;
var wWidth = w + 1, wHeight = h;
//... render the rectangle shape
/* we are using the same image, but we are scaling it to the size of the rectangle
and placing it at the same location as the wall.
*/
var u, v, uW, vH; // texture x- and y- values and sizes. compute these.
ctx.drawImage(image, sX, sY, iWidth, iHeight, u, v, uW, vH);
}
Поскольку я не знаком с вашим кодом, выполняющим трассировку лучей, его систему координат и т. Д., Вам может потребоваться дополнительная настройка значений для wX
, wY
, wWidth
и wHeight
(например, , переведите точки из центра в верхний левый угол).