Trouble with changing textures in three.js - javascript

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...

Related

Three.js 360 Image - Texture marked for update but image is incomplete

This is the code I'm using -
var camera, scene, renderer;
var Container = document.getElementById('container');
var imageFile = Container.getAttribute('data');
var isUserInteracting = false,
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0;
init();
animate();
function closeModal() {
}
function init() {
var container, mesh;
container = document.getElementById( 'gallery-modal' );
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
var geometry = new THREE.SphereGeometry( 500, 60, 40 );
geometry.scale( - 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {
map: new THREE.TextureLoader().load( imageFile )
} );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
//renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setSize( window.innerWidth, 500);
container.appendChild( renderer.domElement );
// Controls to move the image
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'wheel', onDocumentMouseWheel, false );
document.addEventListener( 'dragover', function ( event ) {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}, false );
document.addEventListener( 'dragenter', function ( event ) {
document.body.style.opacity = 0.5;
}, false );
document.addEventListener( 'dragleave', function ( event ) {
document.body.style.opacity = 1;
}, false );
var galleryDOM = document.getElementById('gallery');
var modal = document.getElementById('gallery-modal');
galleryDOM.addEventListener('click', function(e) {
if(e.target.localName == 'img') {
//console.log(e.target.src);
modal.style.display = "block";
var reader = new FileReader();
reader.addEventListener('load', function(e) {
material.map.image.src = e.target.result;
material.map.needsUpdate = true;
}, false);
}
});
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = 'none';
}
}
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
isUserInteracting = true;
onPointerDownPointerX = event.clientX;
onPointerDownPointerY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
}
function onDocumentMouseMove( event ) {
if ( isUserInteracting === true ) {
lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;
}
}
function onDocumentMouseUp( event ) {
isUserInteracting = false;
}
function onDocumentMouseWheel( event ) {
camera.fov += event.deltaY * 0.05;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame( animate );
update();
}
function update() {
if ( isUserInteracting === false ) {
lon += 0.1;
}
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = THREE.Math.degToRad( 90 - lat );
theta = THREE.Math.degToRad( lon );
camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
camera.target.y = 500 * Math.cos( phi );
camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );
camera.lookAt( camera.target );
/*
// distortion
camera.position.copy( camera.target ).negate();
*/
renderer.render( scene, camera );
}
UPDATE** I'm no longer recieving an error, but this also isn't changing the texture image?
I've add my entire code. I'm trying to create a gallery effect, click a placeholder image, modal opens with 360 image, but I need to it switch 360 images based on the placeholder clicked.

Three.js scene with Obj and Cubemap, receiving THbindTexture: textures can not be used with multiple targets

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.

Three.js won't render when object is rotated

Arrggh, I really need some help, going nuts. I have a three.js HTML5 page with three objects (1)cube, (2)cylinder and (3) an imported OBJ mesh.
Everything works fine until I try to rotate the mesh (guitar), then nothing renders. I can rotate and position it fine before adding to the scene, but if I try to rotate it within the render function everything goes black.
Can anyone tell me what I am doing wrong? Code is attached below.
thanks
<script src="../build/three.min.js"></script>
<script src="js/loaders/DDSLoader.js"></script>
<script src="js/loaders/MTLLoader.js"></script>
<script src="js/loaders/OBJMTLLoader.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var container, stats;
var camera, scene, renderer;
var guitar,button1,cube;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
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.z = 640;
// scene
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 );
// model
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var loader = new THREE.OBJMTLLoader();
loader.load( 'obj/male02/guitarOBJ.obj', 'obj/male02/male02_dds.mtl', function ( guitar ) {
guitar.rotation.x = 1.57;
scene.add( guitar );
} );
var geometry = new THREE.CylinderGeometry( 5, 5, 50, 32 );
var material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
button1 = new THREE.Mesh( geometry, material );
button1.rotation.y = 1;
button1.rotation.z = 0.75;
scene.add( button1 );
var geometry = new THREE.BoxGeometry( 100, 100, 100 );
for ( var i = 0; i < geometry.faces.length; i += 2 ) {
var hex = Math.random() * 0xffffff;
geometry.faces[ i ].color.setHex( hex );
geometry.faces[ i + 1 ].color.setHex( hex );
}
var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );
cube = new THREE.Mesh( geometry, material );
cube.position.y = 150;
scene.add( cube );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
/////////document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
///function onDocumentMouseMove( event ) {
///mouseX = ( event.clientX - windowHalfX ) / 2;
///mouseY = ( event.clientY - windowHalfY ) / 2;
///}
function onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut, false );
mouseXOnMouseDown = event.clientX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOut( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentTouchStart( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
}
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
guitar.rotation.y = button1.rotation.y = cube.rotation.y += ( targetRotation - cube.rotation.y ) * 0.05;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
Check this fiddle here. It is done exactly like how you did it.
Maybe the if clause makes a difference? Maybe you should not try rotating something before the mesh is properly loaded?
if(mesh){
mesh.rotation.y += 0.02;
}
Otherwise I would try simplifying the code to isolate the issue. Could be something else bothering you.

Clickable three Js Objects / Convex Items

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

detect cylinder faces in three.js

I've created a scene with textured and meshed cylinder and a grid with line and vertices of three.js. The cylinder has a spinning effect by dragging mouse left or right.
<!DOCTYPE html>
<html lang="en">
<head>
<title>3d Model using HTML5 and three.js</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="three.min.js" type="text/javascript"></script>
<script src="Stats.js" type="text/javascript"></script>
<script src="Detector.js" type="text/javascript"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, scene, renderer, light, projector;
var particleMaterial;
var cylinder, line, geometry, geometry1;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var objects = [];
var radious = 1600, theta = 45, onMouseDownTheta = 45, phi = 60, onMouseDownPhi = 60, isShiftDown = false;
init();
animate();
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 = 'Drag to spin the cylinder<br/>Objective: By spining left, cylinder should go into the surface and by spining right it should come out.';
container.appendChild( info );
// camera
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.y = 200;
camera.position.z = 800;
// scene
scene = new THREE.Scene();
// light
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 0 );
scene.add( light );
// texture
var materials = [];
for ( var i = 0; i < 6; i ++ ) {
materials.push( new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } ) );
}//alert(materials.length);
// Grid
geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );
geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );
for ( var i = 0; i <= 20; i ++ ) {
line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
line.position.z = ( i * 50 ) - 500;
scene.add( line );
line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
line.position.x = ( i * 50 ) - 500;
line.rotation.y = 90 * Math.PI / 180;
scene.add( line );
}
// cylinder
geometry1 = new THREE.CylinderGeometry(100, 100, 300, 16, 4, false);
cylinder = new THREE.Mesh(geometry1 ,new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));
//cylinder.position.x = 100;
cylinder.position.y = -50;
//cylinder.overdraw = true;
scene.add(cylinder);
alert(geometry1.faces.length);
objects.push(cylinder);
// projector
projector = new THREE.Projector();
// renderer
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.left = window.innerWidth / - 2;
camera.right = window.innerWidth / 2;
camera.top = window.innerHeight / 2;
camera.bottom = window.innerHeight / - 2;
camera.aspect = window.innerWidth / window.innerHeight;
//camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut, false );
mouseXOnMouseDown = event.clientX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOut( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentTouchStart( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
}
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
cylinder.rotation.y += ( targetRotation - cylinder.rotation.y ) * 0.05;
renderer.render( scene, camera );
}
</script>
</body>
</html>
How do I know which face of cylinder is selected by clicking on a face of it ?
You have to shoot a virtual ray from your viewpoint to the cube. You can then read out the face or faceIndex from the intersected object.
function onDocumentMouseDown( event ) {
event.preventDefault();
// position of mouse + screen calc
var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
projector.unprojectVector( vector, camera );
// create a ray from the camera thru the vector
var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
// array of intersecting object (front to back)
var intersects = ray.intersectObjects( objects );
// are we hitting something?
if ( intersects.length > 0 ) {
// first intersection should be the object (Mesh,...)
console.log(intersects[0].object);
// gimme face as THREE.Face3/4 object
console.log(intersects[0].face);
// tell me face index (int)
console.log(intersects[0].faceIndex);
// lets change color of the intersected object for fun
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
}
}
Also check out the canvas_interactive_cubes example

Categories