Refactor Scene component to improve camera positioning and rendering. Adjust default near clipping plane value, update floor position, and streamline camera view creation with extrinsic matrix handling.

This commit is contained in:
2025-03-24 16:36:02 +08:00
parent 76a530b293
commit c67e1ca728

View File

@ -12,7 +12,7 @@ const THREE_ADDONS = {
} as const
const DEFAULT_NEAR = 0.1
const DEFAULT_NEAR = 0.05
const DEFAULT_FAR = 1
const CAMERA_EXTRINSIC_MATRIX_MAP: Record<string, number[]> = {
"AE_01": [
@ -70,7 +70,7 @@ const intrinsicToFov = (intrinsic: number[], image_size: { width: number, height
const Scene = () => {
function Floor() {
return (
<mesh rotation-x={-Math.PI / 2} position-y={-0.05} receiveShadow>
<mesh rotation-x={-Math.PI / 2} position-y={-0.5} receiveShadow>
<planeGeometry args={[15, 15]} />
<meshStandardMaterial color="#ccc" />
</mesh>
@ -92,11 +92,17 @@ const Scene = () => {
// https://www.ilyameerovich.com/simple-3d-text-meshes-in-three-js/
const CameraViewFromExtrinsic = ({ extrinsic, name, near, far, fov, textSize, aspect }: CameraViewFromExtrinsicProps) => {
console.assert(extrinsic.length === 16, "extrinsic must be a 4x4 matrix")
const font = new FontLoader().parse(HelvetikerRegular)
const camera = new THREE.PerspectiveCamera(fov ?? 60, aspect ?? 4 / 3, near ?? DEFAULT_NEAR, far ?? DEFAULT_FAR)
// the camera by default is looking up to the y-axis
// we want it to look at the origin
camera.rotation.x = -Math.PI / 2
const helper = <cameraHelper args={[camera]} />
const Rt = new THREE.Matrix4()
// @ts-expect-error 16 elements
camera.applyMatrix4(new THREE.Matrix4(...extrinsic))
Rt.set(...extrinsic)
camera.applyMatrix4(Rt)
const textRef = useRef<THREE.Mesh>(null)
const { camera: viewCamera } = useThree()
@ -110,11 +116,8 @@ const Scene = () => {
let text: JSX.Element | null = null
if (name) {
const geo = new THREE_ADDONS.TextGeometry(name ?? "", { font, size: textSize ?? 0.1, depth: 0.001 })
const matrix = new THREE.Matrix4()
// @ts-expect-error 16 elements
matrix.set(...extrinsic)
const position = new THREE.Vector3()
position.setFromMatrixPosition(matrix)
position.setFromMatrixPosition(Rt)
text = (
<mesh ref={textRef} position={position}>
@ -132,24 +135,30 @@ const Scene = () => {
)
}
return (
// Note that we don't need to import anything, All three.js objects will be treated
// as native JSX elements, just like you can just write <div /> or <span /> in
// regular ReactDOM. The general rule is that Fiber components are available under
// the camel-case version of their name in three.js.
<>
<CameraControls />
const scene = (<group>
{/* <OrbitControls /> */}
<ambientLight intensity={0.05} />
<directionalLight castShadow position={[3.3, 6, 4.4]} intensity={5} />
<Floor />
{Object.entries(CAMERA_EXTRINSIC_MATRIX_MAP).map(([key, value]) => {
const intrinsic = CAMERA_INTRINSIC_MATRIX_MAP[key]
const fov = intrinsicToFov(intrinsic, { width: IMAGE_WIDTH, height: IMAGE_HEIGHT })
return <CameraViewFromExtrinsic key={key} name={key} extrinsic={value} fov={fov.fov_x} aspect={IMAGE_WIDTH / IMAGE_HEIGHT} />
const { fov_x, fov_y } = intrinsicToFov(intrinsic, { width: IMAGE_WIDTH, height: IMAGE_HEIGHT })
// make the far reverse proportional to the fov
const far = (1 / fov_x) * 20
return <CameraViewFromExtrinsic key={key} name={`${key}(${fov_x.toFixed(1)})`} extrinsic={value} fov={fov_x} aspect={IMAGE_WIDTH / IMAGE_HEIGHT} far={far} />
})}
<Axes />
</group>)
return (
// Note that we don't need to import anything, All three.js objects will be treated
// as native JSX elements, just like you can just write <div /> or <span /> in
// regular ReactDOM. The general rule is that Fiber components are available under
// the camel-case version of their name in three.js.
<>
<CameraControls />
<Stats />
{scene}
</>
)
}