3D数字孪生 – Three.js 项目实战之相机控制器(五)

机器学习

oz@0xozram 9号在twitter上发了这样的一个短视频:
20230629171639_rec_.gif
当然,这属于机器学习领域的内容,也就是大名鼎鼎的 google 在2015开源的 tensorflow,TensorFlow.js也可以与Web图形库(如D3.js、Three.js等)结合使用,帮助开发者实现数据的可视化和实时交互。

image.png

不一样的Control

那么,以上的 “废话” ,又与我们的所讲的内容有什么关系呢? 在 three/drei中我们也有类似组件~ 可以看这里: facecontrols

20230629201328_rec_.gif

这是 three/drei组件库中的案例,感兴趣的小伙伴可以看这里:脸部控制, 其原理也很简单,那便是由 threejs 与 mediapipe 结合,还是那句话,google出品,必是精品啊!!

Google MediaPipe的应用场景包括增强现实(AR)、虚拟现实(VR)、人机交互、视频分析和处理、智能摄像头等领域。开发者可以利用MediaPipe的功能和工具,快速构建高性能的多媒体处理应用程序。

下面,我们就来看看,在three/drei中,两大框架是如何强强合并的吧!

源码的位置 :FaceControls.tsx

我们源码简化一下来看:

// 代码只是为了解释,所以做了很多的精简。

import { useFaceLandmarker } from './FaceLandmarker'


export type FaceControlsApi = THREE.EventDispatcher & {
  /** Detect faces from the video */
  detect: (video: HTMLVideoElement, time: number) => void
  /** Compute the target for the camera */
  computeTarget: () => THREE.Object3D
  /** Update camera's position/rotation to the `target` */
  update: (delta: number, target?: THREE.Object3D) => void
  /** <Facemesh> ref api */
  facemeshApiRef: RefObject<FacemeshApi>
  /** <Webcam> ref api */
  webcamApiRef: RefObject<WebcamApi>
  /** Play the video */
  play: () => void
  /** Pause the video */
  pause: () => void
}

const FaceControlsContext = createContext({} as FaceControlsApi)

export const FaceControls = forwardRef<FaceControlsApi, FaceControlsProps>(
  (
   //。。。
  ) => {
    const scene = useThree((state) => state.scene)
    const defaultCamera = useThree((state) => state.camera)

    const explCamera = camera || defaultCamera

    const webcamApiRef = useRef<WebcamApi>(null)

    const facemeshApiRef = useRef<FacemeshApi>(null)

    //
    // computeTarget()
    //
    // 计算目标位置和旋转摄像头


    const computeTarget = useCallback<FaceControlsApi['computeTarget']>(() => {
      
    }, [explCamera, irisLeftDirPos, irisLeftLookAt, irisRightDirPos, irisRightLookAt, scene, target])

    //
    // update()
    //
    // 更新相机位置和旋转摄像头
    //

    const [current] = useState(() => new THREE.Object3D())
    const update = useCallback<FaceControlsApi['update']>(
      function (delta, target) {
        if (explCamera) {
          target ??= computeTarget()

          if (smoothTime > 0) {
            // damping current
            const eps = 1e-9
            easing.damp3(current.position, target.position, smoothTime, delta, undefined, undefined, eps)
            easing.dampE(current.rotation, target.rotation, smoothTime, delta, undefined, undefined, eps)
          } else {
            // instant
            current.position.copy(target.position)
            current.rotation.copy(target.rotation)
          }
          // 实时更新相机位置
          explCamera.position.copy(current.position)
          explCamera.rotation.copy(current.rotation)
        }
      },
    )

    //
    // detect()
    //

    const [faces, setFaces] = useState<FaceLandmarkerResult>()
    const faceLandmarker = useFaceLandmarker()
    const detect = useCallback<FaceControlsApi['detect']>(
      
    )

    useFrame((_, delta) => {
      if (!manualUpdate) {
        update(delta)
      }
    })

    const points = faces?.faceLandmarks[0]
    const facialTransformationMatrix = faces?.facialTransformationMatrixes?.[0]
    const faceBlendshapes = faces?.faceBlendshapes?.[0]
    return (
      <FaceControlsContext.Provider value={api}>
        
      </FaceControlsContext.Provider>
    )
  }
)

export const useFaceControls = () => useContext(FaceControlsContext)

useFaceLandmarker实时抓取到画面图像人脸的位置变化,并同步更新相机位置(其实理解比较浅,只是为了更好的理解FaceContrls,稍微瞄了一眼(^▽^),有深入了解的小伙伴欢迎指正)。

常规的相机控制器

偏了节奏!回归正题。我们还是主打以实战运用为主,下面我们就来介绍常见的几种相机控制器,以及在实战中的运用。

CameraControls

回顾3D数字孪生 – Three.js 项目介绍与基础环境搭建(一)中,我们有提到过,如何让场景中的相机受控,其中我们就用到了CameraControls,只需在场景中添加:

 <Canvas
    shadows

    gl={{

      logarithmicDepthBuffer: true,

    }}

  >

    // ...
    <CameraControls />
</Canvas>

就可以实现操控相机,具体的参数可查看 CameraControl 属性,对于 API 属性大家可以自行检(chat)索 (GPT)理解就好,AI 时代,个人没有过强的实战运用,反而这方面的解释,很容易把他人带偏。

相机控制器模块代码:BaseSence => components => Camera.tsx

// 添加场景相机
import { useThree, PerspectiveCameraProps } from '@react-three/fiber';
import {
  PerspectiveCamera,
  CameraControls,
  PresentationControls,
  FlyControls,
  OrbitControls,
  FirstPersonControls,
  MapControls,
} from '@react-three/drei';
import * as THREE from 'three';

import PointerCtrl from './CtrlPointerLock';
import React, { useContext, useEffect } from 'react';
import { observer, ThreeStoreContext } from 'mobx-threejs-store';

const Camera = (props: any) => {
  const threeObj = useThree();
  const camera = threeObj.camera;
  const mobxStore = useContext(ThreeStoreContext);
  const flyCtrl = () => {
    return (
      <group>
        <FirstPersonControls
          far={100000}
          movementSpeed={100}
          activeLook={false}
          lookVertical={true}
        ></FirstPersonControls>
        {/* <OrbitControls /> */}
        <MapControls zoomSpeed={0.1} />
      </group>
    );
  };

  const ctrl = () => {
    return (
      <group>
        {/* 相机控制器 */}
        {/* <PresentationControls /> */}
        <CameraControls />
        {/* <PointerCtrl /> */}
      </group>
    );
  };
  return (
    <>
      {mobxStore.threeStore.cameraCtrls.choiceCtrls ? ctrl() : flyCtrl()}
      <PerspectiveCamera
        makeDefault
        position={[-100, 200, 1000]}
        fov={48}
        near={1}
        far={100000}
        maxDistance={10}
        {...props}
      />
    </>
  );
};
export default observer(Camera);

mobxStore.threeStore.cameraCtrls.choiceCtrls是我们在应用层做的一些开关,以便我们更好的切换相机控制器的方式。

20230630115603_rec_.gif

CameraControl默认已经初始化旋转、平移、缩放、动画效果、手势等行为。

PresentationControls

PresentationControls用于创建演示或展示性的相机控制效果。它提供了一些交互功能,可以自动控制相机的移动和旋转,以便在场景中进行演示或展示。
PresentationControls 的主要特点和功能包括:

  1. 自动漫游:PresentationControls 可以自动控制相机在场景中进行漫游,展示不同的视角和位置。
  2. 平滑过渡:它提供平滑的相机过渡效果,使相机的移动和旋转更加流畅。
  3. 定时控制:PresentationControls 可以通过设置持续时间和延迟时间来控制漫游的速度和开始时间。
  4. 可定制性:它提供了一些参数和选项,可以调整漫游的速度、相机路径和动画效果。

因为在实战中,目前并没有很明确的应用场景,所以,临时加了一下。下面,我就献丑了….

20230630110006_rec_.gif

image.png
PresentationControls控制,包裹住你想展示的组件,同时设置你想要的参数,控制相机。

以下是为常见的参数控制:

  • snap:这个参数可能是指相机控制的”捕捉”或”对齐”功能。它可能控制相机的位置和角度是否会被自动对齐到某个特定的值或位置。
  • global:这个参数可能指定相机控制是基于全局坐标系还是基于局部坐标系。如果设置为 true,则表示相机控制是基于全局坐标系进行的,如果设置为 false,则表示相机控制是基于局部坐标系进行的。
  • zoom:这个参数控制相机的缩放比例。值为 1 表示原始大小,小于 1 表示缩小,大于 1 表示放大。
  • rotation:这个参数控制相机的旋转角度。它是一个包含三个值的数组,分别代表绕 x、y 和 z 轴的旋转角度。
  • polar:这个参数可能指定相机在极坐标系下的位置。它是一个包含两个值的数组,第一个值代表相机在极坐标系中的极角(polar angle),第二个值代表相机在极坐标系中的方位角(azimuthal angle)。
  • azimuth:这个参数可能指定相机在水平方向上的旋转范围。它是一个包含两个值的数组,第一个值代表相机的最小水平旋转角度,第二个值代表相机的最大水平旋转角度。

值得一提的是,以上两种相机不要混着用,当然有些组合是合理,否则就会出现下面的情况, PresentationControlsMapControls一起使用,两种控制器会出现争抢控制的情况。
20230630112621_rec_.gif

FirstPersonControls

第一人称的视觉相机控制,相信很多小伙伴在做业务开发时,都会用到。
下面,我们就结合键盘的键位”AWSDRF“来实现对场景中,相机的六个方向控制。

20230630142928_rec_.gif

简单的案例,我们可以这样测试,在Canvas组件中,只留下基础效果。

<Canvas
    shadows

    gl={{

      logarithmicDepthBuffer: true,

    }}

  >

    {/* 场景类 */}
    {/* <BaseSence /> */}
    {/* 工厂类 */}
    {/* <Factory /> */}
    {props.children}
    {/* 帮助类 */}
    <>
      <FirstPersonControls
        activeLook
        enabled
        heightCoef={1}
        heightMax={1}
        heightMin={0}
        lookSpeed={0.005}
        lookVertical
        movementSpeed={1}
        verticalMax={3.141592653589793}
        verticalMin={0}
      />
      <Box>
        <meshBasicMaterial wireframe />
      </Box>
    </>
    <MapControls />
    <GridModule />
    <Gizmo />
  </Canvas>

20230630145125_rec_.gif
这里我们添加了两种控制器,是可完美的兼容的。

others

剩下的相机操作,也都类似,其它的相机还有:

感兴趣的小伙伴,可以自己看案例照着案例学习就好啦~

相机运动

下一篇,将分享如何让相机,相机如何跟随小车运动,始终跟随者任务点进行观察。

好了,觉得有帮助的小伙伴,欢迎点赞、关注加收藏,有什么问题,我们评论区见~
20230629111155_rec_.gif

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYdmc075' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片