Three.js 入门篇-制作 3D 动漫角色欣赏

前言

废话不多说,先上一波炫酷前端效果展示,点我去欣赏。最近有个任务,刚搞完一个卡通网 kt5.cn,没有一点点流量。 如何为卡通网带来点人气呢? ,于是就有了这篇《Three.js 制作 3D 动漫角色欣赏篇》,顺便想带旺一下给卡通网。

一、与卡通相关又与前端相关的主题及制作思路

突发奇想,要不针对一些 3d 动漫的角色,搞个展示 show 的页面吧:

    1. 3D 模型哪里来? ,当然是去大名鼎鼎的
    2. 3d warehouse(https://3dwarehouse.sketchup.com/),大品牌,放心;谷歌出品、必是精品;
    3. 如何把 3d 模型展示出来了,当然是选择来自 未来前端技术 的 Three.js,支持多种
    4. 3D 模型的加载,敲定 AR/VR 不在话下;
    5. 二话不说下载 3D 模型撸代码开干。

二、Three.js加载 3D 模型代码一般思路

Three.js 的代码经典思路:

  1. 创建一个场景 Scene
  2. 给场景加个相机 Camera
  3. 创建一个渲染器 Renderer
  4. 把 3D 模型加载进来,添加到场景
  5. 渲染循环(动画)。如果 3D 模型自带动画就直接播放其动画、不然后就自己添加平移 / 缩放 / 旋转等效果动画

三、源码及关键注释

点击查看在线效果

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>3D 动漫角色欣赏 : Centaur-Vert</title>
    <meta
      content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"
      name="viewport"
    />
    <meta content="yes" name="apple-mobile-web-app-capable" />
    <meta content="black" name="apple-mobile-web-app-status-bar-style" />
    <meta content="telephone=no" name="format-detection" />
    <meta content="email=no" name="format-detection" />
    <link type="text/css" rel="stylesheet" href="main.css" />
    <style>
      body {
        font-family: Monospace;
        background-color: #000;
        color: #fff;
        margin: 0px;
        overflow: hidden;
      }
      #percent {
        color: #fff;
        position: absolute;
        top: 10px;
        right: 0;
        width: 400px;
        text-align: center;
        z-index: 100;
        display: block;
        font-size: 20px;
        font-weight: 700;
        letter-spacing: 3px;
      }
    </style>
  </head>
  <body>
    <div id="percent">0%</div>
    <div id="container"></div>
    <div id="info"></div>
    <script src="https://threejs.org/build/three.js"></script><!-- 引入Three.js -->
    <script src="./js/libs/stats.min.js"></script><!-- 可选:引入Three.js的渲染统计统计器 -->
    <script src="./js/loaders/ColladaLoader.js"></script><!-- 引入Three.js的针对Collada文件(.dae后缀)的异步加载器,你可以理解为ajax相似的东西 -->
    <script src="./js/controls/OrbitControls.js"></script><!-- 引入Three.js的模型控制器插件,用于绑定鼠标/触模操控3d模型 -->
    <script>
      var container, stats, clock, controls
      var camera, scene, renderer, mixer, avatar
      var loadingEl = document.getElementById('percent')

      init()
      animate()

      function init() {
        container = document.getElementById('container')
        // 创建一个透视相机Camera
        camera = new THREE.PerspectiveCamera(
          25,
          window.innerWidth / window.innerHeight,
          1,
          1000
        )
        camera.position.set(0, 10, 20)
        scene = new THREE.Scene()
        // 使用THREE.Clock来启动一个计时器
        clock = new THREE.Clock()

        // 加载collada 3d模型
        var loader = new THREE.ColladaLoader()
        loader.load(
          './models/centaur-vert/model.dae',
          function(collada) {
            loadingEl.remove()
            var animations = collada.animations
            avatar = collada.scene
            // 加载完之后按需调整一下3D模型的比例
            avatar.scale.x = 0.0025
            avatar.scale.y = 0.0025
            avatar.scale.z = 0.0025
            // console.log(avatar)

            avatar.traverse(function(node) {
              if (node.isSkinnedMesh) { // 有皮肤就不进行视锥采集
                node.frustumCulled = false
              }
            })
            if (animations.length > 0) {
              // 如果有动画就播放动画
              mixer = new THREE.AnimationMixer(avatar)
              mixer.clipAction(animations[0]).play()
            }
            scene.add(avatar) // 添加把3D模型添加到场景
          },
          function(event) { // 添加加载进度展示
            loadingEl.innerHTML =
              '3D模型加载进度:' +
              (((event.loaded * 100) / event.total) | 0) +
              '% <br>操作方式:鼠标 + 加上下左右键'
          }
        )

        // 添加网格
        var gridHelper = new THREE.GridHelper(10, 20)
        scene.add(gridHelper)

        // 添加灯光(环境光源,白光)
        var ambientLight = new THREE.AmbientLight(0xffffff, 0.2)
        scene.add(ambientLight)

        // 添加灯光(点光源,白光)
        var pointLight = new THREE.PointLight(0xffffff, 0.8)
        scene.add(camera)
        camera.add(pointLight)

        // 创建渲染器
        renderer = new THREE.WebGLRenderer({ antialias: true }) // 抗锯齿
        renderer.setPixelRatio(window.devicePixelRatio) // 设置dpr
        renderer.setSize(window.innerWidth, window.innerHeight) // 设置比率
        container.appendChild(renderer.domElement)

        // 绑定鼠标/触屏操控事件
        controls = new THREE.OrbitControls(camera, renderer.domElement)
        controls.screenSpacePanning = true
        controls.minDistance = 5
        controls.maxDistance = 40
        controls.target.set(0, 2, 0)
        controls.update()

        // 添加左上角的渲染统计
        stats = new Stats()
        container.appendChild(stats.dom)

        // 监控屏幕大小变化事件
        window.addEventListener('resize', onWindowResize, false)
      }

      function onWindowResize() { // 监控屏幕大小变化进行适配渲染
        camera.aspect = window.innerWidth / window.innerHeight
        camera.updateProjectionMatrix()
        renderer.setSize(window.innerWidth, window.innerHeight)
      }

      // 动画代码,绕z轴旋转
      function animate() {
        avatar && avatar.rotation && (avatar.rotation.z += 0.005) 
        requestAnimationFrame(animate)

        render()
        stats.update()
      }

      function render() {
        var delta = clock.getDelta()

        if (mixer !== undefined) {
          mixer.update(delta)
        }

        renderer.render(scene, camera)
      }
    </script>
  </body>
</html>
<script></script>

参考引用

1: https://threejs.org/
2: https://github.com/mrdoob/three.js/

本文同步发布于:https://blog.csdn.net/u012609766/article/details/100771979#_6

作者: 博主

Talk is cheap, show me the code!

发表评论

邮箱地址不会被公开。

Captcha Code