I try to convert threejs to R3F from demo but the camera does not work

ThreeJS code from https://codepen.io/HunorMarton/pen/JwWLJo

original code

const distance = 500;
const camera = new THREE.OrthographicCamera( window.innerWidth/-2, window.innerWidth/2, window.innerHeight / 2, window.innerHeight / -2, 0.1, 10000 );

camera.rotation.x = 50*Math.PI/180;
camera.rotation.y = 20*Math.PI/180;
camera.rotation.z = 10*Math.PI/180;

const initialCameraPositionY = -Math.tan(camera.rotation.x)*distance;
const initialCameraPositionX = Math.tan(camera.rotation.y)*Math.sqrt(distance**2 + initialCameraPositionY**2);
camera.position.y = initialCameraPositionY;
camera.position.x = initialCameraPositionX;
camera.position.z = distance;

My Codesandbox boring-panini-6s85vw - CodeSandbox

my convert code to

    const distance = 500
    const newCamera = new OrthographicCamera(size.width / -2, size.width / 2, size.height / 2, size.height / -2, 0.1, 10000)
    camera.near = newCamera.near
    camera.far = newCamera.far
    camera.rotation.x = (50 * Math.PI) / 180
    camera.rotation.y = (20 * Math.PI) / 180
    camera.rotation.z = (10 * Math.PI) / 180
    const initialCameraPositionY = -Math.tan(camera.rotation.x) * distance
    const initialCameraPositionX = Math.tan(camera.rotation.y) * Math.sqrt(distance ** 2 + initialCameraPositionY ** 2)
    camera.position.y = initialCameraPositionY
    camera.position.x = initialCameraPositionX
    camera.position.z = distance

this is my first tutorial by can anyone help me about camera angle

setting the camera has no effect if you also have orbitcontrols, whose only purpose is to set the camera. you have to places of code that pull on the camera.

another thing is that the camera you create isn’t actually used anywhere, you don’t render out with it.

imo it should be relatively easy, use drei/orthocam for instance which can makeDefault so that it’s being used to render. or alternatively render yourself, but why if it’s just this:

  const distance = 500
  const rotX = (50 * Math.PI) / 180
  const rotY = (20 * Math.PI) / 180
  const initialCameraPositionY = -Math.tan(rotX) * distance
  const initialCameraPositionX = Math.tan(rotY) * Math.sqrt(distance ** 2 + initialCameraPositionY ** 2)
  return (
    <>
      <OrthographicCamera
        makeDefault
        rotation={[rotX, rotY, (10 * Math.PI) / 180]}
        position={[initialCameraPositionX, initialCameraPositionY, distance]}
      />

you don’t need recoil either, you can access that camera now from anywhere, it’s the new default

const cam = useThree(state => state.camera)
useEffect(() => {
  camera.doSomething()
}, [camera])
1 Like

you also don’t need to sync the light to the cam, you can just mount it directly into it

      <OrthographicCamera
        makeDefault
        rotation={[rotX, rotY, (10 * Math.PI) / 180]}
        position={[initialCameraPositionX, initialCameraPositionY, distance]}>
        <directionalLight
          intensity={0.6}
          color={new Color('#ffffff')}
          castShadow
          position={[-100, -100, 200]}
          shadow-mapSize={[2048, 2048]}>
          <orthographicCamera attach="shadow-camera" args={[-distance, distance, distance, -distance]} />
        </directionalLight>
      </OrthographicCamera>
1 Like

Ok its work as my expect
next question how to set target of directionalLight to ChickenView

i try to set with following code but its does not work

      <ChickenView ref={chickenRef} />
      <OrthographicCamera
        makeDefault
        rotation={[rotX, rotY, (10 * Math.PI) / 180]}
        position={[initialCameraPositionX, initialCameraPositionY, distance]}
      >
        <directionalLight
          intensity={0.6}
          color={new Color('#ffffff')}
          castShadow
          position={[-150, 100, -700]}
          shadow-mapSize={[2048, 2048]}
          target={chickenRef.current}
        >
          <orthographicCamera
            attach="shadow-camera"
            args={[-distance, distance, distance, -distance]}
          />
        </directionalLight>
      </OrthographicCamera>

it null pointer at this line

target={chickenRef.current}
Uncaught TypeError: Cannot read properties of null (reading 'matrixWorld')
    at DirectionalLightShadow.updateMatrices

well in any way you want. right now you’re just putting null into it, a ref is filled after render not before. just set it straight up + updateMatrixWorld Volumetric spotlight - CodeSandbox or you can use refs + effects,

const ref = useRef()
const light = useRef()
...
useLayoutEffect(() => {
  light.current.target = ref.current
}, [])
...
<Chicken ref={ref} />
<directionalLight ref={light} />

or a setstate

const [chicken, set] = useState()
...
<Chicken ref={set} />
{chicken && <directionalLight target={chicken} />}

i’d prefer uLE because there’s no FOUC. chicken will be unlit for a single frame with the last one.

1 Like

All enought, thank for your help :smiley: