Функция проецирования xyz на координаты экрана xy

Привет, я пытаюсь создать гибридную 2D / 3D-игру, используя коммерческий движок для разработки 2D-игр.

В игре будет серия 2D-спрайтов, которые будут отображаться на экране в зависимости от их глубины в псевдо-3D-пространстве, а не только их положения по x и y, как показано на рисунке.

Функция проецирования xyz на координаты экрана xy

Если спрайт «A» находится в точке x, y, z (150,20,100) в мире шириной 500, высотой 500 и глубиной 500, где он должен быть отображен на экране с разрешением 1024x768?

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

Может ли кто-нибудь помочь мне с необходимой логикой, учитывая сценарий на иллюстрации? Мне нравится функция на любом языке, даже псевдокод, который возвращает пару X и Y после передачи ей параметров x, y, z.

Спасибо

А) Выберите один язык. Б) Я не совсем понимаю проблему. Разве вы не можете просто удалить позицию y? Тогда это просто проблема масштабирования

jhamon 29.11.2018 14:52

Вы смотрели статью Википедии "3D-проекция"? Рассмотрены три случая ...

Damien 29.11.2018 14:54

@jhamon A) На каком языке вы лучше всего владеете? Если он у вас есть, вы можете опубликовать свое решение на этом языке.

user1800742 30.11.2018 16:43

@jhamon B) Моя проблема в том, что я ищу простой и экономичный механизм кодирования, в котором я могу вставить координаты xyz и получить обратно координаты xy. Большинство решений для 3D-проекции кажутся излишними для того, что мне нужно.

user1800742 30.11.2018 16:54

@Damien Я проверил страницу Википедии, спасибо, я просто не могу понять ее в данный момент, и у меня нет возможности преобразовать то, что там описано, в код функции, который я могу повторно использовать в своей программе

user1800742 30.11.2018 17:03
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
870
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вам нужен простейший код и вы не хотите углубляться в матрицы, попробуйте что-нибудь вроде этого:

Vec2 screenCenter = Vec2( screensize.x/2, screensize.y/2 ); // half of your screen resolution
                                                            // try changing it to see what happens
                                                            // you can animate it to add special effects
float perspStrength = 500.0f;   // actually an inverse of perspective strength
                                // lower values means bigger effect

Vec2 project( Vec3 pos )        // projection code
{
    Vec2 localPos = pos - screenCenter; // Move point (0,0) to the center of your screen

    float scale = pos.z/perspStrength;  // scale your Z to ~(0-1) range
    scale += 1.0f;                      // move your Z to ~(1-2) range

    localPos.x /= scale;                // scale position according to Z distance
    localPos.y /= scale;

    Vec2 result = localPos + screenCenter;  // Move point (0,0) back to the corner

    return result;
//    return Vec3( result.x, result.y, scale ); // you can also return scale used for this object
                                                // so you can render distant objects as smaller
}

Я написал этот код, предполагая, что он будет использоваться со значениями с плавающей запятой. Я выбрал 500 contant только потому, что вы предположили, что Z находится в диапазоне (0,500), поэтому я хотел переместить его в диапазон (0-1). Мы не хотим иметь 0 в нашем коде проекции, потому что мы будем делить на это значение, поэтому мы добавляем 1, чтобы переместить масштаб в диапазон (1-2). Не стесняйтесь изменять эти значения и смотреть, что произойдет.

Согласно вашему второму вопросу: Я думаю, что вы переписали этот код, используя целые числа, поэтому деление на 500 отменяет ваше значение Z=100 и дает тот же результат, что и вектор Z=100. Чтобы исправить это, вы можете изменить int на float, и все должно быть в порядке. Если вы не хотите или не можете этого делать и вам нужен код для целых чисел, его нужно немного изменить:

Вместо шкалы с плавающей запятой мы можем использовать int и представить масштаб в единицах 1/1000, поэтому базовый масштаб будет равен 1000.

Самый простой способ получить шкалу:

int scale = 1000 - pos.z;

Если вам нужно масштабирование эффекта перспективы, вы можете использовать это вместо:

int perspStrength = 100;
int scale = 1000 - (pos.z*perspStrength/100);

Теперь, когда у вас есть scale в единицах 1/1000, вы можете масштабировать свои векторы:

localPos.x = localPos.x * scale / 1000;
localPos.y = localPos.y * scale / 1000;

Спасибо @kolenda, это то, что я ищу, и спасибо также за включение значения шкалы в набор результатов, но что делает float perspStrength = 500.0f; значит? может ли это значение быть простым целым числом, например 500?

user1800742 30.11.2018 17:14

Я подозреваю, что причина того, что почти все решения для 3D-кодирования так быстро усложняются, заключается в том, что они попадают во вращение камеры и объектов, которые мне не нужны в моем сценарии. Камера всегда смотрит прямо, а объекты буквально плоские и визуализируются как 2D-спрайты.

user1800742 30.11.2018 17:23

kolenda, однако после его реализации я заметил, что в вашем решении положение объекта по оси Z не влияет на положение объекта по осям X и Y. Ваш код будет отображаться на объекте в позиции (100,100,100) на том же экране x, y, что и объект в позиции (100,100,0). Так быть не должно!

user1800742 01.12.2018 12:32

Другие вопросы по теме