wuic-framework-lib 1.3.0 → 1.5.0

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 (21) hide show
  1. package/fesm2022/{wuic-framework-lib-chart-list.component-C02jeFGy.mjs → wuic-framework-lib-chart-list.component-0J1ghIrS.mjs} +4 -4
  2. package/fesm2022/{wuic-framework-lib-code-editor.component-BZNLr0Jj.mjs → wuic-framework-lib-code-editor.component-C21mvjyr.mjs} +277 -13
  3. package/fesm2022/{wuic-framework-lib-designer.component-N_CfbGnr.mjs → wuic-framework-lib-designer.component-x10ZzUEy.mjs} +1649 -184
  4. package/fesm2022/{wuic-framework-lib-first-run-wizard.component-lW7-xMm3.mjs → wuic-framework-lib-first-run-wizard.component-BuSxs_CM.mjs} +83 -43
  5. package/fesm2022/{wuic-framework-lib-framework-docs.component-CGQbmSkv.mjs → wuic-framework-lib-framework-docs.component-xTGLbEnp.mjs} +1326 -99
  6. package/fesm2022/{wuic-framework-lib-pivot-builder.component-0gJz9RWr.mjs → wuic-framework-lib-pivot-builder.component-BkFFjPm4.mjs} +6 -6
  7. package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-C9LvmFsL.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-Bi-TrJB6.mjs} +2 -2
  8. package/fesm2022/{wuic-framework-lib-report-designer.component-DcpdzFjh.mjs → wuic-framework-lib-report-designer.component-ZvB46-LV.mjs} +2 -2
  9. package/fesm2022/{wuic-framework-lib-report-viewer.component-BHpbGpp9.mjs → wuic-framework-lib-report-viewer.component-BR-BfI2r.mjs} +2 -2
  10. package/fesm2022/wuic-framework-lib-scene3d-designer.component-BQzFxSXP.mjs +4578 -0
  11. package/fesm2022/wuic-framework-lib-scene3d-light-baker-gpu-0LjqhSNn.mjs +303 -0
  12. package/fesm2022/wuic-framework-lib-scene3d-shader-effect-CQLWkuh1.mjs +2227 -0
  13. package/fesm2022/wuic-framework-lib-scene3d-viewer.component-imoV3HOs.mjs +999 -0
  14. package/fesm2022/{wuic-framework-lib-scheduler-list.component-DHoukjf-.mjs → wuic-framework-lib-scheduler-list.component-xzlTEkoq.mjs} +2 -2
  15. package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-VsaXepUC.mjs → wuic-framework-lib-spreadsheet-list-sf.component-CrS6fOGj.mjs} +4 -4
  16. package/fesm2022/wuic-framework-lib-workflow-designer.component-5xtQ7-6z.mjs +9474 -0
  17. package/fesm2022/{wuic-framework-lib-wuic-framework-lib-Deudd4MY.mjs → wuic-framework-lib-wuic-framework-lib-3TZ-j-yL.mjs} +2682 -732
  18. package/fesm2022/wuic-framework-lib.mjs +1 -1
  19. package/package.json +2 -1
  20. package/types/wuic-framework-lib.d.ts +762 -9
  21. package/fesm2022/wuic-framework-lib-workflow-designer.component-epj3oKq3.mjs +0 -5114
@@ -0,0 +1,303 @@
1
+ import * as THREE from 'three';
2
+ import { i as isBakeableMesh, W as WUIC_BAKED_FLAG } from './wuic-framework-lib-scene3d-designer.component-BQzFxSXP.mjs';
3
+
4
+ /**
5
+ * Lightmap baking su COMPUTE SHADER (WebGPU) — stessa semantica del baker CPU
6
+ * (`bakeVertexLighting`): lambert diffuso per ambient/directional/point/spot
7
+ * con attenuazione morbida e ombre opzionali, scritto nei vertex colors e
8
+ * materiale sostituito con MeshBasicMaterial unlit.
9
+ *
10
+ * La differenza e' DOVE gira il lavoro: un kernel TSL (un thread per vertice)
11
+ * calcola luce e occlusione; le ombre usano Moller-Trumbore brute-force sul
12
+ * triangle soup world-space di tutte le mesh bakabili. Il raycaster CPU e'
13
+ * O(V x L x T) sul main thread e blocca l'UI per secondi/minuti su scene
14
+ * dense; lo stesso lavoro in compute e' massicciamente parallelo.
15
+ *
16
+ * Richiede il renderer WebGPU attivo (`renderer.computeAsync`): il chiamante
17
+ * fa fallback sul baker CPU per WebGL o in caso d'errore.
18
+ */
19
+ /** Oltre questo budget (vertici x luci x triangoli) il bake GPU rifiuta e si va di CPU. */
20
+ const MAX_GPU_BAKE_WORK = 4e10;
21
+ async function bakeVertexLightingGpu(renderer, content, lights, options) {
22
+ if (typeof renderer?.computeAsync !== 'function') {
23
+ throw new Error('bakeVertexLightingGpu: renderer senza computeAsync (serve WebGPURenderer)');
24
+ }
25
+ const webgpu = await import('three/webgpu');
26
+ const TSL = webgpu.TSL;
27
+ const { Fn, If, Loop, Break, instanceIndex, storage, float, vec3, vec4, uint } = TSL;
28
+ const meshes = [];
29
+ content.traverse((obj) => {
30
+ if (isBakeableMesh(obj)) {
31
+ meshes.push(obj);
32
+ }
33
+ });
34
+ if (meshes.length === 0) {
35
+ return { bakedMeshes: 0, totalVertices: 0 };
36
+ }
37
+ content.updateMatrixWorld(true);
38
+ // --- Vertici (world) di TUTTE le mesh in un unico buffer: un dispatch solo.
39
+ const ranges = [];
40
+ let vertexCount = 0;
41
+ for (const mesh of meshes) {
42
+ const geometry = mesh.geometry;
43
+ if (!geometry.getAttribute('normal')) {
44
+ geometry.computeVertexNormals();
45
+ }
46
+ const count = geometry.getAttribute('position').count;
47
+ ranges.push({ mesh, offset: vertexCount, count });
48
+ vertexCount += count;
49
+ }
50
+ const posArray = new Float32Array(vertexCount * 4);
51
+ const nrmArray = new Float32Array(vertexCount * 4);
52
+ const v = new THREE.Vector3();
53
+ const n = new THREE.Vector3();
54
+ const normalMatrix = new THREE.Matrix3();
55
+ for (const { mesh, offset } of ranges) {
56
+ const geometry = mesh.geometry;
57
+ const position = geometry.getAttribute('position');
58
+ const normal = geometry.getAttribute('normal');
59
+ normalMatrix.getNormalMatrix(mesh.matrixWorld);
60
+ for (let i = 0; i < position.count; i++) {
61
+ v.fromBufferAttribute(position, i).applyMatrix4(mesh.matrixWorld);
62
+ n.fromBufferAttribute(normal, i).applyMatrix3(normalMatrix).normalize();
63
+ const o = (offset + i) * 4;
64
+ posArray[o] = v.x;
65
+ posArray[o + 1] = v.y;
66
+ posArray[o + 2] = v.z;
67
+ posArray[o + 3] = 1;
68
+ nrmArray[o] = n.x;
69
+ nrmArray[o + 1] = n.y;
70
+ nrmArray[o + 2] = n.z;
71
+ nrmArray[o + 3] = 0;
72
+ }
73
+ }
74
+ // --- Triangle soup world-space per l'occlusione (solo con ombre attive).
75
+ let triCount = 0;
76
+ let triArray = new Float32Array(0);
77
+ if (options.shadows) {
78
+ const triPositions = [];
79
+ const a = new THREE.Vector3();
80
+ const b = new THREE.Vector3();
81
+ const c = new THREE.Vector3();
82
+ for (const { mesh } of ranges) {
83
+ const geometry = mesh.geometry;
84
+ const position = geometry.getAttribute('position');
85
+ const index = geometry.getIndex();
86
+ const faces = index ? index.count / 3 : position.count / 3;
87
+ for (let f = 0; f < faces; f++) {
88
+ const i0 = index ? index.getX(f * 3) : f * 3;
89
+ const i1 = index ? index.getX(f * 3 + 1) : f * 3 + 1;
90
+ const i2 = index ? index.getX(f * 3 + 2) : f * 3 + 2;
91
+ a.fromBufferAttribute(position, i0).applyMatrix4(mesh.matrixWorld);
92
+ b.fromBufferAttribute(position, i1).applyMatrix4(mesh.matrixWorld);
93
+ c.fromBufferAttribute(position, i2).applyMatrix4(mesh.matrixWorld);
94
+ triPositions.push(a.x, a.y, a.z, 0, b.x, b.y, b.z, 0, c.x, c.y, c.z, 0);
95
+ }
96
+ }
97
+ triArray = new Float32Array(triPositions);
98
+ triCount = triArray.length / 12;
99
+ }
100
+ // --- Luci: pre-risolte su CPU con la STESSA semantica di gatherLight.
101
+ // A=[type, effIntensity, cosOuter, spotDenom] B=[rgb,0]
102
+ // C=dir: versore VERSO la luce | point/spot: posizione world D=direzione cono spot.
103
+ const packedA = [];
104
+ const packedB = [];
105
+ const packedC = [];
106
+ const packedD = [];
107
+ const lightPos = new THREE.Vector3();
108
+ const targetPos = new THREE.Vector3();
109
+ const dir = new THREE.Vector3();
110
+ let lightCount = 0;
111
+ for (const light of lights) {
112
+ if (!light.visible) {
113
+ continue;
114
+ }
115
+ if (light.isAmbientLight) {
116
+ packedA.push(0, light.intensity, 0, 0);
117
+ packedB.push(light.color.r, light.color.g, light.color.b, 0);
118
+ packedC.push(0, 0, 0, 0);
119
+ packedD.push(0, 0, 0, 0);
120
+ }
121
+ else if (light.isDirectionalLight) {
122
+ const dl = light;
123
+ dl.getWorldPosition(lightPos);
124
+ dl.target.getWorldPosition(targetPos);
125
+ dir.subVectors(lightPos, targetPos).normalize();
126
+ packedA.push(1, light.intensity, 0, 0);
127
+ packedB.push(light.color.r, light.color.g, light.color.b, 0);
128
+ packedC.push(dir.x, dir.y, dir.z, 0);
129
+ packedD.push(0, 0, 0, 0);
130
+ }
131
+ else if (light.isPointLight || light.isSpotLight) {
132
+ light.getWorldPosition(lightPos);
133
+ const isSpot = !!light.isSpotLight;
134
+ let cosOuter = -2;
135
+ let spotDenom = 1;
136
+ let effIntensity = light.intensity;
137
+ if (isSpot) {
138
+ const spot = light;
139
+ spot.target.getWorldPosition(targetPos);
140
+ dir.subVectors(targetPos, lightPos).normalize();
141
+ cosOuter = Math.cos(spot.angle);
142
+ const cosInner = Math.cos(spot.angle * (1 - spot.penumbra));
143
+ spotDenom = Math.max(cosInner - cosOuter, 1e-6);
144
+ // Fattore 0.12 (unita' candela leggibili) ripiegato nell'intensita'.
145
+ effIntensity *= 0.12;
146
+ packedD.push(dir.x, dir.y, dir.z, 0);
147
+ }
148
+ else {
149
+ packedD.push(0, 0, 0, 0);
150
+ }
151
+ packedA.push(isSpot ? 3 : 2, effIntensity, cosOuter, spotDenom);
152
+ packedB.push(light.color.r, light.color.g, light.color.b, 0);
153
+ packedC.push(lightPos.x, lightPos.y, lightPos.z, 0);
154
+ }
155
+ else {
156
+ continue; // tipi non supportati dal bake
157
+ }
158
+ lightCount++;
159
+ }
160
+ if (lightCount === 0) {
161
+ // Nessuna luce supportata: colori a zero, la CPU farebbe lo stesso.
162
+ return applyBakeResults(ranges, new Float32Array(vertexCount * 4));
163
+ }
164
+ const shadowWork = options.shadows ? vertexCount * lightCount * Math.max(triCount, 1) : vertexCount * lightCount;
165
+ if (shadowWork > MAX_GPU_BAKE_WORK) {
166
+ throw new Error(`bakeVertexLightingGpu: scena oltre il budget GPU (${shadowWork.toExponential(1)})`);
167
+ }
168
+ // --- Storage buffer + kernel TSL.
169
+ const positionsAttr = new webgpu.StorageBufferAttribute(posArray, 4);
170
+ const normalsAttr = new webgpu.StorageBufferAttribute(nrmArray, 4);
171
+ const trianglesAttr = new webgpu.StorageBufferAttribute(triCount > 0 ? triArray : new Float32Array(4), 4);
172
+ const lightsAAttr = new webgpu.StorageBufferAttribute(new Float32Array(packedA), 4);
173
+ const lightsBAttr = new webgpu.StorageBufferAttribute(new Float32Array(packedB), 4);
174
+ const lightsCAttr = new webgpu.StorageBufferAttribute(new Float32Array(packedC), 4);
175
+ const lightsDAttr = new webgpu.StorageBufferAttribute(new Float32Array(packedD), 4);
176
+ const colorsAttr = new webgpu.StorageBufferAttribute(new Float32Array(vertexCount * 4), 4);
177
+ const positions = storage(positionsAttr, 'vec4', vertexCount).toReadOnly();
178
+ const normals = storage(normalsAttr, 'vec4', vertexCount).toReadOnly();
179
+ const triangles = storage(trianglesAttr, 'vec4', Math.max(triCount * 3, 1)).toReadOnly();
180
+ const lightsA = storage(lightsAAttr, 'vec4', lightCount).toReadOnly();
181
+ const lightsB = storage(lightsBAttr, 'vec4', lightCount).toReadOnly();
182
+ const lightsC = storage(lightsCAttr, 'vec4', lightCount).toReadOnly();
183
+ const lightsD = storage(lightsDAttr, 'vec4', lightCount).toReadOnly();
184
+ const colors = storage(colorsAttr, 'vec4', vertexCount);
185
+ const withShadows = options.shadows && triCount > 0;
186
+ const kernel = Fn(() => {
187
+ If(instanceIndex.lessThan(uint(vertexCount)), () => {
188
+ const P = positions.element(instanceIndex).xyz.toVar();
189
+ const N = normals.element(instanceIndex).xyz.toVar();
190
+ const acc = vec3(0).toVar();
191
+ Loop(lightCount, ({ i: li }) => {
192
+ const A = lightsA.element(li).toVar();
193
+ const B = lightsB.element(li).xyz.toVar();
194
+ const lightType = A.x;
195
+ const intensity = A.y;
196
+ If(lightType.lessThan(0.5), () => {
197
+ // Ambient: contributo piatto.
198
+ acc.addAssign(B.mul(intensity));
199
+ }).Else(() => {
200
+ const lambert = float(0).toVar();
201
+ const atten = float(1).toVar();
202
+ const toLight = vec3(0, 1, 0).toVar();
203
+ const shadowDist = float(1e9).toVar();
204
+ const skip = float(0).toVar();
205
+ If(lightType.lessThan(1.5), () => {
206
+ // Directional: C = versore verso la luce.
207
+ toLight.assign(lightsC.element(li).xyz);
208
+ lambert.assign(N.dot(toLight).max(0));
209
+ }).Else(() => {
210
+ // Point/Spot: C = posizione world della luce.
211
+ const dvec = lightsC.element(li).xyz.sub(P).toVar();
212
+ const dist = dvec.length().toVar();
213
+ If(dist.lessThanEqual(1e-6), () => {
214
+ skip.assign(1);
215
+ }).Else(() => {
216
+ toLight.assign(dvec.div(dist));
217
+ lambert.assign(N.dot(toLight).max(0));
218
+ // Attenuazione morbida (non fisica), come il baker CPU.
219
+ atten.assign(float(1).div(dist.mul(dist).mul(0.08).add(1)));
220
+ shadowDist.assign(dist);
221
+ If(lightType.greaterThan(2.5), () => {
222
+ // Spot: A.z = cosOuter, A.w = denom (cosInner - cosOuter).
223
+ const coneDir = lightsD.element(li).xyz;
224
+ const cosAngle = toLight.negate().dot(coneDir).toVar();
225
+ If(cosAngle.lessThanEqual(A.z), () => {
226
+ skip.assign(1); // fuori dal cono
227
+ }).Else(() => {
228
+ const spotFactor = cosAngle.sub(A.z).div(A.w).clamp(0, 1);
229
+ atten.mulAssign(spotFactor);
230
+ });
231
+ });
232
+ });
233
+ });
234
+ If(skip.lessThan(0.5).and(lambert.greaterThan(0)).and(atten.greaterThan(0)), () => {
235
+ const lit = float(1).toVar();
236
+ if (withShadows) {
237
+ // Raggio d'ombra Moller-Trumbore brute-force sul triangle soup.
238
+ const origin = P.add(N.mul(0.02)).toVar();
239
+ const maxT = shadowDist.sub(0.04).min(1000).toVar();
240
+ Loop(triCount, ({ i: ti }) => {
241
+ const base = ti.mul(3);
242
+ const v0 = triangles.element(base).xyz;
243
+ const e1 = triangles.element(base.add(1)).xyz.sub(v0).toVar();
244
+ const e2 = triangles.element(base.add(2)).xyz.sub(v0).toVar();
245
+ const h = toLight.cross(e2).toVar();
246
+ const det = e1.dot(h).toVar();
247
+ If(det.abs().greaterThan(1e-7), () => {
248
+ const f = float(1).div(det);
249
+ const s = origin.sub(v0).toVar();
250
+ const u = f.mul(s.dot(h)).toVar();
251
+ If(u.greaterThanEqual(0).and(u.lessThanEqual(1)), () => {
252
+ const q = s.cross(e1).toVar();
253
+ const w = f.mul(toLight.dot(q)).toVar();
254
+ If(w.greaterThanEqual(0).and(u.add(w).lessThanEqual(1)), () => {
255
+ const t = f.mul(e2.dot(q));
256
+ If(t.greaterThan(0.001).and(t.lessThan(maxT)), () => {
257
+ lit.assign(0);
258
+ Break();
259
+ });
260
+ });
261
+ });
262
+ });
263
+ });
264
+ }
265
+ acc.addAssign(B.mul(intensity.mul(lambert).mul(atten).mul(lit)));
266
+ });
267
+ });
268
+ });
269
+ // Clamp morbido per non bruciare (tone-map naive, come CPU).
270
+ colors.element(instanceIndex).assign(vec4(acc.min(1), 1));
271
+ });
272
+ });
273
+ await renderer.computeAsync(kernel().compute(vertexCount));
274
+ const resultBuffer = await renderer.getArrayBufferAsync(colorsAttr);
275
+ return applyBakeResults(ranges, new Float32Array(resultBuffer));
276
+ }
277
+ /** Scrive i colori calcolati nei vertex colors e applica il materiale unlit (mirror del baker CPU). */
278
+ function applyBakeResults(ranges, packedColors) {
279
+ let totalVertices = 0;
280
+ for (const { mesh, offset, count } of ranges) {
281
+ const geometry = mesh.geometry;
282
+ const colors = new Float32Array(count * 3);
283
+ for (let i = 0; i < count; i++) {
284
+ const src = (offset + i) * 4;
285
+ colors[i * 3] = packedColors[src];
286
+ colors[i * 3 + 1] = packedColors[src + 1];
287
+ colors[i * 3 + 2] = packedColors[src + 2];
288
+ }
289
+ geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
290
+ const orig = Array.isArray(mesh.material) ? mesh.material[0] : mesh.material;
291
+ mesh.material = new THREE.MeshBasicMaterial({
292
+ color: orig?.color instanceof THREE.Color ? orig.color.clone() : new THREE.Color(0xffffff),
293
+ map: orig?.map || null,
294
+ vertexColors: true
295
+ });
296
+ mesh.userData[WUIC_BAKED_FLAG] = true;
297
+ totalVertices += count;
298
+ }
299
+ return { bakedMeshes: ranges.length, totalVertices };
300
+ }
301
+
302
+ export { bakeVertexLightingGpu };
303
+ //# sourceMappingURL=wuic-framework-lib-scene3d-light-baker-gpu-0LjqhSNn.mjs.map