From e29e07c5bfec8a1b53e4e86d5f5605f80f1a2700 Mon Sep 17 00:00:00 2001 From: kcbanner Date: Tue, 5 Nov 2024 00:56:59 -0500 Subject: [PATCH 1/7] Use the new @extern field, .is_dll_import, to link the memory allocation functions from a shared library with the -msvc ABI --- src/memory.zig | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/memory.zig b/src/memory.zig index 132631f..5ed96e9 100644 --- a/src/memory.zig +++ b/src/memory.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const options = @import("zmesh_options"); pub fn init(alloc: std.mem.Allocator) void { std.debug.assert(mem_allocator == null and mem_allocations == null); @@ -7,10 +8,27 @@ pub fn init(alloc: std.mem.Allocator) void { mem_allocations = std.AutoHashMap(usize, usize).init(alloc); mem_allocations.?.ensureTotalCapacity(32) catch unreachable; - zmeshMallocPtr = zmeshMalloc; - zmeshCallocPtr = zmeshCalloc; - zmeshReallocPtr = zmeshRealloc; - zmeshFreePtr = zmeshFree; + const zmeshMallocPtr = @extern(*?*const fn (size: usize) callconv(.C) ?*anyopaque, .{ + .name = "zmeshMallocPtr", + .is_dll_import = options.shared, + }); + const zmeshCallocPtr = @extern(*?*const fn (num: usize, size: usize) callconv(.C) ?*anyopaque, .{ + .name = "zmeshCallocPtr", + .is_dll_import = options.shared, + }); + const zmeshReallocPtr = @extern(*?*const fn (ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque, .{ + .name = "zmeshReallocPtr", + .is_dll_import = options.shared, + }); + const zmeshFreePtr = @extern(*?*const fn (maybe_ptr: ?*anyopaque) callconv(.C) void, .{ + .name = "zmeshFreePtr", + .is_dll_import = options.shared, + }); + + zmeshMallocPtr.* = zmeshMalloc; + zmeshCallocPtr.* = zmeshCalloc; + zmeshReallocPtr.* = zmeshRealloc; + zmeshFreePtr.* = zmeshFree; meshopt_setAllocator(zmeshMalloc, zmeshFree); } @@ -33,8 +51,6 @@ var mem_allocations: ?std.AutoHashMap(usize, usize) = null; var mem_mutex: std.Thread.Mutex = .{}; const mem_alignment = 16; -extern var zmeshMallocPtr: ?*const fn (size: usize) callconv(.C) ?*anyopaque; - pub fn zmeshMalloc(size: usize) callconv(.C) ?*anyopaque { mem_mutex.lock(); defer mem_mutex.unlock(); @@ -50,8 +66,6 @@ pub fn zmeshMalloc(size: usize) callconv(.C) ?*anyopaque { return mem.ptr; } -extern var zmeshCallocPtr: ?*const fn (num: usize, size: usize) callconv(.C) ?*anyopaque; - fn zmeshCalloc(num: usize, size: usize) callconv(.C) ?*anyopaque { const ptr = zmeshMalloc(num * size); if (ptr != null) { @@ -66,8 +80,6 @@ pub fn zmeshAllocUser(user: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque { return zmeshMalloc(size); } -extern var zmeshReallocPtr: ?*const fn (ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque; - fn zmeshRealloc(ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque { mem_mutex.lock(); defer mem_mutex.unlock(); @@ -91,8 +103,6 @@ fn zmeshRealloc(ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque { return mem.ptr; } -extern var zmeshFreePtr: ?*const fn (maybe_ptr: ?*anyopaque) callconv(.C) void; - fn zmeshFree(maybe_ptr: ?*anyopaque) callconv(.C) void { if (maybe_ptr) |ptr| { mem_mutex.lock(); From 21f50170a7902a8ec516fcfcd11f5a680c711a13 Mon Sep 17 00:00:00 2001 From: kcbanner Date: Sat, 28 Jun 2025 13:41:50 -0400 Subject: [PATCH 2/7] - Alignment fixup --- src/memory.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/memory.zig b/src/memory.zig index 5ed96e9..2c6da37 100644 --- a/src/memory.zig +++ b/src/memory.zig @@ -49,7 +49,7 @@ extern fn meshopt_setAllocator( var mem_allocator: ?std.mem.Allocator = null; var mem_allocations: ?std.AutoHashMap(usize, usize) = null; var mem_mutex: std.Thread.Mutex = .{}; -const mem_alignment = 16; +const mem_alignment: std.mem.Alignment = .@"16"; pub fn zmeshMalloc(size: usize) callconv(.C) ?*anyopaque { mem_mutex.lock(); @@ -87,9 +87,9 @@ fn zmeshRealloc(ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque { const old_size = if (ptr != null) mem_allocations.?.get(@intFromPtr(ptr.?)).? else 0; const old_mem = if (old_size > 0) - @as([*]align(mem_alignment) u8, @ptrCast(@alignCast(ptr)))[0..old_size] + @as([*]align(mem_alignment.toByteUnits()) u8, @ptrCast(@alignCast(ptr)))[0..old_size] else - @as([*]align(mem_alignment) u8, undefined)[0..0]; + @as([*]align(mem_alignment.toByteUnits()) u8, undefined)[0..0]; const mem = mem_allocator.?.realloc(old_mem, size) catch @panic("zmesh: out of memory"); @@ -109,7 +109,7 @@ fn zmeshFree(maybe_ptr: ?*anyopaque) callconv(.C) void { defer mem_mutex.unlock(); const size = mem_allocations.?.fetchRemove(@intFromPtr(ptr)).?.value; - const mem = @as([*]align(mem_alignment) u8, @ptrCast(@alignCast(ptr)))[0..size]; + const mem = @as([*]align(mem_alignment.toByteUnits()) u8, @ptrCast(@alignCast(ptr)))[0..size]; mem_allocator.?.free(mem); } } From dfe5ef1e971e9d4c78bd5acac76c501a22cc748a Mon Sep 17 00:00:00 2001 From: kcbanner Date: Sun, 20 Jul 2025 02:24:02 -0400 Subject: [PATCH 3/7] - Remove usingnamespace usage - Fixup build script / callconv deprecations --- build.zig | 37 ++++++-------- src/io.zig | 136 +------------------------------------------------ src/memory.zig | 24 ++++----- src/zcgltf.zig | 136 +++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 161 insertions(+), 172 deletions(-) diff --git a/build.zig b/build.zig index 6719288..5768607 100644 --- a/build.zig +++ b/build.zig @@ -23,34 +23,31 @@ pub fn build(b: *std.Build) void { } const options_module = options_step.createModule(); - - _ = b.addModule("root", .{ + const zmesh_module = b.addModule("root", .{ .root_source_file = b.path("src/root.zig"), + .target = target, + .optimize = optimize, .imports = &.{ .{ .name = "zmesh_options", .module = options_module }, }, }); - const zmesh_lib = if (options.shared) blk: { - const lib = b.addSharedLibrary(.{ - .name = "zmesh", + const zmesh_lib = b.addLibrary(.{ + .name = "zmesh", + .linkage = if (options.shared) .dynamic else .static, + .root_module = b.createModule(.{ .target = target, .optimize = optimize, - }); + }), + }); - if (target.result.os.tag == .windows) { - lib.root_module.addCMacro("PAR_SHAPES_API", "__declspec(dllexport)"); - lib.root_module.addCMacro("CGLTF_API", "__declspec(dllexport)"); - lib.root_module.addCMacro("MESHOPTIMIZER_API", "__declspec(dllexport)"); - lib.root_module.addCMacro("ZMESH_API", "__declspec(dllexport)"); - } + if (options.shared and target.result.os.tag == .windows) { + zmesh_lib.root_module.addCMacro("PAR_SHAPES_API", "__declspec(dllexport)"); + zmesh_lib.root_module.addCMacro("CGLTF_API", "__declspec(dllexport)"); + zmesh_lib.root_module.addCMacro("MESHOPTIMIZER_API", "__declspec(dllexport)"); + zmesh_lib.root_module.addCMacro("ZMESH_API", "__declspec(dllexport)"); + } - break :blk lib; - } else b.addStaticLibrary(.{ - .name = "zmesh", - .target = target, - .optimize = optimize, - }); b.installArtifact(zmesh_lib); zmesh_lib.linkLibC(); @@ -93,9 +90,7 @@ pub fn build(b: *std.Build) void { const tests = b.addTest(.{ .name = "zmesh-tests", - .root_source_file = b.path("src/root.zig"), - .target = target, - .optimize = optimize, + .root_module = zmesh_module, }); b.installArtifact(tests); diff --git a/src/io.zig b/src/io.zig index 7587c88..6339603 100644 --- a/src/io.zig +++ b/src/io.zig @@ -1,8 +1,6 @@ const std = @import("std"); const assert = std.debug.assert; -const mem = @import("memory.zig"); - /// Deprecated. Use `zmesh.io.zcgltf.parseAndLoadFile` instead. pub const parseAndLoadFile = zcgltf.parseAndLoadFile; /// Deprecated. Use `zmesh.io.zcgltf.freeData` instead. @@ -10,136 +8,4 @@ pub const freeData = zcgltf.freeData; /// Deprecated. Use `zmesh.io.zcgltf.appendMeshPrimitive` instead. pub const appendMeshPrimitive = zcgltf.appendMeshPrimitive; -pub const zcgltf = struct { - const bindings = @import("zcgltf.zig"); - const Data = bindings.Data; - - pub usingnamespace bindings; - - pub fn parseAndLoadFile(pathname: [:0]const u8) bindings.Error!*Data { - const options = bindings.Options{ - .memory = .{ - .alloc_func = mem.zmeshAllocUser, - .free_func = mem.zmeshFreeUser, - }, - }; - - const data = try bindings.parseFile(options, pathname); - errdefer bindings.free(data); - - try bindings.loadBuffers(options, data, pathname); - - return data; - } - - pub fn freeData(data: *Data) void { - bindings.free(data); - } - - pub fn appendMeshPrimitive( - data: *Data, - mesh_index: u32, - prim_index: u32, - indices: *std.ArrayList(u32), - positions: *std.ArrayList([3]f32), - normals: ?*std.ArrayList([3]f32), - texcoords0: ?*std.ArrayList([2]f32), - tangents: ?*std.ArrayList([4]f32), - ) !void { - assert(mesh_index < data.meshes_count); - assert(prim_index < data.meshes.?[mesh_index].primitives_count); - - const mesh = &data.meshes.?[mesh_index]; - const prim = &mesh.primitives[prim_index]; - - const num_vertices: u32 = @as(u32, @intCast(prim.attributes[0].data.count)); - const num_indices: u32 = @as(u32, @intCast(prim.indices.?.count)); - - // Indices. - { - try indices.ensureTotalCapacity(indices.items.len + num_indices); - - const accessor = prim.indices.?; - const buffer_view = accessor.buffer_view.?; - - assert(accessor.stride == buffer_view.stride or buffer_view.stride == 0); - assert(buffer_view.buffer.data != null); - - const data_addr = @as([*]const u8, @ptrCast(buffer_view.buffer.data)) + - accessor.offset + buffer_view.offset; - - if (accessor.stride == 1) { - if (accessor.component_type != .r_8u) { - return error.InvalidIndicesAccessorComponentType; - } - const src = @as([*]const u8, @ptrCast(data_addr)); - var i: u32 = 0; - while (i < num_indices) : (i += 1) { - indices.appendAssumeCapacity(src[i]); - } - } else if (accessor.stride == 2) { - if (accessor.component_type != .r_16u) { - return error.InvalidIndicesAccessorComponentType; - } - const src = @as([*]const u16, @ptrCast(@alignCast(data_addr))); - var i: u32 = 0; - while (i < num_indices) : (i += 1) { - indices.appendAssumeCapacity(src[i]); - } - } else if (accessor.stride == 4) { - if (accessor.component_type != .r_32u) { - return error.InvalidIndicesAccessorComponentType; - } - const src = @as([*]const u32, @ptrCast(@alignCast(data_addr))); - var i: u32 = 0; - while (i < num_indices) : (i += 1) { - indices.appendAssumeCapacity(src[i]); - } - } else { - return error.InvalidIndicesAccessorStride; - } - } - - // Attributes. - { - const attributes = prim.attributes[0..prim.attributes_count]; - for (attributes) |attrib| { - const accessor = attrib.data; - assert(accessor.component_type == .r_32f); - - const buffer_view = accessor.buffer_view.?; - assert(buffer_view.buffer.data != null); - - assert(accessor.stride == buffer_view.stride or buffer_view.stride == 0); - assert(accessor.stride * accessor.count == buffer_view.size); - - const data_addr = @as([*]const u8, @ptrCast(buffer_view.buffer.data)) + - accessor.offset + buffer_view.offset; - - if (attrib.type == .position) { - assert(accessor.type == .vec3); - const slice = @as([*]const [3]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; - try positions.appendSlice(slice); - } else if (attrib.type == .normal) { - if (normals) |n| { - assert(accessor.type == .vec3); - const slice = @as([*]const [3]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; - try n.appendSlice(slice); - } - } else if (attrib.type == .texcoord) { - if (texcoords0) |tc| { - assert(accessor.type == .vec2); - const slice = @as([*]const [2]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; - try tc.appendSlice(slice); - } - } else if (attrib.type == .tangent) { - if (tangents) |tan| { - assert(accessor.type == .vec4); - const slice = @as([*]const [4]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; - try tan.appendSlice(slice); - } - } - } - } - } -}; +pub const zcgltf = @import("zcgltf.zig"); diff --git a/src/memory.zig b/src/memory.zig index 2c6da37..b72d580 100644 --- a/src/memory.zig +++ b/src/memory.zig @@ -8,19 +8,19 @@ pub fn init(alloc: std.mem.Allocator) void { mem_allocations = std.AutoHashMap(usize, usize).init(alloc); mem_allocations.?.ensureTotalCapacity(32) catch unreachable; - const zmeshMallocPtr = @extern(*?*const fn (size: usize) callconv(.C) ?*anyopaque, .{ + const zmeshMallocPtr = @extern(*?*const fn (size: usize) callconv(.c) ?*anyopaque, .{ .name = "zmeshMallocPtr", .is_dll_import = options.shared, }); - const zmeshCallocPtr = @extern(*?*const fn (num: usize, size: usize) callconv(.C) ?*anyopaque, .{ + const zmeshCallocPtr = @extern(*?*const fn (num: usize, size: usize) callconv(.c) ?*anyopaque, .{ .name = "zmeshCallocPtr", .is_dll_import = options.shared, }); - const zmeshReallocPtr = @extern(*?*const fn (ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque, .{ + const zmeshReallocPtr = @extern(*?*const fn (ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque, .{ .name = "zmeshReallocPtr", .is_dll_import = options.shared, }); - const zmeshFreePtr = @extern(*?*const fn (maybe_ptr: ?*anyopaque) callconv(.C) void, .{ + const zmeshFreePtr = @extern(*?*const fn (maybe_ptr: ?*anyopaque) callconv(.c) void, .{ .name = "zmeshFreePtr", .is_dll_import = options.shared, }); @@ -38,8 +38,8 @@ pub fn deinit() void { mem_allocator = null; } -const MallocFn = *const fn (size: usize) callconv(.C) ?*anyopaque; -const FreeFn = *const fn (ptr: ?*anyopaque) callconv(.C) void; +const MallocFn = *const fn (size: usize) callconv(.c) ?*anyopaque; +const FreeFn = *const fn (ptr: ?*anyopaque) callconv(.c) void; extern fn meshopt_setAllocator( allocate: MallocFn, @@ -51,7 +51,7 @@ var mem_allocations: ?std.AutoHashMap(usize, usize) = null; var mem_mutex: std.Thread.Mutex = .{}; const mem_alignment: std.mem.Alignment = .@"16"; -pub fn zmeshMalloc(size: usize) callconv(.C) ?*anyopaque { +pub fn zmeshMalloc(size: usize) callconv(.c) ?*anyopaque { mem_mutex.lock(); defer mem_mutex.unlock(); @@ -66,7 +66,7 @@ pub fn zmeshMalloc(size: usize) callconv(.C) ?*anyopaque { return mem.ptr; } -fn zmeshCalloc(num: usize, size: usize) callconv(.C) ?*anyopaque { +fn zmeshCalloc(num: usize, size: usize) callconv(.c) ?*anyopaque { const ptr = zmeshMalloc(num * size); if (ptr != null) { @memset(@as([*]u8, @ptrCast(ptr))[0 .. num * size], 0); @@ -75,12 +75,12 @@ fn zmeshCalloc(num: usize, size: usize) callconv(.C) ?*anyopaque { return null; } -pub fn zmeshAllocUser(user: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque { +pub fn zmeshAllocUser(user: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque { _ = user; return zmeshMalloc(size); } -fn zmeshRealloc(ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque { +fn zmeshRealloc(ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque { mem_mutex.lock(); defer mem_mutex.unlock(); @@ -103,7 +103,7 @@ fn zmeshRealloc(ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque { return mem.ptr; } -fn zmeshFree(maybe_ptr: ?*anyopaque) callconv(.C) void { +fn zmeshFree(maybe_ptr: ?*anyopaque) callconv(.c) void { if (maybe_ptr) |ptr| { mem_mutex.lock(); defer mem_mutex.unlock(); @@ -114,7 +114,7 @@ fn zmeshFree(maybe_ptr: ?*anyopaque) callconv(.C) void { } } -pub fn zmeshFreeUser(user: ?*anyopaque, ptr: ?*anyopaque) callconv(.C) void { +pub fn zmeshFreeUser(user: ?*anyopaque, ptr: ?*anyopaque) callconv(.c) void { _ = user; zmeshFree(ptr); } diff --git a/src/zcgltf.zig b/src/zcgltf.zig index a3de0ed..befb6ce 100644 --- a/src/zcgltf.zig +++ b/src/zcgltf.zig @@ -1,11 +1,139 @@ const builtin = @import("builtin"); const std = @import("std"); const assert = std.debug.assert; +const mem = @import("memory.zig"); pub const Bool32 = i32; pub const CString = [*:0]const u8; pub const MutCString = [*:0]u8; +pub fn parseAndLoadFile(pathname: [:0]const u8) Error!*Data { + const options = Options{ + .memory = .{ + .alloc_func = mem.zmeshAllocUser, + .free_func = mem.zmeshFreeUser, + }, + }; + + const data = try parseFile(options, pathname); + errdefer free(data); + + try loadBuffers(options, data, pathname); + + return data; +} + +pub fn freeData(data: *Data) void { + free(data); +} + +pub fn appendMeshPrimitive( + data: *Data, + mesh_index: u32, + prim_index: u32, + indices: *std.ArrayList(u32), + positions: *std.ArrayList([3]f32), + normals: ?*std.ArrayList([3]f32), + texcoords0: ?*std.ArrayList([2]f32), + tangents: ?*std.ArrayList([4]f32), +) !void { + assert(mesh_index < data.meshes_count); + assert(prim_index < data.meshes.?[mesh_index].primitives_count); + + const mesh = &data.meshes.?[mesh_index]; + const prim = &mesh.primitives[prim_index]; + + const num_vertices: u32 = @as(u32, @intCast(prim.attributes[0].data.count)); + const num_indices: u32 = @as(u32, @intCast(prim.indices.?.count)); + + // Indices. + { + try indices.ensureTotalCapacity(indices.items.len + num_indices); + + const accessor = prim.indices.?; + const buffer_view = accessor.buffer_view.?; + + assert(accessor.stride == buffer_view.stride or buffer_view.stride == 0); + assert(buffer_view.buffer.data != null); + + const data_addr = @as([*]const u8, @ptrCast(buffer_view.buffer.data)) + + accessor.offset + buffer_view.offset; + + if (accessor.stride == 1) { + if (accessor.component_type != .r_8u) { + return error.InvalidIndicesAccessorComponentType; + } + const src = @as([*]const u8, @ptrCast(data_addr)); + var i: u32 = 0; + while (i < num_indices) : (i += 1) { + indices.appendAssumeCapacity(src[i]); + } + } else if (accessor.stride == 2) { + if (accessor.component_type != .r_16u) { + return error.InvalidIndicesAccessorComponentType; + } + const src = @as([*]const u16, @ptrCast(@alignCast(data_addr))); + var i: u32 = 0; + while (i < num_indices) : (i += 1) { + indices.appendAssumeCapacity(src[i]); + } + } else if (accessor.stride == 4) { + if (accessor.component_type != .r_32u) { + return error.InvalidIndicesAccessorComponentType; + } + const src = @as([*]const u32, @ptrCast(@alignCast(data_addr))); + var i: u32 = 0; + while (i < num_indices) : (i += 1) { + indices.appendAssumeCapacity(src[i]); + } + } else { + return error.InvalidIndicesAccessorStride; + } + } + + // Attributes. + { + const attributes = prim.attributes[0..prim.attributes_count]; + for (attributes) |attrib| { + const accessor = attrib.data; + assert(accessor.component_type == .r_32f); + + const buffer_view = accessor.buffer_view.?; + assert(buffer_view.buffer.data != null); + + assert(accessor.stride == buffer_view.stride or buffer_view.stride == 0); + assert(accessor.stride * accessor.count == buffer_view.size); + + const data_addr = @as([*]const u8, @ptrCast(buffer_view.buffer.data)) + + accessor.offset + buffer_view.offset; + + if (attrib.type == .position) { + assert(accessor.type == .vec3); + const slice = @as([*]const [3]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; + try positions.appendSlice(slice); + } else if (attrib.type == .normal) { + if (normals) |n| { + assert(accessor.type == .vec3); + const slice = @as([*]const [3]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; + try n.appendSlice(slice); + } + } else if (attrib.type == .texcoord) { + if (texcoords0) |tc| { + assert(accessor.type == .vec2); + const slice = @as([*]const [2]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; + try tc.appendSlice(slice); + } + } else if (attrib.type == .tangent) { + if (tangents) |tan| { + assert(accessor.type == .vec4); + const slice = @as([*]const [4]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; + try tan.appendSlice(slice); + } + } + } + } +} + pub const FileType = enum(c_int) { invalid, gltf, @@ -25,8 +153,8 @@ pub const Result = enum(c_int) { legacy_gltf, }; -const MallocFn = *const fn (user: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque; -const FreeFn = *const fn (user: ?*anyopaque, ptr: ?*anyopaque) callconv(.C) void; +const MallocFn = *const fn (user: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque; +const FreeFn = *const fn (user: ?*anyopaque, ptr: ?*anyopaque) callconv(.c) void; pub const MemoryOptions = extern struct { alloc_func: ?MallocFn = null, @@ -41,9 +169,9 @@ pub const FileOptions = extern struct { CString, *usize, *?*anyopaque, - ) callconv(.C) Result; + ) callconv(.c) Result; - const ReleaseFn = *const fn (*const MemoryOptions, *const FileOptions, ?*anyopaque) callconv(.C) void; + const ReleaseFn = *const fn (*const MemoryOptions, *const FileOptions, ?*anyopaque) callconv(.c) void; read: ?ReadFn = null, release: ?ReleaseFn = null, From 04b6715c9ab437061c37858a3152b2e1e7297d9f Mon Sep 17 00:00:00 2001 From: kcbanner Date: Wed, 13 Aug 2025 20:31:12 -0400 Subject: [PATCH 4/7] - Change `appendMeshPrimitive` to use unmanaged data structures --- src/zcgltf.zig | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/zcgltf.zig b/src/zcgltf.zig index befb6ce..968acdd 100644 --- a/src/zcgltf.zig +++ b/src/zcgltf.zig @@ -28,14 +28,15 @@ pub fn freeData(data: *Data) void { } pub fn appendMeshPrimitive( + allocator: std.mem.Allocator, data: *Data, mesh_index: u32, prim_index: u32, - indices: *std.ArrayList(u32), - positions: *std.ArrayList([3]f32), - normals: ?*std.ArrayList([3]f32), - texcoords0: ?*std.ArrayList([2]f32), - tangents: ?*std.ArrayList([4]f32), + indices: *std.ArrayListUnmanaged(u32), + positions: *std.ArrayListUnmanaged([3]f32), + normals: ?*std.ArrayListUnmanaged([3]f32), + texcoords0: ?*std.ArrayListUnmanaged([2]f32), + tangents: ?*std.ArrayListUnmanaged([4]f32), ) !void { assert(mesh_index < data.meshes_count); assert(prim_index < data.meshes.?[mesh_index].primitives_count); @@ -48,7 +49,7 @@ pub fn appendMeshPrimitive( // Indices. { - try indices.ensureTotalCapacity(indices.items.len + num_indices); + try indices.ensureTotalCapacity(allocator, indices.items.len + num_indices); const accessor = prim.indices.?; const buffer_view = accessor.buffer_view.?; @@ -110,24 +111,24 @@ pub fn appendMeshPrimitive( if (attrib.type == .position) { assert(accessor.type == .vec3); const slice = @as([*]const [3]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; - try positions.appendSlice(slice); + try positions.appendSlice(allocator, slice); } else if (attrib.type == .normal) { if (normals) |n| { assert(accessor.type == .vec3); const slice = @as([*]const [3]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; - try n.appendSlice(slice); + try n.appendSlice(allocator, slice); } } else if (attrib.type == .texcoord) { if (texcoords0) |tc| { assert(accessor.type == .vec2); const slice = @as([*]const [2]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; - try tc.appendSlice(slice); + try tc.appendSlice(allocator, slice); } } else if (attrib.type == .tangent) { if (tangents) |tan| { assert(accessor.type == .vec4); const slice = @as([*]const [4]f32, @ptrCast(@alignCast(data_addr)))[0..num_vertices]; - try tan.appendSlice(slice); + try tan.appendSlice(allocator, slice); } } } From 45d18ec61e851a6311ebd372cf92287e4f70f830 Mon Sep 17 00:00:00 2001 From: Chris Heyes <22148308+hazeycode@users.noreply.github.com> Date: Thu, 28 Aug 2025 23:52:20 +0100 Subject: [PATCH 5/7] Update ArrayList usage to 0.15.1 --- src/Shape.zig | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Shape.zig b/src/Shape.zig index bf440f2..90b4dee 100644 --- a/src/Shape.zig +++ b/src/Shape.zig @@ -458,20 +458,22 @@ test "zmesh.invert" { test "zmesh.custom" { const zmesh = @import("root.zig"); - zmesh.init(std.testing.allocator); + const allocator = std.testing.allocator; + + zmesh.init(allocator); defer zmesh.deinit(); - var positions = std.ArrayList([3]f32).init(std.testing.allocator); - defer positions.deinit(); - try positions.append(.{ 0.0, 0.0, 0.0 }); - try positions.append(.{ 1.0, 0.0, 0.0 }); - try positions.append(.{ 1.0, 0.0, 1.0 }); - - var indices = std.ArrayList(IndexType).init(std.testing.allocator); - defer indices.deinit(); - try indices.append(0); - try indices.append(1); - try indices.append(2); + var positions: std.ArrayList([3]f32) = .{}; + defer positions.deinit(allocator); + try positions.append(allocator, .{ 0.0, 0.0, 0.0 }); + try positions.append(allocator, .{ 1.0, 0.0, 0.0 }); + try positions.append(allocator, .{ 1.0, 0.0, 1.0 }); + + var indices: std.ArrayList(IndexType) = .{}; + defer indices.deinit(allocator); + try indices.append(allocator, 0); + try indices.append(allocator, 1); + try indices.append(allocator, 2); var shape = Shape.init(indices, positions, null, null); defer shape.deinit(); From b27e22c275ea5bab5cad88863b87d5610bc90321 Mon Sep 17 00:00:00 2001 From: Chris Heyes <22148308+hazeycode@users.noreply.github.com> Date: Thu, 28 Aug 2025 23:52:44 +0100 Subject: [PATCH 6/7] bump minimum_zig_version to 0.15.1 --- build.zig.zon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig.zon b/build.zig.zon index 1b418ea..2ec8cf3 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -2,7 +2,7 @@ .name = .zmesh, .fingerprint = 0xb56bea39e6c0eda0, .version = "0.11.0-dev", - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.15.1", .paths = .{ "build.zig", "build.zig.zon", From 6a92ab8b1de3b1ee882ee4b4da2ff3f76f7911fd Mon Sep 17 00:00:00 2001 From: Chris Heyes <22148308+hazeycode@users.noreply.github.com> Date: Fri, 29 Aug 2025 00:31:34 +0100 Subject: [PATCH 7/7] Update README code examples for Zig 0.15.1 --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3f4f5a3..2d6feeb 100644 --- a/README.md +++ b/README.md @@ -74,11 +74,12 @@ pub fn main() !void { const data = try zmesh.io.zcgltf.parseAndLoadFile(content_dir ++ "cube.gltf"); defer zmesh.io.zcgltf.freeData(data); - var mesh_indices = std.ArrayList(u32).init(allocator); - var mesh_positions = std.ArrayList([3]f32).init(allocator); - var mesh_normals = std.ArrayList([3]f32).init(allocator); + var mesh_indices = std.ArrayListUnmanaged(u32){}; + var mesh_positions = std.ArrayListUnmanaged([3]f32){}; + var mesh_normals = std.ArrayListUnmanaged([3]f32){}; - zmesh.io.zcgltf.appendMeshPrimitive( + try zmesh.io.zcgltf.appendMeshPrimitive( + allocator, data, 0, // mesh index 0, // gltf primitive index (submesh index) @@ -98,8 +99,8 @@ pub fn main() !void { normal: [3]f32, }; - var remap = std.ArrayList(u32).init(allocator); - remap.resize(src_indices.items.len) catch unreachable; + var remap = std.ArrayListUnmanaged(u32){}; + try remap.resize(allocator, src_indices.items.len); const num_unique_vertices = zmesh.opt.generateVertexRemap( remap.items, // 'vertex remap' (destination) @@ -108,8 +109,8 @@ pub fn main() !void { src_vertices.items, // non-optimized vertices ); - var optimized_vertices = std.ArrayList(Vertex).init(allocator); - optimized_vertices.resize(num_unique_vertices) catch unreachable; + var optimized_vertices = std.ArrayListUnmanaged(Vertex){}; + try optimized_vertices.resize(allocator, num_unique_vertices); zmesh.opt.remapVertexBuffer( Vertex, // Zig type describing your vertex