Search code examples
reactjsthree.jspoint-clouds

Potree/Three.js - Where can I find the real time camera (active camera) position coordinates?


I'm developing an app using React, which uses the Potree viewer (https://github.com/potree/potree) to display large points cloud files; within the viewer I'm trying to display the real-time camera coordinates (X, Y, Z) to the user, as well as will use them to optimise the cloud rendering.

I have been able to source where the coordinates are, by getting the active camera (viewer.scene.getActiveCamera()) and finding the coordinates in viewer.scene.cameraP.position.x/y/z. Though these values seem static, and I'm saying this because I have tried to update my React component using a useEffect() hook, based on the changing of any of the coordinates, which doesn't work.

Is there anyone who encountered the same issue before and could help me out in finding/sourcing the camera coordinates real-time values, or assist me in actually using the values I have already found and make them updating real time in React?

function Coordinates({ viewer, drawerOpen }) {
  const myActiveCamera = viewer.scene.getActiveCamera();
  const [cameraCoords, setCameraCoords] = useState(null);

  useEffect(() => {
    console.log("hello");
    if (viewer !== null && viewer.scene !== null) {

      setCameraCoords(myActiveCamera.position);
    }
  }, [myActiveCamera.position.x, myActiveCamera.position.y, myActiveCamera.position.z]);

  console.log(viewer);
  console.log(myActiveCamera);
  console.log(cameraCoords);

  return (
    <Container maxWidth={false} style={{ marginLeft: drawerOpen && '210px' }}>
      <Contents container alignItems="center">
        <CameraAlt /> {/*Camera Icon*/}

        <Divider orientation="vertical" flexItem />

        {viewer ? (
          <Typography variant="p">
            X: {cameraCoords.x.toFixed(8)}
          </Typography>
        ) : (
          <Typography variant="p">X: 0.0</Typography>
        )}

        <Divider orientation="vertical" flexItem />

        {viewer ? (
          <Typography variant="p">
            Y: {cameraCoords.y.toFixed(8)}
          </Typography>
        ) : (
          <Typography variant="p">Y: 0.0</Typography>
        )}

        <Divider orientation="vertical" flexItem />

        {viewer ? (
          <Typography variant="p">
            Z: {cameraCoords.z.toFixed(8)}
          </Typography>
        ) : (
          <Typography variant="p">Z: 0.0</Typography>
        )}
      </Contents>
    </Container>
  );
}

Solution

  • After a few hours spent investigating and trying, I have come up with a solution. The principle behind it is the same as a digital clock.

    Here's the code:

    function Coordinates({ viewer, drawerOpen }) {
    
      //Declaring the state for the cameraposition coordinates and setting their default to 0
      const [activeCameraCoordinates, setActiveCameraCoordinates] = useState({ x: 0, y: 0, z: 0 });
    
      //The useEffect and the timer, work together to achieve a real time value update displayed to the user
      useEffect(() => {
        setInterval(() => {
          if (viewer !== 'undefined' && viewer !== undefined && viewer !== null) {
            let cameraPosition = viewer.scene.getActiveCamera().position;
            setActiveCameraCoordinates(cameraPosition);
          }
        }, 100)
      })
    
      return (
        <Container maxWidth={false} style={{ marginLeft: drawerOpen && '210px' }}>
          <Contents container alignItems="center">
            <CameraAlt />
    
            <Divider orientation="vertical" flexItem />
            <Typography variant="p">X:
              {activeCameraCoordinates.x.toFixed(2)}
            </Typography>
            <Divider orientation="vertical" flexItem />
            <Typography variant="p">Y:
              {activeCameraCoordinates.y.toFixed(2)}
            </Typography>
            <Divider orientation="vertical" flexItem />
            <Typography variant="p">Z:
              {activeCameraCoordinates.z.toFixed(2)}
            </Typography>
          </Contents>
        </Container >
      );
    }