I'm trying to change the camera position in the code and update the controller base on it.
Easily, I run:
camera.position.x = 20;
controls.update();
but this doesn't work at all !
controls.update() reset the camera position !
take webgl_decals as example, just declare the controller out of init() function, (so that you can call it in console), in console, run:
camera.position.x = 20;
controls.update();
the camera position will reset and will not change its position !
Is this the right way of of changing the camera position ?
any solution ?
If you are using OrbitControls and you want to set the camera position programmatically, you can do so by using the following pattern:
controls.enabled = false;
camera.position.set( 10, 10, 10 );
camera.lookAt( controls.target );
controls.enabled = true;
three.js r.97
Ok i found the solution, i was trying to update the camera by changing camera.position , instead I changed controls.target and it works !
Please take into consideration updating the controller by controls.update() after making this change.
Related
I need to set the initial 'lookAt' point of the scene, that will be the center of the screen and of the control's rotation.
If possible, I would prefer to set a point (or an object's position), not rotation angles.
The control is OrbitControl. If I simply set lookAt before the Control initialization, the center is restored to (0,0,0) on the first user interaction, which causes a 'gap' ...
// camera
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 0.1, 20000);
camera.position.set(0,20,20);
camera.lookAt(new THREE.Vector3(0,10,0));
// controls
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
How can I set the initial point in a proper way?
Try setting the control's target and remove the camera.lookAt call:
controls.target = new THREE.Vector3(0, 10, 0);
controls.update();
Or more directly (without instanciating a new THREE.Vector3 but updating the values):
controls.target.set(0, 10, 0);
NB: controls.update() advice still remains for the 1st frame
I want the same object to be rendered twice, once on-screen and once off-screen. The on-screen mesh has a geometry and a MeshLambertMaterial. This material has vertexColors: THREE.VertexColors. The off-screen mesh has the same geometry and a MeshBasicMeterial with vertexColors: THREE.FaceColors. During initial setup each faceColor is set to a unique color. Each vertexColor is set to a single color (Later these vertexcolors can change by "painting" on the object).
Then I want to render both object. In this fiddle you see how that looks with two scenes rendered side by side. The object with the MeshLambertMeterial is now half red to make things clearer. As you can see, both scenes seem to use the same material. Also, when I switch the order I get the following error:
[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1.
To make things even weirder, when run the fiddle I see the object rendered with the MeshBasicMaterial twice. However, when I run the exact same code locally, I see the object rendered with the MeshLambertMaterial twice.
Eventually I want the object with the MeshBasicMeterial to render to a rendertarget, but with that I run into the same problems. I want to be able to show the object with the LambertMetarial on screen and when I hover over the object with the mouse, to get the color in that position in the renderTarget, where the BasicMaterial is rendered to.
I hope it is clear what the problem is, if not, please let me know.
fiddle
EDIT: Issue resolved.
When using WebGLRenderer, two meshes having different materials can now share a geometry.
three.js r.88
First of all, always make sure you try the latest three.js everywhere. especially, do not use the jsfiddle's r54 but instead use an up-to-date external resource like http://threejs.org/build/three.min.js - this solves one of your problems.
The main thing is that you need to update the vertex colors between the render calls (and if they are changed, you have to do that anyway). Here's what does the trick:
function render () {
var SCREEN_WIDTH = WIDTH, SCREEN_HEIGHT = HEIGHT;
camera.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT;
camera.updateProjectionMatrix();
renderer.clear();
geometry.colorsNeedUpdate = true;
// left side
renderer.setViewport( 0, 0, 0.5 * SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.render( scene, camera );
geometry.colorsNeedUpdate = true;
// right side
renderer.setViewport( 0.5 * SCREEN_WIDTH, 0, 0.5 * SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.render( pickRenderScene, camera );
}
http://jsfiddle.net/E3F4f/4/
I'm trying to create a simple first person shooter in ThreeJS and am having some trouble with shooting a ray out of the camera. I am using the code for the PointerLock example code on Mr. Doob's github and am just trying to change the color of a box when I look at it and click the mouse but my code seems to just change boxes colors at random.
Here is the code for looking for collisions:
function onDocumentMouseDown( event ) {
event.preventDefault();
var vector = new THREE.Vector3(0,0,1);
projector.unprojectVector(vector, camera);
var rayCam = new THREE.Ray(camera.position, vector.sub(camera.position).normalize() );
var rayCaster = new THREE.Raycaster(rayCam.origin, rayCam.direction);
//rayCaster.ray = rayCam;
var intersects = rayCaster.intersectObjects(scene.children);
if (intersects.length) {
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
}
}
My code works when you stand in one place but when you start moving the code acts as if the camera is still at the origin, where it started out. How can I modify this code to take into account the fact that I will be moving around?
I have a camera that moves in a few different ways in the scene. The camera should rotate around a target position. In my case, this is a point on a mesh that the user has targeted. Because the camera usually doesn't require moving relative to this point, I was not able to use the pivot idea here: https://github.com/mrdoob/three.js/issues/1830. My current solution uses the following code:
var rotationY = new THREE.Matrix4();
var rotationX = new THREE.Matrix4();
var translation = new THREE.Matrix4();
var translationInverse = new THREE.Matrix4();
var matrix = new THREE.Matrix4();
function rotateCameraAroundObject(dx, dy, target) {
// collect up and right vectors from camera perspective
camComponents.up = rotateVectorForObject(new THREE.Vector3(0,1,0), camera.matrixWorld);
camComponents.right = rotateVectorForObject(new THREE.Vector3(1,0,0), camera.matrixWorld);
matrix.identity();
rotationX.makeRotationAxis(camComponents.right, -dx);
rotationY.makeRotationAxis(camComponents.up, -dy);
translation.makeTranslation(
target.position.x - camera.position.x,
target.position.y - camera.position.y,
target.position.z - camera.position.z);
translationInverse.getInverse(translation);
matrix.multiply(translation).multiply(rotationY).multiply(rotationX).multiply(translationInverse);
camera.applyMatrix(matrix);
camera.lookAt(target.position);
}
The issue is that we do not want to use lookAt, because of the reorientation. We want to be able to remove that line.
If we use the code above without lookAt, we rotate around the point but we do not look at the point. My understanding is that my method should rotate the camera's view as much as the camera itself is rotate, but instead the camera is rotated only a small amount. Could anyone help me understand what's wrong?
EDIT: Cleaned up the original post and code to hopefully clarify my question.
My thinking is that I can translate to the origin (my target position), rotate my desired amount, and then translate back to the beginning position. Because of the rotation, I expect to be in a new position looking at the origin.
In fact, I'm testing it now without the translation matrices being used, so the matrix multiplication line is:
matrix.multiply(rotationY).multiply(rotationX);
and it seems to be behaving the same. Thanks for all the help so far!
ONE MORE THING! A part of the problem is that when the camera behaves badly close to the north or south poles. I am looking for a 'free roaming' sort of feel.
Put the following in your render loop:
camera.position.x = target.position.x + radius * Math.cos( constant * elapsedTime );
camera.position.z = target.position.z + radius * Math.sin( constant * elapsedTime );
camera.lookAt( target.position );
renderer.render( scene, camera );
Alternatively, you can use THREE.OrbitControls or THREE.TrackballControls. See the three.js examples.
The Gimbal lock that you are referring to (reorientation) is because of the use of Euler angles in the default implementation of the camera lookat. If you set
camera.useQuaternion = true;
before your call to lookat, then euler angles will not be used. Would this solve your problem ?
I am creating a 3d game using THREE.JS and the Web Audio API. One of the problems I am having is that I want to use the web audio Listener orientation, and define the listener to be the camera, whose position and direction are constantly being updated
My question, is there anyway to easily get the vector direction of a THREE camera?
I was trying to calculate it by using the old camera position, and using the velocity vectors to calculate which way it is facing, but this won't work when the camera is standing still...
Would it be feasible to create a unit vector by getting using camera.rotation.x, camera.rotation.y, camera.rotation.z ?
or is there an even easier way?
Thanks so much for your time!
You want to know the direction in world space in which the camera is looking.
In camera space, the camera is located at the origin and is looking down it's negative z-axis.
Pick a point in front of the camera in camera space:
var pLocal = new THREE.Vector3( 0, 0, -1 );
Now transform that point into world space:
var pWorld = pLocal.applyMatrix4( camera.matrixWorld );
You can now construct the desired direction vector:
var dir = pWorld.sub( camera.position ).normalize();
EDIT: Updated for three.js r.57
EDIT: Also see: three.js set and read camera look vector
In revision 69 (not sure in what revision it was introduced), you can call
camera.getWorldDirection()
to get the camera orientation vector.
if your camera is a child of the player object .e.g. in FPS game. Do the same calculation on the player (parent of camera) , and use this (the Bullit gets the right direction, in this case from obj)
Bullit.prototype.getDirection=function(obj){
this.position.add(obj.position);
var pLocal = new THREE.Vector3( 0, 0, -1 );
var pWorld = pLocal.applyMatrix4( obj.matrixWorld );
var dir = pWorld.sub( obj.position ).normalize();
this.direction=dir;
}