Skip to content

Commit

Permalink
Implement RF_BEAM_LIGHTNING.
Browse files Browse the repository at this point in the history
From Jonathan <[email protected]>
  • Loading branch information
skullernet committed Oct 24, 2023
1 parent 4c23f64 commit 121b6bd
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 52 deletions.
5 changes: 4 additions & 1 deletion src/client/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,11 @@ static void CL_ParseDeltaEntity(server_frame_t *frame,
Com_Error(ERR_DROP, "%s: bad sound", __func__);

// mask off high bits for non-extended servers
if (!cl.csr.extended)
if (!cl.csr.extended) {
state->renderfx &= RF_SHELL_LITE_GREEN - 1;
if (state->renderfx & RF_BEAM)
state->renderfx &= ~RF_GLOW;
}
}

static void CL_ParsePacketEntities(server_frame_t *oldframe,
Expand Down
147 changes: 96 additions & 51 deletions src/refresh/tess.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,18 +153,100 @@ void GL_DrawParticles(void)
} while (total);
}

/* all things serve the Beam */
void GL_DrawBeams(void)
static void GL_DrawBeamSegment(const vec3_t start, const vec3_t end, color_t color, float width)
{
vec3_t d1, d2, d3;
vec_t *start, *end;
color_t color;
vec_t *dst_vert;
uint32_t *dst_color;
QGL_INDEX_TYPE *dst_indices;
vec_t length;
int numverts;
int numindices;

VectorSubtract(end, start, d1);
VectorSubtract(glr.fd.vieworg, start, d2);
CrossProduct(d1, d2, d3);
VectorNormalize(d3);
VectorScale(d3, width, d3);

length = VectorLength(d1);
if (length < 0.1f)
return;

if (tess.numverts + 4 > TESS_MAX_VERTICES ||
tess.numindices + 6 > TESS_MAX_INDICES) {
qglDrawElements(GL_TRIANGLES, tess.numindices,
QGL_INDEX_ENUM, tess.indices);
tess.numverts = tess.numindices = 0;
}

dst_vert = tess.vertices + tess.numverts * 5;
VectorAdd(start, d3, dst_vert);
VectorSubtract(start, d3, dst_vert + 5);
VectorSubtract(end, d3, dst_vert + 10);
VectorAdd(end, d3, dst_vert + 15);

dst_vert[3] = 0; dst_vert[4] = 0;
dst_vert[8] = 1; dst_vert[9] = 0;
dst_vert[13] = 1; dst_vert[14] = length;
dst_vert[18] = 0; dst_vert[19] = length;

dst_color = (uint32_t *)tess.colors + tess.numverts;
dst_color[0] = color.u32;
dst_color[1] = color.u32;
dst_color[2] = color.u32;
dst_color[3] = color.u32;

dst_indices = tess.indices + tess.numindices;
dst_indices[0] = tess.numverts + 0;
dst_indices[1] = tess.numverts + 2;
dst_indices[2] = tess.numverts + 3;
dst_indices[3] = tess.numverts + 0;
dst_indices[4] = tess.numverts + 1;
dst_indices[5] = tess.numverts + 2;

tess.numverts += 4;
tess.numindices += 6;
}

#define MIN_LIGHTNING_SEGMENTS 3
#define MAX_LIGHTNING_SEGMENTS 7
#define MIN_SEGMENT_LENGTH 10

static void GL_DrawLightningBeam(const vec3_t start, const vec3_t end, color_t color, float width)
{
vec3_t d1, segments[MAX_LIGHTNING_SEGMENTS - 1];
vec_t length;
int i, num_segments = MIN_LIGHTNING_SEGMENTS + Q_rand_uniform(MAX_LIGHTNING_SEGMENTS - MIN_LIGHTNING_SEGMENTS);

VectorSubtract(end, start, d1);
length = VectorNormalize(d1);

num_segments = min(num_segments, (int)(length / MIN_SEGMENT_LENGTH));
if (num_segments <= 1) {
GL_DrawBeamSegment(start, end, color, width);
return;
}

for (i = 0; i < num_segments - 1; i++) {
int dir = Q_rand_uniform(q_countof(bytedirs));
float dist = 4 + crand() * 16;
float frac = (float)(i + 1) / num_segments;
VectorMA(start, frac * length, d1, segments[i]);
VectorMA(segments[i], dist, bytedirs[dir], segments[i]);
}

for (i = 0; i < num_segments; i++) {
const float *seg_start = (i == 0) ? start : segments[i - 1];
const float *seg_end = (i == num_segments - 1) ? end : segments[i];

GL_DrawBeamSegment(seg_start, seg_end, color, width);
}
}

void GL_DrawBeams(void)
{
vec_t *start, *end;
color_t color;
float width;
entity_t *ent;
int i;

Expand All @@ -181,24 +263,13 @@ void GL_DrawBeams(void)
GL_TexCoordPointer(2, 5, tess.vertices + 3);
GL_ColorBytePointer(4, 0, tess.colors);

numverts = numindices = 0;
for (i = 0, ent = glr.fd.entities; i < glr.fd.num_entities; i++, ent++) {
if (!(ent->flags & RF_BEAM)) {
continue;
}

start = ent->origin;
end = ent->oldorigin;
VectorSubtract(end, start, d1);
VectorSubtract(glr.fd.vieworg, start, d2);
CrossProduct(d1, d2, d3);
VectorNormalize(d3);
length = ent->frame * 1.2f;
VectorScale(d3, length, d3);

length = VectorLength(d1);
if (length < 0.001f)
continue;

if (ent->skinnum == -1) {
color.u32 = ent->rgba.u32;
Expand All @@ -207,44 +278,18 @@ void GL_DrawBeams(void)
}
color.u8[3] *= ent->alpha;

if (numverts + 4 > TESS_MAX_VERTICES ||
numindices + 6 > TESS_MAX_INDICES) {
qglDrawElements(GL_TRIANGLES, numindices,
QGL_INDEX_ENUM, tess.indices);
numverts = numindices = 0;
}
width = ent->frame * 1.2f;

dst_vert = tess.vertices + numverts * 5;
VectorAdd(start, d3, dst_vert);
VectorSubtract(start, d3, dst_vert + 5);
VectorSubtract(end, d3, dst_vert + 10);
VectorAdd(end, d3, dst_vert + 15);

dst_vert[3] = 0; dst_vert[4] = 0;
dst_vert[8] = 1; dst_vert[9] = 0;
dst_vert[13] = 1; dst_vert[14] = length;
dst_vert[18] = 0; dst_vert[19] = length;

dst_color = (uint32_t *)tess.colors + numverts;
dst_color[0] = color.u32;
dst_color[1] = color.u32;
dst_color[2] = color.u32;
dst_color[3] = color.u32;

dst_indices = tess.indices + numindices;
dst_indices[0] = numverts + 0;
dst_indices[1] = numverts + 2;
dst_indices[2] = numverts + 3;
dst_indices[3] = numverts + 0;
dst_indices[4] = numverts + 1;
dst_indices[5] = numverts + 2;

numverts += 4;
numindices += 6;
if (ent->flags & RF_GLOW) {
GL_DrawLightningBeam(start, end, color, width);
} else {
GL_DrawBeamSegment(start, end, color, width);
}
}

qglDrawElements(GL_TRIANGLES, numindices,
qglDrawElements(GL_TRIANGLES, tess.numindices,
QGL_INDEX_ENUM, tess.indices);
tess.numverts = tess.numindices = 0;
}

void GL_BindArrays(void)
Expand Down

0 comments on commit 121b6bd

Please sign in to comment.