Point SpotLight in same direction as camera three.js (Flashlight) - javascript

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).

Related

Three.js Move object forward without translateZ

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.

ThreeJS understanding where lights are

I've been trying for around 30 minutes to position a pointlight at the bottom of my model with very poor results. I don't know how many units my model is and I can't seem to exactly locate my light in the scene most of the time.
I tried adding a cube at the exact position of my pointlight but somehow adding another geometry to my scene breaks the texture update function for my main obj, so I guess that's out of the question.
Any tips on how to position lights with precision?
My code is at view-source:http://creativiii.com/3Dproject/
Each geometry has a boundingSphere attribute that you can use to figure out the size of your object. https://threejs.org/docs/api/core/Geometry.html
If the attribute does not have a value you can compute it using geometry.computeBoundingSphere();
As for the lights for each of the light types there is a helper function associated with it that will show you where the light is:
https://threejs.org/docs/index.html?q=Helper#Reference/Extras.Helpers/HemisphereLightHelper
https://threejs.org/docs/index.html?q=Helper#Reference/Extras.Helpers/DirectionalLightHelper
https://threejs.org/docs/index.html?q=Helper#Reference/Extras.Helpers/PointLightHelper
https://threejs.org/docs/index.html?q=Helper#Reference/Extras.Helpers/SpotLightHelper

Three.js - Create 3D text that's unaffected by zooming and panning

Three.js version: r79
Basically, I want to have a 3D object (a mesh created with THREE.TextGeometry) act like it's in 2D space but is always in the same exact place on the screen (never moves with the camera, no matter if I zoom or pan). Is there a way to do this?
I'm actually not quite sure how unless I make what I feel is a giant hack and update the coordinates of the text mesh every time there is a mouse scroll event or pan event.
One solution is to add the mesh as a child of the camera.
scene.add( camera ); // required, since the camera has a child
camera.add( mesh );
mesh.position.set( 0, 0, - 100 ); // or whatever
three.js r.79

three.js SpotLight orientation (direction) issue

Well, here is the problem,
Actually what I try to achieve is to place, at some places, some spotlights in a basic three.js example.
Here is the way I try to set the spotlight target position :
var light = new THREE.SpotLight(0xFFFFFF);
light.position.set(0,130,0);
light.target.position.set(200,-130,400);
scene.add(light);
The spotlight (light) keeps lighting the point (0,0,0) even if, when I console.log the target.position.(x,y,z) it gives me the right values...
Here is a quick fiddle I did with my full example.
http://jsfiddle.net/1xfno37y/7/
You have to update your light.target after changing (eg. setting position):
light.target.updateMatrixWorld();
Or just add your light.target to the scene:
scene.add( light.target );
Three.js r.71
http://jsfiddle.net/1xfno37y/19/
Further reading: Critical bug with spotLight.target.position #5555

How can I apply TrackballControls to a moving target?

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.

Categories