Align mesh and object bounding boxes with helper axes - three.js

The bounding box doesn't seem to be aligned with the 3d mesh. This is the reason. Can you please give me some tips on how should I rotate the bounding box so that it's properly aligned with 3d mesh?
This is the screenshot of the 3d mesh and misaligned object bounding box:
Things I've tried:
Tried the approach of offsetting center position from object.
Tried to remove the rotation and translation of the object before calling 'setFromObject'.
Tried to rotate the box directly.

You can try to use the center point of the model's AABB in order to offset it as requested. The code for this looks like so:
const box = new THREE.Box3().setFromObject( model );
const center = box.getCenter( new THREE.Vector3() );
object.position.x += ( object.position.x - center.x );
object.position.y += ( object.position.y - center.y );
object.position.z += ( object.position.z - center.z );

Related

Bounding box that is parallel to the camera

My problem is how to define the camera location, given a lookAt vector, when the camera is not on the z axis, so it captures all objects according to its fov and aspect.
I think I need to get a bounding box of my objects that is perpendicular to the camera's lookAt and top and bottom front and back edges are parallel to the xz plane. Then the back of the bounding box is the 'far' plane and I can calculate the distance from it (or fov) and set the camera accordingly.
My question is, how to get such a bounding box (Box3 instance), given some objects on the scene and the lookAt vector ?
My question is, how to get such a bounding box (Box3 instance), given some objects on the scene and the lookAt vector ?
Instances of THREE.Box3 are axis-aligned bounding boxes. No matter how the camera is rotated, it is not possible to generate a different bounding box for a given set of 3D objects.
Maybe you can use a quite common approach 3D viewers which ensures to always display an imported 3D object in the viewport. Exemplary code from the open source glTF viewer looks like this:
const aabb = new THREE.Box3().setFromObject( object );
const center = aabb.getCenter( new THREE.Vector3() );
const size = aabb.getSize( new THREE.Vector3() ).length();
// centering object
object.position.x += ( object.position.x - center.x );
object.position.y += ( object.position.y - center.y );
object.position.z += ( object.position.z - center.z );
// update camera
camera.near = size / 100;
camera.far = size * 100;
camera.updateProjectionMatrix();
camera.position.copy( center );
camera.position.x += size / 2.0;
camera.position.y += size / 5.0;
camera.position.z += size / 2.0;
camera.lookAt( center );

Three.js - How to Rotate Shader Material?

My problem is trying to get the sky to rotate on its z-axis. For example if I rotate the sky by 180 degrees the shadow from the sun light should display in the opposite direction.
The code sandbox: https://codesandbox.io/s/friendly-cloud-c00zr?file=/src/main.js:
This is where I create the sky in the main.js file:
const createSky = () => {
const sky = new Sky();
sky.scale.setScalar(1000);
sky.castShadow = true;
return sky;
};
I’ve tried rotateZ and sky.rotation to no avail.
The code in the sky.js file:
https://codesandbox.io/s/little-microservice-7nh53?file=/src/sky.js
is a modified iteration of the original three.js sky-sun-shader:
https://threejs.org/examples/webgl_shaders_sky.html
All that I have changed is the up position of the sky and its geometry from boxBuffer to sphereBuffer.
I would post the code here but it but it's over 200 lines of code.
I am wondering if there is a special way to rotate this ShaderMaterial in sky.js?
sky.material.uniforms.sunPosition.value.copy( light.position ); It looks like you can use this line to have the sun move from east to west.
Here the east-west is on the x axis and north-south is on z;
let sunPivot = new THREE.Object3D();
//add the light to the pivot at an offset off 100 units( can be changed );
light.positions.set( -100, 0, 0);
sunPivot.add( light );
in the render loop:
sunPivot.rotateZ( 0.005 ); //arbitrary rotation speed
light.getWorldPosition( sky.material.uniforms.sunPosition.value ); //the uniform value as target (puts the world position of the light into the sunPosition.value

How to change the volume of DirectionalLight in THREE to cast larger shadows?

I have a DirectionalLight in my screen casting light downwards onto a large 3d model. I have a plane above this model that I'd like a shadow projected (orthographically) onto the 3d model. This did not work as I had expected, so after adding the DirectionalLightHelper, I noticed that the volume of the DirectionalLight is only a small portion of the 3D model. When the plane is within this volume, the shadow works.
I assume that I need to increase the volume of the DirectionalLight box to be able to project light onto the entire model?
Try to increase the frustum of the internal shadow camera like in this example: https://threejs.org/examples/webaudio_timing.html
var d = 5;
directionalLight.castShadow = true;
directionalLight.shadow.camera.left = - d;
directionalLight.shadow.camera.right = d;
directionalLight.shadow.camera.top = d;
directionalLight.shadow.camera.bottom = - d;

How to setup a camera that follows a circle path?

I'm trying to create a camera that follows an object that rotates on a orbit around a sphere. But everytime the camera reaches the polar coordinates of the orbit, the direction changes. I just set the position of the camera according to the object that is has to follow and calling lookAt afterwards:
function render() {
rotation += 0.002;
// set the marker position
pt = path.getPoint( t );
// set the marker position
marker.position.set( pt.x, pt.y, pt.z );
marker.lookAt( new THREE.Vector3(0,0,0) );
// rotate the mesh that illustrates the orbit
mesh.rotation.y = rotation
// set the camera position
var cameraPt = cameraPath.getPoint( t );
camera.position.set( cameraPt.x, cameraPt.y, cameraPt.z );
camera.lookAt( marker.position );
t = (t >= 1) ? 0 : t += 0.002;
renderer.render( scene, camera );
}
Here's a complete fiddle: http://jsfiddle.net/krw8nwLn/69/
I've created another fiddle with a second cube which represents the desired camera behaviour: http://jsfiddle.net/krw8nwLn/70/
What happens is that the camera's lookAt function will always try to align the camera with the horizontal plane (so that the "up" direction is always (0, 1, 0). And when you reach the top and bottom of the ellipse path, the camera will instantaneously rotate 180° so that up is still up. You can also see this in your "desired behaviour" example, as the camera cube rotates so that the colors on the other side are shown.
A solution is to not use lookAt for this case, because it does not support cameras doing flips like this. Instead set the camera's rotation vector directly. (Which requires some math, but you look like a math guy.)

Feature projection into equirectangular panorama with THREE.js

Relatively new to THREE.js. I am trying to figure out how to project a DIV with text into an equirectangular panorama.
I have this simple example working with my panorama images.
https://threejs.org/examples/webgl_panorama_equirectangular
The question: I have a latitude and longitude of a feature that's in my panorama, I'd like to project a DIV labeling such item into 3D space. How do I convert longitude and latitude into X and Y on the canvas so I can change the DIVS left and top style attributes so the label renders in 3D space and appears fixed to its coordinates?
UPDATE:
For clarity, how does one take planet earth longitude and latitude, and convert it into X Y pixels inside a mesh? I know where the image was taken on earth, and I know where an item in that picture was taken on earth. I want to label that item in 3D space.
Any help would be much appreciated. Thanks.
Code from this question seems to do the trick:
3d coordinates to 2d screen position
function getCoordinates( element, camera ) {
var screenVector = new THREE.Vector3();
element.localToWorld( screenVector );
screenVector.project( camera );
var posx = Math.round(( screenVector.x + 1 ) * renderer.domElement.offsetWidth / 2 );
var posy = Math.round(( 1 - screenVector.y ) * renderer.domElement.offsetHeight / 2 );
console.log( posx, posy );
}
I updated the jsfiddle with the new version of Three.js
http://jsfiddle.net/L0rdzbej/409/

Resources