Giter Site home page Giter Site logo

zgltf's Introduction

glTF parser for Zig codebase

This project is a glTF 2.0 parser written in Zig, aiming to replace the use of some C/C++ libraries. All glTF types are fully documented, so it comes nicely with IDE autocompletion, reducing back and forth with the specification.

This library intends to mimic the glTF file structure in memory. Thereby it's designed around arrays and indexes instead of pointers as you may see in cgltf or other libraries. Also, it's the user's responsibility to load glTF files and their related binaries in memory.

Note: It's not as complete as the glTF specification yet, but because it's straightforward to add new parsed fields, we'll get new stuff incrementally and on-demand.

If you would like to contribute, don't hesitate! :)

Examples

const std = @import("std");
const Gltf = @import("zgltf");

const allocator = std.heap.page_allocator;
const print = std.debug.print;

pub fn main() void {
    const buffer = try std.fs.cwd().readFileAllocOptions(
        allocator,
        "test-samples/rigged_simple/RiggedSimple.gltf",
        512_000,
        null,
        4,
        null
    );
    defer allocator.free(buf);

    var gltf = Self.init(allocator);
    defer gltf.deinit();

    try gltf.parse(buf);

    for (gltf.nodes.items) |node| {
        const message =
            \\\ Node's name: {s}
            \\\ Children count: {}
            \\\ Have skin: {}
        ;

        print(message, .{
            node.name,
            node.children.items.len,
            node.skin != null,
        });
    }

    // Or use the debufPrint method.
    gltf.debugPrint();
}

Also you could easily load data from an Accessor with getDataFromBufferView:

const gltf = Gltf.init(allocator);
try gltf.parse(my_gltf_buf);

const bin = try std.fs.cwd().readFileAllocOptions(
    allocator,
    "test-samples/rigged_simple/RiggedSimple0.bin",
    5_000_000,
    null,
    4,
    null
);
defer allocator.free(buf);

var vertices = ArrayList(f32).init(allocator);
defer vertices.deinit();

const mesh = gltf.data.meshes.items[0];
for (mesh.primitives.items) |primitive| {
    for (primitive.attributes.items) |attribute| {
        switch (attribute) {
            // Accessor for mesh vertices:
            .position => |accessor_index| {
                const accessor = gltf.data.accessors.items[accessor_index];
                gltf.getDataFromBufferView(f32, &vertices, accessor, bin);
            },
            else => {}
        }
    }
}

Also, there is an iterator method that helps you pull data from accessors:

// ...
for (primitive.attributes.items) |attribute| {
    switch (attribute) {
        .position => |idx| {
            const accessor = gltf.data.accessors.items[idx];
            var it = accessor.iterator(f32, &gltf, gltf.glb_binary.?);
            while (it.next()) |v| {
                try vertices.append(.{
                    .pos = .{ v[0], v[1], v[2] },
                    .normal = .{ 1, 0, 0 },
                    .color = .{ 1, 1, 1, 1 },
                    .uv_x = 0,
                    .uv_y = 0,
                });
            }
        },
        .normal => |idx| {
            const accessor = gltf.data.accessors.items[idx];
            var it = accessor.iterator(f32, &gltf, gltf.glb_binary.?);
            var i: u32 = 0;
            while (it.next()) |n| : (i += 1) {
                vertices.items[initial_vertex + i].normal = .{ n[0], n[1], n[2] };
            }
        },
        else => {},
    }
}

Install

Note: Zig 0.11.x is required.

const zgltf = @import("path-to-zgltf/build.zig");
exe.addModule("zgltf", zgltf.module(b));

Features

  • glTF 2.0 json file
  • Scenes
  • Nodes
  • Buffers/BufferViews
  • Meshes
  • Images
  • Materials
  • Animations
  • Skins
  • Cameras
  • Parse glb files
  • Morth targets
  • Extras data
  • glTF writer

Also, we supports some glTF extensions:

  • khr_lights_punctual
  • khr_materials_emissive_strength
  • khr_materials_ior
  • khr_materials_transmission

Contributing to the project

Don’t be shy about shooting any questions you may have. If you are a beginner/junior, don’t hesitate, I will always encourage you. It’s a safe place here. Also, I would be very happy to receive any kind of pull requests, you will have (at least) some feedback/guidance rapidly.

Behind screens, there are human beings, living any sort of story. So be always kind and respectful, because we all sheer to learn new things.

zgltf's People

Contributors

kooparse avatar zkburke avatar ashpil avatar fabioarnold avatar mikastiv avatar sirius902 avatar

Stargazers

Ivan Mar (sOkam!) avatar Gaffel avatar James Martinez avatar Bjorn avatar  avatar Belhorma Bendebiche avatar Clayton avatar Arne Koenig avatar Łukasz Mróz avatar xieyao avatar Lion Schitik avatar  avatar Trenton w Fleming avatar  avatar Ali Cheraghi avatar Brad Svercl avatar  avatar Chad Cuddigan avatar Lemon Drop avatar  avatar  avatar  avatar Andrew Moon avatar Ivan Notaros avatar Alexander Kuznetsov avatar Grabli66 avatar  avatar Guido Schmidt avatar  avatar Arda Güneş avatar alex (she/they) avatar Sean Bohan avatar  avatar  avatar  avatar Prajwal Chapagain avatar Jacob Moena avatar  avatar Rafael Ristovski avatar bootra avatar Nikita avatar Aksel Hjerpbakk avatar Tonis avatar max avatar Chris Heyes avatar Jan Ph. H. avatar Arnaud Valensi avatar

Watchers

 avatar  avatar

zgltf's Issues

Read vertex indices data

Hi, I'm following a vulkan guide and I'm having a hard time loading vertex indices. I was wondering if I'm doing something wrong because the values I get don't make sense.

Here's what I have currently:

const data = try std.fs.cwd().readFileAllocOptions(allocator, filepath, std.math.maxInt(usize), null, 4, null);

var gltf = Gltf.init(allocator);
try gltf.parse(data);

// ...

var indices = std.ArrayList(u16).init(allocator);

const index_accessor = gltf.data.accessors.items[primitive.indices.?];
gltf.getDataFromBufferView(u16, &indices, index_accessor, data);

I'm iterating over the primitives of the mesh and fetching indices like above. The model I'm loading is a simple cube that has 24 vertices and 36 indices (it is a glb file). My issue is that the indices I get are in the range [~15000, ~30000]

Thanks

`gltf.parse` assumes 4-byte aligned little endian data

Ran into this because I used @embedFile to embed my glb model. Unfortunately, according to ziglang/zig#4680 it's currently not possible to specify alignment for @embedFile.

I know it's simpler to just assume these preconditions (and it's probably faster to cast to u32 pointers). But it would be nice to at least have an assertion for alignment and endianness to help with the error search.

The safer/correct but also slower way would be to treat the data as a byte stream and use something like this:

var reader = std.io.fixedBufferStream(data).reader();
const my_int = reader.readInt(u32, .little);

Edit: nvm, saw in the glTF spec that 4-byte alignment is a requirement. So at least an assertion would be nice.

Change Accessor's count field from i32 to usize

I was thinking the count field of Accessor could be a usize instead of a i32 when adding the iterator. Unless there is a good reason for it to be a signed integer like being part of the spec? It seems to be usize in other gltf libraries I looked at.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.