217 lines
6.9 KiB
TypeScript
217 lines
6.9 KiB
TypeScript
|
|
import { AmbientLight, BoxBufferGeometry, BufferGeometry, Color, ConeBufferGeometry, CubeRefractionMapping, CubeTextureLoader, FrontSide, Geometry, LinearEncoding, Mesh, MeshPhysicalMaterial, Object3D, SphereBufferGeometry, sRGBEncoding, Texture, TextureLoader, TorusBufferGeometry, TorusKnotBufferGeometry, Vector3 } from 'three';
|
|
import { Singleton } from './Singleton';
|
|
import { Viewer } from './Viewer';
|
|
import { PMREMGenerator3 } from './PMREMGenerator2';
|
|
import type { PhysicalMaterialRecord, TextureTableRecord } from 'webcad_ue4_api';
|
|
import { MaterialEditorCameraControl } from './MaterialMouseControl';
|
|
import { GetConfig } from '../lib/libOutputConfig';
|
|
|
|
async function textureRenderUpdate(textureRecord:TextureTableRecord){
|
|
const texture = textureRecord['texture'] as Texture;
|
|
|
|
texture.wrapS = textureRecord.WrapS;
|
|
texture.wrapT = textureRecord.WrapT;
|
|
texture.anisotropy = 16;
|
|
texture.rotation = textureRecord.rotation;
|
|
texture.repeat.set(textureRecord.repeatX, textureRecord.repeatY);
|
|
texture.offset.set(textureRecord.moveX, textureRecord.moveY);
|
|
texture.needsUpdate = true;
|
|
|
|
// for (let f of this.waits)
|
|
// f();
|
|
// this.waits.length = 0;
|
|
//
|
|
// this.AsyncUpdated();
|
|
}
|
|
/**
|
|
* 材质编辑器
|
|
*/
|
|
export class MaterialEditor extends Singleton
|
|
{
|
|
private _pointerLocked = false;
|
|
|
|
Geometrys: Map<string, Geometry | BufferGeometry>;
|
|
|
|
CurGeometryName = "球";
|
|
Canvas: HTMLElement;
|
|
ShowObject: Object3D;
|
|
ShowMesh: Mesh;
|
|
Viewer: Viewer;
|
|
|
|
private _MeshMaterial: MeshPhysicalMaterial = new MeshPhysicalMaterial({});
|
|
//构造
|
|
private constructor()
|
|
{
|
|
super();
|
|
this.initGeometrys();
|
|
|
|
this.LoadDefaultExr();
|
|
this.LoadMetalEnv();
|
|
}
|
|
|
|
initGeometrys()
|
|
{
|
|
this.Geometrys = new Map<string, Geometry | BufferGeometry>(
|
|
[
|
|
["球", new SphereBufferGeometry(1000, 32, 32)],
|
|
["圆环", new TorusBufferGeometry(0.8 * 1e3, 0.4 * 1e3, 32, 64)],
|
|
["立方体", new BoxBufferGeometry(1e3, 1e3, 1e3, 1, 1, 1)],
|
|
["环面纽结", new TorusKnotBufferGeometry(0.7 * 1e3, 0.3 * 1e3, 128, 64)],
|
|
["圆锥体", new ConeBufferGeometry(1 * 1e3, 2 * 1e3, 32)],
|
|
// ["球(多面)", new SphereBufferGeometry(1 * 1e3, 64, 64)],
|
|
// ["立方体(多面)", new BoxBufferGeometry(1 * 1e3, 1 * 1e3, 1 * 1e3, 128, 128, 128)]
|
|
]
|
|
);
|
|
}
|
|
initViewer()
|
|
{
|
|
if (!this.Viewer)
|
|
{
|
|
this.Viewer = new Viewer(this.Canvas);
|
|
// this.Viewer.PreViewer.Cursor.CursorObject.visible = false;
|
|
// this.Viewer.UsePass = false;
|
|
this.initScene();
|
|
new MaterialEditorCameraControl(this.Viewer, this.ShowObject.position);
|
|
this.Viewer.ZoomAll();
|
|
|
|
// 初始化相机位置到观察物体的正后方
|
|
// CameraUpdate中的Rotate参数类型并非标准的欧拉角。。。
|
|
this.Viewer.RotateAround(new Vector3(0, -90 * 8, 0), this.ShowObject.position);
|
|
this.Viewer.Pan(new Vector3(0, 0, -1500));
|
|
this.Viewer.UpdateRender();
|
|
this.Viewer.Fov = 90;
|
|
}
|
|
}
|
|
SetViewer(canvas: HTMLElement)
|
|
{
|
|
this.Canvas = canvas;
|
|
this.initViewer();
|
|
this.CurGeometryName = "球";
|
|
}
|
|
initScene()
|
|
{
|
|
let scene = this.Viewer.Scene;
|
|
this.ShowObject = new Object3D();
|
|
let geo = this.Geometrys.get(this.CurGeometryName);
|
|
this.ShowMesh = new Mesh(geo, this._MeshMaterial);
|
|
this.ShowMesh.scale.set(1000, 1000, 1000);
|
|
|
|
this.ShowObject.add(this.ShowMesh);
|
|
scene.add(this.ShowObject);
|
|
|
|
//环境光
|
|
let ambient = new AmbientLight();
|
|
ambient.intensity = 0.7;
|
|
scene.add(ambient);
|
|
}
|
|
|
|
metaTexture: Texture;
|
|
metaPromise: Promise<Texture>;
|
|
async LoadMetalEnv(): Promise<Texture>
|
|
{
|
|
if (this.metaTexture) return this.metaTexture;
|
|
if (this.metaPromise) return this.metaPromise;
|
|
|
|
return new Promise(async (res, rej) =>
|
|
{
|
|
let urls = [...GetConfig().envTextureSrc];
|
|
new CubeTextureLoader()
|
|
.load(urls, (t) =>
|
|
{
|
|
t.encoding = sRGBEncoding;
|
|
t.mapping = CubeRefractionMapping;
|
|
t.encoding = LinearEncoding;
|
|
|
|
let pmremGenerator = new PMREMGenerator3(this.Viewer.Renderer);
|
|
let ldrCubeRenderTarget = pmremGenerator.fromCubemap(t);
|
|
|
|
this.metaTexture = ldrCubeRenderTarget.texture;
|
|
res(this.metaTexture);
|
|
|
|
this.Viewer.Scene.background = this.metaTexture;
|
|
this.Viewer.UpdateRender();
|
|
});
|
|
});
|
|
}
|
|
|
|
exrPromise: Promise<Texture>;
|
|
exrTexture: Texture;
|
|
async LoadDefaultExr(): Promise<Texture>
|
|
{
|
|
if (this.exrTexture) return this.exrTexture;
|
|
if (this.exrPromise) return this.exrPromise;
|
|
|
|
this.exrPromise = new Promise<Texture>((res, rej) =>
|
|
{
|
|
let urls = [...GetConfig().grayEnvTextureSrc];
|
|
new CubeTextureLoader()
|
|
.load(urls, (t) =>
|
|
{
|
|
t.encoding = sRGBEncoding;
|
|
t.mapping = CubeRefractionMapping;
|
|
t.encoding = LinearEncoding;
|
|
|
|
let pmremGenerator = new PMREMGenerator3(this.Viewer.Renderer);
|
|
let target = pmremGenerator.fromCubemap(t);
|
|
this.exrTexture = target.texture;
|
|
res(this.exrTexture);
|
|
|
|
this.Viewer.UpdateRender();
|
|
});
|
|
});
|
|
return this.exrPromise;
|
|
}
|
|
|
|
private Material: PhysicalMaterialRecord;
|
|
setMaterial(mat: PhysicalMaterialRecord)
|
|
{
|
|
this.Material = mat;
|
|
this._MeshMaterial.copy(mat.Material);
|
|
|
|
let mtl = this._MeshMaterial;
|
|
if (mtl.metalness > 0.8)
|
|
this.LoadMetalEnv().then(env =>
|
|
{
|
|
mtl.envMap = env;
|
|
mtl.needsUpdate = true;
|
|
});
|
|
else
|
|
this.LoadDefaultExr().then(exr =>
|
|
{
|
|
mtl.envMap = exr;
|
|
mtl.needsUpdate = true;
|
|
});
|
|
|
|
this.Update();
|
|
}
|
|
|
|
dispose()
|
|
{
|
|
}
|
|
|
|
async Update()
|
|
{
|
|
let mat = this.ShowMesh.material as MeshPhysicalMaterial;
|
|
mat.needsUpdate = true;
|
|
|
|
this._MeshMaterial.copy(this.Material.Material);
|
|
|
|
let mtl = this._MeshMaterial;
|
|
if (mtl.metalness > 0.8)
|
|
this.LoadMetalEnv().then(env =>
|
|
{
|
|
mtl.envMap = env;
|
|
mtl.needsUpdate = true;
|
|
});
|
|
else
|
|
this.LoadDefaultExr().then(exr =>
|
|
{
|
|
mtl.envMap = exr;
|
|
mtl.needsUpdate = true;
|
|
});
|
|
|
|
this.Viewer.UpdateRender();
|
|
}
|
|
}
|