+++ date = "2024-08-01" tags = ["react", "vrm"] title = "react-threeを使ってglbを表示する" +++ 今回はreactの`tsx`で書きます。 ```sh $ npx create-react-app galaxy --template typescript ``` これで準備はできましたが、設定ファイルを見てみます。 ```json:tsconfig.json { "compilerOptions": { "target": "es5", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": [ "src" ] } ``` `es5`, `react-jsx`を使っているようです。 buildなどはwebpackではなく`react-scripts`ですね。 ```json:package.json "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" } ``` ```ts:src/App.tsx import React from 'react'; import './App.css'; import { ThreeFiberGalaxy } from './pages/galaxy'; function App() { return } export default App; ``` 今回はこれを改造していきます。 [package.json](https://git.syui.ai/ai/star/src/branch/main/galaxy-react/package.json) ```ts:src/pages/galaxy.tsx // https://gist.github.com/artokun/fb7f0c68a01ba5d9813abb3ccce254c4 import * as THREE from 'three' import { Points, useGLTF } from '@react-three/drei' import { GLTF } from 'three-stdlib' import { useFrame, Canvas } from '@react-three/fiber' import { useMemo, useRef } from 'react' import { EffectComposer, SelectiveBloom } from '@react-three/postprocessing' type GLTFResult = GLTF & { nodes: { Object_2: THREE.Mesh } materials: { ['Scene_-_Root']: THREE.PointsMaterial } } export function Galaxy(props: JSX.IntrinsicElements['group']) { const ref = useRef(null!) const galaxyCenterLightRef = useRef(null!) const { nodes } = useGLTF('./models/galaxy.glb') as GLTFResult const [positions, colors] = useMemo(() => { nodes.Object_2.geometry.center() const positions = new Float32Array( nodes.Object_2.geometry.attributes.position.array.buffer ) const colors = new Float32Array(positions.length) const getDistanceToCenter = (x: number, y: number, z: number) => Math.sqrt(x * x + y * y + z * z) // make colors closer to 0,0,0 be more reddish and colors further away be more blueish const color = new THREE.Color() for (let i = 0; i < positions.length; i += 3) { const x = positions[i] const y = positions[i + 1] const z = positions[i + 2] const distanceToCenter = getDistanceToCenter(x, y, z) const normalizedDistanceToCenter = distanceToCenter / 100 // make colors closer to 0,0,0 be more reddish and colors further away be more blueish (do not use hsl) // color.setHSL( // (0.15 * (0.21 + Math.cos(distanceToCenter * 0.02))) / 2, // 0.75, // 0.6 // ) color.setRGB( Math.cos(normalizedDistanceToCenter), THREE.MathUtils.randFloat(0, 0.8), Math.sin(normalizedDistanceToCenter) ) color.toArray(colors, i) } return [positions, colors] }, [nodes]) //const starTexture = useLoader(THREE.TextureLoader, '/star.png') // slowly rotate the galaxy useFrame(({ clock }) => { ref.current.rotation.z = clock.getElapsedTime() / 5 // zoom in and out // ref.current.scale.setScalar(Math.sin(clock.getElapsedTime() / 2) + 1.5) }) // make particles glow return ( ) } useGLTF.preload('./models/galaxy.glb') ``` `App.tsx`で読み込むため以下を追記します。 ```ts:src/pages/galaxy.tsx export const ThreeFiberGalaxy = () => { return ( ) } ``` `public/models/galaxy.glb`を置いてください。とりあえずこれで完了です。 ```sh $ npm run start ``` controlを追加します。 ```sh import { Points, useGLTF, OrbitControls } from '@react-three/drei' export const ThreeFiberGalaxy = () => { return ( ) } ``` できましたね。大体はこんな感じになります。 他のカスタマイズについては`perplexity.ai`にでも聞いてみてください。