How to calculate local rotation to keep text upright? - rotation

I have text on the screen that always faces the user and remains upright with the following code (this is working):
object.lookAt(camera.position);
object.rotation.x = camera.rotation.x;
object.rotation.y = camera.rotation.y;
object.rotation.z = camera.rotation.z;
Now, after a button has rotated the scene by 90 degrees about the y-axis,
target = new THREE.Vector3(camera.position.z, camera.position.y, -camera.position.x);
object.lookAt(target);
So the text is facing the user as desired, but I can't figure out how to calculate the object rotation to keep the text vertical as I rotate the scene around with trackball controls:
object.rotation.x = ??
object.rotation.y = ??
object.rotation.z = ??
Suggestions? Thanks!

The easiest solution is to use THREE.OrbitControls instead.
Then, in your render loop:
object.quaternion.copy( camera.quaternion );
three.js r.69

Related

aframe/threejs camera manual rotation

I am trying to manually tween camera rotation to 0,0:
camera.object3D.matrixAutoUpdate=false;
var orgrot = { x : camera.object3D.rotation.x, y: camera.object3D.rotation.y };
var target = { x : 0, y: 0 };
var tween = new TWEEN.Tween(orgrot).to(target, 500);
tween.onUpdate(function(){
camera.object3D.rotation.x= this.x;
camera.object3D.rotation.y= this.y;
camera.object3D.updateMatrix();
});
The tween works as expected, but I am loosing mouse control over camera.
To get it back I am setting matrixAutoUpdate to true
tween.onComplete(function(){
document.querySelector('#camera').object3D.matrixAutoUpdate=true
});
But after that, the camera rotation changes back to original position (before tween ) and I would like to keep 0,0. What I am missing ? thanks
UPDATE Below is a version using aframe only without going into threejs objects
I think the problem is camera look-control component
When enabled - I can not animate camera rotation or even setAttribute.
I have to disable it first - than fire animation and than enable it again.
But the problem is, when I enable it again:
camera.setAttribute ('look-controls-enabled',"true")
camera goes back to original rotation ( state before reset animation ).
Similar problem when using matrixAutoUpdate=false/true
Here is my pen http://codepen.io/anon/pen/dMjrWd
If you rotate left 30deg, it will fire resetCamera animation - it works as intended.
But only when look component is disabled. If I enable it again in "animationend" event - the rotation will go back to original state and trigger resetCamera again and again
You really should not have to mess with matrixAutoUpdate.
But given that you are, try the following to force the position, quaternion, and scale to match the matrix:
object.matrix.decompose( object.position, object.quaternion, object.scale );
three.js r.76
I see several problems. If you are using aframe you should not access the object3D directly. You should do
cameraEl.setAttribute('position', {x: 0, y: 0; z;0 })
You can apply a tween to any entity using the declarative API
If you want to modify the camera independently of the running tween you can wrap your camera in another entity
<a-entity rotation="0 360 0"><a-entity id="camera" camera><a-animation ...></a-animation></a-entity></a-entity>
try this codeblock, it works for me on aframe 0.8.2
static faceCameraToCoords(camera, coords){
camera.setAttribute("look-controls",{enabled:false})
camera.setAttribute("rotation", coords);
var newX = camera.object3D.rotation.x
var newY = camera.object3D.rotation.y
camera.components['look-controls'].pitchObject.rotation.x = newX
camera.components['look-controls'].yawObject.rotation.y = newY
camera.setAttribute("look-controls",{enabled:true})
}
You can no longer set a-camera rotation after version 0.8.0.
Updated solution for Aframe 0.9.2:
Given the following camera setup:
<a-entity
id="rig"
position="0 1.6 0">
<a-camera position="0 0 0"></a-camera>
</a-entity>
You can directly alter the camera rotation thus:
const cameraEl = document.querySelector('a-camera');
cameraEl.components['look-controls'].pitchObject.rotation.x = newRotation.x;
cameraEl.components['look-controls'].yawObject.rotation.y = newRotation.y;
Make sure the newRotation values are in radians. For example, use THREE.Math.degToRad(newRotation.x).

Get mouse clicked point's 3D coordinate in three.js

I'm new in THREE.js.
I'm trying to get 3D coordinates of point on mouse click on the object (not simple objects: Box, Sphere,..) in Canvas.
In detail, I'm working with 3D objects viewer - I have camera (THREE.PerspectiveCamera), mouse controls (rotate, zoom, move), add/remove objects (my own object, loaded using loaders for THREE.js) in scene,.. And I want to add a function, which gets 3D coordinates for clicked point in 3D.
Exactly, I want coordinates of the end point of a ray - begining from mouse click on the camera_near_window and ending to the object's point, I've clicked on..
I tried a lot of ways to do it:
Getting coordinates of point on z=0 plane -- It works fine, but it is on z=0 plane and it is not that I need, cause I have OrbitControls..
THREE.js example - clickable objects -- It uses CanvasRenderer (not WebGLRenderer) and works for a little objects (but works for my project): browser crashes when I load many objects (CanvasRenderer needs 5x more memory then WebGLRenderer).
"How to get object in WebGL 3d space from a mouse click coordinate" - I tried this one too, but raycaster.intersectObjects found nothing, intersects was an empty array (maybe it works for only simple objects like box, sphere,..).
Can anyone show me the demo code which gets 3D point coords for clicked point of clicking object in 3D, please..?
So, as I think this question is useful for someone, I'll answer it myself (I'll write my resolve):
var renderer, canvas, canvasPosition, camera, scene, rayCaster, mousePosition;
function init() {
renderer = new THREE.WebGLRenderer({ antialias: false });
canvas = renderer.domElement;
canvasPosition = $(canvas).position();
camera = new THREE.PerspectiveCamera(20, $(canvas).width() / $(canvas).height(), 0.01, 1e10);
scene = new THREE.Scene();
rayCaster = new THREE.Raycaster();
mousePosition = new THREE.Vector2();
scene.add(camera);
var myObjects = new THREE.Object3D();
// myObjects.add( your object );
// myObjects.add( your object );
// myObjects.add( your object );
myObjects.name = 'MyObj_s';
scene.add(myObjects);
};
function getClicked3DPoint(evt) {
evt.preventDefault();
mousePosition.x = ((evt.clientX - canvasPosition.left) / canvas.width) * 2 - 1;
mousePosition.y = -((evt.clientY - canvasPosition.top) / canvas.height) * 2 + 1;
rayCaster.setFromCamera(mousePosition, camera);
var intersects = rayCaster.intersectObjects(scene.getObjectByName('MyObj_s').children, true);
if (intersects.length > 0)
return intersects[0].point;
};

How to hide a html overlay label on a sphere object

I have a sphere model along with html text labels overlayed onto it at fixed positions. How can I hide them when they are behind the object when i am rotating my sphere using orbit controls?
Anyone knows about any references on stackoverflow or any examples which can solve my issue?
See this example how you could do it: http://jsfiddle.net/L0rdzbej/194/
I have put the relevant code in the updateLabelVisibility()-function, it looks like this:
var meshPosition = mesh.getWorldPosition();
var eye = camera.position.clone().sub( meshPosition );
var dot = eye.clone().normalize().dot( meshPosition.normalize() );
//IS TRUE WHEN THE MESH IS OCCLUDED BY THE SPHERE = dot value below 0.0
var ocluded = dot < -0.2;
if ( ocluded ) {
// HIDE LABEL IF CAMERA CANT SEE IT (I.E. WHEN IT IS BEHIND THE GLOBE)
label.style.visibility = "hidden";
}
else {
// DISPLAY LABEL IF MESH IS VISIBLE TO THE CAMERA
label.style.visibility = "visible";
}
Where mesh is the marker where your label is attached to. The dot is basically telling you how far around the sphere it is, within a certain distance of 90 degree. Simply said by values below zero the label is longer visible by going further around the back.
To be fair I based this off some code from: https://zeitgeist-globe.appspot.com/

Unable to get a DirectionalLight shadow to update correctly

I have a DirectionalLight in my scene. When I first create the light the shadow covers the intended area. When the viewport is resized (canvas size) I update the shadowCamera parameters (right,left,top,bottom), and the light's position and target, but the shadow only covers the area before the update.
What flag do I have to set to get the shadow properly updated to reflect the new settings?
Here is the pattern you need to follow to update a shadow camera on-the-fly:
light.shadowCameraLeft = -100;
light.shadowCameraRight = 100;
light.shadowCamera.left = light.shadowCameraLeft;
light.shadowCamera.right = light.shadowCameraRight;
...
light.shadowCamera.updateProjectionMatrix();
three.js r.64

how to display a mesh in front of my camera in Three.Js?

i want to show a mesh (like gunshot) in front of my perspective camera(with first person controls) i wrote this code in the render function of my page:
var pos = camera.position;
var rot = camera.rotation;
shot.rotation.x = rot.x;
shot.rotation.y = rot.y;
shot.rotation.z = rot.z;
shot.position.x = pos.x;
shot.position.y= pos.y;
shot.position.z = pos.z + 500;
if i just change the position of my camera its good, but if i change the camera's rotation i don't see the shot in front of that.
how can i do this?
It would seem that you need to make the "shot" a child of the camera. It's not clear from your example whether you're doing that already, but this should make the shot move around with the camera properly.

Resources