Problems getting camera navigation working in threejs - javascript

I'm trying to work out camera navigation functionality in threejs, using THREE.OrbitControls. Even though I'm following a guide, I just can't seem to get it working.
The link to my fiddle code is: https://jsfiddle.net/Matty1/uc671jbL/18/
It's on line 18/19 of the javascript:
const controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.update();
Any advice would be appreciated.

You have included OrbitControls from a relative path in your fiddle. Try it like so:
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x19d7f8);
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,5);
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener('resize', function(){
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width/height;
camera.updateProjectionMatrix;
} )
const controls = new THREE.OrbitControls( camera, renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.124/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.124/examples/js/controls/OrbitControls.js"></script>

Related

THREE.JS canvas not responsive after landscape mode

my three.js canvas is not responsive on ios
when I go to landscape mode on iPhone 12 the canvas is not responsive. it becomes small an squarish, and when I go back to portrait mode it stays in this new size (small square)
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.01,1000);
var clock = new THREE.Clock();
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener ('resize', ()=> {
renderer.setSize(window.innerWidth,window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
})
var rmapped = 0;
const controls = new OrbitControls( camera, renderer.domElement );
var loader = new GLTFLoader();
scene.background = new THREE.Color(0x000000)
const cube = new THREE.BoxGeometry( 1,1,1 );
var light1 = new THREE.PointLight( 0xff0040, 2, 50 );
light1.add( new THREE.Mesh( cube, new THREE.MeshBasicMaterial( { color: 0xff0040 } ) ) );
scene.add( light1 );
var light2 = new THREE.PointLight( 0x0040ff, 2, 50 );
light2.add( new THREE.Mesh( cube, new THREE.MeshBasicMaterial( { color: 0x0040ff } ) ) );
light2.position.x=3;
var light2Obj = new THREE.Object3D();
light2Obj.add(light2);
scene.add(light2Obj);
camera.position.set(0, 5, 10);
function animate(){
requestAnimationFrame(animate);
light1.rotateY(0.005);
light2Obj.rotateY(0.009);
renderer.render( scene, camera );
function render() {
renderer.render( scene, camera );
}
}
animate()
Any idea of what the problem is ? seems to work on Android.
read somewhere that resizeobserver api could be a solution but i cannot figure it out
this is what it looks like
lanscape mode:
https://i.stack.imgur.com/LXnnz.jpg
back to portrait mode
https://i.stack.imgur.com/QjkBR.jpg

How to center three js object into DIV:

I cannot center three js object into DIV
Here is my code:
import * as THREE from 'https://cdn.skypack.dev/pin/three#v0.128.0-iDyvDZdRCoyR9DXa2rWg/mode=imports,min/optimized/three.js';
const container = document.getElementById("canvas");
// const selected = document.querySelector("#canvas");
// document.body.appendChild(container);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( container.offsetWidth, container.offsetWidth );
// renderer.setSize( item.clientWidth, item.clientHeight );
container.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
const animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
And that's how the problem looks:
Object just going outside the DIV:
I dont know why it happens. I'm trying to fix this a couple of days and try a lot of ways and it still does not work. Probably I don't understand something and need your help...
I guess i solved the problem. I just delete padding of the #canvas in css and its now work as expected.

Three.js — Uncaught TypeError: THREE.OrbitControls is not a constructor

I am trying to add Orbit Controls to my scene without success. The code below keeps giving me an error Uncaught TypeError: THREE.OrbitControls is not a constructor. I have tried different solutions I came across the web but, the error still persists. What am I doing wrong?
Pseudocode
Add Orbit Controls
Be able to use Orbit Controls in the scene
Thank you in advance.
Codepen
HTML
<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.js"></script>
<script src="https://82mou.github.io/threejs/js/OrbitControls.js"></script>
</body>
</html>
JS
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
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 );
// CAMERA
var camera = new THREE.PerspectiveCamera(75, 320 / 240, 1, 1000);
camera.position.set(250, 200, 250);
camera.lookAt(0, 0, 0);
// add controls for the camera
var controls = new THREE.OrbitControls(camera);
var geometry = new THREE.PlaneGeometry(100, 50);
var material = new THREE.MeshBasicMaterial( { color: 0xFFFFFF } );
var plane = new THREE.Mesh( geometry, material );
scene.add( plane );
camera.position.z = 200;
var animate = function () {
requestAnimationFrame( animate );
controls.update();
// plane.rotation.x += 0.01;
// plane.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
There is an issue in your codepen. When you import OrbitControls via ES6 imports, it's not necessary to use the THREE namespace. So when doing something like this:
import { OrbitControls } from "https://unpkg.com/three#0.112/examples/jsm/controls/OrbitControls.js";
you have to to create OrbitControls like so:
controls = new OrbitControls( camera, renderer.domElement );
Live example: https://jsfiddle.net/68kzagry/1/

Three js renderer size issues. Trying to set a perfect size

I've been working on three js model , to embed the model to my website. Finally made it but there's only one problem.I couldn't get the renderer.setSize() to fit my div. In other words, I can see scroll bar which I don't want to see there. How do I setSize so that it perfectly fits my canvas ?
I saw one post regarding the same problem , he wanted to avoid scrolling as well. I tried to follow the answer as stated in the post but nothing's going on. Then I headed to three js documentation , followed what stated there.
.setSize ( width : Integer, height : Integer, updateStyle : Boolean ) : null
Still couldn't figure it out. Why even the code in documentation is not working ? BUT , i'm not sure if I found a trick , I was just playing around with the setSize values.
renderer.setSize( window.innerWidth * 0.99 ,window.innerHeight * 0.99);
as you can see there , I added * 0.99 , and there's no more scroll bar! Didn't mean to do it this way , but what's the correct code to adjust it ? Here's my code
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>THEE JS BOX APP</title>
<style>
body { margin: 0; width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/OBJloader.js"></script>
<script>
// CREATING AN EMPTY SCENE
var scene = new THREE.Scene();
// CAMERA
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 9000 );
camera.position.z = 200;
// ORBIT CONTROL
var controls = new THREE.OrbitControls( camera );
// RENDERER
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#ffffff");
renderer.setSize( window.innerWidth * 0.99 ,window.innerHeight * 0.99);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// APPEND RENDERER TO DOM
document.body.appendChild( renderer.domElement );
// WINDOW RESIZE
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
// instantiate a loader
var loader = new THREE.OBJLoader();
// load a resource
loader.load(
// resource URL
'img/logovoivode1.obj',
// called when resource is loaded
function ( object ) {
scene.add( object );
},
// called when loading is in progresses
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened' );
}
);
// ***************************** LIGHTING **********************************//
// White directional light at half intensity shining from the top.
//var directionalLight = new THREE.DirectionalLight( 0xffffff, 5 );
//scene.add( directionalLight );
var light = new THREE.AmbientLight( 0xffffff, 0.5); // soft white light
scene.add( light );
var pointlight = new THREE.PointLight( 0xffffff, 0.5, 1000);
light.position.set(10, 0, 25);
scene.add(pointlight);
//var DLight = new THREE.DirectionalLight( 0xffffff, 50);
//scene.add(DLight);
// var spotlight = new THREE.SpotLight( 0xffffff, 0.5, 1000, 0.3);
// ************************ END-OF-LIGHTING *****************************//
// CREATING A BOX
// var geometry = new THREE.BoxGeometry(1, 1, 1);
// var material = new THREE.MeshBasicMaterial({ color: 0xffffff, wireframe:true});
// var cube = new THREE.Mesh( geometry, material);
// ADD CUBE TO THE SCENE
// scene.add(cube);
// ANIMATION LOOP
function animate() {
requestAnimationFrame( animate );
//scene.rotation.x += 0.01;
//scene.rotation.y += 0.01;
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
Your issue is caused by "inner element whitespaces".
When an html parser parses your source code, it also parses the spaces/entets/tabs between your tags as text, and then makes it smaller till its just 1 space. This 1 space is the cause of your issue, but knowing what causes it is the first step to solving the problem.
Original problem, for reference:
body {
margin: 0;
width: 100%;
height: 100%;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/OrbitControls.js"></script>
<script>
// CREATING AN EMPTY SCENE
var scene = new THREE.Scene();
// CAMERA
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 9000 );
camera.position.z = 200;
// ORBIT CONTROL
var controls = new THREE.OrbitControls( camera );
// RENDERER
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#ffffff");
renderer.setSize( window.innerWidth ,window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// APPEND RENDERER TO DOM
document.body.appendChild( renderer.domElement );
// WINDOW RESIZE
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
scene.add( new THREE.Mesh( new THREE.CubeGeometry(100,130,70), new THREE.MeshBasicMaterial({ color: 0x444444 }) ) );
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
</script>
Using font-size: 0
By setting the font-size to 0, you basically squash the space to PX width and height, making sure it doesn't contribute to your problem
body {
margin: 0;
width: 100%;
height: 100%;
font-size: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/OrbitControls.js"></script>
<script>
// CREATING AN EMPTY SCENE
var scene = new THREE.Scene();
// CAMERA
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 9000 );
camera.position.z = 200;
// ORBIT CONTROL
var controls = new THREE.OrbitControls( camera );
// RENDERER
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#ffffff");
renderer.setSize( window.innerWidth ,window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// APPEND RENDERER TO DOM
document.body.appendChild( renderer.domElement );
// WINDOW RESIZE
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
scene.add( new THREE.Mesh( new THREE.CubeGeometry(100,130,70), new THREE.MeshBasicMaterial({ color: 0x444444 }) ) );
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
</script>
Using overflow: hidden
Just take our problems, and hide them for the next person trying to fix it properly.
body {
margin: 0;
width: 100%;
height: 100%;
}
html, body {
overflow: hidden;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/OrbitControls.js"></script>
<script>
// CREATING AN EMPTY SCENE
var scene = new THREE.Scene();
// CAMERA
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 9000 );
camera.position.z = 200;
// ORBIT CONTROL
var controls = new THREE.OrbitControls( camera );
// RENDERER
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#ffffff");
renderer.setSize( window.innerWidth ,window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// APPEND RENDERER TO DOM
document.body.appendChild( renderer.domElement );
// WINDOW RESIZE
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
scene.add( new THREE.Mesh( new THREE.CubeGeometry(100,130,70), new THREE.MeshBasicMaterial({ color: 0x444444 }) ) );
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
</script>
Using display: flex
When you use the flex display mode, the browser ignores all inner white spaces in the current element
body {
margin: 0;
width: 100%;
height: 100%;
display: flex;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/OrbitControls.js"></script>
<script>
// CREATING AN EMPTY SCENE
var scene = new THREE.Scene();
// CAMERA
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 9000 );
camera.position.z = 200;
// ORBIT CONTROL
var controls = new THREE.OrbitControls( camera );
// RENDERER
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#ffffff");
renderer.setSize( window.innerWidth ,window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// APPEND RENDERER TO DOM
document.body.appendChild( renderer.domElement );
// WINDOW RESIZE
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
scene.add( new THREE.Mesh( new THREE.CubeGeometry(100,130,70), new THREE.MeshBasicMaterial({ color: 0x444444 }) ) );
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
</script>
Setting the display of the canvas to block
If you set the display property of the canvas to block, then you don't have to worry about the inner element white spaces, as they don't have anny effect between block elements.
body {
margin: 0;
width: 100%;
height: 100%;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/OrbitControls.js"></script>
<script>
// CREATING AN EMPTY SCENE
var scene = new THREE.Scene();
// CAMERA
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 9000 );
camera.position.z = 200;
// ORBIT CONTROL
var controls = new THREE.OrbitControls( camera );
// RENDERER
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#ffffff");
renderer.setSize( window.innerWidth ,window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// APPEND RENDERER TO DOM
document.body.appendChild( renderer.domElement );
// WINDOW RESIZE
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
scene.add( new THREE.Mesh( new THREE.CubeGeometry(100,130,70), new THREE.MeshBasicMaterial({ color: 0x444444 }) ) );
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
</script>

Rendering blank screen when trying to play animation in threejs

I'm trying to animate an exported model(from 3dsmax -> dae file -> json) with animations using three.js. I am not getting any console errors but rather just a blank screen. Anyone have any ideas on why this is happening? I'm happy to also include json, png's, max file, dae file or any other resource that may be of help. Any help would be much appreciated. I'm stuck...here is the javascript:
<script>
var camera, scene, renderer, animmesh;
var clock = new THREE.Clock();
function init() {
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 5;
scene = new THREE.Scene();
scene.add(camera);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var loader = new THREE.JSONLoader();
loader.load("../../assets/model-threejs.json", function (model, material) {
createScene(model, material);
});
}
function createScene(model, material) {
material[0].skinning = true;
animmesh = new THREE.SkinnedMesh(model, material[0]);
scene.add(animmesh);
}
function render() {
renderer.render(scene, camera);
}
init();
render();
</script>
You had several problems. 1) Your elephant was so big it was off the screen. 2) You need to tell the camera to look at the origin. 3) When you simplified the code you made it too simple, you still need the animate loop.
This code works (since I didn't have your PNG files, I used a MeshNormalMaterial):
var camera, scene, renderer, animmesh, controls;
var clock = new THREE.Clock();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.x = -900;
scene.add(camera);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth*.9, window.innerHeight*.9 );
document.body.appendChild( renderer.domElement );
var loader = new THREE.JSONLoader();
loader.load("model-threejs.json", function (model, material) {
animmesh = new THREE.Mesh(model, new THREE.MeshNormalMaterial());
scene.add(animmesh);
animate();
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render(scene, camera);
camera.lookAt(new THREE.Vector3(0,0,0));
}
init();

Categories