Explorar el Código

Add ACameraControlsPlugin, DeviceOrientationControlsPlugin, PointerLockControlsPlugin, their examples

master
Palash Bansal hace 2 años
padre
commit
af403173a9
No account linked to committer's email address

+ 46
- 0
examples/device-orientation-controls-plugin/index.html Ver fichero

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Device Orientation Controls Plugin</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
{
"imports": {
"threepipe": "./../../dist/index.mjs",
"@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs"
}
}

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
#deviceOrientationOverlay{
position: absolute; top: 0; left: 0; right: 0; bottom: 0; height: 100%; width: 100%;
display: flex; justify-content: center; align-items: center; cursor: pointer;
font-size: 1.5rem; background: rgba(240,240,240,0.5); color: #333333;
backdrop-filter: blur(16px);
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
<div id="deviceOrientationOverlay">
Tap the screen to enable device orientation controls <br/>
(works only on devices with gyroscope)
</div>
</div>

</body>

+ 30
- 0
examples/device-orientation-controls-plugin/script.ts Ver fichero

@@ -0,0 +1,30 @@
import {_testFinish, DeviceOrientationControlsPlugin, IObject3D, ThreeViewer} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'

async function init() {

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true,
plugins: [DeviceOrientationControlsPlugin],
})

const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true))

ui.appendChild(viewer.scene.mainCamera.uiConfig)

await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr')
await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', {
autoCenter: true,
autoScale: true,
})

const overlayEl = document.getElementById('deviceOrientationOverlay') as HTMLDivElement
overlayEl.addEventListener('click', () => {
viewer.scene.mainCamera.controlsMode = 'deviceOrientation'
overlayEl.style.display = 'none'
})

}

init().then(_testFinish)

+ 3
- 0
examples/index.html Ver fichero

@@ -243,6 +243,9 @@
<li><a href="./transform-controls-plugin/">Transform Controls Plugin </a></li>
<li><a href="./editor-view-widget-plugin/">Editor View Widget Plugin </a></li>
<li><a href="./fullscreen-plugin/">FullScreen Plugin </a></li>
<li><a href="./device-orientation-controls-plugin/">Device Orientation Controls Plugin (Gyroscope) </a></li>
<li><a href="./pointer-lock-controls-plugin/">Pointer Lock(FPS) Controls Plugin </a></li>
<li><a href="./three-first-person-controls-plugin/">Three First Person(look around) Controls Plugin </a></li>
</ul>
<h2 class="category">Import</h2>
<ul>

+ 45
- 0
examples/pointer-lock-controls-plugin/index.html Ver fichero

@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Pointer Lock Controls Plugin</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
{
"imports": {
"threepipe": "./../../dist/index.mjs",
"@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs"
}
}

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
#pointerLockOverlay{
position: absolute; top: 0; left: 0; right: 0; bottom: 0; height: 100%; width: 100%;
display: flex; justify-content: center; align-items: center; pointer-events: none;
font-size: 1.5rem; background: rgba(240,240,240,0.5); color: #333333;
backdrop-filter: blur(16px);
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
<div id="pointerLockOverlay">
Tap the screen to enable pointer lock controls
</div>
</div>

</body>

+ 29
- 0
examples/pointer-lock-controls-plugin/script.ts Ver fichero

@@ -0,0 +1,29 @@
import {_testFinish, IObject3D, PointerLockControlsPlugin, ThreeViewer} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'

async function init() {

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true,
plugins: [PointerLockControlsPlugin],
})

const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true))

ui.appendChild(viewer.scene.mainCamera.uiConfig)

await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr')
await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', {
autoCenter: true,
autoScale: true,
})
viewer.scene.mainCamera.controlsMode = 'pointerLock'

const overlayEl = document.getElementById('pointerLockOverlay') as HTMLDivElement
viewer.scene.mainCamera.controls?.addEventListener('lock', ()=> overlayEl.style.display = 'none')
viewer.scene.mainCamera.controls?.addEventListener('unlock', ()=> overlayEl.style.display = 'flex')

}

init().then(_testFinish)

+ 45
- 0
examples/three-first-person-controls-plugin/index.html Ver fichero

@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three First Person Controls Plugin</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
{
"imports": {
"threepipe": "./../../dist/index.mjs",
"@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs"
}
}

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
#firstPersonControlsOverlay{
position: absolute; top: 0; left: 0; right: 0; bottom: 0; height: 100%; width: 100%;
display: flex; justify-content: center; align-items: center; cursor: pointer;
font-size: 1.5rem; background: rgba(240,240,240,0.5); color: #333333;
backdrop-filter: blur(16px);
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
<div id="firstPersonControlsOverlay">
Tap the screen to enable three first person(look around) controls
</div>
</div>

</body>

+ 30
- 0
examples/three-first-person-controls-plugin/script.ts Ver fichero

@@ -0,0 +1,30 @@
import {_testFinish, IObject3D, ThreeFirstPersonControlsPlugin, ThreeViewer} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'

async function init() {

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true,
plugins: [ThreeFirstPersonControlsPlugin],
})

const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true))

ui.appendChild(viewer.scene.mainCamera.uiConfig)

await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr')
await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', {
autoCenter: true,
autoScale: true,
})

const overlayEl = document.getElementById('firstPersonControlsOverlay') as HTMLDivElement
overlayEl.addEventListener('click', () => {
viewer.scene.mainCamera.controlsMode = 'threeFirstPerson'
overlayEl.style.display = 'none'
})

}

init().then(_testFinish)

+ 7
- 1
examples/tweakpane-editor/script.ts Ver fichero

@@ -7,6 +7,7 @@ import {
ContactShadowGroundPlugin,
CustomBumpMapPlugin,
DepthBufferPlugin,
DeviceOrientationControlsPlugin,
DropzonePlugin,
EditorViewWidgetPlugin,
FilmicGrainPlugin,
@@ -26,11 +27,13 @@ import {
Object3DWidgetsPlugin,
PickingPlugin,
PLYLoadPlugin,
PointerLockControlsPlugin,
ProgressivePlugin,
RenderTargetPreviewPlugin,
Rhino3dmLoadPlugin,
SceneUiConfigPlugin,
STLLoadPlugin,
ThreeFirstPersonControlsPlugin,
ThreeViewer,
TonemapPlugin,
TransformControlsPlugin,
@@ -102,6 +105,9 @@ async function init() {
GaussianSplattingPlugin,
ContactShadowGroundPlugin,
CanvasSnapshotPlugin,
DeviceOrientationControlsPlugin,
PointerLockControlsPlugin,
ThreeFirstPersonControlsPlugin,
...extraImportPlugins,
])

@@ -114,7 +120,7 @@ async function init() {
editor.loadPlugins({
['Viewer']: [ViewerUiConfigPlugin, SceneUiConfigPlugin, DropzonePlugin, FullScreenPlugin, TweakpaneUiPlugin],
['Scene']: [ContactShadowGroundPlugin],
['Interaction']: [HierarchyUiPlugin, TransformControlsPlugin, PickingPlugin, Object3DGeneratorPlugin, GeometryGeneratorPlugin, EditorViewWidgetPlugin, Object3DWidgetsPlugin],
['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],

+ 26
- 0
src/plugins/base/ACameraControlsPlugin.ts Ver fichero

@@ -0,0 +1,26 @@
import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {TControlsCtor} from '../../core'

export abstract class ACameraControlsPlugin extends AViewerPluginSync<''> {
readonly enabled = true
toJSON: any = undefined
protected abstract _controlsCtor: TControlsCtor
abstract readonly controlsKey: string

onAdded(viewer: ThreeViewer): void {
super.onAdded(viewer)
this._cameraChanged({camera: viewer.scene.mainCamera})
viewer.scene.addEventListener('mainCameraChange', this._cameraChanged)
}

onRemove(viewer: ThreeViewer): void {
this._cameraChanged({lastCamera: viewer.scene.mainCamera})
viewer.scene.removeEventListener('mainCameraChange', this._cameraChanged)
super.onRemove(viewer)
}

private _cameraChanged = (e: any) => {
e.lastCamera?.removeControlsCtor?.(this.controlsKey)
e.camera?.setControlsCtor?.(this.controlsKey, this._controlsCtor)
}
}

+ 4
- 0
src/plugins/index.ts Ver fichero

@@ -2,6 +2,7 @@
export {PipelinePassPlugin} from './base/PipelinePassPlugin'
export {BaseImporterPlugin} from './base/BaseImporterPlugin'
export {BaseGroundPlugin} from './base/BaseGroundPlugin'
export {ACameraControlsPlugin} from './base/ACameraControlsPlugin'

// pipeline
export {ProgressivePlugin} from './pipeline/ProgressivePlugin'
@@ -26,6 +27,9 @@ export {FullScreenPlugin} from './interaction/FullScreenPlugin'
export {PickingPlugin} from './interaction/PickingPlugin'
export {TransformControlsPlugin} from './interaction/TransformControlsPlugin'
export {EditorViewWidgetPlugin} from './interaction/EditorViewWidgetPlugin'
export {DeviceOrientationControlsPlugin} from './interaction/DeviceOrientationControlsPlugin'
export {PointerLockControlsPlugin} from './interaction/PointerLockControlsPlugin'
export {ThreeFirstPersonControlsPlugin} from './interaction/ThreeFirstPersonControlsPlugin'

// import
export {Rhino3dmLoadPlugin} from './import/Rhino3dmLoadPlugin'

+ 10
- 0
src/plugins/interaction/DeviceOrientationControlsPlugin.ts Ver fichero

@@ -0,0 +1,10 @@
import {ACameraControlsPlugin} from '../base/ACameraControlsPlugin'
import {TControlsCtor} from '../../core'
import {DeviceOrientationControls2} from '../../three'

export class DeviceOrientationControlsPlugin extends ACameraControlsPlugin {
public static readonly PluginType = 'DeviceOrientationControlsPlugin'
readonly controlsKey = 'deviceOrientation'

protected _controlsCtor: TControlsCtor = (object, _domElement)=> new DeviceOrientationControls2(object)
}

+ 10
- 0
src/plugins/interaction/PointerLockControlsPlugin.ts Ver fichero

@@ -0,0 +1,10 @@
import {ACameraControlsPlugin} from '../base/ACameraControlsPlugin'
import {TControlsCtor} from '../../core'
import {PointerLockControls2} from '../../three'

export class PointerLockControlsPlugin extends ACameraControlsPlugin {
public static readonly PluginType = 'PointerLockControlsPlugin'
readonly controlsKey = 'pointerLock'

protected _controlsCtor: TControlsCtor = (object, domElement) => new PointerLockControls2(object, !domElement?.ownerDocument ? (domElement || document).documentElement : domElement)
}

+ 10
- 0
src/plugins/interaction/ThreeFirstPersonControlsPlugin.ts Ver fichero

@@ -0,0 +1,10 @@
import {ACameraControlsPlugin} from '../base/ACameraControlsPlugin'
import {TControlsCtor} from '../../core'
import {FirstPersonControls2} from '../../three'

export class ThreeFirstPersonControlsPlugin extends ACameraControlsPlugin {
public static readonly PluginType = 'ThreeFirstPersonControlsPlugin'
readonly controlsKey = 'threeFirstPerson'

protected _controlsCtor: TControlsCtor = (object, domElement) => new FirstPersonControls2(object, domElement || document.documentElement)
}

+ 14
- 3
src/three/controls/DeviceOrientationControls2.ts Ver fichero

@@ -1,6 +1,6 @@
import {Euler, EulerOrder, EventDispatcher, MathUtils, Object3D, Quaternion, Vector3} from 'three'
import {IEvent, now, serialize} from 'ts-browser-helpers'
import {uiPanelContainer, uiSlider} from 'uiconfig.js'
import {uiButton, uiPanelContainer, uiSlider} from 'uiconfig.js'
import {ICameraControls} from '../../core'

// eslint-disable-next-line @typescript-eslint/naming-convention
@@ -63,7 +63,15 @@ export class DeviceOrientationControls2 extends EventDispatcher implements ICame
private _initQuaternion = new Quaternion()
private _initQuaternionInvert = new Quaternion()
private _initQuaternionDest = new Quaternion()

@uiButton('Reset View')
resetView() {
(this._initQuaternionDest as any).__init = false
}

@uiButton()
connect() {
if (this.enabled) return

this.onScreenOrientationChangeEvent() // run once on load

@@ -99,7 +107,9 @@ export class DeviceOrientationControls2 extends EventDispatcher implements ICame

}

@uiButton()
disconnect() {
if (!this.enabled) return

window.removeEventListener('orientationchange', this.onScreenOrientationChangeEvent)
window.removeEventListener('deviceorientation', this.onDeviceOrientationChangeEvent)
@@ -163,6 +173,7 @@ export class DeviceOrientationControls2 extends EventDispatcher implements ICame

_q2.multiply(_q0.setFromAxisAngle(_zee, -orient)) // adjust for screen orientation

// debugger
if (!(this._initQuaternionDest as any).__init) {
this._initQuaternionDest.copy(_q2).invert()
;(this._initQuaternionDest as any).__init = true
@@ -171,9 +182,9 @@ export class DeviceOrientationControls2 extends EventDispatcher implements ICame
_q2.premultiply(this._initQuaternionDest)

const mTime = 1 / 60
// this.object.quaternion.multiply(this._initQuaternionInvert)
this.object.quaternion.multiply(this._initQuaternionInvert)
this.object.quaternion.slerp(_q2, this.dampingFactor / (Math.min(1, time - this._lastTime) / mTime))
// this.object.quaternion.multiply(this._initQuaternion)
this.object.quaternion.multiply(this._initQuaternion)
// console.log(time - this._lastTime, mTime)

this._lastTime = time

+ 4
- 3
src/three/controls/FirstPersonControls2.ts Ver fichero

@@ -1,6 +1,7 @@
import {MathUtils, Object3D, Spherical, Vector3} from 'three'
import {IEvent, now, serialize, SimpleEventDispatcher} from 'ts-browser-helpers'
import {EventDispatcher, MathUtils, Object3D, Spherical, Vector3} from 'three'
import {IEvent, now, serialize} from 'ts-browser-helpers'
import {uiFolderContainer, uiInput, uiToggle} from 'uiconfig.js'
import {ICameraControls} from '../../core'

// eslint-disable-next-line @typescript-eslint/naming-convention
const _lookDirection = new Vector3()
@@ -13,7 +14,7 @@ const _target = new Vector3()
const _changeEvent: IEvent<'change'> = {type: 'change'}

@uiFolderContainer('First Person Controls')
export class FirstPersonControls2 extends SimpleEventDispatcher<'change'> {
export class FirstPersonControls2 extends EventDispatcher implements ICameraControls<'change'> {
readonly object: Object3D
readonly domElement: HTMLElement | Document


Cargando…
Cancelar
Guardar