# Conflicts: # package.json # src/viewer/ThreeViewer.tsmaster
| @@ -2,6 +2,8 @@ module.exports = { | |||
| 'root': true, | |||
| 'extends': [ | |||
| 'eslint:recommended', | |||
| 'plugin:@typescript-eslint/eslint-recommended' , | |||
| 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin | |||
| ], | |||
| 'parserOptions': { | |||
| 'ecmaVersion': 2018, | |||
| @@ -45,7 +47,6 @@ module.exports = { | |||
| 'overrides': [ | |||
| { | |||
| 'files': ['**/*.ts', '**/*.tsx'], | |||
| 'parser': '@typescript-eslint/parser', // Specifies the ESLint parser | |||
| 'parserOptions': { | |||
| 'ecmaVersion': 2021, // Allows for the parsing of modern ECMAScript features | |||
| @@ -37,17 +37,17 @@ jobs: | |||
| steps: | |||
| - uses: actions/checkout@v3 | |||
| - name: Use Node.js ${{ matrix.node-version }} | |||
| uses: actions/setup-node@v3 | |||
| - uses: actions/setup-node@v3 | |||
| with: | |||
| node-version: ${{ matrix.node-version }} | |||
| cache: 'npm' | |||
| - run: npm ci # this will also run `npm run prepare` which will build | |||
| - run: npm run docs | |||
| cache-dependency-path: '**/package-lock.json' # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-data | |||
| - run: npm ci # this will also run `npm run prepare` which will build # todo use --cache .npm | |||
| - run: npm run docs-all | |||
| - run: mkdir _site | |||
| - run: mv -t _site docs dist examples README.md LICENSE index.html | |||
| - run: mv -t _site src docs dist examples README.md LICENSE index.html | |||
| - run: mkdir -p _site/plugins | |||
| - run: find plugins -maxdepth 2 -type d \( -name dist -o -name docs \) -exec sh -c "mkdir -p _site/{} && cp -r {} _site/{}/.." \; | |||
| - run: find plugins -maxdepth 2 -type d \( -name dist -o -name docs -name src \) -exec sh -c "mkdir -p _site/{} && cp -r {} _site/{}/.." \; | |||
| - name: Setup Pages | |||
| uses: actions/configure-pages@v3 | |||
| - name: Upload artifact | |||
| @@ -1,4 +1,5 @@ | |||
| dist | |||
| lib | |||
| docs | |||
| /index.html | |||
| examples/**/*.js | |||
| @@ -6,3 +6,5 @@ | |||
| # Datasource local storage ignored files | |||
| /dataSources/ | |||
| /dataSources.local.xml | |||
| # GitHub Copilot persisted chat sessions | |||
| /copilot/chatSessions | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Ambient Light</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,52 @@ | |||
| import { | |||
| _testFinish, | |||
| AmbientLight2, | |||
| Box3B, | |||
| IObject3D, | |||
| Mesh, | |||
| Object3DWidgetsPlugin, | |||
| PhysicalMaterial, | |||
| PlaneGeometry, | |||
| ThreeViewer, | |||
| Vector3, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| dropzone: { | |||
| allowedExtensions: ['gltf', 'glb', 'hdr', 'obj', 'fbx', 'bin', 'png', 'jpeg', 'webp', 'jpg', 'exr'], | |||
| addOptions: { | |||
| disposeSceneObjects: true, | |||
| autoSetEnvironment: true, // when hdr/exr is dropped | |||
| }, | |||
| }, | |||
| plugins: [Object3DWidgetsPlugin], | |||
| }) | |||
| // viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/ShadowmappableMesh.glb', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const ground = new Mesh( | |||
| new PlaneGeometry(100, 100) | |||
| .rotateX(-Math.PI / 2) | |||
| .translate(0, new Box3B().expandByObject(result!).getSize(new Vector3()).y / -2, 0), | |||
| new PhysicalMaterial({ | |||
| color: '#ffffff', | |||
| }) | |||
| ) | |||
| viewer.scene.addObject(ground) | |||
| const light = viewer.scene.addObject(new AmbientLight2(0x00ff00, 5)) | |||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | |||
| ui.appendChild(light.uiConfig, {expanded: true}) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,54 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Blend Load</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-blend-importer": "./../../plugins/blend-importer/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module"> | |||
| import {_testFinish, ThreeViewer} from 'threepipe' | |||
| import {BlendLoadPlugin} from '@threepipe/plugin-blend-importer' | |||
| const viewer = new ThreeViewer({canvas: document.getElementById('mcanvas')}) | |||
| viewer.addPluginsSync([BlendLoadPlugin]) | |||
| async function init() { | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const result = await viewer.load('https://asset-samples.threepipe.org/minimal/default-cube.blend', { | |||
| autoCenter: true, | |||
| autoScale: false, | |||
| }) | |||
| console.log(result) | |||
| } | |||
| init().then(_testFinish) | |||
| </script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>BlueprintJs Ui Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-blueprintjs": "./../../plugins/blueprintjs/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,25 @@ | |||
| import {_testFinish, IObject3D, ThreeViewer, TonemapPlugin} from 'threepipe' | |||
| import {BlueprintJsUiPlugin} from '@threepipe/plugin-blueprintjs' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| }) | |||
| const ui = viewer.addPluginSync(new BlueprintJsUiPlugin()) | |||
| ui.appendChild(viewer.uiConfig) | |||
| ui.setupPluginUi(TonemapPlugin) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const mesh = result?.getObjectByName('node_damagedHelmet_-6514') | |||
| ui.appendChild(mesh?.uiConfig) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Camera View Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,79 @@ | |||
| import {_testFinish, CameraView, CameraViewPlugin, EasingFunctions, ThreeViewer, Vector3} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| import {createSimpleButtons} from '../examples-utils/simple-bottom-buttons.js' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| }) | |||
| const cameraViewPlugin = viewer.addPluginSync(CameraViewPlugin) | |||
| console.log(cameraViewPlugin) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| // Get the current camera view and save it in a variable | |||
| const initialView = cameraViewPlugin.getView() | |||
| const topView = new CameraView( | |||
| 'topView', | |||
| new Vector3(0, 6, 0), | |||
| initialView.target, | |||
| ) | |||
| const leftView = new CameraView( | |||
| 'leftView', | |||
| new Vector3(-6, 0, 0), | |||
| initialView.target, | |||
| ) | |||
| const rightView = new CameraView( | |||
| 'leftView', | |||
| new Vector3(6, 0, 0), | |||
| initialView.target, | |||
| ) | |||
| createSimpleButtons({ | |||
| ['Top View']: async() => cameraViewPlugin.animateToView(topView, 1000, EasingFunctions.easeInOutSine), | |||
| ['Left View']: async() => cameraViewPlugin.animateToView(leftView, 1000, EasingFunctions.easeInOutSine), | |||
| ['Right View']: async() => cameraViewPlugin.animateToView(rightView, 1000, EasingFunctions.easeInOutSine), | |||
| ['Pan right/left']: async(btn) => { | |||
| btn.disabled = true | |||
| const currentView = cameraViewPlugin.getView() | |||
| await cameraViewPlugin.animateToView(new CameraView( | |||
| 'view', | |||
| currentView.position, | |||
| new Vector3(4, 0, 0).sub(currentView.target), | |||
| )) | |||
| btn.disabled = false | |||
| }, | |||
| ['Move up/down']: async(btn) => { | |||
| btn.disabled = true | |||
| const currentView = cameraViewPlugin.getView() | |||
| await cameraViewPlugin.animateToView(new CameraView( | |||
| 'view', | |||
| new Vector3(currentView.position.x, 5 - currentView.position.y, currentView.position.z), | |||
| currentView.target, | |||
| )) | |||
| btn.disabled = false | |||
| }, | |||
| ['Reset']: async() => cameraViewPlugin.animateToView(initialView, 1000, EasingFunctions.easeInOutSine), | |||
| }) | |||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | |||
| ui.appendChild(viewer.scene.mainCamera.uiConfig) | |||
| const uiC = ui.setupPluginUi(CameraViewPlugin)! | |||
| uiC.expanded = true | |||
| uiC.uiRefresh?.() | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,35 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Canvas Snapshot Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,63 @@ | |||
| import {_testFinish, CanvasSnapshotPlugin, isWebpExportSupported, ThreeViewer} from 'threepipe' | |||
| import {createSimpleButtons} from '../examples-utils/simple-bottom-buttons.js' | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| renderScale: 'auto', | |||
| }) | |||
| async function init() { | |||
| const snapshotPlugin = viewer.addPluginSync(new CanvasSnapshotPlugin()) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load('https://threejs.org/examples/models/gltf/kira.glb', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| createSimpleButtons({ | |||
| ['Download snapshot (rect png)']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| await snapshotPlugin.downloadSnapshot('snapshot.png', { | |||
| scale: 1, // scale the final image | |||
| displayPixelRatio: 2, // render scale | |||
| mimeType: 'image/png', // mime type of the image | |||
| rect: { // region to take snapshot. Crop center of the canvas | |||
| height: viewer.canvas.clientHeight / 2, | |||
| width: viewer.canvas.clientWidth / 2, | |||
| x: viewer.canvas.clientWidth / 4, | |||
| y: viewer.canvas.clientHeight / 4, | |||
| }, | |||
| }) | |||
| btn.disabled = false | |||
| }, | |||
| ['Download snapshot (jpeg)']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| await snapshotPlugin.downloadSnapshot('snapshot.jpeg', { | |||
| mimeType: 'image/jpeg', // mime type of the image | |||
| quality: 0.9, // quality of the image (0-1) only for jpeg and webp | |||
| displayPixelRatio: 2, // render scale | |||
| }) | |||
| btn.disabled = false | |||
| }, | |||
| ['Download snapshot (webp)']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| if (!isWebpExportSupported()) { | |||
| alert('WebP export is not supported in this browser, try the latest version of chrome, firefox or edge.') | |||
| btn.disabled = false | |||
| return | |||
| } | |||
| await snapshotPlugin.downloadSnapshot('snapshot.webp', { | |||
| mimeType: 'image/webp', // mime type of the image | |||
| scale: 1, // scale the final image | |||
| quality: 0.9, // quality of the image (0-1) only for jpeg and webp | |||
| displayPixelRatio: 2, // render scale | |||
| }) | |||
| btn.disabled = false | |||
| }, | |||
| }) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Chromatic Aberration Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,20 @@ | |||
| import {_testFinish, ChromaticAberrationPlugin, IObject3D, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| }) | |||
| viewer.addPluginSync(ChromaticAberrationPlugin) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf') | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(ChromaticAberrationPlugin) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Clearcoat Tint Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,44 @@ | |||
| import {_testFinish, ClearcoatTintPlugin, IObject3D, PhysicalMaterial, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| }) | |||
| const clearcoatTint = viewer.addPluginSync(ClearcoatTintPlugin) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', { | |||
| setBackground: true, | |||
| }) | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const model = result?.getObjectByName('node_damagedHelmet_-6514') | |||
| const materials = (model?.materials || []) as PhysicalMaterial[] | |||
| for (const material of materials) { | |||
| material.clearcoat = 1 | |||
| // add initial properties | |||
| ClearcoatTintPlugin.AddClearcoatTint(material, { | |||
| tintColor: '#ff0000', | |||
| thickness: 1, | |||
| }) | |||
| // set properties like this or from the UI | |||
| // material.userData._clearcoatTint!.tintColor = '#ff0000' | |||
| // Add extra clearcoat tint ui mapped to this material. | |||
| // This is also added inside the material ui by default by the material extension automatically. | |||
| const config = material.uiConfig | |||
| if (!config) continue | |||
| ui.appendChild(clearcoatTint.materialExtension.getUiConfig?.(material), {expanded: true}) | |||
| ui.appendChild(config) | |||
| } | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Contact Shadow Ground Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,22 @@ | |||
| import {_testFinish, ContactShadowGroundPlugin, IObject3D, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| }) | |||
| viewer.addPluginSync(ContactShadowGroundPlugin) | |||
| await Promise.all([ | |||
| viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'), | |||
| viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf'), | |||
| ]) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(ContactShadowGroundPlugin, {expanded: true}) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Custom Bump Map Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,41 @@ | |||
| import {_testFinish, CustomBumpMapPlugin, ITexture, Mesh, PhysicalMaterial, PlaneGeometry, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| }) | |||
| const customBump = viewer.addPluginSync(CustomBumpMapPlugin) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const model = new Mesh(new PlaneGeometry(4, 2), new PhysicalMaterial()) | |||
| const material = model.material | |||
| viewer.scene.addObject(model) | |||
| const bumpMap1 = await viewer.load<ITexture>('https://threejs.org/examples/textures/brick_bump.jpg') | |||
| const bumpMap2 = await viewer.load<ITexture>('https://threejs.org/examples/textures/planets/earth_specular_2048.jpg') | |||
| customBump.enableCustomBump(material, bumpMap2, -0.2) | |||
| material.bumpMap = bumpMap1 || null | |||
| material.bumpScale = -0.01 | |||
| material.setDirty() | |||
| // set properties like this or from the UI | |||
| // material.userData._customBumpMat = texture | |||
| // material.setDirty() | |||
| // to disable | |||
| // material.userData._hasCustomBump = false | |||
| // material.setDirty() | |||
| ui.setupPluginUi(CustomBumpMapPlugin) | |||
| const config = material.uiConfig! | |||
| ui.appendChild(customBump.materialExtension.getUiConfig?.(material), {expanded: true}) | |||
| ui.appendChild(config) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,46 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Device Orientation Controls Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| #deviceOrientationOverlay{ | |||
| position: absolute; top: 0; left: 0; right: 0; bottom: 0; height: 100%; width: 100%; | |||
| display: flex; justify-content: center; align-items: center; cursor: pointer; | |||
| font-size: 1.5rem; background: rgba(240,240,240,0.5); color: #333333; | |||
| backdrop-filter: blur(16px); | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| <div id="deviceOrientationOverlay"> | |||
| Tap the screen to enable device orientation controls <br/> | |||
| (works only on devices with gyroscope) | |||
| </div> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,30 @@ | |||
| import {_testFinish, DeviceOrientationControlsPlugin, IObject3D, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| plugins: [DeviceOrientationControlsPlugin], | |||
| }) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.appendChild(viewer.scene.mainCamera.uiConfig) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const overlayEl = document.getElementById('deviceOrientationOverlay') as HTMLDivElement | |||
| overlayEl.addEventListener('click', () => { | |||
| viewer.scene.mainCamera.controlsMode = 'deviceOrientation' | |||
| overlayEl.style.display = 'none' | |||
| }) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -11,7 +11,8 @@ | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs" | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| @@ -1,9 +1,10 @@ | |||
| import { | |||
| _testFinish, | |||
| Box3B, | |||
| DirectionalLight, | |||
| DirectionalLight2, | |||
| IObject3D, | |||
| Mesh, | |||
| Object3DWidgetsPlugin, | |||
| PCFSoftShadowMap, | |||
| PhysicalMaterial, | |||
| PlaneGeometry, | |||
| @@ -11,6 +12,7 @@ import { | |||
| ThreeViewer, | |||
| Vector3, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| @@ -24,6 +26,7 @@ async function init() { | |||
| autoSetEnvironment: true, // when hdr/exr is dropped | |||
| }, | |||
| }, | |||
| plugins: [Object3DWidgetsPlugin], | |||
| }) | |||
| // viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | |||
| @@ -44,23 +47,25 @@ async function init() { | |||
| ground.receiveShadow = true | |||
| viewer.scene.addObject(ground) | |||
| const directionalLight = viewer.scene.addObject(new DirectionalLight(0xffffff, 4)) | |||
| directionalLight.position.set(2, 2, 2) | |||
| directionalLight.lookAt(0, 0, 0) | |||
| directionalLight.castShadow = true | |||
| directionalLight.shadow.mapSize.setScalar(1024) | |||
| directionalLight.shadow.camera.near = 0.1 | |||
| directionalLight.shadow.camera.far = 10 | |||
| directionalLight.shadow.camera.top = 2 | |||
| directionalLight.shadow.camera.bottom = -2 | |||
| directionalLight.shadow.camera.left = -2 | |||
| directionalLight.shadow.camera.right = 2 | |||
| const light = viewer.scene.addObject(new DirectionalLight2(0xffffff, 4)) | |||
| light.position.set(2, 2, 2) | |||
| light.lookAt(0, 0, 0) | |||
| light.castShadow = true | |||
| light.shadow.mapSize.setScalar(1024) | |||
| light.shadow.camera.near = 0.1 | |||
| light.shadow.camera.far = 10 | |||
| light.shadow.camera.top = 2 | |||
| light.shadow.camera.bottom = -2 | |||
| light.shadow.camera.left = -2 | |||
| light.shadow.camera.right = 2 | |||
| viewer.renderManager.renderer.shadowMap.type = PCFSoftShadowMap | |||
| const rt = viewer.addPluginSync(RenderTargetPreviewPlugin) | |||
| rt.addTarget(()=>directionalLight.shadow.map || undefined, 'shadow', true, true, true) | |||
| rt.addTarget(()=>light.shadow.map || undefined, 'shadow', true, true, true) | |||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | |||
| ui.appendChild(light.uiConfig, {expanded: true}) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Editor View Widget Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,35 @@ | |||
| import {_testFinish, EditorViewWidgetPlugin, IObject3D, ThreeViewer, timeout} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| }) | |||
| viewer.scene.setBackgroundColor(0x151822) | |||
| const plugin = viewer.addPluginSync(new EditorViewWidgetPlugin('bottom-left', 256)) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf') | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(EditorViewWidgetPlugin) | |||
| // look at the model from left | |||
| plugin.setOrientation('-z') | |||
| await timeout(1000) // wait for 1 sec | |||
| // look at the model from back | |||
| plugin.setOrientation('-x') | |||
| await timeout(1000) // wait for 1 sec | |||
| // look at the model from front | |||
| plugin.setOrientation('+z') | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -19,7 +19,7 @@ function replaceImports(code) { | |||
| .replaceAll(` from '../`, ` from '${rootPath+examplePath}`) | |||
| } | |||
| setupCodePreview( | |||
| document.getElementById('canvas-container') || document.querySelector('.code-preview-container') || document.body, | |||
| document.querySelector('.code-preview-container') || document.getElementById('canvas-container') || document.body, | |||
| scripts, | |||
| scripts.map(s=>s.textContent ? 'js' : s.split('.').pop()), // title | |||
| scripts.map(s=>(typeof s === 'string' && s.endsWith('.js')) ? s : (codePath+examplePath+window.location.pathname.split('/examples/').pop().replace('index.html', '')+(s.textContent ? 'index.html' : s))), // todo: github link | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Filmic Grain Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,20 @@ | |||
| import {_testFinish, FilmicGrainPlugin, IObject3D, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| }) | |||
| viewer.addPluginSync(FilmicGrainPlugin) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf') | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(FilmicGrainPlugin) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Fragment Clipping Extension Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,49 @@ | |||
| import { | |||
| _testFinish, | |||
| FragmentClippingExtensionPlugin, | |||
| IObject3D, | |||
| PhysicalMaterial, | |||
| ThreeViewer, | |||
| Vector4, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| }) | |||
| const fragmentClipping = viewer.addPluginSync(FragmentClippingExtensionPlugin) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', { | |||
| setBackground: true, | |||
| }) | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const model = result?.getObjectByName('node_damagedHelmet_-6514') | |||
| const materials = (model?.materials || []) as PhysicalMaterial[] | |||
| for (const material of materials) { | |||
| FragmentClippingExtensionPlugin.AddFragmentClipping(material, { | |||
| clipPosition: new Vector4(0.5, 0.5, 0, 0), | |||
| clipParams: new Vector4(0.1, 0.05, 0, 1), | |||
| }) | |||
| // set properties like this or from the UI | |||
| // material.userData._fragmentClipping!.clipPosition.set(0, 0, 0, 0) | |||
| // material.setDirty() | |||
| // Add extra fragment clipping extension ui mapped to this material. | |||
| // This is also added inside the material ui by default by the material extension automatically. | |||
| const config = material.uiConfig | |||
| if (!config) continue | |||
| ui.appendChild(fragmentClipping.materialExtension.getUiConfig?.(material), {expanded: true}) | |||
| ui.appendChild(config) | |||
| } | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,35 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>GBuffer Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,95 @@ | |||
| import { | |||
| _testFinish, | |||
| downloadBlob, | |||
| FloatType, | |||
| GBufferPlugin, | |||
| HalfFloatType, | |||
| IObject3D, | |||
| RenderTargetPreviewPlugin, | |||
| ThreeViewer, | |||
| } from 'threepipe' | |||
| import {createSimpleButtons} from '../examples-utils/simple-bottom-buttons.js' | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| zPrepass: true, | |||
| }) | |||
| async function init() { | |||
| const gbufferPlugin = viewer.addPluginSync(new GBufferPlugin( | |||
| HalfFloatType, | |||
| true, // isPrimaryGBuffer (used for zprepass etc) | |||
| true, // enabled by default | |||
| true, // render the flags buffer (used for eg selective tonemapping) | |||
| true, // render depth texture | |||
| FloatType)) // render depth texture as Float type. available - UnsignedShort(16 bits), UnsignedInt(24 bits) or Float(32 bits) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const model = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/kira.glb', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| let id = 1 | |||
| model?.traverse((o) => { | |||
| o.materials?.forEach(m=>{ | |||
| if (!m.userData.gBufferData) m.userData.gBufferData = {} | |||
| if (!m.userData.gBufferData.materialId) m.userData.gBufferData.materialId = id += 10 | |||
| }) | |||
| }) | |||
| // Disable automatic near/far plane calculation based on scene bounding box | |||
| viewer.scene.mainCamera.userData.autoNearFar = false | |||
| viewer.scene.mainCamera.userData.minNearPlane = 1 | |||
| viewer.scene.mainCamera.userData.maxFarPlane = 10 | |||
| viewer.scene.refreshScene() | |||
| const gbufferTarget = gbufferPlugin.target | |||
| if (!gbufferTarget) { | |||
| throw new Error('gbufferPlugin.target returned undefined') | |||
| } | |||
| // to render depth buffer to screen, uncomment this line: | |||
| // viewer.renderManager.screenPass.overrideReadBuffer = gbufferTarget | |||
| const getNormalDepth = ()=>({texture: gbufferPlugin.normalDepthTexture}) | |||
| const getFlags = ()=>({texture: gbufferPlugin.flagsTexture}) | |||
| const getDepthTexture = ()=>({texture: gbufferPlugin.depthTexture}) | |||
| const targetPreview = await viewer.addPlugin(RenderTargetPreviewPlugin) | |||
| targetPreview.addTarget(getNormalDepth, 'normalDepth') | |||
| targetPreview.addTarget(getFlags, 'gBufferFlags') | |||
| targetPreview.addTarget(getDepthTexture, 'depthTexture') | |||
| const screenPass = viewer.renderManager.screenPass | |||
| createSimpleButtons({ | |||
| ['Toggle Normal+Depth']: () => { | |||
| const rt = getNormalDepth() | |||
| screenPass.overrideReadBuffer = screenPass.overrideReadBuffer?.texture === rt.texture ? null : rt | |||
| viewer.setDirty() | |||
| }, | |||
| ['Toggle Gbuffer Flags']: () => { | |||
| const rt = getFlags() | |||
| screenPass.overrideReadBuffer = screenPass.overrideReadBuffer?.texture === rt.texture ? null : rt | |||
| viewer.setDirty() | |||
| }, | |||
| ['Toggle Depth Texture']: () => { | |||
| const rt = getDepthTexture() | |||
| screenPass.overrideReadBuffer = screenPass.overrideReadBuffer?.texture === rt.texture ? null : rt | |||
| viewer.setDirty() | |||
| }, | |||
| ['Download snapshot']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| const blob = await viewer.getScreenshotBlob({mimeType: 'image/png'}) | |||
| if (blob) downloadBlob(blob, 'file.png') | |||
| else console.error('Unable to get screenshot') | |||
| btn.disabled = false | |||
| }, | |||
| }) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,38 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Geometry Generator Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "three": "./../../dist/index.mjs", | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-geometry-generator": "./../../plugins/geometry-generator/dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,31 @@ | |||
| import {_testFinish, CameraViewPlugin, Object3DGeneratorPlugin, PickingPlugin, ThreeViewer} from 'threepipe' | |||
| import {GeometryGeneratorPlugin} from '@threepipe/plugin-geometry-generator' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| plugins: [PickingPlugin, CameraViewPlugin, Object3DGeneratorPlugin], | |||
| }) | |||
| const generator = viewer.addPluginSync(GeometryGeneratorPlugin) | |||
| viewer.scene.setBackgroundColor('#444466') | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| console.log(generator.generators) | |||
| const sphere = generator.generateObject('sphere', {radius: 0.5, widthSegments: 32, heightSegments: 32}) | |||
| viewer.scene.addObject(sphere) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(GeometryGeneratorPlugin) | |||
| ui.setupPluginUi(PickingPlugin) | |||
| ui.setupPluginUi(Object3DGeneratorPlugin) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>GLTF Transmission Test (MSAA)</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,52 @@ | |||
| import {_testFinish, IObject3D, RenderTargetPreviewPlugin, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| rgbm: true, | |||
| zPrepass: false, | |||
| }) | |||
| async function init() { | |||
| const targetPreview = viewer.addPluginSync(RenderTargetPreviewPlugin) | |||
| targetPreview.addTarget(()=>viewer.renderManager.composerTarget, 'composer-1', false, false) | |||
| viewer.renderManager.renderPass.preserveTransparentTarget = true | |||
| targetPreview.addTarget(()=>viewer.renderManager.renderPass.transparentTarget, 'transparent', true, true) | |||
| targetPreview.addTarget(()=>viewer.renderManager.composerTarget2, 'composer-2', false, false) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const [model, model2] = await Promise.all([ | |||
| viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/IridescenceLamp.glb', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }), | |||
| viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/IridescentDishWithOlives.glb', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }), | |||
| ]) | |||
| if (!model || !model2) { | |||
| console.error('model not loaded') | |||
| return | |||
| } | |||
| model.position.x = -1 | |||
| model2.position.x = 1 | |||
| model2.position.y = -1.2 | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(false)) | |||
| const m1 = model?.getObjectByName('lamp_transmission') | |||
| const m2 = model2?.getObjectByName('glassCover') | |||
| const materials = [...m1?.materials || [], ...m2?.materials || []] | |||
| for (const material of materials) { | |||
| const config = material.uiConfig | |||
| if (!config) continue | |||
| ui.appendChild(config) | |||
| } | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>HDRi Ground Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,50 @@ | |||
| import {_testFinish, CameraViewPlugin, HDRiGroundPlugin, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| dropzone: { | |||
| allowedExtensions: ['gltf', 'glb', 'hdr', 'bin', 'png', 'jpeg', 'webp', 'jpg', 'exr'], | |||
| addOptions: { | |||
| disposeSceneObjects: true, | |||
| autoSetEnvironment: true, // when hdr is dropped | |||
| autoSetBackground: true, | |||
| }, | |||
| }, | |||
| plugins: [CameraViewPlugin], | |||
| }) | |||
| const hdriGround = viewer.addPluginSync(HDRiGroundPlugin) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', { | |||
| setBackground: true, | |||
| }) | |||
| await viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| autoScaleRadius: 10, | |||
| }) | |||
| viewer.scene.background = 'environment' // this is not really required since setBackground is also set to true above | |||
| hdriGround.worldRadius = 50 | |||
| hdriGround.tripodHeight = 10 | |||
| const bounds = viewer.scene.getBounds(true, true) | |||
| bounds.getCenter(hdriGround.originPosition) | |||
| hdriGround.originPosition.y -= (bounds.max.y - bounds.min.y) / 2 | |||
| hdriGround.enabled = true | |||
| console.log(hdriGround) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(HDRiGroundPlugin) | |||
| await viewer.fitToView(undefined, 2.5) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Hemisphere Light</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,52 @@ | |||
| import { | |||
| _testFinish, | |||
| Box3B, | |||
| HemisphereLight2, | |||
| IObject3D, | |||
| Mesh, | |||
| Object3DWidgetsPlugin, | |||
| PhysicalMaterial, | |||
| PlaneGeometry, | |||
| ThreeViewer, | |||
| Vector3, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| dropzone: { | |||
| allowedExtensions: ['gltf', 'glb', 'hdr', 'obj', 'fbx', 'bin', 'png', 'jpeg', 'webp', 'jpg', 'exr'], | |||
| addOptions: { | |||
| disposeSceneObjects: true, | |||
| autoSetEnvironment: true, // when hdr/exr is dropped | |||
| }, | |||
| }, | |||
| plugins: [Object3DWidgetsPlugin], | |||
| }) | |||
| // viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/ShadowmappableMesh.glb', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const ground = new Mesh( | |||
| new PlaneGeometry(100, 100) | |||
| .rotateX(-Math.PI / 2) | |||
| .translate(0, new Box3B().expandByObject(result!).getSize(new Vector3()).y / -2, 0), | |||
| new PhysicalMaterial({ | |||
| color: '#ffffff', | |||
| }) | |||
| ) | |||
| viewer.scene.addObject(ground) | |||
| const light = viewer.scene.addObject(new HemisphereLight2(0x0000ff, 0xff0000, 20)) | |||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | |||
| ui.appendChild(light.uiConfig, {expanded: true}) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -17,7 +17,8 @@ | |||
| <body> | |||
| <canvas id="three-canvas" style="width: 800px; height: 600px;"></canvas> | |||
| <script id="example-script" type="module" data-scripts="./index.html"> | |||
| import {ThreeViewer} from 'https://threepipe.org/dist/index.mjs' | |||
| // import {ThreeViewer} from 'https://threepipe.org/dist/index.mjs' | |||
| import {ThreeViewer} from './../../dist/index.mjs' | |||
| const viewer = new ThreeViewer({canvas: document.getElementById('three-canvas')}) | |||
| // Load an environment map | |||
| @@ -32,3 +33,4 @@ | |||
| }) | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @@ -6,6 +6,8 @@ const viewer = new ThreeViewer({ | |||
| msaa: true, | |||
| }) | |||
| // Note: see also: CanvasSnapshotPlugin | |||
| async function init() { | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| @@ -220,19 +220,32 @@ | |||
| <h2 class="category">Post-Processing</h2> | |||
| <ul> | |||
| <li><a href="./tonemap-plugin/">Tonemap Plugin </a></li> | |||
| <li><a href="./vignette-plugin/">Vignette Plugin </a></li> | |||
| <li><a href="./chromatic-aberration-plugin/">Chromatic Aberration Plugin </a></li> | |||
| <li><a href="./filmic-grain-plugin/">Filmic Grain Plugin </a></li> | |||
| <li><a href="./frame-fade-plugin/">Frame Fade Plugin </a></li> | |||
| </ul> | |||
| <h2 class="category">Rendering</h2> | |||
| <ul> | |||
| <li><a href="./progressive-plugin/">Progressive Plugin </a></li> | |||
| <li><a href="./custom-pipeline/">Custom Pipeline specification </a></li> | |||
| <li><a href="./depth-buffer-plugin/">Depth Buffer Plugin </a></li> | |||
| <li><a href="./normal-buffer-plugin/">Normal Buffer Plugin </a></li> | |||
| <li><a href="./custom-pipeline/">Custom Pipeline specification </a></li> | |||
| <li><a href="./gbuffer-plugin/">GBuffer Plugin <br/>(NormalDepth+Flags) </a></li> | |||
| <li><a href="./virtual-cameras-plugin/">Virtual Cameras Plugin </a></li> | |||
| <li><a href="./virtual-camera/">Virtual Camera (Animated) </a></li> | |||
| </ul> | |||
| <h2 class="category">Interaction</h2> | |||
| <ul> | |||
| <li><a href="./picking-plugin/">Picking (Selection) Plugin </a></li> | |||
| <li><a href="./camera-view-plugin/">Camera View (Animation) Plugin </a></li> | |||
| <li><a href="./dropzone-plugin/">Dropzone (Drag & Drop) Plugin </a></li> | |||
| <li><a href="./transform-controls-plugin/">Transform Controls Plugin </a></li> | |||
| <li><a href="./editor-view-widget-plugin/">Editor View Widget Plugin </a></li> | |||
| <li><a href="./fullscreen-plugin/">FullScreen Plugin </a></li> | |||
| <li><a href="./device-orientation-controls-plugin/">Device Orientation Controls Plugin (Gyroscope) </a></li> | |||
| <li><a href="./pointer-lock-controls-plugin/">Pointer Lock(FPS) Controls Plugin </a></li> | |||
| <li><a href="./three-first-person-controls-plugin/">Three First Person(look around) Controls Plugin </a></li> | |||
| </ul> | |||
| <h2 class="category">Import</h2> | |||
| <ul> | |||
| @@ -249,10 +262,13 @@ | |||
| <li><a href="./stl-load/">STL Load </a></li> | |||
| <li><a href="./ktx2-load/">KTX2 Load </a></li> | |||
| <li><a href="./ktx-load/">KTX Load </a></li> | |||
| <li><a href="./blend-load/">BLEND Load </a></li> | |||
| <li><a href="./splat-load/">SPLAT Load<br/>(Gaussian Splatting) </a></li> | |||
| <li><a href="./extra-importer-plugins/">Extra(3ds, 3mf, collada, amf, bvh, vox, gcode, mdd, pcd, tilt, wrl, ldraw, vtk, xyz) Load </a></li> | |||
| </ul> | |||
| <h2 class="category">Export</h2> | |||
| <ul> | |||
| <li><a href="./canvas-snapshot-plugin/">Canvas Snapshot Plugin<br/>(Image Snapshot) </a></li> | |||
| <li><a href="./image-snapshot-export/">PNG, JPEG, WEBP Export<br/>(Image Snapshot) </a></li> | |||
| <li><a href="./render-target-export/">EXR, PNG, JPEG, WEBP Export<br/>(Render Target Export) </a></li> | |||
| <li><a href="./glb-export/">GLB Export </a></li> | |||
| @@ -266,6 +282,11 @@ | |||
| <li><a href="./scene-uiconfig/">Scene UI </a></li> | |||
| <li><a href="./viewer-uiconfig/">Viewer UI </a></li> | |||
| </ul> | |||
| <h2 class="category">UI Plugins</h2> | |||
| <ul> | |||
| <li><a href="./tweakpane-ui-plugin/">Tweakpane UI Plugin </a></li> | |||
| <li><a href="./blueprintjs-ui-plugin/">Blueprint.js UI Plugin </a></li> | |||
| </ul> | |||
| <h2 class="category">Animation</h2> | |||
| <ul> | |||
| <li><a href="./gltf-animation-plugin/">glTF Animation Plugin </a></li> | |||
| @@ -273,9 +294,21 @@ | |||
| <li><a href="./gltf-camera-animation/">glTF Camera Animation </a></li> | |||
| <li><a href="./gltf-animation-page-scroll/">glTF Animation Page Scroll </a></li> | |||
| </ul> | |||
| <h2 class="category">Materials</h2> | |||
| <ul> | |||
| <li><a href="./clearcoat-tint-plugin/">Clearcoat Tint Plugin</a></li> | |||
| <li><a href="./fragment-clipping-extension-plugin/">Fragment Clipping Extension Plugin </a></li> | |||
| <li><a href="./noise-bump-material-plugin/">SparkleBump(NoiseBump) Material Plugin </a></li> | |||
| <li><a href="./custom-bump-map-plugin/">Custom Bump Map Plugin </a></li> | |||
| </ul> | |||
| <h2 class="category">Utils</h2> | |||
| <ul> | |||
| <li><a href="./contact-shadow-ground-plugin/">Contact Shadow Ground Plugin</a></li> | |||
| <li><a href="./hdri-ground-plugin/">HDRi Ground Plugin <br/>(Projected Skybox)</a></li> | |||
| <li><a href="./render-target-preview/">Render Target Preview Plugin </a></li> | |||
| <li><a href="./object3d-generator-plugin/">Object3D Generator Plugin <br/>(Lights, Cameras)</a></li> | |||
| <li><a href="./geometry-generator-plugin/">Geometry Generator Plugin </a></li> | |||
| <li><a href="./object3d-widgets-plugin/">Object3D Widgets Plugin <br/>(Lights, Cameras)</a></li> | |||
| <li><a href="./geometry-uv-preview/">Geometry UV Preview Plugin </a></li> | |||
| <li><a href="./parallel-asset-import/">Parallel Asset Import </a></li> | |||
| <li><a href="./obj-to-glb/">Convert OBJ to GLB </a></li> | |||
| @@ -284,15 +317,28 @@ | |||
| </ul> | |||
| <h2 class="category">Samples</h2> | |||
| <ul> | |||
| <li><a href="./html-sample/">HTML/JS Sample </a></li> | |||
| <li><a href="./html-js-sample/">HTML/JS Sample </a></li> | |||
| <li><a href="./react-js-sample/">React/JS Sample </a></li> | |||
| <li><a href="./react-jsx-sample/">React/JSX Sample </a></li> | |||
| <li><a href="./react-tsx-sample/">React/TSX Sample </a></li> | |||
| <li><a href="./vue-html-sample/">Vue/HTML Sample </a></li> | |||
| <li><a href="./vue-sfc-sample/">Vue/SFC Sample </a></li> | |||
| <li><a href="./svelte-sample/">Svelte Sample </a></li> | |||
| </ul> | |||
| <h2 class="category">Lights</h2> | |||
| <ul> | |||
| <li><a href="./directional-light/">Directional Light </a></li> | |||
| <li><a href="./spot-light/">Spot Light </a></li> | |||
| <li><a href="./point-light/">Point Light </a></li> | |||
| <li><a href="./ambient-light/">Ambient Light </a></li> | |||
| <li><a href="./hemisphere-light/">Hemisphere Light </a></li> | |||
| <li><a href="./rect-area-light/">Rect Area Light </a></li> | |||
| </ul> | |||
| <h2 class="category">Tests</h2> | |||
| <ul> | |||
| <li><a href="./multi-viewer-test/">Multiple Viewers Test </a></li> | |||
| <li><a href="./gltf-transmission-test/">glTF Transmission Test </a></li> | |||
| <li><a href="./gltf-transmission-test-msaa/">glTF Transmission Test + MSAA </a></li> | |||
| <li><a href="./uint8-rgbm-hdr-test/">Uint8 RGBM HDR Test </a></li> | |||
| <li><a href="./half-float-hdr-test/">Half-float HDR Test </a></li> | |||
| <li><a href="./sphere-rgbm-test/">RGBM Test </a></li> | |||
| @@ -0,0 +1,57 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Multiple Viewers Test</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, .mcanvas, .container { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| .container{ | |||
| display: grid; | |||
| grid-template-columns: 1fr 1fr; | |||
| grid-template-rows: 1fr 1fr; | |||
| } | |||
| .canvas-container{ | |||
| position: relative; | |||
| width: 100%; | |||
| height: 100%; | |||
| overflow: hidden; | |||
| outline: 1px solid #464646; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div class="container"> | |||
| <div class="canvas-container"> | |||
| <canvas id="mcanvas1" class="mcanvas"></canvas> | |||
| </div> | |||
| <div class="canvas-container"> | |||
| <canvas id="mcanvas2" class="mcanvas"></canvas> | |||
| </div> | |||
| <div class="canvas-container"> | |||
| <canvas id="mcanvas3" class="mcanvas"></canvas> | |||
| </div> | |||
| <div class="canvas-container"> | |||
| <canvas id="mcanvas4" class="mcanvas"></canvas> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,37 @@ | |||
| import {_testFinish, ThreeViewer} from 'threepipe' | |||
| const models = [ | |||
| 'https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', | |||
| 'https://threejs.org/examples/models/fbx/Samba Dancing.fbx', | |||
| 'https://threejs.org/examples/models/draco/bunny.drc', | |||
| 'https://threejs.org/examples/models/gltf/kira.glb', | |||
| ] | |||
| async function init(i: number) { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas' + (i + 1)) as HTMLCanvasElement, | |||
| msaa: true, | |||
| debug: true, | |||
| dropzone: { | |||
| allowedExtensions: ['gltf', 'glb', 'hdr', 'bin', 'png', 'jpeg', 'webp', 'jpg', 'exr'], | |||
| addOptions: { | |||
| disposeSceneObjects: true, | |||
| autoSetEnvironment: true, // when hdr is dropped | |||
| autoSetBackground: true, | |||
| }, | |||
| }, | |||
| }) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', { | |||
| // setBackground: true, | |||
| }) | |||
| const result = await viewer.load(models[i], { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| console.log(result) | |||
| } | |||
| Promise.all(new Array(4).fill(0).map(async(_, i) => init(i))).then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>SparkleBump(NoiseBump) Material Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,42 @@ | |||
| import {_testFinish, IObject3D, NoiseBumpMaterialPlugin, PhysicalMaterial, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| }) | |||
| const noiseBump = viewer.addPluginSync(NoiseBumpMaterialPlugin) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', { | |||
| setBackground: true, | |||
| }) | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const model = result?.getObjectByName('node_damagedHelmet_-6514') | |||
| const materials = (model?.materials || []) as PhysicalMaterial[] | |||
| for (const material of materials) { | |||
| NoiseBumpMaterialPlugin.AddNoiseBumpMaterial(material, { | |||
| flakeScale: 300, | |||
| }) | |||
| // set properties like this or from the UI | |||
| // material.userData._noiseBumpMat!.bumpNoiseParams = [1, 1] | |||
| // material.setDirty() | |||
| // Add extra noise bump extension ui mapped to this material. | |||
| // This is also added inside the material ui by default by the material extension automatically. | |||
| const config = material.uiConfig | |||
| if (!config) continue | |||
| ui.appendChild(noiseBump.materialExtension.getUiConfig?.(material), {expanded: true}) | |||
| ui.appendChild(config) | |||
| } | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,38 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Object3D Generator Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "three": "./../../dist/index.mjs", | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane-editor": "./../../plugins/tweakpane-editor/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,44 @@ | |||
| import { | |||
| _testFinish, | |||
| CameraViewPlugin, | |||
| Object3DGeneratorPlugin, | |||
| Object3DWidgetsPlugin, | |||
| PickingPlugin, | |||
| ThreeViewer, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| import {HierarchyUiPlugin} from '@threepipe/plugin-tweakpane-editor' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| plugins: [PickingPlugin, CameraViewPlugin, Object3DWidgetsPlugin, HierarchyUiPlugin], | |||
| }) | |||
| const generator = viewer.addPluginSync(Object3DGeneratorPlugin) | |||
| viewer.scene.setBackgroundColor('#444466') | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| console.log(generator.generators) | |||
| const object = generator.generate('light-directional', {color: 0x00ff00}) | |||
| console.log(object) | |||
| viewer.getPlugin(PickingPlugin)?.setSelectedObject(object) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(Object3DGeneratorPlugin)!.expanded = true | |||
| ui.setupPluginUi(HierarchyUiPlugin) | |||
| ui.setupPluginUi(PickingPlugin) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,37 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Object3D Widgets Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "three": "./../../dist/index.mjs", | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,59 @@ | |||
| import { | |||
| _testFinish, | |||
| CameraViewPlugin, | |||
| Object3DGeneratorPlugin, | |||
| Object3DWidgetsPlugin, | |||
| ThreeViewer, | |||
| Vector3, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| plugins: [CameraViewPlugin, Object3DGeneratorPlugin], | |||
| }) | |||
| const widgets = viewer.addPluginSync(Object3DWidgetsPlugin) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(Object3DWidgetsPlugin) | |||
| viewer.scene.setBackgroundColor('#444466') | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| console.log(widgets.helpers) | |||
| const generator = viewer.getPlugin(Object3DGeneratorPlugin)! | |||
| let object | |||
| object = generator.generate('camera-perspective', { | |||
| position: new Vector3(5, 5, 0), | |||
| }) | |||
| ui.appendChild(object?.uiConfig) | |||
| object = generator.generate('light-directional', { | |||
| position: new Vector3(5, 0, 5), | |||
| }) | |||
| ui.appendChild(object?.uiConfig) | |||
| object = generator.generate('light-spot', { | |||
| position: new Vector3(-5, 0, 5), | |||
| }) | |||
| ui.appendChild(object?.uiConfig) | |||
| object = generator.generate('light-point', { | |||
| position: new Vector3(-5, 5, -5), | |||
| }) | |||
| ui.appendChild(object?.uiConfig) | |||
| viewer.scene.mainCamera.position.z += 10 | |||
| viewer.scene.mainCamera.setDirty() | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Picking (Selection) Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,33 @@ | |||
| import {_testFinish, IObject3D, PickingPlugin, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| }) | |||
| const picking = viewer.addPluginSync(PickingPlugin) | |||
| picking.hoverEnabled = true | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf') | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(PickingPlugin) | |||
| picking.addEventListener('hitObject', (e)=>{ | |||
| console.log('Hit object', e) | |||
| }) | |||
| picking.addEventListener('selectedObjectChanged', (e)=>{ | |||
| console.log('Selected Object Changed', e) | |||
| }) | |||
| picking.addEventListener('hoverObjectChanged', (e)=>{ | |||
| console.log('Hover Object Changed', e) | |||
| }) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Point Light</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,69 @@ | |||
| import { | |||
| _testFinish, | |||
| Box3B, | |||
| IObject3D, | |||
| Mesh, | |||
| Object3DWidgetsPlugin, | |||
| PCFSoftShadowMap, | |||
| PhysicalMaterial, | |||
| PlaneGeometry, | |||
| PointLight2, | |||
| RenderTargetPreviewPlugin, | |||
| ThreeViewer, | |||
| Vector3, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| dropzone: { | |||
| allowedExtensions: ['gltf', 'glb', 'hdr', 'obj', 'fbx', 'bin', 'png', 'jpeg', 'webp', 'jpg', 'exr'], | |||
| addOptions: { | |||
| disposeSceneObjects: true, | |||
| autoSetEnvironment: true, // when hdr/exr is dropped | |||
| }, | |||
| }, | |||
| plugins: [Object3DWidgetsPlugin], | |||
| }) | |||
| // viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/fbx/Samba Dancing.fbx', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const ground = new Mesh( | |||
| new PlaneGeometry(100, 100) | |||
| .rotateX(-Math.PI / 2) | |||
| .translate(0, new Box3B().expandByObject(result!).getSize(new Vector3()).y / -2, 0), | |||
| new PhysicalMaterial({ | |||
| color: '#ffffff', | |||
| }) | |||
| ) | |||
| ground.castShadow = false | |||
| ground.receiveShadow = true | |||
| viewer.scene.addObject(ground) | |||
| const light = viewer.scene.addObject(new PointLight2(0xffffff, 8)) | |||
| light.position.set(0, 4, 1) | |||
| light.lookAt(0, 0, 0) | |||
| light.distance = 10 | |||
| light.decay = 1 | |||
| light.castShadow = true | |||
| light.shadow.mapSize.setScalar(1024) | |||
| light.shadow.camera.near = 0.1 | |||
| light.shadow.camera.far = 10 | |||
| viewer.renderManager.renderer.shadowMap.type = PCFSoftShadowMap | |||
| const rt = viewer.addPluginSync(RenderTargetPreviewPlugin) | |||
| rt.addTarget(()=>light.shadow.map || undefined, 'shadow', true, true, true) | |||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | |||
| ui.appendChild(light.uiConfig, {expanded: true}) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,45 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Pointer Lock Controls Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| #pointerLockOverlay{ | |||
| position: absolute; top: 0; left: 0; right: 0; bottom: 0; height: 100%; width: 100%; | |||
| display: flex; justify-content: center; align-items: center; pointer-events: none; | |||
| font-size: 1.5rem; background: rgba(240,240,240,0.5); color: #333333; | |||
| backdrop-filter: blur(16px); | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| <div id="pointerLockOverlay"> | |||
| Tap the screen to enable pointer lock controls | |||
| </div> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,29 @@ | |||
| import {_testFinish, IObject3D, PointerLockControlsPlugin, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| plugins: [PointerLockControlsPlugin], | |||
| }) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.appendChild(viewer.scene.mainCamera.uiConfig) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| viewer.scene.mainCamera.controlsMode = 'pointerLock' | |||
| const overlayEl = document.getElementById('pointerLockOverlay') as HTMLDivElement | |||
| viewer.scene.mainCamera.controls?.addEventListener('lock', ()=> overlayEl.style.display = 'none') | |||
| viewer.scene.mainCamera.controls?.addEventListener('unlock', ()=> overlayEl.style.display = 'flex') | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -1,4 +1,4 @@ | |||
| import {_testFinish, BoxGeometry, Color, Mesh, PhysicalMaterial, PopmotionPlugin, ThreeViewer} from 'threepipe' | |||
| import {_testFinish, BoxGeometry, Color, Mesh, PhysicalMaterial, PopmotionPlugin, ThreeViewer, Vector3} from 'threepipe' | |||
| import {createSimpleButtons} from '../examples-utils/simple-bottom-buttons.js' | |||
| async function init() { | |||
| @@ -20,16 +20,11 @@ async function init() { | |||
| createSimpleButtons({ | |||
| ['Move Up/Down']: async(btn) => { | |||
| btn.disabled = true | |||
| await popmotion.animateAsync({ | |||
| from: cube.position.y, | |||
| to: cube.position.y + (isMovedUp ? -1 : 1), | |||
| await popmotion.animateTargetAsync(cube, 'position', { | |||
| to: cube.position.clone().add(new Vector3(0, isMovedUp ? -1 : 1, 0)), | |||
| duration: 500, // ms | |||
| onUpdate: (v) => { | |||
| cube.position.setY(v) | |||
| cube.setDirty() | |||
| }, | |||
| onComplete: () => isMovedUp = !isMovedUp, | |||
| }) | |||
| }) // setDirty is automatically called on the cube since it's the target | |||
| btn.disabled = false | |||
| }, | |||
| ['Rotate +90deg']: async(btn) => { | |||
| @@ -0,0 +1,56 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Threepipe React/JS Sample</title> | |||
| <style> | |||
| html, body{ | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| </head> | |||
| <body> | |||
| <div id="root"></div> | |||
| <script id="example-script" type="module" data-scripts="./index.html"> | |||
| // import {ThreeViewer} from 'https://threepipe.org/dist/index.mjs' | |||
| import {ThreeViewer} from './../../dist/index.mjs' | |||
| import React from 'https://esm.sh/react' | |||
| import ReactDOM from 'https://esm.sh/react-dom' | |||
| function ThreeViewerComponent({ src }) { | |||
| const canvasRef = React.useRef(null); | |||
| React.useEffect(() => { | |||
| const viewer = new ThreeViewer({canvas: canvasRef.current}) | |||
| // Load an environment map | |||
| const envPromise = viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const modelPromise = viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| Promise.all([envPromise, modelPromise]).then(([env, model])=>{ | |||
| console.log('Loaded', model, env, viewer) | |||
| }) | |||
| return () => { | |||
| viewer.dispose() | |||
| } | |||
| }, []); | |||
| return React.createElement( | |||
| 'canvas', | |||
| {id: 'three-canvas', style: {width: 800, height: 600}, ref: canvasRef}, | |||
| ) | |||
| } | |||
| ReactDOM.render( | |||
| React.createElement(ThreeViewerComponent), | |||
| document.getElementById('root') | |||
| ) | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,60 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Threepipe React/JSX Sample</title> | |||
| <style> | |||
| html, body{ | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <!-- Include Babel for JSX transformation --> | |||
| <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="root"></div> | |||
| <script id="example-script" type="text/babel" data-scripts="./index.html" data-type="module"> | |||
| // import {ThreeViewer} from 'https://threepipe.org/dist/index.mjs' | |||
| import {ThreeViewer} from './../../dist/index.mjs' | |||
| import React from 'https://esm.sh/react' | |||
| import ReactDOM from 'https://esm.sh/react-dom' | |||
| function ThreeViewerComponent({ src, env }) { | |||
| const canvasRef = React.useRef(null); | |||
| React.useEffect(() => { | |||
| const viewer = new ThreeViewer({canvas: canvasRef.current}) | |||
| // Load an environment map | |||
| const envPromise = viewer.setEnvironmentMap(env) | |||
| const modelPromise = viewer.load(src, { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| Promise.all([envPromise, modelPromise]).then(([env, model])=>{ | |||
| console.log('Loaded', model, env, viewer) | |||
| }) | |||
| return () => { | |||
| viewer.dispose() | |||
| } | |||
| }, []); | |||
| return ( | |||
| <canvas id="three-canvas" style={{ width: 800, height: 600 }} ref={canvasRef} /> | |||
| ) | |||
| } | |||
| ReactDOM.render( | |||
| <ThreeViewerComponent | |||
| src={'https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf'} | |||
| env={'https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'} | |||
| />, | |||
| document.getElementById('root') | |||
| ) | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Threepipe React/TSX Sample</title> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "react": "https://esm.sh/react", | |||
| "react-dom": "https://esm.sh/react-dom" | |||
| } | |||
| } | |||
| </script> | |||
| <style> | |||
| html, body{ | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.tsx;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="root"></div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,41 @@ | |||
| import {_testFinish, ThreeViewer} from 'threepipe' | |||
| // @ts-expect-error no need react here | |||
| import React from 'react' | |||
| // @ts-expect-error no need react-dom here | |||
| import ReactDOM from 'react-dom' | |||
| function ThreeViewerComponent({src, env}: {src: string, env: string}) { | |||
| const canvasRef = React.useRef(null) | |||
| React.useEffect(() => { | |||
| const viewer = new ThreeViewer({canvas: canvasRef.current}) | |||
| // Load an environment map | |||
| const envPromise = viewer.setEnvironmentMap(env) | |||
| const modelPromise = viewer.load(src, { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| Promise.all([envPromise, modelPromise]).then(([env, model])=>{ | |||
| console.log('Loaded', model, env, viewer) | |||
| }) | |||
| return () => { | |||
| viewer.dispose() | |||
| } | |||
| }, []) | |||
| return ( | |||
| <canvas id="three-canvas" style={{width: 800, height: 600}} ref={canvasRef} /> | |||
| ) | |||
| } | |||
| async function init() { | |||
| ReactDOM.render( | |||
| <ThreeViewerComponent | |||
| src={'https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf'} | |||
| env={'https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'} | |||
| />, | |||
| document.getElementById('root') | |||
| ) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Rect Area Light</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,56 @@ | |||
| import { | |||
| _testFinish, | |||
| Box3B, | |||
| IObject3D, | |||
| Mesh, | |||
| Object3DWidgetsPlugin, | |||
| PhysicalMaterial, | |||
| PlaneGeometry, | |||
| RectAreaLight2, | |||
| ThreeViewer, | |||
| Vector3, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| dropzone: { | |||
| allowedExtensions: ['gltf', 'glb', 'hdr', 'obj', 'fbx', 'bin', 'png', 'jpeg', 'webp', 'jpg', 'exr'], | |||
| addOptions: { | |||
| disposeSceneObjects: true, | |||
| autoSetEnvironment: true, // when hdr/exr is dropped | |||
| }, | |||
| }, | |||
| plugins: [Object3DWidgetsPlugin], | |||
| }) | |||
| // viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/ShadowmappableMesh.glb', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const ground = new Mesh( | |||
| new PlaneGeometry(100, 100) | |||
| .rotateX(-Math.PI / 2) | |||
| .translate(0, new Box3B().expandByObject(result!).getSize(new Vector3()).y / -2, 0), | |||
| new PhysicalMaterial({ | |||
| color: '#ffffff', | |||
| }) | |||
| ) | |||
| viewer.scene.addObject(ground) | |||
| const light = viewer.scene.addObject(new RectAreaLight2(0xffffff, 4)) | |||
| light.position.set(2, 4, 0) | |||
| light.lookAt(0, 4, 0) | |||
| light.width = 2 | |||
| light.height = 10 | |||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | |||
| ui.appendChild(light.uiConfig, {expanded: true}) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,54 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Blend Load</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-gaussian-splatting": "./../../plugins/gaussian-splatting/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module"> | |||
| import {_testFinish, ThreeViewer} from 'threepipe' | |||
| import {GaussianSplattingPlugin} from '@threepipe/plugin-gaussian-splatting' | |||
| const viewer = new ThreeViewer({canvas: document.getElementById('mcanvas')}) | |||
| viewer.addPluginsSync([GaussianSplattingPlugin]) | |||
| async function init() { | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const result = await viewer.load('https://asset-samples.threepipe.org/splat/bonsai.splat', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| console.log(result) | |||
| } | |||
| init().then(_testFinish) | |||
| </script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Spot Light</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,73 @@ | |||
| import { | |||
| _testFinish, | |||
| Box3B, | |||
| IObject3D, | |||
| Mesh, | |||
| Object3DWidgetsPlugin, | |||
| PCFSoftShadowMap, | |||
| PhysicalMaterial, | |||
| PlaneGeometry, | |||
| RenderTargetPreviewPlugin, | |||
| SpotLight2, | |||
| ThreeViewer, | |||
| Vector3, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| dropzone: { | |||
| allowedExtensions: ['gltf', 'glb', 'hdr', 'obj', 'fbx', 'bin', 'png', 'jpeg', 'webp', 'jpg', 'exr'], | |||
| addOptions: { | |||
| disposeSceneObjects: true, | |||
| autoSetEnvironment: true, // when hdr/exr is dropped | |||
| }, | |||
| }, | |||
| plugins: [Object3DWidgetsPlugin], | |||
| }) | |||
| // viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/fbx/Samba Dancing.fbx', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const ground = new Mesh( | |||
| new PlaneGeometry(100, 100) | |||
| .rotateX(-Math.PI / 2) | |||
| .translate(0, new Box3B().expandByObject(result!).getSize(new Vector3()).y / -2, 0), | |||
| new PhysicalMaterial({ | |||
| color: '#ffffff', | |||
| }) | |||
| ) | |||
| ground.castShadow = false | |||
| ground.receiveShadow = true | |||
| viewer.scene.addObject(ground) | |||
| const light = viewer.scene.addObject(new SpotLight2(0xffffff, 10)) | |||
| light.position.set(2, 2, 2) | |||
| light.lookAt(0, 0, 0) | |||
| light.angle = 0.5 | |||
| light.penumbra = 0.2 | |||
| light.distance = 5 | |||
| light.decay = 0.5 | |||
| light.castShadow = true | |||
| light.shadow.mapSize.setScalar(1024) | |||
| light.shadow.camera.near = 0.1 | |||
| light.shadow.camera.far = 10 | |||
| light.shadow.camera.aspect = 1 | |||
| light.shadow.camera.fov = 45 | |||
| viewer.renderManager.renderer.shadowMap.type = PCFSoftShadowMap | |||
| const rt = viewer.addPluginSync(RenderTargetPreviewPlugin) | |||
| rt.addTarget(()=>light.shadow.map || undefined, 'shadow', true, true, true) | |||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | |||
| ui.appendChild(light.uiConfig, {expanded: true}) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,29 @@ | |||
| <script> | |||
| import {onDestroy, onMount} from 'svelte'; | |||
| const {ThreeViewer} = window.threepipe; // umd imported from unpkg in index.html | |||
| // or | |||
| // import {ThreeViewer} from 'threepipe'; // esm imported from npm | |||
| let canvasRef; | |||
| let viewer; | |||
| onMount(() => { | |||
| viewer = new ThreeViewer({canvas: canvasRef}); | |||
| // Load an environment map | |||
| const envPromise = viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'); | |||
| const modelPromise = viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }); | |||
| Promise.all([envPromise, modelPromise]).then(([env, model]) => { | |||
| console.log('Loaded', model, env, viewer); | |||
| }); | |||
| }); | |||
| onDestroy(() => viewer.dispose()) | |||
| </script> | |||
| <canvas bind:this={canvasRef} id="three-canvas" style="width: 800px; height: 600px"></canvas> | |||
| @@ -0,0 +1,47 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Threepipe Svelte Sample</title> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style> | |||
| html, body{ | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script src="./../../dist/index.js"></script> | |||
| <!-- <script src="https://unpkg.com/threepipe"></script>--> | |||
| <script src="https://unpkg.com/svelte-browser-import"></script> | |||
| </head> | |||
| <body> | |||
| <div id="app"> | |||
| </div> | |||
| <script type="module" data-scripts="./App.svelte" id="example-script"> | |||
| window["svelte-browser-import"].importSvelte('./App.svelte').then(App=> { | |||
| const app = new App({ | |||
| target: document.getElementById('app'), | |||
| }) | |||
| // to destroy the app | |||
| // app.$destroy() | |||
| }) | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,45 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Three First Person Controls Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| #firstPersonControlsOverlay{ | |||
| position: absolute; top: 0; left: 0; right: 0; bottom: 0; height: 100%; width: 100%; | |||
| display: flex; justify-content: center; align-items: center; cursor: pointer; | |||
| font-size: 1.5rem; background: rgba(240,240,240,0.5); color: #333333; | |||
| backdrop-filter: blur(16px); | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| <div id="firstPersonControlsOverlay"> | |||
| Tap the screen to enable three first person(look around) controls | |||
| </div> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,30 @@ | |||
| import {_testFinish, IObject3D, ThreeFirstPersonControlsPlugin, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| plugins: [ThreeFirstPersonControlsPlugin], | |||
| }) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.appendChild(viewer.scene.mainCamera.uiConfig) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const overlayEl = document.getElementById('firstPersonControlsOverlay') as HTMLDivElement | |||
| overlayEl.addEventListener('click', () => { | |||
| viewer.scene.mainCamera.controlsMode = 'threeFirstPerson' | |||
| overlayEl.style.display = 'none' | |||
| }) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Transform Controls Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,32 @@ | |||
| import {_testFinish, IObject3D, PickingPlugin, ThreeViewer, TransformControlsPlugin} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| }) | |||
| viewer.scene.setBackgroundColor(0x151822) | |||
| const picking = viewer.addPluginSync(PickingPlugin) | |||
| const transformControlsPlugin = viewer.addPluginSync(TransformControlsPlugin) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const model = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf') | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(TransformControlsPlugin, {expanded: true}) | |||
| ui.setupPluginUi(PickingPlugin) | |||
| // Get the underlying transform controls (instance of TransformControls2) | |||
| const transformControls = transformControlsPlugin.transformControls | |||
| console.log(transformControls) | |||
| // Transform controls plugin automatically tracks the selected object in the PickingPlugin and shows the transform controls | |||
| picking.setSelectedObject(model) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -28,10 +28,12 @@ | |||
| "es2020", | |||
| "esnext", | |||
| "dom" | |||
| ] | |||
| ], | |||
| "jsx": "react" | |||
| }, | |||
| "include": [ | |||
| "./**/*.ts" | |||
| "./**/*.ts", | |||
| "./**/*.tsx" | |||
| ], | |||
| "exclude": [ | |||
| "node_modules", | |||
| @@ -19,7 +19,10 @@ | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane-editor": "./../../plugins/tweakpane-editor/dist/index.mjs", | |||
| "@threepipe/plugin-extra-importers": "./../../plugins/extra-importers/dist/index.mjs" | |||
| "@threepipe/plugin-extra-importers": "./../../plugins/extra-importers/dist/index.mjs", | |||
| "@threepipe/plugin-blend-importer": "./../../plugins/blend-importer/dist/index.mjs", | |||
| "@threepipe/plugin-geometry-generator": "./../../plugins/geometry-generator/dist/index.mjs", | |||
| "@threepipe/plugin-gaussian-splatting": "./../../plugins/gaussian-splatting/dist/index.mjs" | |||
| } | |||
| } | |||
| @@ -32,7 +35,7 @@ | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <body class="code-preview-container"> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| @@ -1,33 +1,59 @@ | |||
| import { | |||
| _testFinish, | |||
| CameraViewPlugin, | |||
| CanvasSnapshotPlugin, | |||
| ChromaticAberrationPlugin, | |||
| ClearcoatTintPlugin, | |||
| ContactShadowGroundPlugin, | |||
| CustomBumpMapPlugin, | |||
| DepthBufferPlugin, | |||
| DeviceOrientationControlsPlugin, | |||
| DropzonePlugin, | |||
| EditorViewWidgetPlugin, | |||
| FilmicGrainPlugin, | |||
| FragmentClippingExtensionPlugin, | |||
| FrameFadePlugin, | |||
| FullScreenPlugin, | |||
| GBufferPlugin, | |||
| GLTFAnimationPlugin, | |||
| HalfFloatType, | |||
| HDRiGroundPlugin, | |||
| HemisphereLight, | |||
| KTX2LoadPlugin, | |||
| KTXLoadPlugin, | |||
| NoiseBumpMaterialPlugin, | |||
| NormalBufferPlugin, | |||
| Object3DGeneratorPlugin, | |||
| Object3DWidgetsPlugin, | |||
| PickingPlugin, | |||
| PLYLoadPlugin, | |||
| PointerLockControlsPlugin, | |||
| ProgressivePlugin, | |||
| RenderTargetPreviewPlugin, | |||
| Rhino3dmLoadPlugin, | |||
| SceneUiConfigPlugin, | |||
| STLLoadPlugin, | |||
| ThreeFirstPersonControlsPlugin, | |||
| ThreeViewer, | |||
| TonemapPlugin, | |||
| TransformControlsPlugin, | |||
| USDZLoadPlugin, | |||
| ViewerUiConfigPlugin, | |||
| VignettePlugin, | |||
| VirtualCamerasPlugin, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| import {TweakpaneEditorPlugin} from '@threepipe/plugin-tweakpane-editor' | |||
| import {HierarchyUiPlugin, TweakpaneEditorPlugin} from '@threepipe/plugin-tweakpane-editor' | |||
| import {BlendLoadPlugin} from '@threepipe/plugin-blend-importer' | |||
| import {extraImportPlugins} from '@threepipe/plugin-extra-importers' | |||
| import {GeometryGeneratorPlugin} from '@threepipe/plugin-geometry-generator' | |||
| import {GaussianSplattingPlugin} from '@threepipe/plugin-gaussian-splatting' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| renderScale: 'auto', | |||
| msaa: true, | |||
| rgbm: true, | |||
| zPrepass: false, // set it to true if you only have opaque objects in the scene to get better performance. | |||
| @@ -44,34 +70,68 @@ async function init() { | |||
| await viewer.addPlugins([ | |||
| new ProgressivePlugin(), | |||
| new GLTFAnimationPlugin(), | |||
| new ViewerUiConfigPlugin(), | |||
| GLTFAnimationPlugin, | |||
| PickingPlugin, | |||
| new TransformControlsPlugin(false), | |||
| EditorViewWidgetPlugin, | |||
| CameraViewPlugin, | |||
| ViewerUiConfigPlugin, | |||
| ClearcoatTintPlugin, | |||
| FragmentClippingExtensionPlugin, | |||
| NoiseBumpMaterialPlugin, | |||
| CustomBumpMapPlugin, | |||
| VirtualCamerasPlugin, | |||
| // new SceneUiConfigPlugin(), // this is already in ViewerUiPlugin | |||
| new DepthBufferPlugin(HalfFloatType, true, true), | |||
| new GBufferPlugin(HalfFloatType, true, true, true), | |||
| new DepthBufferPlugin(HalfFloatType, false, false), | |||
| new NormalBufferPlugin(HalfFloatType, false), | |||
| new RenderTargetPreviewPlugin(false), | |||
| new FrameFadePlugin(), | |||
| new HDRiGroundPlugin(false, true), | |||
| new VignettePlugin(false), | |||
| new ChromaticAberrationPlugin(false), | |||
| new FilmicGrainPlugin(false), | |||
| KTX2LoadPlugin, | |||
| KTXLoadPlugin, | |||
| PLYLoadPlugin, | |||
| Rhino3dmLoadPlugin, | |||
| STLLoadPlugin, | |||
| USDZLoadPlugin, | |||
| BlendLoadPlugin, | |||
| HierarchyUiPlugin, | |||
| GeometryGeneratorPlugin, | |||
| Object3DWidgetsPlugin, | |||
| Object3DGeneratorPlugin, | |||
| GaussianSplattingPlugin, | |||
| ContactShadowGroundPlugin, | |||
| CanvasSnapshotPlugin, | |||
| DeviceOrientationControlsPlugin, | |||
| PointerLockControlsPlugin, | |||
| ThreeFirstPersonControlsPlugin, | |||
| ...extraImportPlugins, | |||
| ]) | |||
| const rt = viewer.getOrAddPluginSync(RenderTargetPreviewPlugin) | |||
| rt.addTarget({texture: viewer.getPlugin(GBufferPlugin)?.normalDepthTexture}, 'normalDepth') | |||
| rt.addTarget({texture: viewer.getPlugin(GBufferPlugin)?.flagsTexture}, 'gBufferFlags') | |||
| rt.addTarget(viewer.getPlugin(DepthBufferPlugin)?.target, 'depth', false, false, false) | |||
| rt.addTarget(viewer.getPlugin(NormalBufferPlugin)?.target, 'normal', false, true, false) | |||
| editor.loadPlugins({ | |||
| ['Viewer']: [ViewerUiConfigPlugin, SceneUiConfigPlugin, DropzonePlugin, FullScreenPlugin], | |||
| ['GBuffer']: [DepthBufferPlugin, NormalBufferPlugin], | |||
| ['Post-processing']: [TonemapPlugin, ProgressivePlugin, FrameFadePlugin], | |||
| ['Animation']: [GLTFAnimationPlugin], | |||
| ['Viewer']: [ViewerUiConfigPlugin, SceneUiConfigPlugin, DropzonePlugin, FullScreenPlugin, TweakpaneUiPlugin], | |||
| ['Scene']: [ContactShadowGroundPlugin], | |||
| ['Interaction']: [HierarchyUiPlugin, TransformControlsPlugin, PickingPlugin, Object3DGeneratorPlugin, GeometryGeneratorPlugin, EditorViewWidgetPlugin, Object3DWidgetsPlugin, DeviceOrientationControlsPlugin, PointerLockControlsPlugin, ThreeFirstPersonControlsPlugin], | |||
| ['GBuffer']: [GBufferPlugin, DepthBufferPlugin, NormalBufferPlugin], | |||
| ['Post-processing']: [TonemapPlugin, ProgressivePlugin, FrameFadePlugin, VignettePlugin, ChromaticAberrationPlugin, FilmicGrainPlugin], | |||
| ['Export']: [CanvasSnapshotPlugin], | |||
| ['Animation']: [GLTFAnimationPlugin, CameraViewPlugin], | |||
| ['Extras']: [HDRiGroundPlugin, Rhino3dmLoadPlugin, ClearcoatTintPlugin, FragmentClippingExtensionPlugin, NoiseBumpMaterialPlugin, CustomBumpMapPlugin, VirtualCamerasPlugin], | |||
| ['Debug']: [RenderTargetPreviewPlugin], | |||
| }) | |||
| const hemiLight = viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 5)) | |||
| hemiLight.name = 'Hemisphere Light' | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| // const result = await viewer.load<IObject3D>('https://cdn.jsdelivr.net/gh/KhronosGroup/glTF-Blender-Exporter@master/polly/project_polly.gltf', { | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Tweakpane Ui Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,26 @@ | |||
| import {_testFinish, IObject3D, ThreeViewer, TonemapPlugin} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| }) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.appendChild(viewer.uiConfig) | |||
| ui.setupPluginUi(TonemapPlugin) | |||
| ui.setupPluginUi(TweakpaneUiPlugin) // to change the color scheme | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const mesh = result?.getObjectByName('node_damagedHelmet_-6514') | |||
| ui.appendChild(mesh?.uiConfig) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Vignette Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,20 @@ | |||
| import {_testFinish, IObject3D, ThreeViewer, VignettePlugin} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| }) | |||
| viewer.addPluginSync(VignettePlugin) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf') | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| ui.setupPluginUi(VignettePlugin) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Virtual Camera</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,85 @@ | |||
| import { | |||
| _testFinish, | |||
| IObject3D, | |||
| LinearToneMapping, | |||
| Mesh, | |||
| PerspectiveCamera2, | |||
| PlaneGeometry, | |||
| PopmotionPlugin, | |||
| ProgressivePlugin, | |||
| Texture, | |||
| ThreeViewer, | |||
| ToneMapping, | |||
| TonemapPlugin, | |||
| UnlitMaterial, | |||
| VirtualCamerasPlugin, | |||
| } from 'threepipe' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| debug: true, | |||
| plugins: [new ProgressivePlugin(16)], | |||
| }) | |||
| const virtualCameras = viewer.addPluginSync(VirtualCamerasPlugin) | |||
| const popmotion = viewer.addPluginSync(PopmotionPlugin) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| const aspect = 2 | |||
| const plane = new Mesh( | |||
| new PlaneGeometry(5 * aspect, 5) | |||
| .translate(0, 0, -3), | |||
| new UnlitMaterial({ | |||
| color: '#ffffff', | |||
| }) | |||
| ) | |||
| plane.castShadow = false | |||
| plane.receiveShadow = true | |||
| viewer.scene.addObject(plane) | |||
| const camera = new PerspectiveCamera2('', viewer.canvas, false, 45, aspect) | |||
| camera.position.set(0, 0, 5) | |||
| camera.target.set(0, 0.25, 0) | |||
| camera.userData.autoLookAtTarget = true | |||
| camera.near = 1 | |||
| camera.far = 10 | |||
| camera.setDirty() | |||
| const vCam = virtualCameras.addCamera(camera) | |||
| plane.material.map = vCam.target.texture as Texture | |||
| popmotion.animate({ | |||
| from: 0, | |||
| to: 1, | |||
| repeat: Infinity, | |||
| duration: 6000, | |||
| onUpdate: (v)=>{ | |||
| // Set camera position xz in a circle around the target | |||
| const angle = v * Math.PI * 2 + Math.PI / 2 | |||
| const radius = 5 | |||
| camera.position.set(Math.cos(angle) * radius, 0, Math.sin(angle) * radius) | |||
| camera.setDirty() | |||
| viewer.setDirty() // since camera is not in the scene | |||
| }, | |||
| }) | |||
| // We need to disable tonemapping when rendering the virtual camera, otherwise the tonemapping will be applied multiple times. | |||
| let lastTonemapping: ToneMapping = LinearToneMapping | |||
| const tonemap = viewer.getPlugin(TonemapPlugin)! | |||
| virtualCameras.addEventListener('preRenderCamera', ()=>{ | |||
| lastTonemapping = tonemap.toneMapping | |||
| // Comment this and see what happens to the color in the plane | |||
| tonemap.toneMapping = LinearToneMapping | |||
| }) | |||
| virtualCameras.addEventListener('postRenderCamera', ()=>{ | |||
| tonemap.toneMapping = lastTonemapping | |||
| }) | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Virtual Cameras Plugin</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,69 @@ | |||
| import { | |||
| _testFinish, | |||
| HemisphereLight, | |||
| IObject3D, | |||
| PerspectiveCamera2, | |||
| ProgressivePlugin, | |||
| RenderTargetPreviewPlugin, | |||
| ThreeViewer, | |||
| Vector3, | |||
| VirtualCamerasPlugin, | |||
| } from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| debug: true, | |||
| plugins: [new ProgressivePlugin(16)], | |||
| }) | |||
| const virtualCameras = viewer.addPluginSync(VirtualCamerasPlugin) | |||
| viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/fbx/Samba Dancing.fbx', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| viewer.scene.mainCamera.position.set(5, 5, 5) | |||
| viewer.scene.mainCamera.target.set(0, 0.25, 0) | |||
| viewer.scene.mainCamera.setDirty() | |||
| const views = [ | |||
| [new Vector3(5, 0, 0), 'right'], | |||
| [new Vector3(0, 5, 0), 'top'], | |||
| [new Vector3(0, 0, 5), 'front'], | |||
| ] as const | |||
| const rt = viewer.addPluginSync(RenderTargetPreviewPlugin) | |||
| const ui = viewer.addPluginSync(TweakpaneUiPlugin, true) | |||
| ui.appendChild(viewer.scene.mainCamera.uiConfig) | |||
| for (const [view, name] of views) { | |||
| const camera = new PerspectiveCamera2('', viewer.canvas, false, 45, 1) | |||
| camera.name = name | |||
| camera.position.copy(view) | |||
| camera.target.set(0, 0.25, 0) | |||
| camera.userData.autoLookAtTarget = true | |||
| camera.setDirty() | |||
| camera.addEventListener('update', ()=>{ | |||
| viewer.setDirty() // since the camera is not added to the scene it wont update automatically when setDirty is called(like from the UI) | |||
| }) | |||
| viewer.scene.mainCamera.addEventListener('update', ()=>{ | |||
| camera.target.copy(viewer.scene.mainCamera.target) // sync the lookAt target of all the cameras | |||
| camera.setDirty() | |||
| }) | |||
| const vCam = virtualCameras.addCamera(camera) | |||
| rt.addTarget(()=>vCam.target, name, false, false, true) | |||
| ui.appendChild(camera.uiConfig) | |||
| } | |||
| } | |||
| init().then(_testFinish) | |||
| @@ -0,0 +1,57 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Threepipe Vue/HTML Sample</title> | |||
| <style> | |||
| html, body{ | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| </head> | |||
| <body> | |||
| <div id="app"> | |||
| <canvas id="three-canvas" style="width: 800px; height: 600px" ref="canvasRef"></canvas> | |||
| </div> | |||
| <script id="example-script" type="module" data-scripts="./index.html"> | |||
| // import { ThreeViewer } from 'https://threepipe.org/dist/index.mjs' | |||
| import { ThreeViewer } from './../../dist/index.mjs' | |||
| import { createApp, ref, onMounted, onBeforeUnmount } from "https://unpkg.com/vue@3/dist/vue.esm-browser.prod.js"; | |||
| const ThreeViewerComponent = { | |||
| setup() { | |||
| const canvasRef = ref(null); | |||
| onMounted(() => { | |||
| const viewer = new ThreeViewer({ canvas: canvasRef.value }); | |||
| // Load an environment map | |||
| const envPromise = viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'); | |||
| const modelPromise = viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }); | |||
| Promise.all([envPromise, modelPromise]).then(([env, model]) => { | |||
| console.log('Loaded', model, env, viewer); | |||
| }); | |||
| onBeforeUnmount(() => { | |||
| viewer.dispose(); | |||
| }); | |||
| }); | |||
| return { canvasRef }; | |||
| }, | |||
| }; | |||
| const app = createApp(ThreeViewerComponent); | |||
| app.mount('#app'); | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,48 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Threepipe React/TSX Sample</title> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.prod.js", | |||
| "vue-import": "https://unpkg.com/vue-import/dist/vue-import.esm-browser.js" | |||
| } | |||
| } | |||
| </script> | |||
| <!-- "vue-import": "./vue-import/dist/vue-import.esm-browser.prod.js"--> | |||
| <style> | |||
| html, body{ | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| </head> | |||
| <body> | |||
| <div id="app"> | |||
| <three-viewer></three-viewer> | |||
| </div> | |||
| <script type="module" data-scripts="./script.vue" id="example-script"> | |||
| import { createApp } from 'vue'; | |||
| import vueImport from 'vue-import'; | |||
| (async ()=>{ | |||
| const app = createApp(); | |||
| app.component('three-viewer', await vueImport('script.vue', {})) | |||
| app.mount('#app'); | |||
| })() | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,36 @@ | |||
| <template> | |||
| <canvas id="three-canvas" style="width: 800px; height: 600px" ref="canvasRef"></canvas> | |||
| </template> | |||
| <script> | |||
| import {ThreeViewer} from "threepipe"; | |||
| import {onBeforeUnmount, onMounted, ref} from "vue" | |||
| export default { | |||
| setup() { | |||
| const canvasRef = ref(null); | |||
| onMounted(() => { | |||
| const viewer = new ThreeViewer({canvas: canvasRef.value}); | |||
| // Load an environment map | |||
| const envPromise = viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr'); | |||
| const modelPromise = viewer.load('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }); | |||
| Promise.all([envPromise, modelPromise]).then(([env, model]) => { | |||
| console.log('Loaded', model, env, viewer); | |||
| }); | |||
| onBeforeUnmount(() => { | |||
| viewer.dispose(); | |||
| }); | |||
| }); | |||
| return {canvasRef}; | |||
| }, | |||
| }; | |||
| </script> | |||
| @@ -1,25 +1,33 @@ | |||
| { | |||
| "name": "threepipe", | |||
| "version": "0.0.13", | |||
| "version": "0.0.24", | |||
| "description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.", | |||
| "main": "src/index.ts", | |||
| "main": "dist/index.js", | |||
| "module": "dist/index.mjs", | |||
| "types": "src/index.ts", | |||
| "sources": "src/index.ts", | |||
| "browser": "dist/index.js", | |||
| "type": "module", | |||
| "scripts": { | |||
| "compile": "rimraf lib && npm run compile:esm && npm run copy:css", | |||
| "compile:esm": "tsc -p ./src", | |||
| "copy:css": "copyfiles -u 1 \"src/**/*.css\" lib", | |||
| "new:pack": "npm run prepare && clean-package && npm pack && clean-package restore", | |||
| "new:publish": "npm run prepare && clean-package && npm publish && clean-package restore", | |||
| "build": "rimraf dist && npm run update-version && NODE_ENV=production rollup -c", | |||
| "dev": "rollup -c -w", | |||
| "build:rollup": "rimraf dist && npm run update-version && NODE_ENV=production rollup -c", | |||
| "build": "npm run update-version && vite build", | |||
| "dev:rollup": "rollup -c -w", | |||
| "dev": "NODE_ENV=development vite build --watch", | |||
| "build-examples": "tsc --project examples/tsconfig.build.json", | |||
| "dev-examples": "tsc --project examples/tsconfig.build.json -w", | |||
| "serve-docs": "ws -d docs -p 8080", | |||
| "serve": "ws -d . -p 9229", | |||
| "docs": "npx typedoc && markdown-to-html", | |||
| "build-plugins": "node scripts/build-plugins.mjs", | |||
| "prepare": "npm run build && npm run build-plugins && npm run build-examples", | |||
| "update-version": "node scripts/update-version.mjs" | |||
| "docs-plugins": "node scripts/each-plugin.mjs run docs", | |||
| "docs-all": "npm run docs && npm run docs-plugins", | |||
| "build-plugins": "node scripts/each-plugin.mjs install", | |||
| "prepare": "npm run build && npm run compile && npm run build-plugins && npm run build-examples", | |||
| "update-version": "node scripts/update-version.mjs" | |||
| }, | |||
| "clean-package": { | |||
| "remove": [ | |||
| @@ -73,12 +81,14 @@ | |||
| "@rollup/plugin-commonjs": "^25.0.0", | |||
| "@rollup/plugin-json": "^6.0.0", | |||
| "@rollup/plugin-node-resolve": "^15.0.2", | |||
| "@rollup/plugin-replace": "^5.0.2", | |||
| "@rollup/plugin-terser": "^0.4.3", | |||
| "@rollup/plugin-typescript": "^11.1.1", | |||
| "@rollup/plugin-typescript": "^11.1.5", | |||
| "@types/stats.js": "^0.17.0", | |||
| "@typescript-eslint/eslint-plugin": "^5.59.7", | |||
| "@typescript-eslint/parser": "^5.59.5", | |||
| "clean-package": "^2.2.0", | |||
| "copyfiles": "^2.4.1", | |||
| "eslint": "^8.40.0", | |||
| "eslint-import-resolver-typescript": "^3.5.5", | |||
| "eslint-plugin-deprecation": "^1.4.1", | |||
| @@ -86,35 +96,36 @@ | |||
| "eslint-plugin-import": "^2.27.5", | |||
| "local-web-server": "^5.3.0", | |||
| "markdown-to-html-cli": "^3.7.0", | |||
| "popmotion": "^11.0.5", | |||
| "rimraf": "^5.0.1", | |||
| "rollup": "^3.23.0", | |||
| "rollup-plugin-license": "^3.0.1", | |||
| "rollup-plugin-glsl": "^1.3.0", | |||
| "rollup-plugin-license": "^3.0.1", | |||
| "rollup-plugin-postcss": "^4.0.2", | |||
| "stats.js": "^0.17.0", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2021/package.tgz", | |||
| "tslib": "^2.5.0", | |||
| "typedoc": "^0.24.7", | |||
| "typescript": "^5.0.4", | |||
| "typedoc": "^0.25.7", | |||
| "typescript": "^5.3.3", | |||
| "typescript-plugin-css-modules": "^5.0.1", | |||
| "uiconfig.js": "^0.0.6", | |||
| "rollup-plugin-replace": "^2.2.0", | |||
| "popmotion": "^11.0.5" | |||
| "vite": "^5.0.12", | |||
| "vite-plugin-dts": "^3.7.0" | |||
| }, | |||
| "dependencies": { | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1014/package.tgz", | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1020/package.tgz", | |||
| "@types/webxr": "^0.5.1", | |||
| "@types/wicg-file-system-access": "^2020.9.5", | |||
| "ts-browser-helpers": "^0.8.0" | |||
| "stats.js": "^0.17.0", | |||
| "ts-browser-helpers": "^0.12.0", | |||
| "uiconfig.js": "^0.0.12" | |||
| }, | |||
| "//": { | |||
| "dependencies": { | |||
| "uiconfig.js": "^0.0.6", | |||
| "ts-browser-helpers": "^0.8.0", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz", | |||
| "three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.152.2012.tar.gz", | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1014/package.tgz", | |||
| "@types/three-f": "https://github.com/repalash/three-ts-types/archive/refs/tags/v0.152.1014.tar.gz", | |||
| "uiconfig.js": "^0.0.12", | |||
| "ts-browser-helpers": "^0.12.0", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2021/package.tgz", | |||
| "three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.152.2021.tar.gz", | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1020/package.tgz", | |||
| "@types/three-f": "https://github.com/repalash/three-ts-types/archive/refs/tags/v0.152.1020.tar.gz", | |||
| "@types/three-pkg": "https://gitpkg.now.sh/repalash/three-ts-types/types/three?modded_three" | |||
| }, | |||
| "local_dependencies": { | |||
| @@ -0,0 +1,22 @@ | |||
| { | |||
| "name": "@threepipe/plugin-blend-importer", | |||
| "version": "0.0.1", | |||
| "lockfileVersion": 3, | |||
| "requires": true, | |||
| "packages": { | |||
| "": { | |||
| "name": "@threepipe/plugin-blend-importer", | |||
| "version": "0.0.1", | |||
| "license": "Apache-2.0", | |||
| "dependencies": { | |||
| "threepipe": "file:./../../src/" | |||
| }, | |||
| "devDependencies": {} | |||
| }, | |||
| "../../src": {}, | |||
| "node_modules/threepipe": { | |||
| "resolved": "../../src", | |||
| "link": true | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,57 @@ | |||
| { | |||
| "name": "@threepipe/plugin-blend-importer", | |||
| "description": "Basic importer for .blend file", | |||
| "version": "0.0.1", | |||
| "devDependencies": { | |||
| }, | |||
| "dependencies": { | |||
| "threepipe": "file:./../../src/" | |||
| }, | |||
| "clean-package": { | |||
| "remove": [ | |||
| "clean-package", | |||
| "scripts", | |||
| "devDependencies", | |||
| "//", | |||
| "markdown-to-html" | |||
| ], | |||
| "replace": { | |||
| "dependencies": { | |||
| "threepipe": "^0.0.13" | |||
| } | |||
| } | |||
| }, | |||
| "type": "module", | |||
| "main": "dist/index.js", | |||
| "module": "dist/index.mjs", | |||
| "types": "dist/index.d.ts", | |||
| "files": [ | |||
| "dist", | |||
| "src" | |||
| ], | |||
| "scripts": { | |||
| "new:pack": "npm run prepare && clean-package && npm pack && clean-package restore", | |||
| "new:publish": "npm run prepare && clean-package && npm publish --access public && clean-package restore", | |||
| "prepare": "npm run build", | |||
| "build": "rimraf dist && NODE_ENV=production rollup -c", | |||
| "dev": "rollup -c -w", | |||
| "docs": "rimraf docs && npx typedoc" | |||
| }, | |||
| "author": "repalash <palash@shaders.app>", | |||
| "license": "Apache-2.0", | |||
| "keywords": [ | |||
| "three", | |||
| "three.js", | |||
| "threepipe", | |||
| "editor", | |||
| "plugin" | |||
| ], | |||
| "bugs": { | |||
| "url": "https://github.com/repalash/threepipe/issues" | |||
| }, | |||
| "homepage": "https://github.com/repalash/threepipe#readme", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git://github.com/repalash/threepipe.git" | |||
| } | |||
| } | |||
| @@ -0,0 +1,99 @@ | |||
| // rollup.config.js | |||
| import commonjs from '@rollup/plugin-commonjs'; | |||
| import json from '@rollup/plugin-json'; | |||
| import resolve from '@rollup/plugin-node-resolve'; | |||
| import typescript from '@rollup/plugin-typescript'; | |||
| import license from 'rollup-plugin-license' | |||
| import packageJson from './package.json' assert {type: 'json'}; | |||
| import path from 'path' | |||
| import {fileURLToPath} from 'url'; | |||
| import postcss from 'rollup-plugin-postcss' | |||
| import replace from '@rollup/plugin-replace' | |||
| import terser from "@rollup/plugin-terser"; | |||
| const __filename = fileURLToPath(import.meta.url); | |||
| const __dirname = path.dirname(__filename); | |||
| const {name, version, author} = packageJson | |||
| // const {main, module, browser} = packageJson["clean-package"].replace | |||
| const isProduction = process.env.NODE_ENV === 'production' | |||
| const settings = { | |||
| globals: { | |||
| "three": "threepipe", | |||
| "threepipe": "threepipe" | |||
| }, | |||
| sourcemap: true | |||
| } | |||
| export default { | |||
| input: './src/index.ts', | |||
| output: [ | |||
| // { | |||
| // file: main, | |||
| // name: main, | |||
| // ...settings, | |||
| // format: 'cjs', | |||
| // plugins: [ | |||
| // isProduction && terser() | |||
| // ] | |||
| // }, | |||
| { | |||
| file: './dist/index.mjs', | |||
| ...settings, | |||
| name: name, | |||
| format: 'es', | |||
| plugins: [ | |||
| isProduction && terser() | |||
| ] | |||
| }, | |||
| { | |||
| file: './dist/index.js', | |||
| ...settings, | |||
| name: name, | |||
| format: 'umd', | |||
| plugins: [ | |||
| isProduction && terser() | |||
| ] | |||
| } | |||
| ], | |||
| external: Object.keys(settings.globals), | |||
| plugins: [ | |||
| replace({ | |||
| 'from \'three\'': 'from \'threepipe\'', | |||
| delimiters: ['', ''], | |||
| }), | |||
| replace({ | |||
| 'process.env.NODE_ENV': JSON.stringify('production'), | |||
| }), | |||
| postcss({ | |||
| modules: false, | |||
| autoModules: true, // todo; issues with typescript import css, because inject is false | |||
| inject: false, | |||
| minimize: isProduction, | |||
| // Or with custom options for `postcss-modules` | |||
| }), | |||
| json(), | |||
| resolve({}), | |||
| typescript({ | |||
| }), | |||
| commonjs({ | |||
| include: 'node_modules/**', | |||
| extensions: ['.js'], | |||
| ignoreGlobal: false, | |||
| sourceMap: false | |||
| }), | |||
| license({ | |||
| banner: ` | |||
| @license | |||
| ${name} v${version} | |||
| Copyright 2022<%= moment().format('YYYY') > 2022 ? '-' + moment().format('YYYY') : null %> ${author} | |||
| ${packageJson.license} License | |||
| `, | |||
| thirdParty: { | |||
| output: path.join(__dirname, 'dist', 'dependencies.txt'), | |||
| includePrivate: true, // Default is false. | |||
| }, | |||
| }) | |||
| ] | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| import {AnyOptions, BaseImporterPlugin, FileLoader, ILoader, Importer, Object3D, Scene} from 'threepipe' | |||
| import {parseBlend} from './js-blend/main.js' | |||
| import {createObjects} from './loader' | |||
| /** | |||
| * Adds support for loading Blend `.blend`, `application/x-blender` files and data uris | |||
| */ | |||
| export class BlendLoadPlugin extends BaseImporterPlugin { | |||
| public static readonly PluginType = 'BlendLoadPlugin' | |||
| constructor() { | |||
| super() | |||
| } | |||
| protected _importer = new Importer(class extends FileLoader implements ILoader { | |||
| async loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<any> { | |||
| this.setResponseType('arraybuffer') | |||
| const res = (await super.loadAsync(url, onProgress)) as ArrayBuffer | |||
| const blend = await parseBlend(res) | |||
| const objects = await createObjects(blend) | |||
| const root = new Object3D() | |||
| root.add(...objects) | |||
| // console.log(res, blend, root) | |||
| blend.scene = root | |||
| return blend | |||
| } | |||
| transform(res: any, _: AnyOptions): Scene { | |||
| // console.log(res) | |||
| // res.scene.userData.kinematics = res.kinematics | |||
| // res.scene.userData.library = res.library | |||
| return res.scene | |||
| } | |||
| }, ['blend'], ['application/x-blender'], true) | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| declare module '*.txt' { | |||
| const content: string | |||
| export default content | |||
| } | |||
| declare module '*.glsl' { | |||
| const content: string | |||
| export default content | |||
| } | |||
| declare module '*.vert' { | |||
| const content: string | |||
| export default content | |||
| } | |||
| declare module '*.frag' { | |||
| const content: string | |||
| export default content | |||
| } | |||
| declare module '*.module.scss' { | |||
| const content: any | |||
| export default content | |||
| export const stylesheet: string | |||
| } | |||
| declare module '*.module.css' { | |||
| const content: any | |||
| export default content | |||
| export const stylesheet: string | |||
| } | |||
| declare module '*.css' { | |||
| const content: string | |||
| export default content | |||
| } | |||
| declare module '*.css?inline' { // for vite | |||
| const content: string | |||
| export default content | |||
| } | |||
| // export {} | |||
| // hack for typedoc | |||
| // eslint-disable-next-line @typescript-eslint/naming-convention | |||
| // declare type OffscreenCanvas = HTMLCanvasElement | |||
| @@ -0,0 +1 @@ | |||
| export {BlendLoadPlugin} from './BlendLoadPlugin' | |||
| @@ -0,0 +1,21 @@ | |||
| MIT License | |||
| Copyright (c) 2020 Anthony C, Weathersby | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in all | |||
| copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| SOFTWARE. | |||