I modified an example from Three.js library and I tried to add click event on objects.
After a lot of attempts... I'm still not capable to listening for clicks.
This code produces convex forms.
There is my code:
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, scene, renderer;
var objects = [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.y = 400;
scene = new THREE.Scene();
var light, object, object2, materials;
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 0 );
scene.add( light );
var map = THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg' );
map.wrapS = map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
materials = [
new THREE.MeshLambertMaterial( { ambient: 0xbbbbbb, map: map } ),
new THREE.MeshBasicMaterial( { color: 0x242424, wireframe: true, transparent: false, opacity: 0.1 } )
];
// random convex
points = [];
for ( var i = 0; i < 15; i ++ ) {
points.push( randomPointInSphere( 50 ) );
}
object = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points ), materials );
object.position.set( -250, 0, 200 );
scene.add( object );
objects.push( object );
object.callback = function() { console.log('blabla');}
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function randomPointInSphere( radius ) {
return new THREE.Vector3(
( Math.random() - 0.5 ) * 1 * radius,
( Math.random() - 0.5 ) * 1 * radius,
( Math.random() - 0.5 ) * 1 * radius
);
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
var timer = Date.now() * 0.0001;
camera.position.x = Math.cos( timer ) * 800;
camera.position.z = Math.sin( timer ) * 800;
camera.lookAt( scene.position );
for ( var i = 0, l = scene.children.length; i < l; i ++ ) {
var object = scene.children[ i ];
object.rotation.x = timer * 5;
object.rotation.y = timer * 2.5;
}
renderer.render( scene, camera );
}
function addMeteor()
{
var map = THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg' );
map.wrapS = map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
var materials = [
new THREE.MeshLambertMaterial( { ambient: 0xbbbbbb, map: map } ),
new THREE.MeshBasicMaterial( { color: 0x242424, wireframe: true, transparent: false, opacity: 0.1 } )
];
objects.push( materials );
var object3;
var points3 = [];
for ( var i = 0; i < 10; i ++ ) {
points3.push( randomPointInSphere( 50 ) );
}
object3 = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points3 ), materials );
object3.position.set( -50, Math.floor((Math.random()*window.innerWidth)), Math.floor((Math.random()* window.innerHeight)) );
scene.add( object3 );
objects.push( object3 );
}
projector = new THREE.Projector();
// listeners
document.addEventListener( 'mousedown', onDocumentMouseDown, false)
// keyboard handler
function onDocumentMouseDown( event ) {
event.preventDefault();
console.log('blabla');
var vector = new THREE.Vector3(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1,
0.5 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
console.log(objects);
var intersects = ray.intersectObjects( objects );
console.log(intersects);
if ( intersects.length > 0 ) {
intersects[0].object.callback();
console.log('blabla');
}
}
renderer.render( scene, camera );
I was supposed to push Mesh into Objects array, but which one?
THREE.SceneUtils.createMultiMaterialObject() creates an object with two child meshes.
So, you need to set the recursive flag to true when calling Raycaster.intersectObjects().
var intersects = ray.intersectObjects( objects, true );
three.js r.62
Related
I have an animation prototype - which plays on scroll - is there a way to reset animation on scroll to top/bottom? Basically from the top it plays and stops when it reaches the bottom? Right now the animation loops and ignores top/bottom (start/end).
When scrolled from the top it plays forward and when reached the bottom it plays in reverse is the desired bahaviour.
var container, stats, controls;
var camera, scene, renderer, light;
var clock = new THREE.Clock();
var mixer = [];
var mixers = [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set( 0, 100, 100 );
scene = new THREE.Scene();
light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 200, 0 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 200, 100 );
light.castShadow = true;
light.shadow.camera.top = 180;
light.shadow.camera.bottom = -100;
light.shadow.camera.left = -120;
light.shadow.camera.right = 120;
scene.add( light );
// scene.add( new THREE.CameraHelper( light.shadow.camera ) );
var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
// model
var loader = new THREE.FBXLoader();
loader.load( 'https://threejs.org/examples/models/fbx/Samba Dancing.fbx', function ( object ) {
object.mixer = new THREE.AnimationMixer( object );
mixers.push( object.mixer );
var action = object.mixer.clipAction( object.animations[ 0 ] );
action.play();
object.traverse( function ( child ) {
if ( child.isMesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
} );
object.position.y = 85;
scene.add( object );
} );
renderer = new THREE.WebGLRenderer( { alpha: true, antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
container.appendChild( renderer.domElement );
window.addEventListener( 'mousewheel', onMouseWheel, false );
window.addEventListener( 'touchstart', onTouchStart, false );
window.addEventListener( 'touchmove', onTouchMove, false );
window.addEventListener('resize', onResize, false);
// stats
stats = new Stats();
container.appendChild( stats.dom );
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onMouseWheel( event ) {
if(event.deltaY > 0){
for ( var i = 0; i < mixers.length; i ++ ) {
mixers[ i ].update( clock.getDelta() * 5 );
}
} else {
for ( var i = 0; i < mixers.length; i ++ ) {
mixers[ i ].update( clock.getDelta() * -5 );
}
}
}
function onTouchStart(event) {
startY = event.touches[ 0 ].pageY;
}
function onTouchMove( event ) {
var delta = event.deltaY;
if(event.deltaY > 0){
for ( var i = 0; i < mixers.length; i ++ ) {
mixers[ i ].update( clock.getDelta() * 5 );
}
} else {
for ( var i = 0; i < mixers.length; i ++ ) {
mixers[ i ].update( clock.getDelta() * -5 );
}
}
}
function animate() {
delta = clock.getDelta();
requestAnimationFrame( animate );
renderer.render( scene, camera );
stats.update();
}
body {
margin: 0px;
overflow: hidden;
}
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/inflate.min.js"></script>
<script src="https://threejs.org/examples/js/loaders/FBXLoader.js"></script>
<script src="https://threejs.org/examples/js/WebGL.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
First off you should never link directly to threejs.org. Your example will break when the three.js devs update the version which will make your question example useless to others. Use a specific version from a CDN!
Otherwise if you save off the clips
object.mixer = new THREE.AnimationMixer( object );
mixers.push( object.mixer );
const clip = object.animations[0];
clips.push(clip);
var action = object.mixer.clipAction(clip);
action.play();
Then maybe you could use code like this
function updateAnimation(direction) {
const delta = direction * 5 * clock.getDelta();
for (let i = 0; i < mixers.length; ++i) {
const mixer = mixers[i];
const clip = clips[i];
const duration = clip.duration;
const newTime = THREE.MathUtils.clamp(mixer.time + delta, 0, duration);
mixer.setTime(newTime);
}
}
function onMouseWheel( event ) {
updateAnimation(Math.sign(event.deltaY));
}
...
var container, stats, controls;
var camera, scene, renderer, light;
var duration;
var clock = new THREE.Clock();
var mixer = [];
var mixers = [];
var clips = [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set( 0, 100, 100 );
scene = new THREE.Scene();
light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 200, 0 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 200, 100 );
light.castShadow = true;
light.shadow.camera.top = 180;
light.shadow.camera.bottom = -100;
light.shadow.camera.left = -120;
light.shadow.camera.right = 120;
scene.add( light );
// scene.add( new THREE.CameraHelper( light.shadow.camera ) );
var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
// model
var loader = new THREE.FBXLoader();
loader.load( 'https://threejs.org/examples/models/fbx/Samba Dancing.fbx', function ( object ) {
object.mixer = new THREE.AnimationMixer( object );
mixers.push( object.mixer );
const clip = object.animations[0];
clips.push(clip);
var action = object.mixer.clipAction(clip);
action.play();
object.traverse( function ( child ) {
if ( child.isMesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
} );
object.position.y = 85;
scene.add( object );
} );
renderer = new THREE.WebGLRenderer( { alpha: true, antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
container.appendChild( renderer.domElement );
window.addEventListener( 'mousewheel', onMouseWheel, false );
window.addEventListener('resize', onResize, false);
// stats
stats = new Stats();
container.appendChild( stats.dom );
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function updateAnimation(direction) {
const delta = direction * 5 * clock.getDelta();
for (let i = 0; i < mixers.length; ++i) {
const mixer = mixers[i];
const clip = clips[i];
const duration = clip.duration;
const newTime = THREE.MathUtils.clamp(mixer.time + delta, 0, duration);
mixer.setTime(newTime);
}
}
function onMouseWheel( event ) {
updateAnimation(Math.sign(event.deltaY));
}
function animate() {
delta = clock.getDelta();
requestAnimationFrame( animate );
renderer.render( scene, camera );
stats.update();
}
body {
margin: 0px;
overflow: hidden;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.113.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.113.2/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.113.2/examples/js/libs/inflate.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.113.2/examples/js/loaders/FBXLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.113.2/examples/js/WebGL.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.113.2/examples/js/libs/stats.min.js"></script>
I'm working with the three.js ocean scene and 3D canvas text. The 3D text is suppose to replace the location of the ball, but the text doesn't appear.
When I inspect elements, I only notice the canvas for the background rendering. How can both canvases- the background and 3D text- appear? How can I overlay a canvas on another?
What is another way to have 3D text over the water without using canvas or canvasrenderer.js for the 3D text?
Original code for Canvas 3D Text: https://github.com/mrdoob/three.js/blob/master/examples/canvas_geometry_text.html
JavaScript to combine both elements:
var container, stats;
var camera, scene, renderer;
var parameters = {
width: 2000,
height: 2000,
widthSegments: 250,
heightSegments: 250,
depth: 1500,
param: 4,
filterparam: 1
};
var waterNormals;
var group;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var loader = new THREE.FontLoader();
loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {
} );
init();
animate();
function init( font ) {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 150, 500 );
scene = new THREE.Scene();
// Get text from hash
var theText = "three.js";
var hash = document.location.hash.substr( 1 );
if ( hash.length !== 0 ) {
theText = hash;
}
var geometry0 = new THREE.TextGeometry( theText, {
font: font,
size: 80,
height: 20,
curveSegments: 2
});
geometry.computeBoundingBox();
var centerOffset = -0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
var material0 = new THREE.MultiMaterial( [
new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } ),
new THREE.MeshBasicMaterial( { color: 0x000000, overdraw: 0.5 } )
] );
var mesh = new THREE.Mesh( geometry0, material0 );
mesh.position.x = centerOffset;
mesh.position.y = 100;
mesh.position.z = 50;
group = new THREE.Group();
group.add( mesh );
scene.add( group );
renderer = new THREE.CanvasRenderer();
renderer.setClearColor( 0xf0f0f0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
camera.position.set( 2000, 750, 2000 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enablePan = false;
controls.minDistance = 1000.0;
controls.maxDistance = 5000.0;
controls.maxPolarAngle = Math.PI * 0.495;
controls.target.set( 0, 500, 0 );
scene.add( new THREE.AmbientLight( 0x444444 ) );
var light = new THREE.DirectionalLight( 0xffffbb, 1 );
light.position.set( - 1, 1, - 1 );
scene.add( light );
waterNormals = new THREE.TextureLoader().load( 'textures/waternormals.jpg' );
waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
water = new THREE.Water( renderer, camera, scene, {
textureWidth: 512,
textureHeight: 512,
waterNormals: waterNormals,
alpha: 1.0,
sunDirection: light.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 50.0,
} );
mirrorMesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
water.material
);
mirrorMesh.add( water );
mirrorMesh.rotation.x = - Math.PI * 0.5;
scene.add( mirrorMesh );
// load skybox
var cubeMap = new THREE.CubeTexture( [] );
cubeMap.format = THREE.RGBFormat;
var loader = new THREE.ImageLoader();
loader.load( 'textures/skyboxsun25degtest.png', function ( image ) {
var getSide = function ( x, y ) {
var size = 1024;
var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;
var context = canvas.getContext( '2d' );
context.drawImage( image, - x * size, - y * size );
return canvas;
};
cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
cubeMap.needsUpdate = true;
} );
var cubeShader = THREE.ShaderLib[ 'cube' ];
cubeShader.uniforms[ 'tCube' ].value = cubeMap;
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
var skyBox = new THREE.Mesh(
new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
skyBoxMaterial
);
scene.add( skyBox );
var geometry = new THREE.IcosahedronGeometry( 400, 4 );
for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
}
var material = new THREE.MeshPhongMaterial( {
vertexColors: THREE.FaceColors,
shininess: 100,
envMap: cubeMap
} );
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
water.material.uniforms.time.value += 1.0 / 60.0;
controls.update();
water.render();
renderer.render( scene, camera );
}
The first thing i notice is that you are calling the init(); animate(); functions before the loader has a chance to load the font ( and because of that you are not passing the font into the init function like the canvas_geometry_text example ).
I've pasted the code from the ocean example below ( with comments for how I modified it to work with the code from the canvas_geometry_text example ). I've tested this and it works
var container, stats;
var camera, scene, renderer;
var sphere;
var parameters = {
width: 2000,
height: 2000,
widthSegments: 250,
heightSegments: 250,
depth: 1500,
param: 4,
filterparam: 1
};
var waterNormals;
// 1.
// copy+paste this code from the canvas_geometry_text file
var loader = new THREE.FontLoader();
loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {
init( font );
animate();
} );
// 2.
// comment out these calls to init() and animate()
// these will be called in the loader's callback above instead
// init();
// animate();
// add 'font' parameter to init
function init( font ) {
container = document.createElement( 'div' );
document.body.appendChild( container );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
camera.position.set( 2000, 750, 2000 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enablePan = false;
controls.minDistance = 1000.0;
controls.maxDistance = 5000.0;
controls.maxPolarAngle = Math.PI * 0.495;
controls.target.set( 0, 500, 0 );
scene.add( new THREE.AmbientLight( 0x444444 ) );
var light = new THREE.DirectionalLight( 0xffffbb, 1 );
light.position.set( - 1, 1, - 1 );
scene.add( light );
waterNormals = new THREE.TextureLoader().load( 'textures/waternormals.jpg' );
waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
water = new THREE.Water( renderer, camera, scene, {
textureWidth: 512,
textureHeight: 512,
waterNormals: waterNormals,
alpha: 1.0,
sunDirection: light.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 50.0,
} );
mirrorMesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
water.material
);
mirrorMesh.add( water );
mirrorMesh.rotation.x = - Math.PI * 0.5;
scene.add( mirrorMesh );
// load skybox
var cubeMap = new THREE.CubeTexture( [] );
cubeMap.format = THREE.RGBFormat;
var loader = new THREE.ImageLoader();
loader.load( 'textures/skyboxsun25degtest.png', function ( image ) {
var getSide = function ( x, y ) {
var size = 1024;
var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;
var context = canvas.getContext( '2d' );
context.drawImage( image, - x * size, - y * size );
return canvas;
};
cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
cubeMap.needsUpdate = true;
} );
var cubeShader = THREE.ShaderLib[ 'cube' ];
cubeShader.uniforms[ 'tCube' ].value = cubeMap;
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
var skyBox = new THREE.Mesh(
new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
skyBoxMaterial
);
scene.add( skyBox );
// 3.
// comment out all the sphere mesh code
// var geometry = new THREE.IcosahedronGeometry( 400, 4 );
// for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
// geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
// }
// var material = new THREE.MeshPhongMaterial( {
// vertexColors: THREE.FaceColors,
// shininess: 100,
// envMap: cubeMap
// } );
// sphere = new THREE.Mesh( geometry, material );
// scene.add( sphere );
// 4.
// copy+paste the text mesh code from canvas_geometry_text
var theText = "Hello three.js! :)";
var hash = document.location.hash.substr( 1 );
if ( hash.length !== 0 ) {
theText = hash;
}
var geometry = new THREE.TextGeometry( theText, {
font: font,
size: 80,
height: 20,
curveSegments: 2
});
geometry.computeBoundingBox();
var centerOffset = -0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
var material = new THREE.MultiMaterial( [
new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } ),
new THREE.MeshBasicMaterial( { color: 0x000000, overdraw: 0.5 } )
] );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = centerOffset;
mesh.position.y = 100;
mesh.position.z = 0;
mesh.rotation.x = 0;
mesh.rotation.y = Math.PI * 2;
group = new THREE.Group();
group.add( mesh );
scene.add( group );
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var time = performance.now() * 0.001;
// 6.
// comment out the sphere animation code
// sphere.position.y = Math.sin( time ) * 500 + 250;
// sphere.rotation.x = time * 0.5;
// sphere.rotation.z = time * 0.51;
// 7.
// copy+paste the sphere animation code above
// but replace 'sphere' with 'group'
group.position.y = Math.sin( time ) * 500 + 250;
group.rotation.x = time * 0.5;
group.rotation.z = time * 0.51;
water.material.uniforms.time.value += 1.0 / 60.0;
controls.update();
water.render();
renderer.render( scene, camera );
}
I'm trying to create a three.js scene with a cubemap panorama background and a few .obj files with .mtl textures placed in the scene. However, I'm receiving this WebGL error that I can't figure out the source of:
THbindTexture: textures can not be used with multiple targets
Does anyone know what could possibly be going wrong? Here is the relevant code:
var camera, cubeCamera, scene, object, renderer;
var cube, sphere, torus;
var fov = 70,
isUserInteracting = false,
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0;
var skyLoader = new THREE.TextureLoader();
skyLoader.load( 'pano.jpg', function ( texture ) {
texture.mapping = THREE.UVMapping;
init( texture );
animate();
} );
function init( texture ) {
camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 );
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0x444444 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
directionalLight.position.set( 0, 0, 1 ).normalize();
scene.add( directionalLight );
var mesh = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), new THREE.MeshBasicMaterial( { map: texture } ) );
mesh.scale.x = -1;
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
cubeCamera = new THREE.CubeCamera( 1, 1000, 256 );
scene.add( cubeCamera );
document.body.appendChild( renderer.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
document.addEventListener( 'MozMousePixelScroll', onDocumentMouseWheel, false);
window.addEventListener( 'resize', onWindowResized, false );
onWindowResized( null );
var loader = new THREE.OBJLoader();
loader.load( 'nsa_sanantonio.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material.envMap = texture;
// add any other properties you want here. check the docs.
}
} );
scene.add( object );
} );
}
function onWindowResized( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.projectionMatrix.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
onPointerDownPointerX = event.clientX;
onPointerDownPointerY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
}
function onDocumentMouseMove( event ) {
lon = ( event.clientX - onPointerDownPointerX ) * 0.1 + onPointerDownLon;
lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
}
function onDocumentMouseWheel( event ) {
// WebKit
if ( event.wheelDeltaY ) {
fov -= event.wheelDeltaY * 0.05;
// Opera / Explorer 9
} else if ( event.wheelDelta ) {
fov -= event.wheelDelta * 0.05;
// Firefox
} else if ( event.detail ) {
fov += event.detail * 1.0;
}
camera.projectionMatrix.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var time = Date.now();
lon += .15;
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = THREE.Math.degToRad( 90 - lat );
theta = THREE.Math.degToRad( lon );
camera.position.x = 100 * Math.sin( phi ) * Math.cos( theta );
camera.position.y = 100 * Math.cos( phi );
camera.position.z = 100 * Math.sin( phi ) * Math.sin( theta );
camera.lookAt( scene.position );
cubeCamera.updateCubeMap( renderer, scene );
renderer.render( scene, camera );
}
I don't understand how two textures are being applied at once.
I got the Objloader code from here.
But it also doesn't work with the normal obj/stl loader. I have a demo on my website at http://www.zakziebell.com/nsa (you'll see that my model is black)
bindTexture: textures can not be used with multiple targets
means you're trying to use the same texture in 2 different ways, once as a 2D texture and again as a cubemap. A texture can only be one thing or the other not both.
I'm setting up a texture on a mesh in three.js:
var container, stats;
var camera, scene, projector, raycaster, renderer;
var mouse = new THREE.Vector2(), INTERSECTED;
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0,
target = new THREE.Vector3();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 1, 1000 );
scene = new THREE.Scene();
texture = THREE.ImageUtils.loadTexture( "textures/DIVE_IMMO_00000.jpg");
var background = new THREE.MeshBasicMaterial({map: texture});
var sphere = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), background );
sphere.scale.x = -1;
scene.add( sphere );
//projector = new THREE.Projector();
//raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor( 0xf0f0f0 );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
document.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false);
//
window.addEventListener( 'resize', onWindowResize, false );
}
Next, i want to change the texture on this mesh using a button. I've try :
function newTexture() {
sphere.material.texture = THREE.ImageUtils.loadTexture( "textures/DIVE_IMMO_00004.jpg");
sphere.material.texture.needsUpdate = true;
}
also:
texture2 = THREE.ImageUtils.loadTexture( "textures/DIVE_IMMO_00004.jpg"); and
function newTexture() {
background = new THREE.MeshBasicMaterial({map: texture2});
}
but it doesn't work, and i really don't understand why.
Sorry for this noob question ^^
UPDATE: FULL CODE PAGE
var container, stats;
var camera, scene, projector, raycaster, renderer;
var mouse = new THREE.Vector2(), INTERSECTED;
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0,
target = new THREE.Vector3();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 1, 1000 );
scene = new THREE.Scene();
//textures
texture = THREE.ImageUtils.loadTexture( "textures/DIVE_IMMO_00000.jpg");
texture_salon= THREE.ImageUtils.loadTexture( 'textures/btn_salon.png');
//materials
var background = new THREE.MeshBasicMaterial({map: texture});
var mat_salon = new THREE.MeshBasicMaterial( { map: texture_salon } )
mat_salon.transparent = true;
mat_salon.map.needsUpdate = true;
mat_salon.depthTest = false;
//Objects
var sphere = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), background );
sphere.scale.x = -1;
scene.add( sphere );
var plane_salon = new THREE.Mesh( new THREE.PlaneGeometry( 80, 60 ), mat_salon );
plane_salon.position.set( -280, 0, 100 );
plane_salon.lookAt( camera.position );
plane_salon.id = 01;
scene.add( plane_salon );
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor( 0xf0f0f0 );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
document.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false);
//
window.addEventListener( 'resize', onWindowResize, false );
}
function newTexture() {
sphere.material.map = THREE.ImageUtils.loadTexture( "textures/DIVE_IMMO_00004.jpg");
sphere.material.map.needsUpdate = true;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
onPointerDownPointerX = event.clientX;
onPointerDownPointerY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
var projector = new THREE.Projector();
var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
projector.unprojectVector( vector, camera );
var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
var intersects = raycaster.intersectObjects( scene.children,true );
if ( intersects.length > 0 ) {
SELECTED = intersects[0].object;
if (SELECTED.id == 01){
$('#plan').css('display', '');
$('#Menu-plan').css('height', '285px');
RotToKitchen();
}
}
}
function onDocumentMouseMove( event ) {
lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
}
function onDocumentMouseWheel( event ) {
if ( event.wheelDeltaY ) {fov -= event.wheelDeltaY * 0.05;} // WebKit
else if ( event.wheelDelta ) {fov -= event.wheelDelta * 0.05;} // Opera / Explorer 9
else if ( event.detail ) {fov += event.detail * 1.0;} // Firefox
}
function animate() {
requestAnimationFrame( animate );
render();
}
function RotToKitchen() {
var id = requestAnimationFrame( RotToKitchen );
if (lon < 90) {lon +=0.85;}
else if (lon > 91) {lon -=0.85;}
else cancelAnimationFrame( id );
render();
}
function render() {
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = THREE.Math.degToRad( 90 - lat );
theta = THREE.Math.degToRad( lon );
target.x = 0 * Math.sin( phi ) * Math.cos( theta );
target.y = 0 * Math.cos( phi );
target.z = 0 * Math.sin( phi ) * Math.sin( theta );
camera.position.x = 100 * Math.sin( phi ) * Math.cos( theta );
camera.position.y = 100 * Math.cos( phi );
camera.position.z = 100 * Math.sin( phi ) * Math.sin( theta );
camera.lookAt( target );
renderer.render( scene, camera );
}
One issue I notice is that you do sphere.material.texture = ... while it should be sphere.material.map = ...
And sphere.material.texture.needsUpdate should be sphere.material.map.needsUpdate = true;
I think it is better to update the existing texture:
texture = THREE.ImageUtils.loadTexture( "textures/DIVE_IMMO_00000.jpg");
update it:
texture.image = ( "textures/DIVE_IMMO_00004.jpg" );
texture.needsUpdate = true;
Not sure how it works with preloading the image etc...
i am using threejs with my colladaLoader, and my model displays fine except for the fact that the ambient light or something related makes it dark sometimes.. the light comes and goes. with the following code, how can i disable this behavior and make is lighting constant and bright?
CODE:
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, scene, renderer, objects;
var particleLight, pointLight;
var skin;
function load_model(el,model_url,type) {
window.loader = new THREE.ColladaLoader();
window.loader.options.convertUpAxis = true;
window.imageReplace = [{"name":"stock.jpg","new_image":"colors/generated_color.png"}];
window.loader.load( model_url, imageReplace, function ( collada ) {
//console.log(collada);
dae = collada.scene;
skin = collada.skins[ 0 ];
dae.scale.x = dae.scale.y = dae.scale.z = 0.040;
dae.updateMatrix();
//setMaterial(dae, new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( "/media/images/stock.jpg") } ));
window.init(el);
window.animate();
} );
window.init = function(el) {
container = document.createElement( 'div' );
el.append( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set( 2, 2, 3 );
scene = new THREE.Scene();
// Add the COLLADA
scene.add( dae );
particleLight = new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) );
scene.add( particleLight );
// Lights
// scene.add( new THREE.AmbientLight( 0xFFFFFF ) );
var directionalLight = new THREE.DirectionalLight(/*Math.random() * 0xffffff*/0xeeeeee );
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 );
// pointLight = new THREE.PointLight( 0xffffff, 4 );
// pointLight.position = particleLight.position;
// scene.add( pointLight );
renderer = new THREE.WebGLRenderer();
if ( type =='edit')
renderer.setSize( window.innerWidth/2, window.innerHeight/2 );
else
renderer.setSize( window.innerWidth/3, window.innerHeight/3 );
container.appendChild( renderer.domElement );
// stats = new Stats();
// stats.domElement.style.position = 'absolute';
// stats.domElement.style.top = '0px';
// container.appendChild( stats.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
if ( type =='edit')
renderer.setSize( window.innerWidth/2, window.innerHeight/2 );
else
renderer.setSize( window.innerWidth/3, window.innerHeight/3 );
}
//
var t = 0;
var clock = new THREE.Clock();
window.animate = function() {
var delta = clock.getDelta();
requestAnimationFrame( animate );
if ( t > 1 ) t = 0;
if ( skin ) {
// guess this can be done smarter...
// (Indeed, there are way more frames than needed and interpolation is not used at all
// could be something like - one morph per each skinning pose keyframe, or even less,
// animation could be resampled, morphing interpolation handles sparse keyframes quite well.
// Simple animation cycles like this look ok with 10-15 frames instead of 100 ;)
for ( var i = 0; i < skin.morphTargetInfluences.length; i++ ) {
skin.morphTargetInfluences[ i ] = 0;
}
skin.morphTargetInfluences[ Math.floor( t * 30 ) ] = 1;
t += delta;
}
window.render();
//stats.update();
}
window.render = function() {
var timer = Date.now() * 0.0005;
camera.position.x = Math.cos( timer ) * 10;
camera.position.y = 2;
camera.position.z = Math.sin( timer ) * 10;
camera.lookAt( scene.position );
particleLight.position.x = Math.sin( timer * 4 ) * 3009;
particleLight.position.y = Math.cos( timer * 5 ) * 4000;
particleLight.position.z = Math.cos( timer * 4 ) * 3009;
renderer.render( scene, camera );
}
}
Your main (?) light position is defined as random like this:
directionalLight.position.x = Math.random() - 0.5;
directionalLight.position.y = Math.random() - 0.5;
directionalLight.position.z = Math.random() - 0.5;
Just use hardcoded, constant position there.
You can use ambient light too, that doesn't need position at all. You can uncomment that from your code, if you want.