Compare commits
No commits in common. "master" and "r0-to-allie" have entirely different histories.
master
...
r0-to-alli
@ -17,9 +17,11 @@ execute_process(
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
message(INFO ${LIBPIPEWIRE_CFLAGS})
|
||||
#add_compile_options("-I/nix/store/2hm4rjvywd00p417y43i9rzx8v793qi0-pipewire-1.4.5-dev/include/pipewire-0.3 -I/nix/store/2hm4rjvywd00p417y43i9rzx8v793qi0-pipewire-1.4.5-dev/include/spa-0.2")
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBPIPEWIRE_CFLAGS}")
|
||||
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
|
||||
# -I /nix/store/2hm4rjvywd00p417y43i9rzx8v793qi0-pipewire-1.4.5-dev/include/pipewire-0.3 \
|
||||
# -I /nix/store/2hm4rjvywd00p417y43i9rzx8v793qi0-pipewire-1.4.5-dev/include/spa-0.2 ")
|
||||
|
||||
add_compile_definitions(_POSIX_C_SOURCE=200112L)
|
||||
add_compile_definitions(_GNU_SOURCE)
|
||||
@ -41,12 +43,8 @@ add_executable(codegen_l1_5 src/l1_5/anne/codegen.c)
|
||||
#add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
#target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon)
|
||||
#
|
||||
add_executable(r2a src/l2/tests/r2/r2a.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
target_link_libraries(r2a ${LIBPIPEWIRE_LIBS} -lwayland-client -lrt -lm -lxkbcommon)
|
||||
|
||||
add_executable(r2c src/l2/tests/r2/r2c.c)
|
||||
target_link_libraries(r2c -lm)
|
||||
|
||||
#add_executable(2a_render_test src/l2/tests/r2/r2a.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
#target_link_libraries(2a_render_test ${LIBPIPEWIRE_LIBS} -lwayland-client -lrt -lm -lxkbcommon)
|
||||
#
|
||||
#add_executable(3_render_test src/l2/tests/r3/r3.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
#target_link_libraries(3_render_test -lwayland-client -lm -lvulkan -lxkbcommon)
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
Fonts used:
|
||||
DM Serif Text made by Colophon Foundry
|
||||
Roboto made by Christian Robertson, Paratype, Font Bureau
|
||||
Great Vibes made by Robert Leuschke
|
||||
@ -20,10 +20,6 @@ void generate_code_for_alice_on_l1(){
|
||||
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("RefListNodeAliceGenericMeshHand"), true, false);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("RefListNodeAliceShinyMeshHand"), true, false);
|
||||
|
||||
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
|
||||
.T = cstr("GenericMeshTopology")
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -7,13 +7,14 @@
|
||||
void generate_l1_lucy_headers(){
|
||||
SpanU8 l = cstr("l1"), ns = cstr("lucy");
|
||||
mkdir_nofail("l1/eve/lucy");
|
||||
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
|
||||
.T = cstr("LucyImage"), .t_primitive = true});
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("OptionLucyImage"), true, false);
|
||||
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){
|
||||
.T = cstr("LucyImage"), .t_primitive = true}, true);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("KVPU32ToLucyStoredGlyph"), true, false);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("KVPU32ToLucyFaceFixedSize"), true, false);
|
||||
|
||||
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("LucyGlyphCachingRequest"), true, true);
|
||||
/* Vector of iterators */
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("RefListNodeLucyImage"), true, false);
|
||||
|
||||
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
|
||||
.T = cstr("LucyPositionedStagingGlyph"), .vec = true, .sort = true,
|
||||
|
||||
@ -46,9 +46,72 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8
|
||||
"size_t %s_get_size_in_bytes(const %s* self) {\n"
|
||||
SPACE "return self->pixels.len * sizeof(%s);\n"
|
||||
"}\n\n", tex, tex, memb));
|
||||
/* Result<tex, VecU8> structure */
|
||||
/* Method _to_bitmap_text()
|
||||
* We use the assumption that bytes in type member are tightly packed
|
||||
* Actually, our current method of texture read/write is super inefficient
|
||||
*/
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"VecU8 %s_to_bitmap_text(const %s* self) {\n"
|
||||
SPACE "assert(SIZE_MAX / self->pixels.len >= 100);\n"
|
||||
SPACE "size_t len = self->pixels.len * sizeof(%s);\n"
|
||||
SPACE "VecU8 res = VecU8_new_zeroinit(8 + len);\n"
|
||||
SPACE "size_t width = self->width;\n"
|
||||
SPACE "size_t height = self->pixels.len / self->width;\n"
|
||||
SPACE "assert(UINT32_MAX / width >= 10 && UINT32_MAX / height >= 10);\n"
|
||||
SPACE "for (int i = 0; i < 4; i++)\n"
|
||||
SPACE SPACE "*VecU8_mat(&res, 0 + i) = (width >> (8 * i)) & 0xff;\n"
|
||||
SPACE "for (int i = 0; i < 4; i++)\n"
|
||||
SPACE SPACE "*VecU8_mat(&res, 4 + i) = (height >> (8 * i)) & 0xff;\n"
|
||||
SPACE "memcpy(res.buf + 8, self->pixels.buf, len);\n"
|
||||
SPACE "return res;\n"
|
||||
"}\n\n", tex, tex, memb));
|
||||
/* Method _write_to_file
|
||||
* Aborts on failure */
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"void %s_write_to_file(const %s* self, const char* path) {\n"
|
||||
SPACE "VecU8 data = %s_to_bitmap_text(self);\n"
|
||||
SPACE "write_whole_file_or_abort(path, VecU8_to_span(&data));\n"
|
||||
SPACE "VecU8_drop(data);\n"
|
||||
"}\n\n", tex, tex, tex));
|
||||
/* Result<tex, SpanU8> structure */
|
||||
VecU8 g_resoftex = get_ResultType_inst_name(tex, cstr("SpanU8"));
|
||||
SpanU8 resoftex = VecU8_to_span(&g_resoftex);
|
||||
VecU8_append_vec(&res, generate_result_template_inst(tex, cstr("SpanU8"), false, true));
|
||||
/* I also add this, because why not?? Maye I will use it in the future... */
|
||||
VecU8_append_vec(&res, generate_result_template_inst(tex, cstr("VecU8"), false, false));
|
||||
/* Method _from_bitmap_text()
|
||||
* We assume that bytes are tightly packed in member type */
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"%s %s_from_bitmap_text(SpanU8 text) {\n"
|
||||
SPACE "if (text.len < 8)\n"
|
||||
SPACE SPACE "return (%s){.variant = Result_Err, .err = cstr(\"No header *crying emoji*\")};\n"
|
||||
SPACE "size_t width = 0, height = 0;\n"
|
||||
SPACE "for (int i = 0; i < 4; i++)\n"
|
||||
SPACE SPACE "width |= (((size_t)*SpanU8_at(text, 0 + i)) << (8 * i));\n"
|
||||
SPACE "for (int i = 0; i < 4; i++)\n"
|
||||
SPACE SPACE "height |= (((size_t)*SpanU8_at(text, 4 + i)) << (8 * i));\n"
|
||||
SPACE "if (SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10)\n"
|
||||
SPACE SPACE "return (%s){.variant = Result_Err, .err = cstr(\"Image is too big\")};\n"
|
||||
SPACE "size_t len = width * height * sizeof(%s);\n"
|
||||
SPACE "if (text.len < 8 + len)\n"
|
||||
SPACE SPACE "return (%s){.variant = Result_Err, .err = cstr(\"Texture size and file size mismatch\")};\n"
|
||||
SPACE "%s res = %s_new(width, height);\n"
|
||||
SPACE "memcpy(res.pixels.buf, text.data + 8, len);\n"
|
||||
SPACE "return (%s){.variant = Result_Ok, .ok = res};\n"
|
||||
"}\n\n", resoftex, tex, resoftex, resoftex, memb, resoftex, tex, tex, resoftex));
|
||||
/* Method _read_from_file */
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"%s %s_read_from_file(SpanU8 path) {\n"
|
||||
SPACE "VecU8 data = read_whole_file_or_abort(path);\n"
|
||||
SPACE "%s res = %s_from_bitmap_text(VecU8_to_span(&data));\n"
|
||||
SPACE "if (res.variant != Result_Ok) {\n"
|
||||
SPACE SPACE "fprintf(stderr, \"Tried loading bitmap texture from file, but encountered decoding error: \");\n"
|
||||
SPACE SPACE "SpanU8_fprint(res.err, stderr);\n"
|
||||
SPACE SPACE "abortf(\"\\n\");\n"
|
||||
SPACE "}\n"
|
||||
SPACE "VecU8_drop(data);\n"
|
||||
SPACE "return res.ok;\n"
|
||||
"}\n\n", tex, tex, resoftex, tex));
|
||||
/* Method _is_inside() */
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"bool %s_is_inside(const %s* self, S32 x, S32 y) {\n"
|
||||
@ -83,6 +146,7 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8
|
||||
SPACE "}\n"
|
||||
"}\n\n", tex, tex, memb, tex, luminosity_formula));
|
||||
|
||||
VecU8_drop(g_resoftex);
|
||||
VecU8_drop(g_pixvec);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
typedef struct {
|
||||
VecU8 result;
|
||||
VecU8 filename;
|
||||
VecU8 nt_filename;
|
||||
} GeneratedHeader;
|
||||
|
||||
NODISCARD GeneratedHeader begin_header(SpanU8 filename) {
|
||||
@ -26,13 +26,14 @@ NODISCARD GeneratedHeader begin_header(SpanU8 filename) {
|
||||
VecU8_append_span(&res, cstr("\n#define "));
|
||||
VecU8_append_vec(&res, guard);
|
||||
VecU8_append_span(&res, cstr("\n/* Automatically generated file. Do not edit it. */\n\n"));
|
||||
return (GeneratedHeader){.result = res, .filename = VecU8_from_span(filename) };
|
||||
return (GeneratedHeader){.result = res, .nt_filename = VecU8_fmt("%s%c", filename, 0) };
|
||||
}
|
||||
|
||||
/* Codegen script's working directory should be `gen` */
|
||||
void finish_header(GeneratedHeader header) {
|
||||
VecU8_append_span(&header.result, cstr("#endif\n"));
|
||||
write_file_by_path(header.filename, VecU8_to_span(&header.result));
|
||||
write_whole_file_or_abort((const char*)header.nt_filename.buf, VecU8_to_span(&header.result));
|
||||
VecU8_drop(header.nt_filename);
|
||||
VecU8_drop(header.result);
|
||||
}
|
||||
|
||||
@ -42,7 +43,9 @@ void finish_header(GeneratedHeader header) {
|
||||
#define SPACE16 " "
|
||||
|
||||
void finish_layer(SpanU8 layer_name) {
|
||||
write_file_by_path(VecU8_fmt("%s/dorothy.txt", layer_name), cstr(""));
|
||||
VecU8 nt_name = VecU8_fmt("%s/dorothy.txt%c", layer_name, 0);
|
||||
write_whole_file_or_abort((const char*)nt_name.buf, cstr(""));
|
||||
VecU8_drop(nt_name);
|
||||
}
|
||||
|
||||
int get_number_of_parts_in_header_namespace(SpanU8 ns) {
|
||||
@ -85,7 +88,9 @@ NODISCARD VecU8 prepend_spaces_to_SpanU8_lines(SpanU8 lines, int tabulation){
|
||||
void generate_SOME_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, VecU8 body, VecU8 name){
|
||||
VecU8 text = VecU8_fmt("/* Automatically generated file. Don't edit it.\n"
|
||||
"* Don't include it in more than one place */\n\n%v", body);
|
||||
write_file_by_path(VecU8_fmt("%s/eve/%s/%v.h", layer, bonus_ns, name), VecU8_to_span(&text));
|
||||
VecU8 nt_path = VecU8_fmt("%s/eve/%s/%v.h%c", layer, bonus_ns, name, 0);
|
||||
write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text));
|
||||
VecU8_drop(nt_path);
|
||||
VecU8_drop(text);
|
||||
}
|
||||
|
||||
@ -111,9 +116,4 @@ NODISCARD VecU8 codegen_include_relative_to_root(SpanU8 bonus_ns, SpanU8 abs_pat
|
||||
return res;
|
||||
}
|
||||
|
||||
/* returns back `type` string, but if it is "", returns "void" instead */
|
||||
SpanU8 c_type_empty_means_void(SpanU8 type){
|
||||
return type.len > 0 ? type : cstr("void");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -209,7 +209,7 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
|
||||
}
|
||||
|
||||
// todo: generate a special span method to check equality of contents
|
||||
bool SpanU8_cont_equal(SpanU8 a, SpanU8 b) {
|
||||
bool strings_in_spans_equal(SpanU8 a, SpanU8 b) {
|
||||
if (a.len != b.len)
|
||||
return false;
|
||||
for (size_t i = 0; i < a.len; i++) {
|
||||
@ -235,7 +235,7 @@ U32 SpanU8_decode_as_utf8(SpanU8* rem){
|
||||
if (rem->len < (size_t)sz)
|
||||
return 0;
|
||||
U32 res = first & (b - 1);
|
||||
for (int i = 1; i <= sz; i++) {
|
||||
for (int i = 1; i < sz; i++) {
|
||||
U8 th = rem->data[0];
|
||||
if ((th & 0b11000000) != 0b10000000)
|
||||
return 0;
|
||||
@ -252,12 +252,4 @@ U32 SpanU8_decode_as_utf8(SpanU8* rem){
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SpanU8_is_prefix(SpanU8 a, SpanU8 str){
|
||||
return str.len >= a.len && SpanU8_cont_equal(a, SpanU8_span(str, 0, a.len));
|
||||
}
|
||||
|
||||
bool SpanU8_is_postfix(SpanU8 a, SpanU8 str){
|
||||
return str.len >= a.len && SpanU8_cont_equal(a, SpanU8_span(str, str.len - a.len, a.len));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -13,4 +13,12 @@ typedef struct{
|
||||
U32 len;
|
||||
} U32Segment;
|
||||
|
||||
U64 U64Segment_get_length_resp_alignment(U64Segment self, U8 alignment_exp) {
|
||||
if (self.start & ((1ull << alignment_exp) - 1)) {
|
||||
U64 pad_left = (1ull << alignment_exp) - (self.start & ((1ull << alignment_exp) - 1));
|
||||
return self.len >= pad_left ? self.len - pad_left : 0;
|
||||
}
|
||||
return self.len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -16,18 +16,24 @@ typedef struct {
|
||||
};
|
||||
} Result_VecU8_or_int;
|
||||
|
||||
void Result_VecU8_or_int_drop(Result_VecU8_or_int obj) {
|
||||
if (obj.variant == Result_Ok)
|
||||
VecU8_drop(obj.Ok);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Result_variant variant;
|
||||
int Err;
|
||||
} Result_ok_or_int;
|
||||
|
||||
/* path is VecU8. Aborts on error */
|
||||
NODISCARD VecU8 read_file_by_path(VecU8 path){
|
||||
VecU8_append(&path, 0);
|
||||
FILE* fp = fopen((const char*)path.buf, "rb");
|
||||
void Result_ok_or_int_drop(Result_ok_or_int obj) {}
|
||||
|
||||
NODISCARD VecU8 read_whole_file_or_abort(SpanU8 path) {
|
||||
VecU8 filename = VecU8_fmt("%s%c", path, 0);
|
||||
FILE* fp = fopen((const char*)filename.buf, "rb");
|
||||
if (!fp)
|
||||
abortf("Can't open file %s: %s\n", (const char*)path.buf, strerror(errno));
|
||||
VecU8_drop(path);
|
||||
abortf("Can't open file %s: %s\n", (const char*)filename.buf, strerror(errno));
|
||||
VecU8_drop(filename);
|
||||
if (fseek(fp, 0, SEEK_END) != 0) {
|
||||
abortf("fseek: %s\n", strerror(errno));
|
||||
}
|
||||
@ -40,18 +46,23 @@ NODISCARD VecU8 read_file_by_path(VecU8 path){
|
||||
}
|
||||
VecU8 result = (VecU8){.buf = safe_malloc(file_size), .len = file_size, .capacity = file_size};
|
||||
size_t nread = fread(result.buf, 1, (size_t)file_size, fp);
|
||||
if ((long)nread < file_size) {
|
||||
if (nread < file_size) {
|
||||
abortf("fread\n");
|
||||
}
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
||||
|
||||
void write_file_by_path(VecU8 path, SpanU8 content){
|
||||
VecU8_append(&path, 0);
|
||||
FILE* fd = fopen((const char*)path.buf, "wb");
|
||||
NODISCARD VecU8 read_file_by_path(VecU8 path){
|
||||
VecU8 content = read_whole_file_or_abort(VecU8_to_span(&path));
|
||||
VecU8_drop(path);
|
||||
return content;
|
||||
}
|
||||
|
||||
void write_whole_file_or_abort(const char* filename, SpanU8 content) {
|
||||
FILE* fd = fopen(filename, "wb");
|
||||
if (!fd) {
|
||||
abortf("Can't open file %s: %s\n", (const char*)path.buf, strerror(errno));
|
||||
abortf("Can't open file %s: %s\n", filename, strerror(errno));
|
||||
}
|
||||
if (fwrite(content.data, 1, content.len, fd) < content.len) {
|
||||
abortf("fwrite\n");
|
||||
|
||||
@ -3,38 +3,38 @@
|
||||
int main(){
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i", 0);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("0")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("0")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i%i%i%i", -1LL, 0LL, 44LL, -231LL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("-1044-231")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("-1044-231")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i", 44LL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("44")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("44")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%u", 44ULL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("44")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("44")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%u %i", 18446744073709551615ULL, -1LL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("18446744073709551615 -1")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("18446744073709551615 -1")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i %i", 9223372036854775807LL, -9223372036854775807LL-1);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("9223372036854775807 -9223372036854775808")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("9223372036854775807 -9223372036854775808")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 vec2 = vcstr("vec2");
|
||||
VecU8 res = VecU8_fmt("%i %v %i", -1230LL, vec2, 1340LL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("-1230 vec2 1340")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("-1230 vec2 1340")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -4,16 +4,13 @@
|
||||
#include "l1_5_templ_very_base.h"
|
||||
#include "margaret.h"
|
||||
#include "lucy.h"
|
||||
#include "gui.h"
|
||||
|
||||
int main() {
|
||||
mkdir_nofail("l1_5");
|
||||
mkdir_nofail("l1_5/eve");
|
||||
generate_l1_5_liza_headers();
|
||||
generate_l1_5_template_instantiation_for_base_types();
|
||||
generate_l1_5_template_instantiations_for_margaret();
|
||||
generate_l1_5_lucy_headers();
|
||||
generate_l1_5_gui_headers();
|
||||
finish_layer(cstr("l1_5"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
#ifndef prototype1_src_l1_5_anne_gui_h
|
||||
#define prototype1_src_l1_5_anne_gui_h
|
||||
|
||||
#include "../codegen/trait_wrap_boil.h"
|
||||
|
||||
void generate_l1_5_gui_headers(){
|
||||
mkdir_nofail("l1_5/eve/gui");
|
||||
SpanU8 l = cstr("l1_5"), ns = cstr("gui");
|
||||
generate_trait_wrapper_templ_inst_eve_header(l, ns, (trait_wrapper_boil_options){
|
||||
.trait = {
|
||||
.name = cstr("Widget"),
|
||||
.methods = (SpanNamedMethodSignatureRecordRef){
|
||||
.data = (NamedMethodSignatureRecordRef[]){
|
||||
{
|
||||
.takes_self = true,
|
||||
.takes_mut_self = true,
|
||||
.params = (SpanNamedVariableRecordRef){
|
||||
.data = (NamedVariableRecordRef[]){
|
||||
{ .type = cstr("uvec2"), .name = cstr("max_limits") }
|
||||
}, .len = 1
|
||||
},
|
||||
.return_type = cstr("uvec2"),
|
||||
.name = cstr("DRAW_PREPARE"),
|
||||
},
|
||||
{
|
||||
.takes_self = true,
|
||||
.takes_mut_self = true,
|
||||
.params = (SpanNamedVariableRecordRef){
|
||||
.data = (NamedVariableRecordRef[]){
|
||||
{ .type = cstr("ivec2"), .name = cstr("drawing_offset") },
|
||||
{ .type = cstr("uvec2"), .name = cstr("surface_sz") },
|
||||
{ .type = cstr("BorderS32"), .name = cstr("border") },
|
||||
}, .len = 3
|
||||
},
|
||||
.return_type = cstr(""),
|
||||
.name = cstr("DRAW"),
|
||||
}
|
||||
}, .len = 2
|
||||
},
|
||||
.drop_primitive = false,
|
||||
.base_struct_name = cstr("Widget"),
|
||||
},
|
||||
.box = true, .mut_ref = true
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -4,32 +4,8 @@
|
||||
#include "../codegen/trait_wrap_boil.h"
|
||||
|
||||
void generate_l1_5_liza_headers() {
|
||||
mkdir_nofail("l1_5/eve/liza");
|
||||
SpanU8 l = cstr("l1_5"), ns = cstr("liza");
|
||||
generate_trait_wrapper_templ_inst_eve_header(l, ns, (trait_wrapper_boil_options){
|
||||
.trait = {
|
||||
.name = cstr("LizaInstrument"),
|
||||
.methods = (SpanNamedMethodSignatureRecordRef){
|
||||
// todo: request options for instrument
|
||||
.data = (NamedMethodSignatureRecordRef[]){
|
||||
{
|
||||
.takes_self = true,
|
||||
.params = (SpanNamedVariableRecordRef){
|
||||
.data = (NamedVariableRecordRef[]){
|
||||
{.type = cstr("double"), .name = cstr("frequency") },
|
||||
{ .type = cstr("double"), .name = cstr("time") },
|
||||
}, .len = 2
|
||||
},
|
||||
.return_type = cstr("BoxLizaSound"),
|
||||
.name = cstr("ding"),
|
||||
}
|
||||
}, .len = 1
|
||||
},
|
||||
.drop_primitive = false,
|
||||
.base_struct_name = cstr(""),
|
||||
},
|
||||
.box = true, .ref = true, .mut_ref = true
|
||||
});
|
||||
mkdir_nofail("l1_5/liza");
|
||||
// todo: use#include "../codegen/trait_wrap_boil.h"
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -414,8 +414,7 @@ NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op
|
||||
return res;
|
||||
}
|
||||
|
||||
void generate_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op,
|
||||
bool generate_node_struct) {
|
||||
void generate_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op, bool generate_node_struct) {
|
||||
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
|
||||
generate_rbtree_Map_template_instantiation(op, generate_node_struct), get_name_of_rbtree_map_structure(op));
|
||||
}
|
||||
|
||||
@ -11,8 +11,6 @@ typedef struct {
|
||||
#include "../../../gen/l1/eve/embassy_l1_5/SpanNamedVariableRecordRef.h"
|
||||
|
||||
typedef struct {
|
||||
bool takes_self;
|
||||
bool takes_mut_self;
|
||||
SpanNamedVariableRecordRef params;
|
||||
SpanU8 return_type;
|
||||
SpanU8 name;
|
||||
@ -22,36 +20,24 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
SpanNamedMethodSignatureRecordRef methods;
|
||||
bool drop_primitive;
|
||||
SpanU8 name;
|
||||
/* It is usually either name or "void" */
|
||||
SpanU8 base_struct_name;
|
||||
} NamedTraitDefRecordRef;
|
||||
|
||||
NODISCARD VecU8 generate_trait_table_structure(NamedTraitDefRecordRef trait){
|
||||
VecU8 res = VecU8_from_cstr("typedef struct {\n");
|
||||
VecU8 res = VecU8_from_cstr("typedef struct {");
|
||||
// todo: add iteration macro
|
||||
for (size_t i = 0; i < trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = *SpanNamedMethodSignatureRecordRef_at(trait.methods, i);
|
||||
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s (*%s)(", c_type_empty_means_void(method.return_type), method.name));
|
||||
if (method.takes_self) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
method.takes_mut_self ? "%s*" : "const %s*",
|
||||
c_type_empty_means_void(trait.base_struct_name)));
|
||||
}
|
||||
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s (*%s)(", method.return_type, method.name));
|
||||
for (size_t p = 0; p < method.params.len; p++) {
|
||||
NamedVariableRecordRef param = *SpanNamedVariableRecordRef_at(method.params, p);
|
||||
if (p || method.takes_self)
|
||||
if (p)
|
||||
VecU8_append_span(&res, cstr(", "));
|
||||
VecU8_append_span(&res, param.type);
|
||||
}
|
||||
VecU8_append_span(&res, cstr(");\n"));
|
||||
}
|
||||
if (!trait.drop_primitive) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
SPACE "void (*drop)(%s*);\n",
|
||||
c_type_empty_means_void(trait.base_struct_name)));
|
||||
}
|
||||
VecU8_append_vec(&res, VecU8_fmt("} %s_Table;\n\n", trait.name));
|
||||
VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", trait.name));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -62,113 +48,10 @@ typedef struct {
|
||||
bool mut_ref;
|
||||
} trait_wrapper_boil_options;
|
||||
|
||||
/* (refkind, mut) in {(Ref, false), (MutRef, true), (Box, true)} */
|
||||
void codegen_append_trait_wrapper_structure_some_refkind(VecU8* res, NamedTraitDefRecordRef trait,
|
||||
SpanU8 refkind, bool mut){
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "%s%s* r;\n" /* epsilon / const, op.trait.base_struct_name */
|
||||
SPACE "const %s_Table* t;\n" /* op.trait.name */
|
||||
"} %s%s;\n\n", /* refkind, op.trait.name */
|
||||
mut ? cstr("") : cstr("const "),
|
||||
c_type_empty_means_void(trait.base_struct_name),
|
||||
trait.name, refkind, trait.name));
|
||||
}
|
||||
|
||||
/* (refkind, self_as_ptr) in {(Ref, false), (MutRef, false), (Box, true)} */
|
||||
void codegen_append_trait_wrapper_some_method_some_refkind(VecU8* res, SpanU8 trait_name,
|
||||
NamedMethodSignatureRecordRef method, SpanU8 refkind, bool self_as_ptr){
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"%s %s%s_%s(%s%s%s self",
|
||||
/* return_type, refkind, trait.name, method.name, refkind, trait.name */
|
||||
c_type_empty_means_void(method.return_type),
|
||||
refkind, trait_name, method.name, refkind, trait_name, self_as_ptr ? cstr("*") : cstr("")));
|
||||
for (size_t p = 0; p < method.params.len; p++) {
|
||||
NamedVariableRecordRef param = method.params.data[p];
|
||||
VecU8_append_vec(res, VecU8_fmt(", %s %s", param.type, param.name));
|
||||
}
|
||||
VecU8_append_span(res, cstr("){\n" SPACE));
|
||||
if (method.return_type.len > 0)
|
||||
VecU8_append_span(res, cstr("return "));
|
||||
VecU8_append_vec(res, VecU8_fmt("self%s""t->%s(",
|
||||
self_as_ptr ? cstr("->") : cstr("."),
|
||||
method.name));
|
||||
if (method.takes_self) {
|
||||
VecU8_append_vec(res, VecU8_fmt("self%s""r", self_as_ptr ? cstr("->") : cstr(".")));
|
||||
}
|
||||
for (size_t p = 0; p < method.params.len; p++) {
|
||||
NamedVariableRecordRef param = method.params.data[p];
|
||||
if (p > 0 || method.takes_self)
|
||||
VecU8_append_span(res, cstr(", "));
|
||||
VecU8_append_span(res, param.name);
|
||||
}
|
||||
VecU8_append_span(res, cstr(");\n}\n\n"));
|
||||
}
|
||||
|
||||
NODISCARD VecU8 generate_trait_wrapper_boilerplate(trait_wrapper_boil_options op) {
|
||||
/* Checking */
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
assert(!method.takes_mut_self || method.takes_self);
|
||||
}
|
||||
|
||||
VecU8 res = VecU8_new();
|
||||
VecU8_append_vec(&res, generate_trait_table_structure(op.trait));
|
||||
if (op.ref) {
|
||||
codegen_append_trait_wrapper_structure_some_refkind(&res, op.trait, cstr("Ref"), false);
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
if (method.takes_mut_self)
|
||||
continue;
|
||||
codegen_append_trait_wrapper_some_method_some_refkind(&res, op.trait.name, method, cstr("Ref"), false);
|
||||
}
|
||||
}
|
||||
if (op.mut_ref) {
|
||||
codegen_append_trait_wrapper_structure_some_refkind(&res, op.trait, cstr("MutRef"), true);
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
codegen_append_trait_wrapper_some_method_some_refkind(&res, op.trait.name, method, cstr("MutRef"), false);
|
||||
}
|
||||
}
|
||||
if (op.box) {
|
||||
codegen_append_trait_wrapper_structure_some_refkind(&res, op.trait, cstr("Box"), true);
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
codegen_append_trait_wrapper_some_method_some_refkind(&res, op.trait.name, method, cstr("Box"), true);
|
||||
}
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"void Box%s_drop(Box%s self){\n" /* trait.name, trait.name */
|
||||
"%s" /* epsilon / calling self.t->drop() */
|
||||
SPACE "free(self.r);\n"
|
||||
"}\n\n",
|
||||
op.trait.name, op.trait.name,
|
||||
op.trait.drop_primitive ? cstr("") : cstr(SPACE "self.t->drop(self.r);\n")));
|
||||
if (op.ref) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"Ref%s Box%s_ref(Box%s *self) {\n"
|
||||
SPACE "return (Ref%s){.r = self->r, .t = self->t};\n"
|
||||
"}\n\n", op.trait.name, op.trait.name, op.trait.name, op.trait.name));
|
||||
}
|
||||
if (op.mut_ref) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"MutRef%s Box%s_mut_ref(Box%s *self) {\n"
|
||||
SPACE "return (MutRef%s){.r = self->r, .t = self->t};\n"
|
||||
"}\n\n", op.trait.name, op.trait.name, op.trait.name, op.trait.name));
|
||||
}
|
||||
}
|
||||
// todo: write it
|
||||
return res;
|
||||
}
|
||||
|
||||
void generate_trait_wrapper_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, trait_wrapper_boil_options op){
|
||||
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_trait_wrapper_boilerplate(op),
|
||||
VecU8_from_span(op.trait.name));
|
||||
}
|
||||
|
||||
void generate_trait_wrapper_templ_inst_guarded_header(SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies,
|
||||
trait_wrapper_boil_options op){
|
||||
generate_SOME_templ_inst_guarded_header(layer, bonus_ns,
|
||||
VecU8_fmt("#include <stdlib.h>\n%s", dependencies),
|
||||
generate_trait_wrapper_boilerplate(op), VecU8_from_span(op.trait.name));
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -20,7 +20,7 @@ void stdin_skip_whitespaces(){
|
||||
}
|
||||
}
|
||||
|
||||
// Aborts on error, skips whitespaces
|
||||
// Aborts on error
|
||||
OptionU64 stdin_read_U64(){
|
||||
stdin_skip_whitespaces();
|
||||
U64 x = 0;
|
||||
|
||||
@ -1,230 +0,0 @@
|
||||
#ifndef prototype1_src_l1_5_core_parsing_string_h
|
||||
#define prototype1_src_l1_5_core_parsing_string_h
|
||||
|
||||
#include "../../l1/core/VecU8_as_str.h"
|
||||
#include <math.h>
|
||||
|
||||
void SpanU8_parsing_expect_char(SpanU8* rem, char ch){
|
||||
if (rem->len == 0) {
|
||||
abortf("Unexpected EOF. Syntax error\n");
|
||||
}
|
||||
if (*rem->data != (U8)ch) {
|
||||
abortf("Expected %d, got %d. Syntax error\n", (int)(*rem->data), (int)ch);
|
||||
}
|
||||
rem->data++;
|
||||
rem->len--;
|
||||
}
|
||||
|
||||
/* if `expected` is prefix of `rem`, `rem` will be advanced by |`expected`| and true will be returned.
|
||||
* Otherwise false is returned and `rem` is untouched */
|
||||
bool SpanU8_parsing_try_read_prefix(SpanU8* rem, SpanU8 expected){
|
||||
if (rem->len < expected.len) {
|
||||
return false;
|
||||
}
|
||||
if (SpanU8_cont_equal(SpanU8_span(*rem, 0, expected.len), expected)) {
|
||||
rem->data += expected.len;
|
||||
rem->len -= expected.len;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpanU8_parsing_try_read_char(SpanU8* rem, char ch){
|
||||
if (rem->len == 0) {
|
||||
return false;
|
||||
}
|
||||
if (rem->data[0] == (U8)ch) {
|
||||
rem->data++;
|
||||
rem->len--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SpanU8_parsing_skip_entire_line(SpanU8* rem){
|
||||
while (rem->len > 0) {
|
||||
U8 ch = *(rem->data++);
|
||||
rem->len--;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SpanU8_parsing_skip_char(SpanU8* rem){
|
||||
assert(rem->len > 0);
|
||||
rem->data++;
|
||||
rem->len--;
|
||||
}
|
||||
|
||||
bool SpanU8_parsing_is_char_ahead(SpanU8* rem, char ch){
|
||||
return rem->len > 0 ? rem->data[0] == (U8)ch : false;
|
||||
}
|
||||
|
||||
/* Time to learn how to read integers */
|
||||
|
||||
/* returns positive on error, returns 0 on success */
|
||||
int SpanU8_read_U64(SpanU8* rem_ret, U64* res_ret){
|
||||
SpanU8 rem = *rem_ret;
|
||||
U64 x = 0;
|
||||
while (rem.len > 0) {
|
||||
U8 ch = *rem.data;
|
||||
if (!('0' <= ch && ch <= '9')) {
|
||||
break;
|
||||
}
|
||||
U64 d = (U64)(ch - '0');
|
||||
if (x == 0 && rem_ret->data != rem.data) {
|
||||
return 1;
|
||||
}
|
||||
if (x > UINT64_MAX / 10) {
|
||||
return 2;
|
||||
}
|
||||
x *= 10;
|
||||
if (x > UINT64_MAX - d) {
|
||||
return 2;
|
||||
}
|
||||
x += d;
|
||||
rem.data++;
|
||||
rem.len--;
|
||||
}
|
||||
if (rem_ret->data == rem.data) {
|
||||
return 1;
|
||||
}
|
||||
*res_ret = x;
|
||||
*rem_ret = rem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
U64 SpanU64_expect_read_U64(SpanU8* rem){
|
||||
U64 x;
|
||||
int code = SpanU8_read_U64(rem, &x);
|
||||
if (code)
|
||||
abortf("Failed to read U64. Syntax error\n");
|
||||
return x;
|
||||
}
|
||||
|
||||
int SpanU8_read_S64(SpanU8* rem_ret, S64* ret){
|
||||
SpanU8 rem = *rem_ret;
|
||||
U64 x = 0;
|
||||
bool saw_minus = false;
|
||||
bool saw_digit = false;
|
||||
while (rem.len > 0) {
|
||||
U8 ch = *rem.data;
|
||||
if ('0' <= ch && ch <= '9') {
|
||||
U64 d = (U64)(ch - '0');
|
||||
if (x == 0 && rem_ret->len - rem.len > (U64)saw_minus) {
|
||||
return 1;
|
||||
}
|
||||
if (x > 9223372036854775808UL / 10) {
|
||||
return 2;
|
||||
}
|
||||
x *= 10;
|
||||
if (x > 9223372036854775808UL - d) {
|
||||
return 2;
|
||||
}
|
||||
x += d;
|
||||
saw_digit = true;
|
||||
} else if (ch == '-') {
|
||||
if (rem_ret->data != rem.data) {
|
||||
break;
|
||||
}
|
||||
saw_minus = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
rem.data++;
|
||||
rem.len--;
|
||||
}
|
||||
if (!saw_digit) {
|
||||
return 1;
|
||||
}
|
||||
assert(x <= 9223372036854775808UL);
|
||||
if (x == 9223372036854775808UL) {
|
||||
if (saw_minus) {
|
||||
*ret = -9223372036854775807L-1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
} else {
|
||||
if (saw_minus) {
|
||||
*ret = -(S64)x;
|
||||
} else {
|
||||
*ret = (S64)x;
|
||||
}
|
||||
}
|
||||
*rem_ret = rem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* returns positive int on error, 0 on success */
|
||||
int SpanU8_read_float(SpanU8* rem_ret, float* res_ret){
|
||||
SpanU8 rem = *rem_ret;
|
||||
|
||||
float res = 0;
|
||||
bool saw_minus = false;
|
||||
bool saw_digit = false;
|
||||
bool saw_dot = false;
|
||||
float mul = 1;
|
||||
|
||||
while (rem.len > 0) {
|
||||
U8 ch = *rem.data;
|
||||
if (ch == '.') {
|
||||
if (saw_dot) {
|
||||
return 1;
|
||||
}
|
||||
saw_dot = true;
|
||||
} else if (ch == '-') {
|
||||
if (rem_ret->data != rem.data) {
|
||||
break;
|
||||
}
|
||||
saw_minus = true;
|
||||
} else if ('0' <= ch && ch <= '9') {
|
||||
float d = (float)(ch - '0');
|
||||
if (saw_dot) {
|
||||
mul /= 10.f;
|
||||
res = (res + d * mul);
|
||||
} else {
|
||||
res = (res * 10 + d);
|
||||
}
|
||||
saw_digit = true;
|
||||
} else if (ch == 'e') {
|
||||
SpanU8_parsing_skip_char(&rem);
|
||||
S64 exp;
|
||||
int ret = SpanU8_read_S64(&rem, &exp);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (exp > 1000 || exp < -999) {
|
||||
return 2;
|
||||
}
|
||||
/* If compiler won't perform pow optimization here, I will throw my chair out of the window */
|
||||
res = res * powf(10.f, (float)exp);
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
rem.data++;
|
||||
rem.len--;
|
||||
}
|
||||
if (!saw_digit) {
|
||||
return 1;
|
||||
}
|
||||
if (saw_dot && mul == 1.f) {
|
||||
return 1;
|
||||
}
|
||||
if (saw_minus) {
|
||||
res = -(res);
|
||||
}
|
||||
*res_ret = res;
|
||||
*rem_ret = rem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
float SpanU8_expect_read_float(SpanU8* rem){
|
||||
float x;
|
||||
int code = SpanU8_read_float(rem, &x);
|
||||
if (code)
|
||||
abortf("Failed to read float. Syntax error\n");
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -29,7 +29,7 @@ bool string_contains_string_ignorecase(SpanU8 str1, SpanU8 str2) {
|
||||
|
||||
bool is_string_in_string_vec(SpanU8 a, const VecVecU8* B) {
|
||||
for (size_t i = 0; i < B->len; i++) {
|
||||
if (SpanU8_cont_equal(a, VecU8_to_span(VecVecU8_at(B, i))))
|
||||
if (strings_in_spans_equal(a, VecU8_to_span(VecVecU8_at(B, i))))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -59,7 +59,6 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
vec3 pos;
|
||||
vec3 color;
|
||||
} ShinyMeshVertexInc;
|
||||
|
||||
typedef struct {
|
||||
@ -86,6 +85,7 @@ ShinyMeshTopology ShinyMeshTopology_clone(const ShinyMeshTopology* self) {
|
||||
|
||||
typedef struct{
|
||||
mat4 model_t;
|
||||
vec3 color_off;
|
||||
vec3 color_on;
|
||||
} ShinyMeshInstanceInc;
|
||||
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
#ifndef prototype1_src_l2_alice_model_file_h
|
||||
#define prototype1_src_l2_alice_model_file_h
|
||||
|
||||
#include "../../../gen/l1/VecAndSpan_vec2.h"
|
||||
#include "../../../gen/l1/VecAndSpan_vec3.h"
|
||||
#include "../../l1_5/core/parsing_string.h"
|
||||
#include "../../l1/system/fileio.h"
|
||||
#include "assets.h"
|
||||
#include "stdalign.h"
|
||||
@ -11,7 +8,7 @@
|
||||
static_assert(sizeof(float) == 4, "...");
|
||||
static_assert(sizeof(GenericMeshVertexInc) == 4 * (3 + 2), "...");
|
||||
static_assert(alignof(GenericMeshVertexInc) == 4, "...");
|
||||
static_assert(sizeof(ShinyMeshVertexInc) == 4 * (3 + 3), "...");
|
||||
static_assert(sizeof(ShinyMeshVertexInc) == 4 * (3), "...");
|
||||
static_assert(alignof(ShinyMeshVertexInc) == 4, "...");
|
||||
|
||||
/* Yes, at this point I really started thinking that maybe I should have written Alice as a template */
|
||||
@ -29,8 +26,10 @@ void alice_write_generic_mesh_to_file(GenericMeshTopology model, VecU8 file_path
|
||||
memcpy(buf, model.vertices.buf, model.vertices.len * sizeof(GenericMeshVertexInc));
|
||||
buf += model.vertices.len * sizeof(GenericMeshVertexInc);
|
||||
memcpy(buf, model.indexes.buf, model.indexes.len * sizeof(U32));
|
||||
write_file_by_path(file_path, VecU8_to_span(&res));
|
||||
VecU8_append(&file_path, 0);
|
||||
write_whole_file_or_abort((const char*)file_path.buf, VecU8_to_span(&res));
|
||||
GenericMeshTopology_drop(model);
|
||||
VecU8_drop(file_path);
|
||||
VecU8_drop(res);
|
||||
}
|
||||
|
||||
@ -72,8 +71,10 @@ void alice_write_shiny_mesh_to_file(ShinyMeshTopology model, VecU8 file_path){
|
||||
memcpy(buf, model.vertices.buf, model.vertices.len * sizeof(ShinyMeshVertexInc));
|
||||
buf += model.vertices.len * sizeof(ShinyMeshVertexInc);
|
||||
memcpy(buf, model.indexes.buf, model.indexes.len * sizeof(U32));
|
||||
write_file_by_path(file_path, VecU8_to_span(&res));
|
||||
VecU8_append(&file_path, 0);
|
||||
write_whole_file_or_abort((const char*)file_path.buf, VecU8_to_span(&res));
|
||||
ShinyMeshTopology_drop(model);
|
||||
VecU8_drop(file_path);
|
||||
VecU8_drop(res);
|
||||
}
|
||||
|
||||
@ -102,143 +103,6 @@ ShinyMeshTopology alice_expect_read_shiny_mesh_from_file(VecU8 file_path){
|
||||
return (ShinyMeshTopology){.vertices = vertices, .indexes = indexes};
|
||||
}
|
||||
|
||||
/* Just read code, okay? Just read source code, I can't explain THAT */
|
||||
int alice_obj_file_parser_try_read_vert_index(SpanU8* rem, U64 limit, S32* ret_ind){
|
||||
SpanU8_parsing_try_read_char(rem, '/');
|
||||
U64 x;
|
||||
if (SpanU8_read_U64(rem, &x)) {
|
||||
*ret_ind = -1;
|
||||
} else {
|
||||
if (x == 0)
|
||||
return 1;
|
||||
x--;
|
||||
if (x >= limit)
|
||||
return 3;
|
||||
*ret_ind = (S32)x;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In wavefront .obj file each face consists of 3 vertices and each vertex in a face
|
||||
* can be specified in the following forms: v, v/vt, v//vn, v/vt/vn. vn is of course ignored,
|
||||
* because only sussies store normal vectors in a file.
|
||||
* Returns positive on error. 0 on success. Don't read source code
|
||||
*/
|
||||
int alice_obj_file_parser_try_read_vertex_data(SpanU8* rem, U64 vertices_pos_limit, U64 vertices_tex_limit,
|
||||
S32* ret_pos_ind, S32* ret_tex_ind){
|
||||
int ret;
|
||||
ret = alice_obj_file_parser_try_read_vert_index(rem, vertices_pos_limit, ret_pos_ind);
|
||||
if (ret) {
|
||||
return 3;
|
||||
}
|
||||
if (*ret_pos_ind < 0) {
|
||||
return 1;
|
||||
}
|
||||
ret = alice_obj_file_parser_try_read_vert_index(rem, vertices_tex_limit, ret_tex_ind);
|
||||
if (ret > 0) {
|
||||
return 3;
|
||||
}
|
||||
S32 who_cares;
|
||||
alice_obj_file_parser_try_read_vert_index(rem, UINT64_MAX, &who_cares);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GenericMeshVertexInc alice_obj_file_parser_retrieve_data_from_vertex_arrays(
|
||||
const Vecvec3* vertex_pos, const Vecvec2* vertex_tex, S32 pos_ind, S32 tex_ind){
|
||||
return (GenericMeshVertexInc){
|
||||
.pos = *Vecvec3_at(vertex_pos, (U64)pos_ind),
|
||||
.tex = tex_ind >= 0 ? *Vecvec2_at(vertex_tex, (U64)tex_ind) : (vec2){0, 0}
|
||||
};
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/eve/alice/OptionGenericMeshTopology.h"
|
||||
|
||||
/* My life f****** sucks so much */
|
||||
OptionGenericMeshTopology alice_read_generic_mesh_from_obj_file(VecU8 file_path){
|
||||
Vecvec3 vertex_pos = Vecvec3_new();
|
||||
Vecvec2 vertex_tex = Vecvec2_new();
|
||||
VecU8 text_buffer = read_file_by_path(file_path);
|
||||
VecGenericMeshVertexInc mesh_vertices = VecGenericMeshVertexInc_new();
|
||||
VecU32 mesh_indexes = VecU32_new();
|
||||
SpanU8 text = VecU8_to_span(&text_buffer);
|
||||
while (text.len > 0) {
|
||||
if (SpanU8_parsing_try_read_prefix(&text, cstr("v "))) {
|
||||
float x, y, z;
|
||||
if (SpanU8_read_float(&text, &x))
|
||||
goto failure;
|
||||
if (!SpanU8_parsing_try_read_char(&text, ' '))
|
||||
goto failure;
|
||||
if (SpanU8_read_float(&text, &y))
|
||||
goto failure;
|
||||
if (!SpanU8_parsing_try_read_char(&text, ' '))
|
||||
goto failure;
|
||||
if (SpanU8_read_float(&text, &z))
|
||||
goto failure;
|
||||
if (!SpanU8_parsing_try_read_char(&text, '\n'))
|
||||
goto failure;
|
||||
Vecvec3_append(&vertex_pos, (vec3){x, y, z});
|
||||
} else if (SpanU8_parsing_try_read_prefix(&text, cstr("vt "))) {
|
||||
float u, v;
|
||||
if (SpanU8_read_float(&text, &u))
|
||||
goto failure;
|
||||
if (!SpanU8_parsing_try_read_char(&text, ' '))
|
||||
goto failure;
|
||||
if (SpanU8_read_float(&text, &v))
|
||||
goto failure;
|
||||
if (!SpanU8_parsing_try_read_char(&text, '\n'))
|
||||
goto failure;
|
||||
Vecvec2_append(&vertex_tex, (vec2){u, v});
|
||||
} else if (SpanU8_parsing_try_read_prefix(&text, cstr("f "))) {
|
||||
S32 pos_ind, tex_ind;
|
||||
if (alice_obj_file_parser_try_read_vertex_data(&text,
|
||||
vertex_pos.len, vertex_tex.len, &pos_ind, &tex_ind)) {
|
||||
goto failure;
|
||||
}
|
||||
GenericMeshVertexInc A = alice_obj_file_parser_retrieve_data_from_vertex_arrays(
|
||||
&vertex_pos, &vertex_tex, pos_ind, tex_ind);
|
||||
if (!SpanU8_parsing_try_read_char(&text, ' '))
|
||||
goto failure;
|
||||
|
||||
if (alice_obj_file_parser_try_read_vertex_data(&text,
|
||||
vertex_pos.len, vertex_tex.len, &pos_ind, &tex_ind)) {
|
||||
goto failure;
|
||||
}
|
||||
GenericMeshVertexInc B = alice_obj_file_parser_retrieve_data_from_vertex_arrays(
|
||||
&vertex_pos, &vertex_tex, pos_ind, tex_ind);
|
||||
if (!SpanU8_parsing_try_read_char(&text, ' '))
|
||||
goto failure;
|
||||
|
||||
if (alice_obj_file_parser_try_read_vertex_data(&text,
|
||||
vertex_pos.len, vertex_tex.len, &pos_ind, &tex_ind)) {
|
||||
goto failure;
|
||||
}
|
||||
GenericMeshVertexInc C = alice_obj_file_parser_retrieve_data_from_vertex_arrays(
|
||||
&vertex_pos, &vertex_tex, pos_ind, tex_ind);
|
||||
if (!SpanU8_parsing_try_read_char(&text, '\n'))
|
||||
goto failure;
|
||||
|
||||
VecGenericMeshVertexInc_append(&mesh_vertices, A);
|
||||
VecGenericMeshVertexInc_append(&mesh_vertices, B);
|
||||
VecGenericMeshVertexInc_append(&mesh_vertices, C);
|
||||
U64 k = mesh_vertices.len;
|
||||
VecU32_append_span(&mesh_indexes, (SpanU32){.data = (U32[]){k - 3, k - 2, k - 1}, .len = 3});
|
||||
} else {
|
||||
SpanU8_parsing_skip_entire_line(&text);
|
||||
}
|
||||
}
|
||||
/* End */
|
||||
return Some_GenericMeshTopology((GenericMeshTopology){.vertices = mesh_vertices, .indexes = mesh_indexes});
|
||||
failure:
|
||||
VecGenericMeshVertexInc_drop(mesh_vertices);
|
||||
VecU32_drop(mesh_indexes);
|
||||
return None_GenericMeshTopology();
|
||||
}
|
||||
|
||||
GenericMeshTopology alice_expect_read_generic_mesh_from_obj_file(VecU8 file_path){
|
||||
OptionGenericMeshTopology option = alice_read_generic_mesh_from_obj_file(file_path);
|
||||
return OptionGenericMeshTopology_expect(option);
|
||||
}
|
||||
|
||||
/* No beauty, just pure brute force */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@ -11,7 +11,6 @@ Callbacks(..), aliceMainloop, newAlice, aliceSetSkyColor, aliceNewLucyFace,
|
||||
aliceLucyFaceOfSize, lucyFaceAddGlyphs, aliceClearText, aliceAddText,
|
||||
aliceAddGenericMeshHand, aliceGenericMeshResizeInstanceArr, aliceGenericMeshSetInst,
|
||||
aliceAddShinyMeshHand, aliceShinyMeshResizeInstanceArr, aliceShinyMeshSetInst, aliceGetCamBack,
|
||||
aliceGetCamRight, aliceGetCamUp, aliceSetFOV,
|
||||
aliceGetCamPos, aliceSetCamPos, aliceSetPointLightCount, aliceSetPointLight,
|
||||
aliceIsPressed
|
||||
) where
|
||||
@ -23,6 +22,7 @@ import Data.Int (Int8, Int16, Int32, Int64)
|
||||
import Foreign.Ptr (Ptr, FunPtr, nullPtr, plusPtr, castPtr)
|
||||
import Foreign.Marshal.Alloc (alloca)
|
||||
import Foreign.Storable (Storable(..))
|
||||
import Data.IORef (newIORef, readIORef, writeIORef, modifyIORef)
|
||||
import qualified Data.Text
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Data.ByteString (useAsCStringLen)
|
||||
@ -58,16 +58,17 @@ instance Storable AliceGenericMeshInstance where
|
||||
peek _ = error "Please don't"
|
||||
poke ptr (AliceGenericMeshInstance modelT) = poke (castPtr ptr :: Ptr Mat4) modelT
|
||||
|
||||
-- model_t color_on
|
||||
data AliceShinyMeshInstance = AliceShinyMeshInstance Mat4 Vec3
|
||||
-- model_t color_off color_on
|
||||
data AliceShinyMeshInstance = AliceShinyMeshInstance Mat4 Vec3 Vec3
|
||||
|
||||
instance Storable AliceShinyMeshInstance where
|
||||
sizeOf _ = sizeOf (undefined :: Mat4) + sizeOf (undefined :: Vec3)
|
||||
sizeOf _ = sizeOf (undefined :: Mat4)
|
||||
alignment _ = 4
|
||||
peek _ = error "Don't do that, please"
|
||||
poke ptr (AliceShinyMeshInstance modelT colorOn) = do
|
||||
poke ptr (AliceShinyMeshInstance modelT colorOff colorOn) = do
|
||||
poke (castPtr ptr :: Ptr Mat4) modelT
|
||||
poke (castPtr (ptr `plusPtr` (sizeOf (undefined :: Mat4))) :: Ptr Vec3) colorOn
|
||||
poke (castPtr (ptr `plusPtr` (sizeOf (undefined :: Mat4)) ) :: Ptr Vec3) colorOff
|
||||
poke (castPtr (ptr `plusPtr` (sizeOf (undefined :: Mat4)) `plusPtr` (sizeOf (undefined :: Vec3))) :: Ptr Vec3) colorOn
|
||||
|
||||
-- pos color
|
||||
data AlicePointLight = AlicePointLight Vec3 Vec3
|
||||
@ -96,6 +97,17 @@ aliceMainloop alice cb = alloca $ \ptr -> do
|
||||
poke ptr cb
|
||||
allieAliceMainloop alice ptr
|
||||
|
||||
--aliceClearScreenTextLabel :: AliceAnotherFrameCap s -> IO ()
|
||||
--aliceClearScreenTextLabel (AliceAnotherFrameCap alice) = allieAliceClearScreenText alice
|
||||
|
||||
--aliceAddScreenTextLabel :: AliceAnotherFrameCap s -> String -> IO ()
|
||||
--aliceAddScreenTextLabel (AliceAnotherFrameCap alice) str = useAsCStringLen
|
||||
-- (encodeUtf8 $ Data.Text.pack $ str) $ \(cstr, len) ->
|
||||
-- allieAliceAddScreenTextLabel alice (castPtr cstr) (fromIntegral len)
|
||||
|
||||
|
||||
--allieRunAlice :: Callbacks ->
|
||||
|
||||
useAsUtf8StringLen :: String -> (Ptr Word8 -> Word64 -> IO a) -> IO a
|
||||
useAsUtf8StringLen str cb = useAsCStringLen (encodeUtf8 $ Data.Text.pack $ str) $ \(cstr, len) -> cb (castPtr cstr) (fromIntegral len)
|
||||
|
||||
@ -168,20 +180,7 @@ aliceGetCamBack alice = alloca $ \ptr -> do
|
||||
allie_alice_get_cam_back alice ptr
|
||||
peek ptr
|
||||
|
||||
foreign import ccall "allie_alice_get_cam_right" allie_alice_get_cam_right :: Alice -> Ptr Vec3 -> IO ()
|
||||
|
||||
aliceGetCamRight :: Alice -> IO Vec3
|
||||
aliceGetCamRight alice = alloca $ \ptr -> do
|
||||
allie_alice_get_cam_right alice ptr
|
||||
peek ptr
|
||||
|
||||
foreign import ccall "allie_alice_get_cam_up" allie_alice_get_cam_up :: Alice -> Ptr Vec3 -> IO ()
|
||||
|
||||
aliceGetCamUp :: Alice -> IO Vec3
|
||||
aliceGetCamUp alice = alloca $ \ptr -> do
|
||||
allie_alice_get_cam_up alice ptr
|
||||
peek ptr
|
||||
|
||||
-- todo: add right and up
|
||||
|
||||
foreign import ccall "allie_alice_get_cam_pos" allie_alice_get_cam_pos :: Alice -> Ptr Vec3 -> IO ()
|
||||
|
||||
@ -195,9 +194,6 @@ foreign import ccall "allie_alice_set_cam_pos" allie_alice_set_cam_pos :: Alice
|
||||
aliceSetCamPos :: Alice -> Vec3 -> IO ()
|
||||
aliceSetCamPos alice (Vec3 x y z) = allie_alice_set_cam_pos alice x y z
|
||||
|
||||
-- Easy mapping
|
||||
foreign import ccall "allie_alice_set_fov" aliceSetFOV :: Alice -> Float -> IO ()
|
||||
|
||||
-- Maps well
|
||||
foreign import ccall "allie_alice_set_point_light_count" aliceSetPointLightCount :: Alice -> Int -> IO ()
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
module Geom(Vec2(..), Vec3(..), Vec4(..), Mat4(..), Addable(..), Multipliable(..), mat4Transit, mat4rot3d,
|
||||
HasLength, normalize) where
|
||||
module Geom(Vec2(..), Vec3(..), Vec4(..), Mat4(..), Addable(..), Multipliable(..), mat4Transit) where
|
||||
|
||||
import Foreign.Storable(Storable(..))
|
||||
import Foreign.Ptr (Ptr, castPtr, plusPtr)
|
||||
@ -44,24 +43,10 @@ instance Multipliable Vec4 Float Vec4 where
|
||||
|
||||
data Mat4 = Mat4 !Vec4 !Vec4 !Vec4 !Vec4
|
||||
|
||||
instance Multipliable Mat4 Vec4 Vec4 where
|
||||
(Mat4 vx vy vz vw) ^*^ (Vec4 ax ay az aw) = (vx ^*^ ax ^+^ vy ^*^ ay ^+^ vz ^*^ az ^+^ vw ^*^ aw)
|
||||
|
||||
instance Multipliable Mat4 Mat4 Mat4 where
|
||||
m ^*^ (Mat4 bx by bz bw) = Mat4 (m ^*^ bx) (m ^*^ by) (m ^*^ bz) (m ^*^ bw)
|
||||
|
||||
mat4Transit :: Vec3 -> Mat4
|
||||
mat4Transit (Vec3 x y z) = Mat4 (Vec4 1 0 0 0) (Vec4 0 1 0 0) (Vec4 0 0 1 0) (Vec4 x y z 1)
|
||||
|
||||
mat4rot3d :: Vec3 -> Float -> Mat4
|
||||
mat4rot3d (Vec3 rx ry rz) a = let cosa = cos(a) in let sina = sin(a) in
|
||||
Mat4
|
||||
(Vec4 (rx * rx * (1 - cosa) + cosa) (rx * ry * (1 - cosa) + sina * rz) (rx * rz * (1 - cosa) - sina * ry) 0)
|
||||
(Vec4 (rx * ry * (1 - cosa) - sina * rz) (ry * ry * (1 - cosa) + cosa) (ry * rz * (1 - cosa) + sina * rx) 0)
|
||||
(Vec4 (rx * rz * (1 - cosa) + sina * ry) (ry * rz * (1 - cosa) - sina * rx) (rz * rz * (1 - cosa) + cosa) 0)
|
||||
|
||||
(Vec4 0 0 0 1)
|
||||
|
||||
|
||||
|
||||
instance Storable Vec2 where
|
||||
sizeOf _ = 2 * sizeOf (undefined :: Float)
|
||||
@ -127,13 +112,4 @@ instance Storable Mat4 where
|
||||
poke (castPtr ptr) v1
|
||||
poke (ptr `plusPtr` vec4Size) v2
|
||||
poke (ptr `plusPtr` (2 * vec4Size)) v3
|
||||
poke (ptr `plusPtr` (3 * vec4Size)) v4
|
||||
|
||||
class HasLength a where
|
||||
vlength :: a -> Float
|
||||
|
||||
normalize :: (Multipliable a Float a, HasLength a) => a -> a
|
||||
normalize v = v ^*^ (1 / (vlength v))
|
||||
|
||||
instance HasLength Vec2 where
|
||||
vlength (Vec2 a b) = sqrt (a * a + b * b)
|
||||
poke (ptr `plusPtr` (3 * vec4Size)) v4
|
||||
@ -431,35 +431,35 @@ AlicePipeline0b create_graphics_pipeline_0_b(
|
||||
{
|
||||
.location = 1, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshVertexInc, color),
|
||||
},
|
||||
{
|
||||
.location = 2, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshVertex, normal),
|
||||
},
|
||||
|
||||
/* This is a mat4 datatype, so it will take 4 entire 'locations' */
|
||||
{
|
||||
.location = 3, .binding = 1,
|
||||
.location = 2, .binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, x)
|
||||
},
|
||||
{
|
||||
.location = 4, .binding = 1,
|
||||
.location = 3, .binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, y)
|
||||
},
|
||||
{
|
||||
.location = 5, .binding = 1,
|
||||
.location = 4, .binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, z)
|
||||
},
|
||||
{
|
||||
.location = 6, .binding = 1,
|
||||
.location = 5, .binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, w)
|
||||
},
|
||||
{
|
||||
.location = 6, .binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstanceInc, color_off)
|
||||
},
|
||||
{
|
||||
.location = 7, .binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
@ -660,6 +660,7 @@ void Jane_alice_destroy(VkDevice device, Jane_alice jane) {
|
||||
vkDestroyFence(device, jane.roxy, NULL);
|
||||
}
|
||||
|
||||
// todo: handle case where presentation and graphics are from the same family
|
||||
typedef struct {
|
||||
VkQueue graphics_queue;
|
||||
VkQueue presentation_queue;
|
||||
@ -823,14 +824,7 @@ struct Alice {
|
||||
};
|
||||
|
||||
ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, AliceGenericMeshPath paths){
|
||||
GenericMeshTopology topology;
|
||||
if (SpanU8_is_postfix(cstr(".AliceGenericMesh"), VecU8_to_span(&paths.topology_path) )) {
|
||||
topology = alice_expect_read_generic_mesh_from_file(paths.topology_path);
|
||||
} else if (SpanU8_is_postfix(cstr(".obj"), VecU8_to_span(&paths.topology_path) )) {
|
||||
topology = alice_expect_read_generic_mesh_from_obj_file(paths.topology_path);
|
||||
} else {
|
||||
abortf("Иди своей дорогой\n");
|
||||
}
|
||||
GenericMeshTopology topology = alice_expect_read_generic_mesh_from_file(paths.topology_path);
|
||||
|
||||
ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand));
|
||||
AliceGenericMeshHand* mm = &mm_node->el;
|
||||
@ -1401,6 +1395,83 @@ void recreate_swapchain(Alice *alice) {
|
||||
alice->swfb = new_swfb;
|
||||
}
|
||||
|
||||
// todo: delete it
|
||||
/* It is just a stupid example */
|
||||
void update_state(Alice* alice) {
|
||||
float fl = AliceWaylandApp_get_elapsed_time(&alice->wl);
|
||||
// todo: ok, maybe I don't want an example. I am good enough
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_w])
|
||||
// CamControlInfo_forward(&alice->scene.cam, fl);
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_s])
|
||||
// CamControlInfo_backward(&alice->scene.cam, fl);
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_a])
|
||||
// CamControlInfo_left(&alice->scene.cam, fl);
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_d])
|
||||
// CamControlInfo_right(&alice->scene.cam, fl);
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_q])
|
||||
// CamControlInfo_down(&alice->scene.cam, fl);
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_e])
|
||||
// CamControlInfo_up(&alice->scene.cam, fl);
|
||||
//
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_bracketright]) {
|
||||
// for (size_t i = 0; i < alice->scene.smeshnyavka_3.len; i++) {
|
||||
// ObjectInfo* oi = &alice->scene.smeshnyavka_3.buf[i];
|
||||
// vec3 p1 = alice->scene.cam.pos;
|
||||
// vec3 r = vec3_normalize(vec3_minus_vec3(p1, oi->pos));
|
||||
// oi->rotation = mat3_mul_mat3(marie_3d_rot_mat3(r, fl * 0.7f), oi->rotation);
|
||||
// Scene_update_smeshnyavka_3(&alice->scene, i);
|
||||
// }
|
||||
// }
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_bracketleft]) {
|
||||
// for (size_t i = 0; i < alice->scene.smeshnyavka_1.len; i++) {
|
||||
// ObjectInfo* oi = &alice->scene.smeshnyavka_1.buf[i];
|
||||
// oi->rotation = mat3_mul_mat3(marie_3d_rot_mat3((vec3){0, 0, 1}, fl * 0.4f), oi->rotation);
|
||||
// Scene_update_smeshnyavka_1(&alice->scene, i);
|
||||
// }
|
||||
// }
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_minus]) {
|
||||
// for (size_t i = 0; i < alice->scene.smeshnyavka_3.len; i++) {
|
||||
// ObjectInfo* oi = &alice->scene.smeshnyavka_3.buf[i];
|
||||
// vec3 p1 = alice->scene.cam.pos;
|
||||
// float dist = vec3_length(vec3_minus_vec3(p1, oi->pos));
|
||||
// float fac = 80/dist;
|
||||
// oi->scale *= (1 - 0.01f * fl * fac);
|
||||
// Scene_update_smeshnyavka_3(&alice->scene, i);
|
||||
// }
|
||||
// }
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_equal]) {
|
||||
// for (size_t i = 0; i < alice->scene.smeshnyavka_3.len; i++) {
|
||||
// ObjectInfo* oi = &alice->scene.smeshnyavka_3.buf[i];
|
||||
// vec3 p1 = alice->scene.cam.pos;
|
||||
// float dist = vec3_length(vec3_minus_vec3(p1, oi->pos));
|
||||
// float fac = 80/dist;
|
||||
// oi->scale *= (1 + 0.01f * fl * fac);
|
||||
// Scene_update_smeshnyavka_3(&alice->scene, i);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// GenericModelOnSceneMem* model = VecGenericModelOnSceneMem_mat(&alice->scene.generic_models, 0);
|
||||
// assert(model->instance_attr.count >= 1);
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_j]) {
|
||||
// alice->scene.smeshnyavka_1.buf[0].pos.x -= fl;
|
||||
// Scene_update_smeshnyavka_1(&alice->scene, 0);
|
||||
// }
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_k]) {
|
||||
// alice->scene.smeshnyavka_1.buf[0].pos.z -= fl;
|
||||
// Scene_update_smeshnyavka_1(&alice->scene, 0);
|
||||
// }
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_l]) {
|
||||
// alice->scene.smeshnyavka_1.buf[0].pos.z += fl;
|
||||
// Scene_update_smeshnyavka_1(&alice->scene, 0);
|
||||
// }
|
||||
// if (alice->wl.first_0x80_keys[XKB_KEY_semicolon]) {
|
||||
// alice->scene.smeshnyavka_1.buf[0].pos.x += fl;
|
||||
// Scene_update_smeshnyavka_1(&alice->scene, 0);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/* It creates image views, descriptor sets, framebuffers. But not for generic models.
|
||||
* If we ever gonna do defragmentation, this step would have to be repeated */
|
||||
void alice_create_mem_dependant_vk_obj(Alice* alice){
|
||||
@ -1666,6 +1737,18 @@ static void alice_mainloop_h_wl_keyboard_key(
|
||||
alice->callbacks.on_wl_keyboard_key(alice->guest, keysym, key_action);
|
||||
if (key_action == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
if (keysym == XKB_KEY_1) {
|
||||
// vec3 p = alice->cam_info.pos;
|
||||
// p.y += 1.5f;
|
||||
// ShinyModelOnSceneMem* model = VecShinyModelOnSceneMem_mat(&alice->scene.shiny_models, 0);
|
||||
// assert(model->instance_attr.count >= 1);
|
||||
// VecObjectInfo_mat(&alice->scene.smeshnyavka_3, 0)->pos = p;
|
||||
// Scene_update_smeshnyavka_3(&alice->scene, 0);
|
||||
//
|
||||
// Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->scene.pipeline0_ubo.staging_updatable);
|
||||
// assert(ubo->point_light_count >= 1);
|
||||
// ubo->point_light_arr[0].pos = p;
|
||||
//
|
||||
// printf("Point light source pos set to %f %f %f\n", p.x, p.y, p.z);
|
||||
} else if (keysym == XKB_KEY_2) {
|
||||
alice->rendering_config.hdr_factor /= 1.05f;
|
||||
printf("hdr factor decreased to %f\n", alice->rendering_config.hdr_factor);
|
||||
@ -1891,13 +1974,8 @@ Alice* Alice_new(){
|
||||
|
||||
alice->device = margaret_create_logical_device(alice->physical_device, alice->queue_fam);
|
||||
|
||||
if (alice->queue_fam.for_graphics == alice->queue_fam.for_presentation) {
|
||||
vkGetDeviceQueue(alice->device, alice->queue_fam.for_graphics, 0, &alice->queues.graphics_queue);
|
||||
alice->queues.presentation_queue = alice->queues.graphics_queue;
|
||||
} else {
|
||||
vkGetDeviceQueue(alice->device, alice->queue_fam.for_graphics, 0, &alice->queues.graphics_queue);
|
||||
vkGetDeviceQueue(alice->device, alice->queue_fam.for_presentation, 0, &alice->queues.presentation_queue);
|
||||
}
|
||||
vkGetDeviceQueue(alice->device, alice->queue_fam.for_graphics, 0, &alice->queues.graphics_queue);
|
||||
vkGetDeviceQueue(alice->device, alice->queue_fam.for_presentation, 0, &alice->queues.presentation_queue);
|
||||
|
||||
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(
|
||||
alice->physical_device, alice->surface, alice->wl.sane_image_extent_limit);
|
||||
@ -1964,10 +2042,11 @@ Alice* Alice_new(){
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
||||
/* | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT */,
|
||||
mem_type_id_device_local, 6, false, 10000);
|
||||
mem_type_id_device_local, 6, false, 16);
|
||||
|
||||
alice->dev_local_images = MargaretImgAllocator_new(alice->device, alice->physical_device,
|
||||
mem_type_id_device_local, 16000000);
|
||||
mem_type_id_device_local, 16);
|
||||
|
||||
|
||||
alice->jane = Jane_alice_create(alice->device);
|
||||
/* Luckily, swapchain image allocation is not managed by me */
|
||||
@ -2027,6 +2106,15 @@ void Alice_set_point_light(Alice* alice, int index, Pipeline0PointLight data){
|
||||
ubo->point_light_arr[index] = data;
|
||||
}
|
||||
|
||||
|
||||
void Alice_clear_screen_text(Alice* alice){
|
||||
LucyRenderer_clear(&alice->lucy_renderer);
|
||||
}
|
||||
|
||||
void Alice_add_screen_text(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs, vec4 color, SpanU8 text, ivec2 start_pos){
|
||||
LucyRenderer_add_text(&alice->lucy_renderer, ffs, color, 0, text, start_pos);
|
||||
}
|
||||
|
||||
/* This function actually consumes alice handler. Alice must not be used after */
|
||||
void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) {
|
||||
alice->callbacks.on_wl_keyboard_key = callbacks->on_wl_keyboard_key;
|
||||
@ -2118,7 +2206,7 @@ void allie_alice_clear_text(Alice* alice){
|
||||
void allie_alice_add_text(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs,
|
||||
float color_x, float color_y, float color_z, float color_w, const U8* text_data, U64 text_len,
|
||||
S32 start_pos_x, S32 start_pos_y){
|
||||
LucyRenderer_add_simple_label(&alice->lucy_renderer, ffs, (vec4){color_x, color_y, color_z, color_w}, 0,
|
||||
LucyRenderer_add_text(&alice->lucy_renderer, ffs, (vec4){color_x, color_y, color_z, color_w}, 0,
|
||||
(SpanU8){text_data, text_len}, (ivec2){start_pos_x, start_pos_y});
|
||||
}
|
||||
|
||||
@ -2148,6 +2236,26 @@ void allie_alice_shiny_mesh_resize_instance_arr(Alice* alice, ListNodeAliceShiny
|
||||
AliceShinyMeshHand_resize_instance_arr(alice, &mesh_hand->el, new_count);
|
||||
}
|
||||
|
||||
// void allie_alice_generic_mesh_set_inst(
|
||||
// ListNodeAliceGenericMeshHand* mesh_hand, U64 index,
|
||||
// float xx, float xy, float xz, float xw, float yx, float yy, float yz, float yw,
|
||||
// float zx, float zy, float zz, float zw, float wx, float wy, float wz, float ww){
|
||||
// AliceGenericMeshHand_set_inst(&mesh_hand->el, index, (GenericMeshInstanceInc){.model_t = {
|
||||
// .x = {xx, xy, xz, xw}, .y = {yx, yy, yz, yw}, .z = {zx, zy, zz, zw}, .w = {wx, wy, wz, ww},
|
||||
// }});
|
||||
// }
|
||||
//
|
||||
// void allie_alice_shiny_mesh_set_inst(
|
||||
// ListNodeAliceGenericMeshHand* mesh_hand, U64 index,
|
||||
// float xx, float xy, float xz, float xw, float yx, float yy, float yz, float yw,
|
||||
// float zx, float zy, float zz, float zw, float wx, float wy, float wz, float ww,
|
||||
// float clr_off_x, float clr_off_y, float clr_off_z, float clr_off_w,
|
||||
// float clr_on_x, float clr_on_y, float clr_on_z, float clr_on_w){
|
||||
// AliceShinyMeshHand_set_inst(&mesh_hand->el, index, (ShinyMeshInstanceInc){.model_t = {
|
||||
// }, .color_on = {}});
|
||||
//
|
||||
// }
|
||||
|
||||
void allie_alice_generic_mesh_set_inst(
|
||||
ListNodeAliceGenericMeshHand* mesh_hand, U64 index, const GenericMeshInstanceInc* inst){
|
||||
AliceGenericMeshHand_set_inst(&mesh_hand->el, index, *inst);
|
||||
@ -2179,7 +2287,7 @@ void allie_alice_set_cam_pos(Alice* alice, float x, float y, float z){
|
||||
}
|
||||
|
||||
void allie_alice_set_fov(Alice* alice, float fov){
|
||||
alice->cam_info.cam.fov = MIN_float(MAX_float(fov, 0.001), M_PIf - 0.01);
|
||||
alice->cam_info.cam.fov = fov;
|
||||
}
|
||||
|
||||
void allie_alice_set_point_light_count(Alice* alice, int new_count){
|
||||
|
||||
@ -598,37 +598,37 @@ GenericMeshTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
|
||||
|
||||
U32 quad_to_triangles_conv_arr[6] = {0, 1, 2, 0, 2, 3};
|
||||
|
||||
ShinyMeshTopology generate_shiny_cube(vec3 color) {
|
||||
ShinyMeshTopology generate_shiny_cube(float r) {
|
||||
ShinyMeshVertexInc vert[24] = {
|
||||
{{+1, +1, +1}, color},
|
||||
{{+1, -1, +1}, color},
|
||||
{{+1, -1, -1}, color},
|
||||
{{+1, +1, -1}, color},
|
||||
{{+r, +r, +r}},
|
||||
{{+r, -r, +r}},
|
||||
{{+r, -r, -r}},
|
||||
{{+r, +r, -r}},
|
||||
|
||||
{{-1, -1, -1}, color},
|
||||
{{-1, -1, +1}, color},
|
||||
{{-1, +1, +1}, color},
|
||||
{{-1, +1, -1}, color},
|
||||
{{-r, -r, -r}},
|
||||
{{-r, -r, +r}},
|
||||
{{-r, +r, +r}},
|
||||
{{-r, +r, -r}},
|
||||
|
||||
{{+1, +1, +1}, color},
|
||||
{{+1, +1, -1}, color},
|
||||
{{-1, +1, -1}, color},
|
||||
{{-1, +1, +1}, color},
|
||||
{{+r, +r, +r}},
|
||||
{{+r, +r, -r}},
|
||||
{{-r, +r, -r}},
|
||||
{{-r, +r, +r}},
|
||||
|
||||
{{-1, -1, -1}, color},
|
||||
{{+1, -1, -1}, color},
|
||||
{{+1, -1, +1}, color},
|
||||
{{-1, -1, +1}, color},
|
||||
{{-r, -r, -r}},
|
||||
{{+r, -r, -r}},
|
||||
{{+r, -r, +r}},
|
||||
{{-r, -r, +r}},
|
||||
|
||||
{{+1, +1, +1}, color},
|
||||
{{-1, +1, +1}, color},
|
||||
{{-1, -1, +1}, color},
|
||||
{{+1, -1, +1}, color},
|
||||
{{+r, +r, +r}},
|
||||
{{-r, +r, +r}},
|
||||
{{-r, -r, +r}},
|
||||
{{+r, -r, +r}},
|
||||
|
||||
{{-1, -1, -1}, color},
|
||||
{{-1, +1, -1}, color},
|
||||
{{+1, +1, -1}, color},
|
||||
{{+1, -1, -1}, color},
|
||||
{{-r, -r, -r}},
|
||||
{{-r, +r, -r}},
|
||||
{{+r, +r, -r}},
|
||||
{{+r, -r, -r}},
|
||||
};
|
||||
VecShinyMeshVertexInc vertices_vec = VecShinyMeshVertexInc_from_span(
|
||||
(SpanShinyMeshVertexInc){ .data = vert, .len = ARRAY_SIZE(vert) });
|
||||
@ -685,22 +685,6 @@ MarieTriangle restore_triangle_from_mesh_topology(const VecGenericMeshVertexInc*
|
||||
};
|
||||
}
|
||||
|
||||
void r4_generate_flat_normal_map(VecU8 save_path){
|
||||
TextureDataR8G8B8A8 normal = TextureDataR8G8B8A8_new(1, 1);
|
||||
*TextureDataR8G8B8A8_mat(&normal, 0, 0) = compress_normal_vec_into_norm_texel((vec3){0, 1, 0});
|
||||
TextureDataR8G8B8A8_write_to_png_nofail(&normal, VecU8_to_span(&save_path));
|
||||
VecU8_drop(save_path);
|
||||
TextureDataR8G8B8A8_drop(normal);
|
||||
}
|
||||
|
||||
void generate_single_pixel_gray_tex(VecU8 save_path, U8 clr){
|
||||
TextureDataR8 tex = TextureDataR8_new(1, 1);
|
||||
*TextureDataR8_mat(&tex, 0, 0) = clr;
|
||||
TextureDataR8_write_to_png_nofail(&tex, VecU8_to_span(&save_path));
|
||||
VecU8_drop(save_path);
|
||||
TextureDataR8_drop(tex);
|
||||
}
|
||||
|
||||
/* r is radius, w is length of cylinder. Will write everything into files for us */
|
||||
void r4_asset_gen_generic_mesh_cylinder(float s_resol, float r, float w, U32 k,
|
||||
VecU8 path_to_mesh, VecU8 path_to_template_tex, VecU8 path_to_normal_tex){
|
||||
@ -807,8 +791,13 @@ void r4_asset_gen_generic_mesh_cylinder(float s_resol, float r, float w, U32 k,
|
||||
VecU8_drop(path_to_template_tex);
|
||||
TextureDataR8G8B8A8_drop(template);
|
||||
|
||||
/* Here I generate normal tex trivially. */
|
||||
TextureDataR8G8B8A8 normal = TextureDataR8G8B8A8_new(1, 1);
|
||||
*TextureDataR8G8B8A8_mat(&normal, 0, 0) = compress_normal_vec_into_norm_texel((vec3){0, 1, 0});
|
||||
/* Right now it's just a pixel... */
|
||||
r4_generate_flat_normal_map(path_to_normal_tex);
|
||||
TextureDataR8G8B8A8_write_to_png_nofail(&normal, VecU8_to_span(&path_to_normal_tex));
|
||||
VecU8_drop(path_to_normal_tex);
|
||||
TextureDataR8G8B8A8_drop(normal);
|
||||
}
|
||||
|
||||
void r4_asset_gen_generic_mesh_quad(float width, float length, VecU8 path_to_save){
|
||||
@ -895,16 +884,15 @@ int gen_assets_for_r4() {
|
||||
mkdir_nofail("l2/textures");
|
||||
mkdir_nofail("l2/textures/r4");
|
||||
generate_one_forth_of_a_cylinder_with_bublazhuzhka(10, 2, 6);
|
||||
alice_write_shiny_mesh_to_file(generate_shiny_cube((vec3){0.6f, 0.6f, 0.7f}), vcstr("l2/models/cube.AliceShinyMesh"));
|
||||
alice_write_shiny_mesh_to_file(generate_shiny_cube(0.3f), vcstr("l2/models/cube.AliceShinyMesh"));
|
||||
alice_write_shiny_mesh_to_file(generate_shiny_lamp(0.3f, 0.13f, 0.19f), vcstr("l2/models/lamp.AliceShinyMesh"));
|
||||
r4_asset_gen_generic_mesh_quad(10, 10, vcstr("l2/models/quad.AliceGenericMesh"));
|
||||
r4_asset_gen_generic_mesh_cylinder(200, 0.4f, 0.17f, 30, vcstr("l2/models/puck.AliceGenericMesh"),
|
||||
r4_asset_gen_generic_mesh_cylinder(200, 0.4f, 0.06f, 5, vcstr("l2/models/puck.AliceGenericMesh"),
|
||||
vcstr("l2/textures/puck_TEMPLATE.png"), vcstr("l2/textures/puck_NORMAL.png"));
|
||||
r4_asset_gen_generic_mesh_cylinder(100, 0.04f, 1.5f, 4, vcstr("l2/models/stick.AliceGenericMesh"),
|
||||
r4_asset_gen_generic_mesh_cylinder(80, 0.13f, 1.5f, 4, vcstr("l2/models/stick.AliceGenericMesh"),
|
||||
vcstr("l2/textures/stick_TEMPLATE.png"), vcstr("l2/textures/stick_NORMAL.png"));
|
||||
r4_generate_flat_normal_map(vcstr("l2/textures/flat_NORMAL.png"));
|
||||
generate_single_pixel_gray_tex(vcstr("l2/textures/no_SPECULAR.png"), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,7 +0,0 @@
|
||||
#ifndef prototype1_src_l2_gui_label_h
|
||||
#define prototype1_src_l2_gui_label_h
|
||||
|
||||
#include "../lucy/glyph_render.h"
|
||||
|
||||
|
||||
#endif
|
||||
@ -1,104 +0,0 @@
|
||||
#ifndef prototype1_src_l2_gui_widget_h
|
||||
#define prototype1_src_l2_gui_widget_h
|
||||
|
||||
#include "../../../gen/l1/geom.h"
|
||||
#include "../../l1/core/util.h"
|
||||
|
||||
#define WIDGET_DIM_INF 1000000
|
||||
|
||||
bool is_widget_size_limit_contain_inf(uvec2 max_limits){
|
||||
return max_limits.x >= WIDGET_DIM_INF || max_limits.y >= WIDGET_DIM_INF;
|
||||
}
|
||||
|
||||
void assert_sane_widget_size(uvec2 sz){
|
||||
assert(sz.x < WIDGET_DIM_INF || sz.y < WIDGET_DIM_INF);
|
||||
}
|
||||
|
||||
void assert_sane_widget_size_limits(uvec2 max_limits){
|
||||
assert(max_limits.x <= WIDGET_DIM_INF || max_limits.y <= WIDGET_DIM_INF);
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
ivec2 lt, rb;
|
||||
} BorderS32;
|
||||
|
||||
bool BorderS32_empty(BorderS32 self){
|
||||
return self.lt.x >= self.rb.x || self.lt.y >= self.rb.y;
|
||||
}
|
||||
|
||||
BorderS32 BorderS32_intersect(BorderS32 a, BorderS32 b){
|
||||
return (BorderS32){
|
||||
{MAX_S32(a.lt.x, b.lt.x), MAX_S32(a.lt.y, b.lt.y)},
|
||||
{MAX_S32(a.rb.x, b.rb.x), MAX_S32(a.rb.y, b.rb.y)},
|
||||
};
|
||||
}
|
||||
|
||||
uvec2 widget_size_max_of_all(uvec2 a, uvec2 b){
|
||||
return (uvec2){MAX_U32(a.x, b.x), MAX_U32(a.y, b.y)};
|
||||
}
|
||||
|
||||
uvec2 widget_size_min_of_all(uvec2 a, uvec2 b){
|
||||
return (uvec2){MIN_U32(a.x, b.x), MIN_U32(a.y, b.y)};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
/* .x == WIDGET_DIM_INF indicates that no preparation was made before the draw operation.
|
||||
* Calling draw at that state will cause abort. draw operation will reset this flag. This makes framework foolproof.
|
||||
* Initialize and reset with {WIDGET_DIM_INF, 0} */
|
||||
uvec2 sz_my_choice;
|
||||
} Widget;
|
||||
|
||||
Widget Widget_new(){
|
||||
return (Widget){.sz_my_choice = {WIDGET_DIM_INF, 0}};
|
||||
}
|
||||
|
||||
#include "../../../gen/l1_5/eve/gui/Widget.h"
|
||||
|
||||
uvec2 MutRefWidget_draw_prepare(MutRefWidget self, uvec2 max_limits){
|
||||
if (!self.r)
|
||||
return (uvec2){0};
|
||||
self.r->sz_my_choice = MutRefWidget_DRAW_PREPARE(self, max_limits);
|
||||
assert_sane_widget_size(self.r->sz_my_choice);
|
||||
return self.r->sz_my_choice;
|
||||
}
|
||||
|
||||
void MutRefWidget_draw(MutRefWidget self, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border){
|
||||
if (!self.r)
|
||||
return;
|
||||
if (self.r->sz_my_choice.x >= WIDGET_DIM_INF)
|
||||
abortf("Drawing widget before negotiating it's size\n");
|
||||
MutRefWidget_draw(self, drawing_offset, surface_sz, border);
|
||||
self.r->sz_my_choice = (uvec2){WIDGET_DIM_INF, 0};
|
||||
}
|
||||
|
||||
/* Some very simple widgets */
|
||||
|
||||
typedef struct {
|
||||
Widget base;
|
||||
U32 width;
|
||||
U32 height;
|
||||
} EmptyWidget;
|
||||
|
||||
uvec2 Widget_Table_EmptyWidget_DRAW_PREPARE(Widget* ug, uvec2 limits){
|
||||
EmptyWidget* self = (EmptyWidget*)ug;
|
||||
uvec2 R = widget_size_min_of_all((uvec2){self->width, self->height}, limits);
|
||||
return is_widget_size_limit_contain_inf(R) ? (uvec2){0, 0} : R;
|
||||
}
|
||||
|
||||
void Widget_Table_EmptyWidget_DRAW(Widget* ug, ivec2 drawing_offset, uvec2 surface_sz, BorderS32 border){}
|
||||
|
||||
void Widget_Table_EmptyWidget_drop(Widget* ug){}
|
||||
|
||||
const Widget_Table Widget_Table_EmptyWidget = {
|
||||
.DRAW_PREPARE = Widget_Table_EmptyWidget_DRAW_PREPARE,
|
||||
.DRAW = Widget_Table_EmptyWidget_DRAW,
|
||||
.drop = Widget_Table_EmptyWidget_drop,
|
||||
};
|
||||
|
||||
BoxWidget EmptyWidget_new_box(U32 width, U32 height){
|
||||
EmptyWidget* r = safe_malloc(sizeof(EmptyWidget));
|
||||
*r = (EmptyWidget){.base = Widget_new(), .width = width, .height = height};
|
||||
return (BoxWidget){.r = (Widget*)r, .t = &Widget_Table_EmptyWidget};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -3,7 +3,35 @@
|
||||
|
||||
#include "playing_sound_loop.h"
|
||||
|
||||
#include "../../../gen/l1_5/eve/liza/LizaInstrument.h"
|
||||
// todo: rewrite with the help of l1_5
|
||||
|
||||
typedef struct {
|
||||
/* self (takes ownership) */
|
||||
void (*drop)(void*);
|
||||
/* self, frequency, time, returns: new sound box */
|
||||
BoxLizaSound (*ding)(const void*, double, double);
|
||||
// todo: request options for instrument
|
||||
} LizaInstrument_Table;
|
||||
|
||||
typedef struct {
|
||||
const void* r;
|
||||
const LizaInstrument_Table* t;
|
||||
} RefLizaInstrument;
|
||||
|
||||
typedef struct {
|
||||
void* r;
|
||||
const LizaInstrument_Table* t;
|
||||
} MutLizaInstrument;
|
||||
|
||||
typedef struct {
|
||||
void* m;
|
||||
const LizaInstrument_Table* t;
|
||||
} BoxLizaInstrument;
|
||||
|
||||
void BoxLizaInstrument_drop(BoxLizaInstrument self) {
|
||||
self.t->drop(self.m);
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/eve/liza/VecBoxLizaInstrument.h"
|
||||
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
// todo: move loop here and rewrite with l1_5 help
|
||||
|
||||
#include "../../l1/core/int_primitives.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
/* self (takes ownership) */
|
||||
|
||||
@ -7,15 +7,12 @@
|
||||
#include "../../../gen/l1/VecAndSpan_U32Segment.h"
|
||||
#include "../../../gen/l1/vulkan/VecVkDescriptorImageInfo.h"
|
||||
#include "../../../gen/l1/pixel_masses.h"
|
||||
#include "../../../gen/l1/VecAndSpan_U32.h"
|
||||
|
||||
#include "../../l1_5/core/buff_rb_tree_node.h"
|
||||
#include "../../l1_5/core/rb_tree_node.h"
|
||||
|
||||
#define LUCY_MAX_DESCRIPTOR_COUNT 100
|
||||
|
||||
typedef U32 lucy_image_index_t;
|
||||
|
||||
typedef struct {
|
||||
/* This value is actually Option<MargaretSubbuf>. If staging_buffer is already deleted (after it is no longer used),
|
||||
* staging_buffer.len will be 0 */
|
||||
@ -23,16 +20,18 @@ typedef struct {
|
||||
MargaretImg img;
|
||||
VkImageView img_view;
|
||||
U64 usage;
|
||||
U64 pos_in_desc_array;
|
||||
/* 0 if this image isn't scheduled for deletion on th next cycle.
|
||||
* 1 if it is */
|
||||
int scheduled_for_deletion;
|
||||
} LucyImage;
|
||||
#include "../../../gen/l1/eve/lucy/ListLucyImage.h"
|
||||
|
||||
#include "../../../gen/l1/eve/lucy/OptionLucyImage.h"
|
||||
#include "../../../gen/l1/eve/lucy/VecOptionLucyImage.h"
|
||||
typedef ListNodeLucyImage* RefListNodeLucyImage;
|
||||
#include "../../../gen/l1/eve/lucy/VecRefListNodeLucyImage.h"
|
||||
|
||||
typedef struct {
|
||||
U32 img_slot_id;
|
||||
ListNodeLucyImage* img;
|
||||
U32 w, h;
|
||||
U32 advance_x;
|
||||
ivec2 bearing;
|
||||
@ -72,28 +71,22 @@ struct LucyFace {
|
||||
|
||||
struct LucyGlyphCache {
|
||||
MargaretEngineReference ve;
|
||||
VecOptionLucyImage image_slots;
|
||||
ListLucyImage images;
|
||||
VkDescriptorSetLayout descriptor_set_layout;
|
||||
VkDescriptorSet descriptor_set;
|
||||
|
||||
/* to_be_freed_of_old_staging_next_cycle never intersect with to_be_copied_to_device_next_cycle */
|
||||
VecU32 to_be_freed_of_old_staging_next_cycle;
|
||||
VecU32 to_be_copied_to_device_next_cycle;
|
||||
VecRefListNodeLucyImage to_be_freed_of_old_staging_next_cycle;
|
||||
VecRefListNodeLucyImage to_be_copied_to_device_next_cycle;
|
||||
/* deletion will be performed last */
|
||||
VecU32 to_be_deleted;
|
||||
VecRefListNodeLucyImage to_be_deleted;
|
||||
};
|
||||
|
||||
|
||||
LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve){
|
||||
VkDescriptorSetLayout my_desc_set_layout;
|
||||
VkDescriptorSetLayoutBindingFlagsCreateInfo set_layout_crinfo_flags = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
|
||||
.bindingCount = 1,
|
||||
.pBindingFlags = (VkDescriptorBindingFlags[]){ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT }
|
||||
};
|
||||
check(vkCreateDescriptorSetLayout(ve.device, &(VkDescriptorSetLayoutCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.pNext = &set_layout_crinfo_flags,
|
||||
.bindingCount = 1,
|
||||
.pBindings = (VkDescriptorSetLayoutBinding[]){{
|
||||
.binding = 0,
|
||||
@ -104,31 +97,20 @@ LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve){
|
||||
}, NULL, &my_desc_set_layout) == VK_SUCCESS);
|
||||
VkDescriptorSet descriptor_set = margaret_allocate_descriptor_set(ve.device, ve.descriptor_pool,
|
||||
my_desc_set_layout);
|
||||
VecOptionLucyImage image_slots = VecOptionLucyImage_new_zeroinit(LUCY_MAX_DESCRIPTOR_COUNT);
|
||||
for (size_t i = 0; i < LUCY_MAX_DESCRIPTOR_COUNT; i++) {
|
||||
image_slots.buf[i].variant = Option_None;
|
||||
}
|
||||
return (LucyGlyphCache){
|
||||
.ve = ve, .image_slots = image_slots,
|
||||
.descriptor_set_layout = my_desc_set_layout, .descriptor_set = descriptor_set,
|
||||
.to_be_freed_of_old_staging_next_cycle = VecU32_new(),
|
||||
.to_be_copied_to_device_next_cycle = VecU32_new(),
|
||||
.to_be_deleted = VecU32_new()};
|
||||
return (LucyGlyphCache){.ve = ve, .images = ListLucyImage_new(),
|
||||
.descriptor_set_layout = my_desc_set_layout, .descriptor_set = descriptor_set};
|
||||
}
|
||||
|
||||
void LucyFaceFixedSize_get_rid_of_myself(LucyFaceFixedSize* self){
|
||||
LucyGlyphCache* cache = self->p->p;
|
||||
BufRBTree_MapU32ToLucyStoredGlyph* glyphs = &self->glyphs;
|
||||
for (size_t gid = 0; gid < glyphs->el.len; gid++) {
|
||||
U32 slot_id = glyphs->el.buf[gid].value.img_slot_id;
|
||||
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&cache->image_slots, slot_id);
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
assert(img->usage > 0);
|
||||
if (--img->usage) {
|
||||
assert(!img->scheduled_for_deletion);
|
||||
img->scheduled_for_deletion = 1;
|
||||
VecU32_append(&cache->to_be_deleted, slot_id);
|
||||
ListNodeLucyImage* img = glyphs->el.buf[gid].value.img;
|
||||
assert(img->el.usage > 0);
|
||||
if (--img->el.usage) {
|
||||
assert(!img->el.scheduled_for_deletion);
|
||||
img->el.scheduled_for_deletion = 1;
|
||||
VecRefListNodeLucyImage_append(&cache->to_be_deleted, img);
|
||||
}
|
||||
}
|
||||
BufRBTree_MapU32ToLucyStoredGlyph_sink(glyphs);
|
||||
@ -152,7 +134,7 @@ typedef struct {
|
||||
TextureDataR8 bitmap;
|
||||
/* Will be determined in the next phase */
|
||||
uvec2 pos;
|
||||
U32 img_slot_id;
|
||||
ListNodeLucyImage* img;
|
||||
} LucyPositionedStagingGlyph;
|
||||
|
||||
bool LucyPositionedStagingGlyph_less_LucyPositionedStagingGlyph(
|
||||
@ -167,37 +149,18 @@ void LucyPositionedStagingGlyph_drop(LucyPositionedStagingGlyph self){
|
||||
/* Instantiation for helper type */
|
||||
#include "../../../gen/l1/eve/lucy/VecLucyPositionedStagingGlyph.h"
|
||||
|
||||
/* Helper function */
|
||||
U32 LucyGlyphCache_add_glyphs__find_image_slot(LucyGlyphCache* cache){
|
||||
for (U32 i = 0; i < cache->image_slots.len; i++) {
|
||||
OptionLucyImage* slot = &cache->image_slots.buf[i];
|
||||
if (slot->variant == Option_None) {
|
||||
slot->variant = Option_Some;
|
||||
slot->some.scheduled_for_deletion = 0;
|
||||
slot->some.usage = 0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
abortf("LucyCache run out of image descriptor in a descriptor set (dictated by layout).\n"
|
||||
"You better add up on them\n");
|
||||
}
|
||||
|
||||
/* Helper function */
|
||||
void LucyGlyphCache_add_glyphs__close_img(
|
||||
LucyGlyphCache* cache, U32 img_slot_id, U32 img_width, U32 img_height
|
||||
LucyGlyphCache* cache, ListNodeLucyImage* img, U32 img_width, U32 img_height
|
||||
){
|
||||
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&cache->image_slots, img_slot_id);
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
assert(img->usage > 0);
|
||||
assert(!img->scheduled_for_deletion);
|
||||
assert(img->el.usage > 0);
|
||||
img_width = MAX_U32(img_width, 10); // Just a precaution. empty buffers aren't supported by Margaret
|
||||
img_height = MAX_U32(img_height, 10);
|
||||
VecU32_append(&cache->to_be_copied_to_device_next_cycle, img_slot_id);
|
||||
img->staging_buffer = MargaretBufAllocator_alloc(cache->ve.staging_buffers, img_width * img_height * 1);
|
||||
img->img = MargaretImgAllocator_alloc(cache->ve.dev_local_images, img_width, img_height, VK_FORMAT_R8_UNORM,
|
||||
VecRefListNodeLucyImage_append(&cache->to_be_copied_to_device_next_cycle, img);
|
||||
img->el.staging_buffer = MargaretBufAllocator_alloc(cache->ve.staging_buffers, img_width * img_height * 1);
|
||||
img->el.img = MargaretImgAllocator_alloc(cache->ve.dev_local_images, img_width, img_height, VK_FORMAT_R8_UNORM,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
img->img_view = margaret_create_view_for_image(cache->ve.device, img->img.a.image,
|
||||
img->el.img_view = margaret_create_view_for_image(cache->ve.device, img->el.img.a.image,
|
||||
VK_FORMAT_R8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
|
||||
@ -265,14 +228,11 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
|
||||
U32 starting_x = 0;
|
||||
VecU32 landscape = VecU32_new_reserved(200);
|
||||
U32 img_width = 0, img_height = 0;
|
||||
U32 img_slot_id = LucyGlyphCache_add_glyphs__find_image_slot(cache);
|
||||
ListNodeLucyImage* img = ListLucyImage_insert(&cache->images, (LucyImage){0});
|
||||
for (size_t j = 0; j < ready.len; j++) {
|
||||
LucyPositionedStagingGlyph* p_glyph;
|
||||
one_more_chance:
|
||||
{}
|
||||
int s = 23123;
|
||||
p_glyph = &ready.buf[j];
|
||||
LucyImage* img = &VecOptionLucyImage_mat(&cache->image_slots, img_slot_id)->some;
|
||||
U64 new_width_required = p_glyph->bitmap.width + starting_x;
|
||||
if (new_width_required > max_dim) {
|
||||
/* Resetting row */
|
||||
@ -290,12 +250,12 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
|
||||
U64 new_height_required = height_here + p_glyph->bitmap.height;
|
||||
if (new_height_required > max_dim) {
|
||||
/* Resetting image */
|
||||
LucyGlyphCache_add_glyphs__close_img(cache, img_slot_id, img_width, img_height);
|
||||
LucyGlyphCache_add_glyphs__close_img(cache, img, img_width, img_height);
|
||||
starting_x = 0;
|
||||
landscape.len = 0;
|
||||
img_width = 0;
|
||||
img_height = 0;
|
||||
img_slot_id = LucyGlyphCache_add_glyphs__find_image_slot(cache);
|
||||
img = ListLucyImage_insert(&cache->images, (LucyImage){0});
|
||||
goto one_more_chance;
|
||||
}
|
||||
/* Success */
|
||||
@ -303,25 +263,24 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
|
||||
*VecU32_mat(&landscape, starting_x + x) = new_height_required;
|
||||
}
|
||||
img_height = MAX_U64(img_height, new_height_required);
|
||||
p_glyph->img_slot_id = img_slot_id;
|
||||
p_glyph->img = img;
|
||||
p_glyph->pos = (uvec2){starting_x, height_here};
|
||||
img->usage++; /* p_glyph uses it, that's a rock fact */
|
||||
img->el.usage++; /* p_glyph uses it, that's a rock fact */
|
||||
BufRBTree_MapU32ToLucyStoredGlyph *glyphs = &p_glyph->sized_face->glyphs;
|
||||
U64 map_it = BufRBTree_MapU32ToLucyStoredGlyph_find(glyphs, p_glyph->codepoint);
|
||||
assert(map_it > 0 && map_it < glyphs->tree.len);
|
||||
LucyStoredGlyph* actual_glyph = &glyphs->el.buf[map_it - 1].value;
|
||||
actual_glyph->pos_on_atlas = (uvec2){starting_x, height_here};
|
||||
actual_glyph->img_slot_id = img_slot_id;
|
||||
actual_glyph->img = img;
|
||||
starting_x += p_glyph->bitmap.width;
|
||||
}
|
||||
LucyGlyphCache_add_glyphs__close_img(cache, img_slot_id, img_width, img_height);
|
||||
LucyGlyphCache_add_glyphs__close_img(cache, img, img_width, img_height);
|
||||
/* Phase 3. We have all the data. Now what?
|
||||
* Now we fill staging buffers with glyphs bitsets from `ready` vector */
|
||||
for (size_t j = 0; j < ready.len; j++) {
|
||||
LucyPositionedStagingGlyph* p_glyph = &ready.buf[j];
|
||||
LucyImage* image = &VecOptionLucyImage_mat(&cache->image_slots, p_glyph->img_slot_id)->some;
|
||||
U64 staging_width = image->img.width;
|
||||
U8* staging = (U8*)MargaretSubbuf_get_mapped(&image->staging_buffer);
|
||||
U64 staging_width = p_glyph->img->el.img.width;
|
||||
U8* staging = (U8*)MargaretSubbuf_get_mapped(&p_glyph->img->el.staging_buffer);
|
||||
for (U64 y = 0; y < p_glyph->bitmap.height; y++) {
|
||||
U64 Y = y + p_glyph->pos.y;
|
||||
for (U64 x = 0; x < p_glyph->bitmap.width; x++) {
|
||||
@ -337,59 +296,65 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
|
||||
|
||||
/* This must not happen before all the LucyFaceFixedSizes are destroyed */
|
||||
void LucyGlyphCache_drop(LucyGlyphCache self){
|
||||
for (size_t i = 0; i < self.image_slots.len; i++) {
|
||||
assert(self.image_slots.buf[i].variant == Option_None);
|
||||
}
|
||||
VecU32_drop(self.to_be_freed_of_old_staging_next_cycle);
|
||||
VecU32_drop(self.to_be_copied_to_device_next_cycle);
|
||||
VecU32_drop(self.to_be_deleted);
|
||||
assert(self.images.first == NULL);
|
||||
VecRefListNodeLucyImage_drop(self.to_be_freed_of_old_staging_next_cycle);
|
||||
VecRefListNodeLucyImage_drop(self.to_be_copied_to_device_next_cycle);
|
||||
VecRefListNodeLucyImage_drop(self.to_be_deleted);
|
||||
}
|
||||
|
||||
void LucyGlyphCache_another_frame(LucyGlyphCache* self){
|
||||
for (size_t i = 0; i < self->to_be_freed_of_old_staging_next_cycle.len; i++) {
|
||||
U32 slot_id = self->to_be_freed_of_old_staging_next_cycle.buf[i];
|
||||
LucyImage* img = &self->image_slots.buf[slot_id].some;
|
||||
LucyImage* img = &self->to_be_freed_of_old_staging_next_cycle.buf[i]->el;
|
||||
assert(img->staging_buffer.len != 0);
|
||||
MargaretBufAllocator_free(self->ve.staging_buffers, img->staging_buffer);
|
||||
img->staging_buffer.len = 0;
|
||||
}
|
||||
for (size_t i = 0; i < self->to_be_copied_to_device_next_cycle.len; i++) {
|
||||
U32 slot_id = self->to_be_copied_to_device_next_cycle.buf[i];
|
||||
OptionLucyImage* img_slot = &self->image_slots.buf[slot_id];
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
ListNodeLucyImage* img_node = self->to_be_copied_to_device_next_cycle.buf[i];
|
||||
LucyImage* img = &img_node->el;
|
||||
assert(img->staging_buffer.len != 0);
|
||||
if (img->scheduled_for_deletion)
|
||||
continue;
|
||||
margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(self->ve.transfer_cmd_buffer,
|
||||
&img->staging_buffer, &img->img, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||
VecU32_append(&self->to_be_freed_of_old_staging_next_cycle, slot_id);
|
||||
|
||||
vkUpdateDescriptorSets(self->ve.device, 1, &(VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self->descriptor_set, .dstBinding = 0, .dstArrayElement = slot_id,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.pImageInfo = &(VkDescriptorImageInfo){
|
||||
.sampler = self->ve.nearest_sampler, .imageView = img->img_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
}
|
||||
}, 0, NULL);
|
||||
VecRefListNodeLucyImage_append(&self->to_be_freed_of_old_staging_next_cycle, img_node);
|
||||
}
|
||||
/* We technically could carry out each deletion request in O(1) and each img creation request in O(1),
|
||||
* but who cares, it's no problem going over the entire descriptor set when something get's added or deleted */
|
||||
for (size_t i = 0; i < self->to_be_deleted.len; i++) {
|
||||
U32 slot_id = self->to_be_copied_to_device_next_cycle.buf[i];
|
||||
OptionLucyImage* img_slot = &self->image_slots.buf[slot_id];
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
ListNodeLucyImage* img_node = self->to_be_deleted.buf[i];
|
||||
LucyImage* img = &img_node->el;
|
||||
assert(img->scheduled_for_deletion);
|
||||
assert(img->usage == 0);
|
||||
if (img->staging_buffer.len != 0)
|
||||
MargaretBufAllocator_free(self->ve.staging_buffers, img->staging_buffer);
|
||||
MargaretImgAllocator_free(self->ve.dev_local_images, img->img.a);
|
||||
img_slot->variant = Option_None;
|
||||
ListLucyImage_erase_by_it(&self->images, img_node);
|
||||
}
|
||||
if ((self->to_be_copied_to_device_next_cycle.len > 0) || (self->to_be_deleted.len > 0)) {
|
||||
U32 descriptor_i = 0;
|
||||
VecVkDescriptorImageInfo desc_elements = VecVkDescriptorImageInfo_new();
|
||||
for (ListNodeLucyImage* list_node = self->images.first; list_node; list_node = list_node->next) {
|
||||
if (descriptor_i == LUCY_MAX_DESCRIPTOR_COUNT) {
|
||||
abortf("Today you are out of luck\n");
|
||||
}
|
||||
LucyImage* img = &list_node->el;
|
||||
img->pos_in_desc_array = descriptor_i;
|
||||
VecVkDescriptorImageInfo_append(&desc_elements, (VkDescriptorImageInfo){
|
||||
.sampler = self->ve.nearest_sampler, .imageView = img->img_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
});
|
||||
descriptor_i++;
|
||||
}
|
||||
vkUpdateDescriptorSets(self->ve.device, 1, &(VkWriteDescriptorSet){
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self->descriptor_set, .dstBinding = 0, .dstArrayElement = 0,
|
||||
.descriptorCount = desc_elements.len,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.pImageInfo = desc_elements.buf
|
||||
}, 0, NULL);
|
||||
VecVkDescriptorImageInfo_drop(desc_elements);
|
||||
}
|
||||
self->to_be_freed_of_old_staging_next_cycle.len = 0;
|
||||
self->to_be_copied_to_device_next_cycle.len = 0;
|
||||
|
||||
@ -6,22 +6,12 @@
|
||||
#include "../../../gen/l1/geom.h"
|
||||
|
||||
// todo: rewrite this crrp crap using instances
|
||||
// typedef struct{
|
||||
// vec4 color;
|
||||
// vec2 pos;
|
||||
// vec2 tex_cord;
|
||||
// U32 tex_ind;
|
||||
// } LucyVertex;
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct{
|
||||
vec4 color;
|
||||
vec2 lt_pos;
|
||||
vec2 br_pos;
|
||||
vec2 lt_tex;
|
||||
vec2 br_tex;
|
||||
vec2 pos;
|
||||
vec2 tex_cord;
|
||||
U32 tex_ind;
|
||||
} LucyRenderInstance;
|
||||
} LucyVertex;
|
||||
|
||||
typedef struct {
|
||||
MargaretEngineReference ve;
|
||||
@ -29,7 +19,7 @@ typedef struct {
|
||||
VkPipelineLayout pipeline_layout;
|
||||
VkPipeline pipeline;
|
||||
|
||||
U64 glyphs_count;
|
||||
U64 vertex_count;
|
||||
MargaretSubbuf staging_vbo;
|
||||
MargaretSubbuf vbo;
|
||||
bool need_to_transfer;
|
||||
@ -61,27 +51,23 @@ LucyRenderer LucyRenderer_new(
|
||||
.fragment_shader_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/lucy/frag.spv", root_dir)),
|
||||
.vertexBindingDescriptionCount = 1,
|
||||
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]){
|
||||
{ .binding = 0, .stride = sizeof(LucyRenderInstance), .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE } },
|
||||
.vertexAttributeDescriptionCount = 6,
|
||||
{ .binding = 0, .stride = sizeof(LucyVertex), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX } },
|
||||
.vertexAttributeDescriptionCount = 4,
|
||||
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]){
|
||||
{.location = 0, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(LucyRenderInstance, color)},
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(LucyVertex, color)},
|
||||
{.location = 1, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyRenderInstance, lt_pos)},
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyVertex, pos)},
|
||||
{.location = 2, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyRenderInstance, br_pos)},
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyVertex, tex_cord)},
|
||||
{.location = 3, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyRenderInstance, lt_tex)},
|
||||
{.location = 4, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyRenderInstance, br_tex)},
|
||||
{.location = 5, .binding = 0,
|
||||
.format = VK_FORMAT_R32_UINT, .offset = offsetof(LucyRenderInstance, tex_ind)},
|
||||
.format = VK_FORMAT_R32_UINT, .offset = offsetof(LucyVertex, tex_ind)},
|
||||
},
|
||||
.depthTestEnable = false, .depthWriteEnable = false, .blendEnable = true,
|
||||
});
|
||||
|
||||
return (LucyRenderer){.ve = ve, .cache = cache, .pipeline_layout = pipeline_layout, .pipeline = pipeline,
|
||||
.glyphs_count = 0, .staging_vbo = MargaretBufAllocator_alloc(ve.staging_buffers, 67),
|
||||
.vertex_count = 0, .staging_vbo = MargaretBufAllocator_alloc(ve.staging_buffers, 67),
|
||||
.vbo = MargaretBufAllocator_alloc(ve.dev_local_buffers, 67)
|
||||
};
|
||||
}
|
||||
@ -90,47 +76,20 @@ LucyRenderer LucyRenderer_new(
|
||||
* before LucyRenderer_another_frame
|
||||
*/
|
||||
void LucyRenderer_clear(LucyRenderer* self){
|
||||
self->glyphs_count = 0;
|
||||
self->vertex_count = 0;
|
||||
}
|
||||
|
||||
void LucyRenderer_draw_char_glyph(LucyRenderer* self, vec4 color, ivec2 pos, LucyStoredGlyph* glyph){
|
||||
if (glyph->w > 0 && glyph->h > 0) {
|
||||
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&self->cache->image_slots, glyph->img_slot_id);
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
float atlas_w = (float)img->img.width;
|
||||
float atlas_h = (float)img->img.height;
|
||||
ivec2 positioned = ivec2_add_ivec2(pos, glyph->bearing);
|
||||
|
||||
U64 needed_vbo_length = (self->glyphs_count + 1) * sizeof(LucyRenderInstance);
|
||||
if (self->staging_vbo.len < needed_vbo_length) {
|
||||
printf("LucyRenderer Staging Buffer: Gotta replace %lu with %lu\n",
|
||||
self->staging_vbo.len, needed_vbo_length);
|
||||
MargaretBufAllocator_expand_or_move_old_host_visible(
|
||||
self->ve.staging_buffers, &self->staging_vbo, needed_vbo_length);
|
||||
}
|
||||
|
||||
LucyRenderInstance* vbo_data = (LucyRenderInstance*)MargaretSubbuf_get_mapped(&self->staging_vbo);
|
||||
vbo_data[self->glyphs_count++] = (LucyRenderInstance){
|
||||
.color = color,
|
||||
.lt_pos = (vec2){(float)positioned.x, (float)positioned.y},
|
||||
.br_pos = (vec2){(float)(positioned.x + glyph->w), (float)(positioned.y + glyph->h)},
|
||||
.lt_tex = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y) / atlas_h
|
||||
},
|
||||
.br_tex = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x + glyph->w) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y + glyph->h) / atlas_h
|
||||
}, .tex_ind = glyph->img_slot_id
|
||||
};
|
||||
}
|
||||
void LucyRenderer__append_vertex_to_vao(LucyRenderer* self, LucyVertex vert_data){
|
||||
self->vertex_count++;
|
||||
assert(self->vertex_count * sizeof(LucyVertex) <= self->staging_vbo.len);
|
||||
LucyVertex* staging = (LucyVertex*)MargaretSubbuf_get_mapped(&self->staging_vbo);
|
||||
staging[self->vertex_count - 1] = vert_data;
|
||||
}
|
||||
|
||||
/* When another_frame starts, you are safe to call this function, but you also have to call it
|
||||
* before LucyRenderer_another_frame, because _another_frame method records transfer of data
|
||||
*/
|
||||
void LucyRenderer_add_simple_label(
|
||||
void LucyRenderer_add_text(
|
||||
LucyRenderer* self, RBTreeNodeLucyFaceFixedSize* ffs, vec4 color,
|
||||
U32 additional_y_advance, SpanU8 text, ivec2 start_pos
|
||||
){
|
||||
@ -153,23 +112,69 @@ void LucyRenderer_add_simple_label(
|
||||
}
|
||||
assert(map_it > 0 && map_it < glyphs->tree.len);
|
||||
LucyStoredGlyph* glyph = &glyphs->el.buf[map_it - 1].value;
|
||||
LucyRenderer_draw_char_glyph(self, color, pos, glyph);
|
||||
if (glyph->w > 0 && glyph->h > 0) {
|
||||
float atlas_w = (float)glyph->img->el.img.width;
|
||||
float atlas_h = (float)glyph->img->el.img.height;
|
||||
U32 desc_elem_id = glyph->img->el.pos_in_desc_array;
|
||||
ivec2 positioned = ivec2_add_ivec2(pos, glyph->bearing);
|
||||
LucyVertex v0 = {
|
||||
.color = color, .pos = (vec2){(float)positioned.x, (float)positioned.y},
|
||||
.tex_cord = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y) / atlas_h
|
||||
}, .tex_ind = desc_elem_id
|
||||
};
|
||||
LucyVertex v1 = {
|
||||
.color = color, .pos = (vec2){(float)(positioned.x + glyph->w), (float)positioned.y},
|
||||
.tex_cord = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x + glyph->w) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y) / atlas_h
|
||||
}, .tex_ind = desc_elem_id
|
||||
};
|
||||
LucyVertex v2 = {
|
||||
.color = color, .pos = (vec2){(float)positioned.x, (float)(positioned.y + glyph->h)},
|
||||
.tex_cord = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y + glyph->h) / atlas_h
|
||||
}, .tex_ind = desc_elem_id
|
||||
};
|
||||
LucyVertex v3 = {
|
||||
.color = color, .pos = (vec2){(float)(positioned.x + glyph->w), (float)(positioned.y + glyph->h)},
|
||||
.tex_cord = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x + glyph->w) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y + glyph->h) / atlas_h
|
||||
}, .tex_ind = desc_elem_id
|
||||
};
|
||||
/* What if we run out of space? */
|
||||
U64 needed_vbo_length = (self->vertex_count + 6) * sizeof(LucyVertex);
|
||||
if (self->staging_vbo.len < needed_vbo_length) {
|
||||
printf("LucyRenderer Staging Buffer: Gotta replace %lu with %lu\n",
|
||||
self->staging_vbo.len, needed_vbo_length);
|
||||
MargaretBufAllocator_expand_or_move_old_host_visible(
|
||||
self->ve.staging_buffers, &self->staging_vbo, needed_vbo_length);
|
||||
}
|
||||
LucyRenderer__append_vertex_to_vao(self, v1);
|
||||
LucyRenderer__append_vertex_to_vao(self, v0);
|
||||
LucyRenderer__append_vertex_to_vao(self, v2);
|
||||
LucyRenderer__append_vertex_to_vao(self, v1);
|
||||
LucyRenderer__append_vertex_to_vao(self, v2);
|
||||
LucyRenderer__append_vertex_to_vao(self, v3);
|
||||
|
||||
}
|
||||
pos.x += (S32)glyph->advance_x;
|
||||
}
|
||||
}
|
||||
|
||||
/* It only records transfer commands (transfer command buffer is passed in MargaretEngineReference object) */
|
||||
void LucyRenderer_another_frame(LucyRenderer* self){
|
||||
U64 needed_vbo_length = self->glyphs_count * sizeof(LucyRenderInstance);
|
||||
if (self->vbo.len < needed_vbo_length) {
|
||||
MargaretBufAllocator_expand_or_free_old(self->ve.dev_local_buffers, &self->vbo, needed_vbo_length);
|
||||
if (self->vbo.len < self->vertex_count * sizeof(LucyVertex)) {
|
||||
MargaretBufAllocator_expand_or_free_old(self->ve.dev_local_buffers, &self->vbo,
|
||||
self->vertex_count * sizeof(LucyVertex));
|
||||
}
|
||||
if ((self->need_to_transfer) && self->glyphs_count > 0) {
|
||||
printf("LucyRenderer: we are doing copying\n");
|
||||
|
||||
if (self->need_to_transfer && self->vertex_count > 0) {
|
||||
self->need_to_transfer = false;
|
||||
margaret_rec_cmd_copy_buffer_one_to_one_part(self->ve.transfer_cmd_buffer,
|
||||
&self->staging_vbo, &self->vbo, 0, needed_vbo_length);
|
||||
&self->staging_vbo, &self->vbo, 0, self->vertex_count * sizeof(LucyVertex));
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +189,7 @@ void LucyRenderer_another_frame_rec_drawing(
|
||||
(VkBuffer[]){MargaretSubbuf_get_buffer(&self->vbo)}, (VkDeviceSize[]){self->vbo.start});
|
||||
vkCmdBindDescriptorSets(drawing_cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, self->pipeline_layout, 0,
|
||||
1, (VkDescriptorSet[]){self->cache->descriptor_set}, 0, NULL);
|
||||
vkCmdDraw(drawing_cmd_buf, 6, self->glyphs_count, 0, 0);
|
||||
vkCmdDraw(drawing_cmd_buf, self->vertex_count, 1, 0, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -241,11 +241,11 @@ void MargaretBufAllocator_free(MargaretBufAllocator* self, MargaretSubbuf alloca
|
||||
|
||||
bool eret = BufRBTree_MapU64ToU64_erase(&allocation.block->occupants, allocation.start);
|
||||
assert(eret);
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
}
|
||||
|
||||
NODISCARD MargaretSubbuf MargaretBufAllocator_alloc(MargaretBufAllocator* self, U64 req_size){
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
req_size = margaret_bump_buffer_size_to_alignment(req_size, self->alignment_exp);
|
||||
|
||||
VkPhysicalDeviceMaintenance3Properties maintenance3_properties = {
|
||||
@ -270,11 +270,11 @@ NODISCARD MargaretSubbuf MargaretBufAllocator_alloc(MargaretBufAllocator* self,
|
||||
new_block->occupation_counter = req_size;
|
||||
bool iret = BufRBTree_MapU64ToU64_insert(&new_block->occupants, 0, req_size);
|
||||
assert(iret);
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
return (MargaretSubbuf){.block = &self->blocks.first->el, 0, req_size};
|
||||
}
|
||||
MargaretBufAllocator__put_buf_to_a_gap(self, free_gap.some, req_size);
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
return (MargaretSubbuf){.block = free_gap.some.block, .start = free_gap.some.start, req_size};
|
||||
}
|
||||
|
||||
@ -305,7 +305,7 @@ NODISCARD MargaretSubbuf MargaretBufAllocator_expand(
|
||||
if (allocation->start + bigger_size > right_free_space.start + right_free_space.len){
|
||||
return MargaretBufAllocator_alloc(self, bigger_size);
|
||||
}
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator__erase_gap(self, allocation->block, right_free_space.start, right_free_space.len);
|
||||
MargaretBufAllocator__insert_gap(self, allocation->block,
|
||||
allocation->start + bigger_size,
|
||||
@ -315,7 +315,7 @@ NODISCARD MargaretSubbuf MargaretBufAllocator_expand(
|
||||
U64 my_it = BufRBTree_MapU64ToU64_find(&allocation->block->occupants, allocation->start);
|
||||
assert(my_it > 0 && my_it <= allocation->block->occupants.el.len);
|
||||
allocation->block->occupants.el.buf[my_it - 1].value = bigger_size;
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
return (MargaretSubbuf){0};
|
||||
}
|
||||
|
||||
@ -342,9 +342,9 @@ void MargaretBufAllocator_expand_or_move_old_host_visible(
|
||||
memcpy(MargaretSubbuf_get_mapped(&maybe_bigger), MargaretSubbuf_get_mapped(allocation), allocation->len);
|
||||
MargaretBufAllocator_free(self, *allocation);
|
||||
*allocation = maybe_bigger;
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
}
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
}
|
||||
|
||||
/* It tries to expand buffer, but if it fails, it creates a freshly-new buffer. It
|
||||
|
||||
@ -172,6 +172,12 @@
|
||||
* const VkAllocationCallbacks* pAllocator)
|
||||
*/
|
||||
|
||||
// todo: get rid of this whole VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT crap. MargaretMA is for non-host-visible
|
||||
// todo: for staging buffers you better use MargaretBufferAllocator. Ou, yeah, I have yet to write them
|
||||
|
||||
|
||||
// todo: chucking rewrite all of this. Yes, I want all of this crrp rewritten
|
||||
|
||||
#include "../../l1/core/util.h"
|
||||
#include "../../l1_5/core/buff_rb_tree_node.h"
|
||||
#include "../../../gen/l1_5/BufRBTree_MapU64ToU64.h"
|
||||
@ -183,18 +189,10 @@ typedef struct{
|
||||
} MargaretIAFreeSegment;
|
||||
|
||||
#include "../../l1/core/uint_segments.h"
|
||||
|
||||
U64 margaret_get_length_resp_alignment(U64 start, U64 full_len, U8 alignment_exp) {
|
||||
if (start & ((1ull << alignment_exp) - 1)) {
|
||||
U64 pad_left = (1ull << alignment_exp) - (start & ((1ull << alignment_exp) - 1));
|
||||
return full_len >= pad_left ? full_len - pad_left : 0;
|
||||
}
|
||||
return full_len;
|
||||
}
|
||||
|
||||
// todo: substitute U64Segment_get_length_resp_alignment by my own function
|
||||
bool MargaretIAFreeSegment_less_resp_align(const MargaretIAFreeSegment* A, const MargaretIAFreeSegment* B, U8 alignment_exp){
|
||||
U64 A_len = margaret_get_length_resp_alignment(A->start, A->len, alignment_exp);
|
||||
U64 B_len = margaret_get_length_resp_alignment(B->start, B->len, alignment_exp);
|
||||
U64 A_len = U64Segment_get_length_resp_alignment((U64Segment){A->start, A->len}, alignment_exp);
|
||||
U64 B_len = U64Segment_get_length_resp_alignment((U64Segment){B->start, B->len}, alignment_exp);
|
||||
if (A_len == B_len) {
|
||||
if (A->block == B->block) {
|
||||
return A->start < B->start;
|
||||
@ -293,7 +291,6 @@ OptionMargaretIAFreeSegment MargaretMemFreeSpaceManager_search(
|
||||
if (man->free_space_in_memory[alignment_exp].variant == Option_None) {
|
||||
assert(man->set_present.len > 0);
|
||||
assert(man->free_space_in_memory[man->set_present.buf[0]].variant == Option_Some);
|
||||
assert(man->free_space_in_memory[alignment_exp].variant == Option_None);
|
||||
BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment* have = &man->free_space_in_memory[man->set_present.buf[0]].some;
|
||||
man->free_space_in_memory[alignment_exp] = Some_BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment(
|
||||
BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment_new_reserved(alignment_exp, have->el.len));
|
||||
@ -301,7 +298,6 @@ OptionMargaretIAFreeSegment MargaretMemFreeSpaceManager_search(
|
||||
BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment_insert(
|
||||
&man->free_space_in_memory[alignment_exp].some, *VecMargaretIAFreeSegment_at(&have->el, i));
|
||||
}
|
||||
VecU8_append(&man->set_present, alignment_exp);
|
||||
}
|
||||
assert(man->free_space_in_memory[alignment_exp].variant == Option_Some);
|
||||
U64 sit = BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment_find_min_grtr_or_eq(
|
||||
@ -337,7 +333,6 @@ void MargaretImgAllocator__insert_gap(MargaretImgAllocator* self, U64 block_id,
|
||||
|
||||
void MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){
|
||||
VkDeviceMemory memory;
|
||||
printf("DEBUG MargaretImgAllocator: allocating block of size %lu\n", capacity);
|
||||
check(vkAllocateMemory(self->device, &(VkMemoryAllocateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = capacity, .memoryTypeIndex = self->memory_type_id
|
||||
@ -345,33 +340,11 @@ void MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){
|
||||
VecMargaretImgAllocatorOneBlock_append(&self->blocks, (MargaretImgAllocatorOneBlock){
|
||||
.images = BufRBTree_MapU64ToU64_new_reserved(1),
|
||||
.capacity = capacity,
|
||||
.occupation_counter = capacity, // sounds sus
|
||||
.occupation_counter = capacity,
|
||||
.mem_hand = memory,
|
||||
.mapped_memory = NULL /* not supported */});
|
||||
}
|
||||
|
||||
/* Idk where to put it */
|
||||
void MargaretImgAllocator__debug(const MargaretImgAllocator* self){
|
||||
printf("=============================== MargaretImgAllocator ============\n"
|
||||
"All blocks: { ");
|
||||
for (size_t i = 0; i < self->blocks.len; i++) {
|
||||
printf(" %lu/%lu ", self->blocks.buf[i].occupation_counter, self->blocks.buf[i].capacity);
|
||||
}
|
||||
printf("}\n");
|
||||
for (size_t ai = 0; ai < self->mem_free_space.set_present.len; ai++) {
|
||||
U8 alignment_exp = self->mem_free_space.set_present.buf[ai];
|
||||
printf("Free spaces at alignment_exp = %d:\n", (int)alignment_exp);
|
||||
assert(self->mem_free_space.free_space_in_memory[alignment_exp].variant == Option_Some);
|
||||
const BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment* set =
|
||||
&self->mem_free_space.free_space_in_memory[alignment_exp].some;
|
||||
assert(set->guest == alignment_exp);
|
||||
for (size_t i = 0; i < set->el.len; i++) {
|
||||
const MargaretIAFreeSegment *free_seg = &set->el.buf[i];
|
||||
printf(" Block %lu, start %lu, len %lu\n", free_seg->block, free_seg->start, free_seg->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MargaretImgAllocator MargaretImgAllocator_new(
|
||||
VkDevice device, VkPhysicalDevice physical_device, U8 memory_type_id, U64 initial_block_size
|
||||
){
|
||||
@ -384,7 +357,6 @@ MargaretImgAllocator MargaretImgAllocator_new(
|
||||
};
|
||||
MargaretImgAllocator__add_block(&self, initial_block_size);
|
||||
MargaretImgAllocator__insert_gap(&self, 0, 0, initial_block_size);
|
||||
// MargaretImgAllocator__debug(&self);
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -518,7 +490,6 @@ NODISCARD MargaretImgAllocation MargaretImgAllocator__alloc(
|
||||
U64 pitch = self->blocks.buf[self->blocks.len - 1].capacity;
|
||||
// Old blocks remain intact
|
||||
U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(2 * pitch, maintenance3_properties.maxMemoryAllocationSize));
|
||||
// U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(pitch, maintenance3_properties.maxMemoryAllocationSize));
|
||||
MargaretImgAllocator__add_block(self, new_capacity);
|
||||
U64 bid = self->blocks.len - 1;
|
||||
MargaretImgAllocator__insert_gap(self, bid, mem_requirements.size, new_capacity - mem_requirements.size);
|
||||
@ -527,13 +498,11 @@ NODISCARD MargaretImgAllocation MargaretImgAllocator__alloc(
|
||||
bool iret = BufRBTree_MapU64ToU64_insert(&block->images, 0, mem_requirements.size);
|
||||
assert(iret);
|
||||
check(vkBindImageMemory(self->device, fresh_img, block->mem_hand, 0) == VK_SUCCESS);
|
||||
// MargaretImgAllocator__debug(self);
|
||||
return (MargaretImgAllocation){.block = bid, fresh_img, 0};
|
||||
}
|
||||
U64 aligned_pos = MargaretImgAllocator__add_img_given_gap(self, free_gap.some, mem_requirements.size, alignment_exp);
|
||||
VkDeviceMemory memory = VecMargaretImgAllocatorOneBlock_at(&self->blocks, free_gap.some.block)->mem_hand;
|
||||
check(vkBindImageMemory(self->device, fresh_img, memory, aligned_pos) == VK_SUCCESS);
|
||||
// MargaretImgAllocator__debug(self);
|
||||
return (MargaretImgAllocation){.block = free_gap.some.block, .image = fresh_img, .start = aligned_pos};
|
||||
}
|
||||
|
||||
|
||||
@ -309,27 +309,20 @@ NODISCARD VecU8 margaret_stringify_device_memory_properties_2(VkPhysicalDevice p
|
||||
VkDevice margaret_create_logical_device(VkPhysicalDevice physical_device, MargaretChosenQueueFamilies queue_fam) {
|
||||
VkPhysicalDeviceFeatures physical_features;
|
||||
vkGetPhysicalDeviceFeatures(physical_device, &physical_features);
|
||||
float qfam_queue_priorities[1] = {1.f};
|
||||
VkDeviceQueueCreateInfo queue_crinfo[2] = { 0 };
|
||||
int queue_c = 0;
|
||||
if (queue_fam.for_graphics == queue_fam.for_presentation) {
|
||||
queue_c = 1;
|
||||
queue_crinfo[0].queueFamilyIndex = queue_fam.for_graphics;
|
||||
} else {
|
||||
queue_c = 2;
|
||||
queue_crinfo[0].queueFamilyIndex = queue_fam.for_graphics;
|
||||
queue_crinfo[1].queueFamilyIndex = queue_fam.for_presentation;
|
||||
}
|
||||
for (int i = 0; i < queue_c; i++) {
|
||||
queue_crinfo[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queue_crinfo[i].queueCount = 1;
|
||||
queue_crinfo[i].pQueuePriorities = qfam_queue_priorities;
|
||||
// todo: handle case of `two in one`
|
||||
float qfam_instance_priorities[1] = {1.f};
|
||||
VkDeviceQueueCreateInfo logical_device_queue_crinfo[2] = { 0 };
|
||||
for (int i = 0; i < 2; i++) {
|
||||
logical_device_queue_crinfo[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
logical_device_queue_crinfo[i].queueCount = 1;
|
||||
logical_device_queue_crinfo[i].pQueuePriorities = qfam_instance_priorities;
|
||||
}
|
||||
logical_device_queue_crinfo[0].queueFamilyIndex = queue_fam.for_graphics;
|
||||
logical_device_queue_crinfo[1].queueFamilyIndex = queue_fam.for_presentation;
|
||||
|
||||
VkPhysicalDeviceVulkan12Features used_vk12_features = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.runtimeDescriptorArray = true,
|
||||
.descriptorBindingPartiallyBound = true,
|
||||
.shaderSampledImageArrayNonUniformIndexing = true,
|
||||
};
|
||||
// We DEMAND synchronization2
|
||||
@ -352,8 +345,8 @@ VkDevice margaret_create_logical_device(VkPhysicalDevice physical_device, Margar
|
||||
VkDeviceCreateInfo device_crinfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = (const void*)&used_features2,
|
||||
.queueCreateInfoCount = queue_c,
|
||||
.pQueueCreateInfos = queue_crinfo,
|
||||
.queueCreateInfoCount = ARRAY_SIZE(logical_device_queue_crinfo),
|
||||
.pQueueCreateInfos = logical_device_queue_crinfo,
|
||||
.enabledExtensionCount = ARRAY_SIZE(needed_extensions),
|
||||
.ppEnabledExtensionNames = needed_extensions,
|
||||
// We leave that filed because we have specified features2 in `.pNext`
|
||||
@ -590,8 +583,6 @@ MargaretScoredPhysicalDevice margaret_score_physical_device(
|
||||
return (MargaretScoredPhysicalDevice){dev, -1, cstr("No shaderSampledImageArrayNonUniformIndexing")};
|
||||
if (!vk12_features.runtimeDescriptorArray)
|
||||
return (MargaretScoredPhysicalDevice){dev, -1, cstr("No runtimeDescriptorArray")};
|
||||
if (!vk12_features.descriptorBindingPartiallyBound)
|
||||
return (MargaretScoredPhysicalDevice){dev, -1, cstr("No descriptorBindingPartiallyBound")};
|
||||
ResultMargaretChosenQueueFamiliesOrSpanU8 queue_families = margaret_choose_good_queue_families(dev, surface);
|
||||
if (queue_families.variant == Result_Err)
|
||||
return (MargaretScoredPhysicalDevice){dev, -1, queue_families.err};
|
||||
|
||||
@ -98,8 +98,5 @@ mat4 marie_3d_scal_mat4(float scale){
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
vec2 ivec2_to_vec2(ivec2 v){
|
||||
return (vec2){(float)v.x, (float)v.y};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -186,8 +186,10 @@ void save_tree_to_file(const BufRBTree_SetS64* set, SpanU8 name){
|
||||
}
|
||||
VecU8_append_span(&graph, cstr("}\n"));
|
||||
mkdir_nofail("GRAPHS");
|
||||
write_file_by_path(VecU8_fmt("GRAPHS/GRAPH_%s.gv", name), VecU8_to_span(&graph));
|
||||
VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.gv%c", name, 0);
|
||||
write_whole_file_or_abort((CSTR)dot_filename_nt.buf, VecU8_to_span(&graph));
|
||||
VecU8_drop(graph);
|
||||
VecU8_drop(dot_filename_nt);
|
||||
VecU8 command_nt = VecU8_fmt("dot -Tpng GRAPHS/GRAPH_%s.gv -o GRAPHS/GRAPH_%s.png%c", name, name, 0);
|
||||
calling_system_func_nofail((CSTR)command_nt.buf);
|
||||
VecU8_drop(command_nt);
|
||||
|
||||
@ -118,8 +118,10 @@ void save_tree_to_file(const RBTree_SetS64* set, SpanU8 name){
|
||||
}
|
||||
VecU8_append_span(&graph, cstr("}\n"));
|
||||
mkdir_nofail("GRAPHS");
|
||||
write_file_by_path(VecU8_fmt("GRAPHS/GRAPH_%s.gv", name), VecU8_to_span(&graph));
|
||||
VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.gv%c", name, 0);
|
||||
write_whole_file_or_abort((CSTR)dot_filename_nt.buf, VecU8_to_span(&graph));
|
||||
VecU8_drop(graph);
|
||||
VecU8_drop(dot_filename_nt);
|
||||
VecU8 command_nt = VecU8_fmt("dot -Tpng GRAPHS/GRAPH_%s.gv -o GRAPHS/GRAPH_%s.png%c", name, name, 0);
|
||||
calling_system_func_nofail((CSTR)command_nt.buf);
|
||||
VecU8_drop(command_nt);
|
||||
|
||||
135
src/l2/tests/r0/textures/bitmap_converter.py
Executable file
@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Convert between custom bottom‑up raw files (.r8g8b8a8 / .r8b8g8 / .r8 / .a8)
|
||||
and normal PNG using Pillow.
|
||||
|
||||
Format
|
||||
------
|
||||
uint32 width (little‑endian)
|
||||
uint32 height (little‑endian)
|
||||
pixel data rows bottom‑first:
|
||||
* .r8g8b8a8 : R G B A (4× uint8)
|
||||
* .r8b8g8 : R G B (3× uint8)
|
||||
* .r8 : R (1× uint8 <- grayscale)
|
||||
* .a8 : A (can convert from it, but can't convert to it)
|
||||
|
||||
CLI
|
||||
---
|
||||
raw -> png : python raw_png_conv.py to_png input.raw output.png
|
||||
png -> raw : python raw_png_conv.py to_raw input.png output.raw
|
||||
"""
|
||||
import argparse
|
||||
import struct
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# Helpers
|
||||
# --------------------------------------------------------------------- #
|
||||
|
||||
|
||||
RAW_FORMATS = {
|
||||
".r8g8b8a8": {"pix_size": 4, "mode": "RGBA"},
|
||||
".r8g8b8": {"pix_size": 3, "mode": "RGB"},
|
||||
".r8": {"pix_size": 1, "mode": "L"},
|
||||
".a8": {"pix_size": 1, "mode": None}, # special-cased (alpha-only)
|
||||
}
|
||||
|
||||
|
||||
def get_fmt(path: Path):
|
||||
fmt = RAW_FORMATS.get(path.suffix.lower())
|
||||
if not fmt:
|
||||
raise ValueError(f"Unknown raw extension: {path.suffix}")
|
||||
return fmt
|
||||
|
||||
|
||||
def read_header_and_data(path: Path, pix_size: int):
|
||||
with path.open("rb") as f:
|
||||
header = f.read(8)
|
||||
if len(header) != 8:
|
||||
raise ValueError("File too short for header")
|
||||
w, h = struct.unpack("<II", header)
|
||||
expected = w * h * pix_size
|
||||
data = f.read()
|
||||
if len(data) != expected:
|
||||
raise ValueError(
|
||||
f"Pixel data length mismatch: expected {expected}, got {len(data)}"
|
||||
)
|
||||
return w, h, data
|
||||
|
||||
|
||||
def read_raw(path: Path) -> Image.Image:
|
||||
"""Load any supported raw file -> Pillow Image."""
|
||||
spec = get_fmt(path)
|
||||
w, h, data = read_header_and_data(path, spec["pix_size"])
|
||||
|
||||
row_len = w * spec["pix_size"]
|
||||
rows = [data[i : i + row_len] for i in range(0, len(data), row_len)]
|
||||
top_down = b"".join(reversed(rows)) # flip bottom‑up -> top‑down
|
||||
|
||||
# Special handling for .a8 (alpha-only -> LA with black color)
|
||||
if path.suffix.lower() == ".a8":
|
||||
big = bytearray(4 * len(top_down))
|
||||
big[3::4] = top_down
|
||||
big = bytes(big)
|
||||
return Image.frombytes("RGBA", (w, h), big)
|
||||
|
||||
# Normal cases can be constructed directly
|
||||
return Image.frombytes(spec["mode"], (w, h), top_down)
|
||||
|
||||
|
||||
def write_raw(img: Image.Image, path: Path) -> None:
|
||||
"""Write Pillow Image -> raw file chosen by path suffix."""
|
||||
ext = path.suffix.lower()
|
||||
spec = get_fmt(path)
|
||||
|
||||
if ext == ".a8":
|
||||
raise ValueError("Don't convert to .a8 format")
|
||||
|
||||
target_mode = spec["mode"]
|
||||
if img.mode != target_mode:
|
||||
img = img.convert(target_mode)
|
||||
|
||||
w, h = img.size
|
||||
data = img.tobytes()
|
||||
row_len = w * spec["pix_size"]
|
||||
rows = [data[i : i + row_len] for i in range(0, len(data), row_len)]
|
||||
bottom_first = b"".join(reversed(rows)) # top‑down -> bottom‑up
|
||||
|
||||
with path.open("wb") as f:
|
||||
f.write(struct.pack("<II", w, h))
|
||||
f.write(bottom_first)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# CLI
|
||||
# --------------------------------------------------------------------- #
|
||||
|
||||
def to_png(src: Path, dst: Path):
|
||||
read_raw(src).save(dst, "PNG")
|
||||
|
||||
|
||||
def to_raw(src: Path, dst: Path):
|
||||
write_raw(Image.open(src), dst)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Convert raw <-> PNG")
|
||||
sub = ap.add_subparsers(dest="cmd", required=True)
|
||||
p_png = sub.add_parser("to_png", help="raw -> png")
|
||||
p_png.add_argument("src", type=Path)
|
||||
p_png.add_argument("dst", type=Path)
|
||||
p_raw = sub.add_parser("to_raw", help="png -> raw")
|
||||
p_raw.add_argument("src", type=Path)
|
||||
p_raw.add_argument("dst", type=Path)
|
||||
args = ap.parse_args()
|
||||
|
||||
if args.cmd == "to_png":
|
||||
to_png(args.src, args.dst)
|
||||
else:
|
||||
to_raw(args.src, args.dst)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -105,7 +105,7 @@ const LizaInstrument_Table LizaInstrument_Table_WeirdGuitar = {
|
||||
BoxLizaInstrument BoxLizaInstrument_from_WeirdGuitar(WeirdGuitar obj) {
|
||||
void* mem = safe_malloc(sizeof(WeirdGuitar));
|
||||
memcpy(mem, &obj, sizeof(WeirdGuitar));
|
||||
return (BoxLizaInstrument){.r = mem, .t = &LizaInstrument_Table_WeirdGuitar};
|
||||
return (BoxLizaInstrument){.m = mem, .t = &LizaInstrument_Table_WeirdGuitar};
|
||||
}
|
||||
|
||||
/* ElectroBlaster which produces AmplitudeModulationSound */
|
||||
@ -192,7 +192,7 @@ const LizaInstrument_Table LizaInstrument_Table_AMKeys = {
|
||||
BoxLizaInstrument BoxLizaInstrument_from_AMKeys(AMKeys obj) {
|
||||
void* mem = safe_malloc(sizeof(AMKeys));
|
||||
memcpy(mem, &obj, sizeof(AMKeys));
|
||||
return (BoxLizaInstrument){.r = mem, .t = &LizaInstrument_Table_AMKeys};
|
||||
return (BoxLizaInstrument){.m = mem, .t = &LizaInstrument_Table_AMKeys};
|
||||
}
|
||||
|
||||
/* FMKeys which produces FrequencyModulationSound */
|
||||
@ -278,7 +278,7 @@ const LizaInstrument_Table LizaInstrument_Table_FMKeys = {
|
||||
BoxLizaInstrument BoxLizaInstrument_from_FMKeys(FMKeys obj) {
|
||||
void* mem = safe_malloc(sizeof(FMKeys));
|
||||
memcpy(mem, &obj, sizeof(FMKeys));
|
||||
return (BoxLizaInstrument){.r = mem, .t = &LizaInstrument_Table_FMKeys};
|
||||
return (BoxLizaInstrument){.m = mem, .t = &LizaInstrument_Table_FMKeys};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -100,8 +100,7 @@ static void r2a_app_h_pw_stream_process(void *ug){
|
||||
return;
|
||||
}
|
||||
struct spa_buffer *buf = b->buffer;
|
||||
assert(buf->n_datas >= 1);
|
||||
const uint32_t stride = sizeof(int16_t) * DEFAULT_CHANNELS;
|
||||
uint32_t stride = sizeof(int16_t) * DEFAULT_CHANNELS;
|
||||
uint32_t n_frames = buf->datas[0].maxsize / stride;
|
||||
if (b->requested)
|
||||
n_frames = SPA_MIN(b->requested, n_frames);
|
||||
@ -516,12 +515,12 @@ static void r2a_app_h_wl_keyboard_key(
|
||||
};
|
||||
if (state->selected_instrument < state->instruments.len) {
|
||||
// todo: add box to ref and box to mref methods
|
||||
BoxLizaInstrument* instrument = &VecMyInstrument_mat(&state->instruments, state->selected_instrument)->liza;
|
||||
const BoxLizaInstrument* instrument = &VecMyInstrument_at(&state->instruments, state->selected_instrument)->liza;
|
||||
for (int i = 0; i < ARRAY_SIZE(octave); i++) {
|
||||
if (keysym == octave[i] && key_action == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
safe_pthread_mutex_lock(&state->audio_thread_bridge->mut);
|
||||
VecBoxLizaSound_append(&state->audio_thread_bridge->cmd.new_sounds,
|
||||
BoxLizaInstrument_ding(instrument, 440 * pow(2, (double)i / 12), 0.9));
|
||||
instrument->t->ding(instrument->m, 440 * pow(2, (double)i / 12), 0.9));
|
||||
safe_pthread_mutex_unlock(&state->audio_thread_bridge->mut);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ void BoxLizaSound_drop(BoxLizaSound self) {
|
||||
free(self.m);
|
||||
}
|
||||
|
||||
#include "../../../../gen/l1/eve/r2/VecBoxLizaSound.h"
|
||||
#include "../../../../gen/l2/eve/r2/VecBoxLizaSound.h"
|
||||
|
||||
typedef struct {
|
||||
bool stop;
|
||||
|
||||
@ -1,232 +0,0 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sound/asound.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DESIRED_SAMPLE_RATE 44100
|
||||
#define DESIRED_CHANNELS 2 // Prefer stereo, as mono often not supported on hardware
|
||||
#define DESIRED_PERIOD_SIZE 1024
|
||||
#define DESIRED_PERIODS 4
|
||||
#define FORMAT SNDRV_PCM_FORMAT_S16_LE
|
||||
#define DURATION 5 // seconds
|
||||
#define BYTES_PER_SAMPLE 2
|
||||
|
||||
int main() {
|
||||
int card = -1, device = -1;
|
||||
FILE *proc = fopen("/proc/asound/pcm", "r");
|
||||
if (!proc) {
|
||||
perror("Failed to open /proc/asound/pcm");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Opened /proc/asound/pcm\n");
|
||||
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), proc)) {
|
||||
if (strstr(line, "playback")) {
|
||||
sscanf(line, "%02d-%02d", &card, &device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(proc);
|
||||
|
||||
if (card < 0 || device < 0) {
|
||||
fprintf(stderr, "No playback devices found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char devname[64];
|
||||
snprintf(devname, sizeof(devname), "/dev/snd/pcmC%dD%dp", card, device);
|
||||
|
||||
int fd = open(devname, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open PCM device");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Opened device\n");
|
||||
|
||||
struct snd_pcm_hw_params params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
// Initialize to full possible ranges for refinement
|
||||
int i;
|
||||
for (i = SNDRV_PCM_HW_PARAM_FIRST_MASK; i <= SNDRV_PCM_HW_PARAM_LAST_MASK; i++) {
|
||||
struct snd_mask *mask = ¶ms.masks[i - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
mask->bits[0] = ~0U;
|
||||
mask->bits[1] = ~0U;
|
||||
}
|
||||
for (i = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; i <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; i++) {
|
||||
struct snd_interval *interval = ¶ms.intervals[i - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
interval->min = 0;
|
||||
interval->max = ~0U;
|
||||
interval->openmin = interval->openmax = 0;
|
||||
interval->integer = 0;
|
||||
}
|
||||
params.rmask = ~0U;
|
||||
params.cmask = 0;
|
||||
params.info = ~0U;
|
||||
|
||||
// Refine to hardware-supported ranges
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, ¶ms) < 0) {
|
||||
perror("Failed initial HW_REFINE");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Refined hw params\n");
|
||||
|
||||
// Set access to RW_INTERLEAVED if supported
|
||||
struct snd_mask *access_mask = ¶ms.masks[SNDRV_PCM_HW_PARAM_ACCESS - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
unsigned int access_bit = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
|
||||
if (!(access_mask->bits[access_bit / 32] & (1U << (access_bit % 32)))) {
|
||||
fprintf(stderr, "RW_INTERLEAVED access not supported\n");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
memset(access_mask, 0, sizeof(*access_mask));
|
||||
access_mask->bits[access_bit / 32] |= (1U << (access_bit % 32));
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_ACCESS);
|
||||
|
||||
// Set format to S16_LE if supported
|
||||
struct snd_mask *format_mask = ¶ms.masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
unsigned int format_bit = FORMAT;
|
||||
if (!(format_mask->bits[format_bit / 32] & (1U << (format_bit % 32)))) {
|
||||
fprintf(stderr, "S16_LE format not supported\n");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
memset(format_mask, 0, sizeof(*format_mask));
|
||||
format_mask->bits[format_bit / 32] |= (1U << (format_bit % 32));
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
|
||||
// Set channels to nearest supported (prefer DESIRED_CHANNELS)
|
||||
struct snd_interval *channels_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_CHANNELS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int channels = DESIRED_CHANNELS;
|
||||
if (channels < channels_int->min) channels = channels_int->min;
|
||||
if (channels > channels_int->max) channels = channels_int->max;
|
||||
if (channels != DESIRED_CHANNELS) {
|
||||
fprintf(stderr, "Adjusted channels to %u (hardware range: %u-%u)\n", channels, channels_int->min, channels_int->max);
|
||||
}
|
||||
channels_int->min = channels_int->max = channels;
|
||||
channels_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
|
||||
// Set sample rate to nearest supported
|
||||
struct snd_interval *rate_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int sample_rate = DESIRED_SAMPLE_RATE;
|
||||
if (sample_rate < rate_int->min) sample_rate = rate_int->min;
|
||||
if (sample_rate > rate_int->max) sample_rate = rate_int->max;
|
||||
if (sample_rate != DESIRED_SAMPLE_RATE) {
|
||||
fprintf(stderr, "Adjusted sample rate to %u Hz (hardware range: %u-%u)\n", sample_rate, rate_int->min, rate_int->max);
|
||||
}
|
||||
rate_int->min = rate_int->max = sample_rate;
|
||||
rate_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_RATE);
|
||||
|
||||
// Set period size to nearest supported
|
||||
struct snd_interval *period_size_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_PERIOD_SIZE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int period_size = DESIRED_PERIOD_SIZE;
|
||||
if (period_size < period_size_int->min) period_size = period_size_int->min;
|
||||
if (period_size > period_size_int->max) period_size = period_size_int->max;
|
||||
if (period_size != DESIRED_PERIOD_SIZE) {
|
||||
fprintf(stderr, "Adjusted period size to %u frames (hardware range: %u-%u)\n", period_size, period_size_int->min, period_size_int->max);
|
||||
}
|
||||
period_size_int->min = period_size_int->max = period_size;
|
||||
period_size_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
|
||||
|
||||
// Set periods (less strict, clamp to range)
|
||||
struct snd_interval *periods_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_PERIODS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int periods = DESIRED_PERIODS;
|
||||
if (periods < periods_int->min) periods = periods_int->min;
|
||||
if (periods > periods_int->max) periods = periods_int->max;
|
||||
if (periods != DESIRED_PERIODS) {
|
||||
fprintf(stderr, "Adjusted periods to %u (hardware range: %u-%u)\n", periods, periods_int->min, periods_int->max);
|
||||
}
|
||||
periods_int->min = periods_int->max = periods;
|
||||
periods_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
|
||||
// Refine again with desired values to confirm
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, ¶ms) < 0) {
|
||||
perror("Failed to refine desired HW params");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Refined hw params the last time\n");
|
||||
|
||||
// Now apply the parameters
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms) < 0) {
|
||||
perror("Failed to set HW params");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("HW params set\n");
|
||||
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_PREPARE, 0) < 0) {
|
||||
perror("Failed to prepare PCM");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Prepared\n");
|
||||
|
||||
// Generate and play sine wave
|
||||
size_t frame_size = channels * BYTES_PER_SAMPLE;
|
||||
short *buffer = malloc(period_size * frame_size);
|
||||
if (!buffer) {
|
||||
perror("Failed to allocate buffer");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long total_frames = (unsigned long)sample_rate * DURATION;
|
||||
unsigned long frames_written = 0;
|
||||
double phase = 0.0;
|
||||
const double freq = 440.0; // Hz
|
||||
const double phase_inc = 2.0 * M_PI * freq / sample_rate;
|
||||
|
||||
while (frames_written < total_frames) {
|
||||
size_t frames_to_write = period_size;
|
||||
if (frames_written + frames_to_write > total_frames) {
|
||||
frames_to_write = total_frames - frames_written;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < frames_to_write; ++j) {
|
||||
short sample = (short)(32767.0 * sin(phase));
|
||||
for (unsigned int ch = 0; ch < channels; ++ch) {
|
||||
buffer[j * channels + ch] = sample;
|
||||
}
|
||||
phase += phase_inc;
|
||||
if (phase >= 2.0 * M_PI) phase -= 2.0 * M_PI;
|
||||
}
|
||||
|
||||
ssize_t bytes_written = write(fd, buffer, frames_to_write * frame_size);
|
||||
printf("bytes written = %lu\n", bytes_written);
|
||||
if (bytes_written < 0) {
|
||||
if (errno == EPIPE) {
|
||||
// Underrun: recover
|
||||
ioctl(fd, SNDRV_PCM_IOCTL_PREPARE, 0);
|
||||
continue;
|
||||
}
|
||||
perror("Write failed");
|
||||
break;
|
||||
}
|
||||
|
||||
frames_written += bytes_written / frame_size;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
// Drain remaining data
|
||||
ioctl(fd, SNDRV_PCM_IOCTL_DRAIN, 0);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 916 KiB |
6026920
src/l3/models/skeleton.obj
113
src/l3/r4/R4.hs
@ -1,16 +1,6 @@
|
||||
import Allie
|
||||
import Geom
|
||||
import Control.Monad (forM_, when)
|
||||
import Data.Char (ord)
|
||||
import Data.IORef (newIORef, readIORef, writeIORef, modifyIORef)
|
||||
import Data.Word(Word32, Word64)
|
||||
|
||||
lucyFaceAddGlyphRange :: LucyFaceFixedSize -> Char -> Char -> IO ()
|
||||
lucyFaceAddGlyphRange ffs a b = lucyFaceAddGlyphs ffs aInt (bInt - aInt + 1)
|
||||
where aInt = ((fromIntegral $ ord a) :: Word32)
|
||||
bInt = ((fromIntegral $ ord b) :: Word32)
|
||||
|
||||
-- Game configurable
|
||||
import Control.Monad (forM_)
|
||||
|
||||
goodColorOfCube :: (Integral a) => a -> Vec3
|
||||
goodColorOfCube i = ((Vec3 100 0 0) ^*^ t) ^+^ ((Vec3 0 50 90) ^*^ (1 - t)) where t = ((fromIntegral i :: Float) / 4)
|
||||
@ -18,114 +8,49 @@ goodColorOfCube i = ((Vec3 100 0 0) ^*^ t) ^+^ ((Vec3 0 50 90) ^*^ (1 - t)) wher
|
||||
goodLightPos :: (Integral a) => a -> Vec3
|
||||
goodLightPos i = ((Vec3 0 2 1) ^*^ t) ^+^ ((Vec3 5 1 1) ^*^ (1 - t)) where t = ((fromIntegral i :: Float) / 4)
|
||||
|
||||
projectDirOntoPlane :: Vec3 -> Vec2
|
||||
projectDirOntoPlane (Vec3 x y z) = normalize (Vec2 x z)
|
||||
|
||||
heroHeight :: Float
|
||||
heroHeight = 1.89
|
||||
|
||||
heroCamPos :: Vec2 -> Vec3
|
||||
heroCamPos (Vec2 x z) = Vec3 x heroHeight z
|
||||
|
||||
puckLevitationHeight :: Float
|
||||
puckLevitationHeight = 0.4 + 0.2
|
||||
|
||||
puckSpots :: [Vec2]
|
||||
puckSpots = [(Vec2 (-10) (-10)), (Vec2 (-15) (-15)) , (Vec2 (-18) (-18)), (Vec2 (-18) (-25)), (Vec2 (-18) (-30))]
|
||||
|
||||
introText :: String
|
||||
introText = "Накануне новогодняя сессия 2025 года. Все были готовы провести экзамен по матану, но злой Гринч похитил 67 " ++
|
||||
"шайб с бергамотом Матвея и улетел. Вся надежда была потеряна, но в полёте Гринч выронил все шайбы, и те упали в Дубки. Тебе " ++
|
||||
"необходимо вернуть их Матвею.\n" ++
|
||||
"Естесственно, вернёшь ты их Гринчу, так как ты и сам не понимаешь преобразования Фурье и хочешь помочь сорвать " ++
|
||||
"экзамен.\n\n" ++
|
||||
"Итак, ты в Дубках..."
|
||||
|
||||
main :: IO()
|
||||
main = do
|
||||
alice <- newAlice
|
||||
aliceSetSkyColor alice (Vec4 0.9 0 0.6 1)
|
||||
aliceSetCamPos alice (Vec3 0 heroHeight 0)
|
||||
face <- aliceNewLucyFace alice "src/l3/fonts/DMSerifText-Regular.ttf"
|
||||
faceOf40 <- aliceLucyFaceOfSize face 40
|
||||
lucyFaceAddGlyphRange faceOf40 ' ' '~'
|
||||
lucyFaceAddGlyphRange faceOf40 'а' 'я'
|
||||
lucyFaceAddGlyphRange faceOf40 'А' 'Я'
|
||||
lucyFaceAddGlyphs faceOf40 32 (126 - 32 + 1)
|
||||
aliceAddText alice faceOf40 (Vec4 1 1 0 1) "Privet" 100 200
|
||||
|
||||
weirdStructure <- aliceAddGenericMeshHand alice "gen/l2/models/log_10_2_6.AliceGenericMesh"
|
||||
"src/l3/textures/log_10_2_6_diffuse.png" "gen/l2/textures/log_10_2_6_NORMAL.png" "src/l3/textures/log_10_2_6_specular.png"
|
||||
aliceGenericMeshResizeInstanceArr alice weirdStructure 1
|
||||
|
||||
aliceGenericMeshSetInst weirdStructure 0 (AliceGenericMeshInstance (mat4Transit (Vec3 (-3.0) (0.0) (-5.0))))
|
||||
|
||||
floorTile <- aliceAddGenericMeshHand alice "gen/l2/models/quad.AliceGenericMesh"
|
||||
"src/l3/textures/asphalt_diffuse.png" "gen/l2/textures/flat_NORMAL.png" "src/l3/textures/funny_floor_specular.png"
|
||||
aliceGenericMeshResizeInstanceArr alice floorTile 49
|
||||
|
||||
puck <- aliceAddGenericMeshHand alice "gen/l2/models/puck.AliceGenericMesh"
|
||||
"src/l3/textures/puck_diffuse.png" "gen/l2/textures/puck_NORMAL.png" "src/l3/textures/puck_specular.png"
|
||||
|
||||
forM_ [0..6] $ \x -> forM_ [0..6] $ \z ->
|
||||
aliceGenericMeshSetInst floorTile (z * 7 + x) (AliceGenericMeshInstance
|
||||
(mat4Transit (Vec3 ((fromIntegral x) * 10 - 35) 0 ((fromIntegral z) * 10 - 35))))
|
||||
aliceGenericMeshSetInst weirdStructure 0 (AliceGenericMeshInstance (mat4Transit (Vec3 (-3.0) (-2.0) (-5.0))))
|
||||
|
||||
cube <- aliceAddShinyMeshHand alice "gen/l2/models/cube.AliceShinyMesh"
|
||||
aliceShinyMeshResizeInstanceArr alice cube 5
|
||||
|
||||
|
||||
aliceSetPointLightCount alice 5
|
||||
forM_ [0..4] $ \i -> do
|
||||
aliceShinyMeshSetInst cube i (AliceShinyMeshInstance (mat4Transit (goodLightPos i)) (goodColorOfCube i))
|
||||
aliceShinyMeshSetInst cube i (AliceShinyMeshInstance (mat4Transit (goodLightPos i)) (Vec3 1 1 1) (goodColorOfCube i))
|
||||
aliceSetPointLight alice (fromIntegral i) (AlicePointLight (goodLightPos i) (goodColorOfCube i))
|
||||
|
||||
aliceGenericMeshResizeInstanceArr alice puck (fromIntegral $ length puckSpots)
|
||||
forM_ (zip[0..] puckSpots) $ \(i, (Vec2 x z)) -> aliceGenericMeshSetInst puck (fromIntegral i) (AliceGenericMeshInstance
|
||||
(mat4Transit (Vec3 x puckLevitationHeight z )))
|
||||
|
||||
heroPos <- newIORef (Vec2 0 0)
|
||||
puckRotation <- newIORef (0 :: Float)
|
||||
|
||||
-- state <- newIORef 67
|
||||
-- Create the Callbacks structure.
|
||||
let callbacks = Callbacks myonKeyboardKey myonAnotherFrame where
|
||||
myonKeyboardKey keysym keyAction = do
|
||||
-- old <- readIORef state
|
||||
-- writeIORef state (old + 1)
|
||||
putStrLn ("Got a keypress")
|
||||
myonAnotherFrame fl = do
|
||||
curPuckRotation <- readIORef puckRotation
|
||||
writeIORef puckRotation (curPuckRotation + fl * 0.2)
|
||||
|
||||
--forM_ (zip[0..] puckSpots) $ \(i, (Vec2 x z)) -> aliceGenericMeshSetInst puck (fromIntegral i) (AliceGenericMeshInstance
|
||||
-- (rot4) ^*^ (mat4Transit (Vec3 x puckLevitationHeight z )))
|
||||
|
||||
|
||||
backDir <- aliceGetCamBack alice
|
||||
let projBack = projectDirOntoPlane backDir
|
||||
rightDir <- aliceGetCamRight alice
|
||||
let projRight = projectDirOntoPlane rightDir
|
||||
goForward <- aliceIsPressed alice (fromIntegral $ ord 'w')
|
||||
when goForward $ do
|
||||
curHeroPos <- readIORef heroPos
|
||||
let nextHeroPos = (curHeroPos ^+^ (projBack ^*^ (fl * (-10))))
|
||||
writeIORef heroPos nextHeroPos
|
||||
aliceSetCamPos alice $ heroCamPos nextHeroPos
|
||||
goBackward <- aliceIsPressed alice (fromIntegral $ ord 's')
|
||||
when goBackward $ do
|
||||
curHeroPos <- readIORef heroPos
|
||||
let nextHeroPos = (curHeroPos ^+^ (projBack ^*^ (fl * (10))))
|
||||
writeIORef heroPos nextHeroPos
|
||||
aliceSetCamPos alice $ heroCamPos nextHeroPos
|
||||
goLeft <- aliceIsPressed alice (fromIntegral $ ord 'a')
|
||||
when goLeft $ do
|
||||
curHeroPos <- readIORef heroPos
|
||||
let nextHeroPos = (curHeroPos ^+^ (projRight ^*^ (fl * (-10))))
|
||||
writeIORef heroPos nextHeroPos
|
||||
aliceSetCamPos alice $ heroCamPos nextHeroPos
|
||||
goRight <- aliceIsPressed alice (fromIntegral $ ord 'd')
|
||||
when goRight $ do
|
||||
curHeroPos <- readIORef heroPos
|
||||
let nextHeroPos = (curHeroPos ^+^ (projRight ^*^ (fl * (10))))
|
||||
writeIORef heroPos nextHeroPos
|
||||
aliceSetCamPos alice $ heroCamPos nextHeroPos
|
||||
oldPos <- aliceGetCamPos alice
|
||||
goForward <- aliceIsPressed alice 0x77
|
||||
if goForward
|
||||
then do
|
||||
backDir <- aliceGetCamBack alice
|
||||
aliceSetCamPos alice (oldPos ^+^ (backDir ^*^ (-fl * 10)))
|
||||
else return ()
|
||||
|
||||
--cur <- readIORef state
|
||||
--aliceClearScreenTextLabel alicePerm
|
||||
--aliceAddScreenTextLabel alicePerm ("Current value is = " ++ show cur)
|
||||
|
||||
|
||||
-- Allocate space for the struct, poke it, and pass to C.
|
||||
aliceMainloop alice callbacks
|
||||
|
||||
120
src/l3/r4/r4.c
@ -18,107 +18,71 @@ AliceGenericMeshPath AliceGenericMeshPath_for_puck(){
|
||||
};
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
Alice* alice;
|
||||
LucyFace* font_face;
|
||||
RBTreeNodeLucyFaceFixedSize* font_face_of_size_40;
|
||||
} R4AlphaStuff;
|
||||
|
||||
void main_h_on_wayland_keyboard_key(void* data, U32 keysym, U32 act){
|
||||
|
||||
}
|
||||
|
||||
void main_h_on_another_frame(void* data, float fl){
|
||||
R4AlphaStuff *st = data;
|
||||
Alice* alice = st->alice;
|
||||
margaret_ns_time TIME = margaret_clock_gettime_monotonic_raw();
|
||||
// printf("Updating text\n");
|
||||
// LucyRenderer_clear(&alice->lucy_renderer);
|
||||
// VecU8 text = VecU8_fmt("Time is %u.%u\nHave a good day sir\n", (U64)TIME.tv_sec, (U64)TIME.tv_nsec);
|
||||
// LucyRenderer_add_text(&alice->lucy_renderer, st->font_face_of_size_40, (vec4){0.1f, 0.2f, 0, 1}, 0,
|
||||
// VecU8_to_span(&text), (ivec2){100, 100});
|
||||
|
||||
}
|
||||
|
||||
int main(){
|
||||
R4AlphaStuff st;
|
||||
Alice* alice = Alice_new();
|
||||
st.alice = alice;
|
||||
st.alice->guest = &st;
|
||||
|
||||
// st.font_face = LucyFace_new(st.alice->ft_library, &st.alice->lucy_cache,
|
||||
// VecU8_fmt("%s/src/l3/fonts/DMSerifText-Regular.ttf", cstr(".")));
|
||||
st.font_face = LucyFace_new(st.alice->ft_library, &st.alice->lucy_cache,
|
||||
VecU8_fmt("%s/src/l3/fonts/GreatVibes-Regular.ttf", cstr(".")));
|
||||
st.font_face_of_size_40 = LucyFace_of_size(st.font_face, 40);
|
||||
LucyFace* font_face = LucyFace_new(alice->ft_library, &alice->lucy_cache,
|
||||
VecU8_fmt("%s/src/l3/fonts/DMSerifText-Regular.ttf", cstr(".")));
|
||||
RBTreeNodeLucyFaceFixedSize* font_face_of_size_40 = LucyFace_of_size(font_face, 40);
|
||||
VecLucyGlyphCachingRequest lucy_requests = VecLucyGlyphCachingRequest_new();
|
||||
VecU32Segment ranges_needed = VecU32Segment_new();
|
||||
VecU32Segment_append(&ranges_needed, (U32Segment){.start = 32, .len = 126 - 32 + 1});
|
||||
VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){
|
||||
.sized_face = st.font_face_of_size_40, .codepoint_ranges = ranges_needed,
|
||||
.sized_face = font_face_of_size_40, .codepoint_ranges = ranges_needed,
|
||||
});
|
||||
LucyGlyphCache_add_glyphs(lucy_requests);
|
||||
lucy_requests = VecLucyGlyphCachingRequest_new();
|
||||
ranges_needed = VecU32Segment_new();
|
||||
VecU32Segment_append(&ranges_needed, (U32Segment){.start = 0x430, .len = 0x44f - 0x430 + 1});
|
||||
VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){
|
||||
.sized_face = st.font_face_of_size_40, .codepoint_ranges = ranges_needed,
|
||||
});
|
||||
|
||||
LucyGlyphCache_add_glyphs(lucy_requests);
|
||||
LucyRenderer_add_simple_label(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
|
||||
cstr("Bebra budet\nотнюхана\n"), (ivec2){10, 10});
|
||||
LucyRenderer_add_text(&alice->lucy_renderer, font_face_of_size_40, (vec4){1, 0, 0, 1}, 0,
|
||||
cstr("Bebra budet\notnyahana"), (ivec2){10, 10});
|
||||
|
||||
// ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(st.alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6));
|
||||
// AliceGenericMeshHand_resize_instance_arr(st.alice, &model_gen->el, 1);
|
||||
//
|
||||
// for (int X = 0; X < 1; X++) {
|
||||
// for (int Z = 0; Z < 1; Z++) {
|
||||
// AliceGenericMeshHand_set_inst(&model_gen->el, X * 10 + Z, (GenericMeshInstanceInc){
|
||||
// .model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}),
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6));
|
||||
AliceGenericMeshHand_resize_instance_arr(alice, &model_gen->el, 1);
|
||||
|
||||
ListNodeAliceShinyMeshHand *model_sh = Alice_add_shiny_mesh(st.alice, vcstr("./gen/l2/models/cube.AliceShinyMesh"));
|
||||
AliceShinyMeshHand_resize_instance_arr(st.alice, &model_sh->el, 100);
|
||||
|
||||
for (int X = 0; X < 10; X++) {
|
||||
for (int Z = 0; Z < 10; Z++) {
|
||||
AliceShinyMeshHand_set_inst(&model_sh->el, X * 10 + Z, (ShinyMeshInstanceInc){
|
||||
.color_on = {0, 1, 0},
|
||||
.model_t = marie_translation_mat4((vec3){11.f * (float)X - 20, 10, 4.f * (float)Z - 10}),
|
||||
for (int X = 0; X < 1; X++) {
|
||||
for (int Z = 0; Z < 1; Z++) {
|
||||
AliceGenericMeshHand_set_inst(&model_gen->el, X * 10 + Z, (GenericMeshInstanceInc){
|
||||
.model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&st.alice->pipeline0_ubo.staging);
|
||||
assert(pipeline_0_ubo_point_light_max_count >= 100);
|
||||
ubo->point_light_count = 100;
|
||||
ubo->spotlight_count = 0;
|
||||
for (int X = 0; X < 10; X++) {
|
||||
for (int Z = 0; Z < 10; Z++) {
|
||||
ubo->point_light_arr[X * 10 + Z] = (Pipeline0PointLight){
|
||||
.pos = (vec3){11.f * (float)X - 20, 10, 4.f * (float)Z - 10},
|
||||
.color = {5, 5, 5}
|
||||
};
|
||||
}
|
||||
}
|
||||
ubo->point_light_arr[0].color = (vec3){100, 100, 100};
|
||||
// ListNodeAliceShinyMeshHand *model_sh = Alice_add_shiny_mesh(alice, vcstr("./gen/l2/models/cube.AliceShinyMesh"));
|
||||
// AliceShinyMeshHand_resize_instance_arr(alice, &model_sh->el, 100);
|
||||
|
||||
// for (int X = 0; X < 10; X++) {
|
||||
// for (int Z = 0; Z < 10; Z++) {
|
||||
// AliceShinyMeshHand_set_inst(&model_sh->el, X * 10 + Z, (ShinyMeshInstanceInc){
|
||||
// .color_on = {0, 1, 0}, .color_off = {0.3f, 0.6f, 0.3f},
|
||||
// .model_t = marie_translation_mat4((vec3){11.f * (float)X - 20, 10, 4.f * (float)Z - 10}),
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging);
|
||||
// assert(pipeline_0_ubo_point_light_max_count >= 100);
|
||||
// ubo->point_light_count = 100;
|
||||
// ubo->spotlight_count = 0;
|
||||
// for (int X = 0; X < 10; X++) {
|
||||
// for (int Z = 0; Z < 10; Z++) {
|
||||
// ubo->point_light_arr[X * 10 + Z] = (Pipeline0PointLight){
|
||||
// .pos = (vec3){11.f * (float)X - 20, 10, 4.f * (float)Z - 10},
|
||||
// .color = {5, 5, 5}
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// ubo->point_light_arr[0].color = (vec3){100, 100, 100};
|
||||
|
||||
|
||||
ListNodeAliceGenericMeshHand* skeleton_mesh = Alice_add_generic_mesh(st.alice, (AliceGenericMeshPath){
|
||||
.topology_path = vcstr("./src/l3/models/skeleton.obj"),
|
||||
.diffuse_texture_path = vcstr("./src/l3/models/bone.png"),
|
||||
.normal_texture_path = vcstr("./gen/l2/textures/flat_NORMAL.png"),
|
||||
.specular_texture_path = vcstr("./gen/l2/textures/flat_NORMAL.png"),
|
||||
});
|
||||
|
||||
AliceGenericMeshHand_resize_instance_arr(alice, &skeleton_mesh->el, 1);
|
||||
AliceGenericMeshHand_set_inst(&skeleton_mesh->el, 0, (GenericMeshInstanceInc){
|
||||
.model_t = marie_translation_mat4((vec3){5.f, -3, 12.f}),
|
||||
});
|
||||
|
||||
// ListNodeAliceGenericMeshHand* model_puck = Alice_add_generic_mesh(st->alice, AliceGenericMeshPath_for_puck());
|
||||
// AliceGenericMeshHand_resize_instance_arr(st->alice, &model_puck->el, 100);
|
||||
// ListNodeAliceGenericMeshHand* model_puck = Alice_add_generic_mesh(alice, AliceGenericMeshPath_for_puck());
|
||||
// AliceGenericMeshHand_resize_instance_arr(alice, &model_puck->el, 100);
|
||||
// for (int X = 0; X < 10; X++) {
|
||||
// for (int Z = 0; Z < 10; Z++) {
|
||||
// AliceGenericMeshHand_set_inst(&model_puck->el, X * 10 + Z, (GenericMeshInstanceInc){
|
||||
@ -126,7 +90,7 @@ int main(){
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
Alice_mainloop(st.alice, &(AliceCallbacks){
|
||||
Alice_mainloop(alice, &(AliceCallbacks){
|
||||
.on_wl_keyboard_key = main_h_on_wayland_keyboard_key,
|
||||
.on_another_frame = main_h_on_another_frame,
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 544 B |
|
Before Width: | Height: | Size: 282 B |
@ -1,7 +1,7 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 norm;
|
||||
layout(location = 1) in vec3 color_off;
|
||||
layout(location = 1) in vec3 color_off;
|
||||
layout(location = 2) in vec3 color_on;
|
||||
layout(location = 3) in vec3 pos;
|
||||
|
||||
@ -50,6 +50,6 @@ void main(){
|
||||
for (int i = 0; i < spotlight_count; i++) {
|
||||
Pipeline0Spotlight lamp = spotlight_arr[i];
|
||||
}
|
||||
vec3 color = color_off * diffuse_illumination + (0.05 + 0.45 * length(color_off)) * specular_illumination + color_on;
|
||||
vec3 color = color_off * diffuse_illumination + 0.5 * specular_illumination + color_on;
|
||||
fin_color = vec4(color, 1);
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 pos;
|
||||
layout(location = 1) in vec3 color;
|
||||
layout(location = 2) in vec3 normal;
|
||||
layout(location = 1) in vec3 normal;
|
||||
|
||||
layout(location = 3) in mat4 model_t;
|
||||
/* 3 <- 4, 5, 6 */
|
||||
layout(location = 2) in mat4 model_t;
|
||||
/* 2 <- 3, 4, 5 */
|
||||
layout(location = 6) in vec3 color_off;
|
||||
layout(location = 7) in vec3 color_on;
|
||||
layout(location = 8) in mat3 normal_t;
|
||||
/* 8 <- 9, 10 */
|
||||
@ -21,7 +21,7 @@ layout(push_constant, std430) uniform pc {
|
||||
|
||||
void main(){
|
||||
vsout_normal = normalize(normal_t * normal);
|
||||
vsout_color_off = color;
|
||||
vsout_color_off = color_off;
|
||||
vsout_color_on = color_on;
|
||||
vec4 real_pos = model_t * vec4(pos, 1);
|
||||
vsout_pos = real_pos.xyz;
|
||||
|
||||
@ -13,5 +13,4 @@ layout (binding=0) uniform sampler2D images[];
|
||||
void main(){
|
||||
float I = texture(images[nonuniformEXT(tex_ind)], tex_cord).r;
|
||||
fin_color = vec4(color.rgb, color.a * I);
|
||||
//fin_color = vec4(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 color;
|
||||
layout(location = 1) in vec2 lt_pos;
|
||||
layout(location = 2) in vec2 br_pos;
|
||||
layout(location = 3) in vec2 lt_tex;
|
||||
layout(location = 4) in vec2 br_tex;
|
||||
layout(location = 5) in uint tex_ind;
|
||||
layout(location = 1) in vec2 pos;
|
||||
layout(location = 2) in vec2 tex_cord;
|
||||
layout(location = 3) in uint tex_ind;
|
||||
|
||||
layout(push_constant, std430) uniform pc {
|
||||
float width;
|
||||
@ -25,17 +23,8 @@ float deng(float B1, float x){
|
||||
}
|
||||
|
||||
void main(){
|
||||
const vec2 all_v_pos[6] = vec2[](
|
||||
vec2(br_pos.x, lt_pos.y), lt_pos, vec2(lt_pos.x, br_pos.y),
|
||||
vec2(br_pos.x, lt_pos.y), vec2(lt_pos.x, br_pos.y), br_pos
|
||||
);
|
||||
const vec2 all_v_tex[6] = vec2[](
|
||||
vec2(br_tex.x, lt_tex.y), lt_tex, vec2(lt_tex.x, br_tex.y),
|
||||
vec2(br_tex.x, lt_tex.y), vec2(lt_tex.x, br_tex.y), br_tex
|
||||
);
|
||||
vsout_color = color;
|
||||
vsout_tex_cord = all_v_tex[gl_VertexIndex % 6];
|
||||
vsout_tex_cord = tex_cord;
|
||||
vsout_tex_ind = tex_ind;
|
||||
vec2 pos = all_v_pos[gl_VertexIndex % 6];
|
||||
gl_Position = vec4(deng(width, pos.x), deng(height, pos.y), 0, 1);
|
||||
}
|
||||
|
||||