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:
parent
cd2804b659
commit
7ca6c2128c
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue