From 02dff112424cd0f1e08bff3c92666e04daf6b33c Mon Sep 17 00:00:00 2001 From: peterino2 Date: Sun, 19 Oct 2025 23:35:28 -0700 Subject: [PATCH] samplegame is now compiling on windows in both debug and static build modes on 0.15 --- build.zig | 2 +- engine/assets/src/cook.zig | 9 +- engine/audio/src/sound_engine.zig | 2 +- engine/core/src/core.zig | 9 ++ engine/core/src/ecs.zig | 16 ++ engine/core/src/extern/externModule.zig | 2 +- engine/core/src/gameObject.zig | 2 +- engine/core/src/logging.zig | 7 +- engine/imgui/src/utils/consoleWindow.zig | 4 +- engine/main.zig | 2 +- engine/net/src/enet/EnetTransport.zig | 2 +- engine/net/src/net.zig | 4 +- engine/physics/build.zig | 7 +- engine/physics/src/physicsSystem.zig | 79 ++++------ engine/rend/src/camera/CameraComponent.zig | 6 +- engine/rend/src/meshes/gltfLoader.zig | 4 +- engine/rend/src/sgpu/renderer.zig | 2 +- engine/sys/src/systemProc.zig | 4 +- engine/ui/src/sgpu/textRenderer.zig | 5 +- extras/bsp/src/QuakeMap.zig | 26 ++-- extras/bsp/src/maploader.zig | 4 +- extras/bsp/src/zalgebra/generic_vector.zig | 142 ++++++++++++------ extras/bsp/src/zalgebra/main.zig | 60 +++++++- extras/bsp/src/zalgebra/mat3.zig | 66 ++++---- extras/bsp/src/zalgebra/mat4.zig | 121 +++++++-------- extras/bsp/src/zalgebra/quaternion.zig | 6 +- .../gameExtras/src/debuggers/EngineTool.zig | 2 +- .../src/debuggers/PhysicsObjectList.zig | 9 +- .../src/debuggers/RendererDebug.zig | 2 +- .../gameExtras/src/debuggers/fileBrowser.zig | 2 +- extras/gameExtras/src/gameplay/FpCamera.zig | 5 +- lib/p2/src/structures/sparse-set.zig | 4 - lib/zphysics/build.zig | 7 +- projects/content/meshes/fpsArms_magnum.fbx | 3 - projects/headless/main.zig | 2 +- projects/sampleGame/externGame/externGame.zig | 2 +- projects/sampleGame/main.zig | 2 +- projects/tools/newProjectMaker.zig | 56 +++---- projects/tools/toolbox.zig | 4 +- 39 files changed, 397 insertions(+), 296 deletions(-) delete mode 100644 projects/content/meshes/fpsArms_magnum.fbx diff --git a/build.zig b/build.zig index 2b29c5c..26771fc 100644 --- a/build.zig +++ b/build.zig @@ -245,7 +245,7 @@ const DynamicDepList: []const struct { dep: []const u8, artifact: []const u8 } = .{ .dep = "sdl3", .artifact = "SDL3" }, .{ .dep = "spng", .artifact = "spng_c" }, .{ .dep = "lua", .artifact = "luac" }, - // .{ .dep = "miniaudio", .artifact = "miniaudio_c" }, + .{ .dep = "miniaudio", .artifact = "miniaudio_c" }, .{ .dep = "zphysics", .artifact = "joltc" }, // .{ .dep = "enet", .artifact = "enet_c" }, .{ .dep = "ozz", .artifact = "ozz_cpp" }, diff --git a/engine/assets/src/cook.zig b/engine/assets/src/cook.zig index 21f3fc9..f70e3a1 100644 --- a/engine/assets/src/cook.zig +++ b/engine/assets/src/cook.zig @@ -117,8 +117,8 @@ pub fn getExtension(path: []const u8) ?[]const u8 { pub fn generateCookFile(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8) !void { if (getExtension(path)) |extension| { if (gCookRegistry.typesByExt.get(extension)) |assetType| { - var cookFilePath = std.ArrayList(u8).init(allocator); - defer cookFilePath.deinit(); + var cookFilePath = std.ArrayList(u8){}; + defer cookFilePath.deinit(allocator); const generateFunction = gCookRegistry.generates.get(assetType).?; var outPath: std.ArrayListUnmanaged(u8) = .{}; @@ -132,7 +132,10 @@ pub fn generateCookFile(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []c const file = try dir.createFile(outPath.items, .{}); defer file.close(); - try file.writeAll(cookFilePath.items); + var writeBuf: [4096]u8 = undefined; + + var writer = file.writer(&writeBuf); + try writer.interface.writeAll(cookFilePath.items); } } } diff --git a/engine/audio/src/sound_engine.zig b/engine/audio/src/sound_engine.zig index 8e7f044..cb1c544 100644 --- a/engine/audio/src/sound_engine.zig +++ b/engine/audio/src/sound_engine.zig @@ -8,7 +8,7 @@ const Name = core.Name; const AutoHashMapUnmanaged = std.AutoHashMapUnmanaged; const tracy = core.tracy; -const ma = @import("miniaudio"); +const ma = @import("miniaudio").c; pub fn sound_log(comptime fmt: []const u8, args: anytype) void { core.printInner(core.defaultHighlight, "[SOUND ]: " ++ fmt ++ "\n", args); diff --git a/engine/core/src/core.zig b/engine/core/src/core.zig index 8e827f4..6932ff7 100644 --- a/engine/core/src/core.zig +++ b/engine/core/src/core.zig @@ -105,6 +105,8 @@ pub const shell = p2.shell; pub const algorithm = @import("p2"); pub const math = @import("math.zig"); + +pub const Rayf = math.Rayf; pub const f32x4 = math.f32x4; // __m128_int pub const f32x8 = math.f32x8; // __m256_int pub const f32x16 = math.f32x16; // __m512_int @@ -163,6 +165,11 @@ pub const graphics_log = logging.graphics_log; pub const engine_err = logging.engine_err; pub const engine_errs = logging.engine_errs; +pub const printInner = logging.printInner; + +pub const errorHighlight = logging.errorHighlight; +pub const defaultHighlight = logging.defaultHighlight; + pub const packer = @import("packer"); pub const FileSystem = packer.PackerFS; @@ -398,6 +405,8 @@ pub fn exitNow() void { } pub fn signalShutdown() void { + // destroy all ecs entities first + ecs.destroyAllEntities(); gEngine.exit(); } diff --git a/engine/core/src/ecs.zig b/engine/core/src/ecs.zig index 70c97d8..1f89be9 100644 --- a/engine/core/src/ecs.zig +++ b/engine/core/src/ecs.zig @@ -115,6 +115,22 @@ pub fn createEntity() !Entity { return rv; } +pub fn destroyAllEntities() void { + const registry = getRegistry(); + var elist = std.ArrayList(Entity){}; + defer elist.deinit(registry.allocator); + + core.engine_log("sparse set length {d}", .{registry.baseSet.dense.items.len}); + for (registry.baseSet.dense.items) |dense| { + // TODO: shutdown allocator + elist.append(registry.allocator, Entity{ .handle = dense.sparseIndex }) catch {}; + } + + for (elist.items) |h| { + destroyEntity(h); + } +} + pub fn destroyEntity(e: Entity) void { core.engine_log("entity destroyed: {d}", .{e.handle.index}); const registry = getRegistry(); diff --git a/engine/core/src/extern/externModule.zig b/engine/core/src/extern/externModule.zig index 468da81..c095b7c 100644 --- a/engine/core/src/extern/externModule.zig +++ b/engine/core/src/extern/externModule.zig @@ -75,7 +75,7 @@ pub const LoadedModule = struct { } pub fn load(self: *@This(), allocator: std.mem.Allocator) !void { - core.engine_log("[ModuleLoader] loading module: ", .{}); + core.engine_log("[ModuleLoader] loading module: {s}", .{self.moduleName}); self.lastLoad = std.time.microTimestamp(); try self.stageModule(allocator); diff --git a/engine/core/src/gameObject.zig b/engine/core/src/gameObject.zig index 3923d5c..f3ffb92 100644 --- a/engine/core/src/gameObject.zig +++ b/engine/core/src/gameObject.zig @@ -51,8 +51,8 @@ pub const GameObject = struct { pub fn deinitECS(self: *@This(), handle: core.ObjectHandle) void { _ = handle; if (!self.destroyed) { - self.destroyed = true; self.objectRef.table.destroy(self.objectRef.ptr, core.get(GameObjectSystem).allocator); + self.destroyed = true; } } }; diff --git a/engine/core/src/logging.zig b/engine/core/src/logging.zig index 3c1b153..e53ba6a 100644 --- a/engine/core/src/logging.zig +++ b/engine/core/src/logging.zig @@ -17,7 +17,7 @@ pub const LogBuffer = struct { pub fn init(allocator: std.mem.Allocator) @This() { return .{ - .buffer = std.ArrayList(u8).init(allocator), + .buffer = std.ArrayList(u8){}, .allocator = allocator, }; } @@ -231,7 +231,7 @@ pub const LoggerSys = struct { try core.dispatchJob(L{ .loggerSys = self }); } else { - //self.flushWriteBuffer(); + try self.flushWriteBuffer(); } self.lock.unlock(); @@ -252,6 +252,7 @@ pub const LoggerSys = struct { } else { var writer = self.consoleFile.writer(self.writerBuffer); try writer.interface.writeAll(self.writeOutBuffer.items); + try writer.interface.flush(); } self.writeOutBuffer.clearRetainingCapacity(); self.lock.unlock(); @@ -266,6 +267,7 @@ pub const LoggerSys = struct { var writer = self.consoleFile.writer(self.writerBuffer); try writer.interface.writeAll(self.flushBuffer.items); try self.consoleFile.writeAll(""); + try writer.interface.flush(); } self.flushBuffer.clearRetainingCapacity(); self.lock.unlock(); @@ -327,6 +329,7 @@ pub const LoggerSys = struct { self.flushWriteBuffer() catch {}; self.allocator.free(self.logFilePath); self.logFile.close(); + self.allocator.free(self.writerBuffer); self.writeOutBuffer.deinit(self.allocator); self.flushBuffer.deinit(self.allocator); diff --git a/engine/imgui/src/utils/consoleWindow.zig b/engine/imgui/src/utils/consoleWindow.zig index cdd634c..8342109 100644 --- a/engine/imgui/src/utils/consoleWindow.zig +++ b/engine/imgui/src/utils/consoleWindow.zig @@ -1,4 +1,4 @@ -buffer: core.LogBuffer = undefined, +buffer: core.logging.LogBuffer = undefined, allocator: std.mem.Allocator = undefined, lastLength: usize = 0, consoleBuffer: [1024]u8 = std.mem.zeroes([1024]u8), @@ -10,7 +10,7 @@ pub fn init(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); self.* = .{ .allocator = allocator, - .buffer = core.LogBuffer.init(allocator), + .buffer = core.logging.LogBuffer.init(allocator), }; self.setup(); diff --git a/engine/main.zig b/engine/main.zig index 177c46d..d24d718 100644 --- a/engine/main.zig +++ b/engine/main.zig @@ -46,7 +46,7 @@ pub fn main() !void { core.engine_log("Working Dir set: {s}", .{try std.fs.cwd().realpath(".", &BUFFER)}); } - panickers.attachSegfaultHandler(); + // panickers.attachSegfaultHandler(); try realMain.main(); } diff --git a/engine/net/src/enet/EnetTransport.zig b/engine/net/src/enet/EnetTransport.zig index 5d94896..b82bc0a 100644 --- a/engine/net/src/enet/EnetTransport.zig +++ b/engine/net/src/enet/EnetTransport.zig @@ -262,7 +262,7 @@ pub fn parseConnectTarget(allocator: std.mem.Allocator, in: []const u8) !struct p = try std.fmt.parseInt(u16, ps, 10); } - return .{ .port = p, .address = try std.fmt.allocPrintZ(allocator, "{s}", .{base}) }; + return .{ .port = p, .address = try std.fmt.allocPrintSentinel(allocator, "{s}", .{base}, 0) }; } pub fn createLink(self: *@This(), session: *net.Session) !*net.Link { diff --git a/engine/net/src/net.zig b/engine/net/src/net.zig index 83cfdab..eb6b25e 100644 --- a/engine/net/src/net.zig +++ b/engine/net/src/net.zig @@ -49,12 +49,12 @@ pub const TransportError = error{ }; pub fn ip2String(allocator: std.mem.Allocator, ip: u32) ![:0]u8 { - return try std.fmt.allocPrintZ(allocator, "{d}.{d}.{d}.{d}", .{ + return try std.fmt.allocPrintSentinel(allocator, "{d}.{d}.{d}.{d}", .{ (ip >> 0) & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24) & 0xFF, - }); + }, 0); } pub const TransportRef = netEngine.TransportRef; diff --git a/engine/physics/build.zig b/engine/physics/build.zig index f0d3fcc..b1efd2b 100644 --- a/engine/physics/build.zig +++ b/engine/physics/build.zig @@ -15,7 +15,12 @@ pub fn build(b: *std.Build) void { const core_dep = b.dependency("core", .{ .target = target, .optimize = optimize, .static_build = static_build }); - const zphysics_dep = b.dependency("zphysics", .{ .target = target, .optimize = optimize, .static_build = static_build }); + const zphysics_dep = b.dependency("zphysics", .{ + .target = target, + .optimize = optimize, + .enable_cross_platform_determinism = false, + .static_build = static_build, + }); mod.addImport("core", core_dep.module("core")); mod.addImport("zphysics", zphysics_dep.module("root")); diff --git a/engine/physics/src/physicsSystem.zig b/engine/physics/src/physicsSystem.zig index d0a605a..d2dc85d 100644 --- a/engine/physics/src/physicsSystem.zig +++ b/engine/physics/src/physicsSystem.zig @@ -60,16 +60,9 @@ pub const IgnoreFixedBodiesFilter = extern struct { }; const BroadPhaseLayerInterface = extern struct { - usingnamespace zphysics.BroadPhaseLayerInterface.Methods(@This()); - __v: *const zphysics.BroadPhaseLayerInterface.VTable = &vtable, - + broad_phase_layer_interface: zphysics.BroadPhaseLayerInterface = .init(@This()), object_to_broad_phase: [ObjectLayers.len]zphysics.BroadPhaseLayer = undefined, - const vtable = zphysics.BroadPhaseLayerInterface.VTable{ - .getNumBroadPhaseLayers = _getNumBroadPhaseLayers, - .getBroadPhaseLayer = _getBroadPhaseLayer, - }; - fn init() BroadPhaseLayerInterface { var layer_interface: BroadPhaseLayerInterface = .{}; layer_interface.object_to_broad_phase[ObjectLayers.non_moving] = BroadPhaseLayers.non_moving; @@ -77,26 +70,23 @@ const BroadPhaseLayerInterface = extern struct { return layer_interface; } - fn _getNumBroadPhaseLayers(_: *const zphysics.BroadPhaseLayerInterface) callconv(.c) u32 { + pub fn getNumBroadPhaseLayers(_: *const zphysics.BroadPhaseLayerInterface) callconv(.c) u32 { return BroadPhaseLayers.len; } - fn _getBroadPhaseLayer( - interface_self: *const zphysics.BroadPhaseLayerInterface, + pub fn getBroadPhaseLayer( + broad_phase_layer_interface: *const zphysics.BroadPhaseLayerInterface, object_layer: zphysics.ObjectLayer, ) callconv(.c) zphysics.BroadPhaseLayer { - const self: *const BroadPhaseLayerInterface = @ptrCast(interface_self); + const self: *const BroadPhaseLayerInterface = @alignCast(@fieldParentPtr("broad_phase_layer_interface", broad_phase_layer_interface)); return self.object_to_broad_phase[object_layer]; } }; const ObjectVsBroadPhaseLayerFilter = extern struct { - usingnamespace zphysics.ObjectVsBroadPhaseLayerFilter.Methods(@This()); - __v: *const zphysics.ObjectVsBroadPhaseLayerFilter.VTable = &vtable, + object_vs_broad_phase_layer_filter: zphysics.ObjectVsBroadPhaseLayerFilter = .init(@This()), - const vtable = zphysics.ObjectVsBroadPhaseLayerFilter.VTable{ .shouldCollide = _shouldCollide }; - - fn _shouldCollide( + pub fn shouldCollide( _: *const zphysics.ObjectVsBroadPhaseLayerFilter, object_layer: zphysics.ObjectLayer, broad_phase_layer: zphysics.BroadPhaseLayer, @@ -110,12 +100,9 @@ const ObjectVsBroadPhaseLayerFilter = extern struct { }; const ObjectLayerPairFilter = extern struct { - usingnamespace zphysics.ObjectLayerPairFilter.Methods(@This()); - __v: *const zphysics.ObjectLayerPairFilter.VTable = &vtable, + object_layer_pair_filter: zphysics.ObjectLayerPairFilter = .init(@This()), - const vtable = zphysics.ObjectLayerPairFilter.VTable{ .shouldCollide = _shouldCollide }; - - fn _shouldCollide( + pub fn shouldCollide( _: *const zphysics.ObjectLayerPairFilter, a: zphysics.ObjectLayer, b: zphysics.ObjectLayer, @@ -304,40 +291,40 @@ pub const ShapeSettings = union(enum(u8)) { pub fn release(self: @This()) void { switch (self) { .convex => |x| { - x.release(); + x.asShapeSettings().release(); }, .box => |x| { - x.release(); + x.asShapeSettings().release(); }, .sphere => |x| { - x.release(); + x.asShapeSettings().release(); }, .triangle => |x| { - x.release(); + x.asShapeSettings().release(); }, .capsule => |x| { - x.release(); + x.asShapeSettings().release(); }, .taperedCapsule => |x| { - x.release(); + x.asShapeSettings().release(); }, .cylinder => |x| { - x.release(); + x.asShapeSettings().release(); }, .convexHull => |x| { - x.release(); + x.asShapeSettings().release(); }, .heightField => |x| { - x.release(); + x.asShapeSettings().release(); }, .mesh => |x| { - x.release(); + x.asShapeSettings().release(); }, .decorated => |x| { - x.release(); + x.asShapeSettings().release(); }, .compound => |x| { - x.release(); + x.asShapeSettings().release(); }, } } @@ -345,40 +332,40 @@ pub const ShapeSettings = union(enum(u8)) { pub fn createShape(self: @This()) !*zphysics.Shape { switch (self) { .convex => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .box => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .sphere => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .triangle => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .capsule => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .taperedCapsule => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .cylinder => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .convexHull => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .heightField => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .mesh => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .decorated => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, .compound => |x| { - return try x.createShape(); + return try x.asShapeSettings().createShape(); }, } } diff --git a/engine/rend/src/camera/CameraComponent.zig b/engine/rend/src/camera/CameraComponent.zig index 7e164e7..ae916f2 100644 --- a/engine/rend/src/camera/CameraComponent.zig +++ b/engine/rend/src/camera/CameraComponent.zig @@ -73,8 +73,8 @@ pub fn getNormalRayFromScreen( const width = platform.context().extent.x; const height = platform.context().extent.y; - const sx = core.clamp(s.x, 0, width); - const sy = core.clamp(s.y, 0, height); + const sx = core.math.clamp(s.x, 0, width); + const sy = core.math.clamp(s.y, 0, height); const vec = core.Vectorf{ .x = ((2.0 / width) * sx) - 1.0, @@ -97,7 +97,7 @@ pub fn getNormalRayFromScreen( } pub fn resolve(self: *@This()) void { - const scene = self.entity.fetch(core.Scene).?; + const scene = self.entity.fetch(core.Scene) orelse return; self.updateProjections(); diff --git a/engine/rend/src/meshes/gltfLoader.zig b/engine/rend/src/meshes/gltfLoader.zig index 75271f5..c0b61f8 100644 --- a/engine/rend/src/meshes/gltfLoader.zig +++ b/engine/rend/src/meshes/gltfLoader.zig @@ -37,7 +37,7 @@ pub fn loadIndexedMeshForPoolingGltf(allocator: std.mem.Allocator, meshName: cor defer allocator.free(binaryPath); core.engine_log("{s}", .{binaryPath}); binaryFile = try core.fs().loadFile(binaryPath); - binaryBytes = binaryFile.?.bytes; + binaryBytes = binaryFile.?.bytesNoEnd(); } defer if (binaryFile) |f| core.fs().unmap(f); @@ -231,7 +231,7 @@ pub fn loadIndexedMeshForPoolingGltf(allocator: std.mem.Allocator, meshName: cor .y = texcoords.?[uvIndex + 1], } else core.Vector2f{}; - const normal = if (normalIndex < normals.?.len) core.Vectorf{ + const normal = if (normals != null and normalIndex < normals.?.len) core.Vectorf{ .x = normals.?[i], .y = normals.?[i + 1], .z = normals.?[i + 2], diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index fa0c96e..49a56a8 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -329,7 +329,7 @@ pub const Renderer = struct { // .address_mode_v = .sampleraddressmodeRepeat, // .address_mode_w = .sampleraddressmodeRepeat, // - .mip_lod_bias = -1.0, + .mip_lod_bias = 0.0, .min_lod = 0, // Clamps the minimum of the computed LOD value. .max_lod = 10, // Clamps the maximum of the computed LOD value. .address_mode_u = .sampleraddressmodeRepeat, diff --git a/engine/sys/src/systemProc.zig b/engine/sys/src/systemProc.zig index 276a3ae..d653088 100644 --- a/engine/sys/src/systemProc.zig +++ b/engine/sys/src/systemProc.zig @@ -150,8 +150,8 @@ fn findRootDir(allocator: std.mem.Allocator) ![]u8 { var current_dir = std.fs.cwd(); // Start from current directory and walk up - var path_components = std.ArrayList([]const u8).init(allocator); - defer path_components.deinit(); + var path_components = std.ArrayList([]const u8){}; + defer path_components.deinit(allocator); // Try current directory first current_dir.access("content.txt", .{}) catch { diff --git a/engine/ui/src/sgpu/textRenderer.zig b/engine/ui/src/sgpu/textRenderer.zig index 0f54e35..d1b9442 100644 --- a/engine/ui/src/sgpu/textRenderer.zig +++ b/engine/ui/src/sgpu/textRenderer.zig @@ -376,10 +376,7 @@ pub const TextRenderer = struct { item.destroy(self.allocator); } - for (self.deadList.items) |item| { - item.destroy(self.allocator); - } - + self.deadList.deinit(self.allocator); self.geo.destroy(); self.linearBuffers.deinit(self.allocator); self.assignedBuffers.deinit(self.allocator); diff --git a/extras/bsp/src/QuakeMap.zig b/extras/bsp/src/QuakeMap.zig index 52e920b..1f9b949 100644 --- a/extras/bsp/src/QuakeMap.zig +++ b/extras/bsp/src/QuakeMap.zig @@ -11,6 +11,7 @@ const QuakeMap = @This(); worldspawn: Entity, entities: std.ArrayList(Entity), +allocator: std.mem.Allocator, // uniqueMaterials: std.StringHashMap(u32), // counts for the number // of times a material is used. @@ -28,7 +29,7 @@ pub fn deinit(self: *@This()) void { pub fn read(allocator: Allocator, data: []const u8, error_info: *ErrorInfo) !QuakeMap { var worldspawn: ?Entity = null; - var entities = std.ArrayList(Entity).init(allocator); + var entities = std.ArrayList(Entity){}; var iter = std.mem.tokenizeAny(u8, data, "\r\n"); error_info.line_number = 0; while (iter.next()) |line| { @@ -40,7 +41,7 @@ pub fn read(allocator: Allocator, data: []const u8, error_info: *ErrorInfo) !Qua if (std.mem.eql(u8, entity.classname, "worldspawn")) { worldspawn = entity; } else { - try entities.append(entity); + try entities.append(allocator, entity); } }, else => { @@ -53,6 +54,7 @@ pub fn read(allocator: Allocator, data: []const u8, error_info: *ErrorInfo) !Qua return .{ .worldspawn = worldspawn orelse return error.WorldSpawnNotFound, .entities = entities, + .allocator = allocator, }; } @@ -66,20 +68,23 @@ pub const Entity = struct { spawnflags: u32, properties: std.ArrayList(Property), solids: std.ArrayList(Solid), + allocator: std.mem.Allocator, pub fn deinit(self: *@This()) void { for (self.solids.items) |*solid| { solid.faces.deinit(); } - self.properties.deinit(); + self.solids.deinit(self.allocator); + self.properties.deinit(self.allocator); } pub fn init(allocator: Allocator) Entity { return .{ .classname = &.{}, .spawnflags = 0, - .properties = std.ArrayList(Property).init(allocator), - .solids = std.ArrayList(Solid).init(allocator), + .allocator = allocator, + .properties = std.ArrayList(Property){}, + .solids = std.ArrayList(Solid){}, }; } @@ -124,13 +129,14 @@ pub const Entity = struct { pub const Solid = struct { faces: std.ArrayList(Face), + allocator: std.mem.Allocator, fn init(allocator: Allocator) Solid { - return .{ .faces = std.ArrayList(Face).init(allocator) }; + return .{ .faces = std.ArrayList(Face){}, .allocator = allocator }; } fn computeVertices(self: *Solid) !void { - const allocator = self.faces.allocator; + const allocator = self.allocator; var buffer: [64]Vec3d = undefined; var vertices = std.ArrayListUnmanaged(Vec3d).initBuffer(buffer[0..32]); var clipped = std.ArrayListUnmanaged(Vec3d).initBuffer(buffer[32..64]); @@ -272,10 +278,10 @@ fn readEntity(allocator: Allocator, iter: *TokenIterator(u8, .any), error_info: } else if (std.mem.eql(u8, property.key, "spawnflags")) { entity.spawnflags = try std.fmt.parseInt(u32, property.value, 10); } else { - try entity.properties.append(property); + try entity.properties.append(entity.allocator, property); } }, - '{' => try entity.solids.append(try readSolid(allocator, iter, error_info)), + '{' => try entity.solids.append(entity.allocator, try readSolid(allocator, iter, error_info)), '}' => break, else => { std.debug.print("error in line: {s}\n", .{line}); @@ -301,7 +307,7 @@ fn readSolid(allocator: Allocator, iter: *TokenIterator(u8, .any), error_info: * error_info.line_number += 1; switch (line[0]) { '/' => continue, - '(' => try solid.faces.append(try readFace(line)), + '(' => try solid.faces.append(solid.allocator, try readFace(line)), '}' => break, else => { diff --git a/extras/bsp/src/maploader.zig b/extras/bsp/src/maploader.zig index 0b51c4c..44ea375 100644 --- a/extras/bsp/src/maploader.zig +++ b/extras/bsp/src/maploader.zig @@ -54,7 +54,7 @@ pub const TBMap = struct { "Texture", textureName, // TODO don't hardcode the root path - .{ .path = try std.fmt.bufPrint(&fmtBuf2, "textures/{s}.png", .{textureRef}) }, + .{ .path = try std.fmt.bufPrint(&fmtBuf2, "textures/{s}.png", .{textureRef}), .textureUseBlockySampler = false }, ), ); } @@ -92,7 +92,7 @@ pub const TBMap = struct { vertexCount, 12, ); - defer settings.release(); + defer settings.asShapeSettings().release(); // settings.setMaxConvexRadius(0.1); var nameBuffer: [256]u8 = undefined; diff --git a/extras/bsp/src/zalgebra/generic_vector.zig b/extras/bsp/src/zalgebra/generic_vector.zig index f8f0e0e..baabc70 100644 --- a/extras/bsp/src/zalgebra/generic_vector.zig +++ b/extras/bsp/src/zalgebra/generic_vector.zig @@ -43,8 +43,8 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { else => unreachable, }; - pub usingnamespace switch (dimensions) { - 2 => extern struct { + pub const DimensionImpl = switch (dimensions) { + 2 => struct { /// Construct new vector. pub inline fn new(vx: T, vy: T) Self { return .{ .data = [2]T{ vx, vy } }; @@ -76,7 +76,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return Self.new(vec4.x(), vec4.y()); } }, - 3 => extern struct { + 3 => struct { /// Construct new vector. pub inline fn new(vx: T, vy: T, vz: T) Self { return .{ .data = [3]T{ vx, vy, vz } }; @@ -92,12 +92,12 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { /// Shorthand for (0, 0, 1). pub fn forward() Self { - return new(0, 0, 1); + return Self.new(0, 0, 1); } /// Shorthand for (0, 0, -1). pub fn back() Self { - return forward().negate(); + return Self.forward().negate(); } /// Construct the cross product (as vector) from two vectors. @@ -113,7 +113,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { const result_x = (y1 * z2) - (z1 * y2); const result_y = (z1 * x2) - (x1 * z2); const result_z = (x1 * y2) - (y1 * x2); - return new(result_x, result_y, result_z); + return Self.new(result_x, result_y, result_z); } pub inline fn toVec2(self: Self) GenericVector(2, T) { @@ -132,7 +132,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return Self.new(vec4.x(), vec4.y(), vec4.z()); } }, - 4 => extern struct { + 4 => struct { /// Construct new vector. pub inline fn new(vx: T, vy: T, vz: T, vw: T) Self { return .{ .data = [4]T{ vx, vy, vz, vw } }; @@ -140,12 +140,12 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { /// Shorthand for (0, 0, 1, 0). pub fn forward() Self { - return new(0, 0, 1, 0); + return Self.new(0, 0, 1, 0); } /// Shorthand for (0, 0, -1, 0). pub fn back() Self { - return forward().negate(); + return Self.forward().negate(); } pub inline fn z(self: Self) T { @@ -183,6 +183,8 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { else => unreachable, }; + pub const new = DimensionImpl.new; + pub inline fn x(self: Self) T { return self.data[0]; } @@ -191,6 +193,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return self.data[1]; } + pub const z = DimensionImpl.z; + pub const w = DimensionImpl.w; + pub inline fn xMut(self: *Self) *T { return &self.data[0]; } @@ -199,6 +204,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return &self.data[1]; } + pub const zMut = DimensionImpl.zMut; + pub const wMut = DimensionImpl.wMut; + /// Set all components to the same given value. pub fn set(val: T) Self { const result: Data = @splat(val); @@ -245,6 +253,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return right().negate(); } + pub const forward = DimensionImpl.forward; + pub const back = DimensionImpl.back; + /// Negate the given vector. pub fn negate(self: Self) Self { return self.scale(-1); @@ -255,7 +266,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { pub fn cast(self: Self, comptime dest_type: type) GenericVector(dimensions, dest_type) { const dest_info = @typeInfo(dest_type); - if (dest_info != .Float and dest_info != .Int) { + if (dest_info != .float and dest_info != .int) { panic("Error, dest type should be integer or float.\n", .{}); } @@ -273,6 +284,14 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return .{ .data = result }; } + pub const fromVec2 = DimensionImpl.fromVec2; + pub const fromVec3 = DimensionImpl.fromVec3; + pub const fromVec4 = DimensionImpl.fromVec4; + + pub const toVec2 = DimensionImpl.toVec2; + pub const toVec3 = DimensionImpl.toVec3; + pub const toVec4 = DimensionImpl.toVec4; + /// Transform vector to array. pub fn toArray(self: Self) [dimensions]T { return self.data; @@ -290,12 +309,24 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return @sqrt(self.dot(self)); } + /// Return the length (magnitude) squared of given vector. + /// x^2 + y^2 + z^2 ... + pub fn lengthSq(self: Self) T { + return self.dot(self); + } + /// Return the distance between two points. /// √[(x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 ...] pub fn distance(first_vector: Self, second_vector: Self) T { return length(first_vector.sub(second_vector)); } + /// Return the distance squared between two points. + /// (x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 ... + pub fn distanceSq(first_vector: Self, second_vector: Self) T { + return lengthSq(first_vector.sub(second_vector)); + } + /// Construct new normalized vector from a given one. pub fn norm(self: Self) Self { const l = self.length(); @@ -329,6 +360,12 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return .{ .data = result }; } + /// Component wise division betwen two given vector. + pub fn div(first_vector: Self, second_vector: Self) Self { + const result = first_vector.data / second_vector.data; + return .{ .data = result }; + } + /// Construct vector from the max components in two vectors pub fn max(first_vector: Self, second_vector: Self) Self { const result = @max(first_vector.data, second_vector.data); @@ -362,16 +399,41 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type { return .{ .data = result }; } + pub const rotate = DimensionImpl.rotate; + pub const cross = DimensionImpl.cross; + + pub fn swizzle(self: Self, comptime comps: []const u8) SwizzleType(comps.len) { + if (comps.len == 1) { + return self.data[@intFromEnum(@field(Component, &.{comps[0]}))]; + } + + var result = GenericVector(comps.len, T).zero(); + inline for (comps, 0..) |comp, i| { + result.data[i] = self.data[@intFromEnum(@field(Component, &.{comp}))]; + } + return result; + } + + fn SwizzleType(comps_len: usize) type { + return switch (comps_len) { + 1 => T, + else => GenericVector(comps_len, T), + }; + } + + /// Deprecated; use `swizzle` instead pub inline fn swizzle2(self: Self, comptime vx: Component, comptime vy: Component) GenericVector(2, T) { - return GenericVector(2, T).new(self.data[@intFromEnum(vx)], self.data[@intFromEnum(vy)]); + return self.swizzle(@tagName(vx) ++ @tagName(vy)); } + /// Deprecated; use `swizzle` instead pub inline fn swizzle3(self: Self, comptime vx: Component, comptime vy: Component, comptime vz: Component) GenericVector(3, T) { - return GenericVector(3, T).new(self.data[@intFromEnum(vx)], self.data[@intFromEnum(vy)], self.data[@intFromEnum(vz)]); + return self.swizzle(@tagName(vx) ++ @tagName(vy) ++ @tagName(vz)); } + /// Deprecated; use `swizzle` instead pub inline fn swizzle4(self: Self, comptime vx: Component, comptime vy: Component, comptime vz: Component, comptime vw: Component) GenericVector(4, T) { - return GenericVector(4, T).new(self.data[@intFromEnum(vx)], self.data[@intFromEnum(vy)], self.data[@intFromEnum(vz)], self.data[@intFromEnum(vw)]); + return self.swizzle(@tagName(vx) ++ @tagName(vy) ++ @tagName(vz) ++ @tagName(vw)); } }; } @@ -564,7 +626,7 @@ test "zalgebra.Vectors.length" { } } -test "zalgebra.Vectors.distance" { +test "zalgebra.Vectors.distance/Sq" { // Vec2 { const a = Vec2.zero(); @@ -572,7 +634,9 @@ test "zalgebra.Vectors.distance" { const c = Vec2.new(0, 5); try expectEqual(a.distance(b), 1); + try expectEqual(a.distanceSq(b), 1); try expectEqual(a.distance(c), 5); + try expectEqual(a.distanceSq(c), 25); } // Vec3 @@ -582,7 +646,9 @@ test "zalgebra.Vectors.distance" { const c = Vec3.new(0, 5, 0); try expectEqual(a.distance(b), 1); + try expectEqual(a.distanceSq(b), 1); try expectEqual(a.distance(c), 5); + try expectEqual(a.distanceSq(c), 25); } // Vec4 @@ -592,7 +658,9 @@ test "zalgebra.Vectors.distance" { const c = Vec4.new(0, 5, 0, 0); try expectEqual(a.distance(b), 1); + try expectEqual(a.distanceSq(b), 1); try expectEqual(a.distance(c), 5); + try expectEqual(a.distanceSq(c), 25); } } @@ -886,50 +954,24 @@ test "vector conversions 4 -> 2" { // Just touching every component // not testing every combination cause it's too many -test "swizzle2" { +test "swizzle" { + const v1 = Vec2.new(1, 2); + const x = v1.swizzle("x"); + try expectEqual(1, x); + const v2 = Vec2.new(1, 2); - const yx = v2.swizzle2(.y, .x); + const yx = v2.swizzle("yx"); try expectEqual(Vec2.new(2, 1), yx); const v3 = Vec3.new(1, 2, 3); - const zy = v3.swizzle2(.z, .y); - const xx = v3.swizzle2(.x, .x); + const zy = v3.swizzle("zy"); + const xx = v3.swizzle("xx"); try expectEqual(Vec2.new(3, 2), zy); try expectEqual(Vec2.new(1, 1), xx); const v4 = Vec4.new(1, 2, 3, 4); - const wz = v4.swizzle2(.w, .z); - const xy = v4.swizzle2(.x, .y); + const wz = v4.swizzle("wz"); + const xy = v4.swizzle("xy"); try expectEqual(Vec2.new(4, 3), wz); try expectEqual(Vec2.new(1, 2), xy); } - -test "swizzle3" { - const v2 = Vec2.new(1, 2); - const yxy = v2.swizzle3(.y, .x, .y); - try expectEqual(Vec3.new(2, 1, 2), yxy); - - const v3 = Vec3.new(1, 2, 3); - const zyx = v3.swizzle3(.z, .y, .x); - try expectEqual(Vec3.new(3, 2, 1), zyx); - - const v4 = Vec4.new(1, 2, 3, 4); - const wzy = v4.swizzle3(.w, .z, .y); - const xxx = v4.swizzle3(.x, .x, .x); - try expectEqual(Vec3.new(4, 3, 2), wzy); - try expectEqual(Vec3.new(1, 1, 1), xxx); -} - -test "swizzle4" { - const v2 = Vec2.new(1, 2); - const yxyx = v2.swizzle4(.y, .x, .y, .x); - try expectEqual(Vec4.new(2, 1, 2, 1), yxyx); - - const v3 = Vec3.new(1, 2, 3); - const zyxz = v3.swizzle4(.z, .y, .x, .z); - try expectEqual(Vec4.new(3, 2, 1, 3), zyxz); - - const v4 = Vec4.new(1, 2, 3, 4); - const wzyx = v4.swizzle4(.w, .z, .y, .x); - try expectEqual(Vec4.new(4, 3, 2, 1), wzyx); -} diff --git a/extras/bsp/src/zalgebra/main.zig b/extras/bsp/src/zalgebra/main.zig index a779336..00765e4 100644 --- a/extras/bsp/src/zalgebra/main.zig +++ b/extras/bsp/src/zalgebra/main.zig @@ -4,16 +4,55 @@ const std = @import("std"); const expectEqual = std.testing.expectEqual; const math = std.math; -pub usingnamespace @import("generic_vector.zig"); -pub usingnamespace @import("mat3.zig"); -pub usingnamespace @import("mat4.zig"); -pub usingnamespace @import("quaternion.zig"); +const generic_vector = @import("generic_vector.zig"); + +pub const Vec2 = generic_vector.Vec2; +pub const Vec2_f64 = generic_vector.Vec2_f64; +pub const Vec2_i32 = generic_vector.Vec2_i32; +pub const Vec2_usize = generic_vector.Vec2_usize; + +pub const Vec3 = generic_vector.Vec3; +pub const Vec3_f64 = generic_vector.Vec3_f64; +pub const Vec3_i32 = generic_vector.Vec3_i32; +pub const Vec3_usize = generic_vector.Vec3_usize; + +pub const Vec4 = generic_vector.Vec4; +pub const Vec4_f64 = generic_vector.Vec4_f64; +pub const Vec4_i32 = generic_vector.Vec4_i32; +pub const Vec4_usize = generic_vector.Vec4_usize; + +pub const GenericVector = generic_vector.GenericVector; + +const mat3 = @import("mat3.zig"); + +pub const Mat3 = mat3.Mat3; +pub const Mat3_f64 = mat3.Mat3_f64; + +pub const Mat3x3 = mat3.Mat3x3; + +const mat4 = @import("mat4.zig"); + +pub const Mat4 = mat4.Mat4; +pub const Mat4_f64 = mat4.Mat4_f64; +pub const perspective = mat4.perspective; +pub const perspectiveReversedZ = mat4.perspectiveReversedZ; +pub const orthographic = mat4.orthographic; +pub const lookAt = mat4.lookAt; + +pub const Mat4x4 = mat4.Mat4x4; + +const quat = @import("quaternion.zig"); + +pub const Quat = quat.Quat; +pub const Quat_f64 = quat.Quaternion; + +pub const Quaternion = quat.Quaternion; /// Convert degrees to radians. pub fn toRadians(degrees: anytype) @TypeOf(degrees) { const T = @TypeOf(degrees); - if (@typeInfo(T) != .Float) { + if (@typeInfo(T) != .float) { @compileError("Radians not implemented for " ++ @typeName(T)); } @@ -24,7 +63,7 @@ pub fn toRadians(degrees: anytype) @TypeOf(degrees) { pub fn toDegrees(radians: anytype) @TypeOf(radians) { const T = @TypeOf(radians); - if (@typeInfo(T) != .Float) { + if (@typeInfo(T) != .float) { @compileError("Radians not implemented for " ++ @typeName(T)); } @@ -34,7 +73,7 @@ pub fn toDegrees(radians: anytype) @TypeOf(radians) { /// Linear interpolation between two floats. /// `t` is used to interpolate between `from` and `to`. pub fn lerp(comptime T: type, from: T, to: T, t: T) T { - if (@typeInfo(T) != .Float) { + if (@typeInfo(T) != .float) { @compileError("Lerp not implemented for " ++ @typeName(T)); } @@ -70,3 +109,10 @@ test "zalgebra.lerp" { try expectEqual(lerp(f32, from, to, 0.5), 5); try expectEqual(lerp(f32, from, to, 1), 10); } + +test { + _ = generic_vector; + _ = mat3; + _ = mat4; + _ = quat; +} diff --git a/extras/bsp/src/zalgebra/mat3.zig b/extras/bsp/src/zalgebra/mat3.zig index 224eb75..01df588 100644 --- a/extras/bsp/src/zalgebra/mat3.zig +++ b/extras/bsp/src/zalgebra/mat3.zig @@ -19,10 +19,6 @@ pub const Mat3_f64 = Mat3x3(f64); /// A column-major 3x3 matrix /// Note: Column-major means accessing data like m.data[COLUMN][ROW]. pub fn Mat3x3(comptime T: type) type { - if (@typeInfo(T) != .Float) { - @compileError("Mat3x3 not implemented for " ++ @typeName(T)); - } - const Vector3 = GenericVector(3, T); return extern struct { @@ -85,9 +81,8 @@ pub fn Mat3x3(comptime T: type) type { return result; } - /// Return a pointer to the inner data of the matrix. - pub fn getData(self: *const Self) *const T { - return @ptrCast(&self.data); + pub fn getSlice(self: *const Self) *const [3][3]T { + return self.data[0..3]; } /// Return true if two matrices are equals. @@ -105,6 +100,10 @@ pub fn Mat3x3(comptime T: type) type { /// Construct a 3x3 matrix from given axis and angle (in degrees). pub fn fromRotation(angle_in_degrees: T, axis: Vector3) Self { + if (@typeInfo(T) != .float) { + @compileError("Mat3x3.fromRotation() not implemented for " ++ @typeName(T)); + } + var result = Self.identity(); const norm_axis = axis.norm(); @@ -133,6 +132,10 @@ pub fn Mat3x3(comptime T: type) type { } pub fn rotate(self: Self, angle_in_degrees: T, axis: Vector3) Self { + if (@typeInfo(T) != .float) { + @compileError("Mat3x3.rotate() not implemented for " ++ @typeName(T)); + } + const rotation_mat = Self.fromRotation(angle_in_degrees, axis); return Self.mul(self, rotation_mat); } @@ -140,6 +143,10 @@ pub fn Mat3x3(comptime T: type) type { /// Construct a rotation matrix from euler angles (X * Y * Z). /// Order matters because matrix multiplication are NOT commutative. pub fn fromEulerAngles(euler_angle: Vector3) Self { + if (@typeInfo(T) != .float) { + @compileError("Mat3x3.fromEulerAngles() not implemented for " ++ @typeName(T)); + } + const x = Self.fromRotation(euler_angle.x(), Vector3.right()); const y = Self.fromRotation(euler_angle.y(), Vector3.up()); const z = Self.fromRotation(euler_angle.z(), Vector3.forward()); @@ -149,6 +156,10 @@ pub fn Mat3x3(comptime T: type) type { /// Ortho normalize given matrix. pub fn orthoNormalize(self: Self) Self { + if (@typeInfo(T) != .float) { + @compileError("Mat3x3.orthoNormalize() not implemented for " ++ @typeName(T)); + } + const column_1 = Vector3.new(self.data[0][0], self.data[0][1], self.data[0][2]).norm(); const column_2 = Vector3.new(self.data[1][0], self.data[1][1], self.data[1][2]).norm(); const column_3 = Vector3.new(self.data[2][0], self.data[2][1], self.data[2][2]).norm(); @@ -174,6 +185,10 @@ pub fn Mat3x3(comptime T: type) type { /// Taken from Mike Day at Insomniac Games (and `glm` as the same function). /// For more details: https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/07/euler-angles1.pdf pub fn extractEulerAngles(self: Self) Vector3 { + if (@typeInfo(T) != .float) { + @compileError("Mat3x3.extractEulerAngles() not implemented for " ++ @typeName(T)); + } + const m = self.orthoNormalize(); const theta_x = math.atan2(m.data[1][2], m.data[2][2]); @@ -259,27 +274,22 @@ pub fn Mat3x3(comptime T: type) type { return inv_mat; } - /// Print the 3x3 to stderr. - pub fn debugPrint(self: Self) void { - const print = std.debug.print; + pub fn format( + self: Self, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; - print("({d}, {d}, {d})\n", .{ - self.data[0][0], - self.data[1][0], - self.data[2][0], - }); - - print("({d}, {d}, {d})\n", .{ - self.data[0][1], - self.data[1][1], - self.data[2][1], - }); - - print("({d}, {d}, {d})\n", .{ - self.data[0][2], - self.data[1][2], - self.data[2][2], - }); + for (0..3) |i| { + try writer.print("({d:.2}, {d:.2}, {d:.2})\n", .{ + self.data[0][i], + self.data[1][i], + self.data[2][i], + }); + } } /// Cast a type to another type. @@ -287,7 +297,7 @@ pub fn Mat3x3(comptime T: type) type { pub fn cast(self: Self, comptime dest_type: type) Mat3x3(dest_type) { const dest_info = @typeInfo(dest_type); - if (dest_info != .Float) { + if (dest_info != .float) { std.debug.panic("Error, dest type should be float.\n", .{}); } diff --git a/extras/bsp/src/zalgebra/mat4.zig b/extras/bsp/src/zalgebra/mat4.zig index 2dad4bd..1e122eb 100644 --- a/extras/bsp/src/zalgebra/mat4.zig +++ b/extras/bsp/src/zalgebra/mat4.zig @@ -23,7 +23,7 @@ pub const lookAt = Mat4.lookAt; /// A column-major 4x4 matrix /// Note: Column-major means accessing data like m.data[COLUMN][ROW]. pub fn Mat4x4(comptime T: type) type { - if (@typeInfo(T) != .Float) { + if (@typeInfo(T) != .float) { @compileError("Mat4x4 not implemented for " ++ @typeName(T)); } @@ -92,9 +92,8 @@ pub fn Mat4x4(comptime T: type) type { return result; } - /// Return a pointer to the inner data of the matrix. - pub fn getData(self: *const Self) *const T { - return @ptrCast(&self.data); + pub fn getSlice(self: *const Self) *const [4][4]T { + return self.data[0..4]; } /// Return true if two matrices are equals. @@ -114,12 +113,14 @@ pub fn Mat4x4(comptime T: type) type { /// Construct 4x4 translation matrix by multiplying identity matrix and /// given translation vector. pub fn fromTranslate(axis: Vector3) Self { - var result = Self.identity(); - result.data[3][0] = axis.data[0]; - result.data[3][1] = axis.data[1]; - result.data[3][2] = axis.data[2]; - - return result; + return .{ + .data = .{ + .{ 1, 0, 0, 0 }, + .{ 0, 1, 0, 0 }, + .{ 0, 0, 1, 0 }, + .{ axis.x(), axis.y(), axis.z(), 1 }, + }, + }; } /// Make a translation between the given matrix and the given axis. @@ -217,13 +218,14 @@ pub fn Mat4x4(comptime T: type) type { } pub fn fromScale(axis: Vector3) Self { - var result = Self.identity(); - - result.data[0][0] = axis.x(); - result.data[1][1] = axis.y(); - result.data[2][2] = axis.z(); - - return result; + return .{ + .data = .{ + .{ axis.x(), 0, 0, 0 }, + .{ 0, axis.y(), 0, 0 }, + .{ 0, 0, axis.z(), 0 }, + .{ 0, 0, 0, 1 }, + }, + }; } pub fn scale(self: Self, axis: Vector3) Self { @@ -243,18 +245,17 @@ pub fn Mat4x4(comptime T: type) type { /// Note: Field of view is given in degrees. /// Also for more details https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml. pub fn perspective(fovy_in_degrees: T, aspect_ratio: T, z_near: T, z_far: T) Self { - var result = Self.identity(); - const f = 1 / @tan(root.toRadians(fovy_in_degrees) * 0.5); + const nf = 1 / (z_near - z_far); - result.data[0][0] = f / aspect_ratio; - result.data[1][1] = f; - result.data[2][2] = (z_near + z_far) / (z_near - z_far); - result.data[2][3] = -1; - result.data[3][2] = 2 * z_far * z_near / (z_near - z_far); - result.data[3][3] = 0; - - return result; + return .{ + .data = .{ + .{ f / aspect_ratio, 0, 0, 0 }, + .{ 0, f, 0, 0 }, + .{ 0, 0, (z_near + z_far) * nf, -1 }, + .{ 0, 0, 2 * z_near * z_far * nf, 0 }, + }, + }; } /// Construct a perspective 4x4 matrix with reverse Z and infinite far plane. @@ -262,18 +263,16 @@ pub fn Mat4x4(comptime T: type) type { /// Also for more details https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml. /// For Reversed-Z details https://nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl/ pub fn perspectiveReversedZ(fovy_in_degrees: T, aspect_ratio: T, z_near: T) Self { - var result = Self.identity(); - const f = 1 / @tan(root.toRadians(fovy_in_degrees) * 0.5); - result.data[0][0] = f / aspect_ratio; - result.data[1][1] = f; - result.data[2][2] = 0; - result.data[2][3] = -1; - result.data[3][2] = z_near; - result.data[3][3] = 0; - - return result; + return .{ + .data = .{ + .{ f / aspect_ratio, 0, 0, 0 }, + .{ 0, f, 0, 0 }, + .{ 0, 0, 0, -1 }, + .{ 0, 0, z_near, 0 }, + }, + }; } /// Construct an orthographic 4x4 matrix. @@ -440,37 +439,23 @@ pub fn Mat4x4(comptime T: type) type { }; } - /// Print the 4x4 to stderr. - pub fn debugPrint(self: Self) void { - const print = std.debug.print; + pub fn format( + self: Self, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; - print("({d}, {d}, {d}, {d})\n", .{ - self.data[0][0], - self.data[1][0], - self.data[2][0], - self.data[3][0], - }); - - print("({d}, {d}, {d}, {d})\n", .{ - self.data[0][1], - self.data[1][1], - self.data[2][1], - self.data[3][1], - }); - - print("({d}, {d}, {d}, {d})\n", .{ - self.data[0][2], - self.data[1][2], - self.data[2][2], - self.data[3][2], - }); - - print("({d}, {d}, {d}, {d})\n", .{ - self.data[0][3], - self.data[1][3], - self.data[2][3], - self.data[3][3], - }); + for (0..4) |i| { + try writer.print("({d:.2}, {d:.2}, {d:.2}, {d:.2})\n", .{ + self.data[0][i], + self.data[1][i], + self.data[2][i], + self.data[3][i], + }); + } } /// Cast a type to another type. @@ -478,7 +463,7 @@ pub fn Mat4x4(comptime T: type) type { pub fn cast(self: Self, comptime dest_type: type) Mat4x4(dest_type) { const dest_info = @typeInfo(dest_type); - if (dest_info != .Float) { + if (dest_info != .float) { std.debug.panic("Error, dest type should be float.\n", .{}); } diff --git a/extras/bsp/src/zalgebra/quaternion.zig b/extras/bsp/src/zalgebra/quaternion.zig index 83c5838..9ba5d9f 100644 --- a/extras/bsp/src/zalgebra/quaternion.zig +++ b/extras/bsp/src/zalgebra/quaternion.zig @@ -24,7 +24,7 @@ pub const Quat_f64 = Quaternion(f64); /// A Quaternion for 3D rotations. pub fn Quaternion(comptime T: type) type { - if (@typeInfo(T) != .Float) { + if (@typeInfo(T) != .float) { @compileError("Quaternion not implemented for " ++ @typeName(T)); } @@ -145,7 +145,7 @@ pub fn Quaternion(comptime T: type) type { } /// Convert given quaternion to rotation 3x3 matrix. - fn toMat3(self: Self) Mat3x3(T) { + pub fn toMat3(self: Self) Mat3x3(T) { var result: Mat3x3(T) = undefined; const normalized = self.norm(); @@ -378,7 +378,7 @@ pub fn Quaternion(comptime T: type) type { pub fn cast(self: Self, comptime dest_type: type) Quaternion(dest_type) { const dest_info = @typeInfo(dest_type); - if (dest_info != .Float) { + if (dest_info != .float) { std.debug.panic("Error, dest type should be float.\n", .{}); } diff --git a/extras/gameExtras/src/debuggers/EngineTool.zig b/extras/gameExtras/src/debuggers/EngineTool.zig index b6303eb..e169c8d 100644 --- a/extras/gameExtras/src/debuggers/EngineTool.zig +++ b/extras/gameExtras/src/debuggers/EngineTool.zig @@ -60,7 +60,7 @@ pub fn windowOpen(entry: *igutils.MenuEntry, dt: f64) void { ig.textSlice(slice); } - if (core.getEngineObject(core.EcsRegistry)) |ecsReg| { + if (core.getEngineObject(core.ecs.EcsRegistry)) |ecsReg| { ig.separator(); for (ecsReg.containerNames.items, 0..) |*name, i| { diff --git a/extras/gameExtras/src/debuggers/PhysicsObjectList.zig b/extras/gameExtras/src/debuggers/PhysicsObjectList.zig index 1a33b73..a75b6db 100644 --- a/extras/gameExtras/src/debuggers/PhysicsObjectList.zig +++ b/extras/gameExtras/src/debuggers/PhysicsObjectList.zig @@ -1,7 +1,6 @@ allocator: std.mem.Allocator, lastUpdateFrame: u64 = 0, -arena: std.heap.ArenaAllocator, bodyIds: std.ArrayList(physics.BodyId), pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "extras.PhysicsObjectList"); @@ -11,8 +10,7 @@ pub fn create(allocator: std.mem.Allocator) !*@This() { self.* = .{ .allocator = allocator, - .arena = std.heap.ArenaAllocator.init(allocator), - .bodyIds = std.ArrayList(physics.BodyId).init(allocator), + .bodyIds = std.ArrayList(physics.BodyId){}, }; if (core.getEngineObject(igutils.TopBar)) |topbar| { @@ -27,7 +25,7 @@ pub fn windowOpen(entry: *igutils.MenuEntry, dt: f64) void { const self: *@This() = @ptrCast(@alignCast(entry.ctx)); self.bodyIds.clearRetainingCapacity(); - physics.context().system.getBodyIds(&self.bodyIds) catch return; + physics.context().system.getBodyIds(self.allocator, &self.bodyIds) catch return; if (ig.begin("Physics Objects", &entry.open, .{})) { ig.textf("total Physics Objects count: {d}", .{self.bodyIds.items.len}); @@ -39,8 +37,7 @@ pub fn windowOpen(entry: *igutils.MenuEntry, dt: f64) void { } pub fn destroy(self: *@This()) void { - self.arena.deinit(); - self.bodyIds.deinit(); + self.bodyIds.deinit(self.allocator); self.allocator.destroy(self); } diff --git a/extras/gameExtras/src/debuggers/RendererDebug.zig b/extras/gameExtras/src/debuggers/RendererDebug.zig index b05c552..b655b3a 100644 --- a/extras/gameExtras/src/debuggers/RendererDebug.zig +++ b/extras/gameExtras/src/debuggers/RendererDebug.zig @@ -28,7 +28,7 @@ pub fn setup(self: *@This()) void { pub fn windowOpen(entry: *igu.MenuEntry, dt: f64) void { const self: *@This() = @ptrCast(@alignCast(entry.ctx)); - core.rollingAverage(&self.dtAverage, dt, 50); + core.math.rollingAverage(&self.dtAverage, dt, 50); if (ig.begin("renderer debug", null, .{})) { if (self.dtAverage > 0.000001) { diff --git a/extras/gameExtras/src/debuggers/fileBrowser.zig b/extras/gameExtras/src/debuggers/fileBrowser.zig index 810ffa1..295bf14 100644 --- a/extras/gameExtras/src/debuggers/fileBrowser.zig +++ b/extras/gameExtras/src/debuggers/fileBrowser.zig @@ -22,7 +22,7 @@ pub fn Browser(comptime T: type) type { const self = try allocator.create(@This()); self.* = .{ - .browserName = try std.fmt.allocPrintZ(allocator, "Browser", .{}), + .browserName = try std.fmt.allocPrintSentinel(allocator, "Browser", .{}, 0), .allocator = allocator, }; diff --git a/extras/gameExtras/src/gameplay/FpCamera.zig b/extras/gameExtras/src/gameplay/FpCamera.zig index 3126627..9710e1c 100644 --- a/extras/gameExtras/src/gameplay/FpCamera.zig +++ b/extras/gameExtras/src/gameplay/FpCamera.zig @@ -57,7 +57,10 @@ pub fn setPosition(self: *@This(), position: core.Vectorf) void { } pub fn getPosition(self: *@This()) core.Vectorf { - return self.camera.fetch(core.Scene).?.getPosition(); + if (self.camera.fetch(core.Scene)) |scene| { + return scene.getPosition(); + } + return .{}; } // movement value can be sourced from a mouse binding that has enableMouseRelative() on diff --git a/lib/p2/src/structures/sparse-set.zig b/lib/p2/src/structures/sparse-set.zig index 117a16f..0fba59e 100644 --- a/lib/p2/src/structures/sparse-set.zig +++ b/lib/p2/src/structures/sparse-set.zig @@ -555,10 +555,6 @@ pub fn SparseSetAdvanced(comptime T: type, comptime SparseSize: u32) type { self.dense.deinit(self.allocator); } - pub fn denseList(self: @This()) []const T { - return self.dense.items; - } - pub const EcsContainerInterfaceVTable = EcsContainerInterface.Implement(@This()); pub fn handleExists(self: @This(), handle: SetHandle) bool { diff --git a/lib/zphysics/build.zig b/lib/zphysics/build.zig index 21c3389..53d9082 100644 --- a/lib/zphysics/build.zig +++ b/lib/zphysics/build.zig @@ -48,8 +48,7 @@ pub fn build(b: *std.Build) void { ) orelse true, }; - const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse false; - _ = static_build; + const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse true; const user_extensions = b.option( []const std.Build.LazyPath, @@ -74,14 +73,14 @@ pub fn build(b: *std.Build) void { const joltc = b.addLibrary(.{ .name = "joltc", - .linkage = if (options.shared) .dynamic else .static, + .linkage = if (!static_build) .dynamic else .static, .root_module = b.createModule(.{ .target = target, .optimize = optimize, }), }); - if (options.shared and target.result.os.tag == .windows) + if (!static_build and target.result.os.tag == .windows) joltc.root_module.addCMacro("JPC_API", "extern __declspec(dllexport)"); b.installArtifact(joltc); diff --git a/projects/content/meshes/fpsArms_magnum.fbx b/projects/content/meshes/fpsArms_magnum.fbx deleted file mode 100644 index f45c995..0000000 --- a/projects/content/meshes/fpsArms_magnum.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:15021d3c62174c709aaa3b7e5340cd584d0a7089702eeb740391a5ba0f69cd2e -size 2322940 diff --git a/projects/headless/main.zig b/projects/headless/main.zig index 9c74ea2..5b33474 100644 --- a/projects/headless/main.zig +++ b/projects/headless/main.zig @@ -111,7 +111,7 @@ pub fn testThing(self: *@This()) !void { core.setBarrierCount(workerCount); for (0..workerCount) |i| { - const name = try std.fmt.allocPrintZ(std.heap.c_allocator, "MultiJob{d}", .{i}); + const name = try std.fmt.allocPrintSentinel(std.heap.c_allocator, "MultiJob{d}", .{i}, 0); try core.dispatchJob(MultiJob{ .threadName = name, .threadId = @intCast(i) }); } } diff --git a/projects/sampleGame/externGame/externGame.zig b/projects/sampleGame/externGame/externGame.zig index 4e180ab..dbf73a2 100644 --- a/projects/sampleGame/externGame/externGame.zig +++ b/projects/sampleGame/externGame/externGame.zig @@ -152,7 +152,7 @@ pub const ExternGameObject = struct { } // change this into a parallel for - for (0..300) |i| { + for (0..1) |i| { _ = try core.get(core.GameObjectSystem).spawnObject(BoxObject, "Box", .{ .posRot = .{ .position = .{ .x = core.itof32((i % 10)) * 2, .y = 15.0, .z = core.itof32(@divFloor(i, 10) * 2) }, diff --git a/projects/sampleGame/main.zig b/projects/sampleGame/main.zig index b18e069..5a8d56f 100644 --- a/projects/sampleGame/main.zig +++ b/projects/sampleGame/main.zig @@ -494,7 +494,7 @@ pub fn deinit(self: *@This()) void { pub fn main() anyerror!void { var spec = try backlog.getSpec("sampleGame"); - // try spec.put("useGPA", .{ .boolean = false }); + try spec.put("useGPA", .{ .boolean = true }); _ = backlog.startEngine(&NeonObjectTable, &spec); // try backlog.initializeAndRunStandardProgram(@This(), .{ diff --git a/projects/tools/newProjectMaker.zig b/projects/tools/newProjectMaker.zig index a2889c8..bdde544 100644 --- a/projects/tools/newProjectMaker.zig +++ b/projects/tools/newProjectMaker.zig @@ -225,7 +225,7 @@ fn loadFileAllocFromCwd(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []c const filesize = (try file.stat()).size + 1; // add null byte const buffer: []u8 = try allocator.alloc(u8, filesize); errdefer allocator.free(buffer); - try file.reader().readNoEof(buffer[0 .. buffer.len - 1]); + _ = try file.read(buffer[0 .. buffer.len - 1]); buffer[buffer.len - 1] = 0; return buffer; } @@ -295,11 +295,8 @@ fn writeBuildZigFiles(self: *@This()) !void { fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void { const out_path = "build.zig"; - var content = std.ArrayList(u8).init(self.allocator); - defer content.deinit(); - - var writer = content.writer(); - + var content = std.ArrayList(u8){}; + defer content.deinit(self.allocator); const template = \\ const std = @import("std"); \\ const Backlog = @import("Backlog"); @@ -315,7 +312,7 @@ fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void { \\ }}); ; - try writer.print(template, .{self.engineRelative.?}); + try content.print(self.allocator, template, .{self.engineRelative.?}); const template2 = \\ const program = blbuild.program(.{{ @@ -330,9 +327,9 @@ fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void { \\ }} ; - try writer.print(template2, .{self.targetName.?}); + try content.print(self.allocator, template2, .{self.targetName.?}); - try writer.writeByte(0); + try content.append(self.allocator, 0); try self.writeZigFile(workingDir, out_path, content.items); } @@ -348,13 +345,12 @@ const entries: []const struct { name: []const u8, path: []const u8 } = &.{ }; fn writeBuildZigZon(self: *@This(), workingDir: *std.fs.Dir) !void { - var content = std.ArrayList(u8).init(self.allocator); - defer content.deinit(); + var content = std.ArrayList(u8){}; + defer content.deinit(self.allocator); - var writer = content.writer(); - try writer.print(".{{\n", .{}); + try content.print(self.allocator, ".{{\n", .{}); - try writer.print( + try content.print(self.allocator, \\ .name = .{s}, \\ .version = "0.0.0", \\ .dependencies = .{{ @@ -362,34 +358,35 @@ fn writeBuildZigZon(self: *@This(), workingDir: *std.fs.Dir) !void { , .{ std.fs.path.basename(self.targetDir.?), self.engineRelative.? }); for (entries) |entry| { - try writer.print(" .{s} = .{{ .path = \"{s}/{s}\" }},\n", .{ entry.name, self.engineRelative.?, entry.path }); + try content.print(self.allocator, " .{s} = .{{ .path = \"{s}/{s}\" }},\n", .{ entry.name, self.engineRelative.?, entry.path }); } - try writer.print( + try content.print(self.allocator, \\ }}, \\ , .{}); - try writer.print( + try content.print(self.allocator, \\ .paths = .{{ "" }}, \\ , .{}); - try writer.print( + try content.print(self.allocator, \\ .fingerprint = {s}, \\ , .{self.fingerprint.?}); - try writer.print("}}", .{}); + try content.print(self.allocator, "}}", .{}); const file = try workingDir.createFile("build.zig.zon", .{}); defer file.close(); - try file.writeAll(content.items); + var writer = file.writer(&wbuf); + try writer.interface.writeAll(content.items); } fn writeMainZig(self: *@This(), workingDir: *std.fs.Dir) !void { - var content = std.ArrayList(u8).init(self.allocator); - defer content.deinit(); + var content = std.ArrayList(u8){}; + defer content.deinit(self.allocator); const template = \\ pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "main"); @@ -435,10 +432,11 @@ fn writeMainZig(self: *@This(), workingDir: *std.fs.Dir) !void { \\ ; - try content.appendSlice(template); - try content.appendSlice(self.targetName.?); - try content.appendSlice(template2); - try content.append(0); + const allocator = self.allocator; + try content.appendSlice(allocator, template); + try content.appendSlice(allocator, self.targetName.?); + try content.appendSlice(allocator, template2); + try content.append(allocator, 0); const out_path = "src/main.zig"; @@ -447,15 +445,17 @@ fn writeMainZig(self: *@This(), workingDir: *std.fs.Dir) !void { try self.writeZigFile(workingDir, out_path, content.items); } +var wbuf: [4096]u8 = undefined; fn writeZigFile(self: *@This(), workingDir: *std.fs.Dir, out_path: []const u8, contents: []const u8) !void { var ast = try std.zig.Ast.parse(self.allocator, @as([:0]const u8, @ptrCast(contents[0 .. contents.len - 1])), .zig); defer ast.deinit(self.allocator); - const out = try ast.render(self.allocator); + const out = try ast.renderAlloc(self.allocator); const file = try workingDir.createFile(out_path, .{}); defer file.close(); - try file.writeAll(out); + var fw = file.writer(&wbuf); + try fw.interface.writeAll(out); } fn updateFingerPrint(self: *@This(), zonEntry: []const u8) void { diff --git a/projects/tools/toolbox.zig b/projects/tools/toolbox.zig index 2298e37..dac56e9 100644 --- a/projects/tools/toolbox.zig +++ b/projects/tools/toolbox.zig @@ -107,8 +107,8 @@ fn findRootDir(allocator: std.mem.Allocator) ![]u8 { var current_dir = std.fs.cwd(); // Start from current directory and walk up - var path_components = std.ArrayList([]const u8).init(allocator); - defer path_components.deinit(); + var path_components = std.ArrayList([]const u8){}; + defer path_components.deinit(allocator); // Try current directory first current_dir.access("content.txt", .{}) catch {