three.js cube resize - javascript

My code with three.js is this:
cube = new THREE.Mesh(new THREE.CubeGeometry(200, 200, 200, 1, 1, 1, materials), new THREE.MeshFaceMaterial());
cube.position.y = 150;
cube.position.x = 0;
scene.add(cube);
But when i render my Cube the size of this cube is always different. I try to explain better.
Every time I resize my browser and refresh the page the cube size is different. Is possible set the cube size fixed? Also if the window resize!'

You can set a fixed size to the renderer:
renderer.setSize(WIDTH, HEIGHT);
Take a loot at this simple example: http://jsfiddle.net/9stj8/
Also check if your code is handling the window resize event.

I know this question has already been answered, but I wanted to submit a little something for posterity sake, and the frustration levels of those who follow in our steps.
Three.js uses a camera object to provide a view on your 3d scene. I've been primarily working with the Perspective Camera (instead of the orthographic camera, sorry can't help you at this time if you are using the ortho cam.), and I happened to stumble across the solution to the problem you are discussing. The perspective takes certain parameters upon creation:
fov (an angle that determines the vertical field of view
aspect ratio (width / height value) <-- Important!
near clipping plane (scalar value of when a object is close enough to be considered "behind" the camera lens, and therefore no longer visible)
far clipping plane (scalar value of when an object is far enough away to be considered invisible to the camera
Since the browser window is your view port, often we use the browser window properties to set up the camera's aspect ratio. Since these properties set up the camera to render properly (if there is a mismatch between viewport size and camera/renderer settings, your image will come out smashed/squished/distorted, if it comes out at all), if the browser window is resized the camera values no longer match values that the camera is using to render the scene.
As Juan Mellado pointed out, you change the size of the viewport using the renderer.setSize(w,h) method. If you want the window resize changes to also update the renderer and the camera, do this:
function onResize()
{
var width, height;
width = window.innerWidth; // for example
height = window.innerHeight; // for example
//First update the camera's aspect ratio: width / height
camera.aspect = width/height;
//Whenever you make a change to the camera,
//you must update for your changes to take effect
camera.updateProjectionMatrix();
//Here we reset the size of the window to the new height
renderer.setSize(width, height);
}
Now that we have declared a callback function that can handle updating the camera and renderer, don't forget to bind it to the window.resize event. I just use jQuery to do that:
jQuery(window).resize(onResize);
or
window.onresize = onResize;
Recap:
1.) The values used to calculate Camera Aspect Ratio must match the values passed as the renderer size values.
2.) If you want the camera aspect ratio and the renderer size values to scale with the size of the browser, you must bind a callback function to the window.onresize event to do that.
3.) If you make a change to the camera, after its been created, you must call "updateProjectionMatrix()" to update the camera's internal values in order for your changes to take effect.
If all goes well, when you change the window size, the camera aspect ratio and the renderer size will automatically scale with the window size.
Cheers and happy coding!

Related

Fit object group to page centre without breaking OrbitControls

What I have is an OrthographicCamera set up so that is has an isometric view of the scene and OrbitConrols added to allow for panning around and zooming but not for rotation.
What I’d like to have is a button that will centre the objects in a scene and zoom the OrthographicCamera so that the objects fit within the canvas area while keeping the isometric view, i.e. the angle between the camera.position and the camera.lookAt (control.target) point.
What I’ve tried is to set the controls.target at the centre of the bounding box of the objects in the scene.
I have 2 problems with the code at the moment.
The First is I couldn’t work out how to calculate the zoom level needed to make sure the objects in the scene are all in view. I’ve hard coded a value for just now.
The Second is that with the current code, if the camera is panned so that the objects appear nearly off the screen, either up or down, then when centred the angle of the camera changes. This was happening when the camera was panned far left or right but setting the max and min Azimuth Angle seems to prevent this.
camera rotates after centring
The image above shows the scene when loaded then after centering when the camera was panned so the objects were going off the top of the screen.
I have tried a number of ways to do this after looking at answers to similar questions as this but am still having problems getting it to work.
function fitDrawingToPage(){
// Variables Bbox etc are set outside the function
Bbox = new THREE.Box3();
for (const object of sceneObjects) Bbox.expandByObject(object);
newTarget = Bbox.getCenter(new THREE.Vector3());
controls.target.set( newTarget.x, newTarget.y, newTarget.z );
controls.update();
camera.zoom = 0.5;
camera.updateProjectionMatrix();
camera.updateMatrix();
render();
}
current example of code in jsfiddle

Three.js - Take up all available space with plane geometry (emulate background-size:cover property)

I would like to build a three.js scene containing a large plane geometry that should take up all the available space, regardless of the aspect ratio of the viewport.
I have made a rough fiddle to highlight the issue: https://jsfiddle.net/nq2oy9ca/1/
Using the following resize function:
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth/window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
});
the image is only scaled if there are changes to the y axis of the viewport - it doesn't react to changes on the x axis.
This means that it will take up all space only if the viewport has a narrow aspect ratio: if the aspect ratio becomes wide enough, the background will become visible to the the left and the right.
Removing the function prevents the image from being resized at all.
I reckon the result could be achieved by dynamically updating the camera distance ( camera.position.z ) whenever the viewport is resized, but i don't know how that value correlates to the viewport \ canvas size.
Any feedback would be appreciated, thanks in advance!

THREE.js fit Orthographic camera to scene

I've searched through many related questions on stack overflow, but I couldn't quite find the answer to this problem.
I have a big, dynamic group of Object3D's in my scene, with an orthographic camera looking at them head-on.
I want to have a simple function which, when called, will simply match the top/left/bottom/right/zoom properties of the Orthographic camera to properly fit the Object3D group.
I've tried all kinds of things, but none of my code is worth posting. I need to look at this from a whole new angle (pun intended). I have found various other answers which discuss changing the fov of the camera, once you know the distance from the face of bounding box of the group to the camera, but I don't know how to implement that with an orthographic camera, since (as far as I've tried) the fov property doesn't work with it (maybe it actually does, I just don't know).
So I don't particularly like asking for code, but nevertheless I would like a function which would automatically adjsut the appropriate properties of the Orthographic camera to fit the object passed to it as a parameter, for example:
function fitOrthographicCameraToObject3DGroup(group) {
//implement here (my question)
}
Calculate the bounding box of your mesh and apply this code.
This works for me
var camera = new THREE.OrthographicCamera(container.offsetWidth / -2, container.offsetWidth / 2, container.offsetHeight / 2, container.offsetHeight / -2, 100, 100000);
//For centering the meshGroup
var box = new THREE.Box3().setFromObject(meshGroup);
box.center(meshGroup.position);
meshGroup.localToWorld(box);
meshGroup.position.multiplyScalar(-1);
//For fitting the object to the screen when using orthographic camera
Camera.zoom = Math.min(container.offsetWidth / (box.max.x - box.min.x),
container.offsetHeight / (box.max.y - box.min.y)) * 0.4;
Camera.updateProjectionMatrix();
Camera.updateMatrix();
Setting the top/left/bottom/right of the orthographic camera once you have the bounding box should not be a problem. Just take the half lengths of the bounding box.
The zoom is the issue and for that you can confine your scene in a unit cube by scaling up or down your scene by the appropriate amount depending on your bounding box size. Then you dont have to worry about the zoom and the above top/left/bottom/right values become 0.5/0.5/-0.5/-0.5.

Craftyjs scene size

I'm working with crafty on a game with an open world and i want to use the full window screen.
But when i start the game, the scene is not the full width.
I have tried:
Crafty.init(window.innerWidth, window.innerHeight);
Crafty.viewport.init(window.innerWidth, window.innerHeight);
It seems that it takes the biggest sprite width & height and uses that.
But when i try to create a bigger rectangle so it would use that, it still uses that sprites' height & width
Crafty.canvas.init(..) seems to create a new canvas.
How do i create a full size canvas-scene in crafty?
In crafty 0.5.4 in the Crafty.viewport.init() function, the width and height of crafty is initialized as:
this.width = (!w ? w : Crafty.DOM.width (something like that))
same for height
Change Crafty.DOM.width to window.innerWidth and it is fixed
PS. Crafty 0.6(beta) solves this too.

Camera arguments in Three.js

This is how a camera is instantiated:
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR
);
What do these values mean?
I was wondering the same thing so I looked it up, it is a view "frustum".
I'll paste here a code comment I wrote in a recent project because it sums it up nicely IMHO.
// "What the f*** is a frustum?" you ask. Well I did.
// Think about it as a truncated pyramid. The tip is the camera. From a certain
// point "down" the pyramid (the "near plane"), stuff can be seen on-screen.
// After the "base" of the pyramid (the "far plane"), stuff is too far to be
// seen. Stuff outside the pyramid is off-screen too. There is also the "aspect
// ratio" (the rectangle that makes up the pyramid's base, so this value is
// width/height) and the "field of view" (think of it as a lens or something,
// it distorts the pyramid so there's more objects on screen - it is set in
// degrees and 45° is more-or-less a "natural" perspective. The bigger the
// number, the more "perspective" there is).
I found this tutorial very useful for understanding all the camera parameters, and the difference between PerspectiveCamera and OrthographicCamera.
PerspectiveCamera
Fov (Field of view) - This is part of scene that can be seen from the position of the camera. As you probably know, we, humans, have almost 180-degree field of view, while some birds might even have a complete 360-degree field of view. However, for computers, we usually use the field of view between 60 and 90 degrees.
Aspect - The aspect ratio is ratio between the horizontal and vertical size of the area where we render the output. As we usually use the entire window, we will just use that ratio. The aspect ratio determines the difference between the horizontal field of view and the vertical field of view as you can see in the figure on the following page. Ordinary value is window.innerWidth / window.innerHeight.
Near - This property defines a min distance from the camera the Three.js renders the scene. Usually, this is a very small value, e.g. 0.1.
Far - This property defines a max distance we see the scene from the position of the camera. If we set this as too low, a part of our scene might not be rendered; if we set it as too high, in some cases, it might affect the rendering performance. Normal value is between 500 and 2000.
OrthographicCamera
Left (Camera frustum left plane) - You should see this as what is the left border of what will be rendered. If we set this value to -100, you won’t see any objects that are farther to the left.
Right (Camera frustum right plane) - Anything farther to the right won't be rendered.
Top (Camera frustum top plane) - The maximum top position to be rendered.
Bottom (Camera frustum bottom plane) The bottom position to be rendered.
Near (Camera frustum near plane) - From this point on, based on the position of the camera, the scene will be rendered.
Far (Camera frustum far plane) - The furthest point, based on the position of the camera, to which the scene will be rendered.
The following picture should be very illustrative:
The main difference between the two camera modes is that in the OrthographicCamera distance plays no role, so all the elements are of the same size, as you can see in the case of the red and yellow ball.
Finally here is some code you can use to switch from one camera to the other:
this.switchCamera = function(SCENE_WIDTH, SCENE_HEIGHT) {
if (camera instanceof THREE.PerspectiveCamera) {
camera = new THREE.OrthographicCamera( SCENE_WIDTH / - 2, SCENE_WIDTH / 2, SCENE_HEIGHT / 2, SCENE_HEIGHT / - 2, 0.1, 1000 );
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = -1;
camera.lookAt(scene.position);
this.perspective = "Orthographic";
} else {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = -1;
camera.lookAt(scene.position);
this.perspective = "Perspective";
}
};
Notes:
The function camera.lookAt(scene.position) orients the camera to where the scene is located, so it is visible.
Units in three.js are SI units, so the values of left,right,top,bottom should not assumed to be pixels.
The aspect ratio of the camera's frustum should normally match the canvas' aspect ratio.
SCENE_WIDTH, SCENE_HEIGHT, can be determined through the geometries that are added in the scene. The orthographic frustum could be much larger than the scene but it wouldn't be very parsimonious.
Useful links:
http://www.glprogramming.com/red/chapter03.html
Three.js - Orthographic camera
The first param is FOV means field of view, imagine a camera on a tripod, if you change lens to wide angle you get a higher FOV. Try to imagine a cone coming out from the camera, it can only see objects in that area.
ASPECT means aspect ratio, a widescreen TV is 16/9 and old ones were 4/3, usually just give it the screen width/height or the dims of a DIV you would like three.js to use.
fov: Camera frustum vertical field of view.
aspect: Camera frustum aspect ratio.
near: Camera frustum near plane.
far: Camera frustum far plane.
On these pages there some image for the FOV, NEAR plane, anmd FAR plane.
https://threejsfundamentals.org/threejs/lessons/resources/frustum-3d.svg
https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/ViewFrustum.svg/440px-ViewFrustum.svg.png
https://threejsfundamentals.org/threejs/lessons/threejs-cameras.html
https://en.wikipedia.org/wiki/Viewing_frustum
This is the aspect ratio.
https://en.wikipedia.org/wiki/Aspect_ratio_(image)
This is the official docs.
https://threejs.org/docs/#api/en/cameras/PerspectiveCamera

Categories

Resources