113 lines
3.8 KiB
TypeScript
113 lines
3.8 KiB
TypeScript
import { useRef, useEffect } from "react";
|
|
import { useThree } from "@react-three/fiber";
|
|
import * as THREE from "three";
|
|
import {
|
|
useAzimuth,
|
|
useElevation,
|
|
useShadows,
|
|
useSunPosition,
|
|
useFloorItems,
|
|
useWallItems,
|
|
useTileDistance,
|
|
} from "../../../store/store";
|
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
|
const shadowWorker = new Worker(
|
|
new URL(
|
|
"../../../services/factoryBuilder/webWorkers/shadowWorker",
|
|
import.meta.url
|
|
)
|
|
);
|
|
|
|
export default function Shadows() {
|
|
const { shadows, setShadows } = useShadows();
|
|
const { sunPosition, setSunPosition } = useSunPosition();
|
|
const lightRef = useRef<THREE.DirectionalLight | null>(null);
|
|
const targetRef = useRef<THREE.Object3D | null>(null);
|
|
const { controls, gl } = useThree();
|
|
const { elevation, setElevation } = useElevation();
|
|
const { azimuth, setAzimuth } = useAzimuth();
|
|
const { floorItems } = useFloorItems();
|
|
const { wallItems } = useWallItems();
|
|
const { planeValue } = useTileDistance();
|
|
|
|
useEffect(() => {
|
|
gl.shadowMap.enabled = true;
|
|
gl.shadowMap.type = THREE.PCFShadowMap;
|
|
}, [gl, floorItems, wallItems]);
|
|
|
|
useEffect(() => {
|
|
if (lightRef.current && targetRef.current) {
|
|
lightRef.current.target = targetRef.current;
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
shadowWorker.onmessage = (event) => {
|
|
const { lightPosition, controlsTarget } = event.data;
|
|
if (lightRef.current && targetRef.current && controls) {
|
|
lightRef.current.position.copy(lightPosition);
|
|
targetRef.current.position.copy(controlsTarget);
|
|
}
|
|
};
|
|
}, [shadowWorker, controls]);
|
|
|
|
const updateShadows = () => {
|
|
if (controls && shadowWorker) {
|
|
const offsetDistance = CONSTANTS.shadowConfig.shadowOffset;
|
|
const controlsTarget = (controls as any).getTarget();
|
|
shadowWorker.postMessage({ controlsTarget, sunPosition, offsetDistance });
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (controls && shadows) {
|
|
updateShadows();
|
|
(controls as any).addEventListener("update", updateShadows);
|
|
return () => {
|
|
(controls as any).removeEventListener("update", updateShadows);
|
|
};
|
|
}
|
|
}, [controls, elevation, azimuth, shadows]);
|
|
|
|
return (
|
|
<>
|
|
{/* {(lightRef.current?.shadow) &&
|
|
<cameraHelper visible={shadows} args={[lightRef.current.shadow.camera]} />
|
|
} */}
|
|
<directionalLight
|
|
ref={lightRef}
|
|
castShadow={shadows}
|
|
shadow-mapSize-width={CONSTANTS.shadowConfig.shadowmapSizewidth}
|
|
shadow-mapSize-height={CONSTANTS.shadowConfig.shadowmapSizeheight}
|
|
shadow-camera-far={CONSTANTS.shadowConfig.shadowcamerafar}
|
|
shadow-camera-near={CONSTANTS.shadowConfig.shadowcameranear}
|
|
shadow-camera-top={CONSTANTS.shadowConfig.shadowcameratop}
|
|
shadow-camera-bottom={CONSTANTS.shadowConfig.shadowcamerabottom}
|
|
shadow-camera-left={CONSTANTS.shadowConfig.shadowcameraleft}
|
|
shadow-camera-right={CONSTANTS.shadowConfig.shadowcameraright}
|
|
shadow-bias={CONSTANTS.shadowConfig.shadowbias}
|
|
shadow-normalBias={CONSTANTS.shadowConfig.shadownormalBias}
|
|
/>
|
|
<object3D ref={targetRef} />
|
|
<mesh
|
|
position={CONSTANTS.shadowConfig.shadowMaterialPosition}
|
|
rotation={CONSTANTS.shadowConfig.shadowMaterialRotation}
|
|
receiveShadow
|
|
>
|
|
{/* <planeGeometry
|
|
args={[CONSTANTS.planeConfig.width, CONSTANTS.planeConfig.height]}
|
|
/>
|
|
<shadowMaterial
|
|
opacity={CONSTANTS.shadowConfig.shadowMaterialOpacity}
|
|
transparent
|
|
/> */}
|
|
<planeGeometry args={[planeValue.width, planeValue.height]} />
|
|
<shadowMaterial
|
|
opacity={CONSTANTS.shadowConfig.shadowMaterialOpacity}
|
|
transparent
|
|
/>
|
|
</mesh>
|
|
</>
|
|
);
|
|
}
|