169 lines
4.7 KiB
Markdown
169 lines
4.7 KiB
Markdown
# 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](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html).
|
||
|
||
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! :)
|
||
|
||
Note: The main branch is for the latest Zig release (0.15.1).
|
||
|
||
## Examples
|
||
|
||
```zig
|
||
const std = @import("std");
|
||
const Gltf = @import("zgltf").Gltf;
|
||
|
||
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 = Gltf.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 orelse "Unnamed Node",
|
||
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`:
|
||
|
||
```zig
|
||
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:
|
||
|
||
```zig
|
||
// ...
|
||
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.15.1 is required.**
|
||
|
||
```sh
|
||
zig fetch --save git+https://github.com/kooparse/zgltf
|
||
```
|
||
|
||
```zig
|
||
const zgltf = b.dependency("zgltf", .{});
|
||
exe.addModule("zgltf", zgltf.module("zgltf"));
|
||
```
|
||
|
||
## Features
|
||
|
||
- [x] glTF 2.0 json file
|
||
- [x] Scenes
|
||
- [x] Nodes
|
||
- [x] Buffers/BufferViews
|
||
- [x] Meshes
|
||
- [x] Images
|
||
- [x] Materials
|
||
- [x] Animations
|
||
- [x] Skins
|
||
- [x] Cameras
|
||
- [x] Parse `glb` files
|
||
- [ ] Morth targets
|
||
- [ ] Extras data
|
||
- [ ] glTF writer
|
||
|
||
Also, we supports some glTF extensions:
|
||
|
||
- [x] khr_lights_punctual
|
||
- [x] khr_materials_emissive_strength
|
||
- [x] khr_materials_ior
|
||
- [x] khr_materials_transmission
|
||
- [x] khr_materials_volume
|
||
- [x] khr_materials_dispersion
|
||
|
||
## 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.
|