Search code examples
autodesk-forgeautodesk-viewer

how to add custom material to a fragment in forge viewer


I have an extension with such methods, and when I call this method to change the material (color it red), the object becomes transparent and the following errors appear in the console

WebGLRenderer.js:5561 WebGL: INVALID_VALUE: uniform3fv: no array

[.WebGL-0000737C06582900] GL_INVALID_OPERATION: Active draw buffers with missing fragment shader outputs.

setColorToItem = (id) => { 
        const material = this.createMaterial('#ff0000'); 
        const model = this.viewer.model; 
        const frags = model.getFragmentList(); 
        model.unconsolidate(); 
 
        this.tree.enumNodeFragments( 
            id, 
            (fragId) => { 
                frags.setMaterial(fragId, material); 
                this.viewer.impl.getFragmentProxy(model, fragId).updateAnimTransform(); 
            }, 
            true, 
        ); 
        this.viewer.impl.invalidate(true); 
    }; 
 
    createMaterial = (color) => { 
        const threeColor = new THREE.Color(color); 
        const material = new THREE.MeshPhongMaterial({ 
            side: THREE.DoubleSide, 
            flatShading: true, 
            color: threeColor, 
        }); 
 
        const materials = this.viewer.impl.matman(); 
 
        materials.addMaterial('CustomMaterial' + color.toString(), material, true); 
 
        return material; 
    };

What could be the problem? I tried using different materials (MeshBasicMaterial, MeshLambertMaterial) version forge-viewer 7 version threejs 0.71 as indicated here https://forge.autodesk.com/en/docs/viewer/v7/developers_guide/viewer_basics / also tried the latest


Solution

  • I tried this with a slightly modified version of your code snippet (as shown below) with the viewer version 7.*, and I can set the color to the material successfully. Is there perhaps any other custom JavaScript logic in your app that could interfere with the new materials? From the error logs it looks like the shader is having issues obtaining the 3 float values (red, green, blue) from the THREE.Color object.

    function createMaterial(viewer, color) {
        const material = new THREE.MeshPhongMaterial({
            side: THREE.DoubleSide,
            flatShading: true,
            color: new THREE.Color(color),
        });
        const materials = viewer.impl.matman();
        materials.addMaterial('CustomMaterialRed', material, true);
        return material;
    }
    
    function applyMaterial(model, dbid, material) {
        const tree = model.getInstanceTree();
        const frags = model.getFragmentList();
        tree.enumNodeFragments(
            dbid,
            (fragid) => frags.setMaterial(fragid, material),
            true
        );
        model.unconsolidate();
    }
    
    // ...
    
    let mat = createMaterial(viewer, '#ff0000');
    applyMaterial(viewer.model, 1234, mat);