当前位置: 首页 > news >正文

Manim实现镜面反射特效

本文将介绍如何使用ManimCE框架实现镜面反射特效,让你的动画更加生动有趣。

1. 实现原理

1.1. 对称点计算

实现镜面反射的核心是计算点关于直线的对称点。

代码中的symmetry_point函数通过向量投影的方法计算对称点:

# 关于直线的对称点
# p1和p2在直线l上,计算p关于l的对称点
def symmetry_point(p1, p2, p):"""计算点p关于由两点p1和p2确定的直线的对称点参数:p1, p2 : 直线上的两点 (numpy array or list)p : 直线外的点 (numpy array or list)返回:对称点坐标 (numpy array)"""# 转换为numpy数组确保计算正确p1 = np.array(p1)p2 = np.array(p2)p = np.array(p)# 计算直线的方向向量direction = p2 - p1# 计算从p1到p的向量vec_p1p = p - p1# 计算投影长度(点p在直线上的投影点到p1的距离)proj_length = np.dot(vec_p1p, direction) / np.dot(direction, direction)# 计算点p在直线上的投影点projection = p1 + proj_length * direction# 对称点 = 2 * 投影点 - 原点symmetric_point = 2 * projection - preturn np.array([symmetric_point[0], symmetric_point[1], 0])

这个函数使用了向量投影的数学原理,先找到点在直线上的投影,然后根据投影点计算对称点。具体步骤是:

  1. 计算直线的方向向量
  2. 计算从直线上一点到目标点的向量
  3. 计算该向量在直线方向上的投影长度
  4. 找到投影点坐标
  5. 通过公式 2 * 投影点 - 原点 计算对称点

1.2. 反射动画类设计

MirrorReflection 类继承自Manim的 Animation 类,用于创建和管理镜面反射效果:

# 镜面反射动画类
class MirrorReflection(Animation):def __init__(self,mobject,mirror: Line = None,reflect_opacity=0.3,reflect_stroke_opacity=0.5,**kwargs,):# 初始化参数self.original = mobjectself.mirror = mirror if mirror else Line(LEFT, RIGHT)self.reflect_opacity = reflect_opacityself.reflect_stroke_opacity = reflect_stroke_opacity# 创建反射对象并设置初始属性self.reflection = mobject.copy()self._update_reflection_position()self.reflection.set_fill(opacity=self.reflect_opacity * mobject.get_fill_opacity())self.reflection.set_stroke(opacity=self.reflect_stroke_opacity * mobject.get_stroke_opacity())# 添加动态更新器self.reflection.add_updater(self._update_reflection)super().__init__(mobject, **kwargs)

1.3. 动态更新机制

为了确保反射效果能够跟随原始对象的变化而实时更新,代码实现了几个关键方法:

def _update_reflection_position(self):"""更新反射对象的位置"""points = self.original.get_points()new_points = []p1, p2 = self.mirror.get_start(), self.mirror.get_end()for p in points:# 使用对称点计算函数计算每个点的反射位置new_points.append(symmetry_point(p1, p2, p))# 应用新位置self.reflection.set_points(new_points)def _update_reflection(self, reflection_mobject):"""更新反射对象的属性"""# 重新创建反射对象并应用垂直翻转temp_reflection = self.original.copy()reflection_mobject.become(temp_reflection)# 更新反射对象位置和透明度self._update_reflection_position()reflection_mobject.set_fill(opacity=self.reflect_opacity * self.original.get_fill_opacity())reflection_mobject.set_stroke(opacity=self.reflect_stroke_opacity * self.original.get_stroke_opacity())

这些方法确保了无论原始对象如何移动、缩放或旋转,反射效果都会相应地更新,保持视觉上的一致性。

2. 使用示例

让我们看看如何在实际场景中使用这个镜面反射特效:

# 使用示例
class Example(Scene):def construct(self):# 创建三角形对象triangle = Triangle(color=BLUE)triangle.shift(2 * LEFT)# 创建垂直镜面mirror = Line(UP * 3, DOWN * 3, color=WHITE)# 创建镜面反射动画mirror_reflection = MirrorReflection(triangle, mirror=mirror)reflection = mirror_reflection.create_reflection_mobject()# 添加到场景self.add(mirror, triangle, reflection)self.wait()# 动画演示self.play(triangle.animate.shift(UP))self.wait()self.play(triangle.animate.scale(1.5))self.wait()self.play(triangle.animate.shift(DOWN))self.wait()self.play(Rotate(triangle, angle=PI))self.wait()

使用步骤非常简单:

  1. 创建需要添加反射效果的原始对象(这里是一个蓝色三角形)
  2. 创建镜面(这里是一条白色垂直线)
  3. 创建MirrorReflection实例,并传入原始对象和镜面
  4. 通过create_reflection_mobject()方法获取反射对象
  5. 将原始对象、镜面和反射对象添加到场景中
  6. 对原始对象执行各种动画操作,观察反射效果的实时更新

在这个例子中,我们演示了对象的上移、缩放、下移和旋转四种操作,反射效果都会实时跟随更新,保持与原始对象的对称关系。

3. 总结

3.1. 特效特点

这个镜面反射特效具有以下特点:

  1. 实时更新:无论原始对象如何变换,反射效果都会实时更新,保持视觉一致性
  2. 高度可定制:可以调整反射对象的填充透明度和描边透明度,创建不同的视觉效果
  3. 灵活的镜面设置:可以自定义镜面的位置、方向和样式,适应不同场景需求
  4. 易用性:封装成了独立的动画类,使用简单,只需几行代码就能添加专业的反射效果

3.2. 使用场景

镜面反射特效适用于多种场景:

  1. 数学教学:用于几何对称、坐标系变换等概念的可视化教学
  2. 物理模拟:模拟光的反射、镜像对称等物理现象
  3. 艺术效果:为动画添加美感和层次感,提升视觉吸引力
  4. 交互演示:用于展示对称关系、变换过程等
  5. Logo和品牌展示:创建镜像效果的动态Logo动画

通过这个简单而强大的镜面反射特效,可以为你的Manim动画增添更多的视觉魅力和专业感。

http://www.hskmm.com/?act=detail&tid=15891

相关文章:

  • 25Java基础之IO(二)
  • 【P2860】[USACO06JAN] Redundant Paths G - Harvey
  • GUI软件构造
  • 企业微信客服API模式接入第三方客服系统,对接大模型AI智能体
  • react使用ctx和reducer代替redux
  • KM 乱记
  • 深入解析:B树与B+树的原理区别应用
  • linux中的服务监控,停用自动重启
  • RHEL7/CentOS7 install NVIDIA drivers and CUDA
  • 浅谈 Burnside 和 Polya 的证明
  • 算法学习笔记:支配对
  • 西电PCB设计指南第5章学习笔记
  • ImageMagick - 关于图片压缩,通过dk整理的一些可用指令 - window64
  • 【杂记】原 hack
  • 全新升级!EasyDSS会议管理3大核心功能,让远程协作更高效
  • 黄金、原油期货数据API对接文档
  • 我的笔记方案
  • 聊聊前序、中序、后序表达式
  • flink书籍 - --
  • 详述大模型备案
  • Asp.Net Core 鉴权授权
  • 124
  • 我的笔记记录方案
  • AT_arc156_d [ARC156D] Xor Sum 5
  • iOS Provisioning Profile 证书 描述文件
  • 计算快速付氏变换FFT前需要加窗函数
  • 直播预告| PostgreSQL 与 IvorySQL 在云原生时代的演进与实践
  • KGDB(Kernel GNU Debugger)工具使用方法详解 - 详解
  • Wallpaper Engine v2.7.3 动态壁纸软件-内含数百款动态皮肤 - 实践
  • 力扣155题 最小栈