Skip to content

Commit

Permalink
feat: キャラ編集のUXを向上 (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
shun-shobon authored Nov 5, 2024
2 parents e23dcc9 + 3846e50 commit 60f8e86
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
71 changes: 60 additions & 11 deletions app/components/ModelLoad.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { OrbitControls, useGLTF } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import { Billboard, OrbitControls, Text, useGLTF } from "@react-three/drei";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { Bloom, EffectComposer } from "@react-three/postprocessing";
import { type ReactNode, useEffect, useRef } from "react";
import type { Group, MeshStandardMaterial } from "three";
import { type ReactNode, Suspense, useEffect, useMemo, useRef } from "react";
import type { MeshStandardMaterial } from "three";
import * as THREE from "three";
import { OutlineEffect } from "three/addons/effects/OutlineEffect.js";
import type { Accessory, CharacterSetting } from "~/features/profile/Profile";

const HAIR_MESH_NAMES = [
Expand Down Expand Up @@ -39,11 +40,15 @@ function useCharacterSetting(setting: CharacterSetting) {

const { scene } = useGLTF(modelPath);

useEffect(() => {
const threeTone = useMemo(() => {
const threeTone = new THREE.TextureLoader().load("/assets/threeTone.jpg");
threeTone.minFilter = THREE.NearestFilter;
threeTone.magFilter = THREE.NearestFilter;

return threeTone;
}, []);

useEffect(() => {
scene.traverse((child) => {
if (!(child as THREE.Mesh).isMesh) return;
const mesh = child as THREE.Mesh;
Expand All @@ -56,10 +61,11 @@ function useCharacterSetting(setting: CharacterSetting) {
emissive: oldMaterial.emissive,
emissiveIntensity: oldMaterial.emissiveIntensity,
emissiveMap: oldMaterial.emissiveMap,
side: oldMaterial.side,
});
mesh.material = newMaterial;
});
}, [scene]);
}, [scene, threeTone]);

useEffect(() => {
scene.traverse((child) => {
Expand Down Expand Up @@ -111,26 +117,69 @@ export function ModelViewer({ characterSetting }: ModelProps): ReactNode {
background: new THREE.Color("#0ea5e9"),
}}
camera={{
position: [0, 0, 2],
position: [1, 0, 2],
fov: 30,
}} // カメラの初期位置と視野角を設定
>
{/* ライトを設定 */}
<ambientLight />
<directionalLight position={[6, 5, 5]} intensity={1} />
{/* ポストプロセッシング */}
<EffectComposer>
<EffectComposer autoClear={false}>
<Bloom intensity={1} luminanceThreshold={1} radius={0.8} mipmapBlur />
</EffectComposer>
{/* GLBモデルの読み込みと表示 */}
<Model characterSetting={characterSetting} />
<Suspense
fallback={
<Billboard>
<Text
fontSize={0.1}
font="/assets/font.ttf"
characters="読み込み中…"
>
読み込み中…
</Text>
</Billboard>
}
>
{/* GLBモデルの読み込みと表示 */}
<Model characterSetting={characterSetting} />
</Suspense>
{/* カメラコントロールの追加(ユーザーが自由にカメラを操作できるようにする) */}
<OrbitControls
enableZoom={false}
enablePan={false}
minPolarAngle={(Math.PI / 5) * 2}
maxPolarAngle={(Math.PI / 5) * 2}
maxDistance={3}
minDistance={1}
autoRotate
autoRotateSpeed={2}
/>
{/* アウトラインエフェクト */}
{/* <OutlineRenderer /> */}
</Canvas>
);
}

// 参考: https://github.com/pmndrs/react-three-fiber/discussions/1045
function OutlineRenderer(): ReactNode {
const { size, gl, scene, camera } = useThree();

const effect = useMemo(() => {
const effect = new OutlineEffect(gl, {
defaultThickness: 0.003,
defaultColor: new THREE.Color("#333333").toArray(),
});

return effect;
}, [gl]);

useEffect(() => {
effect.setSize(size.width, size.height);
}, [effect, size]);

useFrame(() => {
effect.render(scene, camera);
}, 1);

return null;
}
Binary file added public/assets/font.ttf
Binary file not shown.

0 comments on commit 60f8e86

Please sign in to comment.