diff --git a/src/proto/pp_sim/pp_sim_core.c b/src/proto/pp_sim/pp_sim_core.c index ece4cea8..d0314807 100644 --- a/src/proto/pp_sim/pp_sim_core.c +++ b/src/proto/pp_sim/pp_sim_core.c @@ -3,6 +3,7 @@ S_SharedState S_shared_state = ZI; Readonly S_Ent S_nil_ent = { .local_to_parent_xf = CompXformIdentity, .final_local_to_world_xf = CompXformIdentity, + .tint = { 0.5, 0.5, 0.5, 1 }, }; //////////////////////////////////////////////////////////// @@ -151,7 +152,7 @@ S_Ent *S_EntFromKey(S_Lookup *lookup, S_Key key) //////////////////////////////////////////////////////////// //~ Iteration helpers -void S_ResetIter(Arena *arena, S_Iter *iter, S_Lookup *lookup, S_Key key, S_IterKind kind) +S_Ent *S_FirstEntEx(Arena *arena, S_Iter *iter, S_Lookup *lookup, S_Key key, S_IterKind kind) { iter->kind = kind; iter->lookup = lookup; @@ -175,6 +176,7 @@ void S_ResetIter(Arena *arena, S_Iter *iter, S_Lookup *lookup, S_Key key, S_Iter n->ent_key = key; SllStackPush(iter->first_dfs, n); } + return S_NextEnt(arena, iter); } S_Ent *S_NextEnt(Arena *arena, S_Iter *iter) @@ -374,7 +376,7 @@ JobDef(S_SimWorker, _, __) lookup = S_LookupFromWorld(frame_arena, world); ////////////////////////////// - //- Rebuild entity tree + //- Build entity tree { /* Reset tree links */ @@ -454,9 +456,21 @@ JobDef(S_SimWorker, _, __) ////////////////////////////// //- Update entities from user control - S_ResetIter(frame_arena, &iter, &lookup, S_RootKey, S_IterKind_Pre); - for (S_Ent *ent = S_NextEnt(frame_arena, &iter); !S_IsEntNil(ent); ent = S_NextEnt(frame_arena, &iter)) + for (S_Ent *ent = S_FirstEnt(frame_arena, &iter, &lookup); !S_IsEntNil(ent); ent = S_NextEnt(frame_arena, &iter)) { + if (!S_IsKeyNil(ent->camera)) + { + ent->local_to_parent_xf.og.x += 1; + } + } + + ////////////////////////////// + //- Compute final world transforms + + for (S_Ent *ent = S_FirstEnt(frame_arena, &iter, &lookup); !S_IsEntNil(ent); ent = S_NextEnt(frame_arena, &iter)) + { + S_Ent *parent = S_EntFromKey(&lookup, ent->parent); + ent->final_local_to_world_xf = MulXform(parent->final_local_to_world_xf, ent->local_to_parent_xf); } ////////////////////////////// diff --git a/src/proto/pp_sim/pp_sim_core.h b/src/proto/pp_sim/pp_sim_core.h index b4779896..bddb2959 100644 --- a/src/proto/pp_sim/pp_sim_core.h +++ b/src/proto/pp_sim/pp_sim_core.h @@ -2,7 +2,7 @@ //~ Key types #define S_NilKey ((S_Key) { 0 }) -#define S_RootKey ((S_Key) { .v.hi = 0x75ebb7a47d1ca753, .v.lo = 0x2d505fc8961e5576 }) +#define S_RootKey ((S_Key) { .v.hi = 0xaaaaaaaaaaaaaaaa, .v.lo = 0xaaaaaaaaaaaaaaaa }) Struct(S_Key) { @@ -43,7 +43,9 @@ Struct(S_Ent) S_Key key; ////////////////////////////// - //- Pre-solve data + //- Build data + + Vec4 tint; S_Key follow; S_Key camera; @@ -241,7 +243,8 @@ S_Ent *S_EntFromKey(S_Lookup *lookup, S_Key key); //////////////////////////////////////////////////////////// //~ Iteration helpers -void S_ResetIter(Arena *arena, S_Iter *iter, S_Lookup *lookup, S_Key key, S_IterKind kind); +#define S_FirstEnt(arena, iter, lookup) S_FirstEntEx((arena), (iter), (lookup), S_RootKey, S_IterKind_Pre) +S_Ent *S_FirstEntEx(Arena *arena, S_Iter *iter, S_Lookup *lookup, S_Key key, S_IterKind kind); S_Ent *S_NextEnt(Arena *arena, S_Iter *iter); //////////////////////////////////////////////////////////// diff --git a/src/proto/pp_vis/pp_vis_core.c b/src/proto/pp_vis/pp_vis_core.c index a7614fb3..cdf94758 100644 --- a/src/proto/pp_vis/pp_vis_core.c +++ b/src/proto/pp_vis/pp_vis_core.c @@ -28,9 +28,10 @@ void V_Shutdown(void) void V_PushTestEnts(Arena *arena, S_EntList *list) { S_Key player_key = S_RandKey(); + S_Key child_key = S_RandKey(); S_Key camera_key = S_RandKey(); - i32 count = 2; + i32 count = 3; for (u64 i = 0; i < count; ++i) { S_EntListNode *n = PushStruct(arena, S_EntListNode); @@ -43,24 +44,42 @@ void V_PushTestEnts(Arena *arena, S_EntList *list) /* Test player */ case 0: { + ent->tint = Color_Red; ent->key = player_key; ent->camera = camera_key; - { S_Shape *shape = &ent->local_shape; shape->points_count = 4; shape->points[0] = VEC2(100, 100); shape->points[1] = VEC2(200, 100); - shape->points[2] = VEC2(150, 200); - shape->points[3] = VEC2(125, 200); - // shape->radius = 1; + shape->points[2] = VEC2(200, 200); + shape->points[3] = VEC2(100, 200); + shape->radius = 0; + } + } break; + + /* Test child */ + case 1: + { + ent->tint = Color_Cyan; + ent->key = child_key; + ent->parent = player_key; + { + S_Shape *shape = &ent->local_shape; + shape->points_count = 1; + shape->points[0] = VEC2(100, 100); + // shape->points[1] = VEC2(200, 100); + // shape->points[2] = VEC2(150, 200); + // shape->points[3] = VEC2(125, 200); + shape->radius = 20; + // ent->local_to_parent_xf = XformFromPos(VEC2(500, 500)); } } break; /* Test camera */ - case 1: + case 2: { - ent->key = camera_key; + // ent->key = camera_key; } break; default: @@ -417,19 +436,16 @@ JobDef(V_VisWorker, _, __) //- Build render data /* Build shapes */ - S_ResetIter(frame_arena, &iter, &lookup, S_RootKey, S_IterKind_Pre); - for (S_Ent *ent = S_NextEnt(frame_arena, &iter); !S_IsEntNil(ent); ent = S_NextEnt(frame_arena, &iter)) + for (S_Ent *ent = S_FirstEnt(frame_arena, &iter, &lookup); !S_IsEntNil(ent); ent = S_NextEnt(frame_arena, &iter)) { - Xform xf = ent->final_local_to_world_xf; - S_Shape shape = S_MulXformShape(ent->final_local_to_world_xf, ent->local_shape); - for (i32 point_idx = 0; point_idx < shape.points_count; ++point_idx) + b32 is_visible = ent->tint.w != 0; + if (is_visible) { - Vec2 *p = &shape.points[point_idx]; - *p = MulXformV2(xf, *p); + Xform xf = ent->final_local_to_world_xf; + S_Shape shape = S_MulXformShape(ent->final_local_to_world_xf, ent->local_shape); + Vec4 color = ent->tint; + V_DrawShape(dverts_arena, dvert_idx_arena, shape, LinearFromSrgb(color), 16, V_DrawFlag_Line); } - - Vec4 color = Color_Red; - V_DrawShape(dverts_arena, dvert_idx_arena, shape, LinearFromSrgb(color), 16); } ////////////////////////////// diff --git a/src/proto/pp_vis/pp_vis_draw.c b/src/proto/pp_vis/pp_vis_draw.c index c6c1f01c..ae7e9321 100644 --- a/src/proto/pp_vis/pp_vis_draw.c +++ b/src/proto/pp_vis/pp_vis_draw.c @@ -1,51 +1,123 @@ -void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color_lin, i32 detail) -{ - TempArena scratch = BeginScratchNoConflict(); +//////////////////////////////////////////////////////////// +//~ Shape helpers - Vec2Array draw_points = ZI; - if (shape.radius == 0) +void V_DrawPoly(Arena *verts_arena, Arena *idx_arena, Vec2Array points, Vec4 color_lin, V_DrawFlag flags) +{ + if (flags & V_DrawFlag_Line) { - draw_points.points = shape.points; - draw_points.count = shape.points_count; + i32 verts_count = points.count; + if (verts_count >= 2) + { + TempArena scratch = BeginScratchNoConflict(); + { + f32 half_thickness = 1; + i32 lines_count = verts_count == 2 ? 1 : verts_count; + i32 line_verts_count = lines_count * 4; + i32 idx_count = lines_count * 6; + i32 idx_offset = ArenaCount(verts_arena, V_DVert); + + /* Push dverts */ + V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, line_verts_count); + for (i32 line_idx = 0; line_idx < lines_count; ++line_idx) + { + i32 a_idx = line_idx; + i32 b_idx = line_idx + 1; + if (b_idx >= lines_count) + { + b_idx = 0; + } + + Vec2 a = points.points[a_idx]; + Vec2 b = points.points[b_idx]; + + Vec2 a_to_b = SubVec2(b, a); + Vec2 perp = Vec2WithLen(PerpVec2(a_to_b), half_thickness); + + Vec2 p0 = AddVec2(a, perp); + Vec2 p1 = SubVec2(a, perp); + Vec2 p2 = SubVec2(b, perp); + Vec2 p3 = AddVec2(b, perp); + + i32 offset = line_idx * 4; + dverts[offset + 0] = (V_DVert) { .pos = p0, .color_lin = color_lin }; + dverts[offset + 1] = (V_DVert) { .pos = p1, .color_lin = color_lin }; + dverts[offset + 2] = (V_DVert) { .pos = p2, .color_lin = color_lin }; + dverts[offset + 3] = (V_DVert) { .pos = p3, .color_lin = color_lin }; + } + + /* Generate indices */ + i32 *indices = PushStructsNoZero(idx_arena, i32, idx_count); + for (i32 line_idx = 0; line_idx < lines_count; ++line_idx) + { + i32 indices_offset = line_idx * 6; + i32 vert_idx_offset = idx_offset + (line_idx * 4); + indices[indices_offset + 0] = vert_idx_offset + 0; + indices[indices_offset + 1] = vert_idx_offset + 1; + indices[indices_offset + 2] = vert_idx_offset + 2; + indices[indices_offset + 3] = vert_idx_offset + 0; + indices[indices_offset + 4] = vert_idx_offset + 2; + indices[indices_offset + 5] = vert_idx_offset + 3; + } + } + EndScratch(scratch); + } } else { - draw_points.points = PushStructsNoZero(scratch.arena, Vec2, detail); - draw_points.count = detail; - for (i32 i = 0; i < detail; ++i) + i32 verts_count = points.count; + if (verts_count >= 3) { - f32 rad = ((f32)i / (f32)detail) * Tau; - Vec2 dir = Vec2FromAngle(rad); - Vec2 sp = S_SupportPointFromShape(shape, dir); - draw_points.points[i] = sp; + i32 idx_offset = ArenaCount(verts_arena, V_DVert); + i32 tris_count = verts_count - 2; + i32 idx_count = tris_count * 3; + + /* Push dverts */ + V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, verts_count); + for (i32 point_idx = 0; point_idx < (i32)points.count; ++point_idx) + { + V_DVert *dvert = &dverts[point_idx]; + dvert->pos = points.points[point_idx]; + dvert->color_lin = color_lin; + } + + /* Generate indices in a fan pattern */ + i32 *indices = PushStructsNoZero(idx_arena, i32, idx_count); + for (i32 i = 0; i < tris_count; ++i) + { + i32 tri_offset = i * 3; + indices[tri_offset + 0] = idx_offset; + indices[tri_offset + 1] = idx_offset + i + 1; + indices[tri_offset + 2] = idx_offset + i + 2; + } } } - - i32 verts_count = draw_points.count; - if (verts_count >= 3) - { - i32 idx_offset = ArenaCount(verts_arena, V_DVert); - V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, verts_count); - for (i32 point_idx = 0; point_idx < (i32)draw_points.count; ++point_idx) - { - V_DVert *dvert = &dverts[point_idx]; - dvert->pos = draw_points.points[point_idx]; - dvert->color_lin = color_lin; - } - - i32 tris_count = verts_count - 2; - i32 idx_count = tris_count * 3; - i32 *indices = PushStructsNoZero(idx_arena, i32, idx_count); - - /* Generate indices in a fan pattern */ - for (i32 i = 0; i < tris_count; ++i) - { - i32 tri_offset = idx_offset + (i * 3); - indices[tri_offset + 0] = idx_offset; - indices[tri_offset + 1] = i + 1; - indices[tri_offset + 2] = i + 2; - } - } - - EndScratch(scratch); +} + +void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color_lin, i32 detail, V_DrawFlag flags) +{ + if (shape.radius == 0) + { + Vec2Array draw_points = ZI; + draw_points.points = shape.points; + draw_points.count = shape.points_count; + V_DrawPoly(verts_arena, idx_arena, draw_points, color_lin, flags); + } + else + { + TempArena scratch = BeginScratchNoConflict(); + { + Vec2Array draw_points = ZI; + draw_points.points = PushStructsNoZero(scratch.arena, Vec2, detail); + draw_points.count = detail; + for (i32 i = 0; i < detail; ++i) + { + f32 rad = ((f32)i / (f32)detail) * Tau; + Vec2 dir = Vec2FromAngle(rad); + Vec2 sp = S_SupportPointFromShape(shape, dir); + draw_points.points[i] = sp; + } + V_DrawPoly(verts_arena, idx_arena, draw_points, color_lin, flags); + } + EndScratch(scratch); + } } diff --git a/src/proto/pp_vis/pp_vis_draw.h b/src/proto/pp_vis/pp_vis_draw.h index c18798e4..3597d97a 100644 --- a/src/proto/pp_vis/pp_vis_draw.h +++ b/src/proto/pp_vis/pp_vis_draw.h @@ -1 +1,14 @@ -void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color_lin, i32 detail); +//////////////////////////////////////////////////////////// +//~ Flag types + +Enum(V_DrawFlag) +{ + V_DrawFlag_None = 0, + V_DrawFlag_Line = (1 << 0), +}; + +//////////////////////////////////////////////////////////// +//~ Shape helpers + +void V_DrawPoly(Arena *verts_arena, Arena *idx_arena, Vec2Array points, Vec4 color_lin, V_DrawFlag flags); +void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color_lin, i32 detail, V_DrawFlag flags);