From b256fc903af678a7af8162c9878ab44d287e80df Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Tue, 11 Mar 2025 02:41:03 +0300 Subject: [PATCH] /apps/tools/twndel: triangluation, triangle render --- apps/tools/twndel/state.h | 3 +- apps/tools/twndel/tool.c | 81 +++++++++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/apps/tools/twndel/state.h b/apps/tools/twndel/state.h index ff89ded..abcb362 100644 --- a/apps/tools/twndel/state.h +++ b/apps/tools/twndel/state.h @@ -45,9 +45,10 @@ typedef struct Point { int16_t x, y, z; } Point; +/* TODO: store topology in terms on edge connections? might be bad, as it's stateful */ /* triangles have p3 = INVALID_POINT */ /* lines have p2, p3 = INVALID_POINT */ -/* points have p1, p2, p3 = INVALID_POINT */ +/* billboards have p1, p2, p3 = INVALID_POINT */ typedef struct Face { uint16_t p[4]; /* texture origin, as point on face plane, in absolute coordinates */ diff --git a/apps/tools/twndel/tool.c b/apps/tools/twndel/tool.c index 0fac5eb..00d3a80 100644 --- a/apps/tools/twndel/tool.c +++ b/apps/tools/twndel/tool.c @@ -125,21 +125,33 @@ static void render_object(uint8_t object) { draw_line_3d(p2, p3, 1, (Color){255,255,255,255}); draw_line_3d(p3, p0, 1, (Color){255,255,255,255}); } - } else { + + } else if (f->p[2] != INVALID_POINT) { Vec3 p0 = point_to_vec3(object, f->p[0]); Vec3 p1 = point_to_vec3(object, f->p[1]); Vec3 p2 = point_to_vec3(object, f->p[2]); - // if (state.solid_display_mode) - // draw_triangle(state.current_texture, - // p0, p1, p2, ) - // else { - // draw_line_3d(p0, p1, 1, (Color){255,255,255,255}); - // draw_line_3d(p1, p2, 1, (Color){255,255,255,255}); - // draw_line_3d(p2, p3, 1, (Color){255,255,255,255}); - // draw_line_3d(p3, p0, 1, (Color){255,255,255,255}); - // } - } + Vec3 n = vec3_norm(vec3_cross(vec3_sub(p1, p0), vec3_sub(p2, p0))); + Vec2 to = { f->tex_x / (float)POINTS_PER_METER, f->tex_y / (float)POINTS_PER_METER, }; + Vec2 tul = project_texture_coordinate(to, n, p0, (float)f->tex_scale); + Vec2 tdl = project_texture_coordinate(to, n, p1, (float)f->tex_scale); + Vec2 tdr = project_texture_coordinate(to, n, p2, (float)f->tex_scale); + + if (state.solid_display_mode) + draw_triangle(state.current_texture, + p0, p1, p2, + tul, tdl, tdr, + (Color){255,255,255,255}, + (Color){255,255,255,255}, + (Color){255,255,255,255}); + else { + draw_line_3d(p0, p1, 1, (Color){255,255,255,255}); + draw_line_3d(p1, p2, 1, (Color){255,255,255,255}); + draw_line_3d(p2, p0, 1, (Color){255,255,255,255}); + } + + } else + SDL_assert_always(false); } } @@ -358,12 +370,12 @@ static void show_snap_lines(Vec3 p) { } -static void process_operation_move_point(Operation *op) { +static bool process_operation_move_point(Operation *op) { /* finish dragging around */ /* TODO: dont keep empty ops on stack? */ if (input_action_just_released("select")) { state.op_active = false; - return; + return false; } float size = sinf(ctx.frame_number / 10) * 0.05f + 0.05f; @@ -418,8 +430,12 @@ static void process_operation_move_point(Operation *op) { } } - if (point_moved) + if (point_moved) { audio_play("/data/bong.ogg", NULL, false, 0.12f, 0.0f); + return true; + } + + return false; } @@ -432,6 +448,36 @@ static void reverse_operation_move_point(Operation *op) { } +static void try_subdividing_from_moving(uint8_t object, uint16_t point) { + Object *o = &state.objects[object]; + + for (uint16_t fi = 0; fi < o->faces_sz; ++fi) { + Face *f = &o->faces[fi]; + if (f->p[3] == INVALID_POINT) continue; + for (uint16_t pi = 0; pi < 4; ++pi) { + if (f->p[pi] == point) { + Face new0 = *f; + new0.p[0] = f->p[pi]; + new0.p[1] = f->p[(pi + 1) % 4]; + new0.p[2] = f->p[(pi + 3) % 4]; + new0.p[3] = INVALID_POINT; + + push_face(object, + f->p[(pi + 1) % 4], + f->p[(pi + 2) % 4], + f->p[(pi + 3) % 4], + INVALID_POINT, + f->texture, + f->tex_scale, + f->tex_x, + f->tex_y); + *f = new0; + } + } + } +} + + static void process_operations(void) { if (input_action_just_pressed("undo")) { /* TODO: checks and defined limit */ @@ -463,7 +509,7 @@ static void process_operations(void) { if (input_action_just_pressed("select")) push_operation((Operation){ .kind = OPERATION_MOVE_POINT, - .data = { .move_point = { .point = point_select } }, + .data = { .move_point = { .point = point_select, .object = obj_select } }, }, true ); } } @@ -472,7 +518,10 @@ static void process_operations(void) { Operation *op = &state.op_stack[state.op_stack_ptr % UNDO_STACK_SIZE]; switch (op->kind) { case OPERATION_MOVE_POINT: { - process_operation_move_point(op); + bool update = process_operation_move_point(op); + + if (update) + try_subdividing_from_moving(op->data.move_point.object, op->data.move_point.point); break; }