diff options
author | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
---|---|---|
committer | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
commit | abef6da56913f1c55528103e60a50451a39628b1 (patch) | |
tree | b3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/SelOutlineRenderer.c |
initial commit
Diffstat (limited to 'src/SelOutlineRenderer.c')
-rw-r--r-- | src/SelOutlineRenderer.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/SelOutlineRenderer.c b/src/SelOutlineRenderer.c new file mode 100644 index 0000000..1082d8a --- /dev/null +++ b/src/SelOutlineRenderer.c @@ -0,0 +1,141 @@ +#include "SelOutlineRenderer.h" +#include "PackedCol.h" +#include "Graphics.h" +#include "Game.h" +#include "Event.h" +#include "Picking.h" +#include "Funcs.h" +#include "Camera.h" +#include "Options.h" + +static GfxResourceID selOutline_vb; +static float base_size; +static PackedCol color; +#define SELOUTLINE_NUM_VERTICES (16 * 6) + +#define SelOutline_Y(y)\ +0,y,1, 0,y,2, 1,y,2, 1,y,1,\ +3,y,1, 3,y,2, 2,y,2, 2,y,1,\ +0,y,0, 0,y,1, 3,y,1, 3,y,0,\ +0,y,3, 0,y,2, 3,y,2, 3,y,3, + +#define SelOutline_X(x)\ +x,1,0, x,2,0, x,2,1, x,1,1,\ +x,1,3, x,2,3, x,2,2, x,1,2,\ +x,0,0, x,1,0, x,1,3, x,0,3,\ +x,3,0, x,2,0, x,2,3, x,3,3, + +#define SelOutline_Z(z)\ +0,1,z, 0,2,z, 1,2,z, 1,1,z,\ +3,1,z, 3,2,z, 2,2,z, 2,1,z,\ +0,0,z, 0,1,z, 3,1,z, 3,0,z,\ +0,3,z, 0,2,z, 3,2,z, 3,3,z, + + +static void BuildMesh(struct RayTracer* selected) { + static const cc_uint8 indices[288] = { + SelOutline_Y(0) SelOutline_Y(3) /* YMin, YMax */ + SelOutline_X(0) SelOutline_X(3) /* XMin, XMax */ + SelOutline_Z(0) SelOutline_Z(3) /* ZMin, ZMax */ + }; + + struct VertexColoured* ptr; + int i; + Vec3 delta; + float dist, offset; + float size, scale; + Vec3 coords[4]; + + Vec3_Sub(&delta, &Camera.CurrentPos, &selected->Min); + dist = Vec3_LengthSquared(&delta); + + offset = 0.01f; + if (dist < 4.0f * 4.0f) offset = 0.00625f; + if (dist < 2.0f * 2.0f) offset = 0.00500f; + + scale = 1.0f / 16.0f; + if (dist < 32.0f * 32.0f) scale = 1.0f / 32.0f; + if (dist < 16.0f * 16.0f) scale = 1.0f / 64.0f; + if (dist < 8.0f * 8.0f) scale = 1.0f / 96.0f; + if (dist < 4.0f * 4.0f) scale = 1.0f / 128.0f; + if (dist < 2.0f * 2.0f) scale = 1.0f / 192.0f; + size = base_size * scale; + + /* How a face is laid out: + #--#-------#--#<== OUTER_MAX (3) + | | | | + | #-------#<===== INNER_MAX (2) + | | | | + | | | | + | | | | + (1) INNER_MIN =====>#-------# | + | | | | + (0) OUTER_MIN ==>#--#-------#--# + + - these are used to fake thick lines, by making the lines appear slightly inset + - note: actual difference between inner and outer is much smaller than the diagram + */ + Vec3_Add1(&coords[0], &selected->Min, -offset); + Vec3_Add1(&coords[1], &coords[0], size); + Vec3_Add1(&coords[3], &selected->Max, offset); + Vec3_Add1(&coords[2], &coords[3], -size); + + ptr = (struct VertexColoured*)Gfx_LockDynamicVb(selOutline_vb, + VERTEX_FORMAT_COLOURED, SELOUTLINE_NUM_VERTICES); + for (i = 0; i < Array_Elems(indices); i += 3, ptr++) + { + ptr->x = coords[indices[i + 0]].x; + ptr->y = coords[indices[i + 1]].y; + ptr->z = coords[indices[i + 2]].z; + ptr->Col = color; + } + Gfx_UnlockDynamicVb(selOutline_vb); +} + +void SelOutlineRenderer_Render(struct RayTracer* selected, cc_bool dirty) { + if (Gfx.LostContext) return; + + if (!selOutline_vb) + selOutline_vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_COLOURED, SELOUTLINE_NUM_VERTICES); + + Gfx_SetAlphaBlending(true); + Gfx_SetDepthWrite(false); + Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); + + if (dirty) BuildMesh(selected); + else Gfx_BindDynamicVb(selOutline_vb); + + Gfx_DrawVb_IndexedTris(SELOUTLINE_NUM_VERTICES); + Gfx_SetDepthWrite(true); + Gfx_SetAlphaBlending(false); +} + + +/*########################################################################################################################* +*-----------------------------------------------SelOutlineRenderer component----------------------------------------------* +*#########################################################################################################################*/ +static void OnContextLost(void* obj) { + Gfx_DeleteDynamicVb(&selOutline_vb); +} + +static void OnInit(void) { + int opacity; + cc_uint8 rgb[3]; + Event_Register_(&GfxEvents.ContextLost, NULL, OnContextLost); + + base_size = Options_GetFloat(OPT_SELECTED_BLOCK_OUTLINE_SCALE, 1, 16, 1); + opacity = Options_GetInt(OPT_SELECTED_BLOCK_OUTLINE_OPACITY, 0, 255, 102); + + if (Options_GetColor(OPT_SELECTED_BLOCK_OUTLINE_COLOR, rgb)) { + color = PackedCol_Make(rgb[0], rgb[1], rgb[2], opacity); + } else { + color = PackedCol_Make(0, 0, 0, opacity); /* Black by default */ + } +} + +static void OnFree(void) { OnContextLost(NULL); } + +struct IGameComponent SelOutlineRenderer_Component = { + OnInit, /* Init */ + OnFree, /* Free */ +}; |