模型上色、换肤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body {
margin: 0;
}
#process{
position: absolute;
top:0;
left:0;
font-size:20px;
color: aliceblue;
}
#operation{
position: absolute;
top:0;
right:20px;
/* transform: translateX(-50%); */
}
</style>
</head>
<body>
<script type="module">
import * as THREE from "three";
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// import {Rhino3dmLoader} from 'three/examples/jsm/loaders/3DMLoader.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(5, 2, 0);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({
antialias: true
})
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
/**
* 创建地面
*/
const geometry2 = new THREE.PlaneGeometry(100, 100);
const material2 = new THREE.MeshStandardMaterial({ color: 0xffffff });
const plane = new THREE.Mesh(geometry2, material2);
//旋转
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.add(plane);
/**
* 灯光
*/
//环境光
const ambientLight = new THREE.AmbientLight(0x404040); // 柔和的白光
scene.add(ambientLight);
// 平行光
const directionLight = new THREE.DirectionalLight(0xffffff, 1);
directionLight.castShadow = true;
//让阴影更清晰
directionLight.shadow.mapSize.width = 2048;
directionLight.shadow.mapSize.height = 2048;
//不设置以下内容看不见
directionLight.shadow.camera.left = -100;
directionLight.shadow.camera.right = 100;
directionLight.shadow.camera.top = 100;
directionLight.shadow.camera.bottom = -100;
directionLight.position.set(150, 20, 0);
const directionalLightHelper = new THREE.DirectionalLightHelper(directionLight, 5);
scene.add(directionLight);
let model;
let modelScene;
/**
* 修改模型颜色
*/
const oInput = document.getElementById("color");
//添加事件
oInput.addEventListener('input',(event)=>{
if(model){
model.material.color.set(event.target.value);
}
})
/**
* 修改整个加载进来的模型大小
*/
const fangdaButton = document.getElementById("fangda");
fangdaButton.addEventListener('click',(event)=>{
if(modelScene){
modelScene.scene.scale.set(++modelScene.scene.scale.x,++modelScene.scene.scale.y,++modelScene.scene.scale.z);
}
})
const suoxiaoButton = document.getElementById("suoxiao");
suoxiaoButton.addEventListener('click',(event)=>{
if(modelScene && modelScene.scene.scale.x>1){
modelScene.scene.scale.set(--modelScene.scene.scale.x,--modelScene.scene.scale.y,--modelScene.scene.scale.z);
}
})
const gLTFLoader = new GLTFLoader();
const oProcess = document.getElementById("process"); //用于显示加载进度
gLTFLoader.load(
"models/CesiumMan.glb",
(gltf) =>{
// console.log(1);
console.log(gltf);
// console.log(2);
modelScene = gltf
// gltf.scene.scale.set(10,10,10);
model = gltf.scene.children[0].children[1];
scene.add(gltf.scene);
},
(xhr) => {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
oProcess.textContent = ( xhr.loaded / xhr.total * 100 ) + '%'
},
(error) =>{
console.log(error);
}
);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
const animete = () => {
requestAnimationFrame(animete);
renderer.render(scene, camera);
};
animete();
</script>
<p id="process"></p>
<div id="operation">
<input type="button" value="放大" id="fangda">
<input type="button" value="缩小" id ="suoxiao">
<input type="color" id="color">
</div>
</body>
</html>
模型动画
按下W,控制动画。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body {
margin: 0;
}
#process{
position: absolute;
top:0;
left:0;
font-size:20px;
color: aliceblue;
}
#operation{
position: absolute;
top:0;
right:20px;
/* transform: translateX(-50%); */
}
</style>
</head>
<body>
<script type="module">
import * as THREE from "three";
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// import {Rhino3dmLoader} from 'three/examples/jsm/loaders/3DMLoader.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(5, 2, 0);
camera.lookAt(0, 0, 0);
// const cubeCamera = new THREE.Mesh(
// new THREE.SphereGeometry(0.2),
// new THREE.MeshBasicMaterial({color:0xff1ff1,wireframe:true})
// );
// //相机位置的向量,缩放0.6得到新的向量
// const pVector = camera.position.clone().multiplyScalar(0.8);
// cubeCamera.position.copy(pVector);
// scene.add(cubeCamera);
const renderer = new THREE.WebGLRenderer({
antialias: true
})
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
/**
* 创建地面
*/
const geometry2 = new THREE.PlaneGeometry(100, 100);
const material2 = new THREE.MeshStandardMaterial({ color: 0xffffff });
const plane = new THREE.Mesh(geometry2, material2);
//旋转
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.add(plane);
/**
* 创建立方体
*/
const cube1 = new THREE.Mesh(new THREE.BoxGeometry(3, 3, 3),new THREE.MeshStandardMaterial({color:0x404040}));
const cube2 = new THREE.Mesh(new THREE.BoxGeometry(2, 5, 3),new THREE.MeshStandardMaterial({color:0x404040}));
const cube3 = new THREE.Mesh(new THREE.BoxGeometry(3, 10, 4),new THREE.MeshStandardMaterial({color:0x404040}));
const cube4 = new THREE.Mesh(new THREE.BoxGeometry(3, 3, 5),new THREE.MeshStandardMaterial({color:0x404040}));
cube1.position.set(10, 0, 20);
cube2.position.set(-10, 0, 20);
cube3.position.set(10, 0, -20);
cube4.position.set(-10, 0, -20);
// cube1.castShadow = true;
scene.add(cube1,cube2,cube3,cube4);
/**
* 灯光
*/
//环境光
const ambientLight = new THREE.AmbientLight(0x404040); // 柔和的白光
scene.add(ambientLight);
// 平行光
const directionLight = new THREE.DirectionalLight(0xffffff, 3);
directionLight.castShadow = true;
//让阴影更清晰
directionLight.shadow.mapSize.width = 2048;
directionLight.shadow.mapSize.height = 2048;
//不设置以下内容看不见
directionLight.shadow.camera.left = -100;
directionLight.shadow.camera.right = 100;
directionLight.shadow.camera.top = 100;
directionLight.shadow.camera.bottom = -100;
directionLight.position.set(10, 20, 0);
const directionalLightHelper = new THREE.DirectionalLightHelper(directionLight, 5);
scene.add(directionLight);
let materialmodel;
let modelScene;
/**
* 修改模型颜色
*/
const oInput = document.getElementById("color");
//添加事件
oInput.addEventListener('input',(event)=>{
if(materialmodel){
materialmodel.material.color.set(event.target.value);
}
})
/**
* 修改整个加载进来的模型大小
*/
const fangdaButton = document.getElementById("fangda");
fangdaButton.addEventListener('click',(event)=>{
if(modelScene){
modelScene.scene.scale.set(++modelScene.scene.scale.x,++modelScene.scene.scale.y,++modelScene.scene.scale.z);
}
})
const suoxiaoButton = document.getElementById("suoxiao");
suoxiaoButton.addEventListener('click',(event)=>{
if(modelScene && modelScene.scene.scale.x>1){
modelScene.scene.scale.set(--modelScene.scene.scale.x,--modelScene.scene.scale.y,--modelScene.scene.scale.z);
}
// if(action) action.stop();
})
/**
* 换肤
*/
const huanfuButton = document.getElementById("huanfu");
huanfuButton.addEventListener('click',(event)=>{
if(materialmodel){
// 创建一个纹理贴图
const textureLoader = new THREE.TextureLoader();
const name = Math.floor(Math.random() * 55) + 1;
const texture = textureLoader.load('./img/'+name+'.jpg');
materialmodel.material.map = texture;
mesh.material.needsUpdate = true;
}
})
const gLTFLoader = new GLTFLoader();
const oProcess = document.getElementById("process"); //用于显示加载进度
let mixer; //动画用
let action;
gLTFLoader.load(
"models/CesiumMan.glb",
(gltf) =>{
console.log(gltf);
modelScene = gltf
materialmodel = gltf.scene.children[0].children[1];
//获取动作
const realmodel = gltf.scene;
const animations = gltf.animations;
mixer = new THREE.AnimationMixer(realmodel);
; const runClip = animations.find(clip => clip.name==="animation_0");
if(runClip){
action = mixer.clipAction(runClip);
// action.play();
// action.reset();
// action.stop();
}
scene.add(gltf.scene);
},
(xhr) => {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
oProcess.textContent = ( xhr.loaded / xhr.total * 100 ) + '%'
},
(error) =>{
console.log(error);
}
);
/**
* 键盘控制动作
*
*/
window.addEventListener("keydown",(event)=>{
if(event.code ==="KeyW" && !action.isRunning()){
// if(!action.isScheduled()){
// action.play();
// action.fadeIn(0.5);
// }
action.reset().fadeIn(0.5).play();
console.log(event.code);
//重置后慢慢启动动作
}
})
window.addEventListener("keyup",(event)=>{
if(event.code ==="KeyW"){
action.fadeOut(0.5);
}
})
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.addEventListener("change",()=>{
//获取合适的位置坐标
// console.log(camera.position);
})
const clock = new THREE.Clock();
const animete = () => {
//动画用
const elapsedTime = clock.getDelta();
// console.log(elapsedTime);
if(mixer) {
mixer.update(elapsedTime);
}
requestAnimationFrame(animete);
renderer.render(scene, camera);
};
animete();
</script>
<p id="process"></p>
<div id="operation">
<input type="button" value="放大" id="fangda">
<input type="button" value="缩小" id ="suoxiao">
<input type="button" value="换肤" id="huanfu">
<!-- <input type="button" value="换肤" id="stop"> -->
<input type="color" id="color">
</div>
</body>
</html>