Three.js moving the camera left and right side of the scene - three.js

I am working on a three.js prototype in which a 3d model of the train is added to the scene. My requirement is to move the camera either left / right side of the scene to view the complete train.
I tried using below code -
function onKeyDown(){
var zdelta = 20;
switch( event.keyCode ) {
case 65: // look left
camera.position.z = camera.position.z + zdelta;
}
}
But the scene was rotating rather than panning in the left side.
So it will be great help, if anyone shares their idea on this :)
Thanks,
Satheesh K

Using a keydown event listener is definitely the right approach. Try it with this code:
var scene, camera, renderer, cubeObj;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
camera.position.y = - 10;
camera.position.x = 10;
var cubeGeo = new THREE.BoxGeometry( 200, 150, 100 );
var cubeGeoMaterial = new THREE.MeshPhongMaterial( { color: 0x808080 } );
cubeObj = new THREE.Mesh( cubeGeo, cubeGeoMaterial );
cubeObj.position.x = - 70;
cubeObj.position.y = - 50;
cubeObj.position.z = 0;
cubeObj.rotation.x = 0.5;
scene.add( cubeObj );
var cubeGeo2 = new THREE.BoxGeometry( 200, 150, 100 );
var cubeGeoMaterial2 = new THREE.MeshPhongMaterial( { color: 0x808080 } );
var cubeObj2 = new THREE.Mesh( cubeGeo2, cubeGeoMaterial2 );
cubeObj2.position.x = 160;
cubeObj2.position.y = - 50;
cubeObj2.position.z = - 5;
cubeObj2.rotation.x = 0.5;
scene.add( cubeObj2 );
var cubeGeo3 = new THREE.BoxGeometry( 200, 150, 100 );
var cubeGeoMaterial3 = new THREE.MeshPhongMaterial( { color: 0x808080 } );
var cubeObj3 = new THREE.Mesh( cubeGeo3, cubeGeoMaterial3 );
cubeObj3.position.x = 440;
cubeObj3.position.y = - 50;
cubeObj3.position.z = 0;
cubeObj3.rotation.x = 0.5;
scene.add( cubeObj3 );
renderer = new THREE.WebGLRenderer( {
antialias: true
} );
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 100, 1000, 100 );
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 500;
spotLight.shadow.camera.far = 4000;
spotLight.shadow.camera.fov = 30;
//scene.add( spotLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
scene.add( directionalLight );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xcce0ff );
document.body.appendChild( renderer.domElement );
document.addEventListener( 'keydown', onKeyDown, false );
}
function onKeyDown( event ) {
const step = 5; // world units
switch ( event.keyCode ) {
case 37:
camera.position.x -= step;
break;
case 39:
camera.position.x += step;
break;
}
}
function animate() {
renderer.render( scene, camera );
requestAnimationFrame( animate );
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.114/build/three.js"></script>

Related

Threejs / Raycast doesn't compute intersection with my cube

Here is my js files. It works. When I click on the cube, it goes inside raycast function, but doesn't enter the for loop and console.log( intersects[ 0 ] ) gives undefined
let camera, scene, renderer;
let mesh, mesh_green;
let raycaster, mouse = { x : 0, y : 0 };
init();
function init() {
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 40;
scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: "red" } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
mesh.position.set( 0, 10, 0 );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
raycaster = new THREE.Raycaster();
renderer.domElement.addEventListener( 'click', raycast, false );
function raycast ( e ) {
mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1;
console.log( "raycast" , e.clientX, mouse.x, window.innerWidth);
raycaster.setFromCamera( mouse, camera );
const intersects = raycaster.intersectObjects( scene.children );
for ( let i = 0; i < intersects.length; i++ ) {
console.log( intersects[ i ] );
}
}
It seems your code works by using a latest version of three.js. I've just refactored/simplified it a bit.
let camera, scene, renderer;
let mesh;
let raycaster, pointer = new THREE.Vector2();
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 40;
scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({
color: "red"
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 10, 0);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
raycaster = new THREE.Raycaster();
renderer.domElement.addEventListener('pointerdown', raycast);
}
function raycast(e) {
pointer.x = (e.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(e.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObject(scene);
for (let i = 0; i < intersects.length; i++) {
console.log(intersects[i]);
}
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.140.2/build/three.min.js"></script>

Creating Hole in object using ThreeJS and Stencil method

I am trying to make a hole in a solid object(box) using stencil method in ThreeJS. I found few web pages and similar questions on the net in this regard but couldn't work them out. Specifically This link is what I want to achieve(even one hole is enough). However the code in the link is using Babylon and I need it to be in ThreeJS. Any idea how I can use ThreeJS to achieve this(or to translate it to ThreeJS)?
Update 1:
There is a sample in ThreeJS examples "misc_exporter_ply.html"(it's got nothing to do with stencil buffer though) and so I tried to use it as it has a simple scene with only one box. I added another cylinder inside the box to represent the hole.
I could get it to work so that there is a visible hole. Yet it's not perfect as the stencil buffer is not working as expected:
Image 1
Image 2
And here is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - exporter - ply</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info">
three.js webgl - exporter - ply<br/><br/>
<button id="exportASCII">export ASCII</button> <button id="exportBinaryBigEndian">export binary (Big Endian)</button> <button id="exportBinaryLittleEndian">export binary (Little Endian)</button>
</div>
<script type="module">
import * as THREE from '../build/three.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { PLYExporter } from './jsm/exporters/PLYExporter.js';
let scene, camera, renderer, exporter, mesh, meshHole, mesh0, mesh1;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 200, 100, 200 );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa1caf1 );
//scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
//exporter = new PLYExporter();
//
const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
hemiLight.position.set( 0, 200, 0 );
scene.add( hemiLight );
const directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 0, 200, 100 );
directionalLight.castShadow = true;
directionalLight.shadow.camera.top = 180;
directionalLight.shadow.camera.bottom = - 100;
directionalLight.shadow.camera.left = - 120;
directionalLight.shadow.camera.right = 120;
scene.add( directionalLight );
// ground
const ground = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0xaaaaaa, depthWrite: false } ) );
ground.rotation.x = - Math.PI / 2;
ground.receiveShadow = true;
scene.add( ground );
const grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
// mesh
const boxHole = new THREE.CylinderGeometry( 15, 15, 65, 32, 32 );//BoxGeometry( 20, 20, 51 );
let matHole = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
matHole.colorWrite = false;
meshHole = new THREE.Mesh( boxHole, matHole );
meshHole.castShadow = true;
meshHole.position.y = 50;
meshHole.rotation.x = Math.PI / 2;
scene.add( meshHole );
const geometry = new THREE.BoxGeometry( 50, 50, 50 );
mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial({ color: 0xaaaaaa }) );
mesh.castShadow = true;
mesh.position.y = 50;
scene.add( mesh );
// back faces
const mat0 = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
mat0.side = THREE.FrontSide;
mat0.depthWrite = false;
mat0.depthTest = false;
mat0.colorWrite = false;
//mat0.stencilWrite = true;
mat0.stencilFunc = THREE.AlwaysStencilFunc;
mat0.stencilFail = THREE.KeepStencilOp;
//mat0.stencilZFail = THREE.IncrementWrapStencilOp;
//mat0.stencilZPass = THREE.ReplaceStencilOp;
mat0.stencilRef = 1;
const boxHole0 = new THREE.CylinderGeometry( 15, 15, 65, 32, 32 );
mesh0 = new THREE.Mesh( boxHole0, mat0 );
mesh0.rotation.x = Math.PI / 2;
mesh0.castShadow = true;
mesh0.position.y = 50;
scene.add( mesh0 );
// front faces
const mat1 = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
mat1.side = THREE.DoubleSide;
//mat1.depthWrite = false;
//mat1.depthTest = true;
//mat1.colorWrite = false;
//mat1.stencilWrite = true;
mat1.depthFunc=THREE.AlwaysDepth;
mat1.stencilFunc = THREE.EqualStencilFunc;
mat1.stencilFail = THREE.IncrementStencilOp;
//mat1.stencilZFail = THREE.DecrementWrapStencilOp;
//mat1.stencilZPass = THREE.DecrementWrapStencilOp;
mat1.stencilRef = 1;
const boxHole1 = new THREE.CylinderGeometry( 15, 15, 65, 32, 32, true );
mesh1 = new THREE.Mesh( boxHole1, mat1 );
mesh1.rotation.x = Math.PI / 2;
mesh1.castShadow = true;
mesh1.position.z = 0;
mesh1.position.y = 50;
scene.add( mesh1 );
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.localClippingEnabled = true;
document.body.appendChild( renderer.domElement );
//
const controls = new OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 25, 0 );
controls.update();
//
window.addEventListener( 'resize', onWindowResize );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
const link = document.createElement( 'a' );
link.style.display = 'none';
document.body.appendChild( link );
</script>
</body>
</html>
Got it working at the end:
Box with cylinder hole
import * as THREE from '../build/three.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { PLYExporter } from './jsm/exporters/PLYExporter.js';
let scene, camera, renderer, exporter, mesh, meshHole, mesh0, mesh1;
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 200, 100, 200 );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa1caf1 );
//scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
//exporter = new PLYExporter();
//
const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
hemiLight.position.set( 0, 200, 0 );
scene.add( hemiLight );
const directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 0, 200, 100 );
directionalLight.castShadow = true;
directionalLight.shadow.camera.top = 180;
directionalLight.shadow.camera.bottom = - 100;
directionalLight.shadow.camera.left = - 120;
directionalLight.shadow.camera.right = 120;
scene.add( directionalLight );
// ground
const ground = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0xaaaaaa, depthWrite: false } ) );
ground.rotation.x = - Math.PI / 2;
ground.receiveShadow = true;
scene.add( ground );
const grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
// mesh
const boxHole = new THREE.CylinderGeometry( 15, 15, 51, 32, 32 );//BoxGeometry( 20, 20, 51 );
let matHole = new THREE.MeshPhongMaterial({ color: 0xaaaaaa });
matHole.colorWrite = false;
meshHole = new THREE.Mesh( boxHole, matHole );
meshHole.castShadow = true;
meshHole.position.y = 50;
meshHole.rotation.x = Math.PI / 2;
scene.add( meshHole );
const geometry = new THREE.BoxGeometry( 50, 50, 50 );
mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial({ color: 0xaaaaaa }) );
mesh.castShadow = true;
mesh.position.y = 50;
scene.add( mesh );
// front faces
const mat0 = new THREE.MeshPhongMaterial({ color: 0xaaaaaa });
mat0.side = THREE.FrontSide;
//mat0.depthWrite = false;
//mat0.depthTest = false;
mat0.colorWrite = false;
const boxHole0 = new THREE.CylinderGeometry( 15, 15, 51, 32, 32 );
mesh0 = new THREE.Mesh( boxHole0, mat0 );
mesh0.rotation.x = Math.PI / 2;
mesh0.castShadow = true;
mesh0.position.y = 50;
scene.add( mesh0 );
mat0.stencilWrite = true;
mat0.stencilFunc = THREE.AlwaysStencilFunc;
mat0.stencilFail = THREE.KeepStencilOp;
mat0.stencilZFail = THREE.KeepStencilOp;
mat0.stencilZPass = THREE.ReplaceStencilOp;
mat0.stencilRef = 1;
// back faces
const mat1 = new THREE.MeshPhongMaterial({ color: 0xaaaaaa });
mat1.side = THREE.BackSide;
mat1.depthWrite = false;
mat1.depthTest = true;
//mat1.colorWrite = false;
const boxHole1 = new THREE.CylinderGeometry( 15, 15, 51, 32, 32, true );
mesh1 = new THREE.Mesh( boxHole1, mat1 );
mesh1.rotation.x = Math.PI / 2;
mesh1.castShadow = true;
mesh1.position.z = 0;
mesh1.position.y = 50;
scene.add( mesh1 );
mat1.depthFunc=THREE.AlwaysDepth;
mat1.stencilWrite = true;
mat1.stencilFunc = THREE.EqualStencilFunc;
mat1.stencilFail = THREE.DecrementWrapStencilOp;
mat1.stencilZFail = THREE.DecrementWrapStencilOp;
mat1.stencilZPass = THREE.DecrementWrapStencilOp;
mat1.stencilRef = 1;
mesh1.onAfterRender = function ( renderer ) {
renderer.clearStencil();
};
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.localClippingEnabled = true;
document.body.appendChild( renderer.domElement );
//
const controls = new OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 25, 0 );
controls.update();
//
window.addEventListener( 'resize', onWindowResize );
}

Converting THREE.js Geometry into BufferGeometry?

I'm relatively new to THREE.js and I got this code but I'd like to reconstruct this Geometry into BufferGeometry to get the efficiency benefits. I saw this (var bufferGeometry = new THREE.BufferGeometry().fromGeometry( geometry );) as a possible solution but I could not implement it I'm sure it's simple I just lack the experience with THREE.js to recognize this.
let rainGeo = new THREE.Geometry()
for (let i = 0; i < rainCount; i++) {
rainDrop = new THREE.Vector3(
Math.random() * 120 - 60,
Math.random() * 180 - 80,
Math.random() * 130 - 60,
)
rainDrop.velocity = {}
rainDrop.velocity = 0
bufferGeometry.vertices.push(rainDrop)
}
rainMaterial = new THREE.PointsMaterial({
color: '#ffffff',
size: .3,
transparent: true,
map: THREE.ImageUtils.loadTexture(
'images/snow_mask_2.png'),
blending: THREE.AdditiveBlending,
})
rain = new THREE.Points(bufferGeometry, rainMaterial)
rain.rotation.x = -1.5707963267948963
rain.rotation.y = -3.22
scene.add(rain)
function rainVariation() {
bufferGeometry.vertices.forEach(p => {
p.velocity -= 0.1 + Math.random() * 0.1;
p.y += p.velocity;
if (p.y < -60) {
p.y = 60;
p.velocity = 0;
}
});
bufferGeometry.verticesNeedUpdate = true;
rain.rotation.y += 0.008
}
Try it with this ported code as a basis. I suggest that you manage the velocity per raindrop in a separate array (since these data are not necessary in the shader).
let camera, scene, renderer, rain;
const vertex = new THREE.Vector3();
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 100;
scene = new THREE.Scene();
const geometry = new THREE.BufferGeometry();
const vertices = [];
for (let i = 0; i < 1000; i++) {
vertices.push(
Math.random() * 120 - 60,
Math.random() * 180 - 80,
Math.random() * 130 - 60
);
}
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
const material = new THREE.PointsMaterial( { color: '#ffffff' } );
rain = new THREE.Points( geometry, material );
scene.add(rain);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function rainVariation() {
var positionAttribute = rain.geometry.getAttribute( 'position' );
for ( var i = 0; i < positionAttribute.count; i ++ ) {
vertex.fromBufferAttribute( positionAttribute, i );
vertex.y -= 1;
if (vertex.y < - 60) {
vertex.y = 90;
}
positionAttribute.setXYZ( i, vertex.x, vertex.y, vertex.z );
}
positionAttribute.needsUpdate = true;
}
function animate() {
requestAnimationFrame( animate );
rainVariation();
renderer.render( scene, camera );
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.115/build/three.js"></script>

Video transition in Three.js

I want to play multiple videos in Three.js environment. I have finished loading video as texture and play it below and stuck at how to implement to load multiple video textures and play. Also adding some transition into it :(. Hope anyone can help me , give me some suggestions or right direction to do it. I'm fresh to webGL and Three.js.
// MAIN
// standard global variables
var container, scene, camera, renderer, controls, stats;
// custom global variables
var video, videoImage, videoImageContext, videoTexture;
var mouseX = 0;
var mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight;
init();
animate();
// FUNCTIONS
function init() {
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,200,500);
camera.lookAt(scene.position);
// RENDERER
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
renderer.setClearColor (0xFFFFFF, 1);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
// CONTROLS
// controls = new THREE.OrbitControls( camera, renderer.domElement );
// EVENTS
THREEx.WindowResize(renderer, camera);
// LIGHT
// var light = new THREE.PointLight(0xffffff);
// light.position.set(0,250,0);
// scene.add(light);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture( 'logo.jpg' );
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(500, 500, 0, 0);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
// floor.wrapS = THREE.RepeatWrapping;
// floor.position.y = -0.5;
// floor.rotation.x = - (Math.PI / 2);
floor.position.y = -100;
floor.rotation.x = - (Math.PI / 2);
scene.add(floor);
///////////
// VIDEO //
///////////
// create the video element
video = document.createElement( 'video' );
// video.id = 'video';
// video.type = ' video/ogg; codecs="theora, vorbis" ';
video.src = "video3.mp4";
video.load(); // must call after setting/changing source
video.play();
// alternative method --
// create DIV in HTML:
// <video id="myVideo" autoplay style="display:none">
// <source src="videos/sintel.ogv" type='video/ogg; codecs="theora, vorbis"'>
// </video>
// and set JS variable:
// video = document.getElementById( 'myVideo' );
videoImage = document.createElement( 'canvas' );
videoImage.width = 1280;
videoImage.height = 546;
videoImageContext = videoImage.getContext( '2d' );
// background color if no video present
videoImageContext.fillStyle = '#000000';
videoImageContext.fillRect( 0, 0, videoImage.width, videoImage.height );
videoTexture = new THREE.Texture( videoImage );
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
var movieMaterial = new THREE.MeshBasicMaterial( { map: videoTexture, overdraw: true, side:THREE.DoubleSide } );
// the geometry on which the movie will be displayed;
// movie image will be scaled to fit these dimensions.
var movieGeometry = new THREE.PlaneGeometry( 600, 300, 4, 4 );
var movieScreen = new THREE.Mesh( movieGeometry, movieMaterial );
movieScreen.position.set(0,50,-200);
scene.add(movieScreen);
camera.position.set(0,200,450);
var vector = new THREE.Vector3(0,200,450);
camera.lookAt(movieScreen.position);
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
}
function onDocumentMouseMove(event) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY ) * 0.2;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * 0.05;
camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
camera.lookAt(scene.position);
if ( video.readyState === video.HAVE_ENOUGH_DATA )
{
videoImageContext.drawImage( video, 0, 0 );
if ( videoTexture )
videoTexture.needsUpdate = true;
}
renderer.render( scene, camera );
}

Three.js Restrict the mouse movement to Scene only

I am working on the cube example from three.js (webgl_interactive_cubes_gpu.html). I realized that events goes to the entire html page. I mean i can rotate, zoom in or zoom out, even if the mouse pointer is not inside the scene..
I google a little bit and found some answers (Allow mouse control of three.js scene only when mouse is over canvas) but they do not work for me..Below is my code...
var container, stats;
var camera, controls, scene, renderer;
var pickingData = [], pickingTexture, pickingScene;
var objects = [];
var highlightBox;
var mouse = new THREE.Vector2();
var offset = new THREE.Vector3( 10, 10, 10 );
init();
animate();
function init() {
container = document.getElementById( "container" );
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 1000;
//camera.translateZ( -500 );
controls = new THREE.TrackballControls(camera);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 4;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
scene = new THREE.Scene();
pickingScene = new THREE.Scene();
pickingTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
pickingTexture.minFilter = THREE.LinearFilter;
pickingTexture.generateMipmaps = false;
scene.add( new THREE.AmbientLight( 0x555555 ));
var light = new THREE.SpotLight( 0xffffff, 1.5 );
light.position.set( 0, 500, 2000 );
scene.add( light );
var geometry = new THREE.Geometry(),
pickingGeometry = new THREE.Geometry(),
pickingMaterial = new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors } ),
defaultMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors} );
function applyVertexColors( g, c ) {
g.faces.forEach( function( f ) {
var n = ( f instanceof THREE.Face3 ) ? 3 : 4;
for( var j = 0; j < n; j ++ ) {
f.vertexColors[ j ] = c;
}
} );
}
var geom = new THREE.BoxGeometry(0.005, 0.005, 0.005 );
var color = new THREE.Color();
var matrix = new THREE.Matrix4();
var quaternion = new THREE.Quaternion();
var coord="219_163_189;130_173_179;161_113_231;
var splitCoord=coord.split(";");
var coordColr="0_255_255;255_255_0;0_0_255;0_255_0;255_255_0;
var splitCoordColor=coordColr.split(";");
for ( var i = 0; i < splitCoord.length; i++ ) {
var position = new THREE.Vector3();
var xyz=splitCoord[i].split("_");
var col=splitCoordColor[i].split("_");
position.x = xyz[0];
position.y = xyz[1];
position.z = xyz[2];
var rotation = new THREE.Euler();
rotation.x = 0
rotation.y = 0;
rotation.z = 0;
var scale = new THREE.Vector3();
scale.x = 200 + 100;
scale.y = 200 + 100;
scale.z = 200 + 100;
quaternion.setFromEuler(rotation, false );
matrix.compose( position, quaternion, scale);
col[0]=col[0]/255;
col[1]=col[1]/255;
col[2]=col[2]/255;
applyVertexColors(geom, color.setRGB(col[0], col[1], col[2]));
geometry.merge(geom, matrix);
// give the geom's vertices a color corresponding to the "id"
applyVertexColors( geom, color.setHex( i ) );
pickingGeometry.merge( geom, matrix );
pickingData[ i ] = {
position: position,
rotation: rotation,
scale: scale
};
}
var drawnObject = new THREE.Mesh( geometry, defaultMaterial );
scene.add(drawnObject);
pickingScene.add( new THREE.Mesh( pickingGeometry, pickingMaterial ) );
highlightBox = new THREE.Mesh(
new THREE.BoxGeometry( 0.01, 0.01, 0.01 ),
new THREE.MeshLambertMaterial( { color: 0xffff00 }
) );
scene.add( highlightBox );
renderer = new THREE.WebGLRenderer( );
//renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(800, 800);
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
//renderer.domElement.addEventListener('mousemove', onMouseMove );
}
function onMouseMove( e ) {
mouse.x = e.clientX;
mouse.y = e.clientY;
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function pick() {
//render the picking scene off-screen
renderer.render( pickingScene, camera, pickingTexture );
//create buffer for reading single pixel
var pixelBuffer = new Uint8Array( 4 );
//read the pixel under the mouse from the texture
renderer.readRenderTargetPixels(pickingTexture, mouse.x, pickingTexture.height - mouse.y, 1, 1, pixelBuffer);
//interpret the pixel as an ID
var id = ( pixelBuffer[0] << 16 ) | ( pixelBuffer[1] << 8 ) | ( pixelBuffer[2] );
var data = pickingData[ id ];
if (data) {
//move our highlightBox so that it surrounds the picked object
if ( data.position && data.rotation && data.scale ){
highlightBox.position.copy( data.position );
highlightBox.rotation.copy( data.rotation );
highlightBox.scale.copy( data.scale ).add( offset );
highlightBox.visible = true;
}
} else {
highlightBox.visible = false;
}
}
function render() {
controls.update();
pick();
renderer.render( scene, camera );
}
any help is greatly appreciated..
Thanks
You can pass in the canvas as an argument to the TrackballsControls constructor.
var controls = new THREE.TrackballControls(camera, renderer.domElement);
That should solve the problem.
EDIT: included a working example,
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, 400 / 300, 1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(400, 300);
document.body.appendChild(renderer.domElement);
var controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 4;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
var render = function() {
requestAnimationFrame(render);
controls.update();
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
could not get your code to run at all so..

Resources