Проверка пересечений/столкновений ограничительной рамки с усеченным видом

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


person leohutson    schedule 18.03.2011    source источник


Ответы (2)


I figured out that building a world-space model of the view frustum and checking for bbox collisions with it was the wrong way to go about this.

A much simpler method is to go the opposite way and convert each vertex of a given bbox to screen-space, and if any vertex of the bbox is within the screen bounds then count that bbox as visible. I get the screen-space position by multiplying against the camera matrix and then accounting for perspective based on the field of view of the camera.

Вот код:

vertexMatrix = matrix([vertex.x,vertex.y,vertex.z,1]) 
productMatrix = (vertexMatrix * camMatrix)
pVectSS = vector(prodMatrix[0][0],prodMatrix[0][1],prodMatrix[0][2])

pointX = ((pVectSS.x/(-pVectSS.z))/tan(radians(hFOV/2)))/2.0+.5
pointY = ((pVectSS.y/(-pVectSS.z))/tan(radians(vFOV/2)))/2.0+.5

ключ:

 camMatrix = camera inverse world-space matrix
 pVectSS = position vector screen-space
 hFOV = horizontal field of view
 vFOV = vertical field of view
person leohutson    schedule 21.03.2011

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

Умножение вершины на матрицу требует эквивалента 4-точечного произведения, поэтому вам потребуется эквивалент 32-точечного произведения, чтобы проверить все 8 углов. Вычисление расстояния от точки до плоскости требует скалярного произведения и сложения, что несколько эффективнее в худшем случае и намного эффективнее в среднем (поскольку вы часто можете отбросить объект после отсечения одной или двух плоскостей, и не более трех). Существует ряд оптимизаций плоскостей отсечения, которые используют временную когерентность, и я не буду вдаваться в подробности.

Кроме того, вы можете заранее выполнить грубую отбраковку, рассчитав расстояние от центральной точки до плоскости и проверив, больше ли оно радиуса ограничивающей рамки. Это будет очень дешево отбраковывать объекты, которые явно находятся «в» или «вне». Или, в качестве альтернативы, вы можете сравнить точечный продукт вашего вектора обзора с косинусом вашего значения поля зрения плюс некоторое «заполнение» (или, альтернативно, просто посмотреть, положительно ли оно) в качестве первой сверхгрубой проверки. Как вы помните, скалярное произведение двух векторов говорит вам, насколько они указывают в одном и том же направлении. Что-то, что имеет отрицательное скалярное произведение с вашим вектором обзора, безусловно, является тем, что вы можете безопасно отбросить, потому что оно позади вас.

person Damon    schedule 21.03.2011
comment
Я должен был уточнить, почему скорость в данном случае не имеет значения; сценарий используется для предварительной обработки 3D-сцены, чтобы решить, какие объекты экспортировать в средство визуализации с трассировкой лучей, поэтому, по сути, его скорость выполнения не важна, важна только скорость реализации :). Мой ответ на самом деле тоже был немного неправильным, так как есть пограничный случай, когда большой объект находится близко к камере, а все его вершины находятся за пределами FOV, поэтому я закончил тем, что просто нарисовал экранное пространство вокруг мирового пространства, это довольно плохой хак, но пока достаточно хороший. - person leohutson; 23.03.2011
comment
Для трассировщика лучей даже несколько фрагментов здесь и там на границах могут иметь огромное значение. Вы можете нарисовать свою сцену с помощью OpenGL (с фиксированной функциональностью, если хотите, так как скорость не имеет большого значения, и это легко) и выполнить запрос окклюзии для каждого объекта (поддерживается практически всеми видеокартами, поскольку по крайней мере половина десятилетие). Нет z-теста, поэтому прозрачные объекты не отбрасывают то, что находится за ними полностью, нас все равно не интересует красивый рендеринг. Все, что нам нужно, — это положительное число в запросе для любого объекта, у которого есть хотя бы один нарисованный фрагмент. - person Damon; 23.03.2011
comment
Хотя на ум приходит другое: как быть с объектами, которые отбраковываются (независимо от метода), но все равно нужны? Когда кто-то говорит о трассировке лучей, первое, что приходит на ум, это блестящие вещи с отражениями. Объект может быть очень хорошо виден на отражающей поверхности, когда он находится далеко за пределами усеченного конуса обзора. Это может быть не очень заметно в некоторых ситуациях, но даст очень забавные эффекты в других, особенно с анимацией. Если это может быть проблемой, лучше ничего не отбрасывать при экспорте сцены. - person Damon; 23.03.2011
comment
Да, вы правы, в данном случае нужно было отбраковывать объекты, потому что каждый объект был в районе 3 миллионов полигонов, плюс все отражения очень диффузные, так что на них особо не влияют удаленные объекты. Трассировщик лучей не хотел сам отбирать объекты, поскольку, как вы говорите, на отражающие объекты обычно влияют объекты за пределами экрана. - person leohutson; 28.03.2011