# Conflicts: # package.json # src/viewer/ThreeViewer.tsmaster
| 'root': true, | 'root': true, | ||||
| 'extends': [ | 'extends': [ | ||||
| 'eslint:recommended', | 'eslint:recommended', | ||||
| 'plugin:@typescript-eslint/eslint-recommended' , | |||||
| 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin | |||||
| ], | ], | ||||
| 'parserOptions': { | 'parserOptions': { | ||||
| 'ecmaVersion': 2018, | 'ecmaVersion': 2018, | ||||
| 'overrides': [ | 'overrides': [ | ||||
| { | { | ||||
| 'files': ['**/*.ts', '**/*.tsx'], | 'files': ['**/*.ts', '**/*.tsx'], | ||||
| 'parser': '@typescript-eslint/parser', // Specifies the ESLint parser | 'parser': '@typescript-eslint/parser', // Specifies the ESLint parser | ||||
| 'parserOptions': { | 'parserOptions': { | ||||
| 'ecmaVersion': 2021, // Allows for the parsing of modern ECMAScript features | 'ecmaVersion': 2021, // Allows for the parsing of modern ECMAScript features |
| steps: | steps: | ||||
| - uses: actions/checkout@v3 | - uses: actions/checkout@v3 | ||||
| - name: Use Node.js ${{ matrix.node-version }} | |||||
| uses: actions/setup-node@v3 | |||||
| - uses: actions/setup-node@v3 | |||||
| with: | with: | ||||
| node-version: ${{ matrix.node-version }} | node-version: ${{ matrix.node-version }} | ||||
| cache: 'npm' | 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: 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: 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 | - name: Setup Pages | ||||
| uses: actions/configure-pages@v3 | uses: actions/configure-pages@v3 | ||||
| - name: Upload artifact | - name: Upload artifact |
| dist | dist | ||||
| lib | |||||
| docs | docs | ||||
| /index.html | /index.html | ||||
| examples/**/*.js | examples/**/*.js |
| # Datasource local storage ignored files | # Datasource local storage ignored files | ||||
| /dataSources/ | /dataSources/ | ||||
| /dataSources.local.xml | /dataSources.local.xml | ||||
| # GitHub Copilot persisted chat sessions | |||||
| /copilot/chatSessions |
| <!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> |
| 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) |
| <!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> |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <script type="importmap"> | <script type="importmap"> | ||||
| { | { | ||||
| "imports": { | "imports": { | ||||
| "threepipe": "./../../dist/index.mjs" | |||||
| "threepipe": "./../../dist/index.mjs", | |||||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||||
| } | } | ||||
| } | } | ||||
| import { | import { | ||||
| _testFinish, | _testFinish, | ||||
| Box3B, | Box3B, | ||||
| DirectionalLight, | |||||
| DirectionalLight2, | |||||
| IObject3D, | IObject3D, | ||||
| Mesh, | Mesh, | ||||
| Object3DWidgetsPlugin, | |||||
| PCFSoftShadowMap, | PCFSoftShadowMap, | ||||
| PhysicalMaterial, | PhysicalMaterial, | ||||
| PlaneGeometry, | PlaneGeometry, | ||||
| ThreeViewer, | ThreeViewer, | ||||
| Vector3, | Vector3, | ||||
| } from 'threepipe' | } from 'threepipe' | ||||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||||
| async function init() { | async function init() { | ||||
| autoSetEnvironment: true, // when hdr/exr is dropped | autoSetEnvironment: true, // when hdr/exr is dropped | ||||
| }, | }, | ||||
| }, | }, | ||||
| plugins: [Object3DWidgetsPlugin], | |||||
| }) | }) | ||||
| // viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | // viewer.scene.addObject(new HemisphereLight(0xffffff, 0x444444, 10)) | ||||
| ground.receiveShadow = true | ground.receiveShadow = true | ||||
| viewer.scene.addObject(ground) | 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 | viewer.renderManager.renderer.shadowMap.type = PCFSoftShadowMap | ||||
| const rt = viewer.addPluginSync(RenderTargetPreviewPlugin) | 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) | init().then(_testFinish) |
| <!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> |
| 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) |
| .replaceAll(` from '../`, ` from '${rootPath+examplePath}`) | .replaceAll(` from '../`, ` from '${rootPath+examplePath}`) | ||||
| } | } | ||||
| setupCodePreview( | 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, | ||||
| scripts.map(s=>s.textContent ? 'js' : s.split('.').pop()), // title | 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 | 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 |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) | |||||
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <body> | <body> | ||||
| <canvas id="three-canvas" style="width: 800px; height: 600px;"></canvas> | <canvas id="three-canvas" style="width: 800px; height: 600px;"></canvas> | ||||
| <script id="example-script" type="module" data-scripts="./index.html"> | <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')}) | const viewer = new ThreeViewer({canvas: document.getElementById('three-canvas')}) | ||||
| // Load an environment map | // Load an environment map | ||||
| }) | }) | ||||
| </script> | </script> | ||||
| </body> | </body> | ||||
| </html> |
| msaa: true, | msaa: true, | ||||
| }) | }) | ||||
| // Note: see also: CanvasSnapshotPlugin | |||||
| async function init() { | async function init() { | ||||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') |
| <h2 class="category">Post-Processing</h2> | <h2 class="category">Post-Processing</h2> | ||||
| <ul> | <ul> | ||||
| <li><a href="./tonemap-plugin/">Tonemap Plugin </a></li> | <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> | <li><a href="./frame-fade-plugin/">Frame Fade Plugin </a></li> | ||||
| </ul> | </ul> | ||||
| <h2 class="category">Rendering</h2> | <h2 class="category">Rendering</h2> | ||||
| <ul> | <ul> | ||||
| <li><a href="./progressive-plugin/">Progressive Plugin </a></li> | <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="./depth-buffer-plugin/">Depth Buffer Plugin </a></li> | ||||
| <li><a href="./normal-buffer-plugin/">Normal 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> | </ul> | ||||
| <h2 class="category">Interaction</h2> | <h2 class="category">Interaction</h2> | ||||
| <ul> | <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="./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="./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> | </ul> | ||||
| <h2 class="category">Import</h2> | <h2 class="category">Import</h2> | ||||
| <ul> | <ul> | ||||
| <li><a href="./stl-load/">STL Load </a></li> | <li><a href="./stl-load/">STL Load </a></li> | ||||
| <li><a href="./ktx2-load/">KTX2 Load </a></li> | <li><a href="./ktx2-load/">KTX2 Load </a></li> | ||||
| <li><a href="./ktx-load/">KTX 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> | <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> | </ul> | ||||
| <h2 class="category">Export</h2> | <h2 class="category">Export</h2> | ||||
| <ul> | <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="./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="./render-target-export/">EXR, PNG, JPEG, WEBP Export<br/>(Render Target Export) </a></li> | ||||
| <li><a href="./glb-export/">GLB Export </a></li> | <li><a href="./glb-export/">GLB Export </a></li> | ||||
| <li><a href="./scene-uiconfig/">Scene UI </a></li> | <li><a href="./scene-uiconfig/">Scene UI </a></li> | ||||
| <li><a href="./viewer-uiconfig/">Viewer UI </a></li> | <li><a href="./viewer-uiconfig/">Viewer UI </a></li> | ||||
| </ul> | </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> | <h2 class="category">Animation</h2> | ||||
| <ul> | <ul> | ||||
| <li><a href="./gltf-animation-plugin/">glTF Animation Plugin </a></li> | <li><a href="./gltf-animation-plugin/">glTF Animation Plugin </a></li> | ||||
| <li><a href="./gltf-camera-animation/">glTF Camera Animation </a></li> | <li><a href="./gltf-camera-animation/">glTF Camera Animation </a></li> | ||||
| <li><a href="./gltf-animation-page-scroll/">glTF Animation Page Scroll </a></li> | <li><a href="./gltf-animation-page-scroll/">glTF Animation Page Scroll </a></li> | ||||
| </ul> | </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> | <h2 class="category">Utils</h2> | ||||
| <ul> | <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="./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="./geometry-uv-preview/">Geometry UV Preview Plugin </a></li> | ||||
| <li><a href="./parallel-asset-import/">Parallel Asset Import </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> | <li><a href="./obj-to-glb/">Convert OBJ to GLB </a></li> | ||||
| </ul> | </ul> | ||||
| <h2 class="category">Samples</h2> | <h2 class="category">Samples</h2> | ||||
| <ul> | <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> | </ul> | ||||
| <h2 class="category">Lights</h2> | <h2 class="category">Lights</h2> | ||||
| <ul> | <ul> | ||||
| <li><a href="./directional-light/">Directional Light </a></li> | <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> | </ul> | ||||
| <h2 class="category">Tests</h2> | <h2 class="category">Tests</h2> | ||||
| <ul> | <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/">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="./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="./half-float-hdr-test/">Half-float HDR Test </a></li> | ||||
| <li><a href="./sphere-rgbm-test/">RGBM Test </a></li> | <li><a href="./sphere-rgbm-test/">RGBM Test </a></li> |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) | |||||
| <!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> |
| 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) | |||||
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| 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' | import {createSimpleButtons} from '../examples-utils/simple-bottom-buttons.js' | ||||
| async function init() { | async function init() { | ||||
| createSimpleButtons({ | createSimpleButtons({ | ||||
| ['Move Up/Down']: async(btn) => { | ['Move Up/Down']: async(btn) => { | ||||
| btn.disabled = true | 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 | duration: 500, // ms | ||||
| onUpdate: (v) => { | |||||
| cube.position.setY(v) | |||||
| cube.setDirty() | |||||
| }, | |||||
| onComplete: () => isMovedUp = !isMovedUp, | onComplete: () => isMovedUp = !isMovedUp, | ||||
| }) | |||||
| }) // setDirty is automatically called on the cube since it's the target | |||||
| btn.disabled = false | btn.disabled = false | ||||
| }, | }, | ||||
| ['Rotate +90deg']: async(btn) => { | ['Rotate +90deg']: async(btn) => { |
| <!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> |
| <!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> |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| <!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> |
| 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) |
| <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> |
| <!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> |
| <!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> |
| 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) |
| <!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> |
| 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) |
| "es2020", | "es2020", | ||||
| "esnext", | "esnext", | ||||
| "dom" | "dom" | ||||
| ] | |||||
| ], | |||||
| "jsx": "react" | |||||
| }, | }, | ||||
| "include": [ | "include": [ | ||||
| "./**/*.ts" | |||||
| "./**/*.ts", | |||||
| "./**/*.tsx" | |||||
| ], | ], | ||||
| "exclude": [ | "exclude": [ | ||||
| "node_modules", | "node_modules", |
| "threepipe": "./../../dist/index.mjs", | "threepipe": "./../../dist/index.mjs", | ||||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs", | "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs", | ||||
| "@threepipe/plugin-tweakpane-editor": "./../../plugins/tweakpane-editor/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" | |||||
| } | } | ||||
| } | } | ||||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | <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> | <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | ||||
| </head> | </head> | ||||
| <body> | |||||
| <body class="code-preview-container"> | |||||
| <div id="canvas-container"> | <div id="canvas-container"> | ||||
| <canvas id="mcanvas"></canvas> | <canvas id="mcanvas"></canvas> | ||||
| </div> | </div> |
| import { | import { | ||||
| _testFinish, | _testFinish, | ||||
| CameraViewPlugin, | |||||
| CanvasSnapshotPlugin, | |||||
| ChromaticAberrationPlugin, | |||||
| ClearcoatTintPlugin, | |||||
| ContactShadowGroundPlugin, | |||||
| CustomBumpMapPlugin, | |||||
| DepthBufferPlugin, | DepthBufferPlugin, | ||||
| DeviceOrientationControlsPlugin, | |||||
| DropzonePlugin, | DropzonePlugin, | ||||
| EditorViewWidgetPlugin, | |||||
| FilmicGrainPlugin, | |||||
| FragmentClippingExtensionPlugin, | |||||
| FrameFadePlugin, | FrameFadePlugin, | ||||
| FullScreenPlugin, | FullScreenPlugin, | ||||
| GBufferPlugin, | |||||
| GLTFAnimationPlugin, | GLTFAnimationPlugin, | ||||
| HalfFloatType, | HalfFloatType, | ||||
| HDRiGroundPlugin, | |||||
| HemisphereLight, | |||||
| KTX2LoadPlugin, | KTX2LoadPlugin, | ||||
| KTXLoadPlugin, | KTXLoadPlugin, | ||||
| NoiseBumpMaterialPlugin, | |||||
| NormalBufferPlugin, | NormalBufferPlugin, | ||||
| Object3DGeneratorPlugin, | |||||
| Object3DWidgetsPlugin, | |||||
| PickingPlugin, | |||||
| PLYLoadPlugin, | PLYLoadPlugin, | ||||
| PointerLockControlsPlugin, | |||||
| ProgressivePlugin, | ProgressivePlugin, | ||||
| RenderTargetPreviewPlugin, | RenderTargetPreviewPlugin, | ||||
| Rhino3dmLoadPlugin, | Rhino3dmLoadPlugin, | ||||
| SceneUiConfigPlugin, | SceneUiConfigPlugin, | ||||
| STLLoadPlugin, | STLLoadPlugin, | ||||
| ThreeFirstPersonControlsPlugin, | |||||
| ThreeViewer, | ThreeViewer, | ||||
| TonemapPlugin, | TonemapPlugin, | ||||
| TransformControlsPlugin, | |||||
| USDZLoadPlugin, | USDZLoadPlugin, | ||||
| ViewerUiConfigPlugin, | ViewerUiConfigPlugin, | ||||
| VignettePlugin, | |||||
| VirtualCamerasPlugin, | |||||
| } from 'threepipe' | } from 'threepipe' | ||||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | 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 {extraImportPlugins} from '@threepipe/plugin-extra-importers' | ||||
| import {GeometryGeneratorPlugin} from '@threepipe/plugin-geometry-generator' | |||||
| import {GaussianSplattingPlugin} from '@threepipe/plugin-gaussian-splatting' | |||||
| async function init() { | async function init() { | ||||
| const viewer = new ThreeViewer({ | const viewer = new ThreeViewer({ | ||||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | ||||
| renderScale: 'auto', | |||||
| msaa: true, | msaa: true, | ||||
| rgbm: true, | rgbm: true, | ||||
| zPrepass: false, // set it to true if you only have opaque objects in the scene to get better performance. | zPrepass: false, // set it to true if you only have opaque objects in the scene to get better performance. | ||||
| await viewer.addPlugins([ | await viewer.addPlugins([ | ||||
| new ProgressivePlugin(), | 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 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 NormalBufferPlugin(HalfFloatType, false), | ||||
| new RenderTargetPreviewPlugin(false), | new RenderTargetPreviewPlugin(false), | ||||
| new FrameFadePlugin(), | new FrameFadePlugin(), | ||||
| new HDRiGroundPlugin(false, true), | |||||
| new VignettePlugin(false), | |||||
| new ChromaticAberrationPlugin(false), | |||||
| new FilmicGrainPlugin(false), | |||||
| KTX2LoadPlugin, | KTX2LoadPlugin, | ||||
| KTXLoadPlugin, | KTXLoadPlugin, | ||||
| PLYLoadPlugin, | PLYLoadPlugin, | ||||
| Rhino3dmLoadPlugin, | Rhino3dmLoadPlugin, | ||||
| STLLoadPlugin, | STLLoadPlugin, | ||||
| USDZLoadPlugin, | USDZLoadPlugin, | ||||
| BlendLoadPlugin, | |||||
| HierarchyUiPlugin, | |||||
| GeometryGeneratorPlugin, | |||||
| Object3DWidgetsPlugin, | |||||
| Object3DGeneratorPlugin, | |||||
| GaussianSplattingPlugin, | |||||
| ContactShadowGroundPlugin, | |||||
| CanvasSnapshotPlugin, | |||||
| DeviceOrientationControlsPlugin, | |||||
| PointerLockControlsPlugin, | |||||
| ThreeFirstPersonControlsPlugin, | |||||
| ...extraImportPlugins, | ...extraImportPlugins, | ||||
| ]) | ]) | ||||
| const rt = viewer.getOrAddPluginSync(RenderTargetPreviewPlugin) | 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(DepthBufferPlugin)?.target, 'depth', false, false, false) | ||||
| rt.addTarget(viewer.getPlugin(NormalBufferPlugin)?.target, 'normal', false, true, false) | rt.addTarget(viewer.getPlugin(NormalBufferPlugin)?.target, 'normal', false, true, false) | ||||
| editor.loadPlugins({ | 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], | ['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') | 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', { | // const result = await viewer.load<IObject3D>('https://cdn.jsdelivr.net/gh/KhronosGroup/glTF-Blender-Exporter@master/polly/project_polly.gltf', { |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| 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) |
| <!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> |
| <!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> |
| <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> |
| { | { | ||||
| "name": "threepipe", | "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.", | "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", | "module": "dist/index.mjs", | ||||
| "types": "src/index.ts", | "types": "src/index.ts", | ||||
| "sources": "src/index.ts", | "sources": "src/index.ts", | ||||
| "browser": "dist/index.js", | |||||
| "type": "module", | "type": "module", | ||||
| "scripts": { | "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:pack": "npm run prepare && clean-package && npm pack && clean-package restore", | ||||
| "new:publish": "npm run prepare && clean-package && npm publish && 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", | "build-examples": "tsc --project examples/tsconfig.build.json", | ||||
| "dev-examples": "tsc --project examples/tsconfig.build.json -w", | "dev-examples": "tsc --project examples/tsconfig.build.json -w", | ||||
| "serve-docs": "ws -d docs -p 8080", | "serve-docs": "ws -d docs -p 8080", | ||||
| "serve": "ws -d . -p 9229", | "serve": "ws -d . -p 9229", | ||||
| "docs": "npx typedoc && markdown-to-html", | "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": { | "clean-package": { | ||||
| "remove": [ | "remove": [ | ||||
| "@rollup/plugin-commonjs": "^25.0.0", | "@rollup/plugin-commonjs": "^25.0.0", | ||||
| "@rollup/plugin-json": "^6.0.0", | "@rollup/plugin-json": "^6.0.0", | ||||
| "@rollup/plugin-node-resolve": "^15.0.2", | "@rollup/plugin-node-resolve": "^15.0.2", | ||||
| "@rollup/plugin-replace": "^5.0.2", | |||||
| "@rollup/plugin-terser": "^0.4.3", | "@rollup/plugin-terser": "^0.4.3", | ||||
| "@rollup/plugin-typescript": "^11.1.1", | |||||
| "@rollup/plugin-typescript": "^11.1.5", | |||||
| "@types/stats.js": "^0.17.0", | "@types/stats.js": "^0.17.0", | ||||
| "@typescript-eslint/eslint-plugin": "^5.59.7", | "@typescript-eslint/eslint-plugin": "^5.59.7", | ||||
| "@typescript-eslint/parser": "^5.59.5", | "@typescript-eslint/parser": "^5.59.5", | ||||
| "clean-package": "^2.2.0", | "clean-package": "^2.2.0", | ||||
| "copyfiles": "^2.4.1", | |||||
| "eslint": "^8.40.0", | "eslint": "^8.40.0", | ||||
| "eslint-import-resolver-typescript": "^3.5.5", | "eslint-import-resolver-typescript": "^3.5.5", | ||||
| "eslint-plugin-deprecation": "^1.4.1", | "eslint-plugin-deprecation": "^1.4.1", | ||||
| "eslint-plugin-import": "^2.27.5", | "eslint-plugin-import": "^2.27.5", | ||||
| "local-web-server": "^5.3.0", | "local-web-server": "^5.3.0", | ||||
| "markdown-to-html-cli": "^3.7.0", | "markdown-to-html-cli": "^3.7.0", | ||||
| "popmotion": "^11.0.5", | |||||
| "rimraf": "^5.0.1", | "rimraf": "^5.0.1", | ||||
| "rollup": "^3.23.0", | "rollup": "^3.23.0", | ||||
| "rollup-plugin-license": "^3.0.1", | |||||
| "rollup-plugin-glsl": "^1.3.0", | "rollup-plugin-glsl": "^1.3.0", | ||||
| "rollup-plugin-license": "^3.0.1", | |||||
| "rollup-plugin-postcss": "^4.0.2", | "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", | "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", | "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": { | "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/webxr": "^0.5.1", | ||||
| "@types/wicg-file-system-access": "^2020.9.5", | "@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": { | "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" | "@types/three-pkg": "https://gitpkg.now.sh/repalash/three-ts-types/types/three?modded_three" | ||||
| }, | }, | ||||
| "local_dependencies": { | "local_dependencies": { |
| { | |||||
| "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 | |||||
| } | |||||
| } | |||||
| } |
| { | |||||
| "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" | |||||
| } | |||||
| } |
| // 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. | |||||
| }, | |||||
| }) | |||||
| ] | |||||
| } |
| 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) | |||||
| } |
| 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 |
| export {BlendLoadPlugin} from './BlendLoadPlugin' |
| 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. |