BabylonJS 6.0文档 Deep Dive 动画(四):通过动画排序制作卡通片

一种最为直接的方法是为每个动画剪辑(Animatin Clip)指定开始时间,最终形成一个卡通动画(Cartoon)。

1. 设计

1.1 概述

动画的脚本如下:

  • 摄像机显示了一栋带门的建筑物。
  • 摄像机靠近门并停止。
  • 门打开,摄像机进入房间。
  • 当摄像机进入房间时,房间里的灯亮起。
  • 门关上,摄像机在房间里扫了一圈。

本次目的是展示电影剪辑的制作方式,因此房间和门将简单地用没有纹理的网格制成作为例子。

1.2 执行者

  • 相机(Camera) - Universal Camera
  • 门(Door) - 向内打开, 铰链在右侧(旋转轴)
  • 聚光灯(Lights) - 带有球体以显示位置

1.3 时间排序

以下为各个执行者在不同时间段的执行动作:

对于每个执行者,可以创建一个动画,其中包含每个定时事件的关键点。

1.4 动画

对于相机

移动相机会更改相机的位置,相机绕 y 轴旋转。

由于动画只能更改一个属性,因此相机需要两个动画。

移动摄像机,关键点将在时间 0 处,摄像机将从建筑物开始,朝向和向下移动,直到时间 3 秒刚好在门外。

当门打开时,摄像机将保持其位置 2 秒钟,然后在时间 5 秒以远离门的角度向前移动到房间,在时间 8 秒停止。

相机不会旋转 9 秒,然后相机需要 14 秒才能旋转 180 度以面向门。

相机的key frame将是它在帧 0、3、5 和 8 秒的位置以及它在 0、9 和 14 秒的旋转。

TypeScript 复制代码
//for camera move forward
const movein = new BABYLON.Animation("movein", "position", frameRate, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);

const movein_keys = [];

movein_keys.push({
  frame: 0,
  value: new BABYLON.Vector3(0, 5, -30),
});

movein_keys.push({
  frame: 3 * frameRate,
  value: new BABYLON.Vector3(0, 2, -10),
});

movein_keys.push({
  frame: 5 * frameRate,
  value: new BABYLON.Vector3(0, 2, -10),
});

movein_keys.push({
  frame: 8 * frameRate,
  value: new BABYLON.Vector3(-2, 2, 3),
});

movein.setKeys(movein_keys);

//for camera to sweep round
const rotate = new BABYLON.Animation("rotate", "rotation.y", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);

const rotate_keys = [];

rotate_keys.push({
  frame: 0,
  value: 0,
});

rotate_keys.push({
  frame: 9 * frameRate,
  value: 0,
});

rotate_keys.push({
  frame: 14 * frameRate,
  value: Math.PI,
});

rotate.setKeys(rotate_keys);

对于门

门将围绕一个铰链旋转(y 轴)。打开和关闭旋转各需要 2 秒。

Key frame将是 0、3、5 、13 和 15 秒。

扫描的关键值将是它在帧处绕 y 轴的旋转。

TypeScript 复制代码
//for door to open and close
const sweep = new BABYLON.Animation("sweep", "rotation.y", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);

const sweep_keys = [];

sweep_keys.push({
  frame: 0,
  value: 0,
});

sweep_keys.push({
  frame: 3 * frameRate,
  value: 0,
});

sweep_keys.push({
  frame: 5 * frameRate,
  value: Math.PI / 3,
});

sweep_keys.push({
  frame: 13 * frameRate,
  value: Math.PI / 3,
});

sweep_keys.push({
  frame: 15 * frameRate,
  value: 0,
});

sweep.setKeys(sweep_keys);

对于灯光

不同灯光的强度会有所不同,它是一组灯光。

灯的关键点是保持关闭 7 秒,在 10 秒时达到最强,直到 14 秒熄灭。

TypeScript 复制代码
//for light to brighten and dim
const lightDimmer = new BABYLON.Animation("dimmer", "intensity", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);

const light_keys = [];

light_keys.push({
  frame: 0,
  value: 0,
});

light_keys.push({
  frame: 7 * frameRate,
  value: 0,
});

light_keys.push({
  frame: 10 * frameRate,
  value: 1,
});

light_keys.push({
  frame: 14 * frameRate,
  value: 1,
});

light_keys.push({
  frame: 15 * frameRate,
  value: 0,
});

lightDimmer.setKeys(light_keys);

2. 卡通动画

现在只需同时运行所有的动画剪辑:

TypeScript 复制代码
scene.beginDirectAnimation(camera, [movein, rotate], 0, 25 * frameRate, false);
scene.beginDirectAnimation(hinge, [sweep], 0, 25 * frameRate, false);
scene.beginDirectAnimation(spotLights[0], [lightDimmer], 0, 25 * frameRate, false);
scene.beginDirectAnimation(spotLights[1], [lightDimmer.clone()], 0, 25 * frameRate, false);

Playground示例

相关推荐
wyzqhhhh16 分钟前
京东啊啊啊啊啊
开发语言·前端·javascript
JIngJaneIL16 分钟前
基于java+ vue助农电商系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
想学后端的前端工程师26 分钟前
【Java集合框架深度解析:从入门到精通-后端技术栈】
前端·javascript·vue.js
VcB之殇31 分钟前
git常用操作合集
前端·git
yinuo1 小时前
前端跨页面通讯终极指南⑧:Cookie 用法全解析
前端
小鑫同学1 小时前
vue-pdf-interactor 技术白皮书:为现代 Web 应用注入交互式 PDF 能力
前端·vue.js·github
GISer_Jing1 小时前
Nano Banana:AI图像生成与编辑新标杆
前端·javascript·人工智能
csdn_aspnet1 小时前
用100行實現HTML5可存檔塗鴉版
javascript
布茹 ei ai1 小时前
城市天气查询系统 (City Weather Dashboard)
javascript·vue.js·html·css3·开源软件·天气预报
gyx_这个杀手不太冷静1 小时前
上线前不做 Code Review?你可能正在给团队埋雷!
前端·代码规范·团队管理