I have been trying to use pointerlock controls to move in the way the camera is looking. Recently the getDirection() method was added and I use it like this.
if ( moveForward ){
velocity.x += 20.0 * controls.getDirection().x * delta;
controls.getObject().translateX( velocity.x * delta );
}
It sort of works until (I'm guessing here) the errors add up and it starts moving whereever it wants when I hit the forward key. The idea is that I look with the mouse and then I want to move in that direction, Zero gravity, I am not constrained in any direction. Can someone help? I am working with r72.
Edit:
I found taht FlyControls are closer to what I want, but if you check the example: Fly controls
It pans in direction wherever the mouse was last. I want the camera to move with the mouse, at the same speed, and if the mouse doesn't move, camera shouldn't move either. Any ideas?
Related
I have a ThreeJS set up where the camera can move through a 3D world and while moving it will change its lookAt multiple times. So let's assume that camera.getWorldDirection() will always be more or less random.
Now I need the camera to move exactly left / right / up / down relative to camera.getWorldDirection().
You can't just use something like camera.position.x += 1 because that only applies for a world direction of Vector3(0, 0, -1). If the world direction changes to e.g. (1, -1, 0), moving the camera to the right does require changes in the X and the Z axis.
I had a look at quaternions and 4D matrices but I can't get my monkeybrain around them. Would be really nice if someone could help me out.
Here is a demo: https://normanwink.com/demo/room/
I found the answer here in a non-accepted answer.
You gotta use camera.translateX() and similar functions to transform its local position. That way you can always manipulate camera.position to move it around and have the translate functions to add offsets relative to the cameras viewing angle.
I'm using the translateZ function so that camera can move forward/backward along its lookat direction. But translateZ moves it relatively. So camera.translateZ(10); followed by another camera.translateZ(10); will move the camera by 20 units in total. Because of this, I can't use it in a tween animation where I tween the parameter inside of that function.
So I was wondering if there's a way to translate along Z in absolute coordinates, for example if I'm looking at object in origin, I'd like to set distance_from_origin while still maintaining lookat direction?
camera.absTranslateZ(distance_from_origin);
I use something similar on all my camera rigs. I only need 2 variables: the focus position (vec3) and the z-distance. I then reset the position on each frame:
var focusPos = new THREE.Vector3();
var zDist = 10;
// Called once per frame
update() {
// reset camera position
camera.position.copy(focusPos);
// Set camera rotations if needed
// camera.rotation.set(rotX, rotY, 0);
// Apply z-translation to dolly in/out
camera.translateZ(zDist);
}
I like this approach because it lets you change and even tween the focus position, so you're not always looking at the origin. However, it depends on how you're calculating your camera rotations, you might run into gimbal lock if you need more complex rotations.
I have created a raytracing algorithm which currently displays a triangle on screen, and am now having trouble moving the camera around correctly.
I would like my code to have the arrow keys rotate the camera, and WASD move the camera in 3D space. The camera currently rotates correctly using two rotation matrices for y and z rotations.
The Problem
Moving the camera, rather than rotating, is where the issue arises. To move the camera, I require two vectors - cameraForward and cameraRight. These vectors can be added on to the position of the camera when input is detected. These vectors will also need to change when the cemara is rotated, in the same rotation as all the rays experience. But when I apply these rotation matrices to the vectors representing cameraRight and cameraForward, there seems to be an issue. Holding down the A or D key will result in the camera moving unexpectedly in circles or odd wavy lines.
I managed to fix the issue with cameraForward by using a different method. I added a couple lines of code which calculate when the ray at the centre as been 'fired' and proceed to set cameraForward to that ray. Therefore cameraForward will always follow the central ray being sent out i.e. the centre of the field of view. However, I cannot do the same with cameraRight, as this vector is not in the field of view.
Before solving cameraForward using this method the same issue arose with moving forwards and backwards.
I also tried taking the cross product of one of the other rays along with the cameraForward vector which I thought might produce cameraRight, but to no avail - more sporadic camera movement
I do not have the vector for cameraUp either so cannot calculate the cross product to find cameraRight.
I also thought maybe the code was being run too many times and the vector was rotated multiple times. However mvoing the code elsewhere had no effect and the method it was already in is run every frame, so I do not believe that is the issue.
Here is my code to rotate the camera right and the method which does the rotation.
camRight's inital value is (0, 0, 1)
camRight = normalize(rotateVector(camRight, rotationZ));
camRight = normalize(rotateVector(camRight, rotationY));
function rotateVector(v, m) {
return new Vector3(dot(m.a, v), dot(m.b, v), dot(m.c, v));
}
I know this code works as the code rotating the camera view functions correctly using the same matrices and methods.
(the following code)
myDirection = normalize(rotateVector(myDirection, rotationZ));
myDirection = normalize(rotateVector(myDirection, rotationY));
When the user presses A or D the following code is run
if (keys[65]) {
camPos = add(camPos, normalize(camRight));
requestAnimationFrame(render);
}
if (keys[68]) {
camPos = subtract(camPos, normalize(camRight));
requestAnimationFrame(render);
}
The camera moves forwards and backward correctly, as previously mentioned. Initially, the camera moves left and right correctly too (as its inital value of (0, 0, 1) is correct), but if I rotate the camera, the values for cameraRight go wild.
Have I assumed something wrongly? or is there a flaw in my logic somewhere?
Thank for any help
I am currently creating a VR web app using three.js. As the camera controls I am using the device orientation controls used here in the google cardboard three.js demo.
What I need to do is add keyboard controls to this(e.g Up arrow to go forward etc). I've fiddled around with moving the camera on the two axis (x and z) here:
if (e.keyCode == '38') {
camera.position.set(0, 10, camera.position.z+4);
controls.target.set(
camera.position.x +4,
camera.position.y,
camera.position.z
);
effect.render(scene, camera);
...
However I want to make the character move relative to where they are looking (e.g You look one way and press the Up arrow and the character moves the way you looking). Like a first person view.
Does anyone have any ideas on how this is done? Ive tried using the first person controls from three.js but this eliminates the head tracking which is essential for a VR game.
Any answers would be greatly appreciated. (My source code is practically just the Google cardboard three.js demo code with a function added in too detect key presses)
I solved this by different approach. I created an object3d which is moving in scene. Model and camera are child of this object.
I'm rotating object 3d with camera and in the same time rotate model in opposite direction. When i rotate camera object looks keeping direction. when i want to move object, just translateX object with camera and make model rotation to 0. That did the trick.
On long distances (I have millions of units) started to be jerky. Reason is lost precision.
I solved it by keeping position of object at 0,0,0 and move all other things in opposite direction. That makes your model is still on 0,0,0 coords with right rotation and world is moving around.
Most simple example:
you trying something like
scene.add(character_model);
scene.add(camera);
//camera.rotate ....
character_model.translateX(1);
character_model.rotateX(1);
//etc ...
and now you trying to move camera around the pivot (character_model), but this is overcomplicated mathematics.
Try:
var controls_dimension = new THREE.Object3D();
scene.add(controls_dimension);
controls_dimension.add(character_model);
controls_dimension.add(camera);
//use controls to rotate with this object, not with character_model
controls_dimension.rotateX(2);
// in the same rotate model to opposite direction. You can make
// illusion of rotating camera, not a model.
character_model.rotateX(2*-1);
/*
when you want to go in camera direction=controls_dimension=controls_dimension.translateX(1)
and we moving (you most only animate model rotation to controls_dimension.rotation)
*/
I use Pointer Lock for capturing the cursor in a game I'm developing in JavaScript with three.js. I've done my basic Googling, but I can't seem to find why, on Chrome OS, the cursor doesn't seem to move. If you look at http://scheib.github.io/HTMLMisc/PointerLockAndFullscreen.html Pointer Locking is working just fine and there's even a nice "cursor" to go along with the movement!
JavaScript Console output (The logging is me):
I "fabricate" the movementX/Y with
if (evt.movementX === undefined) {
evt.movementX = evt.screenX - lastx;
evt.movementY = evt.screenY - lasty;
lastx = evt.screenX;
lasty = evt.screenY;
}
In case you're wondering, I'm just setting up basic graphics.
The cursor is not moving because you have "lock" it. But evt.movementX and evt.movementY gives you the direction of the movement.
You have to update the position or direction of your camera and render the result to make it feel like it moves.
Under pointer lock, only the movementX and movementY properties are available. All other "ordinary" position co-ordinates are deliberately set to zero.
In pointer lock mode, it is perceived that there is no cursor, only mouse movement, so there's no (screenX,screenY) for a cursor which does not exist, nor is there an (offsetX,offsetY) for the same reason.
Only (movementX,movementY) by design.