9 Oct 2017

Clone room face of the model

I made a sample with Forge Viewer a few months ago. In this application, the 'room' objects in a building are rendered with shader (the object faces are colored in native Three.js way). I just got a chance to sort it out for reference. 



Firstly, we need to have a building model with 'room' objects. It is a pity Forge translator does not extract native Revit file in the format of level (floor), rooms, while Navisworks has the concept of rooms and brings this along when imported into Forge. So, we can save the Revit file to NWD format and send to Forge to translate. before opening in Navisworks, make sure the options for Revit are ticked.




All rooms have the property [Type=Room] .By Viewer.search, we can find out all rooms. The code snippet below further filter out the rooms that locate on the specific floor.


            function (idArray) {
                console.log('rooms numbers in this floor:' + idArray.length);
                $.each(idArray, function(num, dbid) {
                                function(propData) {
                                    //check if this room is from specific floor
                                    var findit = propData.properties.filter(function(item) { 
                                        return (item.displayName === 'Layer' 
                                        && item.displayValue === _specificFloorName); 

For each room object, get the fragments, and get the triangles of the object as introduced in the other blog: Show up Mesh Triangles from Data of HitTest

Finally, draw the triangles by Three.js mesh:

function createFaceGeometry(vA, vB, vC, geom,color){
           var geom = new THREE.Geometry();
        var vIndex = geom.vertices.length;
        var face = new THREE.Face3(vIndex, vIndex + 1, vIndex + 2);
        return geom;
    function drawFaceMesh(geom, overlaySceneName, material, mesh){
        if(!material) {
            material = _faceMaterial
        var faceMesh = new THREE.Mesh(geom, material);  
        _viewer.impl.addOverlay(_overlaySceneName, faceMesh);
        return faceMesh;

With the workflow I introduced in the other blog Show/Hide Textures of Object in Forge Viewer, the shader faces can be toggled visible or not. The code below filter out the specific materials that are for shader face (with the special names) and make the material transparent.  


this.hideShader = function() {  
        //get materials collection of this model
        var mats = _viewer.impl.matman()._materials;
        //define a color in grey
        var grey = new THREE.Color(0.5, 0.5, 0.5);

        //iterate each material
        for (index in mats) {

            var m = mats[index];

                //if this is a material created for the shader face
                _oldTextures[index] = m.map;
                _oldColors[index] = m.color; 

                //set texture to null
                m.map = null;
                //set the color to the grey (but because m.transparent = true, this line does not take effect )
                m.color = grey;

                //set the material completely transparent
                m.transparent = true;
                m.opacity = 0;
                //notify Viewer to refresh the scene.
                m.needsUpdate = true; 
        _viewer.impl.invalidate(true, true, false);

This is the test JS code project: https://jsfiddle.net/xiaodongliang/1qe0jnpo/6/ and the extension source code is available at https://gist.github.com/xiaodongliang/377c9e34eac238cf0d912ce5eb74e1ea .  Some codes are borrowed from the IoT project my colleague Ryuji Ogasawara produced. Thank you Ryuji!  

Related Article