@quake2ts/engine 0.0.804 → 0.0.807

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.
@@ -17538,6 +17538,524 @@ async function captureRenderTarget(device, texture) {
17538
17538
  outputBuffer.unmap();
17539
17539
  return result;
17540
17540
  }
17541
+
17542
+ // src/render/null/renderer.ts
17543
+ var NullRenderer = class {
17544
+ constructor(width = 800, height = 600) {
17545
+ this.width = 0;
17546
+ this.height = 0;
17547
+ this.collisionVis = null;
17548
+ this.debug = null;
17549
+ this.particleSystem = null;
17550
+ this.frameCount = 0;
17551
+ this.callLog = [];
17552
+ this.width = width;
17553
+ this.height = height;
17554
+ }
17555
+ renderFrame(options, entities = []) {
17556
+ this.frameCount++;
17557
+ this.callLog.push(`renderFrame(frame=${this.frameCount}, entities=${entities.length})`);
17558
+ const cameraState = options.cameraState ?? options.camera.toState();
17559
+ this.callLog.push(` camera: pos=${cameraState.position}, angles=${cameraState.angles}`);
17560
+ }
17561
+ // Stub implementations (all no-op)
17562
+ async registerPic(name, data) {
17563
+ this.callLog.push(`registerPic(${name})`);
17564
+ return { width: 256, height: 256 };
17565
+ }
17566
+ registerTexture(name, texture) {
17567
+ this.callLog.push(`registerTexture(${name})`);
17568
+ return { width: texture.width, height: texture.height };
17569
+ }
17570
+ begin2D() {
17571
+ this.callLog.push("begin2D()");
17572
+ }
17573
+ end2D() {
17574
+ this.callLog.push("end2D()");
17575
+ }
17576
+ drawPic(x, y, pic, color) {
17577
+ this.callLog.push(`drawPic(${x}, ${y})`);
17578
+ }
17579
+ drawString(x, y, text, color) {
17580
+ this.callLog.push(`drawString(${x}, ${y}, "${text}")`);
17581
+ }
17582
+ drawCenterString(y, text) {
17583
+ this.callLog.push(`drawCenterString(${y}, "${text}")`);
17584
+ }
17585
+ drawfillRect(x, y, width, height, color) {
17586
+ this.callLog.push(`drawfillRect(${x}, ${y}, ${width}, ${height})`);
17587
+ }
17588
+ setEntityHighlight(entityId, color) {
17589
+ }
17590
+ clearEntityHighlight(entityId) {
17591
+ }
17592
+ highlightSurface(faceIndex, color) {
17593
+ }
17594
+ removeSurfaceHighlight(faceIndex) {
17595
+ }
17596
+ setDebugMode(mode) {
17597
+ }
17598
+ setBrightness(value) {
17599
+ }
17600
+ setGamma(value) {
17601
+ }
17602
+ setFullbright(enabled) {
17603
+ }
17604
+ setAmbient(value) {
17605
+ }
17606
+ setLightStyle(index, pattern) {
17607
+ }
17608
+ setUnderwaterWarp(enabled) {
17609
+ }
17610
+ setBloom(enabled) {
17611
+ }
17612
+ setBloomIntensity(value) {
17613
+ }
17614
+ setLodBias(bias) {
17615
+ }
17616
+ renderInstanced(model, instances) {
17617
+ }
17618
+ getPerformanceReport() {
17619
+ return {
17620
+ frameTimeMs: 0,
17621
+ gpuTimeMs: 0,
17622
+ cpuFrameTimeMs: 0,
17623
+ drawCalls: 0,
17624
+ triangles: 0,
17625
+ vertices: 0,
17626
+ textureBinds: 0,
17627
+ shaderSwitches: 0,
17628
+ visibleSurfaces: 0,
17629
+ culledSurfaces: 0,
17630
+ visibleEntities: 0,
17631
+ culledEntities: 0,
17632
+ memoryUsageMB: { textures: 0, geometry: 0, total: 0 }
17633
+ };
17634
+ }
17635
+ getMemoryUsage() {
17636
+ return {
17637
+ texturesBytes: 0,
17638
+ geometryBytes: 0,
17639
+ shadersBytes: 0,
17640
+ buffersBytes: 0,
17641
+ totalBytes: 0
17642
+ };
17643
+ }
17644
+ dispose() {
17645
+ this.callLog.push("dispose()");
17646
+ }
17647
+ // Test utilities
17648
+ getCallLog() {
17649
+ return this.callLog;
17650
+ }
17651
+ resetCallLog() {
17652
+ this.callLog = [];
17653
+ }
17654
+ getFrameCount() {
17655
+ return this.frameCount;
17656
+ }
17657
+ };
17658
+
17659
+ // src/render/types/coordinates.ts
17660
+ var CoordinateSystem = /* @__PURE__ */ ((CoordinateSystem2) => {
17661
+ CoordinateSystem2["QUAKE"] = "quake";
17662
+ CoordinateSystem2["OPENGL"] = "opengl";
17663
+ CoordinateSystem2["WEBGPU"] = "webgpu";
17664
+ return CoordinateSystem2;
17665
+ })(CoordinateSystem || {});
17666
+
17667
+ // src/render/matrix/webgl.ts
17668
+ var WebGLMatrixBuilder = class {
17669
+ constructor() {
17670
+ this.coordinateSystem = "opengl" /* OPENGL */;
17671
+ }
17672
+ buildProjectionMatrix(camera) {
17673
+ const projection = glMatrix.mat4.create();
17674
+ glMatrix.mat4.perspective(
17675
+ projection,
17676
+ camera.fov * shared.DEG2RAD,
17677
+ camera.aspect,
17678
+ camera.near,
17679
+ camera.far
17680
+ );
17681
+ return projection;
17682
+ }
17683
+ buildViewMatrix(camera) {
17684
+ const quakeToGl = glMatrix.mat4.fromValues(
17685
+ 0,
17686
+ 0,
17687
+ -1,
17688
+ 0,
17689
+ // Quake +X (forward) → GL -Z
17690
+ -1,
17691
+ 0,
17692
+ 0,
17693
+ 0,
17694
+ // Quake +Y (left) → GL -X
17695
+ 0,
17696
+ 1,
17697
+ 0,
17698
+ 0,
17699
+ // Quake +Z (up) → GL +Y
17700
+ 0,
17701
+ 0,
17702
+ 0,
17703
+ 1
17704
+ );
17705
+ const [pitch, yaw, roll] = camera.angles;
17706
+ const pitchRad = pitch * shared.DEG2RAD;
17707
+ const yawRad = yaw * shared.DEG2RAD;
17708
+ const rollRad = roll * shared.DEG2RAD;
17709
+ const rotationQuake = glMatrix.mat4.create();
17710
+ glMatrix.mat4.identity(rotationQuake);
17711
+ glMatrix.mat4.rotateZ(rotationQuake, rotationQuake, -yawRad);
17712
+ glMatrix.mat4.rotateY(rotationQuake, rotationQuake, -pitchRad);
17713
+ glMatrix.mat4.rotateX(rotationQuake, rotationQuake, -rollRad);
17714
+ const rotationGl = glMatrix.mat4.create();
17715
+ glMatrix.mat4.multiply(rotationGl, quakeToGl, rotationQuake);
17716
+ const negativePosition = glMatrix.vec3.negate(glMatrix.vec3.create(), camera.position);
17717
+ const rotatedPosQuake = glMatrix.vec3.create();
17718
+ glMatrix.vec3.transformMat4(rotatedPosQuake, negativePosition, rotationQuake);
17719
+ const translationGl = glMatrix.vec3.fromValues(
17720
+ rotatedPosQuake[1] ? -rotatedPosQuake[1] : 0,
17721
+ // Y → -X
17722
+ rotatedPosQuake[2] || 0,
17723
+ // Z → Y
17724
+ rotatedPosQuake[0] ? -rotatedPosQuake[0] : 0
17725
+ // X → -Z
17726
+ );
17727
+ const view = glMatrix.mat4.clone(rotationGl);
17728
+ view[12] = translationGl[0];
17729
+ view[13] = translationGl[1];
17730
+ view[14] = translationGl[2];
17731
+ return view;
17732
+ }
17733
+ };
17734
+ var WebGPUMatrixBuilder = class {
17735
+ constructor() {
17736
+ this.coordinateSystem = "webgpu" /* WEBGPU */;
17737
+ }
17738
+ buildProjectionMatrix(camera) {
17739
+ const projection = glMatrix.mat4.create();
17740
+ const f = 1 / Math.tan(camera.fov * shared.DEG2RAD / 2);
17741
+ const rangeInv = 1 / (camera.near - camera.far);
17742
+ projection[0] = f / camera.aspect;
17743
+ projection[5] = f;
17744
+ projection[10] = camera.far * rangeInv;
17745
+ projection[11] = -1;
17746
+ projection[14] = camera.near * camera.far * rangeInv;
17747
+ return projection;
17748
+ }
17749
+ buildViewMatrix(camera) {
17750
+ const [pitch, yaw, roll] = camera.angles;
17751
+ const pitchRad = pitch * shared.DEG2RAD;
17752
+ const yawRad = yaw * shared.DEG2RAD;
17753
+ const rollRad = roll * shared.DEG2RAD;
17754
+ const rotationQuake = glMatrix.mat4.create();
17755
+ glMatrix.mat4.identity(rotationQuake);
17756
+ glMatrix.mat4.rotateZ(rotationQuake, rotationQuake, -yawRad);
17757
+ glMatrix.mat4.rotateY(rotationQuake, rotationQuake, -pitchRad);
17758
+ glMatrix.mat4.rotateX(rotationQuake, rotationQuake, -rollRad);
17759
+ glMatrix.mat4.fromValues(
17760
+ 0,
17761
+ 0,
17762
+ -1,
17763
+ 0,
17764
+ // Column 0: Quake X maps to View Z? Wait.
17765
+ -1,
17766
+ 0,
17767
+ 0,
17768
+ 0,
17769
+ // Column 1: Quake Y maps to View X?
17770
+ 0,
17771
+ 1,
17772
+ 0,
17773
+ 0,
17774
+ // Column 2: Quake Z maps to View Y?
17775
+ 0,
17776
+ 0,
17777
+ 0,
17778
+ 1
17779
+ );
17780
+ const quakeToWgpu = glMatrix.mat4.fromValues(
17781
+ 0,
17782
+ 0,
17783
+ -1,
17784
+ 0,
17785
+ // Col 0: X -> -Z
17786
+ -1,
17787
+ 0,
17788
+ 0,
17789
+ 0,
17790
+ // Col 1: Y -> -X
17791
+ 0,
17792
+ 1,
17793
+ 0,
17794
+ 0,
17795
+ // Col 2: Z -> Y
17796
+ 0,
17797
+ 0,
17798
+ 0,
17799
+ 1
17800
+ );
17801
+ const rotationView = glMatrix.mat4.create();
17802
+ glMatrix.mat4.multiply(rotationView, quakeToWgpu, rotationQuake);
17803
+ const cameraPos = glMatrix.vec3.fromValues(
17804
+ camera.position[0],
17805
+ camera.position[1],
17806
+ camera.position[2]
17807
+ );
17808
+ const t = glMatrix.vec3.transformMat4(glMatrix.vec3.create(), cameraPos, rotationView);
17809
+ glMatrix.vec3.negate(t, t);
17810
+ const view = glMatrix.mat4.clone(rotationView);
17811
+ view[12] = t[0];
17812
+ view[13] = t[1];
17813
+ view[14] = t[2];
17814
+ return view;
17815
+ }
17816
+ };
17817
+ var IdentityMatrixBuilder = class {
17818
+ constructor() {
17819
+ this.coordinateSystem = "quake" /* QUAKE */;
17820
+ }
17821
+ buildProjectionMatrix(camera) {
17822
+ const projection = glMatrix.mat4.create();
17823
+ glMatrix.mat4.perspective(
17824
+ projection,
17825
+ camera.fov * shared.DEG2RAD,
17826
+ camera.aspect,
17827
+ camera.near,
17828
+ camera.far
17829
+ );
17830
+ return projection;
17831
+ }
17832
+ buildViewMatrix(camera) {
17833
+ const [pitch, yaw, roll] = camera.angles;
17834
+ const pitchRad = pitch * shared.DEG2RAD;
17835
+ const yawRad = yaw * shared.DEG2RAD;
17836
+ const rollRad = roll * shared.DEG2RAD;
17837
+ const rotation = glMatrix.mat4.create();
17838
+ glMatrix.mat4.identity(rotation);
17839
+ glMatrix.mat4.rotateZ(rotation, rotation, yawRad);
17840
+ glMatrix.mat4.rotateX(rotation, rotation, pitchRad);
17841
+ glMatrix.mat4.rotateY(rotation, rotation, rollRad);
17842
+ const translation = glMatrix.mat4.create();
17843
+ glMatrix.mat4.fromTranslation(translation, [
17844
+ -camera.position[0],
17845
+ -camera.position[1],
17846
+ -camera.position[2]
17847
+ ]);
17848
+ const view = glMatrix.mat4.create();
17849
+ glMatrix.mat4.multiply(view, rotation, translation);
17850
+ return view;
17851
+ }
17852
+ };
17853
+ function buildMatrices(builder, camera) {
17854
+ const view = builder.buildViewMatrix(camera);
17855
+ const projection = builder.buildProjectionMatrix(camera);
17856
+ const viewProjection = glMatrix.mat4.create();
17857
+ glMatrix.mat4.multiply(viewProjection, projection, view);
17858
+ return { view, projection, viewProjection };
17859
+ }
17860
+ function quakeToWebGL(v) {
17861
+ return glMatrix.vec3.fromValues(-v[1], v[2], -v[0]);
17862
+ }
17863
+ function quakeToWebGPU(v) {
17864
+ return glMatrix.vec3.fromValues(-v[1], v[2], -v[0]);
17865
+ }
17866
+
17867
+ // src/render/logging/renderer.ts
17868
+ var LoggingRenderer = class {
17869
+ constructor(options = {}) {
17870
+ this.width = 0;
17871
+ this.height = 0;
17872
+ this.collisionVis = null;
17873
+ this.debug = null;
17874
+ this.particleSystem = null;
17875
+ this.logs = [];
17876
+ this.options = {
17877
+ targetSystem: options.targetSystem ?? "quake" /* QUAKE */,
17878
+ verbose: options.verbose ?? true,
17879
+ validateTransforms: options.validateTransforms ?? true
17880
+ };
17881
+ switch (this.options.targetSystem) {
17882
+ case "opengl" /* OPENGL */:
17883
+ this.builder = new WebGLMatrixBuilder();
17884
+ break;
17885
+ case "webgpu" /* WEBGPU */:
17886
+ this.builder = new WebGPUMatrixBuilder();
17887
+ break;
17888
+ default:
17889
+ this.builder = new IdentityMatrixBuilder();
17890
+ }
17891
+ this.log(`LoggingRenderer initialized (target=${this.options.targetSystem})`);
17892
+ }
17893
+ renderFrame(options, entities = []) {
17894
+ this.log(`
17895
+ === FRAME START ===`);
17896
+ const cameraState = options.cameraState ?? options.camera.toState();
17897
+ this.log(`Camera State:`);
17898
+ this.log(` Position: ${this.formatVec3(cameraState.position)} (Quake space)`);
17899
+ this.log(` Angles: ${this.formatVec3(cameraState.angles)} (degrees)`);
17900
+ this.log(` FOV: ${cameraState.fov}\xB0, Aspect: ${cameraState.aspect.toFixed(2)}`);
17901
+ const matrices = buildMatrices(this.builder, cameraState);
17902
+ this.log(`Matrices (${this.options.targetSystem}):`);
17903
+ if (this.options.verbose) {
17904
+ this.log(` View Matrix:`);
17905
+ this.logMatrix(matrices.view);
17906
+ this.log(` Projection Matrix:`);
17907
+ this.logMatrix(matrices.projection);
17908
+ }
17909
+ if (this.options.validateTransforms) {
17910
+ this.validateCoordinateTransforms(cameraState, matrices.view);
17911
+ }
17912
+ this.log(`Entities: ${entities.length}`);
17913
+ if (this.options.verbose && entities.length > 0) {
17914
+ entities.slice(0, 5).forEach((entity, i) => {
17915
+ this.log(` [${i}] type=${entity.type}, model=${entity.model ?? "none"}`);
17916
+ });
17917
+ if (entities.length > 5) {
17918
+ this.log(` ... and ${entities.length - 5} more`);
17919
+ }
17920
+ }
17921
+ this.log(`=== FRAME END ===
17922
+ `);
17923
+ }
17924
+ validateCoordinateTransforms(cameraState, viewMatrix) {
17925
+ const quakePos = cameraState.position;
17926
+ const expectedGL = quakeToWebGL(quakePos);
17927
+ const expectedGPU = quakeToWebGPU(quakePos);
17928
+ const matrixTranslation = [viewMatrix[12], viewMatrix[13], viewMatrix[14]];
17929
+ this.log(`Transform Validation:`);
17930
+ this.log(` Quake position: ${this.formatVec3(quakePos)}`);
17931
+ switch (this.options.targetSystem) {
17932
+ case "opengl" /* OPENGL */:
17933
+ this.log(` Expected GL transform: ${this.formatVec3(expectedGL)}`);
17934
+ break;
17935
+ case "webgpu" /* WEBGPU */:
17936
+ this.log(` Expected WebGPU transform: ${this.formatVec3(expectedGPU)}`);
17937
+ break;
17938
+ }
17939
+ this.log(` Matrix translation: [${matrixTranslation.map((v) => v.toFixed(2)).join(", ")}]`);
17940
+ const posSum = Math.abs(quakePos[0]) + Math.abs(quakePos[1]) + Math.abs(quakePos[2]);
17941
+ const matSum = Math.abs(matrixTranslation[0]) + Math.abs(matrixTranslation[1]) + Math.abs(matrixTranslation[2]);
17942
+ if (posSum > 0 && matSum / posSum > 2) {
17943
+ this.log(` \u26A0\uFE0F WARNING: Matrix translation seems large relative to input - possible double-transform!`);
17944
+ }
17945
+ }
17946
+ formatVec3(v) {
17947
+ return `[${v[0].toFixed(2)}, ${v[1].toFixed(2)}, ${v[2].toFixed(2)}]`;
17948
+ }
17949
+ logMatrix(m) {
17950
+ for (let row = 0; row < 4; row++) {
17951
+ const values = [m[row], m[row + 4], m[row + 8], m[row + 12]];
17952
+ this.log(` [${values.map((v) => v.toFixed(4).padStart(8)).join(" ")}]`);
17953
+ }
17954
+ }
17955
+ log(message) {
17956
+ this.logs.push(message);
17957
+ if (this.options.verbose) {
17958
+ console.log(`[LogRenderer] ${message}`);
17959
+ }
17960
+ }
17961
+ // Stub implementations (with logging)
17962
+ async registerPic(name, data) {
17963
+ this.log(`registerPic("${name}", ${data.byteLength} bytes)`);
17964
+ return { width: 256, height: 256 };
17965
+ }
17966
+ registerTexture(name, texture) {
17967
+ this.log(`registerTexture("${name}", ${texture.width}x${texture.height})`);
17968
+ return { width: texture.width, height: texture.height };
17969
+ }
17970
+ begin2D() {
17971
+ this.log("begin2D()");
17972
+ }
17973
+ end2D() {
17974
+ this.log("end2D()");
17975
+ }
17976
+ drawPic(x, y, pic, color) {
17977
+ this.log(`drawPic(${x}, ${y})`);
17978
+ }
17979
+ drawString(x, y, text, color) {
17980
+ this.log(`drawString(${x}, ${y}, "${text}")`);
17981
+ }
17982
+ drawCenterString(y, text) {
17983
+ this.log(`drawCenterString(${y}, "${text}")`);
17984
+ }
17985
+ drawfillRect(x, y, width, height, color) {
17986
+ this.log(`drawfillRect(${x}, ${y}, ${width}x${height})`);
17987
+ }
17988
+ // All other IRenderer methods as no-ops
17989
+ setEntityHighlight(entityId, color) {
17990
+ }
17991
+ clearEntityHighlight(entityId) {
17992
+ }
17993
+ highlightSurface(faceIndex, color) {
17994
+ }
17995
+ removeSurfaceHighlight(faceIndex) {
17996
+ }
17997
+ setDebugMode(mode) {
17998
+ }
17999
+ setBrightness(value) {
18000
+ }
18001
+ setGamma(value) {
18002
+ }
18003
+ setFullbright(enabled) {
18004
+ }
18005
+ setAmbient(value) {
18006
+ }
18007
+ setLightStyle(index, pattern) {
18008
+ }
18009
+ setUnderwaterWarp(enabled) {
18010
+ }
18011
+ setBloom(enabled) {
18012
+ }
18013
+ setBloomIntensity(value) {
18014
+ }
18015
+ setLodBias(bias) {
18016
+ }
18017
+ renderInstanced(model, instances) {
18018
+ }
18019
+ getPerformanceReport() {
18020
+ return {
18021
+ frameTimeMs: 0,
18022
+ gpuTimeMs: 0,
18023
+ cpuFrameTimeMs: 0,
18024
+ drawCalls: 0,
18025
+ triangles: 0,
18026
+ vertices: 0,
18027
+ textureBinds: 0,
18028
+ shaderSwitches: 0,
18029
+ visibleSurfaces: 0,
18030
+ culledSurfaces: 0,
18031
+ visibleEntities: 0,
18032
+ culledEntities: 0,
18033
+ memoryUsageMB: { textures: 0, geometry: 0, total: 0 }
18034
+ };
18035
+ }
18036
+ getMemoryUsage() {
18037
+ return {
18038
+ texturesBytes: 0,
18039
+ geometryBytes: 0,
18040
+ shadersBytes: 0,
18041
+ buffersBytes: 0,
18042
+ totalBytes: 0
18043
+ };
18044
+ }
18045
+ dispose() {
18046
+ this.log("dispose()");
18047
+ }
18048
+ // Test utilities
18049
+ getLogs() {
18050
+ return this.logs;
18051
+ }
18052
+ resetLogs() {
18053
+ this.logs = [];
18054
+ }
18055
+ printLogs() {
18056
+ console.log(this.logs.join("\n"));
18057
+ }
18058
+ };
17541
18059
  var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
17542
18060
  ConnectionState2[ConnectionState2["Disconnected"] = 0] = "Disconnected";
17543
18061
  ConnectionState2[ConnectionState2["Connecting"] = 1] = "Connecting";
@@ -18012,6 +18530,7 @@ exports.Command = Command;
18012
18530
  exports.CommandRegistry = CommandRegistry;
18013
18531
  exports.ConfigStringRegistry = ConfigStringRegistry;
18014
18532
  exports.ConnectionState = ConnectionState;
18533
+ exports.CoordinateSystem = CoordinateSystem;
18015
18534
  exports.Cvar = Cvar;
18016
18535
  exports.CvarRegistry = CvarRegistry;
18017
18536
  exports.DemoAnalyzer = DemoAnalyzer;
@@ -18029,6 +18548,7 @@ exports.FileType = FileType;
18029
18548
  exports.FixedTimestepLoop = FixedTimestepLoop;
18030
18549
  exports.Framebuffer = Framebuffer;
18031
18550
  exports.IndexBuffer = IndexBuffer;
18551
+ exports.LoggingRenderer = LoggingRenderer;
18032
18552
  exports.LruCache = LruCache;
18033
18553
  exports.MD2_FRAGMENT_SHADER = MD2_FRAGMENT_SHADER;
18034
18554
  exports.MD2_VERTEX_SHADER = MD2_VERTEX_SHADER;
@@ -18047,6 +18567,7 @@ exports.Md3SurfaceMesh = Md3SurfaceMesh;
18047
18567
  exports.MessageWriter = MessageWriter;
18048
18568
  exports.MusicSystem = MusicSystem;
18049
18569
  exports.NetworkMessageParser = NetworkMessageParser;
18570
+ exports.NullRenderer = NullRenderer;
18050
18571
  exports.PARTICLE_FRAGMENT_SHADER = PARTICLE_FRAGMENT_SHADER;
18051
18572
  exports.PARTICLE_VERTEX_SHADER = PARTICLE_VERTEX_SHADER;
18052
18573
  exports.PROTOCOL_VERSION_RERELEASE = PROTOCOL_VERSION_RERELEASE;