three.js 士兵示例(根据规定定位移动)

运用相关:vue3、three.js

模型下载:https://github.com/mrdoob/three.js/  


<template>

  <div ref="sceneRef">

</template>

<script setup>

import {onMounted,ref }from 'vue'

import *as THREEfrom "three"

import { OrbitControls }from 'three/examples/jsm/controls/OrbitControls'

import { GLTFLoader }from 'three/examples/jsm/loaders/GLTFLoader.js'

import gsapfrom 'gsap'

let scene,camera,renderer,orbitControls

let sceneRef =ref()

let model =ref(null)//用于模型移动

let mixer =ref(null)

let clock =new THREE.Clock()

let curve =null

//启动动画

function startAnimation(skinnedMesh, animations, animationName) {

// 申明动画场景

  const m_mixer =new THREE.AnimationMixer(skinnedMesh)

// 查找动画

  const clip = THREE.AnimationClip.findByName(animations, animationName)

if (clip) {

// 播放

    const action =m_mixer.clipAction(clip)

action.play()

}

return m_mixer

}

// 曲线/移动

function makeCurve() {

// 创建曲线

  curve =new THREE.CatmullRomCurve3([

new THREE.Vector3(0,0,0),

new THREE.Vector3(5,0,0),

new THREE.Vector3(0,0,5)

])

// 曲线类型

  curve.curveType ="catmullrom"

  // 设置曲线闭环

  curve.closed =true

  // 设置曲线张力0-1

  curve.tension =0.5

  // 获取点位

  const points =curve.getPoints(100)

// 存储属性

  const geometry =new THREE.BufferGeometry().setFromPoints(points)

// 更改线的颜色

  const material =new THREE.LineBasicMaterial({color:0x000000})

// 生成线

  const  curveObject =new THREE.Line(geometry,material)

// 加入场景

  scene.add(curveObject)

let obj ={num:0 }

gsap.to(obj, {

num:1,

// 时间

    duration:30,

// 循环

    repeat: -1,

// 缓动效果

    ease:'none',

onUpdate() {

let point =curve.getPoint(obj.num)

model.value.scene.position.copy(point)

let pointNext =curve.getPoint(obj.num -0.001)

model.value.scene.lookAt(pointNext)

}

})

// console.log(points)

// console.log('gltf', model)

}

// 引入模型

function loadModel() {

const gltfLoader =new GLTFLoader()

gltfLoader.setPath('/modules/')

.load('Soldier.glb', (gltf) => {

console.log(gltf,'gltf')

// 旋转模型

    gltf.scene.rotation.y =Math.PI

    // 模型缩放

    gltf.scene.scale.set(1,1,1)

// 遍历模型对象(网格对象:改变属性)

    gltf.scene.traverse((object) => {

if (object.isMesh) {

// 阴影

        object.castShadow =true

        // 接受投影

        object.receiveShadow =true

      }

})

// 获取跑步动画

    mixer.value =startAnimation(

gltf.scene,

gltf.animations,

gltf.animations[3].name

    )

model.value = gltf

makeCurve()

scene.add(gltf.scene)

})

}

function init() {

// 场景

  scene =new THREE.Scene()

// 相机 透视相机 fov视场角 aspect宽高比 near靠近摄像机的裁剪平面的距离 far远处的裁剪平面的距离

  camera =new THREE.PerspectiveCamera(75,window.innerWidth /window.innerHeight,0.1,1000)

// 渲染器

  renderer =new  THREE.WebGLRenderer()

// 相机位置

  camera.position.set(5,5,5)

// 相机看向那边

  camera.lookAt(scene.position)

// 添加辅助坐标x(红色),y(绿色),z(蓝色)

  const axes =new THREE.AxesHelper(20)

scene.add(axes)

// 场景背景

  scene.background =new THREE.Color(0xa0a0a0)

// 场景边界雾化效果

  scene.fog =new THREE.Fog(0xa0a0a0,10,30)

// 半球形光源

  const hemiLight =new THREE.HemisphereLight(0xffffff,0x444444)

hemiLight.position.set(0,10,0)

scene.add(hemiLight)

// 创建一个虚拟的球形网格 Mesh 的辅助对象来模拟 半球形光源HemisphereLight

  const hemiLightHelper =new THREE.HemisphereLightHelper(hemiLight,5)

scene.add(hemiLightHelper)

// 地面 Mesh三位网格对象(集合体对象,材质) PlaneGeometry创建平面几何体 MeshPhongMaterial模拟光滑表面的高光效果

  const mesh =new THREE.Mesh(new THREE.PlaneGeometry(100,100),new THREE.MeshPhongMaterial({color:0x999999,depthWrite:false}))

mesh.rotation.x = -Math.PI /2

  mesh.receiveShadow =true

  scene.add(mesh)

// 平行光

  const directionalLight =new THREE.DirectionalLight(0xffffff)

// 灯光需要开启“引起阴影”

  directionalLight.castShadow =true

  // 阴影样式

  directionalLight.shadow.camera.near =0.5

  directionalLight.shadow.camera.far =50

  directionalLight.shadow.camera.left = -10

  directionalLight.shadow.camera.right =10

  directionalLight.shadow.camera.top =10

  directionalLight.shadow.camera.bottom = -10

  directionalLight.position.set(0,5,5)

// 阴影清晰度 默认512

  directionalLight.shadow.mapSize.set(2048,2048)

scene.add(directionalLight)

// 用于模拟场景中平行光 DirectionalLight 的辅助对象. 其中包含了表示光位置的平面和表示光方向的线段

  const directionalLightHelper =new THREE.DirectionalLightHelper(directionalLight,5)

scene.add(directionalLightHelper)

// 渲染阴影

  renderer.shadowMap.enabled =true

  renderer.setSize(window.innerWidth,window.innerHeight)

sceneRef.value.appendChild(renderer.domElement)

}

function animate() {

requestAnimationFrame(animate)

if(mixer.value){

mixer.value.update(clock.getDelta())

}

renderer.render(scene,camera)

}

function initOrbitControls() {

orbitControls =new OrbitControls(camera,renderer.domElement)

// orbitControls.enableDamping = true

  //相机位置与观察目标点最大值

  // orbitControls.maxDistance = 1300

// orbitControls.maxPolarAngle = Math.PI / 2

  // // 上下旋转范围

  // orbitControls.minPolarAngle = -Math.PI / 2 //默认值0

  // orbitControls.maxPolarAngle = Math.PI / 2 //默认值Math.PI

  // // // 左右旋转范围

  // orbitControls.minAzimuthAngle = -Math.PI / 2

// orbitControls.maxAzimuthAngle = Math.PI / 2

}

// 监听窗口大小变化事件

window.addEventListener('resize',function() {

// 更新渲染器尺寸

  renderer.setSize(window.innerWidth,window.innerHeight);

// 更新相机宽高比

  camera.aspect =window.innerWidth /window.innerHeight;

camera.updateProjectionMatrix();

});

onMounted(() => {

init()

loadModel()

initOrbitControls()

animate()

})

<style scoped lang="scss">

</style>



©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容