threepipe
Version:
A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.
69 lines (50 loc) • 2.35 kB
text/typescript
import {BoxGeometry, CylinderGeometry, HemisphereLight, Light, Mesh, Scene, SphereGeometry, Vector3} from 'three'
import {IDisposable} from 'ts-browser-helpers'
import {snapObject} from './snapObject'
import {IMaterial, ITexture, IWebGLRenderer} from '../../core'
export class MaterialPreviewGenerator implements IDisposable {
private _scene: Scene
private _channel: number
private _lights: Light[] = []
constructor() {
const scene = new Scene()
this._channel = 7
const hemisphericLight = new HemisphereLight(0xffffff, 0x444444, 1)
hemisphericLight.position.set(0, 10, 0)
hemisphericLight.layers.set(this._channel)
scene.add(hemisphericLight)
this._lights.push(hemisphericLight)
this._scene = scene
}
dispose() {
[...this._lights].forEach(light => light.dispose())
Object.values(this.shapes).forEach(shape => {
if (shape.geometry) shape.geometry.dispose()
})
}
shapes: Record<string, Mesh> = {
sphere: new Mesh(new SphereGeometry(1)),
cube: new Mesh(new BoxGeometry(1, 1, 1)),
cylinder: new Mesh(new CylinderGeometry(0.5, 0.5, 1)),
}
// todo: show an overlay when this is happening
generate(material: IMaterial, renderer: IWebGLRenderer, environment?: ITexture|null, shape = 'sphere'): string {
const object = this.shapes[shape] || new Mesh(new SphereGeometry(1))
object.material = material
if (!object.geometry.attributes.tangent) object.geometry.computeTangents() // for anisotropy
this._scene.add(object)
this._scene.environment = environment ?? null
const envIntensity = material.envMapIntensity
// clamp since we have no tonemapping
if (typeof envIntensity === 'number') {
material.envMapIntensity = Math.max(envIntensity, 2)
}
const snap = snapObject(renderer, object, this._scene, this._channel, new Vector3(0, 0, 1.5))
// const snap = snapObject(this.viewer, (material.userData.__appliedMeshes as Set<Mesh>).values().next().value, undefined, this._channel)
if (typeof envIntensity === 'number')
material.envMapIntensity = envIntensity
this._scene.remove(object)
object.material = undefined as any
return snap
}
}