Wrote untested polygon triangulation algorithm. Rewrote one-fourth-of-a-cylinder model generation

This commit is contained in:
Андреев Григорий 2026-01-23 03:50:54 +03:00
parent 33df2e4e8e
commit f4400a08a8
13 changed files with 610 additions and 266 deletions

View File

@ -62,5 +62,5 @@ target_link_libraries(r2c -lm)
add_executable(l2_tex_gen src/l2/anne/codegen.c)
target_link_libraries(l2_tex_gen -lm -lpng)
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)
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)

View File

@ -8,7 +8,7 @@
#include "some_tests.h"
#include "util_temp_vulkan.h"
#include "margaret/margaret_misc.h"
#include "marie/graphics_geom.h"
#include "marie.h"
#include "liza.h"
#include "embassy_l1_5.h"
#include "margaret/png_pixel_masses.h"
@ -24,7 +24,7 @@ int main() {
generate_pixel_masses_header();
generate_headers_for_r0_r1_r2_r3();
generate_util_templ_inst_for_vulkan_headers();
generate_marie_headers_for_graphics_geom();
generate_l1_headers_for_marie();
generate_liza_l1_headers();
generate_l1_headers_for_l1_5();
generate_margaret_eve_for_vulkan_utils(); /* margaret misc */

View File

@ -499,7 +499,12 @@ void generate_geom_header() {
VecU8_append_span(&res.result, cstr("#include <math.h>\n\n"));
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("s64vec"), cstr("S64")));
VecU8_append_vec(&res.result, generate_xvec234_structs_and_base_methods(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"));
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")));

21
src/l1/anne/marie.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef PROTOTYPE1_SRC_L1_ANNE_MARIE_H
#define PROTOTYPE1_SRC_L1_ANNE_MARIE_H
#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("MarieHoleConnectTriangStackFrame"), 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);
}
#endif

View File

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

View File

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

View File

@ -253,11 +253,11 @@ U32 SpanU8_decode_as_utf8(SpanU8* rem){
}
bool SpanU8_is_prefix(SpanU8 a, SpanU8 str){
return str.len >= a.len && SpanU8_cont_equal(a, SpanU8_span(str, 0, a.len));
return str.len >= a.len && SpanU8_cont_equal(a, (SpanU8){str.data, a.len});
}
bool SpanU8_is_postfix(SpanU8 a, SpanU8 str){
return str.len >= a.len && SpanU8_cont_equal(a, SpanU8_span(str, str.len - a.len, a.len));
return str.len >= a.len && SpanU8_cont_equal(a, (SpanU8){str.data + str.len - a.len, a.len});
}
#endif

View File

@ -25,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 u);
memcpy(&u, &f, sizeof(uint32_t));
return u;
}
@ -37,6 +37,8 @@ bool marie_same_dir3(float A0, float A1, float A2, float B) {
return A0 == 0 || A1 == 0 || A2 == 0 || (diff & 0x80000000u) == 0;
}
// This function uses floating point arithmetic, which is very bad
/* 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);
}

View File

@ -5,6 +5,7 @@
#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,7 +288,8 @@ 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});
*TextureDataR8G8B8A8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel(normal);
if (TextureDataR8G8B8A8_is_inside(g->tex, x, y))
*TextureDataR8G8B8A8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel(normal);
}
void draw_polygon_on_normal_texture_smooth_param_surf(
@ -319,7 +321,8 @@ 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);
*TextureDataR8G8B8A8_mat(g->tex, x, y) = compress_normal_vec_into_norm_texel(tang_normal);
if (TextureDataR8G8B8A8_is_inside(g->tex, x, y))
*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.
@ -341,30 +344,8 @@ 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
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)));
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);
}
@ -421,58 +402,38 @@ 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"
// todo: rewrite this crrp (again)
TextureDataR8G8B8A8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) {
/* 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){
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* */
vec2 height_map_cb_that_uses_bublazhuzhka(void* ug, vec2 v) {
@ -481,66 +442,27 @@ vec2 height_map_cb_that_uses_bublazhuzhka(void* ug, vec2 v) {
}
// 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) {
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
) {
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);
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);
float r_mag = r * s_resol;
float w_mag = w * s_resol;
float l_mag = l * s_resol;
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;
}
U64 texture_width = (U64)ceilf(2 * r_mag + w_mag);
U64 texture_height = (size_t)ceilf(2 * r_mag + (float)k * l_mag);
// todo: aaaa i am gonna go fucking insane who the fuck wrote trhis shit. AAA, I hate this code so much I hate myself so fuckign much
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};
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});
@ -548,18 +470,18 @@ GenericMeshTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
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 = {r / tex_width, 0}});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, -r}, .tex = {(r + w) / tex_width, 0}});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {0, 0, -r}, .tex = v6tex});
VecGenericMeshVertexInc_append(&vertices, (GenericMeshVertexInc){.pos = {w, 0, -r}, .tex = v7tex});
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 / tex_height}
.tex = {v2tex.x, v2tex.y + (float)(i + j) * l_mag / (float)texture_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 / tex_height}
.tex = {v3tex.x, v3tex.y + (float)(i + j) * l_mag / (float)texture_height}
});
}
}
@ -568,32 +490,97 @@ GenericMeshTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
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 - r *sinf(a * (float)i)) / tex_width, (r + r * cosf(a * (float)i)) / tex_height},
.tex = (vec2){
(r_mag - r_mag * sinf(a * (float)i)) / (float)texture_width,
(r_mag + r_mag * cosf(a * (float)i)) / (float)texture_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 + w + r * sinf(a * (float)i)) / tex_width, (r + r * cosf(a * (float)i)) / tex_height},
.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},
});
}
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));
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)});
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});
}
return (GenericMeshTopology){.vertices = vertices, .indexes = indexes};
{
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);
}
U32 quad_to_triangles_conv_arr[6] = {0, 1, 2, 0, 2, 3};
@ -666,25 +653,6 @@ CubeVertOfFace CubeVertOfFace_next(CubeVertOfFace vert) {
return (CubeVertOfFace){vert.face, (vert.vert_on_it + 1) % 4};
}
#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},
};
}
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});
@ -825,36 +793,37 @@ 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}},
{{+b, 0, +b}},
{{+b, 0, -b}},
{{+b, height, -b}},
{{+b, height, +b}, d_clr},
{{+b, 0, +b}, d_clr},
{{+b, 0, -b}, d_clr},
{{+b, height, -b}, d_clr},
{{-b, 0, -b}},
{{-b, 0, +b}},
{{-b, height, +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, height, +b}},
{{+b, height, -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, 0, -b}},
{{+b, 0, -b}},
{{+b, 0, +b}},
{{-b, 0, +b}},
{{-b, 0, -b}, d_clr},
{{+b, 0, -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, height, +b}, d_clr},
{{-b, height, +b}, d_clr},
{{-b, 0, +b}, d_clr},
{{+b, 0, +b}, d_clr},
{{-b, 0, -b}},
{{-b, height, -b}},
{{+b, height, -b}},
{{+b, 0, -b}},
{{-b, 0, -b}, d_clr},
{{-b, height, -b}, d_clr},
{{+b, height, -b}, d_clr},
{{+b, 0, -b}, d_clr},
};
VecShinyMeshVertexInc vertices = VecShinyMeshVertexInc_from_span(
(SpanShinyMeshVertexInc){ .data = vert, .len = ARRAY_SIZE(vert) });
@ -866,27 +835,11 @@ ShinyMeshTopology generate_shiny_lamp(float height, float a, float b){
return (ShinyMeshTopology){ .vertices = vertices, .indexes = indexes};
}
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);
}
{
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);
}
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));
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));
}
/* We are on l2 */
@ -894,7 +847,7 @@ int gen_assets_for_r4() {
mkdir_nofail("l2/models");
mkdir_nofail("l2/textures");
mkdir_nofail("l2/textures/r4");
generate_one_forth_of_a_cylinder_with_bublazhuzhka(10, 2, 6);
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"));
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"));

View File

@ -947,9 +947,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_MIRRORED_REPEAT,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_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

View File

@ -1,22 +1,344 @@
#ifndef PROTOTYPE1_SRC_L2_MARIE_SHAPE_GEOM_H
#define PROTOTYPE1_SRC_L2_MARIE_SHAPE_GEOM_H
#include "../../../gen/l1_5/marie/clipping.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>
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;
/* 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 */
}
float ST = marie_surface(T.v0, T.v1, T.v2);
if (ST < 0) {
vec2 t = T.v0;
T.v0 = T.v1;
T.v1 = t;
/* 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;
}
marie_clip_ccw_triang_with_ccw_triang_append_to_Vec(C, T, pile);
}
/* 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);
}
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;
}
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);
}
}
/* 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--;
}
return triangles;
}
/* Recursion is dead. Recursion remains dead. And we have killed it.
* Used in hole-connecting triangulation algorithm */
typedef struct {
U64 hole_id;
U64 vertex_in_hole_id;
U64 progress;
U64 progress_in_starting_vertex;
} MarieHoleConnectTriangStackFrame;
#include "../../../gen/l1/eve/marie/VecMarieHoleConnectTriangStackFrame.h"
/* 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++) {
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++) {
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++) {
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++) {
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 = 0; hole < HN; hole++) {
U64 a = rightest_vertex.buf[hole];
MarieHoleAndVertexId b = parent_vertex_of_hole.buf[hole];
VecMarieHoleAndVertexId_append(&connections.buf[hole].buf[a], b);
}
VecVecU64 progress = VecVecU64_new_reserved(HN);
for (size_t h = 0; h < HN; h++) {
VecVecU64_append(&progress, VecU64_new_zeroinit(P->buf[h].len));
}
/* Mapping */
VecMarieHoleAndVertexId detour = VecMarieHoleAndVertexId_new();
MarieHoleAndVertexId cur = {0, 0};
while (true) {
VecMarieHoleAndVertexId* conn = &connections.buf[cur.hole_id].buf[cur.vertex_in_hole_id];
size_t* p = &progress.buf[cur.hole_id].buf[cur.vertex_in_hole_id];
if (*p == conn->len)
break;
assert(*p < conn->len);
VecMarieHoleAndVertexId_append(&detour, cur);
cur = conn->buf[*(p++)];
}
VecU64_drop(rightest_vertex);
VecVecVecMarieHoleAndVertexId_drop(connections);
VecMarieHoleAndVertexId_drop(parent_vertex_of_hole);
VecVecU64_drop(progress);
return detour;
}
VecMarieHoleAndVertexId marie_polygon_hole_removal_triangulation(const VecVecs64vec2* P){
VecMarieHoleAndVertexId detour = marie_polygon_hole_removal(P);
Vecs64vec2 fabricated_mono_polygon = Vecs64vec2_new_zeroinit(detour.len);
for (size_t i = 0; i < detour.len; i++) {
MarieHoleAndVertexId vid = detour.buf[i];
fabricated_mono_polygon.buf[i] = P->buf[vid.hole_id].buf[vid.vertex_in_hole_id];
}
VecU64 mono_polygon_triangulation = marie_polygon_ear_cutting_triangulation(Vecs64vec2_to_span(&fabricated_mono_polygon));
VecMarieHoleAndVertexId back_translated_triangulation =
VecMarieHoleAndVertexId_new_zeroinit(mono_polygon_triangulation.len);
for (size_t i = 0; i < mono_polygon_triangulation.len; i++) {
U64 fake_vertex_id = mono_polygon_triangulation.buf[i];
assert(fake_vertex_id < detour.len);
back_translated_triangulation.buf[i] = detour.buf[fake_vertex_id];
}
VecMarieHoleAndVertexId_drop(detour);
Vecs64vec2_drop(fabricated_mono_polygon);
VecU64_drop(mono_polygon_triangulation);
return back_translated_triangulation;
}
#endif

View File

@ -85,4 +85,13 @@ void TextureDataR8G8B8A8_draw_triangle_of_one_color(TextureDataR8G8B8A8* self, v
.guest = &aboba});
}
void TextureDataR8G8B8A8_triangle_set_color_cvec4(TextureDataR8G8B8A8* self, cvec4 c, MarieTriangle trig){
TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest aboba = { self, c };
marie_rasterize_triangle_with_attr(
(MariePlaneVertAttr){trig.v0, {}}, (MariePlaneVertAttr){trig.v1, {}}, (MariePlaneVertAttr){trig.v2, {}},
(FnMarieRasterizerCallback){.fn = TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest,
.guest = &aboba});
}
#endif

View File

@ -18,10 +18,16 @@ AliceGenericMeshPath AliceGenericMeshPath_for_puck(){
};
}
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;
} R4AlphaStuff;
void main_h_on_wayland_keyboard_key(void* data, U32 keysym, U32 act){
@ -30,7 +36,30 @@ void main_h_on_wayland_keyboard_key(void* data, U32 keysym, U32 act){
void main_h_on_another_frame(void* data, float fl){
R4AlphaStuff *st = data;
Alice* alice = st->alice;
margaret_ns_time TIME = margaret_clock_gettime_monotonic_raw();
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;
// margaret_ns_time TIME = margaret_clock_gettime_monotonic_raw();
// printf("Updating text\n");
// LucyRenderer_clear(&alice->lucy_renderer);
// VecU8 text = VecU8_fmt("Time is %u.%u\nHave a good day sir\n", (U64)TIME.tv_sec, (U64)TIME.tv_nsec);
@ -40,6 +69,7 @@ void main_h_on_another_frame(void* data, float fl){
int main(){
R4AlphaStuff st;
st.hero_pos = (vec3){0, 0.81f, 0};
Alice* alice = Alice_new();
st.alice = alice;
st.alice->guest = &st;
@ -67,16 +97,16 @@ int main(){
LucyRenderer_add_simple_label(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
cstr("Bebra budet\nотнюхана\n"), (ivec2){10, 10});
// ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(st.alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6));
// AliceGenericMeshHand_resize_instance_arr(st.alice, &model_gen->el, 1);
//
// for (int X = 0; X < 1; X++) {
// for (int Z = 0; Z < 1; Z++) {
// AliceGenericMeshHand_set_inst(&model_gen->el, X * 10 + Z, (GenericMeshInstanceInc){
// .model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}),
// });
// }
// }
ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(st.alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6));
AliceGenericMeshHand_resize_instance_arr(st.alice, &model_gen->el, 1);
for (int X = 0; X < 1; X++) {
for (int Z = 0; Z < 1; Z++) {
AliceGenericMeshHand_set_inst(&model_gen->el, X * 10 + Z, (GenericMeshInstanceInc){
.model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}),
});
}
}
ListNodeAliceShinyMeshHand *model_sh = Alice_add_shiny_mesh(st.alice, vcstr("./gen/l2/models/cube.AliceShinyMesh"));
AliceShinyMeshHand_resize_instance_arr(st.alice, &model_sh->el, 100);
@ -117,15 +147,15 @@ int main(){
.model_t = marie_translation_mat4((vec3){5.f, -3, 12.f}),
});
// ListNodeAliceGenericMeshHand* model_puck = Alice_add_generic_mesh(st->alice, AliceGenericMeshPath_for_puck());
// AliceGenericMeshHand_resize_instance_arr(st->alice, &model_puck->el, 100);
// 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}),
// });
// }
// }
ListNodeAliceGenericMeshHand* model_puck = Alice_add_generic_mesh(st.alice, AliceGenericMeshPath_for_puck());
AliceGenericMeshHand_resize_instance_arr(st.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(st.alice, &(AliceCallbacks){
.on_wl_keyboard_key = main_h_on_wayland_keyboard_key,
.on_another_frame = main_h_on_another_frame,