Three.js 小变色龙和苍蝇

文化   2024-09-08 14:00   河南  

小变色龙看着苍蝇。你可以改变他的颜色

实现代码

HTML:

<div id='world'></div>
CSS:
body {  margin: 0;}#world {  position: absolute;  overflow: hidden;  width: 100%;  height: 100%;}

JAVASCRIPT:

'use strict';

let scene, camera, renderer, raycaster, controls, mouse;

let chameleon, branch, fly;

let width, height;

function init() { width = window.innerWidth, height = window.innerHeight; scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000); camera.position.set(30, 0, 10); camera.lookAt(scene.position);

renderer = new THREE.WebGLRenderer(); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(width, height); renderer.setClearColor(0xF2A9B4); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // controls = new THREE.OrbitControls(camera, renderer.domElement); raycaster = new THREE.Raycaster(); mouse = new THREE.Vector2(); addLights(); drawChameleon(); drawBranch(); drawFly(); document.getElementById('world').appendChild(renderer.domElement); document.addEventListener('mousemove', onMouseMove); document.addEventListener('touchmove', onTouchMove); window.addEventListener('resize', onResize, false);}

function addLights() { const light = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6); scene.add(light);

const directLight1 = new THREE.DirectionalLight(); directLight1.castShadow = true; directLight1.position.set(20, 13, 12); scene.add(directLight1);

const directLight2 = new THREE.DirectionalLight({ color: 0xd9fbfc, intensity: 0.6, }); directLight2.castShadow = true; directLight2.position.set(-27, 18, 6); scene.add(directLight2);}

function drawChameleon() { chameleon = new Chameleon(); scene.add(chameleon.group);}

function drawBranch() { branch = drawCylinder(0x17B26F, 0.76, 1.12, 2.14, 5); branch.position.set(-2.76, -5.67, -7.86); branch.rotation.set(rad(85.18), rad(4.14), rad(-20.4)); branch.scale.set(3.78, 11.92, 2.72); branch.castShadow = true; branch.receiveShadow = true; scene.add(branch);}

function drawFly() { fly = new Fly(); scene.add(fly.group);}

function onResize() { width = window.innerWidth; height = window.innerHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height);}

function onMouseMove(event) { mouse.x = (event.clientX / width) * 2 - 1; mouse.y = - (event.clientY / height) * 2 + 1;}

function onTouchMove(event) { event.preventDefault(); mouse.x = (event.touches[0].pageX / width) * 2 - 1; mouse.y = - (event.touches[0].pageY / height) * 2 + 1;}

function rad(degrees) { return degrees * (Math.PI / 180);}

function drawCylinder(materialColor, rTop, rBottom, height, radialSeg) { const geometry = new THREE.CylinderGeometry(rTop, rBottom, height, radialSeg); const material = new THREE.MeshStandardMaterial({ color: materialColor, roughness: 1, shading: THREE.FlatShading, }); const mesh = new THREE.Mesh(geometry, material); return mesh;}

function animate() { requestAnimationFrame(animate);

render();}

function render() { chameleon.changeColor(); chameleon.moveHead(fly.group.position);

fly.moveWings(); fly.moveFly(); renderer.render(scene, camera);}

class Chameleon { constructor() { this.group = new THREE.Group(); this.group.position.set(-1, 3, 2.7); this.group.rotation.set(rad(18.84), 0, rad(2.2)); this.material = new THREE.MeshStandardMaterial({ color: 0x1CCCA3, roughness: 1, shading: THREE.FlatShading, }); this.drawHead(); this.drawBody(); this.drawTail(); this.drawLegs(); this.group.traverse((object) => { if (object instanceof THREE.Mesh) { object.castShadow = true; object.receiveShadow = true; } }); } drawHead() { const headGeometry = new THREE.SphereGeometry(5, 4, 4); this.head = new THREE.Mesh(headGeometry, this.material); this.head.rotation.set(rad(90), rad(45), 0); this.group.add(this.head);

// draw eyes const rightEye = this.drawSkinCylinder(2, 1.3, 1.4, 5); rightEye.position.set(3, 1.6, 1.6); rightEye.rotation.set(rad(-27.2), rad(-45), rad(90)); this.head.add(rightEye);

const rightEyeWhite = drawCylinder(0xffffff, 1.26, 0.78, 1.14, 5); rightEyeWhite.position.set(0.02, -0.37, -0.06); rightEye.add(rightEyeWhite);

const rightEyeBlack = drawCylinder(0x3F3F3F, 0.86, 0.36, 1.14, 5); rightEyeBlack.position.set(-0.01, -0.27, -0.01); rightEyeWhite.add(rightEyeBlack);

const leftEye = rightEye.clone(); leftEye.position.set(-1.62, 1.47, -2.92); leftEye.rotation.set(rad(25), rad(-225), rad(82.8)); this.head.add(leftEye);

const leftEyeWhite = rightEyeWhite.clone(); leftEyeWhite.position.set(0.02, -0.37, -0.06); leftEye.add(leftEyeWhite);

const leftEyeBlack = rightEyeBlack.clone(); leftEyeBlack.position.set(-0.01, -0.27, -0.01); leftEyeWhite.add(leftEyeBlack);

// draw nose const nose = this.drawSkinCylinder(0.88, 3.52, 1.96, 4); nose.position.set(-0.02, 4.53, 0); this.head.add(nose);

// draw cap const cap = this.drawSkinCylinder(0.96, 3.5, 4, 4); cap.position.set(1.88, -1.54, -1.85); this.head.add(cap); } drawBody() { const body = new THREE.Object3D(); body.position.set(4.19, -4.51, -2.7); body.rotation.set(rad(62.4), rad(45), 0); this.group.add(body);

const neck = this.drawSkinCylinder(3.48, 7, 8, 4); neck.position.set(0, -1.46, -5.85); body.add(neck);

const torso = this.drawSkinCylinder(7, 3.9, 6, 4); torso.position.set(-0.03, -8.4, -5.87); body.add(torso);

const back = this.drawSkinCylinder(3.9, 1.4, 3, 4); back.position.set(-0.03, -12.9, -5.87); body.add(back); } drawTail() { const tail = this.drawSkinCylinder(2.14, 1.2, 8.7, 4); tail.position.set(0.05, -7.85, -17.43); tail.rotation.set(rad(48), rad(45), 0); this.group.add(tail);

const tailPart1 = this.drawSkinCylinder(1.2, 1, 13, 4); tailPart1.position.set(-3.76, -6.24, 3.92); tailPart1.rotation.set(rad(67.4), rad(45), rad(-116.6)); tail.add(tailPart1);

const tailPart2 = this.drawSkinCylinder(0.78, 1, 7, 4); tailPart2.position.set(-8.46, -5.13, 8.86); tailPart2.rotation.set(rad(17.6), rad(3), rad(16.2)); tail.add(tailPart2);

const tailPart3 = this.drawSkinCylinder(1.2, 0.76, 5, 4); tailPart3.position.set(-7.55, -1.35, 7.96); tailPart3.rotation.set(rad(67.4), rad(45), rad(-116.6)); tail.add(tailPart3);

const tailPart4 = this.drawSkinCylinder(1.2, 0.74, 4.06, 4); tailPart4.position.set(-5.24, -1.2, 5.52); tailPart4.rotation.set(rad(15.4), rad(2.8), rad(13)); tail.add(tailPart4); } drawLegs() { const rightLeg = this.drawSkinCylinder(1.56, 1, 3.96, 4); rightLeg.position.set(2.34, -5.86, -4.55); rightLeg.rotation.set(rad(-12.6), rad(53), 0); this.group.add(rightLeg);

const finger1 = this.drawSkinCylinder(0.4, 1.04, 2, 4); finger1.position.set(0.32, -1.55, 1.21); finger1.rotation.set(rad(105.4), rad(41), 0); rightLeg.add(finger1);

const finger2 = finger1.clone(); finger2.position.set(-0.76, -1.5, 0.61); finger2.rotation.set(rad(59.8), rad(39.6), rad(69.6)); rightLeg.add(finger2);

const finger3 = finger1.clone(); finger3.position.set(-1.11, -1.57, -0.58); finger3.rotation.set(rad(43.2), rad(-9.8), rad(120.8)); rightLeg.add(finger3);

const leftLeg = rightLeg.clone(); leftLeg.position.set(-2.08, -5.86, -4.55); leftLeg.rotation.set(rad(-20.6), rad(45), 0); this.group.add(leftLeg);

const backRightLeg = rightLeg.clone(); backRightLeg.position.set(2.39, -9.07, -10.93); backRightLeg.rotation.set(rad(-19.4), rad(51.2), rad(4.2)); backRightLeg.scale.set(0.7, 0.7, 0.7); this.group.add(backRightLeg);

const backLeftLeg = backRightLeg.clone(); backLeftLeg.position.set(-2.08, -8.9, -10.1); backLeftLeg.rotation.set(rad(-18), rad(28.6), 0); this.group.add(backLeftLeg); } changeColor() { raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(this.group.children, true);

if (intersects.length > 0) { if (intersects[0].object.material.color.getHexString() === 'ffffff' || intersects[0].object.material.color.getHexString() === '3f3f3f') return;

const time = Date.now() * 0.00005; const h = ((360 * (1.0 + time)) % 360) / 360; intersects[0].object.material.color.setHSL(h, 1.0, 0.6); } } moveHead(flyPosition) { this.head.lookAt(flyPosition); this.head.rotation.x += rad(90); this.head.rotation.y += rad(45); this.head.position.y = 1; } drawSkinCylinder(rTop, rBottom, height, radialSeg) { const geometry = new THREE.CylinderGeometry(rTop, rBottom, height, radialSeg); const mesh = new THREE.Mesh(geometry, this.material); return mesh; }}

class Fly { constructor() { this.group = new THREE.Group(); this.group.position.set(0, 12.71, 19.08); this.wingAngle = 0; this.drawBody(); this.drawWings(); } drawBody() { const flyGeometry = new THREE.BoxGeometry(1, 1, 1); const flyMaterial = new THREE.MeshStandardMaterial({ color: 0x3F3F3F, roughness: 1, shading: THREE.FlatShading, }); const fly = new THREE.Mesh(flyGeometry, flyMaterial); this.group.add(fly); } drawWings() { this.rightWing = drawCylinder(0xffffff, 0.42, 0.08, 1.26, 4); this.rightWing.position.set(0, 0.2, 0.6); this.rightWing.rotation.set(Math.PI / 4, 0, Math.PI / 4); this.rightWing.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, 0.21, 0.04)); this.group.add(this.rightWing);

this.leftWing = this.rightWing.clone(); this.leftWing.position.z = -this.rightWing.position.z; this.group.add(this.leftWing); } moveFly() { const timer = Date.now() * 0.0001; this.group.position.x = 4 * Math.cos(timer * 3); this.group.position.y = 5 * Math.sin(timer * 6); } moveWings() { this.wingAngle += 0.5; const wingAmplitude = Math.PI / 8; this.rightWing.rotation.x = (Math.PI / 4) - (Math.cos(this.wingAngle) * wingAmplitude); this.leftWing.rotation.x = (-Math.PI / 4) + (Math.cos(this.wingAngle) * wingAmplitude); }}

init();animate();



源码:

https://codepen.io/elliezen/pen/evXgdE


体验:

https://codepen.io/elliezen/full/evXgdE




感谢您的阅读      

在看点赞 好文不断  

初识Threejs
初识 Three.js 的奇妙世界,走进三维空间,与小编一起拥抱前端技术,涉及WebGL、WebGPU、Threejs、Shader、GIS、VR/AR、数字孪生、3D图形学等。
 最新文章