Obj 3D + Transform
Object 3D
모든 3D 객체의 부모 클래스
- Scene, Mesh, Group, Camera 등 모든 주요 요소가 Object3D를 상속받음
→ 자동으로 생성되는 Scene도 Object3D의 인스턴스 - position, rotation, scale 등의 변형(Tranform) 속성을 기본적으로 가짐
- Object3D를 상속받은 모든 객체는 Transform(변환)기능 사용 가능
→ useThree 훅을 사용하면 scene을 가져와서 조작 가능
three.js docs
threejs.org
useThree 훅을 이용한 Scene 접근
import { Canvas, useThree } from "@react-three/fiber";
const Element = () => {
const { scene } = useThree(); // Scene 객체 가져오기
return <></>;
};
function App() {
return (
<Canvas>
<Element />
</Canvas>
);
}
- useThree 훅을 사용하여 scene, camera 등 Three.js의 주요 객체에 접근 가능
- useThree는 Canvas 내부에서만 호출 (Canvas 외부에서 호출하면 에러 발생)
CardComponent: 카드 객체 생성
import { useLoader } from "@react-three/fiber";
import * as THREE from "three";
const CardComponent = ({ position, rotationY, rotationZ, imageUrl }) => {
const texture = useLoader(THREE.TextureLoader, imageUrl);
texture.colorSpace = THREE.DisplayP3ColorSpace; // P3 색공간 설정
const materials = [
new THREE.MeshStandardMaterial(), // 오른쪽
new THREE.MeshStandardMaterial(), // 왼쪽
new THREE.MeshStandardMaterial(), // 윗면
new THREE.MeshStandardMaterial(), // 바닥면
new THREE.MeshStandardMaterial({ map: texture }), // 앞면 (이미지 적용)
new THREE.MeshStandardMaterial({ map: texture }), // 뒷면 (이미지 적용)
];
return (
<mesh
position={position}
rotation-y={THREE.MathUtils.degToRad(rotationY)}
rotation-z={THREE.MathUtils.degToRad(rotationZ)}
material={materials}
>
<boxGeometry args={[1, 1.6, 0.01]} />
</mesh>
);
};
- useLoader(THREE.TextureLoader, imageUrl) : 이미지 텍스처 로딩
- THREE.DisplayP3ColorSpace : 더 넓은 색공간 적용 (THREE.SRGBColorSpace 사용)
- ratation-y, rotation-z : degToRad를 사용해 각도를 라디안 값으로 변환
cardData 배열: 카드 정보 저장
const cardData = [
{ imageUrl: "/tarrot_1.png", position: [0, -1, 0], rotationY: -10, rotationZ: 0 },
{ imageUrl: "/tarrot_2.png", position: [0.5, -1.05, -0.1], rotationY: -10, rotationZ: -10 },
{ imageUrl: "/tarrot_3.png", position: [-0.5, -1.05, 0.1], rotationY: -10, rotationZ: 10 },
{ imageUrl: "/tarrot_4.png", position: [-1, -1.15, 0.2], rotationY: -10, rotationZ: 20 },
{ imageUrl: "/tarrot_5.png", position: [1, -1.15, -0.1], rotationY: -10, rotationZ: -20 },
];
// 카드 컴포넌트 렌더링
{cardData.map((props) => (
<CardComponent key={props.imageUrl} {...props} />
))}
- 여러 개의 카드를 관리하기 위한 cardData 선언
- map 함수를 사용, CardComponent를 동적으로 생성
- key 속성으로 imageUrl을 사용, 같은 이미지를 쓰는 경우에는 id를 추가하는 게 좋음
카드 배치 변경
const cardData = [
{ imageUrl: "/card_1.png", position: [0, -1, 0], rotationY: -5, rotationZ: 0 },
{ imageUrl: "/card_2.png", position: [0.5, -1.05, -0.1], rotationY: -5, rotationZ: -10 },
{ imageUrl: "/card_3.png", position: [-0.5, -1.05, 0.1], rotationY: -5, rotationZ: 10 },
{ imageUrl: "/card_4.png", position: [-1, -1.15, 0.2], rotationY: -5, rotationZ: 20 },
{ imageUrl: "/card_5.png", position: [1, -1.15, -0.1], rotationY: -5, rotationZ: -20 },
];
// 컴포넌트에서 반복 렌더링
{cardData.map((props) => (
<CardComponent key={props.imageUrl} {...props} />
))}
- rotationY : Y축 회전 (카드가 좌우로 회전)
- rotationZ : Z축 회전 (카드가 앞뒤로 기울어짐)
AxesHelper로 방향 확인
AxesHelper를 추가해서 좌표축을 시각적으로 확인
<axesHelper args={[5]} />
- args[5] : 축 길이 설정 값을 키우면 더 명확하게 보임)
- CardComponent : 내부에 추가하면 개별 카드의 회전 방향 확인 가능
import './App.css'
import { Canvas } from "@react-three/fiber";
import { OrbitControls } from '@react-three/drei';
import { useLoader, useThree } from "@react-three/fiber";
import * as THREE from "three";
const CardData = [
{
imageUrl: "/card_1.jpg",
position: [-1.1, -1.15, 0.4],
rotationY: 10,
rotationZ: 30,
},
{
imageUrl: "/card_2.jpg",
position: [-0.7, -1.05, 0.2],
rotationY: 10,
rotationZ: 10,
},
{
imageUrl: "/card_3.jpg",
position: [0, -1.05, 0],
rotationY: 0,
rotationZ: 0,
},
{
imageUrl: "/card_4.jpg",
position: [0.7, -1.15, -0.2],
rotationY: -10,
rotationZ: -10,
},
{
imageUrl: "/card_5.jpg",
position: [1.3, -1.30, -0.4],
rotationY: -10,
rotationZ: -30,
},
]
const CardComponent = ({ position, rotationY, rotationZ, imageUrl }) => {
const { scene } = useThree();
const texture = useLoader(THREE.TextureLoader, imageUrl)
texture.colorSpace = THREE.SRGBColorSpace;
scene.rotation.set(0, 20, 0);
const materials = [
new THREE.MeshStandardMaterial(), // 오른쪽
new THREE.MeshStandardMaterial(), // 왼쪽
new THREE.MeshStandardMaterial(), // 윗면
new THREE.MeshStandardMaterial(), // 바닥면
new THREE.MeshStandardMaterial({ map: texture }), // 앞면 (이미지 적용)
new THREE.MeshStandardMaterial({ map: texture }), // 뒷면 (이미지 적용)
];
return (
<mesh
position={position}
rotation-y={THREE.MathUtils.degToRad(rotationY)}
rotation-z={THREE.MathUtils.degToRad(rotationZ)}
material={materials}
>
<axesHelper />
<boxGeometry args={[1, 1.6, 0.02]} />
</mesh>
)
}
function App() {
return (
<Canvas>
<OrbitControls />
<ambientLight intensity={1} /> {/* ambientLight : 환경광 (모든 방향에서 균일하게 씌워지는 빛)-모든 오브젝트가 동일한 강도로 조명을 받는 빛 */}
<directionalLight intensity={3} position={[3, 2, 5]} />
{
CardData.map((props) => {
return <CardComponent key={props.imageUrl} {...props} />
})
}
</Canvas>
);
}
export default App;
- position, rotation 조절하여 카드 배치 변경 (scale도 조절 가능)
- 카드 여러 개를 추가하여 호(arc) 형태로 배치
'React > ReactThreeFiber' 카테고리의 다른 글
Light & Shadow (0) | 2025.03.07 |
---|---|
Material & Texture (1) | 2025.03.05 |
Geometry (0) | 2025.03.04 |
GUI Controller (2) | 2025.03.03 |
3D 개발을 도와주는 도구들 - OrbitControls, AxesHelper, GridHelper (0) | 2025.03.02 |