일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- three.js
- poiemaweb
- Next.js
- REACT
- 개발 회고
- 수학
- HTML5
- 프론트엔드
- 세그먼트 트리
- styled-components
- 자바
- JavaScript
- 엔트리포인트
- State
- react-three/fiber
- js
- 구현
- 자료 구조
- 백준
- 자바스크립트
- 오블완
- 회고
- 토이 프로젝트
- 코딩일기
- 기본 문법
- 시뮬레이션
- 티스토리챌린지
- 모던 자바스크립트 튜토리얼
- 브루트포스
- 해시를 사용한 집합과 맵
- Today
- Total
코딩하는 고릴라
[FE] React-three/fiber로 하늘에 별 띄우기 본문
🦍 상황
- React-three/fiber를 활용하여 별이 떠있는 밤하늘을 3D로 구현해야했다.
- 별들의 x, y, z 좌표를 계산해 하늘에 띄워야 했고, 별들을 잇는 선분들의 좌표 또한 필요로 했다.
🐈 로직
1. 별 띄우기
1. 별자리 이미지를 구해온다 (스텔라리움)
2. 블렌더에서 해당 별자리 이미지를 배경으로 설정하고 별들이 위치한 곳에 구체(Sphere)를 위치시켜 X, Z 좌표를 구한다.

3. 별들의 높이(Y 좌표)는 피타고라스 정리를 통하여 구한다.
4. 모든 별들의 X, Y, Z 좌표를 하드코딩하여 배열로 저장
# data.js
// position : 별 [x, y, z]
export const position = [
// 0 URSA MINOR 작은곰자리
[
[0, 35, 0],
[-1.8, 35, -0.5],
[-3.9, 34.8, -1.5],
[-5.1, 34.6, -3.6],
[-6.5, 34.5, -3.4],
[-7.0, 34.1, -6.1],
[-5.4, 34.3, -6.0],
],
// 1 CEPHEUS 케페우스자리
[
[-0.9, 34.7, 5.7],
[-6.2, 34.1, 7.3],
[-4.0, 33.7, 10.8],
[-7.7, 32.5, 13.7],
[-9.2, 33.1, 9.9],
],
// //2 CASIOPEIA 카시오페이아 자리
[
[5.8, 33.3, 11.4],
[5.0, 32.8, 13.7],
[3.0, 32.6, 14.9],
[2.3, 32.2, 16.3],
[0.0, 32.7, 15.1],
],
// ...
]
5. 해당 좌표 값을 import 한 후, Star 컴포넌트 내 mesh의 position 속성에 해당 x, y, z 좌표 설정
# UserSpace.js
function Star(props) {
// ...
return (
<>
<mesh ref={mesh} position={props.position}> {/* mesh의 position 속성에 x, y, z 좌표 설정 */}
<sphereGeometry args={props.size} />
<meshPhongMaterial
color={curStarState ? colors[colorCheck] : "grey"}
opacity={
curStarState ? Math.max(1 - dayDiff / 360, 0.5) : 0.4
}
transparent={true}
/>
</mesh>
<StarSurround
position={props.position}
location={props.location}
handleClick={handleClick}
/>
</>
);
}
2. 별자리 선 만들기
1. 각 별들과 별 사이를 잇기 위해 별들의 좌표를 이용해 별자리 선의 형태를 하드코딩
- 이 때, 선을 한붓그리기 형태로 쭉 잇게 된다면 원하는 별자리의 형태가 나타나지 않아 3차원 배열의 구조를 가지게끔 한 후, 쭉 이어지는 선들을 하나의 인덱스 내에 저장

# data.js
export const linePosition = [
// 0 URSA MINOR 작은곰자리
[
[
[0, 35, 0],
[-1.8, 35, -0.5],
[-3.9, 34.8, -1.5],
[-5.1, 34.6, -3.6],
[-6.5, 34.5, -3.4],
[-7.0, 34.1, -6.1],
[-5.4, 34.3, -6.0],
],
[
[-5.1, 34.6, -3.6],
[-5.4, 34.3, -6.0],
],
],
//1 CEPHEUS 케페우스자리
[
[
[-0.9, 34.7, 5.7],
[-6.2, 34.1, 7.3],
[-4.0, 33.7, 10.8],
[-7.7, 32.5, 13.7],
[-9.2, 33.1, 9.9],
[-6.2, 34.1, 7.3],
],
[
[-0.9, 34.7, 5.7],
[-4.0, 33.7, 10.8],
],
],
// //2 CASIOPEIA 카시오페이아 자리
[
[
[5.8, 33.3, 11.4],
[5.0, 32.8, 13.7],
[3.0, 32.6, 14.9],
[2.3, 32.2, 16.3],
[0.0, 32.7, 15.1],
],
],
//3 CAMELODALIS 기린 자리
[
[
[5.1, 34.7, 0.7],
[7.6, 34.2, 4.8],
[11.0, 33.7, 3.4],
[11.2, 33.3, 6.8],
[11.6, 32.7, 9.3],
],
[
[7.6, 34.2, 4.8],
[11.6, 32.7, 9.3],
],
],
// ...
]
2. 해당 좌표 값을 import 한 후, Line 컴포넌트의 상위 컴포넌트인 GroupStar 컴포넌트에서 해당 좌표를 THREE.Vector3 값으로 변경 후 props를 통해 Line 컴포넌트로 전달
function GroupStar(props) {
// ...
return (
<group
ref={group}
onPointerEnter={handlePointerEnter}
onPointerLeave={handlePointerLeave}
>
// ...
{/* 하나의 별자리 선을 THREE.Vector3 형태로 바꿔준 후 pos에 저장 */}
{linePosition[groupNum].map((it, index) => {
const pos = it.map((it) => new THREE.Vector3(...it));
return (
<Line
key={index}
points={pos} {/* 여러개의 Point의 좌표를 가진 pos를 props로 전달 */}
groupNum={groupNum}
lineColor={lineColor}
/>
);
})}
</group>
);
}
3. Line 컴포넌트에서 props로 전달받은 점들의 좌표값을 이용해 geometry 생성 및 line 생성
function Line(props) {
// ...
{/* 전달받은 점들의 좌표를 활용하여 LineGeometry 생성 */}
const lineGeometry = new THREE.BufferGeometry().setFromPoints(props.points);
return (
<line geometry={lineGeometry}> {/* 위에서 생성한 lineGeometry 활용하여 line 생성 */}
<lineBasicMaterial
attach="material"
ref={lineRef}
transparent={true}
opacity={
!props.lineColor
? 1
: starLineOpacity === groupNum
? 0.05
: 0.01
}
color={0xced6ff}
/>
</line>
);
}
🐄 결과

- 3D 공간에 별과 별을 잇는 선을 생성할 수 있게 되었다.
🐇 고찰
- 좌표값 설정을 위해 하드코딩 하는데 시간이 다소 소요됐다. 더 좋은 방법이 있을까 고민했었으나 이런 방식으로 하드코딩하는게 최선이었다고 생각한다.
'Project > 별일' 카테고리의 다른 글
[FE] React-three/fiber 겹친 오브젝트 간 렌더링 오류 트러블 슈팅 (2) | 2024.03.05 |
---|---|
[FE] 게시글 등록 상태에 따른 별자리 형성, 해제 (0) | 2024.03.02 |
[FE] 한 번의 post 요청으로 미디어 파일, JS 객체 전송하기 (0) | 2024.03.02 |