forked from HQU-gxy/camera-extrinsic-play
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:
43
src/App.tsx
43
src/App.tsx
@ -12,7 +12,7 @@ const THREE_ADDONS = {
|
|||||||
} as const
|
} as const
|
||||||
|
|
||||||
|
|
||||||
const DEFAULT_NEAR = 0.1
|
const DEFAULT_NEAR = 0.05
|
||||||
const DEFAULT_FAR = 1
|
const DEFAULT_FAR = 1
|
||||||
const CAMERA_EXTRINSIC_MATRIX_MAP: Record<string, number[]> = {
|
const CAMERA_EXTRINSIC_MATRIX_MAP: Record<string, number[]> = {
|
||||||
"AE_01": [
|
"AE_01": [
|
||||||
@ -70,7 +70,7 @@ const intrinsicToFov = (intrinsic: number[], image_size: { width: number, height
|
|||||||
const Scene = () => {
|
const Scene = () => {
|
||||||
function Floor() {
|
function Floor() {
|
||||||
return (
|
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]} />
|
<planeGeometry args={[15, 15]} />
|
||||||
<meshStandardMaterial color="#ccc" />
|
<meshStandardMaterial color="#ccc" />
|
||||||
</mesh>
|
</mesh>
|
||||||
@ -92,11 +92,17 @@ const Scene = () => {
|
|||||||
// https://www.ilyameerovich.com/simple-3d-text-meshes-in-three-js/
|
// https://www.ilyameerovich.com/simple-3d-text-meshes-in-three-js/
|
||||||
|
|
||||||
const CameraViewFromExtrinsic = ({ extrinsic, name, near, far, fov, textSize, aspect }: CameraViewFromExtrinsicProps) => {
|
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 font = new FontLoader().parse(HelvetikerRegular)
|
||||||
const camera = new THREE.PerspectiveCamera(fov ?? 60, aspect ?? 4 / 3, near ?? DEFAULT_NEAR, far ?? DEFAULT_FAR)
|
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 helper = <cameraHelper args={[camera]} />
|
||||||
|
const Rt = new THREE.Matrix4()
|
||||||
// @ts-expect-error 16 elements
|
// @ts-expect-error 16 elements
|
||||||
camera.applyMatrix4(new THREE.Matrix4(...extrinsic))
|
Rt.set(...extrinsic)
|
||||||
|
camera.applyMatrix4(Rt)
|
||||||
|
|
||||||
const textRef = useRef<THREE.Mesh>(null)
|
const textRef = useRef<THREE.Mesh>(null)
|
||||||
const { camera: viewCamera } = useThree()
|
const { camera: viewCamera } = useThree()
|
||||||
@ -110,11 +116,8 @@ const Scene = () => {
|
|||||||
let text: JSX.Element | null = null
|
let text: JSX.Element | null = null
|
||||||
if (name) {
|
if (name) {
|
||||||
const geo = new THREE_ADDONS.TextGeometry(name ?? "", { font, size: textSize ?? 0.1, depth: 0.001 })
|
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()
|
const position = new THREE.Vector3()
|
||||||
position.setFromMatrixPosition(matrix)
|
position.setFromMatrixPosition(Rt)
|
||||||
|
|
||||||
text = (
|
text = (
|
||||||
<mesh ref={textRef} position={position}>
|
<mesh ref={textRef} position={position}>
|
||||||
@ -132,24 +135,30 @@ const Scene = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_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 (
|
return (
|
||||||
// Note that we don't need to import anything, All three.js objects will be treated
|
// 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
|
// 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
|
// regular ReactDOM. The general rule is that Fiber components are available under
|
||||||
// the camel-case version of their name in three.js.
|
// the camel-case version of their name in three.js.
|
||||||
|
|
||||||
<>
|
<>
|
||||||
<CameraControls />
|
<CameraControls />
|
||||||
{/* <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} />
|
|
||||||
})}
|
|
||||||
<Axes />
|
|
||||||
<Stats />
|
<Stats />
|
||||||
|
{scene}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user