[Análisis detallado del motor de juego sobrecargado] Ver el cálculo de la matriz de proyección y la cámara

Este artículo solo enumera las fórmulas y no realiza derivaciones específicas.

OpenGL en sí no tiene el concepto de cámara, pero para las necesidades del producto y la conveniencia de la programación, generalmente abstraemos un componente de cámara. La cámara es similar al ojo humano y puede establecer un sistema de coordenadas local. La posición de la cámara es el origen de las coordenadas, la dirección hacia adelante de la cámara es la dirección en la que mira la cámara y el sistema de coordenadas local se puede establecer dando el eje hacia arriba en la dirección. Luego, el objeto en el sistema de coordenadas mundial se puede transformar en el sistema de coordenadas de la cámara a través de una matriz, que se llama matriz de vista. Al cambiar el sistema de coordenadas local de la cámara, se puede producir el efecto de itinerancia de escena.
Imágenes de Internet

1. Ver fórmula matricial

La matriz de vista transforma las coordenadas del objeto desde las coordenadas del espacio mundial al sistema de coordenadas local de la cámara. Calcular la matriz de vista requiere dar la posición del ojo de la cámara \mathbf{eye}ojo , posición de enfoqueen \mathbf{to}a , el vector YYen el plano donde se encuentran Adelante y ArribaY , tenga en cuenta que Y no necesita ser perpendicular a Adelante, podemos obtener el sistema de coordenadas local de la cámara a través del producto cruzado:
fwd = normalizar (eye − to) derecha = normalizar (Y × fwd) arriba = normalizar (fwd × derecha ) \begin{aligned } & \mathbf{fwd} = normalizar(\mathbf{eye}-\mathbf{to}) \\& \mathbf{right}=normalize(Y\times \mathbf{fwd}) \\ & \mathbf{arriba} = normalizar(\mathbf{fwd}\times\mathbf{right})\end{aligned}adelante=n o ma l i ze ( ojoa )bien=n o ma l i ze ( Y×adelante )arriba=n o ma l i ze ( adelante)×correcto )
Insertar descripción de la imagen aquí
La matriz LookAt es igual a:

M ira A t = [ sidexsidesides − side ⋅ eyeupxupyupz − up ⋅ eyefwdxfwdyfwdz − fwd ⋅ eye 0 0 0 1 ] LookAt= \begin{bmatrix} \mathbf{page}_x & \mathbf{page}_y & \mathbf{page} ; _z & -\mathbf{page}\cdot \mathbf{eye}\\ \mathbf{up}_x & \mathbf{up}_y & \mathbf{up}_z & -\mathbf{up}\cdot \mathbf{ ojo }\\ \mathbf{fwd}_x & \mathbf{fwd}_y & \mathbf{fwd}_z & -\mathbf{fwd}\cdot \mathbf{eye}\\ 0& 0 & 0 & 1 \end{bmatrix }Míralo _ _ _ _= ladoxarribaxadelantex0ladoyarribayadelantey0ladozarribazadelantez0ladoojoarribaojoadelanteojo1

Código para calcular la matriz de vista en Sobrecarga:

OvMaths::FMatrix4 OvMaths::FMatrix4::CreateView(const float p_eyeX, const float p_eyeY, const float p_eyeZ, const float p_lookX, const float p_lookY, const float p_lookZ, const float p_upX, const float p_upY, const float p_upZ)
{
    
    
	const OvMaths::FVector3 eye(p_eyeX, p_eyeY, p_eyeZ); // 摄像机位置
	const OvMaths::FVector3 look(p_lookX, p_lookY, p_lookZ); // 摄像机焦点
	const OvMaths::FVector3 up(p_upX, p_upY, p_upZ); // 摄像机up

	const OvMaths::FVector3 forward(eye - look); // 摄像机的Z轴
	FVector3::Normalize(forward);
	
	// cross得到right轴
	const OvMaths::FVector3 upXForward(OvMaths::FVector3::Cross(up, forward));
	FVector3::Normalize(upXForward);
	
	// cross得到Up轴,等价于Y轴
	const OvMaths::FVector3 v(OvMaths::FVector3::Cross(forward, upXForward));

	OvMaths::FMatrix4 View;

	View.data[0] = upXForward.x;
	View.data[1] = upXForward.y;
	View.data[2] = upXForward.z;
	View.data[3] = -OvMaths::FVector3::Dot(eye, upXForward);
	
	View.data[4] = v.x;
	View.data[5] = v.y;
	View.data[6] = v.z;
	View.data[7] = -OvMaths::FVector3::Dot(eye, v);

	View.data[8] = forward.x;
	View.data[9] = forward.y;
	View.data[10] = forward.z;
	View.data[11] = -OvMaths::FVector3::Dot(eye, forward);

	return View;
}

2. Matriz de proyección

La proyección consiste en proyectar la luz del objeto en el plano cercano de la cámara, convirtiendo el objeto 3D en una imagen 2D y convertir el espacio de coordenadas de la cámara en el espacio de la pantalla, similar al proceso de exposición de una cámara real. Hay dos tipos de proyección: proyección en perspectiva y proyección ortogonal.
Proyección en perspectiva : intenta hacer que las imágenes 2D parezcan 3D imitando la forma en que vemos el mundo real a través del concepto de perspectiva. Los objetos son grandes cerca y pequeños lejos, por lo que algunas líneas paralelas en el espacio 3D ya no parecen paralelas.
Proyección ortográfica : a diferencia de la proyección en perspectiva, los objetos en el tronco de visualización se proyectan directamente sin ningún ajuste debido a su distancia a la cámara. La proyección ortográfica se utiliza ampliamente en el software CAD.

Insertar descripción de la imagen aquí

透视投影矩阵:
[ 2 Z cerca R − L 0 R + LR − L 0 0 2 Z cerca T − BT + BT − B 0 0 0 − Z lejos + Z cerca Z lejos − Z cerca − 2 Z cerca Z lejos Z lejos − Z cerca 0 0 − 1 0 ] \begin{bmatrix} \frac{2Z_{near}}{RL} & 0 & \frac{R+L}{RL} & 0\\ 0 & \frac{2Z_{ cerca}}{TB} & \frac{T+B}{TB} & 0\\ 0 & 0 & -\frac{Z_{lejos}+Z_{cerca}}{Z_{lejos}-Z_{cerca}} & -\frac{2Z_{cerca}Z_{lejos}}{Z_{lejos}-Z_{cerca}} \\ 0 & 0 & -1 & 0 \end{bmatrix} R - L2Z_ _n e a r0000T - B2Z_ _n e a r00R - LR + LT - BT + Bzf a r−Z _n e a rzf a r+ Zn e a r 100zf a r−Z _n e a r2Z_ _n e a rzf a r0
Entre ellos:
     Z cerca y Z lejos son las distancias desde la posición de la cámara a los planos cercano y lejano, Z_cerca y Z_lejos son las distancias desde la posición de la cámara a los planos cercano y lejano.zn e a rZf a rEs la distancia desde la posición de la cámara al plano cercano y al plano lejano
     Coordenadas R, L – X de los límites izquierdo y derecho del plano de proyección Coordenadas
     T, B – Y de los límites superior e inferior del plano de proyección

El código para calcular la matriz de proyección en perspectiva en Overload:

OvMaths::FMatrix4 OvMaths::FMatrix4::CreateFrustum(const float p_left, const float p_right, const float p_bottom, const float p_top, const float p_zNear, const float p_zFar)
{
    
    
	const float maxView = 2.0f * p_zNear;
	const float width = p_right - p_left;
	const float height = p_top - p_bottom;
	const float zRange = p_zFar - p_zNear;

	FMatrix4 Frustum;

	Frustum.data[0] = maxView / width;
	Frustum.data[5] = maxView / height;
	Frustum.data[2] = (p_right + p_left) / width;
	Frustum.data[6] = (p_top + p_bottom) / height;
	Frustum.data[10] = (-p_zFar - p_zNear) / zRange;
	Frustum.data[14] = -1.0f;
	Frustum.data[11] = (-maxView * p_zFar) / zRange;
	Frustum.data[15] = 0.0f;

	return Frustum;
}

正投影矩阵:
[ 2 R − L 0 0 − R + LR − L 0 2 T − B 0 − T + BT − B 0 0 1 Z lejos − Z cerca − Z cerca Z lejos − Z cerca 0 0 0 1 ] \begin{bmatrix} \frac{2}{RL} & 0 & 0 & -\frac{R+L}{RL} \\ 0 & \frac{2}{TB} & 0 & -\frac{T+ B}{TB} \\ 0 & 0 & \frac{1}{Z_{lejos}-Z_{cerca}} & -\frac{Z_{cerca}}{Z_{lejos}-Z_{cerca}} \\ 0 y 0 y 0 y 1 \end{bmatrix} R - L20000T - B20000zf a r−Z _n e a r10R - LR + LT - BT + Bzf a r−Z _n e a rzn e a r1

El código para calcular la matriz de proyección ortográfica en Overload:

OvMaths::FMatrix4 OvMaths::FMatrix4::CreateOrthographic(const float p_size, const float p_aspectRatio, const float p_zNear, const float p_zFar)
{
    
    
    auto ortho = OvMaths::FMatrix4::Identity;

    const auto right = p_size * p_aspectRatio;
    const auto left = -right;

    const auto top = p_size;
    const auto bottom = -top;

    ortho(0, 0) = 2.0f / (right - left);
    ortho(1, 1) = 2.0f / (top - bottom);
    ortho(2, 2) = -2.0f / (p_zFar - p_zNear);
    ortho(0, 3) = -(right + left) / (right - left);
    ortho(1, 3) = -(top + bottom) / (top - bottom);
    ortho(2, 3) = -(p_zFar + p_zNear) / (p_zFar - p_zNear);
    ortho(3, 3) = 1.0f;

    return ortho;
}

3. Embalaje de la cámara

La clase de cámara en Overload es relativamente simple y encapsula principalmente los dos cálculos matriciales anteriores. Cada vez, debe pasar el cuaternión de posición y rotación de la cámara, calcular la matriz de proyección de la vista y guardarla en su propio campo. El código es relativamente simple y no se volverá a analizar.

Supongo que te gusta

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