[Análisis detallado del motor de juego de sobrecarga] Extracción de la vista frustum de la matriz de proyección de la vista y encapsulación de la vista frustum por sobrecarga

El código overload contiene un código interesante que puede deducir inversamente el tronco de la cámara a partir de la matriz de proyección de la vista. Este artículo analizará el principio.

1. Ecuaciones del avión

El tronco de observación está representado por un plano, así que veamos primero la expresión matemática del plano.
La ecuación del plano se puede definir por su normal N = (A, B, C) y un punto Q = (x0, y0, z0), y su forma es: A ( x − x 0 ) + B ( y − y
0 ) + C ( z − z 0 ) = 0 A(x-x_{0})+B(y-y_{0})+C(z-z_{0})=0un ( xX0)+B ( yy0)+C ( zz0)=0          disposición se convierte en:A x + B y + C z + D = 0 Ax+By+Cz+D=0una x+por y+C z+D=0 , 其中D = − A x 0 − B y 0 − C z 0 D=−Ax_{0}−By_{0}−Cz_{0}D=A x0por y0C z0
         La ecuación se puede normalizar aún más:
AA 2 + B 2 + C 2 x + BA 2 + B 2 + C 2 y + CA 2 + B 2 + C 2 z + DA 2 + B 2 + C 2 = 0 \ frac{ A}{\sqrt{A^{2}+B^{2}+C^{2} } } x + \frac{B}{\sqrt{A^{2}+B^{2}+ C^ {2} } }y+\frac{C}{\sqrt{A^{2}+B^{2}+C^{2} } }z+\frac{D}{\sqrt{A^{2 }+ B^{2}+C^{2} } } = 0A2+B2+C2 unX+A2+B2+C2 By+A2+B2+C2 Cz+A2+B2+C2 re=0 se escribe en el formato generalax + by + cz + d = 0 ax+by+cz+d=0una x+por _+cz+d=0
那么点p = ( x 1 , y 1 , z 1 ) p=(x_{1}, y_{1}, z_{1})pag=( x1,y1,z1) al plano es:
D = ax 1 + by 1 + cz 1 + d D=ax_{1}+by_{1}+cz_{1}+dD=una x1+por _1+c z1+d
Un plano dividirá el espacio en dos semiespacios (medio espacio). El espacio con más normales se llama medio espacio positivo (medio espacio positivo), y el espacio con normales que se desvían de él se llama medio espacio negativo (medio espacio negativo). La posición relativa del punto se puede juzgar según el signo de D:

  • D < 0, el punto está ubicado en el semiespacio inverso
  • D = 0, el punto se encuentra en el plano.
  • D > 0, el punto está ubicado en el semiespacio positivo

Esta propiedad se puede utilizar para determinar si un punto está dentro del tronco de visualización.

2. Vista frustrada OpenGL

El tronco de visualización es el área que la cámara puede ver. Sólo se pueden ver los objetos dentro del tronco de visualización. Consiste en el plano cercano cercano, el plano lejano lejano y las cuatro superficies circundantes superior, inferior, izquierda y derecha, formando un área truncada.
Insertar descripción de la imagen aquí
Sin embargo, al construir un tronco de visualización, las ecuaciones de los seis planos generalmente no se ingresan directamente, sino que comúnmente se usa otro conjunto de parámetros que son más intuitivos y fáciles de entender:

  1. fov: el ángulo vertical del tronco de visión
  2. Cerca: la distancia del plano cercano del tronco de visualización.
  3. Lejano: distancia del plano lejano del tronco de visualización
  4. aspecto: la relación de aspecto de la ventana gráfica de la cámara

El significado específico se muestra en la siguiente figura:
Insertar descripción de la imagen aquí

3. Encapsulación de la vista frustum por sobrecarga

La encapsulación de Overload del frustum de visualización se encuentra en los archivos Frustum.h y Frustum.cpp. Veamos primero su definición:

class Frustum
{
    
    
public:
	/**
	* 根据视图投影矩阵提取视锥体
	* @param p_viewProjection
	*/ 
	void CalculateFrustum(const OvMaths::FMatrix4& _viewProjection);
	/**
	* 判断点是不是在视锥体内
	* @param p_x
	* @param p_y
	* @param p_z
	*/
	bool PointInFrustum(float p_x, float p_y, float _z) const;
	/**
	* 判断球是不是在视锥体内
	* @param p_x
	* @param p_y
	* @param p_z
	* @param p_radius
	*/
	bool SphereInFrustum(float p_x, float p_y, loat p_z, float p_radius) const;
	/**
	* 判断立方体是不是在视锥体内
	* @param p_x
	* @param p_y
	* @param p_z
	* @param p_size
	*/
	bool CubeInFrustum(float p_x, float p_y, float _z, float p_size) const;
	/**
	* 判断包围球是不是在视锥体内
	* @param p_boundingSphere
	* @param p_transform
	*/
	bool BoundingSphereInFrustum(const vRendering::Geometry::BoundingSphere& _boundingSphere, const OvMaths::FTransform& _transform) const;
	/**
	* 返回近平面
	*/
	std::array<float, 4> GetNearPlane() const;
	/**
	* 返回远平面
	*/
	std::array<float, 4> GetFarPlane() const;
private:
	float m_frustum[6][4];  // 6个平面的方程参数
};

m_frustum guarda los parámetros de ecuación de 6 planos y, para mejorar la comodidad de operación, define dos enumeraciones como índices:

enum FrustumSide
{
    
    
	RIGHT = 0,		// The RIGHT side of the frustum
	LEFT = 1,		// The LEFT	 side of the frustum
	BOTTOM = 2,		// The BOTTOM side of the frustum
	TOP = 3,		// The TOP side of the frustum
	BACK = 4,		// The BACK	side of the frustum
	FRONT = 5		// The FRONT side of the frustum
};

// 平面方程的参数索引
enum PlaneData
{
    
    
	A = 0,				// The X value of the plane's normal
	B = 1,				// The Y value of the plane's normal
	C = 2,				// The Z value of the plane's normal
	D = 3				// The distance the plane is from the origin
};

La implementación específica de la función está en el archivo Frustum.cpp. Primero veamos el punto de juicio más básico si está dentro de la vista frustum:

bool OvRendering::Data::Frustum::PointInFrustum(float x, float y, float z) const
{
    
    
	for (int i = 0; i < 6; i++)
	{
    
    
		if (m_frustum[i][A] * x + m_frustum[i][B] * y + m_frustum[i][C] * z + m_frustum[i][D] <= 0)
		{
    
    
			return false;
		}
	}
	return true;
}

Las normales de las caras que definen la vista frustum están todas orientadas hacia afuera. Si el punto está dentro de la vista frustum, las distancias desde el punto hasta las seis caras deben ser menores que 0. Para determinar aún más si la esfera está completamente dentro del tronco de observación, la distancia debe ser menor que el número negativo del radio.
Finalmente, analicemos CalculateFrustum, que construye a la inversa una vista frustum basada en una matriz de proyección de vista. Puede consultar la fórmula específica en este artículo, que es muy detallada: Extracción rápida de planos de visualización Frustum de la matriz de proyección de visión mundial No
hay
  nada Hay mucho que decir sobre el código en sí, no es más que la traducción de una fórmula.

Supongo que te gusta

Origin blog.csdn.net/loveoobaby/article/details/133657578
Recomendado
Clasificación