Преобразование перспективы в стиле Mode7 на холсте?

Я делаю игровой движок на основе холста, и мне интересно, есть ли у кого-нибудь хорошая информация о том, как добиться перспективы сверху. То, что я ищу, находится где-то посередине между традиционным видом с высоты птичьего полета и старым видом SNES mode7. Просто небольшой угол, чтобы создать иллюзию 3D.

Я пытаюсь выяснить, что будет лучшим способом справиться с искажением перспективы. Я не делаю повороты, так что 3D-матрица будет переборщить, но мне нужно иметь возможность иметь дело с рендерингом слоев карты под постоянным углом, и было бы неплохо, если бы угол можно было регулировать. Мне также нужно разобраться с искажением глубины. По сути, нижняя строка пикселей должна иметь ширину и высоту пикселя 1: 1, тогда для каждой строки она будет уменьшаться, например, на 5% или что-то в этом роде. Я хотел бы иметь возможность предоставить большой холст в качестве текстуры, а затем указать угол камеры от 0 до 90, где 0 - совершенно горизонтально, а 90 - вид с высоты птичьего полета.

У кого-нибудь есть соответствующие руководства или пример кода? Я немного поискал в Интернете, но все, что я нашел, кажется либо непригодным для использования в этом конкретном приложении, либо слишком сложным, выполняющим всевозможные сумасшедшие 3D-перекосы и повороты. Все, что я хочу, это взять обычную мозаичную сетку и немного откинуть ее назад, без поворотов или подобных сложных вещей.

Вот пример того, что я хочу; http://img801.imageshack.us/img801/2176/perspectivesample.jpg

Нижняя строка пикселей имеет соотношение пикселей 1: 1, а каждая строка над ней постепенно становится короче по горизонтали и вертикали. Исходная текстура верхней центральной области обычно составляет примерно половину высоты нижней центральной области, но она была сжата по вертикали и горизонтали, чтобы соответствовать перспективе.

Я думаю, что лучше всего будет отобразить текущее состояние окна просмотра на другом холсте в плоском виде с высоты птичьего полета, примерно с 50% дополнительным пространством сверху и по бокам, затем вырезать из него верхнюю треугольную область и нарисовать ее на фактическое видимое полотно.

Единственная проблема в том, что я плохо разбираюсь в математике, когда дело доходит до расчета углов и тому подобного.


person Stephen Belanger    schedule 01.10.2010    source источник
comment
У вас есть графический пример где-нибудь в Интернете? Просто хочу получить более четкое представление о том, что вы хотите. Спасибо   -  person Castrohenge    schedule 01.10.2010
comment
Я добавил картинку, чтобы представить, что я хочу. Карта на самом деле представляет собой сетку 32x32, но наклонена назад, чтобы добавить перспективу.   -  person Stephen Belanger    schedule 01.10.2010
comment
Это интересно: acko.net/blog/projective-texturing-with-canvas   -  person Josh Lee    schedule 01.10.2010
comment
Нет ничего проще для понимания? Как я уже сказал, мне не нужны все эти сложные дополнительные вещи, я просто хочу что-то относительно простое. Конечно, мне не нужно от нескольких сотен до тысячи строк кода, чтобы сделать что-то настолько простое.   -  person Stephen Belanger    schedule 02.10.2010
comment
Позвольте мне получить это прямо. Вы хотите повернуть 3D-вид вокруг оси X, и вы хотите сделать это с помощью 2D API без использования всех видов сумасшедших 3D-перекосов и поворотов? Как это может работать?   -  person Stefan Monov    schedule 03.10.2010
comment
Нет. Я не хочу никаких ротаций. Я только хочу наклонить прямоугольную текстуру назад, чтобы она выглядела так, как будто у нее есть перспектива, сделав верхний ряд пикселей более узким, чем нижний ряд. Само по себе это не слишком сложно понять, но он также должен иметь возможность обрабатывать текстуры, которые не идеально центрированы, делая угол с одной стороны отличным от угла с другой стороны. Вот с чем мне нужна помощь... Я не умею совмещать вектора. ›.›   -  person Stephen Belanger    schedule 04.10.2010
comment
разве это не должно быть легко с правильной матрицей преобразования, context.setTransform(....)?   -  person oberhamsi    schedule 27.01.2013
comment
Вам когда-нибудь приходилось работать в режиме 7 из холста?   -  person eri0o    schedule 04.02.2015


Ответы (2)


Если я правильно вас понял, вам просто нужно простое преобразование трапеции. если да, возможно, это или эта ссылка поможет вам. для изображений, которые не центрированы, это будет просто дополнительное ромбовидное преобразование, которое, насколько я знаю, легко возможно с холстом.

person oezi    schedule 08.10.2010

То, о чем вы говорите, можно сделать просто с помощью любого 3D API. Однако, поскольку вы решили попытаться придерживаться 2D-холста, вам нужно делать все в 2D-мире, что означает работу с прямоугольниками, вращением, масштабированием, наклоном и т. Д. Также известно как аффинные преобразования, как упоминалось в другом ответе.

То, что вы хотите сделать, возможно, но поскольку вы хотите использовать 2D, вы должны думать с точки зрения 2D-функций.

  1. Создайте исходное изображение.
  2. Добавьте фрагмент от нижней части исходного изображения к нижней части холста, немного сместив его влево, чтобы центр изображения совпадал с центром текущего холста.
  3. Очень немного увеличить масштаб всего изображения
  4. Повторяйте, пока не доберетесь до верхней части изображения.

Псевдокод будет выглядеть так...

imgA = document.getElementById('source');

// grab image slices from bottom to top of image
for (var ix=height-slice_height;ix>=0;ix-=slice_height)
{

    // move a section of the source image to the target canvas
    ctx.drawImage(imgA, 0,ix,width,slice_height, 
         0-half_slice_width_increase,width,slice_height);
    // stretch the whole canvas
    ctx.scale(scale_ratio, 1);
}

Это потребует много настроек, но это общее решение.

  • scale_ratio будет числом немного большим, но очень близким к 1.
  • ctx – стандартный двухмерный контекст холста.
  • half_slice_width_increase — это 1/2 величины, на которую холст будет увеличиваться при масштабировании с помощью коэффициента масштабирования. Это удерживает масштабированное изображение в центре.

Чтобы выглядеть правильно, вы должны сначала преобразовать фоновые плитки, прежде чем добавлять наложения значков.

person Great Turtle    schedule 04.10.2010
comment
Как я уже сказал в комментариях, мне нужно, чтобы он мог обрабатывать изображения, которые не идеально центрированы. Мне достаточно легко понять, что вы опубликовали, у меня проблемы с компенсацией изображений, которые не центрированы. - person Stephen Belanger; 05.10.2010
comment
Думаю, я не совсем понял, но исходное изображение будет создано на объекте холста в плоском 2D. Это источник. Затем вы берете кусочки готового 2D-изображения и наклоняете его, добавляя линию внизу, делая очень небольшое увеличение и повторяя по мере продвижения вверх. Затем добавьте спрайты на наклонную карту. Я постараюсь сделать рабочую демонстрацию, если у меня будет время на этих выходных. - person Great Turtle; 07.10.2010