Как я могу найти самую большую сферу, которая подходит внутри усеченного конуса?

12

Как найти самую большую сферу, которую вы можете нарисовать в перспективе?

Если смотреть сверху, это будет так:

введите описание изображения здесь

Добавлено: в области справа я выделил четыре точки, о которых, как мне кажется, мы кое-что знаем. Мы можем отменить проекцию всех восьми углов фруза, а также центров ближнего и дальнего концов. Итак, мы знаем точки 1, 3 и 4. Мы также знаем, что точка 2 - это то же расстояние от 3, что и 4 от 3. Итак, мы можем вычислить ближайшую точку на линии 1 - 4 до точки 2, чтобы получить центр? Но настоящая математика и код ускользает от меня.

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

Обновление: я попытался реализовать подход в виде круговой плоскости на двух плоскостях, как это предложили Бобобо и Натан Рид :

function getFrustumsInsphere(viewport,invMvpMatrix) {
    var midX = viewport[0]+viewport[2]/2,
        midY = viewport[1]+viewport[3]/2,
        centre = unproject(midX,midY,null,null,viewport,invMvpMatrix),
        incircle = function(a,b) {
            var c = ray_ray_closest_point_3(a,b);
            a = a[1]; // far clip plane
            b = b[1]; // far clip plane
            c = c[1]; // camera
            var A = vec3_length(vec3_sub(b,c)),
                B = vec3_length(vec3_sub(a,c)),
                C = vec3_length(vec3_sub(a,b)),
                P = 1/(A+B+C),
                x = ((A*a[0])+(B*a[1])+(C*a[2]))*P,
                y = ((A*b[0])+(B*b[1])+(C*b[2]))*P,
                z = ((A*c[0])+(B*c[1])+(C*c[2]))*P;
            c = [x,y,z]; // now the centre of the incircle
            c.push(vec3_length(vec3_sub(centre[1],c))); // add its radius
            return c;
        },
        left = unproject(viewport[0],midY,null,null,viewport,invMvpMatrix),
        right = unproject(viewport[2],midY,null,null,viewport,invMvpMatrix),
        horiz = incircle(left,right),
        top = unproject(midX,viewport[1],null,null,viewport,invMvpMatrix),
        bottom = unproject(midX,viewport[3],null,null,viewport,invMvpMatrix),
        vert = incircle(top,bottom);
    return horiz[3]<vert[3]? horiz: vert;
}

Я признаю, что я облажался; Я пытаюсь адаптировать 2D-код , расширяя его в 3 измерения. Это не правильно вычисляет сферу; кажется, что центральная точка сферы находится на линии между камерой и верхним левым краем каждый раз, и она слишком большая (или слишком близко). Есть ли явные ошибки в моем коде? Работает ли подход, если он исправлен?

Будет
источник
Должна ли сфера быть полностью на задней стороне дальней плоскости, как на картинке?
Микаэль Хогстрем
@ MikaelHögström Я полагаю, что они были бы, чтобы быть как можно большим?
Будет
Хм, я думаю, это зависит от вашей цели ... Если вы нарисуете сферу наполовину за дальним планом, тогда это будет больше, но, возможно, это идет вразрез с вашей целью?
Микаэль Хогстрем
@ MikaelHögström ага я понимаю твой вопрос; да, я хочу нарисовать всю модель, не проходя сквозь нее.
Будет

Ответы:

12

Я предполагаю, что ваш усеченный симметрично, так как ваш рисунок, кажется, предлагает это. Есть три ограничения (два, если ваш усеченный 2D):

A. сфера не может быть больше расстояния между ближней и дальней плоскостями

Если Dрасстояние ближнее-дальнее, первое ограничение просто:

R  D / 2

B. сфера не может расти шире боковых плоскостей

Теперь для другого ограничения, скажем, αэто половинный угол усеченного конуса и Lполовинная ширина дальней плоскости, как показано на этом рисунке:

усеченный

Первая формула задается тригонометрией в треугольнике. Второе происходит от суммы углов треугольника. Что дает нам второе ограничение:

R  L tan((π - 2α) / 4)

Если усеченный является 3D, вы будете иметь третье ограничение с новыми Lи αзначениями.

Конечный результат

RЗначение , которое вы ищете, minиз трех границ.

Как получить параметры

Если вы можете отменить проекцию вида или мирового пространства, вы можете вычислить L, D и α следующим образом, где Pточки находятся в ближней плоскости, а Qточки - в далекой плоскости:

Formula2

Стрелки означают векторы, «.» является точечным произведением, а || указывает длину вектора. Заменить Q2с Q3и P2с , P3чтобы получить L и а в вертикальном измерении.

Сэм Хоцевар
источник
Как, исходя из усеченного конуса (вычисляемого путем непроецирования точек обзора, чтобы приблизиться и удаляться), вы определяете поле зрения? А в 3D есть только два варианта, а не три, верно? Мои попытки поместить ваш алгоритм в код всегда дают мне очень большие R.
Will
@ Я добавлю второй рисунок с формулами, который, надеюсь, поможет.
Сэм Хочевар
2

В 2D: рассмотреть усеченный треугольник (2D)

введите описание изображения здесь

Затем вы хотите найти вкрапление треугольника.

В качестве трехмерной задачи вам нужно найти суть квадратной пирамиды.

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

bobobobo
источник
2
Вероятно, достаточно найти окружность вертикального или горизонтального усеченного контура в 2D, в зависимости от того, что имеет меньшее FOV, по крайней мере, для «стандартного» пороха (без сдвига или чего-либо еще).
Натан Рид
1

Самая большая возможная сфера должна касаться дальней плоскости (используя здесь термины для просмотра вида) прямо в центре. Он также будет касаться верхней / нижней или левой / правой плоскостей, в зависимости от того, какой угол FoV меньше. Я должен сказать, что у меня нет фактического математического доказательства для этих предположений, но они должны быть правы. Может быть, у кого-то есть идея, как это доказать.

Сфера может быть определена ее центральной точкой и радиусом. Cx и Cy совпадают с центром дальней плоскости.

Cz и радиус могут быть получены путем решения системы уравнений на основе предположений, перечисленных выше.

T является одной из нижней / верхней плоскости или левой / правой плоскости (см. Выше) с t1, t2 и t3 как нормализованным вектором нормали и t4 как расстоянием от начала координат. f - центр дальней плоскости.

t1 * cx + t2 * cy + t3 * cz - t4 = r

-fz + cz = r

t1 * cx + t2 * cy + t3 * cz - t4 = -fz + cz

t1 * cx + t2 * cy + fz - t2 = + cz - t3 * cz

t1 * cx + t2 * cy - fz - t2 = cz * (1 - t3)

cz = (t1 * cx + t2 * cy - fz - t2) / (1 - t3)

Затем рассчитывается r, вставляя в него cz: -fz + cz = r

Вы можете получить все плоскости из матрицы проекции, которую вы используете. (Не ViewProjection в этом случае)

после этого вы должны переместить сферу в нужное место: C '= обратный (вид) * C

Луис В
источник
1

Я пытаюсь сделать что-то подобное, и в моем случае скорость важнее точности, если сфера не существует за пределами границ усеченного конуса.

Если вы вычислите кратчайшее расстояние между линейными сегментами (или гранями в 3d), самое короткое найденное расстояние можно использовать как диаметр вкрапления / сферы, которая полностью лежит внутри усеченного конуса. Происхождение врезки / сферы может быть просто средним числом всех вершин (сумма и деление). Это было бы довольно быстро, а также работать для всех типов выпуклых многогранников.

Единственный недостаток заключается в том, что круг или сфера не обязательно будут самым большим вписанным кругом или сферой. Для усеченного конуса с большим объемом и одним очень коротким ребром окружность / сфера будет разделять гораздо меньше пространства усеченного конуса, чем это возможно.

Другая идея

Если вам нужна сфера трехмерного вида, и у вас есть перспективная матрица, используемая для построения этого усеченного контура, то вы можете просто использовать эту матрицу в области единичного куба, и это должно быть идеальным основанием для усеченного конуса. (Диаметр сферы куба - это длина одного из краев куба, центр - середина куба, которая является средним из вершин куба)

нулевое
источник