UNPKG

use-on-demand

Version:
674 lines (591 loc) 20 kB
let scene, camera; let renderer; var width, width; const cars = []; // var stats const config = { isMobile: false, background: 0x282828, }; width = window.innerWidth; height = window.innerHeight; scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(45, width / height, 1, 5000); camera.position.set(330, 330, 330); camera.lookAt(scene.position); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(width, height); renderer.setClearColor(config.background); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; document.body.appendChild(renderer.domElement); checkUserAgent(); buildAuxSystem(); buildLightSystem(); buildbuilding(); buildRoad(); buildStaticCars(); buildMovingCars(); loop(); onWindowResize(); function checkUserAgent() { const n = navigator.userAgent; if (n.match(/Android/i) || n.match(/webOS/i) || n.match(/iPhone/i) || n.match(/iPad/i) || n.match(/iPod/i) || n.match(/BlackBerry/i)) { config.isMobile = true; camera.position.set(420, 420, 420); renderer.shadowMap.enabled = false; } } function buildMovingCars() { const carsPosition = [ [-130, 145, 0], [10, 145, 0], [145, 20, 0.5], [30, -145, 1], [-145, -60, 1.5], ]; carsPosition.forEach(function(elem) { const car = new Car(); const x = elem[0], z = elem[1], r = elem[2]; car.setPosition(x, 0, z); car.mesh.rotation.y = r * Math.PI; cars.push(car); scene.add(car.mesh); }); } function buildStaticCars() { const carsPosition = [ [-84, 82, 1.5], [-58, 82, 1.5], [-32, 82, 1.5], [84, 82, 1.5], ]; carsPosition.forEach(function(elem) { const car = new Car(); const x = elem[0], z = elem[1], r = elem[2]; car.setPosition(x, 0, z); car.mesh.rotation.y = r * Math.PI; scene.add(car.mesh); }); } function buildRoad() { const road = new THREE.Object3D(); const roadColor = 0xffffff; const roadBorderOuterCoords = [ [-160, 160], [160, 160], [160, -160], [-160, -160], ]; const roadBorderOuterHoleCoords = [ [-159, 159], [-159, -159], [159, -159], [159, 159], ]; const roadBorderOuterShape = utils.makeShape(roadBorderOuterCoords, roadBorderOuterHoleCoords); const roadBorderOuterGeometry = utils.makeExtrudeGeometry(roadBorderOuterShape, 0.1); const roadBorderOuter = utils.makeMesh('phong', roadBorderOuterGeometry, roadColor); road.add(roadBorderOuter); const roadBorderInnerCoords = [ [-131, 131], [-131, -131], [131, -131], [131, 131], [19, 131], [19, 99], [99, 99], [99, -99], [-99, -99], [-99, 99], [-19, 99], [-19, 131], ]; const roadBorderInnerShape = utils.makeShape(roadBorderInnerCoords); const roadBorderInnnerGeometry = utils.makeExtrudeGeometry(roadBorderInnerShape, 0.1); const roadBoaderInnder = utils.makeMesh('phong', roadBorderInnnerGeometry, roadColor); roadBoaderInnder.rotation.y = Math.PI; road.add(roadBoaderInnder); let roadLinesGeometry = new THREE.Geometry(); const roadLineGeometry = new THREE.BoxGeometry(20, 0.1, 2); const roadLinesBottomGeometry = new THREE.Geometry(); for (let i = 0; i < 9; i++) { const geometry = roadLineGeometry.clone(); geometry.translate(i * 30, 0, -1); roadLinesBottomGeometry.merge(geometry); } roadLinesBottomGeometry.translate(-120, 0, 145); roadLinesGeometry.merge(roadLinesBottomGeometry); const roadLinesTopGeometry = roadLinesBottomGeometry.clone(); roadLinesTopGeometry.translate(0, 0, -290); roadLinesGeometry.merge(roadLinesTopGeometry); const roadLinesLeftGeometry = roadLinesBottomGeometry.clone(); roadLinesLeftGeometry.rotateY(0.5 * Math.PI); roadLinesGeometry.merge(roadLinesLeftGeometry); const roadLinesRightGeometry = roadLinesBottomGeometry.clone(); roadLinesRightGeometry.rotateY(-0.5 * Math.PI); roadLinesGeometry.merge(roadLinesRightGeometry); roadLinesGeometry = new THREE.BufferGeometry().fromGeometry(roadLinesGeometry); const roadLines = utils.makeMesh('phong', roadLinesGeometry, roadColor); road.add(roadLines); scene.add(road); } function buildbuilding() { const planeGeometry = new THREE.BoxBufferGeometry(320, 6, 320); const plane = utils.makeMesh('lambert', planeGeometry, 0x6f5f6a); plane.position.y = -3; scene.add(plane); addFense(); addGreen(); addTrees(); addHospital(); addLamps(); function addLamps() { const lampsPosition = [ [-12.5, 12.5, 1.25], [-7.5, 12.5, -0.5], [-2.5, 12.5, -0.5], [2.5, 12.5, -0.5], [7.5, 12.5, -0.5], [12.5, 12.5, -0.25], [12.5, 7.5, 0], [12.5, 2.5, 0], [12.5, -2.5, 0], [12.5, -7.5, 0], [12.5, -12.5, 0.25], [7.5, -12.5, 0.5], [2.5, -12.5, 0.5], [-2.5, -12.5, 0.5], [-7.5, -12.5, 0.5], [-12.5, -12.5, 0.75], [-12.5, -7.5, 1], [-12.5, -2.5, 1], [-12.5, 2.5, 1], [-12.5, 7.5, 1], ]; lampsPosition.forEach(function(elem) { const x = elem[0] * 10, z = elem[1] * 10, r = elem[2]; const lamp = createLamp(); lamp.rotation.y = r * Math.PI; lamp.position.set(x, 0, z); scene.add(lamp); }); } function addHospital() { const hospital = createHospital(); hospital.position.z = -20; scene.add(hospital); } function addGreen() { const greenCoords = [ [-120, -120], [-120, 120], [120, 120], [120, -120], [20, -120], [20, -100], [100, -100], [100, 100], [-100, 100], [-100, -100], [-20, -100], [-20, -120], [-120, -120], ]; const greenShape = utils.makeShape(greenCoords); const greenGeometry = utils.makeExtrudeGeometry(greenShape, 3); const green = utils.makeMesh('lambert', greenGeometry, 0xc0c06a); scene.add(green); } function addFense() { const fenseCoords = [ [-130, -130], [-130, 130], [130, 130], [130, -130], [20, -130], [20, -120], [120, -120], [120, 120], [-120, 120], [-120, -120], [-20, -120], [-20, -130], [-130, -130], ]; const fenseShape = utils.makeShape(fenseCoords); const fenseGeometry = utils.makeExtrudeGeometry(fenseShape, 3); const fense = utils.makeMesh('lambert', fenseGeometry, 0xe5cabf); scene.add(fense); } function addTrees() { const treesPosition = [ [-110, -110], [-90, -110], [-70, -110], [-50, -110], [-30, -110], [-10, -110], [10, -110], [30, -110], [50, -110], [70, -110], [90, -110], [-110, 110], [-110, 90], [-110, 70], [-110, 50], [-110, 30], [-110, 10], [-110, -10], [-110, -30], [-110, -50], [-110, -70], [-110, -90], [110, 110], [90, 110], [70, 110], [50, 110], [30, 110], [-30, 110], [-50, 110], [-70, 110], [-90, 110], [110, -110], [110, -90], [110, -70], [110, -50], [110, -30], [110, -10], [110, 10], [110, 30], [110, 50], [110, 70], [110, 90], ]; treesPosition.forEach(function(elem) { const x = elem[0], y = 1, z = elem[1]; const tree = createTree(x, y, z); scene.add(tree); }); } function createLamp() { const lamp = new THREE.Object3D(); const pillarGeomertry = new THREE.CubeGeometry(2, 30, 2); pillarGeomertry.translate(0, 15, 0); const pillar = utils.makeMesh('phong', pillarGeomertry, 0xebd1c2); lamp.add(pillar); const connectGeometry = new THREE.CubeGeometry(10, 1, 1); const connect = utils.makeMesh('phong', connectGeometry, 0x2c0e0e); connect.position.set(3, 30, 0); lamp.add(connect); const lightGeometry = new THREE.CubeGeometry(6, 2, 4); light = utils.makeMesh('phong', lightGeometry, 0xebd1c2); light.position.set(10, 30, 0); lamp.add(light); return lamp; } function createHospital() { const hospital = new THREE.Object3D(); const baseGeometry = new THREE.BoxBufferGeometry(180, 3, 140); const base = utils.makeMesh('lambert', baseGeometry, 0xffffff); base.position.y = 1; hospital.add(base); const frontMainCoords = [ [-80, -30], [-80, 20], [50, 20], [50, 0], [20, -30], [-80, -30], ]; const frontMainShape = utils.makeShape(frontMainCoords); const frontMainGeometry = utils.makeExtrudeGeometry(frontMainShape, 100); const frontMainMaterial = new THREE.MeshPhongMaterial({ map: textures.window() }); frontMainMaterial.map.repeat.set(0.1, 0.08); const frontMain = new THREE.Mesh(frontMainGeometry, frontMainMaterial); frontMain.castShadow = true; frontMain.receiveShadow = true; hospital.add(frontMain); const frontTopShape = frontMainShape; const frontTopGeometry = utils.makeExtrudeGeometry(frontTopShape, 5); const frontTop = utils.makeMesh('lambert', frontTopGeometry, 0xb1a7af); frontTop.position.y = 100; hospital.add(frontTop); let frontRoofShelfGeometry = new THREE.Geometry(); const frontRoofShelfCubeGeometry = new THREE.BoxGeometry(2, 2, 40); // for z-axis for (var i = 0; i < 12; i++) { var geometry = frontRoofShelfCubeGeometry.clone(); geometry.translate(i * 5, 0, 0); frontRoofShelfGeometry.merge(geometry); } // for x-axis for (var i = 0; i < 2; i++) { var geometry = frontRoofShelfCubeGeometry.clone(); geometry.rotateY(0.5 * Math.PI); geometry.scale(1.6, 1, 1); geometry.translate(27, 0, -15 + i * 30); frontRoofShelfGeometry.merge(geometry); } // for y-axis const frontRoofShelfCubeYPosition = [ [0, 0], [1, 0], [0, 1], [1, 1], ]; for (var i = 0; i < frontRoofShelfCubeYPosition.length; i++) { const p = frontRoofShelfCubeYPosition[i]; var geometry = frontRoofShelfCubeGeometry.clone(); geometry.scale(1, 1, 0.4); geometry.rotateX(0.5 * Math.PI); geometry.translate(p[0] * 55, 0, -15 + p[1] * 30); frontRoofShelfGeometry.merge(geometry); } frontRoofShelfGeometry = new THREE.BufferGeometry().fromGeometry(frontRoofShelfGeometry); const frontRoofShelf = utils.makeMesh('phong', frontRoofShelfGeometry, 0xffffff); frontRoofShelf.position.set(-70, 115, 5); hospital.add(frontRoofShelf); const frontPlatGeometry = new THREE.BoxBufferGeometry(150, 3, 90); const fronPlat = utils.makeMesh('lambert', frontPlatGeometry, 0x0792a5); fronPlat.position.set(-3, 18, 25); hospital.add(fronPlat); const frontPlatVerticalGeometry = new THREE.BoxBufferGeometry(150, 15, 3); const frontPlatVertical = utils.makeMesh('phong', frontPlatVerticalGeometry, 0x0792a5); frontPlatVertical.receiveShadow = false; frontPlatVertical.position.set(-3, 24, 68.5); hospital.add(frontPlatVertical); const frontPlatVerticalWhiteGeometry = new THREE.BoxBufferGeometry(150, 3, 3); const frontPlatVerticalWhite = utils.makeMesh('phong', frontPlatVerticalWhiteGeometry, 0xffffff); frontPlatVerticalWhite.position.set(-3, 33, 68.5); hospital.add(frontPlatVerticalWhite); const frontPlatPillarGeometry = new THREE.CylinderGeometry(2, 2, 15, 32); const frontPlatPillar = utils.makeMesh('lambert', frontPlatPillarGeometry, 0xffffff); frontPlatPillar.position.set(-60, 10, 55); hospital.add(frontPlatPillar); const frontPlatPillar2 = frontPlatPillar.clone(); frontPlatPillar2.position.set(55, 10, 55); hospital.add(frontPlatPillar2); const frontBorderVerticles = new THREE.Object3D(); const frontBorderVerticleGeometry = new THREE.BoxBufferGeometry(4, 106, 4); const frontBorderVerticleMesh = utils.makeMesh('phong', frontBorderVerticleGeometry, 0xffffff); const frontBorderVerticle1 = frontBorderVerticleMesh.clone(); frontBorderVerticle1.position.set(-80, 52, 30); frontBorderVerticles.add(frontBorderVerticle1); const frontBorderVerticle2 = frontBorderVerticleMesh.clone(); frontBorderVerticle2.position.set(-80, 52, -20); frontBorderVerticles.add(frontBorderVerticle2); const frontBorderVerticle3 = frontBorderVerticleMesh.clone(); frontBorderVerticle3.position.set(50, 52, -18); frontBorderVerticles.add(frontBorderVerticle3); hospital.add(frontBorderVerticles); const frontRoofCoords = [ [-82, -32], [20, -32], [52, 0], [52, 22], [-82, 22], [-82, -32], ]; const frontRoofHolePath = [ [-78, -28], [20, -28], [48, 0], [48, 18], [-78, 18], [-78, -28], ]; const frontRoofShape = utils.makeShape(frontRoofCoords, frontRoofHolePath); const frontRoofGeometry = utils.makeExtrudeGeometry(frontRoofShape, 8); const frontRoof = utils.makeMesh('phong', frontRoofGeometry, 0xffffff); frontRoof.position.y = 100; hospital.add(frontRoof); const backMainCoords = [ [-80, 20], [-80, 60], [80, 60], [80, 20], [-80, 20], ]; const backMainHolePath = [ [-78, 22], [78, 22], [78, 58], [-78, 58], [-78, 22], ]; const backMainShape = utils.makeShape(backMainCoords, backMainHolePath); const backMainGeometry = utils.makeExtrudeGeometry(backMainShape, 90); const backMain = utils.makeMesh('lambert', backMainGeometry, 0xf2e21b); hospital.add(backMain); const backMiddleCoords = [ [0, 0], [36, 0], [36, 70], [0, 70], [0, 0], ]; const backMiddleHolePath = [ [2, 2], [34, 2], [34, 68], [2, 68], [2, 2], ]; const backMiddleShape = utils.makeShape(backMiddleCoords, backMiddleHolePath); const backMiddkeGeometry = utils.makeExtrudeGeometry(backMiddleShape, 165); const backMiddle = utils.makeMesh('lambert', backMiddkeGeometry, 0xffffff); backMiddle.rotation.x = -0.5 * Math.PI; backMiddle.rotation.z = -0.5 * Math.PI; backMiddle.position.y = 86; backMiddle.position.z = -58; backMiddle.position.x = -78; hospital.add(backMiddle); const backMiddleWindowGeometry = new THREE.PlaneGeometry(32, 66, 1, 1); const backMiddleWindowMaterial = new THREE.MeshPhongMaterial({ map: textures.window() }); backMiddleWindowMaterial.map.repeat.set(2, 6); const backMiddleWindow = new THREE.Mesh(backMiddleWindowGeometry, backMiddleWindowMaterial); backMiddleWindow.position.set(83, 51, -40); backMiddleWindow.rotation.y = 0.5 * Math.PI; hospital.add(backMiddleWindow); const windowBackOrigin = createWindow(); windowBackOrigin.scale.set(0.6, 0.6, 1); windowBackOrigin.rotation.y = Math.PI; windowBackOrigin.position.set(65, 75, -61); for (var i = 0; i < 7; i++) { for (let j = 0; j < 4; j++) { const windowObj = windowBackOrigin.clone(); windowObj.position.x -= i * 22; windowObj.position.y -= j * 20; hospital.add(windowObj); } } return hospital; } function createWindow() { const windowObj = new THREE.Object3D(); const glassGeometry = new THREE.PlaneGeometry(20, 20); const glass = utils.makeMesh('phong', glassGeometry, 0x6a5e74); windowObj.add(glass); const windowBorderGeometry = new THREE.BoxBufferGeometry(22, 2, 2); const windowBorder = utils.makeMesh('phong', windowBorderGeometry, 0xffffff); const windowBorderTop = windowBorder.clone(); windowBorderTop.position.y = 10; windowObj.add(windowBorderTop); const windowBorderBottom = windowBorder.clone(); windowBorderBottom.position.y = -10; windowObj.add(windowBorderBottom); const windowBorderLeft = windowBorder.clone(); windowBorderLeft.rotation.z = 0.5 * Math.PI; windowBorderLeft.position.x = -10; windowObj.add(windowBorderLeft); const windowBorderRight = windowBorderLeft.clone(); windowBorderRight.position.x = 10; windowObj.add(windowBorderRight); return windowObj; } function createTree(x, y, z) { var x = x || 0; var y = y || 0; var z = z || 0; const tree = new THREE.Object3D(); const treeTrunkGeometry = new THREE.BoxBufferGeometry(2, 16, 2); const treeTrunk = utils.makeMesh('lambert', treeTrunkGeometry, 0x8a613a); treeTrunk.position.y = 8; tree.add(treeTrunk); const treeLeafsGeometry = new THREE.BoxBufferGeometry(8, 8, 8); const treeLeafs = utils.makeMesh('lambert', treeLeafsGeometry, 0x9c9e5d); treeLeafs.position.y = 13; tree.add(treeLeafs); tree.position.set(x, y, z); return tree; } } function buildLightSystem() { if (!config.isMobile) { const directionalLight = new THREE.DirectionalLight(0xffffff, 1.1); directionalLight.position.set(300, 1000, 500); directionalLight.target.position.set(0, 0, 0); directionalLight.castShadow = true; const d = 300; directionalLight.shadow.camera = new THREE.OrthographicCamera(-d, d, d, -d, 500, 1600); directionalLight.shadow.bias = 0.0001; directionalLight.shadow.mapSize.width = directionalLight.shadow.mapSize.height = 1024; scene.add(directionalLight); var light = new THREE.AmbientLight(0xffffff, 0.3); scene.add(light); } else { const hemisphereLight = new THREE.HemisphereLight(0xffffff, 1); scene.add(hemisphereLight); var light = new THREE.AmbientLight(0xffffff, 0.15); scene.add(light); } } function buildAuxSystem() { // stats = new Stats() // stats.setMode(0) // stats.domElement.style.position = 'absolute' // stats.domElement.style.left = '5px' // stats.domElement.style.top = '5px' // document.body.appendChild(stats.domElement) // var axisHelper = new THREE.AxesHelper(200) // scene.add(axisHelper) const gridHelper = new THREE.GridHelper(320, 32); scene.add(gridHelper); const controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.25; controls.rotateSpeed = 0.35; } function carMoving(car) { const angle = car.mesh.rotation.y; const x = car.mesh.position.x, z = car.mesh.position.z; if (x < 145 && z === 145) { car.forward(); } else if (angle < 0.5 * Math.PI) { car.turnLeft(0.5 * Math.PI, 0.1); } else if (x === 145 && z > -145) { car.forward(); } else if (angle < Math.PI) { car.turnLeft(0.5 * Math.PI, 0.1); } else if (x > -145 && z == -145) { car.forward(); } else if (angle < 1.5 * Math.PI) { car.turnLeft(0.5 * Math.PI, 0.1); } else if (x === -145 && z < 145) { car.mesh.rotation.y = 1.5 * Math.PI; car.forward(); } else if (angle < 2 * Math.PI) { car.turnLeft(0.5 * Math.PI, 0.1); } else { car.setPosition(-145, 0, 145); car.mesh.rotation.set(0, 0, 0); } } function loop() { // stats.update() cars.forEach(function(car) { carMoving(car); }); renderer.render(scene, camera); requestAnimationFrame(loop); } function onWindowResize() { window.addEventListener('resize', function() { width = window.innerWidth; height = window.innerHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height); }); }