I'm working with Three.JS and I need a cube to fit the size of the window. The cube will always respect the proportion of the window (window.innerWidth and window.innerHeight) but causes the Z position depending on the display ratio closer or farther away.
cube = new THREE.Mesh( new THREE.CubeGeometry( windowWidth, windowHeight, 200, 6, 6, 6, materials ), new THREE.MeshFaceMaterial() );
cube.position.y = ???;
cube.position.z = ???;
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
renderer.setSize( window.innerWidth, window.innerHeight );
camera.updateProjectionMatrix();
cube.position.y = ???;
cube.position.z = ???;
}
Can you think of a solution?
If I understood right you are having problems with the cube Z position.
Well, first of all I would not recommend you to set the position on windowresize() and would say do it on animate. Such as:
function animate() {
cube.position.z = camera.position.z
}
Forgive me but I can't understand any further.
Related
I have a basic function to move my camera as it scrolls but it starts facing backwards and as soon as I do the first scroll it flips around the right way and works as intended. (I'm also very new to coding)
NOTE : there is much more code for other functions and stuffs that I have left out.
const scene = new THREE.Scene();
//Camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
//Renderer
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#bg'),
});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
camera.position.setZ(30);
renderer.render( scene, camera );
//Scrolling to move
function moveCamera(){
const t = document.body.getBoundingClientRect().top;
camera.position.z = t * -0.01;
camera.position.x = t * -0.0002;
camera.rotation.y = t * -0.0002;
}
document.body.onscroll = moveCamera```
I figured it using a simple method :
console.log(camera.position.z) to see where the camera was at each scroll.
It was dipping into the negatives so I wrote a simple if statement to set it back to 0.1 if it ever gets < 0.1
if(camera.position.z < 0.1){
camera.position.z = 0.1
}
I have simple three.js scene (canvas) which I want to respond upon window resize event (particularly change in the width of the screen, keeping height constant).
In normal situation i use window.innerWidth, window.innerHeight property to set the size of canvas to match the window size.
However I want to embed three scene in the html.
So I have put three canvas in <div id="three-container">.
In following code when I resize the window (even width only) the height of the canvas keeps growing. Where is the bug? What am I missing?
To get the size of div container I have tried container.clientWidth, container.offsetWidth and $('#three-container').width() (and height respectively), but for all cases the initial height of div is 0 and keeps growing on resize.
Full code listing:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>default</title>
<link rel="icon" href="">
</head>
<body>
<div id='three-container' class= "row"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"></script>
<script>
var renderer, scene, camera, cube;
var time = 0.0;
var container = window.document.getElementById( 'three-container' );
var w = 100; //container.clientWidth; // container.offsetWidth
var h = 100; //container.clientHeight; // container.offsetHeight
init();
loop();
function init() {
camera = new THREE.PerspectiveCamera( 45, w / h, 1, 1000 );
scene = new THREE.Scene();
scene.add( camera );
camera.position.z = 16;
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0xa696969 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( w, h );
container.appendChild( renderer.domElement );
var geo = new THREE.BoxGeometry( 5, 5, 5);
var mat = new THREE.MeshBasicMaterial({ color: 0xffffff, wireframe: true } );
cube = new THREE.BoxHelper( new THREE.Mesh( geo, mat ), mat.color );
scene.add( cube );
window.addEventListener( 'resize', function onWindowResize() {
w = container.clientWidth; // container.offsetWidth
h = container.clientHeight; // container.offsetHeight
console.log( " w : " + w + " h : " + h);
renderer.setSize( w, h );
camera.aspect = w / h;
camera.updateProjectionMatrix();
}, false );
}
function loop() {
time += 0.01;
requestAnimationFrame( loop );
cube.rotation.x = time ;
cube.rotation.y = time ;
renderer.render( scene, camera );
}
</script>
</body>
</html>
line-height:0; css-property does the trick and keeps the container's height.
#three-container {
line-height:0;
}
The idea to use this property comes from this SO question
jsfiddle example
It's happening because the container DIV is actually 104px high initially, even though the CANVAS is 100px high. I looked in F12 but couldn't see an obvious reason, such as padding. So you then set the canvas to 104px which makes the div 108px, and so on.
A quick fix is to account for the 4, and this shows you that the above is the problem.
renderer.setSize( w, h - 4 );
I'm afraid though you will need to find a more robust way to find the difference in height.
As you can see below, I added a mesh to the scene but everytime I try to scale it or set position, I get an error that the mesh is null.
mesh2.position.set(0,0,-5);
mesh2.scale.set(0.2, 0.3, 0.2);
Uncaught TypeError: Cannot read property 'position' of null
check it out at testing2.site44.com
Please help as I have wasted hours trying to get this to work.
function init()
{
var scene = new THREE.Scene();//CREATE NEW THREE JS SCENE
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var renderer = new THREE.WebGLRenderer({antialias:true}); //INIT NEW THREE JS RENDERER
renderer.setPixelRatio( window.devicePixelRatio ); //SET PIXEL RATIO FOR MOBILE DEVICES
renderer.setClearColor(new THREE.Color('#005b96'), 1) //SET BG COLOR
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); // SET SIZE
document.body.appendChild( renderer.domElement ); //APPLY CANVAS TO BODY
renderer.domElement.id = "canvas_threeJS";//ADD ID TO CANVAS
//ADD CAMERA TO THE SCENE
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR =1000;
var camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(0,3,8); //SET CAMERA POSITION
camera.lookAt(new THREE.Vector3(0,0,-5));
scene.add(camera);
//ADD AMBIENT LIGHT
var ambientLight = new THREE.AmbientLight("#6497b1");
scene.add(ambientLight);
//HANDLE WINDOW RESIZE
//ADD MAIN LIGHT
var light = new THREE.PointLight("#b3cde0",.6);
light.position.set(-5,13,-1);
scene.add(light);
var mesh2 = null;
var loader = new THREE.JSONLoader();
loader.load('assets/models/spaceship001.json', function(geometry) {
mesh2 = new THREE.Mesh(geometry);
scene.add(mesh2);
console.log("done loading model");
});
mesh2.position.set(0,0,-5);
// mesh2.scale.set(0.2, 0.3, 0.2);
//START POSITION OF A LEVEL GROUP
var levelSpawn = -100;
//GET VISIBLE WIDTH AT levelSpawn POSITION
var vFOV = camera.fov * Math.PI / 180; // convert vertical fov to radians
var height = 2 * Math.tan( vFOV / 2 )*levelSpawn; // visible height
var aspect = window.innerWidth / window.innerHeight;
var width = height * aspect;// visible width
//START RENDER
update();
function update()
{
//UPDATE 3D SCENE
renderer.render( scene, camera );
//KEEP RENDERING
requestAnimationFrame( update );
}
}
The problem is that javascript is an asynchronous language. Depending on your background you should read up on that. Try putting a console.log("setting scale and postion") just under or above those two lines. What you'll notice is that the position and scale is set before the mesh is loaded.
What you need to do is set the position and scale inside the callback function that you pass to the load function, just under the console.log("done loading model"); line.
You can also read up on javascript Promises to understand it better.
I am trying out Three.js and I am trying to position a SpotLight at the position of the camera. I use the following code (stripped window creation):
$(document).ready(function() {
init();
});
function init() {
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set(50, 10, 0);
camera.lookAt(new THREE.Vector3(0, 0, 0));
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position = camera.position;
console.log(camera.position);
console.log(spotLight.position);
}
I get as output that camera.position is 50,10,0 (as expected) but spotLight.position is 0,1,0 - even tough I just set it to point at the same value?
Try
spotLight.position.set(camera.position.x, camera.position.y, camera.position.z)
position is read-only
Since SpotLight and Camera are objects (Object3D), you can simply add the spotlight to the camera. The light will be moved, rotated etc. with the camera without any further position copying. In this case you have to position the light relative to the camera:
camera.add(spotLight);
spotLight.position.set(0,0,1);
spotLight.target = camera;
I'm trying to build 3 red Spheres with three.js...with no luck :-(
Now this is my code...anybody can tell me what I'm doing wrong??
The only thing I see is one red sphere...
var camera, scene, renderer,
mouseX = 0, mouseY = 0;
init();
function init() {
// Camera params :
// field of view, aspect ratio for render output, near and far clipping plane.
camera = new THREE.Camera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
// move the camera backwards so we can see stuff!
// default position is 0,0,0.
camera.position.z = 1000;
// the scene contains all the 3D object data
scene = new THREE.Scene();
// and the CanvasRenderer figures out what the
// stuff in the scene looks like and draws it!
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
// the renderer's canvas domElement is added to the body
document.body.appendChild( renderer.domElement );
makeParticles();
// add the mouse move listener
document.addEventListener( 'mousemove', onMouseMove, false );
// render 30 times a second (should also look
// at requestAnimationFrame)
setInterval(update,1000/30);
}
function update(){
//updateParticles();
// and render the scene from the perspective of the camera
renderer.render( scene, camera );
}
function makeParticles() {
var geometry,material,mesh;
// create a sphere shape
geometry = new THREE.SphereGeometry( 50, 16, 16 );
// give a shape red color
material = new THREE.MeshLambertMaterial({color: 0xFF1111});
// create an object
mesh = new THREE.Mesh( geometry, material );
mesh.position.x = 0;
// add it to the scene
scene.addObject( mesh );
}
// called when the mouse moves
function onMouseMove( event ) {
// store the mouseX and mouseY position
mouseX = event.clientX;
mouseY = event.clientY;
}
Kind of late, but if all your spheres are in the same position (mesh.position.x = 0;) you will only see one sphere.