How do I load the Camera from Blender?

Hello dear community,

I created a blender model including an animated camera. I loaded the scene with the GLTF loader and can also view it with a camera created in THREEJS. But how do I get access to the animated camera from Blender? It works with the viewer. https://gltf-viewer.donmccurdy.com/

I’d be happy for help!

Three JS Camera

    // Base camera

    camera = new THREE.PerspectiveCamera(45, sizes.width / sizes.height, 0.1, 1000)

    camera.position.x = 0

    camera.position.y = 15

    camera.position.z = 10

    camera.lookAt (new THREE.Vector3(0,0,0))

    scene.add(camera)

Loading Model from Blender

  var loader = new GLTFLoader();

        var obj;

        loader.load(
      
            // resource URL

            '/models/gltf/rekorderplatte.gltf',

            // called when the resource is loaded

            function ( gltf ) {

                obj = gltf.scene

                scene.add( obj );

                gltf.animations; // Array<THREE.AnimationClip>

                gltf.scene; // THREE.Group

                gltf.scenes; // Array<THREE.Group>

                gltf.cameras; // Array<THREE.Camera>

                gltf.asset; // Object

            },

          [...]

in animate
renderer.render (scene, camera);

hi @maxrekorder
You view with the wrong camere because in your code is wrote exactly this:

camera = new THREE.PerspectiveCamera(45, sizes.width / sizes.height, 0.1, 1000)

If you have to use loaded camera you can try this (at loading complete) :

blender_camera = gltf.cameras[ 0 ]; //if you have one camera or you need the first

and so

renderer.render (scene, blender_camera)

Hey @alessandro_guarino
Thank you for your quick response. That’s how I tried it before. However, I get the error in the console

Uncaught TypeError: Cannot read property ‘parent’ of undefined
at ws.render (three.min.js:6)
at tick (main.js:201)
at main.js:208

main.js 208
renderer.render (scene, blender_camera);

Code full (sorry its a mess)
import {GLTFLoader} from “/lib/GLTFLoader.js”
var scene, renderer
//var camera
var light

//Debug
    const gui = new dat.GUI()


// Canvas
    const canvas = document.getElementById('canvas')
    document.body.appendChild( canvas )

// Sizes
    const sizes = {
        width: window.innerWidth,
        height: window.innerHeight
    }

    window.addEventListener('resize', () =>
    {
        // Update sizes
        sizes.width = window.innerWidth
        sizes.height = window.innerHeight
 
        // Update camera
        // camera.aspect = sizes.width / sizes.height
        // camera.updateProjectionMatrix() 

        // Update renderer
        renderer.setSize(sizes.width, sizes.height)
        renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
    })

// Mouse
    document.addEventListener('mousemove', animateParticles)
    
    let mouseX = 0
    let mouseY = 0
    let nmouseX= 1

    function animateParticles(event) {
        mouseX = event.clientY
        mouseY = event.clientX
        nmouseX = event.clientX / sizes.height

    }

    document.addEventListener('wheel', onMouseWheel)

    let y = 0
    let position = 0

    function onMouseWheel(event){
           y = event.deltaY * 0.0007
    }

// Scene
    scene = new THREE.Scene(); 
    scene.background = new THREE.Color( '#21282a' );

// Grid
    var gridXZ = new THREE.GridHelper(100, 100);
    scene.add(gridXZ);

// Objects (Geometrie)
    const geometry = new THREE.TorusGeometry( 0.7,  0.2, 16, 100);

    const particlesGeometry = new THREE.BufferGeometry
    const particlesCnt = 5000;
    gui.add('particlesCnt',  0, 100000)

    const posArray = new Float32Array (particlesCnt * 3)
    // xyz, xyz, xyz, xyz

    for (let i = 0; i < particlesCnt * 3; i++){
        posArray[i] = (Math.random () - 0.5 ) * 100
    }

  particlesGeometry.setAttribute('position', new THREE.BufferAttribute(posArray, 3))

// Material
    const material = new THREE.PointsMaterial({
    size: 0.0005
})

// Mesh
    const sphere = new THREE.Points(geometry, material)
    const particlesMesh = new THREE.Points(particlesGeometry, material)
    scene.add(sphere, particlesMesh)
    


// Lights
    light = new THREE.HemisphereLight(0xFFFFFF, 0x000000, 1.8)
    const spotLight = new THREE.SpotLight( 0xffffff )
    gui.add(light,'intensity', 0, 1.8)
    scene.add(light, spotLight);



/* Camera
    // Base camera
    camera = new THREE.PerspectiveCamera(45, sizes.width / sizes.height, 0.1, 1000)
    camera.position.x = 0
    camera.position.y = 15
    camera.position.z = 10
    camera.lookAt (new THREE.Vector3(0,0,0))
    scene.add(camera) */


// Renderer 
    renderer = new THREE.WebGLRenderer({
        antialias: true
    })
    renderer.outputEncoding = THREE.sRGBEncoding;   
    renderer.setSize(sizes.width, sizes.height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
    canvas.appendChild (renderer.domElement);

/* Controls
const controls = new THREE.OrbitControls(camera, renderer.domElement)
controls.enableDamping = false
controls.maxDistance = 19
*/
    
// EventListener
    //window.addEventListener("scroll", function(e) {

        // code to increment object.position.z 
    
//    }, true);


// LOADER
    var loader = new GLTFLoader();
    var obj, blender_camera;
    loader.load(
        
        // resource URL
        '/models/gltf/rekorderplatte.gltf',
        // called when the resource is loaded
        function ( gltf ) {
            obj = gltf.scene
            blender_camera = gltf.cameras[ 0 ]; //if you have one camera or you need the first
            
            scene.add( obj, blender_camera );

            gltf.animations; // Array<THREE.AnimationClip>
            gltf.scene; // THREE.Group
            gltf.scenes; // Array<THREE.Group>
            gltf.cameras; // Array<THREE.Camera>
            gltf.asset; // Object

        },
        // called while loading is progressing
        function ( xhr ) {
            
            console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

            if (xhr.loaded / xhr.total * 100 == 100) {
                console.log('Model geladen.')
                scene.background = new THREE.Color( '#21282F' );

            }
        },
        // called when loading has errors
        function ( error ) {

            console.log( 'An error happened' );

        }
    );


// Animate
const clock = new THREE.Clock()

const tick = () =>

{
    const elapsedTime = clock.getElapsedTime()

    //Update Objects
    particlesMesh.rotation.y = mouseY * (elapsedTime * 0.000009)  * -1
    particlesMesh.rotation.x = mouseX * (elapsedTime * 0.000009) 
    
  //  position += y
 //   y *= 0.9
    
    //camera.position.y = y;


    //Update Orbital Control
    //controls.update();

     // Consolole Log
     // console.log(nmouseX)

    // Render
    renderer.render (scene, blender_camera);

    // Call tick again on next frame
    window.requestAnimationFrame( tick )

}

tick();

belnder_camera it’s undefined until your load it’s completed, but you use it in tick() from the firs time.
You can use blender_camera only after loading complete

I see that you don’t have THREE.LoadingManager and init() function…
Of course you can have this approach (if you’re a little bit PRO), but in this case I suggest to start from a more structured example, and please use LoadingManager to have more control

Thank you so much!
I updated my code and it works!

import {GLTFLoader} from "/lib/GLTFLoader.js"

let camera, scene, renderer, cube, clock, mixer;

function init() {
	// Init scene
	scene = new THREE.Scene();
	clock = new THREE.Clock();

// loading model
var loader = new GLTFLoader();
var obj
loader.load(

// resource URL
'/models/gltf/rekorderplatte.gltf',
// called when the resource is loaded
function ( gltf ) {
    camera = gltf.cameras[ '0' ]; //if you have one camera or you need the first
		mixer = new THREE.AnimationMixer( gltf.scene );
		var action = mixer.clipAction( gltf.animations[ 0 ] );
		action.play();
    obj = gltf.scene

    scene.add( obj, light );

    gltf.animations; // Array<THREE.AnimationClip>
    gltf.scene; // THREE.Group
    gltf.scenes; // Array<THREE.Group>
    gltf.cameras; // Array<THREE.Camera>
    gltf.asset; // Object

},
// called while loading is progressing
function ( xhr ) {
    
    console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

    if (xhr.loaded / xhr.total * 100 == 100) {
        console.log('Model geladen.')
        scene.background = new THREE.Color( '#21282F' );
    }
},
// called when loading has errors
function ( error ) {

    console.log( 'An error happened' );

}
);

	// Init camera (PerspectiveCamera)
	camera = new THREE.PerspectiveCamera(
		75,
		window.innerWidth / window.innerHeight,
		0.1,
		1000
	);

	// Init renderer
	renderer = new THREE.WebGLRenderer({ antialias: true });

	// Set size (whole window)
	renderer.setSize(window.innerWidth, window.innerHeight);

	// Render to canvas element
	document.body.appendChild(renderer.domElement);

	// Init BoxGeometry object (rectangular cuboid)
	const geometry = new THREE.BoxGeometry(3, 3, 3);

	// Create material with color
	const material = new THREE.MeshBasicMaterial({ color: 0x0000ff });

	// Add texture - 
	// const texture = new THREE.TextureLoader().load('textures/crate.gif');

	// Create material with texture
	// const material = new THREE.MeshBasicMaterial({ map: texture });

	// Create mesh with geo and material
	cube = new THREE.Mesh(geometry, material);
	// Add to scene
	//scene.add(cube);

	// Position camera
	camera.position.z = 5;
}

// Draw the scene every time the screen is refreshed
function animate() {
	requestAnimationFrame( animate );

	var delta = clock.getDelta();

	if ( mixer ) mixer.update( delta );

	renderer.render( scene, camera );

}

function onWindowResize() {
	// Camera frustum aspect ratio
	camera.aspect = window.innerWidth / window.innerHeight;
	// After making changes to aspect
	camera.updateProjectionMatrix();
	// Reset size
	renderer.setSize(window.innerWidth, window.innerHeight);
}

window.addEventListener('resize', onWindowResize, false);

init();
animate();
2 Likes