├── .gitignore ├── LICENSE ├── README.md ├── config.js ├── img └── favicon.ico ├── package.json ├── public ├── css │ ├── main.css │ └── w2ui-1.4.min.css ├── extensions │ ├── BasicSkeleton │ │ ├── README.md │ │ ├── config.json │ │ └── contents │ │ │ ├── img │ │ │ └── icon.png │ │ │ ├── main.css │ │ │ └── main.js │ ├── CameraRotation │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ ├── img │ │ │ │ └── emblem_camera.png │ │ │ ├── main.css │ │ │ └── main.js │ │ └── extension.gif │ ├── CustomPropertiesExtension │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ └── main.js │ │ └── extension.gif │ ├── DrawToolExtension │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ ├── img │ │ │ │ └── icon.png │ │ │ ├── main.css │ │ │ └── main.js │ │ └── extension.gif │ ├── GoogleMapsLocator │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ ├── main.css │ │ │ └── main.js │ │ └── extension.gif │ ├── IconMarkupExtension │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ ├── main.css │ │ │ └── main.js │ │ └── extension.gif │ ├── NestedViewerExtension │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ ├── main.css │ │ │ └── main.js │ │ └── extension.gif │ ├── PotreeExtension │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ ├── PotreeExtension.js │ │ │ ├── data │ │ │ │ └── lion_takanawa │ │ │ │ │ ├── cloud.js │ │ │ │ │ └── data │ │ │ │ │ └── r │ │ │ │ │ ├── r.bin │ │ │ │ │ ├── r.hrc │ │ │ │ │ ├── r0.bin │ │ │ │ │ ├── r00.bin │ │ │ │ │ ├── r001.bin │ │ │ │ │ ├── r003.bin │ │ │ │ │ ├── r004.bin │ │ │ │ │ ├── r005.bin │ │ │ │ │ ├── r007.bin │ │ │ │ │ ├── r01.bin │ │ │ │ │ ├── r012.bin │ │ │ │ │ ├── r013.bin │ │ │ │ │ ├── r016.bin │ │ │ │ │ ├── r017.bin │ │ │ │ │ ├── r02.bin │ │ │ │ │ ├── r021.bin │ │ │ │ │ ├── r023.bin │ │ │ │ │ ├── r03.bin │ │ │ │ │ ├── r030.bin │ │ │ │ │ ├── r031.bin │ │ │ │ │ ├── r032.bin │ │ │ │ │ ├── r034.bin │ │ │ │ │ ├── r035.bin │ │ │ │ │ ├── r036.bin │ │ │ │ │ ├── r037.bin │ │ │ │ │ ├── r04.bin │ │ │ │ │ ├── r041.bin │ │ │ │ │ ├── r043.bin │ │ │ │ │ ├── r045.bin │ │ │ │ │ ├── r047.bin │ │ │ │ │ ├── r05.bin │ │ │ │ │ ├── r052.bin │ │ │ │ │ ├── r053.bin │ │ │ │ │ ├── r056.bin │ │ │ │ │ ├── r057.bin │ │ │ │ │ ├── r06.bin │ │ │ │ │ ├── r065.bin │ │ │ │ │ ├── r067.bin │ │ │ │ │ ├── r07.bin │ │ │ │ │ ├── r070.bin │ │ │ │ │ ├── r071.bin │ │ │ │ │ ├── r072.bin │ │ │ │ │ ├── r073.bin │ │ │ │ │ ├── r074.bin │ │ │ │ │ ├── r075.bin │ │ │ │ │ ├── r076.bin │ │ │ │ │ ├── r077.bin │ │ │ │ │ ├── r1.bin │ │ │ │ │ ├── r11.bin │ │ │ │ │ ├── r116.bin │ │ │ │ │ ├── r117.bin │ │ │ │ │ ├── r12.bin │ │ │ │ │ ├── r124.bin │ │ │ │ │ ├── r125.bin │ │ │ │ │ ├── r126.bin │ │ │ │ │ ├── r127.bin │ │ │ │ │ ├── r13.bin │ │ │ │ │ ├── r134.bin │ │ │ │ │ ├── r135.bin │ │ │ │ │ ├── r136.bin │ │ │ │ │ ├── r137.bin │ │ │ │ │ ├── r14.bin │ │ │ │ │ ├── r146.bin │ │ │ │ │ ├── r15.bin │ │ │ │ │ ├── r152.bin │ │ │ │ │ ├── r153.bin │ │ │ │ │ ├── r156.bin │ │ │ │ │ ├── r157.bin │ │ │ │ │ ├── r16.bin │ │ │ │ │ ├── r160.bin │ │ │ │ │ ├── r161.bin │ │ │ │ │ ├── r162.bin │ │ │ │ │ ├── r164.bin │ │ │ │ │ ├── r165.bin │ │ │ │ │ ├── r166.bin │ │ │ │ │ ├── r167.bin │ │ │ │ │ ├── r17.bin │ │ │ │ │ ├── r170.bin │ │ │ │ │ ├── r171.bin │ │ │ │ │ ├── r173.bin │ │ │ │ │ ├── r174.bin │ │ │ │ │ ├── r175.bin │ │ │ │ │ ├── r176.bin │ │ │ │ │ ├── r177.bin │ │ │ │ │ ├── r2.bin │ │ │ │ │ ├── r21.bin │ │ │ │ │ ├── r210.bin │ │ │ │ │ ├── r214.bin │ │ │ │ │ ├── r215.bin │ │ │ │ │ ├── r23.bin │ │ │ │ │ ├── r235.bin │ │ │ │ │ ├── r24.bin │ │ │ │ │ ├── r243.bin │ │ │ │ │ ├── r245.bin │ │ │ │ │ ├── r247.bin │ │ │ │ │ ├── r25.bin │ │ │ │ │ ├── r250.bin │ │ │ │ │ ├── r251.bin │ │ │ │ │ ├── r254.bin │ │ │ │ │ ├── r255.bin │ │ │ │ │ ├── r256.bin │ │ │ │ │ ├── r257.bin │ │ │ │ │ ├── r26.bin │ │ │ │ │ ├── r261.bin │ │ │ │ │ ├── r265.bin │ │ │ │ │ ├── r27.bin │ │ │ │ │ ├── r270.bin │ │ │ │ │ ├── r271.bin │ │ │ │ │ ├── r274.bin │ │ │ │ │ ├── r275.bin │ │ │ │ │ ├── r3.bin │ │ │ │ │ ├── r30.bin │ │ │ │ │ ├── r304.bin │ │ │ │ │ ├── r306.bin │ │ │ │ │ ├── r31.bin │ │ │ │ │ ├── r314.bin │ │ │ │ │ ├── r315.bin │ │ │ │ │ ├── r32.bin │ │ │ │ │ ├── r324.bin │ │ │ │ │ ├── r34.bin │ │ │ │ │ ├── r340.bin │ │ │ │ │ ├── r341.bin │ │ │ │ │ ├── r342.bin │ │ │ │ │ ├── r343.bin │ │ │ │ │ ├── r344.bin │ │ │ │ │ ├── r345.bin │ │ │ │ │ ├── r346.bin │ │ │ │ │ ├── r347.bin │ │ │ │ │ ├── r35.bin │ │ │ │ │ ├── r350.bin │ │ │ │ │ ├── r351.bin │ │ │ │ │ ├── r354.bin │ │ │ │ │ ├── r355.bin │ │ │ │ │ ├── r36.bin │ │ │ │ │ ├── r360.bin │ │ │ │ │ ├── r364.bin │ │ │ │ │ ├── r4.bin │ │ │ │ │ ├── r40.bin │ │ │ │ │ ├── r400.bin │ │ │ │ │ ├── r401.bin │ │ │ │ │ ├── r402.bin │ │ │ │ │ ├── r403.bin │ │ │ │ │ ├── r406.bin │ │ │ │ │ ├── r41.bin │ │ │ │ │ ├── r413.bin │ │ │ │ │ ├── r42.bin │ │ │ │ │ ├── r420.bin │ │ │ │ │ ├── r421.bin │ │ │ │ │ ├── r422.bin │ │ │ │ │ ├── r423.bin │ │ │ │ │ ├── r424.bin │ │ │ │ │ ├── r426.bin │ │ │ │ │ ├── r43.bin │ │ │ │ │ ├── r431.bin │ │ │ │ │ ├── r6.bin │ │ │ │ │ ├── r60.bin │ │ │ │ │ ├── r600.bin │ │ │ │ │ ├── r601.bin │ │ │ │ │ ├── r602.bin │ │ │ │ │ ├── r603.bin │ │ │ │ │ ├── r604.bin │ │ │ │ │ ├── r606.bin │ │ │ │ │ ├── r62.bin │ │ │ │ │ ├── r620.bin │ │ │ │ │ ├── r621.bin │ │ │ │ │ ├── r622.bin │ │ │ │ │ ├── r624.bin │ │ │ │ │ └── r626.bin │ │ │ ├── potree.js │ │ │ ├── potree.min.js │ │ │ ├── potree.module.js │ │ │ └── workers │ │ │ │ ├── BinaryDecoderWorker.js │ │ │ │ ├── DEMWorker.js │ │ │ │ ├── EptBinaryDecoderWorker.js │ │ │ │ ├── EptLaszipDecoderWorker.js │ │ │ │ ├── GreyhoundBinaryDecoderWorker.js │ │ │ │ ├── LASDecoderWorker.js │ │ │ │ └── LASLAZWorker.js │ │ └── extension.gif │ ├── TabSelectionExtension │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ └── main.js │ │ └── extension.gif │ ├── TransformationExtension │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ └── main.js │ │ └── extension.gif │ ├── XLSExtension │ │ ├── README.md │ │ ├── config.json │ │ ├── contents │ │ │ ├── ForgeXLS.js │ │ │ ├── img │ │ │ │ └── excel.png │ │ │ ├── libraries │ │ │ │ ├── Blob.js │ │ │ │ ├── FileSaver.min.js │ │ │ │ ├── clipboard.min.js │ │ │ │ ├── notify.min.js │ │ │ │ ├── xlsx.core.js │ │ │ │ └── xlsx.core.min.js │ │ │ ├── main.css │ │ │ ├── main.js │ │ │ └── modeldata.js │ │ └── extension.jpg │ ├── config.json │ ├── extensionloader.css │ └── extensionloader.js ├── img │ └── GitHub_Logo.png ├── index.html └── js │ ├── ForgeTree.js │ └── ForgeViewer.js ├── routes ├── common │ └── oauth.js ├── modelderivative.js ├── oauth.js └── oss.js ├── start.js └── thumbnail.PNG /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # multer temp upload folder 9 | tmp/ 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | .vscode 17 | package-lock.json 18 | .DS_Store 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (http://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Typescript v1 declaration files 46 | typings/ 47 | 48 | # Optional npm cache directory 49 | .npm 50 | 51 | # Optional eslint cache 52 | .eslintcache 53 | 54 | # Optional REPL history 55 | .node_repl_history 56 | 57 | # Output of 'npm pack' 58 | *.tgz 59 | 60 | # Yarn Integrity file 61 | .yarn-integrity 62 | 63 | # dotenv environment variables file 64 | .env 65 | 66 | # extension config 67 | public/extensions/config.json 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Autodesk Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecated! Please use https://github.com/autodesk-platform-services/aps-extensions 2 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | // Autodesk Forge configuration 20 | module.exports = { 21 | // Set environment variables or hard-code here 22 | credentials: { 23 | client_id: process.env.FORGE_CLIENT_ID, 24 | client_secret: process.env.FORGE_CLIENT_SECRET, 25 | callback_url: process.env.FORGE_CALLBACK_URL 26 | }, 27 | scopes: { 28 | // Required scopes for the server-side application 29 | internal: ['bucket:create', 'bucket:read', 'data:read', 'data:create', 'data:write'], 30 | // Required scope for the client-side viewer 31 | public: ['viewables:read'] 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/img/favicon.ico -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "forgeextensions", 3 | "version": "1.0.0", 4 | "description": "Sample application for learnforge.autodesk.io.", 5 | "main": "start.js", 6 | "scripts": { 7 | "start": "node start.js" 8 | }, 9 | "license": "MIT", 10 | "dependencies": { 11 | "express": "^4.18.1", 12 | "express-formidable": "^1.2.0", 13 | "forge-apis": "^0.9.2", 14 | "formidable": "^2.0.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /public/css/main.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | min-height: 100%; 3 | height: 100%; 4 | } 5 | 6 | .fill{ 7 | height: calc(100vh - 100px); 8 | } 9 | 10 | body { 11 | padding-top: 60px; /* space for the top nav bar */ 12 | /* margin-right: 30px; */ 13 | } 14 | 15 | #appBuckets { 16 | overflow: auto; 17 | width: 100%; 18 | height: calc(100vh - 150px); 19 | } 20 | 21 | #forgeViewer { 22 | width: 100%; 23 | } 24 | 25 | .nopadding{padding: 0;} 26 | 27 | .pl{padding-left: 10px;} 28 | 29 | .left_panel{padding: 0 10px;} 30 | 31 | .right_panel{padding: 0 10px;} -------------------------------------------------------------------------------- /public/extensions/BasicSkeleton/README.md: -------------------------------------------------------------------------------- 1 | # Basic Skeleton 2 | 3 | This basic skeleton extension can be used as boilerplate code for creating a custom extension. Please refer to [this tutorial](https://learnforge.autodesk.io/#/viewer/extensions/skeleton) for additional details. 4 | 5 | -------------------------------------------------------------------------------- /public/extensions/BasicSkeleton/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"BasicSkeleton", 3 | "displayname": "Basic Skeleton", 4 | "description": "Basic Skeleton of an extension, can be used as boilerplate code.", 5 | "options":{}, 6 | "viewerversion":"7.*", 7 | "loadonstartup": "false", 8 | "filestoload":{ 9 | "cssfiles":["main.css"], 10 | "jsfiles":["main.js"] 11 | }, 12 | "includeinlist":"false" 13 | } -------------------------------------------------------------------------------- /public/extensions/BasicSkeleton/contents/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/BasicSkeleton/contents/img/icon.png -------------------------------------------------------------------------------- /public/extensions/BasicSkeleton/contents/main.css: -------------------------------------------------------------------------------- 1 | .myAwesomeExtensionIcon { 2 | background-image: url(img/icon.png); 3 | background-size: 24px; 4 | background-repeat: no-repeat; 5 | background-position: center; 6 | } -------------------------------------------------------------------------------- /public/extensions/BasicSkeleton/contents/main.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | class BasicSkeleton extends Autodesk.Viewing.Extension { 19 | constructor(viewer, options) { 20 | super(viewer, options); 21 | this._group = null; 22 | this._button = null; 23 | } 24 | 25 | load() { 26 | console.log('MyAwesomeExtensions has been loaded'); 27 | return true; 28 | } 29 | 30 | unload() { 31 | // Clean our UI elements if we added any 32 | if (this._group) { 33 | this._group.removeControl(this._button); 34 | if (this._group.getNumberOfControls() === 0) { 35 | this.viewer.toolbar.removeControl(this._group); 36 | } 37 | } 38 | console.log('MyAwesomeExtensions has been unloaded'); 39 | return true; 40 | } 41 | 42 | onToolbarCreated() { 43 | // Create a new toolbar group if it doesn't exist 44 | this._group = this.viewer.toolbar.getControl('allMyAwesomeExtensionsToolbar'); 45 | if (!this._group) { 46 | this._group = new Autodesk.Viewing.UI.ControlGroup('allMyAwesomeExtensionsToolbar'); 47 | this.viewer.toolbar.addControl(this._group); 48 | } 49 | 50 | // Add a new button to the toolbar group 51 | this._button = new Autodesk.Viewing.UI.Button('myAwesomeExtensionButton'); 52 | this._button.onClick = (ev) => { 53 | // Execute an action here 54 | }; 55 | this._button.setToolTip('BasicSkeleton'); 56 | this._button.addClass('myAwesomeExtensionIcon'); 57 | this._group.addControl(this._button); 58 | } 59 | } 60 | 61 | Autodesk.Viewing.theExtensionManager.registerExtension('BasicSkeleton', BasicSkeleton); -------------------------------------------------------------------------------- /public/extensions/CameraRotation/README.md: -------------------------------------------------------------------------------- 1 | # Camera Rotation 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=CameraRotation) 4 | 5 | This extension can be used for model demo purpose, it just rotates the building or the model for look around. 6 | 7 | ![thumbnail](extension.gif) 8 | 9 | ## Usage 10 | 11 | Click on the toolbar button to start rotating, click again to stop. 12 | 13 | ## Setup 14 | 15 | Include the CSS & JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 16 | 17 | ```xml 18 | 19 | 20 | ``` 21 | 22 | After Viewer is ready, preferable inside `onDocumentLoadSuccess`, load the extension 23 | 24 | ```javascript 25 | viewer.loadExtension("CameraRotation") 26 | ``` 27 | 28 | ## How it works 29 | -------------------------------------------------------------------------------- /public/extensions/CameraRotation/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"CameraRotation", 3 | "displayname": "Camera Rotation", 4 | "description":"Rotates the model continously untill stopped, can be used for demoing a large model.", 5 | "options":{}, 6 | "loadonstartup": "false", 7 | "filestoload":{ 8 | "cssfiles":["main.css"], 9 | "jsfiles":["main.js"] 10 | }, 11 | "gif": "extension.gif", 12 | "includeinlist":"true" 13 | } -------------------------------------------------------------------------------- /public/extensions/CameraRotation/contents/img/emblem_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/CameraRotation/contents/img/emblem_camera.png -------------------------------------------------------------------------------- /public/extensions/CameraRotation/contents/main.css: -------------------------------------------------------------------------------- 1 | .toolbarCameraRotation { 2 | background-image: url(./img/emblem_camera.png); 3 | background-size: 36px; 4 | background-repeat: no-repeat; 5 | background-position: center; 6 | } -------------------------------------------------------------------------------- /public/extensions/CameraRotation/contents/main.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | /////////////////////////////////////////////////////////////////////////////// 20 | // TurnTable extension illustrating camera rotation around the model 21 | // by Denis Grigor, November 2018 22 | // 23 | /////////////////////////////////////////////////////////////////////////////// 24 | 25 | class TurnTableExtension extends Autodesk.Viewing.Extension { 26 | constructor(viewer, options) { 27 | super(viewer, options); 28 | this.viewer = viewer; 29 | this._group = null; 30 | this._button = null; 31 | this.customize = this.customize.bind(this); 32 | } 33 | 34 | load() { 35 | if (this.viewer.model.getInstanceTree()) { 36 | this.customize(); 37 | } else { 38 | this.viewer.addEventListener(Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, this.customize()); 39 | } 40 | return true; 41 | } 42 | unload() { 43 | console.log('TurnTableExtension is now unloaded!'); 44 | // Clean our UI elements if we added any 45 | if (this._group) { 46 | this._group.removeControl(this._button); 47 | if (this._group.getNumberOfControls() === 0) { 48 | this.viewer.toolbar.removeControl(this._group); 49 | } 50 | } 51 | return true; 52 | } 53 | 54 | customize() { 55 | 56 | let viewer = this.viewer; 57 | 58 | this._button = new Autodesk.Viewing.UI.Button('turnTableButton'); 59 | this._button.addClass('toolbarCameraRotation'); 60 | this._button.setToolTip('Start/Stop Camera rotation'); 61 | 62 | // _group 63 | this._group = new Autodesk.Viewing.UI.ControlGroup('CameraRotateToolbar'); 64 | this._group.addControl(this._button); 65 | this.viewer.toolbar.addControl(this._group); 66 | 67 | let started = false; 68 | 69 | let rotateCamera = () => { 70 | if (started) { 71 | requestAnimationFrame(rotateCamera); 72 | } 73 | 74 | const nav = viewer.navigation; 75 | const up = nav.getCameraUpVector(); 76 | const axis = new THREE.Vector3(0, 0, 1); 77 | const speed = 10.0 * Math.PI / 180; 78 | const matrix = new THREE.Matrix4().makeRotationAxis(axis, speed * 0.1); 79 | 80 | let pos = nav.getPosition(); 81 | pos.applyMatrix4(matrix); 82 | up.applyMatrix4(matrix); 83 | nav.setView(pos, new THREE.Vector3(0, 0, 0)); 84 | nav.setCameraUpVector(up); 85 | var viewState = viewer.getState(); 86 | // viewer.restoreState(viewState); 87 | 88 | }; 89 | 90 | this._button.onClick = function (e) { 91 | started = !started; 92 | if (started) rotateCamera() 93 | }; 94 | 95 | } 96 | 97 | } 98 | 99 | Autodesk.Viewing.theExtensionManager.registerExtension('CameraRotation', 100 | TurnTableExtension); -------------------------------------------------------------------------------- /public/extensions/CameraRotation/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/CameraRotation/extension.gif -------------------------------------------------------------------------------- /public/extensions/CustomPropertiesExtension/README.md: -------------------------------------------------------------------------------- 1 | # Custom Properties Extension 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=CustomPropertiesExtension) 4 | 5 | Extension showing custom properties in the Properties palette, based on their `dbId`. 6 | 7 | ![thumbnail](extension.gif) 8 | 9 | ## Setup 10 | 11 | Include the JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 12 | 13 | ```xml 14 | 15 | ``` 16 | 17 | Load the extension passing the properties you want to add to various objects based on their `dbId`. 18 | 19 | ```javascript 20 | viewer.loadExtension('CustomPropertiesExtension', { 21 | "properties": { 22 | "1": { 23 | "My Group": { 24 | "My Property": "My Property Value" 25 | } 26 | }, 27 | "3": { 28 | "My Other Group": { 29 | "My Other Property": "My Other Property Value" 30 | } 31 | } 32 | } 33 | }) 34 | ``` 35 | 36 | ## Configuration 37 | 38 | The `properties` contains the dbId's you assign custom properties to. 39 | 40 | ## How it works 41 | 42 | The custom properties will appear in the Properties palette. 43 | 44 | ## Futher reading 45 | 46 | The sample is based on [this blog post](https://forge.autodesk.com/blog/adding-custom-properties-property-panel). 47 | -------------------------------------------------------------------------------- /public/extensions/CustomPropertiesExtension/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"CustomPropertiesExtension", 3 | "displayname": "Custom Properties", 4 | "description": "Custom Properties example, info provided in config is showed in Properties palette based on selected object's dbId.", 5 | "options":{ 6 | "properties": { 7 | "1": { 8 | "My Group": { 9 | "My Property": "My Property Value", 10 | "My Second Property": "My Second Property Value" 11 | } 12 | }, 13 | "3": { 14 | "My Other Group": { 15 | "My Other Property": "My Other Property Value" 16 | } 17 | } 18 | } 19 | }, 20 | "editoptions":"true", 21 | "viewerversion":"7.*", 22 | "loadonstartup": "false", 23 | "filestoload":{ 24 | "cssfiles":[], 25 | "jsfiles":["main.js"] 26 | }, 27 | "bloglink":"https://github.com/autodesk-forge/forge-extensions/tree/master/public/extensions/CustomPropertiesExtension", 28 | "includeinlist":"true", 29 | "gif": "extension.gif", 30 | "externaldependencies":[] 31 | } -------------------------------------------------------------------------------- /public/extensions/CustomPropertiesExtension/contents/main.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | // ******************************************* 20 | // Custom Property Panel 21 | // ******************************************* 22 | class CustomPropertyPanel extends Autodesk.Viewing.Extensions.ViewerPropertyPanel { 23 | constructor (viewer, options) { 24 | super(viewer, options); 25 | this.properties = options.properties || {}; 26 | } 27 | 28 | setAggregatedProperties(propertySet) { 29 | Autodesk.Viewing.Extensions.ViewerPropertyPanel.prototype.setAggregatedProperties.call(this, propertySet); 30 | 31 | // add your custom properties here 32 | const dbids = propertySet.getDbIds(); 33 | dbids.forEach(id => { 34 | var propsForObject = this.properties[id.toString()]; 35 | if (propsForObject) { 36 | for (const groupName in propsForObject) { 37 | const group = propsForObject[groupName]; 38 | for (const propName in group) { 39 | const prop = group[propName]; 40 | this.addProperty(propName, prop, groupName); 41 | } 42 | } 43 | } 44 | }); 45 | } 46 | }; 47 | 48 | // ******************************************* 49 | // Custom Properties Extension 50 | // ******************************************* 51 | class CustomPropertiesExtension extends Autodesk.Viewing.Extension { 52 | constructor(viewer, options) { 53 | super(viewer, options); 54 | 55 | this.panel = new CustomPropertyPanel(viewer, options); 56 | } 57 | 58 | async load() { 59 | var ext = await this.viewer.getExtension('Autodesk.PropertiesManager'); 60 | ext.setPanel(this.panel); 61 | 62 | return true; 63 | } 64 | 65 | async unload() { 66 | var ext = await this.viewer.getExtension('Autodesk.PropertiesManager'); 67 | ext.setDefaultPanel(); 68 | 69 | return true; 70 | } 71 | } 72 | 73 | Autodesk.Viewing.theExtensionManager.registerExtension('CustomPropertiesExtension', CustomPropertiesExtension); -------------------------------------------------------------------------------- /public/extensions/CustomPropertiesExtension/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/CustomPropertiesExtension/extension.gif -------------------------------------------------------------------------------- /public/extensions/DrawToolExtension/README.md: -------------------------------------------------------------------------------- 1 | # Draw Tool Extension 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=DrawToolExtension) 4 | 5 | A simple tool that will allow us to draw boxes and spheres. Please use the Draw Tool in only full screen mode. 6 | 7 | ![thumbnail](extension.gif) 8 | 9 | ## Usage 10 | 11 | Load the extension and enter fullscreen. And here's how the drawing works: 12 | 13 | . on mouse button down event the tool will start "drawing" the geometry in the XY plane 14 | . on mouse button up event, the tool will start monitoring mouse move events to control the height of the geometry 15 | . on mouse click event, the geometry will be finalized 16 | 17 | ## Setup 18 | 19 | Include the CSS & JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 20 | 21 | ```xml 22 | 23 | 24 | ``` 25 | 26 | ## Futher reading 27 | 28 | Detailed technical explaination can be found in [this blog post](https://forge.autodesk.com/blog/custom-tools-forge-viewer). 29 | 30 | ## Author 31 | [Petr Broz](https://twitter.com/ipetrbroz) 32 | 33 | -------------------------------------------------------------------------------- /public/extensions/DrawToolExtension/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"DrawToolExtension", 3 | "displayname": "Draw Tool", 4 | "description": "A simple tool that will allow us to draw boxes and spheres.", 5 | "options":{}, 6 | "editoptions":"true", 7 | "viewerversion":"7.*", 8 | "loadonstartup": "false", 9 | "filestoload":{ 10 | "cssfiles":["main.css"], 11 | "jsfiles":["main.js"] 12 | }, 13 | "bloglink":"https://forge.autodesk.com/blog/custom-tools-forge-viewer", 14 | "includeinlist":"true", 15 | "gif": "extension.gif" 16 | } -------------------------------------------------------------------------------- /public/extensions/DrawToolExtension/contents/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/DrawToolExtension/contents/img/icon.png -------------------------------------------------------------------------------- /public/extensions/DrawToolExtension/contents/main.css: -------------------------------------------------------------------------------- 1 | #box-draw-tool-button { 2 | background-image: url(https://img.icons8.com/color/64/000000/left-view.png); 3 | background-size: 24px; 4 | background-repeat: no-repeat; 5 | background-position: center; 6 | } 7 | 8 | #sphere-draw-tool-button { 9 | background-image: url(https://img.icons8.com/color/24/000000/sphere.png); 10 | background-size: 24px; 11 | background-repeat: no-repeat; 12 | background-position: center; 13 | } -------------------------------------------------------------------------------- /public/extensions/DrawToolExtension/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/DrawToolExtension/extension.gif -------------------------------------------------------------------------------- /public/extensions/GoogleMapsLocator/README.md: -------------------------------------------------------------------------------- 1 | # Google Maps Locator 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=GoogleMapsLocator) 4 | 5 | Forge Viewer extension to show location of model on google maps. 6 | 7 | ![thumbnail](extension.gif) 8 | 9 | ## Usage 10 | 11 | - Load the extension in the viewer 12 | - Click the new maps icon in the toolbar 13 | - New docking panel opens showing google maps and the model location mentioned in extension config 14 | 15 | ## Setup 16 | 17 | Include the CSS & JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 18 | 19 | ```xml 20 | 21 | 22 | ``` 23 | 24 | The following sample uses [font-awesome](https://fontawesome.com) icons, but any CSS icon library can be used and google maps api script file. 25 | Get your Google Maps API Key [here](https://developers.google.com/maps/documentation/javascript/get-api-key) 26 | 27 | ```xml 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /public/extensions/GoogleMapsLocator/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"GoogleMapsLocator", 3 | "displayname": "GoogleMapsLocator", 4 | "description": "Show location of model on google maps.", 5 | "options":{"lattitude":0,"longitude":0}, 6 | "editoptions":"true", 7 | "viewerversion":"7.*", 8 | "loadonstartup": "false", 9 | "filestoload":{ 10 | "cssfiles":["main.css"], 11 | "jsfiles":["main.js"] 12 | }, 13 | "includeinlist":"true", 14 | "gif": "extension.gif", 15 | "externaldependencies":[ 16 | {"type": "css", "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css"}, 17 | {"type": "js", "link": "https://maps.googleapis.com/maps/api/js?key="} 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /public/extensions/GoogleMapsLocator/contents/main.css: -------------------------------------------------------------------------------- 1 | #googlemap { 2 | width: 100%; 3 | height: calc(100% - 70px); 4 | } -------------------------------------------------------------------------------- /public/extensions/GoogleMapsLocator/contents/main.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | // ******************************************* 20 | // MiniMap Extension 21 | // ******************************************* 22 | function GoogleMapsLocator(viewer, options) { 23 | Autodesk.Viewing.Extension.call(this, viewer, options); 24 | this.viewer = viewer; 25 | this.panel = null; // dock panel 26 | this.map = null; // Google Map 27 | this.geoExtension = null; // Autodesk.Geolocation extension 28 | this.options = options; 29 | 30 | var _this = this; 31 | // load extension... 32 | viewer.loadExtension('Autodesk.Geolocation').then(function (ext) { _this.geoExtension = ext }); 33 | } 34 | 35 | GoogleMapsLocator.prototype = Object.create(Autodesk.Viewing.Extension.prototype); 36 | GoogleMapsLocator.prototype.constructor = GoogleMapsLocator; 37 | 38 | GoogleMapsLocator.prototype.load = function () { 39 | return true; 40 | }; 41 | 42 | GoogleMapsLocator.prototype.onToolbarCreated = function () { 43 | // Create a new toolbar group if it doesn't exist 44 | this._group = this.viewer.toolbar.getControl('customExtensions'); 45 | if (!this._group) { 46 | this._group = new Autodesk.Viewing.UI.ControlGroup('customExtensions'); 47 | this.viewer.toolbar.addControl(this._group); 48 | } 49 | 50 | // Add a new button to the toolbar group 51 | this._button = new Autodesk.Viewing.UI.Button('showMiniMap'); 52 | this._button.onClick = (ev) => { 53 | if (this.geoExtension === null || !this.geoExtension.hasGeolocationData()) { 54 | alert('Model does not contain geo location information'); 55 | return; 56 | } 57 | 58 | this._enabled = !this._enabled; 59 | this._button.setState(this._enabled ? 0 : 1); 60 | 61 | // if null, create it 62 | if (this.panel == null) { 63 | this.panel = new MiniMapPanel(this.viewer, this.viewer.container, 'miniMapPanel', 'Mini Map'); 64 | } 65 | 66 | // show/hide docking panel 67 | this.panel.setVisible(!this.panel.isVisible()); 68 | 69 | if (!this._enabled) return; 70 | 71 | // initialize the map 72 | if (this.map == null) { 73 | this.map = new google.maps.Map(document.getElementById('googlemap'), { 74 | zoom: 16, 75 | center: { lat: this.options.lattitude, lng: this.options.longitude }, 76 | mapTypeId: 'satellite', 77 | rotateControl: false, 78 | streetViewControl: false, 79 | tilt: 0 80 | }); 81 | } 82 | 83 | // draw model boundoung box & center 84 | var bb = this.viewer.model.getBoundingBox(); 85 | this.drawBoundingBox(bb.min, bb.max); 86 | this.cameraChanged(this.viewer.autocam); // first run (center of the model) 87 | 88 | }; 89 | this._button.setToolTip('Show map location'); 90 | this._button.container.children[0].classList.add('fas', 'fa-map-marked'); 91 | this._group.addControl(this._button); 92 | 93 | // listen to camera changes 94 | this.viewer.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, (e) => { this.cameraChanged(e.target.autocam) }); 95 | }; 96 | 97 | GoogleMapsLocator.prototype.drawBoundingBox = function (min, max) { 98 | // basic check... 99 | if (this.map == null) return; 100 | if (this.geoExtension == null) return; 101 | 102 | // prepare a polygon with the bounding box information 103 | var polygon = []; 104 | polygon.push({ x: min.x, y: min.y }); 105 | polygon.push({ x: min.x, y: max.y }); 106 | polygon.push({ x: max.x, y: max.y }); 107 | polygon.push({ x: max.x, y: min.y }); 108 | 109 | this.drawPolygon(polygon); 110 | } 111 | 112 | GoogleMapsLocator.prototype.drawPolygon = function (polygon) { 113 | // basic check... 114 | var _this = this; 115 | if (_this.map == null) return; 116 | if (_this.geoExtension == null) return; 117 | 118 | // prepare the polygon coordinate to draw it 119 | var coords = []; 120 | polygon.forEach(function (point) { 121 | var geoLoc = _this.geoExtension.lmvToLonLat(point); 122 | coords.push({ lat: geoLoc.y, lng: geoLoc.x }); 123 | }); 124 | var polyOptions = { 125 | path: coords, 126 | strokeColor: '#FF0000', 127 | strokeOpacity: 0.8, 128 | strokeWeight: 2, 129 | fillColor: '#FF0000', 130 | fillOpacity: 0.1, 131 | }; 132 | var polygon = new google.maps.Polygon(polyOptions); 133 | polygon.setMap(_this.map); 134 | } 135 | 136 | GoogleMapsLocator.prototype.cameraChanged = function (camera) { 137 | // basic check... 138 | if (this.map == null) return; 139 | if (this.geoExtension == null) return; 140 | 141 | // adjust the center of the map 142 | var geoLoc = this.geoExtension.lmvToLonLat(camera.center); 143 | this.map.setCenter({ lat: geoLoc.y, lng: geoLoc.x }); 144 | } 145 | 146 | 147 | GoogleMapsLocator.prototype.unload = function () { 148 | if (this.viewer.toolbar !== null) this.viewer.toolbar.removeControl(this.subToolbar); 149 | if (this.panel !== null) this.panel.setVisible(false); 150 | if (this._group) { 151 | this._group.removeControl(this._button); 152 | if (this._group.getNumberOfControls() === 0) { 153 | this.viewer.toolbar.removeControl(this._group); 154 | } 155 | } 156 | return true; 157 | }; 158 | 159 | Autodesk.Viewing.theExtensionManager.registerExtension('GoogleMapsLocator', GoogleMapsLocator); 160 | 161 | // ******************************************* 162 | // MiniMap Panel 163 | // ******************************************* 164 | function MiniMapPanel(viewer, container, id, title, options) { 165 | this.viewer = viewer; 166 | Autodesk.Viewing.UI.DockingPanel.call(this, container, id, title, options); 167 | 168 | // the style of the docking panel 169 | // use this built-in style to support Themes on Viewer 4+ 170 | this.container.classList.add('docking-panel-container-solid-color-a'); 171 | this.container.style.top = "10px"; 172 | this.container.style.left = "10px"; 173 | this.container.style.width = "300px"; 174 | this.container.style.height = "300px"; 175 | this.container.style.resize = "auto"; 176 | 177 | // here we check the existence of a googlemap div 178 | // and remove it if it does 179 | var googleMap = document.getElementById('googlemap'); 180 | if(!!googleMap){ 181 | googleMap.parentElement.removeChild(googleMap) 182 | } 183 | 184 | // this is where we should place the content of our panel 185 | var div = document.createElement('div'); 186 | div.id = 'googlemap'; 187 | this.container.appendChild(div); 188 | } 189 | MiniMapPanel.prototype = Object.create(Autodesk.Viewing.UI.DockingPanel.prototype); 190 | MiniMapPanel.prototype.constructor = MiniMapPanel; 191 | -------------------------------------------------------------------------------- /public/extensions/GoogleMapsLocator/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/GoogleMapsLocator/extension.gif -------------------------------------------------------------------------------- /public/extensions/IconMarkupExtension/README.md: -------------------------------------------------------------------------------- 1 | # Icon Markup Extension 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=IconMarkupExtension) 4 | 5 | Extension showing labels on top of elements, based on their `dbId`. 6 | 7 | ![thumbnail](extension.gif) 8 | 9 | ## Setup 10 | 11 | Include the CSS & JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 12 | 13 | ```xml 14 | 15 | 16 | ``` 17 | 18 | The following sample uses [font-awesome](https://fontawesome.com) icons, but any CSS icon library can be used. 19 | 20 | ```xml 21 | 22 | ``` 23 | Load the extension passing the `dbId`, `label` and `css` for the label. Toolbar button and onClick event can also be configured. 24 | 25 | ```javascript 26 | viewer.loadExtension('IconMarkupExtension', { 27 | button: { 28 | icon: 'fa-thermometer-half', 29 | tooltip: 'Show Temperature' 30 | }, 31 | icons: [ 32 | { dbId: 3944, label: '300°C', css: 'fas fa-thermometer-full' }, 33 | { dbId: 721, label: '356°C', css: 'fas fa-thermometer-full' }, 34 | { dbId: 10312, label: '450°C', css: 'fas fa-thermometer-empty' }, 35 | { dbId: 563, css: 'fas fa-exclamation-triangle' }, 36 | ], 37 | onClick: (id) => { 38 | viewers.select(id); 39 | viewers.utilities.fitToView(); 40 | switch (id){ 41 | case 563: 42 | alert('Sensor offline'); 43 | } 44 | } 45 | }) 46 | ``` 47 | 48 | ## Configuration 49 | 50 | The `button` attribute defines the toolbar button. The `icons` contains the labels shwon on the model. Last, `onClick` is triggered when the user clicks on the label. 51 | 52 | ## How it works 53 | 54 | Labels are positioned over the Viewer canvas and repositioned when the camera changes (e.g. pan, zoom or rotate). 55 | 56 | ## Futher reading 57 | 58 | Detailed technical explaination can be found at [this blog post](https://forge.autodesk.com/blog/placing-custom-markup-dbid). This [live sample](http://forgeplant.herokuapp.com) shows an sample application. 59 | -------------------------------------------------------------------------------- /public/extensions/IconMarkupExtension/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"IconMarkupExtension", 3 | "displayname": "Icon Markups", 4 | "description": "Markups example, based on options provided in config, info is showed on particular object referring dbid.", 5 | "options":{ 6 | "icons": [ 7 | { "dbId": 9256, "label": "30°C", "css": "fas fa-thermometer-full" }, 8 | { "dbId": 920, "label": "35°C", "css": "fas fa-thermometer-full" }, 9 | { "dbId": 1626, "label": "45°C", "css": "fas fa-thermometer-empty" } 10 | ], 11 | "button": { 12 | "icon": "fa-thermometer-half", 13 | "tooltip": "Show Temperature" 14 | } 15 | }, 16 | "editoptions":"true", 17 | "viewerversion":"7.*", 18 | "loadonstartup": "false", 19 | "filestoload":{ 20 | "cssfiles":["main.css"], 21 | "jsfiles":["main.js"] 22 | }, 23 | "bloglink":"https://github.com/autodesk-forge/forge-extensions/tree/master/public/extensions/IconMarkupExtension", 24 | "includeinlist":"true", 25 | "gif": "extension.gif", 26 | "externaldependencies":[ 27 | {"type": "css", "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css"} 28 | ] 29 | 30 | } -------------------------------------------------------------------------------- /public/extensions/IconMarkupExtension/contents/main.css: -------------------------------------------------------------------------------- 1 | 2 | #layout { 3 | width: 100%; 4 | height: calc(100vh); 5 | } 6 | 7 | #sidebar { 8 | size: 35px; 9 | } 10 | 11 | label.markup { 12 | position: absolute; 13 | white-space: nowrap; 14 | cursor: pointer; 15 | } 16 | 17 | label.update { 18 | z-index: 1; 19 | } 20 | 21 | .temperatureBorder{ 22 | background-color: rgba(256, 256, 256, 0.5); 23 | border: 1px solid black; 24 | padding: 5px; 25 | } 26 | 27 | .temperatureHigh { 28 | font-size: 25px; 29 | color: red; 30 | } 31 | 32 | .temperatureOk { 33 | font-size: 20px; 34 | color: blue; 35 | } 36 | 37 | .temperatureYellow { 38 | font-size: 30px; 39 | color: yellow; 40 | } 41 | 42 | .maintenance{ 43 | font-size: 40px; 44 | color: green; 45 | } -------------------------------------------------------------------------------- /public/extensions/IconMarkupExtension/contents/main.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | class IconMarkupExtension extends Autodesk.Viewing.Extension { 19 | constructor(viewer, options) { 20 | super(viewer, options); 21 | this._group = null; 22 | this._button = null; 23 | this._icons = options.icons || []; 24 | } 25 | 26 | load() { 27 | if (this.viewer.model.getInstanceTree()) { 28 | this.customize(); 29 | } else { 30 | this.viewer.addEventListener(Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, this.customize()); 31 | } 32 | return true; 33 | } 34 | 35 | unload() { 36 | // Clean our UI elements if we added any 37 | if (this._group) { 38 | this._group.removeControl(this._button); 39 | if (this._group.getNumberOfControls() === 0) { 40 | this.viewer.toolbar.removeControl(this._group); 41 | } 42 | } 43 | $('#' + this.viewer.clientContainer.id + ' div.adsk-viewing-viewer label.markup').remove(); 44 | return true; 45 | } 46 | 47 | customize(){ 48 | const updateIconsCallback = () => { 49 | if (this._enabled) { 50 | this.updateIcons(); 51 | } 52 | }; 53 | this.viewer.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, updateIconsCallback); 54 | this.viewer.addEventListener(Autodesk.Viewing.ISOLATE_EVENT, updateIconsCallback); 55 | this.viewer.addEventListener(Autodesk.Viewing.HIDE_EVENT, updateIconsCallback); 56 | this.viewer.addEventListener(Autodesk.Viewing.SHOW_EVENT, updateIconsCallback); 57 | } 58 | 59 | onToolbarCreated() { 60 | // Create a new toolbar group if it doesn't exist 61 | this._group = this.viewer.toolbar.getControl('customExtensions'); 62 | if (!this._group) { 63 | this._group = new Autodesk.Viewing.UI.ControlGroup('customExtensions'); 64 | this.viewer.toolbar.addControl(this._group); 65 | } 66 | 67 | // Add a new button to the toolbar group 68 | this._button = new Autodesk.Viewing.UI.Button('IconExtension'); 69 | this._button.onClick = (ev) => { 70 | this._enabled = !this._enabled; 71 | this.showIcons(this._enabled); 72 | this._button.setState(this._enabled ? 0 : 1); 73 | 74 | }; 75 | this._button.setToolTip(this.options.button.tooltip); 76 | this._button.icon.classList.add('fas', this.options.button.icon); 77 | this._group.addControl(this._button); 78 | } 79 | 80 | showIcons(show) { 81 | const $viewer = $('#' + this.viewer.clientContainer.id + ' div.adsk-viewing-viewer'); 82 | 83 | // remove previous... 84 | $('#' + this.viewer.clientContainer.id + ' div.adsk-viewing-viewer label.markup').remove(); 85 | if (!show) return; 86 | 87 | // do we have anything to show? 88 | if (this._icons === undefined || this.icons === null) return; 89 | 90 | // do we have access to the instance tree? 91 | const tree = this.viewer.model.getInstanceTree(); 92 | if (tree === undefined) { console.log('Loading tree...'); return; } 93 | 94 | const onClick = (e) => { 95 | this.viewer.select($(e.currentTarget).data('id')); 96 | this.viewer.utilities.fitToView(); 97 | }; 98 | 99 | this._frags = {} 100 | for (var i = 0; i < this._icons.length; i++) { 101 | // we need to collect all the fragIds for a given dbId 102 | const icon = this._icons[i]; 103 | this._frags['dbId' + icon.dbId] = [] 104 | 105 | // create the label for the dbId 106 | const $label = $(` 107 | 110 | `); 111 | $label.css('display', this.viewer.isNodeVisible(icon.dbId) ? 'block' : 'none'); 112 | $label.on('click', this.options.onClick || onClick); 113 | $viewer.append($label); 114 | 115 | // now collect the fragIds 116 | const getChildren = (topParentId, dbId) => { 117 | if (tree.getChildCount(dbId) === 0) 118 | getFrags(topParentId, dbId); // get frags for this leaf child 119 | tree.enumNodeChildren(dbId, (childId) => { 120 | getChildren(topParentId, childId); 121 | }) 122 | } 123 | const getFrags = (topParentId, dbId) => { 124 | tree.enumNodeFragments(dbId, (fragId) => { 125 | this._frags['dbId' + topParentId].push(fragId); 126 | this.updateIcons(); // re-position for each fragId found 127 | }); 128 | } 129 | getChildren(icon.dbId, icon.dbId); 130 | } 131 | } 132 | 133 | getModifiedWorldBoundingBox(dbId) { 134 | var fragList = this.viewer.model.getFragmentList(); 135 | const nodebBox = new THREE.Box3() 136 | 137 | // for each fragId on the list, get the bounding box 138 | for (const fragId of this._frags['dbId' + dbId]) { 139 | const fragbBox = new THREE.Box3(); 140 | fragList.getWorldBounds(fragId, fragbBox); 141 | nodebBox.union(fragbBox); // create a unifed bounding box 142 | } 143 | 144 | return nodebBox 145 | } 146 | 147 | updateIcons() { 148 | for (const label of $('#' + this.viewer.clientContainer.id + ' div.adsk-viewing-viewer .update')) { 149 | const $label = $(label); 150 | const id = $label.data('id'); 151 | 152 | // get the center of the dbId (based on its fragIds bounding boxes) 153 | const pos = this.viewer.worldToClient(this.getModifiedWorldBoundingBox(id).center()); 154 | 155 | // position the label center to it 156 | $label.css('left', Math.floor(pos.x - $label[0].offsetWidth / 2) + 'px'); 157 | $label.css('top', Math.floor(pos.y - $label[0].offsetHeight / 2) + 'px'); 158 | $label.css('display', this.viewer.isNodeVisible(id) ? 'block' : 'none'); 159 | } 160 | } 161 | } 162 | 163 | Autodesk.Viewing.theExtensionManager.registerExtension('IconMarkupExtension', IconMarkupExtension); -------------------------------------------------------------------------------- /public/extensions/IconMarkupExtension/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/IconMarkupExtension/extension.gif -------------------------------------------------------------------------------- /public/extensions/NestedViewerExtension/README.md: -------------------------------------------------------------------------------- 1 | # NestedViewerExtension 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=NestedViewerExtension) 4 | 5 | Forge Viewer extension showing viewables related to the currently loaded model in another instance of the viewer. 6 | 7 | ![thumbnail](extension.gif) 8 | 9 | ## Usage 10 | 11 | - Load the extension in the viewer 12 | - Click the icon in the toolbar 13 | - New dialog will open, showing a dropdown list of all viewables available for the currently loaded model 14 | 15 | ## Setup 16 | 17 | Include the CSS & JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 18 | 19 | ```xml 20 | 21 | 22 | ``` 23 | 24 | After Viewer is ready, preferable inside `onDocumentLoadSuccess`, load the extension 25 | 26 | ```javascript 27 | viewer.loadExtension("NestedViewerExtension", { filter: ["2d", "3d"], crossSelection: true }) 28 | ``` 29 | 30 | ## Configuration 31 | 32 | The extension accepts an optional _options_ object with the following properties: 33 | - `filter` - array of allowed viewable "roles" ("2d", "3d", or both), by default: `["2d", "3d"]` 34 | - `crossSelection` - boolean flag for cross-selecting elements after they're selected in the main or the nested viewer, `false` by default 35 | 36 | ## How it works 37 | 38 | The extension uses another instance of [GuiViewer3D](https://forge.autodesk.com/en/docs/viewer/v7/reference/Viewing/GuiViewer3D/) 39 | and places it in a custom [DockingPanel](https://forge.autodesk.com/en/docs/viewer/v7/reference/UI/DockingPanel/). 40 | Whenever the "main" viewer loads a different model (observed via the `Autodesk.Viewing.MODEL_ROOT_LOADED_EVENT` event), 41 | the extension collects all viewables available in this model (using `doc.getRoot().search({ type: 'geometry' })`), 42 | and makes them available in the docking panel's dropdown. 43 | -------------------------------------------------------------------------------- /public/extensions/NestedViewerExtension/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NestedViewerExtension", 3 | "displayname": "Viewer in Viewer", 4 | "description": "Nested viewer where viewables related to the currently loaded model can be viewed.", 5 | "options": { 6 | "filter": ["2d", "3d"], 7 | "crossSelection": true 8 | }, 9 | "editoptions":"true", 10 | "viewerversion": "7.*", 11 | "loadonstartup": "false", 12 | "filestoload": { 13 | "cssfiles": ["main.css"], 14 | "jsfiles": ["main.js"] 15 | }, 16 | "gif": "extension.gif", 17 | "includeinlist": "true", 18 | "bloglink": "https://github.com/autodesk-forge/forge-extensions/tree/master/public/extensions/NestedViewerExtension/README.md" 19 | } 20 | -------------------------------------------------------------------------------- /public/extensions/NestedViewerExtension/contents/main.css: -------------------------------------------------------------------------------- 1 | #nestedViewerExtensionButton { 2 | background-image: url(https://img.icons8.com/color/64/000000/picture-in-picture.png); 3 | background-size: 24px; 4 | background-repeat: no-repeat; 5 | background-position: center; 6 | filter: grayscale(100%); 7 | } 8 | 9 | #nestedViewerExtensionButton.active { 10 | filter: none; 11 | } 12 | 13 | #nestedViewerExtensionDropdown { 14 | background: #eee; 15 | color: #333; 16 | } 17 | -------------------------------------------------------------------------------- /public/extensions/NestedViewerExtension/contents/main.js: -------------------------------------------------------------------------------- 1 | class NestedViewerExtension extends Autodesk.Viewing.Extension { 2 | constructor(viewer, options) { 3 | super(viewer, options); 4 | options = options || {}; 5 | this._filter = options.filter || ['2d', '3d']; 6 | this._crossSelection = !!options.crossSelection; 7 | this._group = null; 8 | this._button = null; 9 | this._panel = null; 10 | this._onModelLoaded = this.onModelLoaded.bind(this); 11 | this._onSelectionChanged = this.onSelectionChanged.bind(this); 12 | } 13 | 14 | load() { 15 | this.viewer.addEventListener(Autodesk.Viewing.MODEL_ROOT_LOADED_EVENT, this._onModelLoaded); 16 | if (this._crossSelection) { 17 | this.viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, this._onSelectionChanged); 18 | } 19 | console.log('NestedViewerExtension has been loaded.'); 20 | return true; 21 | } 22 | 23 | unload() { 24 | this.viewer.removeEventListener(Autodesk.Viewing.MODEL_ROOT_LOADED_EVENT, this._onModelLoaded); 25 | if (this._crossSelection) { 26 | this.viewer.removeEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, this._onSelectionChanged); 27 | } 28 | if (this._panel) { 29 | this._panel.uninitialize(); 30 | } 31 | // Clean our UI elements if we added any 32 | if (this._group) { 33 | this._group.removeControl(this._button); 34 | if (this._group.getNumberOfControls() === 0) { 35 | this.viewer.toolbar.removeControl(this._group); 36 | } 37 | } 38 | console.log('NestedViewerExtension has been unloaded.'); 39 | return true; 40 | } 41 | 42 | onModelLoaded() { 43 | if (this._panel) { 44 | this._panel.urn = this.viewer.model.getData().urn; 45 | } 46 | } 47 | 48 | onSelectionChanged() { 49 | if (this._panel) { 50 | // Avoid endless loop between main viewer and 51 | // the nested viewer calling each other's select() method 52 | let vs = this.viewer.getSelection(); 53 | let ps = this._panel._viewer.getSelection(); 54 | if (!this.isSelectionSame(vs, ps)) { 55 | this._panel.select(vs); 56 | } 57 | } 58 | } 59 | 60 | isSelectionSame(sel1, sel2) { 61 | if (sel1.length !== sel2.length) 62 | return false; 63 | 64 | for (let i = 0; i < sel1.length; i++) { 65 | if (sel1[i] !== sel2[i]) 66 | return false; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | onToolbarCreated() { 73 | this._group = this.viewer.toolbar.getControl('nestedViewerExtensionToolbar'); 74 | if (!this._group) { 75 | this._group = new Autodesk.Viewing.UI.ControlGroup('nestedViewerExtensionToolbar'); 76 | this.viewer.toolbar.addControl(this._group); 77 | } 78 | this._button = new Autodesk.Viewing.UI.Button('nestedViewerExtensionButton'); 79 | this._button.onClick = (ev) => { 80 | if (!this._panel) { 81 | this._panel = new NestedViewerPanel(this.viewer, this._filter, this._crossSelection); 82 | this._panel.urn = this.viewer.model.getData().urn; 83 | } 84 | if (this._panel.isVisible()) { 85 | this._panel.setVisible(false); 86 | this._button.removeClass('active'); 87 | } else { 88 | this._panel.setVisible(true); 89 | this._button.addClass('active'); 90 | } 91 | }; 92 | this._button.setToolTip('Nested Viewer'); 93 | this._button.addClass('nestedViewerExtensionIcon'); 94 | this._group.addControl(this._button); 95 | } 96 | } 97 | 98 | class NestedViewerPanel extends Autodesk.Viewing.UI.DockingPanel { 99 | constructor(viewer, filter, crossSelection) { 100 | super(viewer.container, 'nested-viewer-panel', 'Nested Viewer'); 101 | this._urn = ''; 102 | this._parentViewer = viewer; 103 | this._filter = filter; 104 | this._crossSelection = crossSelection; 105 | } 106 | 107 | get urn() { 108 | return this._urn; 109 | } 110 | 111 | set urn(value) { 112 | if (this._urn !== value) { 113 | this._urn = value; 114 | this._updateDropdown(); 115 | } 116 | } 117 | 118 | initialize() { 119 | this.container.style.top = '5em'; 120 | this.container.style.right = '5em'; 121 | this.container.style.width = '500px'; 122 | this.container.style.height = '400px'; 123 | 124 | this.title = this.createTitleBar(this.titleLabel || this.container.id); 125 | this.container.appendChild(this.title); 126 | 127 | this._container = document.createElement('div'); 128 | this._container.style.position = 'absolute'; 129 | this._container.style.left = '0'; 130 | this._container.style.top = '50px'; 131 | this._container.style.width = '100%'; 132 | this._container.style.height = '330px'; // 400px - 50px (title bar) - 20px (footer) 133 | this.container.appendChild(this._container); 134 | 135 | this._overlay = document.createElement('div'); 136 | this._overlay.style.width = '100%'; 137 | this._overlay.style.height = '100%'; 138 | this._overlay.style.display = 'none'; 139 | this._overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; 140 | this._overlay.style.color = 'white'; 141 | this._overlay.style.zIndex = '101'; 142 | this._overlay.style.justifyContent = 'center'; 143 | this._overlay.style.alignItems = 'center'; 144 | this._container.appendChild(this._overlay); 145 | 146 | this._dropdown = document.createElement('select'); 147 | this._dropdown.style.position = 'absolute'; 148 | this._dropdown.style.left = '1em'; 149 | this._dropdown.style.top = '1em'; 150 | this._dropdown.style.setProperty('z-index', '100'); 151 | this._dropdown.setAttribute('id', 'nestedViewerExtensionDropdown'); 152 | this._dropdown.addEventListener('change', this._onDropdownChanged.bind(this)) 153 | this._dropdown.addEventListener('mousedown', function (ev) { ev.stopPropagation(); }); // prevent DockingPanel from kidnapping clicks on the dropdown 154 | this._container.appendChild(this._dropdown); 155 | 156 | this.initializeMoveHandlers(this.container); 157 | this._footer = this.createFooter(); 158 | this.footerInstance.resizeCallback = (width, height) => { 159 | this._container.style.height = `${height - 50 /* title bar */ - 20 /* footer */}px`; 160 | if (this._viewer) { 161 | this._viewer.resize(); 162 | } 163 | }; 164 | this.container.appendChild(this._footer); 165 | } 166 | 167 | setVisible(show) { 168 | super.setVisible(show); 169 | if (show && !this._viewer) { 170 | this._viewer = new Autodesk.Viewing.GuiViewer3D(this._container); 171 | this._viewer.start(); 172 | this._onDropdownChanged(); 173 | if (this._crossSelection) { 174 | this._viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, () => { 175 | this._parentViewer.select(this._viewer.getSelection()); 176 | }); 177 | } 178 | } 179 | } 180 | 181 | select(dbids) { 182 | if (this._viewer) { 183 | this._viewer.select(dbids); 184 | } 185 | } 186 | 187 | _updateDropdown() { 188 | const onDocumentLoadSuccess = (doc) => { 189 | this._manifest = doc; 190 | const filterGeom = (geom) => this._filter.indexOf(geom.data.role) !== -1; 191 | const geometries = doc.getRoot().search({ type: 'geometry' }).filter(filterGeom); 192 | if (geometries.length > 0) { 193 | this._overlay.style.display = 'none'; 194 | this._dropdown.innerHTML = geometries.map(function (geom) { 195 | return ``; 196 | }).join('\n'); 197 | } else { 198 | this._overlay.style.display = 'flex'; 199 | this._overlay.innerText = 'No viewables found'; 200 | this._dropdown.innerHTML = ''; 201 | } 202 | this._onDropdownChanged(); 203 | }; 204 | const onDocumentLoadFailure = () => { 205 | console.error('Could not load document.'); 206 | }; 207 | this._dropdown.innerHTML = ''; 208 | Autodesk.Viewing.Document.load('urn:' + this._urn, onDocumentLoadSuccess, onDocumentLoadFailure); 209 | } 210 | 211 | _onDropdownChanged() { 212 | const guid = this._dropdown.value; 213 | if (guid) { 214 | this._viewer.loadDocumentNode(this._manifest, this._manifest.getRoot().findByGuid(guid)); 215 | } 216 | } 217 | } 218 | 219 | Autodesk.Viewing.theExtensionManager.registerExtension('NestedViewerExtension', NestedViewerExtension); 220 | -------------------------------------------------------------------------------- /public/extensions/NestedViewerExtension/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/NestedViewerExtension/extension.gif -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/README.md: -------------------------------------------------------------------------------- 1 | # PotreeExtension 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=PotreeExtension) 4 | 5 | ![thumbnail](extension.gif) 6 | 7 | Forge Viewer extension for loading and rendering Potree models. 8 | 9 | The extension uses [potree-core](https://github.com/tentone/potree-core) library that has been back-ported to three.js version 71 (the one used by the Forge Viewer). The experimental back-ported version of the library can be found in https://github.com/petrbroz/potree-core/tree/experiment/three71. 10 | 11 | Apart from the library itself (available as either _potree.js_, _potree.min.js_, or _potree.module.js_), this folder also includes various decoders in the _workers_ subfolder, and a sample dataset from https://github.com/tentone/potree-core. 12 | 13 | ## Usage 14 | 15 | - copy this _contents_ folder to your Forge application (the _data_ subfolder is not necessary) 16 | - include the Potree library and this extension in your HTML, after the Forge Viewer script: 17 | 18 | ```html 19 | 20 | 21 | 22 | ``` 23 | 24 | - include `PotreeExtension` when initializing the viewer, for example: 25 | 26 | ```js 27 | Autodesk.Viewing.Initializer(options, () => { 28 | const config = { 29 | extensions: ['PotreeExtension'] 30 | }; 31 | viewer = new Autodesk.Viewing.GuiViewer3D(container, config); 32 | }); 33 | ``` 34 | 35 | - in your JavaScript code, use the extension's `loadPointCloud` method, for example: 36 | 37 | ```js 38 | const potreeExtension = viewer.getExtension('PotreeExtension'); 39 | let position = new THREE.Vector3(0, 0, -25); 40 | let scale = new THREE.Vector3(5, 5, 5); 41 | const pointcloud = await potreeExtension.loadPointCloud('my-pointcloud', url, position, scale); 42 | const bbox = pointcloud.boundingBox.clone().expandByVector(scale); 43 | viewer.navigation.fitBounds(false, bbox); 44 | ``` 45 | -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PotreeExtension", 3 | "displayname": "Potree Point Clouds", 4 | "description": "Forge Viewer extension for loading and rendering Potree point clouds.", 5 | "options": { 6 | "url": "/extensions/PotreeExtension/contents/data/lion_takanawa/cloud.js", 7 | "position": [0.0, 0.0, 0.0], 8 | "scale": [5.0, 5.0, 5.0] 9 | }, 10 | "editoptions": "true", 11 | "viewerversion": "7.*", 12 | "loadonstartup": "false", 13 | "filestoload": { 14 | "cssfiles": [], 15 | "jsfiles": [ 16 | "potree.js", 17 | "PotreeExtension.js" 18 | ] 19 | }, 20 | "gif": "extension.gif", 21 | "includeinlist": "true", 22 | "bloglink": "" 23 | } -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/PotreeExtension.js: -------------------------------------------------------------------------------- 1 | class PotreeExtension extends Autodesk.Viewing.Extension { 2 | constructor(viewer, options) { 3 | super(viewer, options); 4 | this._group = null; 5 | this._pointclouds = new Map(); 6 | this._timer = null; 7 | if (options && options.url) { 8 | this._initConfig = { 9 | url: options.url, 10 | position: null, 11 | scale: null 12 | }; 13 | if (options.position && Array.isArray(options.position)) { 14 | this._initConfig.position = new THREE.Vector3(options.position[0], options.position[1], options.position[2]); 15 | } 16 | if (options.scale && Array.isArray(options.scale)) { 17 | this._initConfig.scale = new THREE.Vector3(options.scale[0], options.scale[1], options.scale[2]); 18 | } 19 | } 20 | } 21 | 22 | load() { 23 | // Setup the overlay scene 24 | this._group = new THREE.Group(); 25 | if (!this.viewer.overlays.hasScene('potree-scene')) { 26 | this.viewer.overlays.addScene('potree-scene'); 27 | } 28 | this.viewer.overlays.addMesh(this._group, 'potree-scene'); 29 | 30 | // Update point clouds on every camera change... 31 | this.viewer.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, this.updatePointClouds.bind(this)); 32 | // ... and also in hard-coded intervals 33 | this._timer = setInterval(this.updatePointClouds.bind(this), 500); 34 | 35 | console.log('PotreeExtension loaded.'); 36 | 37 | if (this._initConfig) { 38 | this.loadPointCloud('my-pointcloud', this._initConfig.url, this._initConfig.position, this._initConfig.scale); 39 | } 40 | 41 | return true; 42 | } 43 | 44 | unload() { 45 | this.viewer.overlays.removeScene('potree-scene'); 46 | console.log('PotreeExtension unloaded.'); 47 | return true; 48 | } 49 | 50 | /** 51 | * Adds potree model into the scene and starts streaming its data. 52 | * @param {string} name Unique name of the model. 53 | * @param {string} url URL of the potree model main file (typically "cloud.js"). 54 | * @param {THREE.Vector3} [position] Optional position to apply to the newly loaded pointcloud. 55 | * @param {THREE.Vector3} [scale] Optional scale to apply to the newly loaded pointcloud. 56 | * @returns {Promise} Potree point cloud object. 57 | * @example 58 | * const ext = viewer.getExtension('PotreeExtension'); 59 | * const pointcloud = await ext.loadPointCloud('lion', '/potree/data/lion_takanawa/cloud.js', new THREE.Vector3(0, 0, -25), new THREE.Vector3(5, 5, 5)); 60 | * console.log(pointcloud); 61 | */ 62 | loadPointCloud(name, url, position, scale) { 63 | if (this._pointclouds.has(name)) { 64 | return Promise.resolve(this._pointclouds.get(name)); 65 | } 66 | return new Promise((resolve, reject) => { 67 | Potree.loadPointCloud(url, name, (ev) => { 68 | const { pointcloud } = ev; 69 | const { material } = pointcloud; 70 | if (position) { 71 | pointcloud.position.copy(position); 72 | } 73 | if (scale) { 74 | pointcloud.scale.copy(scale); 75 | } 76 | material.size = 2; 77 | material.pointColorType = Potree.PointColorType.RGB; //RGB | DEPTH | HEIGHT | POINT_INDEX | LOD | CLASSIFICATION 78 | material.pointSizeType = Potree.PointSizeType.ADAPTIVE; //ADAPTIVE | FIXED 79 | material.shape = Potree.PointShape.CIRCLE; //CIRCLE | SQUARE 80 | this._group.add(pointcloud); 81 | this._pointclouds.set(name, pointcloud); 82 | this.updatePointClouds(); 83 | resolve(pointcloud); 84 | }); 85 | }); 86 | } 87 | 88 | updatePointClouds() { 89 | const pointclouds = Array.from(this._pointclouds.values()); 90 | if (pointclouds) { 91 | const camera = this.viewer.impl.camera; //.perspectiveCamera; 92 | const renderer = this.viewer.impl.glrenderer(); 93 | Potree.updatePointClouds(pointclouds, camera, renderer); 94 | } 95 | } 96 | } 97 | 98 | Autodesk.Viewing.theExtensionManager.registerExtension('PotreeExtension', PotreeExtension); 99 | -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/cloud.js: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.7", 3 | "octreeDir": "data", 4 | "boundingBox": { 5 | "lx": -0.748212993144989, 6 | "ly": -2.78040599822998, 7 | "lz": 2.54782128334045, 8 | "ux": 3.89967638254166, 9 | "uy": 1.86748337745667, 10 | "uz": 7.1957106590271 11 | }, 12 | "tightBoundingBox": { 13 | "lx": -0.748212993144989, 14 | "ly": -2.78040599822998, 15 | "lz": 2.55100011825562, 16 | "ux": 2.4497377872467, 17 | "uy": 1.48934376239777, 18 | "uz": 7.1957106590271 19 | }, 20 | "pointAttributes": [ 21 | "POSITION_CARTESIAN", 22 | "COLOR_PACKED", 23 | "NORMAL_SPHEREMAPPED" 24 | ], 25 | "spacing": 0.0750000029802322, 26 | "scale": 0.001, 27 | "hierarchyStepSize": 6 28 | } 29 | -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r.hrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r.hrc -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r0.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r0.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r00.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r00.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r001.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r001.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r003.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r003.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r004.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r004.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r005.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r005.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r007.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r007.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r01.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r01.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r012.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r012.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r013.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r013.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r016.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r016.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r017.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r017.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r02.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r02.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r021.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r021.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r023.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r023.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r03.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r03.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r030.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r030.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r031.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r031.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r032.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r032.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r034.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r034.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r035.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r035.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r036.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r036.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r037.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r037.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r04.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r04.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r041.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r041.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r043.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r043.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r045.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r045.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r047.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r047.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r05.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r05.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r052.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r052.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r053.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r053.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r056.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r056.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r057.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r057.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r06.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r06.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r065.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r065.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r067.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r067.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r07.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r07.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r070.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r070.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r071.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r071.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r072.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r072.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r073.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r073.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r074.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r074.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r075.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r075.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r076.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r076.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r077.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r077.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r1.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r11.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r11.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r116.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r116.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r117.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r117.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r12.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r12.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r124.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r124.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r125.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r125.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r126.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r126.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r127.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r127.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r13.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r13.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r134.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r134.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r135.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r135.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r136.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r136.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r137.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r137.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r14.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r14.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r146.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r146.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r15.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r15.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r152.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r152.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r153.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r153.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r156.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r156.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r157.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r157.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r16.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r16.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r160.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r160.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r161.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r161.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r162.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r162.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r164.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r164.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r165.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r165.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r166.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r166.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r167.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r167.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r17.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r17.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r170.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r170.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r171.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r171.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r173.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r173.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r174.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r174.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r175.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r175.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r176.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r176.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r177.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r177.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r2.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r21.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r21.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r210.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r210.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r214.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r214.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r215.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r215.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r23.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r23.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r235.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r235.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r24.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r24.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r243.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r243.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r245.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r245.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r247.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r247.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r25.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r25.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r250.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r250.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r251.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r251.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r254.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r254.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r255.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r255.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r256.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r256.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r257.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r257.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r26.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r26.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r261.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r261.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r265.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r265.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r27.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r27.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r270.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r270.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r271.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r271.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r274.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r274.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r275.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r275.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r3.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r3.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r30.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r30.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r304.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r304.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r306.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r306.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r31.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r31.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r314.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r314.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r315.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r315.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r32.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r32.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r324.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r324.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r34.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r34.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r340.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r340.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r341.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r341.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r342.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r342.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r343.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r343.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r344.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r344.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r345.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r345.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r346.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r346.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r347.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r347.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r35.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r35.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r350.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r350.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r351.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r351.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r354.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r354.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r355.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r355.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r36.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r36.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r360.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r360.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r364.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r364.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r4.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r4.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r40.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r40.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r400.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r400.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r401.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r401.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r402.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r402.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r403.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r403.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r406.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r406.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r41.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r41.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r413.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r413.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r42.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r42.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r420.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r420.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r421.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r421.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r422.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r422.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r423.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r423.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r424.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r424.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r426.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r426.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r43.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r43.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r431.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r431.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r6.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r6.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r60.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r60.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r600.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r600.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r601.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r601.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r602.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r602.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r603.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r603.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r604.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r604.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r606.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r606.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r62.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r62.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r620.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r620.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r621.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r621.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r622.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r622.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r624.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r624.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r626.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/contents/data/lion_takanawa/data/r/r626.bin -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/workers/DEMWorker.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | onmessage = function(event) 4 | { 5 | var boundingBox = event.data.boundingBox; 6 | var position = new Float32Array(event.data.position); 7 | var numPoints = position.length / 3; 8 | var width = 64, height = 64; 9 | 10 | var boxSize = 11 | { 12 | x: boundingBox.max[0] - boundingBox.min[0], 13 | y: boundingBox.max[1] - boundingBox.min[1], 14 | z: boundingBox.max[2] - boundingBox.min[2] 15 | }; 16 | 17 | var dem = new Float32Array(width * height); 18 | dem.fill(-Infinity); 19 | 20 | for(var i = 0; i < numPoints; i++) 21 | { 22 | var x = position[3 * i + 0]; 23 | var y = position[3 * i + 1]; 24 | var z = position[3 * i + 2]; 25 | 26 | var dx = x / boxSize.x; 27 | var dy = y / boxSize.y; 28 | 29 | var ix = parseInt(Math.min(width * dx, width - 1)); 30 | var iy = parseInt(Math.min(height * dy, height - 1)); 31 | 32 | var index = ix + width * iy; 33 | dem[index] = z; 34 | } 35 | 36 | var message = 37 | { 38 | dem: 39 | { 40 | width: width, 41 | height: height, 42 | data: dem.buffer 43 | } 44 | }; 45 | 46 | postMessage(message, [message.dem.data]); 47 | }; 48 | -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/workers/EptBinaryDecoderWorker.js: -------------------------------------------------------------------------------- 1 | Potree = { }; 2 | 3 | onmessage = function(event) { 4 | let buffer = event.data.buffer; 5 | let view = new DataView(buffer); 6 | let schema = event.data.schema; 7 | let scale = event.data.scale; 8 | let offset = event.data.offset; 9 | let mins = event.data.mins; 10 | 11 | let dimensions = schema.reduce((p, c) => { 12 | p[c.name] = c; 13 | return p; 14 | }, { }); 15 | 16 | let dimOffset = (name) => { 17 | let offset = 0; 18 | for (var i = 0; i < schema.length; ++i) { 19 | if (schema[i].name == name) return offset; 20 | offset += schema[i].size; 21 | } 22 | return undefined; 23 | }; 24 | 25 | let getExtractor = (name) => { 26 | let offset = dimOffset(name); 27 | let type = dimensions[name].type; 28 | let size = dimensions[name].size; 29 | 30 | if (type == "signed") switch (size) { 31 | case 1: return (p) => view.getInt8(p + offset); 32 | case 2: return (p) => view.getInt16(p + offset, true); 33 | case 4: return (p) => view.getInt32(p + offset, true); 34 | case 8: return (p) => view.getInt64(p + offset, true); 35 | } 36 | if (type == "unsigned") switch (size) { 37 | case 1: return (p) => view.getUint8(p + offset); 38 | case 2: return (p) => view.getUint16(p + offset, true); 39 | case 4: return (p) => view.getUint32(p + offset, true); 40 | case 8: return (p) => view.getUint64(p + offset, true); 41 | } 42 | if (type == "float") switch (size) { 43 | case 4: return (p) => view.getFloat32(p + offset, true); 44 | case 8: return (p) => view.getFloat64(p + offset, true); 45 | } 46 | 47 | let str = JSON.stringify(dimensions[name]); 48 | throw new Error(`Invalid dimension specification for ${name}: ${str}`); 49 | }; 50 | 51 | let pointSize = schema.reduce((p, c) => p + c.size, 0); 52 | let numPoints = buffer.byteLength / pointSize; 53 | 54 | let xyzBuffer, rgbBuffer, intensityBuffer, classificationBuffer, 55 | returnNumberBuffer, numberOfReturnsBuffer, pointSourceIdBuffer; 56 | let xyz, rgb, intensity, classification, returnNumber, numberOfReturns, 57 | pointSourceId; 58 | let xyzExtractor, rgbExtractor, intensityExtractor, classificationExtractor, 59 | returnNumberExtractor, numberOfReturnsExtractor, pointSourceIdExtractor; 60 | let twoByteColor = false; 61 | 62 | if (dimensions["X"] && dimensions["Y"] && dimensions["Z"]) { 63 | xyzBuffer = new ArrayBuffer(numPoints * 4 * 3); 64 | xyz = new Float32Array(xyzBuffer); 65 | xyzExtractor = [ 66 | getExtractor("X"), 67 | getExtractor("Y"), 68 | getExtractor("Z") 69 | ]; 70 | } 71 | 72 | if (dimensions["Red"] && dimensions["Green"] && dimensions["Blue"]) { 73 | rgbBuffer = new ArrayBuffer(numPoints * 4); 74 | rgb = new Uint8Array(rgbBuffer); 75 | rgbExtractor = [ 76 | getExtractor("Red"), 77 | getExtractor("Green"), 78 | getExtractor("Blue") 79 | ]; 80 | 81 | let r, g, b, pos; 82 | for (let i = 0; i < numPoints && !twoByteColor; ++i) { 83 | pos = i * pointSize; 84 | r = rgbExtractor[0](pos); 85 | g = rgbExtractor[1](pos); 86 | b = rgbExtractor[2](pos); 87 | if (r > 255 || g > 255 || b > 255) twoByteColor = true; 88 | } 89 | } 90 | 91 | if (dimensions["Intensity"]) { 92 | intensityBuffer = new ArrayBuffer(numPoints * 4); 93 | intensity = new Float32Array(intensityBuffer); 94 | intensityExtractor = getExtractor("Intensity"); 95 | } 96 | 97 | if (dimensions["Classification"]) { 98 | classificationBuffer = new ArrayBuffer(numPoints); 99 | classification = new Uint8Array(classificationBuffer); 100 | classificationExtractor = getExtractor("Classification"); 101 | } 102 | 103 | if (dimensions["ReturnNumber"]) { 104 | returnNumberBuffer = new ArrayBuffer(numPoints); 105 | returnNumber = new Uint8Array(returnNumberBuffer); 106 | returnNumberExtractor = getExtractor("ReturnNumber"); 107 | } 108 | 109 | if (dimensions["NumberOfReturns"]) { 110 | numberOfReturnsBuffer = new ArrayBuffer(numPoints); 111 | numberOfReturns = new Uint8Array(numberOfReturnsBuffer); 112 | numberOfReturnsExtractor = getExtractor("NumberOfReturns"); 113 | } 114 | 115 | if (dimensions["PointSourceId"]) { 116 | pointSourceIdBuffer = new ArrayBuffer(numPoints * 2); 117 | pointSourceId = new Uint16Array(pointSourceIdBuffer); 118 | pointSourceIdExtractor = getExtractor("PointSourceId"); 119 | } 120 | 121 | let mean = [0, 0, 0]; 122 | let bounds = { 123 | min: [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE], 124 | max: [-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE], 125 | }; 126 | 127 | let x, y, z, r, g, b; 128 | for (let i = 0; i < numPoints; ++i) { 129 | let pos = i * pointSize; 130 | if (xyz) { 131 | x = xyzExtractor[0](pos) * scale.x + offset.x - mins[0]; 132 | y = xyzExtractor[1](pos) * scale.y + offset.y - mins[1]; 133 | z = xyzExtractor[2](pos) * scale.z + offset.z - mins[2]; 134 | 135 | mean[0] += x / numPoints; 136 | mean[1] += y / numPoints; 137 | mean[2] += z / numPoints; 138 | 139 | bounds.min[0] = Math.min(bounds.min[0], x); 140 | bounds.min[1] = Math.min(bounds.min[1], y); 141 | bounds.min[2] = Math.min(bounds.min[2], z); 142 | 143 | bounds.max[0] = Math.max(bounds.max[0], x); 144 | bounds.max[1] = Math.max(bounds.max[1], y); 145 | bounds.max[2] = Math.max(bounds.max[2], z); 146 | 147 | xyz[3 * i + 0] = x; 148 | xyz[3 * i + 1] = y; 149 | xyz[3 * i + 2] = z; 150 | } 151 | 152 | if (rgb) { 153 | r = rgbExtractor[0](pos); 154 | g = rgbExtractor[1](pos); 155 | b = rgbExtractor[2](pos); 156 | 157 | if (twoByteColor) { 158 | r /= 256; 159 | g /= 256; 160 | b /= 256; 161 | } 162 | 163 | rgb[4 * i + 0] = r; 164 | rgb[4 * i + 1] = g; 165 | rgb[4 * i + 2] = b; 166 | } 167 | 168 | if (intensity) intensity[i] = intensityExtractor(pos); 169 | if (classification) classification[i] = classificationExtractor(pos); 170 | if (returnNumber) returnNumber[i] = returnNumberExtractor(pos); 171 | if (numberOfReturns) numberOfReturns[i] = numberOfReturnsExtractor(pos); 172 | if (pointSourceId) pointSourceId[i] = pointSourceIdExtractor(pos); 173 | } 174 | 175 | let indicesBuffer = new ArrayBuffer(numPoints * 4); 176 | let indices = new Uint32Array(indicesBuffer); 177 | for (let i = 0; i < numPoints; ++i) { 178 | indices[i] = i; 179 | } 180 | 181 | let message = { 182 | numPoints: numPoints, 183 | tightBoundingBox: bounds, 184 | mean: mean, 185 | 186 | position: xyzBuffer, 187 | color: rgbBuffer, 188 | intensity: intensityBuffer, 189 | classification: classificationBuffer, 190 | returnNumber: returnNumberBuffer, 191 | numberOfReturns: numberOfReturnsBuffer, 192 | pointSourceId: pointSourceIdBuffer, 193 | indices: indicesBuffer 194 | }; 195 | 196 | let transferables = [ 197 | message.position, 198 | message.color, 199 | message.intensity, 200 | message.classification, 201 | message.returnNumber, 202 | message.numberOfReturns, 203 | message.pointSourceId, 204 | message.indices 205 | ].filter((v) => v); 206 | 207 | postMessage(message, transferables); 208 | } 209 | 210 | -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/workers/EptLaszipDecoderWorker.js: -------------------------------------------------------------------------------- 1 | function readUsingDataView(event) { 2 | performance.mark("laslaz-start"); 3 | 4 | let buffer = event.data.buffer; 5 | let numPoints = event.data.numPoints; 6 | let pointSize = event.data.pointSize; 7 | let pointFormat = event.data.pointFormatID; 8 | let scale = event.data.scale; 9 | let offset = event.data.offset; 10 | 11 | let sourceUint8 = new Uint8Array(buffer); 12 | let sourceView = new DataView(buffer); 13 | 14 | let tightBoundingBox = { 15 | min: [ 16 | Number.POSITIVE_INFINITY, 17 | Number.POSITIVE_INFINITY, 18 | Number.POSITIVE_INFINITY 19 | ], 20 | max: [ 21 | Number.NEGATIVE_INFINITY, 22 | Number.NEGATIVE_INFINITY, 23 | Number.NEGATIVE_INFINITY 24 | ] 25 | }; 26 | 27 | let mean = [0, 0, 0]; 28 | 29 | let pBuff = new ArrayBuffer(numPoints * 3 * 4); 30 | let cBuff = new ArrayBuffer(numPoints * 4); 31 | let iBuff = new ArrayBuffer(numPoints * 4); 32 | let clBuff = new ArrayBuffer(numPoints); 33 | let rnBuff = new ArrayBuffer(numPoints); 34 | let nrBuff = new ArrayBuffer(numPoints); 35 | let psBuff = new ArrayBuffer(numPoints * 2); 36 | 37 | let positions = new Float32Array(pBuff); 38 | let colors = new Uint8Array(cBuff); 39 | let intensities = new Float32Array(iBuff); 40 | let classifications = new Uint8Array(clBuff); 41 | let returnNumbers = new Uint8Array(rnBuff); 42 | let numberOfReturns = new Uint8Array(nrBuff); 43 | let pointSourceIDs = new Uint16Array(psBuff); 44 | 45 | // Point format 3 contains an 8-byte GpsTime before RGB values, so make 46 | // sure we have the correct color offset. 47 | let hasColor = pointFormat == 2 || pointFormat == 3; 48 | let co = pointFormat == 2 ? 20 : 28; 49 | 50 | // TODO This should be cached per-resource since this is an expensive check. 51 | let twoByteColor = false; 52 | if (hasColor) { 53 | let r, g, b, pos; 54 | for (let i = 0; i < numPoints && !twoByteColor; ++i) { 55 | pos = i * pointSize; 56 | r = sourceView.getUint16(pos + co, true) 57 | g = sourceView.getUint16(pos + co + 2, true) 58 | b = sourceView.getUint16(pos + co + 4, true) 59 | if (r > 255 || g > 255 || b > 255) twoByteColor = true; 60 | } 61 | } 62 | 63 | for (let i = 0; i < numPoints; i++) { 64 | // POSITION 65 | let ux = sourceView.getInt32(i * pointSize + 0, true); 66 | let uy = sourceView.getInt32(i * pointSize + 4, true); 67 | let uz = sourceView.getInt32(i * pointSize + 8, true); 68 | 69 | x = ux * scale[0] + offset[0] - event.data.mins[0]; 70 | y = uy * scale[1] + offset[1] - event.data.mins[1]; 71 | z = uz * scale[2] + offset[2] - event.data.mins[2]; 72 | 73 | positions[3 * i + 0] = x; 74 | positions[3 * i + 1] = y; 75 | positions[3 * i + 2] = z; 76 | 77 | mean[0] += x / numPoints; 78 | mean[1] += y / numPoints; 79 | mean[2] += z / numPoints; 80 | 81 | tightBoundingBox.min[0] = Math.min(tightBoundingBox.min[0], x); 82 | tightBoundingBox.min[1] = Math.min(tightBoundingBox.min[1], y); 83 | tightBoundingBox.min[2] = Math.min(tightBoundingBox.min[2], z); 84 | 85 | tightBoundingBox.max[0] = Math.max(tightBoundingBox.max[0], x); 86 | tightBoundingBox.max[1] = Math.max(tightBoundingBox.max[1], y); 87 | tightBoundingBox.max[2] = Math.max(tightBoundingBox.max[2], z); 88 | 89 | // INTENSITY 90 | let intensity = sourceView.getUint16(i * pointSize + 12, true); 91 | intensities[i] = intensity; 92 | 93 | // RETURN NUMBER, stored in the first 3 bits - 00000111 94 | // number of returns stored in next 3 bits - 00111000 95 | let returnNumberAndNumberOfReturns = sourceView.getUint8(i * pointSize + 14, true); 96 | let returnNumber = returnNumberAndNumberOfReturns & 0b0111; 97 | let numberOfReturn = (returnNumberAndNumberOfReturns & 0b00111000) >> 3; 98 | returnNumbers[i] = returnNumber; 99 | numberOfReturns[i] = numberOfReturn; 100 | 101 | // CLASSIFICATION 102 | let classification = sourceView.getUint8(i * pointSize + 15, true); 103 | classifications[i] = classification; 104 | 105 | // POINT SOURCE ID 106 | let pointSourceID = sourceView.getUint16(i * pointSize + 18, true); 107 | pointSourceIDs[i] = pointSourceID; 108 | 109 | // COLOR, if available 110 | if (hasColor) { 111 | let r = sourceView.getUint16(i * pointSize + co, true) 112 | let g = sourceView.getUint16(i * pointSize + co + 2, true) 113 | let b = sourceView.getUint16(i * pointSize + co + 4, true) 114 | 115 | if (twoByteColor) { 116 | r /= 256; 117 | g /= 256; 118 | b /= 256; 119 | } 120 | 121 | colors[4 * i + 0] = r; 122 | colors[4 * i + 1] = g; 123 | colors[4 * i + 2] = b; 124 | colors[4 * i + 3] = 255; 125 | } 126 | } 127 | 128 | let indices = new ArrayBuffer(numPoints * 4); 129 | let iIndices = new Uint32Array(indices); 130 | for (let i = 0; i < numPoints; i++) { 131 | iIndices[i] = i; 132 | } 133 | 134 | performance.mark("laslaz-end"); 135 | 136 | //{ // print timings 137 | // performance.measure("laslaz", "laslaz-start", "laslaz-end"); 138 | // let measure = performance.getEntriesByType("measure")[0]; 139 | // let dpp = 1000 * measure.duration / numPoints; 140 | // let debugMessage = `${measure.duration.toFixed(3)} ms, ${numPoints} points, ${dpp.toFixed(3)} µs / point`; 141 | // console.log(debugMessage); 142 | //} 143 | performance.clearMarks(); 144 | performance.clearMeasures(); 145 | 146 | let message = { 147 | mean: mean, 148 | position: pBuff, 149 | color: cBuff, 150 | intensity: iBuff, 151 | classification: clBuff, 152 | returnNumber: rnBuff, 153 | numberOfReturns: nrBuff, 154 | pointSourceID: psBuff, 155 | tightBoundingBox: tightBoundingBox, 156 | indices: indices 157 | }; 158 | 159 | let transferables = [ 160 | message.position, 161 | message.color, 162 | message.intensity, 163 | message.classification, 164 | message.returnNumber, 165 | message.numberOfReturns, 166 | message.pointSourceID, 167 | message.indices 168 | ]; 169 | 170 | postMessage(message, transferables); 171 | }; 172 | 173 | 174 | 175 | onmessage = readUsingDataView; 176 | 177 | -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/contents/workers/LASDecoderWorker.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | onmessage = function(event) 4 | { 5 | var buffer = event.data.buffer; 6 | var numPoints = event.data.numPoints; 7 | var sourcePointSize = event.data.pointSize; 8 | var pointFormatID = event.data.pointFormatID; 9 | var scale = event.data.scale; 10 | var offset = event.data.offset; 11 | 12 | var sourceUint8 = new Uint8Array(buffer); 13 | var sourceView = new DataView(buffer); 14 | 15 | var targetPointSize = 40; 16 | var targetBuffer = new ArrayBuffer(numPoints * targetPointSize); 17 | var targetView = new DataView(targetBuffer); 18 | 19 | var tightBoundingBox = 20 | { 21 | min: [ Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY ], 22 | max: [ Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY ] 23 | }; 24 | 25 | var mean = [0, 0, 0]; 26 | 27 | var pBuff = new ArrayBuffer(numPoints * 3 * 4); 28 | var cBuff = new ArrayBuffer(numPoints * 4); 29 | var iBuff = new ArrayBuffer(numPoints * 4); 30 | var clBuff = new ArrayBuffer(numPoints); 31 | var rnBuff = new ArrayBuffer(numPoints); 32 | var nrBuff = new ArrayBuffer(numPoints); 33 | var psBuff = new ArrayBuffer(numPoints * 2); 34 | 35 | var positions = new Float32Array(pBuff); 36 | var colors = new Uint8Array(cBuff); 37 | var intensities = new Float32Array(iBuff); 38 | var classifications = new Uint8Array(clBuff); 39 | var returnNumbers = new Uint8Array(rnBuff); 40 | var numberOfReturns = new Uint8Array(nrBuff); 41 | var pointSourceIDs = new Uint16Array(psBuff); 42 | 43 | for (var i = 0; i < numPoints; i++) 44 | { 45 | //POSITION 46 | var ux = sourceView.getInt32(i * sourcePointSize + 0, true); 47 | var uy = sourceView.getInt32(i * sourcePointSize + 4, true); 48 | var uz = sourceView.getInt32(i * sourcePointSize + 8, true); 49 | 50 | var x = ux * scale[0] + offset[0] - event.data.mins[0]; 51 | var y = uy * scale[1] + offset[1] - event.data.mins[1]; 52 | var z = uz * scale[2] + offset[2] - event.data.mins[2]; 53 | 54 | positions[3 * i + 0] = x; 55 | positions[3 * i + 1] = y; 56 | positions[3 * i + 2] = z; 57 | 58 | mean[0] += x / numPoints; 59 | mean[1] += y / numPoints; 60 | mean[2] += z / numPoints; 61 | 62 | tightBoundingBox.min[0] = Math.min(tightBoundingBox.min[0], x); 63 | tightBoundingBox.min[1] = Math.min(tightBoundingBox.min[1], y); 64 | tightBoundingBox.min[2] = Math.min(tightBoundingBox.min[2], z); 65 | 66 | tightBoundingBox.max[0] = Math.max(tightBoundingBox.max[0], x); 67 | tightBoundingBox.max[1] = Math.max(tightBoundingBox.max[1], y); 68 | tightBoundingBox.max[2] = Math.max(tightBoundingBox.max[2], z); 69 | 70 | //INTENSITY 71 | var intensity = sourceView.getUint16(i * sourcePointSize + 12, true); 72 | intensities[i] = intensity; 73 | 74 | //RETURN NUMBER, stored in the first 3 bits - 00000111 75 | //number of returns stored in next 3 bits - 00111000 76 | var returnNumberAndNumberOfReturns = sourceView.getUint8(i * sourcePointSize + 14, true); 77 | var returnNumber = returnNumberAndNumberOfReturns & 0b0111; 78 | var numberOfReturn = (returnNumberAndNumberOfReturns & 0b00111000) >> 3; 79 | returnNumbers[i] = returnNumber; 80 | numberOfReturns[i] = numberOfReturn; 81 | 82 | //CLASSIFICATION 83 | var classification = sourceView.getUint8(i * sourcePointSize + 15, true); 84 | classifications[i] = classification; 85 | 86 | //POINT SOURCE ID 87 | var pointSourceID = sourceView.getUint16(i * sourcePointSize + 18, true); 88 | pointSourceIDs[i] = pointSourceID; 89 | 90 | //COLOR, if available 91 | if (pointFormatID === 2) { 92 | var r = sourceView.getUint16(i * sourcePointSize + 20, true) / 256; 93 | var g = sourceView.getUint16(i * sourcePointSize + 22, true) / 256; 94 | var b = sourceView.getUint16(i * sourcePointSize + 24, true) / 256; 95 | 96 | colors[4 * i + 0] = r; 97 | colors[4 * i + 1] = g; 98 | colors[4 * i + 2] = b; 99 | colors[4 * i + 3] = 255; 100 | } 101 | } 102 | 103 | var indices = new ArrayBuffer(numPoints * 4); 104 | var iIndices = new Uint32Array(indices); 105 | for (var i = 0; i < numPoints; i++) 106 | { 107 | iIndices[i] = i; 108 | } 109 | 110 | var message = 111 | { 112 | mean: mean, 113 | position: pBuff, 114 | color: cBuff, 115 | intensity: iBuff, 116 | classification: clBuff, 117 | returnNumber: rnBuff, 118 | numberOfReturns: nrBuff, 119 | pointSourceID: psBuff, 120 | tightBoundingBox: tightBoundingBox, 121 | indices: indices 122 | }; 123 | 124 | var transferables = 125 | [ 126 | message.position, 127 | message.color, 128 | message.intensity, 129 | message.classification, 130 | message.returnNumber, 131 | message.numberOfReturns, 132 | message.pointSourceID, 133 | message.indices 134 | ]; 135 | 136 | postMessage(message, transferables); 137 | }; 138 | -------------------------------------------------------------------------------- /public/extensions/PotreeExtension/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/PotreeExtension/extension.gif -------------------------------------------------------------------------------- /public/extensions/TabSelectionExtension/README.md: -------------------------------------------------------------------------------- 1 | # TAB Selection Extension 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=TabSelectionExtension) 4 | 5 | Use TAB key to rotate selection, similar to Revit TAB to select nested families. 6 | 7 | ![thumbnail](extension.gif) 8 | 9 | ## Setup 10 | 11 | Include the JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 12 | 13 | ```xml 14 | 15 | ``` 16 | 17 | Load the extension passing the properties you want to add to various objects based on their `dbId`. 18 | 19 | ```javascript 20 | viewer.loadExtension('TabSelectionExtension'); 21 | ``` 22 | 23 | ## How it works 24 | 25 | Select an element, press TAB to select the parent node. Each TAB press will move up on the tree until the root, then reset back to the initial selection. 26 | -------------------------------------------------------------------------------- /public/extensions/TabSelectionExtension/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"TabSelectionExtension", 3 | "displayname": "Tab selection", 4 | "description":"Use TAB to rotate selection based on the model tree. For Revit files, it mimics the nested family selection.", 5 | "options":{}, 6 | "loadonstartup": "false", 7 | "filestoload":{ 8 | "jsfiles":["main.js"], 9 | "cssfiles": [] 10 | }, 11 | "bloglink":"https://github.com/autodesk-forge/forge-extensions/tree/master/public/extensions/TabSelectionExtension", 12 | "gif": "extension.gif", 13 | "includeinlist":"true", 14 | "externaldependencies":[] 15 | } -------------------------------------------------------------------------------- /public/extensions/TabSelectionExtension/contents/main.js: -------------------------------------------------------------------------------- 1 | class TabSelectionExtension extends Autodesk.Viewing.Extension { 2 | constructor(viewer, options) { 3 | super(viewer, options); 4 | this.viewer = viewer; 5 | this.keyDownEventBinder = this.keyDownEvent.bind(this); 6 | this.selectionChangedEventBinder = this.selectionChangedEvent.bind(this); 7 | this.initialSelection = []; 8 | } 9 | 10 | load() { 11 | // track tabs on the document level 12 | document.addEventListener('keydown', this.keyDownEventBinder); 13 | // and viewer selection event 14 | this.viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, this.selectionChangedEventBinder); 15 | return true; 16 | } 17 | 18 | unload() { 19 | document.removeEventListener('keydown', this.keyDownEventBinder); 20 | this.viewer.removeEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, this.selectionChangedEventBinder); 21 | return true; 22 | } 23 | 24 | keyDownEvent(e) { 25 | // key to track 26 | let rotateKey = 9; // TAB 27 | if (e.keyCode == rotateKey) { 28 | // just start the rotate if something is select 29 | if (this.viewer.getSelectionCount() > 0) { 30 | // prevent the default TAB behavior 31 | e.preventDefault(); 32 | this.rotate(); 33 | } 34 | } 35 | } 36 | 37 | selectionChangedEvent() { 38 | // clear the initial selection if user unselect 39 | if (this.viewer.getSelectionCount() === 0) this.initialSelection = []; 40 | } 41 | 42 | rotate() { 43 | // get current selection 44 | let dbIds = this.viewer.getSelection(); 45 | // if first time, let's store the initial dbId 46 | if (this.initialSelection.length == 0) this.initialSelection = dbIds; 47 | // this gives the model tree 48 | let tree = this.viewer.model.getInstanceTree(); 49 | // prepare to store the parent nodes 50 | let newSelection = []; 51 | // let's check the selection... 52 | dbIds.forEach(dbId => { 53 | // get the parent of each selected dbId 54 | let parentId = tree.getNodeParentId(dbId); 55 | // if we reach the root, stop 56 | if (parentId === tree.getRootId()) return; 57 | // store the parent for selection 58 | newSelection.push(parentId); 59 | }); 60 | // any parent to select? 61 | if (newSelection.length > 0) 62 | this.viewer.select(newSelection); 63 | else { 64 | // otherwise return to the initial selection 65 | this.viewer.select(this.initialSelection); 66 | this.initialSelection = []; 67 | } 68 | } 69 | } 70 | 71 | Autodesk.Viewing.theExtensionManager.registerExtension('TabSelectionExtension', TabSelectionExtension); -------------------------------------------------------------------------------- /public/extensions/TabSelectionExtension/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/TabSelectionExtension/extension.gif -------------------------------------------------------------------------------- /public/extensions/TransformationExtension/README.md: -------------------------------------------------------------------------------- 1 | # Transform 2 | 3 | [Demo](https://forge-extensions.autodesk.io/?extension=TransformationExtension) 4 | 5 | Allows moving elements on the model. 6 | 7 | ![thumbnail](extension.gif) 8 | 9 | ## Usage 10 | 11 | Enable the extension, click on the model element, use the `gizmo` to move the element. 12 | 13 | ## Setup 14 | 15 | Include the CSS & JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 16 | 17 | ```xml 18 | 19 | 20 | ``` 21 | 22 | After Viewer is ready, preferable inside `onDocumentLoadSuccess`, load the extension 23 | 24 | ```javascript 25 | viewer.loadExtension("TransformationExtension") 26 | ``` 27 | 28 | ## How it works 29 | 30 | Based on the Three.js [transform control](https://threejs.org/examples/misc_controls_transform.html), the development team implemented the section command using this nice 3d manipulator allowing to select plane, axis and rotation. This is provided out of the box with the [GuiViewer3D](https://forge.autodesk.com/en/docs/viewer/v7/reference/Viewing/GuiViewer3D/) 31 | 32 | Reusing some of their implementation to provide the ability to stick the control on the selected mesh and drag it around. It's more challenging that it may seem as the viewer has a complex way to work with Three.js meshes. This is due to enhancements that we created on top of that library to be able to support models with a huge number of meshes. 33 | -------------------------------------------------------------------------------- /public/extensions/TransformationExtension/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"TransformationExtension", 3 | "displayname": "Transformation", 4 | "description":"Pupose of this extension is to select an element and move or transform it in any direction.", 5 | "options":{}, 6 | "loadonstartup": "false", 7 | "filestoload":{ 8 | "jsfiles":["main.js"], 9 | "cssfiles": [] 10 | }, 11 | "gif": "extension.gif", 12 | "includeinlist":"true", 13 | "externaldependencies":[ 14 | {"type": "css", "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css"} 15 | ] 16 | } -------------------------------------------------------------------------------- /public/extensions/TransformationExtension/extension.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/TransformationExtension/extension.gif -------------------------------------------------------------------------------- /public/extensions/XLSExtension/README.md: -------------------------------------------------------------------------------- 1 | # XLS Extension 2 | 3 | This extension demonstrates how to extract metadata and export it as excel file 4 | 5 | [Demo](https://forge-extensions.autodesk.io/?extension=XLSExtension) 6 | 7 | ![thumbnail](extension.jpg) 8 | 9 | ## Usage 10 | 11 | Load the extension and click on excel icon on toolbar. 12 | 13 | ## Setup 14 | 15 | Include the CSS & JS file on your page. This CDN is compatible with the lastest Viewer version (v7). 16 | 17 | ```xml 18 | 19 | 20 | ``` 21 | 22 | ## External Dependencies 23 | 24 | This sample uses [SheetJS](https://github.com/SheetJS/js-xlsx) and [FileSaver](https://github.com/eligrey/FileSaver.js) as main dependencies. [Notifier](https://notifyjs.jpillora.com/) is a secondary or non-core dependency. 25 | 26 | 27 | -------------------------------------------------------------------------------- /public/extensions/XLSExtension/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"XLSExtension", 3 | "displayname": "XLS Extension", 4 | "description": "Download properties in excel file.", 5 | "options":{}, 6 | "viewerversion":"7.*", 7 | "loadonstartup": "false", 8 | "filestoload":{ 9 | "cssfiles":["main.css"], 10 | "jsfiles":["main.js","ForgeXLS.js","modeldata.js"] 11 | }, 12 | "includeinlist":"true", 13 | "externaldependencies":[ 14 | {"type": "js", "link": "https://github.com/eligrey/Blob.js"}, 15 | {"type": "js", "link": "https://github.com/eligrey/FileSaver.js"}, 16 | {"type": "js", "link": "https://github.com/SheetJS/js-xlsx"} 17 | ] 18 | } -------------------------------------------------------------------------------- /public/extensions/XLSExtension/contents/ForgeXLS.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | if (!window.XLSX) alert('Sheet JS is required for this sample'); 20 | 21 | let ForgeXLS = { 22 | 23 | downloadXLSX: function (fileName, status) { 24 | 25 | if (status) { 26 | status(false, 'Preparing ' + fileName); 27 | status(false, 'Reading project information....'); 28 | } 29 | 30 | this.prepareTables(function (tables) { 31 | if (status) status(false, 'Building XLSX file...'); 32 | 33 | let wb = new Workbook(); 34 | for (const [name, table] of Object.entries(tables)){ 35 | if (name.indexOf('<')==-1) { // skip tables starting with < 36 | let ws = ForgeXLS.sheetFromTable(table); 37 | wb.SheetNames.push(name); 38 | wb.Sheets[name] = ws; 39 | } 40 | }; 41 | 42 | let wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: true, type: 'binary'}); 43 | saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), fileName); 44 | 45 | if (status) status(true, 'Downloading...'); 46 | }) 47 | }, 48 | 49 | sheetFromTable: function (table) { 50 | let ws = {}; 51 | let range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}}; 52 | 53 | let allProperties = []; 54 | table.forEach(function (object) { 55 | for (const [propName, propValue] of Object.entries(object)){ 56 | if (allProperties.indexOf(propName) == -1) 57 | allProperties.push(propName); 58 | } 59 | }); 60 | 61 | table.forEach(function (object) { 62 | allProperties.forEach(function (propName) { 63 | if (!object.hasOwnProperty(propName)) 64 | object[propName] = ''; 65 | }); 66 | }); 67 | 68 | let propsNames = []; 69 | for (let propName in table[0]) { 70 | propsNames.push(propName); 71 | } 72 | //propsNames.sort(); // removed due first 3 ID columns 73 | 74 | let R = 0; 75 | let C = 0; 76 | for (; C != propsNames.length; ++C) { 77 | let cell_ref = XLSX.utils.encode_cell({c: C, r: R}); 78 | ws[cell_ref] = {v: propsNames[C], t: 's'}; 79 | } 80 | R++; 81 | 82 | for (let index = 0; index != table.length; ++index) { 83 | C = 0; 84 | propsNames.forEach(function (propName) { 85 | if (range.s.r > R) range.s.r = 0; 86 | if (range.s.c > C) range.s.c = 0; 87 | if (range.e.r < R) range.e.r = R; 88 | if (range.e.c < C) range.e.c = C; 89 | let cell = {v: table[index][propName]}; 90 | if (cell.v == null) return; 91 | let cell_ref = XLSX.utils.encode_cell({c: C, r: R}); 92 | 93 | if (typeof cell.v === 'number') cell.t = 'n'; 94 | else if (typeof cell.v === 'boolean') cell.t = 'b'; 95 | else if (cell.v instanceof Date) { 96 | cell.t = 'n'; 97 | cell.z = XLSX.SSF._table[14]; 98 | cell.v = datenum(cell.v); 99 | } 100 | else cell.t = 's'; 101 | 102 | ws[cell_ref] = cell; 103 | C++; 104 | }); 105 | R++; 106 | } 107 | if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range); 108 | return ws; 109 | }, 110 | 111 | prepareTables: function (callback) { 112 | let data = new ModelData(this); 113 | data.init(async function () { 114 | let hierarchy = data._modelData.Category; 115 | let t = await ForgeXLS.prepareRawData(hierarchy); 116 | callback(t); 117 | }); 118 | }, 119 | 120 | prepareRawData: async function (hierarchy) { 121 | let tables = {}; 122 | for (let key in hierarchy) { 123 | let idsOnCategory = []; 124 | if (hierarchy.hasOwnProperty(key)) { 125 | idsOnCategory = hierarchy[key]; 126 | let rows = await getAllProperties(idsOnCategory); 127 | tables[key] = formatRows(rows); 128 | } 129 | } 130 | return tables;; 131 | } 132 | }; 133 | 134 | // Get Properties by dbid 135 | async function getProperties(model, dbid) { 136 | return new Promise(function(resolve, reject) { 137 | model.getProperties(dbid, function (props) { 138 | resolve(props); 139 | }); 140 | }); 141 | } 142 | 143 | // Get Properties by Category 144 | async function getAllProperties(idsOnCategory) { 145 | return new Promise(function(resolve, reject) { 146 | let promises = []; 147 | idsOnCategory.forEach(function (dbid) { 148 | promises.push(getProperties(NOP_VIEWER.model, dbid)); 149 | }); 150 | resolve(Promise.all(promises)); 151 | }); 152 | } 153 | 154 | // Helper Functions 155 | function Workbook() { 156 | if (!(this instanceof Workbook)) return new Workbook(); 157 | this.SheetNames = []; 158 | this.Sheets = {}; 159 | } 160 | 161 | function datenum(v, date1904) { 162 | if (date1904) v += 1462; 163 | let epoch = Date.parse(v); 164 | return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); 165 | } 166 | 167 | function s2ab(s) { 168 | let buf = new ArrayBuffer(s.length); 169 | let view = new Uint8Array(buf); 170 | for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; 171 | return buf; 172 | } 173 | 174 | function formatRows(sheets) { 175 | sheets.forEach(sheet => { 176 | let props = sheet.properties 177 | props.forEach(prop =>{ 178 | sheet[prop.displayName] = prop.displayValue 179 | }) 180 | delete sheet.properties 181 | }); 182 | return sheets; 183 | } -------------------------------------------------------------------------------- /public/extensions/XLSExtension/contents/img/excel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/XLSExtension/contents/img/excel.png -------------------------------------------------------------------------------- /public/extensions/XLSExtension/contents/libraries/Blob.js: -------------------------------------------------------------------------------- 1 | /* Blob.js 2 | * A Blob implementation. 3 | * 2014-07-24 4 | * 5 | * By Eli Grey, http://eligrey.com 6 | * By Devin Samarin, https://github.com/dsamarin 7 | * License: MIT 8 | * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md 9 | */ 10 | 11 | /*global self, unescape */ 12 | /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, 13 | plusplus: true */ 14 | 15 | /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ 16 | 17 | (function (view) { 18 | "use strict"; 19 | 20 | view.URL = view.URL || view.webkitURL; 21 | 22 | if (view.Blob && view.URL) { 23 | try { 24 | new Blob; 25 | return; 26 | } catch (e) {} 27 | } 28 | 29 | // Internally we use a BlobBuilder implementation to base Blob off of 30 | // in order to support older browsers that only have BlobBuilder 31 | var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) { 32 | var 33 | get_class = function(object) { 34 | return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; 35 | } 36 | , FakeBlobBuilder = function BlobBuilder() { 37 | this.data = []; 38 | } 39 | , FakeBlob = function Blob(data, type, encoding) { 40 | this.data = data; 41 | this.size = data.length; 42 | this.type = type; 43 | this.encoding = encoding; 44 | } 45 | , FBB_proto = FakeBlobBuilder.prototype 46 | , FB_proto = FakeBlob.prototype 47 | , FileReaderSync = view.FileReaderSync 48 | , FileException = function(type) { 49 | this.code = this[this.name = type]; 50 | } 51 | , file_ex_codes = ( 52 | "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " 53 | + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" 54 | ).split(" ") 55 | , file_ex_code = file_ex_codes.length 56 | , real_URL = view.URL || view.webkitURL || view 57 | , real_create_object_URL = real_URL.createObjectURL 58 | , real_revoke_object_URL = real_URL.revokeObjectURL 59 | , URL = real_URL 60 | , btoa = view.btoa 61 | , atob = view.atob 62 | 63 | , ArrayBuffer = view.ArrayBuffer 64 | , Uint8Array = view.Uint8Array 65 | 66 | , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/ 67 | ; 68 | FakeBlob.fake = FB_proto.fake = true; 69 | while (file_ex_code--) { 70 | FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; 71 | } 72 | // Polyfill URL 73 | if (!real_URL.createObjectURL) { 74 | URL = view.URL = function(uri) { 75 | var 76 | uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a") 77 | , uri_origin 78 | ; 79 | uri_info.href = uri; 80 | if (!("origin" in uri_info)) { 81 | if (uri_info.protocol.toLowerCase() === "data:") { 82 | uri_info.origin = null; 83 | } else { 84 | uri_origin = uri.match(origin); 85 | uri_info.origin = uri_origin && uri_origin[1]; 86 | } 87 | } 88 | return uri_info; 89 | }; 90 | } 91 | URL.createObjectURL = function(blob) { 92 | var 93 | type = blob.type 94 | , data_URI_header 95 | ; 96 | if (type === null) { 97 | type = "application/octet-stream"; 98 | } 99 | if (blob instanceof FakeBlob) { 100 | data_URI_header = "data:" + type; 101 | if (blob.encoding === "base64") { 102 | return data_URI_header + ";base64," + blob.data; 103 | } else if (blob.encoding === "URI") { 104 | return data_URI_header + "," + decodeURIComponent(blob.data); 105 | } if (btoa) { 106 | return data_URI_header + ";base64," + btoa(blob.data); 107 | } else { 108 | return data_URI_header + "," + encodeURIComponent(blob.data); 109 | } 110 | } else if (real_create_object_URL) { 111 | return real_create_object_URL.call(real_URL, blob); 112 | } 113 | }; 114 | URL.revokeObjectURL = function(object_URL) { 115 | if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { 116 | real_revoke_object_URL.call(real_URL, object_URL); 117 | } 118 | }; 119 | FBB_proto.append = function(data/*, endings*/) { 120 | var bb = this.data; 121 | // decode data to a binary string 122 | if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { 123 | var 124 | str = "" 125 | , buf = new Uint8Array(data) 126 | , i = 0 127 | , buf_len = buf.length 128 | ; 129 | for (; i < buf_len; i++) { 130 | str += String.fromCharCode(buf[i]); 131 | } 132 | bb.push(str); 133 | } else if (get_class(data) === "Blob" || get_class(data) === "File") { 134 | if (FileReaderSync) { 135 | var fr = new FileReaderSync; 136 | bb.push(fr.readAsBinaryString(data)); 137 | } else { 138 | // async FileReader won't work as BlobBuilder is sync 139 | throw new FileException("NOT_READABLE_ERR"); 140 | } 141 | } else if (data instanceof FakeBlob) { 142 | if (data.encoding === "base64" && atob) { 143 | bb.push(atob(data.data)); 144 | } else if (data.encoding === "URI") { 145 | bb.push(decodeURIComponent(data.data)); 146 | } else if (data.encoding === "raw") { 147 | bb.push(data.data); 148 | } 149 | } else { 150 | if (typeof data !== "string") { 151 | data += ""; // convert unsupported types to strings 152 | } 153 | // decode UTF-16 to binary string 154 | bb.push(unescape(encodeURIComponent(data))); 155 | } 156 | }; 157 | FBB_proto.getBlob = function(type) { 158 | if (!arguments.length) { 159 | type = null; 160 | } 161 | return new FakeBlob(this.data.join(""), type, "raw"); 162 | }; 163 | FBB_proto.toString = function() { 164 | return "[object BlobBuilder]"; 165 | }; 166 | FB_proto.slice = function(start, end, type) { 167 | var args = arguments.length; 168 | if (args < 3) { 169 | type = null; 170 | } 171 | return new FakeBlob( 172 | this.data.slice(start, args > 1 ? end : this.data.length) 173 | , type 174 | , this.encoding 175 | ); 176 | }; 177 | FB_proto.toString = function() { 178 | return "[object Blob]"; 179 | }; 180 | FB_proto.close = function() { 181 | this.size = 0; 182 | delete this.data; 183 | }; 184 | return FakeBlobBuilder; 185 | }(view)); 186 | 187 | view.Blob = function(blobParts, options) { 188 | var type = options ? (options.type || "") : ""; 189 | var builder = new BlobBuilder(); 190 | if (blobParts) { 191 | for (var i = 0, len = blobParts.length; i < len; i++) { 192 | if (Uint8Array && blobParts[i] instanceof Uint8Array) { 193 | builder.append(blobParts[i].buffer); 194 | } 195 | else { 196 | builder.append(blobParts[i]); 197 | } 198 | } 199 | } 200 | var blob = builder.getBlob(type); 201 | if (!blob.slice && blob.webkitSlice) { 202 | blob.slice = blob.webkitSlice; 203 | } 204 | return blob; 205 | }; 206 | 207 | var getPrototypeOf = Object.getPrototypeOf || function(object) { 208 | return object.__proto__; 209 | }; 210 | view.Blob.prototype = getPrototypeOf(new view.Blob()); 211 | }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); 212 | -------------------------------------------------------------------------------- /public/extensions/XLSExtension/contents/libraries/FileSaver.min.js: -------------------------------------------------------------------------------- 1 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 2 | var saveAs=saveAs||function(e){"use strict";if(typeof e==="undefined"||typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,a=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},i=/constructor/i.test(e.HTMLElement)||e.safari,f=/CriOS\/[\d]+/.test(navigator.userAgent),u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s="application/octet-stream",d=1e3*40,c=function(e){var t=function(){if(typeof e==="string"){n().revokeObjectURL(e)}else{e.remove()}};setTimeout(t,d)},l=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var o=e["on"+t[r]];if(typeof o==="function"){try{o.call(e,n||e)}catch(a){u(a)}}}},p=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob([String.fromCharCode(65279),e],{type:e.type})}return e},v=function(t,u,d){if(!d){t=p(t)}var v=this,w=t.type,m=w===s,y,h=function(){l(v,"writestart progress write writeend".split(" "))},S=function(){if((f||m&&i)&&e.FileReader){var r=new FileReader;r.onloadend=function(){var t=f?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");var n=e.open(t,"_blank");if(!n)e.location.href=t;t=undefined;v.readyState=v.DONE;h()};r.readAsDataURL(t);v.readyState=v.INIT;return}if(!y){y=n().createObjectURL(t)}if(m){e.location.href=y}else{var o=e.open(y,"_blank");if(!o){e.location.href=y}}v.readyState=v.DONE;h();c(y)};v.readyState=v.INIT;if(o){y=n().createObjectURL(t);setTimeout(function(){r.href=y;r.download=u;a(r);h();c(y);v.readyState=v.DONE});return}S()},w=v.prototype,m=function(e,t,n){return new v(e,t||e.name||"download",n)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(e,t,n){t=t||e.name||"download";if(!n){e=p(e)}return navigator.msSaveOrOpenBlob(e,t)}}w.abort=function(){};w.readyState=w.INIT=0;w.WRITING=1;w.DONE=2;w.error=w.onwritestart=w.onprogress=w.onwrite=w.onabort=w.onerror=w.onwriteend=null;return m}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!==null){define("FileSaver.js",function(){return saveAs})} 3 | -------------------------------------------------------------------------------- /public/extensions/XLSExtension/contents/main.css: -------------------------------------------------------------------------------- 1 | .toolbarXLSButton { 2 | background-image: url(img/excel.png); 3 | background-size: 16px; 4 | background-repeat: no-repeat; 5 | background-position: center; 6 | } -------------------------------------------------------------------------------- /public/extensions/XLSExtension/contents/main.js: -------------------------------------------------------------------------------- 1 | class XLSExtension extends Autodesk.Viewing.Extension { 2 | constructor(viewer, options) { 3 | super(viewer, options); 4 | this._group = null; 5 | this._button = null; 6 | } 7 | 8 | load() { 9 | return true; 10 | } 11 | 12 | unload() { 13 | // Clean our UI elements if we added any 14 | if (this._group) { 15 | this._group.removeControl(this._button); 16 | if (this._group.getNumberOfControls() === 0) { 17 | this.viewer.toolbar.removeControl(this._group); 18 | } 19 | } 20 | console.log('MyAwesomeExtensions has been unloaded'); 21 | return true; 22 | } 23 | 24 | onToolbarCreated() { 25 | // Button 1 26 | var button1 = new Autodesk.Viewing.UI.Button('toolbarXLS'); 27 | button1.onClick = function (e) { 28 | ForgeXLS.downloadXLSX(fileName.replace(/\./g, '') + ".xlsx", statusCallback );/*Optional*/ 29 | }; 30 | button1.addClass('toolbarXLSButton'); 31 | button1.setToolTip('Export to .XLSX'); 32 | 33 | // SubToolbar 34 | this.subToolbar = new Autodesk.Viewing.UI.ControlGroup('myAppGroup1'); 35 | this.subToolbar.addControl(button1); 36 | 37 | this.viewer.toolbar.addControl(this.subToolbar); 38 | } 39 | 40 | } 41 | let statusCallback = function(completed, message) { 42 | $.notify(message, { className: "info", position:"bottom right" }); 43 | $('#downloadExcel').prop("disabled", !completed); 44 | } 45 | 46 | Autodesk.Viewing.theExtensionManager.registerExtension('XLSExtension', XLSExtension); 47 | -------------------------------------------------------------------------------- /public/extensions/XLSExtension/contents/modeldata.js: -------------------------------------------------------------------------------- 1 | 2 | // Model data in format for charts 3 | class ModelData { 4 | constructor(viewer) { 5 | this._modelData = {}; 6 | this._viewer = viewer; 7 | } 8 | 9 | init(callback) { 10 | var _this = this; 11 | 12 | _this.getAllLeafComponents(function (dbIds) { 13 | var count = dbIds.length; 14 | dbIds.forEach(function (dbId) { 15 | viewer.getProperties(dbId, function (props) { 16 | props.properties.forEach(function (prop) { 17 | if (!isNaN(prop.displayValue)) return; // let's not categorize properties that store numbers 18 | 19 | // some adjustments for revit: 20 | prop.displayValue = prop.displayValue.replace('Revit ', ''); // remove this Revit prefix 21 | if (prop.displayValue.indexOf('<') == 0) return; // skip categories that start with < 22 | 23 | // ok, now let's organize the data into this hash table 24 | if (_this._modelData[prop.displayName] == null) _this._modelData[prop.displayName] = {}; 25 | if (_this._modelData[prop.displayName][prop.displayValue] == null) _this._modelData[prop.displayName][prop.displayValue] = []; 26 | _this._modelData[prop.displayName][prop.displayValue].push(dbId); 27 | }) 28 | if ((--count) == 0) callback(); 29 | }); 30 | }) 31 | }) 32 | } 33 | 34 | getAllLeafComponents(callback) { 35 | // from https://learnforge.autodesk.io/#/viewer/extensions/panel?id=enumerate-leaf-nodes 36 | viewer.getObjectTree(function (tree) { 37 | var leaves = []; 38 | tree.enumNodeChildren(tree.getRootId(), function (dbId) { 39 | if (tree.getChildCount(dbId) === 0) { 40 | leaves.push(dbId); 41 | } 42 | }, true); 43 | callback(leaves); 44 | }); 45 | } 46 | 47 | hasProperty(propertyName){ 48 | return (this._modelData[propertyName] !== undefined); 49 | } 50 | 51 | getLabels(propertyName) { 52 | return Object.keys(this._modelData[propertyName]); 53 | } 54 | 55 | getCountInstances(propertyName) { 56 | return Object.keys(this._modelData[propertyName]).map(key => this._modelData[propertyName][key].length); 57 | } 58 | 59 | getIds(propertyName, propertyValue) { 60 | return this._modelData[propertyName][propertyValue]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /public/extensions/XLSExtension/extension.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/extensions/XLSExtension/extension.jpg -------------------------------------------------------------------------------- /public/extensions/config.json: -------------------------------------------------------------------------------- 1 | {"Extensions":[{"name":"BasicSkeleton","displayname":"Basic Skeleton","description":"Basic Skeleton of an extension, can be used as boilerplate code.","options":{},"viewerversion":"7.*","loadonstartup":"false","filestoload":{"cssfiles":["main.css"],"jsfiles":["main.js"]},"includeinlist":"false"},{"name":"CameraRotation","displayname":"Camera Rotation","description":"Rotates the model continously untill stopped, can be used for demoing a large model.","options":{},"loadonstartup":"false","filestoload":{"cssfiles":["main.css"],"jsfiles":["main.js"]},"gif":"extension.gif","includeinlist":"true"},{"name":"CustomPropertiesExtension","displayname":"Custom Properties","description":"Custom Properties example, info provided in config is showed in Properties palette based on selected object's dbId.","options":{"properties":{"1":{"My Group":{"My Property":"My Property Value","My Second Property":"My Second Property Value"}},"3":{"My Other Group":{"My Other Property":"My Other Property Value"}}}},"editoptions":"true","viewerversion":"7.*","loadonstartup":"false","filestoload":{"cssfiles":[],"jsfiles":["main.js"]},"bloglink":"https://github.com/autodesk-forge/forge-extensions/tree/master/public/extensions/CustomPropertiesExtension","includeinlist":"true","gif":"extension.gif","externaldependencies":[]},{"name":"DrawToolExtension","displayname":"Draw Tool","description":"A simple tool that will allow us to draw boxes and spheres.","options":{},"editoptions":"true","viewerversion":"7.*","loadonstartup":"false","filestoload":{"cssfiles":["main.css"],"jsfiles":["main.js"]},"bloglink":"https://forge.autodesk.com/blog/custom-tools-forge-viewer","includeinlist":"true","gif":"extension.gif"},{"name":"GoogleMapsLocator","displayname":"GoogleMapsLocator","description":"Show location of model on google maps.","options":{"lattitude":0,"longitude":0},"editoptions":"true","viewerversion":"7.*","loadonstartup":"false","filestoload":{"cssfiles":["main.css"],"jsfiles":["main.js"]},"includeinlist":"true","gif":"extension.gif","externaldependencies":[{"type":"css","link":"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css"},{"type":"js","link":"https://maps.googleapis.com/maps/api/js?key="}]},{"name":"IconMarkupExtension","displayname":"Icon Markups","description":"Markups example, based on options provided in config, info is showed on particular object referring dbid.","options":{"icons":[{"dbId":9256,"label":"30°C","css":"fas fa-thermometer-full"},{"dbId":920,"label":"35°C","css":"fas fa-thermometer-full"},{"dbId":1626,"label":"45°C","css":"fas fa-thermometer-empty"}],"button":{"icon":"fa-thermometer-half","tooltip":"Show Temperature"}},"editoptions":"true","viewerversion":"7.*","loadonstartup":"false","filestoload":{"cssfiles":["main.css"],"jsfiles":["main.js"]},"bloglink":"https://github.com/autodesk-forge/forge-extensions/tree/master/public/extensions/IconMarkupExtension","includeinlist":"true","gif":"extension.gif","externaldependencies":[{"type":"css","link":"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css"}]},{"name":"NestedViewerExtension","displayname":"Viewer in Viewer","description":"Nested viewer where viewables related to the currently loaded model can be viewed.","options":{"filter":["2d","3d"],"crossSelection":true},"editoptions":"true","viewerversion":"7.*","loadonstartup":"false","filestoload":{"cssfiles":["main.css"],"jsfiles":["main.js"]},"gif":"extension.gif","includeinlist":"true","bloglink":"https://github.com/autodesk-forge/forge-extensions/tree/master/public/extensions/NestedViewerExtension/README.md"},{"name":"PotreeExtension","displayname":"Potree Point Clouds","description":"Forge Viewer extension for loading and rendering Potree point clouds.","options":{"url":"/extensions/PotreeExtension/contents/data/lion_takanawa/cloud.js","position":[0,0,0],"scale":[5,5,5]},"editoptions":"true","viewerversion":"7.*","loadonstartup":"false","filestoload":{"cssfiles":[],"jsfiles":["potree.js","PotreeExtension.js"]},"gif":"extension.gif","includeinlist":"true","bloglink":""},{"name":"TabSelectionExtension","displayname":"Tab selection","description":"Use TAB to rotate selection based on the model tree. For Revit files, it mimics the nested family selection.","options":{},"loadonstartup":"false","filestoload":{"jsfiles":["main.js"],"cssfiles":[]},"bloglink":"https://github.com/autodesk-forge/forge-extensions/tree/master/public/extensions/TabSelectionExtension","gif":"extension.gif","includeinlist":"true","externaldependencies":[]},{"name":"TransformationExtension","displayname":"Transformation","description":"Pupose of this extension is to select an element and move or transform it in any direction.","options":{},"loadonstartup":"false","filestoload":{"jsfiles":["main.js"],"cssfiles":[]},"gif":"extension.gif","includeinlist":"true","externaldependencies":[{"type":"css","link":"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css"}]},{"name":"XLSExtension","displayname":"XLS Extension","description":"Download properties in excel file.","options":{},"viewerversion":"7.*","loadonstartup":"false","filestoload":{"cssfiles":["main.css"],"jsfiles":["main.js","ForgeXLS.js","modeldata.js"]},"includeinlist":"true","externaldependencies":[{"type":"js","link":"https://github.com/eligrey/Blob.js"},{"type":"js","link":"https://github.com/eligrey/FileSaver.js"},{"type":"js","link":"https://github.com/SheetJS/js-xlsx"}]}],"ListConfig":{"CreateList":"true","ListId":"extensionlist"},"InbuiltExtensions":[{"name":"Autodesk.Fusion360.Animation","default":"false","includeinlist":"false"},{"name":"Autodesk.Section","default":"true"},{"name":"Autodesk.DefaultTools.NavTools","default":"true"},{"name":"Autodesk.Hyperlink","default":"false","includeinlist":"false"},{"name":"Autodesk.Measure","default":"true"},{"name":"Autodesk.Viewing.FusionOrbit","default":"false"},{"name":"Autodesk.BimWalk","default":"true"},{"name":"Autodesk.GoHome","default":"false","includeinlist":"false"},{"name":"Autodesk.Explode","default":"true"},{"name":"Autodesk.FullScreen","default":"true"},{"name":"Autodesk.LayerManager","default":"false","includeinlist":"false"},{"name":"Autodesk.ModelStructure","default":"true"},{"name":"Autodesk.PropertiesManager","default":"true"},{"name":"Autodesk.ViewerSettings","default":"false","includeinlist":"false"},{"name":"Autodesk.Viewing.Wireframes","default":"false","includeinlist":"false"},{"name":"Autodesk.Viewing.ZoomWindow","default":"false"},{"name":"Autodesk.SplitScreen","default":"false"},{"name":"Autodesk.PDF","default":"false","includeinlist":"false"},{"name":"Autodesk.DocumentBrowser","default":"false"},{"name":"Autodesk.Geolocation","default":"false","includeinlist":"false"},{"name":"Autodesk.CrossFadeEffects","default":"false","includeinlist":"false"},{"name":"Autodesk.Edit2D","default":"false","includeinlist":"false"},{"name":"Autodesk.ViewCubeUi","default":"true"},{"name":"Autodesk.BIM360.Minimap","default":"false"},{"name":"Autodesk.BIM360.GestureDocumentNavigation","default":"false","includeinlist":"false"},{"name":"Autodesk.BIM360.RollCamera","default":"false","includeinlist":"false"},{"name":"Autodesk.Viewing.SceneBuilder","default":"false","includeinlist":"false"},{"name":"Autodesk.Snapping","default":"false"},{"name":"Autodesk.Viewing.Popout","default":"false","includeinlist":"false"},{"name":"Autodesk.VisualClusters","default":"false"},{"name":"Autodesk.AEC.LevelsExtension","default":"false","includeinlist":"false"}],"InbuiltExtensionsConfig":{"CreateList":"true","ListId":"inbuiltextensionlist"}} -------------------------------------------------------------------------------- /public/extensions/extensionloader.css: -------------------------------------------------------------------------------- 1 | #extensionlist{padding: 10px 0px;} 2 | .tobegin{position: absolute;font-size: 20px;opacity: 0.5;top: 15%;left: 5%;} 3 | .extensions-heading{margin-top: 0;} 4 | .popover{min-width: 520px !important;max-width: 520px !important;} 5 | #editextensionconfig{height: 200px;} 6 | #learnmore{float: left;} 7 | #saveconfig{background: #5cb85c;color: white;} 8 | -------------------------------------------------------------------------------- /public/img/GitHub_Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/public/img/GitHub_Logo.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Forge Extensions 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 56 | 57 |
58 |
59 |
60 |
61 |
62 | Sample Models 63 | 64 |
65 | 68 |
69 | tree here 70 |
71 |
72 |
73 |
74 |
  Select a model to load viewer and extensions
75 |
76 |
77 |
78 | 79 |
80 |

Extensions

81 | 82 | 86 | 87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | 97 |
98 |
99 |
100 |
101 | 102 |
103 | 104 | 128 | 129 | 130 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /public/js/ForgeTree.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | $(document).ready(function () { 20 | prepareAppBucketTree(); 21 | $('#refreshBuckets').click(function () { 22 | $('#appBuckets').jstree(true).refresh(); 23 | }); 24 | 25 | $('#createNewBucket').click(function () { 26 | createNewBucket(); 27 | }); 28 | 29 | $('#createBucketModal').on('shown.bs.modal', function () { 30 | $("#newBucketKey").focus(); 31 | }) 32 | 33 | $('#hiddenUploadField').change(function () { 34 | var node = $('#appBuckets').jstree(true).get_selected(true)[0]; 35 | var _this = this; 36 | if (_this.files.length == 0) return; 37 | var file = _this.files[0]; 38 | switch (node.type) { 39 | case 'bucket': 40 | var formData = new FormData(); 41 | formData.append('fileToUpload', file); 42 | formData.append('bucketKey', node.id); 43 | 44 | $.ajax({ 45 | url: '/api/forge/oss/upload', 46 | data: formData, 47 | processData: false, 48 | contentType: false, 49 | type: 'POST', 50 | success: function (data) { 51 | $('#appBuckets').jstree(true).refresh_node(node); 52 | _this.value = ''; 53 | } 54 | }); 55 | break; 56 | } 57 | }); 58 | }); 59 | 60 | function createNewBucket() { 61 | var bucketKey = $('#newBucketKey').val(); 62 | var policyKey = $('#newBucketPolicyKey').val(); 63 | jQuery.post({ 64 | url: '/api/forge/oss/buckets', 65 | contentType: 'application/json', 66 | data: JSON.stringify({ 'bucketKey': bucketKey, 'policyKey': policyKey }), 67 | success: function (res) { 68 | $('#appBuckets').jstree(true).refresh(); 69 | $('#createBucketModal').modal('toggle'); 70 | }, 71 | error: function (err) { 72 | if (err.status == 409) 73 | alert('Bucket already exists - 409: Duplicated') 74 | console.log(err); 75 | } 76 | }); 77 | } 78 | var extensionloaded = false; 79 | function prepareAppBucketTree() { 80 | $('#appBuckets').jstree({ 81 | 'core': { 82 | 'themes': { "icons": true }, 83 | 'data': { 84 | "url": '/api/forge/oss/buckets', 85 | "dataType": "json", 86 | 'multiple': false, 87 | "data": function (node) { 88 | return { "id": node.id }; 89 | } 90 | } 91 | }, 92 | 'types': { 93 | 'default': { 94 | 'icon': 'glyphicon glyphicon-question-sign' 95 | }, 96 | '#': { 97 | 'icon': 'glyphicon glyphicon-cloud' 98 | }, 99 | 'bucket': { 100 | 'icon': 'glyphicon glyphicon-folder-open' 101 | }, 102 | 'object': { 103 | 'icon': 'glyphicon glyphicon-file' 104 | } 105 | }, 106 | "plugins": ["types", "state", "sort", "contextmenu"], 107 | contextmenu: { items: autodeskCustomMenu } 108 | }).on('loaded.jstree', function () { 109 | $('#appBuckets').jstree('open_all'); 110 | }).bind("activate_node.jstree", function (evt, data) { 111 | if (data != null && data.node != null && data.node.type == 'object') { 112 | $("#forgeViewer").empty(); 113 | var urn = data.node.id; 114 | var filename = data.node.text 115 | document.getElementsByClassName('tobegin')[0].style.display = 'none'; 116 | getForgeToken(function (access_token) { 117 | jQuery.ajax({ 118 | url: 'https://developer.api.autodesk.com/modelderivative/v2/designdata/' + urn + '/manifest', 119 | headers: { 'Authorization': 'Bearer ' + access_token }, 120 | success: function (res) { 121 | if (res.progress === 'success' || res.progress === 'complete') launchViewer(urn,filename); 122 | else $("#forgeViewer").html('The translation job still running: ' + res.progress + '. Please try again in a moment.'); 123 | }, 124 | error: function (err) { 125 | var msgButton = 'This file is not translated yet! ' + 126 | '' 128 | $("#forgeViewer").html(msgButton); 129 | } 130 | }); 131 | }) 132 | } 133 | }).on('ready.jstree', function () { 134 | if (!extensionloaded) { 135 | const queryString = window.location.search; 136 | const urlParams = new URLSearchParams(queryString); 137 | let extension = urlParams.get('extension'); 138 | if (extension) { 139 | document.getElementById('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6c2FtcGxlbW9kZWxzL09mZmljZS5ydnQ=_anchor').click(); 140 | window.extension = extension; 141 | } 142 | extensionloaded = true; 143 | } 144 | }); 145 | } 146 | 147 | function autodeskCustomMenu(autodeskNode) { 148 | var items; 149 | 150 | switch (autodeskNode.type) { 151 | case "bucket": 152 | if(autodeskNode.id === "samplemodels"){ 153 | alert('upload in the below transient bucket'); 154 | break; 155 | } 156 | items = { 157 | uploadFile: { 158 | label: "Upload file", 159 | action: function () { 160 | uploadFile(); 161 | }, 162 | icon: 'glyphicon glyphicon-cloud-upload' 163 | } 164 | }; 165 | break; 166 | case "object": 167 | items = { 168 | translateFile: { 169 | label: "Translate", 170 | action: function () { 171 | var treeNode = $('#appBuckets').jstree(true).get_selected(true)[0]; 172 | translateObject(treeNode); 173 | }, 174 | icon: 'glyphicon glyphicon-eye-open' 175 | } 176 | }; 177 | break; 178 | } 179 | 180 | return items; 181 | } 182 | 183 | function uploadFile() { 184 | $('#hiddenUploadField').click(); 185 | } 186 | 187 | function translateObject(node) { 188 | $("#forgeViewer").empty(); 189 | if (node == null) node = $('#appBuckets').jstree(true).get_selected(true)[0]; 190 | var bucketKey = node.parents[0]; 191 | var objectKey = node.id; 192 | jQuery.post({ 193 | url: '/api/forge/modelderivative/jobs', 194 | contentType: 'application/json', 195 | data: JSON.stringify({ 'bucketKey': bucketKey, 'objectName': objectKey }), 196 | success: function (res) { 197 | $("#forgeViewer").html('Translation started! Please try again in a moment.'); 198 | }, 199 | }); 200 | } -------------------------------------------------------------------------------- /public/js/ForgeViewer.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | var viewer; 20 | var fileName; 21 | 22 | function launchViewer(urn, name) { 23 | var options = { 24 | env: 'AutodeskProduction', 25 | getAccessToken: getForgeToken 26 | }; 27 | 28 | fileName = name; 29 | 30 | Autodesk.Viewing.Initializer(options, () => { 31 | viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer')); 32 | viewer.start(); 33 | var documentId = 'urn:' + urn; 34 | Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure); 35 | }); 36 | } 37 | 38 | function onDocumentLoadSuccess(doc) { 39 | var viewables = doc.getRoot().getDefaultGeometry(); 40 | viewer.loadDocumentNode(doc, viewables).then(i => { 41 | // documented loaded, any action? 42 | var ViewerInstance = new CustomEvent("viewerinstance", {detail: {viewer: viewer}}); 43 | document.dispatchEvent(ViewerInstance); 44 | // var LoadExtensionEvent = new CustomEvent("loadextension", { 45 | // detail: { 46 | // extension: "Extension1", 47 | // viewer: viewer 48 | // } 49 | // }); 50 | // document.dispatchEvent(LoadExtensionEvent); 51 | }); 52 | } 53 | 54 | function onDocumentLoadFailure(viewerErrorCode) { 55 | console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode); 56 | } 57 | 58 | function getForgeToken(callback) { 59 | fetch('/api/forge/oauth/token').then(res => { 60 | res.json().then(data => { 61 | callback(data.access_token, data.expires_in); 62 | }); 63 | }); 64 | } -------------------------------------------------------------------------------- /routes/common/oauth.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | const { AuthClientTwoLegged } = require('forge-apis'); 20 | 21 | const config = require('../../config'); 22 | 23 | /** 24 | * Initializes a Forge client for 2-legged authentication. 25 | * @param {string[]} scopes List of resource access scopes. 26 | * @returns {AuthClientTwoLegged} 2-legged authentication client. 27 | */ 28 | function getClient(scopes) { 29 | const { client_id, client_secret } = config.credentials; 30 | return new AuthClientTwoLegged(client_id, client_secret, scopes || config.scopes.internal); 31 | } 32 | 33 | let cache = {}; 34 | async function getToken(scopes) { 35 | const key = scopes.join('+'); 36 | if (cache[key]) { 37 | return cache[key]; 38 | } 39 | const client = getClient(scopes); 40 | let credentials = await client.authenticate(); 41 | cache[key] = credentials; 42 | setTimeout(() => { delete cache[key]; }, credentials.expires_in * 1000); 43 | return credentials; 44 | } 45 | 46 | /** 47 | * Retrieves a 2-legged authentication token for preconfigured public scopes. 48 | * @returns Token object: { "access_token": "...", "expires_at": "...", "expires_in": "...", "token_type": "..." }. 49 | */ 50 | async function getPublicToken() { 51 | return getToken(config.scopes.public); 52 | } 53 | 54 | /** 55 | * Retrieves a 2-legged authentication token for preconfigured internal scopes. 56 | * @returns Token object: { "access_token": "...", "expires_at": "...", "expires_in": "...", "token_type": "..." }. 57 | */ 58 | async function getInternalToken() { 59 | return getToken(config.scopes.internal); 60 | } 61 | 62 | module.exports = { 63 | getClient, 64 | getPublicToken, 65 | getInternalToken 66 | }; 67 | -------------------------------------------------------------------------------- /routes/modelderivative.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | const express = require('express'); 20 | const { 21 | DerivativesApi, 22 | JobPayload, 23 | JobPayloadInput, 24 | JobPayloadOutput, 25 | JobSvfOutputPayload 26 | } = require('forge-apis'); 27 | 28 | const { getClient, getInternalToken } = require('./common/oauth'); 29 | 30 | let router = express.Router(); 31 | 32 | // Middleware for obtaining a token for each request. 33 | router.use(async (req, res, next) => { 34 | const token = await getInternalToken(); 35 | req.oauth_token = token; 36 | req.oauth_client = getClient(); 37 | next(); 38 | }); 39 | 40 | // POST /api/forge/modelderivative/jobs - submits a new translation job for given object URN. 41 | // Request body must be a valid JSON in the form of { "objectName": "" }. 42 | router.post('/jobs', async (req, res, next) => { 43 | let job = new JobPayload(); 44 | job.input = new JobPayloadInput(); 45 | job.input.urn = req.body.objectName; 46 | job.output = new JobPayloadOutput([ 47 | new JobSvfOutputPayload() 48 | ]); 49 | job.output.formats[0].type = 'svf'; 50 | job.output.formats[0].views = ['2d', '3d']; 51 | try { 52 | // Submit a translation job using [DerivativesApi](https://github.com/Autodesk-Forge/forge-api-nodejs-client/blob/master/docs/DerivativesApi.md#translate). 53 | await new DerivativesApi().translate(job, {}, req.oauth_client, req.oauth_token); 54 | res.status(200).end(); 55 | } catch(err) { 56 | next(err); 57 | } 58 | }); 59 | 60 | module.exports = router; 61 | -------------------------------------------------------------------------------- /routes/oauth.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | const express = require('express'); 20 | 21 | const { getPublicToken } = require('./common/oauth'); 22 | 23 | let router = express.Router(); 24 | 25 | // GET /api/forge/oauth/token - generates a public access token (required by the Forge viewer). 26 | router.get('/token', async (req, res, next) => { 27 | try { 28 | const token = await getPublicToken(); 29 | res.json({ 30 | access_token: token.access_token, 31 | expires_in: token.expires_in 32 | }); 33 | } catch(err) { 34 | next(err); 35 | } 36 | }); 37 | 38 | module.exports = router; 39 | -------------------------------------------------------------------------------- /routes/oss.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | const fs = require('fs'); 20 | const formidable = require('express-formidable'); 21 | const express = require('express'); 22 | const { BucketsApi, ObjectsApi, PostBucketsPayload } = require('forge-apis'); 23 | 24 | const { getClient, getInternalToken } = require('./common/oauth'); 25 | const config = require('../config'); 26 | 27 | let router = express.Router(); 28 | 29 | // Middleware for obtaining a token for each request. 30 | router.use(async (req, res, next) => { 31 | const token = await getInternalToken(); 32 | req.oauth_token = token; 33 | req.oauth_client = getClient(); 34 | next(); 35 | }); 36 | 37 | // GET /api/forge/oss/buckets - expects a query param 'id'; if the param is '#' or empty, 38 | // returns a JSON with list of buckets, otherwise returns a JSON with list of objects in bucket with given name. 39 | router.get('/buckets', async (req, res, next) => { 40 | const bucket_name = req.query.id; 41 | if (!bucket_name || bucket_name === '#') { 42 | try { 43 | // Retrieve buckets from Forge using the [BucketsApi](https://github.com/Autodesk-Forge/forge-api-nodejs-client/blob/master/docs/BucketsApi.md#getBuckets) 44 | const buckets = await new BucketsApi().getBuckets({ limit: 64 }, req.oauth_client, req.oauth_token); 45 | res.json(buckets.body.items.map((bucket) => { 46 | return { 47 | id: bucket.bucketKey, 48 | // Remove bucket key prefix that was added during bucket creation 49 | text: bucket.bucketKey.replace(config.credentials.client_id.toLowerCase() + '-', ''), 50 | type: 'bucket', 51 | children: true 52 | }; 53 | })); 54 | } catch(err) { 55 | next(err); 56 | } 57 | } else { 58 | try { 59 | // Retrieve objects from Forge using the [ObjectsApi](https://github.com/Autodesk-Forge/forge-api-nodejs-client/blob/master/docs/ObjectsApi.md#getObjects) 60 | const objects = await new ObjectsApi().getObjects(bucket_name, {}, req.oauth_client, req.oauth_token); 61 | res.json(objects.body.items.map((object) => { 62 | return { 63 | id: Buffer.from(object.objectId).toString('base64'), 64 | text: object.objectKey, 65 | type: 'object', 66 | children: false 67 | }; 68 | })); 69 | } catch(err) { 70 | next(err); 71 | } 72 | } 73 | }); 74 | 75 | router.post('/upload', formidable(), async function (req, res, next) { 76 | const file = req.files.fileToUpload 77 | if (!file) { 78 | res.status(400).send('The required field ("model-file") is missing.'); 79 | return; 80 | } 81 | try { 82 | await uploadObject(req.fields.bucketKey,file.name, file.path); 83 | res.status(200).end(); 84 | } catch (err) { 85 | next(err); 86 | } 87 | }); 88 | 89 | async function uploadObject(bucketKey,objectName, filePath) { 90 | const buffer = await fs.promises.readFile(filePath); 91 | const results = await new ObjectsApi().uploadResources( 92 | bucketKey, 93 | [{ objectKey: objectName, data: buffer }], 94 | { useAcceleration: false, minutesExpiration: 15 }, 95 | null, 96 | await getInternalToken() 97 | ); 98 | if (results[0].error) { 99 | throw results[0].completed; 100 | } else { 101 | return results[0].completed; 102 | } 103 | } 104 | 105 | module.exports = router; 106 | -------------------------------------------------------------------------------- /start.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | const path = require('path'); 20 | const express = require('express'); 21 | const fs = require('fs'); 22 | 23 | let masterconfigpath = './public/extensions/config.json'; 24 | let extensionsconfig = require(masterconfigpath); 25 | let source = './public/extensions'; 26 | let extensions = []; 27 | fs.readdirSync(source, { withFileTypes: true }) 28 | .filter(dirent => dirent.isDirectory()) 29 | .forEach(folder => { 30 | let econfig = require(source+'/'+folder.name+'/config.json') 31 | extensions.push(econfig); 32 | }); 33 | extensionsconfig.Extensions = extensions; 34 | fs.writeFileSync(masterconfigpath, JSON.stringify(extensionsconfig), function(err) { 35 | if (err) throw err; 36 | }); 37 | 38 | const PORT = process.env.PORT || 3000; 39 | const config = require('./config'); 40 | if (config.credentials.client_id == null || config.credentials.client_secret == null) { 41 | console.error('Missing FORGE_CLIENT_ID or FORGE_CLIENT_SECRET env. variables.'); 42 | return; 43 | } 44 | 45 | let app = express(); 46 | app.use(express.static(path.join(__dirname, 'public'))); 47 | app.use(express.json({ limit: '50mb' })); 48 | app.use('/api/forge/oauth', require('./routes/oauth')); 49 | app.use('/api/forge/oss', require('./routes/oss')); 50 | app.use('/api/forge/modelderivative', require('./routes/modelderivative')); 51 | app.use((err, req, res, next) => { 52 | console.error(err); 53 | res.status(err.statusCode).json(err); 54 | }); 55 | app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); }); 56 | -------------------------------------------------------------------------------- /thumbnail.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/forge-extensions/abaae38c6db4e450f0b3951b9ec1dd15bab3a1c8/thumbnail.PNG --------------------------------------------------------------------------------