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