Partición binaria del espacio

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 2 de agosto de 2021; la verificación requiere 1 edición .

La partición del espacio binario es un  método de partición recursiva del espacio euclidiano en conjuntos convexos e hiperplanos . Como resultado, los objetos se representan como una estructura de datos denominada árbol BSP .

El árbol BSP se utiliza para realizar eficientemente las siguientes operaciones en gráficos 3D por computadora :

Los árboles BSP fueron utilizados por primera vez por LucasArts a principios de los años 80. Ganaron popularidad entre los desarrolladores gracias a id Software , que desarrolló los motores Doom ( 1993 ) y Quake ( 1996 ).

Resumen

En un árbol BSP, cada nodo está asociado con una línea o plano de división en el espacio 2D o 3D, respectivamente. En este caso, todos los objetos que se encuentran en la parte frontal del plano pertenecen al subárbol frontal, y todos los objetos que se encuentran en la parte posterior del plano pertenecen al subárbol posterior. Para determinar si un objeto pertenece al anverso o al reverso de una línea o plano de división, es necesario examinar la posición de cada uno de sus puntos. La posición de un punto con respecto al plano está determinada por el producto escalar de la normal del plano y las coordenadas del punto en coordenadas homogéneas . Tres casos son posibles:

  1. El producto escalar es mayor que 0: el punto se encuentra en el lado frontal del plano;
  2. El producto escalar es igual a 0: el punto se encuentra en el plano;
  3. El producto escalar es menor que 0: el punto se encuentra en la parte posterior del plano.

Si para todos los puntos del objeto el producto escalar es mayor que 0, entonces pertenece al subárbol frontal. Si para todos los puntos del objeto el producto escalar es menor que 0, entonces pertenece al subárbol inverso. Si para todos los puntos de un objeto el producto escalar es igual a 0, entonces no importa a qué subárbol pertenezca. Si los productos escalares de los puntos de un objeto tienen un signo diferente, el plano de división lo corta, de modo que los objetos resultantes se encuentran solo en el frente o solo en el reverso. Para cada subnodo del árbol BSP , la declaración anterior es verdadera, con la excepción de que solo aquellos objetos que pertenecen al lado frontal o posterior del plano de división del nodo principal están sujetos a consideración.

Construyendo un árbol

La definición anterior solo describe las propiedades de un árbol BSP , no dice cómo construirlo. Como regla general, un árbol BSP se construye para un conjunto de segmentos en un plano o polígonos en el espacio, que representan una determinada figura o escena. Considere el algoritmo para construir un árbol BSP para un conjunto de polígonos en el espacio:

  1. Si el conjunto de polígonos dado está vacío, termine el algoritmo;
  2. Para un conjunto dado de polígonos, elija un plano de división S;
  3. Cortar todos los polígonos que se cruzan con S;
  4. Asigne todos los polígonos ubicados en el lado frontal de S al subárbol frontal F, y todos los polígonos ubicados en el lado posterior de S al subárbol posterior B;
  5. Ejecute el algoritmo recursivamente para el conjunto de polígonos del subárbol frontal F;
  6. Ejecute el algoritmo recursivamente para el conjunto de polígonos del subárbol inverso B.

Elección del plano de división

El plano de división se elige de tal manera que equilibre el árbol, es decir, de modo que el número de polígonos en los subárboles delantero y trasero sea aproximadamente el mismo:

min(|N(Fi) - N(Bi)|)

donde N(Fi) es el número de polígonos en el lado frontal de algún plano de división i, N(Bi) es el número de polígonos en el lado posterior del plano de división i.

Aplicación

Clasificación de objetos en orden de distancia desde el observador

Al clasificar objetos en orden de eliminación del observador, utilizando el árbol BSP, se examinan las posiciones relativas del vector y el punto de observación ( POV ) y las normales de los planos de ruptura. Si la normal del plano de división y el vector de observación están codirigidos , entonces el subárbol frontal está más alejado del observador que el inverso; de lo contrario, el subárbol inverso está más alejado del observador que el frontal. En este caso, si el plano de división está detrás del observador, es posible que el propio plano, así como el subárbol frontal o posterior, no sean completamente visibles. El algoritmo recursivo para ordenar polígonos usando un árbol BSP es el siguiente:

Procedimiento BypassNode(Nodo) Si el nodo <> NULLPointer Si los vectores están codirigidos (vector de observación, nodo.Normal de SplitPlane) Si DotProduct(ObservationPoint, Node.Normal of SplitPlane) >= 0 // El plano está detrás del observador, el observador solo ve el subárbol frontal TraverseNode(Node.FrontSubtree); De lo contrario // El avión está frente al observador, // el subárbol delantero está más lejos que el subárbol trasero TraverseNode(Node.FrontSubtree); AddPolygonToDisplayList(Node.Polygon); TraverseNode(Nodo.ReverseSubtree); Terminara si; De lo contrario Si DotProduct(ObservationPoint, Node.Normal of SplitPlane) >= 0 // El avión está frente al observador, // el subárbol trasero está más lejos que el subárbol delantero TraverseNode(Nodo.ReverseSubtree); AddPolygonToDisplayList(Node.Polygon); TraverseNode(Node.FrontSubtree); De lo contrario // El avión está detrás del observador, el observador solo ve el subárbol inverso TraverseNode(Nodo.ReverseSubtree); Terminara si; Terminara si; Terminara si; Final;

Este algoritmo se puede optimizar si tenemos en cuenta que para un determinado conjunto de polígonos el árbol tiene una estructura degenerada, en el caso de que para cada polígono de este conjunto todos los polígonos restantes se encuentren solo en el frente o solo en el reverso. Esto es exactamente lo que hizo John Carmack en el motor de DOOM . .

El algoritmo para acelerar de recursivo se puede convertir a iterativo.

Recorte de superficies invisibles

El recorte de superficies invisibles se implementa introduciendo información adicional en el árbol BSP , como marcos (cuadros delimitadores, esferas delimitadoras). Los marcos  son rectángulos o paralelepípedos, círculos o esferas que limitan el área donde se ubican los polígonos de un determinado subárbol. Por lo tanto, cada nodo tiene dos marcos. Se garantiza que el subárbol es invisible a menos que la pirámide visual se cruce con el objeto delimitador. Lo opuesto no es verdad. Sin embargo, una declaración directa es suficiente para cortar el procesamiento de un número significativo de objetos.

La elección de objetos geométricos que representan marcos proviene de la simplicidad del algoritmo para verificar la intersección de la pirámide visual con el marco.

Encontrar colisiones

Al buscar colisiones, el árbol BSP se usa para encontrar el plano más cercano al objeto. La mayoría de las veces, los límites de un objeto vienen dados por una esfera (o círculo) delimitante para simplificar los cálculos. El árbol BSP se recorre desde la raíz hasta el plano más cercano al objeto. En este caso, si no se detectan intersecciones de la esfera delimitadora con ningún plano, entonces no hay colisión; de lo contrario, la hay.

Ejemplo:

Procedimiento del buscador de colisiones (nodo, objeto) Si el nodo <> NULLPointer Si Distancia(Nudo.Plano, Objeto.BoundingSphereCenter) > Objeto.BoundingSphereRadius Si DotProduct(Object.BoundingSphereCenter, SplitPlaneNode.Normal) >= 0 // El objeto está en el lado frontal del plano de rotura, // atravesar solo el subárbol frontal FindCollision(Node.FrontSubtree, Object); De lo contrario // El objeto está en la parte posterior del plano de división, // atravesar solo el subárbol inverso FindCollision(Node.ReverseSubtree, Object); Terminara si; De lo contrario El retorno es colisión; Terminara si; De lo contrario retorno sin colisión; Terminara si; Final;

El algoritmo para acelerar de recursivo se puede convertir a iterativo.

Literatura

Enlaces