Three加载可达鸭

lxf2023-05-09 12:47:01

写在开头

  1. 没买到可达鸭(根本没去买
  2. 可达鸭模型花了2块钱,买回来表面颜色也没有,骨骼也没有别说动画了,研究了几天blender和3dsmax玩不明白,所以模型就是个不会动的可达鸭。本来是想做个有kfc玩具的动画的模型。实力有限
  3. 内容包含:three加载fbx文件,射线模拟点击事件,加载文字

正文

预览

Three加载可达鸭

鸭鸭不会动,文字左右间隔出现

const LEFT_TEXTS = ['拒绝', '绝不', '不会']
const RIGHT_TEXTS = ['加班', '内卷', '秃头']

此处配置输出文字。鸭鸭要是可以动就好了。

加载fbx模型

用到了FBXLoader.js

// 加载模型
function loadModel(url = './model/可达鸭.fbx') { 
  const loader = new FBXLoader()
  loader.load(url, object => {
    object.traverse(child => {
      if (child.isMesh) {
        child.castShadow = true
        child.receiveShadow = true
      }
    })
    scene.add( object )
  })
}

加载字体

用了FontLoader.js和TextGeometry.js

// 加载字体
function initFont() {
  const foader = new FontLoader();
  foader.load( './Microsoft YaHei_Regular.json', f => {
    font = f
    isAuto
      ? autoOutput()
      : window.addEventListener( 'click', onMouseClick );
  }) 
}


// 显示文字
function showText(text) {
  const geometry = new THREE.TextGeometry(text, {
    font: font,
    size: 30,
    height: 5,
    curveSegments: 12,
    bevelEnabled: true,
    bevelThickness: 10,
    bevelSize: 8,
    bevelSegments: 5
  } );
  const material = new THREE.MeshPhongMaterial( {color: new THREE.Color().setHSL( Math.random(), 0.5, 0.5 ), side: THREE.DoubleSide, specular: 0x050505, shininess: 50, emissive: 0x000000 } );
  const mesh = new THREE.Mesh( geometry, material );
  mesh.position.x = isLeft ? -170 : 70;
  mesh.position.y = 150;
  tempMeshs.push(mesh);
  scene.add( mesh );
}

射线模拟点击事件

使用了THREE.Raycaster,用setFromCamera把点击的坐标传进去,从摄像头发射射线,然后用intersectObjects方法传入场景下所有的实体,会返回射线经过的实体集合。

// 鼠标点击
let isThrottle = false
function onMouseClick( event ) {
  if (isThrottle) {
    return;
  }
  setTimeout(() => {
    isThrottle = false
  }, interval)
  pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  // 点击
  raycaster.setFromCamera( pointer, camera );
  const intersects = raycaster.intersectObjects( scene.children );
  const length = intersects.length
  for (let i = 0; i < length; i++) {
    if (intersects[i].object.name === 'Obj3d66-1065924-2-598') {
      showSome()
      break
    }
  }
  isThrottle = true
}

写在最后

  1. 内容比较简单,没有涉及到骨骼,蒙皮和动画。本来有考虑用three去实现骨骼等,但想着用建模软件肯定更方便,结果太菜了,然后就摆烂了。所以算是一个阉割版的kfc可达鸭。
  2. gitee 项目地址在这边,可以直接clone下来尝试。
  3. 有时间写骨骼动画相关的文章