How do i set the theming of components of a model which is hidden:
If i not using the hideModel function everthing is working perfect, but if the model is hided i get an error 2 => BAD_DATA = 2,
this.viewerComponent.viewer.hideModel(this.viewerComponent.viewer.model);
The following things i already tried out:
this.viewerComponent.viewer.getHiddenModels()[0].setThemingColor(idArray[0], color, true);
this.viewerComponent.viewer.setThemingColor(idArray[0], color, this.viewerComponent.viewer.getHiddenModels()[0]);
This is not working for sure, since the model of the viewer will be null after hiding
this.viewerComponent.viewer.setThemingColor(idArray[0], color, this.viewerComponent.viewer.model());
Viewer Version 7
Thanks for help
Unfortunately, viewer.hideModel is a bit of a misnomer because it doesn't just hide the model, it actually unloads it. If you want to hide the model while still keeping all its data in memory, you might be able to achieve a similar result by calling viewer.hide(viewer.model.getRootId()). This will hide (or "ghost", if you have "ghosting" enabled; see below) the individual elements of the model while still keeping them in memory, so you can still configure properties like the theming color.
Related
Some background:
I'm using Forge to visualize IFC models. Some of my uploaded models have IfcOpeningElements which seems to be hidden in Forge by default, at least when setting ghosting to false via viewer.setGhosting(false). I'm also having functionality to hide normal elements in the viewer (viewer.hide(dbIds, model)), and to show/hide all elements (model.setAllVisibility(show)).
The problem I'm having is that I want to be able to show/hide the IfcOpeningElements regardless of showing and hiding "normal" elements.
The approach I tried, which is not working very well is to call model.visibilityManager.getHiddenNodes(). The problem with this approach is that, even for models with IfcOpeningElements, getHiddenNodes only returns a non-empty array after ~15 seconds (probably varies with the size of the model). In the meantime, if the user does anything that makes the app call model.setAllVisibility(true), I'm no longer able to detect the original hidden IfcOpeningElements.
Furthermore, when calling getHiddenNodes after an arbitrary waiting period after the model has loaded, I'm not sure if it returns an empty array because the model is not "ready" to detect hidden elements from IfcOpeningElements or if the model simply does not have any IfcOpeningElements.
So, Is there any good way to detect if a model has any "default" hidden elements without having to wait long after the model is loaded? Or perhaps there is a way to call change the visibility of the entire model without changing the visibility of the IfcOpeningElements?
I'm aware of the possibility to listen to the HIDE_EVENT event, but since I'm not sure if it will fire at all (since I'm not sure if the model has any IfcOpeningElements), I cannot block the application from calling model.setAllVisibility(true) which in turn would make getHiddenNodes() return an empty array even if there was hidden elements to begin with.
How about just skipping loading IfcOpeningElements' geometries? To do so, pass skipHiddenFragments: true to the 3rd argument of Viewer3D#loadDocumentNode
viewer.loadDocumentNode(
doc,
viewable,
{
skipHiddenFragments: true
}
);
This approach will skip loading the IfcOpeningElements' meshes, but you can still see their properties while selecting IfcOpeningElements on the model structure panel. On the other hand, you cannot access their bounding boxes and geometries with this approach.
Regarding how to check default hidden elements, try to call this code after all geometries are loaded. The hiddenDbIds are elements hidden by default.
let model = viewer.getAllModels()[0]; //!<< Check the first model just for demo
let fragList = model.getFragmentList();
let hiddenDbIds = Object.keys( fragList.vizflags ).filter(fragId => !fragList.isFragVisible( fragId )).map(fragId => fragList.getDbIds( fragId ) );
// hiddenDbIds.forEach(dbId => viewer.getProperties(dbId, console.log))
Note. The visible flag will also be changed after changing the objects' visibility. So, ensure that run the above before changing the visibilities.
I'm using the Autodesk Forge viewer v7 using the Edit2D tool. This question is specifically about the snapping functionality. It is currently working but a bit overzealous... It seems to have all of the possible snaps on (endpoint, along line, intersections, centers, etc.). It also seems to snap to layers that I have hidden.
Is there a way to set the snaps that are on and off? Also is there a way to limit the layers that it snaps to? I was looking for possibly a method that will tell me the object(s) it's trying to snap to and the type of snap and let me determine if that's a viable snap point and return true/false or something like that but I couldn't find one. Is there a way to do this?
EDIT
I did find setSnapFilter but it doesn't seem to do anything. I have this implementation in my code:
// #ts-ignore
e.defaultContext.snapper.sheetSnapper.setSnapFilter((e) => {
console.log(e);
return false;
});
However, I never get a console log happening. I have tried this on both the sheet snapper and the layer snapper and I've tried returning both true and false and none of them are ever called or make any difference to the snapping.
Good catch! The context.snapper.sheetSnapper object does have a setSnapFilter method you can override. Unfortunately, this filter is only invoked in the Snapper#onMouseMove method, and the Edit2D extension bypasses this method. That's why overriding the method has no effect. Let me pass this info to the engineering team for consideration.
In any of the Cesium sandcastle examples with entities, clicking an entity shows a green square reticle type thing.
My question is, what is it? I want to implement something that behaves similarly but can't find anything about it in the code base or the documentation.
Note: I have disabled the selection widget in my application.
You can see the reticle thing I am talking about in the attached photo.
You mention:
Note: I have disabled the selection widget in my application.
I'm guessing you have a typo or something, because that green reticle is indeed the SelectionIndicator. It can be disabled by setting a constructor option on the Cesium.Viewer, namely:
var viewer = new Cesium.Viewer('cesiumContainer', {
selectionIndicator: false
});
Check your code to see if you really set this option correctly in the constructor.
After the viewer is constructed, it's a bit late to try to turn it off, since it binds into events generated by viewer.selectedEntity changing values. By default, the selectedEntity gets the SelectionIndicator unless the viewer was constructed without one.
We are currently making the client retrieve the object states when the page loads (which will cause the 'pending' objects in the model to turn into different colors). Then we poll for changes to update the coloring (Firstly: pending object gets colored when the viewer loads, and then we keep polling to check and change state again, to make Forge render those in a different color and store their old color/material. When the polling received a change that an object should no longer be colored, it tells Forge to use the old color/material again.
The problem:
We've found out what the problem is, but we couldn't find out how to fix it. The problem is that changing materials in Forge doesn't work after startup anymore, it only works in the first ~3 seconds or so (the materials were used to show the colors).
However, setting overlays works even after the first ~3 seconds, (showing overlays instead of materials to show the colors).
This is not what we want to achieve. This looks unoptimized, because overlays will be shown through everything.
The materials, however, seem to be 'locked', as in, they cannot be changed anymore after the first ~3 seconds. It seems like they aren't refreshed or something
In the examples, we found they used viewer.impl.invalidate(true) to refresh the Forge viewer, but that doesn't do anything after ~3 seconds.
We've also tried every combination of viewer.impl.invalidate(true, true, true) as well as setting material.needsUpdate to true, as well as trying to re-render the entire scene.
We also found this: https://github.com/mrdoob/three.js/issues/790, but we couldn't find a good way to do that in Forge, we tried viewer.requestSilentRender() but that didn't do anything either.
Anyway, we've tried everything we could come up with and could find online to make the materials work, but nothing made a difference.
We are looking to find someone that's more experienced with how Forge works that can see what the material code is doing wrong.
As for the content, here is all the code you will need to understand what is happening:
DROPBOX LINK
And here is a small part of the "index.html" file that sets the color:
try
{
viewer.restoreAllColorOverlays(); //for materials instead of overlays: viewer.restoreAllColorMaterials();
$.each(colors, function(color, selectionIds)
{
viewer.setColorOverlay(selectionIds, color); //for materials instead of overlays: viewer.setColorMaterial(selectionIds, color);
});
}
catch(error)
{
console.error(error);
}
I have no idea how you implement your app, so I only tell what I found in your codes. If you want to resolve the issue you addressed, you can consider providing a reproducible case demonstrating that, I will gladly pass it to our dev team. Those following items should be in the reproducible case:
A short exact description of what you are trying to achieve. The behavior you observe versus what you expect, and why this is a problem.
A complete yet minimal sample source model to run a test in.
A complete yet minimal Forge app that can be run and debugged with a simple procedure to analyze its behavior lives in the sample model.
A complete yet minimal pure three.js app that can be run and demonstrated the shader effect you want. Note. Forge Viewer is using r71 three.js.
Detailed step-by-step instructions for reproducing the issue, e.g. which element to pick, what command to launch etc.
If your reproducible case could not be posted here publicly, please send it to the forge.help#autodesk.com and remove sensitive data or information before you send.
=== Something I found in your codes:
I found here are some wrong types and missing actions in your ColorMaterial extension. The color property of an material should the a type of the THREE.Color. Here is my modification:
Autodesk.Viewing.Viewer3D.prototype.setColorMaterial = function(objectIds, color)
{
if( !(color instanceof THREE.Color) ) throw 'Invalid argument: Color';
var material = new THREE.MeshPhongMaterial
({
color: color,
opacity: 0.8,
transparent: true
});
viewer.impl.matman().addMaterial( 'ColorMaterial-' + new Date().getTime(), material, true );
// ...........
};
Its' result is here:
In the ColorOverlay extension, The type of material color property is also wrong, it should be a type of THREE.Color, too. Changing it into THREE.Color should work fine. In addition, overlay is covers on 3D objects, so you should call viewer.hide() with your setColorOverlay() together. Otherwise, it won't look like a transparent object.
Without hidding 3D object of the wall:
hide 3D object of the wall:
I have a basic three.js scene in which I am attempting to get objects exported from Blender (as JSON files with embedded morphs) to function and update their shapes with user input.
Here is a test scene
http://onthez.com/temphosting/three-js-morph-test/morph-test.html
The slab is being resized without morphs by simply scaling a box, which is working just fine.
I must be missing something fundamental with the little monument on top. It has 3 morphs (width, depth, height) that are intended to allow it to resize.
I am using this code to implement the morph based on users dat.gui input.
folder1.add( params, 'width', 12, 100 ).step(1).name("Width").onChange( function () {
updateFoundation();
building.morphTargetInfluences['width'] = params.width/100;
roofL.morphTargetInfluences['width'] = params.width/100;
roofR.morphTargetInfluences['width'] = params.width/100;
building.updateMorphs();
});
The materials for building, roofL, and roofR each have morphTargets set as true.
I've been going over the three.js examples here:
http://threejs.org/examples/?q=morph#webgl_morphtargets_human
as well as #webgl_morphtargets and #webgl_morphtargets_horse
Any thoughts or input would be much appreciated!
I believe I've reached a solution for my question I was under the impression that the JSON loader was preserving the morph target names to be used in place of an index number with morphTargetInfluences
something like morphTargetInfluences['myMorphTargetName']
but, after closer inspection in the console it seems like they should be referred to by number like morphTargetInfluences[0]
Not the most intuitive, but I can work with it.