Basic parsing of hl2bsp static props.
This commit is contained in:
parent
76d232b007
commit
84313ce213
|
@ -3297,6 +3297,7 @@ void CL_ClearLerpEntsParticleState(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel);
|
||||||
void CL_LinkStaticEntities(void *pvs, int *areas)
|
void CL_LinkStaticEntities(void *pvs, int *areas)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -3401,6 +3402,33 @@ void CL_LinkStaticEntities(void *pvs, int *areas)
|
||||||
// FIXME: no effects on static ents
|
// FIXME: no effects on static ents
|
||||||
// CLQ1_AddPowerupShell(ent, false, stat->effects);
|
// CLQ1_AddPowerupShell(ent, false, stat->effects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cl.worldmodel->numstaticents)
|
||||||
|
{
|
||||||
|
entity_t *src;
|
||||||
|
for (i = 0; i < cl.worldmodel->numstaticents; i++)
|
||||||
|
{
|
||||||
|
if (cl_numvisedicts == cl_maxvisedicts)
|
||||||
|
{
|
||||||
|
cl_expandvisents=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
src = &cl.worldmodel->staticents[i];
|
||||||
|
if (!src->model || src->model->loadstate != MLS_LOADED)
|
||||||
|
{
|
||||||
|
if (src->model && src->model->loadstate == MLS_NOTLOADED)
|
||||||
|
Mod_LoadModel(src->model, MLV_WARN); //we use threads, so these'll load in time.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!src->light_known)
|
||||||
|
R_CalcModelLighting(src, src->model); //bake and cache, now everything else is working.
|
||||||
|
|
||||||
|
ent = &cl_visedicts[cl_numvisedicts++];
|
||||||
|
*ent = *src;
|
||||||
|
ent->framestate.g[FS_REG].frametime[0] = cl.time;
|
||||||
|
ent->framestate.g[FS_REG].frametime[1] = cl.time;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns cos(angle)
|
//returns cos(angle)
|
||||||
|
|
|
@ -168,6 +168,7 @@ enum mod_purge_e
|
||||||
};
|
};
|
||||||
enum mlverbosity_e
|
enum mlverbosity_e
|
||||||
{
|
{
|
||||||
|
MLV_NOLOAD, //leave it notloaded.
|
||||||
MLV_SILENT,
|
MLV_SILENT,
|
||||||
MLV_WARN,
|
MLV_WARN,
|
||||||
MLV_WARNSYNC,
|
MLV_WARNSYNC,
|
||||||
|
|
|
@ -2127,6 +2127,56 @@ void R_DrawNameTags(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0 ; i<cl.num_statics ; i++)
|
||||||
|
{
|
||||||
|
entity_t *state = &cl_static_entities[i].ent;
|
||||||
|
mod = state->model;
|
||||||
|
if (mod && mod->loadstate == MLS_LOADED)
|
||||||
|
VectorInterpolate(mod->mins, 0.5, mod->maxs, org);
|
||||||
|
else
|
||||||
|
VectorClear(org);
|
||||||
|
VectorAdd(org, state->origin, org);
|
||||||
|
if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y))
|
||||||
|
{
|
||||||
|
char *entstr;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
entstr = state->model->name;
|
||||||
|
if (entstr)
|
||||||
|
{
|
||||||
|
vec2_t scale = {8,8};
|
||||||
|
x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x;
|
||||||
|
y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y;
|
||||||
|
R_DrawTextField(x, y, vid.width - x, vid.height - y, entstr, CON_WHITEMASK, CPRINT_TALIGN, font_default, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0 ; i<cl.worldmodel->numstaticents; i++)
|
||||||
|
{
|
||||||
|
entity_t *state = &cl.worldmodel->staticents[i];
|
||||||
|
mod = state->model;
|
||||||
|
if (mod && mod->loadstate == MLS_LOADED)
|
||||||
|
VectorInterpolate(mod->mins, 0.5, mod->maxs, org);
|
||||||
|
else
|
||||||
|
VectorClear(org);
|
||||||
|
VectorAdd(org, state->origin, org);
|
||||||
|
if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y))
|
||||||
|
{
|
||||||
|
char *entstr;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
entstr = state->model->name;
|
||||||
|
if (entstr)
|
||||||
|
{
|
||||||
|
vec2_t scale = {8,8};
|
||||||
|
x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x;
|
||||||
|
y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y;
|
||||||
|
R_DrawTextField(x, y, vid.width - x, vid.height - y, entstr, CON_WHITEMASK, CPRINT_TALIGN, font_default, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef Q2SERVER //not enough fields for it to really be worth it.
|
#ifdef Q2SERVER //not enough fields for it to really be worth it.
|
||||||
if (w == &sv.world && svs.gametype == GT_QUAKE2 && ge)
|
if (w == &sv.world && svs.gametype == GT_QUAKE2 && ge)
|
||||||
|
|
|
@ -5476,6 +5476,200 @@ static qboolean CModHL2_LoadBrushSides (model_t *mod, qbyte *mod_base, lump_t *l
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int count;
|
||||||
|
struct {
|
||||||
|
unsigned int id;
|
||||||
|
unsigned short flags;
|
||||||
|
unsigned short version;
|
||||||
|
unsigned int ofs;
|
||||||
|
unsigned int len;
|
||||||
|
} sl[1];
|
||||||
|
} hlgamelumpheader_t;
|
||||||
|
static qboolean CModHL2_LoadStaticProps(model_t *mod, qbyte *offset, size_t size, int version)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char name[128];
|
||||||
|
} *modelref;
|
||||||
|
size_t nummodels, numleafrefs, numprops, i;
|
||||||
|
unsigned short *leafref;
|
||||||
|
entity_t *ent;
|
||||||
|
|
||||||
|
size_t modelindex;
|
||||||
|
|
||||||
|
qboolean skip = false;
|
||||||
|
int dxlevel = 95, cpulevel=0, gpulevel=0;
|
||||||
|
|
||||||
|
qbyte *prop;
|
||||||
|
size_t propsize;
|
||||||
|
switch(version)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
propsize = 14*4;
|
||||||
|
break;
|
||||||
|
case 5: //+scale
|
||||||
|
propsize = 15*4;
|
||||||
|
break;
|
||||||
|
case 6://+dxlevels
|
||||||
|
propsize = 16*4;
|
||||||
|
break;
|
||||||
|
case 7: //+rgba
|
||||||
|
case 8: //-dxlevels+[cg]pulevels
|
||||||
|
propsize = 17*4;
|
||||||
|
break;
|
||||||
|
case 9: //+360
|
||||||
|
case 10://-360+flags
|
||||||
|
propsize = 18*4;
|
||||||
|
break;
|
||||||
|
case 11://+scale
|
||||||
|
propsize = 19*4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return true; //version not supported, just ignore it entirely. sorry.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nummodels = LittleLong(*(int*)offset);
|
||||||
|
offset += 4;
|
||||||
|
size -= 4;
|
||||||
|
modelref = (void*)offset;
|
||||||
|
offset += nummodels*sizeof(*modelref);
|
||||||
|
size -= nummodels*sizeof(*modelref);
|
||||||
|
|
||||||
|
numleafrefs = LittleLong(*(int*)offset);
|
||||||
|
offset += 4;
|
||||||
|
size -= 4;
|
||||||
|
leafref = (void*)offset;
|
||||||
|
offset += numleafrefs*sizeof(*leafref);
|
||||||
|
size -= numleafrefs*sizeof(*leafref);
|
||||||
|
|
||||||
|
numprops = LittleLong(*(int*)offset);
|
||||||
|
offset += 4;
|
||||||
|
size -= 4;
|
||||||
|
prop = (void*)offset;
|
||||||
|
offset += numprops*propsize;
|
||||||
|
size -= numprops*propsize;
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
return true; //funny lump size...
|
||||||
|
|
||||||
|
mod->staticents = ZG_Malloc(&mod->memgroup, sizeof(*mod->staticents)*numprops);
|
||||||
|
for (i = 0, ent = mod->staticents; i < numprops; i++)
|
||||||
|
{
|
||||||
|
skip = false;
|
||||||
|
V_ClearEntity(ent);
|
||||||
|
|
||||||
|
ent->playerindex = -1;
|
||||||
|
ent->topcolour = TOP_DEFAULT;
|
||||||
|
ent->bottomcolour = BOTTOM_DEFAULT;
|
||||||
|
#ifdef PEXT_SCALE
|
||||||
|
ent->scale = 1;
|
||||||
|
#endif
|
||||||
|
ent->shaderRGBAf[0] = 1;
|
||||||
|
ent->shaderRGBAf[1] = 1;
|
||||||
|
ent->shaderRGBAf[2] = 1;
|
||||||
|
ent->shaderRGBAf[3] = 1;
|
||||||
|
ent->framestate.g[FS_REG].frame[0] = 0;
|
||||||
|
ent->framestate.g[FS_REG].lerpweight[0] = 1;
|
||||||
|
|
||||||
|
|
||||||
|
ent->origin[0] = LittleFloat(*(float*)prop); prop += sizeof(float);
|
||||||
|
ent->origin[1] = LittleFloat(*(float*)prop); prop += sizeof(float);
|
||||||
|
ent->origin[2] = LittleFloat(*(float*)prop); prop += sizeof(float);
|
||||||
|
ent->angles[0] = LittleFloat(*(float*)prop); prop += sizeof(float);
|
||||||
|
ent->angles[1] = LittleFloat(*(float*)prop); prop += sizeof(float);
|
||||||
|
ent->angles[2] = LittleFloat(*(float*)prop); prop += sizeof(float);
|
||||||
|
modelindex = (unsigned short)LittleShort(*(short*)prop); prop += sizeof(unsigned short);
|
||||||
|
/*firstleaf = LittleShort(*(unsigned short*)prop)*/; prop += sizeof(unsigned short);
|
||||||
|
/*leafcount = LittleShort(*(unsigned short*)prop)*/; prop += sizeof(unsigned short);
|
||||||
|
/*ent->solid = *prop*/; prop += sizeof(qbyte);
|
||||||
|
/*ent->flags = *prop*/; prop += sizeof(qbyte);
|
||||||
|
ent->skinnum = LittleLong(*(unsigned int*)prop); prop += sizeof(unsigned int);
|
||||||
|
/*ent->fademindist = LittleFloat(*(float*)prop)*/; prop += sizeof(float);
|
||||||
|
/*ent->fademaxdist = LittleFloat(*(float*)prop)*/; prop += sizeof(float);
|
||||||
|
/*ent->lightingorigin[0] = LittleFloat(*(float*)prop)*/; prop += sizeof(float);
|
||||||
|
/*ent->lightingorigin[1] = LittleFloat(*(float*)prop)*/; prop += sizeof(float);
|
||||||
|
/*ent->lightingorigin[2] = LittleFloat(*(float*)prop)*/; prop += sizeof(float);
|
||||||
|
if (version >= 5)
|
||||||
|
{
|
||||||
|
/*ent->fadescale = LittleFloat(*(float*)prop);*/ prop += sizeof(float);
|
||||||
|
}
|
||||||
|
if (version >= 8)
|
||||||
|
{
|
||||||
|
skip |= (prop[0] > cpulevel || cpulevel > prop[1]); prop += sizeof(qbyte)*2;
|
||||||
|
skip |= (prop[0] > gpulevel || gpulevel > prop[1]); prop += sizeof(qbyte)*2;
|
||||||
|
}
|
||||||
|
else if (version >= 6)
|
||||||
|
{
|
||||||
|
unsigned short minlev, maxlev;
|
||||||
|
minlev = LittleShort(*(unsigned short*)prop); prop += sizeof(unsigned short);
|
||||||
|
maxlev = LittleShort(*(unsigned short*)prop); prop += sizeof(unsigned short);
|
||||||
|
skip |= (minlev > dxlevel || dxlevel > maxlev);
|
||||||
|
}
|
||||||
|
if (version >= 7)
|
||||||
|
{
|
||||||
|
VectorScale(prop, 1/255.0, ent->shaderRGBAf); prop += sizeof(qbyte)*4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version == 9)
|
||||||
|
{
|
||||||
|
/*disablex360 = LittleLong(*(int*)prop);*/ prop += sizeof(int);
|
||||||
|
}
|
||||||
|
if (version >= 10)
|
||||||
|
{
|
||||||
|
ent->flags = LittleLong(*(int*)prop); prop += sizeof(int);
|
||||||
|
}
|
||||||
|
if (version >= 11)
|
||||||
|
{
|
||||||
|
ent->scale = LittleFloat(*(float*)prop); prop += sizeof(float);
|
||||||
|
}
|
||||||
|
|
||||||
|
//okay, we parsed the prop data now...
|
||||||
|
skip |= modelindex >= nummodels;
|
||||||
|
if (skip)
|
||||||
|
continue; //we're ignoring it for some reason
|
||||||
|
ent->model = Mod_FindName(modelref[modelindex].name);
|
||||||
|
AngleVectorsFLU(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]);
|
||||||
|
|
||||||
|
//Hack: lighting is wrong.
|
||||||
|
ent->light_known = 1;
|
||||||
|
VectorSet(ent->light_dir, 0, 0.707, 0.707);
|
||||||
|
VectorSet(ent->light_avg, 0.75, 0.75, 0.75);
|
||||||
|
VectorSet(ent->light_range, 0.5, 0.5, 0.5);
|
||||||
|
|
||||||
|
//not all props will be emitted, according to d3d levels...
|
||||||
|
mod->numstaticents++;
|
||||||
|
ent++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static qboolean CModHL2_LoadGameLump(model_t *mod, qbyte *mod_base, lump_t *l)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
hlgamelumpheader_t *blob = (void*)(mod_base + l->fileofs);
|
||||||
|
if (!l->filelen)
|
||||||
|
return true; //missing
|
||||||
|
if (l->filelen < sizeof(*blob) + sizeof(*blob->sl)*(blob->count-1))
|
||||||
|
return false; //not even enough space for the header...
|
||||||
|
for (i = 0; i < blob->count; i++)
|
||||||
|
{
|
||||||
|
#define LUMPTYPE(a,b,c,d, minver, maxver) (blob->sl[i].id == (((qbyte)a<<24)|((qbyte)b<<16)|((qbyte)c<<8)|((qbyte)d<<0)) && blob->sl[i].version >= minver && blob->sl[i].version <= maxver)
|
||||||
|
if (LUMPTYPE('s','p','r','p', 4,10) && !blob->sl[i].flags) //static props (placed by mapper)
|
||||||
|
CModHL2_LoadStaticProps(mod, mod_base+blob->sl[i].ofs/*sigh*/, blob->sl[i].len, blob->sl[i].version);
|
||||||
|
else if (LUMPTYPE('d','p','r','p', 4,4) && !blob->sl[i].flags) //dynamic props (generated by textures)
|
||||||
|
;
|
||||||
|
else if (LUMPTYPE('d','p','l','t', 0,0) && !blob->sl[i].flags) //detail prop ldr lighting
|
||||||
|
;
|
||||||
|
else if (LUMPTYPE('d','p','l','h', 0,0) && !blob->sl[i].flags) //detail prop hdr lighting
|
||||||
|
;
|
||||||
|
else
|
||||||
|
Con_Printf("Unsupported gamelump id/version %c%c%c%c %i\n", (blob->sl[i].id>>24),(blob->sl[i].id>>16),(blob->sl[i].id>>8),(blob->sl[i].id>>0),blob->sl[i].version);
|
||||||
|
#undef LUMPTYPE
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
static searchpathfuncs_t *CModHL2_LoadArchive(model_t *mod, void *base, size_t len)
|
static searchpathfuncs_t *CModHL2_LoadArchive(model_t *mod, void *base, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -5591,6 +5785,8 @@ static qboolean VBSP_LoadModel(model_t *mod, qbyte *mod_base, size_t filelen, ch
|
||||||
noerrors = noerrors && CModQ2_LoadAreas (mod, mod_base, &header.lumps[VLUMP_AREAS]);
|
noerrors = noerrors && CModQ2_LoadAreas (mod, mod_base, &header.lumps[VLUMP_AREAS]);
|
||||||
noerrors = noerrors && CModHL2_LoadAreaPortals (mod, mod_base, &header.lumps[VLUMP_AREAPORTALS], &header.lumps[VLUMP_AREAPORTALVERTS]);
|
noerrors = noerrors && CModHL2_LoadAreaPortals (mod, mod_base, &header.lumps[VLUMP_AREAPORTALS], &header.lumps[VLUMP_AREAPORTALVERTS]);
|
||||||
|
|
||||||
|
noerrors = noerrors && CModHL2_LoadGameLump (mod, mod_base, &header.lumps[VLUMP_GAMELUMP]);
|
||||||
|
|
||||||
if (!noerrors)
|
if (!noerrors)
|
||||||
return false;
|
return false;
|
||||||
#ifdef HAVE_SERVER
|
#ifdef HAVE_SERVER
|
||||||
|
|
|
@ -1059,6 +1059,7 @@ void Mod_ModelLoaded(void *ctx, void *data, size_t a, size_t b)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (a != MLS_LOADED)
|
||||||
switch(verbose)
|
switch(verbose)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -1070,6 +1071,7 @@ void Mod_ModelLoaded(void *ctx, void *data, size_t a, size_t b)
|
||||||
if (*mod->name != '*' && strcmp(mod->name, "null") && mod_warnmodels.ival && !previouslyfailed)
|
if (*mod->name != '*' && strcmp(mod->name, "null") && mod_warnmodels.ival && !previouslyfailed)
|
||||||
Con_Printf(CON_ERROR "Unable to load %s\n", mod->name);
|
Con_Printf(CON_ERROR "Unable to load %s\n", mod->name);
|
||||||
break;
|
break;
|
||||||
|
case MLV_NOLOAD: //shouldn't happen.
|
||||||
case MLV_SILENT:
|
case MLV_SILENT:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1338,7 +1340,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
|
||||||
|
|
||||||
BZ_Free(buf);
|
BZ_Free(buf);
|
||||||
|
|
||||||
COM_AddWork(WG_MAIN, Mod_ModelLoaded, mod, NULL, MLS_LOADED, 0);
|
COM_AddWork(WG_MAIN, Mod_ModelLoaded, mod, NULL, MLS_LOADED, verbose);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1356,7 +1358,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
|
||||||
|
|
||||||
model_t *Mod_LoadModel (model_t *mod, enum mlverbosity_e verbose)
|
model_t *Mod_LoadModel (model_t *mod, enum mlverbosity_e verbose)
|
||||||
{
|
{
|
||||||
if (mod->loadstate == MLS_NOTLOADED && *mod->name != '*')
|
if (mod->loadstate == MLS_NOTLOADED && *mod->name != '*' && verbose != MLV_NOLOAD)
|
||||||
{
|
{
|
||||||
mod->loadstate = MLS_LOADING;
|
mod->loadstate = MLS_LOADING;
|
||||||
if (verbose == MLV_ERROR || verbose == MLV_WARNSYNC)
|
if (verbose == MLV_ERROR || verbose == MLV_WARNSYNC)
|
||||||
|
|
|
@ -1133,6 +1133,8 @@ typedef struct model_s
|
||||||
#ifdef HL2BSPS
|
#ifdef HL2BSPS
|
||||||
dispinfo_t *displacements;
|
dispinfo_t *displacements;
|
||||||
unsigned int numdisplacements;
|
unsigned int numdisplacements;
|
||||||
|
entity_t *staticents;
|
||||||
|
size_t numstaticents;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
modelfuncs_t funcs;
|
modelfuncs_t funcs;
|
||||||
|
|
Loading…
Reference in New Issue