迷雾秘境:Threejs 补间动画与 Trimesh 不规则形状的奇幻联动

在 Threejs 中,Fog 类用于创建线性雾的效果。雾效果常用于模拟真实世界中视觉深度递减的效果,也可以用于创建某些艺术效果。当物体距离观察者越远,雾就越浓,物体的颜色就越接近雾的颜色。

Fog

js 复制代码
const scene = new THREE.Scene();
const cube = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 50),
  new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
scene.add(cube);
scene.fog = new THREE.Fog(0x999999, 0.1, 20);

参数:

  • color: 雾的颜色,默认为黑色。

  • near: 雾开始生效的距离,默认为 1。

  • far: 雾完全生效的距离,默认为 1000。

  • .isFog: 只读属性,表示该对象是否为雾对象。

FogExp2

js 复制代码
const scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.02);

参数:

  • color: 雾的颜色,默认为黑色。

  • density: 雾的密度,默认为 0.00025。

  • isFogExp2: 只读属性,表示该对象是否为 FogExp2 对象。

注意:

  • 雾效果是通过改变物体材质的颜色来实现的,如果一个物体的材质不包含颜色信息,那么雾效果将不会对该物体产生影响。

  • 在一些复杂的场景中,雾效果可能会对渲染性能产生影响,因此在使用雾效果时需要权衡性能和视觉效果。

  • 雾效果并不会阻止物体的渲染,而是通过改变物体的颜色来模拟雾的效果。

补间动画(Tween)

Tween.js 是一个轻量级的 JavaScript 库,用于创建补间动画。补间动画是一种常见的动画形式,它通过在两个关键帧之间插入多个中间帧来创建平滑的动画效果。

js 复制代码
//导入tween
import * as TWEEN from "three/examples/jsm/libs/tween.module.js";

//创建补间动画-可以链式调用
const tween = new TWEEN.Tween(sphere.position).to({ x: 6 }, 2000).start();

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
  TWEEN.update(); //更新补间动画
}

方法

  • to(): 设置动画的目标值。

  • start(): 启动动画。

  • stop(): 停止动画。

  • chain(): 链接动画,使一个动画结束后立即开始下一个动画。

  • repeat(): 设置动画重复的次数。

  • yoyo(): 设置动画是否在重复时反向播放。

  • easing(): 设置动画的缓动函数。

  • delay(): 设置动画的延迟时间。

  • interpolation(): 设置动画的插值函数。

  • onUpdate(): 设置动画更新时的回调函数。

  • onComplete(): 设置动画完成时的回调函数。

  • onStart(): 设置动画开始时的回调函数。

  • onStop(): 设置动画停止时的回调函数。

缓动函数

缓动函数用于控制动画的速度,它决定了动画在两个关键帧之间如何变化。Three.js 提供了多种内置的缓动函数:

js 复制代码
const tween = new TWEEN.Tween(sphere.position)
  .to({ x: 6 }, 2000)
  .easing(TWEEN.Easing.Quadratic.InOut);
js 复制代码
//创建补间动画
const tween = new TWEEN.Tween(sphere.position).to({ x: 6 }, 1000);
const tween2 = new TWEEN.Tween(sphere.position).to({ y: -4 }, 1000);
const tween3 = new TWEEN.Tween(sphere.position).to({ x: -6 }, 1000);
const tween4 = new TWEEN.Tween(sphere.position).to({ y: 4 }, 1000);
tween.chain(tween2);
tween2.chain(tween3);
tween3.chain(tween4);
tween4.chain(tween);
tween.start();

Trimesh 不规则形状

之前在学习 CANNON 中知道,绘制物体时不仅需要绘制几何体还需要绘制物理几何体,对于绘制几何体,Three.js 提供了 BufferGeometry 来创建几何体,或者通过导入 3D 模型来创建不规则几何体。同样,在绘制物理几何体时,CANNON.js 提供了 Trimesh 来创建不规则形状,适用于复杂的多面体、不规则的物体,甚至可以基于导入进来的 3D 模型创建对应的物理形状。

Trimesh() 构造函数用于创建不规则形状,适用于复杂的多面体、不规则的物体,甚至可以基于导入进来的 3D 模型创建对应的物理形状。

js 复制代码
//导入GLTFLoader
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
//导入CANNON
import * as CANNON from "cannon-es";
//创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0); // 设置重力

//创建地面
const ground = new THREE.Mesh(
  new THREE.PlaneGeometry(100, 100),
  new THREE.MeshBasicMaterial({ color: 0x303030, side: THREE.DoubleSide })
);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
//创建地面物理
const groundBody = new CANNON.Body({ mass: 0, shape: new CANNON.Plane() });
groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0);
world.addBody(groundBody);

var body;
var mesh;
const gltfLoader = new GLTFLoader();
gltfLoader.load("./models/bunny.gltf", (gltf) => {
  gltf.scene.position.set(0, 2, 0);
  mesh = gltf.scene;
  scene.add(gltf.scene);

  //获取geometry
  const geometry = gltf.scene.getObjectByName("bunny").geometry;

  //创建物理
  let shape = new CANNON.Trimesh(geometry.attributes.position.array, geometry.index.array);
  body = new CANNON.Body({
    mass: 1,
    shape,
    position: gltf.scene.position,
  });
  world.addBody(body);
});

function animate() {
  requestAnimationFrame(animate);
  world.step(1 / 60);
  if (mesh) {
    mesh.position.copy(body.position);
    mesh.quaternion.copy(body.quaternion);
  }
  renderer.render(scene, camera);
}

.Trimesh() 构造函数用于创建不规则形状。

  • vertices: 顶点位置数据。

  • indices: 顶点索引数据。

物理引擎调试

使用 Cannon.js 时,无法直观的看到物体的物理属性,比如碰撞、摩擦力等,因此需要使用调试工具来查看物体的物理属性。

  1. 安装
bash 复制代码
npm install cannon-es-debugger
  1. 导入
js 复制代码
import { CannonDebugger } from "cannon-es-debugger";
  1. 创建调试器
js 复制代码
const cannonDebugger = new CannonDebugger(scene, world, {
  //设置颜色
  color: 0xffffff,
});
  1. 更新调试器
js 复制代码
function animate() {
  requestAnimationFrame(animate);
  world.step(1 / 60);
  cannonDebugger.update(); //更新调试器
  renderer.render(scene, camera);
}

书洞笔记

相关推荐
优雅永不过时·4 天前
实现一个漂亮的Three.js 扫光地面 圆形贴图扫光
前端·javascript·智慧城市·three.js·贴图·shader
3D虚拟工厂11 天前
1️⃣7️⃣three.js_OrbitControls相机控制器
javascript·3d·vue·blender·three.js·uv
3D虚拟工厂12 天前
OrbitControls
three.js
VcB之殇14 天前
three.js中使用canvas生成动态纹理贴图
javascript·three.js
Mintopia15 天前
Three.js 在数字孪生中的应用场景教学
前端·javascript·three.js
FanetheDivine15 天前
three.js学习笔记 2.光照和材质
react.js·three.js
雨夜带刀_16 天前
vue+three.js贴图-自定义贴图.仿写VANS定制功能(three.js+vue)
three.js
小桥风满袖16 天前
Three.js-硬要自学系列19 (曲线颜色渐变、渐变插值、查看设置gltf顶点、山脉高度可视化)
前端·css·three.js
Mintopia16 天前
# 使用 Three.js 实现带随机障碍物的小车行驶模拟
前端·javascript·three.js
渣渣宇a17 天前
Three_3D_Map 中国多个省份的组合边界绘制,填充背景
前端·javascript·three.js