Three.js shatter/explode plane geometry - javascript

I'm trying to create a glass shattering effect in Three.js with Tween and plane geometry but am a bit lost. The mesh/geometry is not updating with the tween, if I call shatter() before the first render you can see that the tween is working, but only for one pass. After a render the mesh/geometry stops updating.
Code so far is as follows,
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; } canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/three.min.js"></script>
<script src="js/ExplodeModifier.js"></script>
<script src="js/tween.min.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.PlaneGeometry(5, 5, 8,8); // create plane
var material = new THREE.MeshBasicMaterial( { color: 0xB20000, wireframe: true});
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
camera.position.z = 5;
function shatter()
{
TWEEN.removeAll();
var explodeModifier = new THREE.ExplodeModifier();
explodeModifier.modify( geometry );
var verticeA = 0;
var verticeB = 1;
var verticeC = 2;
var test = geometry.vertices.length;
geometry.vertices[verticeA].translateX(1);
for(var i = 0; i < (geometry.vertices.length / 256); i++)
{
TWEEN.removeAll();
var pos = new THREE.Vector3();
var final = Math.random();
pos.x = final;
pos.y = final;
pos.z = final;
new TWEEN.Tween(geometry.vertices[verticeA])
.to( { x: pos.x, y: pos.y, z: pos.z }, 2000 )
.easing( TWEEN.Easing.Exponential.InOut )
//.onUpdate( function() { })
.start();
new TWEEN.Tween(geometry.vertices[verticeB])
.to( { x: pos.x, y: pos.y, z: pos.z }, 2000 )
.easing( TWEEN.Easing.Exponential.InOut )
.start();
new TWEEN.Tween(geometry.vertices[verticeC])
.to( { x: pos.x, y: pos.y, z: pos.z }, 2000 )
.easing( TWEEN.Easing.Exponential.InOut )
.start();
verticeA += 3;
verticeB += 3;
verticeC += 3;
}
};
var render = function () {
TWEEN.update();
requestAnimationFrame( render );
renderer.render(scene, camera);
};
render();
shatter();
</script>
</body>
</html>

If you change vertices coordinates, you need to flag this by setting geometry.verticesNeedUpdate=true.
Because you're animating, you need to set this to true after every tween update, either in the update or render callback.

Related

How to animate a glb with GTLF loader in THREE.js

<!DOCTYPE html>
<html>
<head>
<title>____________glTF2_Loader_________</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="three.js"></script>
<script src="GLTFLoader.js"></script>
<script src="OrbitControls.js"></script>
<script>
// Load 3D Scene
var scene = new THREE.Scene();
// Load Camera Perspektive
var camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.set( 1, 1, 20 );
// Load a Renderer
var renderer = new THREE.WebGLRenderer({ alpha: false });
renderer.setClearColor( 0xC5C5C3 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls( camera, renderer.domElement );
//load in camera controls
controls.update();
// Load the Orbitcontroller
// Load Light
var ambientLight = new THREE.AmbientLight( 0xcccccc, 2);
// NOTE: More ambience gives an etherial look. :O
scene.add( ambientLight );
var PointLight = new THREE.PointLight( 0xffffff, 3, 100, 2 );
//color (white), intensity (3 times)
PointLight.position.set( 4, -4, 1 ).normalize();
scene.add( PointLight );
// _____ TODO!!!: FADE INTO SCENE. ___________
// glTf 2.0 Loader
var mixer;
var clock = new THREE.Clock();
var loader = new THREE.GLTFLoader();
let obj;
loader.load( './models/ZOMBIIIL12.glb', function ( gltf ) {
// <<--------- Model Path
mixer = new THREE.AnimationMixer(gltf.scene);
obj = gltf.scene;
var action = mixer.clipAction( gltf.animations[ 0 ] );
console.log( action );
gltf.scene.scale.set( .5, .5, .5 );
gltf.scene.position.x = 0; //Position (x = right+ left-)
gltf.scene.position.y = -5; //Position (y = up+, down-)
gltf.scene.position.Z = 5; //Position (z = front +, back-)
gltf.scene.rotation.y = 90; //rotating on the y axis, + is towards the right, - is towards the left.
obj.rotation.y = camera.rotation.y;
var URll = './texture maps/Material Base Color.png';
var textT = THREE.ImageUtils.loadTexture( URll );
var materiall = new THREE.MeshPhongMaterial({
map : textT,
})
gltf.texture = materiall;
scene.add( gltf.scene );
action.play();
});
function animate() {
renderer.render(scene, camera);
requestAnimationFrame( animate );
}
function render() {
renderer.render( scene, camera );
}
var geometry2 = new THREE.PlaneGeometry( 30, 20, 32 );
var url = './texture maps/GREEN LEAVES.png';
var texture = THREE.ImageUtils.loadTexture( url );
var material2 = new THREE.MeshPhongMaterial({
map : texture,
})
var plane = new THREE.Mesh( geometry2, material2 );
plane.position.z = -1;
scene.add( plane );
/*
var xSpeed = .1;
var zSpeed = .1;
document.addEventListener("keydown", onDocumentKeyDown, false);
//while the document is active, listen for this event called keydown, and run function onDocumentKeyPress
x1 = 0;
function onDocumentKeyDown(event) {
var keyCode = event.which;
if (keyCode == 87) {
//obj.rotation.y += .05;
//rotates the model so that you change where it is facing.
obj.translateZ( .5 );
// camera.rotation.y = obj.rotation.y;
camera.translateZ( .5 );
camera.position.y = obj.position.y - 1.9;
// camera.position.y = obj.position.y - 1.9;
//++++++++++++++++++ WWWWWW KEYYYYYYYY (forward)
} else if (keyCode == 83) {
obj.translateZ( -0.5 );
camera.translateZ( -0.5 );
camera.position.y = obj.position.y - 1.9;
console.log(obj.position.y)
//camera.position.set(obj.position.x, camera.position.y, camera.position.z);
//updates z position by the amount of speed.
// obj.rotation.y = 90;
// camera.rotation = 90;
//camera.translateZ( .1 );
//++++++++++++++++++ SSSSSSS KEYYYYYYYY (back)
} else if (keyCode == 65) {
//obj.rotation.y += 90;
obj.translateX( -.5 );
camera.translateX( -.5 );
camera.position.z = obj.position.z + 20;
//++++++++++++++++++ AAAAAAA KEYYYYYYYY (left)
/// If camera rotation on the y is less than or greater than a certain value, then rotate it on the mouse movement, otherwise, nothing.
} else if (keyCode == 68) {
obj.translateX(.5);
camera.translateX(.5);
camera.position.z = obj.position.z + 20;
//++++++++++++++++++ DDDDDD KEYYYYYYYY (rigtht)
} else if (keyCode == 32) {
obj.position.set(0, 0, 0);
// console.log(obj.position.x);
//space bar
}
//camera.rotation.x += 0.05
};
*/
render();
animate();
</script>
</body>
</html>
above code works to load in the model, however, it does not play the animation when called. I get no errors but it still does not work. The console even logs the action animation that is loaded from the glb model showing that it is there. i tried acting as though it is a json, and using json loader animator functions. I tried using clipaction functions, but they only gave me errors saying that they were either undefined, or just would say that there was an error.
You have to update your animation mixer in your animation loop like so:
var delta = clock.getDelta();
if ( mixer ) mixer.update( delta );
Notice that clock is an instance of THREE.Clock. Create it similar to your camera and scene at the top of your file.
three.js R112

Make css3d rendering plane to be act as a floor in 3JS?

My requirement is to make a css3d rendering plane to be act as a floor. And a 3d cube should be on top of the plane. Following I have attached the code which I tried.Both plane and the cube shares the same scene and camera.But renders are different. But I couldn't place the 3d cube on top of the plane and rotation of the plane and cube are different.
<!DOCTYPE html>
<html lang="en">
<head>
<title>3JS CODE</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="js/three.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script src="js/renderers/CSS3DRenderer.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
var HtmlElement = function ( id, x, y, z, rx ) {
var div = document.createElement( 'div' );
div.innerHTML = "Hello";
div.id = id; //'googleMap';
div.style.width = '1200px';
div.style.height = '950px';
div.style.backgroundColor = 'blue';
var object = new THREE.CSS3DObject( div );
object.position.set( x, y, z );
object.rotation.x = rx;
return object;
};
</script>
<script>
var container, stats;
var camera, controls, mapScene, group, renderer1,renderer2;
var objects = [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 5000 );
camera.position.z = 1000;
camera.position.set(0.18348775328760136, -334.5971567493426, 800.8398185862801);
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 3.0;
controls.zoomSpeed = 2.2;
controls.panSpeed = 2.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 1.3;
mapScene = new THREE.Scene();
// scene.background = new THREE.Color( 0xf0f0f0 );
group = new THREE.Group();
var mapObject = new HtmlElement( 'googleMap', 0, 0, 240, 270 );
group.add( mapObject );
///////////////
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
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.x = 0;
cube.position.y = -300;
cube.position.z = 500;
group.add( cube );
mapScene.add( group );
// renderer
renderer1 = new THREE.CSS3DRenderer();
renderer1.setSize( window.innerWidth, window.innerHeight );
renderer1.domElement.style.position = 'absolute';
renderer1.domElement.style.top = 0;
container.appendChild( renderer1.domElement );
renderer2 = new THREE.WebGLRenderer( { antialias: true } );
renderer2.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer2.domElement );
stats = new Stats();
container.appendChild( stats.dom );
window.addEventListener( 'resize', onWindowResize, false );
render();
// initMap();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer1.setSize( window.innerWidth, window.innerHeight );
renderer2.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
controls.update();
renderer1.render( mapScene, camera );
renderer2.render( mapScene, camera );
}
</script>
</body>
</html>
here's the output
THREE.CSS3DObject does not care about the depth buffer of the WebGLRenderingContext. It has no clue about the depth buffer or even depth test. The order of CSS objects can be defined by the z-index.
You try to mix two completely different technologies, which won't interact together in that way.
But you can still make it work.
For this you have to define the z-index of the CSS3DRenderer element lower then the z-index of the WebGLRenderer element so that the WebGLRenderer draws "in front of" the CSS3DRenderer. Further transparency has to be enabled for the WebGLRenderer:
renderer1 = new THREE.CSS3DRenderer();
renderer1.setSize( window.innerWidth, window.innerHeight );
renderer1.domElement.style.position = 'absolute';
renderer1.domElement.style.zIndex = 0;
renderer1.domElement.style.top = 0;
container.appendChild( renderer1.domElement );
renderer2 = new THREE.WebGLRenderer( { antialias: true, alpha:true } );
renderer2.setSize( window.innerWidth, window.innerHeight );
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.zIndex = 1;
renderer2.domElement.style.top = 0;
container.appendChild( renderer2.domElement );
Then you have to ensure that the WebGLRenderer takes care of the CSS3DObject. Technically this can't be done. But you can trick the system.
You can render a completely transparent plane, with equal size an at equal position, as the CSS3DObject in the WebGLRenderer:
var HtmlElement = function ( id, x, y, z, w, h ) {
var div = document.createElement( 'div' );
div.innerHTML = "Hello";
div.id = id; //'googleMap';
div.style.width = w + 'px';
div.style.height = h + 'px';
div.style.backgroundColor = 'blue';
var object = new THREE.CSS3DObject( div );
object.position.set( x, y, z );
return object;
};
var WebGlObject = function ( x, y, z, w, h ) {
var material = new THREE.MeshBasicMaterial({
color: 0x0000000,
opacity: 0.0,
side: THREE.DoubleSide
});
var geometry = new THREE.PlaneGeometry(w, h);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = x;
mesh.position.y = y;
mesh.position.z = z;
return mesh;
};
var mapObject = HtmlElement('googleMap', 0, 0, 0, 800, 800);
var planeMesh = WebGlObject( 0, 0, 0, 800, 800);
See the example, which is based on the code of your question:
var HtmlElement = function ( id, x, y, z, w, h ) {
var div = document.createElement( 'div' );
//div.innerHTML = "Hello";
div.id = id; //'googleMap';
div.style.width = w + 'px';
div.style.height = h + 'px';
div.style.backgroundColor = 'lightblue';
div.style.color = "red";
div.style.fontSize="200px";
div.style.textAlign="center";
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "https://www.google.com/maps/embed");
iframe.style.width = w + "px";
iframe.style.height = h + "px";
div.appendChild(iframe);
var object = new THREE.CSS3DObject( div );
object.position.set( x, y, z );
return object;
};
var WebGlObject = function ( x, y, z, w, h ) {
var material = new THREE.MeshBasicMaterial({
color: 0x0000000,
opacity: 0.0,
side: THREE.DoubleSide
});
var geometry = new THREE.PlaneGeometry(w, h);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = x;
mesh.position.y = y;
mesh.position.z = z;
return mesh;
};
var container, stats;
var camera, controls, mapScene, group, renderer1,renderer2;
var objects = [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 5000 );
camera.position.set(-600, 300, 700);
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 3.0;
controls.zoomSpeed = 2.2;
controls.panSpeed = 2.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 1.3;
mapScene = new THREE.Scene();
// scene.background = new THREE.Color( 0xf0f0f0 );
group = new THREE.Group();
group.renderOrder=1;
var mapObject = HtmlElement( 'googleMap', 0, 0, 0, 800, 800 );
var planeMesh = WebGlObject(0, 0, 0, 800, 800);
group.add( mapObject );
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
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.x = 0;
cube.position.y = 0;
cube.position.z = 102;
group.add( cube );
group.add( planeMesh );
mapScene.add( group );
// renderer
renderer1 = new THREE.CSS3DRenderer();
renderer1.setSize( window.innerWidth, window.innerHeight );
renderer1.domElement.style.position = 'absolute';
renderer1.domElement.style.zIndex = 0;
renderer1.domElement.style.top = 0;
container.appendChild( renderer1.domElement );
renderer2 = new THREE.WebGLRenderer( { antialias: true, alpha:true } );
renderer2.setSize( window.innerWidth, window.innerHeight );
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.zIndex = 1;
renderer2.domElement.style.top = 0;
container.appendChild( renderer2.domElement );
window.addEventListener( 'resize', onWindowResize, false );
render();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer1.setSize( window.innerWidth, window.innerHeight );
renderer2.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
controls.update();
renderer2.render( mapScene, camera );
renderer1.render( mapScene, camera );
}
<script src="https://threejs.org/build/three.min.js"></script>
<!--script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script-->
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="https://threejs.org/examples/js/renderers/CSS3DRenderer.js"></script>

Disappearing line object in Three.js

I have a strange problem, which can be a three.js bug, but it also can be my curve hands.
I have a scene with some meshes (in example below I used several transparent cubes and small spheres) and one line object (can be Line or LineSegments - doesn't matter) based on buffer geometry. While I rotating the camera line object sometimes disappears form view like it's covered by another object. It seems it also disappears if I cannot see the start point (if rotate camera to a degree where start point is offscreen, even without additional meshes) of the line while 90% of the line object should be in view.
The question is: Why does the line disappear and how should I prevent such its behavior?
This is how it looks on screencast:
http://screencast.com/t/HLC99OMmDdK
And this is an example of the problem:
http://jsfiddle.net/exiara/sa4bxhc3/
You should be able to see how line disappears when camera rotates.
The code of jsfiddle example:
var camera, controls, scene, renderer, dummy, projector,
stats, fps = 30, fpsTimeout = 1000 / fps,
linesGeometry,globalLine;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setClearColor(0xFFFFeF, 1);
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xFFFFeF, 100, 2500 );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 50000 );
camera.position.set(-450, 300, 650);
camera.target = new THREE.Vector3(0,0,0);
controls = new THREE.OrbitControls( camera );
controls.addEventListener('change', render );
// ------------ MAIN PART START ------------ //
var lines = 1000;
linesGeometry = new THREE.BufferGeometry();
var positions = new Float32Array( lines * 6 );
for ( var i = 0, j, ll = lines; i < ll; i++ ) {
j=i*6;
positions[j] = Math.random()*100;
positions[j+1] = Math.random()*100;
positions[j+2] = Math.random()*100;
positions[j+3] = Math.random()*100;
positions[j+4] = Math.random()*100;
positions[j+5] = Math.random()*100;
}
linesGeometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
globalLine = new THREE.Line( linesGeometry, new THREE.LineBasicMaterial({
color: 0x000000,
transparent: true,
opacity: 0.8
} ));
scene.add( globalLine );
// ------------ MAIN PART END ------------ //
// add cubes
var step = 400;
var gridSize = 4;
var offset = step*gridSize/2;
var cubeGeometry = new THREE.BoxGeometry(step, step, step);
var cubeMaterial = new THREE.MeshBasicMaterial({ color:0xFF0000, ambient: 0xCCCCCC, transparent: true, opacity: 0 });
var testCube, edge;
for (var x = -offset; x <= offset; x+=step) {
for (var y = -offset; y <= offset; y+=step) {
for (var z = -offset; z <= offset; z+=step) {
testCube = new THREE.Mesh(cubeGeometry,cubeMaterial);
testCube.position.set(x, y, z);
edge = new THREE.EdgesHelper( testCube, 0x000000 );
scene.add(testCube);
scene.add(edge);
}
}
}
// spheres
var sphereGeometry = new THREE.SphereGeometry( 10,32,16),
sphere;
var spheres = [
[0xff0000, 0, 0, 0 ], // red
[0x0000ff, 200, 0, 0 ], // blue
[0x00FF00, -200, 0, 0 ], // green
[0xFF00ff, 0, 200, 0 ], // magenta
[0x00ffff, 0, -200, 0 ], // aqua
[0xFFff00, 0, 0, 200 ], // lime
[0x000000, 0, 0, -200] // black
];
for (var i = 0, sl = spheres.length; i <sl; i++) {
sphere = new THREE.Mesh(sphereGeometry, new THREE.MeshBasicMaterial({color: spheres[i][0]}));
sphere.position.set(spheres[i][1], spheres[i][2], spheres[i][3]);
scene.add(sphere);
}
/* Stats */
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );
/* window observers */
window.addEventListener( 'resize', onWindowResize, false );
window.addEventListener( 'load', render, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function degInRad(deg) {
return deg * Math.PI / 180;
}
function animate()
{
setTimeout(function() {
requestAnimationFrame(animate);
}, fpsTimeout );
render();
}
function render() {
camera.lookAt(camera.target);
renderer.render( scene, camera );
stats.update();
}
The problem is that you are drawing multiple levels of opacity on top of each other and webgl needs to sort them. So the short answer is to add depthTest: false to your cube material.
var cubeMaterial = new THREE.MeshBasicMaterial({ color:0xFF0000, ambient: 0xCCCCCC, transparent: true, opacity: 0, depthTest: false });
But I would like to mention that what you are doing is inefficient. You should not be drawing a grid that way. Use lines instead.

Using three.js and tween.js to rotate object in 90 degree increments to create a 360 loop

I have a working animation, just not the way I would like.
I would like the object to rotate 90 degrees with a delay (works) then continue to rotate 90 degrees, ultimately looping forever. No matter what I do, it always resets. Even if I set up 4 tweens taking me to 360, the last tween that resets back zero makes the whole object spin in the opposite direction.
Thanks
var width = 1000;
var height = 600;
var scene = new THREE.Scene();
var group = new THREE.Object3D(); //create an empty container
var camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, -500, 1000);
camera.position.x = 180;
camera.position.y = 180;
camera.position.z = 200;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.setClearColor(0xf0f0f0);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry(300, 300, 300);
var material = new THREE.MeshLambertMaterial({
color: 0xffffff,
shading: THREE.SmoothShading,
overdraw: 0.5
});
var cube = new THREE.Mesh(geometry, material);
group.add(cube);
var canvas1 = document.createElement('canvas');
canvas1.width = 1000;
canvas1.height = 1000;
var context1 = canvas1.getContext('2d');
context1.font = "Bold 20px Helvetica";
context1.fillStyle = "rgba(0,0,0,0.95)";
context1.fillText('Text bit', 500, 500);
// canvas contents will be used for a texture
var texture1 = new THREE.Texture(canvas1)
texture1.needsUpdate = true;
var material1 = new THREE.MeshBasicMaterial({
map: texture1,
side: THREE.DoubleSide
});
material1.transparent = true;
var mesh1 = new THREE.Mesh(
new THREE.PlaneBufferGeometry(2000, 2000),
material1
);
mesh1.position.set(-150, 150, 151);
group.add(mesh1);
directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 0, 0)
scene.add(directionalLight);
directionalLight = new THREE.DirectionalLight(0x888888);
directionalLight.position.set(0, 1, 0)
scene.add(directionalLight);
directionalLight = new THREE.DirectionalLight(0xcccccc);
directionalLight.position.set(0, 0, 1)
scene.add(directionalLight);
scene.add(group)
// with help from https://github.com/tweenjs/tween.js/issues/14
var tween = new TWEEN.Tween(group.rotation).to({ y: -(90 * Math.PI / 180)}, 1000).delay(1000);
tween.onComplete(function() {
group.rotation.y = 0;
});
tween.chain(tween);
tween.start();
camera.lookAt(scene.position);
var render = function() {
requestAnimationFrame(render);
TWEEN.update();
renderer.render(scene, camera);
};
render();
=====EDIT=====
I got it working, not sure if this is the most efficient approach but I'm satisfied:
var start = {}
start.y = 0;
var targ = {};
targ.y = 90*Math.PI/180
function rot(s,t) {
start["y"] = s;
targ["y"] = t;
}
var cnt1 = 1;
var cnt2 = 2;
rot(0,90*Math.PI/180);
var tween = new TWEEN.Tween(start).to(targ, 1000).delay(1000);
tween.onUpdate(function() {
group.rotation.y = start.y;
})
tween.onComplete(function() {
_c = cnt1++;
_d = cnt2++;
rot((_c*90)*Math.PI/180,(_d*90)*Math.PI/180)
});
tween.chain(tween);
tween.start();
Simple call setTimeout when tween is end
( http://jsfiddle.net/bhpf4zvy/ ):
function tRotate( obj, angles, delay, pause ) {
new TWEEN.Tween(group.rotation)
.delay(pause)
.to( {
x: obj.rotation._x + angles.x,
y: obj.rotation._y + angles.y,
z: obj.rotation._z + angles.z
}, delay )
.onComplete(function() {
setTimeout( tRotate, pause, obj, angles, delay, pause );
})
.start();
}
tRotate(group, {x:0,y:-Math.PI/2,z:0}, 1000, 500 );
Upd: pfff, what nonsense am I??? Simple use relative animation (http://jsfiddle.net/vv06u6rs/7/):
var tween = new TWEEN.Tween(group.rotation)
.to({ y: "-" + Math.PI/2}, 1000) // relative animation
.delay(1000)
.onComplete(function() {
// Check that the full 360 degrees of rotation,
// and calculate the remainder of the division to avoid overflow.
if (Math.abs(group.rotation.y)>=2*Math.PI) {
group.rotation.y = group.rotation.y % (2*Math.PI);
}
})
.start();
tween.repeat(Infinity)

How to click and slide into three js cube?

i have this code which works nice and i want to add a situation that when i click on the red cube all the page "jump" closer to the cube. (maybe the camera ?).
i do not have any idea and i will hope you can help me.
In general, i want to learn how to click in one object in three js and move into a second object in my page.
this is my code :
<html>
<head>
<script src="js/three.js"></script>
</head>
<body>
<script>
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(document.body.clientWidth, document.body.clientHeight);
document.body.appendChild(renderer.domElement);
renderer.setClearColorHex(0xEEEEEE, 1.0);
renderer.clear();
renderer.shadowCameraFov = 50;
renderer.shadowMapWidth = 1024;;
renderer.shadowMapHeight = 1024;
var fov = 45; // camera field-of-view in degrees
var width = renderer.domElement.width;
var height = renderer.domElement.height;
var aspect = width / height; // view aspect ratio
var near = 1; // near clip plane
var far = 10000; // far clip plane
var camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = -400;
camera.position.x = 200;
camera.position.y = 350;
var scene = new THREE.Scene();
var cube = new THREE.Mesh(
new THREE.CubeGeometry(50, 50, 50),
new THREE.MeshLambertMaterial({ color: 0xff0000 })
);
scene.add(cube);
cube.castShadow = true;
cube.receiveShadow = true;
var plane = new THREE.Mesh(
new THREE.PlaneGeometry(400, 200, 10, 10),
new THREE.MeshLambertMaterial({ color: 0xffffff }));
plane.rotation.x = -Math.PI / 2;
plane.position.y = -25.1;
plane.receiveShadow = true;
scene.add(plane);
var light = new THREE.SpotLight();
light.castShadow = true;
light.position.set(170, 330, -160);
scene.add(light);
var litCube = new THREE.Mesh(
new THREE.CubeGeometry(50, 50, 50),
new THREE.MeshLambertMaterial({ color: 0xffffff }));
litCube.position.y = 50;
litCube.castShadow = true;
scene.add(litCube);
renderer.shadowMapEnabled = true;
renderer.render(scene, camera);
var paused = false;
var last = new Date().getTime();
var down = false;
var sx = 0, sy = 0;
window.onmousedown = function (ev) {
down = true; sx = ev.clientX; sy = ev.clientY;
};
window.onmouseup = function () { down = false; };
window.onmousemove = function (ev) {
if (down) {
var dx = ev.clientX - sx;
var dy = ev.clientY - sy;
camera.position.x += dx;
camera.position.y += dy;
sx += dx;
sy += dy;
}
}
function animate(t) {
if (!paused) {
last = t;
litCube.position.y = 60 - Math.sin(t / 900) * 25;
litCube.position.x = Math.cos(t / 600) * 85;
litCube.position.z = Math.sin(t / 600) * 85;
litCube.rotation.x = t / 500;
litCube.rotation.y = t / 800;
renderer.clear();
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
window.requestAnimationFrame(animate, renderer.domElement);
};
animate(new Date().getTime());
onmessage = function (ev) {
paused = (ev.data == 'pause');
};
</script>
</body>
</html>
waiting for your replay,
thanks :)
You need to implement different and separated parts to do this:
Selecting an object can be done by using a Raycaster, you'll find many examples here on SO and in the three.js examples such as this one
Orienting the camera - see camera.lookAt( target.position ) - and zooming can be done in many ways, but you might want to use a kind of Control to ease the camera placement process, such as one of these. The TrackballControls for example seems appropriate.
One last bit, as your title says "sliding", is how the "camera jump" is done. If you want a smooth zoom, you'll need a kind of easing function. Have a look on Tween.js for this.
vincent wrote an excellent answer. I just want to add an example to help to understand.
Jsfiddle
<script>
var container, stats;
var camera, scene, projector, raycaster, renderer, selected;
var target, zoom=false;
var mouse = new THREE.Vector2(), INTERSECTED;
var radius = 100, theta = 0;
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 );
var geometry = new THREE.CubeGeometry( 20, 20, 20 );
var cube = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: '#F3B557' } ) );
cube.rotation = new THREE.Euler(0,Math.PI/4,0);
cube.position = new THREE.Vector3(-20,0,0);
scene.add(cube);
cube = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: '#F05B47' } ) );
cube.rotation = new THREE.Euler(0,Math.PI/4,0);
cube.position = new THREE.Vector3(20,0,0);
scene.add(cube);
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() {
// set lookAt position according to target position
if(target){
camera.lookAt( target.position );
}else{
camera.lookAt(new THREE.Vector3(0,0,0));
}
//zoom in and out
if(zoom && camera.fov>10){
camera.fov-=1;
camera.updateProjectionMatrix();
}else if(!zoom && camera.fov<70){
camera.fov+=1;
camera.updateProjectionMatrix();
}
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() );
var intersects = raycaster.intersectObjects( scene.children );
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( 0xff0000 );
}
} else {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = null;
}
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 selected cube
function onCanvasMouseDown( event ){
if(INTERSECTED){
target = INTERSECTED;
zoom = true;
}else{
zoom = false;
}
}
</script>

Categories

Resources