import { Color, DataTexture, DoubleSide, MeshBasicMaterial, MeshStandardMaterial, RepeatWrapping, RGBFormat, Texture, TextureLoader, Vector2 } from "three" import { useLoader, type TresLoader } from '@tresjs/core' import { getFilename, patterns, type patternTypes } from "~/components/pattern" const set_metaril_func = (scene: any, material: any) => { scene.children.forEach((el: any) => { if (el.isMesh && !el.isInstancedMesh) { el.castShadow = true el.receiveShadow = true } if (el.material && material.normalMap) { // Получите UV-координаты const uvAttribute = el.geometry.getAttribute('uv'); const uvs = []; if (uvAttribute) { for (let i = 0; i < uvAttribute.count; i++) { uvs.push(uvAttribute.getX(i), uvAttribute.getY(i)); } // Вычисление минимальных и максимальных UV const minU = Math.min(...uvs.filter((_, index) => index % 2 === 0)); // X координаты const maxU = Math.max(...uvs.filter((_, index) => index % 2 === 0)); const minV = Math.min(...uvs.filter((_, index) => index % 2 === 1)); // Y координаты const maxV = Math.max(...uvs.filter((_, index) => index % 2 === 1)); // Определите размеры текстуры на поверхности const surfaceWidth = maxU - minU; const surfaceHeight = (maxV - minV) * el.scale.y; material.normalMap.wrapS = RepeatWrapping; material.normalMap.wrapT = RepeatWrapping; material.normalMap.repeat.set(surfaceWidth, surfaceHeight); material.normalMap.needsUpdate = true } } if (el.material) el.material = material set_metaril_func(el, material) }) } const loaded_patterns: { [key: string]: any } = {} for (let index = 0; index < patterns.length; index++) { const element = patterns[index]; const filename = getFilename(element.name) if (filename) { loaded_patterns[filename] = useLoader(TextureLoader, filename) } } function generateNoiseTexture(width: number, height: number) { const size = width * height; const data = new Uint8Array(4 * size); const color = new Color(0xffffff); for (let i = 0; i < size; i++) { const r = Math.floor(Math.random() * 255) * 0.05; const g = 0; const b = Math.floor(Math.random() * 255) * 0.05; const stride = i * 4; data[stride] = r; data[stride + 1] = g; data[stride + 2] = b; data[stride + 3] = 255; } // used the buffer to create a DataTexture const texture = new DataTexture(data, width, height); texture.needsUpdate = true; return texture; } export const set_material = (scene: any, color: any, pattern: { pattern: patternTypes, count: number } | undefined = undefined) => { let c = color const material = new MeshStandardMaterial({ color: new Color(c || '#9c9c00'), // alphaMap: pattern ? texture : null, transparent: true, opacity: 1, roughness: 0.2, metalness: 0, side: DoubleSide, }) if (pattern && pattern.pattern !== undefined) { const filename = getFilename(pattern.pattern) if (filename) { const texture = loaded_patterns[filename] texture.then((res: Texture) => { res.wrapT = RepeatWrapping; res.repeat.set(1, pattern.count); res.needsUpdate = true material.alphaMap = res }) } } if (scene) set_metaril_func(scene, material) else console.log(scene) }