์ค๋์ ์ด์ด์ Part3 [Three.js ๊ธฐ์ด]์ Chapter02 3Dํ๋ธ ๊ฐ์๋ฅผ ๋ค์์ต๋๋ค.(13~14๊ฐ)
๊ทธ๋ผ ์ค๋ ๊ฐ์์์ ๋ฐฐ์ด ๋ด์ฉ๋ค์ ๊ฐ๋ตํ๊ฒ ์์ฑํด ๋ณผ๊ฒ์!
๐01. OrbitControls
ํ๋ฉด์์์ ์ธํฐ๋ ํฐ๋ธํ๊ฒ ์นด๋ฉ๋ผ ์ปจํธ๋กค์ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ threejs ๋นํธ์ธ ๊ธฐ๋ฅ์ ๋๋ค.
์นด๋ฉ๋ผ๊ฐ ๋ฌผ์ฒด ์ฃผ๋ณ์์ ๊ถค๋๋ฅผ ๊ทธ๋ฆฌ๋ฉฐ ๋๊ณ ์๋ ๊ฑธ ์๊ฐํ์๋ฉด ๋๊ฒ ์ต๋๋ค.
https://threejs.org/docs/index.html?q=Orbit#examples/en/controls/OrbitControls
three.js docs
threejs.org
OrbitControls๋ three/addons ํจํค์ง์์ ์ง์ importํด์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
...
// OrbitController ์ถ๊ฐ
const controls = new OrbitControls(camera, renderer.domElement);
...
OrbitControl์ ์ถ๊ฐํ๊ณ ํ๋ฉด์ ๋ง์ฐ์ค๋ก ๋๋ ค๋ณด๋ฉด ๋ฌผ์ฒด๊ฐ ๊ฐ์ด ๋์๊ฐ๋ ๊ฒ ์ฒ๋ผ ๋ณด์ ๋๋ค.
ํ์ง๋ง ์ค์ ๋ก๋ ๋ฌผ์ฒด๊ฐ ๋์๊ฐ๋ ๊ฒ ์๋๋ผ ๋ฌผ์ฒด ์ฃผ๋ณ์ ๋๊ณ ์๋ ์นด๋ฉ๋ผ๊ฐ ์์ง์ด๊ณ ์๋ ๊ฒ์ผ๋ก,
์๋ x,y,z์ถ์ ์ถ๊ฐํด๋ณด๋ฉด ํ์คํ ๋ง์ฐ์ค์ ๋ฐ๋ผ ์ถ ์์น๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
// ํ๋ฉด์ x,y,z ์ถ ์ถ๊ฐ
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
OrbitControls์ ๋ค์ํ ์์ฑ๋ค
controls.autoRotate = true; // ๋๋๊ทธํ์ง ์์๋ ๋์์ฃผ๋ณ์ ์๋์ผ๋ก ํ์ ํ๊ฒ ๋ง๋ฆ
controls.autoRotateSpeed = 30; // ํ์ ์๋
controls.enableDamping = true; // ๋ฉ์ท์๋ ์์ง์ด๋ ค๋ ๊ด์ฑ ์ค์
controls.dampingFactor = 0.01; // ๊ด์ฑ ๊ฐ ์ ์ฉ
controls.enableZoom = true; // ์นด๋ฉ๋ผ ์ค ์ค์ (์๋ค ์์ง์ Default:true)
controls.enablePan = true; // ์นด๋ฉ๋ผPan๊ธฐ๋ฅ(์ข์ฐ ์์ง์ Default:true)
controls.maxDistance = 50; // ์ต๋ ์ค๊ฑฐ๋ฆฌ
controls.minDistance = 10; // ์ต์ ์ค๊ฑฐ๋ฆฌ
controls.maxPolarAngle = Math.PI/2; // ์์ง๋ฐฉํฅ์ผ๋ก ์ต๋ ์ผ๋ง๋ ๋๋ฆด์์๋์ง
controls.minPolarAngle = Math.PI/3; // ์์ง๋ฐฉํฅ์ผ๋ก ์ต์ ์ผ๋ง๋ ๋๋ฆด์์๋์ง
controls.maxAzimuthAngle = Math.PI/2; // ์ํ๋ฐฉํฅ์ผ๋ก ์ต๋ ์ผ๋ง๋ ๋๋ฆด์์๋์ง
controls.minAzimuthAngle = Math.PI/3; // ์ํ๋ฐฉํฅ์ผ๋ก ์ต์ ์ผ๋ง๋ ๋๋ฆด์์๋์ง
๐02. GUI ์ปจํธ๋กค ์ถ๊ฐ
๋งค๋ฒ ์์ฑ๊ฐ ๋ณ๊ฒฝํ ๋ ๋๋งํด์ ํ์ธํ๋ ๊ฑด ๊ฝค๋ ๋ฒ๊ฑฐ๋กญ์ต๋๋ค. ํนํ ๋ณต์กํ ๋ฌผ์ฒด๋ฅผ ๋ ๋๋งํ ๋๋ ๋ ์์ฐ์ฑ์ ์ข์ง์๊ธฐ๋๋ฌธ์ GUI ํจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
npm install lil-gui
์๋์ฒ๋ผ importํ ํ
import GUI from 'lil-gui';
gui ์ธ์คํด์ค ์์ฑ ํ ์ปจํธ๋กคํ๊ณ ์ํ๋ ์์ฑ๋ค์ ์ถ๊ฐํด์ฃผ์๋ฉด ๋ฉ๋๋ค.
const gui = new GUI();
// gui ์ธ์คํด์ค์ add ๋ฉ์๋๋ฅผ ํตํด GUI ํจ๋์์ ์ปจํธ๋กคํ๊ณ ์ํ๋ ์์ฑ์ ์ถ๊ฐ
gui.add(cube.position, "y", -3, 3, 0.1); // ๋ณ๊ฒฝํ๊ณ ์ํ๋ ๊ฐ์ฒด, ๋ณ๊ฒฝํ๊ณ ์ํ๋ ์์ฑ, ์ต์, ์ต๋๊ฐ, ์คํ
์ต์
:์ฌ๋ผ์ด๋ ํ์นธ์์ง์ผ๋ ๊ฐ ์ผ๋ง๋ ์์ง์ผ์ง
ํ์ง๋ง ์์์ฒ๋ผ ์ฌ์ฉํ ๊ฒฝ์ฐ, ๊ฐ ํ๋ผ๋ฏธํฐ๊ฐ ์ด๋ค๊ฑธ ์๋ฏธํ๋์ง ํ๋ฒ์ ํ์ ์ด ์ด๋ ต๋ค๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
์๋์ฒ๋ผ addํจ์๋ฅผ ์ฒด์ด๋ํ๋ ๋ฐฉ์์ผ๋ก ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
gui.add(cube.position, "y").min(-3).max(3).step(0.1);
์์ ํจ๋์ ์ถ๊ฐํ๋ ๊ฑด ์ด์ง ๊น๋ค๋กญ์ต๋๋ค. gui๋ property ๋ฐ์ดํฐ ํ์ ์ ๋ณด๊ณ ์ ์ ํ ui๋ฅผ ์์์ ์ ํํ๋๋ฐ, hex์ฝ๋๋ rgb์ฝ๋๊ฐ๋ string ํ์ ์ด๋ผ ์ด ๊ฐ๋ง ๋ณด๊ณ ๋ ์์ํ๋ ํธ UI๋ฅผ ์ ํํด์ผํ ์ง ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ๋ํ material์ color property์ ์ ์ฅ๋๋ ๊ฐ์ hexcode๋ rgb๊ฐ ์๋ Three.js์์ ๋นํธ์ธ์ผ๋ก ์ ๊ณตํ๊ณ ์๋ color instance์ด๊ธฐ ๋๋ฌธ์ ์์ ์ฌ์ฉํ ๋ฐฉ์์ฒ๋ผ Property๊ฐ์ ์ง์ ๋ณ๊ฒฝ์ด ๋ถ๊ฐํฉ๋๋ค.
์์ ํจ๋์ ์ถ๊ฐํ๋ ค๋ฉด ์๋์ฒ๋ผ addColor๋ผ๋ ๋ฉ์๋๋ฅผ ๋ฐ๋ก ์ฌ์ฉํด์ผํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ onChange ํจ์๋ฅผ ์ฒด์ด๋์ผ๋ก ๋ฑ๋กํด์ GUI์์์ ๋ณ๊ฒฝํ ์์์ ๋ฐ๋ก ๋ฉํฐ๋ฆฌ์ผ์์์ ์ ์ฉํ ์ ์์ต๋๋ค.
const options = {
color: 0x00ffff,
};
// ์์ ํ๋ ํธ ์ถ๊ฐ ๋ณ๊ฒฝํ ๊ฐ์ฒด, ์์ฑ(16์ง์ ์คํธ๋ง, ๋๋ฒ, guiํ์ ํ์
),
gui.addColor(options, "color").onChange((value) => {
// ๋ณ๊ฒฝํ ๊ฐ์ material ์์์ ๋ฐ์
cube.material.color.set(value);
});
โจ์ค๋์ ํ์ต ์ธ์ฆ ์ท
๋ณธ ํฌ์คํ ์ ํจ์คํธ์บ ํผ์ค ํ๊ธ ์ฑ๋ฆฐ์ง ์ฐธ์ฌ๋ฅผ ์ํด ์์ฑํ์์ต๋๋ค.
https://fastcampus.co.kr/event_online_challenge_2401_mission
์ปค๋ฆฌ์ด ์ฑ์ฅ์ ์ํ ์ต๊ณ ์ ์ค๋ฌด๊ต์ก ์์นด๋ฐ๋ฏธ | ํจ์คํธ์บ ํผ์ค
์ฑ์ธ ๊ต์ก ์๋น์ค ๊ธฐ์ , ํจ์คํธ์บ ํผ์ค๋ ๊ฐ์ธ๊ณผ ์กฐ์ง์ ์ค์ง์ ์ธ '์ (ๆฅญ)'์ ์ฑ์ฅ์ ๋๊ณ ์ ๋ชจ๋ ์ข ๋ฅ์ ๊ต์ก ์ฝํ ์ธ ์๋น์ค๋ฅผ ์ ๊ณตํ๋ ๋ํ๋ฏผ๊ตญ No. 1 ๊ต์ก ์๋น์ค ํ์ฌ์ ๋๋ค.
fastcampus.co.kr