Compare commits
No commits in common. "master" and "r0-to-allie" have entirely different histories.
master
...
r0-to-alli
1
.gitignore
vendored
@ -17,4 +17,3 @@ GRAPH*.png
|
||||
SICK_JOKE*
|
||||
*.hi
|
||||
*_stub.h
|
||||
copying_to_cpp.sh
|
||||
@ -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)
|
||||
|
||||
14
Makefile
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
14
src/l1/anne/marie/graphics_geom.h
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -3,38 +3,38 @@
|
||||
int main(){
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i", 0);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("0")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("0")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i%i%i%i", -1LL, 0LL, 44LL, -231LL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("-1044-231")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("-1044-231")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i", 44LL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("44")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("44")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%u", 44ULL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("44")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("44")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%u %i", 18446744073709551615ULL, -1LL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("18446744073709551615 -1")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("18446744073709551615 -1")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i %i", 9223372036854775807LL, -9223372036854775807LL-1);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("9223372036854775807 -9223372036854775808")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("9223372036854775807 -9223372036854775808")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 vec2 = vcstr("vec2");
|
||||
VecU8 res = VecU8_fmt("%i %v %i", -1230LL, vec2, 1340LL);
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("-1230 vec2 1340")));
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("-1230 vec2 1340")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -4,16 +4,13 @@
|
||||
#include "l1_5_templ_very_base.h"
|
||||
#include "margaret.h"
|
||||
#include "lucy.h"
|
||||
#include "gui.h"
|
||||
|
||||
int main() {
|
||||
mkdir_nofail("l1_5");
|
||||
mkdir_nofail("l1_5/eve");
|
||||
generate_l1_5_liza_headers();
|
||||
generate_l1_5_template_instantiation_for_base_types();
|
||||
generate_l1_5_template_instantiations_for_margaret();
|
||||
generate_l1_5_lucy_headers();
|
||||
generate_l1_5_gui_headers();
|
||||
finish_layer(cstr("l1_5"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,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
|
||||
});
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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};
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdlib.h"
|
||||
|
||||
float frand01(void) {
|
||||
return (float)rand() / (float)RAND_MAX;
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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}};
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -11,7 +11,6 @@ Callbacks(..), aliceMainloop, newAlice, aliceSetSkyColor, aliceNewLucyFace,
|
||||
aliceLucyFaceOfSize, lucyFaceAddGlyphs, aliceClearText, aliceAddText,
|
||||
aliceAddGenericMeshHand, aliceGenericMeshResizeInstanceArr, aliceGenericMeshSetInst,
|
||||
aliceAddShinyMeshHand, aliceShinyMeshResizeInstanceArr, aliceShinyMeshSetInst, aliceGetCamBack,
|
||||
aliceGetCamRight, aliceGetCamUp, aliceSetFOV,
|
||||
aliceGetCamPos, aliceSetCamPos, aliceSetPointLightCount, aliceSetPointLight,
|
||||
aliceIsPressed
|
||||
) where
|
||||
@ -23,6 +22,7 @@ import Data.Int (Int8, Int16, Int32, Int64)
|
||||
import Foreign.Ptr (Ptr, FunPtr, nullPtr, plusPtr, castPtr)
|
||||
import Foreign.Marshal.Alloc (alloca)
|
||||
import Foreign.Storable (Storable(..))
|
||||
import Data.IORef (newIORef, readIORef, writeIORef, modifyIORef)
|
||||
import qualified Data.Text
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Data.ByteString (useAsCStringLen)
|
||||
@ -58,16 +58,17 @@ instance Storable AliceGenericMeshInstance where
|
||||
peek _ = error "Please don't"
|
||||
poke ptr (AliceGenericMeshInstance modelT) = poke (castPtr ptr :: Ptr Mat4) modelT
|
||||
|
||||
-- model_t color_on
|
||||
data AliceShinyMeshInstance = AliceShinyMeshInstance Mat4 Vec3
|
||||
-- model_t color_off color_on
|
||||
data AliceShinyMeshInstance = AliceShinyMeshInstance Mat4 Vec3 Vec3
|
||||
|
||||
instance Storable AliceShinyMeshInstance where
|
||||
sizeOf _ = sizeOf (undefined :: Mat4) + sizeOf (undefined :: Vec3)
|
||||
sizeOf _ = sizeOf (undefined :: Mat4)
|
||||
alignment _ = 4
|
||||
peek _ = error "Don't do that, please"
|
||||
poke ptr (AliceShinyMeshInstance modelT colorOn) = do
|
||||
poke ptr (AliceShinyMeshInstance modelT colorOff colorOn) = do
|
||||
poke (castPtr ptr :: Ptr Mat4) modelT
|
||||
poke (castPtr (ptr `plusPtr` (sizeOf (undefined :: Mat4))) :: Ptr Vec3) colorOn
|
||||
poke (castPtr (ptr `plusPtr` (sizeOf (undefined :: Mat4)) ) :: Ptr Vec3) colorOff
|
||||
poke (castPtr (ptr `plusPtr` (sizeOf (undefined :: Mat4)) `plusPtr` (sizeOf (undefined :: Vec3))) :: Ptr Vec3) colorOn
|
||||
|
||||
-- pos color
|
||||
data AlicePointLight = AlicePointLight Vec3 Vec3
|
||||
@ -96,6 +97,17 @@ aliceMainloop alice cb = alloca $ \ptr -> do
|
||||
poke ptr cb
|
||||
allieAliceMainloop alice ptr
|
||||
|
||||
--aliceClearScreenTextLabel :: AliceAnotherFrameCap s -> IO ()
|
||||
--aliceClearScreenTextLabel (AliceAnotherFrameCap alice) = allieAliceClearScreenText alice
|
||||
|
||||
--aliceAddScreenTextLabel :: AliceAnotherFrameCap s -> String -> IO ()
|
||||
--aliceAddScreenTextLabel (AliceAnotherFrameCap alice) str = useAsCStringLen
|
||||
-- (encodeUtf8 $ Data.Text.pack $ str) $ \(cstr, len) ->
|
||||
-- allieAliceAddScreenTextLabel alice (castPtr cstr) (fromIntegral len)
|
||||
|
||||
|
||||
--allieRunAlice :: Callbacks ->
|
||||
|
||||
useAsUtf8StringLen :: String -> (Ptr Word8 -> Word64 -> IO a) -> IO a
|
||||
useAsUtf8StringLen str cb = useAsCStringLen (encodeUtf8 $ Data.Text.pack $ str) $ \(cstr, len) -> cb (castPtr cstr) (fromIntegral len)
|
||||
|
||||
@ -168,20 +180,7 @@ aliceGetCamBack alice = alloca $ \ptr -> do
|
||||
allie_alice_get_cam_back alice ptr
|
||||
peek ptr
|
||||
|
||||
foreign import ccall "allie_alice_get_cam_right" allie_alice_get_cam_right :: Alice -> Ptr Vec3 -> IO ()
|
||||
|
||||
aliceGetCamRight :: Alice -> IO Vec3
|
||||
aliceGetCamRight alice = alloca $ \ptr -> do
|
||||
allie_alice_get_cam_right alice ptr
|
||||
peek ptr
|
||||
|
||||
foreign import ccall "allie_alice_get_cam_up" allie_alice_get_cam_up :: Alice -> Ptr Vec3 -> IO ()
|
||||
|
||||
aliceGetCamUp :: Alice -> IO Vec3
|
||||
aliceGetCamUp alice = alloca $ \ptr -> do
|
||||
allie_alice_get_cam_up alice ptr
|
||||
peek ptr
|
||||
|
||||
-- todo: add right and up
|
||||
|
||||
foreign import ccall "allie_alice_get_cam_pos" allie_alice_get_cam_pos :: Alice -> Ptr Vec3 -> IO ()
|
||||
|
||||
@ -195,9 +194,6 @@ foreign import ccall "allie_alice_set_cam_pos" allie_alice_set_cam_pos :: Alice
|
||||
aliceSetCamPos :: Alice -> Vec3 -> IO ()
|
||||
aliceSetCamPos alice (Vec3 x y z) = allie_alice_set_cam_pos alice x y z
|
||||
|
||||
-- Easy mapping
|
||||
foreign import ccall "allie_alice_set_fov" aliceSetFOV :: Alice -> Float -> IO ()
|
||||
|
||||
-- Maps well
|
||||
foreign import ccall "allie_alice_set_point_light_count" aliceSetPointLightCount :: Alice -> Int -> IO ()
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
module Geom(Vec2(..), Vec3(..), Vec4(..), Mat4(..), Addable(..), Multipliable(..), mat4Transit, mat4rot3d,
|
||||
HasLength, normalize) where
|
||||
module Geom(Vec2(..), Vec3(..), Vec4(..), Mat4(..), Addable(..), Multipliable(..), mat4Transit) where
|
||||
|
||||
import Foreign.Storable(Storable(..))
|
||||
import Foreign.Ptr (Ptr, castPtr, plusPtr)
|
||||
@ -44,24 +43,10 @@ instance Multipliable Vec4 Float Vec4 where
|
||||
|
||||
data Mat4 = Mat4 !Vec4 !Vec4 !Vec4 !Vec4
|
||||
|
||||
instance Multipliable Mat4 Vec4 Vec4 where
|
||||
(Mat4 vx vy vz vw) ^*^ (Vec4 ax ay az aw) = (vx ^*^ ax ^+^ vy ^*^ ay ^+^ vz ^*^ az ^+^ vw ^*^ aw)
|
||||
|
||||
instance Multipliable Mat4 Mat4 Mat4 where
|
||||
m ^*^ (Mat4 bx by bz bw) = Mat4 (m ^*^ bx) (m ^*^ by) (m ^*^ bz) (m ^*^ bw)
|
||||
|
||||
mat4Transit :: Vec3 -> Mat4
|
||||
mat4Transit (Vec3 x y z) = Mat4 (Vec4 1 0 0 0) (Vec4 0 1 0 0) (Vec4 0 0 1 0) (Vec4 x y z 1)
|
||||
|
||||
mat4rot3d :: Vec3 -> Float -> Mat4
|
||||
mat4rot3d (Vec3 rx ry rz) a = let cosa = cos(a) in let sina = sin(a) in
|
||||
Mat4
|
||||
(Vec4 (rx * rx * (1 - cosa) + cosa) (rx * ry * (1 - cosa) + sina * rz) (rx * rz * (1 - cosa) - sina * ry) 0)
|
||||
(Vec4 (rx * ry * (1 - cosa) - sina * rz) (ry * ry * (1 - cosa) + cosa) (ry * rz * (1 - cosa) + sina * rx) 0)
|
||||
(Vec4 (rx * rz * (1 - cosa) + sina * ry) (ry * rz * (1 - cosa) - sina * rx) (rz * rz * (1 - cosa) + cosa) 0)
|
||||
|
||||
(Vec4 0 0 0 1)
|
||||
|
||||
|
||||
|
||||
instance Storable Vec2 where
|
||||
sizeOf _ = 2 * sizeOf (undefined :: Float)
|
||||
@ -127,13 +112,4 @@ instance Storable Mat4 where
|
||||
poke (castPtr ptr) v1
|
||||
poke (ptr `plusPtr` vec4Size) v2
|
||||
poke (ptr `plusPtr` (2 * vec4Size)) v3
|
||||
poke (ptr `plusPtr` (3 * vec4Size)) v4
|
||||
|
||||
class HasLength a where
|
||||
vlength :: a -> Float
|
||||
|
||||
normalize :: (Multipliable a Float a, HasLength a) => a -> a
|
||||
normalize v = v ^*^ (1 / (vlength v))
|
||||
|
||||
instance HasLength Vec2 where
|
||||
vlength (Vec2 a b) = sqrt (a * a + b * b)
|
||||
poke (ptr `plusPtr` (3 * vec4Size)) v4
|
||||
2194
src/l2/allie/allie.c
504
src/l2/anne/r4.h
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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"
|
||||
@ -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;
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../lucy/glyph_render.h"
|
||||
@ -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};
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
1
src/l2/margaret/allocator_base.h
Normal file
@ -0,0 +1 @@
|
||||
|
||||
@ -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
|
||||
@ -241,11 +241,11 @@ void MargaretBufAllocator_free(MargaretBufAllocator* self, MargaretSubbuf alloca
|
||||
|
||||
bool eret = BufRBTree_MapU64ToU64_erase(&allocation.block->occupants, allocation.start);
|
||||
assert(eret);
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
}
|
||||
|
||||
NODISCARD MargaretSubbuf MargaretBufAllocator_alloc(MargaretBufAllocator* self, U64 req_size){
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
req_size = margaret_bump_buffer_size_to_alignment(req_size, self->alignment_exp);
|
||||
|
||||
VkPhysicalDeviceMaintenance3Properties maintenance3_properties = {
|
||||
@ -270,11 +270,11 @@ NODISCARD MargaretSubbuf MargaretBufAllocator_alloc(MargaretBufAllocator* self,
|
||||
new_block->occupation_counter = req_size;
|
||||
bool iret = BufRBTree_MapU64ToU64_insert(&new_block->occupants, 0, req_size);
|
||||
assert(iret);
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
return (MargaretSubbuf){.block = &self->blocks.first->el, 0, req_size};
|
||||
}
|
||||
MargaretBufAllocator__put_buf_to_a_gap(self, free_gap.some, req_size);
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
return (MargaretSubbuf){.block = free_gap.some.block, .start = free_gap.some.start, req_size};
|
||||
}
|
||||
|
||||
@ -305,7 +305,7 @@ NODISCARD MargaretSubbuf MargaretBufAllocator_expand(
|
||||
if (allocation->start + bigger_size > right_free_space.start + right_free_space.len){
|
||||
return MargaretBufAllocator_alloc(self, bigger_size);
|
||||
}
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator__erase_gap(self, allocation->block, right_free_space.start, right_free_space.len);
|
||||
MargaretBufAllocator__insert_gap(self, allocation->block,
|
||||
allocation->start + bigger_size,
|
||||
@ -315,7 +315,7 @@ NODISCARD MargaretSubbuf MargaretBufAllocator_expand(
|
||||
U64 my_it = BufRBTree_MapU64ToU64_find(&allocation->block->occupants, allocation->start);
|
||||
assert(my_it > 0 && my_it <= allocation->block->occupants.el.len);
|
||||
allocation->block->occupants.el.buf[my_it - 1].value = bigger_size;
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
return (MargaretSubbuf){0};
|
||||
}
|
||||
|
||||
@ -342,9 +342,9 @@ void MargaretBufAllocator_expand_or_move_old_host_visible(
|
||||
memcpy(MargaretSubbuf_get_mapped(&maybe_bigger), MargaretSubbuf_get_mapped(allocation), allocation->len);
|
||||
MargaretBufAllocator_free(self, *allocation);
|
||||
*allocation = maybe_bigger;
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
}
|
||||
// MargaretBufAllocator_debug(self);
|
||||
MargaretBufAllocator_debug(self);
|
||||
}
|
||||
|
||||
/* It tries to expand buffer, but if it fails, it creates a freshly-new buffer. It
|
||||
|
||||
@ -172,6 +172,12 @@
|
||||
* const VkAllocationCallbacks* pAllocator)
|
||||
*/
|
||||
|
||||
// todo: get rid of this whole VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT crap. MargaretMA is for non-host-visible
|
||||
// todo: for staging buffers you better use MargaretBufferAllocator. Ou, yeah, I have yet to write them
|
||||
|
||||
|
||||
// todo: chucking rewrite all of this. Yes, I want all of this crrp rewritten
|
||||
|
||||
#include "../../l1/core/util.h"
|
||||
#include "../../l1_5/core/buff_rb_tree_node.h"
|
||||
#include "../../../gen/l1_5/BufRBTree_MapU64ToU64.h"
|
||||
@ -183,18 +189,10 @@ typedef struct{
|
||||
} MargaretIAFreeSegment;
|
||||
|
||||
#include "../../l1/core/uint_segments.h"
|
||||
|
||||
U64 margaret_get_length_resp_alignment(U64 start, U64 full_len, U8 alignment_exp) {
|
||||
if (start & ((1ull << alignment_exp) - 1)) {
|
||||
U64 pad_left = (1ull << alignment_exp) - (start & ((1ull << alignment_exp) - 1));
|
||||
return full_len >= pad_left ? full_len - pad_left : 0;
|
||||
}
|
||||
return full_len;
|
||||
}
|
||||
|
||||
// todo: substitute U64Segment_get_length_resp_alignment by my own function
|
||||
bool MargaretIAFreeSegment_less_resp_align(const MargaretIAFreeSegment* A, const MargaretIAFreeSegment* B, U8 alignment_exp){
|
||||
U64 A_len = margaret_get_length_resp_alignment(A->start, A->len, alignment_exp);
|
||||
U64 B_len = margaret_get_length_resp_alignment(B->start, B->len, alignment_exp);
|
||||
U64 A_len = U64Segment_get_length_resp_alignment((U64Segment){A->start, A->len}, alignment_exp);
|
||||
U64 B_len = U64Segment_get_length_resp_alignment((U64Segment){B->start, B->len}, alignment_exp);
|
||||
if (A_len == B_len) {
|
||||
if (A->block == B->block) {
|
||||
return A->start < B->start;
|
||||
@ -293,7 +291,6 @@ OptionMargaretIAFreeSegment MargaretMemFreeSpaceManager_search(
|
||||
if (man->free_space_in_memory[alignment_exp].variant == Option_None) {
|
||||
assert(man->set_present.len > 0);
|
||||
assert(man->free_space_in_memory[man->set_present.buf[0]].variant == Option_Some);
|
||||
assert(man->free_space_in_memory[alignment_exp].variant == Option_None);
|
||||
BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment* have = &man->free_space_in_memory[man->set_present.buf[0]].some;
|
||||
man->free_space_in_memory[alignment_exp] = Some_BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment(
|
||||
BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment_new_reserved(alignment_exp, have->el.len));
|
||||
@ -301,7 +298,6 @@ OptionMargaretIAFreeSegment MargaretMemFreeSpaceManager_search(
|
||||
BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment_insert(
|
||||
&man->free_space_in_memory[alignment_exp].some, *VecMargaretIAFreeSegment_at(&have->el, i));
|
||||
}
|
||||
VecU8_append(&man->set_present, alignment_exp);
|
||||
}
|
||||
assert(man->free_space_in_memory[alignment_exp].variant == Option_Some);
|
||||
U64 sit = BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment_find_min_grtr_or_eq(
|
||||
@ -337,7 +333,6 @@ void MargaretImgAllocator__insert_gap(MargaretImgAllocator* self, U64 block_id,
|
||||
|
||||
void MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){
|
||||
VkDeviceMemory memory;
|
||||
printf("DEBUG MargaretImgAllocator: allocating block of size %lu\n", capacity);
|
||||
check(vkAllocateMemory(self->device, &(VkMemoryAllocateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = capacity, .memoryTypeIndex = self->memory_type_id
|
||||
@ -345,33 +340,11 @@ void MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){
|
||||
VecMargaretImgAllocatorOneBlock_append(&self->blocks, (MargaretImgAllocatorOneBlock){
|
||||
.images = BufRBTree_MapU64ToU64_new_reserved(1),
|
||||
.capacity = capacity,
|
||||
.occupation_counter = capacity, // sounds sus
|
||||
.occupation_counter = capacity,
|
||||
.mem_hand = memory,
|
||||
.mapped_memory = NULL /* not supported */});
|
||||
}
|
||||
|
||||
/* Idk where to put it */
|
||||
void MargaretImgAllocator__debug(const MargaretImgAllocator* self){
|
||||
printf("=============================== MargaretImgAllocator ============\n"
|
||||
"All blocks: { ");
|
||||
for (size_t i = 0; i < self->blocks.len; i++) {
|
||||
printf(" %lu/%lu ", self->blocks.buf[i].occupation_counter, self->blocks.buf[i].capacity);
|
||||
}
|
||||
printf("}\n");
|
||||
for (size_t ai = 0; ai < self->mem_free_space.set_present.len; ai++) {
|
||||
U8 alignment_exp = self->mem_free_space.set_present.buf[ai];
|
||||
printf("Free spaces at alignment_exp = %d:\n", (int)alignment_exp);
|
||||
assert(self->mem_free_space.free_space_in_memory[alignment_exp].variant == Option_Some);
|
||||
const BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment* set =
|
||||
&self->mem_free_space.free_space_in_memory[alignment_exp].some;
|
||||
assert(set->guest == alignment_exp);
|
||||
for (size_t i = 0; i < set->el.len; i++) {
|
||||
const MargaretIAFreeSegment *free_seg = &set->el.buf[i];
|
||||
printf(" Block %lu, start %lu, len %lu\n", free_seg->block, free_seg->start, free_seg->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MargaretImgAllocator MargaretImgAllocator_new(
|
||||
VkDevice device, VkPhysicalDevice physical_device, U8 memory_type_id, U64 initial_block_size
|
||||
){
|
||||
@ -384,7 +357,6 @@ MargaretImgAllocator MargaretImgAllocator_new(
|
||||
};
|
||||
MargaretImgAllocator__add_block(&self, initial_block_size);
|
||||
MargaretImgAllocator__insert_gap(&self, 0, 0, initial_block_size);
|
||||
// MargaretImgAllocator__debug(&self);
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -518,7 +490,6 @@ NODISCARD MargaretImgAllocation MargaretImgAllocator__alloc(
|
||||
U64 pitch = self->blocks.buf[self->blocks.len - 1].capacity;
|
||||
// Old blocks remain intact
|
||||
U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(2 * pitch, maintenance3_properties.maxMemoryAllocationSize));
|
||||
// U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(pitch, maintenance3_properties.maxMemoryAllocationSize));
|
||||
MargaretImgAllocator__add_block(self, new_capacity);
|
||||
U64 bid = self->blocks.len - 1;
|
||||
MargaretImgAllocator__insert_gap(self, bid, mem_requirements.size, new_capacity - mem_requirements.size);
|
||||
@ -527,13 +498,11 @@ NODISCARD MargaretImgAllocation MargaretImgAllocator__alloc(
|
||||
bool iret = BufRBTree_MapU64ToU64_insert(&block->images, 0, mem_requirements.size);
|
||||
assert(iret);
|
||||
check(vkBindImageMemory(self->device, fresh_img, block->mem_hand, 0) == VK_SUCCESS);
|
||||
// MargaretImgAllocator__debug(self);
|
||||
return (MargaretImgAllocation){.block = bid, fresh_img, 0};
|
||||
}
|
||||
U64 aligned_pos = MargaretImgAllocator__add_img_given_gap(self, free_gap.some, mem_requirements.size, alignment_exp);
|
||||
VkDeviceMemory memory = VecMargaretImgAllocatorOneBlock_at(&self->blocks, free_gap.some.block)->mem_hand;
|
||||
check(vkBindImageMemory(self->device, fresh_img, memory, aligned_pos) == VK_SUCCESS);
|
||||
// MargaretImgAllocator__debug(self);
|
||||
return (MargaretImgAllocation){.block = free_gap.some.block, .image = fresh_img, .start = aligned_pos};
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -186,8 +186,10 @@ void save_tree_to_file(const BufRBTree_SetS64* set, SpanU8 name){
|
||||
}
|
||||
VecU8_append_span(&graph, cstr("}\n"));
|
||||
mkdir_nofail("GRAPHS");
|
||||
write_file_by_path(VecU8_fmt("GRAPHS/GRAPH_%s.gv", name), VecU8_to_span(&graph));
|
||||
VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.gv%c", name, 0);
|
||||
write_whole_file_or_abort((CSTR)dot_filename_nt.buf, VecU8_to_span(&graph));
|
||||
VecU8_drop(graph);
|
||||
VecU8_drop(dot_filename_nt);
|
||||
VecU8 command_nt = VecU8_fmt("dot -Tpng GRAPHS/GRAPH_%s.gv -o GRAPHS/GRAPH_%s.png%c", name, name, 0);
|
||||
calling_system_func_nofail((CSTR)command_nt.buf);
|
||||
VecU8_drop(command_nt);
|
||||
|
||||
@ -118,8 +118,10 @@ void save_tree_to_file(const RBTree_SetS64* set, SpanU8 name){
|
||||
}
|
||||
VecU8_append_span(&graph, cstr("}\n"));
|
||||
mkdir_nofail("GRAPHS");
|
||||
write_file_by_path(VecU8_fmt("GRAPHS/GRAPH_%s.gv", name), VecU8_to_span(&graph));
|
||||
VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.gv%c", name, 0);
|
||||
write_whole_file_or_abort((CSTR)dot_filename_nt.buf, VecU8_to_span(&graph));
|
||||
VecU8_drop(graph);
|
||||
VecU8_drop(dot_filename_nt);
|
||||
VecU8 command_nt = VecU8_fmt("dot -Tpng GRAPHS/GRAPH_%s.gv -o GRAPHS/GRAPH_%s.png%c", name, name, 0);
|
||||
calling_system_func_nofail((CSTR)command_nt.buf);
|
||||
VecU8_drop(command_nt);
|
||||
|
||||
135
src/l2/tests/r0/textures/bitmap_converter.py
Executable file
@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Convert between custom bottom‑up raw files (.r8g8b8a8 / .r8b8g8 / .r8 / .a8)
|
||||
and normal PNG using Pillow.
|
||||
|
||||
Format
|
||||
------
|
||||
uint32 width (little‑endian)
|
||||
uint32 height (little‑endian)
|
||||
pixel data rows bottom‑first:
|
||||
* .r8g8b8a8 : R G B A (4× uint8)
|
||||
* .r8b8g8 : R G B (3× uint8)
|
||||
* .r8 : R (1× uint8 <- grayscale)
|
||||
* .a8 : A (can convert from it, but can't convert to it)
|
||||
|
||||
CLI
|
||||
---
|
||||
raw -> png : python raw_png_conv.py to_png input.raw output.png
|
||||
png -> raw : python raw_png_conv.py to_raw input.png output.raw
|
||||
"""
|
||||
import argparse
|
||||
import struct
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# Helpers
|
||||
# --------------------------------------------------------------------- #
|
||||
|
||||
|
||||
RAW_FORMATS = {
|
||||
".r8g8b8a8": {"pix_size": 4, "mode": "RGBA"},
|
||||
".r8g8b8": {"pix_size": 3, "mode": "RGB"},
|
||||
".r8": {"pix_size": 1, "mode": "L"},
|
||||
".a8": {"pix_size": 1, "mode": None}, # special-cased (alpha-only)
|
||||
}
|
||||
|
||||
|
||||
def get_fmt(path: Path):
|
||||
fmt = RAW_FORMATS.get(path.suffix.lower())
|
||||
if not fmt:
|
||||
raise ValueError(f"Unknown raw extension: {path.suffix}")
|
||||
return fmt
|
||||
|
||||
|
||||
def read_header_and_data(path: Path, pix_size: int):
|
||||
with path.open("rb") as f:
|
||||
header = f.read(8)
|
||||
if len(header) != 8:
|
||||
raise ValueError("File too short for header")
|
||||
w, h = struct.unpack("<II", header)
|
||||
expected = w * h * pix_size
|
||||
data = f.read()
|
||||
if len(data) != expected:
|
||||
raise ValueError(
|
||||
f"Pixel data length mismatch: expected {expected}, got {len(data)}"
|
||||
)
|
||||
return w, h, data
|
||||
|
||||
|
||||
def read_raw(path: Path) -> Image.Image:
|
||||
"""Load any supported raw file -> Pillow Image."""
|
||||
spec = get_fmt(path)
|
||||
w, h, data = read_header_and_data(path, spec["pix_size"])
|
||||
|
||||
row_len = w * spec["pix_size"]
|
||||
rows = [data[i : i + row_len] for i in range(0, len(data), row_len)]
|
||||
top_down = b"".join(reversed(rows)) # flip bottom‑up -> top‑down
|
||||
|
||||
# Special handling for .a8 (alpha-only -> LA with black color)
|
||||
if path.suffix.lower() == ".a8":
|
||||
big = bytearray(4 * len(top_down))
|
||||
big[3::4] = top_down
|
||||
big = bytes(big)
|
||||
return Image.frombytes("RGBA", (w, h), big)
|
||||
|
||||
# Normal cases can be constructed directly
|
||||
return Image.frombytes(spec["mode"], (w, h), top_down)
|
||||
|
||||
|
||||
def write_raw(img: Image.Image, path: Path) -> None:
|
||||
"""Write Pillow Image -> raw file chosen by path suffix."""
|
||||
ext = path.suffix.lower()
|
||||
spec = get_fmt(path)
|
||||
|
||||
if ext == ".a8":
|
||||
raise ValueError("Don't convert to .a8 format")
|
||||
|
||||
target_mode = spec["mode"]
|
||||
if img.mode != target_mode:
|
||||
img = img.convert(target_mode)
|
||||
|
||||
w, h = img.size
|
||||
data = img.tobytes()
|
||||
row_len = w * spec["pix_size"]
|
||||
rows = [data[i : i + row_len] for i in range(0, len(data), row_len)]
|
||||
bottom_first = b"".join(reversed(rows)) # top‑down -> bottom‑up
|
||||
|
||||
with path.open("wb") as f:
|
||||
f.write(struct.pack("<II", w, h))
|
||||
f.write(bottom_first)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# CLI
|
||||
# --------------------------------------------------------------------- #
|
||||
|
||||
def to_png(src: Path, dst: Path):
|
||||
read_raw(src).save(dst, "PNG")
|
||||
|
||||
|
||||
def to_raw(src: Path, dst: Path):
|
||||
write_raw(Image.open(src), dst)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Convert raw <-> PNG")
|
||||
sub = ap.add_subparsers(dest="cmd", required=True)
|
||||
p_png = sub.add_parser("to_png", help="raw -> png")
|
||||
p_png.add_argument("src", type=Path)
|
||||
p_png.add_argument("dst", type=Path)
|
||||
p_raw = sub.add_parser("to_raw", help="png -> raw")
|
||||
p_raw.add_argument("src", type=Path)
|
||||
p_raw.add_argument("dst", type=Path)
|
||||
args = ap.parse_args()
|
||||
|
||||
if args.cmd == "to_png":
|
||||
to_png(args.src, args.dst)
|
||||
else:
|
||||
to_raw(args.src, args.dst)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ void BoxLizaSound_drop(BoxLizaSound self) {
|
||||
free(self.m);
|
||||
}
|
||||
|
||||
#include "../../../../gen/l1/eve/r2/VecBoxLizaSound.h"
|
||||
#include "../../../../gen/l2/eve/r2/VecBoxLizaSound.h"
|
||||
|
||||
typedef struct {
|
||||
bool stop;
|
||||
|
||||
@ -1,232 +0,0 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sound/asound.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DESIRED_SAMPLE_RATE 44100
|
||||
#define DESIRED_CHANNELS 2 // Prefer stereo, as mono often not supported on hardware
|
||||
#define DESIRED_PERIOD_SIZE 1024
|
||||
#define DESIRED_PERIODS 4
|
||||
#define FORMAT SNDRV_PCM_FORMAT_S16_LE
|
||||
#define DURATION 5 // seconds
|
||||
#define BYTES_PER_SAMPLE 2
|
||||
|
||||
int main() {
|
||||
int card = -1, device = -1;
|
||||
FILE *proc = fopen("/proc/asound/pcm", "r");
|
||||
if (!proc) {
|
||||
perror("Failed to open /proc/asound/pcm");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Opened /proc/asound/pcm\n");
|
||||
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), proc)) {
|
||||
if (strstr(line, "playback")) {
|
||||
sscanf(line, "%02d-%02d", &card, &device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(proc);
|
||||
|
||||
if (card < 0 || device < 0) {
|
||||
fprintf(stderr, "No playback devices found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char devname[64];
|
||||
snprintf(devname, sizeof(devname), "/dev/snd/pcmC%dD%dp", card, device);
|
||||
|
||||
int fd = open(devname, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open PCM device");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Opened device\n");
|
||||
|
||||
struct snd_pcm_hw_params params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
// Initialize to full possible ranges for refinement
|
||||
int i;
|
||||
for (i = SNDRV_PCM_HW_PARAM_FIRST_MASK; i <= SNDRV_PCM_HW_PARAM_LAST_MASK; i++) {
|
||||
struct snd_mask *mask = ¶ms.masks[i - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
mask->bits[0] = ~0U;
|
||||
mask->bits[1] = ~0U;
|
||||
}
|
||||
for (i = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; i <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; i++) {
|
||||
struct snd_interval *interval = ¶ms.intervals[i - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
interval->min = 0;
|
||||
interval->max = ~0U;
|
||||
interval->openmin = interval->openmax = 0;
|
||||
interval->integer = 0;
|
||||
}
|
||||
params.rmask = ~0U;
|
||||
params.cmask = 0;
|
||||
params.info = ~0U;
|
||||
|
||||
// Refine to hardware-supported ranges
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, ¶ms) < 0) {
|
||||
perror("Failed initial HW_REFINE");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Refined hw params\n");
|
||||
|
||||
// Set access to RW_INTERLEAVED if supported
|
||||
struct snd_mask *access_mask = ¶ms.masks[SNDRV_PCM_HW_PARAM_ACCESS - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
unsigned int access_bit = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
|
||||
if (!(access_mask->bits[access_bit / 32] & (1U << (access_bit % 32)))) {
|
||||
fprintf(stderr, "RW_INTERLEAVED access not supported\n");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
memset(access_mask, 0, sizeof(*access_mask));
|
||||
access_mask->bits[access_bit / 32] |= (1U << (access_bit % 32));
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_ACCESS);
|
||||
|
||||
// Set format to S16_LE if supported
|
||||
struct snd_mask *format_mask = ¶ms.masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
unsigned int format_bit = FORMAT;
|
||||
if (!(format_mask->bits[format_bit / 32] & (1U << (format_bit % 32)))) {
|
||||
fprintf(stderr, "S16_LE format not supported\n");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
memset(format_mask, 0, sizeof(*format_mask));
|
||||
format_mask->bits[format_bit / 32] |= (1U << (format_bit % 32));
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
|
||||
// Set channels to nearest supported (prefer DESIRED_CHANNELS)
|
||||
struct snd_interval *channels_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_CHANNELS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int channels = DESIRED_CHANNELS;
|
||||
if (channels < channels_int->min) channels = channels_int->min;
|
||||
if (channels > channels_int->max) channels = channels_int->max;
|
||||
if (channels != DESIRED_CHANNELS) {
|
||||
fprintf(stderr, "Adjusted channels to %u (hardware range: %u-%u)\n", channels, channels_int->min, channels_int->max);
|
||||
}
|
||||
channels_int->min = channels_int->max = channels;
|
||||
channels_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
|
||||
// Set sample rate to nearest supported
|
||||
struct snd_interval *rate_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int sample_rate = DESIRED_SAMPLE_RATE;
|
||||
if (sample_rate < rate_int->min) sample_rate = rate_int->min;
|
||||
if (sample_rate > rate_int->max) sample_rate = rate_int->max;
|
||||
if (sample_rate != DESIRED_SAMPLE_RATE) {
|
||||
fprintf(stderr, "Adjusted sample rate to %u Hz (hardware range: %u-%u)\n", sample_rate, rate_int->min, rate_int->max);
|
||||
}
|
||||
rate_int->min = rate_int->max = sample_rate;
|
||||
rate_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_RATE);
|
||||
|
||||
// Set period size to nearest supported
|
||||
struct snd_interval *period_size_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_PERIOD_SIZE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int period_size = DESIRED_PERIOD_SIZE;
|
||||
if (period_size < period_size_int->min) period_size = period_size_int->min;
|
||||
if (period_size > period_size_int->max) period_size = period_size_int->max;
|
||||
if (period_size != DESIRED_PERIOD_SIZE) {
|
||||
fprintf(stderr, "Adjusted period size to %u frames (hardware range: %u-%u)\n", period_size, period_size_int->min, period_size_int->max);
|
||||
}
|
||||
period_size_int->min = period_size_int->max = period_size;
|
||||
period_size_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
|
||||
|
||||
// Set periods (less strict, clamp to range)
|
||||
struct snd_interval *periods_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_PERIODS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int periods = DESIRED_PERIODS;
|
||||
if (periods < periods_int->min) periods = periods_int->min;
|
||||
if (periods > periods_int->max) periods = periods_int->max;
|
||||
if (periods != DESIRED_PERIODS) {
|
||||
fprintf(stderr, "Adjusted periods to %u (hardware range: %u-%u)\n", periods, periods_int->min, periods_int->max);
|
||||
}
|
||||
periods_int->min = periods_int->max = periods;
|
||||
periods_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
|
||||
// Refine again with desired values to confirm
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, ¶ms) < 0) {
|
||||
perror("Failed to refine desired HW params");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Refined hw params the last time\n");
|
||||
|
||||
// Now apply the parameters
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms) < 0) {
|
||||
perror("Failed to set HW params");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("HW params set\n");
|
||||
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_PREPARE, 0) < 0) {
|
||||
perror("Failed to prepare PCM");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Prepared\n");
|
||||
|
||||
// Generate and play sine wave
|
||||
size_t frame_size = channels * BYTES_PER_SAMPLE;
|
||||
short *buffer = malloc(period_size * frame_size);
|
||||
if (!buffer) {
|
||||
perror("Failed to allocate buffer");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long total_frames = (unsigned long)sample_rate * DURATION;
|
||||
unsigned long frames_written = 0;
|
||||
double phase = 0.0;
|
||||
const double freq = 440.0; // Hz
|
||||
const double phase_inc = 2.0 * M_PI * freq / sample_rate;
|
||||
|
||||
while (frames_written < total_frames) {
|
||||
size_t frames_to_write = period_size;
|
||||
if (frames_written + frames_to_write > total_frames) {
|
||||
frames_to_write = total_frames - frames_written;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < frames_to_write; ++j) {
|
||||
short sample = (short)(32767.0 * sin(phase));
|
||||
for (unsigned int ch = 0; ch < channels; ++ch) {
|
||||
buffer[j * channels + ch] = sample;
|
||||
}
|
||||
phase += phase_inc;
|
||||
if (phase >= 2.0 * M_PI) phase -= 2.0 * M_PI;
|
||||
}
|
||||
|
||||
ssize_t bytes_written = write(fd, buffer, frames_to_write * frame_size);
|
||||
printf("bytes written = %lu\n", bytes_written);
|
||||
if (bytes_written < 0) {
|
||||
if (errno == EPIPE) {
|
||||
// Underrun: recover
|
||||
ioctl(fd, SNDRV_PCM_IOCTL_PREPARE, 0);
|
||||
continue;
|
||||
}
|
||||
perror("Write failed");
|
||||
break;
|
||||
}
|
||||
|
||||
frames_written += bytes_written / frame_size;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
// Drain remaining data
|
||||
ioctl(fd, SNDRV_PCM_IOCTL_DRAIN, 0);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 916 KiB |
6026920
src/l3/models/skeleton.obj
113
src/l3/r4/R4.hs
@ -1,16 +1,6 @@
|
||||
import Allie
|
||||
import Geom
|
||||
import Control.Monad (forM_, when)
|
||||
import Data.Char (ord)
|
||||
import Data.IORef (newIORef, readIORef, writeIORef, modifyIORef)
|
||||
import Data.Word(Word32, Word64)
|
||||
|
||||
lucyFaceAddGlyphRange :: LucyFaceFixedSize -> Char -> Char -> IO ()
|
||||
lucyFaceAddGlyphRange ffs a b = lucyFaceAddGlyphs ffs aInt (bInt - aInt + 1)
|
||||
where aInt = ((fromIntegral $ ord a) :: Word32)
|
||||
bInt = ((fromIntegral $ ord b) :: Word32)
|
||||
|
||||
-- Game configurable
|
||||
import Control.Monad (forM_)
|
||||
|
||||
goodColorOfCube :: (Integral a) => a -> Vec3
|
||||
goodColorOfCube i = ((Vec3 100 0 0) ^*^ t) ^+^ ((Vec3 0 50 90) ^*^ (1 - t)) where t = ((fromIntegral i :: Float) / 4)
|
||||
@ -18,114 +8,49 @@ goodColorOfCube i = ((Vec3 100 0 0) ^*^ t) ^+^ ((Vec3 0 50 90) ^*^ (1 - t)) wher
|
||||
goodLightPos :: (Integral a) => a -> Vec3
|
||||
goodLightPos i = ((Vec3 0 2 1) ^*^ t) ^+^ ((Vec3 5 1 1) ^*^ (1 - t)) where t = ((fromIntegral i :: Float) / 4)
|
||||
|
||||
projectDirOntoPlane :: Vec3 -> Vec2
|
||||
projectDirOntoPlane (Vec3 x y z) = normalize (Vec2 x z)
|
||||
|
||||
heroHeight :: Float
|
||||
heroHeight = 1.89
|
||||
|
||||
heroCamPos :: Vec2 -> Vec3
|
||||
heroCamPos (Vec2 x z) = Vec3 x heroHeight z
|
||||
|
||||
puckLevitationHeight :: Float
|
||||
puckLevitationHeight = 0.4 + 0.2
|
||||
|
||||
puckSpots :: [Vec2]
|
||||
puckSpots = [(Vec2 (-10) (-10)), (Vec2 (-15) (-15)) , (Vec2 (-18) (-18)), (Vec2 (-18) (-25)), (Vec2 (-18) (-30))]
|
||||
|
||||
introText :: String
|
||||
introText = "Накануне новогодняя сессия 2025 года. Все были готовы провести экзамен по матану, но злой Гринч похитил 67 " ++
|
||||
"шайб с бергамотом Матвея и улетел. Вся надежда была потеряна, но в полёте Гринч выронил все шайбы, и те упали в Дубки. Тебе " ++
|
||||
"необходимо вернуть их Матвею.\n" ++
|
||||
"Естесственно, вернёшь ты их Гринчу, так как ты и сам не понимаешь преобразования Фурье и хочешь помочь сорвать " ++
|
||||
"экзамен.\n\n" ++
|
||||
"Итак, ты в Дубках..."
|
||||
|
||||
main :: IO()
|
||||
main = do
|
||||
alice <- newAlice
|
||||
aliceSetSkyColor alice (Vec4 0.9 0 0.6 1)
|
||||
aliceSetCamPos alice (Vec3 0 heroHeight 0)
|
||||
face <- aliceNewLucyFace alice "src/l3/fonts/DMSerifText-Regular.ttf"
|
||||
faceOf40 <- aliceLucyFaceOfSize face 40
|
||||
lucyFaceAddGlyphRange faceOf40 ' ' '~'
|
||||
lucyFaceAddGlyphRange faceOf40 'а' 'я'
|
||||
lucyFaceAddGlyphRange faceOf40 'А' 'Я'
|
||||
lucyFaceAddGlyphs faceOf40 32 (126 - 32 + 1)
|
||||
aliceAddText alice faceOf40 (Vec4 1 1 0 1) "Privet" 100 200
|
||||
|
||||
weirdStructure <- aliceAddGenericMeshHand alice "gen/l2/models/log_10_2_6.AliceGenericMesh"
|
||||
"src/l3/textures/log_10_2_6_diffuse.png" "gen/l2/textures/log_10_2_6_NORMAL.png" "src/l3/textures/log_10_2_6_specular.png"
|
||||
aliceGenericMeshResizeInstanceArr alice weirdStructure 1
|
||||
|
||||
aliceGenericMeshSetInst weirdStructure 0 (AliceGenericMeshInstance (mat4Transit (Vec3 (-3.0) (0.0) (-5.0))))
|
||||
|
||||
floorTile <- aliceAddGenericMeshHand alice "gen/l2/models/quad.AliceGenericMesh"
|
||||
"src/l3/textures/asphalt_diffuse.png" "gen/l2/textures/flat_NORMAL.png" "src/l3/textures/funny_floor_specular.png"
|
||||
aliceGenericMeshResizeInstanceArr alice floorTile 49
|
||||
|
||||
puck <- aliceAddGenericMeshHand alice "gen/l2/models/puck.AliceGenericMesh"
|
||||
"src/l3/textures/puck_diffuse.png" "gen/l2/textures/puck_NORMAL.png" "src/l3/textures/puck_specular.png"
|
||||
|
||||
forM_ [0..6] $ \x -> forM_ [0..6] $ \z ->
|
||||
aliceGenericMeshSetInst floorTile (z * 7 + x) (AliceGenericMeshInstance
|
||||
(mat4Transit (Vec3 ((fromIntegral x) * 10 - 35) 0 ((fromIntegral z) * 10 - 35))))
|
||||
aliceGenericMeshSetInst weirdStructure 0 (AliceGenericMeshInstance (mat4Transit (Vec3 (-3.0) (-2.0) (-5.0))))
|
||||
|
||||
cube <- aliceAddShinyMeshHand alice "gen/l2/models/cube.AliceShinyMesh"
|
||||
aliceShinyMeshResizeInstanceArr alice cube 5
|
||||
|
||||
|
||||
aliceSetPointLightCount alice 5
|
||||
forM_ [0..4] $ \i -> do
|
||||
aliceShinyMeshSetInst cube i (AliceShinyMeshInstance (mat4Transit (goodLightPos i)) (goodColorOfCube i))
|
||||
aliceShinyMeshSetInst cube i (AliceShinyMeshInstance (mat4Transit (goodLightPos i)) (Vec3 1 1 1) (goodColorOfCube i))
|
||||
aliceSetPointLight alice (fromIntegral i) (AlicePointLight (goodLightPos i) (goodColorOfCube i))
|
||||
|
||||
aliceGenericMeshResizeInstanceArr alice puck (fromIntegral $ length puckSpots)
|
||||
forM_ (zip[0..] puckSpots) $ \(i, (Vec2 x z)) -> aliceGenericMeshSetInst puck (fromIntegral i) (AliceGenericMeshInstance
|
||||
(mat4Transit (Vec3 x puckLevitationHeight z )))
|
||||
|
||||
heroPos <- newIORef (Vec2 0 0)
|
||||
puckRotation <- newIORef (0 :: Float)
|
||||
|
||||
-- state <- newIORef 67
|
||||
-- Create the Callbacks structure.
|
||||
let callbacks = Callbacks myonKeyboardKey myonAnotherFrame where
|
||||
myonKeyboardKey keysym keyAction = do
|
||||
-- old <- readIORef state
|
||||
-- writeIORef state (old + 1)
|
||||
putStrLn ("Got a keypress")
|
||||
myonAnotherFrame fl = do
|
||||
curPuckRotation <- readIORef puckRotation
|
||||
writeIORef puckRotation (curPuckRotation + fl * 0.2)
|
||||
|
||||
--forM_ (zip[0..] puckSpots) $ \(i, (Vec2 x z)) -> aliceGenericMeshSetInst puck (fromIntegral i) (AliceGenericMeshInstance
|
||||
-- (rot4) ^*^ (mat4Transit (Vec3 x puckLevitationHeight z )))
|
||||
|
||||
|
||||
backDir <- aliceGetCamBack alice
|
||||
let projBack = projectDirOntoPlane backDir
|
||||
rightDir <- aliceGetCamRight alice
|
||||
let projRight = projectDirOntoPlane rightDir
|
||||
goForward <- aliceIsPressed alice (fromIntegral $ ord 'w')
|
||||
when goForward $ do
|
||||
curHeroPos <- readIORef heroPos
|
||||
let nextHeroPos = (curHeroPos ^+^ (projBack ^*^ (fl * (-10))))
|
||||
writeIORef heroPos nextHeroPos
|
||||
aliceSetCamPos alice $ heroCamPos nextHeroPos
|
||||
goBackward <- aliceIsPressed alice (fromIntegral $ ord 's')
|
||||
when goBackward $ do
|
||||
curHeroPos <- readIORef heroPos
|
||||
let nextHeroPos = (curHeroPos ^+^ (projBack ^*^ (fl * (10))))
|
||||
writeIORef heroPos nextHeroPos
|
||||
aliceSetCamPos alice $ heroCamPos nextHeroPos
|
||||
goLeft <- aliceIsPressed alice (fromIntegral $ ord 'a')
|
||||
when goLeft $ do
|
||||
curHeroPos <- readIORef heroPos
|
||||
let nextHeroPos = (curHeroPos ^+^ (projRight ^*^ (fl * (-10))))
|
||||
writeIORef heroPos nextHeroPos
|
||||
aliceSetCamPos alice $ heroCamPos nextHeroPos
|
||||
goRight <- aliceIsPressed alice (fromIntegral $ ord 'd')
|
||||
when goRight $ do
|
||||
curHeroPos <- readIORef heroPos
|
||||
let nextHeroPos = (curHeroPos ^+^ (projRight ^*^ (fl * (10))))
|
||||
writeIORef heroPos nextHeroPos
|
||||
aliceSetCamPos alice $ heroCamPos nextHeroPos
|
||||
oldPos <- aliceGetCamPos alice
|
||||
goForward <- aliceIsPressed alice 0x77
|
||||
if goForward
|
||||
then do
|
||||
backDir <- aliceGetCamBack alice
|
||||
aliceSetCamPos alice (oldPos ^+^ (backDir ^*^ (-fl * 10)))
|
||||
else return ()
|
||||
|
||||
--cur <- readIORef state
|
||||
--aliceClearScreenTextLabel alicePerm
|
||||
--aliceAddScreenTextLabel alicePerm ("Current value is = " ++ show cur)
|
||||
|
||||
|
||||
-- Allocate space for the struct, poke it, and pass to C.
|
||||
aliceMainloop alice callbacks
|
||||
|
||||
445
src/l3/r4/r4.c
@ -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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 8.5 KiB |