fix(satellites): prevent selecting satellites on far side of earth

- Add isSatelliteFrontFacing() to detect if satellite is on visible side
- Filter satellites in hover and click handlers by front-facing check
- Apply same logic as cables for consistent back-face culling
This commit is contained in:
linkong
2026-03-24 10:44:06 +08:00
parent 543fe35fbb
commit b9fbacade7
2 changed files with 27 additions and 7 deletions

View File

@@ -14,7 +14,7 @@ import {
} from './ui.js'; } from './ui.js';
import { createEarth, createClouds, createTerrain, createStars, createGridLines, toggleTerrain, getEarth } from './earth.js'; import { createEarth, createClouds, createTerrain, createStars, createGridLines, toggleTerrain, getEarth } from './earth.js';
import { loadGeoJSONFromPath, loadLandingPoints, handleCableClick, clearCableSelection, getCableLines, getCablesById, lockedCable as cableLocked, getCableState, setCableState, clearAllCableStates, applyLandingPointVisualState, resetLandingPointVisualState, getAllLandingPoints, getShowCables } from './cables.js'; import { loadGeoJSONFromPath, loadLandingPoints, handleCableClick, clearCableSelection, getCableLines, getCablesById, lockedCable as cableLocked, getCableState, setCableState, clearAllCableStates, applyLandingPointVisualState, resetLandingPointVisualState, getAllLandingPoints, getShowCables } from './cables.js';
import { createSatellites, loadSatellites, updateSatellitePositions, toggleSatellites, toggleTrails, getShowSatellites, getSatelliteCount, selectSatellite, getSatelliteData, getSatellitePoints, setSatelliteRingState, updateLockedRingPosition, updateHoverRingPosition, getSatellitePositions, showPredictedOrbit, hidePredictedOrbit, updateBreathingPhase } from './satellites.js'; import { createSatellites, loadSatellites, updateSatellitePositions, toggleSatellites, toggleTrails, getShowSatellites, getSatelliteCount, selectSatellite, getSatelliteData, getSatellitePoints, setSatelliteRingState, updateLockedRingPosition, updateHoverRingPosition, getSatellitePositions, showPredictedOrbit, hidePredictedOrbit, updateBreathingPhase, isSatelliteFrontFacing } from './satellites.js';
import { setupControls, getAutoRotate, getShowTerrain, zoomLevel, setAutoRotate, toggleAutoRotate, resetView } from './controls.js'; import { setupControls, getAutoRotate, getShowTerrain, zoomLevel, setAutoRotate, toggleAutoRotate, resetView } from './controls.js';
import { initInfoCard, showInfoCard, hideInfoCard, getCurrentType, setInfoCardNoBorder } from './info-card.js'; import { initInfoCard, showInfoCard, hideInfoCard, getCurrentType, setInfoCardNoBorder } from './info-card.js';
@@ -301,8 +301,11 @@ function onMouseMove(event, camera) {
if (satPoints) { if (satPoints) {
const satIntersects = raycaster.intersectObject(satPoints); const satIntersects = raycaster.intersectObject(satPoints);
if (satIntersects.length > 0) { if (satIntersects.length > 0) {
hoveredSatIndexFromIntersect = satIntersects[0].index; const satIndex = satIntersects[0].index;
hoveredSat = selectSatellite(hoveredSatIndexFromIntersect); if (isSatelliteFrontFacing(satIndex, camera)) {
hoveredSatIndexFromIntersect = satIndex;
hoveredSat = selectSatellite(hoveredSatIndexFromIntersect);
}
} }
} }
} }
@@ -440,14 +443,17 @@ function onClick(event, camera, renderer) {
const clickY = event.clientY; const clickY = event.clientY;
let selectedIndex; let selectedIndex;
if (satIntersects.length > 1 && const frontFacingSats = satIntersects.filter(s => isSatelliteFrontFacing(s.index, camera));
if (frontFacingSats.length === 0) return;
if (frontFacingSats.length > 1 &&
now - lastSatClickTime < 500 && now - lastSatClickTime < 500 &&
Math.abs(clickX - lastSatClickPos.x) < 30 && Math.abs(clickX - lastSatClickPos.x) < 30 &&
Math.abs(clickY - lastSatClickPos.y) < 30) { Math.abs(clickY - lastSatClickPos.y) < 30) {
const currentIdx = satIntersects.findIndex(s => s.index === lastSatClickIndex); const currentIdx = frontFacingSats.findIndex(s => s.index === lastSatClickIndex);
selectedIndex = satIntersects[(currentIdx + 1) % satIntersects.length].index; selectedIndex = frontFacingSats[(currentIdx + 1) % frontFacingSats.length].index;
} else { } else {
selectedIndex = satIntersects[0].index; selectedIndex = frontFacingSats[0].index;
} }
lastSatClickTime = now; lastSatClickTime = now;

View File

@@ -415,6 +415,20 @@ export function getSatellitePositions() {
return satellitePositions; return satellitePositions;
} }
export function isSatelliteFrontFacing(index, camera) {
if (!earthObjRef || !camera) return true;
const positions = satellitePositions;
if (!positions || !positions[index]) return true;
const satPos = positions[index].current;
if (!satPos) return true;
const toCamera = new THREE.Vector3().subVectors(camera.position, earthObjRef.position).normalize();
const toSat = new THREE.Vector3().subVectors(satPos, earthObjRef.position).normalize();
return toCamera.dot(toSat) < 0;
}
let earthObjRef = null; let earthObjRef = null;
let sceneRef = null; let sceneRef = null;