Like in lots of other similar questions, I want to move an object forward in three.js based on its rotation. The difference is, I can't use object.translateZ. This is because I'm using a physics simulator and it will mess up if I update the object like that. Here is an example fiddle of my problem. Feel free to play around with my fiddle and add your updated version to your answer.
I would like the cube to move forward by updating mesh.position.x and mesh.position.z based on mesh.rotation.y.
To keep in mind, I've sometimes realized that three.js rotations are a little weird some times when accessing them using mesh.rotation.y.
Thanks!
I would suggest using the mesh.getWorldDirection() to get a direction where you want to move your mesh. Then you can multiply it with a scalar to adjust movement speed.
direction = mesh.getWorldDirection();
mesh.position.add(direction.multiplyScalar(moveSpeed));
Fiddle: https://jsfiddle.net/k1swrxjr/1/
Good luck!
To move your mesh simply increment the value of the position in which you want your mesh to go in you animate() function instead of init function, example as follows:
function animate() {
mesh.position.x += 0.1;
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
This example code will increase x position of your mesh by 0.1 every time animate() is run.
Related
I have an interface I developed with three.js using the CSS3DObject rendering tool.
I have set the orbit to 0 to prevent rotating and limit my movement to panning and zooming.
Please note I'm also using Orbit Control.
I set the position of the camera to x=-2000 with the following code:
camera.position.x=-2000;
camera.position.z=4000;
When I do this, the camera moves positions but is still pointing to (0,0,0) resulting in a skewed look.
So I assume that I need to give it a vector
camera.up = new THREE.Vector3(0,1,0); //keeps the camera horizontal
camera.lookAt(new THREE.Vector3(2000,0,0)); //should point the camera straight forward
Please note that I'm still trying to find a good explanation of how setting up the lookAt works.
After a bit more research, it seems that the orbit control is overriding the camera.lookAt and as a result, doesn't do anything.
To achieve the panning I set the location of the camera x position equal to the value of the target.
I also removed the camera.up line.
var myCameraX = -2000;
var myCameraY = 500;
camera.position.x=myCameraX;
camera.position.y=myCamerYa;
control.target.set(myCameraX,myCameraY,0);
Hope that helps someone.
I am preparing an application which shows a 3D model of a building and it works fine now. I was trying to control "PerspectiveCamera" using LookAt. However, I noticed LookAt does not work when I have the following line in animate function.
controls.update(1);
Therefore, I disabled this line (see below):
function animate(time) {
requestAnimationFrame( animate );
//controls.update(1);
TWEEN.update(time);
renderer.render( scene, camera );
}
However, I lose my mouse control (cannot zoom in/out) when I disable that line. If I enable that line , LookAt does not work properly.
Any suggestion? Thanks.
Just call camera.lookAt() in the animation loop if you're using the controls. That will get it to re-point to whatever you want to lookAt() after you've moved things around with the controls.
I would like to apply the three.js script TrackballControls to a moving object in a way that preserves the ability to zoom and rotate the camera while the object moves through the scene. For example, I would like to be able to have the camera "follow" a moving planet, while the user retains the ability to zoom and rotate around the planet. Here is a basic jsfiddle:
http://jsfiddle.net/mareid/8egUM/3/
(The mouse control doesn't actually work on jsfiddle for some reason, but it does on my machine).
I would like to be able to attach the camera to the red sphere so that it moves along with it, but without losing the ability to zoom and rotate. I can get the camera to follow the sphere easily enough by adding lines like these to the render() function:
mouseControls.target = new THREE.Vector3(object.position);
camera.position.set(object.position.x,object.position.y,object.position.z+20);
But if I do that, the fixed camera.position line overrides the ability of TrackballControls to zoom, rotate, etc. Mathematically, I feel like it should be possible to shift the origin of all of the TrackballControls calculations to the centre of the red sphere, but I can't figure out how to do this. I've tried all sorts of vector additions of the position of the red sphere to the _this.target and _eye vectors in TrackballControls.js, to no avail.
Thanks for your help!
I'd recommend OrbitControls rather than TrackballControls. My answer here applies primarily to OrbitControls; the same principle might also work with TrackballControls (I have not looked at its code in a while).
If you look at how OrbitControls works you should notice it uses this.object for the camera, and this.target for where the camera is looking at, and it uses that vector (the difference between them) for some of its calculations. Movement is applied to both positions when panning; only the camera is moved when rotating. this.pan is set to shift the camera, but out of the box it only deals with a panning perpendicular to the this.object to this.target vector because of the way it sets the panning vector.
Anyway, if you subtract the vector from object.position to controls.target and set controls.pan to that vector, that should make it jump to that object:
Fixed example code:
Add a helper to OrbitControls.js which has access to its local pan variable:
function goTo( vector ) {
// Cloning given vector since it would be modified otherwise
pan.add( vector.clone().sub( this.target ) );
}
Your own code:
function animate() {
requestAnimationFrame(animate);
mouseControls.goTo( object.position ); // Call the new helper
mouseControls.update();
render();
}
You'll also probably want to set mouseControls.noPan to true.
I'm trying to manage a 3Dobject that visualize the controls target in order to make rotation and zoom more immediatly understandable ...
I've made a sample here with an AxisHelper which is supposed to indicate the target and to keep the same size. In OrbitControls.js there are comments on each line I've added.
As you can see if you pan and zoom (right click and scroll) it manages cursors too, but the 'helper' has two problems :
the position and scale of the helper is set after the renders, that why it seems to be somewhat elastic ... And if I place the position/scale updates into the scope.update() function that's the same thing.
the function bellow scales the helper to a constant size, it computes a World/View scale at a defined point (the control's target) from a unit vector. But it seems it's not the good solution because when you scroll to the max zoom the helper is growing.
var point = new THREE.Vector3( 1, 0, 0 );
point = point.applyMatrix4( scope.object.matrixWorld );
var scale = point.distanceTo( scope.target );
helper.scale.set(scale, scale, scale);
So if you have an idea to achieve this you are welcome ...
i'm currently developing something similar with threejs and i think that:
I can't see the demo, my proxy not allow it.
I think that is correct...if the object helper is a mesh or a sprite added to the scene when orbit controls zoom the camera became more near to the objects in the scene, the objects dimension remain the same.
I'm really new in this stuff. I want to make a simple 3D scene, where i can fly around with PointerLockControls, but i want also to have some kind of flashlight. So spot light should point same direction as camera does.
I have made spotlight to follow camera but its target is bound to 0,0,0.
What is the best way to achieve this?
Thank you.
The SpotLight target is an Object3D, not a Vector3.
spotlight.target = myObject;
The best solution in your case is to use a PointLight instead, and use this pattern:
scene.add( camera );
camera.add( pointLight );
If you still want to use a spotlight, then do something like this:
scene.add( camera );
camera.add( spotLight.target );
spotLight.target.position.set( 0, 0, -1 );
spotLight.position.copy( camera.position ); // and reset spotlight position if camera moves
It is not generally required that the camera be added as a child of the scene, but it is required in this case because the light is added as a child of the camera.
three.js r.69
I had the same problem which I solved as follows:
flashlight = new THREE.SpotLight(0xffffff,4,40);
camera.add(flashlight);
flashlight.position.set(0,0,1);
flashlight.target = camera;
Since a SpotLight's .target needs to be an object (and not a position) I found it mentally easier to simply place the flashlight directly behind the camera, and then aim it at the camera. Thus the light shines through the camera and lights up the things in front of it.
This approach is fine if you are after a flashlight effect where the flashlight is held close to the chest (central to the body) and not off on one side.
Inspired by WestLangley's solution above, I found out that spotlight.target and spotlight itself can be added as children to the same object, whether that is the camera or another object, like a car or a gun. Then they are positioned relative to the parent object, so that there is no need to keep copying the position from one object to another.
You could, for instance, do something like this:
scene.add(camera);
camera.add(gun);
gun.position.set(-30,-30,0);
gun.add(spotlight);
spotlight.position.set(0,0,30);
gun.add(spotlight.target);
spotlight.target.position.set(0,0,31);
And now the gun will, by default, follow the camera, and the spotlight will light up along the gun. If the gun is for some reason rotated (deflecting a bullet or crawling on the ground or whatever), the spotlight will rotate too. THREE is a nice piece of software. :-)
If you attach the spotlight to the camera and point it in the same direction as the camera and don't position it away from the center, then the light cone will look constantly circular. For many applications it looks cooler and more realistic that it changes shape dynamically in the projection. A small offset is all it takes (such as in my example above, though I haven't tested that one).