manim进阶篇

您所在的位置:网站首页 画立体物品 manim进阶篇

manim进阶篇

2024-07-17 23:02| 来源: 网络整理| 查看: 265

前言

大家好,我是cigar666。距离写manim入门篇的相关教程已经快一年了。在这期间,我利用manim动画发了不少相关视频,不少其他大佬们也制作了许多非常amazing的作品。我们也有了自己的manim交流群(862671480),有了更多人学习和使用manim。对于初学者,你可以参考@卷毛杨的安装教程(AV38126904,CV2282855)进行安装配置,通过@pdcxs转载的视频教程进行学习,或者查看@cai-hust在github上整理的中文文档(https://github.com/cai-hust/manim-tutorial-CN),或者是跟着我在manim入门篇中的实例进行入门学习(由于版本更新等缘故,一些诸如import部分的代码需要修改),如果遇见问题,可参考@鹤翔万里整理的manim常见问题(https://github.com/Tony031218/manim-projects/blob/master/documents/manim%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98v2.0.pdf)

对于manim的进阶提高,最有效的办法莫过于:大量阅读manim源代码 + 自己不断地摸索和练习 + 和其他manim爱好者的交流。本次专栏作为manim的进阶篇,主要分享关于三维场景中的相关知识,主要涉及一些基础概念、三维曲线及常见的三维曲面的绘制思路。希望能对大家有所帮助。

注1:由于是进阶篇,一些基础知识可能不会展开解释(默认大家已有一定的基础)

注2:由于b站专栏不太方便贴代码,所以文中的代码均以图片形式给出,需要下载源码的童鞋可去我的github里面查看,链接如下:https://github.com/cigar666/my_manim_projects/blob/master/my_projects/ThreeD_projects/ThreeD_Demo.py

Chapter 1 关于三维场景

大家基于Scene创建出来的是降维打击后的二维场景(是俯视图),第三个维度是存在的,我们可以用OUT(沿纸面向外的单位向量,其值为np.array([0,0,1]))或者IN(向内的单位向量,其值为np.array([0,0,-1])),对物体进行移动等操作,但场景显示的仍然是所有物体的俯视图投影(正交投影,没有远大近小的透视关系)。

同样的物体在Scene(左)和ThreeDScene(右)中的渲染结果差别

而三维场景是基于ThreeDScene或其子类(比如SpecialThreeDScene)建立的场景,场景的渲染结果为ThreeDCamera所“看”到的内容。

ThreeDCamera部分代码的截图

至于相机位置及视角的确定,主要通过distance,phi,theta,gamma等参数来确定,通过直接或间接调用set_camera_orientation方法来实现。希望下图能对你的理解有所帮助。

三维场景中相机位置及视角的确定

下面我们用一个简单的示例来加深理解:

示例 1 简单的镜头移动

在这个例子中我们建立了一些简单几何体,并使用了很暴力的for循环的方式来移动镜头(示例中我只改了修改最频繁的theta和phi参数,对gamma和distance也可以用类似的方法实现)。大家可以修改一些参数自己试试,体会下镜头视角的变化带来的场景渲染结果的改变。

代码如下:

实现创建简单三维物体并移动镜头的代码

运行后效果如下:

上述代码的运行结果

因此,在三维场景中我们使用self.set_camera_orientation()方法来调整镜头。当然,在之后的代码中,我们更多地会使用SpecialThreeDScene的self.set_camera_to_default_position()方法来讲镜头调到CONFIG中给的默认参数定义好的位置(但实际上这个方法的内部也是用self.set_camera_orientation()方法来实现的)

Chapter 2 关于曲线的绘制

我们在二维场景中就经常使用ParametricFunction来进行曲线绘制,而在三维场景中我们的操作几乎一模一样(多考虑一个z轴的坐标而已),所以这部分我们给个示例大家体会下就行了。

示例 2 简单的三维曲线绘制

在示例中我们给出了一个半径为2的圆和一个相同半径的螺旋线,螺旋线和圆的差别在于虽然都有沿着z轴旋转运动,但螺旋线多了沿z轴正方向(也就是OUT * t表示的那部分)的运动。(我是用复数表示 旋转/圆 的方程,这部分数学上如果不理解,可以看看我这两期视频:AV83994732,AV86547021)

示例代码如下:

三维空间中的圆和螺旋线的相关代码

运行之后结果如下;

三维空间中的圆和螺旋线

Chapter 3 关于曲面的绘制

我们在三维场景中的曲面通过manim中的ParametricSurface()来实现。我们先通过两个例子看看ParametricSurface具体怎么使用。

示例 3 曲面z=sin(x^2+y^2)

我们通过该实例绘制由方程z=sin(x^2+y^2)所控制的曲面,其余的类似方程也能用相同的方式实现。其代码如下(注:之后代码的CONFIG和此示例中相同,所以之后的代码仅包含construct的部分):

绘制曲面z=sin(x^2+y^2)

其运行结果如下:

通过manim绘制的z=sin(x^2+y^2)的曲面结果

通过上面的代码不难发现,和ParametricFunction的用法十分类似,ParametricSurface需要输入一个曲面方程来定义曲面。在这个例子中我们用lambda函数定义出了曲面方程,方程的返回值为一个ndarray,其三个分量值对应了曲面方程上的点的x、y、z坐标随着u,v的值得变化情况(换句话说,这个示例中我们的曲面上的点的三个坐标为x=u, y=v, z=np.sin(u**2+v**2))。后面的u_min、u_max、v_min、v_max等定义了变量范围,而resolution定义了u,v方向的分段数。

示例 4 参数方程控制的曲面

而曲面方程也可以用参数方程来描述,即u,v不一定非得代表x,y,也可以是其他控制x、y、z变化的参数。

比如如下的代码,我们通过对示例2中的曲线进行修改,就得到了一个简单的螺旋曲面:

使用参数方程绘制螺旋曲面的相关代码

运行后的结果如下图所示:

螺旋曲面的渲染结果

Chapter 4 关于曲面的展示风格

我们之前渲染得到的曲面大多采用了默认的风格或者将checkerboard_colors设为None(此时默认的棋盘格就没了),我们在这部分将探索下其他的曲面展示风格。

示例 5 不同曲面风格的尝试

我们将在接下来的代码中试试不同展示风格的曲面,代码如下:

尝试不同的曲面展示风格的相关代码

代码运行的结果如下:

得到的不同风格的曲面形式

因此,我们可以通过ParametricSurface的config中的已有的属性来修改曲面样式,也可以通过set_color、set_fill等类方法对曲面整体或者分别对曲面的各个面进行编辑(参考我们代码中如何通过曲面的z的值来设定曲面颜色的方法)

Chapter 5 一些其他的尝试与探索

在前面的章节中我们介绍了关于三维场景的基础知识以及在manim中如何绘制一些简单的曲线、曲面,在这部分我们将尝试制作一些稍微复杂但是更加amazing的效果。下面让我们开始这一通操作吧。

示例 6 研究如何通过旋转生成曲面

很多曲面都可以由给定曲线绕着给定的轴通过旋转得到,如旋转抛物面、(单叶\双叶)双曲面等(包括我们在示例三、六中的曲面)。说道旋转,我们一般可以很容易地通过旋转矩阵或者复数的方法(up不懂四元数,所以略)进行实现(这部分的数学理论暂时略过,关于复数与旋转可以看看我的相关视频)。我们将在这个示例中尝试通过这两种方法来实现。

相关代码如下:

通过旋转矩阵与复数实现的旋转曲面的生成

代码运行的结果如下:

通过两种方法得到的旋转曲面的相关动画

示例 7 通过updater制作简单的曲面生成动画

和二维场景一样,通过add_updater也能通过合适的update函数对物体的更新等进行更好的控制。我们将在这个示例中简单看看三维物体是通过add_updater实现动画的。(我在视频从三维时空看复数旋转中也是通过类似方式完成更新的)

具体代码如下:

使用updater制作旋转曲面的生成动画

运行结果如下:

母直线绕z轴旋转生成单叶双曲面的动画

后话

通过上面的这些例子大家应该对三维场景及三维场景中的常见曲线曲面等绘制有所了解。要想对此有更深入的了解建议大家亲手编程操作一下,应该会有更多地收获。

此外,再放一些我制作的三维场景的渲染结果,这些部分由于代码并不短所以不方便在b站展示,但我会将其整理上传到我的github里面供大家学习交流。

通过简单立方体添加updater之后做成的动画效果莫比乌斯带变成心形的动画

我自己也制作了一些三维场景的视频,大家也可以通过视频并结合我在github上对应的代码来进行学习:

感谢大家的支持和观看,我们下次再见ღ( ´・ᴗ・` )

(告诉大家一个小秘密:专栏目前的三连只能手动三连哟)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3