Возврат к предыдущему материалу в Autodesk Forge Viewer - PullRequest
0 голосов
/ 09 марта 2019

Я помещаю новый материал через

highlight(dbId, color) {
let viewer = this.viewer;

let myMaterial = this.createMaterial(color);

// used to rescale and remove the z-fighting
let scaleRatio = 1.005; // this was determined as optimal through visual inspection

var tree = NOP_VIEWER.model.getData().instanceTree;

var result = new Object();
result.dbId = dbId;
result.oldMaterials = {};

tree.enumNodeFragments(dbId,
    function(fragId) {
        result.oldMaterials[fragId] = viewer.model.getFragmentList().getMaterial(fragId);
        viewer.model.getFragmentList().setMaterial(fragId, myMaterial);

        /* important technique if you want to remove z-fighting */
        let fragProxy = viewer.impl.getFragmentProxy(viewer.model, fragId);
        fragProxy.scale = new THREE.Vector3(scaleRatio, scaleRatio, scaleRatio);
        fragProxy.updateAnimTransform();
    },
    true);

viewer.impl.invalidate(true);
return result;
}

createMaterial(color) {

const material = new THREE.MeshPhongMaterial({
    side: THREE.DoubleSide,
    reflectivity: 0.0,
    flatShading: true,
    transparent: true,
    opacity: 0.5,
    color
});

const materials = this.viewer.impl.matman();

materials.addMaterial(
    "MyCustomMaterial" + color.toString(),
    material,
    true);

return material;
}

Затем я пытаюсь вернуть его к предыдущему материалу через

unHighlight(dbId, oldMaterials) {
    let viewer = this.viewer;
    var tree = NOP_VIEWER.model.getData().instanceTree;

    let scaleRatio = 1.020; // this was determined as optimal through visual inspection

    tree.enumNodeFragments(dbId,
        function (fragId) {
            const materials = this.viewer.impl.matman();

            materials.addMaterial(
                "MyCustomMaterial" + dbId + fragId,
                oldMaterials[fragId],
                true);

            viewer.model.getFragmentList().setMaterial(fragId, oldMaterials[fragId]);

            /* important technique if you want to remove z-fighting */
            let fragProxy = viewer.impl.getFragmentProxy(viewer.model, fragId);
            fragProxy.scale = new THREE.Vector3(scaleRatio, scaleRatio, scaleRatio);
            fragProxy.updateAnimTransform();
        },
        true);

    viewer.impl.invalidate(true);

}

Но это не дало видимых результатов.Как я могу вернуться к предыдущим материалам?Если я правильно понимаю логику средства просмотра, у него есть материал для каждого фрагмента каждого dbId.И при вызове setMaterial () мы заменяем предыдущий материал нашим.И чтобы вернуть его, мы должны сохранить старый материал через getMaterial () для каждого элемента fragId, а затем вернуть его через setMaterial ().Но по какой-то причине этот подход не работает.

UPD:

Я обнаружил странную вещь.Когда я сохраняю данные об этом в консоли перед сохранением материала, оказывается, что для одного фрагмента указано несколько материалов.

    highlight(externalId, color, dict) {
    let viewer = this.viewer;
    var dbId = dict[externalId];


    let myMaterial = this.createMaterial(color);

    // used to rescale and remove the z-fighting
    let scaleRatio = 1.005; // this was determined as optimal through visual inspection

    var tree = NOP_VIEWER.model.getData().instanceTree;

    var result = new Object();
    result.dbId = dbId;
    result.oldMaterials = {};

    tree.enumNodeFragments(dbId,
        function (fragId) {
            const previousMaterial = viewer.model.getFragmentList().getMaterial(fragId).clone();
            //!!!!!!!!!!!!!!!!!!!!
            console.log(dbId);
            console.log(fragId);
            console.log(previousMaterial);
            //!!!!!!!!!!!!!!!!!!!!
            result.oldMaterials[fragId] = previousMaterial;
            viewer.model.getFragmentList().setMaterial(fragId, myMaterial);

            /* important technique if you want to remove z-fighting */
            let fragProxy = viewer.impl.getFragmentProxy(viewer.model, fragId);
            fragProxy.scale = new THREE.Vector3(scaleRatio, scaleRatio, scaleRatio);
            fragProxy.updateAnimTransform();
        },
        true);

    viewer.impl.invalidate(true);
    return result;
}

Console log

Ответы [ 2 ]

0 голосов
/ 12 марта 2019

Существует несколько подходов к решению этой проблемы.

Самый простой, как предложил Брайан, использовать viewer.SetThemingColor - хороший пост в блоге можно найти здесь: https://forge.autodesk.com/blog/customize-viewer-context-menu;

Однако описанный выше подход работает только на уровне цвета и не очень полезен, если вы хотите лучше контролировать свойства материала (например, прозрачность).

Другой подход - тот, который вы выбрали, когда вы создаете свой собственный материал и регистрируете его.в MaterialManager Просмотрщика (как вы сделали).При таком подходе при назначении материала фрагменту старые материалы не исчезают / не перезаписываются, но по-прежнему доступны в MaterialManager вместе с вашим пользовательским материалом (таким образом, клонирование избыточно и в целом работает не очень хорошо с материалами three.js).).С этой точки зрения для восстановления материала необходимо переназначить старый материал (ссылка на который может быть сохранена до назначения новых материалов):

highlight(dbId, color) {
  let viewer = this.viewer;
  let myMaterial = this.createMaterial(color);
  this.tree.enumNodeFragments(dbId, (fragId) => {
      //save the reference to original material
      this.originalMaterial[fragId] = viewer.model.getFragmentList().getMaterial(fragId);

      viewer.model.getFragmentList().setMaterial(fragId, myMaterial);
  });


  viewer.impl.invalidate(true);
}


unhighlight(dbId) {
  this.tree.enumNodeFragments(dbId, (fragId) => {

      if (this.originalMaterial[fragId]) {
          viewer.model.getFragmentList().setMaterial(fragId, this.originalMaterial[fragId]);
      }
  });
  viewer.impl.invalidate(true);
}
0 голосов
/ 11 марта 2019

Сохраните копию исходного материала вместо ссылки на его запись в списке фрагментов, которая была бы переопределена вашим пользовательским материалом к ​​моменту попытки восстановления:

result.oldMaterials[dbId] = viewer.model.getFragmentList().getMaterial(fragId).clone();
...