feat: use atlassian dep
This commit is contained in:
parent
92e62ce910
commit
5baa9e057c
4 changed files with 35 additions and 202 deletions
|
@ -13,9 +13,11 @@ pub fn build(b: *std.build.Builder) void {
|
|||
|
||||
const dep_args = .{ .target = target, .optimize = optimize };
|
||||
const boxflow_dep = b.dependency("boxflow", dep_args);
|
||||
const atlassian_dep = b.dependency("atlassian", dep_args);
|
||||
const zalgebra_dep = b.dependency("zalgebra", dep_args);
|
||||
|
||||
exe.addModule("boxflow", boxflow_dep.module("boxflow"));
|
||||
exe.addModule("atlassian", atlassian_dep.module("atlassian"));
|
||||
exe.addModule("zalgebra", zalgebra_dep.module("zalgebra"));
|
||||
|
||||
exe.linkLibC();
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
.url = "https://mzte.de/git/LordMZTE/boxflow/archive/f57b4413d060b32c7391719f319a4666a86ed092.tar.gz",
|
||||
.hash = "1220053e7ffa108b9233858fbc2970865789575ae35d06a2cb4789a6829485b3a552",
|
||||
},
|
||||
.atlassian = .{
|
||||
.url = "https://mzte.de/git/LordMZTE/atlassian/archive/3410b47f431422f2da1d2b68e83273b66e557543.tar.gz",
|
||||
.hash = "122056e309d3b83351036dbda36eee1c877f8e9acdc2fdf4d618635a54bf20e5f126",
|
||||
},
|
||||
.zalgebra = .{
|
||||
.url = "https://github.com/kooparse/zalgebra/archive/2835687295be384b1dbed4518a4a635422ace60a.tar.gz",
|
||||
.hash = "1220f03cf7a6ee2ea0e1961cfbcadf5d283a76632179e354aaf944e7c80e2254d2f8",
|
||||
|
|
194
src/atlas.zig
194
src/atlas.zig
|
@ -1,194 +0,0 @@
|
|||
const std = @import("std");
|
||||
const gl = @import("gl.zig");
|
||||
|
||||
pub const AtlasSprite = struct {
|
||||
xmin: usize,
|
||||
ymin: usize,
|
||||
|
||||
xmax: usize,
|
||||
ymax: usize,
|
||||
|
||||
fn isTouchingOnRight(self: *const AtlasSprite, other: *const AtlasSprite) bool {
|
||||
return other.xmin == self.xmax and
|
||||
other.ymin < self.ymax and
|
||||
other.ymax > self.ymin;
|
||||
}
|
||||
|
||||
fn isTouchingOnBottom(self: *const AtlasSprite, other: *const AtlasSprite) bool {
|
||||
return other.ymin == self.ymax and
|
||||
other.xmax > self.xmin and
|
||||
other.xmin < self.xmax;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn Atlas(comptime Pix: type) type {
|
||||
if (Pix != u8 and Pix != u32) {
|
||||
@compileError("atlas not implemented for pixel type " ++ Pix);
|
||||
}
|
||||
|
||||
return struct {
|
||||
pixels: []Pix,
|
||||
stride: usize,
|
||||
padding: usize,
|
||||
collision_sprites: std.ArrayList(AtlasSprite),
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(
|
||||
alloc: std.mem.Allocator,
|
||||
stride: usize,
|
||||
initial_height: usize,
|
||||
padding: usize,
|
||||
) !Self {
|
||||
const pixels = try alloc.alloc(Pix, stride * initial_height);
|
||||
for (pixels) |*pix|
|
||||
pix.* = 0;
|
||||
|
||||
return .{
|
||||
.pixels = pixels,
|
||||
.stride = stride,
|
||||
.collision_sprites = std.ArrayList(AtlasSprite).init(alloc),
|
||||
.padding = padding,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.collision_sprites.allocator.free(self.pixels);
|
||||
self.collision_sprites.deinit();
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn addSprite(self: *Self, data: []const Pix, stride: usize) !AtlasSprite {
|
||||
// Pile algorithm
|
||||
// My idea actually! (but some greek mathematician mustve been first)
|
||||
var collision_sprite = AtlasSprite{
|
||||
.xmin = self.stride - stride - 1 - self.padding,
|
||||
.ymin = @divExact(self.pixels.len, self.stride),
|
||||
|
||||
.xmax = self.stride - 1,
|
||||
.ymax = @divExact(self.pixels.len, self.stride) +
|
||||
@divExact(data.len, stride) + self.padding,
|
||||
};
|
||||
// yes, this is a state machine
|
||||
const State = enum {
|
||||
up,
|
||||
left,
|
||||
};
|
||||
|
||||
var state: State = .up;
|
||||
|
||||
while (true) {
|
||||
switch (state) {
|
||||
.up => {
|
||||
if (self.isTouchingAnyOnTop(&collision_sprite)) {
|
||||
state = .left;
|
||||
} else {
|
||||
collision_sprite.ymin -= 1;
|
||||
collision_sprite.ymax -= 1;
|
||||
}
|
||||
},
|
||||
.left => {
|
||||
if (!self.isTouchingAnyOnTop(&collision_sprite)) {
|
||||
state = .up;
|
||||
} else if (!self.isTouchingAnyOnLeft(&collision_sprite)) {
|
||||
collision_sprite.xmin -= 1;
|
||||
collision_sprite.xmax -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var sprite = collision_sprite;
|
||||
sprite.xmax -= self.padding;
|
||||
sprite.ymax -= self.padding;
|
||||
|
||||
try self.reserveHeight(collision_sprite.ymax);
|
||||
self.copySpriteData(&sprite, data);
|
||||
try self.collision_sprites.append(collision_sprite);
|
||||
return sprite;
|
||||
}
|
||||
|
||||
pub fn toGlTex(self: *const Self, tex: c_uint) !void {
|
||||
if (Pix == u8) {
|
||||
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
|
||||
}
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
const format = if (Pix == u8) gl.RED else gl.RGBA;
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
format,
|
||||
@intCast(self.stride),
|
||||
@intCast(@divExact(self.pixels.len, self.stride)),
|
||||
0,
|
||||
format,
|
||||
if (Pix == u8) gl.UNSIGNED_BYTE else gl.UNSIGNED_INT_8_8_8_8,
|
||||
self.pixels.ptr,
|
||||
);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
}
|
||||
|
||||
fn isTouchingAnyOnLeft(self: *const Self, sprite: *const AtlasSprite) bool {
|
||||
if (sprite.xmin == 0)
|
||||
return true;
|
||||
for (self.collision_sprites.items) |*s| {
|
||||
if (s.isTouchingOnRight(sprite))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn isTouchingAnyOnTop(self: *const Self, sprite: *const AtlasSprite) bool {
|
||||
if (sprite.ymin == 0)
|
||||
return true;
|
||||
for (self.collision_sprites.items) |*s| {
|
||||
if (s.isTouchingOnBottom(sprite))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn copySpriteData(
|
||||
self: *Self,
|
||||
sprite: *const AtlasSprite,
|
||||
data: []const Pix,
|
||||
) void {
|
||||
const sprite_width = sprite.xmax - sprite.xmin;
|
||||
const sprite_height = sprite.ymax - sprite.ymin;
|
||||
|
||||
var x: usize = 0;
|
||||
while (x < sprite_width) : (x += 1) {
|
||||
var y: usize = 0;
|
||||
while (y < sprite_height) : (y += 1) {
|
||||
const atlas_x = sprite.xmin + x;
|
||||
const atlas_y = sprite.ymin + y;
|
||||
|
||||
self.pixels[atlas_y * self.stride + atlas_x] =
|
||||
data[y * sprite_width + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reserveHeight(self: *Self, height: usize) !void {
|
||||
if (@divExact(self.pixels.len, self.stride) >= height)
|
||||
return;
|
||||
|
||||
const prev_len = self.pixels.len;
|
||||
|
||||
self.pixels = try self.collision_sprites.allocator.realloc(
|
||||
self.pixels,
|
||||
self.stride * height,
|
||||
);
|
||||
|
||||
for (self.pixels[prev_len..]) |*pix|
|
||||
pix.* = 0;
|
||||
}
|
||||
};
|
||||
}
|
37
src/font.zig
37
src/font.zig
|
@ -1,13 +1,14 @@
|
|||
const std = @import("std");
|
||||
const zalgebra = @import("zalgebra");
|
||||
const atlas = @import("atlas.zig");
|
||||
const atlassian = @import("atlassian");
|
||||
|
||||
const c = @import("ffi.zig").c;
|
||||
const gl = @import("gl.zig");
|
||||
const glutil = @import("glutil.zig");
|
||||
const GlState = @import("GlState.zig");
|
||||
|
||||
pub const FontInfo = struct {
|
||||
atlas: atlas.Atlas(u8),
|
||||
atlas: atlassian.Atlas(u8),
|
||||
freetype: c.FT_Library,
|
||||
font_face: c.FT_Face,
|
||||
atlas_id: c_uint,
|
||||
|
@ -26,7 +27,7 @@ pub const FontInfo = struct {
|
|||
};
|
||||
|
||||
pub const Character = struct {
|
||||
sprite: atlas.AtlasSprite,
|
||||
sprite: atlassian.AtlasSprite,
|
||||
/// Offset from the left/top
|
||||
bearing: zalgebra.Vec2_i32,
|
||||
advance: c_long,
|
||||
|
@ -65,12 +66,18 @@ pub fn load() !FontInfo {
|
|||
font_face.*.size.*.metrics.descender) >> 5;
|
||||
var chars = CharMap.init(std.heap.c_allocator);
|
||||
|
||||
var atl = try atlas.Atlas(u8).init(std.heap.c_allocator, 512 - 64, 512 + 128, 4);
|
||||
var atl = try atlassian.Atlas(u8).init(std.heap.c_allocator, 512 - 64, 512 + 128, 4);
|
||||
errdefer atl.deinit();
|
||||
|
||||
var tex: c_uint = 0;
|
||||
gl.genTextures(1, &tex);
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
|
||||
return .{
|
||||
.atlas = atl,
|
||||
.freetype = freetype,
|
||||
|
@ -78,7 +85,7 @@ pub fn load() !FontInfo {
|
|||
.atlas_id = tex,
|
||||
.chars = chars,
|
||||
.line_height = line_height,
|
||||
.need_reupload = true,
|
||||
.need_reupload = false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -98,7 +105,7 @@ pub fn getChar(info: *FontInfo, codepoint: u21) !Character {
|
|||
const bmp = &info.font_face.*.glyph.*.bitmap;
|
||||
|
||||
const sprite = if (bmp.rows * bmp.width == 0)
|
||||
atlas.AtlasSprite{
|
||||
atlassian.AtlasSprite{
|
||||
.xmin = 0,
|
||||
.ymin = 0,
|
||||
.xmax = 0,
|
||||
|
@ -204,15 +211,29 @@ pub fn textVertices(
|
|||
}
|
||||
|
||||
pub fn renderText(vertices: []const f32, info: *FontInfo) void {
|
||||
gl.bindTexture(gl.TEXTURE_2D, info.atlas_id);
|
||||
|
||||
if (info.need_reupload) {
|
||||
std.log.info("reuploading font atlas", .{});
|
||||
info.need_reupload = false;
|
||||
try info.atlas.toGlTex(info.atlas_id);
|
||||
|
||||
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
|
||||
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
gl.RED,
|
||||
@intCast(info.atlas.stride),
|
||||
@intCast(@divExact(info.atlas.pixels.len, info.atlas.stride)),
|
||||
0,
|
||||
gl.RED,
|
||||
gl.UNSIGNED_BYTE,
|
||||
info.atlas.pixels.ptr,
|
||||
);
|
||||
}
|
||||
|
||||
gl.useProgram(GlState.state.font_shader_program);
|
||||
gl.bindVertexArray(GlState.state.font_vao);
|
||||
gl.bindTexture(gl.TEXTURE_2D, info.atlas_id);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, GlState.state.font_vbo);
|
||||
gl.bufferData(
|
||||
gl.ARRAY_BUFFER,
|
||||
|
|
Loading…
Reference in a new issue