rtx: allow patching light entities

change light position and color example:
```
{
	"_xvk_ent_id" "217"
	"_light" "255 0 255 1000"
	"origin" "-2016 300 -432"
}
```

delete light example:
```
{
	"_xvk_ent_id" "219"
}
```
This commit is contained in:
Ivan Avdeev 2021-11-28 13:38:01 -08:00
parent cd2804b659
commit 7ca6c2128c
2 changed files with 107 additions and 49 deletions

View File

@ -5,6 +5,7 @@
#include "eiface.h" // ARRAYSIZE #include "eiface.h" // ARRAYSIZE
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
#include <string.h>
xvk_map_entities_t g_map_entities; xvk_map_entities_t g_map_entities;
@ -146,7 +147,61 @@ static void parseStopDot( const entity_props_t *props, vk_light_entity_t *le) {
le->stopdot2 = cosf(le->stopdot2 * M_PI / 180.f); le->stopdot2 = cosf(le->stopdot2 * M_PI / 180.f);
} }
static void addLightEntity( const entity_props_t *props, unsigned have_fields ) { static void fillLightFromProps( vk_light_entity_t *le, const entity_props_t *props, unsigned have_fields, qboolean patch, int entity_index ) {
switch (le->type) {
case LightTypePoint:
break;
case LightTypeSpot:
case LightTypeEnvironment:
if (!patch || (have_fields & Field_pitch) || (have_fields & Field_angles) || (have_fields & Field_angle)) {
parseAngles(props, le);
}
if (!patch || (have_fields & Field__cone) || (have_fields & Field__cone2)) {
parseStopDot(props, le);
}
break;
default:
ASSERT(false);
}
if (have_fields & Field_target)
Q_strcpy(le->target_entity, props->target);
if (have_fields & Field_origin)
VectorCopy(props->origin, le->origin);
if (have_fields & Field__light)
{
VectorCopy(props->_light, le->color);
} else if (!patch) {
// same as qrad
VectorSet(le->color, 300, 300, 300);
}
if ( (have_fields & Field_style) != 0) {
le->style = props->style;
}
if (le->type != LightEnvironment && (!patch || (have_fields & Field__light))) {
weirdGoldsrcLightScaling(le->color);
}
gEngine.Con_Reportf("%s light %d (ent=%d): %s targetname=%s color=(%f %f %f) origin=(%f %f %f) style=%d dir=(%f %f %f) stopdot=(%f %f)\n",
patch ? "Patch" : "Added",
g_map_entities.num_lights, entity_index,
le->type == LightTypeEnvironment ? "environment" : le->type == LightTypeSpot ? "spot" : "point",
props->targetname,
le->color[0], le->color[1], le->color[2],
le->origin[0], le->origin[1], le->origin[2],
le->style,
le->dir[0], le->dir[1], le->dir[2],
le->stopdot, le->stopdot2);
}
static void addLightEntity( const entity_props_t *props, unsigned have_fields, int entity_index ) {
const int index = g_map_entities.num_lights; const int index = g_map_entities.num_lights;
vk_light_entity_t *le = g_map_entities.lights + index; vk_light_entity_t *le = g_map_entities.lights + index;
unsigned expected_fields = 0; unsigned expected_fields = 0;
@ -172,61 +227,32 @@ static void addLightEntity( const entity_props_t *props, unsigned have_fields )
le->type = LightTypeSpot; le->type = LightTypeSpot;
expected_fields = Field_origin | Field__cone | Field__cone2; expected_fields = Field_origin | Field__cone | Field__cone2;
} }
parseAngles(props, le);
parseStopDot(props, le);
break; break;
case LightEnvironment: case LightEnvironment:
le->type = LightTypeEnvironment; le->type = LightTypeEnvironment;
parseAngles(props, le);
parseStopDot(props, le);
if (g_map_entities.single_environment_index == NoEnvironmentLights) {
g_map_entities.single_environment_index = index;
} else {
g_map_entities.single_environment_index = MoreThanOneEnvironmentLight;
}
break; break;
}
if (have_fields & Field_target) default:
Q_strcpy(le->target_entity, props->target); ASSERT(false);
}
if ((have_fields & expected_fields) != expected_fields) { if ((have_fields & expected_fields) != expected_fields) {
gEngine.Con_Printf(S_ERROR "Missing some fields for light entity\n"); gEngine.Con_Printf(S_ERROR "Missing some fields for light entity\n");
return; return;
} }
VectorCopy(props->origin, le->origin); if (le->type == LightTypeEnvironment) {
if (g_map_entities.single_environment_index == NoEnvironmentLights) {
if ( (have_fields & Field__light) == 0 ) g_map_entities.single_environment_index = index;
{ } else {
// same as qrad g_map_entities.single_environment_index = MoreThanOneEnvironmentLight;
VectorSet(le->color, 300, 300, 300); }
} else {
VectorCopy(props->_light, le->color);
} }
if ( (have_fields & Field_style) != 0) { fillLightFromProps(le, props, have_fields, false, entity_index);
le->style = props->style;
}
if (le->type != LightEnvironment) {
//gEngine.Con_Reportf("Pre scaling: %f %f %f ", values._light[0], values._light[1], values._light[2]);
weirdGoldsrcLightScaling(le->color);
//gEngine.Con_Reportf("post scaling: %f %f %f\n", values._light[0], values._light[1], values._light[2]);
}
gEngine.Con_Reportf("Added light %d: %s targetname=%s color=(%f %f %f) origin=(%f %f %f) style=%d dir=(%f %f %f) stopdot=(%f %f)\n",
g_map_entities.num_lights,
le->type == LightTypeEnvironment ? "environment" : le->type == LightTypeSpot ? "spot" : "point",
props->targetname,
le->color[0], le->color[1], le->color[2],
le->origin[0], le->origin[1], le->origin[2],
le->style,
le->dir[0], le->dir[1], le->dir[2],
le->stopdot, le->stopdot2);
le->entity_index = entity_index;
g_map_entities.num_lights++; g_map_entities.num_lights++;
} }
@ -305,7 +331,34 @@ static void addPatchSurface( const entity_props_t *props, uint32_t have_fields )
} }
} }
static void parseEntities( char *string ) { int findLightEntityWithIndex( int index ) {
// TODO could do binary search (entities are sorted by index) but why
for (int i = 0; i < g_map_entities.num_lights; ++i) {
if (g_map_entities.lights[i].entity_index == index)
return i;
}
return -1;
}
static void addPatchEntity( const entity_props_t *props, uint32_t have_fields ) {
const int light_index = findLightEntityWithIndex( props->_xvk_ent_id );
if (light_index < 0) {
gEngine.Con_Printf(S_ERROR "Patch light entity with index=%d not found\n", props->_xvk_ent_id);
return;
}
if (have_fields == Field__xvk_ent_id) {
gEngine.Con_Reportf("Deleting light entity (%d of %d) with index=%d\n", light_index, g_map_entities.num_lights, props->_xvk_ent_id);
g_map_entities.num_lights--;
memmove(g_map_entities.lights + light_index, g_map_entities.lights + light_index + 1, sizeof(*g_map_entities.lights) * g_map_entities.num_lights - light_index);
return;
}
fillLightFromProps(g_map_entities.lights + light_index, props, have_fields, true, props->_xvk_ent_id);
}
static void parseEntities( char *string, int *count ) {
unsigned have_fields = 0; unsigned have_fields = 0;
entity_props_t values; entity_props_t values;
char *pos = string; char *pos = string;
@ -331,7 +384,7 @@ static void parseEntities( char *string ) {
case Light: case Light:
case LightSpot: case LightSpot:
case LightEnvironment: case LightEnvironment:
addLightEntity( &values, have_fields ); addLightEntity( &values, have_fields, *count );
break; break;
case Worldspawn: case Worldspawn:
@ -341,12 +394,16 @@ static void parseEntities( char *string ) {
case Unknown: case Unknown:
if (have_fields & Field__xvk_surface_id) { if (have_fields & Field__xvk_surface_id) {
addPatchSurface( &values, have_fields ); addPatchSurface( &values, have_fields );
} else if (have_fields & Field__xvk_ent_id) {
addPatchEntity( &values, have_fields );
} }
break; break;
case Ignored: case Ignored:
// Skip // Skip
break; break;
} }
++(*count);
continue; continue;
} }
@ -406,7 +463,7 @@ static void orientSpotlights( void ) {
} }
} }
static void parsePatches( const model_t *const map ) { static void parsePatches( const model_t *const map, int *count) {
char filename[256]; char filename[256];
byte *data; byte *data;
@ -423,12 +480,13 @@ static void parsePatches( const model_t *const map ) {
return; return;
} }
parseEntities( (char*)data ); parseEntities( (char*)data, count );
Mem_Free(data); Mem_Free(data);
} }
void XVK_ParseMapEntities( void ) { void XVK_ParseMapEntities( void ) {
const model_t* const map = gEngine.pfnGetModelByIndex( 1 ); const model_t* const map = gEngine.pfnGetModelByIndex( 1 );
int entities_count = 0;
ASSERT(map); ASSERT(map);
@ -436,8 +494,8 @@ void XVK_ParseMapEntities( void ) {
g_map_entities.num_lights = 0; g_map_entities.num_lights = 0;
g_map_entities.single_environment_index = NoEnvironmentLights; g_map_entities.single_environment_index = NoEnvironmentLights;
parseEntities( map->entities ); parseEntities( map->entities, &entities_count );
parsePatches( map ); parsePatches( map, &entities_count );
orientSpotlights(); orientSpotlights();
} }

View File

@ -17,8 +17,7 @@
X(12, int, style, Int) \ X(12, int, style, Int) \
X(13, int, _xvk_surface_id, Int) \ X(13, int, _xvk_surface_id, Int) \
X(14, string, _xvk_texture, String) \ X(14, string, _xvk_texture, String) \
X(15, int, _xvk_ent_id, Int) \
//X(13, int, _xvk_ent_id, Int) \
typedef enum { typedef enum {
Unknown = 0, Unknown = 0,
@ -45,6 +44,7 @@ typedef enum {
typedef enum { LightTypePoint, LightTypeSurface, LightTypeSpot, LightTypeEnvironment} LightType; typedef enum { LightTypePoint, LightTypeSurface, LightTypeSpot, LightTypeEnvironment} LightType;
typedef struct { typedef struct {
int entity_index;
LightType type; LightType type;
vec3_t origin; vec3_t origin;