Java - Простая плоскость включения / исключения - PullRequest
3 голосов
/ 03 апреля 2012

Возможно, на этот вопрос уже был дан ответ, и если да, укажите мне на ответ. В противном случае, здесь идет.

У вас есть x количество объектов в пространстве, имеющих ограничивающие координаты p0 и p1. p0 и p1 - это каждая трехмерная координата, а p0 всегда имеет более низкие значения - отрицательные или положительные, а p1 всегда имеет более высокие значения.

Теперь у вас есть плоскость, которая совершенно ортогональна направлению камеры C, которая имеет позицию (pC) и курс (hC). Эта плоскость может быть определена как 90 градусов (пи / 2 радиана) от рыскания камеры (иногда называемого «курсом») и высоты тона и простирается до самых дальних определенных границ в пространстве.

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

Есть ли простой способ сделать это? К этому вопросу я не отношусь к проблеме необходимости проверять каждый объект в пространстве; для целей нашего вопроса предположим, что всегда существует ограниченное количество объектов - управляемых путем разделения пространства каким-либо образом - так, чтобы объекты, по которым мы проверяем, всегда были «сомнительными».

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

У меня такое ощущение, что есть простой способ сделать это, но, не взяв компьютерную графику, я никогда не знакомился с математикой.

Ответы [ 3 ]

1 голос
/ 04 апреля 2012

Если какой-либо из 6 углов «куба» (условно известного как ограничивающая ось ограничивающая рамка или AABB) находится на стороне обзора плоскости, возможно, что-то будет видно внутри него.Вы можете начать с проверки двух начальных точек, но если они оба невидимы, вам также необходимо проверить остальные шесть углов следующим образом:

initial corners: p0=(p0.x, p0.y, p0.z)
                 p1=(p1.x, p1.y, p1.z)

other corners:      (p1.x, p0.y, p0.z)
                    (p0.x, p1.y, p0.z)
                    (p0.x, p0.y, p1.z)

                    (p1.x, p1.y, p0.z)
                    (p0.x, p1.y, p1.z)
                    (p1.x, p0.y, p1.z)

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

1 голос
/ 08 апреля 2012

Итак, вот как это сделать.

Сначала необходимо сохранить восемь точек в каждой ограничительной рамке предсказуемым образом, например, каждый бит в целом числе, представляющем его положение относительно центра рамки.,Что вы можете сделать, это использовать 0x4 для представления EAST (+ x) (ноль в этом бите означает WEST), 0x2 для представления NORTH (ноль в этом бите означает SOUTH) и 0x1 для представления TOP (ноль в этом бите означает BOTTOM).Теперь вы можете универсально получить доступ ко всем точкам в одной и той же позиции ограничительной рамки, указав номер позиции.(все нулевые битовые числа равны нулю. Java предупреждает, что эти назначения не имеют смысла, но они помогают с удобочитаемостью.)

Настройка ограничивающего прямоугольника: (сделать это для каждого ограничивающего прямоугольника)

    pointList = new Point3d[8];

    pointList[WEST|SOUTH|BOTTOM] = new Point3d(x0,y0,z0);
    pointList[WEST|SOUTH|TOP]    = new Point3d(x0,y0,z1);
    pointList[WEST|NORTH|BOTTOM] = new Point3d(x0,y1,z0);
    pointList[WEST|NORTH|TOP]    = new Point3d(x0,y1,z1);
    pointList[EAST|SOUTH|BOTTOM] = new Point3d(x1,y0,z0);
    pointList[EAST|SOUTH|TOP]    = new Point3d(x1,y0,z1);
    pointList[EAST|NORTH|BOTTOM] = new Point3d(x1,y1,z0);
    pointList[EAST|NORTH|TOP]    = new Point3d(x1,y1,z1);

Далее вычислите нормаль по углу обзора.(Вращение влево / вправо, наклон - вверх / вниз)

    float nx = -(float)Math.cos(yaw);
    float ny = (float)Math.sin(yaw);
    float nz = (float)Math.sin(pitch);

Я думаю, что негатив - это правильно, но если все невидимо с одной стороны, просто поменяйте его:)

Рассчитайте характеристическую точку, которая является просто индексом, который вы собираетесь проверять в каждом ограничивающем прямоугольнике, потому что он представляет точку в каждом прямоугольнике, которая будет ближайшей к плоскости на невидимой стороне:

    int characteristicPoint = (nx<0?WEST:EAST)|
                              (ny<0?SOUTH:NORTH)|
                              (nz<0?BOTTOM:TOP);

Убедитесь, что каждый ограничивающий прямоугольник настроен таким образом, чтобы x, y, z были меньше, чем x, y, z штрих (x0 = x aught, x1 = x штрих)

Затем соберите вашу характеристику ('отметьте ') точку, ваш набор нормалей (' frustrum ') и положение вашей камеры (x, y, z) и сделайте это с каждым ограничивающим прямоугольником:

    float checkA = ((bounds.pointList[check].x-position.x)*frustrum.x) +
            ((bounds.pointList[check].y-position.y)*frustrum.y);

    float checkB = ((bounds.pointList[check].x-position.x)*frustrum.x) +
            ((bounds.pointList[check].z-position.z)*frustrum.z);
    if(checkB>=0&&checkA>=0) {
        visible = true;
        return;
    } else if(checkB<0&&checkA<0) {
        visible = false;
        return;
    } else {
       float checkC = ((bounds.pointList[check].y-position.y)*frustrum.y) +
            ((bounds.pointList[check].z-position.z)*frustrum.z);
       if(checkC>=0) {
          visible = true;
          return;
       } else {
          visible = false;
          return;
       }

    }

Это простая линейная алгебра (IMO) и логика такова: если точка находится на положительной стороне двух или более линий, представляющих плоскость, она видна.Если он находится на отрицательной стороне буксира или нескольких линий, представляющих плоскость, он невидим.Вы вычисляете первые два, и если они различны (один отрицательный, один положительный), вы проверяете третий и принимаете это значение.

Важно учитывать следующее свойство при обработке линий как уравнений:

-x-y = p != x+y = p

Строка такая же, но ее неявное «обращение» обратное.

Надеюсь, это поможет кому-то еще в этом вопросе.Это было трудно, но приятно, понять.

Это можно сделать более эффективным, сохранив первую половину CheckA, я полагаю:)

1 голос
/ 03 апреля 2012

Я думаю, что вы хотите найти набор пар точек, где обе точки находятся за плоскостью камеры (которую, я думаю, вы описываете как обычную плоскость 2d, содержащую точку pC и с обычным hC), но я могу иметь непонятым.

Если это то, что вы хотите, попробуйте это:

  • hC - ваш самолет нормальный
  • установить vp0 как вектор от pC до p0 (сделать положение p0 - положение pC)
  • установить vp1 как вектор от pC до p1 (сделать положение p1 - положение pC)

p0 виден, если vp0. hC> = 0 (или> 0, если вы хотите, чтобы он был строго перед камерой).

p1 виден, если vp1. hC> = 0 (или> 0, если вы хотите, чтобы он был строго перед камерой).

. Вот стандартное векторное произведение точек.

Так что, если p0 и p1 находятся за камерой, вы можете исключить форму.

...