Warning, /firebird/packages/epic/src/epic-geometry-prettifier.ts is written in an unsupported language. File is not indexed.
0001 import * as THREE from "three";
0002 import { Object3D, Scene, Group, Mesh, MeshPhysicalMaterial } from "three";
0003 import { PMREMGenerator, WebGPURenderer } from "three/webgpu";
0004
0005 /**
0006 * EIC Geometry Prettifier
0007 *
0008 * Applies advanced visual effects to geometry elements when high-quality rendering is enabled.
0009 * Uses procedural environment with studio-style lighting for reflections.
0010 */
0011
0012 // Cached environment map
0013 let cachedEnvMap: THREE.Texture | null = null;
0014
0015 /**
0016 * Creates a procedural environment map with gradient and bright light sources.
0017 */
0018 function createProceduralEnvironment(renderer: WebGPURenderer): THREE.Texture | null {
0019 if (!renderer) {
0020 console.warn('[EicGeometryPrettifier]: No renderer provided');
0021 return null;
0022 }
0023
0024 if (cachedEnvMap) {
0025 return cachedEnvMap;
0026 }
0027
0028 const envScene = new Scene();
0029
0030 // Create gradient sphere
0031 const envGeometry = new THREE.SphereGeometry(500, 64, 64);
0032 const colors: number[] = [];
0033 const positionAttribute = envGeometry.getAttribute('position');
0034
0035 for (let i = 0; i < positionAttribute.count; i++) {
0036 const y = positionAttribute.getY(i);
0037 const x = positionAttribute.getX(i);
0038 const z = positionAttribute.getZ(i);
0039 const t = (y + 500) / 1000;
0040
0041 // Gradient: dark bottom to bright top
0042 const bottomColor = new THREE.Color(0x505060);
0043 const midColor = new THREE.Color(0x8090a0);
0044 const topColor = new THREE.Color(0xd0e0f0);
0045
0046 let color: THREE.Color;
0047 if (t < 0.4) {
0048 color = bottomColor.clone().lerp(midColor, t / 0.4);
0049 } else {
0050 color = midColor.clone().lerp(topColor, (t - 0.4) / 0.6);
0051 }
0052
0053 // Add variation
0054 const angle = Math.atan2(z, x);
0055 const variation = Math.sin(angle * 3) * 0.1 + Math.sin(angle * 7) * 0.05;
0056 color.offsetHSL(0, 0, variation);
0057
0058 colors.push(color.r, color.g, color.b);
0059 }
0060
0061 envGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
0062
0063 const envMaterial = new THREE.MeshBasicMaterial({
0064 vertexColors: true,
0065 side: THREE.BackSide
0066 });
0067
0068 const envMesh = new Mesh(envGeometry, envMaterial);
0069 envScene.add(envMesh);
0070
0071 // Add bright light sources
0072 const lights: { geom: THREE.BufferGeometry; mat: THREE.Material }[] = [];
0073
0074 const addLight = (x: number, y: number, z: number, size: number, intensity: number) => {
0075 const geom = new THREE.SphereGeometry(size, 16, 16);
0076 const mat = new THREE.MeshBasicMaterial({
0077 color: new THREE.Color(intensity, intensity, intensity * 0.98)
0078 });
0079 const mesh = new Mesh(geom, mat);
0080 mesh.position.set(x, y, z);
0081 envScene.add(mesh);
0082 lights.push({ geom, mat });
0083 };
0084
0085 // Main lights
0086 addLight(300, 350, 150, 40, 2.0);
0087 addLight(-250, 200, -200, 25, 1.5);
0088 addLight(100, -100, 350, 20, 1.2);
0089 addLight(-150, 400, 250, 30, 1.8);
0090
0091 // Generate PMREM
0092 const pmremGenerator = new PMREMGenerator(renderer);
0093 pmremGenerator.compileEquirectangularShader();
0094 const envMap = pmremGenerator.fromScene(envScene, 0, 0.1, 1000).texture;
0095
0096 // Cleanup
0097 pmremGenerator.dispose();
0098 envGeometry.dispose();
0099 envMaterial.dispose();
0100 lights.forEach(l => { l.geom.dispose(); l.mat.dispose(); });
0101
0102 cachedEnvMap = envMap;
0103
0104 return envMap;
0105 }
0106
0107 /**
0108 * Find objects by name pattern
0109 */
0110 function findObjectsByPattern(root: Object3D, pattern: string): Object3D[] {
0111 const results: Object3D[] = [];
0112 const regex = new RegExp(pattern.replace(/\*/g, '.*'), 'i');
0113 root.traverse((child) => {
0114 if (regex.test(child.name)) {
0115 results.push(child);
0116 }
0117 });
0118 return results;
0119 }
0120
0121 /**
0122 * Apply mirror material
0123 */
0124 function applyMirrorMaterial(
0125 objects: Object3D[],
0126 envMap: THREE.Texture | null,
0127 clippingPlanes?: THREE.Plane[]
0128 ): void {
0129 for (const obj of objects) {
0130 if (!(obj instanceof Mesh)) continue;
0131
0132 const mirrorMaterial = new MeshPhysicalMaterial({
0133 color: 0xffffff,
0134 metalness: 1.0,
0135 roughness: 0.0,
0136 envMap: envMap,
0137 envMapIntensity: 2.5,
0138 reflectivity: 1.0,
0139 clearcoat: 1.0,
0140 clearcoatRoughness: 0.0,
0141 side: THREE.DoubleSide,
0142 clippingPlanes: clippingPlanes,
0143 clipIntersection: true,
0144 });
0145
0146 if (obj.material) {
0147 if (Array.isArray(obj.material)) {
0148 obj.material.forEach(m => m.dispose());
0149 } else {
0150 obj.material.dispose();
0151 }
0152 }
0153
0154 obj.material = mirrorMaterial;
0155 }
0156
0157 if (objects.length > 0) {
0158 console.log(`[EicGeometryPrettifier]: Applied mirror material to ${objects.length} objects`);
0159 }
0160 }
0161
0162 export interface PrettifyOptions {
0163 renderer: WebGPURenderer;
0164 sceneGeometry: Group;
0165 scene: Scene;
0166 clippingPlanes?: THREE.Plane[];
0167 }
0168
0169 /**
0170 * Main prettify function
0171 */
0172 export async function prettify(geometry: Object3D, options: PrettifyOptions): Promise<void> {
0173 const envMap = createProceduralEnvironment(options.renderer);
0174
0175 if (envMap && options.scene instanceof Scene) {
0176 options.scene.environment = envMap;
0177 }
0178
0179 const drichMirrors = findObjectsByPattern(geometry, 'DRICH_mirror');
0180 applyMirrorMaterial(drichMirrors, envMap, options.clippingPlanes);
0181 }
0182
0183 /**
0184 * Cleanup
0185 */
0186 export function disposePrettifier(): void {
0187 if (cachedEnvMap) {
0188 cachedEnvMap.dispose();
0189 cachedEnvMap = null;
0190 }
0191 }