From e0d0e6393d65f08db09e2f0422946681eb6a4591 Mon Sep 17 00:00:00 2001 From: Ivan Avdeev Date: Sun, 24 Oct 2021 13:17:13 -0700 Subject: [PATCH] rtx: add target support for spotlights, fix #128 --- ref_vk/vk_mapents.c | 67 ++++++++++++++++++++++++++++++++++++++++++++- ref_vk/vk_mapents.h | 14 ++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/ref_vk/vk_mapents.c b/ref_vk/vk_mapents.c index 6de92d16..efeacbac 100644 --- a/ref_vk/vk_mapents.c +++ b/ref_vk/vk_mapents.c @@ -46,6 +46,15 @@ static unsigned parseEntPropInt(const char* value, int *out, unsigned bit) { return (1 == sscanf(value, "%d", out)) ? bit : 0; } +static unsigned parseEntPropString(const char* value, string *out, unsigned bit) { + const int len = Q_strlen(value); + if (len >= sizeof(string)) + gEngine.Con_Printf(S_ERROR, "Map entity value '%s' is too long, max length is %d\n", + value, sizeof(string)); + Q_strncpy(*out, value, sizeof(*out)); + return bit; +} + static unsigned parseEntPropVec3(const char* value, vec3_t *out, unsigned bit) { return (3 == sscanf(value, "%f %f %f", &(*out)[0], &(*out)[1], &(*out)[2])) ? bit : 0; } @@ -175,7 +184,8 @@ static void addLightEntity( const entity_props_t *props, unsigned have_fields ) break; } - // TODO target entity support + if (have_fields & Field_target) + Q_strcpy(le->target_entity, props->target); if ((have_fields & expected_fields) != expected_fields) { gEngine.Con_Printf(S_ERROR "Missing some fields for light entity\n"); @@ -208,6 +218,33 @@ static void addLightEntity( const entity_props_t *props, unsigned have_fields ) g_map_entities.num_lights++; } +static void addTargetEntity( const entity_props_t *props ) { + xvk_mapent_target_t *target = g_map_entities.targets + g_map_entities.num_targets; + + gEngine.Con_Reportf("Adding target entity %s at (%f, %f, %f)\n", + props->targetname, props->origin[0], props->origin[1], props->origin[2]); + + if (g_map_entities.num_targets == MAX_MAPENT_TARGETS) { + gEngine.Con_Printf(S_ERROR "Too many map target entities\n"); + return; + } + + Q_strcpy(target->targetname, props->targetname); + VectorCopy(props->origin, target->origin); + + ++g_map_entities.num_targets; +} + +const xvk_mapent_target_t *findTargetByName(const char *name) { + for (int i = 0; i < g_map_entities.num_targets; ++i) { + const xvk_mapent_target_t *target = g_map_entities.targets + i; + if (Q_strcmp(name, target->targetname) == 0) + return target; + } + + return NULL; +} + static void readWorldspawn( const entity_props_t *props ) { Q_strcpy(g_map_entities.wadlist, props->wad); } @@ -220,6 +257,7 @@ void XVK_ParseMapEntities( void ) { ASSERT(map); + g_map_entities.num_targets = 0; g_map_entities.num_lights = 0; g_map_entities.single_environment_index = NoEnvironmentLights; @@ -239,6 +277,9 @@ void XVK_ParseMapEntities( void ) { values = (entity_props_t){0}; continue; } else if (key[0] == '}') { + const int target_fields = Field_targetname | Field_origin; + if ((have_fields & target_fields) == target_fields) + addTargetEntity( &values ); switch (values.classname) { case Light: case LightSpot: @@ -276,4 +317,28 @@ void XVK_ParseMapEntities( void ) { } #undef CHECK_FIELD } + + // Patch spotlight directions based on target entities + for (int i = 0; i < g_map_entities.num_lights; ++i) { + vk_light_entity_t *const light = g_map_entities.lights + i; + const xvk_mapent_target_t *target; + + if (light->type != LightSpot) + continue; + + if (light->target_entity[0] == '\0') + continue; + + target = findTargetByName(light->target_entity); + if (!target) { + gEngine.Con_Printf(S_ERROR "Couldn't find target entity '%s' for spot light %d\n", light->target_entity, i); + continue; + } + + VectorSubtract(target->origin, light->origin, light->dir); + VectorNormalize(light->dir); + + gEngine.Con_Reportf("Light %d patched direction towards '%s': %f %f %f\n", i, target->targetname, + light->dir[0], light->dir[1], light->dir[2]); + } } diff --git a/ref_vk/vk_mapents.h b/ref_vk/vk_mapents.h index 3376ad2e..fd5c3189 100644 --- a/ref_vk/vk_mapents.h +++ b/ref_vk/vk_mapents.h @@ -15,6 +15,8 @@ X(7, float, _cone2, Float) \ X(8, int, _sky, Int) \ X(9, string, wad, WadList) \ + X(10, string, targetname, String) \ + X(11, string, target, String) \ typedef enum { Unknown = 0, @@ -52,8 +54,17 @@ typedef struct { float stopdot, stopdot2; //char pattern[64]; //int dark; + + string target_entity; } vk_light_entity_t; +typedef struct { + string targetname; + vec3_t origin; +} xvk_mapent_target_t; + +#define MAX_MAPENT_TARGETS 256 + typedef struct { int num_lights; vk_light_entity_t lights[256]; @@ -61,6 +72,9 @@ typedef struct { int single_environment_index; string wadlist; + + int num_targets; + xvk_mapent_target_t targets[MAX_MAPENT_TARGETS]; } xvk_map_entities_t; extern xvk_map_entities_t g_map_entities;