How to make camera update on zoom - three.js

I finally found how to zoom with the mousescroll, but the camera only updates the zoom level when I move the camera by clicking and dragging.
I tried copy pasting code from three.js examples, I tried different browers, I tried adding controls.update(); to both the render and the gameloop function and I tried Googling my issue.
var renderer = new THREE.WebGLRenderer( );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// check when the browser size has changed and adjust the camera accordingly
window.addEventListener( 'resize', function( )
{
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
renderer.setSize( WIDTH, HEIGHT );
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix( );
} );
scene.add( new THREE.AmbientLight( 0x00020 ) );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use only if there is no animation loop
controls.minDistance = 10;
controls.maxDistance = 200;
controls.enableZoom = true;
camera.position.z = 7;
// CUBE
var geometry = new THREE.CubeGeometry( 2, 2, 2 );
var cubeMaterials =
[
new THREE.MeshLambertMaterial( { map: new THREE.TextureLoader( ).load( 'img/1.png' ), side: THREE.DoubleSide } ), // Right side
new THREE.MeshPhongMaterial( { map: new THREE.TextureLoader( ).load( 'img/2.png' ), side: THREE.DoubleSide } ), // Left side
new THREE.MeshLambertMaterial( { map: new THREE.TextureLoader( ).load( 'img/3.png' ), side: THREE.DoubleSide } ), // Top side
new THREE.MeshPhongMaterial( { map: new THREE.TextureLoader( ).load( 'img/4.png' ), side: THREE.DoubleSide } ), // Bottom side
new THREE.MeshLambertMaterial( { map: new THREE.TextureLoader( ).load( 'img/5.png' ), side: THREE.DoubleSide } ), // Front side
new THREE.MeshPhongMaterial( { map: new THREE.TextureLoader( ).load( 'img/6.png' ), side: THREE.DoubleSide } ) // Back side
];
// Create a MeshFaceMaterial, which allows the cube to have different materials on each face
var cubeMaterial = new THREE.MeshFaceMaterial( cubeMaterials );
var cube = new THREE.Mesh( geometry, cubeMaterial );
scene.add( cube );
// Floor
var floorGeometry = new THREE.CubeGeometry( 496, 1, 350 );
var floorMaterial = new THREE.MeshLambertMaterial( { map: new THREE.TextureLoader( ).load( 'images/ctr.png' ), side: THREE.DoubleSide } );
var floorCube = new THREE.Mesh( floorGeometry, floorMaterial );
floorCube.position.y = -5;
scene.add( floorCube );
var ambientLight = new THREE.AmbientLight( 0xFFFFFF, 5.0 );
scene.add(ambientLight);
var light1 = new THREE.PointLight( 0xff0040, 4, 50 );
//scene.add( light1 );
var light2 = new THREE.PointLight( 0x0040ff, 3, 50 );
//scene.add( light2 );
var light3 = new THREE.PointLight( 0x80ff80, 4, 50 );
//scene.add( light3 );
var directionalLight = new THREE.DirectionalLight( 0xFFFFFF, 1 );
directionalLight.position.set( 0, 1, 0 );
//scene.add( directionalLight );
var spotLight = new THREE.SpotLight( 0xFF45F6, 25 );
spotLight.position.set( 0, 3, 0 );
scene.add( spotLight );
// game logic
var update = function( )
{
//cube.rotation.x += 0.01;
//cube.rotation.y += 0.005;
var time = Date.now( ) * 0.0005;
light1.position.x = Math.sin( time * 0.7 ) * 30;
light1.position.y = Math.cos( time * 0.5 ) * 40;
light1.position.z = Math.cos( time * 0.3 ) * 30;
light2.position.x = Math.cos( time * 0.3 ) * 30;
light2.position.y = Math.sin( time * 0.5 ) * 40;
light2.position.z = Math.sin( time * 0.7 ) * 30;
light3.position.x = Math.sin( time * 0.7 ) * 30;
light3.position.y = Math.cos( time * 0.3 ) * 40;
light3.position.z = Math.sin( time * 0.5 ) * 30;
};
// draw scene
var render = function( )
{
renderer.render( scene, camera );
};
// run game loop (update, render, repeat)
var GameLoop = function( )
{
requestAnimationFrame( GameLoop );
update( );
render( );
};
GameLoop( );
</script>
I would really love to be able to zoom in instantly when I scroll and not have it update only when I perform a pan.

Related

Three.js moving the camera left and right side of the scene

I am working on a three.js prototype in which a 3d model of the train is added to the scene. My requirement is to move the camera either left / right side of the scene to view the complete train.
I tried using below code -
function onKeyDown(){
var zdelta = 20;
switch( event.keyCode ) {
case 65: // look left
camera.position.z = camera.position.z + zdelta;
}
}
But the scene was rotating rather than panning in the left side.
So it will be great help, if anyone shares their idea on this :)
Thanks,
Satheesh K
Using a keydown event listener is definitely the right approach. Try it with this code:
var scene, camera, renderer, cubeObj;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
camera.position.y = - 10;
camera.position.x = 10;
var cubeGeo = new THREE.BoxGeometry( 200, 150, 100 );
var cubeGeoMaterial = new THREE.MeshPhongMaterial( { color: 0x808080 } );
cubeObj = new THREE.Mesh( cubeGeo, cubeGeoMaterial );
cubeObj.position.x = - 70;
cubeObj.position.y = - 50;
cubeObj.position.z = 0;
cubeObj.rotation.x = 0.5;
scene.add( cubeObj );
var cubeGeo2 = new THREE.BoxGeometry( 200, 150, 100 );
var cubeGeoMaterial2 = new THREE.MeshPhongMaterial( { color: 0x808080 } );
var cubeObj2 = new THREE.Mesh( cubeGeo2, cubeGeoMaterial2 );
cubeObj2.position.x = 160;
cubeObj2.position.y = - 50;
cubeObj2.position.z = - 5;
cubeObj2.rotation.x = 0.5;
scene.add( cubeObj2 );
var cubeGeo3 = new THREE.BoxGeometry( 200, 150, 100 );
var cubeGeoMaterial3 = new THREE.MeshPhongMaterial( { color: 0x808080 } );
var cubeObj3 = new THREE.Mesh( cubeGeo3, cubeGeoMaterial3 );
cubeObj3.position.x = 440;
cubeObj3.position.y = - 50;
cubeObj3.position.z = 0;
cubeObj3.rotation.x = 0.5;
scene.add( cubeObj3 );
renderer = new THREE.WebGLRenderer( {
antialias: true
} );
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 100, 1000, 100 );
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 500;
spotLight.shadow.camera.far = 4000;
spotLight.shadow.camera.fov = 30;
//scene.add( spotLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
scene.add( directionalLight );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xcce0ff );
document.body.appendChild( renderer.domElement );
document.addEventListener( 'keydown', onKeyDown, false );
}
function onKeyDown( event ) {
const step = 5; // world units
switch ( event.keyCode ) {
case 37:
camera.position.x -= step;
break;
case 39:
camera.position.x += step;
break;
}
}
function animate() {
renderer.render( scene, camera );
requestAnimationFrame( animate );
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.114/build/three.js"></script>

Applying postprocessing steps for specific objects

Based on this example i try to create a scene where several objects get the bloom, and other objects dont.
The white cube in the middle is supposed to be just white (without the bloom)
I'm confused on how to get the result that i want. I tried for example adding a 2nd scene with the white cube but it seems i cant get the order right. Maybe my approch with different scenes is wrong?
Whats the "best" way to achieve this behaviour? I always end up just seeing one scene, just the white cube or the 4 colored ones. (example below shows everything atm)
myFiddle: https://jsfiddle.net/qwertasyx/8qw3ys4z/16/
var scene,scene2,camera, controls, pointLight, stats;
var composer, renderer, mixer;
var params = {
exposure: 1,
bloomStrength: 1.5,
bloomThreshold: 0,
bloomRadius: 0
};
var objects = [];
var clock = new THREE.Clock();
var container = document.getElementById( 'container' );
stats = new Stats();
//container.appendChild( stats.dom );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ReinhardToneMapping;
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
//scene2 = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 2.5,2.5, 10 );
scene.add( camera );
// scene2.add( camera );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.maxPolarAngle = Math.PI * 0.5;
controls.minDistance = 1;
controls.maxDistance = 10;
controls.target.set(2.5,2.5,0)
controls.update()
// scene.add( new THREE.AmbientLight( 0x404040 ) );
pointLight = new THREE.PointLight( 0xffffff, 1 );
// camera.add( pointLight );
var renderScene = new THREE.RenderPass( scene, camera );
//var renderScene2 = new THREE.RenderPass( scene2, camera );
var bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
bloomPass.renderToScreen = true;
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;
composer = new THREE.EffectComposer( renderer );
composer.setSize( window.innerWidth, window.innerHeight );
composer.addPass( renderScene );
composer.addPass( bloomPass );
//composer.addPass( renderScene2 );
//objects
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.x += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.x += 5
cube.position.y += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.y += 5
scene.add( cube );
objects.push(cube)
var material = new THREE.MeshBasicMaterial( { color: 0x0000ff } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
scene.add( cube );
objects.push(cube)
// cube thats supposed to be not bloomy
var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
var cube = new THREE.Mesh( geometry, material );
cube.vrz = 0.01;
cube.position.y += 2.5
cube.position.x += 2.5
scene.add( cube );
objects.push(cube)
var gui = new dat.GUI();
gui.add( params, 'exposure', 0.1, 2 ).onChange( function ( value ) {
renderer.toneMappingExposure = Math.pow( value, 4.0 );
} );
gui.add( params, 'bloomThreshold', 0.0, 1.0 ).onChange( function ( value ) {
bloomPass.threshold = Number( value );
} );
gui.add( params, 'bloomStrength', 0.0, 3.0 ).onChange( function ( value ) {
bloomPass.strength = Number( value );
} );
gui.add( params, 'bloomRadius', 0.0, 1.0 ).step( 0.01 ).onChange( function ( value ) {
bloomPass.radius = Number( value );
} );
window.onresize = function () {
var width = window.innerWidth;
var height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
composer.setSize( width, height );
};
function animate() {
requestAnimationFrame( animate );
objects.forEach(function(obj){
obj.rotation.z += obj.vrz;
});
stats.update();
composer.render();
}
animate();
I had a similar problem once. An example from this comment helped me.
Note that in that example there are 2 scenes and 2 composers (the final composer gets output of the previous composer as its input)
ppoFinal.blendPass.uniforms.tAdd.value = ppoRGB.composer.renderTarget2.texture;
and render() is called on both composers.
ppoRGB.composer.render();
ppoFinal.composer.render();
This pattern allows you to apply postprocessing effects selectively and it works well. The problem is the scalability of the method and probably performance. Because when you want to apply another object with yet different effect, you need to introduce 3rd scene and 3rd composer. For my little project in the past I ended up with 4 scenes and 4 composers...

How to rotate the plane using three.js?

Hey guys I am using three.js and have tried to rotate this plane below but to avail. Any idea how to do it please? Below is the code which renders the plane using three.js. How can I rotate it, please?. Thanks!
var container;
var camera, scene, renderer;
var plane;
var mouse, raycaster, isShiftDown = false;
var cubeGeometry = new THREE.BoxBufferGeometry( 50, 50, 50 );
var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff80, overdraw: 0.5 } );
var objects = [];
init();
render();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'three.js - voxel painter<br><strong>click</strong>: add voxel, <strong>shift + click</strong>: remove voxel, save .png';
container.appendChild( info );
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 500, 800, 1300 );
camera.lookAt( 0, 0, 0 );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
// Grid
var gridHelper = new THREE.GridHelper( 1000, 20 );
scene.add( gridHelper );
//
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
//PlaneBufferGeometry: platform to lay cubes
var geometry = new THREE.PlaneBufferGeometry( 10000, 10000 );
geometry.rotateX( - Math.PI / 2 );
plane = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { visible: false } ) );
scene.add( plane );
objects.push( plane );
// Lights
var ambientLight = new THREE.AmbientLight( 0x606060 );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.x = Math.random() - 0.5;
directionalLight.position.y = Math.random() - 0.5;
directionalLight.position.z = Math.random() - 0.5;
directionalLight.position.normalize();
scene.add( directionalLight );
var directionalLight = new THREE.DirectionalLight( 0x808080 );
directionalLight.position.x = Math.random() - 0.5;
directionalLight.position.y = Math.random() - 0.5;
directionalLight.position.z = Math.random() - 0.5;
directionalLight.position.normalize();
scene.add( directionalLight );
renderer = new THREE.CanvasRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild(renderer.domElement);
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
//document.addEventListener( 'keydown', onDocumentKeyDown, false );
//document.addEventListener( 'keyup', onDocumentKeyUp, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function onDocumentMouseDown( event ) {
event.preventDefault();
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( objects );
if ( intersects.length > 0 ) {
var intersect = intersects[ 0 ];
if ( isShiftDown ) {
if ( intersect.object != plane ) {
scene.remove( intersect.object );
objects.splice( objects.indexOf( intersect.object ), 1 );
}
} else {
var voxel = new THREE.Mesh( cubeGeometry, cubeMaterial );
voxel.position.copy( intersect.point ).add( intersect.face.normal );
voxel.position.divideScalar( 50 ).floor().multiplyScalar( 50 ).addScalar( 25 );
scene.add( voxel );
objects.push( voxel );
}
render();
}
}
function render() {
renderer.render( scene, camera );
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/renderers/CanvasRenderer.js"></script>
<script src="https://threejs.org/examples/js/renderers/Projector.js"></script>
Look at the Plane here
I recommend to use THREE.OrbitControls.
Add orbit control:
orbitControls = new THREE.OrbitControls(camera);
And animate your scene continuously:
function render() {
renderer.render( scene, camera );
requestAnimationFrame(render);
}
Further you have to manage how THREE.OrbitControls and the mouse event (onDocumentMouseDown) interact together.
A possibility would be to handle only the left mouse button in onDocumentMouseDown:
function onDocumentMouseDown( event ) {
if ( event.button != 0 ) // 0 means left mouse button
return;
And to rotate the scene by the right mouse button. This can be done by setting the .mouseButtons property of OrbitControls:
orbitControls.mouseButtons = {
LEFT: THREE.MOUSE.RIGHT,
MIDDLE: THREE.MOUSE.MIDDLE,
RIGHT: THREE.MOUSE.LEFT
}
Further note, that you can enable or disable pane, zoom and rotate by setting .enablePan, .enableZoom respectively .enableRotate.
See the following example, where the boxes are positioned by the left mouse button and the scene can be rotated by holding the right mouse button:
var container;
var camera, scene, renderer;
var plane;
var mouse, raycaster, isShiftDown = false;
var cubeGeometry = new THREE.BoxBufferGeometry( 50, 50, 50 );
var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff80, overdraw: 0.5 } );
var objects = [];
init();
render();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 500, 800, 1300 );
camera.lookAt( 0, 0, 0 );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
var gridHelper = new THREE.GridHelper( 1000, 20 );
scene.add( gridHelper );
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
//PlaneBufferGeometry: platform to lay cubes
var geometry = new THREE.PlaneBufferGeometry( 10000, 10000 );
geometry.rotateX( - Math.PI / 2 );
plane = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { visible: false } ) );
scene.add( plane );
objects.push( plane );
// Lights
var ambientLight = new THREE.AmbientLight( 0x606060 );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.x = Math.random() - 0.5;
directionalLight.position.y = Math.random() - 0.5;
directionalLight.position.z = Math.random() - 0.5;
directionalLight.position.normalize();
scene.add( directionalLight );
var directionalLight = new THREE.DirectionalLight( 0x808080 );
directionalLight.position.x = Math.random() - 0.5;
directionalLight.position.y = Math.random() - 0.5;
directionalLight.position.z = Math.random() - 0.5;
directionalLight.position.normalize();
scene.add( directionalLight );
renderer = new THREE.CanvasRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild(renderer.domElement);
orbitControls = new THREE.OrbitControls(camera);
orbitControls.mouseButtons = {
LEFT: THREE.MOUSE.RIGHT,
MIDDLE: THREE.MOUSE.MIDDLE,
RIGHT: THREE.MOUSE.LEFT
}
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
if ( event.button != 0 )
return;
event.preventDefault();
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( objects );
if ( intersects.length > 0 ) {
var intersect = intersects[ 0 ];
if ( isShiftDown ) {
if ( intersect.object != plane ) {
scene.remove( intersect.object );
objects.splice( objects.indexOf( intersect.object ), 1 );
}
} else {
var voxel = new THREE.Mesh( cubeGeometry, cubeMaterial );
voxel.position.copy( intersect.point ).add( intersect.face.normal );
voxel.position.divideScalar( 50 ).floor().multiplyScalar( 50 ).addScalar( 25 );
scene.add( voxel );
objects.push( voxel );
}
}
}
function render() {
renderer.render( scene, camera );
requestAnimationFrame(render);
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/renderers/CanvasRenderer.js"></script>
<script src="https://threejs.org/examples/js/renderers/Projector.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Three.js - how can I get rid of the flashing red lights on my objects

I'm new to using Three.js and am using this to learn so hopefully this isn't a ridiculous question.
I have a weird transition red color on my mesh objects which is turning the images/texture a red color but I have no idea where it's coming from. I've tried moving the camera angle, but no luck.
Any help is appreciated!
This is the code:
<body>
<div id="container"></div>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/FirstPersonControls.js"></script>
<script src="http://threejs.org/examples/js/Detector.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container;
var camera, controls, scene, renderer;
var light, pointLight;
var mesh, mesh1, mesh2, mesh3, mesh4, mesh5;
var material_sphere1, material_sphere2, material_sphere3, material_sphere4, material_sphere5;
var clock = new THREE.Clock();
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 500 );
camera.position.set( 0, 25, 0 );
var listener = new THREE.AudioListener();
camera.add( listener );
controls = new THREE.FirstPersonControls( camera );
controls.movementSpeed = 160;
controls.lookSpeed = 0.08;
controls.noFly = true;
controls.lookVertical = false;
scene = new THREE.Scene();
var texture = THREE.ImageUtils.loadTexture( 'http://tam.outbrain.com/anita/vr-module-rec-by-nytimes.png', {}, function(){
// use to test when image gets loaded if it does
// alert('texture loaded')
},
function(){
alert('error')
});
var texture2 = THREE.ImageUtils.loadTexture( 'http://tam.outbrain.com/anita/vr-module-rec-by-snl.png', {}, function(){
// use to test when image gets loaded if it does
// alert('texture loaded')
},
function(){
alert('error')
});
var texture3 = THREE.ImageUtils.loadTexture( 'http://tam.outbrain.com/anita/vr-module-rec-by-toms.png', {}, function(){
// use to test when image gets loaded if it does
// alert('texture loaded')
},
function(){
alert('error')
});
var texture4 = THREE.ImageUtils.loadTexture( 'http://tam.outbrain.com/anita/vr-module-rec-by-verse.png', {}, function(){
// use to test when image gets loaded if it does
// alert('texture loaded')
},
function(){
alert('error')
});
var texture5 = THREE.ImageUtils.loadTexture( 'http://tam.outbrain.com/anita/vr-module-rec-by-whats-happening.png', {}, function(){
// use to test when image gets loaded if it does
// alert('texture loaded')
},
function(){
alert('error')
});
var sphere = new THREE.BoxGeometry( 1, 30, 30 );
var sphere2 = new THREE.BoxGeometry( 1, 30, 30 );
var sphere3 = new THREE.BoxGeometry( 1, 30, 30 );
var sphere4 = new THREE.BoxGeometry( 1, 30, 30 );
var sphere5 = new THREE.BoxGeometry( 1, 30, 30 );
material_sphere1 = new THREE.MeshBasicMaterial( { map: texture, color: 0x000000} );
material_sphere2 = new THREE.MeshBasicMaterial( { map: texture2, color: 0x000000} );
material_sphere3 = new THREE.MeshBasicMaterial( { map: texture3, color: 0x000000} );
material_sphere4 = new THREE.MeshBasicMaterial( { map: texture4, color: 0x000000} );
material_sphere5 = new THREE.MeshBasicMaterial( { map: texture5, color: 0x000000} );
// sound spheres
var mesh1 = new THREE.Mesh( sphere, material_sphere1 );
mesh1.position.set( 42, 25, 0 );
scene.add( mesh1 );
//
var mesh2 = new THREE.Mesh( sphere2, material_sphere2 );
mesh2.position.set( 30, 25, 35 );
mesh2.rotation.y = -Math.PI / 4;
scene.add( mesh2 );
//
var mesh3 = new THREE.Mesh( sphere3, material_sphere3 );
mesh3.position.set( -5, 25, 50 );
mesh3.rotation.y = -Math.PI / 2;
scene.add( mesh3 );
//
var mesh4 = new THREE.Mesh( sphere4, material_sphere4 );
mesh4.position.set( 30, 25, -35 );
mesh4.rotation.y = -Math.PI / -4;
scene.add( mesh4 );
//
var mesh5 = new THREE.Mesh( sphere5, material_sphere5 );
mesh5.position.set( -5, 25, -50 );
mesh5.rotation.y = -Math.PI / -2;
scene.add( mesh5 );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.innerHTML = "";
container.appendChild( renderer.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var delta = clock.getDelta(),
time = clock.getElapsedTime() * 5;
controls.update( delta );
material_sphere1.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
material_sphere2.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
material_sphere3.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
material_sphere4.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
material_sphere5.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
renderer.render( scene, camera );
}
</script>
</body>
You have these rows in the render method:
material_sphere1.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
material_sphere2.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
material_sphere3.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
material_sphere4.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
material_sphere5.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 );
you need to remove them in order to remove red flashing.
But then you will not see your images at all as you basic materials are black. So you need to change your materials color from 0x000000 to 0xFFFFFF in materials creation:
material_sphere1 = new THREE.MeshBasicMaterial( { map: texture, color: 0xFFFFFF} );
material_sphere2 = new THREE.MeshBasicMaterial( { map: texture2, color: 0xFFFFFF} );
material_sphere3 = new THREE.MeshBasicMaterial( { map: texture3, color: 0xFFFFFF} );
material_sphere4 = new THREE.MeshBasicMaterial( { map: texture4, color: 0xFFFFFF} );
material_sphere5 = new THREE.MeshBasicMaterial( { map: texture5, color: 0xFFFFFF} );

How can I make three.js update a scene after adding an object or group of objects?

I am fairly new to three.js and have a problem I can't readily find an answer for.
Here is a codepen that should sum up the situation: http://codepen.io/anon/pen/PPYPzO
var container, stats;
var camera, controls, scene, renderer, raycaster, mouse;
init();
animate();
add_world();
var indie_render = true;
for(var j = 0; j < 20; j++){
add_objects(20);
indie_render = !indie_render;
console.log("adding more objects...");
if(!indie_render){render();}
}
function add_world(){
var geometry = new THREE.BoxGeometry( 1000, 1000, 1000);
var mesh = new THREE.MeshBasicMaterial( {color: 0xf5f5dc, wireframe: false, opacity: 0.2, transparent:true } );
var world = new THREE.Mesh( geometry, mesh );
scene.add( world );
render();
}
function add_objects(num, indiv){
var geometry = new THREE.SphereGeometry( 5, 32,32 );
var material = new THREE.MeshBasicMaterial( { shading: THREE.FlatShading } );
material.color.setRGB( Math.random(), Math.random(), Math.random() );
for ( var i = 0; i < num; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
mesh.updateMatrix();
mesh.matrixAutoUpdate = false;
scene.add( mesh );
if(indie_render){
console.log("individual render");
render();
}
}
}
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set(500, 500, -1000);
camera.up.set( 0, 1, 0 );
camera.lookAt(500,500,500);
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
//world
scene = new THREE.Scene();
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( 0x000000, 1 );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
mouse = new THREE.Vector2();
raycaster = new THREE.Raycaster();
container.addEventListener( 'mousemove', onMouseMove, false );
container.addEventListener( 'mousedown', onMouseDown, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}
function onMouseMove( e ) {
mouse.x = ( e.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( e.clientY / renderer.domElement.height ) * 2 + 1;
}
function onMouseDown( e ) {
mouse.x = ( e.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( e.clientY / renderer.domElement.height ) * 2 + 1;
if(e.button == 2){ //right button
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( scene.children, true );
if ( intersects.length > 0 ) {
var geometry = new THREE.SphereGeometry( 5, 32,32 );
var material = new THREE.MeshBasicMaterial( { color:0xff0000, shading: THREE.FlatShading } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(intersects[0].point.x, intersects[0].point.y, intersects[0].point.z);
scene.add(mesh);
render();
}
}
}
In this demo, I init() and animate() a blank scene, and then add a translucent cube, following what seems to be convention. Then I add groups of spheres to the scene in a nested for loop, randomly placing the spheres inside the cube and making a render() call after every scene.add() call.
Currently, the scene adds all the spheres and only then is visible to the user, even though I can add individual objects after the for-loop objects are added (by right-clicking on the cube). I need for the user to be able to watch as spheres are added, rather than waiting for the whole thing to be done.
I realize this may not be the most efficient way to render the scene, but it would be quite helpful if, for example, the info on the objects to be animated is arriving asynchronously from a server. Does anyone have a suggestion?
Thanks
1) First: move call render() to animate:
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
2) Call add_objects asynchronously: setTimeout( add_objects, 0, 20 );
http://codepen.io/anon/pen/bVbEEP

Resources