Compare commits

..

No commits in common. "master" and "r0-to-allie" have entirely different histories.

109 changed files with 4278 additions and 6033814 deletions

1
.gitignore vendored
View File

@ -17,4 +17,3 @@ GRAPH*.png
SICK_JOKE*
*.hi
*_stub.h
copying_to_cpp.sh

View File

@ -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)
@ -59,10 +57,8 @@ target_link_libraries(r2c -lm)
#add_executable(l2t0 src/l2/tests/data_structures/t0.c)
#add_executable(l2t1 src/l2/tests/data_structures/t1.c)
add_executable(l2_t_parsing src/l2/tests/t_parsing.c)
add_executable(l2_tex_gen src/l2/anne/codegen.c)
target_link_libraries(l2_tex_gen -lm -lpng)
add_executable(l3_r4 src/l3/r4/r4.c gen/l_wl_protocols/xdg-shell-private.c)
target_link_libraries(l3_r4 -lvulkan -lwayland-client -lm -lxkbcommon -lpng -lfreetype)
add_executable(l2_r4 src/l3/r4/r4.c gen/l_wl_protocols/xdg-shell-private.c)
target_link_libraries(l2_r4 -lvulkan -lwayland-client -lm -lxkbcommon -lpng -lfreetype)

View File

@ -16,8 +16,6 @@ HEADERS_src_l2 := $(HEADERS_gen_l1_5) $(call find_headers,l2)
#HEADERS_gen_l2 := $(HEADERS_src_l2) gen/l2/dorothy.txt
HEADERS_gen_l2 := gen/l2/dorothy.txt
HEADERS_src_l3 := $(HEADERS_gen_l2) $(call find_headers,l3)
cflags := -Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type -Wno-unused-parameter \
--std=c99 -g -ggdb -O0 \
-fno-trapping-math -D_POSIX_C_SOURCE=200112L -D_GNU_SOURCE
@ -69,8 +67,8 @@ gen/l_wl_protocols/xdg-shell-private.c: $(wl_protocols)/stable/xdg-shell/xdg-she
mkdir -p gen/l_wl_protocols
wayland-scanner private-code $< $@
.PHONY: gen_l_wl_protocols
gen_l_wl_protocols : $(l_wl_protocols)
.PHONY: gen/l_wl_protocols
gen/l_wl_protocols : $(l_wl_protocols)
out/l2/codegen: src/l2/anne/codegen.c $(HEADERS_src_l2)
mkdir -p out/l2
@ -147,14 +145,6 @@ out/l3/r4: src/l3/r4/R4.hs src/l2/allie/Allie.hs $(full_allie_obj)
run_r4: out/l3/r4
./out/l3/r4
out/l3/r4b: src/l3/r4/r4.c $(HEADERS_src_l3) $(l_wl_protocols) $(ASSETS_gen_l_adele)
mkdir -p out/l3
$(cc) $(cflags) -o $@ $< $(xdg_shell_private_c) -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype
.PHONY: run_r4b
run_r4b: out/l3/r4b
./out/l3/r4b
.PHONY: clean
clean:
rm -rf gen out

View File

@ -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

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_anne_alice_h
#define prototype1_src_l1_anne_alice_h
#include "../codegen/codegen.h"
@ -19,8 +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

View File

@ -8,13 +8,12 @@
#include "some_tests.h"
#include "util_temp_vulkan.h"
#include "margaret/margaret_misc.h"
#include "marie.h"
#include "marie/graphics_geom.h"
#include "liza.h"
#include "embassy_l1_5.h"
#include "margaret/png_pixel_masses.h"
#include "lucy.h"
#include "alice.h"
#include "precise_integers.h"
int main() {
mkdir_nofail("l1");
@ -25,14 +24,13 @@ int main() {
generate_pixel_masses_header();
generate_headers_for_r0_r1_r2_r3();
generate_util_templ_inst_for_vulkan_headers();
generate_l1_headers_for_marie();
generate_marie_headers_for_graphics_geom();
generate_liza_l1_headers();
generate_l1_headers_for_l1_5();
generate_margaret_eve_for_vulkan_utils(); /* margaret misc */
generate_margaret_png_pixel_masses_header();
generate_l1_lucy_headers();
generate_code_for_alice_on_l1();
generate_l1_header_for_precise_integers();
finish_layer(cstr("l1"));
return 0;
}

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_ANNE_CODEGEN_FROM_L1_5_H
#define PROTOTYPE1_SRC_L1_ANNE_CODEGEN_FROM_L1_5_H
#include "../codegen/util_template_inst.h"
@ -11,3 +12,5 @@ void generate_l1_headers_for_l1_5() {
generate_eve_span_company_for_primitive(l, ns, cstr("NamedMethodSignatureRecordRef"), false, true);
generate_eve_span_company_for_primitive(l, ns, cstr("BufRBTreeNode"), true, false);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE_SRC_L1_CODEGEN_GEOM_H
#define PROTOTYPE_SRC_L1_CODEGEN_GEOM_H
#include "../codegen/codegen.h"
@ -12,137 +13,147 @@ NODISCARD VecU8 codegen_name_xvecn(SpanU8 xvec, int n) {
return VecU8_fmt("%s%c", xvec, '0' + n);
}
void codegen_append_xvecn_struct_and_base_methods(VecU8* res, SpanU8 xvec, SpanU8 memb, int n) {
VecU8 xvecn = codegen_name_xvecn(xvec, n);
NODISCARD VecU8 generate_xvecn_struct_and_base_methods(SpanU8 xvec, SpanU8 memb, int n) {
VecU8 g_xvecn = codegen_name_xvecn(xvec, n);
SpanU8 xvecn = VecU8_to_span(&g_xvecn);
VecU8 res = VecU8_new();
/* Structure definition */
VecU8_append_cstr(res, "typedef struct {\n");
VecU8_append_span(&res, cstr("typedef struct {\n"));
for (int ci = 0; ci < n; ci++) {
VecU8_append_fmt(res, SPACE "%s %s;\n", memb, vec_field_name(ci));
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s %s;\n", memb, vec_field_name(ci)));
}
VecU8_append_fmt(res, "} %r;\n\n", xvecn);
VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", xvecn));
/* xvecn_add_xvecn method */
VecU8_append_fmt(res,
"%r %r_add_%r(%r A, %r B) {\n"
SPACE "return(%r){ ",
xvecn, xvecn, xvecn, xvecn, xvecn, xvecn);
for (int ci = 0; ci < n; ci++) {
if (ci)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "A.%s + B.%s", vec_field_name(ci), vec_field_name(ci));
}
VecU8_append_cstr(res, " };\n}\n\n");
/* xvecn_minus_xvecn method */
VecU8_append_vec(res, VecU8_fmt(
"%r %r_minus_%r(%r A, %r B) {\n"
SPACE "return (%r){ ",
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_add_%s(%s A, %s B) {\n"
SPACE "return(%s){ ",
xvecn, xvecn, xvecn, xvecn, xvecn, xvecn));
for (int ci = 0; ci < n; ci++) {
if (ci)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "A.%s - B.%s", vec_field_name(ci), vec_field_name(ci));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("A.%s + B.%s", vec_field_name(ci), vec_field_name(ci)));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xvecn_minus_xvecn method */
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_minus_%s(%s A, %s B) {\n"
SPACE "return (%s){ ",
xvecn, xvecn, xvecn, xvecn, xvecn, xvecn));
for (int ci = 0; ci < n; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("A.%s - B.%s", vec_field_name(ci), vec_field_name(ci)));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xvecn_minus method */
VecU8_append_fmt(res,
"%r %r_minus(%r A) {\n"
SPACE "return (%r){ ",
xvecn, xvecn, xvecn, xvecn);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_minus(%s A) {\n"
SPACE "return (%s){ ",
xvecn, xvecn, xvecn, xvecn));
for (int ci = 0; ci < n; ci++) {
if (ci)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "-A.%s", vec_field_name(ci));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("-A.%s", vec_field_name(ci)));
}
VecU8_append_cstr(res, " };\n}\n\n");
/* xvecn_mul_scal method */
VecU8_append_fmt(res,
"%r %r_mul_scal(%r A, %s B) {\n"
SPACE "return (%r) { ",
xvecn, xvecn, xvecn, memb, xvecn);
for (int ci = 0; ci < n; ci++) {
if (ci)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "A.%s * B", vec_field_name(ci));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
VecU8_drop(xvecn);
VecU8_drop(g_xvecn);
return res;
}
void codegen_append_xvecn_struct_and_cool_methods(VecU8* res, SpanU8 xvec, SpanU8 memb, int n, SpanU8 sqrt_func) {
VecU8 xvecn = codegen_name_xvecn(xvec, n);
codegen_append_xvecn_struct_and_base_methods(res, xvec, memb, n);
NODISCARD VecU8 generate_xvecn_struct_and_cool_methods(SpanU8 xvec, SpanU8 memb, int n, SpanU8 sqrt_func) {
VecU8 g_xvecn = codegen_name_xvecn(xvec, n);
SpanU8 xvecn = VecU8_to_span(&g_xvecn);
VecU8 res = generate_xvecn_struct_and_base_methods(xvec, memb, n);
/* xvecn_length method */
VecU8_append_fmt(res,
"%s %r_length(%r A) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_length(%s A) {\n"
SPACE "return %s(",
memb, xvecn, xvecn, sqrt_func);
memb, xvecn, xvecn, sqrt_func));
for (int i = 0; i < n; i++) {
if (i)
VecU8_append_cstr(res, " + ");
VecU8_append_fmt(res, "A.%s * A.%s", vec_field_name(i), vec_field_name(i));
VecU8_append_span(&res, cstr(" + "));
VecU8_append_vec(&res, VecU8_fmt("A.%s * A.%s", vec_field_name(i), vec_field_name(i)));
}
VecU8_append_cstr(res, ");\n}\n\n");
/* xvecn_div_by_scal method */
VecU8_append_fmt(res,
"%r %r_div_by_scal(%r A, %s B) {\n"
SPACE "return %r_mul_scal(A, 1/B);\n"
"}\n\n", xvecn, xvecn, xvecn, memb, xvecn);
/* xvecn_mul_xvecn method */
VecU8_append_fmt(res,
"%r %r_mul_%r(%r A, %r B) {\n"
SPACE "return (%r){ ",
xvecn, xvecn, xvecn, xvecn, xvecn, xvecn);
VecU8_append_span(&res, cstr(");\n}\n\n"));
/* xvecn_mul_scal method */
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_mul_scal(%s A, %s B) {\n"
SPACE "return (%s) { ",
xvecn, xvecn, xvecn, memb, xvecn));
for (int ci = 0; ci < n; ci++) {
if (ci)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "A.%s * B.%s", vec_field_name(ci), vec_field_name(ci));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("A.%s * B", vec_field_name(ci)));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xvecn_div_by_scal method */
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_div_by_scal(%s A, %s B) {\n"
SPACE "return %s_mul_scal(A, 1/B);\n"
"}\n\n", xvecn, xvecn, xvecn, memb, xvecn));
/* xvecn_mul_xvecn method */
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_mul_%s(%s A, %s B) {\n"
SPACE "return (%s){ ",
xvecn, xvecn, xvecn, xvecn, xvecn, xvecn));
for (int ci = 0; ci < n; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("A.%s * B.%s", vec_field_name(ci), vec_field_name(ci)));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xvecn_dot method */
VecU8_append_fmt(res,
"%s %r_dot(%r A, %r B) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_dot(%s A, %s B) {\n"
SPACE "return ",
memb, xvecn, xvecn, xvecn);
memb, xvecn, xvecn, xvecn));
for (int i = 0; i < n; i++) {
if (i)
VecU8_append_cstr(res, " + ");
VecU8_append_fmt(res, "A.%s * B.%s", vec_field_name(i), vec_field_name(i));
VecU8_append_span(&res, cstr(" + "));
VecU8_append_vec(&res, VecU8_fmt("A.%s * B.%s", vec_field_name(i), vec_field_name(i)));
}
VecU8_append_cstr(res, ";\n}\n\n");
VecU8_append_span(&res, cstr(";\n}\n\n"));
/* xvecn_normalize method */
VecU8_append_fmt(res,
"%r %r_normalize(%r A) {\n"
SPACE "return %r_div_by_scal(A, %r_length(A));\n"
"}\n\n", xvecn, xvecn, xvecn, xvecn, xvecn);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_normalize(%s A) {\n"
SPACE "return %s_div_by_scal(A, %s_length(A));\n"
"}\n\n", xvecn, xvecn, xvecn, xvecn, xvecn));
VecU8_drop(xvecn);
VecU8_drop(g_xvecn);
return res;
}
void codegen_append_xvecn_method_and_one(VecU8* res, SpanU8 xvec, int n) {
NODISCARD VecU8 generate_xvecn_method_and_one(SpanU8 xvec, int n) {
assert(2 <= n && n < 4);
VecU8 xvecn = codegen_name_xvecn(xvec, n);
VecU8 xvecn_pp = codegen_name_xvecn(xvec, n + 1);
VecU8 g_xvecn = codegen_name_xvecn(xvec, n);
VecU8 g_xvecn_pp = codegen_name_xvecn(xvec, n + 1);
SpanU8 xvecn = VecU8_to_span(&g_xvecn);
SpanU8 xvecn_pp = VecU8_to_span(&g_xvecn_pp);
VecU8_append_fmt(res,
"%r %r_and_one(%r A) {\n"
SPACE "return (%r){ ",
VecU8 res = VecU8_fmt(
"%s %s_and_one(%s A) {\n"
SPACE "return (%s){ ",
xvecn_pp, xvecn, xvecn, xvecn_pp);
for (int i = 0; i < n; i++) {
VecU8_append_fmt(res, "A.%s, ", vec_field_name(i));
VecU8_append_vec(&res, VecU8_fmt("A.%s, ", vec_field_name(i)));
}
VecU8_append_cstr(res, "1 };\n}\n\n");
VecU8_append_span(&res, cstr("1 };\n}\n\n"));
VecU8_drop(xvecn_pp);
VecU8_drop(xvecn);
VecU8_drop(g_xvecn_pp);
VecU8_drop(g_xvecn);
return res;
}
void codegen_append_xvec3_method_cross(VecU8* res, SpanU8 xvec) {
VecU8 xvec3 = codegen_name_xvecn(xvec, 3);
VecU8_append_fmt(res,
"%r %r_cross(%r A, %r B) {\n"
SPACE "return (%r){A.y * B.z - A.z * B.y, -A.x * B.z + A.z * B.x, A.x * B.y - A.y * B.x};\n"
NODISCARD VecU8 generate_xvec3_method_cross(SpanU8 xvec) {
VecU8 g_xvec3 = codegen_name_xvecn(xvec, 3);
SpanU8 xvec3 = VecU8_to_span(&g_xvec3);
VecU8 res = VecU8_fmt(
"%s %s_cross(%s A, %s B) {\n"
SPACE "return (%s){A.y * B.z - A.z * B.y, -A.x * B.z + A.z * B.x, A.x * B.y - A.y * B.x};\n"
"}\n\n", xvec3, xvec3, xvec3, xvec3, xvec3);
VecU8_drop(xvec3);
VecU8_drop(g_xvec3);
return res;
}
NODISCARD VecU8 codegen_name_xmatnm(SpanU8 xmat, int cols, int rows) {
@ -152,256 +163,201 @@ NODISCARD VecU8 codegen_name_xmatnm(SpanU8 xmat, int cols, int rows) {
return VecU8_fmt("%s%cx%c", xmat, '0' + cols, '0' + rows);
}
void codegen_append_xmatnm_struct_and_methods(VecU8* res,
NODISCARD VecU8 generate_xmatnm_struct_and_methods(
SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int cols, int rows, int sizeof_member
) {
VecU8 xmatnm = codegen_name_xmatnm(xmat, cols, rows);
VecU8 xvecm = codegen_name_xvecn(xvec, rows);
VecU8 g_xmatnm = codegen_name_xmatnm(xmat, cols, rows);
SpanU8 xmatnm = VecU8_to_span(&g_xmatnm);
VecU8 g_xvecm = codegen_name_xvecn(xvec, rows);
SpanU8 xvecm = VecU8_to_span(&g_xvecm);
VecU8 res = VecU8_new();
/* Structure xmatnm. todo: NO, std140 is NOT OUR EVERYTHING. TODO: get rid of padding
/* Structure xmatnm
* With columns padded to 16 bytes (for std140, std140 is our everything) */
int sv = (rows * sizeof_member) % 16;
VecU8_append_cstr(res, "typedef struct {\n");
VecU8_append_span(&res, cstr("typedef struct {\n"));
for (int x = 0; x < cols; x++) {
VecU8_append_fmt(res, SPACE "%r %s;\n", xvecm, vec_field_name(x));
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s %s;\n", xvecm, vec_field_name(x)));
if (sv) {
VecU8_append_fmt(res, SPACE "char _padding_%u[%u];\n", (U64)x, (U64)(16 - sv));
VecU8_append_vec(&res, VecU8_fmt(SPACE "char _padding_%u[%u];\n", (U64)x, (U64)(16 - sv)));
}
}
VecU8_append_fmt(res, "} %r;\n\n", xmatnm);
VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", xmatnm));
/* xmatnm_new method */
VecU8_append_fmt(res, "%r %r_new(", xmatnm, xmatnm);
VecU8_append_vec(&res, VecU8_fmt("%s %s_new(", xmatnm, xmatnm));
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
if (x > 0 || y > 0)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "%s %s%s", memb, vec_field_name(x), vec_field_name(y));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("%s %s%s", memb, vec_field_name(x), vec_field_name(y)));
}
}
VecU8_append_fmt(res, ") {\n" SPACE "return (%r){ ", xmatnm);
VecU8_append_vec(&res, VecU8_fmt(") {\n" SPACE "return (%s){ ", xmatnm));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, ".%s = { ", vec_field_name(x));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt(".%s = { ", vec_field_name(x)));
for (int y = 0; y < rows; y++) {
if (y)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "%s%s", vec_field_name(x), vec_field_name(y));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("%s%s", vec_field_name(x), vec_field_name(y)));
}
VecU8_append_cstr(res, " }");
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xmatnm_add_xmatnm method */
VecU8_append_fmt(res,
"%r %r_add_%r(%r A, %r B) {\n"
SPACE "return (%r){ ",
xmatnm, xmatnm, xmatnm, xmatnm, xmatnm, xmatnm);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_add_%s(%s A, %s B) {\n"
SPACE "return (%s){ ",
xmatnm, xmatnm, xmatnm, xmatnm, xmatnm, xmatnm));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, ".%s = %r_add_%r(A.%s, B.%s)",
vec_field_name(x), xvecm, xvecm, vec_field_name(x), vec_field_name(x));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt(".%s = %s_add_%s(A.%s, B.%s)",
vec_field_name(x), xvecm, xvecm, vec_field_name(x), vec_field_name(x)));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xmatnm_minus_xmatnm method */
VecU8_append_fmt(res,
"%r %r_minus_%r(%r A, %r B) {\n"
SPACE "return (%r){ ",
xmatnm, xmatnm, xmatnm, xmatnm, xmatnm, xmatnm);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_minus_%s(%s A, %s B) {\n"
SPACE "return (%s){ ",
xmatnm, xmatnm, xmatnm, xmatnm, xmatnm, xmatnm));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, ".%s = %r_minus_%r(A.%s, B.%s)",
vec_field_name(x), xvecm, xvecm, vec_field_name(x), vec_field_name(x));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt(".%s = %s_minus_%s(A.%s, B.%s)",
vec_field_name(x), xvecm, xvecm, vec_field_name(x), vec_field_name(x)));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xmatnm_minus method */
VecU8_append_fmt(res,
"%r %r_minus(%r A) {\n"
SPACE "return (%r){ ",
xmatnm, xmatnm, xmatnm, xmatnm);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_minus(%s A) {\n"
SPACE "return (%s){ ",
xmatnm, xmatnm, xmatnm, xmatnm));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, ".%s = %r_minus(A.%s)",
vec_field_name(x), xvecm, vec_field_name(x));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt(".%s = %s_minus(A.%s)",
vec_field_name(x), xvecm, vec_field_name(x)));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xmatnm_mul_scal method */
VecU8_append_fmt(res,
"%r %r_mul_scal(%r A, %s B) {\n"
SPACE "return (%r){ ",
xmatnm, xmatnm, xmatnm, memb, xmatnm);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_mul_scal(%s A, %s B) {\n"
SPACE "return (%s){ ",
xmatnm, xmatnm, xmatnm, memb, xmatnm));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, ".%s = %r_mul_scal(A.%s, B)",
vec_field_name(x), xvecm, vec_field_name(x));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt(".%s = %s_mul_scal(A.%s, B)",
vec_field_name(x), xvecm, vec_field_name(x)));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
/* xmatnm_div_by_scal method */
VecU8_append_fmt(res,
"%r %r_div_by_scal(%r A, %s B) {\n"
SPACE "return %r_mul_scal(A, 1/B);\n"
"}\n\n", xmatnm, xmatnm, xmatnm, memb, xmatnm);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_div_by_scal(%s A, %s B) {\n"
SPACE "return %s_mul_scal(A, 1/B);\n"
"}\n\n", xmatnm, xmatnm, xmatnm, memb, xmatnm));
VecU8 xvecn = codegen_name_xvecn(xvec, cols);
VecU8 g_xvecn = codegen_name_xvecn(xvec, cols);
SpanU8 xvecn = VecU8_to_span(&g_xvecn);
/* xmatnm_mul_xvecn */
VecU8_append_fmt(res,
"%r %r_mul_%r(%r A, %r B) {\n"
SPACE "return (%r){ ",
xvecm, xmatnm, xvecn, xmatnm, xvecn, xvecm);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_mul_%s(%s A, %s B) {\n"
SPACE "return (%s){ ",
xvecm, xmatnm, xvecn, xmatnm, xvecn, xvecm));
for (int y = 0; y < rows; y++) {
if (y)
VecU8_append(res, ',');
VecU8_append_cstr(res, "\n" SPACE8);
VecU8_append(&res, ',');
VecU8_append_span(&res, cstr("\n" SPACE8));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_cstr(res, " + ");
VecU8_append_fmt(res, "A.%s.%s * B.%s", vec_field_name(x), vec_field_name(y), vec_field_name(x));
VecU8_append_span(&res, cstr(" + "));
VecU8_append_vec(&res, VecU8_fmt("A.%s.%s * B.%s", vec_field_name(x), vec_field_name(y), vec_field_name(x)));
}
}
VecU8_append_cstr(res, "\n" SPACE "};\n}\n\n");
VecU8_append_span(&res, cstr("\n" SPACE "};\n}\n\n"));
VecU8_drop(xvecn);
VecU8_drop(xvecm);
VecU8_drop(xmatnm);
VecU8_drop(g_xvecn);
VecU8_drop(g_xvecm);
VecU8_drop(g_xmatnm);
return res;
}
/* xmatnm_transpose method */
void codegen_append_xmatnm_transpose_method(VecU8* res, SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int cols, int rows) {
VecU8 xmatnm = codegen_name_xmatnm(xmat, cols, rows);
VecU8 xmatmn = codegen_name_xmatnm(xmat, rows, cols);
VecU8_append_fmt(res,
"%r %r_transpose(%r A) {\n"
SPACE "return (%r){ ",
NODISCARD VecU8 generate_xmatnm_transpose_method(SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int cols, int rows) {
VecU8 g_xmatnm = codegen_name_xmatnm(xmat, cols, rows);
VecU8 g_xmatmn = codegen_name_xmatnm(xmat, rows, cols);
SpanU8 xmatnm = VecU8_to_span(&g_xmatnm);
SpanU8 xmatmn = VecU8_to_span(&g_xmatmn);
VecU8 res = VecU8_fmt(
"%s %s_transpose(%s A) {\n"
SPACE "return (%s){ ",
xmatmn, xmatnm, xmatnm, xmatmn);
for (int bx = 0; bx < rows; bx++) {
if (bx)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, ".%s = { ", vec_field_name(bx));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt(".%s = { ", vec_field_name(bx)));
for (int by = 0; by < cols; by++) {
if (by)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "A.%s.%s", vec_field_name(by), vec_field_name(bx));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("A.%s.%s", vec_field_name(by), vec_field_name(bx)));
}
VecU8_append_cstr(res, " }");
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
VecU8_drop(xmatmn);
VecU8_drop(xmatnm);
VecU8_drop(g_xmatmn);
VecU8_drop(g_xmatnm);
return res;
}
void codegen_append_xmat234_det_method(VecU8* res, SpanU8 xmat, SpanU8 xvec, SpanU8 memb){
VecU8_append_fmt(res,
"%s %s2_det(%s2 a){\n"
SPACE "return a.x.x * a.y.y - a.x.y * a.y.x;\n"
"}\n\n", memb, xmat, xmat);
VecU8_append_fmt(res,
"%s %s3_det(%s3 a){\n"
SPACE "return", memb, xmat, xmat);
for (int i = 0; i < 3; i++) {
if (i)
VecU8_append_cstr(res, "\n" SPACE SPACE);
for (int j = 0; j < 3; j++) {
if (j == i)
continue;
int k = 3 - i - j;
assert(k != i && k != j);
bool minused = ((i > j) + (j > k) + (i > k)) % 2;
VecU8_append_fmt(res, " %c a.x.%s * a.y.%s * a.z.%s",
minused ? '-' : '+', vec_field_name(i), vec_field_name(j), vec_field_name(k));
}
}
VecU8_append_cstr(res, ";\n}\n\n");
NODISCARD VecU8 generate_square_xmatn_methods(SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int n) {
VecU8 g_xmatn = codegen_name_xmatnm(xmat, n, n);
SpanU8 xmatn = VecU8_to_span(&g_xmatn);
VecU8 res = VecU8_new();
VecU8_append_fmt(res,
"%s %s4_det(%s4 a){\n"
SPACE "return", memb, xmat, xmat);
for (int i = 0; i < 4; i++) {
if (i)
VecU8_append_cstr(res, "\n" SPACE SPACE);
for (int j = 0; j < 4; j++) {
if (j == i)
continue;
for (int k = 0; k < 4; k++) {
if (i == k || j == k)
continue;
int u = 6 - i - j - k;
assert(u != i && u != j && u != k);
bool minused = ((i > j) + (j > k) + (i > k) + (i > u) + (j > u) + (k > u)) % 2;
VecU8_append_fmt(res, " %c a.x.%s * a.y.%s * a.z.%s * a.w.%s",
minused ? '-' : '+', vec_field_name(i), vec_field_name(j), vec_field_name(k), vec_field_name(u));
}
}
}
VecU8_append_cstr(res, ";\n}\n\n");
}
void codegen_append_square_xmatn_methods(VecU8* res, SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int n) {
VecU8 xmatn = codegen_name_xmatnm(xmat, n, n);
VecU8 xvecn = codegen_name_xvecn(xvec, n);
VecU8_append_fmt(res,
"const %r %r_E = { ", xmatn, xmatn);
VecU8_append_vec(&res, VecU8_fmt(
"const %s %s_E = { ", xmatn, xmatn));
for (int x = 0; x < n; x++) {
if (x)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, ".%s = {", vec_field_name(x));
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt(".%s = {", vec_field_name(x)));
for (int y = 0; y < n; y++) {
if (y)
VecU8_append_cstr(res, ", ");
VecU8_append(res, '0' + (x == y));
VecU8_append_span(&res, cstr(", "));
VecU8_append(&res, '0' + (x == y));
}
VecU8_append_cstr(res, " }");
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_cstr(res, " };\n\n");
VecU8_append_span(&res, cstr(" };\n\n"));
VecU8_append_fmt(res,
"%r %r_new_for_proj(%r v){\n" /* xmatn, xmatn, xvecn */
SPACE "return (%r){ ", /* xmatn */
xmatn, xmatn, xvecn, xmatn);
for (int x = 0; x < n; x++) {
VecU8_append_cstr(res, "\n" SPACE SPACE);
VecU8_append_fmt(res, ".%s={", vec_field_name(x));
for (int y = 0; y < n; y++) {
if (y)
VecU8_append_cstr(res, ", ");
VecU8_append_fmt(res, "v.%s * v.%s", vec_field_name(x), vec_field_name(y));
}
VecU8_append_cstr(res, "},");
}
VecU8_append_cstr(res, "};\n}\n\n");
VecU8_drop(xmatn);
VecU8_drop(xvecn);
VecU8_drop(g_xmatn);
return res;
}
void codegen_append_xmat_inverse_methods(VecU8* res, SpanU8 xmat, SpanU8 xvec, SpanU8 memb){
VecU8_append_fmt(res, "%s4 %s4_inverse(%s4 A) {\n", xmat, xmat, xmat);
VecU8_append_fmt(res, SPACE "%s m2[6][6] = {\n", memb);
NODISCARD VecU8 generate_xmat_inverse_methods(SpanU8 xmat, SpanU8 xvec, SpanU8 memb){
VecU8 res = VecU8_fmt("%s4 %s4_inverse(%s4 A) {\n", xmat, xmat, xmat);
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s m2[6][6] = {\n", memb));
SpanU8 first_of_pair[6] = {cstr("x"), cstr("x"), cstr("x"), cstr("y"), cstr("y"), cstr("z")};
SpanU8 second_of_pair[6] = {cstr("y"), cstr("z"), cstr("w"), cstr("z"), cstr("w"), cstr("w")};
for (int w_col = 0; w_col < 6; w_col++) {
VecU8_append_cstr(res, SPACE SPACE "{ ");
VecU8_append_span(&res, cstr(SPACE SPACE "{ "));
for (int w_row = 0; w_row < 6; w_row++) {
if (w_row)
VecU8_append_cstr(res, ", ");
VecU8_append_span(&res, cstr(", "));
/* first first = A second first = B
* first second = C second second = D
* A * D - B * C */
VecU8_append_fmt(res, "A.%s.%s * A.%s.%s - A.%s.%s * A.%s.%s",
VecU8_append_vec(&res, VecU8_fmt("A.%s.%s * A.%s.%s - A.%s.%s * A.%s.%s",
first_of_pair[w_col], first_of_pair[w_row], second_of_pair[w_col], second_of_pair[w_row],
second_of_pair[w_col], first_of_pair[w_row], first_of_pair[w_col], second_of_pair[w_row]
);
));
}
VecU8_append_cstr(res, " },\n");
VecU8_append_span(&res, cstr(" },\n"));
}
VecU8_append_cstr(res, SPACE "};\n");
VecU8_append_span(&res, cstr(SPACE "};\n"));
U64 a0_contr[4] = {5, 5, 4, 3};
U64 a1_contr[4] = {4, 2, 2, 1};
@ -409,152 +365,147 @@ void codegen_append_xmat_inverse_methods(VecU8* res, SpanU8 xmat, SpanU8 xvec, S
SpanU8 a0[4] = {cstr("y"), cstr("x"), cstr("x"), cstr("x")};
SpanU8 a1[4] = {cstr("z"), cstr("z"), cstr("y"), cstr("y")};
SpanU8 a2[4] = {cstr("w"), cstr("w"), cstr("w"), cstr("z")};
VecU8_append_fmt(res, SPACE "%s m3[4][4] = {\n", memb);
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s m3[4][4] = {\n", memb));
for (int no_col = 0; no_col < 4; no_col++) {
SpanU8 walking_column = a0[no_col];
U64 minor_col_pair = a0_contr[no_col];
VecU8_append_cstr(res, SPACE SPACE "{ ");
VecU8_append_span(&res, cstr(SPACE SPACE "{ "));
for (int no_row = 0; no_row < 4; no_row++) {
if (no_row)
VecU8_append_cstr(res, ", \n" SPACE SPACE);
VecU8_append_fmt(res,
VecU8_append_span(&res, cstr(", \n" SPACE SPACE));
VecU8_append_vec(&res, VecU8_fmt(
"A.%s.%s * m2[%u][%u] - A.%s.%s * m2[%u][%u] + A.%s.%s * m2[%u][%u]",
walking_column, a0[no_row], minor_col_pair, a0_contr[no_row],
walking_column, a1[no_row], minor_col_pair, a1_contr[no_row],
walking_column, a2[no_row], minor_col_pair, a2_contr[no_row]);
walking_column, a2[no_row], minor_col_pair, a2_contr[no_row]));
}
VecU8_append_cstr(res, " },\n");
VecU8_append_span(&res, cstr(" },\n"));
}
VecU8_append_cstr(res, SPACE "};\n");
VecU8_append_fmt(res,
VecU8_append_span(&res, cstr(SPACE "};\n"));
VecU8_append_vec(&res, VecU8_fmt(
SPACE "%s d = 1 / (A.x.x * m3[0][0] - A.x.y * m3[0][1] + A.x.z * m3[0][2] - A.x.w * m3[0][3]);\n"
SPACE "return (mat4){ ",
memb);
SPACE "return (mat4){ "
, memb));
for (U64 i = 0; i < 4; i++) {
if (i)
VecU8_append_cstr(res, ",\n" SPACE SPACE );
VecU8_append_fmt(res, ".%s={ ", vec_field_name((int)i));
VecU8_append_span(&res, cstr(",\n" SPACE SPACE ));
VecU8_append_vec(&res, VecU8_fmt(".%s={ ", vec_field_name((int)i)));
for (U64 j = 0; j < 4; j++) {
if (j)
VecU8_append_cstr(res,", ");
VecU8_append_fmt(res, "%sm3[%u][%u] * d",
(i + j) % 2 ? cstr("-") : cstr(""), j, i);
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt("%sm3[%u][%u] * d",
(i + j) % 2 ? cstr("-") : cstr(""), j, i));
}
VecU8_append_cstr(res, " }");
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"%s2 %s2_inverse(%s2 A) {\n" /* xmat, xmat, xmat */
SPACE "%s d = 1 / (A.x.x * A.y.y - A.y.x * A.x.y);\n" /* memb */
SPACE "return (%s2){ .x = { A.y.y * d, -A.x.y * d}, .y = {-A.y.x * d, A.x.x * d}};\n" /* xmat */
"}\n\n", xmat, xmat, xmat, memb, xmat);
"}\n\n", xmat, xmat, xmat, memb, xmat));
/* No inverse for mat3 yet :( */
// VecU8_append_vec(&res, VecU8_fmt( "%s3 %s3_inverse(%s3 A) {\n", xmat, xmat, xmat));
// VecU8_append_vec(&res, VecU8_fmt(SPACE "%s d = 1 / ("));
// VecU8_append_span(&res, cstr("}\n"));
return res;
}
void codegen_append_xmatnm_method_mul_xmatkn(VecU8* res, SpanU8 xmat, int n, int m, int k) {
VecU8 xmatkm = codegen_name_xmatnm(xmat, k, m);
VecU8 xmatnm = codegen_name_xmatnm(xmat, n, m);
VecU8 xmatkn = codegen_name_xmatnm(xmat, k, n);
NODISCARD VecU8 generate_xmatnm_method_mul_xmatkn(SpanU8 xmat, int n, int m, int k) {
VecU8 g_xmatkm = codegen_name_xmatnm(xmat, k, m);
VecU8 g_xmatnm = codegen_name_xmatnm(xmat, n, m);
VecU8 g_xmatkn = codegen_name_xmatnm(xmat, k, n);
SpanU8 xmatkm = VecU8_to_span(&g_xmatkm);
SpanU8 xmatnm = VecU8_to_span(&g_xmatnm);
SpanU8 xmatkn = VecU8_to_span(&g_xmatkn);
VecU8_append_fmt(res,
"%r %r_mul_%r(%r A, %r B) {\n"
SPACE "return (%r){ ",
VecU8 res = VecU8_fmt(
"%s %s_mul_%s(%s A, %s B) {\n"
SPACE "return (%s){ ",
xmatkm, xmatnm, xmatkn, xmatnm, xmatkn, xmatkm);
for (int x = 0; x < k; x++) {
if (x)
VecU8_append_cstr(res, ",");
VecU8_append_cstr(res, "\n" SPACE8);
VecU8_append_span(&res, cstr(","));
VecU8_append_span(&res, cstr("\n" SPACE8));
VecU8_append_fmt(res, ".%s = { ", vec_field_name(x));
VecU8_append_vec(&res, VecU8_fmt(".%s = { ", vec_field_name(x)));
for (int y = 0; y < m; y++) {
if (y)
VecU8_append_cstr(res, ", ");
VecU8_append_span(&res, cstr(", "));
for (int z = 0; z < n; z++) {
if (z)
VecU8_append_cstr(res, " + ");
VecU8_append_fmt(res, "A.%s.%s * B.%s.%s",
vec_field_name(z), vec_field_name(y), vec_field_name(x), vec_field_name(z));
VecU8_append_span(&res, cstr(" + "));
VecU8_append_vec(&res, VecU8_fmt("A.%s.%s * B.%s.%s",
vec_field_name(z), vec_field_name(y), vec_field_name(x), vec_field_name(z)));
}
}
VecU8_append_cstr(res, " }");
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_cstr(res, " };\n}\n\n");
VecU8_append_span(&res, cstr(" };\n}\n\n"));
VecU8_drop(xmatkm);
VecU8_drop(xmatnm);
VecU8_drop(xmatkn);
VecU8_drop(g_xmatkm);
VecU8_drop(g_xmatnm);
VecU8_drop(g_xmatkn);
return res;
}
void codegen_append_xvec234_structs_and_base_methods(VecU8* res, SpanU8 xvec, SpanU8 memb) {
NODISCARD VecU8 generate_xvec234_structs_and_base_methods(SpanU8 xvec, SpanU8 memb) {
VecU8 res = VecU8_new();
for (int n = 2; n <= 4; n++)
codegen_append_xvecn_struct_and_base_methods(res, xvec, memb, n);
VecU8_append_vec(&res, generate_xvecn_struct_and_base_methods(xvec, memb, n));
return res;
}
void codegen_append_xvec234_structs_and_cool_methods(VecU8* res, SpanU8 xvec, SpanU8 memb, SpanU8 sqrt_func) {
NODISCARD VecU8 generate_xvec234_structs_and_cool_methods(SpanU8 xvec, SpanU8 memb, SpanU8 sqrt_func) {
VecU8 res = VecU8_new();
for (int n = 2; n <= 4; n++)
codegen_append_xvecn_struct_and_cool_methods(res, xvec, memb, n, sqrt_func);
VecU8_append_vec(&res, generate_xvecn_struct_and_cool_methods(xvec, memb, n, sqrt_func));
for (int n = 2; n <= 3; n++)
codegen_append_xvecn_method_and_one(res, xvec, n);
codegen_append_xvec3_method_cross(res, xvec);
VecU8_append_vec(&res, generate_xvecn_method_and_one(xvec, n));
VecU8_append_vec(&res, generate_xvec3_method_cross(xvec));
return res;
}
void codegen_append_xmat234x234_structs_and_base_methods(VecU8* res,
SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int sizeof_member
){
NODISCARD VecU8 generate_xmat234x234_structs_methods(SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int sizeof_member) {
VecU8 res = VecU8_new();
for (int cols = 2; cols <= 4; cols++) {
for (int rows = 2; rows <= 4; rows++) {
codegen_append_xmatnm_struct_and_methods(res, xmat, xvec, memb, cols, rows, sizeof_member);
VecU8_append_vec(&res, generate_xmatnm_struct_and_methods(xmat, xvec, memb, cols, rows, sizeof_member));
}
}
for (int cols = 2; cols <= 4; cols++) {
for (int rows = 2; rows <= 4; rows++) {
codegen_append_xmatnm_transpose_method(res, xmat, xvec, memb, cols, rows);
VecU8_append_vec(&res, generate_xmatnm_transpose_method(xmat, xvec, memb, cols, rows));
}
}
for (int n = 2; n <= 4; n++) {
codegen_append_square_xmatn_methods(res, xmat, xvec, memb, n);
VecU8_append_vec(&res, generate_square_xmatn_methods(xmat, xvec, memb, n));
}
for (int n = 2; n <= 4; n++) {
for (int m = 2; m <= 4; m++) {
for (int k = 2; k <= 4; k++) {
codegen_append_xmatnm_method_mul_xmatkn(res, xmat, n, m, k);
VecU8_append_vec(&res, generate_xmatnm_method_mul_xmatkn(xmat, n, m, k));
}
}
}
codegen_append_xmat234_det_method(res, xmat, xvec, memb);
}
void codegen_append_xmat234x234_structs_and_cool_methods(VecU8* res,
SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int sizeof_member
){
codegen_append_xmat234x234_structs_and_base_methods(res, xmat, xvec, memb, sizeof_member);
codegen_append_xmat_inverse_methods(res, xmat, xvec, memb);
VecU8_append_vec(&res, generate_xmat_inverse_methods(xmat, xvec, memb));
return res;
}
void generate_geom_header() {
GeneratedHeader res = begin_header(cstr("l1/geom.h"));
VecU8_append_span(&res.result, cstr("#include \"../../src/l1/core/int_primitives.h\"\n"));
VecU8_append_span(&res.result, cstr("#include <math.h>\n\n"));
codegen_append_xvec234_structs_and_base_methods(&res.result, cstr("cvec"), cstr("U8"));
codegen_append_xvec234_structs_and_base_methods(&res.result, cstr("uvec"), cstr("U32"));
codegen_append_xvec234_structs_and_base_methods(&res.result, cstr("s64vec"), cstr("S64"));
codegen_append_xvec234_structs_and_base_methods(&res.result, cstr("ivec"), cstr("S32"));
for (U64 i = 2; i <= 4; i++) {
VecU8_append_vec(&res.result, VecU8_fmt("typedef ivec%u s32vec%u;\n", i, i));
}
VecU8_append_span(&res.result, cstr("\n"));
codegen_append_xvec234_structs_and_cool_methods(&res.result, cstr("vec"), cstr("float"), cstr("sqrtf"));
codegen_append_xvec234_structs_and_cool_methods(&res.result, cstr("dvec"), cstr("double"), cstr("sqrt"));
// todo: remove padding from matrix structure. VERY IMPORTANT!!! Add padding on the fly when transferring to vulkan
codegen_append_xmat234x234_structs_and_cool_methods(&res.result, cstr("mat"), cstr("vec"), cstr("float"), sizeof(float));
codegen_append_xmat234x234_structs_and_base_methods(&res.result, cstr("s64mat"), cstr("s64vec"), cstr("S64"), sizeof(S64));
VecU8_append_vec(&res.result, generate_xvec234_structs_and_base_methods(cstr("cvec"), cstr("U8")));
VecU8_append_vec(&res.result, generate_xvec234_structs_and_base_methods(cstr("uvec"), cstr("U32")));
VecU8_append_vec(&res.result, generate_xvec234_structs_and_base_methods(cstr("ivec"), cstr("S32")));
VecU8_append_vec(&res.result, generate_xvec234_structs_and_cool_methods(cstr("vec"), cstr("float"), cstr("sqrtf")));
VecU8_append_vec(&res.result, generate_xvec234_structs_and_cool_methods(cstr("dvec"), cstr("double"), cstr("sqrt")));
VecU8_append_vec(&res.result, generate_xmat234x234_structs_methods(cstr("mat"), cstr("vec"), cstr("float"), sizeof(float)));
/* VecU8_append_vec(&res.result, generate_xmat234x234_structs_methods(cstr("dmat"), cstr("dvec"), cstr("double"), sizeof(double))); */
finish_header(res);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_ANNE_LIZA_H
#define PROTOTYPE1_SRC_L1_ANNE_LIZA_H
#include "../codegen/util_template_inst.h"
@ -8,11 +9,13 @@ void generate_liza_l1_headers() {
mkdir_nofail("l1/eve/liza");
// todo: continue OptionT + util_templates_instantiation_options refactoring from here
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("BoxLizaSound"), .vec = true}, false);
.T = cstr("BoxLizaSound"), .vec = true});
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("PlayingSound"), .vec_extended = true}, false);
.T = cstr("PlayingSound"), .vec_extended = true});
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("BoxLizaInstrument"), .vec = true}, false);
.T = cstr("BoxLizaInstrument"), .vec = true});
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("MyInstrument"), .vec = true}, false);
.T = cstr("MyInstrument"), .vec = true});
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_anne_lucy_h
#define prototype1_src_l1_anne_lucy_h
#include "../codegen/util_template_inst.h"
#include "../codegen/list_template_inst.h"
@ -6,15 +7,18 @@
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,
}, false);
});
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_ANNE_MARGARET_MARGARET_MISC_H
#define PROTOTYPE1_SRC_L1_ANNE_MARGARET_MARGARET_MISC_H
#include "../../codegen/util_template_inst.h"
#include "../../codegen/list_template_inst.h"
@ -10,7 +11,7 @@ void generate_margaret_eve_for_vulkan_utils() {
mkdir_nofail("l1/eve/margaret");
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("MargaretScoredPhysicalDevice"), .t_primitive = true, .vec = true, .sort = true
}, false);
});
/* For l2/margaret/{ vulkan_img_claire.h , vulkan_buffer_claire.h } */
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretIAFreeSegment"), true, false);
@ -27,3 +28,6 @@ void generate_margaret_eve_for_vulkan_utils() {
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("MargaretImgAllocatorOneBlock"), true, false);
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){.T = cstr("MargaretBufAllocatorOneBlock")}, true);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_ANNE_MARGARET_PNG_PIXEL_MASSES_H
#define PROTOTYPE1_SRC_L1_ANNE_MARGARET_PNG_PIXEL_MASSES_H
#include "../../codegen/util_template_inst.h"
@ -14,9 +15,7 @@ color_type_name_in_png color_types_names_in_png[] = {
{4, cstr("PNG_COLOR_TYPE_RGBA")},
};
void codegen_append_margaret_png_texture_data_methods(VecU8* res,
SpanU8 format_signature, S64 depth, S64 channel_count
){
NODISCARD VecU8 generate_margaret_png_texture_data_methods(SpanU8 format_signature, S64 depth, S64 channel_count) {
if (depth != 8)
abortf("Please no\n");
SpanU8 color_type = cstr("");
@ -28,12 +27,15 @@ void codegen_append_margaret_png_texture_data_methods(VecU8* res,
abortf("Please don't\n");
U64 sizeof_pixel = (U64)depth / 8 * (U64)channel_count;
VecU8 res = VecU8_new();
VecU8 promise = VecU8_fmt("MargaretPromisedPng%s", format_signature);
VecU8 tex = VecU8_fmt("TextureData%s", format_signature);
VecU8 g_promise = VecU8_fmt("MargaretPromisedPng%s", format_signature);
SpanU8 promise = VecU8_to_span(&g_promise);
VecU8 g_tex = VecU8_fmt("TextureData%s", format_signature);
SpanU8 tex = VecU8_to_span(&g_tex);
VecU8_append_fmt(res,
"NODISCARD ResultVoidOrVecU8 %r_write_to_png(const %r* self, SpanU8 filename) {\n" /* tex, tex */
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD ResultVoidOrVecU8 %s_write_to_png(const %s* self, SpanU8 filename) {\n" /* tex, tex */
SPACE "VecU8 nt_filename = VecU8_fmt(\"%%s%%c\", filename, 0);\n"
SPACE "FILE *fp = fopen((CSTR)nt_filename.buf, \"wb\");\n"
SPACE "VecU8_drop(nt_filename);\n"
@ -61,7 +63,7 @@ void codegen_append_margaret_png_texture_data_methods(VecU8* res,
SPACE SPACE "PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);\n"
SPACE "row_pointers = calloc(height, sizeof(row_pointers));\n"
SPACE "for (U32 y = 0; y < height; y++) {\n"
SPACE SPACE "row_pointers[height - 1 - y] = (png_bytep)((%r_at(self, 0, y)));\n" /* tex */
SPACE SPACE "row_pointers[height - 1 - y] = (png_bytep)((%s_at(self, 0, y)));\n" /* tex */
SPACE "}\n"
SPACE "png_set_rows(pngshka, info, row_pointers);\n"
SPACE "png_write_png(pngshka, info, 0, NULL);\n"
@ -72,38 +74,38 @@ void codegen_append_margaret_png_texture_data_methods(VecU8* res,
SPACE "return (ResultVoidOrVecU8){.variant = Result_Ok};\n"
"}\n\n"
"/* Aborts on error */\n"
"void %r_write_to_png_nofail(const %r* self, SpanU8 filename) {\n" /* tex, tex */
SPACE "ResultVoidOrVecU8 res = %r_write_to_png(self, filename);\n" /* tex */
"void %s_write_to_png_nofail(const %s* self, SpanU8 filename) {\n" /* tex, tex*/
SPACE "ResultVoidOrVecU8 res = %s_write_to_png(self, filename);\n" /* tex */
SPACE "if (res.variant == Result_Err) {\n"
SPACE SPACE "SpanU8_fprint(VecU8_to_span(&res.err), stderr);\n"
SPACE SPACE "abortf(\" %r_write_to_png\\n\");\n" /* tex */
SPACE SPACE "abortf(\" %s_write_to_png\\n\");\n" /* tex */
SPACE "}\n"
"}\n",
tex, tex, depth, color_type, tex, tex, tex, tex, tex);
tex, tex, depth, color_type, tex, tex, tex, tex, tex));
/* Non clonable structure */
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"typedef struct {\n"
SPACE "FILE* fp;\n"
SPACE "png_structp pngshka;\n"
SPACE "png_infop info;\n"
SPACE "png_infop end_info;\n"
"} %r;\n\n"
"void %r_drop(%r self) {\n"
"} %s;\n\n"
"void %s_drop(%s self) {\n"
SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n"
SPACE "fclose(self.fp);\n"
"}\n\n",
promise, promise, promise);
promise, promise, promise));
VecU8_append_vec(res, generate_result_template_inst(VecU8_to_span(&promise), cstr("VecU8"), false, false));
VecU8_append_vec(&res, generate_result_template_inst(promise, cstr("VecU8"), false, false));
VecU8_append_fmt(res,
"NODISCARD Result%rOrVecU8 %r_begin(SpanU8 filename) {\n" /* promise, promise */
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD Result%sOrVecU8 %s_begin(SpanU8 filename) {\n" /* promise, promise */
SPACE "VecU8 nt_filename = VecU8_fmt(\"%%s%%c\", filename, 0);\n"
SPACE "FILE* fp = fopen((CSTR)nt_filename.buf, \"rb\");\n"
SPACE "VecU8_drop(nt_filename);\n"
SPACE "if (!fp) {\n"
SPACE SPACE "return (Result%rOrVecU8){.variant = Result_Err,\n" /* promise */
SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err,\n" /* promise */
SPACE SPACE SPACE ".err = VecU8_fmt(\"Unable to open file %%s\", filename)};\n"
SPACE "}\n"
SPACE "png_structp pngshka = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb);\n"
@ -118,7 +120,7 @@ void codegen_append_margaret_png_texture_data_methods(VecU8* res,
SPACE "if (setjmp(png_jmpbuf(pngshka))) {\n"
SPACE SPACE "png_destroy_read_struct(&pngshka, &info, &end_info);\n"
SPACE SPACE "fclose(fp);\n"
SPACE SPACE "return (Result%rOrVecU8){.variant = Result_Err,\n" /* promise */
SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err,\n" /* promise */
SPACE SPACE SPACE ".err = VecU8_from_cstr(\"Some png error happened\")};\n"
SPACE "}\n"
SPACE "png_init_io(pngshka, fp);\n"
@ -126,55 +128,55 @@ void codegen_append_margaret_png_texture_data_methods(VecU8* res,
SPACE "U32 width, height;\n"
SPACE "int bit_depth, color_type;\n"
SPACE "check(png_get_IHDR(pngshka, info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));\n",
promise, promise, promise, promise);
promise, promise, promise, promise));
/* We are still in PROMISE_begin method, now we need to do the conversion */
if (depth == 8) {
VecU8_append_cstr(res,
VecU8_append_span(&res, cstr(
SPACE "if (bit_depth == 16)\n"
SPACE SPACE "png_set_strip_16(pngshka);\n"
SPACE "else if (color_type == PNG_COLOR_TYPE_GRAY && (bit_depth == 1 || bit_depth == 2 || bit_depth == 4))\n"
SPACE SPACE "png_set_expand_gray_1_2_4_to_8(pngshka);\n"
);
));
} else
assert(false);
if (channel_count == 3 || channel_count == 4) {
VecU8_append_cstr(res,
VecU8_append_span(&res, cstr(
SPACE "if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)\n"
SPACE SPACE "png_set_gray_to_rgb(pngshka);\n"
SPACE "else if (color_type == PNG_COLOR_TYPE_PALETTE)"
SPACE SPACE "png_set_palette_to_rgb(pngshka);\n"
);
));
} else if (channel_count == 1 || channel_count == 2) {
VecU8_append_cstr(res,
VecU8_append_span(&res, cstr(
SPACE "if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGBA) {\n"
SPACE SPACE "png_set_rgb_to_gray_fixed(pngshka, 1, 21268, 71514);\n"
SPACE "} else if (color_type == PNG_COLOR_TYPE_PALETTE) {\n"
SPACE SPACE "png_set_palette_to_rgb(pngshka);\n"
SPACE SPACE "png_set_rgb_to_gray_fixed(pngshka, 1, 21268, 71514);\n"
SPACE "}\n"
);
));
} else
assert(false);
if (channel_count == 4 || channel_count == 2) {
VecU8_append_cstr(res,
VecU8_append_span(&res, cstr(
SPACE "if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_PALETTE) {\n"
SPACE SPACE "if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) \n"
SPACE SPACE SPACE "png_set_tRNS_to_alpha(pngshka);\n"
SPACE SPACE "else\n"
SPACE SPACE SPACE "png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);\n"
SPACE "}\n"
);
));
} else if (channel_count == 1 || channel_count == 3) {
VecU8_append_cstr(res,
VecU8_append_span(&res, cstr(
SPACE "if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_RGBA)\n"
SPACE SPACE "png_set_strip_alpha(pngshka);\n"
);
));
} else
assert(false);
/* At this point we have a converted image png structure */
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
SPACE "png_read_update_info(pngshka, info);\n"
SPACE "{\n"
SPACE SPACE "U32 new_width, new_height;\n"
@ -182,34 +184,34 @@ void codegen_append_margaret_png_texture_data_methods(VecU8* res,
SPACE SPACE "check(png_get_IHDR(pngshka, info, &new_width, &new_height, &new_bit_depth, &new_color_type, NULL, NULL, NULL));\n"
SPACE SPACE "assert(new_width == width && new_height == height && new_bit_depth == %i && new_color_type == %s);\n" /* depth, color_type */
SPACE "}\n"
SPACE "return (Result%rOrVecU8){.variant = Result_Ok,\n" /* promise */
SPACE SPACE ".ok = (%r){.fp = fp, .pngshka = pngshka, .info = info, .end_info = end_info}};\n" /* promise */
SPACE "return (Result%sOrVecU8){.variant = Result_Ok,\n" /* promise */
SPACE SPACE ".ok = (%s){.fp = fp, .pngshka = pngshka, .info = info, .end_info = end_info}};\n" /* promise */
"}\n\n",
(S64)depth, color_type,
promise, promise);
promise, promise));
VecU8_append_fmt(res,
"SizeOfRectangleU32 %r_get_extent(const %r* self) {\n" /* promise, promise */
VecU8_append_vec(&res, VecU8_fmt(
"SizeOfRectangleU32 %s_get_extent(const %s* self) {\n" /* promise, promise */
SPACE "U32 width, height;\n"
SPACE "int bit_depth, color_type;\n"
SPACE "check(png_get_IHDR(self->pngshka, self->info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));\n"
SPACE "return (SizeOfRectangleU32){width, height};\n"
"}\n\n",
promise, promise);
promise, promise));
assert(depth == 8 || depth == 16);
assert(channel_count == 1 || channel_count == 2 || channel_count == 4 || channel_count == 3);
VecU8_append_fmt(res,
"size_t %r_get_needed_buffer_size(const %r* self) {\n" /* promise, promise */
SPACE "SizeOfRectangleU32 dim = %r_get_extent(self);\n" /* promise */
VecU8_append_vec(&res, VecU8_fmt(
"size_t %s_get_needed_buffer_size(const %s* self) {\n" /* promise, promise */
SPACE "SizeOfRectangleU32 dim = %s_get_extent(self);\n" /* promise */
SPACE "return %u * dim.width * dim.height;\n" /* sizeof_pixel */
"}\n\n",
promise, promise, promise, sizeof_pixel);
promise, promise, promise, sizeof_pixel));
VecU8_append_fmt(res,
"NODISCARD ResultVoidOrVecU8 %r_finish(%r self, void* buffer) {\n" /* promise, promise */
SPACE "SizeOfRectangleU32 dim = %r_get_extent(&self);\n" /* promise */
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD ResultVoidOrVecU8 %s_finish(%s self, void* buffer) {\n" /* promise, promise */
SPACE "SizeOfRectangleU32 dim = %s_get_extent(&self);\n" /* promise */
SPACE "png_bytep* row_pointers = NULL;\n"
SPACE "if (setjmp(png_jmpbuf(self.pngshka))) {\n"
SPACE SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n"
@ -229,35 +231,37 @@ void codegen_append_margaret_png_texture_data_methods(VecU8* res,
SPACE "free(row_pointers);\n"
SPACE "return (ResultVoidOrVecU8){.variant = Result_Ok};\n"
"}\n\n",
promise, promise, promise, sizeof_pixel);
promise, promise, promise, sizeof_pixel
));
VecU8_append_fmt(res,
"NODISCARD Result%rOrVecU8 %r_finish_into_%r(%r self) {\n" /* tex, promise, tex, promise */
SPACE "SizeOfRectangleU32 dim = %r_get_extent(&self);\n" /* promise */
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD Result%sOrVecU8 %s_finish_into_%s(%s self) {\n" /* tex, promise, tex, promise */
SPACE "SizeOfRectangleU32 dim = %s_get_extent(&self);\n" /* promise */
SPACE "if (dim.width >= UINT32_MAX / 10 || dim.height >= UINT32_MAX / 10) {\n"
SPACE SPACE "return (Result%rOrVecU8){.variant = Result_Err, .err = vcstr(\"Input image is too big\")};\n" /* tex */
SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err, .err = vcstr(\"Input image is too big\")};\n" /* tex */
SPACE "}\n"
SPACE "%r tex = %r_new(dim.width, dim.height);\n" /* tex, tex */
SPACE "ResultVoidOrVecU8 res = %r_finish(self, tex.pixels.buf);\n" /* promise */
SPACE "%s tex = %s_new(dim.width, dim.height);\n" /* tex, tex */
SPACE "ResultVoidOrVecU8 res = %s_finish(self, tex.pixels.buf);\n" /* promise */
SPACE "if (res.variant == Result_Err) {\n"
SPACE SPACE "%r_drop(tex);\n" /* tex */
SPACE SPACE "return (Result%rOrVecU8){.variant = Result_Err, .err = res.err};\n" /* tex */
SPACE SPACE "%s_drop(tex);\n" /* tex */
SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err, .err = res.err};\n" /* tex */
SPACE "}\n"
SPACE "return (Result%rOrVecU8){.variant = Result_Ok, .ok = tex};\n" /* tex */
SPACE "return (Result%sOrVecU8){.variant = Result_Ok, .ok = tex};\n" /* tex */
"}\n\n",
tex, promise, tex, promise, promise, tex, tex, tex, promise, tex, tex, tex
);
));
VecU8_append_vec(&res, VecU8_fmt(
VecU8_append_fmt(res,
"/* aborts on error */\n"
"NODISCARD %r %r_read_from_png_nofail(SpanU8 name) {\n" /* tex, tex */
SPACE "Result%rOrVecU8 res_1 = %r_begin(name);\n" /* promise, promise */
"NODISCARD %s %s_read_from_png_nofail(SpanU8 name) {\n" /* tex, tex */
SPACE "Result%sOrVecU8 res_1 = %s_begin(name);\n" /* promise, promise */
SPACE "if (res_1.variant == Result_Err) {\n"
SPACE SPACE "SpanU8_fprint(VecU8_to_span(&res_1.err), stderr);\n"
SPACE SPACE "abortf(\" MargaretPromisedPng_begin\\n\");\n"
SPACE "}\n"
SPACE "/* res_1 invalidated, we moved ownership to _finish methos */\n"
SPACE "Result%rOrVecU8 res_2 = %r_finish_into_%r(res_1.ok);\n" /* tex, promise, tex */
SPACE "Result%sOrVecU8 res_2 = %s_finish_into_%s(res_1.ok);\n" /* tex, promise, tex */
SPACE "if (res_2.variant == Result_Err) {\n"
SPACE SPACE "SpanU8_fprint(VecU8_to_span(&res_2.err), stderr);\n"
SPACE SPACE "abortf(\" MargaretPromisedPng_finish (into TextureData)\\n\");\n"
@ -265,31 +269,34 @@ void codegen_append_margaret_png_texture_data_methods(VecU8* res,
SPACE "return res_2.ok;\n"
"}\n\n",
tex, tex, promise, promise, tex, promise, tex
);
));
VecU8_drop(promise);
VecU8_drop(tex);
VecU8_drop(g_promise);
VecU8_drop(g_tex);
return res;
}
void generate_margaret_png_pixel_masses_header() {
GeneratedHeader header = begin_header(cstr("l1/margaret/png_pixel_masses.h"));
VecU8_append_cstr(&header.result,
VecU8_append_span(&header.result, cstr(
"#include \"../pixel_masses.h\"\n"
"#include \"../ResultVoidOrVecU8.h\"\n"
"#include <png.h>\n\n");
"#include <png.h>\n\n"));
VecU8_append_cstr(&header.result,
VecU8_append_span(&header.result, cstr(
"void margaret_libpng_h_error_cb(png_structp pngshka, png_const_charp err) {\n"
SPACE "printf(\"[!] %s\\n\", err);\n"
"}\n\n"
"void margaret_libpng_h_warning_cb(png_structp pngshka, png_const_charp warning) {\n"
SPACE "printf(\"[.] %s\\n\", warning);\n"
"}\n\n");
"}\n\n"));
codegen_append_margaret_png_texture_data_methods(&header.result, cstr("R8"), 8, 1);
codegen_append_margaret_png_texture_data_methods(&header.result, cstr("R8G8B8"), 8, 3);
codegen_append_margaret_png_texture_data_methods(&header.result, cstr("R8G8B8A8"), 8, 4);
VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8"), 8, 1));
VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8G8B8"), 8, 3));
VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8G8B8A8"), 8, 4));
finish_header(header);
}
#endif

View File

@ -1,17 +0,0 @@
#pragma once
#include "../codegen/util_template_inst.h"
void generate_l1_headers_for_marie() {
SpanU8 l = cstr("l1");
SpanU8 ns = cstr("marie");
mkdir_nofail("l1/eve/marie");
/* graphics_geom */
generate_eve_span_company_for_primitive(l, ns, cstr("MarieTriangle"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MarieTriangleAttr"), true, false);
/* shape_geom */
generate_eve_span_company_for_primitive(l, ns, cstr("MarieEarCuttingTriangulVertState"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MarieHoleAndVertexId"), true, false);
generate_eve_span_company_for_non_primitive_clonable(l, ns, cstr("VecMarieHoleAndVertexId"), true, false);
generate_eve_span_company_for_non_primitive_clonable(l, ns, cstr("VecVecMarieHoleAndVertexId"), true, false);
}

View File

@ -0,0 +1,14 @@
#ifndef PROTOTYPE1_SRC_L1_ANNE_MARIE_GRAPHICS_GEOM_H
#define PROTOTYPE1_SRC_L1_ANNE_MARIE_GRAPHICS_GEOM_H
#include "../../codegen/util_template_inst.h"
void generate_marie_headers_for_graphics_geom() {
SpanU8 l = cstr("l1");
SpanU8 ns = cstr("marie");
mkdir_nofail("l1/eve/marie");
generate_eve_span_company_for_primitive(l, ns, cstr("MarieTriangle"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MarieTriangleAttr"), true, false);
}
#endif

View File

@ -1,60 +1,124 @@
#pragma once
#ifndef PROTOTYPE_SRC_L1_CODEGEN_PIXEL_MASSES_H
#define PROTOTYPE_SRC_L1_CODEGEN_PIXEL_MASSES_H
#include "../codegen/codegen.h"
#include "../codegen/util_template_inst.h"
/* Used to generate both _at() and _cat() methods */
void codegen_append_texture_data_method_at(VecU8* res, SpanU8 tex, SpanU8 memb, bool const_access) {
VecU8_append_fmt(res,
NODISCARD VecU8 generate_texture_data_method_at(SpanU8 tex, SpanU8 pixvec, SpanU8 memb, bool const_access) {
return VecU8_fmt(
"%s%s* %s_%sat(%s%s* self, size_t x, size_t y) {\n"
SPACE "assert(x < self->width);\n"
SPACE "return Vec%s_%sat(&self->pixels, x + y * self->width);\n"
SPACE "return %s_%sat(&self->pixels, x + y * self->width);\n"
"}\n\n",
const_access ? cstr("const ") : cstr(""), memb, tex, const_access ? cstr("") : cstr("m"),
const_access ? cstr("const ") : cstr(""), tex, memb, const_access ? cstr("") : cstr("m"));
const_access ? cstr("const ") : cstr(""), tex, pixvec, const_access ? cstr("") : cstr("m"));
}
/* `tex` is the type name of texture data type
* `memb` is the type name of pixel data type */
void codegen_append_texture_data_struct_and_necc_methods(VecU8* res,
SpanU8 tex, SpanU8 memb, SpanU8 luminosity_formula
) {
VecU8_append_fmt(res,
NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 memb, SpanU8 luminosity_formula) {
VecU8 g_pixvec = VecU8_fmt("Vec%s", memb);
SpanU8 pixvec = VecU8_to_span(&g_pixvec);
VecU8 res = VecU8_fmt(
"typedef struct {\n"
SPACE "Vec%s pixels;\n"
SPACE "%s pixels;\n"
SPACE "size_t width;\n"
SPACE "size_t height;\n"
"} %s;\n\n", memb, tex);
"} %s;\n\n", pixvec, tex);
/* Method _new() */
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_new(U32 width, U32 height) {\n"
SPACE "assert(width == 0 || height == 0 ||\n"
SPACE SPACE "!(SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10));\n"
SPACE "return (%s){.pixels = Vec%s_new_zeroinit((size_t)width * height), .width = width, .height = height};\n"
"}\n\n", tex, tex, tex, memb);
SPACE "return (%s){.pixels = %s_new_zeroinit((size_t)width * height), .width = width, .height = height};\n"
"}\n\n", tex, tex, tex, pixvec));
/* Method _drop() */
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"void %s_drop(%s self) {\n"
SPACE "Vec%s_drop(self.pixels);\n"
"}\n\n", tex, tex, memb);
SPACE "%s_drop(self.pixels);\n"
"}\n\n", tex, tex, pixvec));
/* Methods _at and _cat */
codegen_append_texture_data_method_at(res, tex, memb, false);
codegen_append_texture_data_method_at(res, tex, memb, true);
VecU8_append_vec(&res, generate_texture_data_method_at(tex, pixvec, memb, false));
VecU8_append_vec(&res, generate_texture_data_method_at(tex, pixvec, memb, true));
/* Method _get_size_in_bytes */
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"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 */
VecU8_append_vec(res, generate_result_template_inst(tex, cstr("VecU8"), false, false));
"}\n\n", tex, tex, memb));
/* 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_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"bool %s_is_inside(const %s* self, S32 x, S32 y) {\n"
SPACE "return x >= 0 && y >= 0 && x < (S32)self->width && self->width * y + x < self->pixels.len;\n"
"}\n\n", tex, tex);
"}\n\n", tex, tex));
/* Method _print() */
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"void %s_print(const %s* self) {\n" /* tex, tex */
SPACE "U64 width = self->width;\n"
SPACE "U64 height = self->height;\n"
@ -80,7 +144,11 @@ void codegen_append_texture_data_struct_and_necc_methods(VecU8* res,
SPACE SPACE "}\n"
SPACE SPACE "putc('\\n', stdout);\n"
SPACE "}\n"
"}\n\n", tex, tex, memb, tex, luminosity_formula);
"}\n\n", tex, tex, memb, tex, luminosity_formula));
VecU8_drop(g_resoftex);
VecU8_drop(g_pixvec);
return res;
}
void generate_pixel_masses_header() {
@ -89,13 +157,14 @@ void generate_pixel_masses_header() {
VecU8_append_span(&res.result, cstr("#include \"../../src/l1/system/fileio.h\"\n"));
VecU8_append_span(&res.result, cstr("#include \"VecAndSpan_cvec3.h\"\n"));
VecU8_append_span(&res.result, cstr("#include \"VecAndSpan_cvec4.h\"\n\n"));
codegen_append_texture_data_struct_and_necc_methods(&res.result,
cstr("TextureDataR8"), cstr("U8"), cstr("(float)pix / 255"));
codegen_append_texture_data_struct_and_necc_methods(&res.result,
cstr("TextureDataR8G8B8"), cstr("cvec3"),
cstr("(float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f"));
codegen_append_texture_data_struct_and_necc_methods(&res.result,
cstr("TextureDataR8G8B8A8"), cstr("cvec4"),
cstr("(float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f"));
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8"), cstr("U8"),
cstr("(float)pix / 255")));
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8"), cstr("cvec3"),
cstr("(float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f")));
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8A8"), cstr("cvec4"),
cstr("(float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f")));
finish_header(res);
}
#endif

View File

@ -1,20 +0,0 @@
#pragma once
// todo: write something here after I close КТ-1
#include "../codegen/codegen.h"
void generate_precise_addition_func(VecU8* res, U64 liA, U64 liB){
assert(liA < 1000 && liB < 1000);
assert(liA >= liB);
VecU8_append_vec(res, VecU8_fmt(
"void S%u_add_S%u(S%u* a, S%u b){\n", liA * 64, liB * 64, liA * 64, liB * 64));
// for (size_t i = 10; )
VecU8_append_span(res, cstr("}\n\n"));
}
void generate_l1_header_for_precise_integers(){
GeneratedHeader h = begin_header(cstr("l1/precise_integers.h"));
VecU8_append_span(&h.result, cstr("#include \"../../src/l1/core/int_primitives.h\"\n"));
finish_header(h);
}

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_ANNE_SOME_TESTS_H
#define PROTOTYPE1_SRC_L1_ANNE_SOME_TESTS_H
#include "../codegen/util_template_inst.h"
@ -16,15 +17,12 @@ void generate_headers_for_r0_r1_r2_r3() {
SpanU8 ns = cstr("r2");
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("PlayingSound"), .vec_extended = true
}, false);
}
mkdir_nofail("l1/eve/r4");
{ /* r4 */
SpanU8 ns = cstr("r4");
generate_eve_span_company_for_primitive(l, ns, cstr("LightSourceState"), true, false);
});
}
mkdir_nofail("l1/eve/ds_test");
{ /* This structure is needed for testing purposes only */
generate_eve_span_company_for_primitive(l, cstr("ds_test"), cstr("RefRBTreeNode_S64"), true, false);
}
}
#endif

View File

@ -1,27 +1,14 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_ANNE_UTIL_TEMP_GEOM_H
#define PROTOTYPE1_SRC_L1_ANNE_UTIL_TEMP_GEOM_H
#include "../codegen/util_template_inst.h"
void generate_util_temp_geom_headers() {
SpanU8 T[] = {cstr("cvec3"), cstr("cvec4"), cstr("vec2"), cstr("vec3"), cstr("vec4"), cstr("s64vec2")};
SpanU8 T[] = {cstr("cvec3"), cstr("cvec4"), cstr("vec2"), cstr("vec3"), cstr("vec4")};
for (size_t i = 0; i < ARRAY_SIZE(T); i++) {
generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), T[i],
cstr("#include \"geom.h\"\n"), true, true);
}
for (size_t i = 0; i < ARRAY_SIZE(T); i++) {
VecU8 Type = VecU8_fmt("Span%s", T[i]);
VecU8 Dep = VecU8_fmt("#include \"VecAndSpan_%s.h\"\n", T[i]);
generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), VecU8_to_span(&Type),
VecU8_to_span(&Dep), true, false);
VecU8_drop(Type);
VecU8_drop(Dep);
}
for (size_t i = 0; i < ARRAY_SIZE(T); i++) {
VecU8 Type = VecU8_fmt("Vec%s", T[i]);
VecU8 Dep = VecU8_fmt("#include \"VecAndSpan_%s.h\"\n", T[i]);
generate_guarded_span_company_for_non_primitive_clonable(cstr("l1"), cstr(""), VecU8_to_span(&Type),
VecU8_to_span(&Dep), true, false);
VecU8_drop(Type);
VecU8_drop(Dep);
}
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_ANNE_UTIL_TEMP_VERY_BASE_H
#define PROTOTYPE1_SRC_L1_ANNE_UTIL_TEMP_VERY_BASE_H
#include "../codegen/util_template_inst.h"
@ -15,7 +16,7 @@ void generate_util_temp_very_base_headers() {
(util_templates_instantiation_options){
.T = T_codegen_VecAndSpan[i],
.t_integer = true, .t_primitive = true, .vec = true, .vec_extended = true,
.vec_equal = true, .span = true, .mut_span = true, .span_extended = true,
.vec_equal = true, .span = true, .span_extended = true, .mut_span = true,
.collab_vec_span = true, .collab_vec_span_extended = true,
});
}
@ -31,7 +32,7 @@ void generate_util_temp_very_base_headers() {
VecU8_to_span(&dependency),
(util_templates_instantiation_options){
.T = VecU8_to_span(&VecT), .t_clonable = true, .vec = true, .vec_extended = true,
.vec_equal = true, .vec_new_of_size = true, .span = true, .collab_vec_span = true,
.span = true, .collab_vec_span = true, .vec_equal = true, .vec_new_of_size = true
});
VecU8_drop(VecT);
VecU8_drop(dependency);
@ -66,11 +67,6 @@ void generate_util_temp_very_base_headers() {
cstr("#include \"../../gen/l1/pixel_masses.h\"\n"), true, false);
generate_guarded_span_company_for_primitive(l, ns, cstr("KVPU64ToU64"), cstr(""), true, false);
/* Currently not clonable, because I forgot to implement clone for rbtree. todo: do this */
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("Json"), .t_clonable = false, .vec = true, .skip_declaration_gen = true}, true);
generate_Option_templ_inst_eve_header(l, ns,
(option_template_instantiation_op){.T = cstr("Json"), .t_clonable = false});
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_ANNE_VULKAN_H
#define PROTOTYPE1_SRC_L1_ANNE_VULKAN_H
#include "../codegen/util_template_inst.h"
@ -42,3 +43,5 @@ void generate_util_templ_inst_for_vulkan_headers() {
generate_guarded_span_company_for_primitive(l, ns, cstr("VkImageMemoryBarrier"), vulkan_dep, true, false);
generate_guarded_span_company_for_primitive(l, ns, cstr("VkDescriptorImageInfo"), vulkan_dep, true, false);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_CODEGEN_CODEGEN_H
#define PROTOTYPE1_SRC_L1_CODEGEN_CODEGEN_H
#include <stdio.h>
#include "../system/fileio.h"
@ -7,18 +8,32 @@
typedef struct {
VecU8 result;
VecU8 filename;
VecU8 nt_filename;
} GeneratedHeader;
NODISCARD GeneratedHeader begin_header(SpanU8 filename) {
VecU8 res = vcstr("#pragma once\n"
"/* Automatically generated file. Do not edit it. */\n\n");
return (GeneratedHeader){.result = res, .filename = VecU8_from_span(filename) };
VecU8 res = VecU8_new();
VecU8 guard = VecU8_from_cstr("PROTOTYPE1_GEN_");
for (size_t i = 0; i < filename.len; i++) {
char ch = (char)*SpanU8_at(filename, i);
if (ch == '.' || ch == '/' || ch == '-' || ch == ',')
VecU8_append(&guard, '_');
else
VecU8_append(&guard, ch);
}
VecU8_append_span(&res, cstr("#ifndef "));
VecU8_append_span(&res, VecU8_to_span(&guard));
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, .nt_filename = VecU8_fmt("%s%c", filename, 0) };
}
/* Codegen script's working directory should be `gen` */
void finish_header(GeneratedHeader header) {
write_file_by_path(header.filename, VecU8_to_span(&header.result));
VecU8_append_span(&header.result, cstr("#endif\n"));
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);
}
@ -28,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) {
@ -71,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);
}
@ -97,7 +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

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_codegen_list_template_inst_h
#define prototype1_src_l1_codegen_list_template_inst_h
#include "codegen.h"
@ -15,21 +16,21 @@ NODISCARD VecU8 generate_List_template_instantiation(list_instantiation_op op, b
VecU8 res = VecU8_new();
if (gen_node_declaration) {
VecU8_append_fmt(&res, "typedef struct ListNode%s ListNode%s;\n", op.T, op.T);
VecU8_append_vec(&res, VecU8_fmt("typedef struct ListNode%s ListNode%s;\n", op.T, op.T));
}
VecU8_append_fmt(&res,
VecU8_append_vec(&res, VecU8_fmt(
"struct ListNode%s {\n" /* op.T */
SPACE "ListNode%s* prev;\n" /* op.T */
SPACE "ListNode%s* next;\n" /* op.T */
SPACE "%s el;\n" /* op.T */
"};\n\n", op.T, op.T, op.T, op.T);
"};\n\n", op.T, op.T, op.T, op.T));
VecU8_append_fmt(&res,
VecU8_append_vec(&res, VecU8_fmt(
"typedef struct {\n"
SPACE "ListNode%s* first;\n" /* op.T */
"} List%s;\n\n", /* op.T */
op.T, op.T);
VecU8_append_fmt(&res,
op.T, op.T));
VecU8_append_vec(&res, VecU8_fmt(
"#define List%s_new() {0}\n\n" /* op.T */
"void List%s_drop(List%s self) {\n" /* op.T, op.T */
SPACE "ListNode%s* cur = self.first;\n" /* op.T */
@ -41,8 +42,8 @@ NODISCARD VecU8 generate_List_template_instantiation(list_instantiation_op op, b
SPACE "}\n"
"}\n\n",
op.T, op.T, op.T, op.T, op.T,
op.t_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE "%s_drop(cur->el);\n", op.T));
VecU8_append_fmt(&res,
op.t_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE "%s_drop(cur->el);\n", op.T)));
VecU8_append_vec(&res, VecU8_fmt(
"ListNode%s* List%s_insert(List%s* self, %s el) {\n" /* op.T, op.T, op.T, op.T */
SPACE "ListNode%s* new_node = safe_malloc(sizeof(ListNode%s));\n" /* op.T, op.T */
SPACE "new_node->prev = NULL;\n"
@ -52,16 +53,16 @@ NODISCARD VecU8 generate_List_template_instantiation(list_instantiation_op op, b
SPACE SPACE "self->first->prev = new_node;\n"
SPACE "self->first = new_node;\n"
SPACE "return new_node;\n"
"}\n\n", op.T, op.T, op.T, op.T, op.T, op.T);
VecU8_append_fmt(&res,
"}\n\n", op.T, op.T, op.T, op.T, op.T, op.T));
VecU8_append_vec(&res, VecU8_fmt(
"void List%s_insert_node(List%s* self, ListNode%s* new_node) {\n" /* op.T, op.T, op.T */
SPACE "new_node->prev = NULL;\n"
SPACE "new_node->next = self->first;\n"
SPACE "if (self->first)\n"
SPACE SPACE "self->first->prev = new_node;\n"
SPACE "self->first = new_node;\n"
"}\n\n", op.T, op.T, op.T);
VecU8_append_fmt(&res,
"}\n\n", op.T, op.T, op.T));
VecU8_append_vec(&res, VecU8_fmt(
"void List%s_erase_by_it(List%s* self, ListNode%s* it) {\n" /* op.T, op.T, op.T */
SPACE "if (it->prev)\n"
SPACE SPACE "it->prev->next = it->next;\n"
@ -73,8 +74,8 @@ NODISCARD VecU8 generate_List_template_instantiation(list_instantiation_op op, b
SPACE "free(it);\n"
"}\n\n",
op.T, op.T, op.T,
op.t_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(it->el);\n", op.T));
VecU8_append_fmt(&res,
op.t_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(it->el);\n", op.T)));
VecU8_append_vec(&res, VecU8_fmt(
"void List%s_sink(List%s* self) {\n" /* op.T, op.T */
SPACE "ListNode%s* cur = self->first;\n" /* op.T */
SPACE "while (cur){\n"
@ -86,7 +87,7 @@ NODISCARD VecU8 generate_List_template_instantiation(list_instantiation_op op, b
SPACE "self->first = NULL;\n"
"}\n\n",
op.T, op.T, op.T, op.T,
op.t_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE "%s_drop(cur->el);\n", op.T));
op.t_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE "%s_drop(cur->el);\n", op.T)));
return res;
}
@ -105,3 +106,6 @@ void generate_List_templ_inst_guarded_header(
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, all_dependencies,
generate_List_template_instantiation(op, true), VecU8_fmt("List%s", op.T));
}
#endif

View File

@ -1,45 +1,40 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_CODEGEN_UTIL_TEMPLATES_H
#define PROTOTYPE1_SRC_L1_CODEGEN_UTIL_TEMPLATES_H
#include "codegen.h"
// todo: add macro that iterates over vector
// todo: add _less_ method
// todo: rewrite this crap
void codegen_append_VecT_struct(VecU8* res, SpanU8 T, bool skip_declaration_gen){
if (!skip_declaration_gen) {
VecU8_append_fmt(res, "typedef struct Vec%s Vec%s;\n\n", T, T);
}
VecU8_append_fmt(res,
"struct Vec%s {\n"
/* if !primitive, requires methods T_drop, and, if also clonable, requires method T_clone */
NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive, bool clonable) {
VecU8 g_VecT = VecU8_fmt("Vec%s", T);
SpanU8 VecT = VecU8_to_span(&g_VecT);
VecU8 res = VecU8_fmt(
"typedef struct {\n"
SPACE "%s* buf;\n"
SPACE "size_t len;\n"
SPACE "size_t capacity;\n"
"};\n\n", T, T);
}
"} %s;\n\n", T, VecT);
// todo: add resize method
/* if !primitive, requires methods T_drop, and, if also clonable, requires method T_clone */
void codegen_append_VecT_base_methods(VecU8* res, SpanU8 T, bool primitive, bool clonable) {
VecU8_append_fmt(res, "#define Vec%s_new() ((Vec%s){ 0 })\n\n", T, T);
VecU8_append_vec(&res, VecU8_fmt("#define %s_new() ((%s){ 0 })\n\n", VecT, VecT));
VecU8_append_fmt(res, "void Vec%s_drop(Vec%s self) {\n", T, T);
VecU8_append_vec(&res, VecU8_fmt("void %s_drop(%s self) {\n", VecT, VecT));
if (!primitive) {
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
SPACE "for (size_t i = 0; i < self.len; i++) \n"
SPACE SPACE "%s_drop(self.buf[i]);\n", T);
SPACE SPACE "%s_drop(self.buf[i]);\n", T));
}
VecU8_append_cstr(res,
SPACE "free(self.buf);\n"
"}\n\n");
VecU8_append_vec(&res, VecU8_fmt(
SPACE "free(self.buf);\n"
"}\n\n"));
VecU8_append_fmt(res,
"NODISCARD Vec%s Vec%s_new_reserved(size_t n) {\n"
SPACE "return (Vec%s){ .buf = (%s*)safe_calloc(n, sizeof(%s)), .len = 0, .capacity = n };\n"
"}\n\n", T, T, T, T, T);
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_reserved(size_t n) {\n"
SPACE "return (%s){ .buf = (%s*)safe_calloc(n, sizeof(%s)), .len = 0, .capacity = n };\n"
"}\n\n", VecT, VecT, VecT, T, T));
VecU8_append_fmt(res,
"void Vec%s_append(Vec%s* self, %s el) {\n" /* T, T, T */
VecU8_append_vec(&res, VecU8_fmt(
"void %s_append(%s* self, %s el) {\n" /* VecT, VecT, T */
SPACE "size_t new_length = self->len + 1;\n"
SPACE "if (new_length > self->capacity) {\n"
SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n"
@ -48,49 +43,48 @@ void codegen_append_VecT_base_methods(VecU8* res, SpanU8 T, bool primitive, bool
SPACE "}\n"
SPACE "self->buf[self->len] = el;\n"
SPACE "self->len = new_length;\n"
"}\n\n", T, T, T, T, T);
"}\n\n", VecT, VecT, T, T, T));
VecU8_append_fmt(res,
"%s* Vec%s_mat(Vec%s* self, size_t i) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"%s* %s_mat(%s* self, size_t i) {\n"
SPACE "assert(i < self->len);\n"
SPACE "return &self->buf[i];\n"
"}\n\n", T, T, T);
"}\n\n", T, VecT, VecT));
VecU8_append_fmt(res,
"const %s* Vec%s_at(const Vec%s* self, size_t i) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"const %s* %s_at(const %s* self, size_t i) {\n"
SPACE "assert(i < self->len);\n"
SPACE "return &self->buf[i];\n"
"}\n\n", T, T, T);
"}\n\n", T, VecT, VecT));
VecU8_append_fmt(res,
"void Vec%s_sink(Vec%s* self, size_t new_len) {\n" /* T, T */
VecU8_append_vec(&res, VecU8_fmt(
"void %s_sink(%s* self, size_t new_len) {\n" /* VecT, VecT */
SPACE "assert(new_len <= self->len);\n"
"%v" /* dropping */
SPACE "self->len = new_len;\n"
"}\n\n", T, T,
"}\n\n", VecT, VecT,
primitive ? vcstr("") : VecU8_fmt(
SPACE "for (size_t i = new_len; i < self->len; i++)\n"
SPACE SPACE "%s_drop(self->buf[i]);\n", /* T */
T));
T)));
if (clonable) {
VecU8_append_fmt(res,
"NODISCARD Vec%s Vec%s_clone(const Vec%s* self) {\n" /* T, T, T */
SPACE "Vec%s res = (Vec%s){.buf = (%s*)safe_calloc(self->len, sizeof(%s)),\n" /* T, T, T, T */
SPACE SPACE ".len = self->len, .capacity = self->len};\n",
T, T, T, T, T, T, T);
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_clone(const %s* self) {\n" /* VecT, VecT, VecT */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(self->len, sizeof(%s)), .len = self->len, .capacity = self->len};\n",
VecT, VecT, VecT, VecT, VecT, T, T));
if (primitive) {
VecU8_append_fmt(res, SPACE "memcpy(res.buf, self->buf, self->len * sizeof(%s));\n", T);
VecU8_append_vec(&res, VecU8_fmt(SPACE "memcpy(res.buf, self->buf, self->len * sizeof(%s));\n", T));
} else {
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
SPACE "for (size_t i = 0; i < self->len; i++)\n"
SPACE SPACE "res.buf[i] = %s_clone(&self->buf[i]);\n", T);
SPACE SPACE "res.buf[i] = %s_clone(&self->buf[i]);\n", T));
}
VecU8_append_cstr(res, SPACE "return res;\n}\n\n");
VecU8_append_span(&res, cstr(SPACE "return res;\n}\n\n"));
}
VecU8_append_fmt(res,
"void Vec%s_append_vec(Vec%s* self, Vec%s b) {\n" /* T, T, T */
VecU8_append_vec(&res, VecU8_fmt(
"void %s_append_vec(%s* self, %s b) {\n" /* VecT, VecT, VecT */
SPACE "size_t new_length = self->len + b.len;\n"
SPACE "if (new_length > self->capacity) {\n"
SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n"
@ -102,114 +96,129 @@ void codegen_append_VecT_base_methods(VecU8* res, SpanU8 T, bool primitive, bool
SPACE "}\n"
SPACE "self->len = new_length;\n"
SPACE "free(b.buf);\n"
"}\n\n", T, T, T, T, T);
"}\n\n", VecT, VecT, VecT, T, T));
if (primitive) {
VecU8_append_fmt(res,
"NODISCARD Vec%s Vec%s_new_zeroinit(size_t len) {\n" /* T, T */
SPACE "return (Vec%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* T, T, T */
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_zeroinit(size_t len) {\n" /* VecT, VecT*/
SPACE "return (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, T, T */
"}\n\n",
T, T, T, T, T);
VecT, VecT, VecT, T, T));
}
VecU8_drop(g_VecT); // VecT invalidated too
return res;
}
/* if !primitive, requires methods T_clone, T_drop */
void codegen_append_VecT_trivmove_extended_methods(VecU8* res, SpanU8 T, bool primitive, bool clonable) {
VecU8 VecT = VecU8_fmt("Vec%s", T);
NODISCARD VecU8 generate_VecT_trivmove_extended_methods(SpanU8 T, bool primitive, bool clonable) {
VecU8 g_VecT = VecU8_fmt("Vec%s", T);
SpanU8 VecT = VecU8_to_span(&g_VecT);
VecU8 res = VecU8_new();
VecU8_append_fmt(res,
"%s%s %r_pop(%r* self) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"%s%s %s_pop(%s* self) {\n"
SPACE "assert(self->len > 0);\n"
SPACE "self->len--;\n"
SPACE "return self->buf[self->len];\n"
"}\n\n", primitive ? cstr("") : cstr("NODISCARD "), T, VecT, VecT);
"}\n\n", primitive ? cstr("") : cstr("NODISCARD "), T, VecT, VecT));
if (!primitive) {
VecU8_append_fmt(res,
"void %r_pop_and_drop(%r* self) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"void %s_pop_and_drop(%s* self) {\n"
SPACE "assert(self->len > 0);\n"
SPACE "%s_drop(self->buf[self->len - 1]);\n"
SPACE "self->len--;\n"
"}\n\n", VecT, VecT, T);
"}\n\n", VecT, VecT, T));
}
VecU8_append_fmt(res,
"%s%s %r_unordered_pop(%r* self, size_t ind) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"%s%s %s_unordered_pop(%s* self, size_t ind) {\n"
SPACE "assert(ind < self->len);\n"
SPACE "%s res = self->buf[ind];\n"
SPACE "self->buf[ind] = self->buf[self->len - 1];\n"
SPACE "self->len--;\n"
SPACE "return res;\n"
"}\n\n", primitive ? cstr("") : cstr("NODISCARD "), T, VecT, VecT, T);
"}\n\n", primitive ? cstr("") : cstr("NODISCARD "), T, VecT, VecT, T));
if (!primitive) {
VecU8_append_fmt(res,
"void %r_unordered_pop_and_drop(%r* self, size_t ind) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"void %s_unordered_pop_and_drop(%s* self, size_t ind) {\n"
SPACE "assert(ind < self->len);\n"
SPACE "%s_drop(self->buf[ind]);\n"
SPACE "self->buf[ind] = self->buf[self->len - 1];\n"
SPACE "self->len--;\n"
"}\n\n", VecT, VecT, T);
"}\n\n", VecT, VecT, T));
}
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_swap_with_empty(%s* cell) {\n"
SPACE "%s val = *cell;\n"
SPACE "*cell = (%s){NULL, 0, 0};\n"
SPACE "return val;\n"
"}\n\n", VecT, VecT, VecT, VecT, VecT));
if (primitive) {
VecU8_append_fmt(res,
"NODISCARD %r %r_new_filled(size_t len, %s el) {\n" /* VecT, VecT, T */
SPACE "%r res = (%r){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_filled(size_t len, %s el) {\n" /* VecT, VecT, T */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
SPACE "for (size_t i = 0; i < len; i++)\n"
SPACE SPACE "res.buf[i] = el;\n"
SPACE "return res;\n"
"}\n\n", VecT, VecT, T, VecT, VecT, T, T);
"}\n\n", VecT, VecT, T, VecT, VecT, T, T));
} else if (clonable) {
VecU8_append_fmt(res,
"NODISCARD %r %r_new_filled(size_t len, const %s* el) {\n" /* VecT, VecT, T */
SPACE "%r res = (%r){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_filled(size_t len, const %s* el) {\n" /* VecT, VecT, T */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
SPACE "for (size_t i = 0; i < len; i++)\n"
SPACE SPACE "res.buf[i] = %s_clone(el);\n" /* T */
SPACE "return res;\n"
"}\n\n", VecT, VecT, T, VecT, VecT, T, T, T);
"}\n\n", VecT, VecT, T, VecT, VecT, T, T, T));
}
VecU8_drop(VecT);
VecU8_drop(g_VecT); // VecT invalidated
return res;
}
// todo: add _less_ method
/* if !integer requires method T_equal_T */
void codegen_append_VecT_equal_method(VecU8* res, SpanU8 T, bool integer) {
VecU8 VecT = VecU8_fmt("Vec%s", T);
VecU8_append_fmt(res,
"bool %r_equal_%r(const %r* A, const %r* B) {\n"
SPACE "if (A->len != B->len)\n"
SPACE SPACE "return false;\n"
SPACE "for (size_t i = 0; i < A->len; i++) {\n", VecT, VecT, VecT, VecT);
NODISCARD VecU8 generate_VecT_equal_method(SpanU8 T, bool integer) {
VecU8 g_VecT = VecU8_fmt("Vec%s", T);
SpanU8 VecT = VecU8_to_span(&g_VecT);
VecU8 res = VecU8_fmt(
"bool %s_equal_%s(const %s* A, const %s* B) {\n"
SPACE "if (A->len != B->len)\n"
SPACE SPACE "return false;\n"
SPACE "for (size_t i = 0; i < A->len; i++) {\n", VecT, VecT, VecT, VecT);
if (integer) {
VecU8_append_cstr(res, SPACE8 "if (A->buf[i] != B->buf[i])\n");
VecU8_append_span(&res, cstr(SPACE8 "if (A->buf[i] != B->buf[i])\n"));
} else {
VecU8_append_fmt(res, SPACE8 "if (!%s_equal_%s(A->buf + i, B->buf + i))\n", T, T);
VecU8_append_vec(&res, VecU8_fmt(SPACE8 "if (!%s_equal_%s(A->buf + i, B->buf + i))\n", T, T));
}
VecU8_append_cstr(res,
VecU8_append_span(&res, cstr(
SPACE SPACE SPACE "return false;\n"
SPACE "}\n"
SPACE "return true;\n"
"}\n\n"
);
));
VecU8_drop(VecT);
VecU8_drop(g_VecT);
return res;
}
/* requires method T_new */
void codegen_append_VecT_new_of_size_method(VecU8* res, SpanU8 T) {
VecU8 VecT = VecU8_fmt("Vec%s", T);
VecU8_append_fmt(res,
"NODISCARD %r %r_new_of_size(size_t len) {\n" /* VecT, VecT */
SPACE "%r res = (%r){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
SPACE "for (size_t i = 0; i < len; i++)\n"
SPACE SPACE "res.buf[i] = %s_new();\n" /* T */
SPACE "return res;\n"
"}\n", VecT, VecT, VecT, VecT, T, T, T);
VecU8_drop(VecT);
NODISCARD VecU8 generate_VecT_new_of_size_method(SpanU8 T) {
VecU8 g_VecT = VecU8_fmt("Vec%s", T);
SpanU8 VecT = VecU8_to_span(&g_VecT);
VecU8 res = VecU8_fmt(
"NODISCARD %s %s_new_of_size(size_t len) {\n" /* VecT, VecT */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
SPACE "for (size_t i = 0; i < len; i++)\n"
SPACE SPACE "res.buf[i] = %s_new();\n" /* T */
SPACE "return res;\n"
"}\n", VecT, VecT, VecT, VecT, T, T, T);
VecU8_drop(g_VecT);
return res;
}
/* helper function. SpanT is either SpanT or MutSpanT */
@ -220,16 +229,13 @@ void codegen_append_some_span_equal_method(VecU8* res, SpanU8 SpanT) {
"}\n\n", SpanT, SpanT, SpanT, SpanT));
}
/* Helper function. (span_mod, mod) is in {("", "const "), ("Mut", "")} */
void codegen_append_some_span_struct(VecU8* res, SpanU8 T, SpanU8 span_mod, SpanU8 mod, bool skip_declaration_gen) {
if (!skip_declaration_gen) {
VecU8_append_vec(res, VecU8_fmt("typedef struct %sSpan%s %sSpan%s;\n\n", span_mod, T, span_mod, T));
}
/* helper function. (SpanT, mod) is either (SpanT "const ") or (MutSpanT, "") */
void codegen_append_some_span_struct(VecU8* res, SpanU8 T, SpanU8 SpanT, SpanU8 mod) {
VecU8_append_vec(res, VecU8_fmt(
"struct %sSpan%s {\n" /* span_mod, T */
SPACE "%s%s* data;\n" /* mod, T */
"typedef struct {\n"
SPACE "%s%s* data;\n"
SPACE "size_t len;\n"
"};\n\n", span_mod, T, mod, T));
"} %s;\n\n", mod, T, SpanT));
}
/* helper function. (SpanT, mod) is either (SpanT "const ") or (MutSpanT, "") */
@ -251,143 +257,153 @@ void codegen_append_some_span_span_method(VecU8* res, SpanU8 SpanT) {
"}\n\n", SpanT, SpanT, SpanT, SpanT));
}
void codegen_append_SpanT_structures(VecU8* res, SpanU8 T, bool add_mutable, bool skip_declaration_gen){
codegen_append_some_span_struct(res, T, cstr(""), cstr("const "), skip_declaration_gen);
if (add_mutable)
codegen_append_some_span_struct(res, T, cstr("Mut"), cstr(""), skip_declaration_gen);
}
/* T must be sized. Option `add_sort` requires option `add_mutable` and method T_less
* add_mutable option generates MutSpanT.
* add_equal option generates equal method. add_extended option generated extended methods
*/
void codegen_append_SpanT_base_methods(VecU8* res,
NODISCARD VecU8 generate_SpanT_struct_and_methods(
SpanU8 T, bool integer, bool add_mutable, bool add_equal, bool add_extended
) {
VecU8 SpanT = VecU8_fmt("Span%s", T);
VecU8 MutSpanT = VecU8_fmt("MutSpan%s", T);
VecU8 g_SpanT = VecU8_fmt("Span%s", T);
VecU8 g_MutSpanT = VecU8_fmt("MutSpan%s", T);
SpanU8 SpanT = VecU8_to_span(&g_SpanT);
SpanU8 MutSpanT = VecU8_to_span(&g_MutSpanT);
VecU8 res = VecU8_new();
codegen_append_some_span_struct(&res, T, SpanT, cstr("const "));
if (add_mutable)
codegen_append_some_span_struct(&res, T, MutSpanT, cstr(""));
if (add_equal) {
codegen_append_some_span_equal_method(res, VecU8_to_span(&SpanT));
codegen_append_some_span_equal_method(&res, SpanT);
if (add_mutable)
codegen_append_some_span_equal_method(res, VecU8_to_span(&MutSpanT));
codegen_append_some_span_equal_method(&res, MutSpanT);
}
if (add_mutable) {
VecU8_append_fmt(res,
"%r %r_to_%r(%r self) {\n"
SPACE "return (%r){.data = self.data, .len = self.len};\n"
"}\n\n", SpanT, MutSpanT, SpanT, MutSpanT, SpanT);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_to_%s(%s self) {\n"
SPACE "return (%s){.data = self.data, .len = self.len};\n"
"}\n\n", SpanT, MutSpanT, SpanT, MutSpanT, SpanT));
}
codegen_append_some_span_at_method(res, T, VecU8_to_span(&SpanT), cstr("const "));
codegen_append_some_span_at_method(&res, T, SpanT, cstr("const "));
if (add_mutable)
codegen_append_some_span_at_method(res, T, VecU8_to_span(&MutSpanT), cstr(""));
codegen_append_some_span_at_method(&res, T, MutSpanT, cstr(""));
if (add_extended) {
codegen_append_some_span_span_method(res, VecU8_to_span(&SpanT));
codegen_append_some_span_span_method(&res, SpanT);
if (add_mutable)
codegen_append_some_span_span_method(res, VecU8_to_span(&MutSpanT));
codegen_append_some_span_span_method(&res, MutSpanT);
}
VecU8_drop(MutSpanT);
VecU8_drop(SpanT);
VecU8_drop(g_MutSpanT);
VecU8_drop(g_SpanT);
return res;
}
void codegen_append_span_company_sort_methods(VecU8* res, SpanU8 T, bool t_integer, bool mut_span, bool vec){
VecU8_append_fmt(res,
NODISCARD VecU8 generate_span_company_sort_methods(SpanU8 T, bool t_integer, bool mut_span, bool vec){
VecU8 res = VecU8_new();
VecU8_append_vec(&res, VecU8_fmt(
"int %s_qcompare(const void* a, const void* b) {\n" /* T */
SPACE "const %s* A = a;\n" /* T */
SPACE "const %s* B = b;\n" /* T */
SPACE "return %v;\n" /* we return stuff */
"}\n\n",
T, T, T, t_integer ? vcstr("(int)(*B < *A) - (int)(*A < *B)") :
VecU8_fmt("(int)%s_less_%s(B, A) - (int)%s_less_%s(A, B)", T, T, T, T));
VecU8_fmt("(int)%s_less_%s(B, A) - (int)%s_less_%s(A, B)", T, T, T, T)));
if (mut_span) {
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"void MutSpan%s_sort(MutSpan%s self) {\n"
SPACE "qsort(self.data, self.len, sizeof(%s), %s_qcompare);\n"
"}\n\n", T, T, T, T);
"}\n\n", T, T, T, T));
}
if (vec) {
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
"void Vec%s_sort(Vec%s* self) {\n"
SPACE "qsort(self->buf, self->len, sizeof(%s), %s_qcompare);\n"
"}\n\n", T, T, T, T);
"}\n\n", T, T, T, T));
}
return res;
}
/* T must be trivially movable. If !primitive, requires methods T_drop (implicitly) and, if clonable, requires T_clone */
void codegen_append_SpanT_VecT_trivmove_collab(VecU8* res,
SpanU8 T, bool primitive, bool clonable, bool add_mutable, bool add_extended) {
VecU8 SpanT = VecU8_fmt("Span%s", T);
VecU8 MutSpanT = VecU8_fmt("MutSpan%s", T);
VecU8 VecT = VecU8_fmt("Vec%s", T);
NODISCARD VecU8 generate_SpanT_VecT_trivmove_collab(SpanU8 T, bool primitive, bool clonable, bool add_mutable, bool add_extended) {
VecU8 g_SpanT = VecU8_fmt("Span%s", T);
VecU8 g_MutSpanT = VecU8_fmt("MutSpan%s", T);
VecU8 g_VecT = VecU8_fmt("Vec%s", T);
SpanU8 SpanT = VecU8_to_span(&g_SpanT);
SpanU8 MutSpanT = VecU8_to_span(&g_MutSpanT);
SpanU8 VecT = VecU8_to_span(&g_VecT);
VecU8 res = VecU8_new();
if (clonable) {
VecU8_append_fmt(res,
"NODISCARD %r %r_from_span(%r src){\n" /* VecT, VecT, SpanT */
SPACE "%r res = (%r){ .buf = (%s*)safe_calloc(src.len, sizeof(%s)), .len = src.len, .capacity = src.len };\n", /* VecT, VecT, T, T */
VecT, VecT, SpanT, VecT, VecT, T, T);
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_from_span(%s src){\n" /* VecT, VecT, SpanT */
SPACE "%s res = (%s){ .buf = (%s*)safe_calloc(src.len, sizeof(%s)), .len = src.len, .capacity = src.len };\n", /* VecT, VecT, T, T */
VecT, VecT, SpanT, VecT, VecT, T, T));
if (primitive) {
VecU8_append_fmt(res, SPACE "memcpy(res.buf, src.data, src.len * sizeof(%s));\n", T);
VecU8_append_vec(&res, VecU8_fmt(
SPACE "memcpy(res.buf, src.data, src.len * sizeof(%s));\n", T));
} else {
VecU8_append_fmt(res,
VecU8_append_vec(&res, VecU8_fmt(
SPACE "for (size_t i = 0; i < src.len; i++)\n"
SPACE8 "res.buf[i] = %s_clone(&src.data[i]);\n", T);
SPACE8 "res.buf[i] = %s_clone(&src.data[i]);\n", T));
}
VecU8_append_cstr(res, SPACE "return res;\n}\n\n");
VecU8_append_span(&res, cstr(SPACE "return res;\n}\n\n"));
}
VecU8_append_fmt(res,
"%r %r_to_span(const %r* vec){\n"
SPACE "return (%r){vec->buf, vec->len};\n"
"}\n\n", SpanT, VecT, VecT, SpanT);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_to_span(const %s* vec){\n"
SPACE "return (%s){vec->buf, vec->len};\n"
"}\n\n", SpanT, VecT, VecT, SpanT));
if (add_mutable) {
VecU8_append_fmt(res,
"%r %r_to_mspan(%r* vec){\n"
SPACE "return (%r){vec->buf, vec->len};\n"
"}\n\n", MutSpanT, VecT, VecT, MutSpanT);
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_to_mspan(%s* vec){\n"
SPACE "return (%s){vec->buf, vec->len};\n"
"}\n\n", MutSpanT, VecT, VecT, MutSpanT));
}
if (clonable) {
VecU8_append_fmt(res,
"void %r_append_span(%r* self, %r b) {\n" /* VecT, VecT, SpanT */
VecU8_append_vec(&res, VecU8_fmt(
"void %s_append_span(%s* self, %s b) {\n" /* VecT, VecT, SpanT */
SPACE "size_t new_length = self->len + b.len;\n"
SPACE "if (new_length > self->capacity) {\n"
SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n"
SPACE SPACE "self->buf = (%s*)safe_realloc(self->buf, new_capacity * sizeof(%s));\n" /* T, T */
SPACE SPACE "self->capacity = new_capacity;\n"
SPACE "}\n", VecT, VecT, SpanT, T, T);
SPACE "}\n", VecT, VecT, SpanT, T, T));
if (primitive) {
VecU8_append_fmt(res,
SPACE "memcpy(self->buf + self->len, b.data, b.len * sizeof(%s));\n", T);
VecU8_append_vec(&res, VecU8_fmt(
SPACE "memcpy(self->buf + self->len, b.data, b.len * sizeof(%s));\n", T));
} else {
VecU8_append_fmt(res,
SPACE "for (size_t i = 0; i < b.len; i++)\n"
SPACE SPACE "self->buf[self->len + i] = %s_clone(&b.data[i]);\n", T);
VecU8_append_vec(&res, VecU8_fmt(
SPACE "for (size_t i = 0; i < b.len; i++)\n"
SPACE SPACE "self->buf[self->len + i] = %s_clone(&b.data[i]);\n", T));
}
VecU8_append_cstr(res,
VecU8_append_span(&res, cstr(
SPACE "self->len = new_length;\n"
"}\n\n");
"}\n\n"));
}
if (add_extended) {
VecU8_append_fmt(res,
"%r %r_span(const %r* vec, size_t start, size_t len) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_span(const %s* vec, size_t start, size_t len) {\n"
SPACE "assert(start < SIZE_MAX - len && start + len <= vec->len);\n"
SPACE "return (%r){.data = vec->buf + start, .len = len};\n"
"}\n\n", SpanT, VecT, VecT, SpanT);
SPACE "return (%s){.data = vec->buf + start, .len = len};\n"
"}\n\n", SpanT, VecT, VecT, SpanT));
if (add_mutable) {
VecU8_append_fmt(res,
"%r %r_mspan(%r* vec, size_t start, size_t len) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_mspan(%s* vec, size_t start, size_t len) {\n"
SPACE "assert(start < SIZE_MAX - len && start + len <= vec->len);\n"
SPACE "return (%r){.data = vec->buf + start, .len = len};\n"
"}\n\n", MutSpanT, VecT, VecT, MutSpanT);
SPACE "return (%s){.data = vec->buf + start, .len = len};\n"
"}\n\n", MutSpanT, VecT, VecT, MutSpanT));
}
}
VecU8_drop(VecT);
VecU8_drop(MutSpanT);
VecU8_drop(SpanT);
VecU8_drop(g_VecT);
VecU8_drop(g_MutSpanT);
VecU8_drop(g_SpanT);
return res;
}
/* The only reason this function exists is because in C it is easier to supply a lot of brace list arguments,
@ -410,8 +426,6 @@ typedef struct {
bool sort;
bool collab_vec_span;
bool collab_vec_span_extended;
bool skip_declaration_gen;
} util_templates_instantiation_options;
void util_templates_instantiation_options_fix(util_templates_instantiation_options* op) {
@ -439,51 +453,37 @@ void util_templates_instantiation_options_fix(util_templates_instantiation_optio
assert(!op->t_primitive || op->t_clonable);
}
NODISCARD VecU8 generate_util_templates_instantiation(util_templates_instantiation_options op,
bool generate_structures, bool generate_methods) {
NODISCARD VecU8 generate_util_templates_instantiation(util_templates_instantiation_options op) {
VecU8 res = VecU8_new();
util_templates_instantiation_options_fix(&op);
if (generate_structures) {
if (op.vec) {
codegen_append_VecT_struct(&res, op.T, op.skip_declaration_gen);
}
if (op.span) {
codegen_append_SpanT_structures(&res, op.T, op.mut_span, op.skip_declaration_gen);
}
if (op.vec) {
VecU8_append_vec(&res, generate_VecT_struct_and_base_methods(op.T, op.t_primitive, op.t_clonable));
}
if (generate_methods) {
if (op.vec) {
codegen_append_VecT_base_methods(&res, op.T, op.t_primitive, op.t_clonable);
}
if (op.vec_extended) {
assert(op.vec);
codegen_append_VecT_trivmove_extended_methods(&res, op.T, op.t_primitive, op.t_clonable);
}
if (op.vec_equal) {
assert(op.vec);
codegen_append_VecT_equal_method(&res, op.T, op.t_integer);
}
if (op.vec_new_of_size) {
assert(op.vec);
codegen_append_VecT_new_of_size_method(&res, op.T);
}
if (op.span) {
codegen_append_SpanT_base_methods(&res, op.T, op.t_integer, op.mut_span, false, op.span_extended);
}
if (op.sort) {
codegen_append_span_company_sort_methods(&res, op.T, op.t_integer, op.mut_span, op.vec);
}
if (op.collab_vec_span) {
assert(op.vec && op.span);
codegen_append_SpanT_VecT_trivmove_collab(&res,
op.T, op.t_primitive, op.t_clonable, op.mut_span, op.collab_vec_span_extended);
}
if (op.vec_extended) {
assert(op.vec);
VecU8_append_vec(&res, generate_VecT_trivmove_extended_methods(op.T, op.t_primitive, op.t_clonable));
}
if (op.vec_equal) {
assert(op.vec);
VecU8_append_vec(&res, generate_VecT_equal_method(op.T, op.t_integer));
}
if (op.vec_new_of_size) {
assert(op.vec);
VecU8_append_vec(&res, generate_VecT_new_of_size_method(op.T));
}
if (op.span) {
VecU8_append_vec(&res, generate_SpanT_struct_and_methods(op.T, op.t_integer, op.mut_span, false, op.span_extended));
}
if (op.sort) {
VecU8_append_vec(&res, generate_span_company_sort_methods(op.T, op.t_integer, op.mut_span, op.vec));
}
if (op.collab_vec_span) {
assert(op.vec && op.span);
VecU8_append_vec(&res, generate_SpanT_VecT_trivmove_collab(op.T, op.t_primitive, op.t_clonable, op.mut_span, op.collab_vec_span_extended));
}
return res;
}
/* Does not include .h postfix. .h postfix and `path` prefix have to be added by someone else */
NODISCARD VecU8 util_templates_instantiation_get_appropriate_filename(util_templates_instantiation_options op) {
util_templates_instantiation_options_fix(&op);
return VecU8_fmt("%s%s%s""%s%s",
@ -491,49 +491,38 @@ NODISCARD VecU8 util_templates_instantiation_get_appropriate_filename(util_templ
(int)op.vec + (int)op.span > 1 ? cstr("_") : cstr(""), op.T);
}
void generate_util_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, util_templates_instantiation_options op,
bool separate_struct_and_methods) {
if (separate_struct_and_methods) {
VecU8 name_for_structures = VecU8_fmt("%v_struct", util_templates_instantiation_get_appropriate_filename(op));
VecU8 name_for_methods = VecU8_fmt("%v_methods", util_templates_instantiation_get_appropriate_filename(op));
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_util_templates_instantiation(op, true, false),
name_for_structures);
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_util_templates_instantiation(op, false, true),
name_for_methods);
} else {
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_util_templates_instantiation(op, true, true),
util_templates_instantiation_get_appropriate_filename(op));
}
void generate_util_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, util_templates_instantiation_options op) {
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_util_templates_instantiation(op),
util_templates_instantiation_get_appropriate_filename(op));
}
void generate_eve_span_company_for_primitive(SpanU8 layer, SpanU8 ns, SpanU8 T, bool with_vector, bool with_span) {
generate_util_templ_inst_eve_header(layer, ns, (util_templates_instantiation_options){
.T = T,
.t_primitive = true, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span
}, false);
});
}
void generate_eve_span_company_for_non_primitive_clonable(SpanU8 layer, SpanU8 ns, SpanU8 T, bool with_vector, bool with_span) {
generate_util_templ_inst_eve_header(layer, ns, (util_templates_instantiation_options){
.T = T,
.t_clonable = true, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span
}, false);
});
}
void generate_eve_span_company_for_non_primitive_non_clonable(SpanU8 layer, SpanU8 ns, SpanU8 T, bool with_vector, bool with_span) {
generate_util_templ_inst_eve_header(layer, ns, (util_templates_instantiation_options){
.T = T,
.vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span
}, false);
});
}
void generate_util_templ_inst_guarded_header(
SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, util_templates_instantiation_options op
) {
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, VecU8_fmt("%v%s\n",
codegen_include_relative_to_root(bonus_ns, cstr("src/l1/core/util.h")), dependencies),
generate_util_templates_instantiation(op, true, true), util_templates_instantiation_get_appropriate_filename(op));
generate_util_templates_instantiation(op), util_templates_instantiation_get_appropriate_filename(op));
}
void generate_guarded_span_company_for_primitive(
@ -563,7 +552,6 @@ void generate_guarded_span_company_for_non_primitive_non_clonable(
});
}
NODISCARD VecU8 get_ResultType_inst_name(SpanU8 OkT, SpanU8 ErrT){
bool ok_t_void = OkT.len == 0;
bool err_t_void = ErrT.len == 0;
@ -580,48 +568,48 @@ NODISCARD VecU8 generate_result_template_inst(SpanU8 OkT, SpanU8 ErrT, bool ok_t
assert(!ok_t_void || ok_t_primitive);
assert(!err_t_void || err_t_primitive);
VecU8 ResultT = get_ResultType_inst_name(OkT, ErrT);
VecU8 g_ResultT = get_ResultType_inst_name(OkT, ErrT);
SpanU8 ResultT = VecU8_to_span(&g_ResultT);
VecU8 res = VecU8_new();
VecU8_append_cstr(&res,
VecU8_append_span(&res, cstr(
"typedef struct {\n"
SPACE "Result_variant variant;\n");
SPACE "Result_variant variant;\n"));
if (ok_t_void && !err_t_void) {
VecU8_append_fmt(&res, SPACE "%s err;\n", ErrT);
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s err;\n", ErrT));
} else if (!ok_t_void && err_t_void) {
VecU8_append_fmt(&res, SPACE "%s ok;\n", OkT);
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s ok;\n", OkT));
} else {
VecU8_append_fmt(&res,
VecU8_append_vec(&res, VecU8_fmt(
SPACE "union {\n"
SPACE SPACE "%s ok;\n"
SPACE SPACE "%s err;\n"
SPACE "};\n", OkT, ErrT);
SPACE "};\n", OkT, ErrT));
}
VecU8_append_fmt(&res, "} %r;\n\n", ResultT);
VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", ResultT));
/* This method is 100% useless */
if (!ok_t_primitive || !err_t_primitive) {
VecU8_append_fmt(&res,
"void %r_drop(%r self) {\n", ResultT, ResultT);
VecU8_append_vec(&res, VecU8_fmt(
"void %s_drop(%s self) {\n", ResultT, ResultT));
if (ok_t_primitive && !err_t_primitive) {
VecU8_append_fmt(&res,
VecU8_append_vec(&res, VecU8_fmt(
SPACE "if (self.variant == Result_Err)\n"
SPACE SPACE "%s_drop(self.err);\n", ErrT);
SPACE SPACE "%s_drop(self.err);\n", ErrT));
} else if (!ok_t_primitive && err_t_primitive) {
VecU8_append_fmt(&res,
VecU8_append_vec(&res, VecU8_fmt(
SPACE "if (self.variant == Result_Ok)\n"
SPACE SPACE "%s_drop(self.ok);\n", OkT);
SPACE SPACE "%s_drop(self.ok);\n", OkT));
} else {
VecU8_append_fmt(&res,
VecU8_append_vec(&res, VecU8_fmt(
SPACE "if (self.variant == Result_Ok)\n"
SPACE SPACE "%s_drop(self.ok);\n"
SPACE "else\n"
SPACE SPACE "%s_drop(self.err);\n", OkT, ErrT);
SPACE SPACE "%s_drop(self.err);\n", OkT, ErrT));
}
VecU8_append_cstr(&res, "}\n\n");
VecU8_append_span(&res, cstr("}\n\n"));
}
VecU8_drop(ResultT); /* ResultT variable invalidated */
VecU8_drop(g_ResultT); /* ResultT variable invalidated */
return res;
}
@ -660,53 +648,52 @@ void option_template_instantiation_op_fix(option_template_instantiation_op* self
NODISCARD VecU8 generate_OptionT_struct_and_methods(option_template_instantiation_op op) {
option_template_instantiation_op_fix(&op);
VecU8 OptionT = VecU8_fmt("Option%s", op.T);
VecU8 g_OptionT = VecU8_fmt("Option%s", op.T);
SpanU8 OptionT = VecU8_to_span(&g_OptionT);
VecU8 res = VecU8_new();
if (op.t_ptr) {
VecU8_append_fmt(&res, "typedef %s %r;\n", op.T, OptionT);
VecU8_append_fmt(&res, "#define None_%s() NULL\n", op.T);
VecU8_append_fmt(&res, "%r Some_%s(%s ref) {\n" SPACE "return ref;\n}\n\n", OptionT, op.T, op.T);
VecU8_append_fmt(&res,
"%s %r_expect(%r self) {\n"
SPACE "if (self == NULL){\n"
SPACE SPACE "abortf(\"Expected something in %r got NULL\\n\");\n"
VecU8_append_vec(&res, VecU8_fmt("typedef %s %s;\n", op.T, OptionT));
VecU8_append_vec(&res, VecU8_fmt("#define None_%s() NULL\n", op.T));
VecU8_append_vec(&res, VecU8_fmt("%s Some_%s(%s ref) {\n" SPACE "return ref;\n}\n\n", OptionT, op.T, op.T));
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_expect(%s self) {\n"
SPACE "return self;\n"
"}\n\n", op.T, OptionT, OptionT, OptionT);
"}\n\n", op.T, OptionT, OptionT));
} else {
VecU8_append_fmt(&res,
VecU8_append_vec(&res, VecU8_fmt(
"typedef struct {\n"
SPACE "Option_variant variant;\n"
SPACE "%s some;\n"
"} %r;\n\n", op.T, OptionT);
VecU8_append_fmt(&res, "#define None_%s() (%r){ .variant = Option_None }\n\n", op.T, OptionT);
VecU8_append_fmt(&res,
"NODISCARD %r Some_%s(%s obj) {\n"
SPACE "return (%r){ .variant = Option_Some, .some = obj };\n"
"}\n\n", OptionT, op.T, op.T, OptionT);
VecU8_append_fmt(&res,
"NODISCARD %s %r_expect(%r self){\n"
"} %s;\n\n", op.T, OptionT));
VecU8_append_vec(&res, VecU8_fmt("#define None_%s() (%s){ .variant = Option_None }\n\n", op.T, OptionT));
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s Some_%s(%s obj) {\n"
SPACE "return (%s){ .variant = Option_Some, .some = obj };\n"
"}\n\n", OptionT, op.T, op.T, OptionT));
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_expect(%s self){\n"
SPACE "if (self.variant == Option_None)\n"
SPACE SPACE "abortf(\"Expected something in %r got None\\n\");\n"
SPACE SPACE "abortf(\"Expected something in %s got None\\n\");\n"
SPACE "return self.some;\n"
"}\n\n", op.T, OptionT, OptionT, OptionT);
"}\n\n", op.T, OptionT, OptionT, OptionT));
if (!op.t_primitive) {
VecU8_append_fmt(&res,
"void %r_drop(%r self) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"void %s_drop(%s self) {\n"
SPACE "if (self.variant == Option_None)\n"
SPACE SPACE "%s_drop(self.some);\n"
"}\n\n", OptionT, OptionT, op.T);
"}\n\n", OptionT, OptionT, op.T));
if (op.t_clonable) {
VecU8_append_fmt(&res,
"NODISCARD %r %r_clone(const %r* self) {\n"
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_clone(const %s* self) {\n"
SPACE "if (self->variant == Option_None)\n"
SPACE SPACE "return (%r) { .variant = Option_None };\n"
SPACE "return (%r){ .variant = Option_Some, .some = %s_clone(&self->some) };\n"
"}\n\n", OptionT, OptionT, OptionT, OptionT, OptionT, op.T);
SPACE SPACE "return (%s) { .variant = Option_None };\n"
SPACE "return (%s){ .variant = Option_Some, .some = %s_clone(&self->some) };\n"
"}\n\n", OptionT, OptionT, OptionT, OptionT, OptionT, op.T));
}
}
}
VecU8_drop(OptionT);
VecU8_drop(g_OptionT);
return res;
}
@ -722,3 +709,5 @@ void generate_Option_templ_inst_guarded_header(
codegen_include_relative_to_root(bonus_ns, cstr("src/l1/core/util.h")), dependencies),
generate_OptionT_struct_and_methods(op), VecU8_fmt("Option%s", op.T));
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_CORE_VECU8_AS_STR_H
#define PROTOTYPE1_SRC_L1_CORE_VECU8_AS_STR_H
#include <stdarg.h>
@ -34,13 +35,6 @@ void SpanU8_fprint(SpanU8 str, FILE* stream) {
putc((int)*SpanU8_at(str, i), stream);
}
/* Not thread safe */
void VecU8_print(VecU8 self){
SpanU8_print(VecU8_to_span(&self));
VecU8_drop(self);
}
/* Wrapper around vsnprintf */
NODISCARD VecU8 VecU8_format(const char *fmt, ...) {
assert(fmt);
@ -108,12 +102,6 @@ void S64_stringification_into_buf(S64 x, VecU8* targ){
}
}
VecU8 S64_stringification(S64 x){
VecU8 res = VecU8_new();
S64_stringification_into_buf(x, &res);
return res;
}
size_t U64_stringification_get_length(U64 x){
if (x == 0)
return 1;
@ -147,16 +135,17 @@ void U64_stringification_into_buf(U64 x, VecU8* targ){
}
}
VecU8 U64_stringification(U64 x){
VecU8 res = VecU8_new();
U64_stringification_into_buf(x, &res);
return res;
}
NODISCARD VecU8 VecU8_fmt_va_list(const char* fmt, va_list args){
/* %s - SpanU8
* %v - VecU8
* %u - U64
* %c - int (one byte character)
* %i - S64
*/
NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
assert(fmt);
size_t k = 0;
va_list repeat;
va_copy(repeat, args);
va_list args;
va_start(args, fmt);
for (const char *ch = fmt; *ch; ) {
if (*ch == '%') {
ch++;
@ -169,7 +158,7 @@ NODISCARD VecU8 VecU8_fmt_va_list(const char* fmt, va_list args){
va_arg(args, int);
k++;
} else if (*ch == 'v') {
/* We had not taken ownership of it YET (will take it the next iteration) */
/* We had not taken ownership of YET (will take it the next iteration) */
VecU8 vs = va_arg(args, VecU8);
k += vs.len;
} else if (*ch == 'i') {
@ -178,9 +167,6 @@ NODISCARD VecU8 VecU8_fmt_va_list(const char* fmt, va_list args){
} else if (*ch == 'u') {
U64 x = va_arg(args, U64);
k += U64_stringification_get_length(x);
} else if (*ch == 'r') {
VecU8 vs = va_arg(args, VecU8);
k += vs.len;
} else
abortf("Format syntax error at pos %lu! Watch out, be careful", (size_t)(ch - fmt));
} else {
@ -188,31 +174,29 @@ NODISCARD VecU8 VecU8_fmt_va_list(const char* fmt, va_list args){
}
ch++;
}
va_end(args);
VecU8 res = VecU8_new_reserved(k);
va_start(args, fmt);
for (const char *ch = fmt; *ch;) {
if (*ch == '%') {
ch++;
if (*ch == '%') {
VecU8_append(&res, '%');
} else if (*ch == 's') {
SpanU8 s = va_arg(repeat, SpanU8);
SpanU8 s = va_arg(args, SpanU8);
VecU8_append_span(&res, s);
} else if (*ch == 'c') {
int byte = va_arg(repeat, int);
int byte = va_arg(args, int);
VecU8_append(&res, (U8)byte);
} else if (*ch == 'v') {
VecU8 vs = va_arg(repeat, VecU8);
VecU8 vs = va_arg(args, VecU8);
VecU8_append_vec(&res, vs); /* Moved ownership of vs argument */
} else if (*ch == 'i') {
S64 x = va_arg(repeat, S64);
S64 x = va_arg(args, S64);
S64_stringification_into_buf(x, &res);
} else if (*ch == 'u') {
U64 x = va_arg(repeat, U64);
U64 x = va_arg(args, U64);
U64_stringification_into_buf(x, &res);
} else if (*ch == 'r') {
VecU8 vs = va_arg(repeat, VecU8);
VecU8_append_span(&res, VecU8_to_span(&vs));
/* But we won't deallocate `vs` because never took ownership of it */
} else
assert(false);
} else {
@ -220,42 +204,12 @@ NODISCARD VecU8 VecU8_fmt_va_list(const char* fmt, va_list args){
}
ch++;
}
va_end(repeat);
return res;
}
/* %s - SpanU8
* %v - VecU8
* %u - U64
* %c - int (one byte character)
* %i - S64
* %r - VecU8 (but taken by reference, it won't be deallocated)
* Yes, I am breaking the dumb ownership-syntax-crutch convention I set up myself
*/
NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
assert(fmt);
va_list args;
va_start(args, fmt);
VecU8 res = VecU8_fmt_va_list(fmt, args);
va_end(args);
return res;
}
void VecU8_append_cstr(VecU8* res, const char* lit){
VecU8_append_span(res, SpanU8_from_cstr(lit));
}
// todo: add VecX_resize method. I really REALLY need to refactor this awful code
void VecU8_append_fmt(VecU8* res, const char* fmt, ...){
va_list args;
va_start(args, fmt);
VecU8 t = VecU8_fmt_va_list(fmt, args);
VecU8_append_vec(res, t);
va_end(args);
}
// 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++) {
@ -281,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;
@ -298,78 +252,4 @@ U32 SpanU8_decode_as_utf8(SpanU8* rem){
return 0;
}
bool SpanU8_is_prefix(SpanU8 a, SpanU8 str){
if (str.len < a.len)
return false;
for (size_t i = 0; i < a.len; i++) {
if (a.data[i] != str.data[i]) {
return false;
}
}
return true;
}
bool SpanU8_is_postfix(SpanU8 a, SpanU8 str){
if (str.len < a.len)
return false;
for (size_t i = 0; i < a.len; i++) {
if (a.data[i] != str.data[str.len - a.len + i]) {
return false;
}
}
return true;
}
// todo: automatically generate such methods for vectors of nice types
bool SpanU8_less_SpanU8(SpanU8 a, SpanU8 b){
size_t i = 0;
while (i < a.len && i < b.len) {
if (a.data[i] < b.data[i])
return true;
if (b.data[i] < a.data[i])
return false;
i++;
}
/* If i < b->len, then a is eigen-prefix of b, which means a < b
* Or... i < a->len, and this means b is eigen-prefix of a => a > b
* Or... a == b . Here we also return false */
return i < b.len;
}
bool VecU8_less_VecU8(const VecU8* a, const VecU8* b){
return SpanU8_less_SpanU8(VecU8_to_span(a), VecU8_to_span(b));
}
char digit_to_big_hex(U32 d){
assert(d < 16);
return d >= 10 ? (char)('A' + d - 10) : (char)('0' + d);
}
char digit_to_small_hex(U32 d){
assert(d < 16);
return d >= 10 ? (char)('a' + d - 10) : (char)('0' + d);
}
static_assert(0b11000000 == 0xC0 && 0b10000000 == 0x80 && 0b00111111 == 0x3F &&
0b11100000 == 0xE0 && 0b11110000 == 0xF0, "asdasda");
/* Some bytes (encoding codepoint U) will be appended to str. Utf-8 works only with codepoints below (1u << 21) */
void VecU8_encode_as_utf8(VecU8* str, U32 U){
if (U < (1u << 7)) {
VecU8_append(str, (U8)U);
} else if (U < (1u << 11)) {
VecU8_append_span(str, (SpanU8){(U8[]){
0xC0 | (U8)(U >> 6), 0x80 | (U8)(U & 0x3F)
}, 2});
} else if (U < (1u << 16)) {
VecU8_append_span(str, (SpanU8){(U8[]){
0xE0 | (U8)(U >> 12), 0x80 | (U8)((U >> 6) & 0x3F), (U8)(U & 0x3F)
}, 3});
} else {
/* U < (1u << 21) */
VecU8_append_span(str, (SpanU8){(U8[]){
0xF0 | (U8)(U >> 18), 0x80 | (U8)((U >> 12) & 0x3F), 0x80 | (U8)((U >> 6) & 0x3F), (U8)(U & 0x3F)
}, 4});
}
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_CORE_CHICKEN_VECU8_H
#define PROTOTYPE1_SRC_L1_CORE_CHICKEN_VECU8_H
#ifndef PROTOTYPE1_L1_CODEGEN_BOOTSTRAP_USE_CHICKEN_VECU8
#error "Use chicken_VecU8.h only during the very first l1 bootstrap stage"
@ -95,3 +96,5 @@ void VecU8_append_span(VecU8* self, SpanU8 b) {
memcpy(self->buf + self->len, b.data, b.len);
self->len = new_length;
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_CORE_INT_PRIMITIVES_H
#define PROTOTYPE1_SRC_CORE_INT_PRIMITIVES_H
#include <stdint.h>
#include <stddef.h>
@ -25,3 +26,5 @@ int_minmax_function_Definition(U64)
int_minmax_function_Definition(S64)
int_minmax_function_Definition(float)
int_minmax_function_Definition(double)
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_core_uint_segments_h
#define prototype1_src_l1_core_uint_segments_h
#include "int_primitives.h"
@ -11,3 +12,13 @@ typedef struct{
U32 start;
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

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_CORE_UTIL_H
#define PROTOTYPE1_SRC_CORE_UTIL_H
#include <stdio.h>
#include <stdlib.h>
@ -92,3 +93,5 @@ typedef struct{
} KVPU64ToU64;
#define check(expr) if (!(expr)) { abortf("Assertion failed at %s : %d : " #expr "\n", __FILE__, __LINE__); }
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE_1_SRC_L1_MARIE_GEOM_ALG_UTILS_H
#define PROTOTYPE_1_SRC_L1_MARIE_GEOM_ALG_UTILS_H
#include <stdbool.h>
#include <string.h>
@ -24,7 +25,7 @@ _Static_assert(FLT_MIN_EXP == -125, "Float is not binary32");
uint32_t marie_pun_float2u32(float f) {
uint32_t u;
memcpy(&u, &f, sizeof(uint32_t));
memcpy(&u, &f, sizeof u);
return u;
}
@ -36,6 +37,60 @@ bool marie_same_dir3(float A0, float A1, float A2, float B) {
return A0 == 0 || A1 == 0 || A2 == 0 || (diff & 0x80000000u) == 0;
}
float marie_surface(vec2 vi, vec2 vj, vec2 u) {
return u.x * (vi.y - vj.y) + u.y * (vj.x - vi.x) + (vi.x * vj.y - vj.x * vi.y);
}
typedef vec4 MarieVertAttr;
typedef struct {
vec2 pos;
MarieVertAttr attr;
} MariePlaneVertAttr;
typedef struct {
vec2 v0;
vec2 v1;
vec2 v2;
} MarieTriangle;
MarieTriangle MarieTriangle_mat3x2_mul_pos(MarieTriangle self, mat3x2 trop) {
return (MarieTriangle){
.v0 = mat3x2_mul_vec3(trop, vec2_and_one(self.v0)),
.v1 = mat3x2_mul_vec3(trop, vec2_and_one(self.v1)),
.v2 = mat3x2_mul_vec3(trop, vec2_and_one(self.v2))};
}
#include "../../../gen/l1/eve/marie/VecMarieTriangle.h"
typedef struct {
MariePlaneVertAttr v0;
MariePlaneVertAttr v1;
MariePlaneVertAttr v2;
} MarieTriangleAttr;
MarieTriangleAttr MarieTriangle_goto_nat_cords_pres_par(MarieTriangle self, mat3x2 trop) {
return (MarieTriangleAttr){
{mat3x2_mul_vec3(trop, vec2_and_one(self.v0)), {self.v0.x, self.v0.y, 0, 0}},
{mat3x2_mul_vec3(trop, vec2_and_one(self.v1)), {self.v1.x, self.v1.y, 0, 0}},
{mat3x2_mul_vec3(trop, vec2_and_one(self.v2)), {self.v2.x, self.v2.y, 0, 0}},
};
}
#include "../../../gen/l1/eve/marie/VecMarieTriangleAttr.h"
vec2 marie_intersect_lines(vec2 A1, vec2 B1, vec2 A2, vec2 B2) {
vec2 alpha = vec2_minus_vec2(B1, A1);
vec2 beta = vec2_minus_vec2(A2, B2);
vec2 gamma = vec2_minus_vec2(A2, A1);
float det_alpha_beta = alpha.x * beta.y - alpha.y * beta.x;
float det_gamma_beta = gamma.x * beta.y - gamma.y * beta.x;
float t1 = det_gamma_beta / det_alpha_beta;
return vec2_add_vec2(A1, vec2_mul_scal(alpha, t1));
}
float marie_clamp_float(float a, float l, float r) {
return (a < l) ? l : ((a <= r) ? a : r);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_system_creating_child_proc_h
#define prototype1_src_l1_system_creating_child_proc_h
#include "../core/util.h"
@ -12,3 +13,6 @@ void calling_system_func_nofail(const char* command) {
abortf("Error: command terminated abnormally\n");
}
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_SYSTEM_FILEIO_H
#define PROTOTYPE1_SRC_SYSTEM_FILEIO_H
#include "../core/VecU8_as_str.h"
@ -15,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));
}
@ -39,22 +46,29 @@ 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");
}
VecU8_drop(path);
fclose(fd);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_SYSTEM_FSMANIP_H
#define PROTOTYPE1_SRC_L1_SYSTEM_FSMANIP_H
/* For posix */
#include <sys/stat.h>
@ -11,3 +12,6 @@ void mkdir_nofail(const char* filename) {
if (ret < 0 && errno != EEXIST)
abortf("Unable to create directory %s\n", filename);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_SYSTEM_PTHREAD_H
#define PROTOTYPE1_SRC_L1_SYSTEM_PTHREAD_H
#include "../core/util.h"
#include <pthread.h>
@ -26,3 +27,6 @@ void safe_pthread_mutex_destroy(pthread_mutex_t* mut) {
void safe_pthread_join(pthread_t thread) {
pthread_join(thread, NULL);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_SYSTEM_SHARED_MEMORY_H
#define PROTOTYPE1_SRC_L1_SYSTEM_SHARED_MEMORY_H
#include <fcntl.h>
#include <sys/mman.h>
@ -32,3 +33,5 @@ static int allocate_shm_file(size_t size) {
}
return fd;
}
#endif

View File

@ -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;

View File

@ -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;
}

View File

@ -1,44 +0,0 @@
#pragma once
#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
});
}

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_5_anne_l1_5_templ_very_base_h
#define prototype1_src_l1_5_anne_l1_5_templ_very_base_h
#include "../codegen/buff_rbtree_set_map_template_inst.h"
#include "../codegen/rbtree_set_map_template_inst.h"
@ -16,14 +17,9 @@ void generate_l1_5_template_instantiation_for_base_types(){
generate_rbtree_Set_templ_inst_guarded_header(l, ns, cstr(""), (set_instantiation_op){
.T = cstr("S64"), .t_integer = true }, true);
// todo: move vector declaration HERE (might wait)
// todo: move vector declaration HERE
generate_buf_rbtree_Map_templ_inst_guarded_header(l, ns, cstr("#include \"../../gen/l1/VecKVPU64ToU64.h\"\n"),
(map_instantiation_op){.K = cstr("U64"), .k_integer = true, .V = cstr("U64"), .v_integer = true,});
// todo: implement recursion for heap-allocated red-black tree, to make json dictionary clonable
generate_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
.K = cstr("VecU8"), .k_clonable = true,
.V = cstr("Json"), .v_clonable = false,
.skip_declaration_gen = true,
}, false, true);
}
#endif

View File

@ -1,32 +1,11 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_5_ANNE_LIZA_H
#define PROTOTYPE1_SRC_L1_5_ANNE_LIZA_H
#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

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_5_anne_lucy_h
#define prototype1_src_l1_5_anne_lucy_h
#include "../codegen/buff_rbtree_set_map_template_inst.h"
@ -8,6 +9,8 @@ void generate_l1_5_lucy_headers(){
generate_buf_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
.K = cstr("U32"), .k_integer = true, .V = cstr("LucyStoredGlyph"), .v_primitive = true});
generate_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
.K = cstr("U32"), .k_integer = true, .V = cstr("LucyFaceFixedSize")}, true, false);
.K = cstr("U32"), .k_integer = true, .V = cstr("LucyFaceFixedSize")}, true);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_5_anne_margaret_h
#define prototype1_src_l1_5_anne_margaret_h
#include "../codegen/buff_rbtree_set_map_template_inst.h"
#include "../codegen/rbtree_set_map_template_inst.h"
@ -23,3 +24,5 @@ void generate_l1_5_template_instantiations_for_margaret(){
.alternative_comp_set_name_embed = cstr("Len"),
});
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_5_CODEGEN_ALL_SET_MAP_TEMPL_UTIL_INST_H
#define PROTOTYPE1_SRC_L1_5_CODEGEN_ALL_SET_MAP_TEMPL_UTIL_INST_H
#include "../../l1/codegen/util_template_inst.h"
@ -45,7 +46,6 @@ typedef struct {
bool at, mat;
bool pop, pop_substitute;
bool skip_declaration_gen;
} map_instantiation_op;
void map_instantiation_op_fix(map_instantiation_op* self){
@ -67,7 +67,7 @@ void map_instantiation_op_fix(map_instantiation_op* self){
/* --- Sharing is caring --- */
/* Assuming A and B are passed as intended */
/* Assuming A nd B are passed as intended */
NODISCARD VecU8 codegen_rbtree_map__less(map_instantiation_op op, VecU8 A, VecU8 B){
if (op.guest_data_T.len > 0) {
assert(op.alternative_less.len > 0);
@ -77,7 +77,7 @@ NODISCARD VecU8 codegen_rbtree_map__less(map_instantiation_op op, VecU8 A, VecU8
return VecU8_fmt("%s(%v, %v)", op.alternative_less, A, B);
if (op.k_integer)
return VecU8_fmt("%v < %v", A, B);
return VecU8_fmt("%s_less_%s(%v, %v)", op.K, op.K, A, B);
return VecU8_fmt("%s_less_%s(%v %v)", op.K, op.K, A, B);
}
NODISCARD VecU8 codegen_rbtree_map__exp_passing_key_val(map_instantiation_op op){
@ -96,3 +96,6 @@ NODISCARD VecU8 codegen_rbtree_map__taking_ref_k_argument(map_instantiation_op o
NODISCARD VecU8 codegen_rbtree_map__taking_t_argument(map_instantiation_op op){
return op.V.len > 0 ? VecU8_fmt("%s key, %s value", op.K, op.V) : VecU8_fmt("%s key", op.K);
}
#endif

View File

@ -1,5 +1,6 @@
#pragma once
// todo: refactor (with VecU8_append_fmt)
#ifndef PROTOTYPE1_SRC_L1_5_CODEGEN_RB_TREE_SET_MAP_TEMPLATE_INST_H
#define PROTOTYPE1_SRC_L1_5_CODEGEN_RB_TREE_SET_MAP_TEMPLATE_INST_H
#include "all_set_map_templ_util_inst.h"
/* Assuming A nd B are passed as intended */
@ -17,65 +18,61 @@ NODISCARD VecU8 codegen_buf_rbtree_map__exp_passing_cur_key(map_instantiation_op
void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 TT
){
if (!op.skip_declaration_gen) {
VecU8_append_vec(res, VecU8_fmt("typedef struct %s %s;\n\n", set, set));
}
VecU8_append_fmt(res,
"struct %s{\n"
VecU8_append_vec(res, VecU8_fmt(
"typedef struct {\n"
SPACE "VecBufRBTreeNode tree;\n"
SPACE "U64 root;\n"
SPACE "Vec%s el;\n"
"%v"
"};\n\n",
set, TT, op.guest_data_T.len > 0 ? VecU8_fmt(SPACE "%s guest;\n", op.guest_data_T) : vcstr(""));
"} %s;\n\n",
TT, op.guest_data_T.len > 0 ? VecU8_fmt(SPACE "%s guest;\n", op.guest_data_T) : vcstr(""), set));
if (op.guest_data_T.len > 0) {
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"NODISCARD %s %s_new(%s guest) {\n" /* set, set, op.guest_data_T */
SPACE "return (%s){.tree = VecBufRBTreeNode_new_zeroinit(1), .root = 0, .el = Vec%s_new(), .guest = guest};\n" /* set, TT */
"}\n\n",
set, set, op.guest_data_T,
set, TT);
VecU8_append_fmt(res,
set, TT));
VecU8_append_vec(res, VecU8_fmt(
"NODISCARD %s %s_new_reserved(%s guest, size_t size) {\n" /* set, set, op.guest_data_T */
SPACE "return (%s){.tree = (VecBufRBTreeNode){\n" /* set */
SPACE SPACE ".buf = (BufRBTreeNode*)safe_calloc(size + 1, sizeof(BufRBTreeNode)), .len = 1, .capacity = size + 1},\n"
SPACE SPACE ".root = 0, .el = Vec%s_new_reserved(size), .guest = guest};\n" /* TT */
"}\n\n",
set, set, op.guest_data_T,
set, TT);
set, TT));
} else {
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"NODISCARD %s %s_new() {\n" /* set, set */
SPACE "return (%s){.tree = VecBufRBTreeNode_new_zeroinit(1), .root = 0, .el = Vec%s_new()};\n" /* set, TT */
"}\n\n",
set, set,
set, TT);
VecU8_append_fmt(res,
set, TT));
VecU8_append_vec(res, VecU8_fmt(
"NODISCARD %s %s_new_reserved(size_t size) {\n" /* set, set */
SPACE "return (%s){.tree = (VecBufRBTreeNode){\n"
SPACE SPACE ".buf = (BufRBTreeNode*)safe_calloc(size + 1, sizeof(BufRBTreeNode)), .len = 1, .capacity = size + 1},\n"
SPACE SPACE ".root = 0, .el = Vec%s_new_reserved(size)};\n" /* set, TT */
"}\n\n",
set, set,
set, TT);
set, TT));
}
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"void %s_drop(%s self) {\n" /* set, set */
SPACE "VecBufRBTreeNode_drop(self.tree);\n"
SPACE "Vec%s_drop(self.el);\n" /* TT */
"}\n\n", set, set, TT);
"}\n\n", set, set, TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"void %s_sink(%s* self) {\n" /* set, set */
SPACE "self->tree.len = 1;\n"
SPACE "self->tree.buf[0] = (BufRBTreeNode){0};\n"
SPACE "Vec%s_sink(&self->el, 0);\n" /* TT */
"}\n\n", set, set, TT);
"}\n\n", set, set, TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find(const %s* self, %v key) {\n" /* set, set, taking_ref_k_argument */
SPACE "U64 cur = self->root;\n"
SPACE "while (cur != 0) {\n"
@ -90,21 +87,21 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
"}\n\n",
set, set, codegen_rbtree_map__taking_ref_k_argument(op),
codegen_rbtree_map__less(op, vcstr("key"), codegen_buf_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key")));
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key"))));
if (op.k_clonable && op.v_clonable) {
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"NODISCARD %s %s_clone(const %s* self){\n" /* set, set, set */
SPACE "return (%s){.tree = VecBufRBTreeNode_clone(&self->tree), .root = self->root,\n" /* set */
SPACE SPACE ".el = Vec%s_clone(&self->el)%s};\n" /* TT, whether to clone guest or no */
"}\n\n",
set, set, set,
set,
TT, op.guest_data_T.len > 0 ? cstr(", .guest = self->guest") : cstr(""));
TT, op.guest_data_T.len > 0 ? cstr(", .guest = self->guest") : cstr("")));
}
// todo: move to common code (update: I no longer care)
VecU8_append_fmt(res,
// todo: move to common code
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find_next(const %s* self, U64 x){\n"
SPACE "assert(x != 0 && x < self->tree.len);\n"
SPACE "if (self->tree.buf[x].right != 0)\n"
@ -117,10 +114,10 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
SPACE SPACE SPACE "return p;\n"
SPACE SPACE "x = p;\n"
SPACE "}\n"
"}\n\n", set, set);
"}\n\n", set, set));
// todo: move to comon code (core/buff_rb_tree_node.h)
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find_prev(const %s* self, U64 x){\n"
SPACE "assert(x != 0 && x < self->tree.len);\n"
SPACE "if (self->tree.buf[x].left != 0)\n"
@ -133,19 +130,19 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
SPACE SPACE SPACE "return p;\n"
SPACE SPACE "x = p;\n"
SPACE "}\n"
"}\n\n", set, set);
"}\n\n", set, set));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find_min(const %s* self) {\n"
SPACE "return self->root != 0 ? BufRBTree_minimum_in_subtree(self->tree.buf, self->root) : 0;\n"
"}\n\n", set, set);
"}\n\n", set, set));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find_max(const %s* self) {\n"
SPACE "return self->root != 0 ? BufRBTree_maximum_in_subtree(self->tree.buf, self->root) : 0;\n"
"}\n\n", set, set);
"}\n\n", set, set));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find_max_less(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */
SPACE "U64 last_less = 0;\n"
SPACE "U64 cur = self->root;\n"
@ -168,9 +165,9 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
"}\n\n",
set, set, codegen_rbtree_map__taking_ref_k_argument(op),
codegen_rbtree_map__less(op, vcstr("key"), codegen_buf_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key")));
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key"))));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find_max_less_or_eq(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */
SPACE "U64 last_less = 0;\n"
SPACE "U64 cur = self->root;\n"
@ -188,10 +185,10 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
"}\n\n",
set, set, codegen_rbtree_map__taking_ref_k_argument(op),
codegen_rbtree_map__less(op, vcstr("key"), codegen_buf_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key")));
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key"))));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find_min_grtr(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */
SPACE "U64 last_grtr = 0;\n"
SPACE "U64 cur = self->root;\n"
@ -214,10 +211,10 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
"}\n\n",
set, set, codegen_rbtree_map__taking_ref_k_argument(op),
codegen_rbtree_map__less(op, vcstr("key"), codegen_buf_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key")));
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key"))));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"U64 %s_find_min_grtr_or_eq(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */
SPACE "U64 last_grtr = 0;\n"
SPACE "U64 cur = self->root;\n"
@ -235,13 +232,13 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
"}\n\n",
set, set, codegen_rbtree_map__taking_ref_k_argument(op),
codegen_rbtree_map__less(op, vcstr("key"), codegen_buf_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key")));
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key"))));
VecU8 line_that_appends_new_el_to_el_vec = op.V.len > 0 ?
VecU8_fmt("VecKVP%sTo%s_append(&self->el, (KVP%sTo%s){.key = key, .value = value});", op.K, op.V, op.K, op.V) :
VecU8_fmt("Vec%s_append(&self->el, key);", op.K);
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
/* This method is unsafe. Arguments key, value will be taken if 0 is returned,
* or left on their place if not-0 is returned */
"/* UNSAFE */\n"
@ -250,7 +247,7 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
SPACE SPACE "assert(self->tree.len == 1);\n"
SPACE SPACE "VecBufRBTreeNode_append(&self->tree, (BufRBTreeNode){.color = RBTree_black});\n"
SPACE SPACE "self->root = 1;\n"
SPACE SPACE "%r\n" /* line_that_appends_new_el_to_el_vec */
SPACE SPACE "%s\n" /* line_that_appends_new_el_to_el_vec */
SPACE SPACE "return 0;\n"
SPACE "}\n"
SPACE "U64 cur = self->root;\n"
@ -263,7 +260,7 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
SPACE SPACE SPACE SPACE "VecBufRBTreeNode_append(&self->tree, (BufRBTreeNode){.parent = cur, .color = RBTree_red});\n"
SPACE SPACE SPACE SPACE "self->tree.buf[cur].left = n;\n"
SPACE SPACE SPACE SPACE "BufRBTree_fix_after_insert(self->tree.buf, &self->root, n);\n"
SPACE SPACE SPACE SPACE "%r\n" /* line_that_appends_new_el_to_el_vec */
SPACE SPACE SPACE SPACE "%s\n" /* line_that_appends_new_el_to_el_vec */
SPACE SPACE SPACE SPACE "return 0;\n"
SPACE SPACE SPACE "}\n"
SPACE SPACE "} else if (%v) {\n" /* el[cur] < key */
@ -274,7 +271,7 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
SPACE SPACE SPACE SPACE "VecBufRBTreeNode_append(&self->tree, (BufRBTreeNode){.parent = cur, .color = RBTree_red});\n"
SPACE SPACE SPACE SPACE "self->tree.buf[cur].right = n;\n"
SPACE SPACE SPACE SPACE "BufRBTree_fix_after_insert(self->tree.buf, &self->root, n);\n"
SPACE SPACE SPACE SPACE "%r\n" /* line_that_appends_new_el_to_el_vec */
SPACE SPACE SPACE SPACE "%s\n" /* line_that_appends_new_el_to_el_vec */
SPACE SPACE SPACE SPACE "return 0;\n"
SPACE SPACE SPACE "}\n"
SPACE SPACE "} else {\n"
@ -283,11 +280,11 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
SPACE "}\n"
"}\n\n",
set, set, codegen_rbtree_map__taking_t_argument(op),
line_that_appends_new_el_to_el_vec,
VecU8_to_span(&line_that_appends_new_el_to_el_vec),
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_key_val(op), codegen_buf_rbtree_map__exp_passing_cur_key(op)),
line_that_appends_new_el_to_el_vec,
VecU8_to_span(&line_that_appends_new_el_to_el_vec),
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), codegen_rbtree_map__exp_passing_key_val(op)),
line_that_appends_new_el_to_el_vec);
VecU8_to_span(&line_that_appends_new_el_to_el_vec)));
VecU8_drop(line_that_appends_new_el_to_el_vec);
// VecU8_append_vec(res, VecU8_fmt(
@ -328,7 +325,7 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
// "}\n\n",
// set, set));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"bool %s_insert(%s* self, %v) {\n" /* set, set, taking_t_argument */
SPACE "U64 col = %s_try_insert(self, key" "%s" ");\n" /* set, "" /, value */
SPACE "if (col == 0)\n"
@ -339,12 +336,12 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
set, set, codegen_rbtree_map__taking_t_argument(op),
set, op.V.len > 0 ? cstr(", value") : cstr(""),
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(value);\n", op.V));
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(value);\n", op.V)));
// todo: write _erase_by_iter method
// todo: rewrite _erase using _erase_by_it
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"bool %s_erase(%s* self, %v key) {\n" /* set, set, taking_ref_k_argument */
SPACE "U64 v = %s_find(self, key);\n" /* set */
SPACE "if (v == 0)\n"
@ -359,7 +356,7 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
set, set, codegen_rbtree_map__taking_ref_k_argument(op), set,
op.k_primitive ? vcstr("") : VecU8_fmt(
SPACE "%s_drop(self->el.buf[v - 1]%s);\n", op.K, op.V.len > 0 ? cstr(".key") : cstr("")),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(self->el.buf[v - 1].value);\n", op.V));
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(self->el.buf[v - 1].value);\n", op.V)));
}
NODISCARD VecU8 codegen_buf_rbtree_map__option_returned_ref_v(map_instantiation_op op, bool mut){
@ -386,7 +383,7 @@ NODISCARD VecU8 codegen_buf_rbtree_map__none_ref_v(map_instantiation_op op, bool
}
void codegen_append_buf_rbtree_map__method_at(VecU8* res, map_instantiation_op op, SpanU8 set, bool mut){
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"%v %s_%s(%s%s* self, %v key) {\n" /* option_returned_ref_t, set, mat/at, e/const, set, taking_ref_t_argument */
SPACE "U64 cur = self->root;\n"
SPACE "while (cur != 0) {\n"
@ -406,7 +403,8 @@ void codegen_append_buf_rbtree_map__method_at(VecU8* res, map_instantiation_op o
codegen_rbtree_map__less(op, vcstr("key"), codegen_buf_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_buf_rbtree_map__exp_passing_cur_key(op), vcstr("key")),
codegen_buf_rbtree_map__some_ref_v(op, mut),
codegen_buf_rbtree_map__none_ref_v(op, mut));
codegen_buf_rbtree_map__none_ref_v(op, mut)
));
}
NODISCARD VecU8 get_name_of_buf_rbtree_set_structure(set_instantiation_op op){
@ -421,7 +419,8 @@ NODISCARD VecU8 get_name_of_buf_rbtree_set_structure(set_instantiation_op op){
NODISCARD VecU8 generate_buf_rbtree_Set_template_instantiation(set_instantiation_op op){
set_instantiation_op_fix(&op);
VecU8 res = VecU8_new();
VecU8 set = get_name_of_buf_rbtree_set_structure(op);
VecU8 g_set = get_name_of_buf_rbtree_set_structure(op);
SpanU8 set = VecU8_to_span(&g_set);
map_instantiation_op map_op = {.K = op.T,
.k_integer = op.t_integer, .k_primitive = op.t_primitive, .k_clonable = op.t_clonable,
@ -430,16 +429,16 @@ NODISCARD VecU8 generate_buf_rbtree_Set_template_instantiation(set_instantiation
.alternative_comp_map_name_embed = op.alternative_comp_set_name_embed, .guest_data_T = op.guest_data_T,
};
codegen_append_buff_rbtree_map__structure_and_simplest_methods(&res, map_op, VecU8_to_span(&set), op.T);
codegen_append_buff_rbtree_map__structure_and_simplest_methods(&res, map_op, set, op.T);
VecU8_append_fmt(&res,
"const %s* %r_at_iter(const %r* self, U64 it) {\n" /* op.T, set, set */
VecU8_append_vec(&res, VecU8_fmt(
"const %s* %s_at_iter(const %s* self, U64 it) {\n" /* op.T, set, set */
SPACE "assert(0 < it && it < self->tree.len);\n"
SPACE "return &self->el.buf[it - 1];\n"
"}\n\n",
op.T, set, set);
op.T, set, set));
VecU8_drop(set);
VecU8_drop(g_set);
return res;
}
@ -462,7 +461,7 @@ void generate_buf_rbtree_Set_templ_inst_guarded_header(
void codegen_append_buff_rbtree_map__method_at_iter(VecU8* res, map_instantiation_op op, SpanU8 set, bool mut){
assert(op.V.len > 0);
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"void %s_%s(%s%s* self, U64 it, %v* ret_key, %v* ret_value) {\n" /* set, method name, self access modifier, set, key ret ptr, value ret ptr */
SPACE "assert(0 < it && it < self->tree.len);\n"
SPACE "*ret_key = %s" "self->el.buf[it - 1].key;\n" /* epsilon / ampersand */
@ -472,7 +471,7 @@ void codegen_append_buff_rbtree_map__method_at_iter(VecU8* res, map_instantiatio
op.k_integer ? VecU8_from_span(op.K) : VecU8_fmt("const %s*", op.K),
mut ? VecU8_fmt("%s*", op.V) : (op.v_integer ? VecU8_from_span(op.V) : VecU8_fmt("const %s*", op.V)),
op.k_integer ? cstr("") : cstr("&"), (op.v_integer && !mut) ? cstr("") : cstr("&"));
op.k_integer ? cstr("") : cstr("&"), (op.v_integer && !mut) ? cstr("") : cstr("&")));
}
NODISCARD VecU8 get_name_of_buf_rbtree_map_structure(map_instantiation_op op){
@ -543,7 +542,6 @@ NODISCARD VecU8 generate_buf_rbtree_Map_template_instantiation(map_instantiation
codegen_append_buff_rbtree_map__method_at_iter(&res, op, map, false);
codegen_append_buff_rbtree_map__method_at_iter(&res, op, map, true);
VecU8_drop(map_g);
return res;
}
@ -560,3 +558,5 @@ void generate_buf_rbtree_Map_templ_inst_guarded_header(
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, all_dependencies,
generate_buf_rbtree_Map_template_instantiation(op), get_name_of_buf_rbtree_map_structure(op));
}
#endif

View File

@ -1,81 +1,82 @@
#pragma once
// todo: refactor (with VecU8_append_fmt)
#ifndef prototype1_src_l1_5_codegen_rbtree_set_map_template_inst_h
#define prototype1_src_l1_5_codegen_rbtree_set_map_template_inst_h
#include "all_set_map_templ_util_inst.h"
NODISCARD VecU8 generate_rbtree__node_struct_name(map_instantiation_op op){
NODISCARD VecU8 codegen_rbtree__node_struct_name(map_instantiation_op op){
return (op.V.len > 0) ? VecU8_fmt("RBTreeNode_KVP%sTo%s", op.K, op.V) : VecU8_fmt("RBTreeNode_%s", op.K);
}
void codegen_append_rbtree__node_structure(VecU8* res, map_instantiation_op op){
NODISCARD VecU8 codegen_rbtree__node_structure(map_instantiation_op op){
map_instantiation_op_fix(&op);
VecU8_append_fmt(res,
VecU8 node_g = codegen_rbtree__node_struct_name(op);
SpanU8 node = VecU8_to_span(&node_g);
VecU8 res = VecU8_fmt(
"typedef struct {\n"
SPACE "RBTreeNode base;\n"
SPACE "%s key;\n" /* op.K*/
"%v" /* "" / op.V value; */
"} %v;\n\n", /* node */
"} %s;\n\n", /* node */
op.K, op.V.len > 0 ? VecU8_fmt(SPACE "%s value;\n", op.V) : vcstr(""),
generate_rbtree__node_struct_name(op));
node);
VecU8_drop(node_g);
return res;
}
NODISCARD VecU8 codegen_rbtree_map__exp_passing_cur_key(map_instantiation_op op){
return VecU8_fmt("%s" "((%v*)cur)->key", op.k_integer ? cstr("") : cstr("&"), generate_rbtree__node_struct_name(op));
return VecU8_fmt("%s" "((%v*)cur)->key", op.k_integer ? cstr("") : cstr("&"), codegen_rbtree__node_struct_name(op));
}
void codegen_append_rbtree_map__structure(VecU8* res, map_instantiation_op op, SpanU8 set){
if (!op.skip_declaration_gen) {
VecU8_append_fmt(res, "typedef struct %s %s;\n\n", set, set);
}
VecU8_append_fmt(res,
"struct %s {\n"
void codegen_append_rbtree_map__structure_and_simplest_methods(
VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 TT
){
VecU8_append_vec(res, VecU8_fmt(
"typedef struct {\n"
SPACE "RBTreeNode* root;\n"
SPACE "RBTreeNode* NIL;\n"
"%v" /* "" / guest field */
"};\n\n",
set,
op.guest_data_T.len == 0 ? vcstr("") : VecU8_fmt("%s guest;\n", op.guest_data_T));
}
"} %s;\n\n",
op.guest_data_T.len == 0 ? vcstr("") : VecU8_fmt("%s guest;\n", op.guest_data_T),
set));
void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 TT){
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"NODISCARD %s %s_new(" "%v" ") {\n" /* set, set, "" / GT guest */
/* Only color field initialization is important (should be 0) */
SPACE "RBTreeNode* NIL = (RBTreeNode*)safe_calloc(1, sizeof(RBTreeNode));\n"
SPACE "return (%s){.root = NIL, .NIL = NIL" "%s" "};\n" /* set, "" / , .guest = guest */
"}\n\n",
set, set, op.guest_data_T.len == 0 ? vcstr("") : VecU8_fmt("%s guest", op.guest_data_T),
set, op.guest_data_T.len == 0 ? cstr("") : cstr(", .guest = guest"));
set, op.guest_data_T.len == 0 ? cstr("") : cstr(", .guest = guest")));
// todo: figure out mutability restrictions crrp later (update: it is finally time to do that. But I can't bother)
VecU8_append_fmt(res,
// todo: figure out mutability restrictions crrp later
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find_min(const %s* self) {\n" /* TT, set, set */
SPACE "if (self->root == self->NIL)\n"
SPACE SPACE "return NULL;\n"
SPACE "return (RBTreeNode_%s*)RBTreeNode_minimum_in_subtree(self->root, self->NIL);\n" /* TT */
"}\n\n", TT, set, set, TT);
"}\n\n", TT, set, set, TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find_max(const %s* self) {\n" /* TT, set, set */
SPACE "if (self->root == self->NIL)\n"
SPACE SPACE "return NULL;\n"
SPACE "return (RBTreeNode_%s*)RBTreeNode_maximum_in_subtree(self->root, self->NIL);\n" /* TT */
"}\n\n", TT, set, set, TT);
"}\n\n", TT, set, set, TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find_next(const %s* self, RBTreeNode_%s* x){\n" /* TT, set, set, TT */
SPACE "return (RBTreeNode_%s *)RBTreeNode_find_next((RBTreeNode*)x, self->NIL);\n" /* TT */
"}\n\n", TT, set, set, TT, TT);
"}\n\n", TT, set, set, TT, TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find_prev(const %s* self, RBTreeNode_%s* x){\n" /* TT, set, set, TT */
SPACE "return (RBTreeNode_%s *)RBTreeNode_find_prev((RBTreeNode*)x, self->NIL);\n" /* TT */
"}\n\n", TT, set, set, TT, TT);
"}\n\n", TT, set, set, TT, TT));
/* Here we read and write something to ->left, ->right field of NIL sentinel node.
* These fields are correct pointers (NULL), so everything is ok */
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"void %s_drop(%s self){\n" /* set, set */
SPACE "RBTreeNode* cur = self.root;\n"
SPACE "while (cur != self.NIL){\n"
@ -99,9 +100,10 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
SPACE "free(self.NIL);\n"
"}\n\n", set, set,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_%s*)cur)->key);\n", op.K, TT),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_%s*)cur)->value);\n", op.V, TT));
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_%s*)cur)->value);\n", op.V, TT)
));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_k_argument */
SPACE "RBTreeNode* cur = self->root;\n"
SPACE "while (cur != self->NIL) {\n"
@ -118,9 +120,9 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
TT, set, set, codegen_rbtree_map__taking_ref_k_argument(op),
codegen_rbtree_map__less(op, vcstr("key"), codegen_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), vcstr("key")),
TT);
TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find_max_less(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_t_argument */
SPACE "RBTreeNode_%s* last_less = NULL;\n" /* TT */
SPACE "RBTreeNode* cur = self->root;\n"
@ -144,9 +146,9 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
TT, set, set, codegen_rbtree_map__taking_ref_k_argument(op), TT,
codegen_rbtree_map__less(op, vcstr("key"), codegen_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), vcstr("key")),
TT, TT);
TT, TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find_max_less_or_eq(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_t_argument */
SPACE "RBTreeNode_%s* last_less = NULL;\n" /* TT */
SPACE "RBTreeNode* cur = self->root;\n"
@ -165,9 +167,9 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
TT, set, set, codegen_rbtree_map__taking_ref_k_argument(op), TT,
codegen_rbtree_map__less(op, vcstr("key"), codegen_rbtree_map__exp_passing_cur_key(op)),
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), vcstr("key")),
TT, TT);
TT, TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find_min_grtr(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_t_argument */
SPACE "RBTreeNode_%s* last_grtr = NULL;\n" /* TT */
SPACE "RBTreeNode* cur = self->root;\n"
@ -192,10 +194,10 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
codegen_rbtree_map__less(op, vcstr("key"), codegen_rbtree_map__exp_passing_cur_key(op)),
TT,
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), vcstr("key")),
TT);
TT));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"RBTreeNode_%s* %s_find_min_grtr_or_eq(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_t_argument */
SPACE "RBTreeNode_%s* last_grtr = NULL;\n" /* TT */
SPACE "RBTreeNode* cur = self->root;\n"
@ -215,10 +217,10 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
codegen_rbtree_map__less(op, vcstr("key"), codegen_rbtree_map__exp_passing_cur_key(op)),
TT,
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), vcstr("key")),
TT);
TT));
// todo: implement it like i deed in BufRBTree
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
/* This method is unsafe. Arguments key, value will be taken if 0 is returned,
* or left on their place if not-0 is returned */
"/* UNSAFE */\n"
@ -251,9 +253,9 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), codegen_rbtree_map__exp_passing_key_val(op)),
TT,
TT, TT, TT,
TT, op.V.len == 0 ? cstr("") : cstr(", .value = value"));
TT, op.V.len == 0 ? cstr("") : cstr(", .value = value")));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"bool %s_insert(%s* self, %v){\n" /* set, set, taking_t_argument */
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key" "%s" ");\n" /* TT, set, "" /, value */
SPACE "if (col == NULL)\n"
@ -264,9 +266,9 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
set, set, codegen_rbtree_map__taking_t_argument(op),
TT, set, op.V.len > 0 ? cstr(", value") : cstr(""),
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(value);\n", op.V));
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(value);\n", op.V)));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"void %s_erase_by_iter(%s* self, RBTreeNode_%s* it) {\n" /* set, set, TT */
SPACE "assert(it != NULL);\n"
"%v" /* "" / op.K_drop(it->key) */
@ -276,9 +278,9 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
"}\n\n",
set, set, TT,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(it->key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(it->value);\n", op.V));
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(it->value);\n", op.V)));
VecU8_append_fmt(res,
VecU8_append_vec(res, VecU8_fmt(
"bool %s_erase(%s* self, %v key) {\n" /* set, set, taking_ref_k_argument */
SPACE "RBTreeNode_%s* v = %s_find(self, key);\n" /* TT, set */
SPACE "if (v == NULL)\n"
@ -287,13 +289,7 @@ void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_o
SPACE "return true;\n"
"}\n\n",
set, set, codegen_rbtree_map__taking_ref_k_argument(op),
TT, set, set);
VecU8_append_fmt(res,
"bool %s_empty(const %s* self){\n" /* set, set */
SPACE "return self->root == self->NIL;\n"
"}\n\n",
set, set);
TT, set, set));
}
@ -315,9 +311,8 @@ NODISCARD VecU8 generate_rbtree_Set_template_instantiation(set_instantiation_op
VecU8 res = VecU8_new();
VecU8 set_g = get_name_of_rbtree_set_structure(op);
if (generate_node_struct)
codegen_append_rbtree__node_structure(&res, map_op);
codegen_append_rbtree_map__structure(&res, map_op, VecU8_to_span(&set_g));
codegen_append_rbtree_map__simplest_methods(&res, map_op, VecU8_to_span(&set_g), op.T);
VecU8_append_vec(&res, codegen_rbtree__node_structure(map_op));
codegen_append_rbtree_map__structure_and_simplest_methods(&res, map_op, VecU8_to_span(&set_g), op.T);
VecU8_drop(set_g);
return res;
}
@ -345,102 +340,83 @@ NODISCARD VecU8 get_name_of_rbtree_map_structure(map_instantiation_op op){
return VecU8_fmt("RBTree_Map%sTo%s", op.K, op.V);
}
NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op op, bool generate_node_struct,
bool generate_map_struct, bool generate_methods){
NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op op, bool generate_node_struct){
map_instantiation_op_fix(&op);
VecU8 res = VecU8_new();
VecU8 map = get_name_of_rbtree_map_structure(op);
VecU8 kvp = VecU8_fmt("KVP%sTo%s", op.K, op.V);
VecU8 map_g = get_name_of_rbtree_map_structure(op);
SpanU8 map = VecU8_to_span(&map_g);
VecU8 kvp_g = VecU8_fmt("KVP%sTo%s", op.K, op.V);
SpanU8 kvp = VecU8_to_span(&kvp_g);
if (generate_node_struct)
codegen_append_rbtree__node_structure(&res, op);
if (generate_map_struct)
codegen_append_rbtree_map__structure(&res, op, VecU8_to_span(&map));
if (generate_methods) {
codegen_append_rbtree_map__simplest_methods(&res, op, VecU8_to_span(&map), VecU8_to_span(&kvp));
VecU8_append_vec(&res, codegen_rbtree__node_structure(op));
codegen_append_rbtree_map__structure_and_simplest_methods(&res, op, map, kvp);
if (op.pop_substitute) {
VecU8_append_fmt(&res,
"%s" "Option%s %r_pop_substitute(%r* self, %s key, %s value) {\n" /* "" / NODISCARD , op.V, map, map, op.K, op.V */
/* Using unsafe method with conditional ownership transfer */
SPACE "RBTreeNode_%r* col = %r_try_insert(self, key, value);\n" /* kvp, map */
SPACE "if (col == NULL) {\n"
SPACE SPACE "return None_%s();\n" /* op.V */
SPACE "} else {\n"
"%v" /* "" / dropping col->key */
SPACE SPACE "%s saved = col->value;\n" /* op.V */
SPACE SPACE "col->key = key;\n"
SPACE SPACE "col->value = value;\n"
SPACE SPACE "return Some_%s(saved);\n" /* op.V */
SPACE "}\n"
"}\n\n",
op.v_primitive ? cstr("") : cstr("NODISCARD "), op.V, map, map, op.K, op.V,
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE"%s_drop(col->key);\n", op.K),
op.V, op.V);
}
if (!op.v_primitive) {
VecU8_append_fmt(&res,
"bool %r_erase_substitute(%r* self, %s key, %s value) {\n" /* map, map, op.K, op.V */
SPACE "RBTreeNode_%r* col = %r_try_insert(self, key, value);\n" /* kvp, map */
SPACE "if (col == NULL)\n"
SPACE SPACE "return true;\n"
"%v" "%v" /* "" / op.K_drop(col->key), "" / op.V_drop(col->value) */
SPACE "col->key = key;\n"
SPACE "col->value = value;\n"
SPACE "return false;\n"
"}\n\n",
map, map, op.K, op.V, kvp, map,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->value);\n", op.V));
}
if (op.pop){
// todo: write _pop_by_it
// todo: rewrite pop using _pop_by_it
VecU8_append_fmt(&res,
"Option%s %r_pop(%r* self, %v key) {\n" /* op.V, map, map, taking_ref_k_argument */
SPACE "RBTreeNode_%r* v = %r_find(self, key);\n" /* kvp, map */
SPACE "if (v == NULL)\n"
SPACE SPACE "return None_%s();\n" /* op.V */
"%v" /* "" / op.K_drop(v->key) */
"%s saved = v->value;\n" /* op.V */
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, (RBTreeNode*)v);\n"
SPACE "free(v);\n"
SPACE "return Some_%s(saved);\n" /* op.V */
"}\n\n",
op.V, map, map, codegen_rbtree_map__taking_ref_k_argument(op),
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->key);\n", op.K),
op.V, op.V);
}
// todo: write generator for methods _at and _mat
if (op.pop_substitute) {
VecU8_append_vec(&res, VecU8_fmt(
"%s" "Option%s %s_pop_substitute(%s* self, %s key, %s value) {\n" /* "" / NODISCARD , op.V, map, map, op.K, op.V */
/* Using unsafe method with conditional ownership transfer */
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key, value);\n" /* kvp, map */
SPACE "if (col == NULL) {\n"
SPACE SPACE "return None_%s();\n" /* op.V */
SPACE "} else {\n"
"%v" /* "" / dropping col->key */
SPACE SPACE "%s saved = col->value;\n" /* op.V */
SPACE SPACE "col->key = key;\n"
SPACE SPACE "col->value = value;\n"
SPACE SPACE "return Some_%s(saved);\n" /* op.V */
SPACE "}\n"
"}\n\n",
op.v_primitive ? cstr("") : cstr("NODISCARD "), op.V, map, map, op.K, op.V,
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE"%s_drop(col->key);\n", op.K),
op.V, op.V));
}
VecU8_drop(map);
VecU8_drop(kvp);
if (!op.v_primitive) {
VecU8_append_vec(&res, VecU8_fmt(
"bool %s_erase_substitute(%s* self, %s key, %s value) {\n" /* map, map, op.K, op.V */
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key, value);\n" /* kvp, map */
SPACE "if (col == NULL)\n"
SPACE SPACE "return true;\n"
"%v" "%v" /* "" / op.K_drop(col->key), "" / op.V_drop(col->value) */
SPACE "col->key = key;\n"
SPACE "col->value = value;\n"
SPACE "return false;\n"
"}\n\n",
map, map, op.K, op.V, kvp, map,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->value);\n", op.V)));
}
if (op.pop){
// todo: write _pop_by_it
// todo: rewrite pop using _pop_by_it
VecU8_append_vec(&res, VecU8_fmt(
"Option%s %s_pop(%s* self, %v key) {\n" /* op.V, map, map, taking_ref_k_argument */
SPACE "RBTreeNode_%s* v = %s_find(self, key);\n" /* kvp, map */
SPACE "if (v == NULL)\n"
SPACE SPACE "return None_%s();\n" /* op.V */
"%v" /* "" / op.K_drop(v->key) */
"%s saved = v->value;\n" /* op.V */
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, (RBTreeNode*)v);\n"
SPACE "free(v);\n"
SPACE "return Some_%s(saved);\n" /* op.V */
"}\n\n",
op.V, map, map, codegen_rbtree_map__taking_ref_k_argument(op),
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->key);\n", op.K),
op.V, op.V));
}
// todo: write generator for methods _at and _mat
return res;
}
void generate_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op,
bool generate_node_struct, bool separate_struct_and_methods
) {
if (separate_struct_and_methods) {
assert(!generate_node_struct);
VecU8 name_for_struct = VecU8_fmt("%v_struct", get_name_of_rbtree_map_structure(op));
VecU8 name_for_method = VecU8_fmt("%v_method", get_name_of_rbtree_map_structure(op));
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
generate_rbtree_Map_template_instantiation(op, false, true, false),
name_for_struct);
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
generate_rbtree_Map_template_instantiation(op, false, false, true),
name_for_method);
} else {
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
generate_rbtree_Map_template_instantiation(op, generate_node_struct, true, true),
get_name_of_rbtree_map_structure(op));
}
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));
}
void generate_rbtree_Map_templ_inst_guarded_header(
@ -449,6 +425,8 @@ void generate_rbtree_Map_templ_inst_guarded_header(
VecU8 all_dependencies = VecU8_fmt("%v%s",
codegen_include_relative_to_root(bonus_ns, cstr("src/l1_5/core/rb_tree_node.h")), dependencies);
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, all_dependencies,
generate_rbtree_Map_template_instantiation(op, generate_node_struct, true, true),
get_name_of_rbtree_map_structure(op));
generate_rbtree_Map_template_instantiation(op, generate_node_struct), get_name_of_rbtree_map_structure(op));
}
#endif

View File

@ -1,5 +1,6 @@
#pragma once
// todo: refactor (with VecU8_append_fmt)
#ifndef PROTOTYPE1_SRC_L1_5_CODEGEN_TRAIT_BOX_AND_REF_H
#define PROTOTYPE1_SRC_L1_5_CODEGEN_TRAIT_BOX_AND_REF_H
#include "../../l1/codegen/codegen.h"
typedef struct {
@ -10,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;
@ -21,36 +20,25 @@ typedef struct {
typedef struct {
SpanNamedMethodSignatureRecordRef methods;
bool drop_primitive;
SpanU8 name;
/* It is usually either name or "void" */
SpanU8 base_struct_name;
} NamedTraitDefRecordRef;
void codegen_append_trait_table_structure(VecU8* res, NamedTraitDefRecordRef trait){
VecU8_append_cstr(res, "typedef struct {\n");
NODISCARD VecU8 generate_trait_table_structure(NamedTraitDefRecordRef trait){
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_fmt(res, SPACE "%s (*%s)(", c_type_empty_means_void(method.return_type), method.name);
if (method.takes_self) {
VecU8_append_fmt(res,
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)
VecU8_append_cstr(res, ", ");
VecU8_append_span(res, param.type);
if (p)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, param.type);
}
VecU8_append_cstr(res, ");\n");
VecU8_append_span(&res, cstr(");\n"));
}
if (!trait.drop_primitive) {
VecU8_append_fmt(res,
SPACE "void (*drop)(%s*);\n",
c_type_empty_means_void(trait.base_struct_name));
}
VecU8_append_fmt(res, "} %s_Table;\n\n", trait.name);
VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", trait.name));
return res;
}
typedef struct {
@ -60,112 +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_fmt(res,
"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_fmt(res,
"%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_fmt(res, ", %s %s", param.type, param.name);
}
VecU8_append_cstr(res,"){\n" SPACE);
if (method.return_type.len > 0)
VecU8_append_cstr(res, "return ");
VecU8_append_fmt(res, "self%s""t->%s(",
self_as_ptr ? cstr("->") : cstr("."), method.name);
if (method.takes_self) {
VecU8_append_fmt(res, "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_cstr(res, ", ");
VecU8_append_span(res, param.name);
}
VecU8_append_cstr(res, ");\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();
codegen_append_trait_table_structure(&res, 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_fmt(&res,
"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_fmt(&res,
"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_fmt(&res,
"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

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_5_CORE_RB_TREE_NODE_H
#define PROTOTYPE1_SRC_L1_5_CORE_RB_TREE_NODE_H
#include "../../l1/core/util.h"
@ -255,3 +256,5 @@ void BufRBTree_empty_index_erase(VecBufRBTreeNode* tree, U64* root, U64 z) {
// self->el.len--;
}
#endif

View File

@ -1,36 +0,0 @@
#pragma once
#include "../../../gen/l1/geom.h"
#include "randomness.h"
// Convert HSV (hue is in degrees; s, v in [0,1]) to RGB (in [0,1]^3)
static vec3 hsv_to_rgb(float h, float s, float v) {
h = fmodf(h, 360.0f);
if (h < 0.0f) h += 360.0f;
float hf = h / 60.0f;
int i = (int)floorf(hf);
float f = hf - (float)i;
float p = v * (1.0f - s);
float q = v * (1.0f - s * f);
float t = v * (1.0f - s * (1.0f - f));
vec3 rgb;
switch (i) {
case 0: rgb.x = v; rgb.y = t; rgb.z = p; break;
case 1: rgb.x = q; rgb.y = v; rgb.z = p; break;
case 2: rgb.x = p; rgb.y = v; rgb.z = t; break;
case 3: rgb.x = p; rgb.y = q; rgb.z = v; break;
case 4: rgb.x = t; rgb.y = p; rgb.z = v; break;
default: // i == 5:
rgb.x = v; rgb.y = p; rgb.z = q; break;
}
return rgb;
}
/* Cute little function that has nothing to do with rainbows */
vec3 sample_rainbow_color() {
float hue = frand01() * 360.0f;
float s = 0.95f + 0.05f * frand01(); // in [0.95, 1.0]
float v = 0.85f + 0.15f * frand01(); // in [0.85, 1.0]
return hsv_to_rgb(hue, s, v);
}

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_5_core_input_olproga_h
#define prototype1_src_l1_5_core_input_olproga_h
#include "../../../gen/l1/OptionU64.h"
#include "../../../gen/l1/VecAndSpan_U8.h"
@ -19,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;
@ -79,3 +80,6 @@ U64 stdin_read_U64_nofail(){
abortf("No number found\n");
return x.some;
}
#endif

View File

@ -1,260 +0,0 @@
#pragma once
#include "../../l1/core/VecU8_as_str.h"
#include <math.h>
/* 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;
}
void SpanU8_parsing_skip_char(SpanU8* rem){
assert(rem->len > 0);
rem->data++;
rem->len--;
}
bool SpanU8_parsing_try_read_char(SpanU8* rem, char ch){
if (rem->len == 0) {
return false;
}
if (rem->data[0] == (U8)ch) {
SpanU8_parsing_skip_char(rem);
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;
}
}
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, 0 on success, rem_ret is untouched on error */
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;
}
/* Returns positive on error, 0 on success, rem_ret is untouched on error */
int SpanU8_read_S64(SpanU8* rem_ret, S64* ret, bool allow_leading_zero){
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 (!allow_leading_zero && 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;
}
/* Helper function. Btw, floating point numbers suck */
float SpanU8_read_float_h_pow10(S64 p){
assert(-50 <= p && p <= 50);
float twopowers[6] = {10.f};
U32 ap = (U32)labs(p);
for (int i = 0; i + 1 < 6; i++) {
twopowers[i + 1] = twopowers[i] * twopowers[i];
}
float rc = 1.f;
for (int i = 0; i < 6; i++) {
if (ap & 1) {
rc *= twopowers[i];
}
ap >>= 1;
}
if (p < 0) {
rc = 1.f / rc;
}
return rc;
}
/* returns positive int on error, 0 on success, rem_ret is untouched on error */
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' || ch == 'E') {
SpanU8_parsing_skip_char(&rem);
if (SpanU8_parsing_is_char_ahead(rem, '+'))
SpanU8_parsing_skip_char(&rem);
S64 exp;
int ret = SpanU8_read_S64(&rem, &exp, true);
if (ret)
return ret;
if (res == 0.f)
break;
if (exp > 50 || exp < -50) {
return 2;
}
res *= SpanU8_read_float_h_pow10(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;
}
void SpanU8_parsing_skip_spaces(SpanU8* rem){
while (rem->len) {
U8 ch = *rem->data;
if (!(ch == '\t' || ch == ' ' || ch == '\n' || ch == '\r'))
break;
SpanU8_parsing_skip_char(rem);
}
}
bool is_hex_char(char ch){
return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F');
}
static_assert('a' > 'A', "ASCII check");
static_assert('A' > '0', "ASCII check");
U32 char_to_hex_digit(char ch){
if (ch >= 'a')
return ch - 'a' + 10;
if (ch >= 'A')
return ch - 'A' + 10;
return ch - '0';
}
/* Should return true on success */
bool SpanU8_parsing_try_read_hex_digit(SpanU8* rem, U32* ret){
if (rem->len == 0)
return false;
char ch = (char)rem->data[0];
if (is_hex_char(ch)) {
*ret = char_to_hex_digit(ch);
SpanU8_parsing_skip_char(rem);
return true;
}
return false;
}

View File

@ -1,62 +0,0 @@
#pragma once
#include "../marie/geom_util.h"
#include "math.h"
typedef vec4 quaternion_t;
/* quaternion multiplication (quaternions are stored in vec4) */
vec4 quaternion_fl_mul(vec4 A, vec4 B){
return (vec4){
A.x * B.x - A.y * B.y - A.z * B.z - A.w * B.w,
A.x * B.y + A.y * B.x + A.z * B.w - A.w * B.z,
A.x * B.z - A.y * B.w + A.z * B.x + A.w * B.y,
A.x * B.w + A.y * B.z - A.z * B.y + A.w * B.x,
};
}
/* Assumes abs(a) is 1 */
vec4 unit_quaternion_fl_inverse(vec4 a){
return (vec4){a.x, -a.y, -a.z, -a.w};
}
vec4 quaternion_fl_inverse(vec4 a){
float m = vec4_length(a);
m = 1 / (m * m);
return (vec4){a.x * m, -a.y * m, -a.z * m, -a.w * m};
}
/* It is assumed that q unit, i.e. abs(q) ~= 1 */
mat3 unit_quaternion_fl_to_rot3d_mat3(vec4 q){
float a = q.x;
float Rx = q.y;
float Ry = q.z;
float Rz = q.w;
return mat3_add_mat3(mat3_add_mat3(
mat3_mul_scal(mat3_E, 2*a*a - 1),
mat3_mul_scal(mat3_for_cross_product((vec3){Rx, Ry, Rz}), -2 * a)),
mat3_mul_scal(mat3_new_for_proj((vec3){Rx, Ry, Rz}), 2));
}
/* This thing requires some MATH */
// vec4 unit_quaternion_fl_power(vec4 q, float t){
// float qva = vec3_length((vec3){q.y, q.z, q.w});
// float fi = atan2f(qva, q.x);
// const float rub = 0.001f;
// float e_x = cosf(t * fi);
// float e_vc;
// // float t_to_3 = t*t*t;
// // float t_to_5 = t_to_3*t*t;
// // float fi_to_2 = fi * fi;
// // float fi_to_4 = fi_to_2 * fi_to_2;
// // Remember, qva = sin(fi)
// if (qva < rub) {
// /* I have a feeling this is an overkill... Well, only time __and 100 hours of testing__ will show ;) */
// // e_vc = t + (-t_to_3+t) / 6 * fi_to_2 + (3 * t_to_5 - 10 * t_to_3 + 7 * t) / 360 * fi_to_4;
// e_vc = t + (-t*t*t+t) / 6 * fi * fi ;
// } else {
// e_vc = sinf(t *fi) / qva;
// }
// return (vec4){e_x, e_vc * q.y, e_vc * q.z, e_vc * q.w};
}

View File

@ -1,7 +0,0 @@
#pragma once
#include "stdlib.h"
float frand01(void) {
return (float)rand() / (float)RAND_MAX;
}

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_5_core_rb_tree_node_h
#define prototype1_src_l1_5_core_rb_tree_node_h
#include "../../l1/core/util.h"
@ -273,3 +274,5 @@ void RBTree_erase_empty_by_iter(RBTreeNode** root, RBTreeNode* NIL, RBTreeNode*
if (y_org_clr == RBTREE_BLACK)
RBTree_fix_after_delete(root, NIL, x);
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L1_5_CORE_STRINGOP_H
#define PROTOTYPE1_SRC_L1_5_CORE_STRINGOP_H
#include "../../../gen/l1/VecAndSpan_U8.h"
#include "../../../gen/l1/VecAndSpan_VecU8.h"
@ -28,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;
@ -38,3 +39,5 @@ void VecU8_add_vertical_separator(VecU8* self) {
if (self->len)
VecU8_append_span(self, cstr(" | "));
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l1_5_core_stringsearch_h
#define prototype1_src_l1_5_core_stringsearch_h
#include "../../l1/core/VecU8_as_str.h"
#include "../../../gen/l1/VecAndSpan_U64.h"
@ -35,3 +36,7 @@ NODISCARD VecU64 z_function(SpanU8 s){
}
return Z;
}
#endif

View File

@ -1,7 +0,0 @@
#pragma once
#include "../../../gen/l1/geom.h"
mat3 mat3_for_cross_product(vec3 r){
return (mat3){.x = {0, -r.z, r.y}, .y = {r.z, 0, -r.x}, .z = {-r.y, r.x, 0}};
}

View File

@ -1,95 +0,0 @@
#pragma once
#include "../../../gen/l1/geom.h"
/* cross product (vi - u) x (vj - u). If {vi, vj, vu} are points of CCW triangle, this will be it's positive surface */
float marie_surface(vec2 vi, vec2 vj, vec2 u) {
return u.x * (vi.y - vj.y) + u.y * (vj.x - vi.x) + (vi.x * vj.y - vj.x * vi.y);
}
/* 2 lines on a plane (of float type). Assumes lines are intersecting */
vec2 marie_intersect_lines(vec2 A1, vec2 B1, vec2 A2, vec2 B2) {
vec2 alpha = vec2_minus_vec2(B1, A1);
vec2 beta = vec2_minus_vec2(A2, B2);
vec2 gamma = vec2_minus_vec2(A2, A1);
float det_alpha_beta = alpha.x * beta.y - alpha.y * beta.x;
float det_gamma_beta = gamma.x * beta.y - gamma.y * beta.x;
float t1 = det_gamma_beta / det_alpha_beta;
return vec2_add_vec2(A1, vec2_mul_scal(alpha, t1));
}
/* Triangle (ABC) and a ray (from origin P to point Q) in 3d space (of float type). Returns bool: do they intersect */
bool marie_intersect_triangle_and_ray(vec3 A, vec3 B, vec3 C, vec3 P, vec3 Q, vec3* ret){
vec3 alpha = vec3_minus_vec3(A, C);
vec3 beta = vec3_minus_vec3(B, C);
vec3 gamma = vec3_minus_vec3(P, Q);
vec3 delta = vec3_minus_vec3(P, C);
float det_alpha_beta_gamma = mat3_det((mat3){.x = alpha, .y = beta, .z = gamma});
float det_delta_beta_gamma = mat3_det((mat3){.x = delta, .y = beta, .z = gamma});
float det_alpha_delta_gamma = mat3_det((mat3){.x = alpha, .y = delta, .z = gamma});
float det_alpha_beta_delta = mat3_det((mat3){.x = alpha, .y = beta, .z = delta});
if (det_alpha_beta_gamma < 0.0001)
return false;
float b_0 = det_delta_beta_gamma / det_alpha_beta_gamma;
float b_1 = det_alpha_delta_gamma / det_alpha_beta_gamma;
float t = det_alpha_beta_delta / det_alpha_beta_gamma;
if (b_0 < 0 || b_1 < 0 || b_0 + b_1 > 1 || t < 0)
return false;
*ret = vec3_add_vec3(P, vec3_mul_scal(gamma, -t));
return true;
}
/* any inv exp q => any abs bitness a =>
* vec2#(a)#.(q) -> vec2#(a)#.(q) -> vec2#(a)#.(q) -> vec2#(2a+3)#.(2q) */
S64 marie_precise_surface(s64vec2 vi, s64vec2 vj, s64vec2 u){
s64vec2 da = s64vec2_minus_s64vec2(vi, u);
s64vec2 db = s64vec2_minus_s64vec2(vj, u);
/* da, db are vec2#(a+1)#.(q) */
return da.x * db.y - da.y * db.x;
}
bool marie_precise_do_intersect_2d_interv_and_seg(s64vec2 a, s64vec2 b, s64vec2 c, s64vec2 d){
s64vec2 alpha = s64vec2_minus_s64vec2(b, a);
s64vec2 beta = s64vec2_minus_s64vec2(c, d);
s64vec2 gamma = s64vec2_minus_s64vec2(c, a);
S64 det_alpha_beta = alpha.x * beta.y - alpha.y * beta.x;
S64 det_gamma_beta = gamma.x * beta.y - gamma.y * beta.x;
if (det_alpha_beta == 0) {
if (det_gamma_beta != 0)
return false;
if (a.x < b.x) {
return !(c.x <= a.x && d.x <= a.x) && !(b.x <= c.x && b.x <= d.x);
} else if (b.x < a.x) {
return !(c.x <= b.x && d.x <= b.x) && !(a.x <= c.x && a.x <= d.x);
} else if (a.y < b.y) {
return !(c.y <= a.y && d.y <= a.y) && !(b.y <= c.y && b.y <= d.y);
} else if (b.y < a.y) {
return !(c.y <= b.y && d.y <= b.y) && !(a.y <= c.y && a.y <= d.y);
} else
return false; /* This code is unreachable, actually */
}
/* Return det_gamma_beta/det_alpha_beta in (0; 1) */
return 0 < det_gamma_beta && det_gamma_beta < det_alpha_beta;
}
/* Does not work for degenerate case where s(b_prev, b, b_next) = 0.
* Returns false if a is on the edge of angle(b_prev, b, b_next) */
bool marie_precise_is_in_ccw_angle(s64vec2 b_prev, s64vec2 b, s64vec2 b_next, s64vec2 a){
S64 sx = marie_precise_surface(b_prev, b, b_next);
S64 sy = marie_precise_surface(b_prev, b, a);
S64 sz = marie_precise_surface(b, b_next, a);
if (sx < 0) {
return sy > 0 || sz > 0;
} else {
return sy > 0 && sz > 0;
}
}
/* Read source code to understand */
bool marie_order_s64vec2_less(s64vec2 a, s64vec2 b){
return a.x < b.x || (a.x == b.x && a.y < b.y);
}

View File

@ -1,6 +1,7 @@
#pragma once
#ifndef prototype1_src_l2_alice_assets_h
#define prototype1_src_l2_alice_assets_h
#include "../../l1_5/marie/graphics_geom.h"
#include "../marie/graphics_geom.h"
#include "../../../gen/l1/VecAndSpan_U32.h"
#include "../../../gen/l1/VecAndSpan_U8.h"
@ -32,18 +33,19 @@ GenericMeshTopology GenericMeshTopology_clone(const GenericMeshTopology* self) {
return (GenericMeshTopology){.vertices = VecGenericMeshVertexInc_clone(&self->vertices), .indexes = VecU32_clone(&self->indexes)};
}
/* non-primitive */
typedef struct {
VecU8 topology_path;
VecU8 diffuse_texture_path;
VecU8 normal_texture_path;
VecU8 specular_texture_path;
} AliceGenericMeshTexturePaths;
} AliceGenericMeshPath;
/* non-primitive */
typedef struct {
VecU8 topology_path;
AliceGenericMeshTexturePaths tex;
} AliceGenericMeshPaths;
void AliceGenericMeshPath_drop(AliceGenericMeshPath self) {
VecU8_drop(self.topology_path);
VecU8_drop(self.diffuse_texture_path);
VecU8_drop(self.normal_texture_path);
VecU8_drop(self.specular_texture_path);
}
typedef struct {
mat4 model_t;
@ -57,7 +59,6 @@ typedef struct {
typedef struct {
vec3 pos;
vec3 color;
} ShinyMeshVertexInc;
typedef struct {
@ -84,6 +85,7 @@ ShinyMeshTopology ShinyMeshTopology_clone(const ShinyMeshTopology* self) {
typedef struct{
mat4 model_t;
vec3 color_off;
vec3 color_on;
} ShinyMeshInstanceInc;
@ -131,3 +133,6 @@ typedef struct {
Pipeline0PointLight point_light_arr[pipeline_0_ubo_point_light_max_count];
Pipeline0Spotlight spotlight_arr[pipeline_0_ubo_spotlight_max_count];
} Pipeline0UBO;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,6 @@
#pragma once
#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"
@ -10,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 */
@ -28,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);
}
@ -71,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);
}
@ -101,139 +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;
}
/* No beauty, just pure brute force */
/* 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);
}
#endif

View File

@ -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 ()

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
#pragma once
#ifndef prototype1_src_l2_anne_r4_h
#define prototype1_src_l2_anne_r4_h
#include "../alice/assets.h"
#include "../../../gen/l1/pixel_masses.h"
#include "../marie/rasterization.h"
#include "../marie/texture_processing.h"
#include "../marie/shape_geom.h"
#include <math.h>
/* generating my cool textures2 */
@ -287,8 +287,7 @@ typedef struct {
void draw_polygon_on_normal_texture_smooth_param_surf_h_draw_cb(void* ug, S32 x, S32 y, vec4 attr) {
draw_polygon_on_normal_texture_smooth_param_surf_H_DrawGuest* g = ug;
vec3 normal = g->my_client.fn(g->my_client.guest, (vec2){attr.x, attr.y});
if (TextureDataR8G8B8A8_is_inside(g->tex, x, y))
*TextureDataR8G8B8A8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel(normal);
*TextureDataR8G8B8A8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel(normal);
}
void draw_polygon_on_normal_texture_smooth_param_surf(
@ -320,8 +319,7 @@ void draw_polygon_on_normal_texture_exaggerated_param_surf_draw_cb(void* ug, S32
draw_polygon_on_normal_texture_exaggerated_param_surf_H_DrawGuest* g = ug;
vec3 normal = g->my_client.fn(g->my_client.guest, (vec3){attr.x, attr.y, attr.z});
vec3 tang_normal = mat3_mul_vec3(g->BNT_trans, normal);
if (TextureDataR8G8B8A8_is_inside(g->tex, x, y))
*TextureDataR8G8B8A8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel(tang_normal);
*TextureDataR8G8B8A8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel(tang_normal);
}
/* We can't derive texture coordinates from parameter space coordinates, you have to do it yourself.
@ -343,8 +341,30 @@ void draw_polygon_on_normal_texture_nat_cords_exaggerated_param_surf(
// todo: also, maybe, add a function to derive BNT and do cool stuff with trop mat3x2
void draw_triang_on_normal_tex_absolutely_flat(TextureDataR8G8B8A8* tex, MarieTriangle t){
TextureDataR8G8B8A8_triangle_set_color_cvec4(tex, compress_normal_vec_into_norm_texel((vec3){0, 1, 0}), t);
typedef struct {
TextureDataR8G8B8A8* tex;
} draw_polygon_on_normal_texture_absolutely_flat_H_DrawGuest;
void draw_polygon_on_normal_texture_absolutely_flat_h_draw_cb(void* ug, S32 x, S32 y, vec4 attr) {
draw_polygon_on_normal_texture_absolutely_flat_H_DrawGuest* g = ug;
*TextureDataR8G8B8A8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel((vec3){0, 1, 0});
}
void draw_polygon_on_normal_texture_nat_cords_absolutely_flat(TextureDataR8G8B8A8* tex,
vec2 ta, vec2 tb, vec2 tc
) {
draw_polygon_on_normal_texture_absolutely_flat_H_DrawGuest aboba = {tex};
marie_rasterize_triangle_with_attr((MariePlaneVertAttr){.pos = ta}, (MariePlaneVertAttr){.pos = tb},
(MariePlaneVertAttr){.pos = tc}, (FnMarieRasterizerCallback){
.fn = draw_polygon_on_normal_texture_absolutely_flat_h_draw_cb, .guest = (void*)&aboba});
}
// todo: replace it with a "color everything in one color" function
void draw_polygon_on_normal_texture_absolutely_flat(TextureDataR8G8B8A8* tex,
vec2 pa, vec2 pb, vec2 pc, mat3x2 trop
) {
draw_polygon_on_normal_texture_nat_cords_absolutely_flat(tex, mat3x2_mul_vec3(trop, vec2_and_one(pa)),
mat3x2_mul_vec3(trop, vec2_and_one(pb)), mat3x2_mul_vec3(trop, vec2_and_one(pc)));
}
@ -401,37 +421,57 @@ void TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(
}
#include "../../../gen/l1/margaret/png_pixel_masses.h"
#include "../marie/texture_processing.h"
#include "../../l1/system/fsmanip.h"
#include "../alice/model_file.h"
/* Situation: we generated vertices array of generic mesh, we filled .tex attribute (scaled pixel pos)
* Now I want the normally scaled stuff back */
MarieTriangle restore_triangle_from_mesh_topology(const VecGenericMeshVertexInc* vertices,
U32 texture_width, U32 texture_height, U32 vi1, U32 vi2, U32 vi3){
vec2 tex1 = VecGenericMeshVertexInc_at(vertices, vi1)->tex;
vec2 tex2 = VecGenericMeshVertexInc_at(vertices, vi2)->tex;
vec2 tex3 = VecGenericMeshVertexInc_at(vertices, vi3)->tex;
return (MarieTriangle){
.v0 = {tex1.x * (float)texture_width, tex1.y * (float)texture_height},
.v1 = {tex2.x * (float)texture_width, tex2.y * (float)texture_height},
.v2 = {tex3.x * (float)texture_width, tex3.y * (float)texture_height},
};
}
MarieTriangle restore_triangle_from_vert_array_complete_mesh_topology(const VecGenericMeshVertexInc* vertices,
U32 texture_width, U32 texture_height, U32 vi1, U32 vi2, U32 vi3, VecU32* indexes){
VecU32_append_span(indexes, (SpanU32){(U32[]){vi1, vi2, vi3}, 3});
return restore_triangle_from_mesh_topology(vertices, texture_width, texture_height, vi1, vi2, vi3);
}
void generate_template_and_normal_and_model_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k){
// todo: rewrite this crrp (again)
TextureDataR8G8B8A8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) {
assert(k >= 1);
const float a = M_PI_2f / (float)k;
const float l = 2 * r * sinf(M_PI_4f / (float)k);
}
size_t width_pix = (size_t)ceilf(s_resol * (2 * r + w));
size_t height_pix = (size_t)ceilf(s_resol * (2 * r + (float)k * l));
vec2 cord_resol = {(float)width_pix / (2 * r + w), (float)height_pix / (2 * r + (float)k * l)};
const vec2 v0tex = {r, r};
const vec2 v1tex = {r + w, r};
const vec2 v4tex = {r, 0};
const vec2 v5tex = {r + w, 0};
TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width_pix, height_pix);
mat3x2 cord_resol_trop = (mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y};
vec3 color_1 = (vec3){0.3f, 0.5f, 0.1f};
TextureDataR8G8B8A8_draw_parametrized_triangle_of_one_color(&res, color_1, (MarieTriangle){v0tex, v4tex, v5tex}, cord_resol_trop);
TextureDataR8G8B8A8_draw_parametrized_triangle_of_one_color(&res, color_1, (MarieTriangle){v0tex, v5tex, v1tex}, cord_resol_trop);
vec3 color_2 = (vec3){0.1f, 0.2f, 0.8f};
vec3 color_3 = (vec3){0.2f, 0.3f, 0.9f};
vec3 color_4 = (vec3){0.1f, 0.5f, 0.7f};
vec3 color_5 = (vec3){0.7f, 0.05f, 0.2f};
for (size_t i = 1; i <= k; i++) {
vec2 A = (vec2){r - r * sinf(a * (float)i), r + r * cosf(a * (float)i)};
vec2 B = (vec2){r - r * sinf(a * (float)(i-1)), r + r * cosf(a * (float)(i-1))};
TextureDataR8G8B8A8_draw_parametrized_triangle_of_one_color(&res, color_2, (MarieTriangle){v0tex, B, A}, cord_resol_trop);
}
for (size_t i = 1; i <= k; i++) {
vec2 A = (vec2){r + w + r * sinf(a * (float)i), r + r * cosf(a * (float)i)};
vec2 B = (vec2){r + w + r * sinf(a * (float)(i-1)), r + r * cosf(a * (float)(i-1))};
TextureDataR8G8B8A8_draw_parametrized_triangle_of_one_color(&res, color_3, (MarieTriangle){v1tex, A, B}, cord_resol_trop);
}
for (size_t i = 1; i <= k; i++) {
vec2 A = (vec2){r, 2 * r + (float)(i) * l};
vec2 B = (vec2){r, 2 * r + (float)(i-1) * l};
vec2 C = (vec2){r + w, 2 * r + (float)(i-1) * l};
vec2 D = (vec2){r + w, 2 * r + (float)(i) * l};
vec3 c = i % 2 ? color_4 : color_5;
// todo: replace this crrp with something more normal
TextureDataR8G8B8A8_draw_parametrized_triangle_of_one_color(&res, c, (MarieTriangle){A, B, C}, cord_resol_trop);
TextureDataR8G8B8A8_draw_parametrized_triangle_of_one_color(&res, c, (MarieTriangle){A, C, D}, cord_resol_trop);
}
Bublazhuzhka crap_on_back_side = fill_rectangle_with_crap(w, r);
mat3x2 back_side_trop = (mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y, .z = vec2_mul_vec2((vec2){r, r}, cord_resol)};
TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(&res, &crap_on_back_side, (MarieTriangle){{0, r}, {0, 0}, {w, 0}}, back_side_trop);
TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(&res, &crap_on_back_side, (MarieTriangle){{0, r}, {w, 0}, {w, r}}, back_side_trop);
Bublazhuzhka_drop(crap_on_back_side);
return res;
}
/* Use it as a callback in normal map drawing functions that work with smooth (smooth / flat / cylindrical)
* height maps. Guest pointer is of type Bublazhuzhka* */
@ -440,26 +480,67 @@ vec2 height_map_cb_that_uses_bublazhuzhka(void* ug, vec2 v) {
return Bublazhuzhka_get_derivative(bzh, v);
}
void r4_asset_gen_generic_mesh_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k,
VecU8 path_to_mesh, VecU8 path_to_template_tex, VecU8 path_to_normal_tex
) {
// todo: rewrite this crrp and merge it with other one-fourth-of-a-cylinder generiting functions
TextureDataR8G8B8A8 generate_normal_tex_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) {
assert(k >= 1);
const float a = M_PI_2f / (float)k;
const float l = 2 * r * sinf(M_PI_4f / (float)k);
size_t width_pix = (size_t)ceilf(s_resol * (2 * r + w));
size_t height_pix = (size_t)ceilf(s_resol * (2 * r + (float)k * l));
vec2 cord_resol = {(float)width_pix / (2 * r + w), (float)height_pix / (2 * r + (float)k * l)};
const vec2 v0tex = {r, r};
const vec2 v1tex = {r + w, r};
// const vec2 v2tex = {r, 2 * r};
// const vec2 v3tex = {r + w, 2 * r};
const vec2 v4tex = {r, 0};
const vec2 v5tex = {r + w, 0};
TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width_pix, height_pix);
float r_mag = r * s_resol;
float w_mag = w * s_resol;
float l_mag = l * s_resol;
Bublazhuzhka crap_on_the_back_side = fill_rectangle_with_crap(w, r);
mat3x2 trop_back_side = {.x.x = cord_resol.x, .y.y = cord_resol.y, .z = vec2_mul_vec2((vec2){r, r}, cord_resol)};
draw_polygon_on_normal_texture_flat_param_surf(&res, (vec2){0, 0}, (vec2){w, 0}, (vec2){w, r}, trop_back_side,
(FnHeightMapGradFlatSurfCallback){.fn = height_map_cb_that_uses_bublazhuzhka, .guest = &crap_on_the_back_side});
draw_polygon_on_normal_texture_flat_param_surf(&res, (vec2){0, 0}, (vec2){0, r}, (vec2){w, r}, trop_back_side,
(FnHeightMapGradFlatSurfCallback){.fn = height_map_cb_that_uses_bublazhuzhka, .guest = &crap_on_the_back_side});
Bublazhuzhka_drop(crap_on_the_back_side);
U64 texture_width = (U64)ceilf(2 * r_mag + w_mag);
U64 texture_height = (size_t)ceilf(2 * r_mag + (float)k * l_mag);
const vec2 v0tex = {r_mag / (float)texture_width, r_mag / (float)texture_height};
const vec2 v1tex = {(r_mag + w_mag) / (float)texture_width, r_mag / (float)texture_height};
const vec2 v2tex = {r_mag / (float)texture_width, 2 * r_mag / (float)texture_height};
const vec2 v3tex = {(r_mag + w_mag) / (float)texture_width, 2 * r_mag / (float)texture_height};
const vec2 v6tex = {r_mag / (float)texture_width, 0 / (float)texture_height};
const vec2 v7tex = {(r_mag + w_mag) / (float)texture_width, 0 / (float)texture_height};
mat3x2 str = {.x.x = cord_resol.x, .y.y = cord_resol.y};
draw_polygon_on_normal_texture_absolutely_flat(&res, v0tex, v1tex, v4tex, str);
draw_polygon_on_normal_texture_absolutely_flat(&res, v1tex, v4tex, v5tex, str);
for (size_t i = 0; i < k; i++) {
vec2 A = {r - sinf((float)i * a) * r, r + cosf((float)i * a) * r};
vec2 B = {r - sinf((float)(i + 1) * a) * r, r + cosf((float)(i + 1) * a) * r};
draw_polygon_on_normal_texture_absolutely_flat(&res, A, B, (vec2){r, r}, str);
}
for (size_t i = 0; i < k; i++) {
vec2 A = {r + w + sinf((float)i * a) * r, r + cosf((float)i * a) * r};
vec2 B = {r + w + sinf((float)(i + 1) * a) * r, r + cosf((float)(i + 1) * a) * r};
draw_polygon_on_normal_texture_absolutely_flat(&res, A, B, (vec2){r + w, r}, str);
}
for (size_t i = 0; i < k; i++) {
vec2 A = {r, 2 * r + (float)i * l};
vec2 B = {r + w, 2 * r + (float)i * l};
vec2 C = {r, 2 * r + (float)i * l + l};
vec2 D = {r + w, 2 * r + (float)i * l + l};
draw_polygon_on_normal_texture_absolutely_flat(&res, A, B, C, str);
draw_polygon_on_normal_texture_absolutely_flat(&res, D, B, C, str);
}
return res;
}
GenericMeshTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
assert(k >= 1);
const float a = M_PI_2f / (float)k;
const float l = 2 * r * sinf(M_PI_4f / (float)k);
float tex_width = 2 * r + w;
float tex_height = 2 * r + (float)k * l;
const vec2 v0tex = {r / tex_width, r / tex_height};
const vec2 v1tex = {(r + w) / tex_width, r / tex_height};
const vec2 v2tex = {r / tex_width, 2 * r / tex_height};
const vec2 v3tex = {(r + w) / tex_width, 2 * r / tex_height};
VecGenericMeshVertexInc vertices = VecGenericMeshVertexInc_new_reserved(8 + 4 * k + (k + 2) * 2);
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex});
@ -467,18 +548,18 @@ void r4_asset_gen_generic_mesh_one_fourth_of_a_cylinder(float s_resol, float w,
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, r, 0}, .tex = v3tex});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, -r}, .tex = v6tex});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, -r}, .tex = v7tex});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, -r}, .tex = {r / tex_width, 0}});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, -r}, .tex = {(r + w) / tex_width, 0}});
for (U32 i = 0; i < k; i++) {
for (int j = 0; j < 2; j++) {
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){
.pos = {0, cosf(a * (float)(i + j)) * r, -sinf(a * (float)(i + j)) * r},
.tex = {v2tex.x, v2tex.y + (float)(i + j) * l_mag / (float)texture_height}
.tex = {v2tex.x, v2tex.y + (float)(i + j) * l / tex_height}
});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){
.pos = {w, cosf(a * (float)(i + j)) * r, -sinf(a * (float)(i + j)) * r},
.tex = {v3tex.x, v3tex.y + (float)(i + j) * l_mag / (float)texture_height}
.tex = {v3tex.x, v3tex.y + (float)(i + j) * l / tex_height}
});
}
}
@ -487,132 +568,67 @@ void r4_asset_gen_generic_mesh_one_fourth_of_a_cylinder(float s_resol, float w,
for (U32 i = 0; i <= k; i++) {
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){
.pos = {0, cosf(a * (float)i) * r, -sinf(a * (float)i) * r},
.tex = (vec2){
(r_mag - r_mag * sinf(a * (float)i)) / (float)texture_width,
(r_mag + r_mag * cosf(a * (float)i)) / (float)texture_height},
.tex = (vec2){ (r - r *sinf(a * (float)i)) / tex_width, (r + r * cosf(a * (float)i)) / tex_height},
});
}
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, 0}, .tex = v0tex});
for (U32 i = 0; i <= k; i++) {
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){
.pos = {w, cosf(a * (float)i) * r, -sinf(a * (float)i) * r},
.tex = (vec2){
(r_mag + w_mag + r_mag * sinf(a * (float)i)) / (float)texture_width,
(r_mag + r_mag * cosf(a * (float)i)) / (float)texture_height},
.tex = (vec2){ (r + w + r * sinf(a * (float)i)) / tex_width, (r + r * cosf(a * (float)i)) / tex_height},
});
}
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, 0}, .tex = v1tex});
assert(vertices.len == 8 + 4 * k + (k + 2) * 2);
VecU32 indexes = VecU32_new_reserved(3*(4+2*k+2*k));
TextureDataR8G8B8A8 normal_tex = TextureDataR8G8B8A8_new(texture_width, texture_height);
TextureDataR8G8B8A8 temp_tex = TextureDataR8G8B8A8_new(texture_width, texture_height);
{
Bublazhuzhka crap_on_the_back_side = fill_rectangle_with_crap(w, r);
mat3x2 trop = (mat3x2){.x.x = s_resol, .y.y = s_resol, .z.x = r_mag, .z.y = r_mag};
draw_polygon_on_normal_texture_flat_param_surf(&normal_tex, (vec2){0, 0}, (vec2){w, 0}, (vec2){w, r}, trop,
(FnHeightMapGradFlatSurfCallback){.fn = height_map_cb_that_uses_bublazhuzhka, .guest = &crap_on_the_back_side});
draw_polygon_on_normal_texture_flat_param_surf(&normal_tex, (vec2){0, 0}, (vec2){0, r}, (vec2){w, r}, trop,
(FnHeightMapGradFlatSurfCallback){.fn = height_map_cb_that_uses_bublazhuzhka, .guest = &crap_on_the_back_side});
TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(&temp_tex, &crap_on_the_back_side, (MarieTriangle){{0, r}, {0, 0}, {w, 0}}, trop);
TextureDataR8G8B8A8_draw_triang_part_bublazhuzhka(&temp_tex, &crap_on_the_back_side, (MarieTriangle){{0, r}, {w, 0}, {w, r}}, trop);
Bublazhuzhka_drop(crap_on_the_back_side);
VecU32_append_span(&indexes, (SpanU32){.data = (U32[]){1, 3, 0, 3, 2, 0}, .len = 6});
U32 _span_0[] = {7, 5, 4, 7, 4, 6, 1, 3, 0, 3, 2, 0};
VecU32_append_span(&indexes, (SpanU32){.data = _span_0, .len = ARRAY_SIZE(_span_0)});
for (U32 i = 0; i < k; i++) {
U32 _span_1[] = {
8 + 4 * k + k + 1, 8 + 4 * k + i, 8 + 4 * k + i + 1,
8 + 4 * k + 2 * k + 3, 8 + 4 * k + (k + 2) + i + 1, 8 + 4 * k + (k + 2) + i,
8 + 4 * i + 0, 8 + 4 * i + 1, 8 + 4 * i + 3,
8 + 4 * i + 0, 8 + 4 * i + 3, 8 + 4 * i + 2,
};
VecU32_append_span(&indexes, (SpanU32){.data = _span_1, .len = ARRAY_SIZE(_span_1)});
}
{
U32 A = 4, B = 5, C = 6, D = 7;
vec3 c1 = {0.5f, 0.9f, 0.5f};
MarieTriangle t1 = restore_triangle_from_vert_array_complete_mesh_topology(&vertices,
texture_width, texture_height, D, B, A, &indexes);
MarieTriangle t2 = restore_triangle_from_vert_array_complete_mesh_topology(&vertices,
texture_width, texture_height, D, A, C, &indexes);
TextureDataR8G8B8A8_draw_triangle_of_one_color(&temp_tex, c1, t1);
TextureDataR8G8B8A8_draw_triangle_of_one_color(&temp_tex, c1, t2);
draw_triang_on_normal_tex_absolutely_flat(&normal_tex, t1);
draw_triang_on_normal_tex_absolutely_flat(&normal_tex, t2);
VecU32_append_span(&indexes, (SpanU32){.data = (U32[]){D, B, A, D, A, C}, .len = 6});
}
for (size_t i = 0; i < k; i++) {
U32 O = 8 + 4 * k + k + 1, A = 8 + 4 * k + i, B = 8 + 4 * k + i + 1;
vec3 color_2 = {0.1f, 0.25f, 0.66f};
MarieTriangle t = restore_triangle_from_vert_array_complete_mesh_topology(&vertices,
texture_width, texture_height, O, A, B, &indexes);
draw_triang_on_normal_tex_absolutely_flat(&normal_tex, t);
TextureDataR8G8B8A8_draw_triangle_of_one_color(&temp_tex, color_2, t);
}
for (size_t i = 0; i < k; i++) {
U32 O = 8 + 4 * k + 2 * k + 3, B = 8 + 4 * k + (k + 2) + i + 1, A = 8 + 4 * k + (k + 2) + i;
vec3 color_3 = {0.2f, 0.3f, 0.9f};
MarieTriangle t = restore_triangle_from_vert_array_complete_mesh_topology(&vertices,
texture_width, texture_height, O, B, A, &indexes);
draw_triang_on_normal_tex_absolutely_flat(&normal_tex, t);
TextureDataR8G8B8A8_draw_triangle_of_one_color(&temp_tex, color_3, t);
// vec2 A = {r + w + sinf((float)i * a) * r, r + cosf((float)i * a) * r};
// vec2 B = {r + w + sinf((float)(i + 1) * a) * r, r + cosf((float)(i + 1) * a) * r};
}
for (size_t i = 0; i < k; i++) {
U32 A = 8 + 4 * i + 0, B = 8 + 4 * i + 1, C = 8 + 4 * i + 2, D = 8 + 4 * i + 3;
vec3 c4 = {0.1f, 0.5f, 0.7f};
vec3 c5 = {0.7f, 0.05f, 0.2f};
vec3 c = i % 2 ? c4 : c5;
MarieTriangle t1 = restore_triangle_from_vert_array_complete_mesh_topology(&vertices,
texture_width, texture_height, A, B, D, &indexes);
MarieTriangle t2 = restore_triangle_from_vert_array_complete_mesh_topology(&vertices,
texture_width, texture_height, A, D, C, &indexes);
draw_triang_on_normal_tex_absolutely_flat(&normal_tex, t1);
draw_triang_on_normal_tex_absolutely_flat(&normal_tex, t2);
TextureDataR8G8B8A8_draw_triangle_of_one_color(&temp_tex, c, t1);
TextureDataR8G8B8A8_draw_triangle_of_one_color(&temp_tex, c, t2);
}
alice_write_generic_mesh_to_file((GenericMeshTopology){.vertices = vertices, .indexes = indexes}, path_to_mesh);
TextureDataR8G8B8A8_write_to_png_nofail(&normal_tex, VecU8_to_span(&path_to_normal_tex));
TextureDataR8G8B8A8_drop(normal_tex);
VecU8_drop(path_to_normal_tex);
TextureDataR8G8B8A8_write_to_png_nofail(&temp_tex, VecU8_to_span(&path_to_template_tex));
TextureDataR8G8B8A8_drop(temp_tex);
VecU8_drop(path_to_template_tex);
return (GenericMeshTopology){.vertices = vertices, .indexes = indexes};
}
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) });
@ -650,20 +666,23 @@ CubeVertOfFace CubeVertOfFace_next(CubeVertOfFace vert) {
return (CubeVertOfFace){vert.face, (vert.vert_on_it + 1) % 4};
}
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);
}
#include "../../../gen/l1/margaret/png_pixel_masses.h"
#include "../marie/texture_processing.h"
#include "../../l1/system/fsmanip.h"
#include "../alice/model_file.h"
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);
/* Situation: we generated vertices array of generic mesh, we filled .tex attribute (scaled pixel pos)
* Now I want the normally scaled stuff back */
MarieTriangle restore_triangle_from_mesh_topology(const VecGenericMeshVertexInc* vertices,
U32 texture_width, U32 texture_height, U32 vi1, U32 vi2, U32 vi3){
vec2 tex1 = VecGenericMeshVertexInc_at(vertices, vi1)->tex;
vec2 tex2 = VecGenericMeshVertexInc_at(vertices, vi2)->tex;
vec2 tex3 = VecGenericMeshVertexInc_at(vertices, vi3)->tex;
return (MarieTriangle){
.v0 = {tex1.x * (float)texture_width, tex1.y * (float)texture_height},
.v1 = {tex2.x * (float)texture_width, tex2.y * (float)texture_height},
.v2 = {tex3.x * (float)texture_width, tex3.y * (float)texture_height},
};
}
/* r is radius, w is length of cylinder. Will write everything into files for us */
@ -772,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){
@ -790,37 +814,36 @@ void r4_asset_gen_generic_mesh_quad(float width, float length, VecU8 path_to_sav
/* a is r at bottom, b is r on top. y is in [0, height]. Shape is symmetrical from Oy */
ShinyMeshTopology generate_shiny_lamp(float height, float a, float b){
vec3 d_clr = {0.1f, 0.1f, 0.2f};
ShinyMeshVertexInc vert[24] = {
{{+b, height, +b}, d_clr},
{{+b, 0, +b}, d_clr},
{{+b, 0, -b}, d_clr},
{{+b, height, -b}, d_clr},
{{+b, height, +b}},
{{+b, 0, +b}},
{{+b, 0, -b}},
{{+b, height, -b}},
{{-b, 0, -b}, d_clr},
{{-b, 0, +b}, d_clr},
{{-b, height, +b}, d_clr},
{{-b, height, -b}, d_clr},
{{-b, 0, -b}},
{{-b, 0, +b}},
{{-b, height, +b}},
{{-b, height, -b}},
{{+b, height, +b}, d_clr},
{{+b, height, -b}, d_clr},
{{-b, height, -b}, d_clr},
{{-b, height, +b}, d_clr},
{{+b, height, +b}},
{{+b, height, -b}},
{{-b, height, -b}},
{{-b, height, +b}},
{{-b, 0, -b}, d_clr},
{{+b, 0, -b}, d_clr},
{{+b, 0, +b}, d_clr},
{{-b, 0, +b}, d_clr},
{{-b, 0, -b}},
{{+b, 0, -b}},
{{+b, 0, +b}},
{{-b, 0, +b}},
{{+b, height, +b}, d_clr},
{{-b, height, +b}, d_clr},
{{-b, 0, +b}, d_clr},
{{+b, 0, +b}, d_clr},
{{+b, height, +b}},
{{-b, height, +b}},
{{-b, 0, +b}},
{{+b, 0, +b}},
{{-b, 0, -b}, d_clr},
{{-b, height, -b}, d_clr},
{{+b, height, -b}, d_clr},
{{+b, 0, -b}, d_clr},
{{-b, 0, -b}},
{{-b, height, -b}},
{{+b, height, -b}},
{{+b, 0, -b}},
};
VecShinyMeshVertexInc vertices = VecShinyMeshVertexInc_from_span(
(SpanShinyMeshVertexInc){ .data = vert, .len = ARRAY_SIZE(vert) });
@ -832,62 +855,27 @@ ShinyMeshTopology generate_shiny_lamp(float height, float a, float b){
return (ShinyMeshTopology){ .vertices = vertices, .indexes = indexes};
}
void r4_asset_gen_generic_mesh_one_fourth_of_a_cylinder_2(U64 w, U64 r, U64 k) {
r4_asset_gen_generic_mesh_one_fourth_of_a_cylinder(120, (float)w, (float)r, k,
VecU8_fmt("l2/models/log_%u_%u_%u.AliceGenericMesh", w, r, k),
VecU8_fmt("l2/textures/log_%u_%u_%u_TEMPLATE.png", w, r, k),
VecU8_fmt("l2/textures/log_%u_%u_%u_NORMAL.png", w, r, k));
}
#define pow2_14 16384
/* P : Vec<Vec<vec2#.(14) >>*/
void r4_asset_gen_generic_mesh_horizontal_polygon(const VecVecs64vec2* P, mat3x2 tex_trans, VecU8 save_path){
VecMarieHoleAndVertexId triangulation = marie_polygon_hole_removal_triangulation(P);
VecU64 hole_pref_vert_sz = VecU64_new_zeroinit(P->len + 1);
for (size_t h = 0; h < P->len; h++) {
hole_pref_vert_sz.buf[h + 1] = hole_pref_vert_sz.buf[h] + P->buf[h].len;
void generate_one_forth_of_a_cylinder_with_bublazhuzhka(U64 w, U64 r, U64 k) {
{
TextureDataR8G8B8A8 tex = generate_tex_template_for_one_fourth_of_a_cylinder(120, (float)w, (float)r, k);
TextureDataR8G8B8A8 fixed_tex = TextureDataR8G8B8A8_expand_nontransparent_1px(&tex);
VecU8 name = VecU8_fmt("l2/textures/log_%u_%u_%u_TEMPLATE.png", w, r, k);
TextureDataR8G8B8A8_write_to_png_nofail(&fixed_tex, VecU8_to_span(&name));
VecU8_drop(name);
TextureDataR8G8B8A8_drop(fixed_tex);
TextureDataR8G8B8A8_drop(tex);
}
U64 tvn = hole_pref_vert_sz.buf[P->len];
VecGenericMeshVertexInc vertices = VecGenericMeshVertexInc_new_zeroinit(tvn);
for (size_t h = 0; h < P->len; h++) {
for (size_t i = 0; i < P->buf[h].len; i++) {
size_t vi = hole_pref_vert_sz.buf[h] + i;
s64vec2 pos = P->buf[h].buf[i];
vec2 pos_float_plane = {(float)pos.x / pow2_14, (float)pos.y / pow2_14};
vec3 pos_float = {pos_float_plane.x, 0, -pos_float_plane.y};
*VecGenericMeshVertexInc_mat(&vertices, vi) = (GenericMeshVertexInc){.pos = pos_float,
.tex = mat3x2_mul_vec3(tex_trans, vec2_and_one(pos_float_plane))};
}
{
TextureDataR8G8B8A8 tex = generate_normal_tex_for_one_fourth_of_a_cylinder(120, (float)w, (float)r, k);
TextureDataR8G8B8A8 fixed_tex = TextureDataR8G8B8A8_expand_nontransparent_1px(&tex);
VecU8 name = VecU8_fmt("l2/textures/log_%u_%u_%u_NORMAL.png", w, r, k);
TextureDataR8G8B8A8_write_to_png_nofail(&fixed_tex, VecU8_to_span(&name));
VecU8_drop(name);
TextureDataR8G8B8A8_drop(fixed_tex);
TextureDataR8G8B8A8_drop(tex);
}
VecU32 indexes = VecU32_new_zeroinit(triangulation.len);
for (size_t ii = 0; ii < triangulation.len; ii++) {
MarieHoleAndVertexId p = triangulation.buf[ii];
assert(p.hole_id < P->len);
assert(p.vertex_in_hole_id < P->buf[p.hole_id].len);
U64 vi = hole_pref_vert_sz.buf[p.hole_id] + p.vertex_in_hole_id;
assert(vi < tvn);
indexes.buf[ii] = (U32)vi;
}
alice_write_generic_mesh_to_file((GenericMeshTopology){.vertices = vertices, .indexes = indexes}, save_path);
VecU64_drop(hole_pref_vert_sz);
VecMarieHoleAndVertexId_drop(triangulation);
}
/* #.(q) */
VecVecs64vec2 generate_funny_polygon(){
Vecs64vec2 A = Vecs64vec2_new_zeroinit(60);
for (int i = 0; i < 60; i++) {
float x = cosf((float)i * 2 * M_PIf / 60) * 2;
float y = sinf((float)i * 2 * M_PIf / 60);
A.buf[i] = (s64vec2){(S64)roundf(x * pow2_14), (S64)roundf(y * pow2_14)};
}
VecVecs64vec2 P = VecVecs64vec2_new();
VecVecs64vec2_append(&P, A);
return P;
GenericMeshTopology top = generate_one_fourth_of_a_cylinder((float)w, (float)r, k);
alice_write_generic_mesh_to_file(top, VecU8_fmt("l2/models/log_%u_%u_%u.AliceGenericMesh", w, r, k));
}
/* We are on l2 */
@ -895,22 +883,16 @@ int gen_assets_for_r4() {
mkdir_nofail("l2/models");
mkdir_nofail("l2/textures");
mkdir_nofail("l2/textures/r4");
r4_asset_gen_generic_mesh_one_fourth_of_a_cylinder_2(10, 2, 6);
alice_write_shiny_mesh_to_file(generate_shiny_cube((vec3){0.6f, 0.6f, 0.7f}), vcstr("l2/models/cube.AliceShinyMesh"));
generate_one_forth_of_a_cylinder_with_bublazhuzhka(10, 2, 6);
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);
{ /* Just a test */
VecVecs64vec2 P = generate_funny_polygon();
r4_asset_gen_generic_mesh_horizontal_polygon(&P, (mat3x2){.x.x = 1, .y.y = 1},
vcstr("l2/models/floor1.AliceGenericMesh"));
VecVecs64vec2_drop(P);
}
return 0;
}
#endif

View File

@ -1,73 +0,0 @@
#pragma once
#include "json_encoded.h"
/* todo: add big endian support */
/* Points to some string (BIN segment) + contains decoded json object */
typedef struct {
U32 version;
Json gltf;
/* If length is 0, BIN segment is absent */
SpanU8 bin_segment;
} GLBFileSegments;
void GLBFileSegments_drop(GLBFileSegments self){
Json_drop(self.gltf);
}
/* Returns positive on error, 0 on ok */
int glb_file_get_segments(SpanU8 file, GLBFileSegments* ret){
if (file.len < 12) {
return 1;
}
SpanU8 json_segment = {0, 0}; // length of 0 means segment is absent
SpanU8 bin_segment = {0, 0}; // length of 0 means segment is absent
if (*(const U32*)file.data != 0x46546C67) {
return 2;
}
U32 version = *(const U32*)(file.data + 4);
/* Nobody cares about version */
if (*(const U32*)(file.data + 8) != file.len) {
return 3;
}
U64 cur = 12;
while (cur < file.len) {
if (cur + 8 > file.len) {
return 4;
}
U32 chunk_length = *(const U32*)(file.data + cur);
U32 chunk_type = *(const U32*)(file.data + cur + 4);
if (cur + 8 + chunk_length > file.len) {
return 5;
}
SpanU8 cur_segment = SpanU8_span(file, cur + 8, chunk_length);
if (chunk_type == 0x4E4F534A) {
if (json_segment.len > 0) {
/* Illegal! Two json segments */
return 6;
}
json_segment = cur_segment;
} else if (chunk_type == 0x004E4942) {
if (bin_segment.len > 0) {
/* Illegal! Two bin segments */
return 7;
}
bin_segment = cur_segment;
}
cur += 8 + chunk_length;
}
if (json_segment.len == 0) {
/* Illegal, no json segment */
return 8;
}
SpanU8_print(json_segment);
printf("\n");
OptionJson parsed_json = json_decode(json_segment, 15);
if (parsed_json.variant == Option_None) {
return 9;
}
/* Everything is correct */
*ret = (GLBFileSegments){.version = version, .gltf = parsed_json.some, .bin_segment = bin_segment};
return 0;
}

View File

@ -1,94 +0,0 @@
#pragma once
#include "../../l1/core/VecU8_as_str.h"
#include "../../l1_5/core/rb_tree_node.h"
typedef struct Json Json;
typedef struct VecJson VecJson;
typedef struct RBTree_MapVecU8ToJson RBTree_MapVecU8ToJson;
#include "../../../gen/l1/eve/VecJson_struct.h"
#include "../../../gen/l1_5/eve/RBTree_MapVecU8ToJson_struct.h"
typedef enum {
Json_integer,
Json_float,
Json_dict,
Json_arr,
Json_str,
Json_false,
Json_true,
Json_none,
} Json_variant;
typedef RBTree_MapVecU8ToJson json_dictionary_t;
struct Json{
Json_variant variant;
union {
S64 integer;
float float_num;
json_dictionary_t dict;
VecJson arr;
VecU8 str;
};
};
typedef struct RBTreeNode_KVPVecU8ToJson {
RBTreeNode base;
VecU8 key;
Json value;
} RBTreeNode_KVPVecU8ToJson;
/* Pulling declarations of methods, defined below */
void VecJson_drop(VecJson self);
void RBTree_MapVecU8ToJson_drop(json_dictionary_t self);
void Json_drop(Json self) {
if (self.variant == Json_str) {
VecU8_drop(self.str);
} else if (self.variant == Json_arr) {
VecJson_drop(self.arr);
} else if (self.variant == Json_dict) {
RBTree_MapVecU8ToJson_drop(self.dict);
}
}
#include "../../../gen/l1/eve/VecJson_methods.h"
#include "../../../gen/l1_5/eve/RBTree_MapVecU8ToJson_method.h"
Json Json_from_float(float x){
return (Json){.variant = Json_float, .float_num = x};
}
Json Json_from_int(S64 x){
return (Json){.variant = Json_integer, .integer = x};
}
Json Json_from_VecU8(VecU8 x){
return (Json){.variant = Json_str, .str = x};
}
Json Json_from_SpanU8(SpanU8 x){
return (Json){.variant = Json_str, .str = VecU8_from_span(x)};
}
Json Json_from_bool(bool x){
return (Json){.variant = x ? Json_true : Json_false};
}
const Json Json_None = ((Json){.variant = Json_none});
const Json Json_True = ((Json){.variant = Json_true});
const Json Json_False = ((Json){.variant = Json_false});
Json Json_from_VecJson(VecJson arr){
return (Json){.variant = Json_arr, .arr = arr};
}
Json Json_from_MapVecU8ToJson(json_dictionary_t dict){
return (Json){.variant = Json_dict, .dict = dict};
}
// Bonus
#include "../../../gen/l1/eve/OptionJson.h"

View File

@ -1,282 +0,0 @@
#pragma once
#include "../../l1_5/core/parsing_string.h"
#include "json.h"
void json_encoding_append_utf16(VecU8* res, U8 codepoint){
assert(codepoint < 32);
VecU8_append_span(res, cstr("\\u00"));
VecU8_append(res, digit_to_big_hex(codepoint >> 4));
VecU8_append(res, digit_to_big_hex(codepoint & 0xF));
}
/* Str is being encoded as JSON string literal */
void json_encoding_append_string(VecU8* res, SpanU8 str){
VecU8_append(res, '"');
for (size_t i = 0; i < str.len; i++) {
U8 ch = str.data[i];
if (ch == '\t') {
VecU8_append_span(res, cstr("\\t"));
} else if (ch == '\n') {
VecU8_append_span(res, cstr("\\n"));
} else if (ch == '\r') {
VecU8_append_span(res, cstr("\\r"));
} else if (ch <= 31) {
json_encoding_append_utf16(res, ch);
} else if (ch == '\"') {
VecU8_append_span(res, cstr("\\\""));
} else if (ch == '\\') {
VecU8_append_span(res, cstr("\\\\"));
} else {
VecU8_append(res, ch);
}
}
VecU8_append(res, '"');
}
/* No prettyprinting */
void json_encoding_append_to_str(const Json* obj, VecU8* res){
if (obj->variant == Json_false) {
VecU8_append_span(res, cstr("false"));
} else if (obj->variant == Json_true) {
VecU8_append_span(res, cstr("true"));
} else if (obj->variant == Json_none) {
VecU8_append_span(res, cstr("none"));
} else if (obj->variant == Json_integer) {
S64_stringification_into_buf(obj->integer, res);
} else if (obj->variant == Json_float) {
VecU8_append_vec(res, VecU8_format("%f", obj->float_num));
} else if (obj->variant == Json_str) {
json_encoding_append_string(res, VecU8_to_span(&obj->str));
} else if (obj->variant == Json_arr) {
VecU8_append(res, '[');
const VecJson* arr = &obj->arr;
for (size_t i = 0; i < arr->len; i++) {
if (i) {
VecU8_append_span(res, cstr(", "));
}
json_encoding_append_to_str(&arr->buf[i], res);
}
VecU8_append(res, ']');
} else if (obj->variant == Json_dict) {
VecU8_append(res, '{');
bool was = false;
for (RBTreeNode_KVPVecU8ToJson* it = RBTree_MapVecU8ToJson_find_min(&obj->dict); it;) {
if (was) {
VecU8_append_span(res, cstr(", "));
}
json_encoding_append_string(res, VecU8_to_span(&it->key));
VecU8_append_span(res, cstr(": "));
json_encoding_append_to_str(&it->value, res);
was = true;
it = RBTree_MapVecU8ToJson_find_next(&obj->dict, it);
}
VecU8_append(res, '}');
}
}
/* json depth is w => Required stack depth is w frames */
VecU8 json_encode(const Json* obj){
VecU8 res = VecU8_new();
json_encoding_append_to_str(obj, &res);
return res;
}
/* Kids had their fun with json encoding. Now it's time for adults to enjoy some parsing */
OptionJson json_decoding_h_no_spaces(SpanU8* rem, U32 depth_rem);
OptionJson json_decoding_h(SpanU8* rem, U32 depth_rem){
SpanU8_parsing_skip_spaces(rem);
OptionJson x = json_decoding_h_no_spaces(rem, depth_rem);
SpanU8_parsing_skip_spaces(rem);
return x;
}
/* Returns positive on error, 0 on success */
int json_decoding_parse_string(SpanU8* rem, VecU8* ret_str){
if (!SpanU8_parsing_try_read_char(rem, '\"')) {
return 1;
}
VecU8 res = VecU8_new();
U16 prev_high_surrogate = 0;
while (true) {
if (rem->len == 0) {
VecU8_drop(res);
return 1;
}
U8 ch = rem->data[0];
SpanU8_parsing_skip_char(rem);
if (ch == '\"') {
*ret_str = res;
return 0;
}
if (ch == '\\') {
if (rem->len == 0) {
VecU8_drop(res);
return 2;
}
ch = rem->data[0];
SpanU8_parsing_skip_char(rem);
if (ch == '\"' || ch == '\\' || ch == '/') {
VecU8_append(&res, ch);
} else if (ch == 'b') {
VecU8_append(&res, '\b');
} else if (ch == 'f') {
VecU8_append(&res, '\f');
} else if (ch == 'n') {
VecU8_append(&res, '\n');
} else if (ch == 'r') {
VecU8_append(&res, '\r');
} else if (ch == 't') {
VecU8_append(&res, '\t');
} else if (ch == 'u') {
U16 cur_word = 0;
for (int i = 0; i < 4; i++) {
U32 d;
if (!SpanU8_parsing_try_read_hex_digit(rem, &d)) {
VecU8_drop(res);
return 3;
}
cur_word = (cur_word << 4) | (U16)d;
}
if (0xDC00 <= cur_word && cur_word < 0xE000) {
/* Low surrogate pair */
if (prev_high_surrogate == 0) {
VecU8_drop(res);
return 4;
}
U32 U = (U32)0x10000 + ((U32)(prev_high_surrogate - 0xD800) << 10) + (U32)(cur_word - 0xDC00);
VecU8_encode_as_utf8(&res, U);
prev_high_surrogate = 0;
} else if (0xD800 <= cur_word && cur_word < 0xDC00) {
/* High surrogate pair */
prev_high_surrogate = cur_word;
} else {
prev_high_surrogate = 0;
VecU8_encode_as_utf8(&res, (U32)cur_word);
}
} else {
VecU8_drop(res);
return 5;
}
} else {
/* We ignore illegal characters in string literals */
VecU8_append(&res, ch);
}
}
}
OptionJson json_decoding_h_no_spaces(SpanU8* rem, U32 depth_rem){
if (depth_rem == 0) {
return None_Json();
}
float fl_value;
SpanU8 was = *rem;
int fl_code = SpanU8_read_float(rem, &fl_value);
if (fl_code == 0) {
S64 int_value;
int int_code = SpanU8_read_S64(&was, &int_value, false);
if (was.data == rem->data) {
assert(int_code == 0);
return Some_Json(Json_from_int(int_value));
} else {
return Some_Json(Json_from_float(fl_value));
}
}
bool false_code = SpanU8_parsing_try_read_prefix(rem, cstr("false"));
if (false_code)
return Some_Json(Json_False);
bool true_code = SpanU8_parsing_try_read_prefix(rem, cstr("true"));
if (true_code)
return Some_Json(Json_True);
bool none_code = SpanU8_parsing_try_read_prefix(rem, cstr("none"));
if (none_code)
return Some_Json(Json_None);
if (SpanU8_parsing_is_char_ahead(*rem, '\"')) {
VecU8 str;
int str_code = json_decoding_parse_string(rem, &str);
if (str_code) {
/* str is uninitialized on error */
return None_Json();
}
/* In case of success, str starts owning a VecU8 */
return Some_Json(Json_from_VecU8(str));
}
if (SpanU8_parsing_try_read_char(rem, '[')) {
SpanU8_parsing_skip_spaces(rem);
VecJson arr = VecJson_new();
while (true) {
if (SpanU8_parsing_try_read_char(rem, ']')) {
return Some_Json(Json_from_VecJson(arr));
}
if (arr.len > 0) {
if (!SpanU8_parsing_try_read_char(rem, ',')) {
VecJson_drop(arr);
return None_Json();
}
}
OptionJson x = json_decoding_h(rem, depth_rem - 1);
if (x.variant == Option_None) {
VecJson_drop(arr);
return None_Json();
}
VecJson_append(&arr, x.some);
}
}
if (SpanU8_parsing_try_read_char(rem, '{')) {
SpanU8_parsing_skip_spaces(rem);
json_dictionary_t dict = RBTree_MapVecU8ToJson_new();
while (true) {
if (SpanU8_parsing_try_read_char(rem, '}')) {
return Some_Json(Json_from_MapVecU8ToJson(dict));
}
// todo: add _empty method to rb tree map
if (!RBTree_MapVecU8ToJson_empty(&dict)) {
if (!SpanU8_parsing_try_read_char(rem, ',')) {
RBTree_MapVecU8ToJson_drop(dict);
return None_Json();
}
}
SpanU8_parsing_skip_spaces(rem);
VecU8 key;
int key_code = json_decoding_parse_string(rem, &key);
if (key_code) {
RBTree_MapVecU8ToJson_drop(dict);
return None_Json();
}
SpanU8_parsing_skip_spaces(rem);
if (!SpanU8_parsing_try_read_char(rem, ':')) {
RBTree_MapVecU8ToJson_drop(dict);
VecU8_drop(key);
return None_Json();
}
OptionJson x = json_decoding_h(rem, depth_rem - 1);
if (x.variant == Option_None) {
RBTree_MapVecU8ToJson_drop(dict);
VecU8_drop(key);
return None_Json();
}
bool iret = RBTree_MapVecU8ToJson_insert(&dict, key, x.some);
if (!iret) {
/* Two elements of dictionary share the same key. Very illegal */
RBTree_MapVecU8ToJson_drop(dict);
return None_Json();
}
}
}
return None_Json();
}
/* Given depth_allowed=w, maximum of w frames will be used on stack and the returned Json object will
* have a maximum depth of w */
OptionJson json_decode(SpanU8 text, U32 depth_allowed){
OptionJson x = json_decoding_h(&text, depth_allowed);
if (x.variant == Option_Some && text.len > 0) {
return None_Json();
}
return x;
}

View File

@ -1,3 +0,0 @@
#pragma once
#include "../lucy/glyph_render.h"

View File

@ -1,101 +0,0 @@
#pragma once
#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};
}

View File

@ -1,6 +1,38 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L2_LIZA_INSTRUMENT_H
#define PROTOTYPE1_SRC_L2_LIZA_INSTRUMENT_H
#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"
#endif

View File

@ -1,9 +1,9 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L2_LIZA_PLAYING_SOUND_LOOP_H
#define PROTOTYPE1_SRC_L2_LIZA_PLAYING_SOUND_LOOP_H
// todo: move loop here and rewrite with l1_5 help
#include "../../l1/core/int_primitives.h"
#include <stdlib.h>
typedef struct {
/* self (takes ownership) */
@ -36,3 +36,6 @@ void BoxLizaSound_drop(BoxLizaSound self) {
}
#include "../../../gen/l1/eve/liza/VecBoxLizaSound.h"
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef prototype1_src_l2_lucy_glyph_cache_h
#define prototype1_src_l2_lucy_glyph_cache_h
#include "../margaret/vulkan_utils.h"
#include <ft2build.h>
@ -6,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 */
@ -22,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;
@ -71,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,
@ -103,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);
@ -151,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(
@ -166,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);
}
@ -264,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 */
@ -289,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 */
@ -302,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++) {
@ -336,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;
@ -417,3 +383,5 @@ RBTreeNodeLucyFaceFixedSize* LucyFace_of_size(LucyFace* self, U32 size){
// todo: add a method to RBTree for proper node insertion. This is just pure crap
return RBTree_MapU32ToLucyFaceFixedSize_find(&self->sizes, size);
}
#endif

View File

@ -1,26 +1,17 @@
#pragma once
#ifndef prototype1_src_l2_lucy_rendering_h
#define prototype1_src_l2_lucy_rendering_h
#include "glyph_cache.h"
#include "../../../gen/l1/pixel_masses.h"
#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;
@ -28,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;
@ -60,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)
};
}
@ -89,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
){
@ -152,21 +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) {
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));
}
}
@ -181,5 +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

View File

@ -0,0 +1 @@

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L2_MARGARET_TIME_H
#define PROTOTYPE1_SRC_L2_MARGARET_TIME_H
#include <time.h>
#include "../../l1/core/util.h"
@ -24,3 +25,6 @@ float margaret_ns_time_sec_diff(margaret_ns_time from, margaret_ns_time to) {
float margaret_clock_monotonic_raw_diff(margaret_ns_time start) {
return (float)margaret_ns_time_ns_diff(start, margaret_clock_gettime_monotonic_raw()) / 1e9f;
}
#endif

View File

@ -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

View File

@ -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};
}

View File

@ -1,5 +1,8 @@
#pragma once
#ifndef prototype1_src_l2_margaret_vulkan_memory_h
#define prototype1_src_l2_margaret_vulkan_memory_h
#include <vulkan/vulkan.h>
#include "vulkan_images_claire.h"
#include "vulkan_buffer_claire.h"
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L2_MARGARET_MARGARET_H
#define PROTOTYPE1_SRC_L2_MARGARET_MARGARET_H
#include "../../../gen/l1/OptionU32.h"
#include "../../../gen/l1/VecAndSpan_VecU8.h"
@ -308,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
@ -351,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`
@ -589,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};
@ -946,9 +938,9 @@ VkSampler margaret_create_sampler(VkPhysicalDevice physical_device, VkDevice dev
.magFilter = make_linear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
.minFilter = make_linear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
.mipmapMode = make_linear ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST,
.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeU = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
.mipLodBias = 0.f, // will understand that when I generate mipmaps
.anisotropyEnable = physical_device_features.samplerAnisotropy,
// only if feature device_used_features.samplerAnisotropy was enabled
@ -1246,3 +1238,5 @@ void margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(
});
dst->current_layout = dst_new_layout;
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L2_MARIE_GRAPHICS_GEOM_H
#define PROTOTYPE1_SRC_L2_MARIE_GRAPHICS_GEOM_H
#include "../../../gen/l1/geom.h"
#include <math.h>
@ -97,6 +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

View File

@ -1,47 +1,8 @@
#pragma once
#ifndef SPLITTER_DRAFT_SRC_L2_MARIE_RASTERIZATION_H
#define SPLITTER_DRAFT_SRC_L2_MARIE_RASTERIZATION_H
#include "../../../gen/l1/geom.h"
#include "../../l1/marie/geom_alg_utils.h"
#include "../../l1_5/marie/prim_shape_geom.h"
typedef vec4 MarieVertAttr;
typedef struct {
vec2 pos;
MarieVertAttr attr;
} MariePlaneVertAttr;
typedef struct {
vec2 v0;
vec2 v1;
vec2 v2;
} MarieTriangle;
MarieTriangle MarieTriangle_mat3x2_mul_pos(MarieTriangle self, mat3x2 trop) {
return (MarieTriangle){
.v0 = mat3x2_mul_vec3(trop, vec2_and_one(self.v0)),
.v1 = mat3x2_mul_vec3(trop, vec2_and_one(self.v1)),
.v2 = mat3x2_mul_vec3(trop, vec2_and_one(self.v2))};
}
#include "../../../gen/l1/eve/marie/VecMarieTriangle.h"
typedef struct {
MariePlaneVertAttr v0;
MariePlaneVertAttr v1;
MariePlaneVertAttr v2;
} MarieTriangleAttr;
MarieTriangleAttr MarieTriangle_goto_nat_cords_pres_par(MarieTriangle self, mat3x2 trop) {
return (MarieTriangleAttr){
{mat3x2_mul_vec3(trop, vec2_and_one(self.v0)), {self.v0.x, self.v0.y, 0, 0}},
{mat3x2_mul_vec3(trop, vec2_and_one(self.v1)), {self.v1.x, self.v1.y, 0, 0}},
{mat3x2_mul_vec3(trop, vec2_and_one(self.v2)), {self.v2.x, self.v2.y, 0, 0}},
};
}
#include "../../../gen/l1/eve/marie/VecMarieTriangleAttr.h"
typedef struct {
/* guest, x, y, attribute (custom) */
@ -173,3 +134,5 @@ void marie_rasterize_triangle_with_attr(
}
}
}
#endif

View File

@ -1,288 +1,22 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L2_MARIE_SHAPE_GEOM_H
#define PROTOTYPE1_SRC_L2_MARIE_SHAPE_GEOM_H
#include "../../../gen/l1/VecAndSpan_vec2.h"
#include "../../../gen/l1/VecAndSpan_U64.h"
#include "../../../gen/l1/VecAndSpan_U8.h"
#include "../../../gen/l1/VecAndSpan_s64vec2.h"
#include "../../../gen/l1/VecVecs64vec2.h"
#include "../../../gen/l1/VecAndSpan_VecU64.h"
#include <stdbool.h>
#include <string.h>
#include "../../l1_5/marie/prim_shape_geom.h"
#include "../../../gen/l1_5/marie/clipping.h"
typedef struct{
U64 prev, next;
bool definitely_ear;
} MarieEarCuttingTriangulVertState;
#include "../../../gen/l1/eve/marie/VecMarieEarCuttingTriangulVertState.h"
/* P : Span<vec2#(a)#.(q)>, but widest computational bitness is #(2a + 3) */
void marie_ear_cutting_triangulation_check_vertex(Spans64vec2 P, const VecMarieEarCuttingTriangulVertState* rem,
VecU64* ear_queue, U64 x
){
U64 xp = rem->buf[x].prev;
U64 xn = rem->buf[x].next;
U64 xnn = rem->buf[xn].next;
s64vec2 A = P.data[xp];
s64vec2 B = P.data[x];
s64vec2 C = P.data[xn];
if (marie_precise_surface(A, B, C) <= 0) {
/* We may get input case where C == B (triangle of two vertices). This if block handles that case */
return;
void marie_clip_triang_with_triang_append_to_Vec(MarieTriangle C, MarieTriangle T, VecMarieTriangle* pile) {
float SC = marie_surface(C.v0, C.v1, C.v2);
if (SC < 0) {
vec2 t = C.v0;
C.v0 = C.v1;
C.v1 = t;
}
for (U64 i = xnn; i != xp; i = rem->buf[i].next) {
s64vec2 S = P.data[i];
if (marie_precise_surface(A, B, S) >= 0 &&
marie_precise_surface(B, C, S) >= 0 && marie_precise_surface(C, A, S) >= 0) {
return;
}
}
if (!rem->buf[x].definitely_ear) {
rem->buf[x].definitely_ear = true;
VecU64_append(ear_queue, x);
float ST = marie_surface(T.v0, T.v1, T.v2);
if (ST < 0) {
vec2 t = T.v0;
T.v0 = T.v1;
T.v1 = t;
}
marie_clip_ccw_triang_with_ccw_triang_append_to_Vec(C, T, pile);
}
/* P must be CCW and non-self-intersecting,
* P : Span<vec2#(a)#.(q)>, but widest computational bitness is #(2a + 3)
* Throws exceptions if your numbers are bad */
VecU64 marie_polygon_ear_cutting_triangulation(Spans64vec2 P){
assert(P.len >= 3 && P.len < INT32_MAX);
VecMarieEarCuttingTriangulVertState vertices = VecMarieEarCuttingTriangulVertState_new_zeroinit(P.len);
for (size_t i = 0; i < P.len - 1; i++) {
vertices.buf[i].next = i + 1;
}
for (size_t i = 1; i < P.len; i++) {
vertices.buf[i].prev = i - 1;
}
VecU64 triangles = VecU64_new();
VecU64 ear_queue = VecU64_new();
U64 n = P.len; /* will decrease to 2 */
for (U64 i = 0; i < n; i++) {
marie_ear_cutting_triangulation_check_vertex(P, &vertices, &ear_queue, i);
}
while (n > 2) {
if (ear_queue.len == 0) {
abortf("FATAL EXCEPTION. You messed up floating grid resolution and now marie polygon "
"ear cutting algorithm couldn't find "
"an ear to cut. If that happened in production, well, you suck\n");
}
U64 B = VecU64_pop(&ear_queue);
assert(vertices.buf[B].definitely_ear);
U64 A = vertices.buf[B].prev;
U64 C = vertices.buf[B].next;
assert(A != C);
vertices.buf[A].next = C;
vertices.buf[C].prev = A;
marie_ear_cutting_triangulation_check_vertex(P, &vertices, &ear_queue, A);
marie_ear_cutting_triangulation_check_vertex(P, &vertices, &ear_queue, C);
VecU64_append_span(&triangles, (SpanU64){.data = (U64[]){A, B, C}, .len = 3});
n--;
}
VecU64_drop(ear_queue);
VecMarieEarCuttingTriangulVertState_drop(vertices);
return triangles;
}
/* Used in hole-connecting triangulation algorithm */
typedef struct{
U64 hole_id;
U64 vertex_in_hole_id;
} MarieHoleAndVertexId;
#include "../../../gen/l1/eve/marie/VecMarieHoleAndVertexId.h"
#include "../../../gen/l1/eve/marie/VecVecMarieHoleAndVertexId.h"
#include "../../../gen/l1/eve/marie/VecVecVecMarieHoleAndVertexId.h"
typedef struct {
const VecVecs64vec2* P;
s64vec2 o;
} marie_polygon_hole_removal_H_CompConnGuest;
int marie_polygon_hole_removal_h_comp_connection(const void* A_ptr, const void* B_ptr, void* ug){
MarieHoleAndVertexId A = *(MarieHoleAndVertexId*)A_ptr;
MarieHoleAndVertexId B = *(MarieHoleAndVertexId*)B_ptr;
const marie_polygon_hole_removal_H_CompConnGuest* g =
(const marie_polygon_hole_removal_H_CompConnGuest*)ug;
const VecVecs64vec2* P = ((const marie_polygon_hole_removal_H_CompConnGuest*)ug)->P;
s64vec2 o = ((const marie_polygon_hole_removal_H_CompConnGuest*)ug)->o;
s64vec2 a = P->buf[A.hole_id].buf[A.vertex_in_hole_id];
s64vec2 b = P->buf[B.hole_id].buf[B.vertex_in_hole_id];
assert(marie_order_s64vec2_less(a, o));
assert(marie_order_s64vec2_less(b, o));
S64 s = marie_precise_surface(a, o, b);
assert(s != 0);
return s > 0 ? 1 : -1;
}
/* Holes must not touch each other and must not touch outer polygon,
* lowest S64 value is taken by special purpose. But don't worry about that */
VecMarieHoleAndVertexId marie_polygon_hole_removal(const VecVecs64vec2* P){
assert(P->len >= 1);
assert(P->buf[0].len >= 3);
size_t HN = P->len;
VecU64 rightest_vertex = VecU64_new_zeroinit(HN);
for (size_t hole = 1; hole < HN; hole++) {
printf("C1 hole = %lu\n", hole);
U64 ans = UINT64_MAX;
size_t hs = P->buf[hole].len;
assert(hs >= 3);
s64vec2 old_v = {INT64_MIN, INT64_MIN};
bool got_neg_surf = false;
for (size_t ai = 0; ai < hs; ai++) {
size_t a_prev = ai > 0 ? ai - 1 : hs - 1;
size_t a_next = ai + 1 < hs ? ai + 1 : 0;
s64vec2 new_v = P->buf[hole].buf[ai];
s64vec2 a_prev_v = P->buf[hole].buf[a_prev];
s64vec2 a_next_v = P->buf[hole].buf[a_next];
bool this_is_neg_surf = marie_precise_surface(a_prev_v, new_v, a_next_v) < 0;
if (new_v.x > old_v.x || (new_v.x == old_v.x && new_v.y > old_v.y) ||
(new_v.x == old_v.x && new_v.y == old_v.y && this_is_neg_surf)){
/* two 'negative-surface' vertices of a hole sharing the same position is illegal */
assert(!this_is_neg_surf || !got_neg_surf);
ans = ai;
old_v = new_v;
got_neg_surf = this_is_neg_surf;
}
}
/* Most-right not being 'negative-surface' vertice is impossible */
assert(got_neg_surf);
rightest_vertex.buf[hole] = ans;
}
/* Topmost polygon perimeter (hole zero) has no umbilical vertex, therefore we set it to some impossibly big value*/
rightest_vertex.buf[0] = UINT64_MAX;
VecVecVecMarieHoleAndVertexId connections = VecVecVecMarieHoleAndVertexId_new_reserved(HN);
for (size_t hole = 0; hole < HN; hole++) {
printf("C2 hole = %lu\n", hole);
size_t hs = P->buf[hole].len;
VecVecVecMarieHoleAndVertexId_append(&connections, VecVecMarieHoleAndVertexId_new_reserved(hs));
for (size_t p = 0; p < hs; p++) {
VecVecMarieHoleAndVertexId_append(&connections.buf[hole], VecMarieHoleAndVertexId_new());
}
}
VecMarieHoleAndVertexId parent_vertex_of_hole = VecMarieHoleAndVertexId_new_zeroinit(HN);
for (size_t hole = 1; hole < HN; hole++) {
printf("C3 hole = %lu\n", hole);
size_t a_hs = P->buf[hole].len;
U64 ai = rightest_vertex.buf[hole];
s64vec2 a = P->buf[hole].buf[ai];
U64 ai_next = ai + 1 < a_hs ? ai + 1 : 0;
/* Fake child, indicates we need to detour around the perimeter of a hole.
* FOr vertices that have umbilical cord attached, this 'special connection' is appended prior to
* sorting. Sorting it is possible because because pos(ai_next) < a. For other 'non-childish'
* vertices 'special connection' is also appended, but only after we sort everything
*/
assert(marie_order_s64vec2_less(P->buf[hole].buf[ai_next], a));
VecMarieHoleAndVertexId_append(&connections.buf[hole].buf[ai], (MarieHoleAndVertexId){hole, ai_next});
for (size_t b_hole = 0; b_hole < HN; b_hole++) {
if (b_hole == hole)
continue;
size_t b_hs = P->buf[b_hole].len;
for (size_t bi = 0; bi < b_hs; bi++) {
size_t bi_prev = bi > 0 ? bi - 1 : b_hs - 1;
size_t bi_next = bi + 1 < b_hs ? bi + 1 : 0;
s64vec2 b_prev = P->buf[b_hole].buf[bi_prev];
s64vec2 b = P->buf[b_hole].buf[bi];
s64vec2 b_next = P->buf[b_hole].buf[bi_next];
if (!(b.x > a.x || (b.x == a.x && b.y > a.y)))
goto bi_bad_continue;
if (!marie_precise_is_in_ccw_angle(b_prev, b, b_next, a))
goto bi_bad_continue;
for (size_t c_hole = 0; c_hole < HN; c_hole++) {
size_t c_hs = P->buf[c_hole].len;
for (size_t ci = 0; ci < c_hs; ci++) {
size_t ci_next = ci + 1 < c_hs ? ci + 1 : 0;
s64vec2 c = P->buf[c_hole].buf[ci];
s64vec2 d = P->buf[c_hole].buf[ci_next];
if (marie_precise_do_intersect_2d_interv_and_seg(a, b, c, d))
goto bi_bad_continue;
}
}
/* We are here => current b is good, we need to connect */
VecMarieHoleAndVertexId_append(&connections.buf[b_hole].buf[bi], (MarieHoleAndVertexId){hole, ai});
parent_vertex_of_hole.buf[hole] = (MarieHoleAndVertexId){b_hole, bi};
goto bi_search_end;
bi_bad_continue:{}
}
}
/* We are here => b was not found, which is impossible */
assert(false);
bi_search_end:{}
}
for (size_t hole = 0; hole < HN; hole++) {
printf("C4 hole = %lu\n", hole);
size_t hs = P->buf[hole].len;
assert(hole == 0 || connections.buf[hole].buf[rightest_vertex.buf[hole]].len >= 1);
for (size_t ai = 0; ai < hs; ai++) {
marie_polygon_hole_removal_H_CompConnGuest aboba = {.P = P, .o = P->buf[hole].buf[ai]};
VecMarieHoleAndVertexId* vertex_connections = &connections.buf[hole].buf[ai];
qsort_r(vertex_connections->buf, vertex_connections->len, sizeof(MarieHoleAndVertexId),
marie_polygon_hole_removal_h_comp_connection, &aboba);
if (rightest_vertex.buf[hole] != ai) {
U64 ai_next = ai + 1 < hs ? ai + 1 : 0;
VecMarieHoleAndVertexId_append(vertex_connections, (MarieHoleAndVertexId){hole, ai_next});
}
assert(vertex_connections->len >= 1);
}
}
for (size_t hole = 1; hole < HN; hole++) {
printf("C5 hole = %lu\n", hole); // todo: remove debug vivod
U64 a = rightest_vertex.buf[hole];
MarieHoleAndVertexId b = parent_vertex_of_hole.buf[hole];
VecMarieHoleAndVertexId_append(&connections.buf[hole].buf[a], b);
}
// todo: debug infinite loop
VecVecU64 progress = VecVecU64_new_reserved(HN);
for (size_t h = 0; h < HN; h++) {
VecVecU64_append(&progress, VecU64_new_zeroinit(P->buf[h].len));
}
/* Mapping */
VecMarieHoleAndVertexId detour = VecMarieHoleAndVertexId_new();
MarieHoleAndVertexId cur = {0, 0};
while (true) {
VecMarieHoleAndVertexId* conn = &connections.buf[cur.hole_id].buf[cur.vertex_in_hole_id];
size_t* p = &progress.buf[cur.hole_id].buf[cur.vertex_in_hole_id];
if (*p == conn->len)
break;
assert(*p < conn->len);
VecMarieHoleAndVertexId_append(&detour, cur);
cur = conn->buf[(*p)++];
}
VecU64_drop(rightest_vertex);
VecVecVecMarieHoleAndVertexId_drop(connections);
VecMarieHoleAndVertexId_drop(parent_vertex_of_hole);
VecVecU64_drop(progress);
return detour;
}
VecMarieHoleAndVertexId marie_polygon_hole_removal_triangulation(const VecVecs64vec2* P){
VecMarieHoleAndVertexId detour = marie_polygon_hole_removal(P);
Vecs64vec2 fabricated_mono_polygon = Vecs64vec2_new_zeroinit(detour.len);
for (size_t i = 0; i < detour.len; i++) {
MarieHoleAndVertexId vid = detour.buf[i];
fabricated_mono_polygon.buf[i] = P->buf[vid.hole_id].buf[vid.vertex_in_hole_id];
}
VecU64 mono_polygon_triangulation = marie_polygon_ear_cutting_triangulation(Vecs64vec2_to_span(&fabricated_mono_polygon));
VecMarieHoleAndVertexId back_translated_triangulation =
VecMarieHoleAndVertexId_new_zeroinit(mono_polygon_triangulation.len);
for (size_t i = 0; i < mono_polygon_triangulation.len; i++) {
U64 fake_vertex_id = mono_polygon_triangulation.buf[i];
assert(fake_vertex_id < detour.len);
back_translated_triangulation.buf[i] = detour.buf[fake_vertex_id];
}
VecMarieHoleAndVertexId_drop(detour);
Vecs64vec2_drop(fabricated_mono_polygon);
VecU64_drop(mono_polygon_triangulation);
return back_translated_triangulation;
}
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L2_MARIE_TEXTURE_PROCESSING_H
#define PROTOTYPE1_SRC_L2_MARIE_TEXTURE_PROCESSING_H
#include "../../../gen/l1/pixel_masses.h"
#include "rasterization.h"
@ -84,11 +85,4 @@ void TextureDataR8G8B8A8_draw_triangle_of_one_color(TextureDataR8G8B8A8* self, v
.guest = &aboba});
}
void TextureDataR8G8B8A8_triangle_set_color_cvec4(TextureDataR8G8B8A8* self, cvec4 c, MarieTriangle trig){
TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest aboba = { self, c };
marie_rasterize_triangle_with_attr(
(MariePlaneVertAttr){trig.v0, {}}, (MariePlaneVertAttr){trig.v1, {}}, (MariePlaneVertAttr){trig.v2, {}},
(FnMarieRasterizerCallback){.fn = TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest,
.guest = &aboba});
}
#endif

View File

@ -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);

View File

@ -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);

View File

@ -0,0 +1,135 @@
#!/usr/bin/env python3
"""
Convert between custom bottomup raw files (.r8g8b8a8 / .r8b8g8 / .r8 / .a8)
and normal PNG using Pillow.
Format
------
uint32 width (littleendian)
uint32 height (littleendian)
pixel data rows bottomfirst:
* .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 bottomup -> topdown
# 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)) # topdown -> bottomup
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()

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef PROTOTYPE1_SRC_L2_TESTS_R2_LIZA_COLLECTION_H
#define PROTOTYPE1_SRC_L2_TESTS_R2_LIZA_COLLECTION_H
#include "../../liza/instrument.h"
@ -104,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 */
@ -191,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 */
@ -277,5 +278,8 @@ 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};
}
#endif

View File

@ -5,7 +5,7 @@
#include <stdio.h>
#include "../../../l1/system/pthread.h"
#include "../../margaret/time_utils.h"
#include "../../../l1_5/marie/graphics_geom.h"
#include "../../marie/graphics_geom.h"
#include "../../marie/rasterization.h"
#include <fcntl.h>
@ -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;
}

View File

@ -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;

View File

@ -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(&params, 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 = &params.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 = &params.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, &params) < 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 = &params.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 = &params.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 = &params.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 = &params.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 = &params.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 = &params.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, &params) < 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, &params) < 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;
}

View File

@ -1,423 +0,0 @@
#include "../core/json_encoded.h"
#include <assert.h>
/* It should be noted, that if a nd b point to parts of different strings, then this function is UB */
bool SpanU8_equal(SpanU8 a, SpanU8 b){
return a.data == b.data && a.len == b.len;
}
bool vec_matches_cstr(VecU8 a, const char* b){
bool ans = SpanU8_cont_equal(VecU8_to_span(&a), SpanU8_from_cstr(b));
VecU8_drop(a);
return ans;
}
void tt1(){
SpanU8 str = cstr("ABC=");
SpanU8 rem = str;
bool c = SpanU8_parsing_try_read_prefix(&rem, cstr("ABC"));
check(c);
check(rem.data == str.data + 3);
check(rem.len == 1);
}
void tt2(){
SpanU8 str = cstr("ABC==");
SpanU8 rem = str;
bool c = SpanU8_parsing_try_read_prefix(&rem, cstr("ABD"));
check(!c);
check(SpanU8_equal(rem, str));
}
void tt3(){
SpanU8 str = (SpanU8){.data = (U8*)"ABC", .len = 2};
SpanU8 rem = str;
bool c = SpanU8_parsing_try_read_prefix(&rem, cstr("ABC"));
check(!c);
check(SpanU8_equal(rem, str));
}
void tt4(){
SpanU8 str = cstr("ABC");
SpanU8 rem = str;
SpanU8_parsing_skip_char(&rem);
check(SpanU8_equal(rem, (SpanU8){str.data + 1, str.len - 1}));
}
void tt5(){
SpanU8 str = cstr("AB");
SpanU8 rem = str;
bool c = SpanU8_parsing_try_read_char(&rem, 'A');
check(c && SpanU8_equal(rem, (SpanU8){str.data + 1, str.len - 1}));
}
void tt6(){
SpanU8 str = cstr("ABC");
SpanU8 rem = str;
bool c = SpanU8_parsing_try_read_char(&rem, 'B');
check(!c && SpanU8_equal(rem, str));
}
void tt7(){
SpanU8 str = (SpanU8){.data = (U8*)"AB", .len = 0};
SpanU8 rem = str;
bool c = SpanU8_parsing_try_read_char(&rem, 'A');
check(!c && SpanU8_equal(rem, str));
}
void tt8(){
SpanU8 str = cstr("abcd\n\n");
SpanU8 rem = str;
SpanU8_parsing_skip_entire_line(&rem);
check(SpanU8_equal(rem, (SpanU8){str.data + 5, str.len - 5}));
}
void tt9(){
SpanU8 str = cstr("abcdef");
SpanU8 rem = str;
SpanU8_parsing_skip_entire_line(&rem);
check(SpanU8_equal(rem, (SpanU8){str.data + 6, 0}));
}
void tt10(){
SpanU8 str = cstr("\nab\n\n");
SpanU8 rem = str;
SpanU8_parsing_skip_entire_line(&rem);
check(SpanU8_equal(rem, (SpanU8){str.data + 1, str.len - 1}));
}
void tt11(){
SpanU8 str = cstr("ABC");
check(SpanU8_parsing_is_char_ahead(str, 'A'));
check(!SpanU8_parsing_is_char_ahead(str, 'B'));
str.len = 0;
check(!SpanU8_parsing_is_char_ahead(str, 'A'));
}
void test_u64_reading_with_good_inp(SpanU8 str, U64 right_val, U64 leftovers){
SpanU8 rem = str;
U64 val;
int c = SpanU8_read_U64(&rem, &val);
check(c == 0);
check(rem.data == str.data + str.len - leftovers && rem.len == leftovers);
check(val == right_val);
}
void tt12(){
test_u64_reading_with_good_inp(cstr("18446744073709551615--"), 18446744073709551615ul, 2);
test_u64_reading_with_good_inp(cstr("69+"), 69, 1);
test_u64_reading_with_good_inp(cstr("0"), 0, 0);
}
void test_u64_reading_with_ill_formed_inp(SpanU8 str){
SpanU8 rem = str;
U64 val;
int c = SpanU8_read_U64(&rem, &val);
check(c > 0);
check(SpanU8_equal(str, rem));
}
void tt13(){
test_u64_reading_with_ill_formed_inp(cstr("18446744073709551616"));
test_u64_reading_with_ill_formed_inp(cstr("01"));
test_u64_reading_with_ill_formed_inp(cstr("-123"));
}
void test_s64_reading_with_ill_formed_inp(SpanU8 str){
SpanU8 rem = str;
S64 val;
int c = SpanU8_read_S64(&rem, &val, false);
check(c > 0);
check(SpanU8_equal(str, rem));
}
void tt14(){
test_s64_reading_with_ill_formed_inp(cstr("9223372036854775808"));
test_s64_reading_with_ill_formed_inp(cstr("92233720368547758000"));
test_s64_reading_with_ill_formed_inp(cstr("+9223372036854775808"));
test_s64_reading_with_ill_formed_inp(cstr("-9223372036854775809"));
test_s64_reading_with_ill_formed_inp(cstr("-92233720368547758000"));
test_s64_reading_with_ill_formed_inp(cstr("-09"));
test_s64_reading_with_ill_formed_inp(cstr("09"));
test_s64_reading_with_ill_formed_inp(cstr("00"));
test_s64_reading_with_ill_formed_inp(cstr("-00"));
test_s64_reading_with_ill_formed_inp(cstr("+"));
test_s64_reading_with_ill_formed_inp(cstr("-"));
test_s64_reading_with_ill_formed_inp(cstr("+123"));
}
void test_s64_reading_with_good_inp(SpanU8 str, S64 right_val, U64 leftovers){
SpanU8 rem = str;
S64 val;
int c = SpanU8_read_S64(&rem, &val, false);
check(c == 0);
check(rem.data == str.data + str.len - leftovers && rem.len == leftovers);
check(val == right_val);
}
void tt15(){
test_s64_reading_with_good_inp(cstr("9223372036854775807--"), 9223372036854775807l, 2);
test_s64_reading_with_good_inp(cstr("9223372036854775807"), 9223372036854775807l, 0);
test_s64_reading_with_good_inp(cstr("9223372036854775805"), 9223372036854775805l, 0);
test_s64_reading_with_good_inp(cstr("-9223372036854775808++"), -9223372036854775807l-1, 2);
test_s64_reading_with_good_inp(cstr("-9223372036854775808"), -9223372036854775807l-1, 0);
test_s64_reading_with_good_inp(cstr("413-"), 413, 1);
test_s64_reading_with_good_inp(cstr("0-"), 0, 1);
}
void test_float_near(float right_val, float val, float eps){
check((right_val >= +1e60 && val >= +1e60) || (right_val <= -1e60 && val <= -1e60) || fabsf(right_val - val) < eps);
}
void test_float_reading_with_good_inp(SpanU8 str, float right_val, float eps, U64 lo){
SpanU8 rem = str;
float val;
int c = SpanU8_read_float(&rem, &val);
check(c == 0);
check(rem.data == str.data + str.len - lo && rem.len == lo);
test_float_near(right_val, val, eps);
}
void tt16(){
test_float_reading_with_good_inp(cstr("1022.312"), 1022.312f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("1022.1"), 1022.1f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("0.0000"), 0.f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("0.0e100"), 0.f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("1.2e3"), 1200.f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("101"), 101.f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("-123"), -123.f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("-123e-3"), -0.123f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("98e-3"), 0.098f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("1e50"), 1.e50f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("1e-50"), 1.e-50f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("-1e-50"), -1e-50f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("-1e50"), -1e50f, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("-15e+4"), -150000, 0.00001f, 0);
test_float_reading_with_good_inp(cstr("0.012307405471801758"), 0.012307405471801758f, 0.1f, 0);
test_float_reading_with_good_inp(cstr("-0.012307405471801758"), -0.012307405471801758f, 0.1f, 0);
}
void test_float_reading_with_ill_formed_inp(SpanU8 str){
SpanU8 rem = str;
float val;
int c = SpanU8_read_float(&rem, &val);
check(c > 0);
check(SpanU8_equal(str, rem));
}
void tt17(){
test_float_reading_with_ill_formed_inp(cstr("+123"));
test_float_reading_with_ill_formed_inp(cstr("1e51"));
test_float_reading_with_ill_formed_inp(cstr("1e9223372036854775807"));
test_float_reading_with_ill_formed_inp(cstr("1e9223372036854775808"));
test_float_reading_with_ill_formed_inp(cstr("1e-51"));
test_float_reading_with_ill_formed_inp(cstr("1e-9223372036854775808"));
test_float_reading_with_ill_formed_inp(cstr("1e-9223372036854775809"));
}
void tt18(){
SpanU8 str = cstr(" 1");
SpanU8 rem = str;
SpanU8_parsing_skip_spaces(&rem);
check(SpanU8_equal(rem, (SpanU8){str.data + 3, str.len - 3}));
}
void tt19(){
SpanU8 str = cstr("\t\r\n ");
SpanU8 rem = str;
SpanU8_parsing_skip_spaces(&rem);
check(SpanU8_equal(rem, (SpanU8){str.data + 4, 0}));
}
void tt20(){
SpanU8 str = cstr("1213");
SpanU8 rem = str;
SpanU8_parsing_skip_spaces(&rem);
check(SpanU8_equal(rem, str));
}
void tt21(){
check(is_hex_char('0'));
check(is_hex_char('9'));
check(is_hex_char('A'));
check(is_hex_char('F'));
check(is_hex_char('a'));
check(is_hex_char('f'));
check(!is_hex_char('_') && !is_hex_char('*') && !is_hex_char('~') && !is_hex_char('-') && !is_hex_char('(')
&& !is_hex_char('/') && !is_hex_char(':') && !is_hex_char('G') && !is_hex_char('g') && !is_hex_char('['));
check(char_to_hex_digit('a') == 10 && char_to_hex_digit('A') == 10 && char_to_hex_digit('9') == 9);
SpanU8 str = cstr("E=");
SpanU8 rem = str;
U32 d;
bool c = SpanU8_parsing_try_read_hex_digit(&rem, &d);
check(c);
check(rem.data == str.data + 1 && rem.len == 1);
check(d == 0xE);
check(!SpanU8_parsing_try_read_hex_digit(&rem, &d));
check(rem.data == str.data + 1 && rem.len == 1);
rem.len = 0;
check(!SpanU8_parsing_try_read_hex_digit(&rem, &d));
check(rem.data == str.data + 1 && rem.len == 0);
}
/* Json kicks in */
void tt22(){
VecU8 buf = VecU8_new();
json_encoding_append_utf16(&buf, 17);
check(SpanU8_cont_equal(VecU8_to_span(&buf), cstr("\\u0011")));
json_encoding_append_utf16(&buf, 7);
check(vec_matches_cstr(buf, "\\u0011\\u0007"));
}
void tt23(){
VecU8 buf = VecU8_new();
json_encoding_append_string(&buf, cstr(""));
check(vec_matches_cstr(buf, "\"\""));
}
void tt24(){
VecU8 buf = VecU8_new();
json_encoding_append_string(&buf, cstr("\"\n\t\r\\ AB"));
check(vec_matches_cstr(buf, "\"" "\\\"\\n\\t\\r\\\\ AB" "\""));
}
void test_json_encoding(Json x, const char* str_lit){
VecU8 my_ans = json_encode(&x);
Json_drop(x);
check(vec_matches_cstr(my_ans, str_lit));
}
void tt25(){
test_json_encoding(Json_from_VecJson(VecJson_new()), "[]");
test_json_encoding(Json_None, "none");
test_json_encoding(Json_False, "false");
test_json_encoding(Json_True, "true");
test_json_encoding(Json_from_int(INT64_MIN), "-9223372036854775808");
test_json_encoding(Json_from_SpanU8(cstr("that's right\nLet's do it")), "\"that's right\\nLet's do it\"");
test_json_encoding(Json_from_MapVecU8ToJson(RBTree_MapVecU8ToJson_new()), "{}");
}
void tt26(){
{
Json x = Json_from_float(123.0f);
VecU8 s = json_encode(&x);
check(SpanU8_is_prefix(cstr("123"), VecU8_to_span(&s)));
Json_drop(x);
VecU8_drop(s);
}
{
VecJson v = VecJson_new();
VecJson_append(&v, Json_from_VecJson(VecJson_new()));
VecJson_append(&v, Json_from_int(1223));
test_json_encoding(Json_from_VecJson(v), "[[], 1223]");
}
{
json_dictionary_t d = RBTree_MapVecU8ToJson_new();
RBTree_MapVecU8ToJson_insert(&d, vcstr("k1"), Json_from_int(45));
RBTree_MapVecU8ToJson_insert(&d, vcstr("k2"), Json_from_int(45555));
test_json_encoding(Json_from_MapVecU8ToJson(d), "{\"k1\": 45, \"k2\": 45555}");
}
}
void test_json_equal(const Json* a, const Json* b){
check(a->variant == b->variant)
if (a->variant == Json_integer) {
check(a->integer == b->integer);
} else if (a->variant == Json_float) {
test_float_near(a->float_num, b->float_num, 0.01f);
} else if (a->variant == Json_str) {
check(VecU8_equal_VecU8(&a->str, &b->str));
} else if (a->variant == Json_arr) {
const VecJson* A = &a->arr;
const VecJson* B = &b->arr;
check(A->len == B->len);
for (size_t i = 0; i < A->len; i++) {
test_json_equal(&A->buf[i], &B->buf[i]);
}
} else if (a->variant == Json_dict) {
const json_dictionary_t* A = &a->dict;
const json_dictionary_t* B = &b->dict;
RBTreeNode_KVPVecU8ToJson* i_a = RBTree_MapVecU8ToJson_find_min(A);
RBTreeNode_KVPVecU8ToJson* i_b = RBTree_MapVecU8ToJson_find_min(B);
while (i_a != NULL && i_b != NULL) {
check(VecU8_equal_VecU8(&i_a->key, &i_b->key));
test_json_equal(&i_a->value, &i_b->value);
i_a = RBTree_MapVecU8ToJson_find_next(A, i_a);
i_b = RBTree_MapVecU8ToJson_find_next(B, i_b);
}
check(i_a == NULL);
check(i_b == NULL);
}
}
void test_json_decoding_ok(const char* str_lit, Json right_ans){
OptionJson my_ans = json_decode(SpanU8_from_cstr(str_lit), 10);
check(my_ans.variant == Option_Some);
test_json_equal(&my_ans.some, &right_ans);
Json_drop(my_ans.some);
Json_drop(right_ans);
}
void tt27(){
test_json_decoding_ok("true", Json_True);
test_json_decoding_ok("\n\n1233", Json_from_int(1233));
test_json_decoding_ok("false\r \t ", Json_False);
test_json_decoding_ok(" none", Json_None);
test_json_decoding_ok("999999999999999999999999999999999999999", Json_from_float(1e100));
test_json_decoding_ok(" [ \t\r\r\n ]", Json_from_VecJson(VecJson_new()));
test_json_decoding_ok(" { } ", Json_from_MapVecU8ToJson(RBTree_MapVecU8ToJson_new()));
test_json_decoding_ok(" \"7\" ", Json_from_SpanU8(cstr("7")));
test_json_decoding_ok(" \"XXX\" ", Json_from_SpanU8(cstr("XXX")));
test_json_decoding_ok(" -0.012307405471801758", Json_from_float(-0.012307405471801758f));
{
VecJson x = VecJson_new();
VecJson_append(&x, Json_from_int(12));
VecJson_append(&x, Json_from_int(23));
VecJson_append(&x, Json_from_int(34));
test_json_decoding_ok("[ 12,23 , \n 34 ]", Json_from_VecJson(x));
}
{
json_dictionary_t x = RBTree_MapVecU8ToJson_new();
RBTree_MapVecU8ToJson_insert(&x, vcstr("XXX"), Json_from_int(9990));
test_json_decoding_ok(" { \"XXX\" : 9990 }", Json_from_MapVecU8ToJson(x));
}
}
void tt28(){
json_dictionary_t x = RBTree_MapVecU8ToJson_new();
RBTree_MapVecU8ToJson_insert(&x, vcstr("9\u0449AB-"), Json_from_bool(false));
RBTree_MapVecU8ToJson_insert(&x, vcstr("9\u0449A"), Json_from_int(999));
test_json_decoding_ok(" { \"9\u0449A\" : 999 , \"9\\u0449AB-\" : false }", Json_from_MapVecU8ToJson(x));
}
void test_json_decoding_with_ill_formed_inp(const char* str_lit){
OptionJson res = json_decode(SpanU8_from_cstr(str_lit), 10);
check(res.variant == Option_None);
}
void tt29(){
test_json_decoding_with_ill_formed_inp("{");
test_json_decoding_with_ill_formed_inp("{\"A\": 12, \"A\": 12}");
test_json_decoding_with_ill_formed_inp("[");
test_json_decoding_with_ill_formed_inp("123e2222222222222222222222222");
test_json_decoding_with_ill_formed_inp("\"666");
test_json_decoding_with_ill_formed_inp("{{{}}");
test_json_decoding_with_ill_formed_inp("{\"a\": 2 \"b\": 12}");
test_json_decoding_with_ill_formed_inp("f");
test_json_decoding_with_ill_formed_inp("tru");
test_json_decoding_with_ill_formed_inp("none3");
test_json_decoding_with_ill_formed_inp("]");
test_json_decoding_with_ill_formed_inp("}");
}
int main(){
tt1(); tt2(); tt3(); tt4(); tt5(); tt6(); tt7(); tt8(); tt9(); tt10(); tt11(); tt12(); tt13(); tt14(); tt15();
tt16(); tt17(); tt18(); tt19();
tt20(); tt21(); tt22(); tt23(); tt24(); tt25(); tt26(); tt27();
tt28(); tt29();
return 0;
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 916 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -1,407 +1,98 @@
#include "../../l2/core/glb_file.h"
#include "../../l2/alice/engine.h"
#include "../../l1_5/marie/prim_shape_geom.h"
#include "../../../gen/l1/VecAndSpan_vec3.h"
#include "../../l1_5/core/color.h"
#include "../../l2/allie/allie.c"
#include "linux/input-event-codes.h"
typedef mat3 quad_form3_t;
float quad_form3_mul_vec(quad_form3_t Q, vec3 M) {
return M.x * M.x * Q.x.x * Q.x.x + M.y * M.y * Q.y.y * Q.y.y + M.z * M.z * Q.z.z * Q.z.z +
2 * (M.x * M.y * Q.x.y + M.x * M.z * Q.x.z + M.y * M.x * Q.y.z);
AliceGenericMeshPath AliceGenericMeshPath_for_log(SpanU8 root_dir, U64 w, U64 r, U64 k) {
return (AliceGenericMeshPath){
.topology_path = VecU8_fmt("%s/gen/l2/models/log_%u_%u_%u.AliceGenericMesh", root_dir, w, r, k),
.diffuse_texture_path = VecU8_fmt("%s/src/l3/textures/log_%u_%u_%u_diffuse.png", root_dir, w, r, k),
.normal_texture_path = VecU8_fmt("%s/gen/l2/textures/log_%u_%u_%u_NORMAL.png", root_dir, w, r, k),
.specular_texture_path = VecU8_fmt("%s/src/l3/textures/log_%u_%u_%u_specular.png", root_dir, w, r, k),
};
}
typedef struct{
vec3 pos;
vec3 color;
float magnitude;
} LightSourceState;
#include "../../../gen/l1/eve/r4/VecLightSourceState.h"
typedef struct {
float mass; /* In kg, Not zero */
quad_form3_t inertia_moment; /* Qadratic form, yields kg*m^2 */
/* Center of mass relative to "center of mesh" */
vec3 mass_center;
} RigidBodyConfig;
typedef struct {
RigidBodyConfig p;
vec3 pos;
vec3 speed; // linear speed
mat3 rot;
vec3 angular_speed;
} RigidBodyState;
/* Transforms points relative to center of mass. To get model_t for mesh, multiply transition matrix by this matrix */
mat4 RigidBodyState_get_tran_mat(const RigidBodyState* self){
return mat4_mul_mat4(
marie_translation_mat4(self->pos),
marie_mat3_to_mat4(self->rot));
AliceGenericMeshPath AliceGenericMeshPath_for_puck(){
return (AliceGenericMeshPath){
.topology_path = VecU8_fmt("gen/l2/models/puck.AliceGenericMesh"),
.diffuse_texture_path = VecU8_fmt("src/l3/textures/puck_diffuse.png"),
.normal_texture_path = VecU8_fmt("gen/l2/textures/puck_NORMAL.png"),
.specular_texture_path = VecU8_fmt("src/l3/textures/puck_specular.png"),
};
}
mat4 RigidBodyState_get_tran_mat_of_mesh(const RigidBodyState* self) {
return mat4_mul_mat4(RigidBodyState_get_tran_mat(self),
marie_translation_mat4(vec3_minus(self->p.mass_center)));
}
void main_h_on_wayland_keyboard_key(void* data, U32 keysym, U32 act){
/* point `M` is relative to the center of mass */
vec3 RigidBodyState_translate_point(const RigidBodyState* self, vec3 M){
return vec3_add_vec3(self->pos, mat3_mul_vec3(self->rot, M));
}
/* point Mf is relative to visual mesh coordinate system origin */
vec3 RigidBodyState_translate_point_of_mesh(const RigidBodyState* self, vec3 Mf){
return RigidBodyState_translate_point(self, vec3_minus_vec3(Mf, self->p.mass_center));
}
/* point T is in global coordinate system. It is returned to coordinate system relative to center of mass */
vec3 RigidBodyState_back_translate_point(const RigidBodyState* self, vec3 T) {
return mat3_mul_vec3(mat3_transpose(self->rot), vec3_minus_vec3(T, self->pos));
}
vec3 RigidBodyState_back_translate_point_of_mesh(const RigidBodyState* self, vec3 T) {
return vec3_add_vec3(RigidBodyState_back_translate_point(self, T), self->p.mass_center);
}
typedef struct {
float mass; /* In kg, Not zero */
float velocity; /* Not zero */
} BulletConfig;
vec3 project_dir_onto_plane_xz(vec3 v){
vec2 xz = vec2_normalize((vec2){v.x, v.z});
return (vec3){xz.x, 0, xz.y};
}
typedef struct{
Alice* alice;
LucyFace* font_face;
RBTreeNodeLucyFaceFixedSize* font_face_of_size_40;
vec3 hero_pos;
ListNodeAliceGenericMeshHand* ROA_mesh;
GenericMeshTopology ROA_topology;
RigidBodyState ROA_state;
ListNodeAliceShinyMeshHand* LS_mesh;
VecLightSourceState LS_state;
BulletConfig bullet_config;
U64 misses_count;
U64 hits_count;
Vecvec3 bullets_stuck_on_ROA;
} R4BetaState;
/* We are surrounded by a giant cubic mesh of light sources */
const int lighting_system_dim = 4;
void physics_update(R4BetaState* st, float t){
RigidBodyState *roa_st = &st->ROA_state;
roa_st->pos = vec3_add_vec3(roa_st->pos, vec3_mul_scal(roa_st->speed, t));
mat3 rot_gain;
float rot_speed_amplitude = vec3_length(roa_st->angular_speed);
if (rot_speed_amplitude < 0.00001f){
rot_gain = mat3_E;
} else {
vec3 r = vec3_div_by_scal(roa_st->angular_speed, rot_speed_amplitude);
rot_gain = marie_3d_rot_mat3(r, rot_speed_amplitude);
}
roa_st->rot = mat3_mul_mat3(rot_gain, roa_st->rot);
}
/* Changs linear and rotational speed of RigidBody based on the impact with bullet.
* It does not update mass, moment of intertia, center of mass of rigid body. It is as if the bullet was
* very light compared to rigid body.
* imp is impact position (relative to center of mass)
* m2 is the mass of bullet. `v` is the speed of bullet */
void RigidBodyState_when_shot(RigidBodyState* self, vec3 imp, float m2, vec3 v){
vec3 IO = vec3_minus(imp);
float IO_norm_sq = vec3_dot(IO, IO);
vec3 linear_speed_gain;
if (IO_norm_sq < 0.00001f) {
linear_speed_gain = v;
} else {
vec3 v_projected = vec3_mul_scal(IO, vec3_dot(IO, v) / IO_norm_sq);
linear_speed_gain = vec3_mul_scal(v_projected, m2 / self->p.mass);
}
self->speed = vec3_add_vec3(self->speed, linear_speed_gain);
vec3 www = vec3_mul_scal(vec3_cross(v, IO), m2);
vec3 w = vec3_normalize(www);
float I = quad_form3_mul_vec(self->p.inertia_moment, w);
vec3 angular_speed_gain = vec3_div_by_scal(www, I);
self->angular_speed = vec3_add_vec3(self->angular_speed, angular_speed_gain);
}
void main_h_on_wl_pointer_button(void* data, U32 button, U32 act){
R4BetaState *st = data;
Alice* alice = st->alice;
if (button == BTN_LEFT && act == WL_POINTER_BUTTON_STATE_PRESSED) {
vec3 P = alice->cam_info.cam.pos;
vec3 dir = vec3_minus(alice->cam_info.cam.cam_basis.z);
vec3 Q = vec3_add_vec3(P, dir);
bool hit = false;
vec3 impact;
VecU32* Is = &st->ROA_topology.indexes;
VecGenericMeshVertexInc* Vs = &st->ROA_topology.vertices;
assert(Is->len % 3 == 0);
for (size_t i = 0; i < Is->len; i += 3) {
vec3 A = Vs->buf[Is->buf[i + 0]].pos;
vec3 B = Vs->buf[Is->buf[i + 1]].pos;
vec3 C = Vs->buf[Is->buf[i + 2]].pos;
A = RigidBodyState_translate_point_of_mesh(&st->ROA_state, A);
B = RigidBodyState_translate_point_of_mesh(&st->ROA_state, B);
C = RigidBodyState_translate_point_of_mesh(&st->ROA_state, C);
hit = marie_intersect_triangle_and_ray(A, B, C, P, Q, &impact);
if (hit)
break;
}
if (hit) {
st->hits_count++;
/* See, for some dumb reason I decided that bullets share a mesh with light sources. They are all cubes */
// U64 n = st->bullets_stuck_on_ROA.len + st->LS_state.len;
assert(st->bullets_stuck_on_ROA.len + st->LS_state.len == st->LS_mesh->el.instance_attr.count);
vec3 OI = vec3_minus_vec3(impact, st->ROA_state.pos);
/* OI is only a partial "back translation" */
vec3 impact_in_MC_coords = mat3_mul_vec3(mat3_transpose(st->ROA_state.rot), OI);
Vecvec3_append(&st->bullets_stuck_on_ROA, impact_in_MC_coords);
/* Adjusting linear speed and rotational speed of ROA */
RigidBodyState_when_shot(&st->ROA_state, OI, st->bullet_config.mass,
vec3_mul_scal(dir, st->bullet_config.velocity));
} else {
st->misses_count++;
}
}
}
void main_h_on_wl_keyboard_key(void* data, U32 keysym, U32 act){
R4BetaState *st = data;
// Alice* alice = st->alice;
if (act == WL_KEYBOARD_KEY_STATE_PRESSED) {
if (keysym == XKB_KEY_9) {
if (st->bullet_config.velocity > 0.1) {
st->bullet_config.velocity *= 0.5f;
}
} else if (keysym == XKB_KEY_0) {
if (st->bullet_config.velocity < 1000000) {
st->bullet_config.velocity *= 2;
}
} else if (keysym == XKB_KEY_7) {
if (st->bullet_config.mass > 0.0005) {
st->bullet_config.mass *= 0.5f;
}
} else if (keysym == XKB_KEY_8) {
if (st->bullet_config.mass < 100) {
st->bullet_config.mass *= 2;
}
} else if (keysym == XKB_KEY_semicolon) {
st->ROA_state.speed = (vec3){0};
} else if (keysym == XKB_KEY_colon){
if (vec3_length(st->ROA_state.speed) < 0.2) {
st->ROA_state.speed = (vec3){0};
} else {
st->ROA_state.speed = vec3_mul_scal(st->ROA_state.speed, 0.4f);
}
if (vec3_length(st->ROA_state.angular_speed) < 0.005) {
st->ROA_state.angular_speed = (vec3){0};
} else {
st->ROA_state.angular_speed = vec3_mul_scal(st->ROA_state.angular_speed, 0.5f);
}
}
}
}
void main_h_on_another_frame(void* data, float fl){
R4BetaState *st = data;
Alice* alice = st->alice;
vec3 proj_back = project_dir_onto_plane_xz(alice->cam_info.cam.cam_basis.z);
vec3 proj_right = project_dir_onto_plane_xz(alice->cam_info.cam.cam_basis.x);
const float max_speed = 10.f;
if (alice->wl.first_0x80_keys['w']) {
st->hero_pos = vec3_minus_vec3(st->hero_pos, vec3_mul_scal(proj_back, fl * max_speed));
}
if (alice->wl.first_0x80_keys['s']) {
st->hero_pos = vec3_add_vec3(st->hero_pos, vec3_mul_scal(proj_back, fl * max_speed));
}
if (alice->wl.first_0x80_keys['a']) {
st->hero_pos = vec3_minus_vec3(st->hero_pos, vec3_mul_scal(proj_right, fl * max_speed));
}
if (alice->wl.first_0x80_keys['d']) {
st->hero_pos = vec3_add_vec3(st->hero_pos, vec3_mul_scal(proj_right, fl * max_speed));
}
if (alice->wl.first_0x80_keys['e']) {
st->hero_pos = vec3_add_vec3(st->hero_pos, (vec3){0, max_speed * fl, 0});
}
if (alice->wl.first_0x80_keys['q']) {
st->hero_pos = vec3_add_vec3(st->hero_pos, (vec3){0, -max_speed * fl, 0});
}
alice->cam_info.cam.pos = st->hero_pos;
physics_update(st, fl);
AliceGenericMeshHand_set_inst(&st->ROA_mesh->el, 0, (GenericMeshInstanceInc){
.model_t = RigidBodyState_get_tran_mat_of_mesh(&st->ROA_state),
});
Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&st->alice->pipeline0_ubo.staging);
assert(pipeline_0_ubo_point_light_max_count >= st->LS_state.len);
for (size_t i = 0; i < st->LS_state.len; i++) {
LightSourceState* ls = &st->LS_state.buf[i];
AliceShinyMeshHand_set_inst(&st->LS_mesh->el, i, (ShinyMeshInstanceInc){
.color_on = ls->color,
.model_t = marie_translation_mat4(ls->pos),
});
ubo->point_light_arr[i] = (Pipeline0PointLight){
.pos = ls->pos, .color = vec3_mul_scal(ls->color, 21)};
}
if (st->LS_state.len + st->bullets_stuck_on_ROA.len > st->LS_mesh->el.instance_attr.count) {
AliceShinyMeshHand_resize_instance_arr(alice, &st->LS_mesh->el, st->LS_state.len + st->bullets_stuck_on_ROA.len);
}
for (size_t i = 0; i < st->bullets_stuck_on_ROA.len; i++) {
vec3 bul_pos = st->bullets_stuck_on_ROA.buf[i];
AliceShinyMeshHand_set_inst(&st->LS_mesh->el, st->LS_state.len + i, (ShinyMeshInstanceInc){
.color_on = (vec3){2, 0, 0},
.model_t = mat4_mul_mat4(mat4_mul_mat4(
RigidBodyState_get_tran_mat(&st->ROA_state),
marie_translation_mat4(bul_pos)),
marie_3d_scal_mat4(0.069f)),
});
}
LucyRenderer_clear(&alice->lucy_renderer);
VecU8 text = VecU8_new();
VecU8_append_fmt(&text, "Bullet mass = %v ; bullet velocity = %v\n",
VecU8_format("%.4f", st->bullet_config.mass), VecU8_format("%.4f", st->bullet_config.velocity));
if (st->misses_count == 0 && st->hits_count == 0) {
VecU8_append_cstr(&text, "Press BTN_LEFT to shoot\n");
}
if (st->misses_count > 0) {
VecU8_append_fmt(&text, "You missed %u times\n", st->misses_count);
}
if (st->hits_count > 0) {
VecU8_append_fmt(&text, "You hit ROA %u times\n", st->hits_count);
}
LucyRenderer_add_simple_label(&alice->lucy_renderer, st->font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
VecU8_to_span(&text), (ivec2){10, 10});
VecU8_drop(text);
}
void run_app(){
R4BetaState st;
st.hero_pos = (vec3){0, 0.81f, 0};
int main(){
Alice* alice = Alice_new();
st.alice = alice;
st.alice->guest = &st;
st.font_face = LucyFace_new(st.alice->ft_library, &st.alice->lucy_cache,
vcstr("./src/l3/fonts/DMSerifText-Regular.ttf"));
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("..."), (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});
VecU8 ROA_mesh_path = vcstr("./gen/l2/models/log_10_2_6.AliceGenericMesh");
st.ROA_topology = alice_expect_read_generic_mesh_from_file(ROA_mesh_path);
ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6));
AliceGenericMeshHand_resize_instance_arr(alice, &model_gen->el, 1);
st.ROA_mesh = Alice_add_generic_mesh(st.alice, &st.ROA_topology,
(AliceGenericMeshTexturePaths){
.diffuse_texture_path = vcstr("./src/l3/textures/log_10_2_6_diffuse.png"),
.normal_texture_path = vcstr("./gen/l2/textures/log_10_2_6_NORMAL.png"),
.specular_texture_path = vcstr("./src/l3/textures/log_10_2_6_specular.png")
});
AliceGenericMeshHand_resize_instance_arr(st.alice, &st.ROA_mesh->el, 1);
const float gamma_l_c = 4.f / 3 / M_PIf;
st.ROA_state = (RigidBodyState){
.p.mass = 1.f * 1/4 * M_PIf * 2*2 * 10,
.p.inertia_moment = (mat3){
.x = { 16.926308911016392, 1.5411267097545367e-13, -9.491580156388568e-15},
.y = { 1.5411267097545367e-13, 259.0981544556158, 2.539003832491438},
.z = {-9.491580156388568e-15, 2.539003832491438, 259.09815445561975},
},
.p.mass_center = (vec3){5, 2 * gamma_l_c, -2 * gamma_l_c},
.pos = (vec3){11.f, 3, 4}, .speed = {0},
.rot = mat3_E, .angular_speed = (vec3){0}};
ShinyMeshTopology LS_topology = alice_expect_read_shiny_mesh_from_file(vcstr("./gen/l2/models/cube.AliceShinyMesh"));
st.LS_mesh = Alice_add_shiny_mesh(st.alice, &LS_topology);
ShinyMeshTopology_drop(LS_topology);
const int cubes_in_light_wall = lighting_system_dim * lighting_system_dim;
st.LS_state = VecLightSourceState_new_reserved(cubes_in_light_wall * 6);
const vec3 light_cage_ways[6][2] = {
{{0, 1, 0}, {0, 0, 1}}, {{0, 0, 1}, {0, 1, 0}},
{{1, 0, 0}, {0, 0, 1}}, {{0, 0, 1}, {1, 0, 0}},
{{1, 0, 0}, {0, 1, 0}}, {{0, 1, 0}, {1, 0, 0}},
};
const float light_case_edge_offset = 6.1f;
const float light_case_gap = 12.5f;
const float light_cage_rad = (float)(lighting_system_dim - 1) * light_case_gap / 2 + light_case_edge_offset;
for (U64 s = 0; s < 6; s++) {
vec3 u = light_cage_ways[s][0];
vec3 v = light_cage_ways[s][1];
vec3 dir = vec3_mul_scal(vec3_cross(u, v), light_cage_rad);
for (U64 i = 0; i < lighting_system_dim; i++) {
for (U64 j = 0; j < lighting_system_dim; j++) {
vec3 clr = sample_rainbow_color();
VecLightSourceState_append(&st.LS_state, (LightSourceState){
.pos = vec3_add_vec3(dir, vec3_add_vec3(
vec3_mul_scal(u, -light_cage_rad + light_case_edge_offset + light_case_gap * (float)i),
vec3_mul_scal(v, -light_cage_rad + light_case_edge_offset + light_case_gap * (float)j))),
.color = clr,
.magnitude = 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}),
});
}
}
AliceShinyMeshHand_resize_instance_arr(st.alice, &st.LS_mesh->el, st.LS_state.len);
Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&st.alice->pipeline0_ubo.staging);
assert(pipeline_0_ubo_point_light_max_count >= st.LS_state.len);
ubo->point_light_count = (int)st.LS_state.len;
ubo->spotlight_count = 0;
// ListNodeAliceShinyMeshHand *model_sh = Alice_add_shiny_mesh(alice, vcstr("./gen/l2/models/cube.AliceShinyMesh"));
// AliceShinyMeshHand_resize_instance_arr(alice, &model_sh->el, 100);
st.bullet_config = (BulletConfig){.mass = 0.01f, .velocity = 1000};
st.misses_count = 0;
st.hits_count = 0;
st.bullets_stuck_on_ROA = Vecvec3_new();
// 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}),
// });
// }
// }
Alice_mainloop(st.alice, &(AliceCallbacks){
.on_wl_pointer_button = main_h_on_wl_pointer_button,
.on_wl_keyboard_key = main_h_on_wl_keyboard_key,
// 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* 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){
// .model_t = marie_translation_mat4((vec3){11.f * (float)X - 20, -1, 4.f * (float)Z - 10}),
// });
// }
// }
Alice_mainloop(alice, &(AliceCallbacks){
.on_wl_keyboard_key = main_h_on_wayland_keyboard_key,
.on_another_frame = main_h_on_another_frame,
});
}
int main(){
run_app();
}
return 0;
}

View File

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Some files were not shown because too many files have changed in this diff Show More