diff --git a/Sources/IO/Geometry/IFCImporter/example/controller.html b/Sources/IO/Geometry/IFCImporter/example/controller.html
new file mode 100644
index 00000000000..d77bd53ba33
--- /dev/null
+++ b/Sources/IO/Geometry/IFCImporter/example/controller.html
@@ -0,0 +1,15 @@
+
diff --git a/Sources/IO/Geometry/IFCImporter/example/index.js b/Sources/IO/Geometry/IFCImporter/example/index.js
index 847ad237368..35a4e6d3e8c 100644
--- a/Sources/IO/Geometry/IFCImporter/example/index.js
+++ b/Sources/IO/Geometry/IFCImporter/example/index.js
@@ -6,18 +6,30 @@ import '@kitware/vtk.js/Rendering/Profiles/Geometry';
import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
import vtkResourceLoader from '@kitware/vtk.js/IO/Core/ResourceLoader';
import vtkIFCImporter from '@kitware/vtk.js/IO/Geometry/IFCImporter';
+import vtkURLExtract from '@kitware/vtk.js/Common/Core/URLExtract';
+
+import controlPanel from './controller.html';
// ----------------------------------------------------------------------------
// Example code
// ----------------------------------------------------------------------------
+const userParams = vtkURLExtract.extractURLParameters();
+const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
+fullScreenRenderer.addController(controlPanel);
+
+if (userParams.mergeGeometries === undefined) {
+ userParams.mergeGeometries = true;
+}
+const mergeGeometriesCheckbox = document.querySelector('#mergeGeometries');
+mergeGeometriesCheckbox.checked = Boolean(userParams.mergeGeometries);
+
const importer = vtkIFCImporter.newInstance({
- mergeGeometries: true,
+ mergeGeometries: mergeGeometriesCheckbox.checked,
});
// ----------------------------------------------------------------------------
function update() {
- const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();
@@ -40,10 +52,20 @@ vtkResourceLoader
// Pass WebIFC api to vtkIFCImporter
vtkIFCImporter.setIFCAPI(window.WebIFC);
- // Trigger data download
- importer
- .setUrl(
- 'https://raw.githubusercontent.com/ThatOpen/engine_web-ifc/refs/heads/main/tests/ifcfiles/public/duplex.ifc'
- )
- .then(update);
+ if (userParams.fileURL) {
+ // Trigger data download
+ importer.setUrl(userParams.fileURL).then(update);
+ } else {
+ importer
+ .setUrl(
+ 'https://raw.githubusercontent.com/ThatOpen/engine_web-ifc/refs/heads/main/tests/ifcfiles/public/duplex.ifc'
+ )
+ .then(update);
+ }
});
+
+document.querySelectorAll("input[name='mergeGeometries']").forEach((input) => {
+ input.addEventListener('change', (evt) => {
+ window.location = `?mergeGeometries=${evt.target.checked}`;
+ });
+});
diff --git a/Sources/IO/Geometry/IFCImporter/index.js b/Sources/IO/Geometry/IFCImporter/index.js
index b4969c198f0..3413753e824 100644
--- a/Sources/IO/Geometry/IFCImporter/index.js
+++ b/Sources/IO/Geometry/IFCImporter/index.js
@@ -11,6 +11,7 @@ import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray';
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
+import vtkPolyDataNormals from 'vtk.js/Sources/Filters/Core/PolyDataNormals';
import vtkCellArray from 'vtk.js/Sources/Common/Core/CellArray';
import vtkAppendPolyData from 'vtk.js/Sources/Filters/General/AppendPolyData';
import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';
@@ -244,32 +245,40 @@ function vtkIFCImporter(publicAPI, model) {
publicAPI.importActors = (renderer) => {
if (model.mergeGeometries) {
const opaqueMeshes = meshes.filter((mesh) => mesh.color.w === 1);
- let apd = vtkAppendPolyData.newInstance();
+ const oapd = vtkAppendPolyData.newInstance();
opaqueMeshes.forEach((mesh) => {
const pd = createColoredPolyDataFromIFCMesh(mesh);
- apd.addInputData(pd);
+ oapd.addInputData(pd);
});
+ const opdn = vtkPolyDataNormals.newInstance();
+ opdn.setInputConnection(oapd.getOutputPort());
+ opdn.setComputePointNormals(true);
+
let mapper = vtkMapper.newInstance();
mapper.setColorModeToDirectScalars();
- mapper.setInputConnection(apd.getOutputPort());
+ mapper.setInputConnection(opdn.getOutputPort());
let actor = vtkActor.newInstance();
actor.setMapper(mapper);
renderer.addActor(actor);
const transparentMeshes = meshes.filter((mesh) => mesh.color.w < 1);
- apd = vtkAppendPolyData.newInstance();
+ const tapd = vtkAppendPolyData.newInstance();
transparentMeshes.forEach((mesh) => {
const pd = createColoredPolyDataFromIFCMesh(mesh);
- apd.addInputData(pd);
+ tapd.addInputData(pd);
});
+ const tpdn = vtkPolyDataNormals.newInstance();
+ tpdn.setInputConnection(tapd.getOutputPort());
+ tpdn.setComputePointNormals(true);
+
mapper = vtkMapper.newInstance();
mapper.setColorModeToDirectScalars();
- mapper.setInputConnection(apd.getOutputPort());
+ mapper.setInputConnection(tpdn.getOutputPort());
actor = vtkActor.newInstance();
actor.setMapper(mapper);