I have this above code but for some reason the camera is still looking at the model straight ahead. I want it to look at the model a little from the top. I tried adding rotation through props and through the onCreated function as well, but still no dice. Not sure what simple thing I am missing here.
May or may not be the exact cause - but you are mixing controlled and reactive behaviour (ie. first onCreate is called, then if at any point React rerenders your component and it’s children - it will reset the camera to the state defined by props.)
Consider either using useEffect together with useRef (referencing the imperatively controlled camera) in place of onCreate - or use props to adjust the camera rotation
I refactored the code to be like this, where camera is its own function component. With this the camera is set to center (inside) of the object. None of the values seems to have been applied through the useEffect
something is overwriting your camera like @mjurczyk said. the oncreate, or the rotation prop, all of this seems fine and will rotate the camera. tried it here:
wait, you are using invalidateframeloop, that means it will not render unless props have changed or you indicate that a change has occured by calling the “invalidate” function you get from either useThree or global imports. that is most likely the cause. invalidate is rendering on demand, it for usecases where you want to save battery, but you need to know how to use it. if you just mutate something deep inside threejs it’s not gonna know about this and trigger a frame. drei’s camera do this automatically. remove that line pls, “invalidateFrameloop”
btw, you also use outdated syntax:
ps.
import { Camera } from '@react-three/fiber'
<Canvas shadows frameloop='demand'>
Note: I added useEffect inside my Controls function only now. First iteration was only camera object mutations. I have the second iteration shared up here, where I try to disable the controls, change camera settings and then re-enable them. This is how you do it in pure three.js. Like so in constructor:
this.controls = new OrbitControls(this.camera, this.element3D.current);
I think with r3f’s route of applying props on every frame reveals this issue and that’s why I think this is unique to r3f implementation. With above threejs code, camera position changes on model load work swimmingly
useEffect fires after render (on screen), that means controls have already rendered out once before your effect is called. useLayoutEffect is called before render. if you want to apply something before it goes on screen that should be uLE.
I think with r3f’s route of applying props on every frame
props are only applied when you change them. it completely stays out of the frame rate. the only thing that runs every frame is what you put into useFrame.
And the above works great to change position of the model. I tried adding this same logic to my SceneCamera function but I don’t have access to orbit controls object through useThree. Is there a way to do that?