How to look around a scene in first person in Three.JS? - three.js

I have rendered a simple cube in Three.JS to the screen, now the way I have found online is that I need to use PointerLockControls.js lock the mouse and look around the scene. I have managed to look the cursor and hide it using this, however I am unsure how I go about implementing "look around"
Here is my code so far:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="javascript/three.js"></script>
<script src="javascript/PointerLockControls.js"></script>
<script>
var scene, camera, renderer, geometry, material, cube;
var init = function(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
geometry = new THREE.BoxGeometry();
material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
document.addEventListener("mousedown", doMouseDown, false);
//const controls = new PointerLockControls( camera, document.body);
controls = new THREE.PointerLockControls( camera, document.body );
}
function doMouseDown(event){
controls.lock();
}
function render() {
renderer.render( scene, camera );
};
init();
render();
</script>
</body>
</html>

By "looking around", I assume you want to move the camera around?
This may be a start for you.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
#js3canvas { width:800px; height:600px; }
</style>
</head>
<body>
<canvas id="js3canvas"></canvas>
<script src="javascript/three.js"></script>
<script>
var scene, camera, renderer, geometry, material, cube;
var canvaselt = document.getElementById("js3canvas");
var init = function(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, canvaselt.clientWidth/canvaselt.clientHeight, 0.1, 1000 );
renderer = new THREE.WebGLRenderer( { canvas:canvaselt } );
renderer.setSize(canvaselt.clientWidth, canvaselt.clientHeight);
geometry = new THREE.BoxGeometry();
material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
canvaselt.addEventListener("mousemove", doMouseMove, false);
}
function doMouseMove(ev) { // point camera
camera.lookAt((ev.pageX-400)/100, -(ev.pageY-300)/100, 0);
}
function animate() { // need to animate, not just render once
renderer.render( scene, camera );
requestAnimationFrame( animate );
}
init();
animate();
</script>
</body>
</html>

Related

How to move the Sphere using mouse in three.js? (Uncaught ReferenceError: OrbitControls is not defined)

I was making a sphere that can be moved by a mouse using three.js but the output is just a black screen as shown.
The code I used is:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 0, 0, 50 );
camera.lookAt( 0, 0, 0 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.SphereGeometry( 15, 32, 16 );
const texture = new THREE.TextureLoader().load( 'https://i.imgur.com/kFoWvzw.jpg' );
const material = new THREE.MeshBasicMaterial( { map: texture } );
const sphere = new THREE.Mesh( geometry, material );
const controls = new OrbitControls( camera, renderer.domElement );
controls.mouseButtons = {
LEFT: THREE.MOUSE.ROTATE,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.PAN
}
controls.update();
scene.add( sphere );
function animate()
{
requestAnimationFrame( animate );
sphere.rotation.x += 0.01;
sphere.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
</script>
</body>
</html>
I couldn't explain why the code was unable to render the sphere. What went wrong?
Thank you!
Like the error message indicates, you are trying to use OrbitControls but it cannot be found. This is because it is not part of the core THREE.js library, but it is in the THREE.js examples directory so you need to import it separately.
You can import it through an HTML script tag like you do with THREE.js:
<script src="path/to/your/local/file/OrbitControls.js">.
Notice also that if you import it in your HTML, you should call it as
const controls = new THREE.OrbitControls(...);
as the js/ file adds the class to the THREE object.
See the docs or the source.
This is the complete code on how to move the camera on the Sphere.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three#0.143/build/three.min.js"></script>
<script src=".\three.js-master\three.js-master\examples\js\controls\OrbitControls.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 0, 0, 50 );
camera.lookAt( 0, 0, 0 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.SphereGeometry( 15, 32, 16 );
const texture = new THREE.TextureLoader().load( 'https://i.imgur.com/kFoWvzw.jpg' );
const material = new THREE.MeshBasicMaterial( { map: texture } );
const sphere = new THREE.Mesh( geometry, material );
const controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.update();
scene.add( sphere );
function animate()
{
requestAnimationFrame( animate );
sphere.rotation.x += 0.01;
sphere.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
</script>
</body>
</html>
This is the correct code on how to move the camera on the Sphere...:-)

Change the color of 3D model using colorPicker three.js

I am trying to change the color of 3D object where intersected using color picker.I am trying with dat.gui.I want to change the color of 3d part where it gets clicked and change the selected from the colorPicker.I tried out some possible ways but it doesn't work out.Please,refer to the code I tried out. Help me out with some solution and draw my attention to where I am getting wrong. Thanks.
<!DOCTYPE html>
<html lang="en">
<head>
<title>color</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: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<script src="Detector.js"></script>
<script src="stats.min.js"></script>
<script src="loaders/MTLLoader.js"></script>
<script src="loaders/OBJLoader.js"></script>
<script type='text/javascript' src='DAT.GUI.min.js'></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer,effectController;
var raycaster;
var objects = [];
var selectedObject,selectedPos;
var rotation;
var pos,quat;
var INTERSECTED;
var guiColor;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 15;
controls = new THREE.OrbitControls( camera );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x555000 );
scene.add( camera );
// light
var dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( 200, 200, 1000 ).normalize();
camera.add( dirLight );
camera.add( dirLight.target );
var mtlLoader = new THREE.MTLLoader(); mtlLoader.setBaseUrl('assets/'); mtlLoader.setPath('assets/'); mtlLoader.load('anno.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('assets/');
objLoader.load('anno.obj', function (object) {
scene.add( object );
objects.push( object );
});
});
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
/* Controls */
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = false;
raycaster = new THREE.Raycaster();
gui = new dat.GUI();
parameters =
{
color: "#ff0000",
};
gui.add( parameters, 'reset' ).name("Reset");
guiColor = gui.addColor( parameters, 'color' ).name('Color');
container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
window.addEventListener( 'resize', onWindowResize, false );
renderer.domElement.addEventListener("click", onclick, false);
}
var mouse = new THREE.Vector2();
function onclick(event) {
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, true);
if (intersects.length > 0) {
INTERSECTED = intersects[0].object;
if ( INTERSECTED && INTERSECTED.material.emissive != null ){
guiColor.onChange(function(){
INTERSECTED.material.emissive.setHex(parameters.color)
});
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
I've create a little live demo with your code and a basic working solution. I'd like to highlight three important changes:
You can use the onChange() event handler in order to know when a certain dat.gui property has changed. The demo uses this feature to update the color of a selected object.
I have refactored your raycasting logic into something more simple. I've seen you've copied some code from the official three.js examples but the new code should be sufficient for your case. Besides, it's also better to update Material.color instead of Material.emissive.
If you set OrbitControls.enableDamping to true, you have to update the controls in your animation loop.
https://jsfiddle.net/btuzd23o/2/
three.js R103

three.js GLTFloader Geometry and Material

How do I see geometry and material with GLTFLoader in three.js? Right now it's a blank white page. Sorry this is my 2nd day on three.js, I don't think I understood completely on the manual.
https://threejs.org/docs/#examples/loaders/GLTFLoader
<html>
<head>
<title>demo</title>
<style>
body {margin: 0; overflow: hidden;}
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script src="three.min.js"></script>
<script src="GLTFLoader.js"></script>
<script>
var renderer, scene, camera, myCanvas = document.getElementById('myCanvas');
var renderer = new THREE.WebGLRenderer({ canvas: myCanvas, antialias: true });
renderer.setClearColor(0xffffff);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
var camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 300, 10000);
var scene = new THREE.Scene();
var light = new THREE.AmbientLight(0xffffff, 0.8);
var light2 = new THREE.PointLight(0xffffff, 0.5);
scene.add(light);
scene.add(light2);
var loader = new THREE.GLTFLoader();
loader.load('model.gltf', function (gltf) {
scene.add(gltf.scene);
});
requestAnimationFrame(render);
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
</script>
</body>
</html>
Your camera near plane is super far away.. I also notice you don't position your camera initially.. it's probably starting inside the object..
or your object is too large or too small to see because it's behind the camera near clip plane..
try this:
var camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(100,100,100);
camera.lookAt(new THREE.Vector3(0,0,0));

Interact/rotate object using Three.js

I am using the basic example on three.js but am unable to interact with the object to rotate via mouse interaction. Am I missing something obvious? My desired functionality is to rotate an object (such as a box) left,right,up,down, etc. The code I am using is as follows:
<!DOCTYPE html>
<script src="scripts/three.min.js"></script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My first Three.js app</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script src="scripts/three.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.BoxGeometry( 3, 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 );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
You are missing EventListeners, your scene doesnt know about your mouse moving.
See this simple example from mr.doob on how to spin a cube with the mouse:
http://mrdoob.github.io/three.js/examples/canvas_geometry_cube.html
Similiar to the rotation on the Y-Axis (left, right) you can add rotation on the X-Axis (up, down) too.

Three js Cannot see the sphere

I am just looking at the documentation on the threejs.org website and thought I would give making a sphere a shot, here is what I have quickly mocked up:
<!DOCTYPE html>
<html>
<head>
<title>Sphere</title>
<style>canvas { width: 100%; height: 100% }</style>
</head>
<body>
<script type="text/javascript" src="../../threejs/build/Three.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.SphereGeometry(5, 32, 32);
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var sphere = new THREE.Mesh(geometry, material);
sphere.overdraw = true;
scene.add( sphere );
camera.position.z = 5;
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
</script>
</body>
</html>
Trouble I see no sphere, there are no errors in the console either...could someone help with this one.
Seems like the camera is at the edge of the sphere. Try camera.position.z = 20;.

Resources