@ -1,17 +1,17 @@
|
|||||||
import { useThree } from '@react-three/fiber'
|
import { useThree } from '@react-three/fiber'
|
||||||
import type { MutableRefObject, PropsWithChildren } from 'react'
|
import type { MutableRefObject, PropsWithChildren } from 'react'
|
||||||
import { Suspense, useEffect, useRef } from 'react'
|
import { Suspense, useEffect, useRef } from 'react'
|
||||||
import { BufferGeometry } from 'three'
|
import { Sphere } from 'three'
|
||||||
import { Vector3 } from 'three'
|
import { Vector3 } from 'three'
|
||||||
import { calculateFovFactor } from './Camera'
|
import { calculateFovFactor } from './Camera'
|
||||||
|
|
||||||
type BaseModelProps = {
|
type BaseModelProps = {
|
||||||
cameraRef: MutableRefObject<any>
|
cameraRef: MutableRefObject<any>
|
||||||
geometry: BufferGeometry
|
boundingSphere: Sphere | null | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BaseModel({
|
export function BaseModel({
|
||||||
geometry,
|
boundingSphere,
|
||||||
cameraRef,
|
cameraRef,
|
||||||
children,
|
children,
|
||||||
}: PropsWithChildren<BaseModelProps>) {
|
}: PropsWithChildren<BaseModelProps>) {
|
||||||
@ -21,14 +21,9 @@ export function BaseModel({
|
|||||||
|
|
||||||
// Camera view, adapted from KittyCAD/website
|
// Camera view, adapted from KittyCAD/website
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (geometry && cameraRef.current) {
|
if (boundingSphere && cameraRef.current) {
|
||||||
geometry.computeBoundingSphere()
|
|
||||||
// TODO: understand the implications of this,
|
|
||||||
// it's been disabled as it was causing before and after to be misaligned
|
|
||||||
// geometry.center()
|
|
||||||
|
|
||||||
// move the camera away so the object fits in the view
|
// move the camera away so the object fits in the view
|
||||||
const { radius } = geometry.boundingSphere || { radius: 1 }
|
const { radius } = boundingSphere || { radius: 1 }
|
||||||
if (!camera.position.length()) {
|
if (!camera.position.length()) {
|
||||||
const arbitraryNonZeroStartPosition = new Vector3(0.5, 0.5, 1)
|
const arbitraryNonZeroStartPosition = new Vector3(0.5, 0.5, 1)
|
||||||
camera.position.copy(arbitraryNonZeroStartPosition)
|
camera.position.copy(arbitraryNonZeroStartPosition)
|
||||||
@ -42,7 +37,7 @@ export function BaseModel({
|
|||||||
camera.zoom = fovFactor / camera.position.length()
|
camera.zoom = fovFactor / camera.position.length()
|
||||||
camera.updateProjectionMatrix()
|
camera.updateProjectionMatrix()
|
||||||
}
|
}
|
||||||
}, [geometry, camera, cameraRef, canvasHeight])
|
}, [boundingSphere, camera, cameraRef, canvasHeight])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
|
@ -26,6 +26,7 @@ function loadGeometry(file: string, checkUV = false): BufferGeometry {
|
|||||||
new BufferAttribute(new Float32Array([]), 1)
|
new BufferAttribute(new Float32Array([]), 1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
geometry.computeBoundingSphere() // will be used for auto-centering
|
||||||
return geometry
|
return geometry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
import type { MutableRefObject } from 'react'
|
import type { MutableRefObject } from 'react'
|
||||||
import { useTheme } from '@primer/react'
|
import { useTheme } from '@primer/react'
|
||||||
import { BufferGeometry } from 'three'
|
import {
|
||||||
|
Box3,
|
||||||
|
BufferGeometry,
|
||||||
|
Group,
|
||||||
|
Mesh,
|
||||||
|
MeshBasicMaterial,
|
||||||
|
Sphere,
|
||||||
|
Vector3,
|
||||||
|
} from 'three'
|
||||||
import { Geometry, Base, Subtraction, Intersection } from '@react-three/csg'
|
import { Geometry, Base, Subtraction, Intersection } from '@react-three/csg'
|
||||||
import { BaseModel } from './BaseModel'
|
import { BaseModel } from './BaseModel'
|
||||||
|
|
||||||
@ -13,6 +21,20 @@ type UnifiedModelProps = {
|
|||||||
showDeletions: boolean
|
showDeletions: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCommonSphere(
|
||||||
|
beforeGeometry: BufferGeometry,
|
||||||
|
afterGeometry: BufferGeometry
|
||||||
|
) {
|
||||||
|
const group = new Group()
|
||||||
|
const dummyMaterial = new MeshBasicMaterial()
|
||||||
|
group.add(new Mesh(beforeGeometry, dummyMaterial))
|
||||||
|
group.add(new Mesh(afterGeometry, dummyMaterial))
|
||||||
|
const boundingBox = new Box3().setFromObject(group)
|
||||||
|
const center = new Vector3()
|
||||||
|
boundingBox.getCenter(center)
|
||||||
|
return boundingBox.getBoundingSphere(new Sphere(center))
|
||||||
|
}
|
||||||
|
|
||||||
export function UnifiedModel({
|
export function UnifiedModel({
|
||||||
beforeGeometry,
|
beforeGeometry,
|
||||||
afterGeometry,
|
afterGeometry,
|
||||||
@ -27,9 +49,10 @@ export function UnifiedModel({
|
|||||||
const deletionsColor = theme?.colors.danger.muted
|
const deletionsColor = theme?.colors.danger.muted
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// TODO: here we give beforeGeometry for auto camera centering,
|
<BaseModel
|
||||||
// for the lack of something better. Need to check the implications
|
boundingSphere={getCommonSphere(beforeGeometry, afterGeometry)}
|
||||||
<BaseModel geometry={beforeGeometry} cameraRef={cameraRef}>
|
cameraRef={cameraRef}
|
||||||
|
>
|
||||||
{/* Unchanged */}
|
{/* Unchanged */}
|
||||||
<mesh>
|
<mesh>
|
||||||
<meshPhongMaterial
|
<meshPhongMaterial
|
||||||
|
@ -25,7 +25,7 @@ export function WireframeModel({ geometry, cameraRef, colors }: Props) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModel geometry={geometry} cameraRef={cameraRef}>
|
<BaseModel boundingSphere={geometry.boundingSphere} cameraRef={cameraRef}>
|
||||||
<group ref={groupRef}>
|
<group ref={groupRef}>
|
||||||
<mesh
|
<mesh
|
||||||
castShadow={true}
|
castShadow={true}
|
||||||
|
Reference in New Issue
Block a user