Reputation: 641
I am merging multiple cubes into different block shapes with three.js
using THREE.GeometryUtils.merge
. I want to make these block shapes transparent, but when it's transparent you can see that it's multiple cubes stuck together like this:
How do I make my merged cubes transparent without rendering the inside edges? (how do I remove the inner faces?)
My code that merges the cubes:
geometry = new THREE.CubeGeometry(STEP_SIZE, STEP_SIZE, STEP_SIZE);
for (i = 0; i < shape.length; i++) {
tmpGeometry = new THREE.Mesh(new THREE.CubeGeometry(STEP_SIZE, STEP_SIZE, STEP_SIZE));
tmpGeometry.position.x = STEP_SIZE * shape[i].x;
tmpGeometry.position.y = STEP_SIZE * shape[i].y;
THREE.GeometryUtils.merge(geometry, tmpGeometry);
}
block = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: 0x0000ff, opacity: 0.5, transparent: true }));
Upvotes: 2
Views: 3939
Reputation: 641
After some experimenting I finally got what I wanted. Hope this will help other people.
I go through each face of the block and raycast the block itself using the face's centroid and inverted normal (so that the normal points inward). If it intersects with another face that's part of the block, we know that that face is an inner face and we can go ahead and remove it.
// block is a Three.Mesh object
function removeInternalFaces(block) {
var geometry = block.geometry;
var face;
var toDelete = [];
var blockRaycaster = new THREE.Raycaster();
// raycast itself from the center of each face (negated normal), and whichever face gets intersected
// is an inner face
for (i = 0; i < geometry.faces.length; i++) {
face = geometry.faces[i];
if (face) {
normal = face.normal.clone();
normal.negate();
blockRaycaster.set(face.centroid, normal);
intersects = blockRaycaster.intersectObject(block);
for (j = 0; j < intersects.length; j++) {
toDelete.push(intersects[j].faceIndex);
}
}
}
// actually delete them
for (i = 0; i < toDelete.length; i++) {
delete geometry.faces[toDelete[i]];
}
geometry.faces = geometry.faces.filter( function(v) { return v; });
geometry.elementsNeedUpdate = true; // update faces
}
Upvotes: 4
Reputation: 6887
You can actually initialize cube's each face material separately and individually set the opacity of the inner faces to 0. The Code will be something like this.
var materialArray = [];
materialArray.push(new THREE.MeshLambertMaterial({
opacity:0,
color:0x0000FF,
transparent: true
}));// assuming you want this face to be transparent
materialArray.push(new THREE.MeshLambertMaterial({
opacity:0,
color:0x0000FF,
transparent: true
}));// assuming you want this face to be transparent
materialArray.push(new THREE.MeshLambertMaterial({
opacity:0.5,
color:0x0000FF,
transparent: true
}));
materialArray.push(new THREE.MeshLambertMaterial({
opacity:0.5,
color:0x0000FF,
transparent: true
}));
materialArray.push(new THREE.MeshLambertMaterial({
opacity:0.5,
color:0x0000FF,
transparent: true
}));
materialArray.push(new THREE.MeshLambertMaterial({
opacity:0.5,
color:0x0000FF,
transparent: true
}));
var CubeMat = new THREE.MeshFaceMaterial(materialArray);
and pass this to your cube mesh something like this.
block = new THREE.Mesh(geometry,CubeMat )
check this JsFiddle for a demo
Upvotes: 1