Load, generate, process and optimize triangle meshes in Zig.
Under the hood this library uses below C/C++ libraries:
All memory allocations go through user-supplied, Zig allocator.
As an example program please see procedural mesh (wgpu).
Copy zmesh
to a subdirectory of your project and add the following to your build.zig.zon
.dependencies:
.zmesh = .{ .path = "libs/zmesh" },
Then in your build.zig
add:
pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{ ... });
const zmesh = b.dependency("zmesh", .{});
exe.root_module.addImport("zmesh", zmesh.module("root"));
exe.linkLibrary(zmesh.artifact("zmesh"));
}
Now in your code you may import and use zmesh
:
const zmesh = @import("zmesh");
pub fn main() !void {
...
zmesh.init(allocator);
defer zmesh.deinit();
var custom = zmesh.Shape.init(indices, positions, normals, texcoords);
defer custom.deinit();
var disk = zmesh.Shape.initParametricDisk(10, 2);
defer disk.deinit();
disk.invert(0, 0);
var cylinder = zmesh.Shape.initCylinder(10, 4);
defer cylinder.deinit();
cylinder.merge(disk);
cylinder.translate(0, 0, -1);
disk.invert(0, 0);
cylinder.merge(disk);
cylinder.scale(0.5, 0.5, 2);
cylinder.rotate(math.pi * 0.5, 1.0, 0.0, 0.0);
cylinder.unweld();
cylinder.computeNormals();
...
}
const zmesh = @import("zmesh");
pub fn main() !void {
zmesh.init(allocator);
defer zmesh.deinit();
//
// Load mesh
//
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);
zmesh.io.zcgltf.appendMeshPrimitive(
data,
0, // mesh index
0, // gltf primitive index (submesh index)
&mesh_indices,
&mesh_positions,
&mesh_normals, // normals (optional)
null, // texcoords (optional)
null, // tangents (optional)
);
...
//
// Optimize mesh
//
const Vertex = struct {
position: [3]f32,
normal: [3]f32,
};
var remap = std.ArrayList(u32).init(allocator);
remap.resize(src_indices.items.len) catch unreachable;
const num_unique_vertices = zmesh.opt.generateVertexRemap(
remap.items, // 'vertex remap' (destination)
src_indices.items, // non-optimized indices
Vertex, // Zig type describing your vertex
src_vertices.items, // non-optimized vertices
);
var optimized_vertices = std.ArrayList(Vertex).init(allocator);
optimized_vertices.resize(num_unique_vertices) catch unreachable;
zmesh.opt.remapVertexBuffer(
Vertex, // Zig type describing your vertex
optimized_vertices.items, // optimized vertices (destination)
src_vertices.items, // non-optimized vertices (source)
remap.items, // 'vertex remap' generated by generateVertexRemap()
);
// More optimization steps are available - see `zmeshoptimizer.zig` file.
}