Created
October 11, 2020 12:11
-
-
Save promontis/cced5498e7fdf64e9ac0bfdb83ee2c06 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface Props { | |
object: three.Object3D | undefined; | |
} | |
export const Gizmo = (props: Props) => { | |
const [scale, setScale] = useState(new three.Vector3()); | |
useFrame(({ camera }) => { | |
if (!props.object) { | |
return; | |
} | |
const worldPosition = new three.Vector3(); | |
const worldQuaternion = new three.Quaternion(); | |
const worldScale = new three.Vector3(); | |
props.object.matrixWorld.decompose(worldPosition, worldQuaternion, worldScale); | |
let factor; | |
if (camera.type === "OrthographicCamera") { | |
factor = (camera.top - camera.bottom) / camera.zoom; | |
} else { | |
const worldPosition = new three.Vector3(); | |
const worldQuaternion = new three.Quaternion(); | |
const worldScale = new three.Vector3(); | |
props.object.matrixWorld.decompose(worldPosition, worldQuaternion, worldScale); | |
factor = worldPosition.distanceTo(camera.position) * Math.min(1.9 * Math.tan(Math.PI * camera.fov / 360) / camera.zoom, 7); | |
} | |
setScale(new three.Vector3().set(1, 1, 1).multiplyScalar(factor / 7)); | |
}); | |
const points = useMemo(() => { | |
if (!props.object) { | |
return null; | |
} | |
const box = new three.Box3(); | |
box.setFromObject(props.object); | |
const min = box.min; | |
const max = box.max; | |
const y = 0.01; | |
const point0 = new three.Vector3(min.x, y, max.z); | |
const point1 = new three.Vector3(max.x, y, max.z); | |
const point2 = new three.Vector3(max.x, y, min.z); | |
const point3 = new three.Vector3(min.x, y, min.z); | |
const base = [ | |
point0, point1, | |
point1, point2, | |
point2, point3, | |
point3, point0 | |
]; | |
const centerX = (min.x + max.x) / 2; | |
const centerZ = (min.z + max.z) / 2; | |
const midDown = new three.Vector3(centerX, y, centerZ); | |
const midUp = new three.Vector3(centerX, max.y, centerZ); | |
const line = [midDown, midUp]; | |
const midXMinZ = new three.Vector3(centerX, 0, min.z); | |
const midXMaxZ = new three.Vector3(centerX, 0, max.z); | |
const midZMinX = new three.Vector3(min.x, 0, centerZ); | |
const midZMaxX = new three.Vector3(max.x, 0, centerZ); | |
return { | |
point0, | |
point1, | |
point2, | |
point3, | |
base, | |
line, | |
midXMinZ, | |
midXMaxZ, | |
midZMinX, | |
midZMaxX | |
}; | |
}, [props.object]); | |
const corner = useMemo(() => | |
<> | |
<Billboard size={0.05 * 1.6} color={new three.Color("black")} /> | |
<Billboard size={0.05} color={new three.Color("white")} /> | |
</>, []); | |
const mid = useMemo(() => | |
<> | |
<Billboard size={0.05} color={new three.Color("black")} /> | |
</>, []); | |
if (!props.object || !points) { | |
return null; | |
} | |
return ( | |
<group> | |
<lineSegments onUpdate={self => self.computeLineDistances()}> | |
<geometry attach="geometry" vertices={points.base} /> | |
<lineDashedMaterial color="black" dashSize={.8} gapSize={.4} attach="material" depthTest={false} /> | |
</lineSegments> | |
<lineSegments onUpdate={self => self.computeLineDistances()}> | |
<geometry attach="geometry" vertices={points.line} /> | |
<lineDashedMaterial color="black" dashSize={.8} gapSize={.4} attach="material" depthTest={false} /> | |
</lineSegments> | |
<EndPoint position={points.point0} scale={scale}>{corner}</EndPoint> | |
<EndPoint position={points.point1} scale={scale}>{corner}</EndPoint> | |
<EndPoint position={points.point2} scale={scale}>{corner}</EndPoint> | |
<EndPoint position={points.point3} scale={scale}>{corner}</EndPoint> | |
<EndPoint position={points.line[1]} scale={scale}>{corner}</EndPoint> | |
<EndPoint position={points.midXMinZ} scale={scale}>{mid}</EndPoint> | |
<EndPoint position={points.midXMaxZ} scale={scale}>{mid}</EndPoint> | |
<EndPoint position={points.midZMinX} scale={scale}>{mid}</EndPoint> | |
<EndPoint position={points.midZMaxX} scale={scale}>{mid}</EndPoint> | |
</group> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment