How to tween camera to the top in three.js - javascript

How to tween the camera to the top position with a look to the object in three.js with help of tween.js. The camera tween to the right position works perfectly.
Please use this codepen: http://codepen.io/anon/pen/ObQxjV?editors=1111
image to clarify
var camera, renderer, controls;
//scene
scene = new THREE.Scene();
//camera
camera = new THREE.OrthographicCamera(640 / -2, 640 / 2, 480 / 2, 480 / -2, -5000, 10000000);
camera.position.set(500, 500, 500);
scene.add(camera);
//renderer
renderer = new THREE.WebGLRenderer({ precision: "highp", antialias: true, preserveDrawingBuffer: false });
renderer.setSize(640, 480);
renderer.setClearColor(0xc2c2c2);
$("#canvas").append(renderer.domElement);
//controls
controls = new THREE.OrbitControls(camera, renderer.domElement, renderer, scene);
controls.target = new THREE.Vector3(250, 0, 0)
//axis
var axis = new THREE.AxisHelper( 30000 );
scene.add(axis);
//geometry
var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
var material = new THREE.MeshNormalMaterial();
var cube = new THREE.Mesh( geometry, material );
cube.position.set(250, 0, 0);
scene.add( cube );
animate();
function animate() {
camera.updateProjectionMatrix();
controls.update();
TWEEN.update();
requestAnimationFrame(animate);
render();
}
function render(){
renderer.render(scene, camera);
}
//working tween to the right
$("#workingTweenToTheRight").click(function () {
var destPos = new THREE.Vector3(500, 0, 0);
var destLookAt = new THREE.Vector3(250, 0, 0);
var currentCamPos = {
x: camera.position.x,
y: camera.position.y,
z: camera.position.z
};
var destCamPos = {
x: destPos.x,
y: destPos.y,
z: destPos.z
};
var tween = new TWEEN.Tween(currentCamPos)
.to(destCamPos, 600)
.onUpdate(function () {
camera.position.set(this.x, this.y, this.z);
camera.lookAt(destLookAt);
controls.target = destLookAt;
})
.start();
});
//not working tween to top
$("#notWorkingTweenToTheTop").click(function () {
var destPos = new THREE.Vector3(0, 500, 0);
var destLookAt = new THREE.Vector3(250, 0, 0);
var currentCamPos = {
x: camera.position.x,
y: camera.position.y,
z: camera.position.z
};
var destCamPos = {
x: destPos.x,
y: destPos.y,
z: destPos.z
};
var tween = new TWEEN.Tween(currentCamPos)
.to(destCamPos, 600)
.onUpdate(function () {
camera.position.set(this.x, this.y, this.z);
camera.lookAt(destLookAt);
controls.target = destLookAt;
})
.start();
});
body { margin: 0; }
#canvas {float: left; width: 640px; height: 380px; border: 1px solid #d3d3d3 }
.button { border: 1px solid black; cursor: pointer; width: 230px; height: 20px;}
.button:hover{background: blue; color: white;}
<script src="http://sole.github.io/tween.js/build/tween.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="http://threejs.org/build/three.min.js"></script>
<div id="canvas">
<div id="workingTweenToTheRight" class="button" >working tween to the right</div>
<div id="notWorkingTweenToTheTop" class="button" >not working tween to the top</div>
</div>

You need to set destPos for the "tween to the top" differently:
var destPos = new THREE.Vector3().addVectors(cylinder.position, new THREE.Vector3(0, 500, 0));

Related

Grabbing coordinates from render canvas instead of entire window

I'm experiencing a small problem with an editor I'm building. it's a terrain editor, with toolbars on the left and top, with a canvas on the bottom right. There is a beacon named 'helperHandle' in the canvas which will demonstrate which vector you are currently hovering over. however, the beacon doesn't align properly with the mouse, it seems to be using the entire window as an offset, instead of just the rendering canvas. as you can see from the image below. I've included my code below the image.
The javascript >>
$( document ).ready(function() {
var terrainMesh;
var helperHandle;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var cameraholder;
function main() {
const canvas = document.querySelector('#terrainRender');
const renderer = new THREE.WebGLRenderer({canvas, alpha: true});
var cubes = [];
const fov = 40;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 1000;
cameraholder = new THREE.Object3D();
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0,10,20);
camera.lookAt( 0, 0, 0 );
camera.zoom = 0.5;
const scene = new THREE.Scene();
scene.background = new THREE.Color( 0x555555 );
scene.add(cameraholder);
var size = 10;
var divisions = 10;
var gridHelper = new THREE.GridHelper( size, divisions );
scene.add( gridHelper );
var axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );
var ambient = new THREE.AmbientLight( 0x444444 );
scene.add( ambient );
const color = 0xFFFFFF;
const intensity = 0.1;
light = new THREE.DirectionalLight(color, intensity);
light.position.set(1, 30, 10);
light.target.position.set( 0, 0, 0 );
light.castShadow = true;
var lightHelper = new THREE.DirectionalLightHelper( light, 5 );
scene.add( lightHelper );
const controls = new THREE.OrbitControls(camera, canvas);
controls.target.set(0, 0, 0);
controls.update();
scene.add( light );
var geometry = new THREE.PlaneBufferGeometry(60, 60, 9, 9);
var material = new THREE.MeshBasicMaterial(
{color: 0x666666,
side: THREE.DoubleSide
});
rotateObject(geometry, -90, 0, 0);
geometry.computeFaceNormals(); // needed for helper
var helperHandlegeometry = new THREE.ConeBufferGeometry( 1, 3, 3 );
helperHandlegeometry.rotateX( Math.PI / 2 );
helperHandle = new THREE.Mesh( helperHandlegeometry, new THREE.MeshNormalMaterial() );
scene.add( helperHandle );
terrainMesh = new THREE.Mesh( geometry, material );
scene.add( terrainMesh );
var wireframe = new THREE.WireframeGeometry( geometry );
var line = new THREE.LineSegments( wireframe );
line.material.depthTest = false;
line.material.opacity = 0.25;
line.material.transparent = true;
scene.add( line );
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
const direction = (new THREE.Vector3())
.subVectors(camera.position, boxCenter)
.multiply(new THREE.Vector3(1, 0, 1))
.normalize();
camera.near = boxSize / 100;
camera.far = boxSize * 100;
camera.updateProjectionMatrix();
camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = renderer.domElement.clientWidth;
const height = renderer.domElement.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = renderer.domElement.clientWidth / renderer.domElement.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function onMouseMove( event ) {
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
terrainMesh.updateMatrixWorld();
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObject( terrainMesh );
if ( intersects.length > 0 ) {
helperHandle.position.set( 0, 0, 0 );
helperHandle.lookAt( intersects[ 0 ].face.normal );
helperHandle.position.copy( intersects[ 0 ].point );
}
$('#coords').html(`X: ${mouse.x.toFixed(2)} <br>Y: ${mouse.y.toFixed(2)}`);
}
window.addEventListener( 'mousemove', onMouseMove, false );
requestAnimationFrame(render);
}
main();
});
The html >>
<div id="main">
<div id="toolBar">
</div>
<div class="editorWindow">
<div id="sideBar"></div>
<canvas id="terrainRender"></canvas>
<div id="coords"></div>
</div>
</div>
The CSS (less) >>
div{
}
body { margin: 0; }
#coords{
position: absolute;
top: 0;
width: 40px;
height: 40px;
background-color: #fff;
}
.titleBar{
height: 30px;
width: 100%;
display: block;
background-color: #e0e0e0;
}
#main{
position: relative;
background-color: #f4f4f4;
display: grid;
height: 99vh;
flex-wrap: wrap;
border: 1px solid #aaa;
padding: 0.2%;
.editorWindow{
flex: 1;
flex-direction: row;
display: flex;
}
#toolBar{
height: 60px;
}
#sideBar{
flex: 1 2 10%;
position: relative;
background-color: #f4f4f4;
border: solid 1px #aaa;
}
#terrainRender {
flex: 12 1 80%;
}
}
#terrain{
display: inline-block;
zoom: 100%;
transform-origin: center;
white-space: nowrap;
font-size: 0px;
transform-style: preserve-3d;
/*transform: rotateZ(0deg) rotateY(0deg) rotateX(45deg);*/
}

Three.js adding box to scene not working on iOS

I'm trying to get Three.js to add a box to the scene on iOS but it doesn't seem to work while on macOS Safari it does.
The scene sets up correctly and adds the first box but when adding the "cube" it doesn't appear on the scene
iOS 12.1.1 on an iPad
var scene, renderer, controls, camera;
function init() {
container = document.getElementById("canvas");
container.height = $("#canvas").height();
container.width = $("#canvas").width();
camera = new THREE.PerspectiveCamera(20, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(300, 300, 300);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xfffff0);
scene.add(new THREE.AmbientLight(0x555555));
var light = new THREE.SpotLight(0xffffff, 1.5);
light.position.set(0, 500, 2000);
scene.add(light);
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setClearColor(0xE6EEF2);
renderer.setSize($(container).width(), $(container).height());
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableKeys = false;
controls.enabled = false;
}
function addBox() {
var orientation = {
dim1: 78,
dim2: 62,
dim3: 35
}
var geom = new THREE.BoxGeometry(orientation.dim1, orientation.dim2, orientation.dim3);
geom.translate(orientation.dim1 / 2, orientation.dim2 / 2, orientation.dim3 / 2);
box_material = new THREE.MeshPhongMaterial({
transparent: true,
opacity: 0,
alphaTest: 0.5
});
mesh = new THREE.Mesh(geom, box_material)
var geometry = new THREE.EdgesGeometry(mesh.geometry);
var edges_material = new THREE.LineBasicMaterial({
color: 0x000000,
linewidth: 2
});
var edges = new THREE.LineSegments(geometry, edges_material);
mesh.name = "box1"
scene.add(mesh.add(edges));
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
controls.update();
renderer.render(scene, camera);
}
function addCube() {
pos = {
x: 46,
y: 0,
z: 0
};
orientation = orientation = {
dim1: 46,
dim2: 28,
dim3: 30
}
var geom = new THREE.BoxGeometry(orientation.dim1, orientation.dim2, orientation.dim3);
geom.translate(pos.x + orientation.dim1 / 2, pos.y + orientation.dim2 / 2, pos.z + orientation.dim3 / 2);
material = new THREE.MeshPhongMaterial({
color: Math.random() * 0xffffff,
flatShading: true,
vertexColors: THREE.VertexColors,
transparent: true,
opacity: 0.7
});
mesh = new THREE.Mesh(geom, material)
mesh.name = "cube";
scene.add(mesh);
console.log("added cube");
}
init();
animate();
addBox();
addCube();
body {
margin: 0;
}
.main {
height: 100vh;
display: flex;
position: relative;
}
.content {
display: flex;
width: 100%;
max-height: 100vh;
overflow: auto;
}
.box {
flex: 1 1 auto;
display: flex;
flex-direction: column;
border-left: 1px solid #CED4D9;
border-right: 1px solid #CED4D9;
align-items: center;
}
.boxView-container {
width: 100%;
height: auto;
flex: 1 1 auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<body>
hello2
<div id="root">
<main class="main">
<section class="content">
<div class="box">
<div class="boxView-container" id="canvas"></div>
</div>
</section>
</main>
</div>
</body>
On macOS Safari:
On iOS Safari:
jsfiddle:
http://jsfiddle.net/acrogenesis/d583wyft/44/
I think it is caused by variable scope. You need define some local variables, or else the addCube function will change some global variables above.
like var pos, mesh etc.
function addCube() {
var pos = {x: 46, y: 0, z: 0};
var orientation = {
dim1: 46,
dim2: 28,
dim3: 30
}
var geom = new THREE.BoxGeometry(orientation.dim1, orientation.dim2, orientation.dim3);
geom.translate(pos.x + orientation.dim1 / 2, pos.y + orientation.dim2 / 2, pos.z + orientation.dim3 / 2);
var material = new THREE.MeshPhongMaterial({
color: Math.random() * 0xffffff,
flatShading: true,
vertexColors: THREE.VertexColors,
transparent: true,
opacity: 0.7
});
var mesh = new THREE.Mesh(geom, material)
mesh.name = "cube";
scene.add(mesh);
console.log("added cube");
}
After define these local variables, now working great on iOS.

Three.js Animated curve

I try to animate a 2D curve in Three.js over time.
I'll need more than 4 control points, so I'm not using Bezier curves.
I created a Three.Line based on a SplineCurve.
If I log the geometry.vertices position of my line they'll change over time, but geometry.attributes.position remains the same. Is it possible to animate the line based on the curve animation ? I managed to do this with Bezier Curves, but can't find a way with SplineCurve.
Thank you for your help, here's my code :
First I create the line :
var curve = new THREE.SplineCurve( [
new THREE.Vector3( -10, 0, 10 ),
new THREE.Vector3( -5, 5, 5 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 5, -5, 5 ),
new THREE.Vector3( 10, 0, 10 )
] );
var points = curve.getPoints( 50 );
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
// Create the final object to add to the scene
curveObject = new THREE.Line( geometry, material );
scene.add( curveObject );
curveObject.curve = curve;
Then I try to update it :
curveObject.curve.points[0].x += 1;
curveObject.geometry.vertices = curveObject.curve.getPoints( 50 );
curveObject.geometry.verticesNeedUpdate = true;
curveObject.geometry.attributes.needsUpdate = true;
You can do it like that:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(8, 13, 25);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
var canvas = renderer.domElement;
document.body.appendChild(canvas);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(20, 40));
var curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-10, 0, 10),
new THREE.Vector3(-5, 5, 5),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(5, -5, 5),
new THREE.Vector3(10, 0, 10)
]);
var points = curve.getPoints(50);
var geometry = new THREE.BufferGeometry().setFromPoints(points);
var material = new THREE.LineBasicMaterial({
color: 0x00ffff
});
var curveObject = new THREE.Line(geometry, material);
scene.add(curveObject);
var clock = new THREE.Clock();
var time = 0;
render();
function resize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render() {
if (resize(renderer)) {
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
time += clock.getDelta();
curve.points[1].y = Math.sin(time) * 2.5;
geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(50));
curveObject.geometry.dispose();
curveObject.geometry = geometry;
requestAnimationFrame(render);
}
html,
body {
height: 100%;
margin: 0;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
display;
block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

threejs: Move camera to position inside another object

I'm trying to move the camera controlled by trackballControl into the position of an object.
Right now it's working but as you can see in my fiddle, each time the camera changes position it also changes the z which isn't what I want.
I'm trying to keep the same position but only rotate the globe into the position of the cube.
Here is my code so far
var camera, scene, renderer, controls, cubeMesh;
document.querySelector('button').onclick = function () {
camera.position.copy(cubeMesh.position);
camera.lookAt(controls.target);
};
var initLights = function () {
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
};
var init = function () {
renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize(window.innerWidth, window.innerHeight);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 300;
scene = new THREE.Scene();
controls = new THREE.TrackballControls(camera);
controls.target.set(0, 0, 0);
controls.rotateSpeed = 2;
document.body.appendChild(renderer.domElement);
var sphereGeom = new THREE.SphereGeometry(100, 32, 32);
var sphereMat = new THREE.MeshPhongMaterial({
color: 0xfb3550,
flatShading: true
});
var sphereMesh = new THREE.Mesh(sphereGeom, sphereMat);
//cube
var cubeDim = 20;
var cubeGeom = new THREE.BoxGeometry(cubeDim, cubeDim, cubeDim);
var cubeMat = new THREE.MeshPhongMaterial({
color: 0x7cf93e,
flatShading: true
});
cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);
var spherical = new THREE.Spherical();
spherical.set(100 + cubeDim / 2, 0.4, 0);
cubeMesh.position.setFromSpherical(spherical);
var zero = new THREE.Vector3(0, 0, 0);
cubeMesh.lookAt(zero);
scene.add(sphereMesh);
sphereMesh.add(cubeMesh);
initLights();
};
var render = function () {
renderer.render(scene, camera);
};
var animate = function () {
requestAnimationFrame(animate);
controls.update();
render();
};
init();
animate()
You can test it in my fiddle here
Here is a fiddle where the camera is zoomed a little bit out by clicking the button.
JS Fiddle
var camera, scene, renderer, controls, cubeMesh;
document.querySelector('button').onclick = function () {
let x = cubeMesh.position.x
let y = cubeMesh.position.y
let z = cubeMesh.position.z
camera.position.x = 0
camera.position.y = y + 200
camera.position.z = z + 100
camera.lookAt(controls.target);
};
var initLights = function () {
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
};
var init = function () {
renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize(window.innerWidth, window.innerHeight);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 300;
scene = new THREE.Scene();
controls = new THREE.TrackballControls(camera);
controls.target.set(0, 0, 0);
controls.rotateSpeed = 2;
document.body.appendChild(renderer.domElement);
var sphereGeom = new THREE.SphereGeometry(100, 32, 32);
var sphereMat = new THREE.MeshPhongMaterial({
color: 0xfb3550,
flatShading: true
});
var sphereMesh = new THREE.Mesh(sphereGeom, sphereMat);
//cube
var cubeDim = 20;
var cubeGeom = new THREE.BoxGeometry(cubeDim, cubeDim, cubeDim);
var cubeMat = new THREE.MeshPhongMaterial({
color: 0x7cf93e,
flatShading: true
});
cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);
var spherical = new THREE.Spherical();
spherical.set(100 + cubeDim / 2, 0.4, 0);
cubeMesh.position.setFromSpherical(spherical);
var zero = new THREE.Vector3(0, 0, 0);
cubeMesh.lookAt(zero);
scene.add(sphereMesh);
sphereMesh.add(cubeMesh);
initLights();
};
var render = function () {
console.log(camera.position)
renderer.render(scene, camera);
};
var animate = function () {
requestAnimationFrame(animate);
controls.update();
render();
};
init();
animate()
You have to set the camera target to the position where you want to look at.
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
camera.lookAt(newTarget);
and the THREE.TrackballControls has to be notified to update from the camera THREE.TrackballControls.update:
document.querySelector('button').onclick = function () {
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
controls.reset();
camera.lookAt(newTarget)
camera.updateProjectionMatrix();
controls.update();
};
If the current camera position should be kept and not be reseted, then the position has to be read form the world matrix of the camera and the initial position of the camera has to be set to its current position:
document.querySelector('button').onclick = function ()
var newPosition = new THREE.Vector3(0, 0, 0);
newPosition.applyMatrix4( camera.matrixWorld );
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
controls.reset();
camera.position.copy(newPosition);
camera.lookAt(newTarget)
camera.updateProjectionMatrix();
controls.update();
};
See the example:
var camera, scene, renderer, controls, cubeMesh;
document.getElementById('reset').onclick = function () {
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
controls.reset();
camera.lookAt(newTarget)
camera.updateProjectionMatrix();
controls.update();
};
document.getElementById('target').onclick = function () {
var newPosition = new THREE.Vector3(0, 0, 0);
newPosition.applyMatrix4( camera.matrixWorld );
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
controls.reset();
camera.position.copy(newPosition);
camera.lookAt(newTarget)
camera.updateProjectionMatrix();
controls.update();
};
var initLights = function () {
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
};
var init = function () {
renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize(window.innerWidth, window.innerHeight);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 300;
scene = new THREE.Scene();
controls = new THREE.TrackballControls(camera);
controls.target.set(0, 0, 0);
controls.rotateSpeed = 2;
document.body.appendChild(renderer.domElement);
var sphereGeom = new THREE.SphereGeometry(100, 32, 32);
var sphereMat = new THREE.MeshPhongMaterial({
color: 0xfb3550,
flatShading: true
});
var sphereMesh = new THREE.Mesh(sphereGeom, sphereMat);
//cube
var cubeDim = 20;
var cubeGeom = new THREE.BoxGeometry(cubeDim, cubeDim, cubeDim);
var cubeMat = new THREE.MeshPhongMaterial({
color: 0x7cf93e,
flatShading: true
});
cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);
var spherical = new THREE.Spherical();
spherical.set(100 + cubeDim / 2, 0.4, 0);
cubeMesh.position.setFromSpherical(spherical);
var zero = new THREE.Vector3(0, 0, 0);
cubeMesh.lookAt(zero);
scene.add(sphereMesh);
sphereMesh.add(cubeMesh);
initLights();
};
var render = function () {
renderer.render(scene, camera);
};
var animate = function () {
requestAnimationFrame(animate);
controls.update();
render();
};
init();
animate();
button {
position : absolute;
top : 0;
right : 0;
}
.button2 {
position : absolute;
top : 0;
left : 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
<button id="reset" class="button2">
reset camera
</button>
<button id="target">
look at target
</button>

Three.js shatter/explode plane geometry

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.

Categories

Resources