实验5 OpenGL模型视图变换

https://blog.youkuaiyun.com/wpxu08/article/details/70208361

#include <GL/glut.h>

#include <stdlib.h>

static int year = 0, day = 0;

void init(void)

{

	glClearColor (0.0, 0.0, 0.0, 0.0);

	glShadeModel (GL_FLAT);

}

void display(void)

{

	glClear (GL_COLOR_BUFFER_BIT);

	glColor3f (1.0, 1.0, 1.0);

	glPushMatrix();


	glutWireSphere(1.0, 20, 16); /* draw sun */

	glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);

	glTranslatef (2.0, 0.0, 0.0);

	glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);

	glutWireSphere(0.2, 10, 8); /* draw smaller planet */

	glPopMatrix();

	glutSwapBuffers();

}

void reshape (int w, int h)

{

	glViewport (0, 0, (GLsizei) w, (GLsizei) h);

	glMatrixMode (GL_PROJECTION);

	glLoadIdentity ();

	gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);

	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();

	gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

}

void keyboard (unsigned char key, int x, int y)

{

	switch (key) {

	case 'd':

		day = (day + 10) % 360;

		glutPostRedisplay();

		break;

	case 'D':

		day = (day - 10) % 360;

		glutPostRedisplay();

		break;

	case 'y':

		year = (year + 5) % 360;

		glutPostRedisplay();

		break;

	case 'Y':

		year = (year - 5) % 360;

		glutPostRedisplay();

		break;

	case 27:

		exit(0);

		break;

	default:

		break;

	}

}

int main(int argc, char** argv)

{

	glutInit(&argc, argv);
	
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);

	glutInitWindowSize (500, 500);

	glutInitWindowPosition (100, 100);

	glutCreateWindow (argv[0]);

	init ();

	glutDisplayFunc(display);

	glutReshapeFunc(reshape);

	glutKeyboardFunc(keyboard);

	glutMainLoop();

	return 0;
}

#include <gl/glut.h>

float fEarth = 2.0f; //地球绕太阳的旋转角度

float fMoon = 24.0f; //月球绕地球的旋转角度

void Init()

{

glEnable(GL_DEPTH_TEST); //启用深度测试

glClearColor(0.0f, 0.0f, 0.0f, 0.8f); //背景为黑色

}

void Reshape(int w, int h)

{

if (0 == h)

h = 1;

glViewport(0, 0, w, h); //设置视区尺寸

glMatrixMode(GL_PROJECTION); //指定当前操作投影矩阵堆栈

glLoadIdentity(); //重置投影矩阵

//指定透视投影的观察空间

gluPerspective(45.0f, (float)w / (float)h, 1.0f, 1000.0f);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

void Display(void)

{

//清除颜色和深度缓冲区

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW); //指定当前操作模型视图矩阵堆栈

glLoadIdentity(); //重置模型视图矩阵

glTranslatef(0.0f, 0.0f, -500.0f); //将图形沿z轴负向移动

glColor3f(1.0f, 0.0f, 0.0f); //画太阳

glutSolidSphere(50.0f, 20, 20);

glColor3f(0.0f, 0.0f, 1.0f);

glRotatef(23.27,0.0,0.0,1.0); //地球与太阳的黄赤交角

glRotatef(fEarth, 0.0f, 1.0f, 0.0f);

glTranslatef(200.0f, 0.0f, 0.0f);

glutSolidSphere(20.0f, 20, 20); //画地球

glPopMatrix();

glPopMatrix();

glRotatef(6.0f, 1.0f, 1.0f, 1.0f);

glRotatef(fMoon, 0.0f, 1.0f, 0.0f);

glColor3f(1.0f, 1.0f, 0.0f);

glTranslatef(30.0f, 0.0f, 0.0f);

glutSolidSphere(5.0f, 20, 20); //画月球

glLoadIdentity();

glFlush();

glutSwapBuffers();

}

void myIdle(void) //在空闲时调用,达到动画效果

{

fEarth += 0.03f; //增加旋转步长,产生动画效果

if (fEarth > 360.0f)

fEarth = 2.0f;

fMoon += 0.24f;

if (fMoon > 360.0f)

fMoon = 24.0f;

Display();

}

int main(int argc, char *argv[])

{

glutInit(&argc, argv);

//窗口使用RGB颜色,双缓存和深度缓存

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

glutInitWindowPosition(100,100);

glutInitWindowSize(600, 400);

glutCreateWindow("太阳系动画");

glutReshapeFunc(Reshape);

glutDisplayFunc(Display);

glutIdleFunc(&myIdle);

Init();

glutMainLoop();

return 0;

}

 

### OpenGL模型视图变换高级教程 在OpenGL中,模型视图变换是三维图形渲染的核心部分之一。它涉及将三维模型从世界坐标系转换到观察坐标系,并最终投影到屏幕上的过程。以下内容详细介绍了如何进行模型视图变换的高级实验操作。 #### 1. 模型变换矩阵 模型变换矩阵用于将物体从局部坐标系(对象坐标系)转换到世界坐标系。常见的模型变换包括平移、旋转和缩放。这些变换可以通过组合多个变换矩阵来实现。例如,一个物体可以先进行缩放,然后旋转,最后平移到指定位置[^1]。 ```python import numpy as np def create_model_matrix(translation, rotation, scale): # 创建平移矩阵 translation_matrix = np.array([ [1, 0, 0, translation[0]], [0, 1, 0, translation[1]], [0, 0, 1, translation[2]], [0, 0, 0, 1] ]) # 创建旋转矩阵(假设绕Z轴旋转) angle = np.radians(rotation) rotation_matrix = np.array([ [np.cos(angle), -np.sin(angle), 0, 0], [np.sin(angle), np.cos(angle), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) # 创建缩放矩阵 scale_matrix = np.array([ [scale[0], 0, 0, 0], [0, scale[1], 0, 0], [0, 0, scale[2], 0], [0, 0, 0, 1] ]) # 组合所有变换矩阵 model_matrix = translation_matrix @ rotation_matrix @ scale_matrix return model_matrix ``` #### 2. 视图变换矩阵 视图变换矩阵用于将世界坐标系中的物体转换到观察坐标系。通常通过设置相机的位置、目标点和上方向向量来定义观察矩阵。在OpenGL中,可以使用`glm::lookAt`函数(如果使用GLM库)或手动计算观察矩阵[^1]。 ```python def create_view_matrix(camera_position, target_position, up_vector): # 计算前向向量 forward = (target_position - camera_position).normalized() # 计算右侧向量 right = up_vector.cross(forward).normalized() # 计算新的上方向向量 new_up = forward.cross(right) # 构建观察矩阵 view_matrix = np.array([ [right[0], right[1], right[2], -camera_position.dot(right)], [new_up[0], new_up[1], new_up[2], -camera_position.dot(new_up)], [-forward[0], -forward[1], -forward[2], -camera_position.dot(-forward)], [0, 0, 0, 1] ]) return view_matrix ``` #### 3. 投影变换矩阵 投影变换矩阵将观察坐标系中的物体投影到规范化设备坐标(NDC)空间。有两种主要的投影方式:正交投影和透视投影。正交投影适用于二维场景,而透视投影更接近人眼的视觉效果。 ```python def create_perspective_projection_matrix(fov, aspect_ratio, near_plane, far_plane): fov_rad = np.radians(fov) f = 1 / np.tan(fov_rad / 2) projection_matrix = np.array([ [f / aspect_ratio, 0, 0, 0], [0, f, 0, 0], [0, 0, (far_plane + near_plane) / (near_plane - far_plane), (2 * far_plane * near_plane) / (near_plane - far_plane)], [0, 0, -1, 0] ]) return projection_matrix ``` #### 4. 综合应用 在实际应用中,需要将模型变换矩阵、视图变换矩阵和投影变换矩阵组合起来,形成最终的变换矩阵。这个矩阵可以传递给着色器程序,用于顶点变换[^1]。 ```python def create_mvp_matrix(model_matrix, view_matrix, projection_matrix): mvp_matrix = projection_matrix @ view_matrix @ model_matrix return mvp_matrix ``` #### 5. 实验建议 为了更好地理解模型视图变换,可以尝试以下实验: - 调整模型变换矩阵中的参数,观察物体的移动、旋转和缩放效果。 - 改变视图变换矩阵中的相机位置和目标点,观察场景的变化。 - 使用不同的投影矩阵(正交或透视),比较两者的差异。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值