I'm trying to rotate a shadow camera by 45 degrees. I've managed to rotate the directional light it's attached to using the following code:
sunlight = new THREE.DirectionalLight(0xffffff, 1);
sunlight.position.x = -camera.position.x ;
sunlight.position.y = 300;
sunlight.position.z = camera.position.z ; //default; light shining from top
var vector = new THREE.Vector3;
vector.subVectors(scene.position, sunlight.position);
var q = new THREE.Quaternion();
q.setFromAxisAngle( vector.normalize(), Math.PI / 4 );
sunlight.applyQuaternion( q );
However the shadow camera does not rotate with the light as I'd expected. Trying to rotate the shadow camera itself using the same code does not work. How do I rotate an orthographic camera around its center point?
In the attached image the shadow camera can be seen as the orange square. The light is the black square, seen rotated 45 degrees. I need to apply the same rotation to the orange square as well, so the blue arrow is pointing north west.
Thanks in advance.
Directional lights in THREE.js don't behave like you'd expect. There is a light.target Vector3 parameter that the light Always points to.. so changing the lights rotation won't really do much. Try changing light.target to aim the light. To affect the roll of the shadow camera, you may be able to set the order of its euler with camera.rotation.order = "ZYX". Let me know if this helps.
#Joe Morgan
Related
I have a special control called SphericalControls. Its similar to OrbitControls, but it keeps camera at position 0,0,0 and instead rotates camera on x and y to look around a scene. It is placed in the middle of a SphereBufferGeometry which has a 360 equirectangular image projected upon it. The user can look around the 360 image, and as he does the camera x and y rotation values change.
When a user clicks a button, I need to take these x and y rotation values and rotate the sphere to the rotation of the camera. I then set camera back to x:0 and y:0.
The result is that the camera is reset and the 360 scene has now rotated to show the same rotation view that the camera was previously looking at. So to the user, the view stays basically static, just the values for camera.rotation and sphere rotation have swapped.
This works great if I offset the texture on the sphere:
sphereObj.material.map.wrapS = THREE.RepeatWrapping;
sphereObj.material.map.offset.x = ((camera.rotation.x) / (Math.PI * 2));
sphereObj.material.map.needsUpdate = true;
sphereObj.material.needsUpdate = true;
camera.rotation.set(0, 0);
// Success!
But what I need to do is not offset the texture, but rotate the entire geometry. I have tried:
var axis = new THREE.Vector3(0, 1, 0).normalize();;
var offsetRadian = ((camera.rotation.x) / (Math.PI * 2));
sphere.rotateOnAxis(axis, offsetRadian);
// Fail
But the result is that the sphere rotation is off by approx 30%. Any help is appreciated.
Every objects' rotational data is stored in their respective .quaternion object. Both camera and sphereObj have a quaternion, so what you could do is copy the camera's rotational data into the sphere:
// Get camera's rotation
targetRotation = camera.quaternion;
// Invert rotation
targetRotation.inverse();
// Set sphere's rotation
sphereObj.quaternion.copy(targetRotation);
camera.rotation.set(0, 0, 0);
I'm not entirely sure if you need the .inverse() line... if you're noticing the sphere is rotating in the opposite direction, just get rid of it to get the desired result.
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.)
While rotating camera, lens flare has some rotation based on camera angle, please see this fiddle: http://jsfiddle.net/e4kf3u7t/1/
I want to avoid that, making lens flare always facing camera without rotation, like Sprite behavior: http://jsfiddle.net/e4kf3u7t/3/
Sample code:
var flareColor = new THREE.Color( 0xffffff );
var lensFlare = new THREE.LensFlare( textureFlare0, 200, 0.0, THREE.NormalBlending, flareColor );
lensFlare.position.y = 100;
lensFlare.position.z = 200;
scene.add(lensFlare);
The reason why I want to use Lensflare instead of Sprite is as you can see in fiddle, lens flare disappearing when it center hiding behind another geometry, Sprite doesn't act like that.
I am composing 2D planes with textures. I have 3 levels.
A background plane at z=0,
black shapes for conections at z=0.1 and
small planes with textures at z=0.2
the problem is that when I move the camera planes seems to change z position.
Planes are drawn in incorrect Z, it depend on the position of the camera. Moving the camera it changes again and looks very ugly.
Maybe I need to activate some ZBuffer property for correct drawing
WebGL init is like this and planes are exactly the same (only Z coord change)
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer._microCache = new MicroCache(); //cache de imagenes
renderer.setClearColor(0xeeeeee, 1);
document.body.appendChild(renderer.domElement);
// add directional light source
var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1300).normalize();
scene.add(directionalLight);
//background plane
plane = new THREE.Mesh(new THREE.PlaneGeometry(200000, 200000, 1, 1), new THREE.MeshLambertMaterial({ color: 0xffffff, opacity: planeOpacity, transparent: true }););
plane.position.z = 0;
scene.add(plane);
Other planes are exactly the same but greater Z position
Help please!
Thanks!
Palomo
The thing you're seing is probably z-fighting. Internally, depth is represented by integer in GPU so there is only fixed number of distinct z-s between camera's near and far planes. The solution is to either move your planes apart or narrow camera's near-far range down.
when i have the following code:
camera = new THREE.PerspectiveCamera( 45, width/height, 1, 10000 );
scene.add( camera );
camera.rotation.set(-0.09388335, 0.9945234, 0.0474389);
camera.position.z = 100;
camera.rotation.set(-0.09388335, 0.9945234, 0.0474389);
at render time the position of camera.matrixWorldInverse changes. Anyone knows why?
My guess is that because you are rotating the camera's rotation locally you are changing its position globally. If that's the case then why would the rotate around world axis in the following work:
How to rotate a object on axis world three.js?
I was looking at camera.matrixWorldInverse not camera.matrixWorld