97 lines
4.1 KiB
TypeScript
97 lines
4.1 KiB
TypeScript
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||
|
import { useThree } from "@react-three/fiber";
|
||
|
import * as THREE from "three";
|
||
|
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
||
|
|
||
|
export default function ZoneCentreTarget() {
|
||
|
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||
|
const [previousZoneCentre, setPreviousZoneCentre] = useState<number[] | null>(null);
|
||
|
const sphereRef = useRef<THREE.Mesh>(null);
|
||
|
const { camera, controls }: any = useThree();
|
||
|
|
||
|
|
||
|
useEffect(() => {
|
||
|
if (
|
||
|
selectedZone.zoneViewPortTarget &&
|
||
|
JSON.stringify(previousZoneCentre) !== JSON.stringify(selectedZone.zoneViewPortTarget)
|
||
|
) {
|
||
|
setPreviousZoneCentre(selectedZone.zoneViewPortTarget);
|
||
|
}
|
||
|
}, [selectedZone.zoneViewPortTarget, previousZoneCentre]);
|
||
|
|
||
|
const centrePoint = useMemo(() => {
|
||
|
if (!previousZoneCentre || !selectedZone.zoneViewPortTarget) return null;
|
||
|
return previousZoneCentre.map((value, index) =>
|
||
|
(value + selectedZone.zoneViewPortTarget[index]) / 2
|
||
|
);
|
||
|
}, [previousZoneCentre, selectedZone.zoneViewPortTarget]);
|
||
|
|
||
|
useEffect(() => {
|
||
|
if (selectedZone.zoneName !== "") {
|
||
|
if (sphereRef.current) {
|
||
|
sphereRef.current.position.set(selectedZone.zoneViewPortTarget[0], selectedZone.zoneViewPortTarget[1], selectedZone.zoneViewPortTarget[2]);
|
||
|
}
|
||
|
if (centrePoint) {
|
||
|
|
||
|
if (centrePoint.length > 0) {
|
||
|
|
||
|
let camPosition = new THREE.Vector3(...selectedZone.zoneViewPortPosition);
|
||
|
let CamTarget = new THREE.Vector3(...selectedZone.zoneViewPortTarget);
|
||
|
|
||
|
const direction = new THREE.Vector3().subVectors(CamTarget, camPosition).normalize();
|
||
|
|
||
|
const worldUp = new THREE.Vector3(0, 0, 1);
|
||
|
const right = new THREE.Vector3().crossVectors(worldUp, direction).normalize();
|
||
|
const up = new THREE.Vector3().crossVectors(direction, right).normalize();
|
||
|
|
||
|
const offsetPosition = up.clone().multiplyScalar(20);
|
||
|
|
||
|
camPosition.add(offsetPosition);
|
||
|
|
||
|
|
||
|
const setCam = async () => {
|
||
|
controls.setLookAt(centrePoint[0], 100, centrePoint[2], ...centrePoint, true);
|
||
|
setTimeout(() => {
|
||
|
controls?.setLookAt(
|
||
|
...camPosition.toArray(),
|
||
|
selectedZone.zoneViewPortTarget[0],
|
||
|
selectedZone.zoneViewPortTarget[1],
|
||
|
selectedZone.zoneViewPortTarget[2],
|
||
|
true
|
||
|
);
|
||
|
}, 400)
|
||
|
};
|
||
|
setCam();
|
||
|
} else {
|
||
|
|
||
|
let camPosition = new THREE.Vector3(...selectedZone.zoneViewPortPosition);
|
||
|
let CamTarget = new THREE.Vector3(...selectedZone.zoneViewPortTarget);
|
||
|
|
||
|
const direction = new THREE.Vector3().subVectors(CamTarget, camPosition).normalize();
|
||
|
|
||
|
const worldUp = new THREE.Vector3(0, 0, 1);
|
||
|
const right = new THREE.Vector3().crossVectors(worldUp, direction).normalize();
|
||
|
const up = new THREE.Vector3().crossVectors(direction, right).normalize();
|
||
|
|
||
|
const offsetPosition = up.clone().multiplyScalar(20);
|
||
|
|
||
|
camPosition.add(offsetPosition);
|
||
|
const setCam = async () => {
|
||
|
controls?.setLookAt(
|
||
|
...camPosition.toArray(),
|
||
|
selectedZone.zoneViewPortTarget[0],
|
||
|
selectedZone.zoneViewPortTarget[1],
|
||
|
selectedZone.zoneViewPortTarget[2],
|
||
|
true
|
||
|
);
|
||
|
};
|
||
|
setCam();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}, [selectedZone.zoneViewPortTarget, camera, controls]);
|
||
|
return (
|
||
|
<> </>
|
||
|
);
|
||
|
}
|