Add zoom to fit on first load (#561)
* get the bounding box of assets and get controls Ref * Add zoom to fit on first load Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
This commit was merged in pull request #561.
This commit is contained in:
@@ -19,17 +19,66 @@ import type { ArtifactTypes } from 'src/helpers/cadPackages/common'
|
|||||||
|
|
||||||
const thresholdAngle = 12
|
const thresholdAngle = 12
|
||||||
|
|
||||||
function Asset({ geometry: incomingGeo }) {
|
function Asset({
|
||||||
|
geometry: incomingGeo,
|
||||||
|
dataType,
|
||||||
|
controlsRef,
|
||||||
|
}: {
|
||||||
|
geometry: any
|
||||||
|
dataType: 'INIT' | ArtifactTypes
|
||||||
|
controlsRef: React.MutableRefObject<any>
|
||||||
|
}) {
|
||||||
|
const threeInstance = useThree()
|
||||||
|
const [initZoom, setInitZoom] = useState(true)
|
||||||
const mesh = useEdgeSplit((thresholdAngle * Math.PI) / 180, true, incomingGeo)
|
const mesh = useEdgeSplit((thresholdAngle * Math.PI) / 180, true, incomingGeo)
|
||||||
const edges = React.useMemo(
|
const edges = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
incomingGeo.length
|
incomingGeo.length || dataType !== 'geometry'
|
||||||
? null
|
? null
|
||||||
: new THREE.EdgesGeometry(incomingGeo, thresholdAngle),
|
: new THREE.EdgesGeometry(incomingGeo, thresholdAngle),
|
||||||
[incomingGeo]
|
[incomingGeo, dataType]
|
||||||
|
)
|
||||||
|
React.useEffect(() => {
|
||||||
|
const getBoundingSphere = () => {
|
||||||
|
if (dataType === 'geometry') {
|
||||||
|
return incomingGeo.boundingSphere
|
||||||
|
}
|
||||||
|
const group = new THREE.Group()
|
||||||
|
incomingGeo.forEach((mesh) => group.add(mesh))
|
||||||
|
const bbox = new THREE.Box3().setFromObject(group)
|
||||||
|
return bbox.getBoundingSphere(new THREE.Sphere())
|
||||||
|
}
|
||||||
|
const bSphere = getBoundingSphere()
|
||||||
|
|
||||||
|
const zoomToFit = () => {
|
||||||
|
const { center, radius } = bSphere
|
||||||
|
const { camera } = threeInstance
|
||||||
|
const offset = 4
|
||||||
|
controlsRef.current.reset()
|
||||||
|
controlsRef.current.target.copy(center)
|
||||||
|
|
||||||
|
camera.position.copy(center.clone().add(new THREE.Vector3(offset * radius, -offset * radius, offset * radius)))
|
||||||
|
camera.updateProjectionMatrix()
|
||||||
|
}
|
||||||
|
if(initZoom){
|
||||||
|
zoomToFit()
|
||||||
|
setInitZoom(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [incomingGeo, dataType])
|
||||||
|
const PrimitiveArray = React.useMemo(
|
||||||
|
() =>
|
||||||
|
dataType === 'primitive-array' &&
|
||||||
|
incomingGeo?.map((mesh) => mesh.clone()),
|
||||||
|
[dataType, incomingGeo]
|
||||||
)
|
)
|
||||||
const colorMap = useTexture(texture)
|
const colorMap = useTexture(texture)
|
||||||
|
|
||||||
if (!incomingGeo) return null
|
if (!incomingGeo) return null
|
||||||
|
if (PrimitiveArray)
|
||||||
|
return PrimitiveArray.map((mesh, index) => (
|
||||||
|
<primitive object={mesh} key={index} />
|
||||||
|
))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group dispose={null}>
|
<group dispose={null}>
|
||||||
@@ -53,8 +102,7 @@ function Asset({ geometry: incomingGeo }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let debounceTimeoutId
|
let debounceTimeoutId
|
||||||
function Controls({ onCameraChange, onDragStart, onInit }) {
|
function Controls({ onCameraChange, onDragStart, onInit, controlsRef }) {
|
||||||
const controls = useRef<any>()
|
|
||||||
const threeInstance = useThree()
|
const threeInstance = useThree()
|
||||||
const { camera, gl } = threeInstance
|
const { camera, gl } = threeInstance
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -93,7 +141,7 @@ function Controls({ onCameraChange, onDragStart, onInit }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controls.current) {
|
if (controlsRef.current) {
|
||||||
const dragCallback = () => {
|
const dragCallback = () => {
|
||||||
clearTimeout(debounceTimeoutId)
|
clearTimeout(debounceTimeoutId)
|
||||||
debounceTimeoutId = setTimeout(() => {
|
debounceTimeoutId = setTimeout(() => {
|
||||||
@@ -111,19 +159,19 @@ function Controls({ onCameraChange, onDragStart, onInit }) {
|
|||||||
onDragStart()
|
onDragStart()
|
||||||
clearTimeout(debounceTimeoutId)
|
clearTimeout(debounceTimeoutId)
|
||||||
}
|
}
|
||||||
controls?.current?.addEventListener('end', dragCallback)
|
controlsRef?.current?.addEventListener('end', dragCallback)
|
||||||
controls?.current?.addEventListener('start', dragStart)
|
controlsRef?.current?.addEventListener('start', dragStart)
|
||||||
const oldCurrent = controls.current
|
const oldCurrent = controlsRef.current
|
||||||
dragCallback()
|
dragCallback()
|
||||||
return () => {
|
return () => {
|
||||||
oldCurrent.removeEventListener('end', dragCallback)
|
oldCurrent.removeEventListener('end', dragCallback)
|
||||||
oldCurrent.removeEventListener('start', dragStart)
|
oldCurrent.removeEventListener('start', dragStart)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [camera, controls])
|
}, [camera, controlsRef])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OrbitControls makeDefault ref={controls} args={[camera, gl.domElement]} />
|
<OrbitControls makeDefault ref={controlsRef} args={[camera, gl.domElement]} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,22 +215,18 @@ export function PureIdeViewer({
|
|||||||
}) {
|
}) {
|
||||||
const [isDragging, setIsDragging] = useState(false)
|
const [isDragging, setIsDragging] = useState(false)
|
||||||
const [image, setImage] = useState()
|
const [image, setImage] = useState()
|
||||||
|
const controlsRef = useRef<any>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setImage(dataType === 'png' && artifact)
|
setImage(dataType === 'png' && artifact)
|
||||||
setIsDragging(false)
|
setIsDragging(false)
|
||||||
}, [dataType, artifact])
|
}, [dataType, artifact])
|
||||||
const PrimitiveArray = React.useMemo(
|
|
||||||
() =>
|
|
||||||
dataType === 'primitive-array' && artifact?.map((mesh) => mesh.clone()),
|
|
||||||
[dataType, artifact]
|
|
||||||
)
|
|
||||||
|
|
||||||
// the following are tailwind colors in hex, can't use these classes to color three.js meshes.
|
// the following are tailwind colors in hex, can't use these classes to color three.js meshes.
|
||||||
const pink400 = '#F472B6'
|
const pink400 = '#F472B6'
|
||||||
const indigo300 = '#A5B4FC'
|
const indigo300 = '#A5B4FC'
|
||||||
const indigo900 = '#312E81'
|
const indigo900 = '#312E81'
|
||||||
const jscadLightIntensity = PrimitiveArray ? 0.5 : 1.1
|
const jscadLightIntensity = dataType === 'primitive-array' ? 0.5 : 1.1
|
||||||
return (
|
return (
|
||||||
<div className="relative h-full bg-ch-gray-800 cursor-grab">
|
<div className="relative h-full bg-ch-gray-800 cursor-grab">
|
||||||
{image && (
|
{image && (
|
||||||
@@ -217,6 +261,7 @@ export function PureIdeViewer({
|
|||||||
onDragStart={() => setIsDragging(true)}
|
onDragStart={() => setIsDragging(true)}
|
||||||
onInit={onInit}
|
onInit={onInit}
|
||||||
onCameraChange={onCameraChange}
|
onCameraChange={onCameraChange}
|
||||||
|
controlsRef={controlsRef}
|
||||||
/>
|
/>
|
||||||
<PerspectiveCamera makeDefault up={[0, 0, 1]}>
|
<PerspectiveCamera makeDefault up={[0, 0, 1]}>
|
||||||
<pointLight
|
<pointLight
|
||||||
@@ -257,15 +302,11 @@ export function PureIdeViewer({
|
|||||||
<Box position={[50, 0, 0]} size={[100, 1, 1]} color={pink400} />
|
<Box position={[50, 0, 0]} size={[100, 1, 1]} color={pink400} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{dataType === 'geometry' && artifact && (
|
{dataType !== 'png' && artifact && (
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<Asset geometry={artifact} />
|
<Asset geometry={artifact} dataType={dataType} controlsRef={controlsRef} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
{PrimitiveArray &&
|
|
||||||
PrimitiveArray.map((mesh, index) => (
|
|
||||||
<primitive object={mesh} key={index} />
|
|
||||||
))}
|
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</div>
|
</div>
|
||||||
<DelayedPingAnimation isLoading={isLoading} />
|
<DelayedPingAnimation isLoading={isLoading} />
|
||||||
|
|||||||
Reference in New Issue
Block a user