threejs打造3d跑车竞赛动画效果
代码语言:html
所属分类:三维
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> <style> body { margin: 0; overflow: hidden; } canvas { cursor: move; } </style> </head> <body translate="no"> <script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/three.js"></script> <script src='http://repo.bfw.wiki/bfwrepo/js/OrbitControls.js'></script> <script src='http://repo.bfw.wiki/bfwrepo/js/dat.gui.min.js'></script> <script > window.addEventListener("DOMContentLoaded", app); function app() { var scene, camera, renderer, textureLoader = new THREE.TextureLoader(), controls, GUI, road, cybertruck, ambientLight, daylight, fogColor; var adjustWindow = () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }, init = () => { // setup let licensePlate = textureLoader.load("http://repo.bfw.wiki/bfwrepo/image/5df5d982ef313.png"), grassTile = textureLoader.load("http://repo.bfw.wiki/bfwrepo/image/5df5d982ef313.png"), roadTile = textureLoader.load("http://repo.bfw.wiki/bfwrepo/image/5df5d96d46d8e.png"); scene = new THREE.Scene(); fogColor = { h: 215, s: 80, l: 80 }; scene.fog = new THREE.Fog(`hsl(${fogColor.h},${fogColor.s}%,${fogColor.l}%)`, 0.01, 272); camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(20, 10, 20); camera.lookAt(scene.position); renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: false }); renderer.setClearColor(scene.fog.color.getStyle()); renderer.setSize(window.innerWidth, window.innerHeight); renderer.shadowMap.enabled = true; let camControls = new THREE.OrbitControls(camera, renderer.domElement); camControls.enablePan = false; // road road = new Road(grassTile, roadTile); // cybertruck cybertruck = new Cybertruck(licensePlate); cybertruck.mesh.name = "Cybertruck"; cybertruck.mesh.position.y = cybertruck.height / 2; // ambient light ambientLight = new THREE.AmbientLight(0xffffff); ambientLight.intensity = 1; scene.add(ambientLight); // daylight daylight = new THREE.PointLight(0xffffff, ambientLight.intensity * 2); daylight.position.set(0, 64, 0); daylight.castShadow = true; scene.add(daylight); // config controls = { daylight: ambientLight.intensity, speed: cybertruck.speed, resetCam: () => { camControls.reset(); } }; GUI = new dat.GUI(); GUI.add(controls, "daylight", 0.1, 1, 0.01).name("Daylight").onChange(e => { let newVal = controls.daylight; cybertruck.headlight.intensity = (1 - newVal) * 2; cybertruck.rearlight.intensity = (1 - newVal) * 2; ambientLight.intensity = newVal; daylight.intensity = newVal * 2; let h = fogColor.h, s = fogColor.s, l = newVal * 100; fogColor.l = l * 0.8; let daylightColorStr = `hsl(${h},${s}%,${l.toFixed(0)}%)`, fogColorStr = `hsl(${h},${s}%,${fogColor.l.toFixed(0)}%)`; daylight.color = new THREE.Color(daylightColorStr); renderer.setClearColor(fogColorStr); scene.fog.color.set(fogColorStr); }); GUI.add(controls, "speed", 0, 60, 1).name("Speed (MPH)").onChange(e => { cybertruck.speed = controls.speed; }); GUI.add(controls, "resetCam").name("Reset Camera"); // first render document.body.appendChild(renderer.domElement); renderScene(); }, renderScene = () => { updateObjects(); renderer.render(scene, camera); requestAnimationFrame(renderScene); }, spawnObjects = () => { scene.add(road.mesh); scene.add(cybertruck.mesh); }, updateObjects = () => { if (scene.getObjectByName(cybertruck.mesh.name)) { cybertruck.move(); if (cybertruck.mesh.position.z > road.tileSize) cybertruck.mesh.position.z -= road.tileSize; let cybertruckZ = cybertruck.mesh.position.z; daylight.position.z = cybertruckZ; scene.position.z = -cybertruckZ; } }; init(); window.addEventListener("load", spawnObjects); window.addEventListener("resize", adjustWindow); } class Cybertruck { constructor(licensePlateImg) { this.speed = 5; this.wireframes = false; this.width = 8; this.height = 7.5; this.depth = 23; this.mesh = new THREE.Object3D(); let W = this.width, H = this.height, D = this.depth, flipXVertices = a => [-a[0], a[1], a[2]], toVectors = a => new THREE.Vector3(W * a[0], H * a[1], D * a[2]), reverseFaceDraws = a => a.reverse(), toFaces = a => new THREE.Face3(a[0], a[1], a[2]); // I. Body // A. Main let bodyVerticesArr = [ // back (0–3) [-0.45, 0.26, -0.5], [0.45, 0.26, -0.5], [-0.45, -0.1, -0.48], [0.45, -0.1, -0.48], // top (4–5) [-0.326, 0.5, 0.08], [0.326, 0.5, 0.08], // middle (6–19) [-0.45, -0.1, -0.38], [0.45, -0.1, -0.38], [-0.45, 0.06, -0.36], [0.45, 0.06, -0.36], [-0.45, 0.06, -0.24], [0.45, 0.06, -0.24], [-0.45, -0.15, -0.18], [0.45, -0.15, -0.18], [-0.45, -0.17, 0.255], [0.45, -0.17, 0.255], [-0.45, 0.06, 0.303], [0.45, 0.06, 0.303], [-0.45, 0.06, 0.42], [0.45, 0.06, 0.42], // upper front (20–23) [-0.45, 0.08, 0.47], [0.45, 0.08, 0.47], [-0.33, 0.045, 0.5], [0.33, 0.045, 0.5], // lower front (24–27) [-0.45, -0.13, 0.46], [0.45, -0.13, 0.46], [-0.343, -0.13, 0.488], [0.343, -0.13, 0.488], // bottom flaps (28–31) [-0.41, -0.21, -0.173], [0.41, -0.21, -0.173], [-0.41, -0.23, 0.25], [0.41, -0.23, 0.25], // windows (32–39) [-0.4225, 0.27, -0.14], [0.4225, 0.27, -0.14], [-0.379, 0.39, -0.13], [0.379, 0.39, -0.13], [-0.337, 0.47, 0.08], [0.337, 0.47, 0.08], [-0.425, 0.17, 0.36], [0.425, 0.17, 0.36]], bodyVertices = bodyVerticesArr.map(toVectors), bodyFacesArr = [ [0, 1, 3], [3, 2, 0], [0, 4, 5], [5, 1, 0], [5, 37, 35], [1, 5, 35], [1, 35, 33], [33, 21, 1], [39, 21, 33], [5, 21, 37], [21, 39, 37], [4, 34, 36], [0, 34, 4], [0, 32, 34], [32, 0, 20], [38, 32, 20], [4, 36, 20], [20, 36, 38], [20, 18, 24], [20, 0, 18], [18, 0, 16], [16, 0, 10], [10, 0, 8], [8, 0, 2], [2, 6, 8], [16, 10, 14], [12, 14, 10], [14, 12, 28], [28, 30, 14], [21, 25, 19], [21, 19, 1], [19, 17, 1], [17, 11, 1], [11, 9, 1], [1, 9, 7], [7, 3, 1], [11, 17, 15], [15, 13, 11], [15, 31, 29], [29, 13, 15], [5, 4, 20], [20, 21, 5], [21, 20, 22], [22, 23, 21], [22, 20, 24], [24, 26, 22], [23, 22, 26], [26, 27, 23], [23, 27, 25], [25, 21, 23], [2, 3, 7], [7, 6, 2], [6, 7, 9], [9, 8, 6], [8, 9, 11], [11, 10, 8], [10, 11, 13], [13, 12, 10], [12, 13, 29], [29, 28, 12], [28, 29, 31], [31, 30, 28], [30, 31, 15], [15, 14, 30], [14, 15, 17], [17, 16, 14], [16, 17, 19], [19, 18, 16], [18, 19, 25], [25, 24, 18], [24, 25, 26], [25, 27, 26], [34, 32, 33], [33, 35, 34], [34, 35, 37], [37, 36, 34], [36, 37, 39], [39, 38, 36], [33, 32, 38], [38, 39, 33]], bodyFaces = bodyFacesArr.map(toFaces), bodyGeo = new THREE.Geometry(), bodyMat = new THREE.MeshStandardMaterial({ color: 0xbac3c8, wireframe: this.wireframes }); bodyGeo.vertices = bodyVertices; bodyGeo.faces = bodyFaces; bodyGeo.computeFaceNormals(); let body = new THREE.Mesh(bodyGeo, bodyMat); this.mesh.add(body); // B. Door Handles let doorHandleGeo = new THREE.BoxGeometry(W * 0.01, W * 0.024, D * 0.0375), doorHandleFR = new THREE.Mesh(doorHandleGeo, bodyMat); // front right doorHandleFR.position.set(W * -0.45, H * 0.13, D * 0.0844); doorHandleFR.rotation.x = 4 * Math.PI / 180; body.add(doorHandleFR); // front left let doorHandleFL = doorHandleFR.clone(); doorHandleFL.position.x *= -1; body.add(doorHandleFL); // back right let doorHandleBR = doorHandleFR.clone(); doorHandleBR.position.y = H * 0.165; doorHandleBR.position.z = D * -0.1094; body.add(doorHandleBR); // back left let doorHandleBL = doorHandleBR.clone(); doorHandleBL.position.x *= -1; body.add(doorHandleBL); // C. Door Outlines let doorOutlineMat = new THREE.LineBasicMaterial({ color: 0x000000, transparent: true, opacity: 0.25 }), doorOutlineFLVerticesArr = [ [0.451, -0.17, 0.255], [0.451, 0.12, 0.255], [0.425, 0.192, 0.255], [0.424, 0.192, 0.255]], doorOutlineFLVertices = doorOutlineFLVerticesArr.map(toVectors), doorOutlineFLGeo = new THREE.Geometry(); // front left doorOutlineFLGeo.vertices = doorOutlineFLVertices; let doorOutlineFL = new THREE.Line(doorOutlineFLGeo, doorOutlineMat); this.mesh.add(doorOutlineFL); // front right let doorOutlineFRVerticesArr = doorOutlineFLVerticesArr.map(flipXVertices), doorOutlineFRVertices = doorOutlineFRVerticesArr.map(toVectors), doorOutlineFRGeo = new THREE.Geometry(); doorOutlineFRGeo.vertices = doorOutlineFRVertices; let doorOutlineFR = new THREE.Line(doorOutlineFRGeo, doorOutlineMat); this.mesh.add(doorOutlineFR); // middle left let doorOutlineMLVerticesArr = [ [0.41, -0.23, 0.0594], [0.4505, -0.16, 0.0594], [0.4505, 0.156, 0.0531], [0.424, 0.233, 0.05], [0.41, 0.233, 0.048]], doorOutlineMLVertices = doorOutlineMLVerticesArr.map(toVectors), doorOutlineMLGeo = new THREE.Geometry(); doorOutlineMLGeo.vertices = doorOutlineMLVertices; let doorOutlineML = new THREE.Line(doorOutlineMLGeo, doorOutlineMat); this.mesh.add(doorOutlineML); // middle right let doorOutlineMRVerticesArr = doorOutlineMLVerticesArr.map(flipXVertices), doorOutlineMRVertices = doorOutlineMRVerticesArr.map(toVectors), doorOutlineMRGeo = new THREE.Geometry(); doorOutlineMRGeo.vertices = doorOutlineMRVertices; let doorOutlineMR = new THREE.Line(doorOutlineMRGeo, doorOutlineMat); this.mesh.add(doorOutlineMR); // back left let doorOutlineBLVerticesArr = [ [0.399, -0.23, -0.1313], [0.45, -0.152, -0.1359], [0.4505, 0.195, -0.1406], [0.424, 0.2705, -0.1396], [0.4, 0.2705, -0.1396]], doorOutlineBLVertices = doorOutlineBLVerticesArr.map(toVectors), doorOutlineBLGeo = new THREE.Geometry(); doorOutlineBLGeo.vertices = doorOutlineBLVertices; let doorOutlineBL = new THREE.Line(doorOutlineBLGeo, doorOutlineMat); this.mesh.add(doorOutlineBL); // back right let doorOutlineBRVerticesArr = doorOutlineBLVerticesArr.map(flipXVertices), doorOutlineBRVertices = doorOutlineBRVerticesArr.map(toVectors), doorOutlineBRGeo = new THREE.Geometry(); doorOutlineBRGeo.vertices = doorOutlineBRVertices; let doorOutlineBR = new THREE.Line(doorOutlineBRGeo, doorOutlineMat); this.mesh.add(doorOutlineBR); // D. Fuel Cap let fuelCapVerticesArr = [ [0.4502, -0.014, -0.378], [0.4502, -0.014, -0.4], [0.4502, 0.06, -0.4], [0.4502, 0.06, -0.36]], fuelCapVertices = fuelCapVerticesArr.map(toVectors), fuelCapGeo = new THREE.Geometry(); fuelCapGeo.vertices = fuelCapVertices; let fuelCap = new THREE.Line(fuelCapGeo, doorOutlineMat); this.mesh.add(fuelCap); // II. Top Parts // A. Window let windowMat = new THREE.MeshStandardMaterial({ color: 0x101010, wireframe: this.wireframes }), lightMat = new THREE.MeshBasicMaterial({ color: 0xffffff, wireframe: this.wireframes }), topWindowVerticesArr = [ [-0.371, 0.415, -0.13], [0.371, 0.415, -0.13], [-0.326, 0.5, 0.08], [0.326, 0.5, 0.08], [-0.4145, 0.2, 0.36], [0.4145, 0.2, 0.36]], topWindowVertices = topWindowVerticesArr.map(toVectors), topWindowFacesArr = [ [1, 0, 2], [2, 3, 1], [3, 2, 4], [4, 5, 3]], topWindowFaces = topWindowFacesArr.map(toFaces), topWindowGeo = new THREE.Geometry(); topWindowGeo.vertices = topWindowVertices; topWindowGeo.faces = topWindowFaces; topWindowGeo.computeVertexNormals(); topWindowGeo.computeFaceNormals(); let topWindow = new THREE.Mesh(topWindowGeo, windowMat); this.mesh.add(topWindow); // B. Light let topLightVerticesArr = [ [-0.26, 0.49, 0.09], [0.26, 0.49, 0.09], [-0.26, 0.48, 0.1], [0.26, 0.48, 0.1]], topLightVertices = topLightVerticesArr.map(toVectors), topLightFacesArr = [ [1, 0, 2], [2, 3, 1]], topLightFaces = topLightFacesArr.map(toFaces), topLightGeo = new THREE.Geometry(); topLightGeo.vertices = topLightVertices; topLightGeo.faces = topLightFaces; topLightGeo.computeFaceNormals(); let topLight = new THREE.Mesh(topLightGeo, lightMat); this.mesh.add(topLight); // C. Sliding Door let slidingDoorMat = new THREE.MeshStandardMaterial({ color: 0x767c7f, wireframe: this.wireframes }), slidingDoorVerticesArr = [ [-0.35, 0.274, -0.472], [0.35, 0.274, -0.472], [-0.35, 0.407, -0.145], [0.35, 0.407, -0.145]], slidingDoorVertices = slidingDoorVerticesArr.map(toVectors), slidingDoorFacesArr = [ [1, 0, 2], [2, 3, 1]], slidingDoorFaces = slidingDoorFacesArr.map(toFaces), slidingDoorGeo = new THREE.Geometry(); slidingDoorGeo.vertices = slidingDoorVertices; slidingDoorGeo.faces = slidingDoorFaces; slidingDoorGeo.computeFaceNormals(); let slidingDoor = new THREE.Mesh(slidingDoorGeo, slidingDoorMat); this.mesh.add(slidingDoor); // III. Side Windows let sideWindowsVerticesArr = [ [-0.4, 0.27, -0.14], [0.4, 0.27, -0.14], [-0.351, 0.39, -.........完整代码请登录后点击上方下载按钮下载查看
网友评论0