【计算机图形学-11】OpenGL程序实例分析3——场景漫游 | 实现相机

本机将主要实现相机类.

Camera.h:

#ifndef _CAMERA_H_
#define _CAMERA_H_

#include "Angel.h"

class Camera
{
public:
	Camera();
	~Camera();

	mat4 lookAt(const vec4& eye, const vec4& at, const vec4& up);

	mat4 ortho(const GLfloat left, const GLfloat right,
		const GLfloat bottom, const GLfloat top,
		const GLfloat zNear, const GLfloat zFar);

	mat4 perspective(const GLfloat fovy, const GLfloat aspect,
		const GLfloat zNear, const GLfloat zFar);

	mat4 frustum(const GLfloat left, const GLfloat right,
		const GLfloat bottom, const GLfloat top,
		const GLfloat zNear, const GLfloat zFar);

	// 每次更改相机参数后更新一下相关的数值
	void updateCamera();
	// 处理相机的键盘操作
	void keyboard(unsigned char key, int x, int y);

	// 模视矩阵
	mat4 viewMatrix;
	mat4 projMatrix;

	// 相机位置参数
	float radius = 4.0;
	float rotateAngle = 0.0;
	float upAngle = 0.0;
	vec4 eye;
	vec4 at;
	vec4 up;

	// 投影参数
	#undef near
	#undef far
	float near = 0.1;
	float far = 100.0;
	// 透视投影参数
	float fov = 45.0;
	float aspect = 1.0;
	// 正交投影参数
	float scale = 1.5;

};
#endif

Camera.cpp:

#include "Camera.h"
# include <math.h>

Camera::Camera() { updateCamera(); };
Camera::~Camera() {};


mat4 Camera::lookAt(const vec4& eye, const vec4& at, const vec4& up)
{
	// 相机观察矩阵的计算
	vec4 vpn = eye - at;
	vec4 n = normalize(vpn);
	vec4 u = normalize(cross(up, n));
	vec4 v = normalize(cross(n, u));
	vec4 l1 = vec4(u.x, u.y, u.z, -eye.x * u.x - eye.y * u.y - eye.z * u.z);
	vec4 l2 = vec4(v.x, v.y, v.z, -eye.x * v.x - eye.y * v.y - eye.z * v.z);
	vec4 l3 = vec4(n.x, n.y, n.z, -eye.x * n.x - eye.y * n.y - eye.z * n.z);
	vec4 l4 = vec4(0, 0, 0, 1);
	mat4 c;
	c = mat4(
		l1, l2, l3, l4
	);
	return c;
}

mat4 Camera::ortho(const GLfloat left, const GLfloat right,
	const GLfloat bottom, const GLfloat top,
	const GLfloat zNear, const GLfloat zFar)
{
	// 正交投影矩阵的计算
	mat4 c;
	vec4 l1 = vec4(2/(right-left), 0, 0, -(right + left)/(right-left));
	vec4 l2 = vec4(0, 2/(top-bottom), 0, -(top + bottom)/(top-bottom));
	vec4 l3 = vec4(0, 0, -2/(zFar-zNear), -(zFar+zNear)/(zFar-zNear));
	vec4 l4 = vec4(0, 0, 0, 1);
	c = mat4(
		l1, l2, l3, l4
	);
	return c;
}

mat4 Camera::perspective(const GLfloat fovy, const GLfloat aspect,
	const GLfloat zNear, const GLfloat zFar)
{
	// 透视投影矩阵的计算
	mat4 c;
	GLfloat top = zNear * tan(fovy/2/180*M_PI);
	GLfloat right = top * aspect;
	vec4 l1 = vec4(zNear/right, 0, 0, 0);
	vec4 l2 = vec4(0, zNear/top, 0, 0);
	vec4 l3 = vec4(0,0, -(zFar+zNear)/(zFar-zNear), (-2*zFar*zNear)/(zFar-zNear));
	vec4 l4 = vec4(0,0,-1,0);
	c = mat4(
		l1, l2, l3, l4
	);
	return c;
}

mat4 Camera::frustum(const GLfloat left, const GLfloat right,
	const GLfloat bottom, const GLfloat top,
	const GLfloat zNear, const GLfloat zFar)
{
	// 任意视锥体矩阵
	mat4 c;
	vec4 l1 = vec4(2.0 * zNear / (right - left), 0, (right + left) / (right - left), 0);
	vec4 l2 = vec4(0, 2.0 * zNear / (top - bottom), (top + bottom) / (top - bottom), 0);
	vec4 l3 = vec4(0, 0, -(zFar + zNear) / (zFar - zNear), -2.0 * zFar * zNear / (zFar - zNear));
	vec4 l4 = vec4(0, 0, -1, 0);
	c = mat4(l1, l2, l3, l4);
	return c;
}


void Camera::updateCamera()
{
	// 设置相机位置和方向
	float eyex = 0;			// 根据rotateAngle和upAngle设置x
	float eyey = 0;			// 根据upAngle设置y
	float eyez = radius;	// 根据rotateAngle和upAngle设置z
	eyex = radius * cos(upAngle * M_PI / 180) * sin(rotateAngle * M_PI / 180);
	eyey = radius * sin(upAngle * M_PI / 180);
	eyez = radius * cos(upAngle * M_PI / 180) * cos(rotateAngle * M_PI / 180);
	eye = vec4(eyex, eyey, eyez, 1.0);
	at = vec4(0.0, 0.0, 0.0, 1.0);
	up = vec4(0.0, 1.0, 0.0, 0.0);
}

void Camera::keyboard(unsigned char key, int x, int y)
{

	// 键盘事件处理
	switch (key)
	{
		// 通过按键改变相机和投影的参数
	case 'x':
		rotateAngle += 5.0;
		break;
	case 'X':
		rotateAngle -= 5.0;
		break;

	case 'y':
		upAngle += 5.0;
		if (upAngle > 180)
			upAngle = 180;
		break;
	case 'Y':
		upAngle -= 5.0;
		if (upAngle < -180)
			upAngle = -180;
		break;

	case 'r':
		radius += 0.1;
		break;
	case 'R':
		radius -= 0.1;
		break;

	case 'f':
		fov += 5.0;
		break;
	case 'F':
		fov -= 5.0;
		break;

	case 'a':
		aspect += 0.1;
		break;
	case 'A':
		aspect -= 0.1;
		break;

	case 's':
		scale += 0.1;
		break;
	case 'S':
		scale -= 0.1;
		break;

		// 空格键初始化所有参数
	case ' ':
		radius = 4.0;
		rotateAngle = 0.0;
		upAngle = 0.0;
		fov = 45.0;
		aspect = 1.0;
		scale = 1.5;
		break;
	}
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值