2

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

Community
  • 1
  • 1
majman
  • 1,993
  • 14
  • 23
  • 1
    maybe this can give you other ideas but if you are working with only 90 degree rotations, your algorithm does not seem to be that bad. At least what i got from it from cross-reading your source code O:-) http://stackoverflow.com/questions/18182376/figuring-out-how-much-of-the-side-of-a-cube-is-visible/18188564#18188564 – GuyGood Apr 09 '14 at 13:00

0 Answers0