/zmesh

Zig library for loading, generating, processing and optimising triangle meshes.

Primary LanguageCMIT LicenseMIT

image

Zig library for loading, generating, processing and optimising triangle meshes.

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).

Getting started

Example build.zig:

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.
}