告别枯燥理论!用Ursina像搭积木一样学3D图形学(Python实战)

还记得小时候用积木搭建城堡的快乐吗?当那些五颜六色的方块在手中翻转、堆叠,空间感和创造力就在玩耍中自然培养。今天,我们将用同样的方式探索3D图形学的奥秘——只不过这次,我们的积木是数字化的,而搭建工具是Python中轻量级的Ursina引擎。不需要复杂的数学推导,不需要枯燥的理论背诵,只需几行代码,你就能亲眼看到坐标系、变换矩阵这些抽象概念如何在三维空间中"活"起来。

1. 搭建你的第一个数字积木

安装Ursina只需要一个简单的pip命令:

pip install ursina

让我们从创建一个红色立方体开始:

from ursina import *

app = Ursina()
cube = Entity(model='cube', color=color.red)
app.run()

运行这段代码,你会看到一个窗口弹出,里面悬浮着一个红色立方体。这个简单的Entity就是我们的第一块数字积木。在Ursina中,几乎所有3D对象都是Entity的实例,就像乐高积木虽然形状各异但都是塑料块一样。

关键参数解析

  • model:定义积木的形状,内置支持'cube'、'sphere'等基本几何体
  • color:控制积木外观,可以直接使用color.red这样的命名颜色

试着修改这些参数,比如把cube换成sphere,或者把color.red改成color.azure,立即就能看到变化。这种即时反馈正是Ursina作为学习工具的最大优势——理论不再停留在纸面,而是变成了可以实时把玩的视觉对象。

2. 三维空间中的积木变换

2.1 位置移动:理解三维坐标系

在3D空间中定位一个物体需要三个坐标值(x,y,z)。让我们把立方体移动到屏幕右侧:

cube.position = (2, 0, 0)

尝试修改这些值,观察物体如何移动:

  • x值控制左右(正右负左)
  • y值控制上下(正上负下)
  • z值控制前后(正前负后)

提示:在Ursina中,按住鼠标右键可以旋转视角,中键可以平移场景,滚轮可以缩放。这能帮助你从不同角度观察物体位置。

2.2 缩放操作:直观感受向量乘法

缩放是图形学中最基础的变换之一。让我们把立方体沿不同方向拉伸:

# 均匀放大两倍
cube.scale = 2

# 非均匀缩放
cube.scale = (1.5, 0.5, 3)

通过实时调整这些参数,你可以直观地看到:

  • 当三个缩放值相同时,物体保持原比例
  • 当值不同时,物体在不同轴上发生形变
  • 小于1的值会使物体缩小

2.3 旋转实验:体验欧拉角

旋转是3D图形中最容易让人困惑的概念之一。Ursina让这个过程变得可视化:

# 绕x轴旋转45度
cube.rotation_x = 45

# 组合旋转
cube.rotation = (30, 45, 15)

尝试以下实验:

  1. 只设置rotation_x观察效果
  2. 然后添加rotation_y
  3. 最后加上rotation_z 你会发现三个旋转的顺序会影响最终结果——这正是欧拉角的重要特性。

3. 高级积木技巧:组合与交互

3.1 父子关系:构建复杂结构

就像把多个积木拼成一个更大的模型,Ursina中的Entity可以建立父子关系:

parent = Entity(model='cube')
child = Entity(model='sphere', parent=parent, position=(1,0,0))

parent.rotation_y = 45  # 子对象会跟随旋转

这种层级关系可以用来:

  • 构建关节动画(如机械臂)
  • 创建相对运动的物体组
  • 管理场景中的复杂对象

3.2 材质与光照:让积木更真实

Ursina支持基本的材质和光照效果:

cube = Entity(
    model='cube',
    texture='brick',
    shader=lit_with_shadows_shader
)

可用材质属性包括:

属性 描述 示例值
texture 表面贴图 'brick', 'grass'
shader 着色器类型 lit_with_shadows_shader
color 基础颜色 color.rgba(255,0,0,200)

3.3 交互功能:点击与拖拽

添加交互让学习过程更有趣:

def on_click():
    cube.color = color.random_color()

cube.on_click = on_click

你还可以实现拖拽功能:

from ursina.prefabs.draggable import Draggable

draggable_cube = Draggable(
    model='cube',
    plane_direction=(0,1,0)  # 限制在平面上移动
)

4. 从积木到项目:创意实践

4.1 构建简易太阳系

让我们用学到的知识创建一个太阳系模型:

sun = Entity(model='sphere', scale=2, color=color.yellow)
earth = Entity(model='sphere', parent=sun, x=4, color=color.blue)
moon = Entity(model='sphere', parent=earth, x=1, scale=0.3)

def update():
    sun.rotation_y += 10 * time.dt
    earth.rotation_y += 50 * time.dt

这个例子展示了:

  • 层级关系(月球绕地球转,地球绕太阳转)
  • 使用update函数实现动画
  • time.dt保证帧率无关的平滑运动

4.2 创建3D迷宫游戏

结合碰撞检测,我们可以制作简单游戏:

player = Entity(model='cube', collider='box')
walls = [
    Entity(model='cube', collider='box', position=(x,0,0), scale=(1,5,1))
    for x in range(-5,6,2)
]

def input(key):
    if key == 'd': player.x += 0.5
    if key == 'a': player.x -= 0.5

4.3 可视化算法演示

Ursina特别适合演示排序算法等抽象过程:

bars = [Entity(model='cube', scale=(0.8, random.uniform(1,5), 0.8), 
               position=(i,0,0), color=color.blue)
        for i in range(10)]

def bubble_sort():
    # 实现冒泡排序的可视化
    ...

这种可视化学习方式让算法的时间复杂度和交换过程一目了然。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐