Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions packages/client/src/components/feature/Controls/Controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,25 @@ import { useRef } from 'react';
import { OrbitControls } from '@react-three/drei';
import * as THREE from 'three';
import { useCameraStore } from 'store/useCameraStore';
import { useFrame } from '@react-three/fiber';
import { Camera, useFrame } from '@react-three/fiber';
import type { OrbitControls as OrbitControlsImpl } from 'three-stdlib';

const setCameraPosition = (
camera: Camera,
currentView: THREE.Vector3,
distance: number,
) => {
const direction = currentView
.clone()
.sub(camera.position)
.setLength(camera.position.distanceTo(currentView) - distance);
camera.position.add(direction);
};

export default function Controls() {
const controlsRef = useRef<OrbitControlsImpl>(null!);
const { currentView, setCurrentView, targetView } = useCameraStore();
const { cameraToCurrentView, currentView, setCurrentView, targetView } =
useCameraStore();

useFrame((state, delta) => {
const targetPosition = new THREE.Vector3(0, 0, 0);
Expand All @@ -21,7 +34,7 @@ export default function Controls() {
if (direction.length() > LENGTH_LIMIT) direction.setLength(LENGTH_LIMIT);

setCurrentView(currentView.add(direction));
state.camera.position.add(direction);
setCameraPosition(state.camera, currentView, cameraToCurrentView);

controlsRef.current.target = currentView;
}
Expand Down
53 changes: 28 additions & 25 deletions packages/client/src/components/feature/Galaxy/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as THREE from 'three';
import Star from '../Star';
import { getRandomInt, getGaussianRandomFloat } from '@utils/random';
import { useRef } from 'react';
import { useRef, useMemo } from 'react';
import { useFrame } from '@react-three/fiber';
import {
ARMS,
Expand Down Expand Up @@ -31,43 +31,46 @@ const getSpiralPositions = (offset: number) => {

export default function Galaxy() {
const galaxyRef = useRef<THREE.Group>(null!);
const stars = [];

useFrame((_, delta) => (galaxyRef.current.rotation.y += delta / 100));

for (let arm = 0; arm < ARMS; arm++) {
const stars = useMemo(() => {
const starList = [];
for (let arm = 0; arm < ARMS; arm++) {
for (let star = 0; star < STARS_NUM / (ARMS + 1); star++) {
const size = getRandomInt(STAR_MIN_SIZE, STAR_MAX_SIZE);
const position = getSpiralPositions((arm * 2 * Math.PI) / ARMS);

starList.push(
<Star
key={`${arm}${star}`}
position={position}
size={size}
color={'#FFF'}
/>,
);
}
}

for (let star = 0; star < STARS_NUM / (ARMS + 1); star++) {
const size = getRandomInt(STAR_MIN_SIZE, STAR_MAX_SIZE);
const position = getSpiralPositions((arm * 2 * Math.PI) / ARMS);
const position = new THREE.Vector3(
getGaussianRandomFloat(0, (ARMS_X_MEAN + ARMS_X_DIST) / 4),
getGaussianRandomFloat(0, GALAXY_THICKNESS * 2),
getGaussianRandomFloat(0, (ARMS_X_MEAN + ARMS_X_DIST) / 4),
);

stars.push(
starList.push(
<Star
key={`${arm}${star}`}
key={`star_${star}`}
position={position}
size={size}
color={'#FFF'}
/>,
);
}
}

for (let star = 0; star < STARS_NUM / (ARMS + 1); star++) {
const size = getRandomInt(STAR_MIN_SIZE, STAR_MAX_SIZE);
const position = new THREE.Vector3(
getGaussianRandomFloat(0, (ARMS_X_MEAN + ARMS_X_DIST) / 4),
getGaussianRandomFloat(0, GALAXY_THICKNESS * 2),
getGaussianRandomFloat(0, (ARMS_X_MEAN + ARMS_X_DIST) / 4),
);

stars.push(
<Star
key={`star_${star}`}
position={position}
size={size}
color={'#FFF'}
/>,
);
}
return starList;
}, []);

return <group ref={galaxyRef}>{stars}</group>;
}
10 changes: 9 additions & 1 deletion packages/client/src/components/feature/Screen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { EffectComposer, Bloom } from '@react-three/postprocessing';
import { useControls } from 'leva';
import { CAMERA_POSITION, CAMERA_ROTATION, CAMERA_FAR } from 'constants/camera';
import Controls from '../Controls/Controls.tsx';
import { useCameraStore } from 'store/useCameraStore.ts';

export default function Screen() {
const camera = {
Expand All @@ -13,6 +14,8 @@ export default function Screen() {
far: CAMERA_FAR,
};

const { cameraToCurrentView, setCameraToCurrentView } = useCameraStore();

const { intensity, mipmapBlur, luminanceThreshold, luminanceSmoothing } =
useControls('Bloom', {
intensity: { value: 0.4, min: 0, max: 1.5, step: 0.01 },
Expand All @@ -23,7 +26,12 @@ export default function Screen() {

return (
<div style={{ height: '100vh', width: '100vw' }}>
<Canvas camera={camera}>
<Canvas
camera={camera}
onWheel={(e) =>
setCameraToCurrentView(cameraToCurrentView + e.deltaY / 20)
}
>
<EffectComposer>
<Bloom
intensity={intensity}
Expand Down
1 change: 1 addition & 0 deletions packages/client/src/constants/camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ type Vector3 = [number, number, number];
export const CAMERA_POSITION: Vector3 = [0, 2000, 2000];
export const CAMERA_ROTATION: Vector3 = [-0.5, 0, 0];
export const CAMERA_FAR = 100000;
export const CAMERA_MIN_DISTANCE = 100;
9 changes: 9 additions & 0 deletions packages/client/src/store/useCameraStore.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import { create } from 'zustand';
import * as THREE from 'three';
import { CAMERA_MIN_DISTANCE } from 'constants/camera';

interface cameraState {
currentView: THREE.Vector3;
setCurrentView: (position: THREE.Vector3) => void;
targetView: THREE.Mesh | null;
setTargetView: (star: THREE.Mesh | null) => void;
cameraToCurrentView: number;
setCameraToCurrentView: (distance: number) => void;
}

export const useCameraStore = create<cameraState>()((set) => ({
currentView: new THREE.Vector3(0, 0, 0),
setCurrentView: (position: THREE.Vector3) => set({ currentView: position }),
targetView: null,
setTargetView: (star: THREE.Mesh | null) => set({ targetView: star }),
cameraToCurrentView: CAMERA_MIN_DISTANCE,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뭔가 camera에서 CurrentView로 이동해야할 것만 같은 이름인데..
더 좋은 네이밍이 있을 것 같은데 저도 마땅한게 안떠오르네요
DistanceBetweenAandB 형식으로 하면 너무 길 것 같은디..

setCameraToCurrentView: (distance: number) =>
set({
cameraToCurrentView:
distance > CAMERA_MIN_DISTANCE ? distance : CAMERA_MIN_DISTANCE,
}),
}));