11import { useSphere } from "@react-three/cannon" ;
22import { Trail , useTexture } from "@react-three/drei" ;
33import { useFrame } from "@react-three/fiber" ;
4- import { useEffect , useMemo , useRef } from "react" ;
4+ import { useEffect , useMemo } from "react" ;
55import * as THREE from "three" ;
66import type { Planet } from "@/types/planet" ;
77import { GravitySystem } from "../core/GravitySystem" ;
8- import type { PlanetRegistry } from "../core/PlanetRegistry" ;
8+ import type { PlanetRegistry , PositionRef } from "../core/PlanetRegistry" ;
99
1010type PlanetMeshProps = {
1111 planet : Planet ;
@@ -20,45 +20,42 @@ export function PlanetMesh({
2020 onExplosion,
2121 onSelect,
2222} : PlanetMeshProps ) {
23- const [ ref , api ] = useSphere < THREE . Mesh > (
24- ( ) => ( {
25- mass : planet . mass ,
26- args : [ planet . radius ] ,
27- position : [ planet . position . x , planet . position . y , planet . position . z ] ,
28- velocity : [ planet . velocity . x , planet . velocity . y , planet . velocity . z ] ,
29- angularVelocity : [ 0 , planet . rotationSpeedY , 0 ] , // 物理エンジンでY軸周りの角速度を設定
30- linearDamping : 0 , // 宇宙空間なので抵抗なし
31- angularDamping : 0 , // 宇宙空間なので回転の減衰もない
32- onCollide : ( e ) => {
33- // 衝突時の衝撃が一定以上なら爆発とみなす
34- if ( e . contact . impactVelocity > 0.5 ) {
35- const contactPoint = new THREE . Vector3 (
36- e . contact . contactPoint [ 0 ] ,
37- e . contact . contactPoint [ 1 ] ,
38- e . contact . contactPoint [ 2 ] ,
39- ) ;
40- onExplosion ( contactPoint , planet . radius ) ;
41- }
42- } ,
43- } ) ,
44- useRef < THREE . Mesh > ( null ) ,
45- ) ;
23+ const [ ref , api ] = useSphere < THREE . Mesh > ( ( ) => ( {
24+ mass : planet . mass ,
25+ args : [ planet . radius ] ,
26+ position : [ planet . position . x , planet . position . y , planet . position . z ] ,
27+ velocity : [ planet . velocity . x , planet . velocity . y , planet . velocity . z ] ,
28+ angularVelocity : [ 0 , planet . rotationSpeedY , 0 ] , // 物理エンジンでY軸周りの角速度を設定
29+ linearDamping : 0 , // 宇宙空間なので抵抗なし
30+ angularDamping : 0 , // 宇宙空間なので回転の減衰もない
31+ onCollide : ( e ) => {
32+ // 衝突時の衝撃が一定以上なら爆発とみなす
33+ if ( e . contact . impactVelocity > 0.5 ) {
34+ const contactPoint = new THREE . Vector3 (
35+ e . contact . contactPoint [ 0 ] ,
36+ e . contact . contactPoint [ 1 ] ,
37+ e . contact . contactPoint [ 2 ] ,
38+ ) ;
39+ onExplosion ( contactPoint , planet . radius ) ;
40+ }
41+ } ,
42+ } ) ) ;
4643
4744 // Load the texture (you can use any public Earth texture URL)
4845 const [ colorMap ] = useTexture ( [ planet . texturePath ] ) ;
4946
50- // 物理エンジンの位置を追跡するためのref
51- const position = useRef ( [
52- planet . position . x ,
53- planet . position . y ,
54- planet . position . z ,
55- ] ) ;
47+ const position = useMemo < PositionRef > (
48+ ( ) => ( {
49+ current : [ planet . position . x , planet . position . y , planet . position . z ] ,
50+ } ) ,
51+ [ planet . position . x , planet . position . y , planet . position . z ] ,
52+ ) ;
5653 useEffect ( ( ) => {
5754 const unsubscribe = api . position . subscribe ( ( v ) => {
5855 position . current = v ;
5956 } ) ;
6057 return ( ) => unsubscribe ( ) ; // アンマウント時に購読解除
61- } , [ api . position ] ) ;
58+ } , [ api . position , position ] ) ;
6259
6360 // マウント時に自分のMeshをレジストリに登録し、他の惑星から参照できるようにする
6461 useEffect ( ( ) => {
@@ -77,7 +74,7 @@ export function PlanetMesh({
7774 return ( ) => {
7875 planetRegistry . unregister ( planet . id ) ;
7976 } ;
80- } , [ planet . id , planetRegistry , planet . mass , planet . radius , ref ] ) ;
77+ } , [ planet . id , planetRegistry , planet . mass , planet . radius , ref , position ] ) ;
8178
8279 // 計算用ベクトルをメモリに保持しておく(毎フレームnewしないため)
8380 const gravitySystem = useMemo ( ( ) => new GravitySystem ( ) , [ ] ) ;
0 commit comments