今天使用3DMax建模软件进行3D模型的制作,并且加入动画,通过threejs将模型及其动画部署在VUE框架上。
一、环境及其开发包版本
1. VUE:3.3.4
2. threejs:0.158.0
3. vite:4.4.11
4. 3DMax2021
5. pycharm2021专业版
二、3DMax模型制作
简单制作一个小植物和一个水壶,实现浇水后植物长大的动画。
UV展开,加个材质,上个颜色。
三、项目搭建
项目使用VUE框架。使用命令“npm init vue@latest”创建一个vue项目,并使用命令“npm i three”安装threejs。
在vue文件中引入javascript文件。
ttt.js文件代码如下:
import * as THREE from "three"
import {OrbitControls} from "three/addons/controls/OrbitControls.js";
import {GLTFLoader} from "three/addons/loaders/GLTFLoader.js";
let width = window.innerWidth
let height = window.innerHeight
const scene = new THREE.Scene()
scene.background = new THREE.Color(0x7F7F61)
const camera = new THREE.PerspectiveCamera(60, width / height)
camera.position.set(-3, 10, 10)
camera.lookAt(0, 0, 0)
scene.add(camera)
const aLignt = new THREE.AmbientLight(new THREE.Color(0xffffff), 2)
scene.add(aLignt)
const pointLight = new THREE.PointLight(new THREE.Color(0xffffff), 2, 0, 0)
pointLight.position.set(15, 15, 15)
scene.add(pointLight)
const axes = new THREE.AxesHelper(50)
// scene.add(axes)
const spriteMaterial = new THREE.SpriteMaterial({
map: new THREE.TextureLoader().load('./src/assets/水滴.png'),
transparent: true,
opacity: 0.3
})
const groups = new THREE.Group()
let spritey = 2.91
let spriteflag = false
for (let i = 0; i < 200; i++) {
const sprite = new THREE.Sprite(spriteMaterial)
sprite.scale.set(0.1, 0.2, 0.1)
const x = Math.random() - Math.random()
const y = Math.random() * spritey
// const y = spritey
const z = Math.random() - Math.random()
sprite.position.set(x, y, z)
groups.add(sprite)
}
let ganzi, yezi1, yezi2, yezi3, yezi4, huapen
const group = new THREE.Group()
group.name = 'group'
let geometry, mesh
let track1, track2, track3, track4, track5
let clip, mixer, actionAnimation, clock
const loader = new GLTFLoader();
loader.load('./src/assets/1111.glb', gltf => {
console.log(gltf)
// gltf.scene.scale.set(5,5,5)
group.add(gltf.scene)
scene.add(group)
huapen = group.getObjectByName('花盆')
yezi1 = group.getObjectByName('叶子1')
yezi2 = group.getObjectByName('叶子2')
yezi3 = group.getObjectByName('叶子3')
yezi4 = group.getObjectByName('叶子4')
ganzi = group.getObjectByName('杆子')
mixer = new THREE.AnimationMixer(group)
actionAnimation = mixer.clipAction(gltf.animations[0])
actionAnimation.timeScale = 0
actionAnimation.clampWhenFinished = true
actionAnimation.loop = THREE.LoopOnce
actionAnimation.play()
clock = new THREE.Clock()
})
let mixershuihu, actionanimationshuihu, c1
loader.load('./src/assets/11111.glb', gltf => {
console.log(gltf)
group.add(gltf.scene.getObjectByName('水壶'))
group.getObjectByName('水壶').visible = false
mixershuihu = new THREE.AnimationMixer(group.getObjectByName('水壶'))
actionanimationshuihu = mixershuihu.clipAction(gltf.animations[0])
actionanimationshuihu.timeScale = 4
actionanimationshuihu.clampWhenFinished = false
actionanimationshuihu.loop = THREE.LoopOnce
c1 = new THREE.Clock()
mixershuihu.addEventListener('finished', e => {
group.getObjectByName('水壶').visible = false
actionanimationshuihu.stop()
scene.remove(groups)
spriteflag = false
})
})
const renderer = new THREE.WebGLRenderer({antialias: true})
renderer.setSize(width, height)
renderer.domElement.style.position = 'absolute'
renderer.domElement.style.top = '0'
renderer.domElement.style.left = '0'
renderer.domElement.style.bottom = '0'
renderer.domElement.style.right = '0'
renderer.domElement.style.zIndex = '-1'
let select = 0
const btn = document.getElementById('add')
btn.addEventListener('click', function () {
if (select !== 2) {
select++
} else {
select = 0
}
group.getObjectByName('水壶').visible = true
actionanimationshuihu.play()
groups.traverse(m => {
m.position.y = Math.random() * spritey
})
scene.add(groups)
spriteflag = true
})
const control = new OrbitControls(camera, renderer.domElement);
(function animation() {
if (mixer && clock) {
mixer.update(clock.getDelta())
if (select === 1) {
actionAnimation.timeScale = 1
if (clock.getElapsedTime() >= 5) {
actionAnimation.timeScale = 0
}
} else if (select === 2) {
actionAnimation.timeScale = 1
if (clock.getElapsedTime() >= 22) {
actionAnimation.timeScale = 0
}
}
}
if (mixershuihu && c1) {
mixershuihu.update(c1.getDelta())
}
if (spriteflag) {
groups.traverse(m => {
if (m.position.y >= 0.2) {
m.position.y -= 0.02
}
})
}
renderer.render(scene, camera)
requestAnimationFrame(animation)
})();
window.onresize = () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
document.getElementById('data-three-js').appendChild(renderer.domElement)
四、效果图
项目搭建完毕,使用命令“npm run dev”运行。
点击浇水按钮,实现浇水后植物长大效果,效果图如下: