Autodek forge viewer background color - autodesk-forge

Actually I change the background color in the forge web viewer using the setBackgroudColor command then the TOOLBAR_CREATED_EVENT is fired,
but, this cause a flashing effect
so, is it possible to initialize the color while initializing the GuiViewer3D, using the config paramters ?
Luc

Yes, it's feasible. Here are two approaches.
Change it after loading the model.
viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, () => {
viewer.setEnvMapBackground(false); //!<<< Turn off background image
viewer.setBackgroundColor(255, 226, 110, 219, 219, 219); //!<<< Change background color
}, { once: true }); // once run this handler once
viewer.loadDocumentNode(document, bubble);
Use profile API to change that
const aecProfileSettings = Autodesk.Viewing.ProfileSettings.AEC;
const customAecProfileSettings = Autodesk.Viewing.ProfileSettings.clone(aecProfileSettings);
customAecProfileSettings.settings.envMapBackground = false;
const customAecLightPreset = {};
Autodesk.Viewing.Private.copyLightPreset(
Autodesk.Viewing.Private.LightPresets.find(preset => preset.name == customAecProfileSettings.settings.lightPreset),
customAecLightPreset
);
customAecLightPreset.bgColorGradient = [255, 226, 110, 219, 219, 219];
Autodesk.Viewing.Private.LightPresets.push(customAecLightPreset);
customAecProfileSettings.settings.backgroundColorPreset = JSON.stringify(customAecLightPreset.bgColorGradient);
customAecProfileSettings.settings.lightPreset = customAecLightPreset.name;
const customAecProfile = new Autodesk.Viewing.Profile(customAecProfileSettings);
viewer.start();
viewer.setProfile(customAecProfile);
const documentId = `urn:${urn}`;
Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);

Related

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
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);

Forge Viewer, raster images

Is possible to directly load a raster image (PNG, JPG, TIFF) to Forge Viewer?
I see the Autodesk.PDF add-in that can load PDF, I cant find any Autodesk.IMAGE add-in...
Otherwise I need to prior convert Image into PDF and than load it through Autodesk.PDF.
The Autodesk Forge Viewer is based on Three.js - therefore you can use the Three.js API to load an image/texture, there is no need of a Viewer extension for that.
However it depends what you want to do. In case you just want to load an image in the scene, that code is enough.
const texture = THREE.ImageUtils.loadTexture( "thumbnail256.png" );
const material = new THREE.MeshBasicMaterial({ map : texture });
const geometry = new THREE.PlaneGeometry(5, 20, 32);
const planeMesh = new THREE.Mesh(geometry, material);
const planeMesh.position.set(1, 2, 3);
NOP_VIEWER.overlays.addScene('custom-scene');
NOP_VIEWER.overlays.addMesh(planeMesh, 'custom-scene');
But if you want to apply the texture on an existing element in the loaded scene, you need to proceed like this:
const texture = THREE.ImageUtils.loadTexture( "thumbnail256.png" );
const material = new THREE.MeshBasicMaterial({ map : texture, side: THREE.DoubleSide });
NOP_VIEWER.impl.matman().addMaterial('custom-material', material, true);
const model = NOP_VIEWER.model;
model.unconsolidate(); // If the model is consolidated, material changes won't have any effect
const tree = model.getInstanceTree();
const frags = model.getFragmentList();
const dbids = NOP_VIEWER.getSelection();
for (const dbid of dbids) {
tree.enumNodeFragments(dbid, (fragid) => {
frags.setMaterial(fragid, material);
});
}
NOP_VIEWER.impl.invalidate(true, true, false);
Note you may need to work out the texture uv, depending on the geometry.

Use custom Extension Viewer Autodesk Forge

I'm trying to study Autodesk Forge. I'm trying to test script from this link to register Extension change background color when click button. But when click, alert("Autodesk.ADN.Viewing.Extension.Basic loaded") is visible but nothing happy with background color.
Please tell me why and how to solved it if you know.
Thank in advanced !
AutodeskNamespace("Autodesk.ADN.Viewing.Extension");
Autodesk.ADN.Viewing.Extension.Basic = function (viewer, options) {
Autodesk.Viewing.Extension.call(this, viewer, options);
var _this = this;
_this.load = function () {
alert("Autodesk.ADN.Viewing.Extension.Basic loaded");
viewer.setBackgroundColor(255, 0, 0, 255, 255, 255);
return true;
};
_this.unload = function () {
viewer.setBackgroundColor(160, 176, 184, 190, 207, 216);
alert("Autodesk.ADN.Viewing.Extension.Basic unloaded");
Autodesk.Viewing.theExtensionManager.unregisterExtension(
"Autodesk.ADN.Viewing.Extension.Basic");
return true;
};
};
Autodesk.ADN.Viewing.Extension.Basic.prototype = Object.create(Autodesk.Viewing.Extension.prototype);
Autodesk.ADN.Viewing.Extension.Basic.prototype.constructor = Autodesk.ADN.Viewing.Extension.Basic;
Autodesk.Viewing.theExtensionManager.registerExtension("Autodesk.ADN.Viewing.Extension.Basic", Autodesk.ADN.Viewing.Extension.Basic);
$(document).ready(function(){
$("#button").click(function(){
viewer.loadExtension('Autodesk.ADN.Viewing.Extension.Basic');
})
})
The blog article you linked to is from 2016. Forge Viewer is still evolving pretty fast, so I'm afraid that the code snippet in this blog post is too out-dated.
If you are interested in learning more about the Forge platform, I'd recommend taking a look at the https://learnforge.autodesk.io website. It contains various tutorials and we try and keep them up-to-date whenever the Forge services or the Forge Viewer API changes. There's also a tutorial about viewer extensions specifically: https://learnforge.autodesk.io/#/tutorials/extensions.
To give you an idea, here's how a simple viewer extension would be implemented today, using the viewer version 7.*:
class MyAwesomeExtension extends Autodesk.Viewing.Extension {
constructor(viewer, options) {
super(viewer, options);
}
load() {
console.log('MyAwesomeExtensions has been loaded');
viewer.setEnvMapBackground(null); // Hide background environment if there is one
viewer.setBackgroundColor(0, 64, 128); // Set background color
return true;
}
unload() {
console.log('MyAwesomeExtensions has been unloaded');
return true;
}
}
Autodesk.Viewing.theExtensionManager.registerExtension('MyAwesomeExtension', MyAwesomeExtension);
Then, when initializing the viewer, you would load your extension like so:
let viewer = new Autodesk.Viewing.GuiViewer3D(divElement, { extensions: ['MyAwesomeExtension'] });

How to change the color of sphere objects dynamically (used SceneBuilder in Autodesk forge)

I am working on the example from Custom models in Forge Viewer blog by Petr Broz. I am facing issue in updating the color of sphere objects dynamically. I am getting the value of sphere's color from a json file like this "color": "#FF0000". I have created 3 spheres and I am getting the color of first sphere for the rest also. Why the color is not updating for the other spheres? If the problem is on using same material then I tried giving the sphereMaterial in array also as shown below. Is that wrong or how can i update the color?
var spherecolor='';
var sphereMaterial = [];
const button = document.getElementById('button-geometry');
button.addEventListener('click', async function () {
const sceneBuilder = await viewer.loadExtension('Autodesk.Viewing.SceneBuilder');
const modelBuilder = await sceneBuilder.addNewModel({ conserveMemory: true, modelNameOverride: 'My Custom Model' });
for (var i = 0; i < numOfSphere;i++) {
addGeometry(modelBuilder, jsonGeomConfig.geom[i].dbId, i);
}
});
function addGeometry(modelBuilder, dbId, i) {
const sphereGeometry = new THREE.BufferGeometry().fromGeometry(new THREE.SphereGeometry(0.05, 8, 10));
//Getting spherecolor from json file
spherecolor = jsonGeomConfig.geom[i].color;
sphereMaterial[i] = new THREE.MeshPhongMaterial({ color: spherecolor });
const sphereTransform = new THREE.Matrix4().compose(
new THREE.Vector3(jsonGeomConfig.geom[i].Position.posX, jsonGeomConfig.geom[i].Position.posY, jsonGeomConfig.geom[i].Position.posZ),
new THREE.Quaternion(0, 0, 0, 1),
new THREE.Vector3(2,2,2)
);
modelBuilder.addMaterial('MyCustomMaterial', sphereMaterial[i]);
const sphereGeomId = modelBuilder.addGeometry(sphereGeometry);
const sphereFragId = modelBuilder.addFragment(sphereGeomId, 'MyCustomMaterial', sphereTransform);
modelBuilder.changeFragmentsDbId(sphereFragId, dbId);
}
Be sure to give the materials with different colors different names ... otherwise it'd get overridden - see this live environment:
modelBuilder.addMaterial('MyCustomMaterial'+i, sphereMaterial[i]);
const sphereGeomId = modelBuilder.addGeometry(sphereGeometry);
const sphereFragId = modelBuilder.addFragment(sphereGeomId, 'MyCustomMaterial'+i, sphereTransform);

How do I properly display a chart in html canvas with Chart.js and Angular Framework

I am following a tutorial to build a real time polling using angular. However, by the end of the tutorial, I am not able to display the chart like the tutorial does. What am I doing wrong?
I followed the tutorial, used angular, pusher, chart.js as instructed. It worked fine until I reached Data Visualization part, where I need to display the polling result on a 'Doughnut' chart. All I have is a white line which is used to divide different color of the dataset, but the rest of the chart is not displaying.
My app.component.ts
voteCount = {
salah: 0,
kane: 0,
eriksen: 0,
kevin: 0,
};
castVote(player) {
this.http
.post(`http://localhost:4000/vote`, { player })
.subscribe((res: any) => {
this.vote = res.player;
this.voted = true;
});
}
getVoteClasses(player) {
return {
elect: this.voted && this.vote === player,
lost: this.voted && this.vote !== player,
};
}
chartLabels: string[] = Object.keys(this.voteCount);
chartData: number[] = Object.values(this.voteCount);
chartType = 'doughnut';
ngOnInit() {
const channel = this.pusher.init();
channel.bind('vote', ({player}) => {
this.voteCount[player] += 1;
this.chartData = Object.values(this.voteCount);
});
}
My app.component.html
<div class="chart-box" *ngIf="voted">
<h2>How others voted</h2>
<canvas
baseChart
[data]="chartData"
[labels]="chartLabels"
[chartType]="chartType"
>
</canvas>
</div>
According to the tutorial, the data visualization should look like this:
However, mine looks like this:
I changed the background color of the div, so you can see there is a white line below Eriksen just like the tutorial, however, the rest of the data is not shown.
Edit: I hard-coded some data and assigned them to chartLabels, chartData and chartType, and now the canvas can visualize them:
chartLabels = ['salah', 'kane', 'eriksen', 'kevin'];
chartData = [120, 150, 180, 90];
chartType = 'doughnut';
So this means
chartLabels: string[] = Object.keys(this.voteCount);
chartData: number[] = Object.values(this.voteCount);
chartType = 'doughnut';
are not receiving any data. Why is that?
Edit 2:
After further experiment, I found that
ngOnInit() {
const channel = this.pusher.init();
channel.bind('vote', ({player}) => {
this.voteCount[player] += 1;
this.chartData = Object.values(this.voteCount);
});
}
Object.values(this.voteCount) is not increased so its value stays at 0, so that's why the chart is empty. How do I increase its value each time I click on the player's pic?