When I create multiple mesh's with the same name I can't select them all when I want to remove them from a scene.
I've tried traversing the function to no avail.
event.preventDefault();
scene.traverse(function(child) {
if (child.name === "blueTiles") {
var remove_object = scene.getObjectByName( "blueTiles", true );
scene.remove(remove_object);
}
});
var surroundMaterial = new THREE.MeshBasicMaterial({ color: 0x154995, side: THREE.DoubleSide, transparent: true, opacity: 0.8 });
surroundingCubes = new THREE.Mesh( geometry, surroundMaterial );
scene.add( surroundingCubes );
surroundingCubes.name = "blueTiles";
surroundingCubes.position.set(selectedObject.position.x - 1, 0.11, selectedObject.position.z);
var surroundMaterial = new THREE.MeshBasicMaterial({ color: 0x154995, side: THREE.DoubleSide, transparent: true, opacity: 0.8 });
surroundingCubes = new THREE.Mesh( geometry, surroundMaterial );
scene.add( surroundingCubes );
surroundingCubes.name = "blueTiles";
surroundingCubes.position.set(selectedObject.position.x + 1, 0.11, selectedObject.position.z);
surroundingCubes.rotation.x = Math.PI / 2;
I should be able to only delete all the objects with the name blueTiles
EDIT I switched from names to Groups, and that worked wonders
SOLUTION BELOW
function onDocumentMouseDown(event) {
for (var i = group.children.length - 1; i >= 0; i--) {
group.remove(group.children[i]);
}
var surroundingMaterial = new THREE.MeshBasicMaterial({ color: 0x154995, side: THREE.DoubleSide, transparent: true, opacity: 0.8 });
var geometry = new THREE.PlaneGeometry(1, 1, 1, 1);
if ( selectedObject.position.x - 1 >= 0) {
surroundingCube = new THREE.Mesh( geometry, surroundingMaterial );
surroundingCube.position.set(selectedObject.position.x - 1, 0.11, selectedObject.position.z);
surroundingCube.rotation.x = Math.PI / 2;
group.add(surroundingCube);
}
if ( selectedObject.position.x + 1 <= 9) {
surroundingCube = new THREE.Mesh( geometry, surroundingMaterial );
surroundingCube.position.set(selectedObject.position.x + 1, 0.11, selectedObject.position.z);
surroundingCube.rotation.x = Math.PI / 2;
group.add(surroundingCube);
}
scene.add( group );
}
You can try grouping the meshes using the THREE.group class.
A very basic usage would be something like:
var meshes = new THREE.Group();
var mesh1 = new THREE.Mesh( geometry, material );
var mesh2 = new THREE.Mesh( geometry, material );
var mesh3 = new THREE.Mesh( geometry, material );
meshes.add( mesh1 );
meshes.add( mesh2 );
meshes.add( mesh3 );
scene.add( meshes );
getObjectByName just calls getObjectByProperty (using the name property) which only returns the first object it finds.
You really just need to loop over children of the scene / object3d, check their name, and remove.
If you know all the ones you want to remove will be at the top level it is simple.
Something like....(untested)
for ( var i = 0, l = scene.children.length; i < l; i ++ ) {
if (scene.children[i].name === 'blueTiles') {
scene.remove(scene.children[i]);
}
}
If you also want to check at lower levels, you probably want some sort of recursion.
EDIT...
After having another look at your question..and remembering that there is a traverse function
You seem to already be traversing the scene and have access to the child.
I think you just need to change your function (and not call getObjectByName at all).
scene.traverse(function(child) {
if (child.name === "blueTiles") {
scene.remove(child);
}
});
Related
attempting to apply a bump map to an object loaded, but no change is seen on the material
var loader = new THREE.ObjectLoader();
loader.load("../js/brain2.json", function(object) {
var mapHeight = new THREE.TextureLoader().load( "../js/texture.jpg" );
var material = new THREE.MeshPhongMaterial( { color: 0x888888, specular: 0xEEEEEE, shininess: 5} );
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
child.material.bumpMap = mapHeight;
child.material.bumpScale = 1;
var geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
geometry.computeFaceNormals();
geometry.mergeVertices();
geometry.computeVertexNormals();
child.geometry = new THREE.BufferGeometry().fromGeometry( geometry );
var modifier = new THREE.BufferSubdivisionModifier(1);
modifier.modify(geometry);
child.material.overdraw = 1
};
});
object.scale.set(15, 15, 15);
object.position.x = 1;
object.position.y = 1;
object.position.z = 1;
object.rotation.set( 5, 1, 1 );
scene.add( object );
});
I've already fixed earlier issues with this code, including applying a subdivision modifier to it, but now it appears the bump map refuses to be applied.
Got the following problem:
im trying to make rings around saturn, but it seems they are somehow rendered in wrong order:
The thing is how each planet is created. Each planet is a child of different root object (THREE.Object3d), which contains a bodyContainer (THREE.Object3d). BodyContainer contains the planet mesh. When I add the rings mesh to body or bodycontainer it is rendered as on the picture above.
For tests ive created a 'free' sphere and rings, which ive added. to the scene and everything works as supposed for objects added directly to the scene.
Even if I add rings as a child of the sphere which is added to the scene it works fine.
Here is the code I use to generate the planet body:
export default function generateBody(radius, basic, name) {
var geometry = new THREE.SphereGeometry( radius, 24, 24 );
var material;
if(basic) {
material = new THREE.MeshBasicMaterial({color: 0xFBE200});
} else {
material = new THREE.MeshLambertMaterial({
//depthWrite: false,
//depthTest: true,
});
if(textures[name].hasOwnProperty('map')) material.map = THREE.ImageUtils.loadTexture(textures[name].map);
if(textures[name].hasOwnProperty('bump')) material.bumpMap = THREE.ImageUtils.loadTexture(textures[name].bump);
if(textures[name].hasOwnProperty('specular')) material.specularMap = THREE.ImageUtils.loadTexture(textures[name].specular);
if(textures[name].hasOwnProperty('normal')) material.normalMap = THREE.ImageUtils.loadTexture(textures[name].specular);
}
var mesh = new THREE.Mesh( geometry, material )
mesh.scale.set( params.bodyScale, params.bodyScale, params.bodyScale );
mesh.rotateX(Math.PI / 2);
mesh.renderOrder = 0;
return mesh;
}
and how i add the rings:
var circlemesh = new THREE.XRingGeometry(1.2 * (def && def.diameter || 139822000) * M_TO_AU / 2, 2 * (def && def.diameter || 139822000) * M_TO_AU / 2, 2 * 64, 5, 0, Math.PI * 2);
var circleMaterial = new THREE.MeshLambertMaterial( {
map: THREE.ImageUtils.loadTexture('../img/planet-textures/saturn/saturnringcolor.jpg'),
alphaMap: THREE.ImageUtils.loadTexture('../img/planet-textures/saturn/saturnringpattern.gif'),
//transparent: true,
side: THREE.DoubleSide,
//depthWrite: false,
//depthTest: true
});
var mesh = new THREE.Mesh(circlemesh, circleMaterial);
mesh.renderOrder = 1;
this.body.add(mesh);
furtheron:
this.bodyContainer.add(this.body)
this.root.add(this.bodyContainer)
scene.add(this.root)
For testing on a sphere added directly to the scene i use just a plain sphere geometry and the same mesh for rings used here.
var circlemesh = new THREE.XRingGeometry(1.2 * 5, 2 * 5, 2 * 64, 5, 0, Math.PI * 2);
var circleMaterial = new THREE.MeshLambertMaterial( {
map: THREE.ImageUtils.loadTexture('../img/planet-textures/saturn/saturnringcolor.jpg'),
alphaMap: THREE.ImageUtils.loadTexture('../img/planet-textures/saturn/saturnringpattern.gif'),
transparent: true,
side: THREE.DoubleSide,
//depthWrite: false,
//depthTest: true
});
var ringmesh = new THREE.Mesh(circlemesh, circleMaterial);
//ringmesh.renderOrder = 1;
//scene.add(ringmesh);
var SPHEREgeometry = new THREE.SphereGeometry( 5, 32, 32 );
var SPHEREmaterial = new THREE.MeshLambertMaterial( {color: 0xffff00} );
var sphere = new THREE.Mesh( SPHEREgeometry, SPHEREmaterial );
//sphere.renderOrder = 0;
scene.add( sphere );
sphere.add( ringmesh );
What fixed the problem was increasing the near of the camera.
No extra parameters in material weren't needed.
Here's how you can use Object3D in a parent child setup in THREE:
Object3D Parent Child Fiddle
var root = new THREE.Object3D();
var rootcontainer = new THREE.Object3D();
root.parent = rootcontainer;
mesh = new THREE.Mesh( geometry, material );
root.add( mesh );
rootcontainer.add(root);
scene.add(rootcontainer);
How can I access multiple meshes with the same name?
var mesh1 = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0xffffff }));
mesh1.name = "meshes";
scene.add( mesh1);
var mesh2 = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0xffffff }));
mesh2.name = "meshes";
scene.add( mesh2);
Something like:
meshes.position.z = 2;
You could store the meshes in a two dimensional array indexed by their name. Then you could do:
arr["meshes"].forEach(function(obj, idx){
obj.position.z = 2;
});
Trying to add a simple object to a three.js scene. I'm getting the error Uncaught ReferenceError: Cube is not defined, but it seems to be defined to me. What am I doing wrong here?
Here's a plunker
Here's the relevant js:
// Cube
Cube = function(){
var geometry = new THREE.BoxGeometry( 50, 50, 50 );
for ( var i = 0; i < geometry.faces.length; i += 2 ) {
var hex = Math.random() * 0xffffff;
geometry.faces[ i ].color.setHex( hex );
geometry.faces[ i + 1 ].color.setHex( hex );
}
var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );
box = new THREE.Mesh( geometry, material );
box.position.y = 25;
}
function createCube(){
cube = new Cube();
scene.add(cube);
}
Two things are wrong.
You should be adding the cube mesh to the scene. So instead of box = new THREE.Mesh( geometry, material ); put return box = new THREE.Mesh( geometry, material );
call createCube() after you have defined the function
I have some strange behaviour with bounding box in three.js.
I use STLLoader and for some models everything works fine, but for some of them box is shifted.
For example:
http://oi37.tinypic.com/35a1y4l.jpg
and
http://oi34.tinypic.com/4hf4tl.jpg
Bounding box has right size and it's position is (0,0,0). The same position has loaded STL model.
And here is my code:
function stlLoader() {
var redPhongMaterial = new THREE.MeshPhongMaterial({ color: 0xFFEA32, side: THREE.DoubleSide, ambient:0x000000}); // yellow
var stlLoader = new THREE.STLLoader();
stlLoader.addEventListener('load', function (event) {
var stlGeometry = event.content;
var mesh = new THREE.Mesh(stlGeometry, redPhongMaterial);
mesh.scale.set(2, 2, 2);
mesh.castShadow = true;
mesh.receiveShadow = true;
stlGeometry.computeBoundingBox();
var boundingBox = mesh.geometry.boundingBox.clone();
drawBoundingBox(boundingBox, mesh.scale.x, mesh.scale.y, mesh.scale.z);
mesh.position.y = 0;
mesh.position.x = 0;
mesh.position.z = 0;
scene.add( mesh );
loadComplete();
} );
stlLoader.load( ptsfilestoload );
}
function drawBoundingBox(box, scaleX, scaleY, scaleZ)
{
var length = scaleX * (box.max.x - box.min.x);
var height = scaleY * (box.max.y - box.min.y);
var depth = scaleZ * (box.max.z - box.min.z);
var boundingBoxGeometry = new THREE.CubeGeometry( length, height, depth );
for ( var i = 0; i < boundingBoxGeometry.faces.length; i ++ )
{
boundingBoxGeometry.faces[i].color.setHex( Math.random() * 0xffffff );
}
var boundingBoxMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors, transparent: true, opacity: 0.7 } );
var boundingBoxMesh = new THREE.Mesh( boundingBoxGeometry, boundingBoxMaterial);
scene.add( boundingBoxMesh );
}
Or maybe this is problem with STLLoader? I'm really new to webgl and three.js so any help appreciated
In your drawBoundingBox routine you need
var bboxCenter = box.center ();
boundingBoxMesh .translateX (bboxCenter.x);
boundingBoxMesh .translateY (bboxCenter.y);
boundingBoxMesh .translateZ (bboxCenter.z);
just before you add the mesh to the scene. Your Cube is created around 0,0,0.