Drei : R3F에서 사용할 수 있는 유용한 컴포넌트들을 모아 놓은 라이브러리
지오메트리는 mesh의 모양을 정의하는거 말고도 다른용도로도 사용되지만 이번엔 모양에 대해서만 정리
모든 지오메트리는 BufferGeometry 클래스를 상속받는다.
BufferGeometry는 Attribute라는 데이터를 가지고 있다. 그 중 형상과 관련된것은
이 외에도 mesh의 표면을 정의할 수 있는 아래와 같은 데이터가 있다. 이러한 데이터는 랜더링 시 GPU에 전달되고 매우 빠르게 나온다.
가지고 있는 데이터 뿐만 아니라 사용자정의 데이터도 저장해서 GPU에 전달할 수 있다.
기본 지오메트리 (Three.js의 Geometry 클래스)

import { Box, OrbitControls } from "@react-three/drei";
import * as THREE from "three";
function MyBox(props) {
const geom = new THREE.BoxGeometry();
return <mesh {...props} geometry={geom}></mesh>;
}
function MYElement3D() {
// Drei : R3F에서 사용할 수 있는 유용한 컴포넌트들을 모아 놓은 라이브러리
return (
<>
<OrbitControls />
<ambientLight intensity={0.1} />
<directionalLight position={(2, 1, 3)} intensity={0.5} />
<mesh>
<boxGeometry />
<meshStandardMaterial color="#1abc9c" />
</mesh>
<Box position-x={1.2}>
<meshStandardMaterial color="#8e44ad" />
</Box>
<MyBox position-x={-1.2}>
<meshStandardMaterial color="#e74c3c" />
</MyBox>
</>
);
}
export default MYElement3D;
두개의 mesh에서 한개의 boxGeometry를 같이 사용할 수 있게 하는 방법
useEffect를 사용해서 refMesh의 geometry에서 refWireMesh 사용하도록 한다.
import { OrbitControls } from "@react-three/drei";
import { useEffect, useRef } from "react";
// import * as THREE from "three";
function MYElement3D() {
const refMesh = useRef();
const refWireMesh = useRef();
useEffect(() => {
refWireMesh.current.geometry = refMesh.current.geometry;
}, []);
// Drei : R3F에서 사용할 수 있는 유용한 컴포넌트들을 모아 놓은 라이브러리
return (
<>
<OrbitControls />
<ambientLight intensity={0.1} />
<directionalLight position={(2, 1, 3)} intensity={0.5} />
<mesh ref={refMesh}>
<boxGeometry />
<meshStandardMaterial color="#1abc9c" />
</mesh>
<mesh ref={refWireMesh}>
<meshStandardMaterial emissive="yellow" wireframe={true} />
</mesh>
</>
);
}
export default MYElement3D;
args를 UI에서 변경할 수 있는 방법 : leva사용
args
arguments 줄임말, 각 지오메트리를 위한 클래스의 새엉자에 대한 인자값
도형의 크기를 정의하며 3차원 vector값을 갖는다.
Segments 는 분할
Geometry별 인자 갯수
boxGeometry(6개) : xSize, ySize, zSize, xSegments, ySegments, zSegments
xSize : x축 방향에 대한 크기
xSegments: x축 방향에 대한 분할 수
sphereGeometry(7개) : radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength
반지름
너비 방향에 대한 분할 수 (1 이상 정수)
높이 방향에 대한 분할 수 (1 이상 정수)
수평 방향에 대한 시작 각도 (0 이상 360 미만 유리수)
수평 방향에 대한 연장 각도 (0 이상 360 미만 유리수)
높이 방향에 대한 시작 각도 (0 이상 360 미만 유리수)
높이 방향에 대한 연장 각도 (0 이상 360 미만 유리수)
(phiStart, phiLength)는 radian 단위로 해야됨 Math.PI/180
CylinderGeometry(8개) : topRadius, bottomRadius, height, radialSegments, heightSegments, bopen, thetaStart, thetaLength
윗면 반지름
아랫면 반지름
높이
방사 방향에 대한 분할 수 (1 이상 정수)
높이 방향에 대한 분할 수 (1 이상 정수)
윗면과 아랫면에 대한 개방 여부 (true/false)
시작 각도 (0 이상 360 미만 유리수)
연장 각도 (0 이상 360 미만 유리수)
그 외 GeoMetry인자 확인은 공식문서 확인
https://threejs.org/docs/index.html?q=geoMetry#api/en/geometries/BoxGeometry
import { OrbitControls } from "@react-three/drei";
import { useControls } from "leva";
import { useEffect, useRef } from "react";
// import * as THREE from "three";
function MYElement3D() {
const refMesh = useRef();
const refWireMesh = useRef();
const { xSize, ySize, zSize, xSegments, ySegments, zSegments } = useControls({
xSize: {
value: 1,
min: 0.1,
max: 5,
step: 0.01,
},
ySize: {
value: 1,
min: 0.1,
max: 5,
step: 0.01,
},
zSize: {
value: 1,
min: 0.1,
max: 5,
step: 0.01,
},
xSegments: {
// xSegments는 정수값이여야됨
value: 1,
min: 1,
max: 10,
step: 1,
},
ySegments: {
value: 1,
min: 1,
max: 10,
step: 1,
},
zSegments: {
value: 1,
min: 1,
max: 10,
step: 1,
},
});
useEffect(() => {
refWireMesh.current.geometry = refMesh.current.geometry;
}, [xSize, ySize, zSize, xSegments, ySegments, zSegments]);
return (
<>
<OrbitControls />
<ambientLight intensity={0.1} />
<directionalLight position={(2, 1, 3)} intensity={0.5} />
<mesh ref={refMesh}>
<boxGeometry
args={[xSize, ySize, zSize, xSegments, ySegments, zSegments]}
/>
<meshStandardMaterial color="#1abc9c" />
</mesh>
<mesh ref={refWireMesh}>
<meshStandardMaterial emissive="yellow" wireframe={true} />
</mesh>
</>
);
}
export default MYElement3D;
이 글은 아래 유투브 강의를 듣고 작성한 글 입니다.
https://www.youtube.com/watch?v=0jnGlLb_z7w&list=PLe6NQuuFBu7HUeJkowKRkLWwkdOlhwrje&index=4