feat(earth): satellite dot rendering with hover/lock rings, dim cables when satellite locked
- Change satellite points from squares to circular dots - Add hover ring (white) and lock ring (yellow) for satellites - Fix satellite hover/lock ring state management - Dim all cables when satellite is locked - Increase MAX_SATELLITES to 2000 - Fix satIntersects scoping bug
This commit is contained in:
@@ -12,25 +12,76 @@ let showTrails = true;
|
||||
let animationTime = 0;
|
||||
let selectedSatellite = null;
|
||||
let satellitePositions = [];
|
||||
let hoverRingSprite = null;
|
||||
let lockedRingSprite = null;
|
||||
|
||||
const SATELLITE_API = '/api/v1/visualization/geo/satellites?limit=2000';
|
||||
const MAX_SATELLITES = 500;
|
||||
const MAX_SATELLITES = 2000;
|
||||
const TRAIL_LENGTH = 30;
|
||||
const DOT_TEXTURE_SIZE = 32;
|
||||
|
||||
function createCircularDotTexture() {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = DOT_TEXTURE_SIZE;
|
||||
canvas.height = DOT_TEXTURE_SIZE;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const center = DOT_TEXTURE_SIZE / 2;
|
||||
const radius = center - 2;
|
||||
|
||||
const gradient = ctx.createRadialGradient(center, center, 0, center, center, radius);
|
||||
gradient.addColorStop(0, 'rgba(255, 255, 255, 1)');
|
||||
gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.8)');
|
||||
gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
|
||||
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.beginPath();
|
||||
ctx.arc(center, center, radius, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
const texture = new THREE.CanvasTexture(canvas);
|
||||
texture.needsUpdate = true;
|
||||
return texture;
|
||||
}
|
||||
|
||||
function createRingTexture(innerRadius, outerRadius, color = '#ffffff') {
|
||||
const size = DOT_TEXTURE_SIZE * 2;
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const center = size / 2;
|
||||
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 3;
|
||||
ctx.beginPath();
|
||||
ctx.arc(center, center, (innerRadius + outerRadius) / 2, 0, Math.PI * 2);
|
||||
ctx.stroke();
|
||||
|
||||
const texture = new THREE.CanvasTexture(canvas);
|
||||
texture.needsUpdate = true;
|
||||
return texture;
|
||||
}
|
||||
|
||||
export function createSatellites(scene, earthObj) {
|
||||
initSatelliteScene(scene, earthObj);
|
||||
|
||||
const positions = new Float32Array(MAX_SATELLITES * 3);
|
||||
const colors = new Float32Array(MAX_SATELLITES * 3);
|
||||
|
||||
const dotTexture = createCircularDotTexture();
|
||||
|
||||
const pointsGeometry = new THREE.BufferGeometry();
|
||||
pointsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||
pointsGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
|
||||
|
||||
const pointsMaterial = new THREE.PointsMaterial({
|
||||
size: 3,
|
||||
size: 1.5,
|
||||
map: dotTexture,
|
||||
vertexColors: true,
|
||||
transparent: true,
|
||||
opacity: 0.9,
|
||||
sizeAttenuation: true
|
||||
sizeAttenuation: true,
|
||||
alphaTest: 0.1
|
||||
});
|
||||
|
||||
satellitePoints = new THREE.Points(pointsGeometry, pointsMaterial);
|
||||
@@ -176,7 +227,7 @@ export function updateSatellitePositions(deltaTime = 0) {
|
||||
const trailColors = satelliteTrails.geometry.attributes.color.array;
|
||||
|
||||
const baseTime = new Date();
|
||||
const count = Math.min(satelliteData.length, 500);
|
||||
const count = Math.min(satelliteData.length, MAX_SATELLITES);
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const satellite = satelliteData[i];
|
||||
@@ -315,3 +366,91 @@ export function selectSatellite(index) {
|
||||
export function getSatellitePoints() {
|
||||
return satellitePoints;
|
||||
}
|
||||
|
||||
export function getSatellitePositions() {
|
||||
return satellitePositions;
|
||||
}
|
||||
|
||||
let earthObjRef = null;
|
||||
let sceneRef = null;
|
||||
|
||||
export function showHoverRing(position, isLocked = false) {
|
||||
if (!sceneRef || !earthObjRef) return;
|
||||
|
||||
const ringTexture = createRingTexture(8, 12, isLocked ? '#ffcc00' : '#ffffff');
|
||||
const spriteMaterial = new THREE.SpriteMaterial({
|
||||
map: ringTexture,
|
||||
transparent: true,
|
||||
opacity: 0.8,
|
||||
depthTest: false
|
||||
});
|
||||
|
||||
const sprite = new THREE.Sprite(spriteMaterial);
|
||||
sprite.position.copy(position);
|
||||
sprite.scale.set(3, 3, 1);
|
||||
|
||||
earthObjRef.add(sprite);
|
||||
|
||||
if (isLocked) {
|
||||
if (lockedRingSprite) {
|
||||
earthObjRef.remove(lockedRingSprite);
|
||||
}
|
||||
lockedRingSprite = sprite;
|
||||
} else {
|
||||
if (hoverRingSprite) {
|
||||
earthObjRef.remove(hoverRingSprite);
|
||||
}
|
||||
hoverRingSprite = sprite;
|
||||
}
|
||||
|
||||
return sprite;
|
||||
}
|
||||
|
||||
export function hideHoverRings() {
|
||||
if (!earthObjRef) return;
|
||||
|
||||
if (hoverRingSprite) {
|
||||
earthObjRef.remove(hoverRingSprite);
|
||||
hoverRingSprite = null;
|
||||
}
|
||||
}
|
||||
|
||||
export function hideLockedRing() {
|
||||
if (!earthObjRef || !lockedRingSprite) return;
|
||||
earthObjRef.remove(lockedRingSprite);
|
||||
lockedRingSprite = null;
|
||||
}
|
||||
|
||||
export function updateLockedRingPosition(position) {
|
||||
if (lockedRingSprite && position) {
|
||||
lockedRingSprite.position.copy(position);
|
||||
}
|
||||
}
|
||||
|
||||
export function updateHoverRingPosition(position) {
|
||||
if (hoverRingSprite && position) {
|
||||
hoverRingSprite.position.copy(position);
|
||||
}
|
||||
}
|
||||
|
||||
export function setSatelliteRingState(index, state, position) {
|
||||
switch (state) {
|
||||
case 'hover':
|
||||
hideHoverRings();
|
||||
showHoverRing(position, false);
|
||||
break;
|
||||
case 'locked':
|
||||
hideHoverRings();
|
||||
showHoverRing(position, true);
|
||||
break;
|
||||
case 'none':
|
||||
hideHoverRings();
|
||||
hideLockedRing();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function initSatelliteScene(scene, earth) {
|
||||
sceneRef = scene;
|
||||
earthObjRef = earth;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user