Skip to content

Commit

Permalink
simple_texture
Browse files Browse the repository at this point in the history
  • Loading branch information
ousttrue committed Oct 5, 2024
1 parent da7d801 commit 4d017b6
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 55 deletions.
32 changes: 8 additions & 24 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,12 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
});

var asset_installs: [2]*std.Build.Step.InstallDir = undefined;

{
const asset_wf = samples_deps.namedWriteFiles("glTF-Sample-Assets");
asset_installs[0] = b.addInstallDirectory(.{
.source_dir = asset_wf.getDirectory(),
.install_dir = .prefix,
.install_subdir = "web/glTF-Sample-Assets",
});
}
{
const asset_wf = samples_deps.namedWriteFiles("UniVRM");
asset_installs[1] = b.addInstallDirectory(.{
.source_dir = asset_wf.getDirectory(),
.install_dir = .prefix,
.install_subdir = "web/UniVRM",
});
}
const asset_wf = samples_deps.namedWriteFiles("assets");
const asset_install = b.addInstallDirectory(.{
.source_dir = asset_wf.getDirectory(),
.install_dir = .prefix,
.install_subdir = "web",
});

if (target.result.isWasm()) {
const wasm_wf = samples_deps.namedWriteFiles("wasm");
Expand All @@ -48,17 +36,13 @@ pub fn build(b: *std.Build) void {
.install_subdir = "",
});
b.getInstallStep().dependOn(&wasm_install.step);
for (asset_installs) |asset_install| {
b.getInstallStep().dependOn(&asset_install.step);
}
b.getInstallStep().dependOn(&asset_install.step);
} else {
for (samples_build.samples) |sample| {
const artifact = samples_deps.artifact(sample.name);

const install = b.addInstallArtifact(artifact, .{});
for (asset_installs) |asset_install| {
install.step.dependOn(&asset_install.step);
}
install.step.dependOn(&asset_install.step);
b.getInstallStep().dependOn(&install.step);

const run = b.addRunArtifact(artifact);
Expand Down
Binary file added deps/sokol_samples/assets/testTexture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions deps/sokol_samples/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,26 @@ pub fn build(b: *std.Build) void {
});

// asset
const asset_wf = b.addNamedWriteFiles("assets");
b.default_step.dependOn(&asset_wf.step);
{
_ = asset_wf.addCopyDirectory(b.path("assets"), "", .{});
}
{
const test_models = b.dependency("gltf-test-models", .{});
const asset_wf = b.addNamedWriteFiles("glTF-Sample-Assets");
{
const wf = test_models.namedWriteFiles("glTF-Sample-Assets");
_ = asset_wf.addCopyDirectory(wf.getDirectory(), "", .{});
_ = asset_wf.addCopyDirectory(wf.getDirectory(), "glTF-Sample-Assets", .{});
}
b.default_step.dependOn(&asset_wf.step);
}
{
const test_models = b.dependency("univrm", .{});
const asset_wf = b.addNamedWriteFiles("UniVRM");
{
// const wf = test_models.namedWriteFiles("UniVRM");
_ = asset_wf.addCopyFile(
test_models.path("Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm"),
"AliciaSolid_vrm-0.51.vrm",
"univrm/AliciaSolid_vrm-0.51.vrm",
);
}
b.default_step.dependOn(&asset_wf.step);
}

// sample_framework
Expand Down
4 changes: 2 additions & 2 deletions deps/sokol_samples/sample_framework/Scene.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub fn deinit(self: *@This()) void {
pub fn load(
self: *@This(),
json: std.json.Parsed(zigltf.Gltf),
bin: ?[]const u8,
binmap: std.StringHashMap([]const u8),
) !void {
std.debug.print("{s}\n", .{json.value});
self.gltf = json;
Expand All @@ -77,7 +77,7 @@ pub fn load(
var gltf_buffer = zigltf.GltfBuffer.init(
self.allocator,
gltf,
if (bin) |b| b else &.{},
binmap,
);
defer gltf_buffer.deinit();

Expand Down
104 changes: 92 additions & 12 deletions deps/sokol_samples/sample_framework/gltf_fetcher.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,41 @@ const sokol = @import("sokol");
const rowmath = @import("rowmath");
const zigltf = @import("zigltf");

const GltfCallback = fn (gltf: std.json.Parsed(zigltf.Gltf), bin: ?[]const u8) void;
const GltfCallback = fn (
gltf: std.json.Parsed(zigltf.Gltf),
binmap: std.StringHashMap([]const u8),
) void;

const Task = union(enum) {
gltf: struct {
path: []const u8,
callback: *const GltfCallback,
},
image: struct {
index: u32,
callback: *const GltfCallback,
},
buffer: struct {
path: []const u8,
buffer_index: u32,
index: u32,
callback: *const GltfCallback,
},
};

pub const state = struct {
var allocator: std.mem.Allocator = undefined;
pub var status: [:0]const u8 = "loading...";
pub var status: [:0]const u8 = "fetch gltf...";
var status_buffer: [1024]u8 = undefined;
var tasks: [32]Task = undefined;
var task_count: u32 = 0;
var fetch_buffer: [1024 * 1024 * 32]u8 = undefined;
//
var json: ?std.json.Parsed(zigltf.Gltf) = null;
var binmap: std.StringHashMap([]const u8) = undefined;
};

pub fn init(allocator: std.mem.Allocator) void {
state.allocator = allocator;
state.binmap = std.StringHashMap([]const u8).init(allocator);

// setup sokol-fetch with 2 channels and 6 lanes per channel,
// we'll use one channel for mesh data and the other for textures
Expand All @@ -45,29 +56,81 @@ pub fn fetch_gltf(path: [:0]const u8, on_gltf: *const GltfCallback) !void {
.callback = on_gltf,
},
};
defer state.task_count += 1;

_ = sokol.fetch.send(.{
.path = &path[0],
.callback = fetch_callback,
.buffer = sokol.fetch.asRange(&state.fetch_buffer),
.user_data = sokol.fetch.asRange(&state.tasks[state.task_count]),
});
}

fn fetch_image(index: u32, on_gltf: *const GltfCallback) !void {
const parsed = state.json orelse {
return error.no_gltf;
};

state.task_count += 1;
if (index >= parsed.value.images.len) {
on_gltf(parsed, state.binmap);
} else {
// fetch next
const image = parsed.value.images[index];

if (image.uri) |uri| {
state.status = std.fmt.bufPrintZ(
&state.status_buffer,
"fetch image[{}]: {s}\n",
.{ index, uri },
) catch @panic("bufPrintZ");

state.tasks[state.task_count] = .{
.image = .{
.index = index,
.callback = on_gltf,
},
};
defer state.task_count += 1;

const uriz = try std.fmt.allocPrintZ(state.allocator, "{s}", .{uri});

_ = sokol.fetch.send(.{
.path = &uriz[0],
.callback = fetch_callback,
.buffer = sokol.fetch.asRange(&state.fetch_buffer),
.user_data = sokol.fetch.asRange(&state.tasks[state.task_count]),
});
} else {
try fetch_image(index + 1, on_gltf);
}
}
}

fn toSlice(ptr: [*]const u8, size: usize) []const u8 {
fn to_slice(ptr: [*]const u8, size: usize) []const u8 {
return ptr[0..size];
}

fn getGlb(gltf_or_glb: []const u8) zigltf.Glb {
fn get_glb(gltf_or_glb: []const u8) zigltf.Glb {
if (zigltf.Glb.parse(gltf_or_glb)) |glb| {
return glb;
} else {
return .{ .json_bytes = gltf_or_glb };
}
}

pub fn set_gltf(
parsed: std.json.Parsed(zigltf.Gltf),
_bin: ?[]const u8,
callback: *const GltfCallback,
) !void {
state.json = parsed;
if (_bin) |bin| {
try state.binmap.put("", bin);
}

try fetch_image(0, callback);
}

export fn fetch_callback(response: [*c]const sokol.fetch.Response) void {
std.debug.print("fetch_callback\n", .{});
if (response.*.fetched) {
Expand All @@ -80,12 +143,12 @@ export fn fetch_callback(response: [*c]const sokol.fetch.Response) void {
.{response.*.data.size},
) catch @panic("bufPrintZ");

const bytes = toSlice(
const bytes = to_slice(
@ptrCast(response.*.data.ptr),
response.*.data.size,
);

const glb = getGlb(bytes);
const glb = get_glb(bytes);

if (std.json.parseFromSlice(
zigltf.Gltf,
Expand All @@ -95,9 +158,7 @@ export fn fetch_callback(response: [*c]const sokol.fetch.Response) void {
.ignore_unknown_fields = true,
},
)) |parsed| {
// defer parsed.deinit();
state.status = "parsed";
gltf_task.callback(parsed, glb.bin);
set_gltf(parsed, glb.bin, gltf_task.callback) catch @panic("set_gltf");
} else |e| {
state.status = std.fmt.bufPrintZ(
&state.status_buffer,
Expand All @@ -106,6 +167,25 @@ export fn fetch_callback(response: [*c]const sokol.fetch.Response) void {
) catch @panic("bufPrintZ");
}
},
.image => |image_task| {
const bytes = to_slice(
@ptrCast(response.*.data.ptr),
response.*.data.size,
);

const parsed = state.json orelse {
@panic("no gltf");
};

const image = parsed.value.images[image_task.index];
const uri = image.uri orelse {
@panic("no uri");
};

state.binmap.put(uri, bytes) catch @panic("put");

fetch_image(image_task.index + 1, image_task.callback) catch @panic("fetch_image");
},
.buffer => |buffer_task| {
_ = buffer_task;
unreachable;
Expand Down
11 changes: 10 additions & 1 deletion deps/sokol_samples/tutorials/simple_texture/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,21 @@ export fn init() void {
@panic("parseFromSlice");
};

framework.gltf_fetcher.init(allocator);
framework.gltf_fetcher.set_gltf(parsed, null, &on_load) catch @panic("set_gltf");
}

fn on_load(parsed: std.json.Parsed(zigltf.Gltf), binmap: std.StringHashMap([]const u8)) void {
// build
state.scene.load(parsed, &.{}) catch |e| {
state.scene.load(parsed, binmap) catch |e| {
std.debug.print("{s}\n", .{@errorName(e)});
@panic("Scene.load");
};
}

export fn frame() void {
sokol.fetch.dowork();

state.input.screen_width = sokol.app.widthf();
state.input.screen_height = sokol.app.heightf();
state.orbit.frame(state.input);
Expand All @@ -160,6 +167,8 @@ export fn frame() void {
sokol.debugtext.canvas(sokol.app.widthf() * 0.5, sokol.app.heightf() * 0.5);
sokol.debugtext.pos(0.5, 0.5);
sokol.debugtext.puts(title);
sokol.debugtext.puts("\n");
sokol.debugtext.puts(framework.gltf_fetcher.state.status);

sg.beginPass(.{
.action = state.pass_action,
Expand Down
15 changes: 8 additions & 7 deletions deps/zigltf/src/GltfBuffer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@ pub const GltfBuffer = @This();

allocator: std.mem.Allocator,
gltf: Gltf,
bin: []const u8,
uriMap: std.StringHashMap([]const u8),

pub fn init(
allocator: std.mem.Allocator,
gltf: Gltf,
bin: []const u8,
binmap: std.StringHashMap([]const u8),
) @This() {
return .{
.allocator = allocator,
.gltf = gltf,
.bin = bin,
.uriMap = std.StringHashMap([]const u8).init(allocator),
.uriMap = binmap,
};
}

Expand All @@ -32,8 +30,11 @@ pub fn getImageBytes(self: *@This(), image_index: u32) ![]const u8 {
if (image.bufferView) |bufferView_index| {
return try self.getBufferViewBytes(bufferView_index);
} else if (image.uri) |uri| {
_ = uri;
@panic("image.uri not implemented");
if (self.uriMap.getPtr(uri)) |bytes| {
return bytes.*;
} else {
@panic("image.uri not implemented");
}
} else {
unreachable;
}
Expand Down Expand Up @@ -111,7 +112,7 @@ pub fn getBufferBytes(self: *@This(), buffer_index: u32) ![]const u8 {
if (buffer.uri) |uri| {
return try self.getUriBytes(uri);
} else {
return self.bin;
return try self.getUriBytes("");
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function Item(props: ItemType) {
<ul>
{props.links.map((link, i) => (
<li key={i}>
<a href={link.url}>
<a href={link.url} target="_blank">
{"🔗"}{link.name}
</a>
</li>))}
Expand All @@ -27,7 +27,7 @@ function Item(props: ItemType) {
function Group(props: ItemGroupType) {
return (<>
<div className="item">
<a href={props.url}>{"🔗"}{props.name}</a>
<a href={props.url} target="_blank">{"🔗"}{props.name}</a>
</div>
{props.items.map((props, i) => <Item key={i} {...props} />)}
</>);
Expand Down
Loading

0 comments on commit 4d017b6

Please sign in to comment.