The project's README from github.com/cclank/clay-safari. As one markdown file: README.md.
黏土风格的 3D 可交互双语认知世界 — 走进去,点一点,听听 10 位动物朋友的名字和叫声
A claymation-style 3D bilingual (中文 / English) animal world for kids, built with Blender-scripted models and Three.js.
按 M 进入的俯瞰海报视角 · 左沙右草、一条 S 形河流和一座小桥,17 个物件都带中文 / 拼音 / 英文标签
需要 Node.js 20.19+(20.x)或 22.12+。
git clone https://github.com/cclank/clay-safari.git
cd clay-safari
npm install
npm run dev # http://localhost:5290
开发服务器默认仅供本机访问。需要手机在同一局域网调试时,运行 npm run dev -- --host。
npm run build # 打包到 dist/
npm run preview # 预览打包结果 http://localhost:5291
模型已经导出在 public/models/ 里,不需要安装 Blender 就能运行。想改动物造型再重新生成:
# 需要 Blender 5.x;BLENDER 可指向任意 Blender 可执行文件
BLENDER=/Applications/Blender.app/Contents/MacOS/Blender npm run models
在线地址:https://clay-safari.lanshuagent.com/
项目使用 Cloudflare Workers Static Assets 托管 dist/。部署配置保存在 wrangler.jsonc,无需配置应用 API 密钥。
npx [email protected] login # 首次部署时登录 Cloudflare
npm run deploy # 构建并部署
Fork 后请先修改 wrangler.jsonc 中的 Worker 名称和自定义域名,使用自己 Cloudflare 账号下的域名;也可以移除 routes,仅使用 workers.dev 地址。
| 操作 | 桌面 | 手机 |
|---|---|---|
| 行走 | WASD / 方向键,Shift 加速 | 左下角摇杆 |
| 前往某处 | 点击地面 | 点击地面 |
| 旋转 / 缩放 | 拖动 / 滚轮 | 拖动 / 双指 |
| 认识动物 | 点击动物或道具 | 点击 |
| 自动导览 | 点击 🤖 或 T | 点击 🤖 |
| 俯瞰全景 | M | 🗺️ 按钮 |
| 隐藏 / 显示标签 | L | 🏷️ 按钮 |
| 帮助 | H | ❓ 按钮 |
参考图定风格 ──▶ Blender 脚本捏动物 ──▶ 导出 GLB ──▶ Three.js 生成世界 ──▶ 互动 + 声音 ──▶ 实测打包
src/data.js 里重新规划地图、物件位置和一条穿过小桥的探险路线。blender/build_animals.py 只用球体、胶囊、贝塞尔管道和倒角盒子,每只动物 20–40 行,19 个模型一次跑完约 10 秒。会动的部位(头、尾、鼻子、下颌、翅膀、耳朵)挂在独立的 Empty 上,用 pivot() 把原点挪到关节处,导出后 Three.js 直接绕关节旋转,不需要骨骼。src/clay.js 用分形噪声生成四方连续的灰度凹凸图,配合 MeshPhysicalMaterial 的 sheen 层做轮廓柔光。加载 GLB 时按「关节 × 颜色」合并网格,一只 40 个零件的动物只需约 6 次绘制。src/world.js 生成顶点色地形(沙地 / 草地 / 小路 / 河岸)、河流刻槽、在标准材质里注入着色器的水面、拱桥、实例化植被、太阳、云和一圈「黏土台面」裙边。河道曲线和地形共用同一个公式,水面泡沫因此永远贴着岸。src/audio.js 用振荡器、噪声和滤波器合成 17 种叫声与音效,Web Speech 读中英文名字。
| 模块 | 技术 |
|---|---|
| 建模 | Blender Python (bpy) 参数化建模,glTF 导出,matrix_parent_inverse 关节枢轴 |
| 渲染 | Three.js r185,MeshPhysicalMaterial sheen,PCF 软阴影,ACES 色调映射,EffectComposer + UnrealBloomPass |
| 世界 | 值噪声 / fbm 地形与纹理,顶点色绘制,InstancedMesh 批量植被,onBeforeCompile 注入水面着色器 |
| 寻路 | 网格 A*(八方向、禁止穿角)+ 视线拉直 |
| 声音 | Web Audio API 合成(振荡器、噪声、双二阶滤波、波形整形),Web Speech API 朗读 |
| 工程 | Vite 8,ES Modules,零运行时依赖(仅 three) |
clay-safari/
├── blender/
│ └── build_animals.py # Blender 脚本:19 个黏土模型 → GLB
├── public/models/ # 导出的 GLB(约 3.9 MB)
├── src/
│ ├── data.js # 地图布局、动物数据、导览路线
│ ├── clay.js # 黏土材质、凹凸图、GLB 加载与网格合并
│ ├── world.js # 地形 / 河流 / 植被 / 天空 / 寻路网格
│ ├── nav.js # A* 寻路
│ ├── animals.js # 动物摆放、浮动词卡、待机与点击动画
│ ├── player.js # 探险家控制与相机
│ ├── tour.js # 机器人自动导览
│ ├── audio.js # TTS + 合成叫声 + 环境音
│ ├── effects.js # 蝴蝶、飞鸟、水波、星星、彩带
│ ├── ui.js # 加载页、词卡、探险手册、摇杆
│ ├── tween.js # 极简补间引擎
│ └── main.js # 入口:渲染循环、输入、发现流程
├── docs/images/ # README 截图
├── index.html
└── vite.config.js # Vite 构建配置
加一只新动物
build_animals.py 里写一个 build_xxx(),把会动的部位挂到 head / tail 等 Empty 下并调用 pivot(),加进 BUILDERS,运行 npm run modelssrc/data.js 的 ITEMS 里加一条:中文、拼音、英文、emoji、位置、朝向、缩放、导览观察点src/animals.js 的 update() 和 react() 里加待机和点击动作,在 src/audio.js 的 CALLS 里加叫声kind 设为 'animal'换成真实动物录音 — 把录音放到 public/sounds/<id>.mp3,在 audio.js 的 animalSound(id) 里用 new Audio() 播放并在 ended 时 resolve,其余流程不用改。
换语言 — 词卡文案全部来自 ITEMS,speak() 的语言代码在 main.js 的 sayChain() 里。
欢迎 Issue 和 PR。新动物、新的叫声配方、性能优化、翻译都很欢迎。提交前请跑一遍 npm run build 确认无报错。
MIT © 2026 lank