рд╕рдмрд╕реЗ рдЫреЛрдЯреЗ рдХреЗ рд▓рд┐рдП рддреАрди.js рдкрд░ рддреАрди рдЖрдпрд╛рдореА рдЙрддреНрдкрд╛рдж рдкреНрд░рд╕реНрддреБрддрд┐рдпреЛрдВ


3 рдбреА рдореЗрдВ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рдЙрддреНрдкрд╛рдж рдкреНрд░рд╕реНрддреБрддрд┐рдпрд╛рдВ рд╣рдорд╛рд░реЗ рд╕рдордп рдореЗрдВ рдЗрддрдиреА рджреБрд░реНрд▓рдн рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпреЗ рдХрд╛рд░реНрдп рд╢реБрд░реБрдЖрддреА рдбреЗрд╡рд▓рдкрд░реНрд╕ рд╕реЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╕рд╡рд╛рд▓ рдкреИрджрд╛ рдХрд░рддреЗ рд╣реИрдВред рдЖрдЬ рд╣рдо рдХреБрдЫ рдЖрдзрд╛рд░рднреВрдд рдмрд╛рддреЛрдВ рдкрд░ рдЧреМрд░ рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдЗрд╕ рд╡рд┐рд╖рдп рдореЗрдВ рдЖрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреА рдФрд░ рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рддреНрд░рд┐-рдЖрдпрд╛рдореА рдореЙрдбрд▓ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдЬреИрд╕реЗ рд╕рд░рд▓ рдХрд╛рд░реНрдп рдкрд░ рдареЛрдХрд░ рдирд╣реАрдВ рдЦрд╛рдПрдЧреАред рдПрдХ рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рдЙрдкрдХрд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдереНрд░реА.рдЬреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред


рдХрд╛рдо рдкрд░ рд▓рдЧрдирд╛


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЕрдкрдиреЗ рд▓рд┐рдП рдПрдХ HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдмрдирд╛рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЛ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдХрд┐рд╕реА рднреА рдЪреАрдЬрд╝ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рдХреЛрдИ рдЕрд╕реЗрдВрдмрд▓рд░, рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░, рдЖрджрд┐ред


рд╣рдореЗрдВ рдХреИрдирд╡рд╛рд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдВрдЯреЗрдирд░ рдФрд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдЪрд╛рд╣рд┐рдП - рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рддреАрди.js, obj рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓реЛрдбрд░, рдФрд░ рдорд╛рдЙрд╕ рдХреЗ рд╕рд╛рде рдХреИрдорд░реЗ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯред


<div class='canvas-container'></div> <script src='https://unpkg.com/three@0.99.0/build/three.min.js'></script> <script src='https://unpkg.com/three@0.99.0/examples/js/loaders/OBJLoader.js'></script> <script src='https://unpkg.com/three@0.99.0/examples/js/controls/OrbitControls.js'></script> <script src='./main.js'></script> 

рдпрджрд┐ рдЖрдкрдХрд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ NPM рдФрд░ рдмрд┐рд▓реНрдбрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЖрдк рдкреИрдХреЗрдЬ рддреАрди рд╕реЗ рдпрд╣ рд╕рдм рдЖрдпрд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рджрд░рдЕрд╕рд▓, рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЛ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ, рддреЛ рдЕрдирдкреИрдХ рд╕рднреА рдПрдирдкреАрдПрдо рдкреИрдХреЗрдЬ рд▓реЗрддрд╛ рд╣реИред


рдпрджрд┐ рдЖрдкрдХреЛ рдХреБрдЫ рдкреИрдХреЗрдЬ рд╕реЗ рдЕрдкрдиреЗ рдкреЗрдЬ рдкрд░ рдЬрд▓реНрджреА рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рд╕реАрдбреАрдПрди рдХрд╛ рд▓рд┐рдВрдХ рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИ - рдЕрдирдкреИрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдпрд╛рдж рд░рдЦреЗрдВ, рддреЛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдореБрдЦреНрдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдХреЗ рдПрдХ рд╕рдореВрд╣ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрдЧреАред рдпрд╣ рдЙрджрд╛рд╣рд░рдг рдХреЛ рд╕рд░рд▓ рдХрд░реЗрдЧрд╛ред


 let SCENE; let CAMERA; let RENDERER; let LOADING_MANAGER; let IMAGE_LOADER; let OBJ_LOADER; let CONTROLS; let MOUSE; let RAYCASTER; let TEXTURE; let OBJECT; 

рдереНрд░реА.рдЬреЗрдПрд╕ рдореЗрдВ, рдпрд╣ рд╕рднреА рджреГрд╢реНрдп рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВ рдФрд░ рдХреБрдЫ рдкреНрд░рдХрд╛рд╢ рд╕реНрд░реЛрдд рдмрдирд╛рдПрдВ:


 function initScene() { SCENE = new THREE.Scene(); initLights(); } function initLights() { const ambient = new THREE.AmbientLight(0xffffff, 0.7); SCENE.add(ambient); const directionalLight = new THREE.DirectionalLight(0xffffff); directionalLight.position.set(0, 1, 1); SCENE.add(directionalLight); } 

рдкреНрд░рдХрд╛рд╢ рд╕реНрд░реЛрдд рдЕрд▓рдЧ рд╣реИрдВред рдЬреНрдпрд╛рджрд╛рддрд░ рдРрд╕реЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ, рдкрд░рд┐рд╡реЗрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рджрд┐рд╢рд╛ рдореЗрдВ рдкреНрд░рдХрд╛рд╢ рднрд░рдирд╛, рдФрд░ рджрд┐рд╢рд╛рддреНрдордХ - рдкреНрд░рдХрд╛рд╢ред рдЕрднреА рднреА рдкреНрд░рдХрд╛рд╢ рдХреЗ рдмрд┐рдВрджреБ рд╕реНрд░реЛрдд рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдЕрднреА рддрдХ рдЙрдирдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рд╣рдо рдЪрдордХ рдХреЗ рд░рдВрдЧ рдХреЛ рд╕рдлреЗрдж рдмрдирд╛рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдХреЛрдИ рд╡рд┐рдХреГрддрд┐рдпрд╛рдВ рди рд╣реЛрдВред


рднрд░рдг рдЪрдордХ рдХреЗ рд░рдВрдЧ рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рднреВрд░реЗ рд░рдВрдЧ рдХреЗ рд░рдВрдЧреЛрдВ рдХреЗ рд╕рд╛рде, рдЗрд╕рд▓рд┐рдП рдЖрдк рдПрдХ рдирд░рдо рдЫрд╡рд┐ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред

рджреВрд╕рд░реА рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЪреАрдЬ рдХреИрдорд░рд╛ рд╣реИред рдпрд╣ рдПрдХ рдРрд╕реА рдЗрдХрд╛рдИ рд╣реИ рдЬреЛ рдЙрд╕ рдмрд┐рдВрджреБ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреА рд╣реИ рдЬрд┐рд╕ рдкрд░ рд╣рдо рд╣реИрдВ рдФрд░ рдЬрд┐рд╕ рджрд┐рд╢рд╛ рдореЗрдВ рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВред


 function initCamera() { CAMERA = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000); CAMERA.position.z = 100; } 

рдХреИрдорд░рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рдЖрдорддреМрд░ рдкрд░ рдЖрдВрдЦ рд╕реЗ рдЪреБрдиреЗ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдореЙрдбрд▓ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреЗ рд╣реИрдВред


рддреАрд╕рд░реА рд╡рд╕реНрддреБ рдЬреЛ рд╣рдореЗрдВ рдЪрд╛рд╣рд┐рдП рд╡рд╣ рд╣реИ рд░реЗрдВрдбрд░ред рд╡рд╣ рдЫрд╡рд┐ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдЗрд╕рдХрд╛ рдкреНрд░рд╛рд░рдВрдн рд╕реНрд╡рдпрдВ рдмреЛрд▓рддрд╛ рд╣реИ:


 function initRenderer() { RENDERER = new THREE.WebGLRenderer({ alpha: true }); RENDERER.setPixelRatio(window.devicePixelRatio); RENDERER.setSize(window.innerWidth, window.innerHeight); } 

рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рд╛рд░реВрдкреЛрдВ рдХреЗ рдбреЗрдЯрд╛ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓реЛрдбрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣рд╛рдВ рдЖрдк рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рдПрдХ рд▓рдВрдмреА рд╕реВрдЪреА рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдХреЗрд╡рд▓ рджреЛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдЪрд┐рддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ (рдпрд╣ рдХрд┐рдЯ рдХреЗ рд╕рд╛рде рдЖрддрд╛ рд╣реИ) рдФрд░ рдПрдХ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП (рд╣рдордиреЗ рдЗрд╕реЗ рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЬреЛрдбрд╝рд╛)ред


 function initLoaders() { LOADING_MANAGER = new THREE.LoadingManager(); IMAGE_LOADER = new THREE.ImageLoader(LOADING_MANAGER); OBJ_LOADER = new THREE.OBJLoader(LOADING_MANAGER); } 

рд╣рдо рдореЙрдбрд▓ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рдЬреИрд╕рд╛ рдХрд┐ рдЕрдкреЗрдХреНрд╖рд┐рдд рдерд╛, рдпрд╣ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд░реВрдк рд╕реЗ рд╣реЛрддрд╛ рд╣реИред рдореЙрдбрд▓ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЗрд╕рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдЦреЗрд▓ рд╕рдХрддреЗ рд╣реИрдВ:


 function loadModel() { OBJ_LOADER.load('./model.obj', (object) => { object.scale.x = 0.3; object.scale.y = 0.3; object.scale.z = 0.3; object.rotation.x = -Math.PI / 2; object.position.y = -30; OBJECT = object; SCENE.add(OBJECT); }); } 

рдпрд╣ рдмреИрд░рд▓ рдЕрдВрдЧ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИ:


 function animate() { requestAnimationFrame(animate); render(); } function render() { CAMERA.lookAt(SCENE.position); RENDERER.render(SCENE, CAMERA); } 

рдирддреАрдЬрддрди, рд╣рдореЗрдВ рдЫрд╛рдпрд╛ рдХреЗ рд╕рд╛рде рдмрд╕ рдПрдХ рд╕рдлреЗрдж рдХреНрд░рд┐рд╕рдорд╕ рдХрд╛ рдкреЗрдбрд╝ рдорд┐рд▓рддрд╛ рд╣реИ (рдореИрдВрдиреЗ рдпрд╣рд╛рдВ рд╕реЗ рдореЙрдбрд▓ рд▓рд┐рдпрд╛)ред



рдПрдХ, рджреЛ, рддреАрди, рдХреНрд░рд┐рд╕рдорд╕ рдЯреНрд░реА рдЬрд▓рд╛! рд▓реЗрдХрд┐рди рдмрдирд╛рд╡рдЯ рдХреЗ рдмрд┐рдирд╛, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдпрд╣ рдЬрд▓рд╛ рдирд╣реАрдВ рдЬрд╛рдПрдЧрд╛ред рд╣рд╛рдВ, рдФрд░ рд╣рдо рдХреБрдЫ рдЕрдиреНрдп рд╕рдордп рдЖрдЧ рдФрд░ рдЕрдиреНрдп рддрддреНрд╡реЛрдВ рдХреА рдЫрд╛рдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ ... рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрд░рд┐рд╕рдорд╕ рдЯреНрд░реА рдХрд╛ рдореЙрдбрд▓ "рдЯреАрд╡реА рдкрд░" рд╣реИред


рдмрдирд╛рд╡рдЯ рдкрд░ рдЬрд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЗрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдЖрдХрд╛рд░ рдмрджрд▓рдиреЗ рд╡рд╛рд▓реА рдПрдХ рдорд╛рдирдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╡рд┐рдВрдбреЛ рдЬреЛрдбрд╝рдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реИ:


 function initEventListeners() { window.addEventListener('resize', onWindowResize); onWindowResize(); } function onWindowResize() { CAMERA.aspect = window.innerWidth / window.innerHeight; CAMERA.updateProjectionMatrix(); RENDERER.setSize(window.innerWidth, window.innerHeight); } 

рдмрдирд╛рд╡рдЯ рдЬреЛрдбрд╝реЗрдВ


рд╣рдорд╛рд░реЗ рдореЙрдбрд▓ рдФрд░ рдЪрд┐рддреНрд░ рдмрдирд╛рд╡рдЯ рдмрдЪреНрдЪреЛрдВ рдХреЗ рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рдореЙрдбрд▓ рдкрд░ рд╕реНрдЯрд┐рдХрд░-рдЕрдиреБрд╡рд╛рджрдХреЛрдВ рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддреЗ рд╣реИрдВ, рд╡реЗрдмрдЬреАрдПрд▓ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ рдореЗрдВ рддреНрд░рд┐рдХреЛрдгреЛрдВ рдХрд╛ рдвреЗрд░ рд╣реЛрддрд╛ рд╣реИред рдЕрдкрдиреЗ рдЖрдк рд╕реЗ, рдЙрдирдХреЗ рдкрд╛рд╕ рдХреЛрдИ рд░рдВрдЧ рдирд╣реАрдВ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рддреНрд░рд┐рдХреЛрдг рдХреЗ рд▓рд┐рдП рдмрдирд╛рд╡рдЯ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рддреНрд░рд┐рдХреЛрдгреАрдп "рд╕реНрдЯрд┐рдХрд░" рд╣реИ рдЬрд┐рд╕реЗ рдЖрдкрдХреЛ рдЙрд╕ рдкрд░ рдЫрдбрд╝реА рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ 1000 рддреНрд░рд┐рдХреЛрдг рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ 1000 рдмрдирд╛рд╡рдЯ рдЪрд┐рддреНрд░реЛрдВ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ? рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВред рд╕реНрдкреНрд░рд╛рдЗрдЯ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╕реАрдПрд╕рдПрд╕ рдЖрдЗрдХрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рд╣реИ (рдЖрдк рд╢рд╛рдпрдж рдХрд╛рдо рдкрд░ рдЙрдирдХреЗ рдкрд╛рд╕ рдЖрдП рдереЗ), рдФрд░ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╣реИ рдХрд┐ рдореЙрдбрд▓ рдХреЛ рдХрд┐рд╕ рддреНрд░рд┐рднреБрдЬ рдФрд░ рдХрд╣рд╛рдВ рдкрд░ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред рдФрд░ рдлрд┐рд░ рддреАрди.js рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рд╕рдм рдХреБрдЫ рд╕рдордЭрддреЗ рд╣реИрдВ рдФрд░ рд╣рдо рддреИрдпрд╛рд░ рдкрд░рд┐рдгрд╛рдо рджреЗрдЦрддреЗ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд┐рдЪрд╛рд░ рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╕рдордЭрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред


рдХреНрд░рд┐рд╕рдорд╕ рдЯреНрд░реА рдХреА рд╢рд╛рдЦрд╛рдПрдВ рдПрдХ рдмрд╣реБрдд рд╣реА рдЦреБрд▓рд╛рд╕рд╛ рдЙрджрд╛рд╣рд░рдг рдирд╣реАрдВ рд╣реИрдВред рд╡реЗ рд╕рднреА рд╕рдорд╛рди рд╣реИрдВред рдЗрд╕ рддрд░рд╣ рдХреА рдмрдирд╛рд╡рдЯ рдХреА рд╕рдВрд░рдЪрдирд╛ рдмрд▓реНрдмрд╕реМрд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ рдмрд╣реБрдд рдмреЗрд╣рддрд░ рджрд┐рдЦрд╛рдИ рджреЗрдЧреА:



рд▓реЗрдХрд┐рди рдкрд░реНрдпрд╛рдкреНрдд рд╢рдмреНрдж, рдЪрд▓реЛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдиреАрдЪреЗ рдЙрддрд░реЗрдВред рдмрдирд╛рд╡рдЯ рдХреЛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдХрд░реЗрдВ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдПрдХ рдЪрд┐рддреНрд░ рд▓реЛрдб рдХрд░реЗрдВ:


 function initTexture() { TEXTURE = new THREE.Texture(); } function loadTexture() { IMAGE_LOADER.load('./texture.jpg', (image) => { TEXTURE.image = image; TEXTURE.needsUpdate = true; }); } 

рдЕрдм рд╣рдореЗрдВ рдореЙрдбрд▓ рд▓реЛрдбрд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдЧрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдмрд▓реНрдмрд╕реМрд░ рдЬреИрд╕реА рдмрдирд╛рд╡рдЯ рд╣реЛрддреА, рддреЛ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реЛрддрд╛ред рд▓реЗрдХрд┐рди рдХреНрд░рд┐рд╕рдорд╕ рдХреЗ рдкреЗрдбрд╝ рдХреЗ рд╕рд╛рде, рдмрдирд╛рд╡рдЯ рдХреЗрд╡рд▓ рд╢рд╛рдЦрд╛рдУрдВ рдХреЛ рдХрд╡рд░ рдХрд░рддреА рд╣реИред рдЙрдиреНрд╣реЗрдВ рдХрд┐рд╕реА рддрд░рд╣ рдЕрд▓рдЧ рдХрд░рдирд╛ рдФрд░ рдХреЗрд╡рд▓ рдЙрдиреНрд╣реЗрдВ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ? рдЖрдк рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЛрдВ рд╕реЗ рд╕рдВрдкрд░реНрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдХрдВрд╕реЛрд▓.рд▓реЙрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдФрд░ рдореЙрдбрд▓ рдХреЛ рджреЗрдЦрдиреЗ рдХрд╛ рд╕рдордп рд╣реИред


рдпрджрд┐ рдЖрдк рдореЙрдбрд▓ рдХреЗ рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рднрд╛рдЧ рдХреЛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд░рдирд╛ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рддреЛ рдХрдВрд╕реЛрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рддреЗрдЬрд╝ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рднрд╛рдЧреЛрдВ рдореЗрдВ рдЕрдВрддрд░ рдХреИрд╕реЗ рд╣реЛрддрд╛ рд╣реИред

рдЖрдорддреМрд░ рдкрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдореЙрдбрд▓ рдХреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рджреЛ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВред рдкрд╣рд▓рд╛ (рдЕрдЪреНрдЫрд╛) рд╡рд╣ рд╣реИ рдЬрдм 3 рдбреА рдХрд▓рд╛рдХрд╛рд░ рдиреЗ рдореЙрдбрд▓ рдХреЗ рдШрдЯрдХ рднрд╛рдЧреЛрдВ рдкрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд┐рдП рд╣реИрдВ рдФрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрдирдХреЗ рдирд╛рдо рдХреНрд╖реЗрддреНрд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ рдФрд░ рд╣рдо рдЙрдирд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдпрд╣ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рдХреЗ рдирд╛рдо рд╣реИрдВред рд╣рдо рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред "Christmas_Tree" рд╕рд╛рдордЧреНрд░реА рд╕реЗ рдореЙрдбрд▓ рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд▓рд┐рдП рд╣рдо рдмрдирд╛рд╡рдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:


 function loadModel() { OBJ_LOADER.load('./model.obj', (object) => { object.traverse(function(child) { if (child instanceof THREE.Mesh) { switch (child.material.name) { case 'Christmas_Tree': child.material.map = TEXTURE; break; // . . . } } }); // . . . 

рддреЛ рд╣рдореЗрдВ рдХреБрдЫ рдРрд╕рд╛ рдорд┐рд▓рддрд╛ рд╣реИ:



"рд▓рд╛рд▓" рдФрд░ "рдЧреБрд▓рд╛рдмреА" рд╕рд╛рдордЧреНрд░реА рд╕реЗ рдмрдиреЗ рднрд╛рдЧреЛрдВ рдХреЗ рд▓рд┐рдП (рдпреЗ рдЧреЗрдВрджреЗрдВ рд╣реИрдВ - рдХреНрд░рд┐рд╕рдорд╕ рдЧреЗрдВрджреЗрдВ), рд╣рдо рдмрд╕ рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд░рдВрдЧ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, HSL рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ:


 switch (child.material.name) { case 'Christmas_Tree': child.material.map = TEXTURE; break; case 'red': child.material.color.setHSL(Math.random(), 1, 0.5); break; case 'pink': child.material.color.setHSL(Math.random(), 1, 0.5); break; } 

рдХрд▓рд╛рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдзреНрдпрд╛рди рджреЗрдВ: рдореЙрдбрд▓ рдореЗрдВ рд╕рдм рдХреБрдЫ рдХреЛ рд╕рд╛рд░реНрдердХ рдирд╛рдо рджреЗрдВред рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рдХреЗ рдирд╛рдо рдХреЗрд╡рд▓ рдорд╕реНрддрд┐рд╖реНрдХ рдХреЛ рддреЛрдбрд╝рддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рд▓рд╛рд▓ рд╣рд░рд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдореИрдВрдиреЗ рдЙрдиреНрд╣реЗрдВ рдирд╣реАрдВ рдмрджрд▓рд╛ рдХрд┐ рдЬреЛ рдХреБрдЫ рд╣реЛ рд░рд╣рд╛ рдерд╛, рдЙрд╕реЗ рдкреВрд░реА рдмреЗрддреБрдХреА рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдПред рд╕рд╛рд░ рдирд╛рдо "рдЧреЗрдВрджреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╛рдордЧреНрд░реА" рдЕрдзрд┐рдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд╣реЛрдЧрд╛ред

рд╕рдордмрд╛рд╣реБ рдкреНрд░рдХреНрд╖реЗрдкрдг


рд░реВрд╕реА рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдореЗрдВ рдпреМрдЧрд┐рдХ рд╢рдмреНрдж рд╕рдордмрд╛рд╣реБ рдкреНрд░рдХреНрд╖реЗрдкрдг рд╕рдорд╛рди-рд╕реЗ-рдордзреНрдпрд╡рд░реНрддреА рдкреНрд░рдХреНрд╖реЗрдкрдг рд╣реИред рдШрд░ рдореЗрдВ рдЕрдиреБрд╡рд╛рджрд┐рдд - рдПрдХ рдЖрдпрдд рдкрд░ рдЧреЗрдВрдж рдХреЛ рдЦреАрдВрдЪрд╛ред рдЖрдк рдореБрдЭреЗ рдЙрджреНрдзреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рд╕рднреА рдиреЗ рд╕реНрдХреВрд▓ рдореЗрдВ рдПрдХ рд╡рд┐рд╢реНрд╡ рдорд╛рдирдЪрд┐рддреНрд░ рджреЗрдЦрд╛ - рдпрд╣ рдЖрдпрддрд╛рдХрд╛рд░ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рдпрджрд┐ рд╣рдо рдЗрд╕реЗ рдереЛрдбрд╝рд╛ рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдПрдХ рдЧреНрд▓реЛрдм рдорд┐рд▓рддрд╛ рд╣реИред рдпрд╣ рдмрд╛рдд рд╣реИред рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпреЗ рд╡рд┐рдХреГрддрд┐рдпрд╛рдБ рдХреИрд╕реЗ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рд╣реЛрддреА рд╣реИрдВ, рдЪрд┐рддреНрд░ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:



рд╡рд┐рднрд┐рдиреНрди рдЙрддреНрдкрд╛рджреЛрдВ рдХреЗ рдердВрдмрдиреЗрд▓ рдмрдирд╛рддреЗ рд╕рдордп, рдкреГрд╖реНрдарднреВрдорд┐ рдЕрдХреНрд╕рд░ рдРрд╕реЗ рдЕрдиреБрдорд╛рдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдИ рдЬрд╛рддреА рд╣реИред рд╣рдо рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рдХреГрдд рддрд╕реНрд╡реАрд░ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдПрдХ рдмрдбрд╝реЗ рдХреНрд╖реЗрддреНрд░ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдХреИрдорд░рд╛ рдЗрд╕рдХреЗ рдЕрдВрджрд░ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 function initWorld() { const sphere = new THREE.SphereGeometry(500, 64, 64); sphere.scale(-1, 1, 1); const texture = new THREE.Texture(); const material = new THREE.MeshBasicMaterial({ map: texture }); IMAGE_LOADER.load('./world.jpg', (image) => { texture.image = image; texture.needsUpdate = true; }); SCENE.add(new THREE.Mesh(sphere, material)); } 

рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВрдиреЗ рдЬрд╛рдирдмреВрдЭрдХрд░ рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рдХрдо рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЖрдк рдЬреАрдердм рд╕реЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдПрдХ рдЕрд▓рдЧ рд╕реАрдо рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдЪрд┐рддреНрд░ рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЛ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИ, рддреЛ рдЗрд╕рдХрд╛ рдореВрд▓ рдпрд╣рд╛рдВ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред


рдлрд┐рд▓рд╣рд╛рд▓ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╣реИ:



рд░рдВрдЧреАрди рдЧреЗрдВрджреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдХреНрд░рд┐рд╕рдорд╕ рдХрд╛ рдкреЗрдбрд╝ рдмрд╣реБрдд рдкреНрдпрд╛рд░рд╛ рд▓рдЧрддрд╛ рд╣реИред


рдСрд░реНрдмрд┐рдЯ рдХрдВрдЯреНрд░реЛрд▓ рдХрд░рддрд╛ рд╣реИ


рддреАрди-рдЖрдпрд╛рдореА рдХрдорд░реЗ рдХреА рд╕реБрдВрджрд░рддрд╛ рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдорд╛рдЙрд╕ рдирд┐рдпрдВрддреНрд░рдг рдЬреЛрдбрд╝реЗрдВред рдФрд░ рдлрд┐рд░ рд╕рдм рдХреБрдЫ 3 рдбреА рдореЗрдВ рд▓рдЧрддрд╛ рд╣реИ, рдЖрдкрдХреЛ рдпрд╣ рд╕рдм рдореЛрдбрд╝рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред рдЖрдорддреМрд░ рдкрд░, OrbitControls рдХрд╛ рдЙрдкрдпреЛрдЧ рдРрд╕реЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


 function initControls() { CONTROLS = new THREE.OrbitControls(CAMERA); CONTROLS.minPolarAngle = Math.PI * 1 / 4; CONTROLS.maxPolarAngle = Math.PI * 3 / 4; CONTROLS.update(); } 

рдХреЛрдгреЛрдВ рдкрд░ рдкреНрд░рддрд┐рдмрдВрдз рд▓рдЧрд╛рдирд╛ рд╕рдВрднрд╡ рд╣реИ рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рдЖрдк рдХреИрдорд░реЗ рдХреЛ рдШреБрдорд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд╝реВрдо рдФрд░ рдЕрдиреНрдп рд╡рд┐рдХрд▓реНрдкреЛрдВ рдкрд░ рдкреНрд░рддрд┐рдмрдВрдз рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВред рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдкрд░ рдзреНрдпрд╛рди рджреЗрдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реИ, рдмрд╣реБрдд рд╕рд╛рд░реА рджрд┐рд▓рдЪрд╕реНрдк рдЪреАрдЬреЗрдВ рд╣реИрдВред


рдЖрдк рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдирд┐рдпрдВрддреНрд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рдирд╣реАрдВ рдмрддрд╛ рд╕рдХрддреЗред рдХрдиреЗрдХреНрдЯ, рдЪрд╛рд▓реВ рдФрд░ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдмрд╕ рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рд░рд╛рдЬреНрдп рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордд рднреВрд▓рдирд╛:


 function animate() { requestAnimationFrame(animate); CONTROLS.update(); render(); } 

рдпрд╣рд╛рдВ рдЖрдк рдереЛрдбрд╝рд╛ рд╡рд┐рдЪрд▓рд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрд░рд┐рд╕рдорд╕ рдЯреНрд░реА рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рджрд┐рд╢рд╛рдУрдВ рдореЗрдВ рдШреБрдорд╛ рд╕рдХрддреЗ рд╣реИрдВ ...


Raycaster


рд░реЗрдХрд╛рд╕реНрдЯрд░ рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ: рдпрд╣ рдЕрдВрддрд░рд┐рдХреНрд╖ рдореЗрдВ рдПрдХ рд╕реАрдзреА рд░реЗрдЦрд╛ рдЦреАрдВрдЪрддрд╛ рд╣реИ рдФрд░ рдЙрди рд╕рднреА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдвреВрдВрдврддрд╛ рд╣реИ рдЬрд┐рдирдХреЗ рд╕рд╛рде рдпрд╣ рдЕрдВрддрд░рд┐рдд рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рджрд┐рд▓рдЪрд╕реНрдк рдЪреАрдЬреЗрдВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрддреНрдкрд╛рдж рдкреНрд░рд╕реНрддреБрддрд┐рдпреЛрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рджреЛ рдореБрдЦреНрдп рдорд╛рдорд▓реЗ рд╣реЛрдВрдЧреЗ - рдпрд╣ рдХреБрдЫ рдкрд░ рдорд╛рдЙрд╕ рд╣реЛрд╡рд░ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдирд╛ рдФрд░ рдХреБрдЫ рдкрд░ рдорд╛рдЙрд╕ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдирд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдорд╛рдЙрд╕ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЗ рд╕рд╛рде рдмрд┐рдВрджреБ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдХреНрд░реАрди рдкрд░ рд▓рдВрдмрд╡рдд рд░реЗрдЦрд╛рдПрдВ рдЦреАрдВрдЪрдиреА рд╣реЛрдВрдЧреА рдФрд░ рдЪреМрд░рд╛рд╣реЛрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░рдиреА рд╣реЛрдЧреАред рдпрд╣реА рд╣рдо рдХрд░реЗрдВрдЧреЗред рд░реЗрдВрдбрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдмрдврд╝рд╛рдПрдВ, рдЧреЗрдВрджреЛрдВ рдХреЗ рд╕рд╛рде рдЪреМрд░рд╛рд╣реЛрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░реЗрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдлрд┐рд░ рд╕реЗ рджрдмрд╛рдПрдВ:


 function render() { RAYCASTER.setFromCamera(MOUSE, CAMERA); paintHoveredBalls(); // . . . } function paintHoveredBalls() { if (OBJECT) { const intersects = RAYCASTER.intersectObjects(OBJECT.children); for (let i = 0; i < intersects.length; i++) { switch (intersects[i].object.material.name) { case 'red': intersects[i].object.material.color.set(0x000000); break; case 'pink': intersects[i].object.material.color.set(0xffffff); break; } } } } 

рдорд╛рдЙрд╕ рдХреЗ рд╕рд░рд▓ рдЖрдВрджреЛрд▓рдиреЛрдВ рдХреЗ рд╕рд╛рде, рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред



рд▓реЗрдХрд┐рди рдПрдХ рд╕реВрдХреНрд╖реНрдорддрд╛ рд╣реИ - рддреАрди.js рдирд╣реАрдВ рдЬрд╛рдирддреЗ рдХрд┐ рдХреИрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рд░рдВрдЧ рдмрджрд▓рдирд╛ рд╣реИред рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдпрд╣ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рд╕реБрдЪрд╛рд░реБ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИред рдпрд╣рд╛рдВ рдХреБрдЫ рдЙрдкрдХрд░рдг рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ рдЬреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП Anime.jsред


 <script src='https://unpkg.com/animejs@2.2.0/anime.min.js'></script> 

рд╣рдо рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдЪреЗрддрди рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВ:


 switch (intersects[i].object.material.name) { case 'red': // intersects[i].object.material.color.set(0x000000); anime({ targets: intersects[i].object.material.color, r: 0, g: 0, b: 0, easing: 'easeInOutQuad' }); break; // . . . } 

рдЕрдм рд░рдВрдЧ рдЖрд╕рд╛рдиреА рд╕реЗ рдмрджрд▓ рдЬрд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдорд╛рдЙрд╕ рдХреЗ рдЧреЗрдВрдж рд╕реЗ рджреВрд░ рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж рд╣реАред рдХреБрдЫ рддрдп рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ - рд╡реЗ рд╣рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ рдореЗрдВ рдореЗрдЯрд╛ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдФрд░ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдЧреЗрдВрдж рдПрдирд┐рдореЗрдЯреЗрдб рд╣реИ рдпрд╛ рдирд╣реАрдВред


ES6 + рдореЗрдВ рдкреНрд░рддреАрдХ рдПрдХ рдмрд╣реБрдд рд╣реА рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рд╣реИ, рдЬреЛ рдЕрдиреНрдп рдмрд╛рддреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдбрд░ рдХреЗ рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рд╕реЗ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЬрд╛рдирдХрд╛рд░реА рдЬреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рдпрд╣ рдПрдХ рдирд╛рдо рд╕рдВрдШрд░реНрд╖ рдпрд╛ рддрд░реНрдХ рдХреЛ рддреЛрдбрд╝ рджреЗрдЧрд╛ред

рд╣рдо рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рд╕реНрдерд┐рд░рд╛рдВрдХ рдмрдирд╛рддреЗ рд╣реИрдВ (рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдпрд╣ рдРрд╕реЗ рд╕рднреА рдкреНрд░рддреАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рд╡рд╕реНрддреБ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рд╣рдо рдЗрд╕реЗ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ):


 const _IS_ANIMATED = Symbol('is animated'); 

рдФрд░ рд╣рдо рдЧреЗрдВрджреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рд░рдВрдЧрдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдореЗрдВ рдПрдХ рдЬрд╛рдБрдЪ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:


 if (!intersects[i].object[_IS_ANIMATED]) { anime({ targets: intersects[i].object.material.color, r: 0, g: 0, b: 0, easing: 'easeInOutQuad' }); intersects[i].object[_IS_ANIMATED] = true; } 

рдЕрдм рд╡реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдордБрдбрд░рд╛ рдкрд░ рддреБрд░рдВрдд repaintedред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдкреНрд░рддреАрдХреЛрдВ рдХреА рд╕рд╣рд╛рдпрддрд╛ рд╕реЗ, рдЖрдк рд╕рднреА рдЧреЗрдВрджреЛрдВ рдХреА рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЬрдЧрд╣ рдкрд░ рдмрдЪрдд рдХреЗ рдмрд┐рдирд╛ рдПрдирд┐рдореЗрд╢рди рдореЗрдВ рд╕рдорд╛рди рдЪреЗрдХ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред


рдЯреВрд▓рдЯрд┐рдкреНрд╕


рдЖрдЬ рд╣рдо рдЬреЛ рдЖрдЦрд┐рд░реА рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ рд╡рд╣ рд╣реИ рдЯреВрд▓рдЯрд┐рдкреНрд╕ред рдпрд╣ рдХрд╛рд░реНрдп рдЕрдХреНрд╕рд░ рд╕рд╛рдордирд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдмрд╕ рдЙрдиреНрд╣реЗрдВ рдмрдирд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред


 <div class='popup-3d'>  !</div> 

 .popup-3d { color: #fff; font-family: 'Pacifico', cursive; font-size: 10rem; pointer-events: none; } 

рдпрджрд┐ рдЖрдкрдХреЛ рдЙрдирдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рддреЛ рдкреЙрдЗрдВрдЯрд░-рдИрд╡реЗрдВрдЯ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдирд╛ рдпрд╛рдж рд░рдЦреЗрдВред

рдпрд╣ CSS3DRenderer рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд╛рдлреА рд░реЗрдВрдбрд░рд░ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдпрд╣ рдПрдХ рдРрд╕реА рдЪреАрдЬ рд╣реИ рдЬреЛ рдмрд╕ CSS рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рддрддреНрд╡реЛрдВ рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рдПрдХ рдЖрдо рджреГрд╢реНрдп рдореЗрдВ рд╣реИрдВред рдкреЙрдк-рдЕрдк рд▓реЗрдмрд▓ рдХреЗ рд▓рд┐рдП - рдпрд╣ рд╕рд┐рд░реНрдл рд╡рд╣реА рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдЪрд╛рд╣рд┐рдПред рд╣рдо рдЧреНрд▓реЛрдмрд▓ рд╡реЗрд░рд┐рдПрдмрд▓ CSSRENDERER рдмрдирд╛рддреЗ рд╣реИрдВ, рдЗрд╕реЗ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд░реЗрдВрдбрд░ рдлрдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдирд╣реАрдВ рднреВрд▓рддреЗ рд╣реИрдВред рд╕рдм рдХреБрдЫ рдПрдХ рдирд┐рдпрдорд┐рдд рд░реЗрдВрдбрд░рд░ рдХреА рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 function initCSSRenderer() { CSSRENDERER = new THREE.CSS3DRenderer(); CSSRENDERER.setSize(window.innerWidth, window.innerHeight); CSSRENDERER.domElement.style.position = 'absolute'; CSSRENDERER.domElement.style.top = 0; } function render() { CAMERA.lookAt(SCENE.position); RENDERER.render(SCENE, CAMERA); CSSRENDERER.render(SCENE, CAMERA); } 

рдлрд┐рд▓рд╣рд╛рд▓ рдХреБрдЫ рдирд╣реАрдВ рд╣реБрдЖ рд╣реИред рджрд░рдЕрд╕рд▓, рд╣рдордиреЗ рдХреБрдЫ рдирд╣реАрдВ рдХрд┐рдпрд╛ред рд╣рдо рдкреЙрдк-рдЕрдк рддрддреНрд╡ рдХреЛ рдЖрд░рдВрднреАрдХреГрдд рдХрд░рддреЗ рд╣реИрдВ, рд╣рдо рддреБрд░рдВрдд рдЗрд╕рдХреЗ рдЖрдХрд╛рд░ рдФрд░ рд╕реНрдерд╛рди рдХреЗ рд╕рд╛рде рдЦреЗрд▓ рд╕рдХрддреЗ рд╣реИрдВ:


 function initPopups() { const popupSource = document.querySelector('.popup-3d'); const popup = new THREE.CSS3DObject(popupSource); popup.position.x = 0; popup.position.y = -10; popup.position.z = 30; popup.scale.x = 0.05; popup.scale.y = 0.05; popup.scale.z = 0.05; console.log(popup); SCENE.add(popup); } 

рдЕрдм рд╣рдо рд╢рд┐рд▓рд╛рд▓реЗрдЦ "3 рдбреА" рдореЗрдВ рджреЗрдЦрддреЗ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ 3 рдбреА рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдХреИрдирд╡рд╛рд╕ рдХреЗ рдКрдкрд░ рд╕реНрдерд┐рдд рд╣реИ, рд▓реЗрдХрд┐рди рдкреЙрдк-рдЕрдк рдпреБрдХреНрддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рдЗрддрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИ, рдкреНрд░рднрд╛рд╡ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ


рдЕрдВрддрд┐рдо рд╕реНрдкрд░реНрд╢ рд░рд╣рддрд╛ рд╣реИ - рдХреЛрдг рдХреА рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕реАрдорд╛ рдореЗрдВ рд╢рд┐рд▓рд╛рд▓реЗрдЦ рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдПред рдлрд┐рд░ рд╕реЗ, рд╡реИрд╢реНрд╡рд┐рдХ рдкреНрд░рддреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:


 const _IS_VISIBLE = Symbol('is visible'); 

рдФрд░ рд╣рдо рдХреИрдорд░рд╛ рдХреЗ рд░реЛрдЯреЗрд╢рди рдХреЗ рдХреЛрдг рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкреЙрдк-рдЕрдк рддрддреНрд╡ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ:


 function updatePopups() { const popupSource = document.querySelector('.popup-3d'); const angle = CONTROLS.getAzimuthalAngle(); if (Math.abs(angle) > .9 && popupSource[_IS_VISIBLE]) { anime({ targets: popupSource, opacity: 0, easing: 'easeInOutQuad' }); popupSource[_IS_VISIBLE] = false; } else if (Math.abs(angle) < .9 && !popupSource[_IS_VISIBLE]) { anime({ targets: popupSource, opacity: 1, easing: 'easeInOutQuad' }); popupSource[_IS_VISIBLE] = true; } } 

рд╕рдм рдХреБрдЫ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред рдЕрдм рд╢рд┐рд▓рд╛рд▓реЗрдЦ рдЖрд╕рд╛рдиреА рд╕реЗ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ рдФрд░ рдЧрд╛рдпрдм рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рдСрдЯреЛ-рд░реЛрдЯреЗрдЯ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдЖрдирдВрдж рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВред


 CONTROLS.autoRotate = true; CONTROLS.autoRotateSpeed = -1.0; 


рдирд┐рд╖реНрдХрд░реНрд╖


рдЖрдЬ рд╣рдордиреЗ рджреЗрдЦрд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдкреГрд╖реНрда рдкрд░ рддреАрди-рдЖрдпрд╛рдореА рдореЙрдбрд▓ рдХреИрд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рдорд╛рдЙрд╕ рд╕реЗ рдХреИрд╕реЗ рдЪрд╛рд▓реВ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдЯреВрд▓рдЯрд┐рдкреНрд╕ рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП, рдореЙрдбрд▓ рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдкрд░ рд╣реЛрд╡рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдорд╛рдЙрд╕ рдХрд╛ рдЬрд╡рд╛рдм рдХреИрд╕реЗ рджрд┐рдпрд╛ рдЬрд╛рдП, рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдПрдирд┐рдореЗрд╢рди рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдкрд╛рддреНрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдПред рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рд╕рд╣рд╛рдпрдХ рд╣реИред рдЦреИрд░, рдЖрдЧрд╛рдореА рд╕рднреА рдХреЗ рд╕рд╛рде, рдЕрдм рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЫреБрдЯреНрдЯрд┐рдпреЛрдВ рдХреЗ рджреМрд░рд╛рди рдЖрдк рдХреНрдпрд╛ рд╕реАрдЦ рд╕рдХрддреЗ рд╣реИрдВред


рдкреБрдирд╢реНрдЪ: рд╣реЗрд░рд┐рдВрдЧрдмреЛрди рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдкреВрд░реНрдг рд╕реНрд░реЛрдд рдЧреАрдереВрдм рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИрдВред

Source: https://habr.com/ru/post/hi433876/


All Articles