poppygl 0.0.29 → 0.0.30
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.
- package/dist/index.js +84 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -512,6 +512,77 @@ function srgbDecodeToLinear01(srgb) {
|
|
|
512
512
|
// lib/utils/clamp.ts
|
|
513
513
|
var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
514
514
|
|
|
515
|
+
// lib/render/clipMeshToNearPlane.ts
|
|
516
|
+
function clipMeshToNearPlane(mesh, mvp) {
|
|
517
|
+
const count = mesh.positions.length / 3;
|
|
518
|
+
const distances = new Float64Array(count);
|
|
519
|
+
let needsClipping = false;
|
|
520
|
+
for (let i = 0; i < count; i++) {
|
|
521
|
+
const distance = (mvp[2] + mvp[3]) * mesh.positions[i * 3] + (mvp[6] + mvp[7]) * mesh.positions[i * 3 + 1] + (mvp[10] + mvp[11]) * mesh.positions[i * 3 + 2] + mvp[14] + mvp[15];
|
|
522
|
+
distances[i] = distance;
|
|
523
|
+
if (!(distance >= 0)) needsClipping = true;
|
|
524
|
+
}
|
|
525
|
+
if (!needsClipping) return mesh;
|
|
526
|
+
const positions = Array.from(mesh.positions);
|
|
527
|
+
const normals = mesh.normals ? Array.from(mesh.normals) : null;
|
|
528
|
+
const uvs = mesh.uvs ? Array.from(mesh.uvs) : null;
|
|
529
|
+
const colors = mesh.colors ? Array.from(mesh.colors) : null;
|
|
530
|
+
const indices = [];
|
|
531
|
+
const sourceIndices = mesh.indices ?? Uint32Array.from({ length: count }, (_, i) => i);
|
|
532
|
+
const intersections = /* @__PURE__ */ new Map();
|
|
533
|
+
const intersect = (a, b) => {
|
|
534
|
+
if (a > b) [a, b] = [b, a];
|
|
535
|
+
if (distances[a] === 0) return a;
|
|
536
|
+
if (distances[b] === 0) return b;
|
|
537
|
+
const key = `${a}:${b}`;
|
|
538
|
+
const cached = intersections.get(key);
|
|
539
|
+
if (cached !== void 0) return cached;
|
|
540
|
+
const t = distances[a] / (distances[a] - distances[b]);
|
|
541
|
+
const index = positions.length / 3;
|
|
542
|
+
const interpolate = (values, size) => {
|
|
543
|
+
if (!values) return;
|
|
544
|
+
for (let k = 0; k < size; k++) {
|
|
545
|
+
const start = values[a * size + k];
|
|
546
|
+
values.push(start + t * (values[b * size + k] - start));
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
interpolate(positions, 3);
|
|
550
|
+
interpolate(normals, 3);
|
|
551
|
+
interpolate(uvs, 2);
|
|
552
|
+
interpolate(colors, 3);
|
|
553
|
+
intersections.set(key, index);
|
|
554
|
+
return index;
|
|
555
|
+
};
|
|
556
|
+
for (let i = 0; i < sourceIndices.length; i += 3) {
|
|
557
|
+
const triangle = [
|
|
558
|
+
sourceIndices[i],
|
|
559
|
+
sourceIndices[i + 1],
|
|
560
|
+
sourceIndices[i + 2]
|
|
561
|
+
];
|
|
562
|
+
if (triangle.some((vertex) => !Number.isFinite(distances[vertex]))) continue;
|
|
563
|
+
const polygon = [];
|
|
564
|
+
for (let j = 0; j < 3; j++) {
|
|
565
|
+
const a = triangle[j];
|
|
566
|
+
const b = triangle[(j + 1) % 3];
|
|
567
|
+
const aInside = distances[a] >= 0;
|
|
568
|
+
const bInside = distances[b] >= 0;
|
|
569
|
+
if (aInside) polygon.push(a);
|
|
570
|
+
if (aInside !== bInside) polygon.push(intersect(a, b));
|
|
571
|
+
}
|
|
572
|
+
for (let j = 1; j + 1 < polygon.length; j++) {
|
|
573
|
+
indices.push(polygon[0], polygon[j], polygon[j + 1]);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return {
|
|
577
|
+
...mesh,
|
|
578
|
+
positions: new Float32Array(positions),
|
|
579
|
+
normals: normals ? new Float32Array(normals) : null,
|
|
580
|
+
uvs: uvs ? new Float32Array(uvs) : null,
|
|
581
|
+
colors: colors ? new Float32Array(colors) : null,
|
|
582
|
+
indices: new Uint32Array(indices)
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
|
|
515
586
|
// lib/render/SoftwareRenderer.ts
|
|
516
587
|
var SoftwareRenderer = class {
|
|
517
588
|
width;
|
|
@@ -682,15 +753,15 @@ var SoftwareRenderer = class {
|
|
|
682
753
|
return out;
|
|
683
754
|
}
|
|
684
755
|
drawMesh(mesh, camera, light, material, cullBackFaces = true, gammaOut = true) {
|
|
685
|
-
|
|
756
|
+
let { positions, normals, uvs, indices, model, colors } = mesh;
|
|
686
757
|
const view = camera.view;
|
|
687
758
|
const proj = camera.proj;
|
|
688
759
|
const mvp = mat43.create();
|
|
689
760
|
mat43.multiply(mvp, proj, mat43.multiply(mat43.create(), view, model));
|
|
690
761
|
const normalMat = mat3.create();
|
|
691
762
|
mat3.normalFromMat4(normalMat, model);
|
|
692
|
-
|
|
693
|
-
|
|
763
|
+
let vertexCount = positions.length / 3 | 0;
|
|
764
|
+
let idx = indices ?? (() => {
|
|
694
765
|
const a = new Uint32Array(vertexCount);
|
|
695
766
|
for (let i = 0; i < vertexCount; i++) a[i] = i;
|
|
696
767
|
return a;
|
|
@@ -699,6 +770,16 @@ var SoftwareRenderer = class {
|
|
|
699
770
|
if (!useNormals) {
|
|
700
771
|
useNormals = computeSmoothNormals(positions, idx);
|
|
701
772
|
}
|
|
773
|
+
const clipped = clipMeshToNearPlane(
|
|
774
|
+
{ ...mesh, normals: useNormals, indices: idx },
|
|
775
|
+
mvp
|
|
776
|
+
);
|
|
777
|
+
positions = clipped.positions;
|
|
778
|
+
useNormals = clipped.normals;
|
|
779
|
+
uvs = clipped.uvs;
|
|
780
|
+
colors = clipped.colors;
|
|
781
|
+
idx = clipped.indices;
|
|
782
|
+
vertexCount = positions.length / 3;
|
|
702
783
|
const vScreen = new Array(vertexCount);
|
|
703
784
|
const vInvW = new Float32Array(vertexCount);
|
|
704
785
|
const vNDCz = new Float32Array(vertexCount);
|