Merge e_bike + gps into develop #7

Merged
math-pixel merged 23 commits from feat/gps into develop 2026-05-28 05:55:19 +00:00
3 changed files with 51 additions and 4 deletions
Showing only changes of commit 011e7815a2 - Show all commits
+1
View File
@@ -250,6 +250,7 @@ export function Ebike({ position }: EbikeProps): React.JSX.Element {
minZ: -142, minZ: -142,
maxZ: 138, maxZ: 138,
}} }}
zoom={4}
/> />
</group> </group>
</group> </group>
+48 -4
View File
@@ -42,6 +42,21 @@ export interface EbikeGPSMapProps {
* Optional world position for the GPS screen (defaults to origin) * Optional world position for the GPS screen (defaults to origin)
*/ */
position?: [number, number, number]; position?: [number, number, number];
/**
* Resolution of the offscreen canvas used for the map texture.
* Higher values yield sharper rendering at the cost of GPU memory.
* Default: 1024 (1024×1024 px)
*/
canvasSize?: number;
/**
* Zoom level applied to the map view.
* 1 = full world bounds, 2 = 2× zoom-in centred on the player, etc.
* Values < 1 zoom out beyond the calculated world bounds.
* Default: 1
*/
zoom?: number;
} }
/** /**
@@ -58,6 +73,8 @@ export const EbikeGPSMap: React.FC<EbikeGPSMapProps> = ({
width = 1, width = 1,
height = 1, height = 1,
position = [0, 0, 0], position = [0, 0, 0],
canvasSize = 1024,
zoom = 1,
}) => { }) => {
const [waypoints, setWaypoints] = useState<Waypoint[]>([]); const [waypoints, setWaypoints] = useState<Waypoint[]>([]);
const [mapImage, setMapImage] = useState<HTMLImageElement | HTMLCanvasElement | null>(null); const [mapImage, setMapImage] = useState<HTMLImageElement | HTMLCanvasElement | null>(null);
@@ -65,11 +82,20 @@ export const EbikeGPSMap: React.FC<EbikeGPSMapProps> = ({
// Offscreen high-res canvas for crystal clear rendering // Offscreen high-res canvas for crystal clear rendering
const [offscreenCanvas] = useState(() => { const [offscreenCanvas] = useState(() => {
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.width = 1024; canvas.width = canvasSize;
canvas.height = 1024; canvas.height = canvasSize;
return canvas; return canvas;
}); });
// Resize the canvas whenever canvasSize changes
useEffect(() => {
offscreenCanvas.width = canvasSize;
offscreenCanvas.height = canvasSize;
if (textureRef.current) {
textureRef.current.needsUpdate = true;
}
}, [canvasSize, offscreenCanvas]);
const textureRef = useRef<THREE.CanvasTexture | null>(null); const textureRef = useRef<THREE.CanvasTexture | null>(null);
const animTimeRef = useRef<number>(0); const animTimeRef = useRef<number>(0);
@@ -123,8 +149,8 @@ export const EbikeGPSMap: React.FC<EbikeGPSMapProps> = ({
img.src = mapImageUrl; img.src = mapImageUrl;
}, [mapImageUrl]); }, [mapImageUrl]);
// Determine grid boundaries // Determine grid boundaries (before zoom)
const bounds = useMemo(() => { const baseBounds = useMemo(() => {
if (worldBounds) return worldBounds; if (worldBounds) return worldBounds;
if (waypoints.length === 0) { if (waypoints.length === 0) {
@@ -150,6 +176,24 @@ export const EbikeGPSMap: React.FC<EbikeGPSMapProps> = ({
}; };
}, [waypoints, worldBounds]); }, [waypoints, worldBounds]);
// Apply zoom: shrink the view window around the player position
const bounds = useMemo(() => {
const clampedZoom = Math.max(0.1, zoom);
if (clampedZoom === 1) return baseBounds;
const centerX = startPos.x;
const centerZ = startPos.z;
const halfW = (baseBounds.maxX - baseBounds.minX) / 2 / clampedZoom;
const halfH = (baseBounds.maxZ - baseBounds.minZ) / 2 / clampedZoom;
return {
minX: centerX - halfW,
maxX: centerX + halfW,
minZ: centerZ - halfH,
maxZ: centerZ + halfH,
};
}, [baseBounds, zoom, startPos]);
// Snapped positions // Snapped positions
const startPosSnapped = useMemo(() => { const startPosSnapped = useMemo(() => {
if (waypoints.length === 0) return null; if (waypoints.length === 0) return null;
+2
View File
@@ -266,6 +266,8 @@ export function TestMap({ onOctreeReady }: TestMapProps): React.JSX.Element {
"minZ": -142, "minZ": -142,
"maxZ": 138 "maxZ": 138
}} }}
zoom={1}
canvasSize={900}
/> />
</group> </group>
</group> </group>