render Линии / Фигуры только при помощи 3D координат

optimal user

Известный
Автор темы
107
5
Версия MoonLoader
.026-beta
Есть функции, при помощи которых можно отрисовывать что либо, это:
renderDrawLine и convert3DCoordsToScreen (DrawLine требует экранные координаты, а не игровые)
Но суть в том, что преобразование работает нормально только при условии, что эти координаты видны на экране, иначе рисовать будет вообще в другую сторону
А если нужно отрисовать линию, которая начинается и/или заканчивается вне пределов экрана, но эта линия проходит на экране?
1694861817775.png

Можно получить вектор направления, циклом обрезать и проверять, стало ли видно эти точки - но это нагрузка дополнительная и выглядит не очень адекватным
В С++ не нужно с этим выносить себе мозг и можно просто отрисовывать сразу 3D координаты:

Стало интересно углубиться в этот вопрос, неужели нет варианта адекватно отрисовать такую линию?
 

optimal user

Известный
Автор темы
107
5
Не понял. У тебя примерно такая проблема? Если да, то используй функции ниже. (Да и в той теме тоже решение есть)

Посмотреть вложение 215172
Я об этом написал выше. Что без проверки, находятся ли точки которые ты указываешь в DrawLine на скрине - будет криво
В С++ можно без этой проверки указать координаты 3D мира и Render будет работать вполне удачно, не нужно ничего переводить в координаты экрана

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

Tema05

Известный
1,441
401
Я сам столкнулся с похожей проблемой и мучался как бы сделать нормальный рендер трейсеров к объектам за спиной. Потом нашёл функцию convert3DCoordsToScreenEx которая даёт на 3 аргумента больше чем convert3DCoordsToScreen. При помощи 4 значения можно определять находится ли координата в пределах камеры. Это не тоже самое что пределы экрана (isPointOnScreen). На этом можно сыграть. Там ещё нужно было немного пострадать с логикой, чтобы не было мерцаний и трейсер не уходил в непонятную сторону под определённым углом обзора. И последнее если смотреть в идеально противоположенную сторону от трейсера он должен обрезаться об экран. Поэтому я его делю на 2 пока он не станет умещаться в пространстве от игрока до камеры. Да это то что ты хочешь избежать но я хз как можно рендерить трейсер к точке за спиной при этом когда он не уходит за пределы экрана. Но я посмотрел это в целом не сильно больно. В худшем случаи 10 циклом обрезания длинны. Зачастую хватает 5. Вероятнее всего можно сделать умнее написав свою формулу преобразования координат или используя остальные 2 значения convert3DCoordsToScreenEx но я не разбирался что они значат.
500, 1000, 10 это координаты точки куда нужно рисовать трейсер.
Lua:
local x, y, z = getCharCoordinates(PLAYER_PED)
local position = {
    main = {
        x = 500,
        y = 1000,
        z = 10
    },
    start = {
        x = x,
        y = y,
        z = z
    },
    finish = {
        x = 500,
        y = 1000,
        z = 10
    }
}
if not isPointOnScreen(position.main.x, position.main.y, position.main.z) then
    local _, _, _, z = convert3DCoordsToScreenEx(position.main.x, position.main.y, position.main.z)
    while not (z > 0 and not isPointOnScreen(position.main.x, position.main.y, position.main.z)) do
        if z > 0 then
            position.start.x = position.main.x
            position.start.y = position.main.y
            position.start.z = position.main.z
            position.main.x = (position.main.x + position.finish.x) / 2
            position.main.y = (position.main.y + position.finish.y) / 2
            position.main.z = (position.main.z + position.finish.z) / 2
        else
            position.finish.x = position.main.x
            position.finish.y = position.main.y
            position.finish.z = position.main.z
            position.main.x = (position.main.x + position.start.x) / 2
            position.main.y = (position.main.y + position.start.y) / 2
            position.main.z = (position.main.z + position.start.z) / 2
        end

        _, _, _, z = convert3DCoordsToScreenEx(position.main.x, position.main.y, position.main.z)
    end
end

local x, y, z = getCharCoordinates(PLAYER_PED)
local x1, y1 = convert3DCoordsToScreen(x, y, z)
local x2, y2 = convert3DCoordsToScreen(position.main.x, position.main.y, position.main.z)
renderDrawLine(x1, y1, x2, y2, 1, -1)
 

Tema05

Известный
1,441
401
Конечно не идеальное решение, но уже хоть что-то. Попробую с ним поиграться, спасибо за наводку)
Идеальным будет написать свою формулу для расчётов. Но это ещё суметь нужно.