@aura3d/assets 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/README.md +17 -0
  2. package/dist/AdvancedAssetCorpus.d.ts +124 -0
  3. package/dist/AdvancedAssetCorpus.d.ts.map +1 -0
  4. package/dist/AdvancedAssetCorpus.js +266 -0
  5. package/dist/AdvancedAssetCorpus.js.map +1 -0
  6. package/dist/AssetBundleCacheFixtures.d.ts +62 -0
  7. package/dist/AssetBundleCacheFixtures.d.ts.map +1 -0
  8. package/dist/AssetBundleCacheFixtures.js +222 -0
  9. package/dist/AssetBundleCacheFixtures.js.map +1 -0
  10. package/dist/AssetCache.d.ts +21 -0
  11. package/dist/AssetCache.d.ts.map +1 -0
  12. package/dist/AssetCache.js +54 -0
  13. package/dist/AssetCache.js.map +1 -0
  14. package/dist/AssetCompatibility.d.ts +54 -0
  15. package/dist/AssetCompatibility.d.ts.map +1 -0
  16. package/dist/AssetCompatibility.js +122 -0
  17. package/dist/AssetCompatibility.js.map +1 -0
  18. package/dist/AssetCorpus.d.ts +88 -0
  19. package/dist/AssetCorpus.d.ts.map +1 -0
  20. package/dist/AssetCorpus.js +215 -0
  21. package/dist/AssetCorpus.js.map +1 -0
  22. package/dist/AssetDependencyGraph.d.ts +12 -0
  23. package/dist/AssetDependencyGraph.d.ts.map +1 -0
  24. package/dist/AssetDependencyGraph.js +66 -0
  25. package/dist/AssetDependencyGraph.js.map +1 -0
  26. package/dist/AssetHandle.d.ts +26 -0
  27. package/dist/AssetHandle.d.ts.map +1 -0
  28. package/dist/AssetHandle.js +53 -0
  29. package/dist/AssetHandle.js.map +1 -0
  30. package/dist/AssetImportPreflight.d.ts +43 -0
  31. package/dist/AssetImportPreflight.d.ts.map +1 -0
  32. package/dist/AssetImportPreflight.js +117 -0
  33. package/dist/AssetImportPreflight.js.map +1 -0
  34. package/dist/AssetInspection.d.ts +183 -0
  35. package/dist/AssetInspection.d.ts.map +1 -0
  36. package/dist/AssetInspection.js +397 -0
  37. package/dist/AssetInspection.js.map +1 -0
  38. package/dist/AssetLoader.d.ts +26 -0
  39. package/dist/AssetLoader.d.ts.map +1 -0
  40. package/dist/AssetLoader.js +12 -0
  41. package/dist/AssetLoader.js.map +1 -0
  42. package/dist/AssetManager.d.ts +37 -0
  43. package/dist/AssetManager.d.ts.map +1 -0
  44. package/dist/AssetManager.js +161 -0
  45. package/dist/AssetManager.js.map +1 -0
  46. package/dist/AssetRegistry.d.ts +10 -0
  47. package/dist/AssetRegistry.d.ts.map +1 -0
  48. package/dist/AssetRegistry.js +34 -0
  49. package/dist/AssetRegistry.js.map +1 -0
  50. package/dist/AssetRenderDefaults.d.ts +13 -0
  51. package/dist/AssetRenderDefaults.d.ts.map +1 -0
  52. package/dist/AssetRenderDefaults.js +23 -0
  53. package/dist/AssetRenderDefaults.js.map +1 -0
  54. package/dist/AudioLoader.d.ts +17 -0
  55. package/dist/AudioLoader.d.ts.map +1 -0
  56. package/dist/AudioLoader.js +23 -0
  57. package/dist/AudioLoader.js.map +1 -0
  58. package/dist/BlenderExportValidation.d.ts +64 -0
  59. package/dist/BlenderExportValidation.d.ts.map +1 -0
  60. package/dist/BlenderExportValidation.js +143 -0
  61. package/dist/BlenderExportValidation.js.map +1 -0
  62. package/dist/CarConceptMaterialStability.d.ts +28 -0
  63. package/dist/CarConceptMaterialStability.d.ts.map +1 -0
  64. package/dist/CarConceptMaterialStability.js +1308 -0
  65. package/dist/CarConceptMaterialStability.js.map +1 -0
  66. package/dist/EXRLoader.d.ts +2 -0
  67. package/dist/EXRLoader.d.ts.map +1 -0
  68. package/dist/EXRLoader.js +2 -0
  69. package/dist/EXRLoader.js.map +1 -0
  70. package/dist/ExternalParityGLTFCorpus.d.ts +39 -0
  71. package/dist/ExternalParityGLTFCorpus.d.ts.map +1 -0
  72. package/dist/ExternalParityGLTFCorpus.js +32 -0
  73. package/dist/ExternalParityGLTFCorpus.js.map +1 -0
  74. package/dist/GLTFAnimationRuntime.d.ts +243 -0
  75. package/dist/GLTFAnimationRuntime.d.ts.map +1 -0
  76. package/dist/GLTFAnimationRuntime.js +954 -0
  77. package/dist/GLTFAnimationRuntime.js.map +1 -0
  78. package/dist/GLTFCompressionDecoders.d.ts +42 -0
  79. package/dist/GLTFCompressionDecoders.d.ts.map +1 -0
  80. package/dist/GLTFCompressionDecoders.js +99 -0
  81. package/dist/GLTFCompressionDecoders.js.map +1 -0
  82. package/dist/GLTFExtensionSupport.d.ts +33 -0
  83. package/dist/GLTFExtensionSupport.d.ts.map +1 -0
  84. package/dist/GLTFExtensionSupport.js +85 -0
  85. package/dist/GLTFExtensionSupport.js.map +1 -0
  86. package/dist/GLTFLoader.d.ts +361 -0
  87. package/dist/GLTFLoader.d.ts.map +1 -0
  88. package/dist/GLTFLoader.js +2735 -0
  89. package/dist/GLTFLoader.js.map +1 -0
  90. package/dist/GLTFRenderResources.d.ts +162 -0
  91. package/dist/GLTFRenderResources.d.ts.map +1 -0
  92. package/dist/GLTFRenderResources.js +1684 -0
  93. package/dist/GLTFRenderResources.js.map +1 -0
  94. package/dist/HDRLoader.d.ts +2 -0
  95. package/dist/HDRLoader.d.ts.map +1 -0
  96. package/dist/HDRLoader.js +2 -0
  97. package/dist/HDRLoader.js.map +1 -0
  98. package/dist/ImageLoader.d.ts +15 -0
  99. package/dist/ImageLoader.d.ts.map +1 -0
  100. package/dist/ImageLoader.js +36 -0
  101. package/dist/ImageLoader.js.map +1 -0
  102. package/dist/ImportPipeline.d.ts +39 -0
  103. package/dist/ImportPipeline.d.ts.map +1 -0
  104. package/dist/ImportPipeline.js +105 -0
  105. package/dist/ImportPipeline.js.map +1 -0
  106. package/dist/KTX2BasisTextureTranscoder.d.ts +9 -0
  107. package/dist/KTX2BasisTextureTranscoder.d.ts.map +1 -0
  108. package/dist/KTX2BasisTextureTranscoder.js +178 -0
  109. package/dist/KTX2BasisTextureTranscoder.js.map +1 -0
  110. package/dist/LoadContext.d.ts +20 -0
  111. package/dist/LoadContext.d.ts.map +1 -0
  112. package/dist/LoadContext.js +42 -0
  113. package/dist/LoadContext.js.map +1 -0
  114. package/dist/MaterialLoader.d.ts +17 -0
  115. package/dist/MaterialLoader.d.ts.map +1 -0
  116. package/dist/MaterialLoader.js +138 -0
  117. package/dist/MaterialLoader.js.map +1 -0
  118. package/dist/MeshOptimization.d.ts +20 -0
  119. package/dist/MeshOptimization.d.ts.map +1 -0
  120. package/dist/MeshOptimization.js +65 -0
  121. package/dist/MeshOptimization.js.map +1 -0
  122. package/dist/OBJLoader.d.ts +13 -0
  123. package/dist/OBJLoader.d.ts.map +1 -0
  124. package/dist/OBJLoader.js +492 -0
  125. package/dist/OBJLoader.js.map +1 -0
  126. package/dist/SceneAnalysisFixtures.d.ts +100 -0
  127. package/dist/SceneAnalysisFixtures.d.ts.map +1 -0
  128. package/dist/SceneAnalysisFixtures.js +331 -0
  129. package/dist/SceneAnalysisFixtures.js.map +1 -0
  130. package/dist/SceneLoader.d.ts +27 -0
  131. package/dist/SceneLoader.d.ts.map +1 -0
  132. package/dist/SceneLoader.js +40 -0
  133. package/dist/SceneLoader.js.map +1 -0
  134. package/dist/ShaderLoader.d.ts +12 -0
  135. package/dist/ShaderLoader.d.ts.map +1 -0
  136. package/dist/ShaderLoader.js +18 -0
  137. package/dist/ShaderLoader.js.map +1 -0
  138. package/dist/TextureLoader.d.ts +16 -0
  139. package/dist/TextureLoader.d.ts.map +1 -0
  140. package/dist/TextureLoader.js +17 -0
  141. package/dist/TextureLoader.js.map +1 -0
  142. package/dist/TexturePipeline.d.ts +24 -0
  143. package/dist/TexturePipeline.d.ts.map +1 -0
  144. package/dist/TexturePipeline.js +64 -0
  145. package/dist/TexturePipeline.js.map +1 -0
  146. package/dist/TextureStreaming.d.ts +10 -0
  147. package/dist/TextureStreaming.d.ts.map +1 -0
  148. package/dist/TextureStreaming.js +11 -0
  149. package/dist/TextureStreaming.js.map +1 -0
  150. package/dist/WorkerAssetJobs.d.ts +18 -0
  151. package/dist/WorkerAssetJobs.d.ts.map +1 -0
  152. package/dist/WorkerAssetJobs.js +37 -0
  153. package/dist/WorkerAssetJobs.js.map +1 -0
  154. package/dist/advanced-gallery/index.d.ts +3 -0
  155. package/dist/advanced-gallery/index.d.ts.map +1 -0
  156. package/dist/advanced-gallery/index.js +2 -0
  157. package/dist/advanced-gallery/index.js.map +1 -0
  158. package/dist/asset-corpus/GLTFSceneLoader.d.ts +3 -0
  159. package/dist/asset-corpus/GLTFSceneLoader.d.ts.map +1 -0
  160. package/dist/asset-corpus/GLTFSceneLoader.js +2 -0
  161. package/dist/asset-corpus/GLTFSceneLoader.js.map +1 -0
  162. package/dist/asset-corpus/ProductionAssetCorpus.d.ts +89 -0
  163. package/dist/asset-corpus/ProductionAssetCorpus.d.ts.map +1 -0
  164. package/dist/asset-corpus/ProductionAssetCorpus.js +116 -0
  165. package/dist/asset-corpus/ProductionAssetCorpus.js.map +1 -0
  166. package/dist/asset-corpus/ProductionAssetPipeline.d.ts +3 -0
  167. package/dist/asset-corpus/ProductionAssetPipeline.d.ts.map +1 -0
  168. package/dist/asset-corpus/ProductionAssetPipeline.js +3 -0
  169. package/dist/asset-corpus/ProductionAssetPipeline.js.map +1 -0
  170. package/dist/asset-corpus/ProductionGLTFRenderPipeline.d.ts +65 -0
  171. package/dist/asset-corpus/ProductionGLTFRenderPipeline.d.ts.map +1 -0
  172. package/dist/asset-corpus/ProductionGLTFRenderPipeline.js +110 -0
  173. package/dist/asset-corpus/ProductionGLTFRenderPipeline.js.map +1 -0
  174. package/dist/asset-corpus/ProductionHDRTextureLoader.d.ts +8 -0
  175. package/dist/asset-corpus/ProductionHDRTextureLoader.d.ts.map +1 -0
  176. package/dist/asset-corpus/ProductionHDRTextureLoader.js +2 -0
  177. package/dist/asset-corpus/ProductionHDRTextureLoader.js.map +1 -0
  178. package/dist/asset-corpus/ProductionKTX2TextureLoader.d.ts +7 -0
  179. package/dist/asset-corpus/ProductionKTX2TextureLoader.d.ts.map +1 -0
  180. package/dist/asset-corpus/ProductionKTX2TextureLoader.js +2 -0
  181. package/dist/asset-corpus/ProductionKTX2TextureLoader.js.map +1 -0
  182. package/dist/asset-corpus/ProductionTextureLoader.d.ts +7 -0
  183. package/dist/asset-corpus/ProductionTextureLoader.d.ts.map +1 -0
  184. package/dist/asset-corpus/ProductionTextureLoader.js +2 -0
  185. package/dist/asset-corpus/ProductionTextureLoader.js.map +1 -0
  186. package/dist/asset-corpus/index.d.ts +10 -0
  187. package/dist/asset-corpus/index.d.ts.map +1 -0
  188. package/dist/asset-corpus/index.js +8 -0
  189. package/dist/asset-corpus/index.js.map +1 -0
  190. package/dist/browser-index.d.ts +48 -0
  191. package/dist/browser-index.d.ts.map +1 -0
  192. package/dist/browser-index.js +26 -0
  193. package/dist/browser-index.js.map +1 -0
  194. package/dist/createRenderableScene.d.ts +23 -0
  195. package/dist/createRenderableScene.d.ts.map +1 -0
  196. package/dist/createRenderableScene.js +94 -0
  197. package/dist/createRenderableScene.js.map +1 -0
  198. package/dist/index.d.ts +82 -0
  199. package/dist/index.d.ts.map +1 -0
  200. package/dist/index.js +45 -0
  201. package/dist/index.js.map +1 -0
  202. package/dist/loadRenderableAsset.d.ts +16 -0
  203. package/dist/loadRenderableAsset.d.ts.map +1 -0
  204. package/dist/loadRenderableAsset.js +50 -0
  205. package/dist/loadRenderableAsset.js.map +1 -0
  206. package/dist/loaders/CubeTextureLoader.d.ts +4 -0
  207. package/dist/loaders/CubeTextureLoader.d.ts.map +1 -0
  208. package/dist/loaders/CubeTextureLoader.js +9 -0
  209. package/dist/loaders/CubeTextureLoader.js.map +1 -0
  210. package/dist/loaders/EXRLoader.d.ts +4 -0
  211. package/dist/loaders/EXRLoader.d.ts.map +1 -0
  212. package/dist/loaders/EXRLoader.js +10 -0
  213. package/dist/loaders/EXRLoader.js.map +1 -0
  214. package/dist/loaders/HDRLoader.d.ts +4 -0
  215. package/dist/loaders/HDRLoader.d.ts.map +1 -0
  216. package/dist/loaders/HDRLoader.js +7 -0
  217. package/dist/loaders/HDRLoader.js.map +1 -0
  218. package/dist/loaders/KTX2Loader.d.ts +4 -0
  219. package/dist/loaders/KTX2Loader.d.ts.map +1 -0
  220. package/dist/loaders/KTX2Loader.js +7 -0
  221. package/dist/loaders/KTX2Loader.js.map +1 -0
  222. package/dist/loaders/LoaderDiagnostics.d.ts +18 -0
  223. package/dist/loaders/LoaderDiagnostics.d.ts.map +1 -0
  224. package/dist/loaders/LoaderDiagnostics.js +18 -0
  225. package/dist/loaders/LoaderDiagnostics.js.map +1 -0
  226. package/dist/loaders/MTLLoader.d.ts +10 -0
  227. package/dist/loaders/MTLLoader.d.ts.map +1 -0
  228. package/dist/loaders/MTLLoader.js +14 -0
  229. package/dist/loaders/MTLLoader.js.map +1 -0
  230. package/dist/loaders/OBJLoader.d.ts +12 -0
  231. package/dist/loaders/OBJLoader.d.ts.map +1 -0
  232. package/dist/loaders/OBJLoader.js +16 -0
  233. package/dist/loaders/OBJLoader.js.map +1 -0
  234. package/dist/loaders/TextureLoader.d.ts +6 -0
  235. package/dist/loaders/TextureLoader.d.ts.map +1 -0
  236. package/dist/loaders/TextureLoader.js +11 -0
  237. package/dist/loaders/TextureLoader.js.map +1 -0
  238. package/dist/loaders/ThreeCompatGLTFLoader.d.ts +10 -0
  239. package/dist/loaders/ThreeCompatGLTFLoader.d.ts.map +1 -0
  240. package/dist/loaders/ThreeCompatGLTFLoader.js +13 -0
  241. package/dist/loaders/ThreeCompatGLTFLoader.js.map +1 -0
  242. package/dist/loaders/index.d.ts +15 -0
  243. package/dist/loaders/index.d.ts.map +1 -0
  244. package/dist/loaders/index.js +10 -0
  245. package/dist/loaders/index.js.map +1 -0
  246. package/dist/threejs-compatibility/ThreeCompatAssetProvenance.d.ts +34 -0
  247. package/dist/threejs-compatibility/ThreeCompatAssetProvenance.d.ts.map +1 -0
  248. package/dist/threejs-compatibility/ThreeCompatAssetProvenance.js +16 -0
  249. package/dist/threejs-compatibility/ThreeCompatAssetProvenance.js.map +1 -0
  250. package/dist/threejs-compatibility/ThreeCompatAssetRegistry.d.ts +29 -0
  251. package/dist/threejs-compatibility/ThreeCompatAssetRegistry.d.ts.map +1 -0
  252. package/dist/threejs-compatibility/ThreeCompatAssetRegistry.js +33 -0
  253. package/dist/threejs-compatibility/ThreeCompatAssetRegistry.js.map +1 -0
  254. package/dist/threejs-example-parity/index.d.ts +20 -0
  255. package/dist/threejs-example-parity/index.d.ts.map +1 -0
  256. package/dist/threejs-example-parity/index.js +218 -0
  257. package/dist/threejs-example-parity/index.js.map +1 -0
  258. package/package.json +23 -0
  259. package/src/AdvancedAssetCorpus.ts +454 -0
  260. package/src/AssetBundleCacheFixtures.ts +290 -0
  261. package/src/AssetCache.ts +76 -0
  262. package/src/AssetCompatibility.ts +224 -0
  263. package/src/AssetCorpus.ts +329 -0
  264. package/src/AssetDependencyGraph.ts +83 -0
  265. package/src/AssetHandle.ts +74 -0
  266. package/src/AssetImportPreflight.ts +179 -0
  267. package/src/AssetInspection.ts +706 -0
  268. package/src/AssetLoader.ts +36 -0
  269. package/src/AssetManager.ts +211 -0
  270. package/src/AssetRegistry.ts +44 -0
  271. package/src/AssetRenderDefaults.ts +36 -0
  272. package/src/AudioLoader.ts +41 -0
  273. package/src/BlenderExportValidation.ts +227 -0
  274. package/src/CarConceptMaterialStability.ts +1405 -0
  275. package/src/EXRLoader.ts +1 -0
  276. package/src/ExternalParityGLTFCorpus.ts +65 -0
  277. package/src/GLTFAnimationRuntime.ts +1221 -0
  278. package/src/GLTFCompressionDecoders.ts +190 -0
  279. package/src/GLTFExtensionSupport.ts +138 -0
  280. package/src/GLTFLoader.ts +4001 -0
  281. package/src/GLTFRenderResources.ts +2105 -0
  282. package/src/HDRLoader.ts +1 -0
  283. package/src/ImageLoader.ts +52 -0
  284. package/src/ImportPipeline.ts +148 -0
  285. package/src/KTX2BasisTextureTranscoder.ts +224 -0
  286. package/src/LoadContext.ts +60 -0
  287. package/src/MaterialLoader.ts +166 -0
  288. package/src/MeshOptimization.ts +93 -0
  289. package/src/OBJLoader.ts +551 -0
  290. package/src/SceneAnalysisFixtures.ts +438 -0
  291. package/src/SceneLoader.ts +62 -0
  292. package/src/ShaderLoader.ts +30 -0
  293. package/src/TextureLoader.ts +30 -0
  294. package/src/TexturePipeline.ts +96 -0
  295. package/src/TextureStreaming.ts +20 -0
  296. package/src/WorkerAssetJobs.ts +56 -0
  297. package/src/advanced-gallery/index.ts +18 -0
  298. package/src/asset-corpus/GLTFSceneLoader.ts +9 -0
  299. package/src/asset-corpus/ProductionAssetCorpus.ts +230 -0
  300. package/src/asset-corpus/ProductionAssetPipeline.ts +5 -0
  301. package/src/asset-corpus/ProductionGLTFRenderPipeline.ts +182 -0
  302. package/src/asset-corpus/ProductionHDRTextureLoader.ts +2 -0
  303. package/src/asset-corpus/ProductionKTX2TextureLoader.ts +2 -0
  304. package/src/asset-corpus/ProductionTextureLoader.ts +2 -0
  305. package/src/asset-corpus/index.ts +29 -0
  306. package/src/browser-index.ts +224 -0
  307. package/src/createRenderableScene.ts +128 -0
  308. package/src/index.ts +317 -0
  309. package/src/loadRenderableAsset.ts +67 -0
  310. package/src/loaders/CubeTextureLoader.ts +8 -0
  311. package/src/loaders/EXRLoader.ts +10 -0
  312. package/src/loaders/HDRLoader.ts +7 -0
  313. package/src/loaders/KTX2Loader.ts +7 -0
  314. package/src/loaders/LoaderDiagnostics.ts +36 -0
  315. package/src/loaders/MTLLoader.ts +20 -0
  316. package/src/loaders/OBJLoader.ts +24 -0
  317. package/src/loaders/TextureLoader.ts +14 -0
  318. package/src/loaders/ThreeCompatGLTFLoader.ts +19 -0
  319. package/src/loaders/index.ts +14 -0
  320. package/src/threejs-compatibility/ThreeCompatAssetProvenance.ts +51 -0
  321. package/src/threejs-compatibility/ThreeCompatAssetRegistry.ts +61 -0
  322. package/src/threejs-example-parity/index.ts +262 -0
  323. package/tests/assets.test.ts +311 -0
  324. package/tsconfig.json +7 -0
@@ -0,0 +1,1405 @@
1
+ import type { Material, RenderState, UniformValue } from "@aura3d/rendering";
2
+ import type { GLTFMaterialRenderStateOverride } from "./GLTFRenderResources";
3
+
4
+ export type CarConceptMaterialStabilityProfile = "gallery" | "cinematic";
5
+
6
+ export interface CarConceptMaterialBaseline {
7
+ readonly roughness?: number;
8
+ readonly metallic?: number;
9
+ readonly clearcoat?: number;
10
+ }
11
+
12
+ export interface CarConceptMaterialStabilityOptions {
13
+ readonly materialKey?: string;
14
+ readonly sourceMaterialName?: string;
15
+ readonly nodeName?: string;
16
+ readonly profile?: CarConceptMaterialStabilityProfile;
17
+ readonly baseline?: CarConceptMaterialBaseline;
18
+ readonly roughnessScale?: number;
19
+ readonly metallicScale?: number;
20
+ readonly clearcoatBoost?: number;
21
+ }
22
+
23
+ const BODY_PATTERN = /Paint [12] (Carmine|Pearl|Pearly|Graphite)|Body.*Color|Panel Sides|BodyRoofPanel|BodyPillars|Upper Shell|UpperShell|BodyUpper|UpperBody|Secondary Panel|Wheel ?Arch|Wheelarches|WheelWell|WheelHouse|Fender|Side ?(Panel|Surface)/i;
24
+ const GLASS_PATTERN = /Glass|Window|Windshield|Canopy|Headlight|Taillight|Brakelight|Signallight|Turnsignal|Light ?Lens|\bLens\b/i;
25
+ const LICENSE_PATTERN = /License(?: Plate)?|LicensePlate|Number ?Plate/i;
26
+ const LIGHT_LENS_PATTERN = /Headlight|Taillight|Brakelight|Signallight|Turnsignal|Signal ?Light|Light ?Lens|\bLens\b|BodyHeadlights|BodyTaillights|BodyTurnsignals/i;
27
+ const DETAIL_PATTERN = /Tireside|Tiretread|Rim[12]|Disc|Brake|Hardware|Mirror|Dashboard|Mechanical|Interior|Floormat|material[-_ ]?2|Gasket|Wiper|Handle|HoodTopgrill|TaillightsPanels|Trim|Moulding|Molding|Weatherstrip|Seal|Wheel ?Arch|Wheelarches|WheelWell|WheelHouse|License(?: Plate)?|LicensePlate|Number ?Plate/i;
28
+ const DARK_TRIM_PATTERN = /Gasket|Wiper|Handle|Mirror|HoodTopgrill|TaillightsPanels|Hardware|material[-_ ]?2|\bTrim\b|Moulding|Molding|Weatherstrip|Seal/i;
29
+
30
+ type Rgb = readonly [number, number, number];
31
+ type Rgba = readonly [number, number, number, number];
32
+
33
+ interface CarConceptMaterialRuntimeSurface {
34
+ readonly opacity: number;
35
+ readonly alphaTest: number;
36
+ readonly transmission: number;
37
+ readonly clearcoat: number;
38
+ readonly specular: number;
39
+ readonly metalness: number;
40
+ readonly roughness: number;
41
+ readonly envMapIntensity: number;
42
+ readonly emissive: Rgb;
43
+ readonly toneMapped: boolean;
44
+ }
45
+
46
+ interface GalleryCarConceptRoleSurface extends CarConceptMaterialRuntimeSurface {
47
+ readonly baseColor: Rgba;
48
+ readonly baseColorTextureEnabled: number;
49
+ readonly normalTextureEnabled: number;
50
+ readonly normalScale: number;
51
+ readonly occlusionTextureEnabled: number;
52
+ readonly occlusionStrength: number;
53
+ readonly metallic: number;
54
+ readonly specularColorFactor: Rgb;
55
+ readonly clearcoatRoughness: number;
56
+ readonly materialEnvironmentSpecularScale: number;
57
+ readonly emissiveStrength: number;
58
+ }
59
+
60
+ const GALLERY_ROLE_SURFACES: Record<Exclude<CarConceptMaterialVisualRole, "unclassified">, GalleryCarConceptRoleSurface> = {
61
+ "body-primary-paint": {
62
+ baseColor: [0.72, 0.0065, 0.0038, 1],
63
+ baseColorTextureEnabled: 0,
64
+ normalTextureEnabled: 1,
65
+ normalScale: 0.32,
66
+ occlusionTextureEnabled: 1,
67
+ occlusionStrength: 0.18,
68
+ metallic: 0.06,
69
+ roughness: 0.22,
70
+ specular: 0.62,
71
+ specularColorFactor: [0.56, 0.044, 0.028],
72
+ clearcoat: 0.62,
73
+ clearcoatRoughness: 0.28,
74
+ materialEnvironmentSpecularScale: 0.28,
75
+ envMapIntensity: 0.28,
76
+ emissive: [0, 0, 0],
77
+ emissiveStrength: 0,
78
+ opacity: 1,
79
+ alphaTest: 0,
80
+ transmission: 0,
81
+ metalness: 0.06,
82
+ toneMapped: true
83
+ },
84
+ "body-secondary-paint": {
85
+ baseColor: [0.14, 0.0024, 0.0016, 1],
86
+ baseColorTextureEnabled: 0,
87
+ normalTextureEnabled: 1,
88
+ normalScale: 0.28,
89
+ occlusionTextureEnabled: 1,
90
+ occlusionStrength: 0.2,
91
+ metallic: 0.035,
92
+ roughness: 0.31,
93
+ specular: 0.38,
94
+ specularColorFactor: [0.34, 0.034, 0.024],
95
+ clearcoat: 0.4,
96
+ clearcoatRoughness: 0.4,
97
+ materialEnvironmentSpecularScale: 0.17,
98
+ envMapIntensity: 0.17,
99
+ emissive: [0, 0, 0],
100
+ emissiveStrength: 0,
101
+ opacity: 1,
102
+ alphaTest: 0,
103
+ transmission: 0,
104
+ metalness: 0.035,
105
+ toneMapped: true
106
+ },
107
+ "roof-panel": {
108
+ baseColor: [0.024, 0.028, 0.03, 1],
109
+ baseColorTextureEnabled: 0,
110
+ normalTextureEnabled: 1,
111
+ normalScale: 0.24,
112
+ occlusionTextureEnabled: 1,
113
+ occlusionStrength: 0.34,
114
+ metallic: 0.02,
115
+ roughness: 0.34,
116
+ specular: 0.22,
117
+ specularColorFactor: [0.11, 0.13, 0.14],
118
+ clearcoat: 0.24,
119
+ clearcoatRoughness: 0.42,
120
+ materialEnvironmentSpecularScale: 0.072,
121
+ envMapIntensity: 0.072,
122
+ emissive: [0, 0, 0],
123
+ emissiveStrength: 0,
124
+ opacity: 1,
125
+ alphaTest: 0,
126
+ transmission: 0,
127
+ metalness: 0.02,
128
+ toneMapped: true
129
+ },
130
+ "side-panel": {
131
+ baseColor: [0.026, 0.004, 0.0026, 1],
132
+ baseColorTextureEnabled: 0,
133
+ normalTextureEnabled: 1,
134
+ normalScale: 0.42,
135
+ occlusionTextureEnabled: 1,
136
+ occlusionStrength: 0.62,
137
+ metallic: 0.015,
138
+ roughness: 0.48,
139
+ specular: 0.11,
140
+ specularColorFactor: [0.12, 0.032, 0.022],
141
+ clearcoat: 0.08,
142
+ clearcoatRoughness: 0.62,
143
+ materialEnvironmentSpecularScale: 0.04,
144
+ envMapIntensity: 0.04,
145
+ emissive: [0, 0, 0],
146
+ emissiveStrength: 0,
147
+ opacity: 1,
148
+ alphaTest: 0,
149
+ transmission: 0,
150
+ metalness: 0.015,
151
+ toneMapped: true
152
+ },
153
+ "pillar-trim": {
154
+ baseColor: [0.014, 0.016, 0.018, 1],
155
+ baseColorTextureEnabled: 0,
156
+ normalTextureEnabled: 0,
157
+ normalScale: 0,
158
+ occlusionTextureEnabled: 1,
159
+ occlusionStrength: 0.018,
160
+ metallic: 0,
161
+ roughness: 0.74,
162
+ specular: 0.026,
163
+ specularColorFactor: [0.032, 0.03, 0.028],
164
+ clearcoat: 0,
165
+ clearcoatRoughness: 1,
166
+ materialEnvironmentSpecularScale: 0.006,
167
+ envMapIntensity: 0.006,
168
+ emissive: [0, 0, 0],
169
+ emissiveStrength: 0,
170
+ opacity: 1,
171
+ alphaTest: 0,
172
+ transmission: 0,
173
+ metalness: 0,
174
+ toneMapped: true
175
+ },
176
+ "dark-trim": {
177
+ baseColor: [0.012, 0.012, 0.013, 1],
178
+ baseColorTextureEnabled: 0,
179
+ normalTextureEnabled: 0,
180
+ normalScale: 0,
181
+ occlusionTextureEnabled: 1,
182
+ occlusionStrength: 0.018,
183
+ metallic: 0,
184
+ roughness: 0.74,
185
+ specular: 0.026,
186
+ specularColorFactor: [0.032, 0.03, 0.028],
187
+ clearcoat: 0,
188
+ clearcoatRoughness: 1,
189
+ materialEnvironmentSpecularScale: 0.006,
190
+ envMapIntensity: 0.006,
191
+ emissive: [0, 0, 0],
192
+ emissiveStrength: 0,
193
+ opacity: 1,
194
+ alphaTest: 0,
195
+ transmission: 0,
196
+ metalness: 0,
197
+ toneMapped: true
198
+ },
199
+ glass: {
200
+ baseColor: [0.008, 0.018, 0.024, 1],
201
+ baseColorTextureEnabled: 0,
202
+ normalTextureEnabled: 0,
203
+ normalScale: 0,
204
+ occlusionTextureEnabled: 1,
205
+ occlusionStrength: 0.12,
206
+ metallic: 0,
207
+ roughness: 0.28,
208
+ specular: 0.16,
209
+ specularColorFactor: [0.055, 0.072, 0.086],
210
+ clearcoat: 0.06,
211
+ clearcoatRoughness: 0.48,
212
+ materialEnvironmentSpecularScale: 0.052,
213
+ envMapIntensity: 0.052,
214
+ emissive: [0, 0, 0],
215
+ emissiveStrength: 0,
216
+ opacity: 1,
217
+ alphaTest: 0,
218
+ transmission: 0,
219
+ metalness: 0,
220
+ toneMapped: true
221
+ },
222
+ "light-lens": {
223
+ baseColor: [0.018, 0.014, 0.012, 1],
224
+ baseColorTextureEnabled: 0,
225
+ normalTextureEnabled: 0,
226
+ normalScale: 0,
227
+ occlusionTextureEnabled: 1,
228
+ occlusionStrength: 0.05,
229
+ metallic: 0,
230
+ roughness: 0.42,
231
+ specular: 0.09,
232
+ specularColorFactor: [0.08, 0.056, 0.04],
233
+ clearcoat: 0.04,
234
+ clearcoatRoughness: 0.66,
235
+ materialEnvironmentSpecularScale: 0.018,
236
+ envMapIntensity: 0.018,
237
+ emissive: [0, 0, 0],
238
+ emissiveStrength: 0,
239
+ opacity: 1,
240
+ alphaTest: 0,
241
+ transmission: 0,
242
+ metalness: 0,
243
+ toneMapped: true
244
+ },
245
+ "license-plate": {
246
+ baseColor: [0.46, 0.44, 0.38, 1],
247
+ baseColorTextureEnabled: 0,
248
+ normalTextureEnabled: 0,
249
+ normalScale: 0,
250
+ occlusionTextureEnabled: 1,
251
+ occlusionStrength: 0.28,
252
+ metallic: 0,
253
+ roughness: 0.78,
254
+ specular: 0.04,
255
+ specularColorFactor: [0.042, 0.04, 0.035],
256
+ clearcoat: 0,
257
+ clearcoatRoughness: 1,
258
+ materialEnvironmentSpecularScale: 0.006,
259
+ envMapIntensity: 0.006,
260
+ emissive: [0, 0, 0],
261
+ emissiveStrength: 0,
262
+ opacity: 1,
263
+ alphaTest: 0,
264
+ transmission: 0,
265
+ metalness: 0,
266
+ toneMapped: true
267
+ },
268
+ tire: {
269
+ baseColor: [0.014, 0.014, 0.013, 1],
270
+ baseColorTextureEnabled: 0,
271
+ normalTextureEnabled: 1,
272
+ normalScale: 0.24,
273
+ occlusionTextureEnabled: 1,
274
+ occlusionStrength: 0.18,
275
+ metallic: 0,
276
+ roughness: 0.78,
277
+ specular: 0.038,
278
+ specularColorFactor: [0.035, 0.035, 0.034],
279
+ clearcoat: 0,
280
+ clearcoatRoughness: 1,
281
+ materialEnvironmentSpecularScale: 0.012,
282
+ envMapIntensity: 0.012,
283
+ emissive: [0, 0, 0],
284
+ emissiveStrength: 0,
285
+ opacity: 1,
286
+ alphaTest: 0,
287
+ transmission: 0,
288
+ metalness: 0,
289
+ toneMapped: true
290
+ },
291
+ "wheel-metal": {
292
+ baseColor: [0.46, 0.44, 0.38, 1],
293
+ baseColorTextureEnabled: 0,
294
+ normalTextureEnabled: 1,
295
+ normalScale: 0.07,
296
+ occlusionTextureEnabled: 1,
297
+ occlusionStrength: 0.055,
298
+ metallic: 0.9,
299
+ roughness: 0.22,
300
+ specular: 0.52,
301
+ specularColorFactor: [0.5, 0.46, 0.38],
302
+ clearcoat: 0.08,
303
+ clearcoatRoughness: 1,
304
+ materialEnvironmentSpecularScale: 0.16,
305
+ envMapIntensity: 0.16,
306
+ emissive: [0, 0, 0],
307
+ emissiveStrength: 0,
308
+ opacity: 1,
309
+ alphaTest: 0,
310
+ transmission: 0,
311
+ metalness: 0.9,
312
+ toneMapped: true
313
+ },
314
+ brake: {
315
+ baseColor: [0.48, 0.028, 0.018, 1],
316
+ baseColorTextureEnabled: 0,
317
+ normalTextureEnabled: 1,
318
+ normalScale: 0.06,
319
+ occlusionTextureEnabled: 1,
320
+ occlusionStrength: 0.08,
321
+ metallic: 0,
322
+ roughness: 0.62,
323
+ specular: 0.055,
324
+ specularColorFactor: [0.055, 0.026, 0.018],
325
+ clearcoat: 0,
326
+ clearcoatRoughness: 1,
327
+ materialEnvironmentSpecularScale: 0.012,
328
+ envMapIntensity: 0.012,
329
+ emissive: [0, 0, 0],
330
+ emissiveStrength: 0,
331
+ opacity: 1,
332
+ alphaTest: 0,
333
+ transmission: 0,
334
+ metalness: 0,
335
+ toneMapped: true
336
+ },
337
+ interior: {
338
+ baseColor: [0.22, 0.048, 0.036, 1],
339
+ baseColorTextureEnabled: 0,
340
+ normalTextureEnabled: 1,
341
+ normalScale: 0.085,
342
+ occlusionTextureEnabled: 1,
343
+ occlusionStrength: 0.08,
344
+ metallic: 0,
345
+ roughness: 0.52,
346
+ specular: 0.09,
347
+ specularColorFactor: [0.09, 0.046, 0.035],
348
+ clearcoat: 0.035,
349
+ clearcoatRoughness: 0.72,
350
+ materialEnvironmentSpecularScale: 0.025,
351
+ envMapIntensity: 0.025,
352
+ emissive: [0, 0, 0],
353
+ emissiveStrength: 0,
354
+ opacity: 1,
355
+ alphaTest: 0,
356
+ transmission: 0,
357
+ metalness: 0,
358
+ toneMapped: true
359
+ },
360
+ mechanical: {
361
+ baseColor: [0.012, 0.012, 0.012, 1],
362
+ baseColorTextureEnabled: 0,
363
+ normalTextureEnabled: 1,
364
+ normalScale: 0.06,
365
+ occlusionTextureEnabled: 1,
366
+ occlusionStrength: 0.08,
367
+ metallic: 0,
368
+ roughness: 0.74,
369
+ specular: 0.026,
370
+ specularColorFactor: [0.028, 0.028, 0.026],
371
+ clearcoat: 0,
372
+ clearcoatRoughness: 1,
373
+ materialEnvironmentSpecularScale: 0.008,
374
+ envMapIntensity: 0.008,
375
+ emissive: [0, 0, 0],
376
+ emissiveStrength: 0,
377
+ opacity: 1,
378
+ alphaTest: 0,
379
+ transmission: 0,
380
+ metalness: 0,
381
+ toneMapped: true
382
+ }
383
+ };
384
+
385
+ export type CarConceptMaterialVisualRole =
386
+ | "body-primary-paint"
387
+ | "body-secondary-paint"
388
+ | "roof-panel"
389
+ | "side-panel"
390
+ | "pillar-trim"
391
+ | "dark-trim"
392
+ | "glass"
393
+ | "light-lens"
394
+ | "license-plate"
395
+ | "tire"
396
+ | "wheel-metal"
397
+ | "brake"
398
+ | "interior"
399
+ | "mechanical"
400
+ | "unclassified";
401
+
402
+ export interface CarConceptMaterialVisualRoleContext {
403
+ readonly materialKey?: string;
404
+ readonly sourceMaterialName?: string;
405
+ readonly nodeName?: string;
406
+ }
407
+
408
+ export function carConceptMaterialRenderStateOverrides(
409
+ context: "product-configurator" | "current-routes-flagship" = "product-configurator"
410
+ ): readonly GLTFMaterialRenderStateOverride[] {
411
+ const product = context === "product-configurator";
412
+ return [
413
+ {
414
+ materialName: BODY_PATTERN,
415
+ renderState: { cullMode: "back", blend: false, depthTest: true, depthWrite: true },
416
+ reason: product
417
+ ? "Product car body panels are double-sided in the source GLB; culling back faces prevents subpixel bright seam halos without hiding the original car asset."
418
+ : "Concept-car body panels must not render as double-sided HDR edge overlays in the currentRoutes flagship viewer."
419
+ },
420
+ {
421
+ materialName: GLASS_PATTERN,
422
+ renderState: { cullMode: "back", blend: false, depthTest: true, depthWrite: true },
423
+ reason: product
424
+ ? "Product car glass is rendered as depth-writing dark glazing because the source transmissive/no-depth overlay creates pale HDR silhouette speckle around the windshield and roofline."
425
+ : "Concept-car glass has transmission metadata, but this viewer has no scene-color refraction pass; opaque depth-writing glass prevents white no-depth halos."
426
+ },
427
+ {
428
+ materialName: DETAIL_PATTERN,
429
+ renderState: { cullMode: "back", blend: false, depthTest: true, depthWrite: true },
430
+ reason: product
431
+ ? "Product wheel, tire, trim, and interior detail should not render as blended/no-depth overlay noise in the car hero."
432
+ : "Concept-car trim, wheels, and interior detail must not render as blended HDR speckle overlays."
433
+ }
434
+ ];
435
+ }
436
+
437
+ export function applyCarConceptMaterialStability(
438
+ material: Material,
439
+ options: CarConceptMaterialStabilityOptions = {}
440
+ ): void {
441
+ const profile = options.profile ?? "gallery";
442
+ if (profile === "cinematic") {
443
+ applyCinematicCarConceptMaterialStability(material, options);
444
+ return;
445
+ }
446
+ applyGalleryCarConceptMaterialStability(material, options);
447
+ }
448
+
449
+ export function carConceptMaterialVisualRole(
450
+ context: CarConceptMaterialVisualRoleContext
451
+ ): CarConceptMaterialVisualRole {
452
+ const node = context.nodeName ?? "";
453
+ const materialName = `${context.materialKey ?? ""} ${context.sourceMaterialName ?? ""}`;
454
+ const identity = `${node} ${materialName}`;
455
+
456
+ if (/BodyRoofPanel|\bRoof\b|Upper Shell|UpperShell|BodyUpper|UpperBody|Top(Panel|Shell)|CanopyPanel|Canopy Shell/i.test(identity)) return "roof-panel";
457
+ if (/Panel Sides|mesh-85-primitive|Side ?(Panel|Panels|Surface|Surfaces|Skirt|Sill)|Wheel ?Arch|Wheelarches|WheelWell|WheelHouse|Fender|QuarterPanel|Rocker/i.test(identity)) return "side-panel";
458
+ if (/BodyPillars|PillarTrim|(^|\b)[ABC][-_ ]?Pillar/i.test(identity)) return "pillar-trim";
459
+ if (LICENSE_PATTERN.test(identity)) return "license-plate";
460
+ if (/Tireside|Tiretread|mesh-(89|91|93|95)-primitive/i.test(identity)) return "tire";
461
+ if (/BrakePad/i.test(node) || (/\bBrake\b/i.test(materialName) && !/Brakelight|Brake Light/i.test(identity))) return "brake";
462
+ if (/Rim[12]|BrakeDisc|Disc|mesh-(90|92|94|96)-primitive/i.test(identity)) return "wheel-metal";
463
+ if (/Interior|Dashboard|Seats|Steering|Pedal|Floormat|Cockpit|Cabin|Console/i.test(identity)) return "interior";
464
+ if (/Mechanical|Engine|Axles|BodyUnderside|BodyHoodUnder/i.test(identity)) return "mechanical";
465
+ if (DARK_TRIM_PATTERN.test(identity)) return "dark-trim";
466
+ if (LIGHT_LENS_PATTERN.test(identity)) return "light-lens";
467
+ if (GLASS_PATTERN.test(identity)) return "glass";
468
+ if (/BodyDoor.*Color1|BodyHood$|BodyRearPanelsColor1|Paint 1 (Carmine|Pearl|Pearly|Graphite)/i.test(identity)) return "body-primary-paint";
469
+ if (/BodyDoor.*Color2|BodyPanelsColor2|Paint 2 (Carmine|Pearl|Pearly|Graphite)|Secondary Panel/i.test(identity)) return "body-secondary-paint";
470
+ if (/^Body/i.test(node) && /Panel|Shell|Surface|Door|Hood|Fender|Arch/i.test(node)) {
471
+ return /Color2|Secondary|Paint 2/i.test(identity) ? "body-secondary-paint" : "body-primary-paint";
472
+ }
473
+ return "unclassified";
474
+ }
475
+
476
+ function applyGalleryCarConceptMaterialStability(
477
+ material: Material,
478
+ options: Pick<CarConceptMaterialStabilityOptions, "materialKey" | "sourceMaterialName" | "nodeName">
479
+ ): void {
480
+ const name = `${options.materialKey ?? ""} ${options.sourceMaterialName ?? ""} ${material.name}`;
481
+ const role = options.nodeName ? carConceptMaterialVisualRole(options) : "unclassified";
482
+ if (/Paint [12] (Carmine|Pearl|Pearly|Graphite)|Body.*Color/i.test(name)) {
483
+ if (/Paint 1 Carmine|Body.*Color/i.test(name)) {
484
+ material.setParameter("u_baseColor", [0.42, 0.008, 0.005, 1]);
485
+ }
486
+ if (/Paint 2 Carmine/i.test(name)) {
487
+ material.setParameter("u_baseColor", [0.24, 0.016, 0.012, 1]);
488
+ }
489
+ if (/Paint [12] (Pearl|Pearly)/i.test(name)) {
490
+ material.setParameter("u_baseColor", [0.34, 0.18, 0.15, 1]);
491
+ }
492
+ if (/Paint [12] Graphite/i.test(name)) {
493
+ material.setParameter("u_baseColor", [0.08, 0.088, 0.092, 1]);
494
+ }
495
+ material.setParameter("u_baseColorTextureEnabled", 0);
496
+ material.setParameter("u_normalTextureEnabled", 1);
497
+ material.setParameter("u_normalScale", 0.035);
498
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
499
+ material.setParameter("u_occlusionTextureEnabled", 1);
500
+ material.setParameter("u_occlusionStrength", 0.035);
501
+ material.setParameter("u_specularTextureEnabled", 0);
502
+ material.setParameter("u_specularColorTextureEnabled", 0);
503
+ material.setParameter("u_metallic", 0);
504
+ material.setParameter("u_roughness", 0.37);
505
+ material.setParameter("u_specularFactor", 0.22);
506
+ material.setParameter("u_specularColorFactor", [0.28, 0.05, 0.034]);
507
+ material.setParameter("u_clearcoatTextureEnabled", 0);
508
+ material.setParameter("u_clearcoatRoughnessTextureEnabled", 0);
509
+ material.setParameter("u_clearcoatNormalTextureEnabled", 0);
510
+ material.setParameter("u_clearcoatNormalScale", 0);
511
+ material.setParameter("u_clearcoatFactor", 0.28);
512
+ material.setParameter("u_clearcoatRoughnessFactor", 0.58);
513
+ material.setParameter("u_iridescenceTextureEnabled", 0);
514
+ material.setParameter("u_iridescenceThicknessTextureEnabled", 0);
515
+ material.setParameter("u_iridescenceFactor", 0);
516
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.055);
517
+ if (/Paint 1 Carmine|Body.*Color/i.test(name)) {
518
+ material.setParameter("u_normalScale", 0.052);
519
+ material.setParameter("u_occlusionStrength", 0.052);
520
+ material.setParameter("u_metallic", 0.08);
521
+ material.setParameter("u_roughness", 0.34);
522
+ material.setParameter("u_specularFactor", 0.18);
523
+ material.setParameter("u_specularColorFactor", [0.18, 0.03, 0.02]);
524
+ material.setParameter("u_clearcoatFactor", 0.18);
525
+ material.setParameter("u_clearcoatRoughnessFactor", 0.68);
526
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.06);
527
+ }
528
+ if (/Paint 2 Carmine/i.test(name)) {
529
+ material.setParameter("u_normalScale", 0.034);
530
+ material.setParameter("u_occlusionStrength", 0.07);
531
+ material.setParameter("u_metallic", 0.05);
532
+ material.setParameter("u_roughness", 0.46);
533
+ material.setParameter("u_specularFactor", 0.1);
534
+ material.setParameter("u_specularColorFactor", [0.095, 0.03, 0.024]);
535
+ material.setParameter("u_clearcoatFactor", 0.09);
536
+ material.setParameter("u_clearcoatRoughnessFactor", 0.72);
537
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.028);
538
+ }
539
+ if (/Paint [12] (Pearl|Pearly)/i.test(name)) {
540
+ material.setParameter("u_baseColor", [0.34, 0.18, 0.15, 1]);
541
+ material.setParameter("u_normalScale", 0.016);
542
+ material.setParameter("u_occlusionStrength", 0.026);
543
+ material.setParameter("u_roughness", 0.58);
544
+ material.setParameter("u_specularFactor", 0.065);
545
+ material.setParameter("u_specularColorFactor", [0.07, 0.046, 0.04]);
546
+ material.setParameter("u_clearcoatFactor", 0.055);
547
+ material.setParameter("u_clearcoatRoughnessFactor", 0.72);
548
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.014);
549
+ }
550
+ if (/Paint [12] Graphite/i.test(name)) {
551
+ material.setParameter("u_normalScale", 0.014);
552
+ material.setParameter("u_occlusionStrength", 0.02);
553
+ material.setParameter("u_roughness", 0.62);
554
+ material.setParameter("u_specularFactor", 0.045);
555
+ material.setParameter("u_specularColorFactor", [0.045, 0.047, 0.05]);
556
+ material.setParameter("u_clearcoatFactor", 0.04);
557
+ material.setParameter("u_clearcoatRoughnessFactor", 0.68);
558
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.012);
559
+ }
560
+ }
561
+ applyGalleryCarConceptLegacyRoleBlocks(material, name);
562
+ if (role !== "unclassified") {
563
+ applyGalleryCarConceptMaterialVisualRoleStability(material, role);
564
+ finalizeGalleryCarConceptMaterialVisualRole(material, role, options);
565
+ } else if (BODY_PATTERN.test(name) || GLASS_PATTERN.test(name) || DETAIL_PATTERN.test(name)) {
566
+ applyCarConceptOpaqueRuntimeSurface(material, {
567
+ opacity: 1,
568
+ alphaTest: 0,
569
+ transmission: 0,
570
+ clearcoat: numberParameter(material, "u_clearcoatFactor") ?? 0,
571
+ specular: numberParameter(material, "u_specularFactor") ?? 0,
572
+ metalness: numberParameter(material, "u_metallic") ?? 0,
573
+ roughness: numberParameter(material, "u_roughness") ?? 0.72,
574
+ envMapIntensity: numberParameter(material, "u_materialEnvironmentSpecularScale") ?? 0,
575
+ emissive: vector3Parameter(material, "u_emissiveColor") ?? [0, 0, 0],
576
+ toneMapped: true
577
+ });
578
+ }
579
+ }
580
+
581
+ function applyGalleryCarConceptMaterialVisualRoleStability(
582
+ material: Material,
583
+ role: CarConceptMaterialVisualRole
584
+ ): void {
585
+ disableCarConceptHdrExtensionEscape(material);
586
+
587
+ if (role === "body-primary-paint") {
588
+ material.setParameter("u_baseColor", [0.9, 0.012, 0.0065, 1]);
589
+ material.setParameter("u_baseColorTextureEnabled", 0);
590
+ material.setParameter("u_normalTextureEnabled", 1);
591
+ material.setParameter("u_normalScale", 0.56);
592
+ material.setParameter("u_occlusionTextureEnabled", 1);
593
+ material.setParameter("u_occlusionStrength", 0.78);
594
+ material.setParameter("u_metallic", 0.08);
595
+ material.setParameter("u_roughness", 0.28);
596
+ material.setParameter("u_specularFactor", 0.48);
597
+ material.setParameter("u_specularColorFactor", [0.48, 0.055, 0.035]);
598
+ material.setParameter("u_clearcoatFactor", 0.52);
599
+ material.setParameter("u_clearcoatRoughnessFactor", 0.34);
600
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.24);
601
+ }
602
+ if (role === "body-secondary-paint") {
603
+ material.setParameter("u_baseColor", [0.2, 0.004, 0.0024, 1]);
604
+ material.setParameter("u_baseColorTextureEnabled", 0);
605
+ material.setParameter("u_normalTextureEnabled", 1);
606
+ material.setParameter("u_normalScale", 0.48);
607
+ material.setParameter("u_occlusionTextureEnabled", 1);
608
+ material.setParameter("u_occlusionStrength", 0.72);
609
+ material.setParameter("u_metallic", 0.035);
610
+ material.setParameter("u_roughness", 0.36);
611
+ material.setParameter("u_specularFactor", 0.26);
612
+ material.setParameter("u_specularColorFactor", [0.26, 0.043, 0.028]);
613
+ material.setParameter("u_clearcoatFactor", 0.28);
614
+ material.setParameter("u_clearcoatRoughnessFactor", 0.46);
615
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.13);
616
+ }
617
+ if (role === "roof-panel") {
618
+ material.setParameter("u_baseColor", [0.072, 0.067, 0.064, 1]);
619
+ material.setParameter("u_baseColorTextureEnabled", 0);
620
+ material.setParameter("u_normalTextureEnabled", 1);
621
+ material.setParameter("u_normalScale", 0.026);
622
+ material.setParameter("u_occlusionTextureEnabled", 1);
623
+ material.setParameter("u_occlusionStrength", 0.06);
624
+ material.setParameter("u_metallic", 0);
625
+ material.setParameter("u_roughness", 0.48);
626
+ material.setParameter("u_specularFactor", 0.085);
627
+ material.setParameter("u_specularColorFactor", [0.08, 0.075, 0.07]);
628
+ material.setParameter("u_clearcoatFactor", 0.09);
629
+ material.setParameter("u_clearcoatRoughnessFactor", 0.62);
630
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.024);
631
+ }
632
+ if (role === "pillar-trim" || role === "dark-trim") {
633
+ material.setParameter("u_baseColor", role === "pillar-trim" ? [0.014, 0.016, 0.018, 1] : [0.012, 0.012, 0.013, 1]);
634
+ material.setParameter("u_baseColorTextureEnabled", 0);
635
+ material.setParameter("u_normalTextureEnabled", 0);
636
+ material.setParameter("u_normalScale", 0);
637
+ material.setParameter("u_occlusionTextureEnabled", 1);
638
+ material.setParameter("u_occlusionStrength", 0.018);
639
+ material.setParameter("u_metallic", 0);
640
+ material.setParameter("u_roughness", 0.74);
641
+ material.setParameter("u_specularFactor", 0.026);
642
+ material.setParameter("u_specularColorFactor", [0.032, 0.03, 0.028]);
643
+ material.setParameter("u_clearcoatFactor", 0);
644
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.006);
645
+ }
646
+ if (role === "glass") {
647
+ material.setParameter("u_baseColor", [0.018, 0.032, 0.04, 1]);
648
+ material.setParameter("u_baseColorTextureEnabled", 0);
649
+ material.setParameter("u_normalTextureEnabled", 0);
650
+ material.setParameter("u_normalScale", 0);
651
+ material.setParameter("u_occlusionTextureEnabled", 1);
652
+ material.setParameter("u_occlusionStrength", 0.028);
653
+ material.setParameter("u_metallic", 0);
654
+ material.setParameter("u_roughness", 0.36);
655
+ material.setParameter("u_specularFactor", 0.075);
656
+ material.setParameter("u_specularColorFactor", [0.034, 0.044, 0.052]);
657
+ material.setParameter("u_transmissionTextureEnabled", 0);
658
+ material.setParameter("u_transmissionFactor", 0);
659
+ material.setParameter("u_diffuseTransmissionFactor", 0);
660
+ material.setParameter("u_transmissionFallbackEnergy", 0);
661
+ material.setParameter("u_volumeThicknessFactor", 0);
662
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.022);
663
+ }
664
+ if (role === "light-lens") {
665
+ material.setParameter("u_baseColor", [0.018, 0.014, 0.012, 1]);
666
+ material.setParameter("u_baseColorTextureEnabled", 0);
667
+ material.setParameter("u_normalTextureEnabled", 0);
668
+ material.setParameter("u_normalScale", 0);
669
+ material.setParameter("u_occlusionTextureEnabled", 1);
670
+ material.setParameter("u_occlusionStrength", 0.05);
671
+ material.setParameter("u_metallic", 0);
672
+ material.setParameter("u_roughness", 0.42);
673
+ material.setParameter("u_specularFactor", 0.09);
674
+ material.setParameter("u_specularColorFactor", [0.08, 0.056, 0.04]);
675
+ material.setParameter("u_clearcoatFactor", 0.04);
676
+ material.setParameter("u_clearcoatRoughnessFactor", 0.66);
677
+ material.setParameter("u_emissiveTextureEnabled", 0);
678
+ material.setParameter("u_emissiveStrength", 0);
679
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.018);
680
+ }
681
+ if (role === "license-plate") {
682
+ material.setParameter("u_baseColor", [0.16, 0.152, 0.138, 1]);
683
+ material.setParameter("u_baseColorTextureEnabled", 0);
684
+ material.setParameter("u_normalTextureEnabled", 0);
685
+ material.setParameter("u_normalScale", 0);
686
+ material.setParameter("u_occlusionTextureEnabled", 1);
687
+ material.setParameter("u_occlusionStrength", 0.12);
688
+ material.setParameter("u_metallic", 0);
689
+ material.setParameter("u_roughness", 0.58);
690
+ material.setParameter("u_specularFactor", 0.08);
691
+ material.setParameter("u_specularColorFactor", [0.075, 0.07, 0.062]);
692
+ material.setParameter("u_clearcoatFactor", 0);
693
+ material.setParameter("u_emissiveTextureEnabled", 0);
694
+ material.setParameter("u_emissiveStrength", 0);
695
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.018);
696
+ }
697
+ if (role === "side-panel") {
698
+ material.setParameter("u_baseColor", [0.012, 0.003, 0.0025, 1]);
699
+ material.setParameter("u_baseColorTextureEnabled", 0);
700
+ material.setParameter("u_normalTextureEnabled", 1);
701
+ material.setParameter("u_normalScale", 0.24);
702
+ material.setParameter("u_occlusionTextureEnabled", 1);
703
+ material.setParameter("u_occlusionStrength", 0.9);
704
+ material.setParameter("u_metallic", 0);
705
+ material.setParameter("u_roughness", 0.68);
706
+ material.setParameter("u_specularFactor", 0.025);
707
+ material.setParameter("u_specularColorFactor", [0.026, 0.012, 0.01]);
708
+ material.setParameter("u_clearcoatFactor", 0);
709
+ material.setParameter("u_clearcoatRoughnessFactor", 1);
710
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.004);
711
+ }
712
+ if (role === "wheel-metal") {
713
+ material.setParameter("u_baseColor", [0.32, 0.31, 0.28, 1]);
714
+ material.setParameter("u_baseColorTextureEnabled", 0);
715
+ material.setParameter("u_normalTextureEnabled", 1);
716
+ material.setParameter("u_normalScale", 0.055);
717
+ material.setParameter("u_metallic", 0.9);
718
+ material.setParameter("u_roughness", 0.3);
719
+ material.setParameter("u_specularFactor", 0.36);
720
+ material.setParameter("u_specularColorFactor", [0.34, 0.32, 0.28]);
721
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.075);
722
+ }
723
+ if (role === "brake") {
724
+ material.setParameter("u_baseColor", [0.48, 0.028, 0.018, 1]);
725
+ material.setParameter("u_baseColorTextureEnabled", 0);
726
+ material.setParameter("u_normalTextureEnabled", 1);
727
+ material.setParameter("u_normalScale", 0.06);
728
+ material.setParameter("u_occlusionTextureEnabled", 1);
729
+ material.setParameter("u_occlusionStrength", 0.08);
730
+ material.setParameter("u_metallic", 0);
731
+ material.setParameter("u_roughness", 0.62);
732
+ material.setParameter("u_specularFactor", 0.055);
733
+ material.setParameter("u_specularColorFactor", [0.055, 0.026, 0.018]);
734
+ material.setParameter("u_clearcoatFactor", 0);
735
+ material.setParameter("u_emissiveTextureEnabled", 0);
736
+ material.setParameter("u_emissiveStrength", 0);
737
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.012);
738
+ }
739
+ if (role === "tire") {
740
+ material.setParameter("u_baseColor", [0.014, 0.014, 0.013, 1]);
741
+ material.setParameter("u_normalTextureEnabled", 1);
742
+ material.setParameter("u_normalScale", 0.24);
743
+ material.setParameter("u_roughness", 0.78);
744
+ material.setParameter("u_specularFactor", 0.038);
745
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.012);
746
+ }
747
+ if (role === "interior") {
748
+ material.setParameter("u_baseColor", [0.22, 0.048, 0.036, 1]);
749
+ material.setParameter("u_baseColorTextureEnabled", 0);
750
+ material.setParameter("u_normalTextureEnabled", 1);
751
+ material.setParameter("u_normalScale", 0.085);
752
+ material.setParameter("u_occlusionTextureEnabled", 1);
753
+ material.setParameter("u_occlusionStrength", 0.08);
754
+ material.setParameter("u_metallic", 0);
755
+ material.setParameter("u_roughness", 0.52);
756
+ material.setParameter("u_specularFactor", 0.09);
757
+ material.setParameter("u_specularColorFactor", [0.09, 0.046, 0.035]);
758
+ material.setParameter("u_clearcoatFactor", 0.035);
759
+ material.setParameter("u_clearcoatRoughnessFactor", 0.72);
760
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.025);
761
+ }
762
+ if (role === "mechanical") {
763
+ material.setParameter("u_baseColor", [0.012, 0.012, 0.012, 1]);
764
+ material.setParameter("u_normalScale", 0.06);
765
+ material.setParameter("u_occlusionStrength", 0.08);
766
+ material.setParameter("u_roughness", 0.74);
767
+ material.setParameter("u_specularFactor", 0.026);
768
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.008);
769
+ }
770
+ }
771
+
772
+ function finalizeGalleryCarConceptMaterialVisualRole(
773
+ material: Material,
774
+ role: Exclude<CarConceptMaterialVisualRole, "unclassified">,
775
+ context: Pick<CarConceptMaterialStabilityOptions, "materialKey" | "sourceMaterialName" | "nodeName"> = {}
776
+ ): void {
777
+ const surface = galleryCarConceptRoleSurface(role, context);
778
+ material.setParameter("u_baseColor", surface.baseColor);
779
+ material.setParameter("u_baseColorTextureEnabled", surface.baseColorTextureEnabled);
780
+ material.setParameter("u_normalTextureEnabled", surface.normalTextureEnabled);
781
+ material.setParameter("u_normalScale", surface.normalScale);
782
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
783
+ material.setParameter("u_occlusionTextureEnabled", surface.occlusionTextureEnabled);
784
+ material.setParameter("u_occlusionStrength", surface.occlusionStrength);
785
+ material.setParameter("u_metallic", surface.metallic);
786
+ material.setParameter("u_roughness", surface.roughness);
787
+ material.setParameter("u_specularTextureEnabled", 0);
788
+ material.setParameter("u_specularColorTextureEnabled", 0);
789
+ material.setParameter("u_specularFactor", surface.specular);
790
+ material.setParameter("u_specularColorFactor", surface.specularColorFactor);
791
+ material.setParameter("u_clearcoatTextureEnabled", 0);
792
+ material.setParameter("u_clearcoatRoughnessTextureEnabled", 0);
793
+ material.setParameter("u_clearcoatNormalTextureEnabled", 0);
794
+ material.setParameter("u_clearcoatNormalScale", 0);
795
+ material.setParameter("u_clearcoatFactor", surface.clearcoat);
796
+ material.setParameter("u_clearcoatRoughnessFactor", surface.clearcoatRoughness);
797
+ material.setParameter("u_iorTextureEnabled", 0);
798
+ material.setParameter("u_transmissionTextureEnabled", 0);
799
+ material.setParameter("u_diffuseTransmissionTextureEnabled", 0);
800
+ material.setParameter("u_diffuseTransmissionColorTextureEnabled", 0);
801
+ material.setParameter("u_volumeThicknessTextureEnabled", 0);
802
+ material.setParameter("u_transmissionFactor", 0);
803
+ material.setParameter("u_diffuseTransmissionFactor", 0);
804
+ material.setParameter("u_diffuseTransmissionColorFactor", [1, 1, 1]);
805
+ material.setParameter("u_transmissionFallbackEnergy", 0);
806
+ material.setParameter("u_volumeThicknessFactor", 0);
807
+ material.setParameter("u_volumeAttenuationDistance", 1_000_000);
808
+ material.setParameter("u_volumeAttenuationColor", [1, 1, 1]);
809
+ material.setParameter("u_transmissionParallaxStrength", 0);
810
+ material.setParameter("u_transmissionBounceCount", 0);
811
+ material.setParameter("u_transmissionCausticStrength", 0);
812
+ material.setParameter("u_transmissionBackdropEnabled", 0);
813
+ material.setParameter("u_transmissionBackdropStrength", 0);
814
+ material.setParameter("u_materialEnvironmentSpecularScale", surface.materialEnvironmentSpecularScale);
815
+ material.setParameter("u_iridescenceTextureEnabled", 0);
816
+ material.setParameter("u_iridescenceThicknessTextureEnabled", 0);
817
+ material.setParameter("u_iridescenceFactor", 0);
818
+ material.setParameter("u_sheenColorTextureEnabled", 0);
819
+ material.setParameter("u_sheenRoughnessTextureEnabled", 0);
820
+ material.setParameter("u_sheenColorFactor", [0, 0, 0]);
821
+ material.setParameter("u_sheenRoughnessFactor", 1);
822
+ material.setParameter("u_anisotropyTextureEnabled", 0);
823
+ material.setParameter("u_anisotropyStrength", 0);
824
+ material.setParameter("u_anisotropyRotation", 0);
825
+ material.setParameter("u_dispersion", 0);
826
+ material.setParameter("u_emissiveTextureEnabled", 0);
827
+ material.setParameter("u_emissiveColor", surface.emissive);
828
+ material.setParameter("u_emissiveStrength", surface.emissiveStrength);
829
+ applyGalleryCarConceptSourceTextureDetail(material, role);
830
+ if (role === "glass") {
831
+ material.setParameter("u_ior", 1);
832
+ }
833
+ applyCarConceptOpaqueRuntimeSurface(material, surface);
834
+ }
835
+
836
+ function applyGalleryCarConceptSourceTextureDetail(
837
+ material: Material,
838
+ role: Exclude<CarConceptMaterialVisualRole, "unclassified">
839
+ ): void {
840
+ const sourceBaseColorTexture = materialParameter(material, "u_baseColorTexture");
841
+ const occlusionTexture = materialParameter(material, "u_occlusionTexture");
842
+ const detailTexture = sourceBaseColorTexture ?? occlusionTexture;
843
+ if (!detailTexture) return;
844
+ const sourceTextureWeight = role === "body-primary-paint"
845
+ ? 0.36
846
+ : role === "body-secondary-paint"
847
+ ? 0.32
848
+ : role === "roof-panel"
849
+ ? 0.25
850
+ : role === "side-panel"
851
+ ? 0.4
852
+ : role === "glass"
853
+ ? 0.06
854
+ : role === "wheel-metal"
855
+ ? 0.42
856
+ : role === "tire"
857
+ ? 0.32
858
+ : role === "license-plate"
859
+ ? 0.82
860
+ : role === "light-lens"
861
+ ? 0.12
862
+ : 0;
863
+ const fallbackOcclusionWeight = role === "body-primary-paint"
864
+ ? 0.16
865
+ : role === "body-secondary-paint"
866
+ ? 0.14
867
+ : role === "roof-panel"
868
+ ? 0.18
869
+ : role === "side-panel"
870
+ ? 0.36
871
+ : role === "glass"
872
+ ? 0.04
873
+ : role === "wheel-metal"
874
+ ? 0.2
875
+ : role === "tire"
876
+ ? 0.18
877
+ : role === "license-plate"
878
+ ? 0.28
879
+ : role === "light-lens"
880
+ ? 0.06
881
+ : 0;
882
+ const weight = sourceBaseColorTexture ? sourceTextureWeight : fallbackOcclusionWeight;
883
+ if (weight <= 0) return;
884
+ if (!sourceBaseColorTexture) material.setParameter("u_baseColorTexture", detailTexture);
885
+ const sourcePrefix = sourceBaseColorTexture ? "u_baseColorTexture" : "u_occlusionTexture";
886
+ for (const suffix of ["Offset", "Scale", "Rotation", "TexCoord", "Wrap"] as const) {
887
+ const value = materialParameter(material, `${sourcePrefix}${suffix}`);
888
+ if (value !== undefined) material.setParameter(`u_baseColorTexture${suffix}`, value);
889
+ }
890
+ material.setParameter("u_baseColorTextureEnabled", weight);
891
+ }
892
+
893
+ function galleryCarConceptRoleSurface(
894
+ role: Exclude<CarConceptMaterialVisualRole, "unclassified">,
895
+ context: Pick<CarConceptMaterialStabilityOptions, "materialKey" | "sourceMaterialName" | "nodeName">
896
+ ): GalleryCarConceptRoleSurface {
897
+ const surface = GALLERY_ROLE_SURFACES[role];
898
+ const identity = `${context.nodeName ?? ""} ${context.materialKey ?? ""} ${context.sourceMaterialName ?? ""}`;
899
+ if (role === "body-primary-paint") {
900
+ if (/BodyHood/i.test(identity)) {
901
+ return {
902
+ ...surface,
903
+ baseColor: [0.64, 0.0054, 0.0032, 1],
904
+ normalScale: 0.035,
905
+ occlusionStrength: 0.16,
906
+ roughness: 0.21,
907
+ specular: 0.6,
908
+ specularColorFactor: [0.54, 0.042, 0.026],
909
+ clearcoat: 0.6,
910
+ clearcoatRoughness: 0.28,
911
+ materialEnvironmentSpecularScale: 0.27,
912
+ envMapIntensity: 0.27
913
+ };
914
+ }
915
+ if (/BodyRearPanelsColor1/i.test(identity)) {
916
+ return {
917
+ ...surface,
918
+ baseColor: [0.56, 0.0048, 0.0029, 1],
919
+ normalScale: 0.032,
920
+ occlusionStrength: 0.18,
921
+ roughness: 0.23,
922
+ specular: 0.56,
923
+ specularColorFactor: [0.5, 0.04, 0.025],
924
+ clearcoat: 0.56,
925
+ clearcoatRoughness: 0.3,
926
+ materialEnvironmentSpecularScale: 0.25,
927
+ envMapIntensity: 0.25
928
+ };
929
+ }
930
+ if (/BodyDoor[LR]Color1/i.test(identity)) {
931
+ return {
932
+ ...surface,
933
+ baseColor: [0.76, 0.0072, 0.0042, 1],
934
+ normalScale: 0.04,
935
+ occlusionStrength: 0.18,
936
+ roughness: 0.2,
937
+ specular: 0.66,
938
+ specularColorFactor: [0.58, 0.046, 0.029],
939
+ clearcoat: 0.64,
940
+ clearcoatRoughness: 0.26,
941
+ materialEnvironmentSpecularScale: 0.3,
942
+ envMapIntensity: 0.3
943
+ };
944
+ }
945
+ }
946
+ if (role === "body-secondary-paint") {
947
+ if (/BodyPanelsColor2/i.test(identity)) {
948
+ return {
949
+ ...surface,
950
+ baseColor: [0.078, 0.0015, 0.001, 1],
951
+ normalScale: 0.028,
952
+ occlusionStrength: 0.22,
953
+ roughness: 0.36,
954
+ specular: 0.3,
955
+ specularColorFactor: [0.27, 0.028, 0.02],
956
+ clearcoat: 0.3,
957
+ clearcoatRoughness: 0.48,
958
+ materialEnvironmentSpecularScale: 0.13,
959
+ envMapIntensity: 0.13
960
+ };
961
+ }
962
+ if (/BodyDoor[LR]Color2/i.test(identity)) {
963
+ return {
964
+ ...surface,
965
+ baseColor: [0.17, 0.003, 0.0019, 1],
966
+ normalScale: 0.03,
967
+ occlusionStrength: 0.2,
968
+ roughness: 0.3,
969
+ specular: 0.4,
970
+ specularColorFactor: [0.36, 0.036, 0.024],
971
+ clearcoat: 0.42,
972
+ clearcoatRoughness: 0.4,
973
+ materialEnvironmentSpecularScale: 0.18,
974
+ envMapIntensity: 0.18
975
+ };
976
+ }
977
+ }
978
+ if (role === "light-lens") {
979
+ if (/Headlight/i.test(identity)) {
980
+ return {
981
+ ...surface,
982
+ baseColor: [0.022, 0.024, 0.024, 1],
983
+ specularColorFactor: [0.075, 0.075, 0.068],
984
+ materialEnvironmentSpecularScale: 0.02,
985
+ envMapIntensity: 0.02
986
+ };
987
+ }
988
+ if (/Brake|Tail/i.test(identity)) {
989
+ return {
990
+ ...surface,
991
+ baseColor: [0.045, 0.006, 0.0038, 1],
992
+ specularColorFactor: [0.08, 0.034, 0.024],
993
+ materialEnvironmentSpecularScale: 0.016,
994
+ envMapIntensity: 0.016
995
+ };
996
+ }
997
+ if (/Signal|Turn/i.test(identity)) {
998
+ return {
999
+ ...surface,
1000
+ baseColor: [0.04, 0.018, 0.0045, 1],
1001
+ specularColorFactor: [0.078, 0.052, 0.026],
1002
+ materialEnvironmentSpecularScale: 0.016,
1003
+ envMapIntensity: 0.016
1004
+ };
1005
+ }
1006
+ }
1007
+ if (role === "side-panel") {
1008
+ return {
1009
+ ...surface,
1010
+ baseColor: [0.024, 0.0038, 0.0025, 1],
1011
+ normalScale: 0.42,
1012
+ occlusionStrength: 0.62,
1013
+ roughness: 0.5,
1014
+ specular: 0.1,
1015
+ specularColorFactor: [0.11, 0.03, 0.02],
1016
+ clearcoat: 0.08,
1017
+ clearcoatRoughness: 0.62,
1018
+ materialEnvironmentSpecularScale: 0.04,
1019
+ envMapIntensity: 0.04
1020
+ };
1021
+ }
1022
+ return surface;
1023
+ }
1024
+
1025
+ function disableCarConceptHdrExtensionEscape(material: Material): void {
1026
+ material.setParameter("u_specularTextureEnabled", 0);
1027
+ material.setParameter("u_specularColorTextureEnabled", 0);
1028
+ material.setParameter("u_clearcoatTextureEnabled", 0);
1029
+ material.setParameter("u_clearcoatRoughnessTextureEnabled", 0);
1030
+ material.setParameter("u_clearcoatNormalTextureEnabled", 0);
1031
+ material.setParameter("u_clearcoatNormalScale", 0);
1032
+ material.setParameter("u_clearcoatFactor", 0);
1033
+ material.setParameter("u_clearcoatRoughnessFactor", 1);
1034
+ material.setParameter("u_iorTextureEnabled", 0);
1035
+ material.setParameter("u_transmissionTextureEnabled", 0);
1036
+ material.setParameter("u_diffuseTransmissionTextureEnabled", 0);
1037
+ material.setParameter("u_diffuseTransmissionColorTextureEnabled", 0);
1038
+ material.setParameter("u_volumeThicknessTextureEnabled", 0);
1039
+ material.setParameter("u_transmissionFactor", 0);
1040
+ material.setParameter("u_diffuseTransmissionFactor", 0);
1041
+ material.setParameter("u_diffuseTransmissionColorFactor", [1, 1, 1]);
1042
+ material.setParameter("u_transmissionFallbackEnergy", 0);
1043
+ material.setParameter("u_volumeThicknessFactor", 0);
1044
+ material.setParameter("u_volumeAttenuationDistance", 1_000_000);
1045
+ material.setParameter("u_volumeAttenuationColor", [1, 1, 1]);
1046
+ material.setParameter("u_transmissionParallaxStrength", 0);
1047
+ material.setParameter("u_transmissionBounceCount", 0);
1048
+ material.setParameter("u_transmissionCausticStrength", 0);
1049
+ material.setParameter("u_transmissionBackdropEnabled", 0);
1050
+ material.setParameter("u_transmissionBackdropStrength", 0);
1051
+ material.setParameter("u_iridescenceTextureEnabled", 0);
1052
+ material.setParameter("u_iridescenceThicknessTextureEnabled", 0);
1053
+ material.setParameter("u_iridescenceFactor", 0);
1054
+ material.setParameter("u_sheenColorTextureEnabled", 0);
1055
+ material.setParameter("u_sheenRoughnessTextureEnabled", 0);
1056
+ material.setParameter("u_sheenColorFactor", [0, 0, 0]);
1057
+ material.setParameter("u_sheenRoughnessFactor", 1);
1058
+ material.setParameter("u_anisotropyTextureEnabled", 0);
1059
+ material.setParameter("u_anisotropyStrength", 0);
1060
+ material.setParameter("u_anisotropyRotation", 0);
1061
+ material.setParameter("u_dispersion", 0);
1062
+ }
1063
+
1064
+ function applyGalleryCarConceptLegacyRoleBlocks(material: Material, name: string): void {
1065
+ if (/Panel Sides/i.test(name)) {
1066
+ material.setParameter("u_baseColor", [0.058, 0.014, 0.01, 1]);
1067
+ material.setParameter("u_baseColorTextureEnabled", 0);
1068
+ material.setParameter("u_normalTextureEnabled", 1);
1069
+ material.setParameter("u_normalScale", 0.06);
1070
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1071
+ material.setParameter("u_occlusionTextureEnabled", 1);
1072
+ material.setParameter("u_occlusionStrength", 0.1);
1073
+ material.setParameter("u_specularTextureEnabled", 0);
1074
+ material.setParameter("u_specularColorTextureEnabled", 0);
1075
+ material.setParameter("u_metallic", 0.04);
1076
+ material.setParameter("u_roughness", 0.48);
1077
+ material.setParameter("u_specularFactor", 0.12);
1078
+ material.setParameter("u_specularColorFactor", [0.11, 0.032, 0.024]);
1079
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.035);
1080
+ }
1081
+ if (/BodyRoofPanel/i.test(name)) {
1082
+ material.setParameter("u_baseColor", [0.12, 0.09, 0.08, 1]);
1083
+ material.setParameter("u_baseColorTextureEnabled", 0);
1084
+ material.setParameter("u_normalTextureEnabled", 1);
1085
+ material.setParameter("u_normalScale", 0.028);
1086
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1087
+ material.setParameter("u_occlusionTextureEnabled", 1);
1088
+ material.setParameter("u_occlusionStrength", 0.06);
1089
+ material.setParameter("u_specularTextureEnabled", 0);
1090
+ material.setParameter("u_specularColorTextureEnabled", 0);
1091
+ material.setParameter("u_metallic", 0);
1092
+ material.setParameter("u_roughness", 0.56);
1093
+ material.setParameter("u_specularFactor", 0.075);
1094
+ material.setParameter("u_specularColorFactor", [0.065, 0.05, 0.044]);
1095
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.018);
1096
+ }
1097
+ if (/BodyPillars/i.test(name)) {
1098
+ material.setParameter("u_baseColor", [0.018, 0.02, 0.024, 1]);
1099
+ material.setParameter("u_baseColorTextureEnabled", 0);
1100
+ material.setParameter("u_normalTextureEnabled", 1);
1101
+ material.setParameter("u_normalScale", 0.04);
1102
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1103
+ material.setParameter("u_occlusionTextureEnabled", 1);
1104
+ material.setParameter("u_occlusionStrength", 0.06);
1105
+ material.setParameter("u_specularTextureEnabled", 0);
1106
+ material.setParameter("u_specularColorTextureEnabled", 0);
1107
+ material.setParameter("u_metallic", 0);
1108
+ material.setParameter("u_roughness", 0.52);
1109
+ material.setParameter("u_specularFactor", 0.1);
1110
+ material.setParameter("u_specularColorFactor", [0.07, 0.08, 0.09]);
1111
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.035);
1112
+ }
1113
+ if (/Glass|Window|Windshield/i.test(name)) {
1114
+ material.setParameter("u_baseColor", [0.014, 0.024, 0.032, 1]);
1115
+ material.setParameter("u_baseColorTextureEnabled", 0);
1116
+ material.setParameter("u_normalTextureEnabled", 0);
1117
+ material.setParameter("u_normalScale", 0);
1118
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1119
+ material.setParameter("u_occlusionTextureEnabled", 1);
1120
+ material.setParameter("u_occlusionStrength", 0.025);
1121
+ material.setParameter("u_specularTextureEnabled", 0);
1122
+ material.setParameter("u_specularColorTextureEnabled", 0);
1123
+ material.setParameter("u_iorTextureEnabled", 0);
1124
+ material.setParameter("u_transmissionTextureEnabled", 0);
1125
+ material.setParameter("u_transmissionFactor", 0);
1126
+ material.setParameter("u_diffuseTransmissionFactor", 0);
1127
+ material.setParameter("u_transmissionFallbackEnergy", 0);
1128
+ material.setParameter("u_volumeThicknessFactor", 0);
1129
+ material.setParameter("u_transmissionParallaxStrength", 0);
1130
+ material.setParameter("u_ior", 1.0);
1131
+ material.setParameter("u_metallic", 0);
1132
+ material.setParameter("u_roughness", 0.38);
1133
+ material.setParameter("u_specularFactor", 0.06);
1134
+ material.setParameter("u_specularColorFactor", [0.026, 0.034, 0.042]);
1135
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.014);
1136
+ }
1137
+ if (/Tireside|Tiretread/i.test(name)) {
1138
+ material.setParameter("u_baseColor", [0.014, 0.014, 0.013, 1]);
1139
+ material.setParameter("u_baseColorTextureEnabled", 0);
1140
+ material.setParameter("u_normalScale", 0.24);
1141
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1142
+ material.setParameter("u_occlusionTextureEnabled", 1);
1143
+ material.setParameter("u_occlusionStrength", 0.18);
1144
+ material.setParameter("u_specularTextureEnabled", 0);
1145
+ material.setParameter("u_specularColorTextureEnabled", 0);
1146
+ material.setParameter("u_metallic", 0);
1147
+ material.setParameter("u_roughness", 0.8);
1148
+ material.setParameter("u_specularFactor", 0.035);
1149
+ material.setParameter("u_specularColorFactor", [0.035, 0.035, 0.034]);
1150
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.008);
1151
+ }
1152
+ if (/Rim[12]|Disc|Brake/i.test(name)) {
1153
+ if (/Rim[12]/i.test(name)) {
1154
+ material.setParameter("u_baseColor", /Rim2/i.test(name) ? [0.72, 0.69, 0.62, 1] : [0.23, 0.24, 0.25, 1]);
1155
+ }
1156
+ if (/Disc/i.test(name)) {
1157
+ material.setParameter("u_baseColor", [0.86, 0.82, 0.72, 1]);
1158
+ material.setParameter("u_baseColorTextureEnabled", 1);
1159
+ }
1160
+ material.setParameter("u_normalTextureEnabled", 1);
1161
+ material.setParameter("u_normalScale", /Disc|Rim[12]/i.test(name) ? 0.05 : 0.04);
1162
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1163
+ material.setParameter("u_occlusionTextureEnabled", 1);
1164
+ material.setParameter("u_occlusionStrength", /Disc|Rim[12]/i.test(name) ? 0.06 : 0.04);
1165
+ material.setParameter("u_specularTextureEnabled", 0);
1166
+ material.setParameter("u_specularColorTextureEnabled", 0);
1167
+ material.setParameter("u_metallic", /Disc|Rim[12]/i.test(name) ? 0.86 : 0);
1168
+ material.setParameter("u_roughness", /Disc|Rim[12]/i.test(name) ? 0.34 : 0.68);
1169
+ material.setParameter("u_specularFactor", /Disc|Rim[12]/i.test(name) ? 0.28 : 0.035);
1170
+ material.setParameter("u_specularColorFactor", /Disc|Rim[12]/i.test(name) ? [0.28, 0.26, 0.22] : [0.035, 0.018, 0.012]);
1171
+ material.setParameter("u_materialEnvironmentSpecularScale", /Disc|Rim[12]/i.test(name) ? 0.055 : 0.004);
1172
+ material.setParameter("u_emissiveTextureEnabled", 0);
1173
+ material.setParameter("u_emissiveStrength", /Brake/i.test(name) ? 0.22 : 0.02);
1174
+ material.setParameter("u_emissiveColor", /Brake/i.test(name) ? [0.22, 0.02, 0.01] : [0, 0, 0]);
1175
+ }
1176
+ if (/Hardware|Mirror|Dashboard|material-2/i.test(name)) {
1177
+ if (/Mirror|Hardware|material-2/i.test(name)) {
1178
+ material.setParameter("u_baseColor", [0.018, 0.017, 0.018, 1]);
1179
+ material.setParameter("u_normalScale", 0);
1180
+ }
1181
+ material.setParameter("u_emissiveTextureEnabled", 0);
1182
+ material.setParameter("u_emissiveStrength", /Dashboard/i.test(name) ? 0.22 : 0);
1183
+ material.setParameter("u_emissiveColor", /Dashboard/i.test(name) ? [0.16, 0.052, 0.014] : [0, 0, 0]);
1184
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1185
+ material.setParameter("u_occlusionStrength", 0.02);
1186
+ material.setParameter("u_specularTextureEnabled", 0);
1187
+ material.setParameter("u_specularColorTextureEnabled", 0);
1188
+ material.setParameter("u_metallic", 0);
1189
+ material.setParameter("u_roughness", /Dashboard/i.test(name) ? 0.62 : 0.72);
1190
+ material.setParameter("u_specularFactor", /Dashboard/i.test(name) ? 0.08 : 0.04);
1191
+ material.setParameter("u_specularColorFactor", /Dashboard/i.test(name) ? [0.12, 0.055, 0.035] : [0.055, 0.05, 0.045]);
1192
+ material.setParameter("u_materialEnvironmentSpecularScale", /Dashboard/i.test(name) ? 0.018 : 0.01);
1193
+ }
1194
+ if (/Interior|Mechanical|Floormat/i.test(name)) {
1195
+ if (/Mechanical|Floormat/i.test(name)) {
1196
+ material.setParameter("u_baseColor", [0.016, 0.015, 0.014, 1]);
1197
+ }
1198
+ if (/Interior 3 Carmine/i.test(name)) {
1199
+ material.setParameter("u_baseColor", [0.48, 0.08, 0.055, 1]);
1200
+ }
1201
+ if (/Interior 3 Pearl/i.test(name)) {
1202
+ material.setParameter("u_baseColor", [0.18, 0.158, 0.138, 1]);
1203
+ }
1204
+ material.setParameter("u_normalTextureEnabled", 1);
1205
+ material.setParameter("u_normalScale", /Mechanical|Floormat/i.test(name) ? 0.08 : 0.09);
1206
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1207
+ material.setParameter("u_occlusionStrength", /Mechanical|Floormat/i.test(name) ? 0.12 : 0.06);
1208
+ material.setParameter("u_specularTextureEnabled", 0);
1209
+ material.setParameter("u_specularColorTextureEnabled", 0);
1210
+ material.setParameter("u_metallic", 0);
1211
+ material.setParameter("u_roughness", /Mechanical|Floormat/i.test(name) ? 0.7 : 0.56);
1212
+ material.setParameter("u_specularFactor", /Mechanical|Floormat/i.test(name) ? 0.035 : 0.08);
1213
+ material.setParameter("u_specularColorFactor", /Mechanical|Floormat/i.test(name) ? [0.045, 0.045, 0.042] : [0.12, 0.065, 0.04]);
1214
+ material.setParameter("u_materialEnvironmentSpecularScale", /Mechanical|Floormat/i.test(name) ? 0.01 : 0.02);
1215
+ }
1216
+ }
1217
+
1218
+ function applyCinematicCarConceptMaterialStability(
1219
+ material: Material,
1220
+ options: CarConceptMaterialStabilityOptions
1221
+ ): void {
1222
+ const name = `${options.materialKey ?? ""} ${material.name}`;
1223
+ const carPaint = /Paint [12] (Carmine|Pearl|Pearly|Graphite)|Body.*Color/i.test(name);
1224
+ const darkPanel = /Panel Sides|BodyRoofPanel|BodyPillars/i.test(name);
1225
+ const glass = /Glass|Window|Windshield/i.test(name);
1226
+ const tire = /Tireside|Tiretread/i.test(name);
1227
+ const wheelMetal = /Rim[12]|Disc|Brake/i.test(name);
1228
+ const darkTrim = /Hardware|Mirror|Dashboard|Mechanical|Interior|Floormat|material-2/i.test(name);
1229
+
1230
+ if (carPaint) {
1231
+ if (/Paint [12] Carmine|Body.*Color/i.test(name)) {
1232
+ material.setParameter("u_baseColor", [0.54, 0.018, 0.011, 1]);
1233
+ } else if (/Paint [12] (Pearl|Pearly)|Graphite/i.test(name)) {
1234
+ material.setParameter("u_baseColor", [0.24, 0.052, 0.046, 1]);
1235
+ }
1236
+ material.setParameter("u_normalTextureEnabled", 0);
1237
+ material.setParameter("u_normalScale", 0);
1238
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1239
+ material.setParameter("u_occlusionTextureEnabled", 1);
1240
+ material.setParameter("u_occlusionStrength", 0.002);
1241
+ material.setParameter("u_specularTextureEnabled", 0);
1242
+ material.setParameter("u_specularColorTextureEnabled", 0);
1243
+ material.setParameter("u_metallic", Math.min(numberParameter(material, "u_metallic") ?? 0, 0.18));
1244
+ material.setParameter("u_roughness", Math.max(options.baseline?.roughness !== undefined ? options.baseline.roughness * (options.roughnessScale ?? 1) : 0.62, 0.62));
1245
+ material.setParameter("u_specularFactor", Math.min(numberParameter(material, "u_specularFactor") ?? 0.018, 0.018));
1246
+ material.setParameter("u_specularColorFactor", [0.15, 0.012, 0.01]);
1247
+ material.setParameter("u_clearcoatTextureEnabled", 0);
1248
+ material.setParameter("u_clearcoatRoughnessTextureEnabled", 0);
1249
+ material.setParameter("u_clearcoatNormalTextureEnabled", 0);
1250
+ material.setParameter("u_clearcoatNormalScale", 0);
1251
+ material.setParameter("u_clearcoatFactor", 0);
1252
+ material.setParameter("u_clearcoatRoughnessFactor", 1);
1253
+ material.setParameter("u_iridescenceTextureEnabled", 0);
1254
+ material.setParameter("u_iridescenceThicknessTextureEnabled", 0);
1255
+ material.setParameter("u_iridescenceFactor", 0);
1256
+ material.setParameter("u_materialEnvironmentSpecularScale", 0.001);
1257
+ }
1258
+
1259
+ if (darkPanel || glass) {
1260
+ material.setParameter("u_baseColor", glass ? [0.014, 0.018, 0.022, 1] : [0.048, 0.04, 0.039, 1]);
1261
+ material.setParameter("u_baseColorTextureEnabled", 0);
1262
+ material.setParameter("u_normalTextureEnabled", 0);
1263
+ material.setParameter("u_normalScale", 0);
1264
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1265
+ material.setParameter("u_occlusionTextureEnabled", 1);
1266
+ material.setParameter("u_occlusionStrength", 0.002);
1267
+ material.setParameter("u_specularTextureEnabled", 0);
1268
+ material.setParameter("u_specularColorTextureEnabled", 0);
1269
+ material.setParameter("u_metallic", 0);
1270
+ material.setParameter("u_roughness", glass ? 0.9 : 0.78);
1271
+ material.setParameter("u_specularFactor", glass ? 0.004 : 0.01);
1272
+ material.setParameter("u_specularColorFactor", glass ? [0.006, 0.007, 0.008] : [0.022, 0.014, 0.012]);
1273
+ material.setParameter("u_clearcoatTextureEnabled", 0);
1274
+ material.setParameter("u_clearcoatRoughnessTextureEnabled", 0);
1275
+ material.setParameter("u_clearcoatNormalTextureEnabled", 0);
1276
+ material.setParameter("u_clearcoatNormalScale", 0);
1277
+ material.setParameter("u_clearcoatFactor", 0);
1278
+ material.setParameter("u_transmissionTextureEnabled", 0);
1279
+ material.setParameter("u_transmissionFactor", 0);
1280
+ material.setParameter("u_diffuseTransmissionFactor", 0);
1281
+ material.setParameter("u_transmissionFallbackEnergy", 0);
1282
+ material.setParameter("u_volumeThicknessFactor", 0);
1283
+ material.setParameter("u_ior", 1);
1284
+ material.setParameter("u_materialEnvironmentSpecularScale", glass ? 0.001 : 0.002);
1285
+ }
1286
+
1287
+ if (tire || wheelMetal || darkTrim) {
1288
+ if (tire) material.setParameter("u_baseColor", [0.008, 0.008, 0.008, 1]);
1289
+ if (wheelMetal) material.setParameter("u_baseColor", /Disc/i.test(name) ? [0.12, 0.12, 0.12, 1] : [0.03, 0.03, 0.032, 1]);
1290
+ material.setParameter("u_normalTextureEnabled", tire ? 1 : 0);
1291
+ material.setParameter("u_normalScale", tire ? 0.035 : 0);
1292
+ material.setParameter("u_metallicRoughnessTextureEnabled", 0);
1293
+ material.setParameter("u_occlusionTextureEnabled", 1);
1294
+ material.setParameter("u_occlusionStrength", tire ? 0.002 : 0.004);
1295
+ material.setParameter("u_specularTextureEnabled", 0);
1296
+ material.setParameter("u_specularColorTextureEnabled", 0);
1297
+ material.setParameter("u_metallic", wheelMetal ? Math.min(numberParameter(material, "u_metallic") ?? 0, 0.08) : 0);
1298
+ material.setParameter("u_roughness", tire ? 0.92 : Math.max(numberParameter(material, "u_roughness") ?? 0.72, 0.72));
1299
+ material.setParameter("u_specularFactor", wheelMetal ? 0.012 : 0.004);
1300
+ material.setParameter("u_specularColorFactor", wheelMetal ? [0.012, 0.012, 0.012] : [0.006, 0.006, 0.006]);
1301
+ material.setParameter("u_clearcoatFactor", 0);
1302
+ material.setParameter("u_materialEnvironmentSpecularScale", wheelMetal ? 0.002 : 0.001);
1303
+ }
1304
+ }
1305
+
1306
+ function applyCarConceptOpaqueRuntimeSurface(
1307
+ material: Material,
1308
+ surface: CarConceptMaterialRuntimeSurface
1309
+ ): void {
1310
+ material.setParameter("u_alphaCutoff", surface.alphaTest);
1311
+ material.setParameter("u_opacity", surface.opacity);
1312
+ material.setParameter("u_transparent", surface.opacity < 1 ? 1 : 0);
1313
+ material.setParameter("u_toneMapped", surface.toneMapped ? 1 : 0);
1314
+
1315
+ const materialRecord = material as unknown as Record<string, unknown>;
1316
+ const renderState = (material as unknown as { readonly renderState?: Partial<RenderState> }).renderState;
1317
+ if (renderState && typeof renderState === "object") {
1318
+ setExistingProperty(renderState, "blend", false);
1319
+ setExistingProperty(renderState, "depthTest", true);
1320
+ setExistingProperty(renderState, "depthWrite", true);
1321
+ setExistingProperty(renderState, "cullMode", "back");
1322
+ }
1323
+
1324
+ setExistingProperty(materialRecord, "transparent", false);
1325
+ setExistingProperty(materialRecord, "opacity", surface.opacity);
1326
+ setExistingProperty(materialRecord, "alphaTest", surface.alphaTest);
1327
+ setExistingProperty(materialRecord, "depthTest", true);
1328
+ setExistingProperty(materialRecord, "depthWrite", true);
1329
+ setExistingMaterialSide(materialRecord);
1330
+ setExistingNumberProperty(materialRecord, "transmission", surface.transmission);
1331
+ setExistingNumberProperty(materialRecord, "clearcoat", surface.clearcoat);
1332
+ setExistingNumberProperty(materialRecord, "specular", surface.specular);
1333
+ setExistingNumberProperty(materialRecord, "specularIntensity", surface.specular);
1334
+ setExistingNumberProperty(materialRecord, "metalness", surface.metalness);
1335
+ setExistingNumberProperty(materialRecord, "roughness", surface.roughness);
1336
+ setExistingNumberProperty(materialRecord, "envMapIntensity", surface.envMapIntensity);
1337
+ setExistingEmissive(materialRecord, surface.emissive);
1338
+ setExistingProperty(materialRecord, "toneMapped", surface.toneMapped);
1339
+ setExistingProperty(materialRecord, "needsUpdate", true);
1340
+ }
1341
+
1342
+ function setExistingProperty(target: unknown, key: string, value: unknown): void {
1343
+ if (!target || typeof target !== "object") return;
1344
+ const record = target as Record<string, unknown>;
1345
+ if (!(key in record)) return;
1346
+ try {
1347
+ record[key] = value;
1348
+ } catch {
1349
+ // Some downstream material adapters expose readonly mirrors; ignore those safely.
1350
+ }
1351
+ }
1352
+
1353
+ function setExistingNumberProperty(target: Record<string, unknown>, key: string, value: number): void {
1354
+ if (!(key in target)) return;
1355
+ const current = target[key];
1356
+ if (current !== undefined && typeof current !== "number") return;
1357
+ setExistingProperty(target, key, value);
1358
+ }
1359
+
1360
+ function setExistingMaterialSide(target: Record<string, unknown>): void {
1361
+ if (!("side" in target)) return;
1362
+ setExistingProperty(target, "side", typeof target.side === "number" ? 0 : "front");
1363
+ }
1364
+
1365
+ function setExistingEmissive(target: Record<string, unknown>, emissive: Rgb): void {
1366
+ if (!("emissive" in target)) return;
1367
+ const current = target.emissive;
1368
+ if (current && typeof current === "object") {
1369
+ const color = current as { setRGB?: (r: number, g: number, b: number) => unknown };
1370
+ if (typeof color.setRGB === "function") {
1371
+ try {
1372
+ color.setRGB(emissive[0], emissive[1], emissive[2]);
1373
+ return;
1374
+ } catch {
1375
+ return;
1376
+ }
1377
+ }
1378
+ }
1379
+ setExistingProperty(target, "emissive", [...emissive]);
1380
+ }
1381
+
1382
+ function numberParameter(material: Material, name: string): number | undefined {
1383
+ const value = materialParameter(material, name);
1384
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
1385
+ }
1386
+
1387
+ function vector3Parameter(material: Material, name: string): Rgb | undefined {
1388
+ const value = materialParameter(material, name);
1389
+ if (!Array.isArray(value) && !ArrayBuffer.isView(value)) return undefined;
1390
+ const components = Array.from(value as ArrayLike<number>);
1391
+ if (components.length < 3 || !components.slice(0, 3).every((component) => typeof component === "number" && Number.isFinite(component))) {
1392
+ return undefined;
1393
+ }
1394
+ return [components[0]!, components[1]!, components[2]!];
1395
+ }
1396
+
1397
+ function materialParameter(material: Material, name: string): UniformValue | undefined {
1398
+ const getParameter = (material as unknown as { readonly getParameter?: (parameterName: string) => UniformValue | undefined }).getParameter;
1399
+ if (typeof getParameter !== "function") return undefined;
1400
+ try {
1401
+ return getParameter.call(material, name);
1402
+ } catch {
1403
+ return undefined;
1404
+ }
1405
+ }