找回密码
 立即注册
首页 业界区 安全 Manim实现镜面反射特效

Manim实现镜面反射特效

堵赫然 2025-9-25 21:02:03
本文将介绍如何使用ManimCE框架实现镜面反射特效,让你的动画更加生动有趣。
1. 实现原理

1.1. 对称点计算

实现镜面反射的核心是计算点关于直线的对称点。
代码中的symmetry_point函数通过向量投影的方法计算对称点:
  1. # 关于直线的对称点
  2. # p1和p2在直线l上,计算p关于l的对称点
  3. def symmetry_point(p1, p2, p):
  4.     """
  5.     计算点p关于由两点p1和p2确定的直线的对称点
  6.     参数:
  7.     p1, p2 : 直线上的两点 (numpy array or list)
  8.     p : 直线外的点 (numpy array or list)
  9.     返回:
  10.     对称点坐标 (numpy array)
  11.     """
  12.     # 转换为numpy数组确保计算正确
  13.     p1 = np.array(p1)
  14.     p2 = np.array(p2)
  15.     p = np.array(p)
  16.     # 计算直线的方向向量
  17.     direction = p2 - p1
  18.     # 计算从p1到p的向量
  19.     vec_p1p = p - p1
  20.     # 计算投影长度(点p在直线上的投影点到p1的距离)
  21.     proj_length = np.dot(vec_p1p, direction) / np.dot(direction, direction)
  22.     # 计算点p在直线上的投影点
  23.     projection = p1 + proj_length * direction
  24.     # 对称点 = 2 * 投影点 - 原点
  25.     symmetric_point = 2 * projection - p
  26.     return np.array([symmetric_point[0], symmetric_point[1], 0])
复制代码
这个函数使用了向量投影的数学原理,先找到点在直线上的投影,然后根据投影点计算对称点。具体步骤是:

  • 计算直线的方向向量
  • 计算从直线上一点到目标点的向量
  • 计算该向量在直线方向上的投影长度
  • 找到投影点坐标
  • 通过公式 2 * 投影点 - 原点 计算对称点
1.2. 反射动画类设计

MirrorReflection 类继承自Manim的 Animation 类,用于创建和管理镜面反射效果:
  1. # 镜面反射动画类
  2. class MirrorReflection(Animation):
  3.     def __init__(
  4.         self,
  5.         mobject,
  6.         mirror: Line = None,
  7.         reflect_opacity=0.3,
  8.         reflect_stroke_opacity=0.5,
  9.         **kwargs,
  10.     ):
  11.         # 初始化参数
  12.         self.original = mobject
  13.         self.mirror = mirror if mirror else Line(LEFT, RIGHT)
  14.         self.reflect_opacity = reflect_opacity
  15.         self.reflect_stroke_opacity = reflect_stroke_opacity
  16.         # 创建反射对象并设置初始属性
  17.         self.reflection = mobject.copy()
  18.         self._update_reflection_position()
  19.         self.reflection.set_fill(opacity=self.reflect_opacity * mobject.get_fill_opacity())
  20.         self.reflection.set_stroke(opacity=self.reflect_stroke_opacity * mobject.get_stroke_opacity())
  21.         # 添加动态更新器
  22.         self.reflection.add_updater(self._update_reflection)
  23.         super().__init__(mobject, **kwargs)
复制代码
1.3. 动态更新机制

为了确保反射效果能够跟随原始对象的变化而实时更新,代码实现了几个关键方法:
  1. def _update_reflection_position(self):
  2.     """更新反射对象的位置"""
  3.     points = self.original.get_points()
  4.     new_points = []
  5.     p1, p2 = self.mirror.get_start(), self.mirror.get_end()
  6.     for p in points:
  7.         # 使用对称点计算函数计算每个点的反射位置
  8.         new_points.append(symmetry_point(p1, p2, p))
  9.     # 应用新位置
  10.     self.reflection.set_points(new_points)
  11. def _update_reflection(self, reflection_mobject):
  12.     """更新反射对象的属性"""
  13.     # 重新创建反射对象并应用垂直翻转
  14.     temp_reflection = self.original.copy()
  15.     reflection_mobject.become(temp_reflection)
  16.     # 更新反射对象位置和透明度
  17.     self._update_reflection_position()
  18.     reflection_mobject.set_fill(opacity=self.reflect_opacity * self.original.get_fill_opacity())
  19.     reflection_mobject.set_stroke(opacity=self.reflect_stroke_opacity * self.original.get_stroke_opacity())
复制代码
这些方法确保了无论原始对象如何移动、缩放或旋转,反射效果都会相应地更新,保持视觉上的一致性。
2. 使用示例

让我们看看如何在实际场景中使用这个镜面反射特效:
  1. # 使用示例
  2. class Example(Scene):
  3.     def construct(self):
  4.         # 创建三角形对象
  5.         triangle = Triangle(color=BLUE)
  6.         triangle.shift(2 * LEFT)
  7.         # 创建垂直镜面
  8.         mirror = Line(UP * 3, DOWN * 3, color=WHITE)
  9.         # 创建镜面反射动画
  10.         mirror_reflection = MirrorReflection(triangle, mirror=mirror)
  11.         reflection = mirror_reflection.create_reflection_mobject()
  12.         # 添加到场景
  13.         self.add(mirror, triangle, reflection)
  14.         self.wait()
  15.         # 动画演示
  16.         self.play(triangle.animate.shift(UP))
  17.         self.wait()
  18.         self.play(triangle.animate.scale(1.5))
  19.         self.wait()
  20.         self.play(triangle.animate.shift(DOWN))
  21.         self.wait()
  22.         self.play(Rotate(triangle, angle=PI))
  23.         self.wait()
复制代码
使用步骤非常简单:

  • 创建需要添加反射效果的原始对象(这里是一个蓝色三角形)
  • 创建镜面(这里是一条白色垂直线)
  • 创建MirrorReflection实例,并传入原始对象和镜面
  • 通过create_reflection_mobject()方法获取反射对象
  • 将原始对象、镜面和反射对象添加到场景中
  • 对原始对象执行各种动画操作,观察反射效果的实时更新
在这个例子中,我们演示了对象的上移、缩放、下移和旋转四种操作,反射效果都会实时跟随更新,保持与原始对象的对称关系。
1.gif

3. 总结

3.1. 特效特点

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

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

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

  • 数学教学:用于几何对称、坐标系变换等概念的可视化教学
  • 物理模拟:模拟光的反射、镜像对称等物理现象
  • 艺术效果:为动画添加美感和层次感,提升视觉吸引力
  • 交互演示:用于展示对称关系、变换过程等
  • Logo和品牌展示:创建镜像效果的动态Logo动画
通过这个简单而强大的镜面反射特效,可以为你的Manim动画增添更多的视觉魅力和专业感。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

昨天 06:52

举报

喜欢鼓捣这些软件,现在用得少,谢谢分享!
您需要登录后才可以回帖 登录 | 立即注册