Limit the orbit movement in Forge Viewer - autodesk-forge

I'm having trouble to set rotational limits to the viewer.
I want my viewer to work like this example in Three.js
https://threejs.org/examples/#misc_controls_orbit
Is there anyone that has succeeded with this? And can give me some hints to lead me in the right direction..
I've tried using the code in the example above.
I've tried to set viewer.autocam.constrainOrbitVertical = true when reaching my limit that is about 90 degrees, but it wont give me the result I want..

Unfortunately such a functionality is not available in Forge Viewer. You should however be able to work around it by controlling the camera properties on each CAMERA_CHANGE_EVENT, for example like so:
viewer.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, function() {
const camera = viewer.getCamera();
if (camera.position.x > 0) {
const dist = camera.position.length();
camera.position.x = 0;
camera.position.setLength(dist);
viewer.navigation.updateCamera();
}
});

Related

Set transparent for specific element

I want set transparent for specific element, i follow this code:
var instanceTree = this.viewer.model.getInstanceTree();
var fragList = this.viewer.model.getFragmentList();
this.listElement.forEach(element => {
instanceTree.enumNodeFragments(element, (fragId) => {
console.log(element.material)
var material = fragList.getMaterial(fragId)
if (material) {
material.opacity = value;
material.transparent = true;
material.needsUpdate = true;
}
});
});
this.viewer.impl.invalidate(true, true, true);
but it overide for all elements have that material. How can i set for selected element?
Appreciate any comments.
UPDATE 1:
i found go around way is clone main material than register it with different name:
var newMaterial = material.clone();
const materials = this.viewer.impl.matman();
materials.addMaterial('mymaterial',newMaterial,true);
fragList.setMaterial(fragId,newMaterial);
newMaterial.opacity = value;
newMaterial.transparent = true;
newMaterial.needsUpdate = true;
but effect is not what i want, it has different color and when set transparent i can only see a couple object behind it
You can create your own, custom THREE.js material and assign it to the fragment using fragList.setMaterial(fragId, material).
For more information on using custom materials or shaders, see https://forge.autodesk.com/blog/custom-shader-materials-forge-viewer.
EDIT:
Regarding the visual anomalies (for example, when you only see some of the objects behind something semi-transparent), this is a known problem, unfortunately with no clear solution. When the Forge Model Derivative service creates an SVF file to be viewed in Forge Viewer, the individual scene elements are stored in a data structure optimized for fast traversal, depending on whether they are semi-transparent or fully opaque. This data structure is fixed, and so unfortunately, when you take an object that was originally fully opaque, and you make it semi-transparent, it will most likely be rendered in a wrong order...

Toogle Cesium requestRenderMode after Cesium.viewer has been created

i am trying to toggle Cesiums viewer.requestRenderMode setting, to explore some performance differences.
I created a toggle Button for the requestRenderMode property and call the following function:
function toggleRenderMode() {
console.info("toggleRenderMode");
requestRenderMode = !requestRenderMode;
viewer.requestRenderMode = requestRenderMode
if(requestRenderMode){
viewer.maximumRenderTimeChange = Infinity;
console.info("enabling requestRenderMode");
}else{
viewer.maximumRenderTimeChange = 0;
console.info("disabling requestRenderMode");
}
console.info("viewer.requestRenderMode:",viewer.requestRenderMode);
}
the console output shows me that the viewers requestRenderMode is set according to the code, however it seems that this has no effect on the rendering.
So can this property only be set at the time of Cesium viewers creation?
Thanks a lot!
viewer.requestRenderMode does not exist in the API, what you want is viewer.scene.requestRenderMode.

Cesium JS flying to camera.lookAt (Migrating from Google Earth Plugin API lookAt)

Needing some help migrating my flying functionality from the Google Earth plugin to Cesium. Basically in ge I create a lookAt and called setAbstractView like below
var ge = google.earth.createInstance('map3d')
var lookAt = TVV.mapObject.createLookAt('');
lookAt.set(
21.2765107698755,
-157.825362273258,
0,
ge.ALTITUDE_RELATIVE_TO_GROUND,
20.1690873648706,
74.9605580474674,
764.534479411941
);
ge.getView().setAbstractView(lookAt);
That was my code for google earth plugin. In cesium following the migration guides I do:
// fly to code that works with cesium (but a little bit off)
viewer.camera.flyTo({
destination : Cesium.Cartesian3.fromDegrees(-157.825362273258, 21.2765107698755, 764.534479411941),
orientation : {
heading : Cesium.Math.toRadians(20.1690873648706),
pitch : Cesium.Math.toRadians(74.9605580474674 - 90.0),
roll: 0
}
})
That code goes to almost the right place. I have to drag it down over to the right to see my placemark that I previously set (so the view is not exactly what it was in Google earth).
So I tried this code I also found.
// code that works with cesium
var center = Cesium.Cartesian3.fromDegrees(-157.825362273258, 21.2765107698755);
var heading = Cesium.Math.toRadians(20.1690873648706);
var pitch = Cesium.Math.toRadians(74.9605580474674);
var range = 764.534479411941;
viwer.camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, range));
That code looks MUCH closer to the previous google earth plugin view. However, of course, it does not fly the camera to the view. It only sets the view right away.
My question is, how can I fly the camera to the lookAt view in cesium, taking advantage of my lat, lng, heading, pitch, and range values?
Here are the relevant API docs from GE and Cesium should you find them useful.
GE createLookAt
https://developers.google.com/earth/documentation/reference/interface_g_e_plugin.html#a82f1b3618531a6bfab793b04c76a43e7
GE Camera Control (search for "Panning to an absolute location")
https://developers.google.com/earth/documentation/camera_control
Cesium lookAt
https://cesiumjs.org/Cesium/Build/Documentation/Camera.html#lookAt
Cesium flyTo
https://cesiumjs.org/Cesium/Build/Documentation/Camera.html#flyTo
I also found this but was unsure about how to integrate it. If anybody could provide a codepen/jsfiddle or something of the like that would be greatly appreciated!
https://groups.google.com/forum/#!topic/cesium-dev/r5rddMUeS80
Thanks to Hannah Pinkos from the Cesium Forum for the answer.
After creating an entity and using values for heading, pitch(tilt), and range from the google earth plugin, you can fly to the entity with an offset...
var heading = Cesium.Math.toRadians(20.1690873648706g);
var pitch = Cesium.Math.toRadians(74.9605580474674 - 90);
var range = 764.534479411941;
TVV.mapObject.flyTo(entity, {
offset: new Cesium.HeadingPitchRange(heading, pitch, range)
});

Highlight an array of nodes in Autodesk Viewer

Problem:
I have an array of nodes that I would like to highlight when an action happens.
My Attempted Solution
I have tried using code from the model browser, but it seems to only accept one dbId at a time. I have tried to iterate over my array and call it, but the highlighting doesn't work when that is done.
for (var i = 0; i < dbIdsArray.length; i++) {
viewerApp.getCurrentViewer().impl.rolloverObjectNode(dbIdsArray[i]);
}
Any advice on how to implement this correctly would be a great help.
Thanks
If you want to highlight a couple of dbids, there are some different ways depending on your requirement.
Maybe you can use the API Viewer3D.isolate() to highlight the
selected objects by isolating them, you can just input dbId array as
follow, also, you can zoom the selected items to the viewer window
use the API Viewer3D.fitToView() to focus on them:
viewer.isolate(dbIdArray);
viewer.fitToView(dbIdArray);
If you want to highlight the selected objects with different color,
maybe you can try the new API Viewer3D.setThemingColor(), here is the
simple code sample. Remember you need to clear the color using
Viewer3D.clearThemingColors(). The simple code sample should be like:
I'm able to highlight components using following code:
viewer.addEventListener(
Autodesk.Viewing.SELECTION_CHANGED_EVENT,
function (e) {
if(e.dbIdArray.length) {
var dbId = e.dbIdArray[0];
viewer.impl.highlightObjectNode(
viewer.model, dbId, true, false)
viewer.select([])
viewer.impl.sceneUpdated(true)
}
})
This is using function:
viewer.impl.highlightObjectNode = function(model, dbId, value, simpleHighlight)

Cesium - Applying color filter to ImageryLayer

Has anyone attempted to do this? As far as I can tell from the documentation, there doesn't seem to be a built in function for achieving this. Does anyone know if this is possible? Is it, possibly, a feature that the authors might intend to add to the platform?
The ImageryLayer documentation shows how to control brightness, contrast, hue, saturation, and gamma correction.
To get a globe with a solid color, you can remove the imagery layers like so:
var viewer = new Cesium.Viewer('cesiumContainer', {
baseLayerPicker: false
});
var globe = viewer.scene.globe;
globe.imageryLayers.removeAll();
globe.baseColor = Cesium.Color.LIGHTSLATEGRAY;
A "minimalist map" (as you mention in the comments) is something you would probably need to get from a custom imagery provider. You may want to check out Stamen Maps for some examples of this. In particular, note their "Toner" map comes in a number of sub-varieties, any of which can be selected in Cesium.
For example, to try the "Toner Background" version, you would use:
var viewer = new Cesium.Viewer('cesiumContainer', {
baseLayerPicker: false,
imageryProvider: Cesium.createOpenStreetMapImageryProvider({
url : 'https://stamen-tiles.a.ssl.fastly.net/toner-background/',
credit : 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.'
})
});
EDIT: #EmmanuelBuckski (OP) took this idea and ran with it, mixing the above two techniques together to produce a result that looks really nice! Check it out:
var viewer = new Cesium.Viewer('cesiumContainer', {
baseLayerPicker: false
});
var globe = viewer.scene.globe;
globe.imageryLayers.removeAll();
globe.baseColor = Cesium.Color.fromCssColorString('#f3f3f3');
var tonerLayer = globe.imageryLayers.addImageryProvider(
Cesium.createOpenStreetMapImageryProvider({
url : 'https://stamen-tiles.a.ssl.fastly.net/toner-background/',
credit : 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.'
})
);
tonerLayer.alpha = 0.1;