# Creating a BIM application with IFC.js ###### tags: `BIM` ### Setting Environment * Create Net Project in Visual Studio Code * Install Libraries * Open the Terminals :package: The first thing to do is to create an empty folder and start a new npm project with the command [npm init](https://ithelp.ithome.com.tw/articles/10191682). This will generate a `package.json` file containing some data such as the project name, version, commands and dependencies. In addition, the following dependencies must be installed with npm: ```javascript= //Initail the Project and generate package.json npm init // Install a bundler: we will use rollup.js for this guide npm i rollup --save-dev npm i @rollup/plugin-node-resolve --save-dev //Start to Download the tools... //Install IFC.js npm i web-ifc-three // Install Three.js npm i three ``` You can see your Project have a folder `node_modules` ### Create an HTML file :memo: The next step is to create an HTML file named index.html as the main document of the application. The HTML will have: :::info * A canvas element, used to render the Three.js scene. * An input element, which will open IFC files from our computer to the application. * A script referencing a file called bundle.js, which is the **bundle of the app that we will produce with rollup**. ::: ```javascript= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="/styles.css" /> <title>Document</title> </head> <body> <input type="file" id="file-input" accept=".ifc, .ifcXML, .ifcZIP"> <canvas id="three-canvas"></canvas> </body> <script src="/bundle.js"></script> </html> ``` ### Adding style :lower_left_paintbrush: The following CSS file will make the canvas full screen: ```javascript= * { margin: 0; padding: 0; box-sizing: border-box; } html, body { overflow: hidden; } #three-canvas { position: fixed; top: 0; left: 0; outline: none; } #file-input { z-index: 1; position: absolute; } ``` ### Product the bundle.js #### Create the JS file 🧱 We'll generate the bundle.js file before we used. First step, is create the JavaScript file named `main.js` be used setting up a 3D scene. ```javascript= import { AmbientLight, AxesHelper, DirectionalLight, GridHelper, PerspectiveCamera, Scene, WebGLRenderer, } from "./node_modules/three/build/three.module"; import { OrbitControls } from "./node_modules/three/examples/jsm/controls/OrbitControls"; import { IFCLoader } from "./node_modules/web-ifc-three/IFCLoader"; // 创建Three.js场景 // 创建Three.js场景 const scene = new Scene(); //Object to store the size of the viewport const size = { width: window.innerWidth, height: window.innerHeight, }; // 创建摄像机(用户的视角)。 const aspect = size.width / size.height; const camera = new PerspectiveCamera(75, aspect); camera.position.z = 15; camera.position.y = 13; camera.position.x = 8; // 创建场景的灯光 const lightColor = 0xffffff; const ambientLight = new AmbientLight(lightColor, 0.5); scene.add(ambientLight); const directionalLight = new DirectionalLight(lightColor, 1); directionalLight.position.set(0, 10, 0); directionalLight.target.position.set(-5, 0, 0); scene.add(directionalLight); scene.add(directionalLight.target); // 设置渲染器,获取HTML的画布。 const threeCanvas = document.getElementById("three-canvas"); const renderer = new WebGLRenderer({ canvas: threeCanvas, alpha: true, }); renderer.setSize(size.width, size.height); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // 在场景中创建网格和坐标轴 const grid = new GridHelper(50, 30); scene.add(grid); const axes = new AxesHelper(); axes.material.depthTest = false; axes.renderOrder = 1; scene.add(axes); // 创建轨道控制(用于导航场景)。 const controls = new OrbitControls(camera, threeCanvas); controls.enableDamping = true; controls.target.set(-2, 0, 0); // 动画循环 const animate = () => { controls.update(); renderer.render(scene, camera); requestAnimationFrame(animate); }; animate(); // 根据浏览器的大小调整视口 window.addEventListener("resize", () => { size.width = window.innerWidth; size.height = window.innerHeight; camera.aspect = size.width / size.height; camera.updateProjectionMatrix(); renderer.setSize(size.width, size.height); }); //Sets up the IFC loading const ifcLoader = new IFCLoader(); ifcLoader.ifcManager.setWasmPath("/wasm/"); const input = document.getElementById("file-input"); input.addEventListener( "change", (changed) => { const ifcURL = URL.createObjectURL(changed.target.files[0]); ifcLoader.load(ifcURL, (ifcModel) => scene.add(ifcModel)); }, false ); ``` #### Bundling :scroll: Next, we'll create the rollup configuration file. This file has to be called `rollup.config.js` and includes the reference to the plugins we have previously installed. ```javascript= import resolve from "@rollup/plugin-node-resolve"; export default { input: "main.js", output: [ { format: "esm", file: "bundle.js", }, ], plugins: [resolve()], }; ``` :bulb: About the rollup. You can follow below this link. https://rollupjs.org/introduction/ * Installation ```javascript= npm install --global rollup ``` * Quick Start ```javascript= //compile to a <script> containing a self-executing function ('iife') rollup main.js --file bundle.js --format iife ``` :dart: Also, the package.json file needs to be modified to contain the commands to control rollup easily. In each command, you'll have to specify the relative path to your rollup configuration file. If we have installed everything correctly, we should see the same dependencies in this file (the version of the libraries may differ). package.js ```javascript= { "author": "", "license": "ISC", "type": "module", "dependencies": { "three": "^0.150.1", "web-ifc-three": "^0.0.123" }, "devDependencies": { "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^15.0.1", "rollup": "^3.20.2", "webpack": "^5.76.3", "webpack-cli": "^5.0.1" }, "name": "rollup-tutorial", "version": "1.0.0", "main": "main.js", "scripts": { "build": "rollup -c ./rollup.config.js", "watch": "rollup -w -c ./rollup.config.js" } } ``` Or you can use this command to create bundle.js * `npm run build` will bundle the project and create a file called bundle.js in the root directory of the project. * `npm run watch` will activate the watch mode, updating that file automatically every time we make changes to the code and save it. ![](https://i.imgur.com/UjhLIbJ.png) ### WebAssembly :file_folder: The next thing to do is to copy the web-ifc.wasm and web-ifc-mt.wasm files to a directory in your project. It can be found in node_modules\web-ifc (or node_modules\three\examples\jsm\loaders\ifc if you are only using Three's IFCLoader). This two .wasm file is copies from node_module. We will use it in 3D scene ![](https://i.imgur.com/vB11yQd.png) You can see the function that how to sets up the IFC in `main.js` ![](https://i.imgur.com/PtNkOoO.png) If you have done everything correctly, you should be able to see something similar to this in your local server. From here, the possibilities are endless. Like [this](https://ifcjs.github.io/hello-world/examples/web-ifc-three/helloworld/). ![](https://i.imgur.com/dW9VKrF.png) ### Loading our models :house_buildings: I download [it](https://market.bimsmith.com/?regionId=182) .It have many sample IFC file can be used. Upload the File... ![](https://i.imgur.com/HXsXgay.png =400x) Complete!