I'm currently working on an animation loop using three.js, and I've noticed that most online examples (like mrdoob, stemkoski) rely on unprotected globals at the beginning of the script. I attempted to encapsulate these in the init() function and then pass them as arguments through the animation loop. However, I'm encountering an issue where the renderer is returning as undefined.
I'm uncertain about what I might be overlooking in the code below. My main query revolves around grasping the best practices for setting up an animation loop with proper closure (safeguarding variables that could potentially be global). Any insights would be greatly appreciated!
// MAIN ANIMATION LOOP:
// UPDATE the scene
function update(keyboard, controls, stats, clock) {
var delta = clock.getDelta();
if ( keyboard.pressed("z") )
{
// do something
}
controls.update();
stats.update();
};
// RENDER the scene
function render(renderer, scene, camera) {
renderer.render(scene, camera);
};
// ANIMATE the scene
function animate(scene, camera, renderer, controls, stats, keyboard, clock) {
requestAnimationFrame(animate);
render(renderer, scene, camera);
update(keyboard, controls, stats, clock);
};
// INITIALIZES THE SCENE
function init(images) {
var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = 1920, SCREEN_HEIGHT = 1080;
var VIEW_ANGLE = 20, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,150,1000);
camera.lookAt(scene.position);
// RENDERER
if (Detector.webgl)
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
// STATS
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
// LIGHT
var light = new THREE.PointLight(0xffffff);
light.position.set(100,250,0);
scene.add(light);
// IMAGES
var element1 = THREE.ImageUtils.loadTexture(images.dresser10);
var element2 = THREE.ImageUtils.loadTexture(images.dresser14);
var element1Material = new THREE.SpriteMaterial( { map: element1, useScreenCoordinates: true, alignment: THREE.SpriteAlignment.topLeft } );
var sprite = new THREE.Sprite(element1Material);
sprite.position.set( 50, 50, 0 );
sprite.scale.set( 64, 64, 1.0 );
scene.add(sprite);
animate(container, scene, camera, renderer, controls, stats, keyboard, clock);
};
// WINDOW LOADED EVENT
window.addEventListener ("load", eventWindowLoaded, false);
function eventWindowLoaded() {
loadImages(init); // calls to initialize the scene once the images are loaded
}