Skip to content

Commit 5c4eb6e

Browse files
cjw6kclaude
andcommitted
fix: Keep tidal bulge aligned with Moon during Earth rotation
The tidal bulge was incorrectly rotating with Earth instead of staying aligned with the Moon. Fixed by transforming the moon/sun direction vectors from world space to object space using the inverse of the mesh's rotation quaternion. Now the bulge correctly points toward the Moon regardless of Earth's rotation, as it should physically. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0957ce3 commit 5c4eb6e

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

tidal-harmonics/src/components/canvas/TidalEarth.tsx

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useRef, useMemo } from 'react';
22
import { useFrame, useLoader } from '@react-three/fiber';
3-
import { TextureLoader, Vector3, Texture } from 'three';
3+
import { TextureLoader, Vector3, Texture, Quaternion } from 'three';
44
import type { Mesh } from 'three';
55
import { useCelestialPositions } from '@/hooks/useCelestialPositions';
66
import { useScene } from '@/hooks/useScene';
@@ -92,9 +92,28 @@ export function TidalEarth() {
9292
);
9393

9494
useFrame(({ clock }, delta) => {
95-
// Update moon/sun directions (normalized)
96-
uniforms.moonDirection.value.set(moon[0], moon[1], moon[2]).normalize();
97-
uniforms.sunDirection.value.set(sun[0], sun[1], sun[2]).normalize();
95+
// Earth rotation (do this first so we can use the rotation to transform directions)
96+
if (meshRef.current && playing) {
97+
meshRef.current.rotation.y += ROTATION_SPEEDS.EARTH * delta * speed;
98+
}
99+
100+
// Transform moon/sun directions from world space to object space
101+
// This ensures the tidal bulge always points toward the Moon regardless of Earth's rotation
102+
const moonDir = new Vector3(moon[0], moon[1], moon[2]).normalize();
103+
const sunDir = new Vector3(sun[0], sun[1], sun[2]).normalize();
104+
105+
if (meshRef.current) {
106+
// Get inverse of mesh rotation to transform world -> object space
107+
const inverseQuat = new Quaternion();
108+
meshRef.current.getWorldQuaternion(inverseQuat);
109+
inverseQuat.invert();
110+
111+
moonDir.applyQuaternion(inverseQuat);
112+
sunDir.applyQuaternion(inverseQuat);
113+
}
114+
115+
uniforms.moonDirection.value.copy(moonDir);
116+
uniforms.sunDirection.value.copy(sunDir);
98117

99118
// Pedagogical tidal amplitude for visible effect
100119
// Physical amplitude (0.53m / 6,371km = 8.3e-8) is invisible even at 50,000×
@@ -115,11 +134,6 @@ export function TidalEarth() {
115134
}
116135

117136
uniforms.tidalAmplitude.value = amplitude;
118-
119-
// Earth rotation
120-
if (meshRef.current && playing) {
121-
meshRef.current.rotation.y += ROTATION_SPEEDS.EARTH * delta * speed;
122-
}
123137
});
124138

125139
return (

0 commit comments

Comments
 (0)