在控制台中实现旋转立方体

背景

在一次偶然的探索中,我被一个使用控制台实现3D效果的创意所吸引。经过几个小时的苦学和实践,我完成了这个小Demo,并将其命名为RIC。

简介

RIC (Render In Console) 完全基于Python标准库实现,它通过将三维坐标映射到二维坐标上,在控制台环境中实现了伪3D效果。

github:RIC
效果图

在这里插入图片描述

功能概览
  • 模型封装:目前支持点、线、立方体三种基本模型。
  • 空间变换:封装了旋转、缩放、平移的空间变换方法。
  • 简单API:提供了简洁的API,并支持链式调用,创建和操作三维对象以及在控制台中的渲染变得简单直观。

技术栈

RIC项目主要采用Python作为开发语言,利用其简洁的语法,快速实现了控制台中的三维渲染。

核心组件

Canvas 类

Canvas 类是 RIC 项目的核心组件,负责管理控制台画布和渲染逻辑。它通过模拟一个二维网格,将三维对象的投影绘制到控制台上。为了简化实现,我直接忽略了 y 轴坐标,将 x 和 z 坐标映射到控制台的行和列上,并使用字符绘制出图形。

这个类采用单例模式,确保整个应用程序中只有一个画布实例。主要功能包括:

  • 绘制图形: draw 方法将世界坐标转换为屏幕坐标,并在对应位置绘制字符。
  • 更新画布: update 方法遍历所有已注册的图形对象,并调用它们的 draw 方法。
  • 清理控制台: clear_console 方法通过系统命令清空控制台内容。
  • 刷新显示: flush 方法清空控制台后,将缓存中的画布内容打印到屏幕上,并重置缓存。
  • 注册图形对象: register_graphic 方法将图形对象添加到图形列表中,供画布管理和渲染。
Base 类和 BasePoint 类

Base 类定义了三维变换的抽象方法,提供了统一的接口来处理三维对象的平移、缩放和旋转操作。具体的变换方法包括:

  • 平移: translate 方法接受三个参数 dx、dy 和 dz,用于在各个轴上移动对象。
  • 缩放: scale 方法接受三个参数 sx、sy 和 sz,用于在各个轴上缩放对象。
  • 绕 x 轴旋转: rotatex 方法接受角度 theta,用于绕 x 轴旋转对象。
  • 绕 y 轴旋转: rotatey 方法接受角度 theta,用于绕 y 轴旋转对象。
  • 绕 z 轴旋转: rotatez 方法接受角度 theta,用于绕 z 轴旋转对象。

BasePoint 类是 Base 类的具体实现,表示三维空间中的一个点。它实现了所有的变换方法,并通过 draw 方法将点投影到画布上。

Point 类

Point 类继承自 BasePoint,提供了点的创建和基本操作,是构成更复杂三维模型的基本元素。除了继承 BasePoint 的所有方法,Point 类可以被用于构建线段、立方体等复杂图形。

Line 类

Line 类通过连接两个点来表示线段,支持线的绘制和基本变换,为构建复杂的几何形状提供了可能。Line 类实现了平移、缩放和旋转的方法,并使用基本的直线绘制算法将线段投影到画布上。

  • 绘制线段: draw 方法根据两点的坐标和斜率选择在 x 轴或 z 轴上采样更多的点,确保绘制的线段尽可能接近真实线段。
  • 平移: translate 方法对线段的两个端点应用平移操作。
  • 缩放: scale 方法在缩放线段时,先将线段平移到原点进行缩放,然后再平移回原位置。
  • 旋转: rotatex, rotatey, rotatez 方法对线段的两个端点分别应用绕各轴的旋转操作。
Cuboid 类

Cuboid 类实现了立方体模型,支持立方体的创建和空间变换,是 RIC 项目中最为复杂的三维模型实现。通过组合多个 Line 对象来表示立方体的边,Cuboid 类可以实现对立方体的绘制、平移、缩放和旋转操作。

  • 绘制立方体: draw 方法遍历所有边,并调用每条边的 draw 方法,将立方体的所有边投影到画布上。
  • 平移: translate 方法对立方体的每条边应用平移操作,使得整个立方体在三维空间中移动。
  • 缩放: scale 方法在缩放立方体时,对立方体的每条边应用缩放操作,实现整体缩放效果。
  • 旋转: rotatex, rotatey, rotatez 方法对立方体的每条边分别应用绕各轴的旋转操作,使得整个立方体进行旋转变换。

实现细节

RIC项目的实现涉及到多个关键技术点,包括但不限于:

  • 坐标映射:将三维坐标转换为二维坐标,以适应控制台的显示。
  • 渲染算法:根据模型的几何特性,选择合适的渲染策略,以实现高效的图形输出。
  • 空间变换:实现了旋转、缩放、平移等操作,使得三维模型可以在控制台中自由变换。

示例

代码
旋转

下面是一个使用RIC创建立方体并进行旋转的示例代码:

import time

from RIC.Model import *
from RIC.Canvas import *

# 创建一个画布实例,尺寸为550x100
canvas = Canvas(550, 100)

# 创建一个长方体对象,长宽高均为60,原点位于长方体中心
c = Cuboid(30, 30, 30, -30, -30, -30)
# 将长方体对象注册到画布上
canvas.register_graphic(c)
# 初始化各轴的旋转角度
theta_x, theta_y, theta_z = -1, 3, -1
# 记录上次的时间戳
last_time = time.time()
while True:
    # 获取当前时间戳
    current_time = time.time()
    # 计算时间差
    delta_time = current_time - last_time
    # 更新上次的时间戳
    last_time = current_time
    # 应用变换,围绕x、y、z轴旋转
    c.rotatex(theta_x).rotatey(theta_y).rotatez(theta_z)
    # 更新画布,将图形绘制到画布上
    canvas.update()
    # 将画布的内容输出到控制台并清空
    canvas.flush()

    # 计算还需要等待的时间,以达到约30帧每秒的刷新率
    time_to_wait = 1 / 30 - delta_time
    # 如果还需要等待的时间大于0,则进行等待
    if time_to_wait > 0:
        time.sleep(time_to_wait)

缩放

下面是一个使用RIC创建立方体并进行缩放的示例代码:

from RIC.Model import *
from RIC.Canvas import *

# 创建一个画布实例,尺寸为550x100
canvas = Canvas(550, 500)

# 创建一个长方体对象,长宽高均为60,原点位于长方体中心
c = Cuboid(30, 30, 30, -30, -30, -30)
# 将长方体对象注册到画布上
canvas.register_graphic(c)
c.rotatex(10).rotatez(10)
c.scale(3, 1, 1)
canvas.clear_console()
canvas.update()
canvas.flush()

注意

你可能需要在系统控制台中运行示例,并调整控制台的缓存大小,否则换行会导致显示错乱。至少我在pycharm中还没找到如何设置终端显示宽度

结语

RIC只是我一次简单的尝试,它存在很多问题,如性能问题、渲染算法问题、坐标映射问题等。但是,它确实实现了一个简单的三维图形渲染器,并能对三维模型进行旋转、缩放、平移操作。

如果想要达到更好的效果,我想我还需要继续学习计算机图形学的知识,并尝试使用OpenGL,DirectX等来构建一个更好的渲染器。

多问题,如性能问题、渲染算法问题、坐标映射问题等。但是,它确实实现了一个简单的三维图形渲染器,并能对三维模型进行旋转、缩放、平移操作。

如果想要达到更好的效果,我想我还需要继续学习计算机图形学的知识,并尝试使用OpenGL,DirectX等来构建一个更好的渲染器。

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值