Я хочу проверить усеченный вид относительно ограничивающих прямоугольников, выровненных по оси, некоторых объектов, чтобы примерно проверить, находятся ли эти объекты в поле зрения или нет. Скорость не имеет большого значения.
Проверка пересечений/столкновений ограничительной рамки с усеченным видом
Ответы (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
Это будет работать. Однако обычно лучше выделить плоскости усеченного конуса и вычислить расстояния до них. Вы сказали, что «скорость не имеет большого значения», но в конце концов вы можете обнаружить, что это так. В конце концов, отбраковку усеченной пирамиды делают, чтобы ускорить процесс.
Умножение вершины на матрицу требует эквивалента 4-точечного произведения, поэтому вам потребуется эквивалент 32-точечного произведения, чтобы проверить все 8 углов. Вычисление расстояния от точки до плоскости требует скалярного произведения и сложения, что несколько эффективнее в худшем случае и намного эффективнее в среднем (поскольку вы часто можете отбросить объект после отсечения одной или двух плоскостей, и не более трех). Существует ряд оптимизаций плоскостей отсечения, которые используют временную когерентность, и я не буду вдаваться в подробности.
Кроме того, вы можете заранее выполнить грубую отбраковку, рассчитав расстояние от центральной точки до плоскости и проверив, больше ли оно радиуса ограничивающей рамки. Это будет очень дешево отбраковывать объекты, которые явно находятся «в» или «вне». Или, в качестве альтернативы, вы можете сравнить точечный продукт вашего вектора обзора с косинусом вашего значения поля зрения плюс некоторое «заполнение» (или, альтернативно, просто посмотреть, положительно ли оно) в качестве первой сверхгрубой проверки. Как вы помните, скалярное произведение двух векторов говорит вам, насколько они указывают в одном и том же направлении. Что-то, что имеет отрицательное скалярное произведение с вашим вектором обзора, безусловно, является тем, что вы можете безопасно отбросить, потому что оно позади вас.