实验8 OpenGL太阳系动画

1.实验目的:

  • 熟悉颜色缓存、深度缓存、模板缓存、累计缓存的内容,掌握缓存清除的方法;
  • 建立太阳、地球、月亮的运动模型;
  • 利用双缓存技术,用动画方式显示模型,加深读者对几何变换、投影变换以及观察变换的理解,并提高利用图形软件包绘制图形的能力。

2.实验内容:

  模拟简单的太阳系,如图A.8所示。太阳在中心,地球每365天绕太阳转一周,月球每年绕地球转12周。另外,地球每天24个小时绕它自己的轴旋转。
在这里插入图片描述

图A.8 太阳系动画

3.实验原理:

(1)主要用三维平移变换、旋转变换实现太阳、地球、月亮的相对运动。

  本节实验绘制了一个简单的太阳系。为了编写这个程序,需要使用glRtate函数让这颗行星绕太阳旋转,并且绕自身的轴旋转。还需要使用glTranslate函数让这颗行星远离太阳系原点,移动到自己的轨道上。可以在glutWireSphere函数中使用适当的参数,在绘制两个球体时指定球体的大小。
  为了绘制这个太阳系,首先需要设置一个投影变换和一个视图变换。在这个例子中,可以使用glutPerspective函数和gluLookAt函数。
  绘制太阳比较简单,因为它位于全局固定坐标系统的原点,也就是球体函数进行绘图的位置。因此,绘制太阳时并不需要移动,可以使用glRotate*函数绕一个任意的轴旋转。绘制一颗绕太阳旋转的行星要求进行几次模型变换。这颗行星需要每天绕自己的轴旋转一周,每年沿着自己的轨道绕太阳旋转一周。
  为了确定模型变换的顺序,可以从局部坐标系统的角度考虑。首先,调用初始的glRotate函数对局部坐标系统进行旋转,这个局部坐标系统最初与全局固定坐标系统是一致的。接着,可以调用glTranslate函数把局部坐标系统移动到行星轨道上的一个位置。移动的距离应该等于轨道的半径。因此,第一个glRotate函数实际上确定了这颗行星从什么地方开始绕太阳旋转(或者说,从一年的什么时候开始)。
  第二次调用glRotate函数使局部坐标轴进行旋转,因此确定了这颗行星在一天中的时间。当调用了这些函数变换之后,就可以绘制这颗行星了。

(2)利用双缓存技术实现动画效果。

  双缓存技术能在一个屏幕之外的缓冲区内进行渲染,再用交换命令把图形放到屏幕上。双缓存技术的主要用途是:
①有些复杂图形绘制时间较长,但不需要显示绘制图形的所有步骤,只有整幅图像绘制完之后,才将其置于屏幕上;
②用于制作动画,动画中每一帧都再画面外缓冲区绘制,绘制完之后再交换到屏幕上。实际编程过程中,每个OpenGL支持的窗口系统都可以通过调用glutSwapBuffers()来实现前后缓冲区之间的交换。

4.实验代码:

#include <gl/glut.h>
float fEarth = 2.0f; //地球绕太阳的旋转角度
float fMoon = 24.0f; //月球绕地球的旋转角度
void myInit()
{
	glEnable(GL_DEPTH_TEST); //启用深度测试
	glClearColor(0.0f, 0.0f, 0.0f, 0.8f); //背景为黑色
}

void myReshape(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 myDisplay(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); //画地球

	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); //画月球
	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;
	myDisplay();
}

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(myReshape);
	glutDisplayFunc(myDisplay);
	glutIdleFunc(&myIdle);
	myInit();
	glutMainLoop();
	return 0;
}

5.实验提高

(1)让实验6的茶壶旋转;
(2)让实验7的机器人手臂不停旋转划圈。

React Hooks 是 React 16.8 中新增的特性,它可以让你在函数组件中使用 state、生命周期钩子等 React 特性。使用 Hooks 可以让你写出更简洁、可复用且易于测试的代码。 React Hooks 提供了一系列的 Hook 函数,包括 useState、useEffect、useContext、useReducer、useCallback、useMemo、useRef、useImperativeHandle、useLayoutEffect 和 useDebugValue。每个 Hook 都有特定的用途,可以帮助你处理不同的问题。 下面是 React Hooks 的一些常用 Hook 函数: 1. useState useState 是最常用的 Hook 之一,它可以让你在函数组件中使用 state。useState 接受一个初始状态值,并返回一个数组,数组的第一个值是当前 state 值,第二个值是更新 state 值的函数。 ``` const [count, setCount] = useState(0); ``` 2. useEffect useEffect 可以让你在组件渲染后执行一些副作用操作,比如订阅事件、异步请求数据等。useEffect 接受两个参数,第一个参数是一个回调函数,第二个参数是一个数组,用于控制 useEffect 的执行时机。 ``` useEffect(() => { // 这里可以执行副作用操作 }, [dependencies]); ``` 3. useContext useContext 可以让你在组件树中获取 context 的值。它接受一个 context 对象,并返回该 context 的当前值。 ``` const value = useContext(MyContext); ``` 4. useRef useRef 可以让你在组件之间共享一个可变的引用。它返回一个对象,该对象的 current 属性可以存储任何值,并在组件的生命周期中保持不变。 ``` const ref = useRef(initialValue); ref.current = value; ``` 5. useCallback useCallback 可以让你缓存一个函数,以避免在每次渲染时都创建一个新的函数实例。它接受一个回调函数和一个依赖数组,并返回一个 memoized 的回调函数。 ``` const memoizedCallback = useCallback(() => { // 这里是回调函数的逻辑 }, [dependencies]); ``` 6. useMemo useMemo 可以让你缓存一个计算结果,以避免在每次渲染时都重新计算。它接受一个计算函数和一个依赖数组,并返回一个 memoized 的计算结果。 ``` const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); ``` 以上就是 React Hooks 的一些常用 Hook 函数,它们可以帮助你更好地处理组件状态、副作用、上下文和性能优化等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图形空间

文章不错,赞赏鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值