Manim實(shí)現(xiàn)鏡面反射特效
本文將介紹如何使用ManimCE框架實(shí)現(xiàn)鏡面反射特效,讓你的動畫更加生動有趣。
1. 實(shí)現(xiàn)原理
1.1. 對稱點(diǎn)計(jì)算
實(shí)現(xiàn)鏡面反射的核心是計(jì)算點(diǎn)關(guān)于直線的對稱點(diǎn)。
代碼中的symmetry_point函數(shù)通過向量投影的方法計(jì)算對稱點(diǎn):
# 關(guān)于直線的對稱點(diǎn)
# p1和p2在直線l上,計(jì)算p關(guān)于l的對稱點(diǎn)
def symmetry_point(p1, p2, p):
"""
計(jì)算點(diǎn)p關(guān)于由兩點(diǎn)p1和p2確定的直線的對稱點(diǎn)
參數(shù):
p1, p2 : 直線上的兩點(diǎn) (numpy array or list)
p : 直線外的點(diǎn) (numpy array or list)
返回:
對稱點(diǎn)坐標(biāo) (numpy array)
"""
# 轉(zhuǎn)換為numpy數(shù)組確保計(jì)算正確
p1 = np.array(p1)
p2 = np.array(p2)
p = np.array(p)
# 計(jì)算直線的方向向量
direction = p2 - p1
# 計(jì)算從p1到p的向量
vec_p1p = p - p1
# 計(jì)算投影長度(點(diǎn)p在直線上的投影點(diǎn)到p1的距離)
proj_length = np.dot(vec_p1p, direction) / np.dot(direction, direction)
# 計(jì)算點(diǎn)p在直線上的投影點(diǎn)
projection = p1 + proj_length * direction
# 對稱點(diǎn) = 2 * 投影點(diǎn) - 原點(diǎn)
symmetric_point = 2 * projection - p
return np.array([symmetric_point[0], symmetric_point[1], 0])
這個(gè)函數(shù)使用了向量投影的數(shù)學(xué)原理,先找到點(diǎn)在直線上的投影,然后根據(jù)投影點(diǎn)計(jì)算對稱點(diǎn)。具體步驟是:
- 計(jì)算直線的方向向量
- 計(jì)算從直線上一點(diǎn)到目標(biāo)點(diǎn)的向量
- 計(jì)算該向量在直線方向上的投影長度
- 找到投影點(diǎn)坐標(biāo)
- 通過公式
2 * 投影點(diǎn) - 原點(diǎn)計(jì)算對稱點(diǎn)
1.2. 反射動畫類設(shè)計(jì)
MirrorReflection 類繼承自Manim的 Animation 類,用于創(chuàng)建和管理鏡面反射效果:
# 鏡面反射動畫類
class MirrorReflection(Animation):
def __init__(
self,
mobject,
mirror: Line = None,
reflect_opacity=0.3,
reflect_stroke_opacity=0.5,
**kwargs,
):
# 初始化參數(shù)
self.original = mobject
self.mirror = mirror if mirror else Line(LEFT, RIGHT)
self.reflect_opacity = reflect_opacity
self.reflect_stroke_opacity = reflect_stroke_opacity
# 創(chuàng)建反射對象并設(shè)置初始屬性
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())
# 添加動態(tài)更新器
self.reflection.add_updater(self._update_reflection)
super().__init__(mobject, **kwargs)
1.3. 動態(tài)更新機(jī)制
為了確保反射效果能夠跟隨原始對象的變化而實(shí)時(shí)更新,代碼實(shí)現(xiàn)了幾個(gè)關(guān)鍵方法:
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:
# 使用對稱點(diǎn)計(jì)算函數(shù)計(jì)算每個(gè)點(diǎn)的反射位置
new_points.append(symmetry_point(p1, p2, p))
# 應(yīng)用新位置
self.reflection.set_points(new_points)
def _update_reflection(self, reflection_mobject):
"""更新反射對象的屬性"""
# 重新創(chuàng)建反射對象并應(yīng)用垂直翻轉(zhuǎn)
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())
這些方法確保了無論原始對象如何移動、縮放或旋轉(zhuǎn),反射效果都會相應(yīng)地更新,保持視覺上的一致性。
2. 使用示例
讓我們看看如何在實(shí)際場景中使用這個(gè)鏡面反射特效:
# 使用示例
class Example(Scene):
def construct(self):
# 創(chuàng)建三角形對象
triangle = Triangle(color=BLUE)
triangle.shift(2 * LEFT)
# 創(chuàng)建垂直鏡面
mirror = Line(UP * 3, DOWN * 3, color=WHITE)
# 創(chuàng)建鏡面反射動畫
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()
使用步驟非常簡單:
- 創(chuàng)建需要添加反射效果的原始對象(這里是一個(gè)藍(lán)色三角形)
- 創(chuàng)建鏡面(這里是一條白色垂直線)
- 創(chuàng)建
MirrorReflection實(shí)例,并傳入原始對象和鏡面 - 通過
create_reflection_mobject()方法獲取反射對象 - 將原始對象、鏡面和反射對象添加到場景中
- 對原始對象執(zhí)行各種動畫操作,觀察反射效果的實(shí)時(shí)更新
在這個(gè)例子中,我們演示了對象的上移、縮放、下移和旋轉(zhuǎn)四種操作,反射效果都會實(shí)時(shí)跟隨更新,保持與原始對象的對稱關(guān)系。

3. 總結(jié)
3.1. 特效特點(diǎn)
這個(gè)鏡面反射特效具有以下特點(diǎn):
- 實(shí)時(shí)更新:無論原始對象如何變換,反射效果都會實(shí)時(shí)更新,保持視覺一致性
- 高度可定制:可以調(diào)整反射對象的填充透明度和描邊透明度,創(chuàng)建不同的視覺效果
- 靈活的鏡面設(shè)置:可以自定義鏡面的位置、方向和樣式,適應(yīng)不同場景需求
- 易用性:封裝成了獨(dú)立的動畫類,使用簡單,只需幾行代碼就能添加專業(yè)的反射效果
3.2. 使用場景
鏡面反射特效適用于多種場景:
- 數(shù)學(xué)教學(xué):用于幾何對稱、坐標(biāo)系變換等概念的可視化教學(xué)
- 物理模擬:模擬光的反射、鏡像對稱等物理現(xiàn)象
- 藝術(shù)效果:為動畫添加美感和層次感,提升視覺吸引力
- 交互演示:用于展示對稱關(guān)系、變換過程等
- Logo和品牌展示:創(chuàng)建鏡像效果的動態(tài)Logo動畫
通過這個(gè)簡單而強(qiáng)大的鏡面反射特效,可以為你的Manim動畫增添更多的視覺魅力和專業(yè)感。

浙公網(wǎng)安備 33010602011771號