Must light helpers be added directly to scene? - three.js

Following method of adding light helper works ok:
var light = new THREE.SpotLight( 0xFFFFFF );
light.position.set(100,100,100);
scene.add(light);
var helper = new THREE.SpotLightHelper( light );
scene.add(helper);
but following will cause helper to be off position:
var wrapper = new THREE.Object3D();
wrapper.position.set(100,100,100);
var light = new THREE.SpotLight( 0xFFFFFF );
wrapper.add(light);
var helper = new THREE.SpotLightHelper( light );
wrapper.add(helper);
scene.add(wrapper);
It seems like helper position is taken from absolute light position to scene, but is then applied from it's wrapper, that means it is actually applied twice a thus doesn't match actual position of the light. In this example, helper would appear on (200,200,200). Same applies for PointLight and probably other light types.
Is it possible to put helpers into wrapper together with light and avoid position problem?
see it demonstrated here: http://jsfiddle.net/wfpxdw37/24/

Light Helpers are just that -- helpers.
They must be added as a child of the scene.
Consider that requirement a feature. :-)
three.js r.69

Related

Cannot get Bloompass and EffectComposer working together in Three.js

I cannot get post-processing to work with EffectComposer and BloomPass
I've looked at the past stack overflow posts including making sure that there is a renderpass, bloompass, and then a copyshader, with rendertoscreen set to true on the last pass, but nothing seems to work.
Here is my code:
(I render a simple cylinder earlier)
var renderModel = new THREE.RenderPass( scene, camera );
var effectCopy = new THREE.ShaderPass(THREE.CopyShader);
var effectBloom = new THREE.BloomPass ( 1, 25, 5);
effectCopy.renderToScreen = true;
renderer.autoClear = false;
var composer = new THREE.EffectComposer( renderer );
composer.setSize( width,height );
composer.addPass( renderModel );
composer.addPass( effectBloom );
composer.addPass(effectCopy);
and then I render the scene with
composer.render( 0.05 );
instead of
renderer.render( scene, camera );
Expected result is just a cylinder rendered in the scene(when I comment out adding the bloom and copy pass to the effect composer)
Cannot post images because this is my first question, but it renders a light blue cylinder with a black background.
But instead I just get a black screen when I add the passes.
I have tried doing different combinations such as just the rendermodel and bloom effect but it still doesn't work.
I am using webgl2 if that has any significance.
In case anyone is having trouble and this solution works:
It ended up being some problem with the three.js I was importing from a cdn.
(https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.js)
I changed to a minified version of three.js I had downloaded earlier and post-processing started to work again.
Hopefully, this helps anyone with similar problems.

Emit light from an object

I'm making a Three.js scene in which I have stars object and I would like to be able to make them "glow".
By glow I mean make them really emit light not just put a "halo" effect around them.
I tried to put a PointLight object at the same position as the star, this make light emit from the object but as you can see, it doesn't make the object "glow" which make a weird effect.
My current code looks like this:
class Marker extends THREE.Object3D {
constructor() {
super();
// load obj model
const loader = new OBJLoader();
loader.load(
"https://supersecretdomain.com/star.obj",
object => {
object.traverse(child => {
if (child instanceof THREE.Mesh) {
// child.material.map = texture;
child.material = new THREE.MeshLambertMaterial({
color: 0xffff00
});
child.scale.set(0.01, 0.01, 0.01);
}
});
this.add(object);
}
);
const light = new THREE.PointLight(0xffff00, 0.5, 5);
this.add(light);
}
}
Any idea of how to do this ? ;)
Adding a point light to the star is the correct way to make other objects be affected by its light. To make the star itself shine, you can set the emissive color of the material to something other than black (for best results, you probably want it to be the same color as the light).
In addition to setting up your light, and setting the material emissive property as mentioned by Jave above..
You might want to look into the THREE PostProcessing examples.. Specifically Unreal Bloom pass... If you can get that working, it really sells the effect.
https://threejs.org/examples/webgl_postprocessing_unreal_bloom.html
Notice how the highlight glow actually bleeds into the scene around the object...

Three.js FBXLoader2, change color of single Mesh (in Group or detached)

I have a .fbx model which load via FBXLoader2.
When I add the model (which include 3 meshes) to the scene, it is added as a Group. Now I try to change the color of a single Mesh in the Group, but all 3 meshes are getting the color. Then i thought they might be "linked" because of the Group. So i detached them (SceneUtils.detach).
Now I have all the meshes in the scene. Still, when I change the color of a single mesh, all three of them get the color. When I console.log the mesh (in the group or detached) it shows me the correct mesh.
var loader = new THREE.FBXLoader( manager );
loader.load( 'somemodel.fbx', function( object ) {
model = object;
var modelLength = model.children.length;
for (i=0;i<modelLength;i++) {
THREE.SceneUtils.detach(model.children[0], model, scene);
}
scene.children[0].material.emissive.setHex( 0xff0000 );
}
When i try to change position or scale the mesh, it works fine.
Anybody had the problem before?
Just clone the material and replace it with original once.
scene.children[0].material = scene.children[0].material.clone();
scene.children[0].material.emissive.setHex( 0xff0000 );

Loading multiple objects in Three.js from Blender

I have a quite complex shape (dressed girl) that in Blender is broken down into different objects and it's loaded into Three.js with the JSON loader (with a little hack I made, that uses zipped files instead of just JSON files, as there are a lot of vertices).
As I want to change dynamically the style of the dress from a Web page, I was wondering how I can show/hide different pieces (e.g. sleeves) in the scene.
I tried traversing the THREE.Mesh, but there are no children.
When I export from Blender with the JSON exporter, I don't see anything referring to the names of the objects in the JSON. Is the structure lost?
If you are using meshes containing lots of vertices, I would advise you to use the openCTM webGL loader instead of zip hacking. Here is a link to the loader : http://threejs.org/examples/webgl_loader_ctm.html
This mesh compression tool uses LZMA compression method and can reduce the size of your files by 93%...
Concerning the JSONLoader, using an array might help:
var meshes = [];
...
var loader = new THREE.JSONLoader();
var onGeometry = function(geom)
{
var mesh = new THREE.SceneUtils.createMultiMaterialObject(geom, [material]);
meshes.push( mesh );
...
scene.add(mesh);
};
loader.load("yourfile.js", onGeometry);
Hope this helps
It is possible to load an entire scene with several meshes from a json file exported from Blender and handle them separately!
You can follow the complete process of exporting a entire scene from Blender and the right way of handling the exported meshes on my answer of this post.
So, you can get the different meshes and manipulate them separately using the getObjectByName method. But it is important to know that the loaded object isn't a Geometry anymore. It is labeled with the Scene type by now and it must be handled in a different way.
The loading code must look like this one:
loader = new THREE.JSONLoader();
loader.load( "obj/Books.json", function ( loadedObj ) {
var surface = loadedObj.getObjectByName("Surface");
var outline = loadedObj.getObjectByName("Outline");
var mask = loadedObj.getObjectByName("Mask");
scene.add(surface);
scene.add(outline);
scene.add(mask);
} );
Besides, you can handle the multiple materials of single mesh using THREE.MeshFaceMaterial like in the following code:
var mat1 = new THREE.MeshLambertMaterial( { map: texture1 } );
var mat2 = new THREE.MeshLambertMaterial( { map: texture2 } );
var materials = [mat1, mat2];
var faceMat = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh( geometry, faceMat );
scene.add( mesh );
Hope this helps :)

Can't seem to make a functional THREE.js collada loader

I'm having issues getting a custom made collada object with no built in camera or lighting to render. I more or less copied what I had seen in a few collada examples to create my own loader, which looks like this:
var loader = new THREE.ColladaLoader();
var room, scene, stats;
loader.load('../Models/Rooms/boot.dae', function colladaReady( collada ){
collada.scene.getChildByName('Cube',true).doubleSided = true;
room = collada.scene;
room.scale.x = room.scale.y = room.scale.z = 1;
room.updateMatrix();
init();
});
The init function is fairly basic and looks like this
scene = new THREE.Scene();
scene.add( room );
scene.add( camera );
renderer.render(scene, camera);
Here is the actual object I'm trying to render. I have also tried it out with the monster.dae file that is in the examples folder without success. The Chrome javascript console isn't showing any errors, so I'm not quite sure where to look in my code. It all resembles functional examples, so I'm not sure why it's not functional. Is there something I'm unaware of that is relevant to collada loading?
RESOLVED: The item was rendering, but had no skin or texture associated with it. So it was rendering at the same colour as the background, which understandably appears to not be rendering at all. Discovered by adding a grid to the ground just to check.

Resources