mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 21:21:14 +00:00
This makes it possible for hierarchies to clean themselves up (by deleting their entities (though that will cause other problems later when the hierarchy doesn't own the entities)), thus plugging a memory leak when parsing passage text.
238 lines
5.5 KiB
C
238 lines
5.5 KiB
C
/*
|
|
r_trails.c
|
|
|
|
Interface for trails
|
|
|
|
Copyright (C) 2023 Bill Currie <bill@taniwha.org>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
*/
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include "QF/cvar.h"
|
|
#include "QF/ecs.h"
|
|
#include "QF/render.h"
|
|
#include "QF/sys.h"
|
|
|
|
#include "QF/simd/vec4f.h"
|
|
|
|
#include "r_dynamic.h"
|
|
|
|
psystem_t r_tsystem; //FIXME singleton
|
|
static ecs_system_t trails_system;
|
|
static trailpnt_t *trail_point_buffer;
|
|
static uint32_t trail_point_count;
|
|
static uint32_t trail_point_buffer_size;
|
|
static uint32_t allocated_blocks; // bitmask of 64-point blocks in use
|
|
|
|
typedef struct {
|
|
uint32_t base;
|
|
uint32_t count;
|
|
} pointset_t;
|
|
|
|
enum trails_components {
|
|
trails_pointset,
|
|
|
|
trails_comp_count
|
|
};
|
|
|
|
static void
|
|
pointset_destroy (void *comp, ecs_registry_t *reg)
|
|
{
|
|
pointset_t *pointset = comp;
|
|
int base = pointset->base / 64;
|
|
int count = pointset->count / 64;
|
|
uint32_t mask = ((1 << count) - 1) << base;
|
|
allocated_blocks &= ~mask;
|
|
r_tsystem.numparticles = allocated_blocks;
|
|
}
|
|
|
|
static const component_t trails_components[trails_comp_count] = {
|
|
[trails_pointset] = {
|
|
.size = sizeof (pointset_t),
|
|
.create = 0,
|
|
.name = "pointset",
|
|
.destroy = pointset_destroy,
|
|
},
|
|
};
|
|
|
|
bool
|
|
R_Trail_Valid (psystem_t *system, uint32_t trailid)
|
|
{
|
|
return ECS_EntValid (trailid, trails_system.reg);
|
|
}
|
|
|
|
uint32_t
|
|
R_Trail_Create (psystem_t *system, int num_points, vec4f_t start)
|
|
{
|
|
num_points += 2; // need an extra point at either end
|
|
num_points = (num_points + 31) & ~31; // want a multiple of 32
|
|
num_points *= 2; // each point needs two verts
|
|
|
|
int blocks = num_points / 64;
|
|
uint32_t mask = (1 << blocks) - 1;
|
|
int block_ind;
|
|
for (block_ind = 0; block_ind <= 32 - blocks; block_ind++) {
|
|
if (!(allocated_blocks & mask)) {
|
|
break;
|
|
}
|
|
mask <<= 1;
|
|
}
|
|
if (allocated_blocks & mask) {
|
|
return nullent;
|
|
}
|
|
allocated_blocks |= mask;
|
|
r_tsystem.numparticles = allocated_blocks;
|
|
|
|
uint32_t trail = ECS_NewEntity (trails_system.reg);
|
|
pointset_t pointset = {
|
|
.base = block_ind * 64,
|
|
.count = num_points,
|
|
};
|
|
Ent_SetComponent (trail, trails_system.base + trails_pointset,
|
|
trails_system.reg, &pointset);
|
|
for (uint32_t i = 0; i < pointset.count; i++) {
|
|
static float bary[] = {0, 0, 1, 0, 0, 1, 0, 0};
|
|
auto p = trail_point_buffer + pointset.base + i;
|
|
*p = (trailpnt_t) {
|
|
.pos = start,
|
|
.colora = { 0xc0, 0xa0, 0x60, 0x80 },
|
|
.colorb = { 0x30, 0x30, 0x20, 0x00 },
|
|
.trailid = trail,
|
|
.live = 10,
|
|
};
|
|
p->pos[3] = i & 1 ? 1 : -1;
|
|
VectorCopy (bary + i % 3, p->bary);
|
|
};
|
|
return trail;
|
|
}
|
|
|
|
void
|
|
R_Trail_Update (psystem_t *system, uint32_t trailid, vec4f_t pos)
|
|
{
|
|
pointset_t *p = Ent_GetComponent (trailid,
|
|
trails_system.base + trails_pointset,
|
|
trails_system.reg);
|
|
|
|
trailpnt_t *points = trail_point_buffer + p->base;
|
|
|
|
pos[3] = -1;
|
|
vec4f_t dist = pos - points[4].pos;
|
|
vec4f_t prev1 = points[2].pos;
|
|
vec4f_t prev2 = points[3].pos;
|
|
points[2].pos = pos;
|
|
pos[3] = 1;
|
|
points[3].pos = pos;
|
|
|
|
points[0].pos = points[2].pos + dist;
|
|
points[1].pos = points[3].pos + dist;
|
|
|
|
float len = sqrt (dotf (dist, dist)[0]);
|
|
if (len > 16) {
|
|
for (uint32_t i = 4; i < p->count; i += 2) {
|
|
vec4f_t t1 = points[i + 0].pos;
|
|
vec4f_t t2 = points[i + 1].pos;
|
|
points[i + 0].pos = prev1;
|
|
points[i + 1].pos = prev2;
|
|
prev1 = t1;
|
|
prev2 = t2;
|
|
|
|
points[i + 0].pathoffset = len;
|
|
points[i + 1].pathoffset = len;
|
|
if (i < p->count - 2) {
|
|
dist = points[i + 2].pos - points[i + 0].pos;
|
|
len = sqrt (dotf (dist, dist)[0]);
|
|
}
|
|
}
|
|
} else {
|
|
for (uint32_t i = 4; i < p->count; i += 2) {
|
|
points[i + 0].pathoffset = len;
|
|
points[i + 1].pathoffset = len;
|
|
if (i < p->count - 2) {
|
|
dist = points[i + 2].pos - points[i + 0].pos;
|
|
len = sqrt (dotf (dist, dist)[0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
R_Trail_Destroy (psystem_t *system, uint32_t trailid)
|
|
{
|
|
ECS_DelEntity (trails_system.reg, trailid);
|
|
}
|
|
|
|
|
|
void
|
|
R_ClearTrails (void)
|
|
{
|
|
auto reg = trails_system.reg;
|
|
for (uint32_t i = 0; i < reg->num_entities; i++) {
|
|
uint32_t ent = reg->entities[i];
|
|
uint32_t ind = Ent_Index (ent);
|
|
if (ind == i) {
|
|
ECS_DelEntity (reg, ent);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
R_RunTrails (float dT)
|
|
{
|
|
}
|
|
|
|
void
|
|
R_Trails_Init_Cvars (void)
|
|
{
|
|
Sys_Printf ("R_Trails_Init_Cvars\n");
|
|
}
|
|
|
|
static void
|
|
trails_shutdown (void *data)
|
|
{
|
|
Sys_Printf ("trails_shutdown\n");
|
|
ECS_DelRegistry (trails_system.reg);
|
|
Sys_Free (trail_point_buffer, trail_point_buffer_size);
|
|
}
|
|
|
|
void
|
|
R_Trails_Init (void)
|
|
{
|
|
Sys_Printf ("R_Trails_Init\n");
|
|
Sys_RegisterShutdown (trails_shutdown, 0);
|
|
auto reg = ECS_NewRegistry ("r_trails");
|
|
trails_system.reg = reg;
|
|
trails_system.base = ECS_RegisterComponents (reg, trails_components,
|
|
trails_comp_count);
|
|
ECS_CreateComponentPools (reg);
|
|
|
|
trail_point_count = 32*64;
|
|
trail_point_buffer_size = trail_point_count * sizeof (trailpnt_t);
|
|
trail_point_buffer = Sys_Alloc (trail_point_buffer_size);
|
|
|
|
r_tsystem = (psystem_t) {
|
|
.maxparticles = trail_point_count,
|
|
.particles = (particle_t *) trail_point_buffer,
|
|
.partparams = 0,//FIXME
|
|
.partramps = 0,//FIXME
|
|
};
|
|
}
|