diff --git a/src/pages/Simulation/components/PlanetMesh.tsx b/src/pages/Simulation/components/PlanetMesh.tsx index c4b7250..059cafc 100644 --- a/src/pages/Simulation/components/PlanetMesh.tsx +++ b/src/pages/Simulation/components/PlanetMesh.tsx @@ -5,7 +5,7 @@ import type React from "react"; import { useEffect, useMemo, useRef } from "react"; import * as THREE from "three"; import type { Planet } from "@/types/planet"; -import { calc_gravity_force } from "../utils/gravityUtils"; +import { calcGravityForce } from "../utils/gravityUtils"; type PlanetMeshProps = { planet: Planet; @@ -89,6 +89,7 @@ export function PlanetMesh({ }, [planet.id, planetRegistry, planet.mass, planet.radius, ref]); // 計算用ベクトルをメモリに保持しておく(毎フレームnewしないため) + const force = useMemo(() => new THREE.Vector3(), []); const forceAccumulator = useMemo(() => new THREE.Vector3(), []); const myPosVec = useMemo(() => new THREE.Vector3(), []); const otherPosVec = useMemo(() => new THREE.Vector3(), []); @@ -113,13 +114,14 @@ export function PlanetMesh({ const otherMass = otherMesh.userData.mass || 1; const otherRadius = otherMesh.userData.radius || 0.1; - const force = calc_gravity_force( + calcGravityForce( myPosVec, planet.mass, planet.radius, otherPosVec, otherMass, otherRadius, + force, ); forceAccumulator.add(force); } diff --git a/src/pages/Simulation/utils/gravityUtils.ts b/src/pages/Simulation/utils/gravityUtils.ts index daf80e6..75d558b 100644 --- a/src/pages/Simulation/utils/gravityUtils.ts +++ b/src/pages/Simulation/utils/gravityUtils.ts @@ -1,25 +1,29 @@ -import * as THREE from "three"; +import type * as THREE from "three"; const G = 1; +const softeningFactor = 0.01; -export function calc_gravity_force( +export function calcGravityForce( targetPos: THREE.Vector3, targetMass: number, targetRadius: number, sourcePos: THREE.Vector3, sourceMass: number, sourceRadius: number, -): THREE.Vector3 { - const direction = new THREE.Vector3().subVectors(sourcePos, targetPos); - const distanceSq = direction.lengthSq(); + resultVec: THREE.Vector3, +): void { + const EPS = ((targetRadius + sourceRadius) / 2) * softeningFactor; + + resultVec.subVectors(sourcePos, targetPos); + const distanceSq = resultVec.lengthSq() + EPS ** 2; const distance = Math.sqrt(distanceSq); - // 2つの惑星が接触または重なっている場合は、引力を0にする - const minDistance = targetRadius + sourceRadius; - if (distance < minDistance) { - return new THREE.Vector3(0, 0, 0); + // 距離が0の場合、力は0として扱う(ゼロ除算を避ける) + if (distance === 0) { + resultVec.set(0, 0, 0); + return; } const forceScalar = (G * targetMass * sourceMass) / (distanceSq * distance); - return direction.multiplyScalar(forceScalar); + resultVec.multiplyScalar(forceScalar); }