Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Origami Fold Studio · 折纸折叠工坊

在纸上绘制预设的折痕图(Crease Pattern),通过 3D 动画逐条演示折痕折叠,让一张平面纸片在眼前立起变成折纸作品。

在线体验:https://mchsd.github.io/origami-fold/

功能特性

  • 3D 折叠动画:基于 Three.js 的实时 3D 渲染,折痕按时间线折叠成 3D 形状
  • 折痕图同步:右侧 2D 折痕图(山折红线 / 谷折蓝虚线)与 3D 视图实时联动,当前折叠的折痕高亮显示
  • 自由视角:拖拽旋转、滚轮缩放、右键平移
  • 精细控制:进度条逐帧拖动、0.5× / 1× / 2× 动画速度、播放 / 暂停 / 展开 / 重置
  • 纸色切换:五种双色纸(正反面异色,传统折纸双色纸质感)——米白/暖杏、樱粉/玫红、天蓝/雾蓝、浅绿/草绿、柠檬/橙黄
  • 阶段化叙事:折叠过程按阶段分组(如"立起四边"、"封口"),阶段切换时自动暂停并显示阶段标题、镜头自动飞向操作区域
  • 折痕图动态状态:2D 折痕图中已折折痕自动变淡、当前折痕金色高亮、未折保持原色

内置模型

模型 说明 折痕数
纸盒 四条边同时立起 90°,无盖纸盒 4
纸飞机 中线对折成 V 形机身,两翼上翘 3
纸风车 四条对角线谷折,四片叶片立起 4
纸托盘 四边依次折起 90°,开口托盘 4
折扇 13 条平行折痕交替山/谷折,真实手风琴扇形 13
三浦折叠 Miura-ori 经典折纸:山/谷交替平行四边形网格,20 条折痕整体联动收缩成波浪状立体结构 20
水弹基础 Waterbomb Base 经典基础型:中心谷折 + 四角对角折,三角形面聚拢成星芒状多面体 8
十字对折 折痕交叉专项:两条对角线在中心 O 交叉,四段折痕共享中心端点。hinge 模式:阶段一沿 A-C 对折,阶段二沿 B-D 对折,交叉点 O 由 pins 钉死严格不动,对角共线折痕折叠后保持共线(cos=1.0) 4
棋盘波浪 折痕交叉专项:3×3 网格、12 条折痕在 4 个内部点两两交叉(山/谷交替 45°),同步折叠成棋盘格波浪板。交叉点打断成多条共享端点的折痕,纸面完整无撕裂 12

技术架构

单文件应用(index.html),无构建步骤,仅依赖 CDN 加载的 Three.js(r160)。

折叠引擎:PBD 约束求解(Position-Based Dynamics)

v2 引擎从"硬块顺序旋转"重构为 PBD 约束求解。核心思路:顶点是共享数组(一个顶点只有一个位置,从数据结构上杜绝撕裂),每帧交替执行两类约束:

每帧(按进度推进小步长):
  ├─ 1. 折痕驱动:对每条活动折痕,将 side 面绕折痕轴旋转
  │      Δθ = (目标角度 × 该折痕进度) − 已应用角度(开环积分,无测量漂移)
  ├─ 2. 边长投影:所有三角形边拉回原始长度(_projectEdge)
  └─ 3. 迭代收敛:多轮交替,最终顶点位置满足全部约束

关键设计(踩坑沉淀):

  • 时间感知旋转组:折痕折叠时只 block「已折叠或同时折叠」的折痕边,未折的折痕边是"门",可被整体带走——顺序折叠时后折的折痕带上前面的成果,这是 plane/tray/fan 完美收敛的关键
  • 单面驱动 + 修正的 side 索引:只旋转 side 面顶点(不是两侧分摊),配合显式修正的 side 字段(box/tray 曾全错位)
  • 开环角度积分:直接用「目标角度 × 进度」驱动,不依赖二面角测量反馈,绕开 atan2 主值跳变(wrap)问题;theta0=180° 的折痕配合 unwrap 修正
  • 固定点保护:折痕轴端点保持不动,跳过所有 sideV 顶点

引擎局限(物理铁证)

中心辐射型模型(纸风车 / 水弹基础)与部分环形网格(三浦折叠)不是刚性可折叠的——共享顶点被多个叶片/单元沿不同方向拉扯,真实纸张会起皱。PBD 下这些模型保持边长完美(无撕裂),但折痕角度只能收敛到视觉近似(风车 ~50°、水弹 ~81°),无法达到理论目标角。这是折纸几何的物理限制,不是引擎 bug;树状折痕图模型(纸盒/飞机/托盘/折扇)则精确收敛到 0.00°。

新增一个模型

MODELS 数组中追加一条定义即可:

{
  id: 'my-model', name: '我的模型', color: '#f5e6c8',
  desc: '模型描述',
  camera: [200, 150, 200],        // 视角初始位置
  vertices: [[x, y], ...],        // 2D 纸面坐标(3D 中映射为 (x, 0, y))
  faces: [[i, j, k], ...],        // 三角形(顶点索引)
  creases: [{
    a: 0, b: 1,                    // 折痕两端顶点
    angle: 90,                     // 折叠角度(正=山折,负=谷折)
    start: 0.0, duration: 1.4,     // 时间线(秒)
    label: '折痕说明',
    side: 2                        // 被旋转侧的起始面索引(引擎自动 BFS 出完整旋转组)
  }, ...]
}

模型也可用 generate() 函数程序化生成(参见三浦折叠/折扇)。

注意:折痕必须是两个面的公共边(内部网格边),不能是纸的边界边——边界边没有二面角可测、无法折叠。程序化生成时务必避开边界(曾踩坑:Miura 首版把左右边界生成为折痕,折叠完全失效)。

验证

项目无正式测试框架,verify_origami.js + verify_pbd.js 是事实标准验证工具:从 index.html 提取全部模型数据 + 引擎逻辑,用纯 JS 复现折叠过程并断言:

  1. 无 NaN
  2. 折痕轴端点不动
  3. 无撕裂:共享非折痕边的两面,边端点在两面中位置一致
  4. 关键形状断言(按模型)
node verify_pbd.js   # 238 项断言,全部通过(PBD 引擎:无撕裂/交叉点/波浪)
node verify_origami.js  # 305 项断言,全部通过

页面内置 window.__dbg 调试接口可实时导出顶点位置 / 已应用角度 / 二面角。

折痕交叉的处理方式

交叉折痕(多条折痕共享端点)是本次新增模型的核心课题,两种处理策略:

  1. 打断成共享端点的折痕段(棋盘波浪):3×3 网格中水平/垂直折痕在内部点交叉,每个交叉点 = 4 条折痕的公共端点。侧组 BFS 以折痕边为墙,每个单元独立驱动,交叉点由 PBD 边长约束协调——纸面完整无撕裂(边长 0.03%),波浪成型
  2. pins 钉死 + 分阶段折叠(十字对折):交叉点 O 由 pins: [[4,0,0,0]] 钉死在原点(4 条折痕公共端点物理静止),两阶段依次对折(hinge 模式:墙 = 同 start 折痕边),折叠后 B-O-D / A-O-C 保持共线(cos=1.0)

物理边界(诚实归因):水弹棋盘折(山/谷交替 45°)本身不是刚性可折叠的——纸折叠时整体自由漂移 + 波浪变形,交叉点绝对位移是几何必然而非撕裂(边长保持已单独断言)。验证脚本对 checker 断言的是相对结构(波浪起伏 z 范围 > 20 + 交叉点相对距离保持 < 12%),而非绝对不动。

本地运行

无需安装依赖,直接以静态页面打开:

# 方式一:直接双击 index.html
# 方式二:本地静态服务器
python -m http.server 8000 --directory .
# 访问 http://localhost:8000

注意:模块化脚本(ESM)在部分浏览器下要求通过 HTTP 访问,推荐方式二。

部署

推送到 GitHub 仓库后启用 GitHub Pages(Settings → Pages → 部署分支 main),即可获得公网访问链接。

技术要点与已知限制

  • 刚性折叠:引擎只支持刚性折纸(Rigid Origami),不支持压平(squash fold)、内翻(inside reverse fold)等多层非刚体折叠,因此经典复杂模型(千纸鹤等)暂无法表达
  • 单层纸:每个顶点只有一个位置,不支持折叠后纸张层叠
  • 中心辐射模型:纸风车/水弹基础/三浦折叠存在物理性角度近似(见上"引擎局限"),视觉成型但非精确目标角
  • 双色纸实现:背面颜色通过 onBeforeCompile 注入 if (!gl_FrontFacing) 片段着色器分支实现,换色时 needsUpdate 重编译

About

Origami Fold Studio - 折纸折叠工坊: crease pattern 2D + 3D fold animation

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages