I'm trying to only show the single side of a cube mesh that is facing the camera, and have hacked together a very inelegant working version but I can't imagine it's the right way to go about this.
The camera and cube will always be at right angles to each other, so I thought I could extrapolate the camera's directional vector and take the inverse of that to get the correct face of the cube. With the face determined, I then set all other materials to a transparent material.
I created a simple(ish) scene where the camera's position is fixed and I'm simply rotating the cube:
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 2, 5000);
camera.eulerOrder = "YXZ";
camera.position.set(0, 0, 0);
scene.add(camera);
cubeGeometry = new THREE.CubeGeometry(10, 5, 10);
var cubeGeometryMaterials = [
new THREE.MeshBasicMaterial({color:0xff0000, transparent: true, opacity: 0.75, side: THREE.DoubleSide}),
new THREE.MeshBasicMaterial({color:0x00ff00, transparent: true, opacity: 0.75, side: THREE.DoubleSide}),
new THREE.MeshBasicMaterial({color:0xffffff, transparent: true, opacity: 0.75, side: THREE.DoubleSide}),
new THREE.MeshBasicMaterial({color:0x000000, transparent: true, opacity: 0.75, side: THREE.DoubleSide}),
new THREE.MeshBasicMaterial({color:0x0000ff, transparent: true, opacity: 0.75, side: THREE.DoubleSide}),
new THREE.MeshBasicMaterial({color:0xff00ff, transparent: true, opacity: 0.75, side: THREE.DoubleSide})
];
mesh = new THREE.Mesh( cubeGeometry, new THREE.MeshFaceMaterial(cubeGeometryMaterials) );
mesh.originalMaterials = cubeGeometryMaterials.slice(0);
mesh.position.set(camera.position.x, -5, camera.position.z - 25);
scene.add(mesh);
cubeQuaternion = new THREE.Quaternion();
cubeQuaternion.setFromRotationMatrix(mesh.matrix);
cubeVector = (new THREE.Vector3( 0, 0, 1 )).applyQuaternion(cubeQuaternion);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
$('#three').append(renderer.domElement);
animate();
}
and here's what I cobbled together for the rendering:
function render() {
// rotate cube
mesh.rotation.y += (rotateAngle - mesh.rotation.y)/10;
if(Math.abs(mesh.rotation.y - rotateAngle) < 0.001){
cancelAnimationFrame(rafID);
}
// update cubeVector
// via: https://stackoverflow.com/questions/15696963/three-js-set-and-read-camera-look-vector
// & https://stackoverflow.com/questions/18058776/how-to-tell-if-the-camera-is-looking-at-the-face-of-a-plane
cubeQuaternion.setFromRotationMatrix(mesh.matrix);
cubeVector = (new THREE.Vector3( 0, 0, 1 )).applyQuaternion(cubeQuaternion).negate();
// vector.round() doesn't seem to work?
var roundedVector = {
x: Math.round(cubeVector.x),
y: Math.round(cubeVector.y),
z: Math.round(cubeVector.z)
}
var faceName = roundedVector.x+"x"+roundedVector.y+"x"+roundedVector.z;
var faceIndex = faces.indexOf(faceName);
var newMaterial;
for(var i = 0, len = mesh.material.materials.length; i < len; i ++){
if(showOneSide == true){
// only side facing camera has original material
if(i == faceIndex){
newMaterial = mesh.originalMaterials[i];
}else{
newMaterial = transparentMaterial;
}
}else{
// show original material
newMaterial = mesh.originalMaterials[i];
}
// change material if not already set
if(mesh.material.materials[i] != newMaterial){
mesh.material.materials[i] = newMaterial;
mesh.material.materials[i].needsUpdate = true;
if(showOneSide){
$('#face-index').text('faceIndex: '+i);
}
}
}
renderer.render(scene, camera);
}
Any guidance on the best way to go about this would be amazing!
the current fiddle: http://jsfiddle.net/majman/6vrH8/
referenced these questions - three.js set and read camera look vector - How to tell if the camera is looking at the face of a plane