Clickable objects inside equirectangular map three.js - javascript

I am trying to use raycaster to make objects become clickable. I have seen countless examples of this, and I have tried this code many times with no luck. The only difference I see between my example and the rest I have come across is that I am inside of a sphere.
I start my code by creating some variables (Some may not be leftover from using past examples).
var container, stats;
var camera, controls, scene, renderer, projector;
var isUserInteracting = false;
var mouse = { x: 0, y: 0, z: 0 }, intersected;
var fov = 70,
texture_placeholder,
isUserInteracting = false,
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0;
init();
animate();
I continue by setting up my init() function where I set a camera and create my sphere.
function init() {
var container, mesh1;
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
projector = new THREE.Projector();
mesh1 = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( "spherical_map_small.jpg" )} ) );
mesh1.scale.x = -1;
mesh1.side = THREE.DoubleSide;
scene.add( mesh1 );
Still in the init() function, I then create a cube geometry (this is what I want to be clickable).
meshMaterial = new THREE.MeshBasicMaterial({ color: 0x33CC00});
var geometry = new THREE.CubeGeometry( 20, 20, 20 );
var object = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0x33CC00} ) );
object.position.x = 75;
object.position.y = 10;
object.position.z = 0;
object.rotation.y = 45;
scene.add( object );
objects.push( object );
Still in init(), I set up the renderer, and add some event listeners.
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
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 );
Now the problem. Next is the function that should make my box 'object' clickable, which does not seem to work. I believe I am telling it to say "works." every time an object in the scene is clicked.
I have read about raycasting with three.js for hours, and believe I have a decent understanding of how it should work, I just can not get it to work.
function onDocumentMouseUp( event ) {
isUserInteracting = false;
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
var vector = new THREE.Vector3( mouse.x, mouse.y, .5 );
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(vector, camera);
var intersects = raycaster.intersectObjects(scene, true);
if ( intersects.length ) {
alert('works.');
}
}
Any help would be appreciated. Thank you.

Just a thought, try using:
raycaster.intersectObjects(scene.children, true);
And have u set recursive (true) ? Otherwise it will not check the descendants

Related

Three.js r73 - rotating multiple objects back and forth as a unique object

I have a simulation of a box that unfolds each different face, each face is a different geometry with pivots on the bottom of the geometry.
When i MouseDown on a face, it's supposed to tween rotate in its x axis 90degrees. And on MouseDown again the opposite value as if the box face was closed.
The problem happens that the values rendered on the tween are not uniform.
Below is the MouseDown function:
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 ) {
controls.enabled = false;
if (SELECTED) {
if (SELECTED == intersects[ 0 ].object) {
//same selected;
new TWEEN.Tween(rotationTween).to( targetB, 500).easing(TWEEN.Easing.Cubic.InOut).onUpdate(function(){
SELECTED.rotateOnAxis( new THREE.Vector3(1,0,0), rotationTween.x );
}).start();
//TWEEN.remove(Tween);
} else {
//new selected;
SELECTED = intersects[ 0 ].object;
new TWEEN.Tween(rotationTween).to( target, 500).easing(TWEEN.Easing.Cubic.InOut).onUpdate(function(){
SELECTED.rotateOnAxis( new THREE.Vector3(1,0,0), rotationTween.x );
}).start();
//TWEEN.remove(Tween);
}
} else {
//first time selected;
SELECTED = intersects[ 0 ].object;
new TWEEN.Tween( rotationTween ).to(target , 500).easing(TWEEN.Easing.Cubic.InOut).onUpdate(function(){
SELECTED.rotateOnAxis( new THREE.Vector3(1,0,0), rotationTween.x );
}).start();
//TWEEN.remove(Tween);
}
}
}
Any other details give me a msg. Thx.
I'll try to be brief but I have to explain my situation:
The OBJECTIVE: to create a cube with individual faces that opens individually on each click.
Furthermore I got to a point where only one face is opened on click. If other opened it should close. It was a bit far from my project since when the face is "clicked" the hole scene would stay freeze, no listeners. The faces also have the same root hierarchy in the code above, wich feels wrong if you thinck in a box, where the top and bottom face would be children of the back face (in my project case).
I got really stuck when I had to rotate the faces over tweens. First problem was after the initial faces positioning THEY WILL KEEP THEY'RE ROTATION VALUES. So the left face of the box will start the render with a rotation.y = Math.PI/2, and so on. Here follows the cube creation code:
interactFace.js
interactFace = function (fText, fSize, matColor) {
//create face mesh
this.mat = new THREE.MeshPhongMaterial({color: matColor, opacity: 0.3, transparent: true, side: THREE.DoubleSide});
this.geometry = new THREE.PlaneGeometry(fSize,fSize);
this.geometry = new THREE.Geometry();
this.geometry.vertices.push(
new THREE.Vector3( fSize/2, 0, 0 ),
new THREE.Vector3( -fSize/2, 0, 0 ),
new THREE.Vector3( fSize/2, fSize, 0 ),
new THREE.Vector3( -fSize/2, fSize, 0 )
);
this.geometry.faces.push( new THREE.Face3( 0, 1, 2 ) );
this.geometry.faces.push( new THREE.Face3( 1, 2, 3 ) );
this.mesh = new THREE.Mesh(this.geometry, this.mat);
this.textGeo = new THREE.TextGeometry( fText, {
size: fSize/8,
height: 0,
curveSegments: 4,
font: "verdana",
weight: "normal",
style: "normal",
bevelThickness: 0,
bevelSize: 0,
bevelEnabled: false });
this.TextMaterial = new THREE.MeshFaceMaterial( [
new THREE.MeshPhongMaterial( { color: 0x000000, shading: THREE.FlatShading } ), // front
new THREE.MeshPhongMaterial( { color: 0x000000, shading: THREE.SmoothShading } ) // side
] );
this.textMesh = new THREE.Mesh( this.textGeo, this.TextMaterial);
this.build(fSize);
};
interactFace.prototype = {
constructor: interactFace,
build: function (fSize) {
this.mesh.castShadow = true;
this.textGeo.computeBoundingBox();
this.textGeo.computeVertexNormals();
//this.geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, 0, -fSize/2 ) );
//this.textGeo.position.set( -fSize/4, fSize/2, 0.01 );
this.textGeo.applyMatrix( new THREE.Matrix4().makeTranslation( -fSize/4, fSize/2, 0.01 ) );
this.mesh.add(this.textMesh);
}
};
and then the cube assembled with the faces. I left commented the options i tried after desperate moments. I had an early problem using rotation on objects and after accessing then by they're parents they rotate by the parents axis, giving me problems. So I switched rotation to rotateOnAxis, witch worked for this problem, but with the rotation.order switched for the top axis of the faces, this option became useless, hence no need for additional vector creation for this case:
interactCube.js
interactCube = function (fSize, objects) {
this.pivot = new THREE.Group();
var menuItems = [ 'PG 01', 'PG 02', 'PG 03', 'PG 04', 'PG 05', 'PG 06' ];
var menuItemsCoordinates = [
[ 0, 0 , 0, 0, -Math.PI/2, -Math.PI/2], // rotation.x
[ 0, Math.PI/2 , Math.PI, -Math.PI/2, Math.PI, Math.PI], // rotation.y
[ 0, 0 , 0, 0, Math.PI, 0], // rotation.z
[ 0, fSize/2 , 0, -fSize/2, 0, 0], //position.x
[ 0, 0 , 0, 0, 0, fSize], //position.y
[ fSize, fSize/2 , 0, fSize/2, 0, 0] //position.z <-- last item is top face, child of front face
];
this.build(fSize, menuItems, menuItemsCoordinates);
}
interactCube.prototype = {
constructor: interactCube,
build: function (fSize, menuItems, menuItemsCoordinates) {
for (var i = 0; i < menuItems.length; i++) {
this.face = new interactFace(menuItems[i], fSize, 0x585858);
this.face.mesh.rotation.order = 'ZYX';
//<-- ROTATION BEFORE TRANSLATION
/*
this.face.mesh.rotation.set( menuItemsCoordinates[0][i], menuItemsCoordinates[1][i], menuItemsCoordinates[2][i]);
this.face.mesh.position.set( menuItemsCoordinates[3][i], menuItemsCoordinates[4][i], menuItemsCoordinates[5][i] );
*/
var rotation = new THREE.Matrix4().makeRotationX( menuItemsCoordinates[0][i] );
this.face.mesh.applyMatrix(rotation);
var rotation = new THREE.Matrix4().makeRotationY( menuItemsCoordinates[1][i] );
this.face.mesh.applyMatrix(rotation);
var rotation = new THREE.Matrix4().makeRotationZ( menuItemsCoordinates[2][i] );
this.face.mesh.applyMatrix(rotation);
var translation = new THREE.Matrix4().makeTranslation(menuItemsCoordinates[3][i], menuItemsCoordinates[4][i], menuItemsCoordinates[5][i]);
this.face.mesh.applyMatrix(translation);
/*
this.face.mesh.rotateOnAxis( new THREE.Vector3(1,0,0), menuItemsCoordinates[0][i] );
this.face.mesh.rotateOnAxis( new THREE.Vector3(0,1,0), menuItemsCoordinates[1][i] );
this.face.mesh.rotateOnAxis( new THREE.Vector3(0,0,1), menuItemsCoordinates[2][i] );
this.face.mesh.translateOnAxis( new THREE.Vector3(1,0,0), menuItemsCoordinates[3][i] );
this.face.mesh.translateOnAxis( new THREE.Vector3(0,1,0), menuItemsCoordinates[4][i] );
this.face.mesh.translateOnAxis( new THREE.Vector3(0,0,1), menuItemsCoordinates[5][i] );
*/
/*
if( ( (i + 1) < menuItems.length ) ) {
this.pivot.add(this.face.mesh);
objects.push(this.face.mesh);
} else {
this.pivot.children[ i - 1 ].add(this.face.mesh);
objects.push(this.face.mesh);
}
*/
this.pivot.add(this.face.mesh);
objects.push(this.face.mesh);
}
}
}
Then I got to the template, the previous code of this problem, I was having issues on creating a unique value for the tween to work with all the faces. All side faces worked very well since they had they rotation.x value to 0. The top and bottom faces was giving me issues since they initial rotation.x values different from 0.
I started then to switch the tween functions to an increment of the initial value. WRONG. incrementing angle inside tween functions is a nightmare,
So I started to research about sin and cos. I got some time a go a job of a 3d menu in flash, whereas i had to map dynamic buttons in a circular position. And I remembered something about the radian values on code languages didn't work exactly as we calculate in degrees. And that I had to give fixed values to the rotation angles. Almost like incrementing and decrementing but without the errors given in the tweens.
So I managed to resolve that by creating 2 vars, one that gets the initial values of the rotation.x of the selected object, and another is this first value incremented by Math.PI/2. So on the onUpdate function I could define a dynamic fixed value, provided by a incremented argument outside the function.
template.js
var container, stats;
var controls;
var camera, scene, renderer;
var cubeMenu;
var objects = [];
var raycaster;
var mouse, INTERSECTED, SELECTED;
var opened = false;
function renderTemplate() {
init();
animate();
}
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 100;
camera.position.y = 20;
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
scene = new THREE.Scene();
createScenario(scene);
cubeMenu = new interactCube(18, objects);
scene.add( cubeMenu.pivot );
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0xf0f0f0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
container.appendChild( renderer.domElement );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'interactive faced cube menu';
container.appendChild( info );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
//
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( objects );
if ( intersects.length > 0 ) {
if ( INTERSECTED != intersects[ 0 ].object ) {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = intersects[ 0 ].object;
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
INTERSECTED.material.emissive.setHex( 0x22aa22 );
}
container.style.cursor = 'pointer';
} else {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = null;
container.style.cursor = 'auto';
}
}
function onDocumentTouchStart( event ) {
event.preventDefault();
event.clientX = event.touches[0].clientX;
event.clientY = event.touches[0].clientY;
onDocumentMouseDown( event );
}
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 );
TWEEN.removeAll();
if ( intersects.length > 0 ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mousedown', onDocumentMouseDown, false );
//controls.enabled = false;
if (SELECTED) {
if (SELECTED == intersects[ 0 ].object) {
if (opened == true) {
//same selected;
var angleSelectedInit = { x: SELECTED.rotation.x };
var angleSelectedEnd = { x: SELECTED.rotation.x - Math.PI/2 };
new TWEEN.Tween( angleSelectedInit ).to( angleSelectedEnd , 500).easing(TWEEN.Easing.Cubic.InOut).onUpdate(function(){
SELECTED.rotation.x = angleSelectedInit.x ;
opened = false;
}).onComplete(function(){
addListeners();
SELECTED = 0; // so the new selected condition wont rotate the closed selected face
}).start();
}
if (opened == false) {
//same selected;
var angleSelectedInit = { x: SELECTED.rotation.x };
var angleSelectedEnd = { x: SELECTED.rotation.x + Math.PI/2 };
new TWEEN.Tween( angleSelectedInit ).to( angleSelectedEnd , 500).easing(TWEEN.Easing.Cubic.InOut).onUpdate(function(){
//alert(SELECTED.rotation.x);
SELECTED.rotation.x = angleSelectedInit.x ;
opened = true;
}).onComplete(function(){
addListeners();
}).start();
}
} else {
if (SELECTED !== 0) {
var angleSelectedInit = { x: SELECTED.rotation.x };
var angleSelectedEnd = { x: SELECTED.rotation.x - Math.PI/2 };
new TWEEN.Tween( angleSelectedInit ).to( angleSelectedEnd , 500).easing(TWEEN.Easing.Cubic.InOut).onUpdate(function(){
//alert(SELECTED.rotation.x);
SELECTED.rotation.x = angleSelectedInit.x ;
}).onComplete(function(){
}).start();
}
//new selected;
//INTERSECTED VAR IS USED ON MOUSEMOVE EVENT = intersects[ 0 ].object;
var angleSelectedInitNew = { x: intersects[ 0 ].object.rotation.x };
var angleSelectedEndNew = { x: intersects[ 0 ].object.rotation.x + Math.PI/2 };
new TWEEN.Tween( angleSelectedInitNew ).to( angleSelectedEndNew , 500).easing(TWEEN.Easing.Cubic.InOut).onUpdate(function(){
//alert(SELECTED.rotation.x);
intersects[ 0 ].object.rotation.x = angleSelectedInitNew.x ;
}).onComplete(function(){
SELECTED = intersects[ 0 ].object;
addListeners();
}).start();
}
} else {
//first time selected;
SELECTED = intersects[ 0 ].object;
var angleSelectedInit = { x: SELECTED.rotation.x };
var angleSelectedEnd = { x: SELECTED.rotation.x + Math.PI/2 };
new TWEEN.Tween( angleSelectedInit ).to( angleSelectedEnd , 500).easing(TWEEN.Easing.Cubic.InOut).onUpdate(function(){
//alert(SELECTED.rotation.x);
SELECTED.rotation.x = angleSelectedInit.x ;
opened = true;
}).onComplete(function(){
addListeners();
}).start();
}
}
}
function onDocumentMouseUp( event) {
}
function addListeners() {
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
TWEEN.update();
controls.update();
}
function render() {
//cubeMenu.pivot.rotation.y += 0.02;
renderer.render( scene, camera );
}
I keep the scenario on a separated file:
scenario.js
function createScenario(scene) {
container = document.createElement( 'div' );
document.body.appendChild( container );
scene.add( new THREE.AmbientLight( 0x505050 ) );
var light = new THREE.SpotLight( 0xffffff, 1.5 );
light.position.set( 0, 500, 2000 );
light.castShadow = true;
light.shadowCameraNear = 200;
light.shadowCameraFar = camera.far;
light.shadowCameraFov = 50;
light.shadowBias = -0.00022;
light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;
scene.add( light );
}
Bottom line, don't increment a value inside a tween.
I hope this code help someone in this community. Since most answers to build this code came from here.
Improvements are most welcome!
Thx.

Problems making a tween on Three.js

I am making my first steps learning JavaScript and playing with Three.js.
I made a reflection cube with a tween animation and i would like to make this tween runs everytime that I reload my site without clicking.
I have two days trying to make it and cant. Can you tell me which is the problem with my code please? I tryied to verify it in the JavaScript console in Chrome and it didnt say anything. If you can help would be amazing because i am doing my best and it's something really hard.
Here is my code with some comments i made:
<script>
// set up the first variables scene, the camera, etc, etc
var container;
var camera, scene, renderer;
var raycaster;
var mouse;
init();
animate();
function init() {
// My scene is a div inside the html
container = document.createElement( 'div' );
document.body.appendChild( container );
//Set up the camera and make an scene
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.target = new THREE.Vector3( 0, 50, 0 );
camera.position.y = 300;
camera.position.z = 500;
scene = new THREE.Scene();
//environment map
var imgAr = [
'sources/cube_sides/0.jpg',
'sources/cube_sides/02.jpg',
'sources/cube_sides/03.jpg',
'sources/cube_sides/04.jpg',
'sources/cube_sides/05.jpg',
'sources/cube_sides/06.jpg',
'sources/cube_sides/07.jpg',
'sources/cube_sides/08.jpg',
'sources/cube_sides/09.jpg',
'sources/cube_sides/010.jpg',
'sources/cube_sides/011.jpg',
'sources/cube_sides/012.jpg',
'sources/cube_sides/013.jpg',
'sources/cube_sides/014.jpg',
'sources/cube_sides/015.jpg',
'sources/cube_sides/016.jpg',
'sources/cube_sides/017.jpg',
'sources/cube_sides/018.jpg'
];
var urls = imgAr.sort(function(){return .6 - Math.random()}).slice(0,6);
var reflectionCube = THREE.ImageUtils.loadTextureCube( urls, THREE.CubeReflectionMapping );
//load the model
var loader = new THREE.BinaryLoader();
loader.load( "sources/obj/mmlogo/mm_logo.js", function ( geometry ) {
var material = new THREE.MeshPhongMaterial( {
color: 0x515151,
morphTargets: true,
overdraw: 0.5,
envMap: reflectionCube,
combine: THREE.AddOperation,
reflectivity: 1,
shininess: 0,
side: THREE.DoubleSide,
} );
//assign a mesh to the geometry
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set( 120, 120, 120 );
mesh.position.y = 50;
mesh.position.x = 0;
mesh.position.z = 700;
mesh.rotation.y = 10;
mesh.rotation.x = 10;
scene.add( mesh );
//mixer = new THREE.AnimationMixer( mesh );
//var clip = THREE.AnimationClip.CreateFromMorphTargetSequence( 'gallop', geometry.morphTargets, 30 );
//mixer.addAction( new THREE.AnimationAction( clip ).warpToDuration( 1 ) );
} );
//set up the Raycaster
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
//set up the renderer
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild(renderer.domElement);
document.addEventListener( 'load', onDocumentLoad, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentLoad( event ) {
event.preventDefault();
var intersects = raycaster.intersectObjects( scene.children );
new TWEEN.Tween( intersects[ 0 ].object.position ).to( {
x: 0,
y: 50,
z: 70 }, 20000 )
.easing( TWEEN.Easing.Sinusoidal.In).start();
new TWEEN.Tween( intersects[ 0 ].object.rotation ).to( {
x: 0,
y: 0,
z: 0 }, 20000 )
.easing( TWEEN.Easing.Sinusoidal.In).start();
}
function animate() {
requestAnimationFrame( animate );
render();
}
var radius = 600;
var theta = 0;
function render() {
TWEEN.update();
theta += 0;
camera.position.y = radius * Math.sin( THREE.Math.degToRad( theta ) );
camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) );
camera.lookAt( camera.target );
renderer.render( scene, camera );
}
</script>

Var undefined when I use a loader in three.js

//Script loader
<script src="js/jquery.min.js"></script>
<script src="js/three.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/ColladaLoader.js" type="text/javascript"></script>
<script>
var loader = new THREE.ColladaLoader();
loader.load( 'texture/bigcube_hetre.dae', function ( collada ) {
window.cubeBigHetre = collada.scene;
var skin = collada.skins[ 0 ];
cubeBigHetre.position.set(0, 0, 0);
cubeBigHetre.scale.set(1, 1, 1);
});
var container;
var camera, scene, renderer;
var plane, cube;
var cubeExport;
init();
render();
function init() {
container = document.createElement( 'div' );
container.setAttribute("id", "container");
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0xf0f0f0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 0, 0, 2000 );
camera.lookAt( new THREE.Vector3() );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.damping = 0.2;
controls.addEventListener( 'change', render );
scene = new THREE.Scene();
// grid
var size = 500, step = 50;
var geometry = new THREE.Geometry();
for ( var i = - size; i <= size; i += step ) {
geometry.vertices.push( new THREE.Vector3( - size, i, 0 ) );
geometry.vertices.push( new THREE.Vector3( size, i, 0 ) );
geometry.vertices.push( new THREE.Vector3( i, - size, 0 ) );
geometry.vertices.push( new THREE.Vector3( i, size, 0 ) );
}
var material = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2, transparent: true } );
var line = new THREE.Line( geometry, material, THREE.LinePieces );
scene.add( line );
//
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
var geometry = new THREE.PlaneBufferGeometry( 1000, 1000 );
plane = new THREE.Mesh( geometry );
plane.visible = false;
scene.add( plane );
// Lights
var ambientLight = new THREE.AmbientLight( 0x606060 );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 1, 0.75, 0.5 ).normalize();
scene.add( directionalLight );
alert(cubeBigHetre);//Uncaught ReferenceError: cubeBigBrun is not defined
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function render() {
renderer.render( scene, camera );
}
</script>
Here is the code, and the problem comes from alert(cubeBigHetre);
It's working in Firefox and Internet Explorer but not with others. The error is : Uncaught ReferenceError: cubeBigBrun is not defined but not in firefox !
Cordialy Alexander
There is a race in your code:
loader.load(..., function)
will call the function when the resource becomes available. So when you call your init() function, the resource may be loaded, the loader callback called and your variable initialized, or the resource may be still downloading, the callback not yet called and your variable still not initialized. This code works by chance in IE and Firefox. Probably you are testing locally and/or experiencing minor differences in Javascript engines across the browsers.
You should move code that depends on the resource to be loaded from the init() function to the loader callback.
Thank you, I think you are true but i can't move it in the loader so I should add a setTimeout().

Cannot read property 'uniform' of undef when rendering mesh with multiple materials

I have exported a 3d model from blender to a three.js file. It has 2 materials applied to different portions of it. It has a lot of vertices and uv coords so i wont post the code here. I can see that it indeed has 2 materials though, so im pretty sure my error is in my three.js code. It does have 0 bones, morph targets, and colors though. I dont know if those are important for my application or not, so my error might be there.
Here is what I have so far:
var camera, scene1, scene2, raycaster, renderer, staticMesh , loader;
var highlighted, standard;
var mouse = new THREE.Vector2(), INTERSECTED;
init();
animate();
function init() {
standard = new THREE.MeshLambertMaterial( { color: 0x9999ff } );
highlighted = new THREE.MeshLambertMaterial( { color: 0xff0000 } )
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 15;
scene1 = new THREE.Scene();
scene2 = new THREE.Scene();
loader = new THREE.JSONLoader();
loader.load( "abs.json", function( geometry ) {
var mesh = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0x9999ff } ) );
//mesh.scale.set( 10, 10, 10 );
mesh.position.y = -6;
mesh.position.x = 0;
scene2.add( mesh );
} );
loader.load( "bodyTest.json", function(geometry, material) {
material[0] = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0x9999ff } ) );
material[1] = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0x9999ff } ) );
var materials = new THREE.MeshFaceMaterial(material);
staticMesh = new THREE.Mesh( geometry, materials );
scene1.add( staticMesh );
} );
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(-1, -1, -1).normalize();
scene1.add(directionalLight);
directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene1.add(directionalLight);
directionalLight = new THREE.DirectionalLight(0xffffff, .5);
directionalLight.position.set(1, 0, 0).normalize();
scene1.add(directionalLight);
directionalLight = new THREE.DirectionalLight(0xffffff, .5);
directionalLight.position.set(-1, 0, 0).normalize();
scene1.add(directionalLight);
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer({ antialiasing: true});
renderer.setClearColor( 0xffffff );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
document.body.appendChild( renderer.domElement );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function animate() {
requestAnimationFrame( animate );
scene1.rotation.y += 0.007;
scene2.rotation.y += 0.007;
/*
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 ).unproject( camera );
raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
var intersects = raycaster.intersectObjects( scene2.children );
if ( intersects.length > 0 ) {
if ( INTERSECTED != intersects[ 0 ].object ) {
if(staticMesh) staticMesh.material.materials[1] = staticMesh.currentMat;
INTERSECTED = intersects[ 0 ].object;
staticMesh.currentMat = staticMesh.material.materials[1]
staticMesh.material.materials[1] = highlighted;
}
} else {
if(staticMesh) staticMesh.material.materials[1] = staticMesh.currentMat;
INTERSECTED = null;
}
*/
renderer.render( scene2, camera );
renderer.render( scene1, camera );
}
As you can see I already commented out portions that I thought the error might be coming from. I have also tried running it with renderer.render( scene1, camera ); commented out and it had no errors.
I don't fully understand how this fixed it, but I found this in a different example and it ended up working. standard is a lambert material i have defined prior.
loader.load( "bodyTest.json", function(geometry) {
var material = [];
material.push( standard );
material.push( standard );
var materials = new THREE.MeshFaceMaterial(material);
staticMesh = new THREE.Mesh( geometry, materials );
scene1.add( staticMesh );
} );
I'd still appreciate an explanation if someone knows what my problem was.

JavaScript interactive 3D Object

I am Trying to create an interactive Sphere with JavaScript for an assignment for HCI, the problem is that I am a novice to JavaScript and Three.js.
what I am after is to make it so when the sphere is clicked on that it displays the statistics of a specific subject. I have created the sphere and made it into an object but I am having trouble with the interaction of the sphere. I don't care if a div or a alert opens when the sphere is clicked on but I just need it to work as a dummy version
below is an example in JavaScript and THREE.js:
var sphere = new Object({}); //declared sphere as an object first.
var angularSpeed = 0.2;
var lastTime = 0;
function animate (){
//update
var time = (new Date()).getTime();
var timeDiff = time - lastTime;
var angleChange = angularSpeed * timeDiff * 0.1 * Math.PI / 1000;
sphere.rotation.y -= angleChange;
sphere2.rotation.sphere -=angleChange;
lastTime = time;
// render
renderer.render(scene, camera);
requestAnimationFrame(function(){ //request new frame
animate();
});
}
// renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// camera
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 500;
// scene
var scene = new THREE.Scene();
//material
var material = new THREE.MeshLambertMaterial({
map:THREE.ImageUtils.loadTexture('images/earth2.jpg')});
//sphere geometry
sphere = new THREE.Mesh(new THREE.SphereGeometry( 100, 50, 50 ), material);
sphere.overdraw = true;
sphere.rotation.x = Math.PI * 0.1;
sphere.position.x= 0; // moves position horizontally (abscissa) + = right and - = left
sphere.position.y= 0; // moves position virtually (ordinate) + = right and - = left
sphere.position.z= 0; // moves position z (applicate) + = forwards and - = backwards
scene.add(sphere);
//animate
animate();
var sphere = new Object:({event});
function statistics(){
alert('You clicked on the div!') // displays the statistics before the rendering
};
sphere.onMouseDown=statistics(event);
.onMouseDown is only available for HTML element. You can't use this function for THREE.js objects, but Raycaster is exactly what you want!
jsfiddle
var container, stats;
var camera, scene, projector, raycaster, renderer, selected, sphere;
var mouse = new THREE.Vector2(), INTERSECTED;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
scene = new THREE.Scene();
var light = new THREE.DirectionalLight( 0xffffff, 2 );
light.position.set( 1, 1, 1 ).normalize();
scene.add( light );
var light = new THREE.DirectionalLight( 0xffffff );
light.position.set( -1, -1, -1 ).normalize();
scene.add( light );
sphere = new THREE.Mesh(new THREE.SphereGeometry( 20, 50, 50 ), new THREE.MeshNormalMaterial());
sphere.overdraw = true;
scene.add(sphere);
projector = new THREE.Projector();
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0xf0f0f0 );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
renderer.domElement.addEventListener( 'mousedown', onCanvasMouseDown, false);
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.lookAt(new THREE.Vector3(0,0,0));
camera.position = new THREE.Vector3(0,100,100);
// find intersections
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, camera );
raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
selected = raycaster.intersectObjects( scene.children );
renderer.render( scene, camera );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
//detect mouse click on the sphere
function onCanvasMouseDown( event ){
if(selected[0].object==sphere){
statistics();
}
}
function statistics(){
alert('You clicked on the div!') // displays the statistics before the rendering
};

Categories