【THREE】都说嫦娥奔月,谁听过野兔奔月的?这就长长见识~

1,278 阅读3分钟

我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛

前言

嫦娥应悔偷灵药,碧海青天夜夜心。

——李商隐

介绍

本期也是临时创作,由three.js创作了野兔奔月3D动画,野兔有个小想法也要找玉兔过中秋。。好吧,是我临时瞎编的,看效果吧:

VID_20210908_095139.gif

正文

1.分析需求

  • 环境搭建
  • 导入月球
  • 野兔奔跑
  • 无尽循环

我们这里模型的是从sketchfab这样的资源网站上获取的,当然你有时间也可以自己创作3d模型,我一般用的是blender,只要不做细腻的毛发和质感这样的皮肤等特别细的,其他的方面算比较容易入门的。当然要不断减少面,毕竟是网页,面多了吃不消的。

微信截图_20210908103007.png

2.环境搭建

<body>
    <div id="app"></div>
    <script src="./js/three.min.js"></script>
    <script src="./js/GLTFLoader.js"></script>
    <script src="./js/OrbitControls.js"></script>
    <script type="module" src="./app.js"></script>
</body>

当然我们要把需要的three包和gltf模型加载器还有轨道控制器引入进去。

class Application {
  constructor() {
    this.app = document.getElementById("app");
    this.w = 0;
    this.h = 0;
    this.scene = null;
    this.camera = null;
    this.renderer = null;
    this.mixer = null;
    this.clock = new THREE.Clock();
    this.init();
  }
  init() {
    // 初始化
    this.scene = new THREE.Scene();
    this.createCamera();
    this.addLight();
    this.renderer = new THREE.WebGLRenderer({
      antialias: true,
    });
    this.renderer.setSize(document.body.clientWidth, document.body.clientHeight);
    this.renderer.setClearColor(new THREE.Color(0x000000));
    this.app.appendChild(this.renderer.domElement);
    new THREE.OrbitControls(this.camera, this.renderer.domElement);
    this.render();
    this.loop();
  }
  addLight() {
    // 添加灯光
    this.ambientLight = new THREE.AmbientLight(0xFFFFFF);
    this.ambientLight.intensity = 1;
    this.scene.add(this.ambientLight);
  }
  createCamera() {
    // 添加相机
    this.camera = new THREE.PerspectiveCamera(
      90,
      document.body.clientWidth / document.body.clientHeight,
      0.2,
      1000
    );
    this.camera.position.set(-12, 7, 10);
  }
  createMoon() {
    // 创建月球
  }
  createRabbit() {
    // 创建野兔
  }
  render() {
    // 主渲染
    this.createRabbit();
    this.createMoon();
  }
  loop() {
    // 循环
    requestAnimationFrame(this.loop.bind(this));
    const {renderer, scene, camera} = this;
    renderer.render(scene, camera);
    camera.lookAt(scene.position);
  }
}
​
window.onload = new Application();
​

我们这主逻辑中完成了这些基础工作:

  • 创建场景scene
  • 创建渲染器renderer,将宽高铺满全屏,且将其视图放到dom中
  • 创建相机
  • 追加常光
  • 追加轨道控制器
  • 循环更新视图

2.导入月球

createMoon() {
    let loader = new THREE.GLTFLoader();
    loader.load("./assets/moon/scene.gltf", gltf => {
        this.moon = gltf.scene;
        this.moon.scale.set(.05, .05, .05)
        this.scene.add(this.moon);
    });
}

我们之前下载好的月球glft模型,通过glft模型加载器找到他的路径执行下载,并且追加到场景中。

3.野兔奔跑

createRabbit() {
    let loader = new THREE.GLTFLoader();
    loader.load("./assets/rabbit/scene.gltf", gltf => {
        this.rabbit = gltf.scene;
        this.rabbit.scale.set(.16, .16, .16)
        this.rabbit.position.set(0, 5, 0)
        this.mixer = new THREE.AnimationMixer(this.rabbit);
        this.mixer.clipAction(gltf.animations[0]).play()
        this.scene.add(this.rabbit);
    });
}

还是一样,我们要导入野兔的gltf模型添加到场景中。这个gltf模型中带了一个奔跑动画,我们创建AnimationMixer,在混合器中中之前这个奔跑动画。这时你发现他并没有动,这是怎么回事呢?我们没有循环更新他的动作执行。

微信截图_20210908105425.png

4.无尽循环

loop() {
    requestAnimationFrame(this.loop.bind(this));
    const {renderer, scene, camera, mixer, clock,moon} = this;
    let delta = clock.getDelta();
    mixer && mixer.update(delta);
    renderer.render(scene, camera);
    camera.lookAt(scene.position);
    if(moon){
        moon.rotation.x-=0.05
    }
}

在这里我们在混合器中不断更新周期就能看到野兔动起来了。别忘了,月球还要来个旋转呢,很简单在x轴方向不断减值就转起来了。

讲到这里这个动画场景已经结束了,是不是超简单~

拓展

我们本期只是用到了three.js的皮毛就可以很简单构建出动画,主要还是模型给力,当然有时间的话,我们可以自己创作模型,blender就特别适合我们去学习导出模型。


创作不易,你们的支持就是我创作的动力,请各位看官老爷们多多点赞评论收藏,一键三连哟~