How to Fit Camera to Object
I am assuming you are using a perspective camera.
You can set the camera's position, field-of-view, or both.
The following calculation is exact for an object that is a cube, so think in terms of the object's bounding box, aligned to face the camera.
If the camera is centered and viewing the cube head-on, define
dist = distance from the camera to the _closest face_ of the cube
and
height = height of the cube.
If you set the camera field-of-view as follows
fov = 2 * Math.atan( height / ( 2 * dist ) ) * ( 180 / Math.PI ); // in degrees
then the cube height will match the visible height.
At this point, you can back the camera up a bit, or increase the field-of-view a bit.
If the field-of-view is fixed, then use the above equation to solve for the distance.
EDIT: If you want the cube width
to match the visible width, let aspect
be the aspect ratio of the canvas ( canvas width divided by canvas height ), and set the camera field-of-view like so
fov = 2 * Math.atan( ( width / aspect ) / ( 2 * dist ) ) * ( 180 / Math.PI ); // in degrees
three.js r.69
How to fit object to camera in threejs using OrthographicCamera?
As @gaitat said, with THREE.OrthographicCamera
you need to adjust it's frustum dimensions to fit the size of an object you want to zoom in.
Straightforward thing to do would be to use geometry.boundingSphere
and set camera top
, left
, bottom
and up
based on that. The easier thing to do would be to use camera.zoom
to do the work, i.e.
// center camera on the object (ellipse in this case)
var boundingSphere = ellipse.geometry.boundingSphere
// aspect equals window.innerWidth / window.innerHeight
if( aspect > 1.0 )
{
// if view is wider than it is tall, zoom to fit height
camera.zoom = viewHeight / ( boundingSphere.radius * 2 )
}
else
{
// if view is taller than it is wide, zoom to fit width
camera.zoom = viewWidth / ( boundingSphere.radius * 2 )
}
// Don't forget this
camera.updateProjectionMatrix()
This will set the zoom level to be such that object (ellipse in this case) fits exactly your camera's frustum.
However, you will also have to center the camera on the object by either:
- rotating the camera to point to the boundingSphere center
- translating the camera so that the boundingSphere center ends up on the camera's frustum axis
Since translating the camera is easier thing to do of the two, and THREE.OrthographicCamera
is mostly used to show 2D representation of your scene (i.e. for UI or some other things that take place on a plane parallel to the camera), here is the code to do just that:
camera.position.copy(boundingSphere.center)
// The number here is more or less arbitrary
// as long as all objects that need to be visible
// end up within the frustum
camera.position.z = 15
This assumes that your objects are in some plane parallel to XY plane and that the camera is positioned to look parallel to Z-axis (as it is by default).
Here is codepen that shows small grid and an ellipse in XY plane. On mouse down camera will zoom to the ellipse, and on mouse up it will come back to it's original state:
https://codepen.io/anon/pen/aJEzew
Making an object fit exactly inside the camera frustum in Three.Js
I have not checked your distance calculations, but you looking straight down the z-axis, while the object isn't vertically centered around 0. Putting your camera.y
at mesh1_BB.max.y / 2
should fix that.
If you don't want to move your camera, at least point it towards the actual center of the object. In that case, using the (axis aligned) bounding box isn't 100% correct anymore.
Aframe/Three fit to screen - calculate zoom
Fitting an object to the screen by:
- changing the camera FoV
- zooming the camera
- repositioning the camera / object
is quite similar once you understand where the formulas came from.
We'll use this neat image (from this SO thread) as it covers all three topics:
0. What do we want to achieve
We want the object (the longer side of either its width or height) to cover the filmHeight
- so it fits the screen.
1. Recalculating the FoV
In this case we do know the focalLength
(camera distance from the object) and filmHeight
(object width or height). We can calculate fov / 2
thanks to our friend trigonometry:
Tan (fov / 2) = (filmHeight / 2) / focalLength
=>
fov = 2 * ATan ((filmHeight / 2)) / focalLength * 180 / PI
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
AFRAME.registerComponent("fit", {
init: function() {
const plane = document.querySelector("a-plane")
const distance = this.el.object3D.position.distanceTo(plane.object3D.position)
var height = plane.getAttribute("geometry").height
var newFov = 2 * Math.atan((height / 2) / distance) * (180 / Math.PI); // in degrees
this.el.sceneEl.camera.fov = newFov
}
})
</script>
<a-scene>
<a-plane position="0 1.6 -2" material="src: https://i.imgur.com/wjobVTN.jpg"></a-plane>
<a-camera position="0 1.6 0" fit></a-camera>
</a-scene>
Calculate camera zoom required for object to fit in screen height
I am doing the following which is based on the boundingSphere radius:
geometry.computeBoundingSphere();
radius = geometry.boundingSphere.radius;
distanceFactor = Math.abs( aspect * radius / Math.sin( fov/2 );
This is based on this stuff right here and I hope i interpreted it the right way:
http://www.flipcode.com/forums/thread/4172
This distanceFactor
is the factor you need to move the camera along its viewing direction to fit it correctly. At the moment i am not sure if it is by height or width but maybe it helps you figure it out. :)
How to select an object and move camera into to another position?
You basically solve this problem in two steps:
First, you have to make 3D objects selectable which can be done via raycasting. There are many official examples that demonstrate 3D interaction based on raycasting, for example:
https://threejs.org/examples/webgl_interactive_cubes
If you know that a certain 3D object was clicked, you animate the camera from its current position to a defined target position. The possible target positions can be defined prior or you compute the in some way on the fly based on the object's bounding volume and the current camera position. The actual animation can be done in many ways. One approach is using a tweening engine like tween.js. Check out the following example to see how it is used together with three.js
:
https://threejs.org/examples/css3d_periodictable
Related Topics
Push Method in React Hooks (Usestate)
Change Values in Array When Doing Foreach
Get Average Color of Image via JavaScript
How to Check If a Variable Is an Integer in JavaScript
Fastest Way to Convert JavaScript Nodelist to Array
JavaScript Checking for Null VS. Undefined and Difference Between == and ===
Switch Statement for Multiple Cases in JavaScript
How to Detect a Textbox's Content Has Changed
Switch Statement for Greater-Than/Less-Than
Controlling Fps with Requestanimationframe
Difference Between Textcontent VS Innertext
React-Router - Pass Props to Handler Component
How to Make Exe Files from a Node.Js App
How to Call Reduce on an Array of Objects to Sum Their Properties
Es6 Variable Import Name in Node.Js
JavaScript Tofixed Not Rounding
How to Change Href of <A> Tag on Button Click Through JavaScript