Hi there,
I’m looking to switch from Babylonjs to Threejs.
I was used to access a lot of elements directly from the scene in Babylonjs.
I did this for example to list all the scene camera’s with scene.cameras
Is there a way in threejs to do the same? I know you can traverse the scene each time, but I would prefer to be able to use a direct category class to access all the camera’s, meshes, etc…
Thanks
Pieter
Cameras are not required to be elements of scenes – i.e. from JavaScript point of view, they are independent objects. However, you can add the cameras to the scene (or to other objects). In this case, the list of cameras can be extracted by:
var allCameras = scene.getObjectsByProperty( 'isCamera', true );
This traverses the scene. You might want to set allCameras
once, and then reuse it.
In case you continuously add/remove cameras, a better approach is to keep your own list of cameras and avoid constant traversing of the whole scene.
3 Likes
Ok, that makes sense, thanks for your reply!
I already tried this with:
scene.getObjectsByProperty('type', 'PerspectiveCamera') as PerspectiveCamera[]
But this will only get me the perspective camera’s off coarse 
Let’s say I would like to toggle through the list of camera’s, what’s the best way to do this?
I’m used to do this using scene.activeCamera = ...
but I can’t seem to find the proper alternative in three.
Thanks for the help!
Pieter
once you have your list of cameras you can just choose which camera to render the scene with eg…
renderer.render(scene, allCameras[idx])
idx++ // or any other way to increment the camera array idx
Yes, the way I was trying to do this was using
const cam = (scene.getObjectsByProperty('type', 'PerspectiveCamera') as PerspectiveCamera[]).find(camera => camera.name === cam_track_name_active)
if (!cam)
return
renderer.render(scene, cam)
console.log('cam', cam.name, cam.position, cam.rotation, cam.zoom, cam.fov, cam.near, cam.far)
Log output:
cam WebGLScrollCam_01_Design Vector3 {x: 6.4161644, y: 1.59999955, z: -23.78284}x: 6.4161644y: 1.59999955z: -23.78284[[Prototype]]: Object Euler {isEuler: true, _x: 2.856280822244528, _y: 0.11301118720663712, _z: -3.108527237449751, _order: 'XYZ', …}isEuler: true_onChangeCallback: ƒ onRotationChange()_order: "XYZ"_x: 2.856280822244528_y: 0.11301118720663712_z: -3.108527237449751order: (...)x: (...)y: (...)z: (...)[[Prototype]]: Object 1 55.00000065335058 0.1 10000
So the camera is found, and should be activated. However I’m still getting only a default camera which was set earlier as a default camera when setting up the scene.
The camera with the name cam_track_name_active
is being loaded along with one of my glb files that contains the animated camera.
For some reason it’s in the scene but switching to it doesn’t seem to work.
Any other things I can try?
Thanks
Pieter
Also I tried this in the console of my chrome browser.
I’ve made scene & renderer available there:
scene.getObjectsByProperty('isCamera', true)[1].name
> 'WebGLScrollCam_01_Design'
renderer.render(scene, scene.getObjectsByProperty('isCamera', true)[1])
> undefined
renderer
> WebGLRenderer {isWebGLRenderer: true, domElement: canvas, debug: {…}, autoClear: true, autoClearColor: true, …}
why is returning renderer.render(scene, scene.getObjectsByProperty('isCamera', true)[1])
undefined? is that the normal return?
Thanks
Ok, so I managed to resolve the issue.
Here is how for anyone that would run into the same issue.
To give the full context, I’m working in Vue3 & Vite.
function animate() {
if (!container || !store_canvas._camera.activeCamera)
return
controls.update()
renderer.render(scene, store_canvas._camera.activeCamera)
requestAnimationFrame(animate)
}
window.addEventListener('resize', onWindowResize)
animate()
My models are loaded via a function to keep my code compact & structured. This makes it a bit harder to update the camera value in the renderer.render(scene, camera)
as this local original camera will overwrite the loaded camera. The one which came in through the loaded *.glb file.
In Vue I’m using pinia for state management, so now i store the active camera via a state, so it can be updated externally from the main threejs render function.
const cam = (scene.getObjectsByProperty('type', 'PerspectiveCamera') as PerspectiveCamera[]).find(camera => camera.name === cam_track_name_active)
if (!cam)
return
store_canvas._camera.activeCamera = cam
Hope this makes sense… now onto converting my animations from babylonjs to threejs 
Pieter