Просмотр исходного кода

Add Object3DGeneratorPlugin, Object3DWidgetsPlugin and examples.

master
Palash Bansal 2 лет назад
Родитель
Сommit
d9141ded70
Аккаунт пользователя с таким Email не найден

+ 1
- 1
examples/geometry-generator-plugin/index.html Просмотреть файл

@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Extra importer plugins</title>
<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 -->

+ 4
- 2
examples/geometry-generator-plugin/script.ts Просмотреть файл

@@ -1,4 +1,4 @@
import {_testFinish, CameraViewPlugin, PickingPlugin, ThreeViewer} from 'threepipe'
import {_testFinish, CameraViewPlugin, Object3DGeneratorPlugin, PickingPlugin, ThreeViewer} from 'threepipe'
import {GeometryGeneratorPlugin} from '@threepipe/plugin-geometry-generator'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'

@@ -7,7 +7,7 @@ async function init() {
const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true,
plugins: [PickingPlugin, CameraViewPlugin],
plugins: [PickingPlugin, CameraViewPlugin, Object3DGeneratorPlugin],
})
const generator = viewer.addPluginSync(GeometryGeneratorPlugin)

@@ -16,12 +16,14 @@ async function init() {
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)

}


+ 38
- 0
examples/object3d-generator-plugin/index.html Просмотреть файл

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

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

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
</div>

</body>

+ 44
- 0
examples/object3d-generator-plugin/script.ts Просмотреть файл

@@ -0,0 +1,44 @@
import {
_testFinish,
CameraViewPlugin,
Object3DGeneratorPlugin,
Object3DWidgetsPlugin,
PickingPlugin,
ThreeViewer,
} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'
import {HierarchyUiPlugin} from '@threepipe/plugin-tweakpane-editor'

async function init() {

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true,
plugins: [PickingPlugin, CameraViewPlugin, Object3DWidgetsPlugin, HierarchyUiPlugin],
})
const generator = viewer.addPluginSync(Object3DGeneratorPlugin)

viewer.scene.setBackgroundColor('#444466')

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

console.log(generator.generators)

const object = generator.generate('light-directional', {color: 0x00ff00})
console.log(object)

viewer.getPlugin(PickingPlugin)?.setSelectedObject(object)

const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true))
ui.setupPluginUi(Object3DGeneratorPlugin)!.expanded = true
ui.setupPluginUi(HierarchyUiPlugin)
ui.setupPluginUi(PickingPlugin)

}

init().then(_testFinish)


+ 37
- 0
examples/object3d-widgets-plugin/index.html Просмотреть файл

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

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

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
</div>

</body>

+ 59
- 0
examples/object3d-widgets-plugin/script.ts Просмотреть файл

@@ -0,0 +1,59 @@
import {
_testFinish,
CameraViewPlugin,
Object3DGeneratorPlugin,
Object3DWidgetsPlugin,
ThreeViewer,
Vector3,
} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'

async function init() {

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

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

viewer.scene.setBackgroundColor('#444466')

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

console.log(widgets.helpers)

const generator = viewer.getPlugin(Object3DGeneratorPlugin)!
let object

object = generator.generate('camera-perspective', {
position: new Vector3(5, 5, 0),
})
ui.appendChild(object?.uiConfig)
object = generator.generate('light-directional', {
position: new Vector3(5, 0, 5),
})
ui.appendChild(object?.uiConfig)
object = generator.generate('light-spot', {
position: new Vector3(-5, 0, 5),
})
ui.appendChild(object?.uiConfig)
object = generator.generate('light-point', {
position: new Vector3(-5, 5, -5),
})
ui.appendChild(object?.uiConfig)

viewer.scene.mainCamera.position.z += 10
viewer.scene.mainCamera.setDirty()

}

init().then(_testFinish)


+ 5
- 1
examples/tweakpane-editor/script.ts Просмотреть файл

@@ -19,6 +19,8 @@ import {
KTXLoadPlugin,
NoiseBumpMaterialPlugin,
NormalBufferPlugin,
Object3DGeneratorPlugin,
Object3DWidgetsPlugin,
PickingPlugin,
PLYLoadPlugin,
ProgressivePlugin,
@@ -89,6 +91,8 @@ async function init() {
BlendLoadPlugin,
HierarchyUiPlugin,
GeometryGeneratorPlugin,
Object3DWidgetsPlugin,
Object3DGeneratorPlugin,
...extraImportPlugins,
])

@@ -98,7 +102,7 @@ async function init() {

editor.loadPlugins({
['Viewer']: [ViewerUiConfigPlugin, SceneUiConfigPlugin, DropzonePlugin, FullScreenPlugin],
['Interaction']: [HierarchyUiPlugin, TransformControlsPlugin, PickingPlugin, GeometryGeneratorPlugin, EditorViewWidgetPlugin],
['Interaction']: [HierarchyUiPlugin, TransformControlsPlugin, PickingPlugin, Object3DGeneratorPlugin, GeometryGeneratorPlugin, EditorViewWidgetPlugin, Object3DWidgetsPlugin],
['GBuffer']: [DepthBufferPlugin, NormalBufferPlugin],
['Post-processing']: [TonemapPlugin, ProgressivePlugin, FrameFadePlugin, VignettePlugin, ChromaticAberrationPlugin, FilmicGrainPlugin],
['Animation']: [GLTFAnimationPlugin, CameraViewPlugin],

+ 138
- 0
src/plugins/extras/Object3DGeneratorPlugin.ts Просмотреть файл

@@ -0,0 +1,138 @@
import {AViewerPluginSync} from '../../viewer'
import {
AmbientLight2,
DirectionalLight2,
HemisphereLight2,
IObject3D,
PerspectiveCamera2,
PointLight2,
RectAreaLight2,
SpotLight2,
} from '../../core'
import {uiButton, uiDropdown, uiPanelContainer} from 'uiconfig.js'
import {Vector3} from 'three'

/**
* Adds support for generating different types of lights and camera objects in the viewer.
* @category Plugin
*/
@uiPanelContainer('Generate Scene Objects')
export class Object3DGeneratorPlugin extends AViewerPluginSync<''> {
public static readonly PluginType = 'Object3DGeneratorPlugin'
enabled = true
toJSON: any = undefined

@uiDropdown('Type', undefined, (that)=>({
children: [()=>Object.keys(that.generators).map(label=>({label}))],
}))
protected _selectedType = ''

@uiButton('Generate')
generate(type?: string, params?: any, addToScene = true) {
if (!this._viewer) throw new Error('No viewer')
const obj = this.generators[type ?? this._selectedType]?.(params)
addToScene && obj && this._viewer.scene.addObject(obj)
return obj
}

generators: Record<string, (params?: any)=>IObject3D> = {
['camera-perspective']: (params: {
controlsMode?: string,
autoAspect?: boolean,
fov?: number,
aspect?: number,
position?: Vector3,
target?: Vector3,
autoLookAtTarget?: boolean,
name?: string,
} = {})=>{
const camera = new PerspectiveCamera2(
params.controlsMode ?? '',
this._viewer?.canvas,
params.autoAspect,
params.fov,
params.aspect,
)
params.position ? camera.position.copy(params.position) : camera.position.set(0, 0, 5)
params.target ? camera.target.copy(params.target) : camera.target.set(0, 0, 0)
camera.autoLookAtTarget = params.autoLookAtTarget ?? true
camera.setDirty()
camera.name = params.name ?? 'Perspective Camera'
return camera
},
['light-directional']: (params: {
color?: number,
intensity?: number,
position?: Vector3,
target?: Vector3,
name?: string,
} = {})=>{
const light = new DirectionalLight2(params.color ?? 0xff0000, params.intensity ?? 3)
params.position ? light.position.copy(params.position) : light.position.set(5, 5, 5)
light.lookAt(params.target ?? new Vector3(0, 0, 0))
light.name = 'Directional Light'
return light
},
['light-ambient']: (params: {
color?: number,
intensity?: number,
name?: string,
} = {})=>{
const light = new AmbientLight2(params.color ?? 0xffffff, params.intensity ?? 1)
light.name = 'Ambient Light'
return light
},
['light-point']: (params: {
color?: number,
intensity?: number,
position?: Vector3,
name?: string,
} = {})=>{
const light = new PointLight2(params.color ?? 0xff0000, params.intensity ?? 3)
params.position ? light.position.copy(params.position) : light.position.set(5, 5, 5)
light.name = 'Point Light'
return light
},
['light-spot']: (params: {
color?: number,
intensity?: number,
position?: Vector3,
target?: Vector3,
name?: string,
} = {})=>{
const light = new SpotLight2(params.color ?? 0xff0000, params.intensity ?? 3)
params.position ? light.position.copy(params.position) : light.position.set(5, 5, 5)
light.lookAt(params.target ?? new Vector3(0, 0, 0))
light.name = 'Spot Light'
return light
},
['light-hemisphere']: (params: {
color?: number,
intensity?: number,
name?: string,
} = {})=>{
const light = new HemisphereLight2(params.color ?? 0xaaaaff, 0x555443, params.intensity ?? 1)
light.name = 'Hemisphere Light'
return light
},
['light-rect-area']: (params: {
color?: number,
intensity?: number,
position?: Vector3,
target?: Vector3,
name?: string,
} = {})=>{
const light = new RectAreaLight2(params.color ?? 0x000ff, params.intensity ?? 3, 2, 2)
params.position ? light.position.copy(params.position) : light.position.set(5, 5, 5)
light.lookAt(params.target ?? new Vector3(0, 0, 0))
light.name = 'Rect Area Light'
return light
},
}

constructor() {
super()
this._selectedType = Object.keys(this.generators)[0]
}

}

+ 112
- 0
src/plugins/extras/Object3DWidgetsPlugin.ts Просмотреть файл

@@ -0,0 +1,112 @@
import {UiObjectConfig} from 'uiconfig.js'
import {IWidget} from '../../core'
import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {IEvent, onChange} from 'ts-browser-helpers'
import {Object3D} from 'three'
import {CameraHelper2, DirectionalLightHelper2, PointLightHelper2, SpotLightHelper2} from '../../three'

export interface IObject3DHelper<T extends Object3D&IWidget = Object3D&IWidget>{
Create: (o: Object3D)=>T,
Check: (o: Object3D)=>boolean,
}

/**
* Adds light and camera helpers/gizmos in the viewer.
* A helper is automatically created when any supported light or camera is added to the scene.
* @category Plugin
*/
export class Object3DWidgetsPlugin extends AViewerPluginSync<''> {
@onChange(Object3DWidgetsPlugin.prototype.setDirty)
enabled = true
public static readonly PluginType = 'Object3DWidgetsPlugin'

helpers: IObject3DHelper[] = [
DirectionalLightHelper2,
SpotLightHelper2,
PointLightHelper2,
CameraHelper2,
]

setDirty() {
this.widgets?.forEach(w => w.visible = !this.isDisabled())
this._viewer?.setDirty()
}

toJSON: any = null

constructor(enabled = true) {
super()
this.enabled = enabled
}

private _widgetRoot = new Object3D()

onAdded(viewer: ThreeViewer) {
super.onAdded(viewer)
viewer.scene.addEventListener('addSceneObject', this._addSceneObject)
viewer.scene.addObject(this._widgetRoot)
}
onRemove(viewer: ThreeViewer) {
viewer.scene.removeEventListener('addSceneObject', this._addSceneObject)
this.widgets.forEach(w => w.dispose && w.dispose())
this.widgets = []
this._widgetRoot.removeFromParent()
this._widgetRoot.clear()
super.onRemove(viewer)
}
private _addSceneObject = (e: any)=>{
this._createWidgets(e.object)
}

refresh() {
this._createWidgets(this._viewer?.scene.modelRoot)
}

widgets: (IWidget&Object3D)[] = []

private _widgetDisposed = (e: IEvent<any>)=> this._unregisterWidget(e.target)

private _registerWidget(w: IWidget&Object3D) {
this.widgets.push(w)
w.addEventListener('dispose', this._widgetDisposed) // todo: maybe unregister when removed from parent, dispose makes little sense.
}
private _unregisterWidget(w: IWidget&Object3D) {
w.removeEventListener('dispose', this._widgetDisposed)
const i = this.widgets.indexOf(w)
if (i >= 0) this.widgets.splice(i, 1)
}

private _createWidgets(o?: Object3D) {
o?.traverse((l: any) => {
const widget = this.widgets.find(w => w.object === l)
if (widget) {
widget.update && widget.update()
return
}
const helpers = this.helpers.filter(h => h.Check(l))
helpers.forEach(h => {
const w = h.Create(l)
w.visible = !this.isDisabled()
this._widgetRoot.add(w)
this._registerWidget(w)
})
})
}

uiConfig: UiObjectConfig = {
type: 'folder',
label: 'Widgets',
children: [
{
type: 'checkbox',
label: 'Enabled',
property: [this, 'enabled'],
},
{
type: 'button',
label: 'Refresh',
value: ()=>this.refresh(),
},
],
}
}

+ 3
- 1
src/plugins/index.ts Просмотреть файл

@@ -50,8 +50,10 @@ export {NoiseBumpMaterialPlugin} from './material/NoiseBumpMaterialPlugin'
export {CustomBumpMapPlugin} from './material/CustomBumpMapPlugin'
export {FragmentClippingExtensionPlugin, FragmentClippingMode} from './material/FragmentClippingExtensionPlugin'

// extras
// rendering
export {VirtualCamerasPlugin} from './rendering/VirtualCamerasPlugin'

// extras
export {HDRiGroundPlugin} from './extras/HDRiGroundPlugin'
export {Object3DWidgetsPlugin} from './extras/Object3DWidgetsPlugin'
export {Object3DGeneratorPlugin} from './extras/Object3DGeneratorPlugin'

Загрузка…
Отмена
Сохранить