15 Mar 2017
This commit is contained in:
parent
fdc53c3cc1
commit
72f2dc8782
|
@ -89,6 +89,8 @@ typedef struct
|
|||
unsigned short max_extent; // default is 16, subdivision step ((texture_step * max_extent) - texture_step)
|
||||
short groupid; // to determine equal landscapes from various groups, -1 - no group
|
||||
|
||||
vec3_t mins, maxs; // terrain bounds (fill by user)
|
||||
|
||||
int reserved[32]; // just for future expansions or mod-makers
|
||||
} mfaceinfo_t;
|
||||
|
||||
|
@ -102,20 +104,6 @@ typedef struct
|
|||
int flags; // sky or slime, no lightmap or 256 subdivision
|
||||
} mtexinfo_t;
|
||||
|
||||
// 73 bytes per VBO vertex
|
||||
// FIXME: align to 32 bytes
|
||||
typedef struct glvert_s
|
||||
{
|
||||
vec3_t vertex; // position
|
||||
vec3_t normal; // normal
|
||||
vec2_t stcoord; // ST texture coords
|
||||
vec2_t lmcoord; // ST lightmap coords
|
||||
vec2_t sccoord; // ST scissor coords (decals only) - for normalmap coords migration
|
||||
vec3_t tangent; // tangent
|
||||
vec3_t binormal; // binormal
|
||||
byte color[4]; // colors per vertex
|
||||
} glvert_t;
|
||||
|
||||
typedef struct glpoly_s
|
||||
{
|
||||
struct glpoly_s *next;
|
||||
|
@ -154,13 +142,11 @@ struct decal_s
|
|||
float dy; //
|
||||
float scale; // Pixel scale
|
||||
short texture; // Decal texture
|
||||
byte flags; // Decal flags FDECAL_*
|
||||
short flags; // Decal flags FDECAL_*
|
||||
short entityIndex; // Entity this is attached to
|
||||
// Xash3D added
|
||||
// Xash3D specific
|
||||
vec3_t position; // location of the decal center in world space.
|
||||
vec3_t saxis; // direction of the s axis in world space
|
||||
struct msurfmesh_s *mesh; // decal mesh in local space
|
||||
int reserved[4]; // for future expansions
|
||||
glpoly_t *polys; // precomputed decal vertices
|
||||
};
|
||||
|
||||
typedef struct mleaf_s
|
||||
|
@ -183,6 +169,32 @@ typedef struct mleaf_s
|
|||
|
||||
} mleaf_t;
|
||||
|
||||
// surface extradata
|
||||
typedef struct mextrasurf_s
|
||||
{
|
||||
vec3_t mins, maxs;
|
||||
vec3_t origin; // surface origin
|
||||
struct msurface_s *surf; // upcast to surface
|
||||
|
||||
int dlight_s, dlight_t; // gl lightmap coordinates for dynamic lightmaps
|
||||
|
||||
int mirrortexturenum; // gl texnum
|
||||
float mirrormatrix[4][4];
|
||||
|
||||
struct mextrasurf_s *mirrorchain; // for gl_texsort drawing
|
||||
struct mextrasurf_s *detailchain; // for detail textures drawing
|
||||
struct msurface_s *lightmapchain; // lightmapped polys
|
||||
struct cl_entity_s *parent; // upcast to owner entity
|
||||
color24 *deluxemap; // note: this is the actual deluxemap data for this surface
|
||||
// begin userdata
|
||||
struct grasshdr_s *grass; // grass that linked by this surface
|
||||
unsigned short grasscount; // number of bushes per polygon (used to determine total VBO size)
|
||||
unsigned short numverts; // world->vertexes[]
|
||||
int firstvertex; // fisrt look up in tr.tbn_vectors[], then acess to world->vertexes[]
|
||||
|
||||
int reserved[32]; // just for future expansions or mod-makers
|
||||
} mextrasurf_t;
|
||||
|
||||
typedef struct msurface_s
|
||||
{
|
||||
int visframe; // should be drawn when node is crossed
|
||||
|
@ -211,44 +223,12 @@ typedef struct msurface_s
|
|||
int lightmaptexturenum;
|
||||
byte styles[MAXLIGHTMAPS];
|
||||
int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap
|
||||
struct msurface_s *lightmapchain; // for new dlights rendering (was cached_dlight)
|
||||
mextrasurf_t *info; // pointer to surface extradata (was cached_dlight)
|
||||
|
||||
color24 *samples; // note: this is the actual lightmap data for this surface
|
||||
decal_t *pdecals;
|
||||
} msurface_t;
|
||||
|
||||
typedef struct msurfmesh_s
|
||||
{
|
||||
unsigned short numVerts;
|
||||
unsigned short numElems; // ~ 20 000 vertex per one surface. Should be enough
|
||||
unsigned int startVert; // user-variable. may be used for construct world single-VBO
|
||||
unsigned int startElem; // user-variable. may be used for construct world single-VBO
|
||||
|
||||
glvert_t *verts; // vertexes array
|
||||
unsigned short *elems; // indices
|
||||
|
||||
struct msurface_s *surf; // pointer to parent surface. Just for consistency
|
||||
struct msurfmesh_s *next; // temporary chain of subdivided surfaces
|
||||
} msurfmesh_t;
|
||||
|
||||
// surface extradata stored in cache.data for all brushmodels
|
||||
typedef struct mextrasurf_s
|
||||
{
|
||||
vec3_t mins, maxs;
|
||||
vec3_t origin; // surface origin
|
||||
msurfmesh_t *mesh; // VBO\VA ready surface mesh. Not used by engine but can be used by mod-makers
|
||||
|
||||
int dlight_s, dlight_t; // gl lightmap coordinates for dynamic lightmaps
|
||||
|
||||
int mirrortexturenum; // gl texnum
|
||||
float mirrormatrix[4][4];
|
||||
struct mextrasurf_s *mirrorchain; // for gl_texsort drawing
|
||||
struct mextrasurf_s *detailchain; // for detail textures drawing
|
||||
color24 *deluxemap; // note: this is the actual deluxemap data for this surface
|
||||
|
||||
int reserved[32]; // just for future expansions or mod-makers
|
||||
} mextrasurf_t;
|
||||
|
||||
typedef struct hull_s
|
||||
{
|
||||
dclipnode_t *clipnodes;
|
||||
|
|
|
@ -18,7 +18,7 @@ GNU General Public License for more details.
|
|||
|
||||
// list of engine features that can be enabled through callback SV_CheckFeatures
|
||||
#define ENGINE_WRITE_LARGE_COORD (1<<0) // replace standard message WRITE_COORD with big message for support more than 8192 units in world
|
||||
#define ENGINE_BUILD_SURFMESHES (1<<1) // bulid surface meshes that goes into mextrasurf->mesh. For mod makers and custom renderers
|
||||
// reserved
|
||||
#define ENGINE_LOAD_DELUXEDATA (1<<2) // loading deluxemap for map (if present)
|
||||
#define ENGINE_TRANSFORM_TRACE_AABB (1<<3) // transform trace bbox into local space of rotating bmodels
|
||||
#define ENGINE_LARGE_LIGHTMAPS (1<<4) // change lightmap sizes from 128x128 to 256x256
|
||||
|
|
|
@ -30,9 +30,6 @@ GNU General Public License for more details.
|
|||
#define CL_RENDER_INTERFACE_VERSION 36
|
||||
#define MAX_STUDIO_DECALS 4096 // + unused space of BSP decals
|
||||
|
||||
#define SURF_INFO( surf, mod ) ((mextrasurf_t *)mod->cache.data + (surf - mod->surfaces))
|
||||
#define INFO_SURF( surf, mod ) (mod->surfaces + (surf - (mextrasurf_t *)mod->cache.data))
|
||||
|
||||
// render info parms
|
||||
#define PARM_TEX_WIDTH 1 // all parms with prefix 'TEX_' receive arg as texnum
|
||||
#define PARM_TEX_HEIGHT 2 // otherwise it's not used
|
||||
|
@ -220,7 +217,6 @@ typedef struct render_api_s
|
|||
int (*COM_CompareFileTime)( const char *filename1, const char *filename2, int *iCompare );
|
||||
void (*Host_Error)( const char *error, ... ); // cause Host Error
|
||||
int (*SPR_LoadExt)( const char *szPicName, unsigned int texFlags ); // extended version of SPR_Load
|
||||
void (*TessPolygon)( struct msurface_s *surf, struct model_s *mod, float tessSize );
|
||||
struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e );
|
||||
const struct ref_overview_s *( *GetOverviewParms )( void );
|
||||
void (*S_FadeMusicVolume)( float fadePercent ); // fade background track (0-100 percents)
|
||||
|
|
|
@ -40,6 +40,8 @@ cvar_t defaultteam = {"mp_defaultteam","0" };
|
|||
cvar_t allowmonsters={"mp_allowmonsters","0", FCVAR_SERVER };
|
||||
|
||||
cvar_t mp_chattime = {"mp_chattime","10", FCVAR_SERVER };
|
||||
cvar_t saved1 = { "saved_cvar", "0", FCVAR_ARCHIVE };
|
||||
|
||||
|
||||
// Engine Cvars
|
||||
cvar_t *g_psv_gravity = NULL;
|
||||
|
@ -480,6 +482,7 @@ void GameDLLInit( void )
|
|||
CVAR_REGISTER (&allowmonsters);
|
||||
|
||||
CVAR_REGISTER (&mp_chattime);
|
||||
CVAR_REGISTER (&saved1);
|
||||
|
||||
// REGISTER CVARS FOR SKILL LEVEL STUFF
|
||||
// Agrunt
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
#ifndef ALIAS_H
|
||||
#define ALIAS_H
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
ALIAS MODELS
|
||||
|
||||
Alias models are position independent, so the cache manager can move them.
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define IDALIASHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I') // little-endian "IDPO"
|
||||
|
||||
#define ALIAS_VERSION 6
|
||||
|
||||
// must match definition in sprite.h
|
||||
#ifndef SYNCTYPE_T
|
||||
#define SYNCTYPE_T
|
||||
typedef enum
|
||||
{
|
||||
ST_SYNC = 0,
|
||||
ST_RAND
|
||||
} synctype_t;
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ALIAS_SINGLE = 0,
|
||||
ALIAS_GROUP
|
||||
} aliasframetype_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ALIAS_SKIN_SINGLE = 0,
|
||||
ALIAS_SKIN_GROUP
|
||||
} aliasskintype_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ident;
|
||||
int version;
|
||||
vec3_t scale;
|
||||
vec3_t scale_origin;
|
||||
float boundingradius;
|
||||
vec3_t eyeposition;
|
||||
int numskins;
|
||||
int skinwidth;
|
||||
int skinheight;
|
||||
int numverts;
|
||||
int numtris;
|
||||
int numframes;
|
||||
synctype_t synctype;
|
||||
int flags;
|
||||
float size;
|
||||
} daliashdr_t;
|
||||
|
||||
// TODO: could be shorts
|
||||
typedef struct
|
||||
{
|
||||
int onseam;
|
||||
int s;
|
||||
int t;
|
||||
} stvert_t;
|
||||
|
||||
typedef struct dtriangle_s
|
||||
{
|
||||
int facesfront;
|
||||
int vertindex[3];
|
||||
} dtriangle_t;
|
||||
|
||||
#define DT_FACES_FRONT 0x0010
|
||||
#define ALIAS_ONSEAM 0x0020
|
||||
|
||||
// This mirrors trivert_t in trilib.h, is present so Quake knows how to
|
||||
// load this data
|
||||
typedef struct
|
||||
{
|
||||
byte v[3];
|
||||
byte lightnormalindex;
|
||||
} trivertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
trivertex_t bboxmin; // lightnormal isn't used
|
||||
trivertex_t bboxmax; // lightnormal isn't used
|
||||
char name[16]; // frame name from grabbing
|
||||
} daliasframe_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numframes;
|
||||
trivertx_t bboxmin; // lightnormal isn't used
|
||||
trivertx_t bboxmax; // lightnormal isn't used
|
||||
} daliasgroup_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numskins;
|
||||
} daliasskingroup_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float interval;
|
||||
} daliasinterval_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float interval;
|
||||
} daliasskininterval_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
aliasframetype_t type;
|
||||
} daliasframetype_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
aliasskintype_t type;
|
||||
} daliasskintype_t;
|
||||
|
||||
#endif//ALIAS_H
|
|
@ -125,7 +125,7 @@ void CL_PlayCDTrack_f( void )
|
|||
if( paused ) Msg( "Paused %s track %u\n", looped ? "looping" : "playing", track );
|
||||
else Msg( "Currently %s track %u\n", looped ? "looping" : "playing", track );
|
||||
}
|
||||
Msg( "Volume is %f\n", Cvar_VariableValue( "musicvolume" ));
|
||||
Msg( "Volume is %f\n", Cvar_VariableValue( "MP3Volume" ));
|
||||
return;
|
||||
}
|
||||
else Msg( "cd: unknown command %s\n", command );
|
||||
|
|
|
@ -137,6 +137,7 @@ qboolean CL_EntityCustomLerp( cl_entity_t *e )
|
|||
case MOVETYPE_STEP:
|
||||
case MOVETYPE_WALK:
|
||||
case MOVETYPE_FLY:
|
||||
case MOVETYPE_COMPOUND:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1057,7 +1058,7 @@ void CL_LinkPacketEntities( frame_t *frame )
|
|||
|
||||
parametric = ( ent->curstate.impacttime != 0.0f && ent->curstate.starttime != 0.0f );
|
||||
|
||||
if( !parametric )
|
||||
if( !parametric && ent->curstate.movetype != MOVETYPE_COMPOUND )
|
||||
{
|
||||
if( ent->curstate.animtime == ent->prevstate.animtime && !VectorCompare( ent->curstate.origin, ent->prevstate.origin ))
|
||||
ent->lastmove = cl.time + 0.2;
|
||||
|
@ -1133,7 +1134,7 @@ void CL_LinkPacketEntities( frame_t *frame )
|
|||
continue;
|
||||
}
|
||||
|
||||
if( ent->curstate.aiment != 0 )
|
||||
if( ent->curstate.aiment != 0 && ent->curstate.movetype != MOVETYPE_COMPOUND )
|
||||
ent->curstate.movetype = MOVETYPE_FOLLOW;
|
||||
|
||||
if( FBitSet( ent->curstate.effects, EF_NOINTERP ))
|
||||
|
|
|
@ -518,7 +518,7 @@ void SCR_InstallParticlePalette( void )
|
|||
if( !pic ) pic = FS_LoadImage( "gfx/palette.pal", NULL, 0 );
|
||||
|
||||
// NOTE: imagelib required this fakebuffer for loading internal palette
|
||||
if( !pic ) pic = FS_LoadImage( "#valve.pal", ((byte *)&i), 768 );
|
||||
if( !pic ) pic = FS_LoadImage( "#valve.pal", (byte *)&i, 768 );
|
||||
|
||||
if( pic )
|
||||
{
|
||||
|
@ -545,11 +545,11 @@ void SCR_InstallParticlePalette( void )
|
|||
void SCR_RegisterTextures( void )
|
||||
{
|
||||
// register gfx.wad images
|
||||
cls.pauseIcon = GL_LoadTexture( "gfx.wad/paused.lmp", NULL, 0, TF_IMAGE, NULL );
|
||||
cls.pauseIcon = GL_LoadTexture( "gfx/paused.lmp", NULL, 0, TF_IMAGE, NULL );
|
||||
if( cl_allow_levelshots->value )
|
||||
cls.loadingBar = GL_LoadTexture( "gfx.wad/lambda.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE, NULL );
|
||||
else cls.loadingBar = GL_LoadTexture( "gfx.wad/lambda.lmp", NULL, 0, TF_IMAGE, NULL );
|
||||
cls.tileImage = GL_LoadTexture( "gfx.wad/backtile.lmp", NULL, 0, TF_IMAGE, NULL );
|
||||
cls.loadingBar = GL_LoadTexture( "gfx/lambda.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE, NULL );
|
||||
else cls.loadingBar = GL_LoadTexture( "gfx/lambda.lmp", NULL, 0, TF_IMAGE, NULL );
|
||||
cls.tileImage = GL_LoadTexture( "gfx/backtile.lmp", NULL, 0, TF_IMAGE, NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2838,7 +2838,7 @@ normal temporary decal
|
|||
*/
|
||||
void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags )
|
||||
{
|
||||
R_DecalShoot( textureIndex, entityIndex, modelIndex, pos, flags, NULL, 1.0f );
|
||||
R_DecalShoot( textureIndex, entityIndex, modelIndex, pos, flags, 1.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2850,7 +2850,7 @@ custom temporary decal
|
|||
*/
|
||||
void CL_FireCustomDecal( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags, float scale )
|
||||
{
|
||||
R_DecalShoot( textureIndex, entityIndex, modelIndex, pos, flags, NULL, scale );
|
||||
R_DecalShoot( textureIndex, entityIndex, modelIndex, pos, flags, scale );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2862,7 +2862,7 @@ spray custom colored decal (clan logo etc)
|
|||
*/
|
||||
void CL_PlayerDecal( int textureIndex, int entityIndex, float *pos )
|
||||
{
|
||||
R_DecalShoot( textureIndex, entityIndex, 0, pos, 0, NULL, 1.0f );
|
||||
R_DecalShoot( textureIndex, entityIndex, 0, pos, 0, 1.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,960 @@
|
|||
/*
|
||||
gl_alias.c - alias model renderer
|
||||
Copyright (C) 2017 Uncle Mike
|
||||
|
||||
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 3 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.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "mathlib.h"
|
||||
#include "const.h"
|
||||
#include "r_studioint.h"
|
||||
#include "triangleapi.h"
|
||||
#include "alias.h"
|
||||
#include "pm_local.h"
|
||||
#include "gl_local.h"
|
||||
#include "cl_tent.h"
|
||||
|
||||
/*
|
||||
=================================================================
|
||||
|
||||
ALIAS MODEL DISPLAY LIST GENERATION
|
||||
|
||||
=================================================================
|
||||
*/
|
||||
|
||||
model_t *aliasmodel;
|
||||
aliashdr_t *paliashdr;
|
||||
|
||||
qboolean used[8192];
|
||||
|
||||
// the command list holds counts and s/t values that are valid for
|
||||
// every frame
|
||||
int commands[8192];
|
||||
int numcommands;
|
||||
|
||||
// all frames will have their vertexes rearranged and expanded
|
||||
// so they are in the order expected by the command list
|
||||
int vertexorder[8192];
|
||||
int numorder;
|
||||
|
||||
int allverts, alltris;
|
||||
|
||||
int stripverts[128];
|
||||
int striptris[128];
|
||||
int stripcount;
|
||||
|
||||
/*
|
||||
================
|
||||
StripLength
|
||||
================
|
||||
*/
|
||||
int StripLength (int starttri, int startv)
|
||||
{
|
||||
int m1, m2;
|
||||
int j;
|
||||
mtriangle_t *last, *check;
|
||||
int k;
|
||||
|
||||
used[starttri] = 2;
|
||||
|
||||
last = &triangles[starttri];
|
||||
|
||||
stripverts[0] = last->vertindex[(startv)%3];
|
||||
stripverts[1] = last->vertindex[(startv+1)%3];
|
||||
stripverts[2] = last->vertindex[(startv+2)%3];
|
||||
|
||||
striptris[0] = starttri;
|
||||
stripcount = 1;
|
||||
|
||||
m1 = last->vertindex[(startv+2)%3];
|
||||
m2 = last->vertindex[(startv+1)%3];
|
||||
|
||||
// look for a matching triangle
|
||||
nexttri:
|
||||
for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
|
||||
{
|
||||
if (check->facesfront != last->facesfront)
|
||||
continue;
|
||||
for (k=0 ; k<3 ; k++)
|
||||
{
|
||||
if (check->vertindex[k] != m1)
|
||||
continue;
|
||||
if (check->vertindex[ (k+1)%3 ] != m2)
|
||||
continue;
|
||||
|
||||
// this is the next part of the fan
|
||||
|
||||
// if we can't use this triangle, this tristrip is done
|
||||
if (used[j])
|
||||
goto done;
|
||||
|
||||
// the new edge
|
||||
if (stripcount & 1)
|
||||
m2 = check->vertindex[ (k+2)%3 ];
|
||||
else
|
||||
m1 = check->vertindex[ (k+2)%3 ];
|
||||
|
||||
stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ];
|
||||
striptris[stripcount] = j;
|
||||
stripcount++;
|
||||
|
||||
used[j] = 2;
|
||||
goto nexttri;
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
// clear the temp used flags
|
||||
for (j=starttri+1 ; j<pheader->numtris ; j++)
|
||||
if (used[j] == 2)
|
||||
used[j] = 0;
|
||||
|
||||
return stripcount;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
FanLength
|
||||
===========
|
||||
*/
|
||||
int FanLength (int starttri, int startv)
|
||||
{
|
||||
int m1, m2;
|
||||
int j;
|
||||
mtriangle_t *last, *check;
|
||||
int k;
|
||||
|
||||
used[starttri] = 2;
|
||||
|
||||
last = &triangles[starttri];
|
||||
|
||||
stripverts[0] = last->vertindex[(startv)%3];
|
||||
stripverts[1] = last->vertindex[(startv+1)%3];
|
||||
stripverts[2] = last->vertindex[(startv+2)%3];
|
||||
|
||||
striptris[0] = starttri;
|
||||
stripcount = 1;
|
||||
|
||||
m1 = last->vertindex[(startv+0)%3];
|
||||
m2 = last->vertindex[(startv+2)%3];
|
||||
|
||||
|
||||
// look for a matching triangle
|
||||
nexttri:
|
||||
for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
|
||||
{
|
||||
if (check->facesfront != last->facesfront)
|
||||
continue;
|
||||
for (k=0 ; k<3 ; k++)
|
||||
{
|
||||
if (check->vertindex[k] != m1)
|
||||
continue;
|
||||
if (check->vertindex[ (k+1)%3 ] != m2)
|
||||
continue;
|
||||
|
||||
// this is the next part of the fan
|
||||
|
||||
// if we can't use this triangle, this tristrip is done
|
||||
if (used[j])
|
||||
goto done;
|
||||
|
||||
// the new edge
|
||||
m2 = check->vertindex[ (k+2)%3 ];
|
||||
|
||||
stripverts[stripcount+2] = m2;
|
||||
striptris[stripcount] = j;
|
||||
stripcount++;
|
||||
|
||||
used[j] = 2;
|
||||
goto nexttri;
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
// clear the temp used flags
|
||||
for (j=starttri+1 ; j<pheader->numtris ; j++)
|
||||
if (used[j] == 2)
|
||||
used[j] = 0;
|
||||
|
||||
return stripcount;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
BuildTris
|
||||
|
||||
Generate a list of trifans or strips
|
||||
for the model, which holds for all frames
|
||||
================
|
||||
*/
|
||||
void BuildTris (void)
|
||||
{
|
||||
int i, j, k;
|
||||
int startv;
|
||||
mtriangle_t *last, *check;
|
||||
int m1, m2;
|
||||
int striplength;
|
||||
trivertx_t *v;
|
||||
mtriangle_t *tv;
|
||||
float s, t;
|
||||
int index;
|
||||
int len, bestlen, besttype;
|
||||
int bestverts[1024];
|
||||
int besttris[1024];
|
||||
int type;
|
||||
|
||||
//
|
||||
// build tristrips
|
||||
//
|
||||
numorder = 0;
|
||||
numcommands = 0;
|
||||
memset (used, 0, sizeof(used));
|
||||
for (i=0 ; i<pheader->numtris ; i++)
|
||||
{
|
||||
// pick an unused triangle and start the trifan
|
||||
if (used[i])
|
||||
continue;
|
||||
|
||||
bestlen = 0;
|
||||
for (type = 0 ; type < 2 ; type++)
|
||||
// type = 1;
|
||||
{
|
||||
for (startv =0 ; startv < 3 ; startv++)
|
||||
{
|
||||
if (type == 1)
|
||||
len = StripLength (i, startv);
|
||||
else
|
||||
len = FanLength (i, startv);
|
||||
if (len > bestlen)
|
||||
{
|
||||
besttype = type;
|
||||
bestlen = len;
|
||||
for (j=0 ; j<bestlen+2 ; j++)
|
||||
bestverts[j] = stripverts[j];
|
||||
for (j=0 ; j<bestlen ; j++)
|
||||
besttris[j] = striptris[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mark the tris on the best strip as used
|
||||
for (j=0 ; j<bestlen ; j++)
|
||||
used[besttris[j]] = 1;
|
||||
|
||||
if (besttype == 1)
|
||||
commands[numcommands++] = (bestlen+2);
|
||||
else
|
||||
commands[numcommands++] = -(bestlen+2);
|
||||
|
||||
for (j=0 ; j<bestlen+2 ; j++)
|
||||
{
|
||||
// emit a vertex into the reorder buffer
|
||||
k = bestverts[j];
|
||||
vertexorder[numorder++] = k;
|
||||
|
||||
// emit s/t coords into the commands stream
|
||||
s = stverts[k].s;
|
||||
t = stverts[k].t;
|
||||
if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
|
||||
s += pheader->skinwidth / 2; // on back side
|
||||
s = (s + 0.5) / pheader->skinwidth;
|
||||
t = (t + 0.5) / pheader->skinheight;
|
||||
|
||||
*(float *)&commands[numcommands++] = s;
|
||||
*(float *)&commands[numcommands++] = t;
|
||||
}
|
||||
}
|
||||
|
||||
commands[numcommands++] = 0; // end of list marker
|
||||
|
||||
Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
|
||||
|
||||
allverts += numorder;
|
||||
alltris += pheader->numtris;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
GL_MakeAliasModelDisplayLists
|
||||
================
|
||||
*/
|
||||
void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr)
|
||||
{
|
||||
int i, j;
|
||||
maliasgroup_t *paliasgroup;
|
||||
int *cmds;
|
||||
trivertx_t *verts;
|
||||
char cache[MAX_QPATH], fullpath[MAX_OSPATH], *c;
|
||||
FILE *f;
|
||||
int len;
|
||||
byte *data;
|
||||
float hscale, vscale; //johnfitz -- padded skins
|
||||
int count; //johnfitz -- precompute texcoords for padded skins
|
||||
int *loadcmds; //johnfitz
|
||||
|
||||
//johnfitz -- padded skins
|
||||
hscale = (float)hdr->skinwidth/(float)TexMgr_PadConditional(hdr->skinwidth);
|
||||
vscale = (float)hdr->skinheight/(float)TexMgr_PadConditional(hdr->skinheight);
|
||||
//johnfitz
|
||||
|
||||
aliasmodel = m;
|
||||
paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m);
|
||||
|
||||
//johnfitz -- generate meshes
|
||||
|
||||
#if 1 //always regenerate meshes
|
||||
|
||||
Con_DPrintf ("meshing %s...\n",m->name);
|
||||
BuildTris ();
|
||||
|
||||
#else //conditional regeneration
|
||||
|
||||
if (gl_alwaysmesh.value) // build it from scratch, and don't bother saving it to disk
|
||||
{
|
||||
Con_DPrintf ("meshing %s...\n",m->name);
|
||||
BuildTris ();
|
||||
}
|
||||
else // check disk cache, and rebuild it and save to disk if necessary
|
||||
{
|
||||
|
||||
//create directories
|
||||
sprintf (gldir, "%s/glquake", com_gamedir);
|
||||
Sys_mkdir (com_gamedir);
|
||||
Sys_mkdir (gldir);
|
||||
|
||||
//
|
||||
// look for a cached version
|
||||
//
|
||||
strcpy (cache, "glquake/");
|
||||
COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/"));
|
||||
strcat (cache, ".ms2");
|
||||
|
||||
COM_FOpenFile (cache, &f);
|
||||
if (f)
|
||||
{
|
||||
fread (&numcommands, 4, 1, f);
|
||||
fread (&numorder, 4, 1, f);
|
||||
fread (&commands, numcommands * sizeof(commands[0]), 1, f);
|
||||
fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
|
||||
fclose (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// build it from scratch
|
||||
//
|
||||
Con_Printf ("meshing %s...\n",m->name);
|
||||
BuildTris ();
|
||||
|
||||
//
|
||||
// save out the cached version
|
||||
//
|
||||
sprintf (fullpath, "%s/%s", com_gamedir, cache);
|
||||
f = fopen (fullpath, "wb");
|
||||
if (f)
|
||||
{
|
||||
fwrite (&numcommands, 4, 1, f);
|
||||
fwrite (&numorder, 4, 1, f);
|
||||
fwrite (&commands, numcommands * sizeof(commands[0]), 1, f);
|
||||
fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
|
||||
fclose (f);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//johnfitz
|
||||
|
||||
|
||||
// save the data out
|
||||
|
||||
paliashdr->poseverts = numorder;
|
||||
|
||||
cmds = Hunk_Alloc (numcommands * 4);
|
||||
paliashdr->commands = (byte *)cmds - (byte *)paliashdr;
|
||||
|
||||
//johnfitz -- precompute texcoords for padded skins
|
||||
loadcmds = commands;
|
||||
while(1)
|
||||
{
|
||||
*cmds++ = count = *loadcmds++;
|
||||
|
||||
if (!count)
|
||||
break;
|
||||
|
||||
if (count < 0)
|
||||
count = -count;
|
||||
|
||||
do
|
||||
{
|
||||
*(float *)cmds++ = hscale * (*(float *)loadcmds++);
|
||||
*(float *)cmds++ = vscale * (*(float *)loadcmds++);
|
||||
} while (--count);
|
||||
}
|
||||
//johnfitz
|
||||
|
||||
verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof(trivertx_t));
|
||||
paliashdr->posedata = (byte *)verts - (byte *)paliashdr;
|
||||
for (i=0 ; i<paliashdr->numposes ; i++)
|
||||
for (j=0 ; j<numorder ; j++)
|
||||
*verts++ = poseverts[i][vertexorder[j]];
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
ALIAS MODELS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
aliashdr_t *pheader;
|
||||
|
||||
stvert_t stverts[MAXALIASVERTS];
|
||||
mtriangle_t triangles[MAXALIASTRIS];
|
||||
|
||||
// a pose is a single set of vertexes. a frame may be
|
||||
// an animating sequence of poses
|
||||
trivertx_t *poseverts[MAXALIASFRAMES];
|
||||
int posenum;
|
||||
|
||||
byte **player_8bit_texels_tbl;
|
||||
byte *player_8bit_texels;
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasFrame
|
||||
=================
|
||||
*/
|
||||
void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
|
||||
{
|
||||
trivertx_t *pframe, *pinframe;
|
||||
int i, j;
|
||||
daliasframe_t *pdaliasframe;
|
||||
|
||||
pdaliasframe = (daliasframe_t *)pin;
|
||||
|
||||
strcpy (frame->name, pdaliasframe->name);
|
||||
frame->firstpose = posenum;
|
||||
frame->numposes = 1;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
// these are byte values, so we don't have to worry about
|
||||
// endianness
|
||||
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
|
||||
}
|
||||
|
||||
|
||||
pinframe = (trivertx_t *)(pdaliasframe + 1);
|
||||
|
||||
poseverts[posenum] = pinframe;
|
||||
posenum++;
|
||||
|
||||
pinframe += pheader->numverts;
|
||||
|
||||
return (void *)pinframe;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasGroup
|
||||
=================
|
||||
*/
|
||||
void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame)
|
||||
{
|
||||
daliasgroup_t *pingroup;
|
||||
int i, numframes;
|
||||
daliasinterval_t *pin_intervals;
|
||||
void *ptemp;
|
||||
|
||||
pingroup = (daliasgroup_t *)pin;
|
||||
|
||||
numframes = LittleLong (pingroup->numframes);
|
||||
|
||||
frame->firstpose = posenum;
|
||||
frame->numposes = numframes;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
// these are byte values, so we don't have to worry about endianness
|
||||
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pingroup->bboxmax.v[i];
|
||||
}
|
||||
|
||||
|
||||
pin_intervals = (daliasinterval_t *)(pingroup + 1);
|
||||
|
||||
frame->interval = LittleFloat (pin_intervals->interval);
|
||||
|
||||
pin_intervals += numframes;
|
||||
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for (i=0 ; i<numframes ; i++)
|
||||
{
|
||||
poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
|
||||
posenum++;
|
||||
|
||||
ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
|
||||
}
|
||||
|
||||
return ptemp;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_FloodFillSkin
|
||||
|
||||
Fill background pixels so mipmapping doesn't have haloes - Ed
|
||||
=================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short x, y;
|
||||
} floodfill_t;
|
||||
|
||||
extern unsigned d_8to24table[];
|
||||
|
||||
// must be a power of 2
|
||||
#define FLOODFILL_FIFO_SIZE 0x1000
|
||||
#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
|
||||
|
||||
#define FLOODFILL_STEP( off, dx, dy ) \
|
||||
{ \
|
||||
if (pos[off] == fillcolor) \
|
||||
{ \
|
||||
pos[off] = 255; \
|
||||
fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
|
||||
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
|
||||
} \
|
||||
else if (pos[off] != 255) fdc = pos[off]; \
|
||||
}
|
||||
|
||||
void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
|
||||
{
|
||||
byte fillcolor = *skin; // assume this is the pixel to fill
|
||||
floodfill_t fifo[FLOODFILL_FIFO_SIZE];
|
||||
int inpt = 0, outpt = 0;
|
||||
int filledcolor = -1;
|
||||
int i;
|
||||
|
||||
if (filledcolor == -1)
|
||||
{
|
||||
filledcolor = 0;
|
||||
// attempt to find opaque black
|
||||
for (i = 0; i < 256; ++i)
|
||||
if (d_8to24table[i] == (255 << 0)) // alpha 1.0
|
||||
{
|
||||
filledcolor = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// can't fill to filled color or to transparent color (used as visited marker)
|
||||
if ((fillcolor == filledcolor) || (fillcolor == 255))
|
||||
{
|
||||
//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
|
||||
return;
|
||||
}
|
||||
|
||||
fifo[inpt].x = 0, fifo[inpt].y = 0;
|
||||
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
|
||||
|
||||
while (outpt != inpt)
|
||||
{
|
||||
int x = fifo[outpt].x, y = fifo[outpt].y;
|
||||
int fdc = filledcolor;
|
||||
byte *pos = &skin[x + skinwidth * y];
|
||||
|
||||
outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
|
||||
|
||||
if (x > 0) FLOODFILL_STEP( -1, -1, 0 );
|
||||
if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 );
|
||||
if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 );
|
||||
if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 );
|
||||
skin[x + skinwidth * y] = fdc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Mod_LoadAllSkins
|
||||
===============
|
||||
*/
|
||||
void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
|
||||
{
|
||||
int i, j, k, size, groupskins;
|
||||
char name[32];
|
||||
byte *copy, *skin, *texels;
|
||||
daliasskingroup_t *pinskingroup;
|
||||
daliasskininterval_t *pinskinintervals;
|
||||
int padx, pady, ii, jj; //johnfitz -- padded player skin
|
||||
char fbr_mask_name[64]; //johnfitz -- added for fullbright support
|
||||
unsigned offset; //johnfitz
|
||||
|
||||
skin = (byte *)(pskintype + 1);
|
||||
|
||||
if (numskins < 1 || numskins > MAX_SKINS)
|
||||
Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
|
||||
|
||||
size = pheader->skinwidth * pheader->skinheight;
|
||||
|
||||
for (i=0 ; i<numskins ; i++)
|
||||
{
|
||||
if (pskintype->type == ALIAS_SKIN_SINGLE)
|
||||
{
|
||||
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
|
||||
|
||||
// save 8 bit texels for the player model to remap
|
||||
texels = Hunk_AllocName(size, loadname);
|
||||
pheader->texels[i] = texels - (byte *)pheader;
|
||||
memcpy (texels, (byte *)(pskintype + 1), size);
|
||||
|
||||
//johnfitz -- rewritten
|
||||
sprintf (name, "%s:frame%i", loadmodel->name, i);
|
||||
offset = (unsigned)(pskintype+1) - (unsigned)mod_base;
|
||||
if (Mod_CheckFullbrights ((byte *)(pskintype+1), size))
|
||||
{
|
||||
pheader->gltextures[i][0] = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight,
|
||||
SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, TEXPREF_PAD | TEXPREF_NOBRIGHT);
|
||||
sprintf (fbr_mask_name, "%s:frame%i_glow", loadmodel->name, i);
|
||||
pheader->fbtextures[i][0] = TexMgr_LoadImage (loadmodel, fbr_mask_name, pheader->skinwidth, pheader->skinheight,
|
||||
SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, TEXPREF_PAD | TEXPREF_FULLBRIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
pheader->gltextures[i][0] = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight,
|
||||
SRC_INDEXED, (byte *)(pskintype+1), loadmodel->name, offset, TEXPREF_PAD);
|
||||
pheader->fbtextures[i][0] = NULL;
|
||||
}
|
||||
|
||||
pheader->gltextures[i][3] = pheader->gltextures[i][2] = pheader->gltextures[i][1] = pheader->gltextures[i][0];
|
||||
pheader->fbtextures[i][3] = pheader->fbtextures[i][2] = pheader->fbtextures[i][1] = pheader->fbtextures[i][0];
|
||||
//johnfitz
|
||||
|
||||
pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// animating skin group. yuck.
|
||||
pskintype++;
|
||||
pinskingroup = (daliasskingroup_t *)pskintype;
|
||||
groupskins = LittleLong (pinskingroup->numskins);
|
||||
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
|
||||
|
||||
pskintype = (void *)(pinskinintervals + groupskins);
|
||||
|
||||
for (j=0 ; j<groupskins ; j++)
|
||||
{
|
||||
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
|
||||
if (j == 0) {
|
||||
texels = Hunk_AllocName(size, loadname);
|
||||
pheader->texels[i] = texels - (byte *)pheader;
|
||||
memcpy (texels, (byte *)(pskintype), size);
|
||||
}
|
||||
|
||||
//johnfitz -- rewritten
|
||||
sprintf (name, "%s:frame%i_%i", loadmodel->name, i,j);
|
||||
offset = (unsigned)(pskintype) - (unsigned)mod_base; //johnfitz
|
||||
if (Mod_CheckFullbrights ((byte *)(pskintype), size))
|
||||
{
|
||||
pheader->gltextures[i][j&3] = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight,
|
||||
SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, TEXPREF_PAD | TEXPREF_NOBRIGHT);
|
||||
sprintf (fbr_mask_name, "%s:frame%i_%i_glow", loadmodel->name, i,j);
|
||||
pheader->fbtextures[i][j&3] = TexMgr_LoadImage (loadmodel, fbr_mask_name, pheader->skinwidth, pheader->skinheight,
|
||||
SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, TEXPREF_PAD | TEXPREF_FULLBRIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
pheader->gltextures[i][j&3] = TexMgr_LoadImage (loadmodel, name, pheader->skinwidth, pheader->skinheight,
|
||||
SRC_INDEXED, (byte *)(pskintype), loadmodel->name, offset, TEXPREF_PAD);
|
||||
pheader->fbtextures[i][j&3] = NULL;
|
||||
}
|
||||
//johnfitz
|
||||
|
||||
pskintype = (daliasskintype_t *)((byte *)(pskintype) + size);
|
||||
}
|
||||
k = j;
|
||||
for (/* */; j < 4; j++)
|
||||
pheader->gltextures[i][j&3] =
|
||||
pheader->gltextures[i][j - k];
|
||||
}
|
||||
}
|
||||
|
||||
return (void *)pskintype;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_CalcAliasBounds -- johnfitz -- calculate bounds of alias model for nonrotated, yawrotated, and fullrotated cases
|
||||
=================
|
||||
*/
|
||||
void Mod_CalcAliasBounds (aliashdr_t *a)
|
||||
{
|
||||
int i,j,k;
|
||||
float dist, yawradius, radius;
|
||||
vec3_t v;
|
||||
|
||||
//clear out all data
|
||||
for (i=0; i<3;i++)
|
||||
{
|
||||
loadmodel->mins[i] = loadmodel->ymins[i] = loadmodel->rmins[i] = 999999;
|
||||
loadmodel->maxs[i] = loadmodel->ymaxs[i] = loadmodel->rmaxs[i] = -999999;
|
||||
radius = yawradius = 0;
|
||||
}
|
||||
|
||||
//process verts
|
||||
for (i=0 ; i<a->numposes; i++)
|
||||
for (j=0; j<a->numverts; j++)
|
||||
{
|
||||
for (k=0; k<3;k++)
|
||||
v[k] = poseverts[i][j].v[k] * pheader->scale[k] + pheader->scale_origin[k];
|
||||
|
||||
for (k=0; k<3;k++)
|
||||
{
|
||||
loadmodel->mins[k] = min (loadmodel->mins[k], v[k]);
|
||||
loadmodel->maxs[k] = max (loadmodel->maxs[k], v[k]);
|
||||
}
|
||||
dist = v[0] * v[0] + v[1] * v[1];
|
||||
if (yawradius < dist)
|
||||
yawradius = dist;
|
||||
dist += v[2] * v[2];
|
||||
if (radius < dist)
|
||||
radius = dist;
|
||||
}
|
||||
|
||||
//rbounds will be used when entity has nonzero pitch or roll
|
||||
radius = sqrt(radius);
|
||||
loadmodel->rmins[0] = loadmodel->rmins[1] = loadmodel->rmins[2] = -radius;
|
||||
loadmodel->rmaxs[0] = loadmodel->rmaxs[1] = loadmodel->rmaxs[2] = radius;
|
||||
|
||||
//ybounds will be used when entity has nonzero yaw
|
||||
yawradius = sqrt(yawradius);
|
||||
loadmodel->ymins[0] = loadmodel->ymins[1] = -yawradius;
|
||||
loadmodel->ymaxs[0] = loadmodel->ymaxs[1] = yawradius;
|
||||
loadmodel->ymins[2] = loadmodel->mins[2];
|
||||
loadmodel->ymaxs[2] = loadmodel->maxs[2];
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_SetExtraFlags -- johnfitz -- set up extra flags that aren't in the mdl
|
||||
=================
|
||||
*/
|
||||
void Mod_SetExtraFlags (model_t *mod)
|
||||
{
|
||||
extern cvar_t r_nolerp_list;
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
if (!mod || !mod->name || mod->type != mod_alias)
|
||||
return;
|
||||
|
||||
mod->flags &= 0xFF; //only preserve first byte
|
||||
|
||||
// nolerp flag
|
||||
for (s=r_nolerp_list.string; *s; s += i+1, i=0)
|
||||
{
|
||||
//search forwards to the next comma or end of string
|
||||
for (i=0; s[i] != ',' && s[i] != 0; i++) ;
|
||||
|
||||
//compare it to the model name
|
||||
if (!strncmp(mod->name, s, i))
|
||||
{
|
||||
mod->flags |= MOD_NOLERP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// noshadow flag (TODO: make this a cvar list)
|
||||
if (!strcmp (mod->name, "progs/flame2.mdl") ||
|
||||
!strcmp (mod->name, "progs/flame.mdl") ||
|
||||
!strcmp (mod->name, "progs/bolt1.mdl") ||
|
||||
!strcmp (mod->name, "progs/bolt2.mdl") ||
|
||||
!strcmp (mod->name, "progs/bolt3.mdl") ||
|
||||
!strcmp (mod->name, "progs/laser.mdl"))
|
||||
mod->flags |= MOD_NOSHADOW;
|
||||
|
||||
// fullbright hack (TODO: make this a cvar list)
|
||||
if (!strcmp (mod->name, "progs/flame2.mdl") ||
|
||||
!strcmp (mod->name, "progs/flame.mdl") ||
|
||||
!strcmp (mod->name, "progs/boss.mdl"))
|
||||
mod->flags |= MOD_FBRIGHTHACK;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasModel
|
||||
=================
|
||||
*/
|
||||
void Mod_LoadAliasModel (model_t *mod, void *buffer)
|
||||
{
|
||||
int i, j;
|
||||
mdl_t *pinmodel;
|
||||
stvert_t *pinstverts;
|
||||
dtriangle_t *pintriangles;
|
||||
int version, numframes, numskins;
|
||||
int size;
|
||||
daliasframetype_t *pframetype;
|
||||
daliasskintype_t *pskintype;
|
||||
int start, end, total;
|
||||
|
||||
start = Hunk_LowMark ();
|
||||
|
||||
pinmodel = (mdl_t *)buffer;
|
||||
mod_base = (byte *)buffer; //johnfitz
|
||||
|
||||
version = LittleLong (pinmodel->version);
|
||||
if (version != ALIAS_VERSION)
|
||||
Sys_Error ("%s has wrong version number (%i should be %i)",
|
||||
mod->name, version, ALIAS_VERSION);
|
||||
|
||||
//
|
||||
// allocate space for a working header, plus all the data except the frames,
|
||||
// skin and group info
|
||||
//
|
||||
size = sizeof (aliashdr_t)
|
||||
+ (LittleLong (pinmodel->numframes) - 1) *
|
||||
sizeof (pheader->frames[0]);
|
||||
pheader = Hunk_AllocName (size, loadname);
|
||||
|
||||
mod->flags = LittleLong (pinmodel->flags);
|
||||
|
||||
//
|
||||
// endian-adjust and copy the data, starting with the alias model header
|
||||
//
|
||||
pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
|
||||
pheader->numskins = LittleLong (pinmodel->numskins);
|
||||
pheader->skinwidth = LittleLong (pinmodel->skinwidth);
|
||||
pheader->skinheight = LittleLong (pinmodel->skinheight);
|
||||
|
||||
if (pheader->skinheight > MAX_LBM_HEIGHT)
|
||||
Sys_Error ("model %s has a skin taller than %d", mod->name,
|
||||
MAX_LBM_HEIGHT);
|
||||
|
||||
pheader->numverts = LittleLong (pinmodel->numverts);
|
||||
|
||||
if (pheader->numverts <= 0)
|
||||
Sys_Error ("model %s has no vertices", mod->name);
|
||||
|
||||
if (pheader->numverts > MAXALIASVERTS)
|
||||
Sys_Error ("model %s has too many vertices", mod->name);
|
||||
|
||||
pheader->numtris = LittleLong (pinmodel->numtris);
|
||||
|
||||
if (pheader->numtris <= 0)
|
||||
Sys_Error ("model %s has no triangles", mod->name);
|
||||
|
||||
pheader->numframes = LittleLong (pinmodel->numframes);
|
||||
numframes = pheader->numframes;
|
||||
if (numframes < 1)
|
||||
Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
|
||||
|
||||
pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
|
||||
mod->synctype = LittleLong (pinmodel->synctype);
|
||||
mod->numframes = pheader->numframes;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
|
||||
pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
|
||||
pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// load the skins
|
||||
//
|
||||
pskintype = (daliasskintype_t *)&pinmodel[1];
|
||||
pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
|
||||
|
||||
//
|
||||
// load base s and t vertices
|
||||
//
|
||||
pinstverts = (stvert_t *)pskintype;
|
||||
|
||||
for (i=0 ; i<pheader->numverts ; i++)
|
||||
{
|
||||
stverts[i].onseam = LittleLong (pinstverts[i].onseam);
|
||||
stverts[i].s = LittleLong (pinstverts[i].s);
|
||||
stverts[i].t = LittleLong (pinstverts[i].t);
|
||||
}
|
||||
|
||||
//
|
||||
// load triangle lists
|
||||
//
|
||||
pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
|
||||
|
||||
for (i=0 ; i<pheader->numtris ; i++)
|
||||
{
|
||||
triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
|
||||
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
triangles[i].vertindex[j] =
|
||||
LittleLong (pintriangles[i].vertindex[j]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// load the frames
|
||||
//
|
||||
posenum = 0;
|
||||
pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
|
||||
|
||||
for (i=0 ; i<numframes ; i++)
|
||||
{
|
||||
aliasframetype_t frametype;
|
||||
frametype = LittleLong (pframetype->type);
|
||||
if (frametype == ALIAS_SINGLE)
|
||||
pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
|
||||
else
|
||||
pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
|
||||
}
|
||||
|
||||
pheader->numposes = posenum;
|
||||
|
||||
mod->type = mod_alias;
|
||||
|
||||
Mod_SetExtraFlags (mod); //johnfitz
|
||||
|
||||
Mod_CalcAliasBounds (pheader); //johnfitz
|
||||
|
||||
//
|
||||
// build the draw lists
|
||||
//
|
||||
GL_MakeAliasModelDisplayLists (mod, pheader);
|
||||
|
||||
//
|
||||
// move the complete, relocatable alias model to the cache
|
||||
//
|
||||
end = Hunk_LowMark ();
|
||||
total = end - start;
|
||||
|
||||
Cache_Alloc (&mod->cache, total, loadname);
|
||||
if (!mod->cache.data)
|
||||
return;
|
||||
memcpy (mod->cache.data, pheader, total);
|
||||
|
||||
Hunk_FreeToLowMark (start);
|
||||
}
|
|
@ -168,10 +168,7 @@ qboolean R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags
|
|||
}
|
||||
|
||||
if( frustum )
|
||||
{
|
||||
mextrasurf_t *info = SURF_INFO( surf, RI.currentmodel );
|
||||
return GL_FrustumCullBox( frustum, info->mins, info->maxs, clipflags );
|
||||
}
|
||||
return GL_FrustumCullBox( frustum, surf->info->mins, surf->info->maxs, clipflags );
|
||||
|
||||
return false;
|
||||
}
|
|
@ -40,7 +40,6 @@ GNU General Public License for more details.
|
|||
typedef struct
|
||||
{
|
||||
vec3_t m_Position; // world coordinates of the decal center
|
||||
vec3_t m_SAxis; // the s axis for the decal in world coordinates
|
||||
model_t *m_pModel; // the model the decal is going to be applied in
|
||||
int m_iTexture; // The decal material
|
||||
int m_Size; // Size of the decal (in world coords)
|
||||
|
@ -92,13 +91,11 @@ static void R_DecalUnlink( decal_t *pdecal )
|
|||
}
|
||||
}
|
||||
|
||||
if( pdecal->mesh )
|
||||
{
|
||||
Mem_Free( pdecal->mesh );
|
||||
}
|
||||
if( pdecal->polys )
|
||||
Mem_Free( pdecal->polys );
|
||||
|
||||
pdecal->psurface = NULL;
|
||||
pdecal->mesh = NULL;
|
||||
pdecal->polys = NULL;
|
||||
}
|
||||
|
||||
// Just reuse next decal in list
|
||||
|
@ -126,7 +123,7 @@ static decal_t *R_DecalAlloc( decal_t *pdecal )
|
|||
pdecal = &gDecalPool[gDecalCount]; // reuse next decal
|
||||
gDecalCount++;
|
||||
count++;
|
||||
} while(( pdecal->flags & FDECAL_PERMANENT ) && count < limit );
|
||||
} while( FBitSet( pdecal->flags, FDECAL_PERMANENT ) && count < limit );
|
||||
}
|
||||
|
||||
// if decal is already linked to a surface, unlink it.
|
||||
|
@ -147,9 +144,9 @@ static void R_GetDecalDimensions( int texture, int *width, int *height )
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// compute the decal basis based on surface normal, and preferred saxis
|
||||
// compute the decal basis based on surface normal
|
||||
//-----------------------------------------------------------------------------
|
||||
void R_DecalComputeBasis( msurface_t *surf, vec3_t pSAxis, vec3_t textureSpaceBasis[3] )
|
||||
void R_DecalComputeBasis( msurface_t *surf, vec3_t textureSpaceBasis[3] )
|
||||
{
|
||||
vec3_t surfaceNormal;
|
||||
|
||||
|
@ -158,44 +155,17 @@ void R_DecalComputeBasis( msurface_t *surf, vec3_t pSAxis, vec3_t textureSpaceBa
|
|||
VectorNegate( surf->plane->normal, surfaceNormal );
|
||||
else VectorCopy( surf->plane->normal, surfaceNormal );
|
||||
|
||||
VectorCopy( surfaceNormal, textureSpaceBasis[2] );
|
||||
|
||||
if( pSAxis )
|
||||
{
|
||||
// T = S cross N
|
||||
CrossProduct( pSAxis, textureSpaceBasis[2], textureSpaceBasis[1] );
|
||||
|
||||
// Name sure they aren't parallel or antiparallel
|
||||
// In that case, fall back to the normal algorithm.
|
||||
if( DotProduct( textureSpaceBasis[1], textureSpaceBasis[1] ) > 1e-6 )
|
||||
{
|
||||
// S = N cross T
|
||||
CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] );
|
||||
|
||||
VectorNormalizeFast( textureSpaceBasis[0] );
|
||||
VectorNormalizeFast( textureSpaceBasis[1] );
|
||||
return;
|
||||
}
|
||||
// Fall through to the standard algorithm for parallel or antiparallel
|
||||
}
|
||||
|
||||
// original Half-Life algorithm: get textureBasis from linked surface
|
||||
VectorCopy( surf->texinfo->vecs[0], textureSpaceBasis[0] );
|
||||
VectorCopy( surf->texinfo->vecs[1], textureSpaceBasis[1] );
|
||||
VectorNormalizeFast( textureSpaceBasis[0] );
|
||||
VectorNormalizeFast( textureSpaceBasis[1] );
|
||||
VectorNormalize2( surf->texinfo->vecs[0], textureSpaceBasis[0] );
|
||||
VectorNormalize2( surf->texinfo->vecs[1], textureSpaceBasis[1] );
|
||||
VectorNormalize2( surfaceNormal, textureSpaceBasis[2] );
|
||||
}
|
||||
|
||||
void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, int texture, vec3_t textureSpaceBasis[3], float decalWorldScale[2] )
|
||||
{
|
||||
float *sAxis = NULL;
|
||||
int width, height;
|
||||
|
||||
if( pDecal->flags & FDECAL_USESAXIS )
|
||||
sAxis = pDecal->saxis;
|
||||
|
||||
// Compute the non-scaled decal basis
|
||||
R_DecalComputeBasis( surf, sAxis, textureSpaceBasis );
|
||||
R_DecalComputeBasis( surf, textureSpaceBasis );
|
||||
R_GetDecalDimensions( texture, &width, &height );
|
||||
|
||||
// world width of decal = ptexture->width / pDecal->scale
|
||||
|
@ -511,79 +481,41 @@ static decal_t *R_DecalIntersect( decalinfo_t *decalinfo, msurface_t *surf, int
|
|||
|
||||
/*
|
||||
====================
|
||||
R_BuildMeshForDecal
|
||||
R_DecalCreatePoly
|
||||
|
||||
creates mesh for decal on first rendering
|
||||
====================
|
||||
*/
|
||||
msurfmesh_t *R_DecalCreateMesh( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t *surf )
|
||||
glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t *surf )
|
||||
{
|
||||
int lnumverts;
|
||||
glpoly_t *poly;
|
||||
float *v;
|
||||
uint i, bufSize;
|
||||
qboolean createSTverts = false;
|
||||
int numVerts, numElems;
|
||||
byte *buffer;
|
||||
msurfmesh_t *mesh;
|
||||
int i;
|
||||
|
||||
if( pdecal->mesh )
|
||||
if( pdecal->polys ) // already created?
|
||||
return pdecal->polys;
|
||||
|
||||
v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &lnumverts );
|
||||
if( !lnumverts ) return NULL; // probably this never happens
|
||||
|
||||
// allocate glpoly
|
||||
poly = Mem_Alloc( com_studiocache, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
|
||||
poly->next = pdecal->polys;
|
||||
poly->flags = surf->flags;
|
||||
pdecal->polys = poly;
|
||||
poly->numverts = lnumverts;
|
||||
|
||||
for( i = 0; i < lnumverts; i++, v += VERTEXSIZE )
|
||||
{
|
||||
// already have mesh
|
||||
return pdecal->mesh;
|
||||
VectorCopy( v, poly->verts[i] );
|
||||
poly->verts[i][3] = v[3];
|
||||
poly->verts[i][4] = v[4];
|
||||
poly->verts[i][5] = v[5];
|
||||
poly->verts[i][6] = v[6];
|
||||
}
|
||||
|
||||
v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &numVerts );
|
||||
if( !numVerts ) return NULL; // probably this never happens
|
||||
|
||||
// allocate mesh
|
||||
numElems = (numVerts - 2) * 3;
|
||||
|
||||
bufSize = sizeof( msurfmesh_t ) + numVerts * sizeof( glvert_t ) + numElems * sizeof( word );
|
||||
buffer = Mem_Alloc( cls.mempool, bufSize );
|
||||
|
||||
mesh = (msurfmesh_t *)buffer;
|
||||
buffer += sizeof( msurfmesh_t );
|
||||
mesh->numVerts = numVerts;
|
||||
mesh->numElems = numElems;
|
||||
|
||||
// setup pointers
|
||||
mesh->verts = (glvert_t *)buffer;
|
||||
buffer += numVerts * sizeof( glvert_t );
|
||||
mesh->elems = (word *)buffer;
|
||||
buffer += numElems * sizeof( word );
|
||||
|
||||
mesh->surf = surf; // NOTE: meshchains can be linked with one surface
|
||||
|
||||
// create indices
|
||||
for( i = 0; i < mesh->numVerts - 2; i++ )
|
||||
{
|
||||
mesh->elems[i*3+0] = 0;
|
||||
mesh->elems[i*3+1] = i + 1;
|
||||
mesh->elems[i*3+2] = i + 2;
|
||||
}
|
||||
|
||||
// fill the mesh
|
||||
for( i = 0; i < numVerts; i++, v += VERTEXSIZE )
|
||||
{
|
||||
glvert_t *out = &mesh->verts[i];
|
||||
VectorCopy( v, out->vertex );
|
||||
VectorCopy( decalinfo->m_Basis[0], out->tangent );
|
||||
VectorCopy( decalinfo->m_Basis[1], out->binormal );
|
||||
VectorCopy( decalinfo->m_Basis[2], out->normal );
|
||||
|
||||
out->stcoord[0] = v[3];
|
||||
out->stcoord[1] = v[4];
|
||||
out->lmcoord[0] = v[5];
|
||||
out->lmcoord[1] = v[6];
|
||||
out->sccoord[0] = (( DotProduct( v , surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] ) / surf->texinfo->texture->width );
|
||||
out->sccoord[1] = (( DotProduct( v , surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] ) / surf->texinfo->texture->height );
|
||||
|
||||
// clear colors (it can be used for vertex lighting)
|
||||
memset( out->color, 0xFF, sizeof( out->color ));
|
||||
}
|
||||
|
||||
pdecal->mesh = mesh;
|
||||
|
||||
return mesh;
|
||||
return poly;
|
||||
}
|
||||
|
||||
// Add the decal to the surface's list of decals.
|
||||
|
@ -612,9 +544,8 @@ static void R_AddDecalToSurface( decal_t *pdecal, msurface_t *surf, decalinfo_t
|
|||
// and will be culled, drawing and sorting
|
||||
// together with surface
|
||||
|
||||
// build mesh for decal if allowed
|
||||
if( host.features & ENGINE_BUILD_SURFMESHES )
|
||||
pdecal->mesh = R_DecalCreateMesh( decalinfo, pdecal, surf );
|
||||
// alloc clipped poly for decal
|
||||
R_DecalCreatePoly( decalinfo, pdecal, surf );
|
||||
}
|
||||
|
||||
static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, float y )
|
||||
|
@ -638,16 +569,13 @@ static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, fl
|
|||
|
||||
VectorCopy( decalinfo->m_Position, pdecal->position );
|
||||
|
||||
if( pdecal->flags & FDECAL_USESAXIS )
|
||||
VectorCopy( decalinfo->m_SAxis, pdecal->saxis );
|
||||
|
||||
pdecal->dx = x;
|
||||
pdecal->dy = y;
|
||||
pdecal->texture = decalinfo->m_iTexture;
|
||||
|
||||
// set scaling
|
||||
pdecal->scale = decalinfo->m_scale;
|
||||
pdecal->entityIndex = decalinfo->m_Entity;
|
||||
pdecal->texture = decalinfo->m_iTexture;
|
||||
|
||||
// check to see if the decal actually intersects the surface
|
||||
// if not, then remove the decal
|
||||
|
@ -667,10 +595,9 @@ void R_DecalSurface( msurface_t *surf, decalinfo_t *decalinfo )
|
|||
{
|
||||
// get the texture associated with this surface
|
||||
mtexinfo_t *tex = surf->texinfo;
|
||||
vec4_t textureU, textureV;
|
||||
float *sAxis = NULL;
|
||||
float s, t, w, h;
|
||||
decal_t *decal = surf->pdecals;
|
||||
vec4_t textureU, textureV;
|
||||
float s, t, w, h;
|
||||
|
||||
// we in restore mode
|
||||
if( cls.state == ca_connected )
|
||||
|
@ -695,11 +622,7 @@ void R_DecalSurface( msurface_t *surf, decalinfo_t *decalinfo )
|
|||
// Determine the decal basis (measured in world space)
|
||||
// Note that the decal basis vectors 0 and 1 will always lie in the same
|
||||
// plane as the texture space basis vectorstextureVecsTexelsPerWorldUnits.
|
||||
|
||||
if( decalinfo->m_Flags & FDECAL_USESAXIS )
|
||||
sAxis = decalinfo->m_SAxis;
|
||||
|
||||
R_DecalComputeBasis( surf, sAxis, decalinfo->m_Basis );
|
||||
R_DecalComputeBasis( surf, decalinfo->m_Basis );
|
||||
|
||||
// Compute an effective width and height (axis aligned) in the parent texture space
|
||||
// How does this work? decalBasis[0] represents the u-direction (width)
|
||||
|
@ -806,13 +729,13 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
|
|||
}
|
||||
|
||||
// Shoots a decal onto the surface of the BSP. position is the center of the decal in world coords
|
||||
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis, float scale )
|
||||
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale )
|
||||
{
|
||||
decalinfo_t decalInfo;
|
||||
hull_t *hull;
|
||||
cl_entity_t *ent = NULL;
|
||||
model_t *model = NULL;
|
||||
int width, height;
|
||||
hull_t *hull;
|
||||
|
||||
if( textureIndex <= 0 || textureIndex >= MAX_TEXTURES )
|
||||
{
|
||||
|
@ -869,13 +792,6 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos
|
|||
VectorCopy( pos, decalInfo.m_Position );
|
||||
}
|
||||
|
||||
// deal with the s axis if one was passed in
|
||||
if( saxis )
|
||||
{
|
||||
flags |= FDECAL_USESAXIS;
|
||||
VectorCopy( saxis, decalInfo.m_SAxis );
|
||||
}
|
||||
|
||||
// this decal must use landmark for correct transition
|
||||
if(!( model->flags & MODEL_HAS_ORIGIN ))
|
||||
{
|
||||
|
@ -906,23 +822,24 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos
|
|||
// triangles the same way.
|
||||
float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount )
|
||||
{
|
||||
float *v;
|
||||
glpoly_t *p = pDecal->polys;
|
||||
int i, count;
|
||||
float *v, *v2;
|
||||
|
||||
if( pDecal->mesh )
|
||||
if( p )
|
||||
{
|
||||
count = pDecal->mesh->numVerts;
|
||||
v = g_DecalClipVerts[0];
|
||||
count = p->numverts;
|
||||
v2 = p->verts[0];
|
||||
|
||||
// if we have mesh so skip clipping and just copy vertexes out (perf)
|
||||
for( i = 0, v = g_DecalClipVerts[0]; i < count; i++, v += VERTEXSIZE )
|
||||
for( i = 0; i < count; i++, v += VERTEXSIZE, v2 += VERTEXSIZE )
|
||||
{
|
||||
glvert_t *p = &pDecal->mesh->verts[i];
|
||||
|
||||
VectorCopy( p->vertex, v );
|
||||
v[3] = p->stcoord[0];
|
||||
v[4] = p->stcoord[1];
|
||||
v[5] = p->lmcoord[0];
|
||||
v[6] = p->lmcoord[1];
|
||||
VectorCopy( v2, v );
|
||||
v[3] = v2[3];
|
||||
v[4] = v2[4];
|
||||
v[5] = v2[5];
|
||||
v[6] = v2[6];
|
||||
}
|
||||
|
||||
// restore pointer
|
||||
|
|
|
@ -480,7 +480,7 @@ void GL_SetRenderMode( int mode );
|
|||
void R_RunViewmodelEvents( void );
|
||||
void R_DrawViewModel( void );
|
||||
int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame );
|
||||
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis, float scale );
|
||||
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale );
|
||||
void R_RemoveEfrags( struct cl_entity_s *ent );
|
||||
void R_AddEfrags( struct cl_entity_s *ent );
|
||||
void R_DecalRemoveAll( int texture );
|
||||
|
|
|
@ -30,11 +30,9 @@ void R_BeginDrawMirror( msurface_t *fa )
|
|||
{
|
||||
matrix4x4 m1, m2, matrix;
|
||||
GLfloat genVector[4][4];
|
||||
mextrasurf_t *es;
|
||||
int i;
|
||||
|
||||
es = SURF_INFO( fa, RI.currentmodel );
|
||||
Matrix4x4_Copy( matrix, es->mirrormatrix );
|
||||
Matrix4x4_Copy( matrix, fa->info->mirrormatrix );
|
||||
|
||||
Matrix4x4_LoadIdentity( m1 );
|
||||
Matrix4x4_ConcatScale( m1, 0.5f );
|
||||
|
@ -205,7 +203,7 @@ void R_DrawMirrors( void )
|
|||
RI.currententity = e = tr.mirror_entities[i].ent;
|
||||
RI.currentmodel = m = RI.currententity->model;
|
||||
|
||||
surf = INFO_SURF( es, m );
|
||||
surf = es->surf;
|
||||
|
||||
ASSERT( RI.currententity != NULL );
|
||||
ASSERT( RI.currentmodel != NULL );
|
||||
|
@ -218,7 +216,7 @@ void R_DrawMirrors( void )
|
|||
{
|
||||
for( tmp = mirrorchain; tmp != es; tmp = tmp->mirrorchain )
|
||||
{
|
||||
surf2 = INFO_SURF( tmp, m );
|
||||
surf2 = tmp->surf;
|
||||
|
||||
if( !tmp->mirrortexturenum )
|
||||
continue; // not filled?
|
||||
|
@ -343,7 +341,6 @@ R_RecursiveMirrorNode
|
|||
*/
|
||||
void R_RecursiveMirrorNode( mnode_t *node, uint clipflags )
|
||||
{
|
||||
mextrasurf_t *extrasurf;
|
||||
int i, clipped;
|
||||
msurface_t *surf, **mark;
|
||||
mleaf_t *pleaf;
|
||||
|
@ -402,15 +399,14 @@ void R_RecursiveMirrorNode( mnode_t *node, uint clipflags )
|
|||
// draw stuff
|
||||
for( c = node->numsurfaces, surf = cl.worldmodel->surfaces + node->firstsurface; c; c--, surf++ )
|
||||
{
|
||||
if(!( surf->flags & SURF_REFLECT ))
|
||||
if( !FBitSet( surf->flags, SURF_REFLECT ))
|
||||
continue;
|
||||
|
||||
if( R_CullSurface( surf, &RI.frustum, clipflags ))
|
||||
continue;
|
||||
|
||||
extrasurf = SURF_INFO( surf, RI.currentmodel );
|
||||
extrasurf->mirrorchain = tr.mirror_entities[0].chain;
|
||||
tr.mirror_entities[0].chain = extrasurf;
|
||||
surf->info->mirrorchain = tr.mirror_entities[0].chain;
|
||||
tr.mirror_entities[0].chain = surf->info;
|
||||
}
|
||||
|
||||
// recurse down the back side
|
||||
|
@ -426,7 +422,6 @@ Check all bmodel surfaces and make personal mirror chain
|
|||
*/
|
||||
void R_FindBmodelMirrors( cl_entity_t *e, qboolean static_entity )
|
||||
{
|
||||
mextrasurf_t *extrasurf;
|
||||
vec3_t mins, maxs;
|
||||
msurface_t *psurf;
|
||||
model_t *clmodel;
|
||||
|
@ -493,9 +488,8 @@ void R_FindBmodelMirrors( cl_entity_t *e, qboolean static_entity )
|
|||
if( R_CullSurface( psurf, frustum, 0 ))
|
||||
continue;
|
||||
|
||||
extrasurf = SURF_INFO( psurf, RI.currentmodel );
|
||||
extrasurf->mirrorchain = tr.mirror_entities[tr.num_mirror_entities].chain;
|
||||
tr.mirror_entities[tr.num_mirror_entities].chain = extrasurf;
|
||||
psurf->info->mirrorchain = tr.mirror_entities[tr.num_mirror_entities].chain;
|
||||
tr.mirror_entities[tr.num_mirror_entities].chain = psurf->info;
|
||||
}
|
||||
|
||||
// store new mirror entity
|
||||
|
|
|
@ -133,9 +133,7 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
|
|||
|
||||
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
||||
{
|
||||
mextrasurf_t *info = SURF_INFO( surf, RI.currentmodel );
|
||||
|
||||
if( !BoundsAndSphereIntersect( info->mins, info->maxs, light->origin, light->radius ))
|
||||
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
|
||||
continue; // no intersection
|
||||
|
||||
if( surf->dlightframe != tr.dlightframecount )
|
||||
|
|
|
@ -1463,7 +1463,6 @@ static render_api_t gRenderAPI =
|
|||
COM_CompareFileTime,
|
||||
Host_Error,
|
||||
pfnSPR_LoadExt,
|
||||
Mod_TesselatePolygon,
|
||||
R_StudioGetTexture,
|
||||
GL_GetOverviewParms,
|
||||
S_FadeMusicVolume,
|
||||
|
|
|
@ -829,7 +829,6 @@ R_BlendLightmaps
|
|||
void R_BlendLightmaps( void )
|
||||
{
|
||||
msurface_t *surf, *newsurf = NULL;
|
||||
mextrasurf_t *info;
|
||||
int i;
|
||||
|
||||
if( r_fullbright->value || !cl.worldmodel->lightdata )
|
||||
|
@ -876,7 +875,7 @@ void R_BlendLightmaps( void )
|
|||
{
|
||||
GL_Bind( GL_TEXTURE0, tr.lightmapTextures[i] );
|
||||
|
||||
for( surf = gl_lms.lightmap_surfaces[i]; surf != NULL; surf = surf->lightmapchain )
|
||||
for( surf = gl_lms.lightmap_surfaces[i]; surf != NULL; surf = surf->info->lightmapchain )
|
||||
{
|
||||
if( surf->polys ) DrawGLPolyChain( surf->polys, 0.0f, 0.0f );
|
||||
}
|
||||
|
@ -894,7 +893,7 @@ void R_BlendLightmaps( void )
|
|||
|
||||
newsurf = gl_lms.dynamic_surfaces;
|
||||
|
||||
for( surf = gl_lms.dynamic_surfaces; surf != NULL; surf = surf->lightmapchain )
|
||||
for( surf = gl_lms.dynamic_surfaces; surf != NULL; surf = surf->info->lightmapchain )
|
||||
{
|
||||
int smax, tmax;
|
||||
int sample_size;
|
||||
|
@ -903,12 +902,11 @@ void R_BlendLightmaps( void )
|
|||
sample_size = Mod_SampleSizeForFace( surf );
|
||||
smax = ( surf->extents[0] / sample_size ) + 1;
|
||||
tmax = ( surf->extents[1] / sample_size ) + 1;
|
||||
info = SURF_INFO( surf, RI.currentmodel );
|
||||
|
||||
if( LM_AllocBlock( smax, tmax, &info->dlight_s, &info->dlight_t ))
|
||||
if( LM_AllocBlock( smax, tmax, &surf->info->dlight_s, &surf->info->dlight_t ))
|
||||
{
|
||||
base = gl_lms.lightmap_buffer;
|
||||
base += ( info->dlight_t * BLOCK_SIZE + info->dlight_s ) * 4;
|
||||
base += ( surf->info->dlight_t * BLOCK_SIZE + surf->info->dlight_s ) * 4;
|
||||
|
||||
R_BuildLightMap( surf, base, BLOCK_SIZE * 4, true );
|
||||
}
|
||||
|
@ -920,15 +918,13 @@ void R_BlendLightmaps( void )
|
|||
LM_UploadBlock( true );
|
||||
|
||||
// draw all surfaces that use this lightmap
|
||||
for( drawsurf = newsurf; drawsurf != surf; drawsurf = drawsurf->lightmapchain )
|
||||
for( drawsurf = newsurf; drawsurf != surf; drawsurf = drawsurf->info->lightmapchain )
|
||||
{
|
||||
if( drawsurf->polys )
|
||||
{
|
||||
info = SURF_INFO( drawsurf, RI.currentmodel );
|
||||
|
||||
DrawGLPolyChain( drawsurf->polys,
|
||||
( drawsurf->light_s - info->dlight_s ) * ( 1.0f / (float)BLOCK_SIZE ),
|
||||
( drawsurf->light_t - info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ));
|
||||
( drawsurf->light_s - drawsurf->info->dlight_s ) * ( 1.0f / (float)BLOCK_SIZE ),
|
||||
( drawsurf->light_t - drawsurf->info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -937,14 +933,12 @@ void R_BlendLightmaps( void )
|
|||
// clear the block
|
||||
LM_InitBlock();
|
||||
|
||||
info = SURF_INFO( surf, RI.currentmodel );
|
||||
|
||||
// try uploading the block now
|
||||
if( !LM_AllocBlock( smax, tmax, &info->dlight_s, &info->dlight_t ))
|
||||
if( !LM_AllocBlock( smax, tmax, &surf->info->dlight_s, &surf->info->dlight_t ))
|
||||
Host_Error( "AllocBlock: full\n" );
|
||||
|
||||
base = gl_lms.lightmap_buffer;
|
||||
base += ( info->dlight_t * BLOCK_SIZE + info->dlight_s ) * 4;
|
||||
base += ( surf->info->dlight_t * BLOCK_SIZE + surf->info->dlight_s ) * 4;
|
||||
|
||||
R_BuildLightMap( surf, base, BLOCK_SIZE * 4, true );
|
||||
}
|
||||
|
@ -953,15 +947,13 @@ void R_BlendLightmaps( void )
|
|||
// draw remainder of dynamic lightmaps that haven't been uploaded yet
|
||||
if( newsurf ) LM_UploadBlock( true );
|
||||
|
||||
for( surf = newsurf; surf != NULL; surf = surf->lightmapchain )
|
||||
for( surf = newsurf; surf != NULL; surf = surf->info->lightmapchain )
|
||||
{
|
||||
if( surf->polys )
|
||||
{
|
||||
info = SURF_INFO( surf, RI.currentmodel );
|
||||
|
||||
DrawGLPolyChain( surf->polys,
|
||||
( surf->light_s - info->dlight_s ) * ( 1.0f / (float)BLOCK_SIZE ),
|
||||
( surf->light_t - info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ));
|
||||
( surf->light_s - surf->info->dlight_s ) * ( 1.0f / (float)BLOCK_SIZE ),
|
||||
( surf->light_t - surf->info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1068,7 +1060,7 @@ void R_RenderDetails( void )
|
|||
|
||||
for( p = es; p; p = p->detailchain )
|
||||
{
|
||||
fa = INFO_SURF( p, RI.currentmodel );
|
||||
fa = p->surf;
|
||||
glt = R_GetTexture( fa->texinfo->texture->gl_texturenum ); // get texture scale
|
||||
DrawGLPoly( fa->polys, glt->xscale, glt->yscale );
|
||||
}
|
||||
|
@ -1112,9 +1104,9 @@ void R_RenderBrushPoly( msurface_t *fa )
|
|||
|
||||
if( RP_NORMALPASS() && fa->flags & SURF_REFLECT )
|
||||
{
|
||||
if( SURF_INFO( fa, RI.currentmodel )->mirrortexturenum )
|
||||
if( fa->info->mirrortexturenum )
|
||||
{
|
||||
GL_Bind( GL_TEXTURE0, SURF_INFO( fa, RI.currentmodel )->mirrortexturenum );
|
||||
GL_Bind( GL_TEXTURE0, fa->info->mirrortexturenum );
|
||||
is_mirror = true;
|
||||
|
||||
// BEGIN WATER STUFF
|
||||
|
@ -1128,7 +1120,7 @@ void R_RenderBrushPoly( msurface_t *fa )
|
|||
else GL_Bind( GL_TEXTURE0, t->gl_texturenum ); // dummy
|
||||
|
||||
// DEBUG: reset the mirror texture after drawing
|
||||
SURF_INFO( fa, RI.currentmodel )->mirrortexturenum = 0;
|
||||
fa->info->mirrortexturenum = 0;
|
||||
}
|
||||
else GL_Bind( GL_TEXTURE0, t->gl_texturenum );
|
||||
|
||||
|
@ -1151,8 +1143,6 @@ void R_RenderBrushPoly( msurface_t *fa )
|
|||
|
||||
if( r_detailtextures->value )
|
||||
{
|
||||
mextrasurf_t *es = SURF_INFO( fa, RI.currentmodel );
|
||||
|
||||
if( RI.fogEnabled || RI.fogCustom )
|
||||
{
|
||||
// don't apply detail textures for windows in the fog
|
||||
|
@ -1160,22 +1150,22 @@ void R_RenderBrushPoly( msurface_t *fa )
|
|||
{
|
||||
if( t->dt_texturenum )
|
||||
{
|
||||
es->detailchain = detail_surfaces[t->dt_texturenum];
|
||||
detail_surfaces[t->dt_texturenum] = es;
|
||||
fa->info->detailchain = detail_surfaces[t->dt_texturenum];
|
||||
detail_surfaces[t->dt_texturenum] = fa->info;
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw stub detail texture for underwater surfaces
|
||||
es->detailchain = detail_surfaces[tr.grayTexture];
|
||||
detail_surfaces[tr.grayTexture] = es;
|
||||
fa->info->detailchain = detail_surfaces[tr.grayTexture];
|
||||
detail_surfaces[tr.grayTexture] = fa->info;
|
||||
}
|
||||
draw_details = true;
|
||||
}
|
||||
}
|
||||
else if( t->dt_texturenum )
|
||||
{
|
||||
es->detailchain = detail_surfaces[t->dt_texturenum];
|
||||
detail_surfaces[t->dt_texturenum] = es;
|
||||
fa->info->detailchain = detail_surfaces[t->dt_texturenum];
|
||||
detail_surfaces[t->dt_texturenum] = fa->info;
|
||||
draw_details = true;
|
||||
}
|
||||
}
|
||||
|
@ -1227,18 +1217,18 @@ dynamic:
|
|||
pglTexSubImage2D( GL_TEXTURE_2D, 0, fa->light_s, fa->light_t, smax, tmax,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, temp );
|
||||
|
||||
fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum];
|
||||
fa->info->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum];
|
||||
gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa;
|
||||
}
|
||||
else
|
||||
{
|
||||
fa->lightmapchain = gl_lms.dynamic_surfaces;
|
||||
fa->info->lightmapchain = gl_lms.dynamic_surfaces;
|
||||
gl_lms.dynamic_surfaces = fa;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum];
|
||||
fa->info->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum];
|
||||
gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa;
|
||||
}
|
||||
}
|
||||
|
@ -1373,18 +1363,14 @@ compare translucent surfaces
|
|||
static int R_SurfaceCompare( const msurface_t **a, const msurface_t **b )
|
||||
{
|
||||
msurface_t *surf1, *surf2;
|
||||
mextrasurf_t *info1, *info2;
|
||||
vec3_t org1, org2;
|
||||
float len1, len2;
|
||||
|
||||
surf1 = (msurface_t *)*a;
|
||||
surf2 = (msurface_t *)*b;
|
||||
|
||||
info1 = SURF_INFO( surf1, RI.currentmodel );
|
||||
info2 = SURF_INFO( surf2, RI.currentmodel );
|
||||
|
||||
VectorAdd( RI.currententity->origin, info1->origin, org1 );
|
||||
VectorAdd( RI.currententity->origin, info2->origin, org2 );
|
||||
VectorAdd( RI.currententity->origin, surf1->info->origin, org1 );
|
||||
VectorAdd( RI.currententity->origin, surf2->info->origin, org2 );
|
||||
|
||||
// compare by plane dists
|
||||
len1 = DotProduct( org1, RI.vforward ) - RI.viewplanedist;
|
||||
|
@ -1875,7 +1861,7 @@ void R_DrawTriangleOutlines( void )
|
|||
// render static surfaces first
|
||||
for( i = 0; i < MAX_LIGHTMAPS; i++ )
|
||||
{
|
||||
for( surf = gl_lms.lightmap_surfaces[i]; surf != NULL; surf = surf->lightmapchain )
|
||||
for( surf = gl_lms.lightmap_surfaces[i]; surf != NULL; surf = surf->info->lightmapchain )
|
||||
{
|
||||
p = surf->polys;
|
||||
for( ; p != NULL; p = p->chain )
|
||||
|
@ -1890,7 +1876,7 @@ void R_DrawTriangleOutlines( void )
|
|||
}
|
||||
|
||||
// render surfaces with dynamic lightmaps
|
||||
for( surf = gl_lms.dynamic_surfaces; surf != NULL; surf = surf->lightmapchain )
|
||||
for( surf = gl_lms.dynamic_surfaces; surf != NULL; surf = surf->info->lightmapchain )
|
||||
{
|
||||
p = surf->polys;
|
||||
|
||||
|
@ -2049,10 +2035,6 @@ void GL_CreateSurfaceLightmap( msurface_t *surf )
|
|||
|
||||
R_SetCacheState( surf );
|
||||
R_BuildLightMap( surf, base, BLOCK_SIZE * 4, false );
|
||||
|
||||
// moved here in case we need valid lightmap coords
|
||||
if( host.features & ENGINE_BUILD_SURFMESHES )
|
||||
Mod_BuildSurfacePolygons( surf, SURF_INFO( surf, loadmodel ));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -161,10 +161,12 @@ load sprite model
|
|||
*/
|
||||
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags )
|
||||
{
|
||||
dsprite_q1_t *pinq1;
|
||||
dsprite_hl_t *pinhl;
|
||||
dsprite_t *pin;
|
||||
short *numi;
|
||||
msprite_t *psprite;
|
||||
short *numi = NULL;
|
||||
dframetype_t *pframetype;
|
||||
msprite_t *psprite;
|
||||
int i, size;
|
||||
|
||||
if( loaded ) *loaded = false;
|
||||
|
@ -179,29 +181,54 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui
|
|||
return;
|
||||
}
|
||||
|
||||
if( i != SPRITE_VERSION )
|
||||
if( i != SPRITE_VERSION_Q1 && i != SPRITE_VERSION_HL )
|
||||
{
|
||||
MsgDev( D_ERROR, "%s has wrong version number (%i should be %i)\n", mod->name, i, SPRITE_VERSION );
|
||||
MsgDev( D_ERROR, "%s has wrong version number (%i should be %i or %i)\n", mod->name, i, SPRITE_VERSION_Q1, SPRITE_VERSION_HL );
|
||||
return;
|
||||
}
|
||||
|
||||
mod->mempool = Mem_AllocPool( va( "^2%s^7", mod->name ));
|
||||
size = sizeof( msprite_t ) + ( pin->numframes - 1 ) * sizeof( psprite->frames );
|
||||
psprite = Mem_Alloc( mod->mempool, size );
|
||||
mod->cache.data = psprite; // make link to extradata
|
||||
|
||||
psprite->type = pin->type;
|
||||
psprite->texFormat = pin->texFormat;
|
||||
psprite->numframes = mod->numframes = pin->numframes;
|
||||
psprite->facecull = pin->facetype;
|
||||
psprite->radius = pin->boundingradius;
|
||||
psprite->synctype = pin->synctype;
|
||||
|
||||
mod->mins[0] = mod->mins[1] = -pin->bounds[0] * 0.5f;
|
||||
mod->maxs[0] = mod->maxs[1] = pin->bounds[0] * 0.5f;
|
||||
mod->mins[2] = -pin->bounds[1] * 0.5f;
|
||||
mod->maxs[2] = pin->bounds[1] * 0.5f;
|
||||
numi = (short *)(pin + 1);
|
||||
if( i == SPRITE_VERSION_Q1 )
|
||||
{
|
||||
pinq1 = (dsprite_q1_t *)buffer;
|
||||
size = sizeof( msprite_t ) + ( pinq1->numframes - 1 ) * sizeof( psprite->frames );
|
||||
psprite = Mem_Alloc( mod->mempool, size );
|
||||
mod->cache.data = psprite; // make link to extradata
|
||||
|
||||
psprite->type = pinq1->type;
|
||||
psprite->texFormat = SPR_ADDITIVE; //SPR_ALPHTEST;
|
||||
psprite->numframes = mod->numframes = pinq1->numframes;
|
||||
psprite->facecull = SPR_CULL_FRONT;
|
||||
psprite->radius = pinq1->boundingradius;
|
||||
psprite->synctype = pinq1->synctype;
|
||||
|
||||
mod->mins[0] = mod->mins[1] = -pinq1->bounds[0] * 0.5f;
|
||||
mod->maxs[0] = mod->maxs[1] = pinq1->bounds[0] * 0.5f;
|
||||
mod->mins[2] = -pinq1->bounds[1] * 0.5f;
|
||||
mod->maxs[2] = pinq1->bounds[1] * 0.5f;
|
||||
numi = NULL;
|
||||
}
|
||||
else if( i == SPRITE_VERSION_HL )
|
||||
{
|
||||
pinhl = (dsprite_hl_t *)buffer;
|
||||
size = sizeof( msprite_t ) + ( pinhl->numframes - 1 ) * sizeof( psprite->frames );
|
||||
psprite = Mem_Alloc( mod->mempool, size );
|
||||
mod->cache.data = psprite; // make link to extradata
|
||||
|
||||
psprite->type = pinhl->type;
|
||||
psprite->texFormat = pinhl->texFormat;
|
||||
psprite->numframes = mod->numframes = pinhl->numframes;
|
||||
psprite->facecull = pinhl->facetype;
|
||||
psprite->radius = pinhl->boundingradius;
|
||||
psprite->synctype = pinhl->synctype;
|
||||
|
||||
mod->mins[0] = mod->mins[1] = -pinhl->bounds[0] * 0.5f;
|
||||
mod->maxs[0] = mod->maxs[1] = pinhl->bounds[0] * 0.5f;
|
||||
mod->mins[2] = -pinhl->bounds[1] * 0.5f;
|
||||
mod->maxs[2] = pinhl->bounds[1] * 0.5f;
|
||||
numi = (short *)(pinhl + 1);
|
||||
}
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
|
@ -211,7 +238,15 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui
|
|||
return;
|
||||
}
|
||||
|
||||
if( *numi == 256 )
|
||||
if( numi == NULL )
|
||||
{
|
||||
rgbdata_t *pal;
|
||||
|
||||
pal = FS_LoadImage( "#id.pal", (byte *)&i, 768 );
|
||||
pframetype = (dframetype_t *)(pinq1 + 1);
|
||||
FS_FreeImage( pal ); // palette installed, no reason to keep this data
|
||||
}
|
||||
else if( *numi == 256 )
|
||||
{
|
||||
byte *src = (byte *)(numi+1);
|
||||
rgbdata_t *pal;
|
||||
|
@ -235,17 +270,17 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui
|
|||
}
|
||||
else
|
||||
{
|
||||
MsgDev( D_ERROR, "%s has wrong number of palette colors %i (should be 256)\n", mod->name, numi );
|
||||
MsgDev( D_ERROR, "%s has wrong number of palette colors %i (should be 256)\n", mod->name, *numi );
|
||||
return;
|
||||
}
|
||||
|
||||
if( pin->numframes < 1 )
|
||||
if( mod->numframes < 1 )
|
||||
{
|
||||
MsgDev( D_ERROR, "%s has invalid # of frames: %d\n", mod->name, pin->numframes );
|
||||
MsgDev( D_ERROR, "%s has invalid # of frames: %d\n", mod->name, mod->numframes );
|
||||
return;
|
||||
}
|
||||
|
||||
for( i = 0; i < pin->numframes; i++ )
|
||||
for( i = 0; i < mod->numframes; i++ )
|
||||
{
|
||||
frametype_t frametype = pframetype->type;
|
||||
psprite->frames[i].type = frametype;
|
||||
|
|
|
@ -1598,8 +1598,12 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight )
|
|||
{
|
||||
int sequence = bound( 0, ent->curstate.sequence, m_pStudioHeader->numseq - 1 );
|
||||
mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + sequence;
|
||||
vec3_t size;
|
||||
|
||||
if( !FBitSet( pseqdesc->flags, STUDIO_LOOPING ) && !pseqdesc->activity && m_pStudioHeader->numseq > 1 )
|
||||
VectorSubtract( pseqdesc->bbmax, pseqdesc->bbmin, size );
|
||||
total = Q_max( size[0], Q_max( size[1], size[2] ));
|
||||
|
||||
if( !FBitSet( pseqdesc->flags, STUDIO_LOOPING ) && !pseqdesc->activity && m_pStudioHeader->numseq > 1 && total > 128.0f )
|
||||
Matrix3x4_OriginFromMatrix( g_studio.lighttransform[0], origin );
|
||||
else Matrix3x4_OriginFromMatrix( g_studio.rotationmatrix, origin );
|
||||
}
|
||||
|
@ -1634,9 +1638,9 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight )
|
|||
{
|
||||
VectorSet( lightDir, mv->skyvec_x, mv->skyvec_y, mv->skyvec_z );
|
||||
|
||||
light.r = LightToTexGamma( mv->skycolor_r );
|
||||
light.g = LightToTexGamma( mv->skycolor_g );
|
||||
light.b = LightToTexGamma( mv->skycolor_b );
|
||||
light.r = mv->skycolor_r;
|
||||
light.g = mv->skycolor_g;
|
||||
light.b = mv->skycolor_b;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3394,11 +3398,16 @@ void R_DrawStudioModel( cl_entity_t *e )
|
|||
}
|
||||
else
|
||||
{
|
||||
if( e->curstate.movetype == MOVETYPE_FOLLOW )
|
||||
if( e->curstate.movetype == MOVETYPE_FOLLOW && e->curstate.aiment > 0 )
|
||||
{
|
||||
RI.currententity = CL_GetEntityByIndex( e->curstate.aiment );
|
||||
R_StudioDrawModelInternal( RI.currententity, 0 );
|
||||
RI.currententity = e;
|
||||
cl_entity_t *parent = CL_GetEntityByIndex( e->curstate.aiment );
|
||||
|
||||
if( parent && parent->model && parent->model->type == mod_studio )
|
||||
{
|
||||
RI.currententity = parent;
|
||||
R_StudioDrawModelInternal( RI.currententity, 0 );
|
||||
RI.currententity = e;
|
||||
}
|
||||
}
|
||||
|
||||
R_StudioDrawModelInternal( e, STUDIO_RENDER|STUDIO_EVENTS );
|
||||
|
|
|
@ -2131,7 +2131,7 @@ qboolean S_Init( void )
|
|||
}
|
||||
|
||||
s_volume = Cvar_Get( "volume", "0.7", FCVAR_ARCHIVE, "sound volume" );
|
||||
s_musicvolume = Cvar_Get( "musicvolume", "1.0", FCVAR_ARCHIVE, "background music volume" );
|
||||
s_musicvolume = Cvar_Get( "MP3Volume", "1.0", FCVAR_ARCHIVE, "background music volume" );
|
||||
s_mixahead = Cvar_Get( "_snd_mixahead", "0.12", 0, "how much sound to mix ahead of time" );
|
||||
s_show = Cvar_Get( "s_show", "0", FCVAR_ARCHIVE, "show playing sounds" );
|
||||
s_lerping = Cvar_Get( "s_lerping", "0", FCVAR_ARCHIVE, "apply interpolation to sound output" );
|
||||
|
|
|
@ -962,31 +962,41 @@ void Cmd_ExecuteString( char *text )
|
|||
// execute the command line
|
||||
Cmd_TokenizeString( text );
|
||||
|
||||
if( !Cmd_Argc()) return; // no tokens
|
||||
if( !Cmd_Argc( )) return; // no tokens
|
||||
|
||||
// check aliases
|
||||
for( a = cmd_alias; a; a = a->next )
|
||||
if( !host.apply_game_config )
|
||||
{
|
||||
if( !Q_stricmp( cmd_argv[0], a->name ))
|
||||
// check aliases
|
||||
for( a = cmd_alias; a; a = a->next )
|
||||
{
|
||||
Cbuf_InsertText( a->value );
|
||||
return;
|
||||
if( !Q_stricmp( cmd_argv[0], a->name ))
|
||||
{
|
||||
Cbuf_InsertText( a->value );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check functions
|
||||
for( cmd = cmd_functions; cmd; cmd = cmd->next )
|
||||
// special mode for restore game.dll archived cvars
|
||||
if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" ))
|
||||
{
|
||||
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
|
||||
// check functions
|
||||
for( cmd = cmd_functions; cmd; cmd = cmd->next )
|
||||
{
|
||||
cmd->function();
|
||||
return;
|
||||
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
|
||||
{
|
||||
cmd->function();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check cvars
|
||||
if( Cvar_Command( )) return;
|
||||
|
||||
if( host.apply_game_config )
|
||||
return; // don't send nothing to server: we is a server!
|
||||
|
||||
// forward the command line to the server, so the entity DLL can parse it
|
||||
if( host.type == HOST_NORMAL )
|
||||
{
|
||||
|
|
|
@ -332,6 +332,7 @@ typedef struct host_parm_s
|
|||
qboolean overview_loading; // another nasty hack to tell imagelib about ovierview
|
||||
qboolean force_draw_version; // used when fraps is loaded
|
||||
qboolean write_to_clipboard; // put image to clipboard instead of disk
|
||||
qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands
|
||||
qboolean crashed; // set to true if crashed
|
||||
|
||||
// some settings were changed and needs to global update
|
||||
|
|
|
@ -987,7 +987,7 @@ void Host_WriteServerConfig( const char *name )
|
|||
{
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\t\t\tCopyright XashXT Group %s ©\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\tsettings.rc - multiplayer server temporare config\n" );
|
||||
FS_Printf( f, "//\t\tgame.cfg - multiplayer server temporare config\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
Cvar_WriteVariables( f, FCVAR_SERVER );
|
||||
FS_Close( f );
|
||||
|
|
|
@ -2163,6 +2163,10 @@ void Con_VidInit( void )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if( !con.background ) // last chance - quake conback image
|
||||
con.background = GL_LoadTexture( "gfx/conback.lmp", NULL, 0, TF_IMAGE, NULL );
|
||||
|
||||
// missed console image will be replaced as gray background like X-Ray or Crysis
|
||||
if( con.background == tr.defaultTexture || con.background == 0 )
|
||||
con.background = tr.grayTexture;
|
||||
|
|
|
@ -375,7 +375,7 @@ void Cvar_DirectSet( convar_t *var, const char *value )
|
|||
if( !var ) return; // ???
|
||||
|
||||
// lookup for registration
|
||||
if( CVAR_CHECK_SENTINEL( var ) || var->next == NULL )
|
||||
if( CVAR_CHECK_SENTINEL( var ) || ( var->next == NULL && !FBitSet( var->flags, FCVAR_EXTENDED|FCVAR_ALLOCATED )))
|
||||
{
|
||||
// need to registering cvar fisrt
|
||||
MsgDev( D_WARN, "Cvar_DirectSet: called for unregistered cvar '%s'\n", var->name );
|
||||
|
@ -472,8 +472,10 @@ void Cvar_Set( const char *var_name, const char *value )
|
|||
convar_t *var = Cvar_FindVar( var_name );
|
||||
|
||||
if( !var )
|
||||
{ // there is an error in C code if this happens
|
||||
MsgDev( D_ERROR, "Cvar_Set: variable '%s' not found\n", var_name );
|
||||
{
|
||||
// there is an error in C code if this happens
|
||||
if( host.type != HOST_DEDICATED )
|
||||
MsgDev( D_ERROR, "Cvar_Set: variable '%s' not found\n", var_name );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -602,6 +604,12 @@ qboolean Cvar_Command( void )
|
|||
return true;
|
||||
}
|
||||
|
||||
if( host.apply_game_config )
|
||||
{
|
||||
if( !FBitSet( v->flags, FCVAR_EXTDLL ))
|
||||
return true; // only game.dll cvars passed
|
||||
}
|
||||
|
||||
if( FBitSet( v->flags, FCVAR_SPONLY ) && CL_GetMaxClients() > 1 )
|
||||
{
|
||||
Msg( "can't set \"%s\" in multiplayer\n", v->name );
|
||||
|
|
|
@ -74,9 +74,6 @@ void Host_PrintEngineFeatures( void )
|
|||
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
||||
MsgDev( D_REPORT, "^3EXT:^7 big world support enabled\n" );
|
||||
|
||||
if( FBitSet( host.features, ENGINE_BUILD_SURFMESHES ))
|
||||
MsgDev( D_REPORT, "^3EXT:^7 surfmeshes enabled\n" );
|
||||
|
||||
if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA ))
|
||||
MsgDev( D_REPORT, "^3EXT:^7 deluxemap support enabled\n" );
|
||||
|
||||
|
@ -258,9 +255,9 @@ void Host_Exec_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
if( !Q_stricmp( "settings.rc", Cmd_Argv( 1 )))
|
||||
if( !Q_stricmp( "game.cfg", Cmd_Argv( 1 )))
|
||||
{
|
||||
// don't execute settings.rc in singleplayer
|
||||
// don't execute game.cfg in singleplayer
|
||||
if( SV_GetMaxClients() == 1 )
|
||||
return;
|
||||
}
|
||||
|
@ -281,7 +278,9 @@ void Host_Exec_f( void )
|
|||
Q_strncat( txt, "\n", len + 2 );
|
||||
Mem_Free( f );
|
||||
|
||||
MsgDev( D_INFO, "execing %s\n", Cmd_Argv( 1 ));
|
||||
if( host.apply_game_config )
|
||||
MsgDev( D_INFO, "execing ^2%s^7\n", Cmd_Argv( 1 ));
|
||||
else MsgDev( D_INFO, "execing %s\n", Cmd_Argv( 1 ));
|
||||
Cbuf_InsertText( txt );
|
||||
Mem_Free( txt );
|
||||
}
|
||||
|
@ -637,6 +636,7 @@ void Host_Print( const char *txt )
|
|||
Q_strcat( host.rd.buffer, txt );
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Print( txt ); // echo to client console
|
||||
}
|
||||
|
||||
|
@ -753,12 +753,16 @@ static void Host_Crash_f( void )
|
|||
Host_InitCommon
|
||||
=================
|
||||
*/
|
||||
void Host_InitCommon( const char *progname, qboolean bChangeGame )
|
||||
void Host_InitCommon( const char *hostname, qboolean bChangeGame )
|
||||
{
|
||||
MEMORYSTATUS lpBuffer;
|
||||
char dev_level[4];
|
||||
char progname[128];
|
||||
char cmdline[128];
|
||||
qboolean parse_cmdline = false;
|
||||
char szTemp[MAX_SYSPATH];
|
||||
string szRootPath;
|
||||
char *in, *out;
|
||||
|
||||
lpBuffer.dwLength = sizeof( MEMORYSTATUS );
|
||||
GlobalMemoryStatus( &lpBuffer );
|
||||
|
@ -777,10 +781,30 @@ void Host_InitCommon( const char *progname, qboolean bChangeGame )
|
|||
|
||||
Memory_Init(); // init memory subsystem
|
||||
|
||||
// some commands may turn engine into infinity loop,
|
||||
// e.g. xash.exe +game xash -game xash
|
||||
// so we clearing all cmd_args, but leave dbg states as well
|
||||
Sys_ParseCommandLine( GetCommandLine( ));
|
||||
progname[0] = cmdline[0] = '\0';
|
||||
in = (char *)hostname;
|
||||
out = progname;
|
||||
|
||||
while( *in != '\0' )
|
||||
{
|
||||
if( parse_cmdline )
|
||||
{
|
||||
*out++ = *in++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *in == ' ' )
|
||||
{
|
||||
parse_cmdline = true;
|
||||
*out++ = '\0';
|
||||
out = cmdline;
|
||||
}
|
||||
else *out++ = *in++;
|
||||
}
|
||||
}
|
||||
*out = '\0'; // write terminator
|
||||
|
||||
Sys_ParseCommandLine( GetCommandLine( ), false );
|
||||
SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors
|
||||
|
||||
host.mempool = Mem_AllocPool( "Zone Engine" );
|
||||
|
@ -823,6 +847,9 @@ void Host_InitCommon( const char *progname, qboolean bChangeGame )
|
|||
}
|
||||
else Q_strncpy( SI.ModuleName, progname, sizeof( SI.ModuleName ));
|
||||
|
||||
if( Sys_CheckParm( "-dedicated" ))
|
||||
host.type = HOST_DEDICATED;
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
// check for duplicate dedicated server
|
||||
|
@ -835,7 +862,7 @@ void Host_InitCommon( const char *progname, qboolean bChangeGame )
|
|||
return;
|
||||
}
|
||||
|
||||
Sys_MergeCommandLine( GetCommandLine( ));
|
||||
Sys_MergeCommandLine( cmdline );
|
||||
|
||||
CloseHandle( host.hMutex );
|
||||
host.hMutex = CreateSemaphore( NULL, 0, 1, "Xash Dedicated Server" );
|
||||
|
@ -955,21 +982,10 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func
|
|||
|
||||
Cmd_AddCommand( "quit", Sys_Quit, "quit the game" );
|
||||
Cmd_AddCommand( "exit", Sys_Quit, "quit the game" );
|
||||
|
||||
// dedicated servers using settings from server.cfg file
|
||||
Cbuf_AddText( va( "exec %s\n", "settings.rc" ));
|
||||
Cbuf_Execute();
|
||||
|
||||
Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "defaultmap" )));
|
||||
}
|
||||
else
|
||||
{
|
||||
Cmd_AddCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
|
||||
Cbuf_AddText( "exec config.cfg\n" );
|
||||
}
|
||||
else Cmd_AddCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
|
||||
|
||||
host.errorframe = 0;
|
||||
Cbuf_Execute();
|
||||
|
||||
// post initializations
|
||||
switch( host.type )
|
||||
|
@ -978,6 +994,7 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func
|
|||
Con_ShowConsole( false ); // hide console
|
||||
// execute startup config and cmdline
|
||||
Cbuf_AddText( va( "exec %s.rc\n", SI.ModuleName ));
|
||||
Cbuf_AddText( "exec config.cfg\n" );
|
||||
// intentional fallthrough
|
||||
case HOST_DEDICATED:
|
||||
// if stuffcmds wasn't run, then init.rc is probably missing, use default
|
||||
|
@ -992,7 +1009,6 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func
|
|||
Cmd_RemoveCommand( "setgl" );
|
||||
|
||||
// we need to execute it again here
|
||||
Cmd_ExecuteString( "exec config.cfg\n" );
|
||||
oldtime = Sys_DoubleTime() - 0.1;
|
||||
SCR_CheckStartupVids(); // must be last
|
||||
|
||||
|
|
|
@ -260,7 +260,9 @@ enum
|
|||
LUMP_NORMAL = 0, // no alpha
|
||||
LUMP_MASKED, // 1-bit alpha channel masked texture
|
||||
LUMP_GRADIENT, // gradient image (decals)
|
||||
LUMP_EXTENDED // bmp images have extened palette with alpha-channel
|
||||
LUMP_EXTENDED, // bmp images have extened palette with alpha-channel
|
||||
LUMP_HALFLIFE, // get predefined half-life palette
|
||||
LUMP_QUAKE1 // get predefined quake palette
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
|
@ -348,28 +348,28 @@ void Image_SetPalette( const byte *pal, uint *d_table )
|
|||
|
||||
void Image_GetPaletteQ1( void )
|
||||
{
|
||||
image.d_rendermode = LUMP_NORMAL;
|
||||
|
||||
if( !q1palette_init )
|
||||
{
|
||||
image.d_rendermode = LUMP_NORMAL;
|
||||
Image_SetPalette( palette_q1, d_8toQ1table );
|
||||
d_8toQ1table[255] = 0; // 255 is transparent
|
||||
q1palette_init = true;
|
||||
}
|
||||
|
||||
image.d_rendermode = LUMP_QUAKE1;
|
||||
image.d_currentpal = d_8toQ1table;
|
||||
}
|
||||
|
||||
void Image_GetPaletteHL( void )
|
||||
{
|
||||
image.d_rendermode = LUMP_NORMAL;
|
||||
|
||||
if( !hlpalette_init )
|
||||
{
|
||||
image.d_rendermode = LUMP_NORMAL;
|
||||
Image_SetPalette( palette_hl, d_8toHLtable );
|
||||
hlpalette_init = true;
|
||||
}
|
||||
|
||||
image.d_rendermode = LUMP_HALFLIFE;
|
||||
image.d_currentpal = d_8toHLtable;
|
||||
}
|
||||
|
||||
|
@ -393,7 +393,22 @@ void Image_GetPaletteLMP( const byte *pal, int rendermode )
|
|||
Image_SetPalette( pal, d_8to24table );
|
||||
image.d_currentpal = d_8to24table;
|
||||
}
|
||||
else Image_GetPaletteHL(); // default half-life palette
|
||||
else
|
||||
{
|
||||
switch( rendermode )
|
||||
{
|
||||
case LUMP_QUAKE1:
|
||||
Image_GetPaletteQ1();
|
||||
break;
|
||||
case LUMP_HALFLIFE:
|
||||
Image_GetPaletteHL(); // default half-life palette
|
||||
break;
|
||||
default:
|
||||
MsgDev( D_ERROR, "Image_GetPaletteLMP: invalid palette specified\n" );
|
||||
Image_GetPaletteHL(); // defaulting to half-life palette
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Image_ConvertPalTo24bit( rgbdata_t *pic )
|
||||
|
|
|
@ -45,7 +45,15 @@ qboolean Image_LoadPAL( const char *name, const byte *buffer, size_t filesize )
|
|||
else if( Q_stristr( name, "gradient" ))
|
||||
rendermode = LUMP_GRADIENT;
|
||||
else if( Q_stristr( name, "valve" ))
|
||||
{
|
||||
rendermode = LUMP_HALFLIFE;
|
||||
buffer = NULL; // force to get HL palette
|
||||
}
|
||||
else if( Q_stristr( name, "id" ))
|
||||
{
|
||||
rendermode = LUMP_QUAKE1;
|
||||
buffer = NULL; // force to get Q1 palette
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: image.d_currentpal not cleared with Image_Reset()
|
||||
|
@ -219,6 +227,7 @@ qboolean Image_LoadSPR( const char *name, const byte *buffer, size_t filesize )
|
|||
{
|
||||
case LUMP_GRADIENT:
|
||||
case LUMP_MASKED:
|
||||
case LUMP_QUAKE1:
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -40,9 +40,6 @@ GNU General Public License for more details.
|
|||
|
||||
#define LM_SAMPLE_SIZE world.lm_sample_size // lightmap resoultion
|
||||
|
||||
#define SURF_INFO( surf, mod ) ((mextrasurf_t *)mod->cache.data + (surf - mod->surfaces))
|
||||
#define INFO_SURF( surf, mod ) (mod->surfaces + (surf - (mextrasurf_t *)mod->cache.data))
|
||||
|
||||
#define CHECKVISBIT( vis, b ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] & (1 << ((b) & 7))) : (byte)false )
|
||||
#define SETVISBIT( vis, b )( void ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] |= (1 << ((b) & 7))) : (byte)false )
|
||||
#define CLEARVISBIT( vis, b )( void ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] &= ~(1 << ((b) & 7))) : (byte)false )
|
||||
|
@ -140,14 +137,12 @@ model_t *Mod_ForName( const char *name, qboolean world );
|
|||
qboolean Mod_RegisterModel( const char *name, int index );
|
||||
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node );
|
||||
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, short *lastleaf );
|
||||
void Mod_TesselatePolygon( msurface_t *surf, model_t *mod, float tessSize );
|
||||
int Mod_BoxLeafnums( const vec3_t mins, const vec3_t maxs, short *list, int listsize, int *lastleaf );
|
||||
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis );
|
||||
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
|
||||
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize );
|
||||
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );
|
||||
int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize );
|
||||
void Mod_BuildSurfacePolygons( msurface_t *surf, mextrasurf_t *info );
|
||||
void Mod_AmbientLevels( const vec3_t p, byte *pvolumes );
|
||||
int Mod_SampleSizeForFace( msurface_t *surf );
|
||||
byte *Mod_GetPVSForPoint( const vec3_t p );
|
||||
|
|
|
@ -1348,7 +1348,7 @@ static void Mod_CalcSurfaceExtents( msurface_t *surf )
|
|||
e = loadmodel->surfedges[surf->firstedge + i];
|
||||
|
||||
if( e >= loadmodel->numedges || e <= -loadmodel->numedges )
|
||||
Host_Error( "Mod_CalcSurfaceBounds: bad edge\n" );
|
||||
Host_Error( "Mod_CalcSurfaceExtents: bad edge\n" );
|
||||
|
||||
if( e >= 0 ) v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
|
||||
else v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
|
||||
|
@ -1381,12 +1381,12 @@ Mod_CalcSurfaceBounds
|
|||
fills in surf->mins and surf->maxs
|
||||
=================
|
||||
*/
|
||||
static void Mod_CalcSurfaceBounds( msurface_t *surf, mextrasurf_t *info )
|
||||
static void Mod_CalcSurfaceBounds( msurface_t *surf )
|
||||
{
|
||||
int i, e;
|
||||
mvertex_t *v;
|
||||
|
||||
ClearBounds( info->mins, info->maxs );
|
||||
ClearBounds( surf->info->mins, surf->info->maxs );
|
||||
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
|
@ -1397,506 +1397,10 @@ static void Mod_CalcSurfaceBounds( msurface_t *surf, mextrasurf_t *info )
|
|||
|
||||
if( e >= 0 ) v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
|
||||
else v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
|
||||
AddPointToBounds( v->position, info->mins, info->maxs );
|
||||
AddPointToBounds( v->position, surf->info->mins, surf->info->maxs );
|
||||
}
|
||||
|
||||
VectorAverage( info->mins, info->maxs, info->origin );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_BuildPolygon
|
||||
=================
|
||||
*/
|
||||
static void Mod_BuildPolygon( mextrasurf_t *info, msurface_t *surf, int numVerts, const float *verts )
|
||||
{
|
||||
float s, t;
|
||||
uint bufSize;
|
||||
vec3_t normal, tangent, binormal;
|
||||
mtexinfo_t *texinfo = surf->texinfo;
|
||||
int i, numElems, sample_size;
|
||||
byte *buffer;
|
||||
msurfmesh_t *mesh;
|
||||
|
||||
// allocate mesh
|
||||
numElems = (numVerts - 2) * 3;
|
||||
|
||||
bufSize = sizeof( msurfmesh_t ) + numVerts * sizeof( glvert_t ) + numElems * sizeof( word );
|
||||
buffer = Mem_Alloc( loadmodel->mempool, bufSize );
|
||||
|
||||
sample_size = Mod_SampleSizeForFace( surf );
|
||||
mesh = (msurfmesh_t *)buffer;
|
||||
buffer += sizeof( msurfmesh_t );
|
||||
mesh->numVerts = numVerts;
|
||||
mesh->numElems = numElems;
|
||||
|
||||
// calc tangent space
|
||||
if( surf->flags & SURF_PLANEBACK )
|
||||
VectorNegate( surf->plane->normal, normal );
|
||||
else VectorCopy( surf->plane->normal, normal );
|
||||
VectorCopy( surf->texinfo->vecs[0], tangent );
|
||||
VectorNegate( surf->texinfo->vecs[1], binormal );
|
||||
|
||||
VectorNormalize( normal ); // g-cont. this is even needed?
|
||||
VectorNormalize( tangent );
|
||||
VectorNormalize( binormal );
|
||||
|
||||
// setup pointers
|
||||
mesh->verts = (glvert_t *)buffer;
|
||||
buffer += numVerts * sizeof( glvert_t );
|
||||
mesh->elems = (word *)buffer;
|
||||
buffer += numElems * sizeof( word );
|
||||
|
||||
mesh->next = info->mesh;
|
||||
mesh->surf = surf; // NOTE: meshchains can be linked with one surface
|
||||
info->mesh = mesh;
|
||||
|
||||
// create indices
|
||||
for( i = 0; i < mesh->numVerts - 2; i++ )
|
||||
{
|
||||
mesh->elems[i*3+0] = 0;
|
||||
mesh->elems[i*3+1] = i + 1;
|
||||
mesh->elems[i*3+2] = i + 2;
|
||||
}
|
||||
|
||||
for( i = 0; i < numVerts; i++, verts += 3 )
|
||||
{
|
||||
glvert_t *out = &mesh->verts[i];
|
||||
|
||||
// vertex
|
||||
VectorCopy( verts, out->vertex );
|
||||
VectorCopy( tangent, out->tangent );
|
||||
VectorCopy( binormal, out->binormal );
|
||||
VectorCopy( normal, out->normal );
|
||||
|
||||
// texture coordinates
|
||||
s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3];
|
||||
s /= texinfo->texture->width;
|
||||
|
||||
t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3];
|
||||
t /= texinfo->texture->height;
|
||||
|
||||
out->stcoord[0] = s;
|
||||
out->stcoord[1] = t;
|
||||
|
||||
// lightmap texture coordinates
|
||||
s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3] - surf->texturemins[0];
|
||||
s += surf->light_s * sample_size;
|
||||
s += sample_size >> 1;
|
||||
s /= BLOCK_SIZE * sample_size;
|
||||
|
||||
t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3] - surf->texturemins[1];
|
||||
t += surf->light_t * sample_size;
|
||||
t += sample_size >> 1;
|
||||
t /= BLOCK_SIZE * sample_size;
|
||||
|
||||
out->lmcoord[0] = s;
|
||||
out->lmcoord[1] = t;
|
||||
|
||||
// clear colors (it can be used for vertex lighting)
|
||||
memset( out->color, 0xFF, sizeof( out->color ));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_SubdividePolygon
|
||||
=================
|
||||
*/
|
||||
static void Mod_SubdividePolygon( mextrasurf_t *info, msurface_t *surf, int numVerts, float *verts, float tessSize )
|
||||
{
|
||||
vec3_t vTotal, nTotal, tTotal, bTotal;
|
||||
vec3_t front[MAX_SIDE_VERTS], back[MAX_SIDE_VERTS];
|
||||
float *v, m, oneDivVerts, dist, dists[MAX_SIDE_VERTS];
|
||||
qboolean lightmap = (surf->flags & SURF_DRAWTILED) ? false : true;
|
||||
vec3_t normal, tangent, binormal, mins, maxs;
|
||||
mtexinfo_t *texinfo = surf->texinfo;
|
||||
vec2_t totalST, totalLM;
|
||||
int sample_size;
|
||||
float s, t, scale;
|
||||
int i, j, f, b;
|
||||
uint bufSize;
|
||||
byte *buffer;
|
||||
msurfmesh_t *mesh;
|
||||
|
||||
ClearBounds( mins, maxs );
|
||||
|
||||
for( i = 0, v = verts; i < numVerts; i++, v += 3 )
|
||||
AddPointToBounds( v, mins, maxs );
|
||||
|
||||
sample_size = Mod_SampleSizeForFace( surf );
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
m = tessSize * (float)floor((( mins[i] + maxs[i] ) * 0.5f ) / tessSize + 0.5f );
|
||||
|
||||
if( maxs[i] - m < 8.0f ) continue;
|
||||
if( m - mins[i] < 8.0f ) continue;
|
||||
|
||||
// cut it
|
||||
for( j = 0, v = verts + i; j < numVerts; j++, v += 3 )
|
||||
dists[j] = *v - m;
|
||||
|
||||
// wrap cases
|
||||
dists[j] = dists[0];
|
||||
v -= i;
|
||||
|
||||
VectorCopy( verts, v );
|
||||
|
||||
for( f = j = b = 0, v = verts; j < numVerts; j++, v += 3 )
|
||||
{
|
||||
if( dists[j] >= 0.0f )
|
||||
{
|
||||
VectorCopy( v, front[f] );
|
||||
f++;
|
||||
}
|
||||
|
||||
if( dists[j] <= 0.0f )
|
||||
{
|
||||
VectorCopy( v, back[b] );
|
||||
b++;
|
||||
}
|
||||
|
||||
if( dists[j] == 0.0f || dists[j+1] == 0.0f )
|
||||
continue;
|
||||
|
||||
if(( dists[j] > 0.0f ) != ( dists[j+1] > 0.0f ))
|
||||
{
|
||||
// clip point
|
||||
dist = dists[j] / (dists[j] - dists[j+1]);
|
||||
front[f][0] = back[b][0] = v[0] + (v[3] - v[0]) * dist;
|
||||
front[f][1] = back[b][1] = v[1] + (v[4] - v[1]) * dist;
|
||||
front[f][2] = back[b][2] = v[2] + (v[5] - v[2]) * dist;
|
||||
f++, b++;
|
||||
}
|
||||
}
|
||||
|
||||
Mod_SubdividePolygon( info, surf, f, front[0], tessSize );
|
||||
Mod_SubdividePolygon( info, surf, b, back[0], tessSize );
|
||||
return;
|
||||
}
|
||||
|
||||
bufSize = sizeof( msurfmesh_t ) + ( numVerts + 2 ) * sizeof( glvert_t ); // temp buffer has no indices
|
||||
buffer = Mem_Alloc( loadmodel->mempool, bufSize );
|
||||
|
||||
mesh = (msurfmesh_t *)buffer;
|
||||
buffer += sizeof( msurfmesh_t );
|
||||
|
||||
// create vertices
|
||||
mesh->numVerts = numVerts + 2;
|
||||
mesh->numElems = numVerts * 3;
|
||||
|
||||
// calc tangent space
|
||||
if( surf->flags & SURF_PLANEBACK )
|
||||
VectorNegate( surf->plane->normal, normal );
|
||||
else VectorCopy( surf->plane->normal, normal );
|
||||
VectorCopy( surf->texinfo->vecs[0], tangent );
|
||||
VectorNegate( surf->texinfo->vecs[1], binormal );
|
||||
|
||||
VectorNormalize( normal ); // g-cont. this is even needed?
|
||||
VectorNormalize( tangent );
|
||||
VectorNormalize( binormal );
|
||||
|
||||
// setup pointers
|
||||
mesh->verts = (glvert_t *)buffer;
|
||||
buffer += numVerts * sizeof( glvert_t );
|
||||
|
||||
VectorClear( vTotal );
|
||||
VectorClear( nTotal );
|
||||
VectorClear( bTotal );
|
||||
VectorClear( tTotal );
|
||||
|
||||
totalST[0] = totalST[1] = 0;
|
||||
totalLM[0] = totalLM[1] = 0;
|
||||
|
||||
scale = ( 1.0f / tessSize );
|
||||
|
||||
for( i = 0; i < numVerts; i++, verts += 3 )
|
||||
{
|
||||
glvert_t *out = &mesh->verts[i+1];
|
||||
|
||||
// vertex
|
||||
VectorCopy( verts, out->vertex );
|
||||
VectorCopy( normal, out->normal );
|
||||
VectorCopy( tangent, out->tangent );
|
||||
VectorCopy( binormal, out->binormal );
|
||||
|
||||
VectorAdd( vTotal, verts, vTotal );
|
||||
VectorAdd( nTotal, normal, nTotal );
|
||||
VectorAdd( tTotal, tangent, tTotal );
|
||||
VectorAdd( bTotal, binormal, bTotal );
|
||||
|
||||
if( lightmap )
|
||||
{
|
||||
// texture coordinates
|
||||
s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3];
|
||||
s /= texinfo->texture->width;
|
||||
|
||||
t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3];
|
||||
t /= texinfo->texture->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
// texture coordinates
|
||||
s = DotProduct( verts, texinfo->vecs[0] ) * scale;
|
||||
t = DotProduct( verts, texinfo->vecs[1] ) * scale;
|
||||
}
|
||||
|
||||
out->stcoord[0] = s;
|
||||
out->stcoord[1] = t;
|
||||
|
||||
totalST[0] += s;
|
||||
totalST[1] += t;
|
||||
|
||||
if( lightmap )
|
||||
{
|
||||
// lightmap texture coordinates
|
||||
s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3] - surf->texturemins[0];
|
||||
s += surf->light_s * sample_size;
|
||||
s += sample_size >> 1;
|
||||
s /= BLOCK_SIZE * sample_size;
|
||||
|
||||
t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3] - surf->texturemins[1];
|
||||
t += surf->light_t * sample_size;
|
||||
t += sample_size >> 1;
|
||||
t /= BLOCK_SIZE * sample_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = t = 0.0f;
|
||||
}
|
||||
|
||||
out->lmcoord[0] = s;
|
||||
out->lmcoord[1] = t;
|
||||
|
||||
totalLM[0] += s;
|
||||
totalLM[1] += t;
|
||||
|
||||
// clear colors (it can be used for vertex lighting)
|
||||
memset( out->color, 0xFF, sizeof( out->color ));
|
||||
}
|
||||
|
||||
// vertex
|
||||
oneDivVerts = ( 1.0f / (float)numVerts );
|
||||
|
||||
VectorScale( vTotal, oneDivVerts, mesh->verts[0].vertex );
|
||||
VectorScale( nTotal, oneDivVerts, mesh->verts[0].normal );
|
||||
VectorScale( tTotal, oneDivVerts, mesh->verts[0].tangent );
|
||||
VectorScale( bTotal, oneDivVerts, mesh->verts[0].binormal );
|
||||
|
||||
VectorNormalize( mesh->verts[0].normal );
|
||||
VectorNormalize( mesh->verts[0].tangent );
|
||||
VectorNormalize( mesh->verts[0].binormal );
|
||||
|
||||
// texture coordinates
|
||||
mesh->verts[0].stcoord[0] = totalST[0] * oneDivVerts;
|
||||
mesh->verts[0].stcoord[1] = totalST[1] * oneDivVerts;
|
||||
|
||||
// lightmap texture coordinates
|
||||
mesh->verts[0].lmcoord[0] = totalLM[0] * oneDivVerts;
|
||||
mesh->verts[0].lmcoord[1] = totalLM[1] * oneDivVerts;
|
||||
|
||||
// copy first vertex to last
|
||||
memcpy( &mesh->verts[i+1], &mesh->verts[1], sizeof( glvert_t ));
|
||||
|
||||
mesh->next = info->mesh;
|
||||
mesh->surf = surf; // NOTE: meshchains can be linked with one surface
|
||||
info->mesh = mesh;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Mod_ConvertSurface
|
||||
|
||||
turn the polychain into one subdivided surface
|
||||
================
|
||||
*/
|
||||
static void Mod_ConvertSurface( mextrasurf_t *info, msurface_t *surf )
|
||||
{
|
||||
msurfmesh_t *poly, *next, *mesh;
|
||||
int numElems, numVerts;
|
||||
glvert_t *outVerts;
|
||||
word *outElems;
|
||||
int i, bufSize;
|
||||
byte *buffer;
|
||||
|
||||
// find the total vertex count and index count
|
||||
numElems = numVerts = 0;
|
||||
|
||||
// determine count of indices and vertices
|
||||
for( poly = info->mesh; poly; poly = poly->next )
|
||||
{
|
||||
numElems += ( poly->numVerts - 2 ) * 3;
|
||||
numVerts += poly->numVerts;
|
||||
}
|
||||
|
||||
// unsigned short limit
|
||||
if( numVerts >= 65536 ) Host_Error( "Mod_ConvertSurface: vertex count %i exceeds 65535\n", numVerts );
|
||||
if( numElems >= 65536 ) Host_Error( "Mod_ConvertSurface: index count %i exceeds 65535\n", numElems );
|
||||
|
||||
bufSize = sizeof( msurfmesh_t ) + numVerts * sizeof( glvert_t ) + numElems * sizeof( word );
|
||||
buffer = Mem_Alloc( loadmodel->mempool, bufSize );
|
||||
|
||||
mesh = (msurfmesh_t *)buffer;
|
||||
buffer += sizeof( msurfmesh_t );
|
||||
|
||||
mesh->numVerts = numVerts;
|
||||
mesh->numElems = numElems;
|
||||
|
||||
// setup pointers
|
||||
mesh->verts = (glvert_t *)buffer;
|
||||
buffer += numVerts * sizeof( glvert_t );
|
||||
mesh->elems = (word *)buffer;
|
||||
buffer += numElems * sizeof( word );
|
||||
|
||||
// setup moving pointers
|
||||
outVerts = (glvert_t *)mesh->verts;
|
||||
outElems = (word *)mesh->elems;
|
||||
|
||||
// store vertex data
|
||||
numElems = numVerts = 0;
|
||||
|
||||
for( poly = info->mesh; poly; poly = poly->next )
|
||||
{
|
||||
// indexes
|
||||
outElems = mesh->elems + numElems;
|
||||
outVerts = mesh->verts + numVerts;
|
||||
|
||||
for( i = 0; i < poly->numVerts - 2; i++ )
|
||||
{
|
||||
outElems[i*3+0] = numVerts;
|
||||
outElems[i*3+1] = numVerts + i + 1;
|
||||
outElems[i*3+2] = numVerts + i + 2;
|
||||
}
|
||||
|
||||
memcpy( outVerts, poly->verts, sizeof( glvert_t ) * poly->numVerts );
|
||||
|
||||
numElems += (poly->numVerts - 2) * 3;
|
||||
numVerts += poly->numVerts;
|
||||
}
|
||||
|
||||
// release the old polys crap
|
||||
for( poly = info->mesh; poly; poly = next )
|
||||
{
|
||||
next = poly->next;
|
||||
Mem_Free( poly );
|
||||
}
|
||||
|
||||
ASSERT( mesh->numVerts == numVerts );
|
||||
ASSERT( mesh->numElems == numElems );
|
||||
|
||||
mesh->next = info->mesh;
|
||||
mesh->surf = surf; // NOTE: meshchains can be linked with one surface
|
||||
info->mesh = mesh;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_BuildSurfacePolygons
|
||||
=================
|
||||
*/
|
||||
void Mod_BuildSurfacePolygons( msurface_t *surf, mextrasurf_t *info )
|
||||
{
|
||||
vec3_t verts[MAX_SIDE_VERTS];
|
||||
char *texname;
|
||||
int i, e;
|
||||
mvertex_t *v;
|
||||
|
||||
if( info->mesh ) return; // already exist
|
||||
|
||||
// convert edges back to a normal polygon
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
if( i == MAX_SIDE_VERTS )
|
||||
{
|
||||
MsgDev( D_ERROR, "BuildSurfMesh: poly %i exceeded %i vertexes!\n", surf - loadmodel->surfaces, MAX_SIDE_VERTS );
|
||||
break; // too big polygon ?
|
||||
}
|
||||
|
||||
e = loadmodel->surfedges[surf->firstedge + i];
|
||||
if( e > 0 ) v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
|
||||
else v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
|
||||
VectorCopy( v->position, verts[i] );
|
||||
}
|
||||
|
||||
// subdivide water or sky sphere for Quake1 maps
|
||||
if( surf->flags & SURF_DRAWTURB && !( surf->flags & SURF_REFLECT ))
|
||||
{
|
||||
Mod_SubdividePolygon( info, surf, surf->numedges, verts[0], 64.0f );
|
||||
Mod_ConvertSurface( info, surf );
|
||||
}
|
||||
else
|
||||
{
|
||||
Mod_BuildPolygon( info, surf, surf->numedges, verts[0] );
|
||||
}
|
||||
|
||||
if( info->mesh ) return; // all done
|
||||
|
||||
if( surf->texinfo && surf->texinfo->texture )
|
||||
texname = surf->texinfo->texture->name;
|
||||
else texname = "notexture";
|
||||
|
||||
MsgDev( D_ERROR, "BuildSurfMesh: surface %i (%s) failed to build surfmesh\n", surf - loadmodel->surfaces, texname );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_TesselatePolygon
|
||||
|
||||
tesselate specified polygon
|
||||
by user request
|
||||
=================
|
||||
*/
|
||||
void Mod_TesselatePolygon( msurface_t *surf, model_t *mod, float tessSize )
|
||||
{
|
||||
mextrasurf_t *info;
|
||||
model_t *old = loadmodel;
|
||||
vec3_t verts[MAX_SIDE_VERTS];
|
||||
char *texname;
|
||||
int i, e;
|
||||
mvertex_t *v;
|
||||
|
||||
if( !surf || !mod ) return; // bad arguments?
|
||||
|
||||
tessSize = bound( 8.0f, tessSize, 256.0f );
|
||||
info = SURF_INFO( surf, mod );
|
||||
loadmodel = mod;
|
||||
|
||||
// release old mesh
|
||||
if( info->mesh )
|
||||
{
|
||||
Mem_Free( info->mesh );
|
||||
info->mesh = NULL;
|
||||
}
|
||||
|
||||
// convert edges back to a normal polygon
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
if( i == MAX_SIDE_VERTS )
|
||||
{
|
||||
MsgDev( D_ERROR, "BuildSurfMesh: poly %i exceeded %i vertexes!\n", surf - loadmodel->surfaces, MAX_SIDE_VERTS );
|
||||
break; // too big polygon ?
|
||||
}
|
||||
|
||||
e = loadmodel->surfedges[surf->firstedge + i];
|
||||
if( e > 0 ) v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
|
||||
else v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
|
||||
VectorCopy( v->position, verts[i] );
|
||||
}
|
||||
|
||||
Mod_SubdividePolygon( info, surf, surf->numedges, verts[0], tessSize );
|
||||
Mod_ConvertSurface( info, surf );
|
||||
|
||||
// restore loadmodel value
|
||||
loadmodel = old;
|
||||
|
||||
if( info->mesh ) return; // all done
|
||||
|
||||
if( surf->texinfo && surf->texinfo->texture )
|
||||
texname = surf->texinfo->texture->name;
|
||||
else texname = "notexture";
|
||||
|
||||
MsgDev( D_ERROR, "BuildSurfMesh: surface %i (%s) failed to build surfmesh\n", surf - loadmodel->surfaces, texname );
|
||||
VectorAverage( surf->info->mins, surf->info->maxs, surf->info->origin );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1918,15 +1422,17 @@ static void Mod_LoadSurfaces( const dlump_t *l )
|
|||
count = l->filelen / sizeof( *in );
|
||||
|
||||
loadmodel->numsurfaces = count;
|
||||
loadmodel->surfaces = Mem_Alloc( loadmodel->mempool, count * sizeof( msurface_t ));
|
||||
loadmodel->cache.data = Mem_Alloc( loadmodel->mempool, count * sizeof( mextrasurf_t ));
|
||||
out = loadmodel->surfaces;
|
||||
info = loadmodel->cache.data;
|
||||
loadmodel->surfaces = out = Mem_Alloc( loadmodel->mempool, count * sizeof( msurface_t ));
|
||||
info = Mem_Alloc( loadmodel->mempool, count * sizeof( mextrasurf_t ));
|
||||
|
||||
for( i = 0; i < count; i++, in++, out++, info++ )
|
||||
{
|
||||
texture_t *tex;
|
||||
|
||||
// setup crosslinks between two parts of msurface_t
|
||||
out->info = info;
|
||||
info->surf = out;
|
||||
|
||||
if(( in->firstedge + in->numedges ) > loadmodel->numsurfedges )
|
||||
{
|
||||
MsgDev( D_ERROR, "Bad surface %i from %i\n", i, count );
|
||||
|
@ -1947,12 +1453,7 @@ static void Mod_LoadSurfaces( const dlump_t *l )
|
|||
out->flags |= (SURF_DRAWTILED|SURF_DRAWSKY);
|
||||
|
||||
if(( tex->name[0] == '*' && Q_stricmp( tex->name, "*default" )) || tex->name[0] == '!' )
|
||||
{
|
||||
out->flags |= (SURF_DRAWTURB|SURF_DRAWTILED);
|
||||
|
||||
if( !( host.features & ENGINE_BUILD_SURFMESHES ))
|
||||
out->flags |= SURF_NOCULL;
|
||||
}
|
||||
out->flags |= (SURF_DRAWTURB|SURF_DRAWTILED|SURF_NOCULL);
|
||||
|
||||
if( !Q_strncmp( tex->name, "water", 5 ) || !Q_strnicmp( tex->name, "laser", 5 ))
|
||||
out->flags |= (SURF_DRAWTURB|SURF_DRAWTILED|SURF_NOCULL);
|
||||
|
@ -1978,7 +1479,7 @@ static void Mod_LoadSurfaces( const dlump_t *l )
|
|||
if( out->texinfo->flags & TEX_SPECIAL )
|
||||
out->flags |= SURF_DRAWTILED;
|
||||
|
||||
Mod_CalcSurfaceBounds( out, info );
|
||||
Mod_CalcSurfaceBounds( out );
|
||||
Mod_CalcSurfaceExtents( out );
|
||||
|
||||
if( loadmodel->lightdata && in->lightofs != -1 )
|
||||
|
@ -1989,16 +1490,12 @@ static void Mod_LoadSurfaces( const dlump_t *l )
|
|||
|
||||
// if deluxemap is present setup it too
|
||||
if( world.deluxedata )
|
||||
info->deluxemap = world.deluxedata + (in->lightofs / 3);
|
||||
out->info->deluxemap = world.deluxedata + (in->lightofs / 3);
|
||||
}
|
||||
|
||||
for( j = 0; j < MAXLIGHTMAPS; j++ )
|
||||
out->styles[j] = in->styles[j];
|
||||
|
||||
// build polygons for non-lightmapped surfaces
|
||||
if( host.features & ENGINE_BUILD_SURFMESHES && (( out->flags & SURF_DRAWTILED ) || !out->samples ))
|
||||
Mod_BuildSurfacePolygons( out, info );
|
||||
|
||||
if( out->flags & SURF_DRAWTURB )
|
||||
GL_SubdivideSurface( out ); // cut up polygon for warps
|
||||
}
|
||||
|
@ -2813,7 +2310,6 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
|
|||
for( j = 0; i != 0 && j < mod->nummodelsurfaces; j++ )
|
||||
{
|
||||
msurface_t *surf = mod->surfaces + mod->firstmodelsurface + j;
|
||||
mextrasurf_t *info = SURF_INFO( surf, mod );
|
||||
|
||||
if( surf->flags & SURF_CONVEYOR )
|
||||
mod->flags |= MODEL_CONVEYOR;
|
||||
|
@ -2826,7 +2322,7 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
|
|||
if( surf->plane->type == PLANE_Z )
|
||||
{
|
||||
// kill bottom plane too
|
||||
if( info->mins[2] == bm->mins[2] + 1.0f )
|
||||
if( surf->info->mins[2] == bm->mins[2] + 1.0f )
|
||||
surf->flags |= SURF_WATERCSG;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -148,7 +148,7 @@ GNU General Public License for more details.
|
|||
#define FDECAL_DONTSAVE 0x04 // Decal was loaded from adjacent level, don't save it for this level
|
||||
// reserved 0x08
|
||||
// reserved 0x10
|
||||
#define FDECAL_USESAXIS 0x20 // Uses the s axis field to determine orientation (footprints)
|
||||
// reserved 0x20
|
||||
#define FDECAL_STUDIO 0x40 // Indicates a studio decal
|
||||
#define FDECAL_LOCAL_SPACE 0x80 // decal is in local space (any decal after serialization)
|
||||
|
||||
|
|
|
@ -478,7 +478,7 @@ void Sys_InitLog( void )
|
|||
{
|
||||
const char *mode;
|
||||
|
||||
if( host.change_game )
|
||||
if( host.change_game && host.type != HOST_DEDICATED )
|
||||
mode = "a";
|
||||
else mode = "w";
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ Sys_ParseCommandLine
|
|||
|
||||
==================
|
||||
*/
|
||||
void Sys_ParseCommandLine( LPSTR lpCmdLine )
|
||||
void Sys_ParseCommandLine( LPSTR lpCmdLine, qboolean uncensored )
|
||||
{
|
||||
const char *blank = "censored";
|
||||
static char commandline[MAX_SYSPATH];
|
||||
|
@ -208,7 +208,8 @@ void Sys_ParseCommandLine( LPSTR lpCmdLine )
|
|||
}
|
||||
}
|
||||
|
||||
if( !host.change_game ) return;
|
||||
if( uncensored || !host.change_game )
|
||||
return;
|
||||
|
||||
for( i = 0; i < host.argc; i++ )
|
||||
{
|
||||
|
@ -233,16 +234,42 @@ Sys_MergeCommandLine
|
|||
*/
|
||||
void Sys_MergeCommandLine( LPSTR lpCmdLine )
|
||||
{
|
||||
const char *blank = "censored";
|
||||
int i;
|
||||
static char commandline[MAX_SYSPATH];
|
||||
|
||||
if( !host.change_game ) return;
|
||||
|
||||
for( i = 0; i < host.argc; i++ )
|
||||
Q_strncpy( commandline, lpCmdLine, Q_strlen( lpCmdLine ) + 1 );
|
||||
lpCmdLine = commandline; // to prevent modify original commandline
|
||||
|
||||
while( *lpCmdLine && ( host.argc < MAX_NUM_ARGVS ))
|
||||
{
|
||||
// second call
|
||||
if( host.type == HOST_DEDICATED && !Q_strnicmp( "+menu_", host.argv[i], 6 ))
|
||||
host.argv[i] = (char *)blank;
|
||||
while( *lpCmdLine && *lpCmdLine <= ' ' )
|
||||
lpCmdLine++;
|
||||
if( !*lpCmdLine ) break;
|
||||
|
||||
if( *lpCmdLine == '\"' )
|
||||
{
|
||||
// quoted string
|
||||
lpCmdLine++;
|
||||
host.argv[host.argc] = lpCmdLine;
|
||||
host.argc++;
|
||||
while( *lpCmdLine && ( *lpCmdLine != '\"' ))
|
||||
lpCmdLine++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unquoted word
|
||||
host.argv[host.argc] = lpCmdLine;
|
||||
host.argc++;
|
||||
while( *lpCmdLine && *lpCmdLine > ' ')
|
||||
lpCmdLine++;
|
||||
}
|
||||
|
||||
if( *lpCmdLine )
|
||||
{
|
||||
*lpCmdLine = 0;
|
||||
lpCmdLine++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ void Sys_Error( const char *error, ... );
|
|||
qboolean Sys_LoadLibrary( dll_info_t *dll );
|
||||
void* Sys_GetProcAddress( dll_info_t *dll, const char* name );
|
||||
qboolean Sys_FreeLibrary( dll_info_t *dll );
|
||||
void Sys_ParseCommandLine( LPSTR lpCmdLine );
|
||||
void Sys_ParseCommandLine( LPSTR lpCmdLine, qboolean uncensored );
|
||||
void Sys_MergeCommandLine( LPSTR lpCmdLine );
|
||||
long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo );
|
||||
void Sys_SetClipboardData( const byte *buffer, size_t size );
|
||||
|
|
|
@ -323,6 +323,7 @@ typedef struct
|
|||
int gmsgHudText; // -1 if not catched (e.g. mod not registered this message)
|
||||
|
||||
void *hInstance; // pointer to game.dll
|
||||
qboolean config_executed; // should to execute config.cfg once time to restore FCVAR_ARCHIVE that specified in hl.dll
|
||||
|
||||
union
|
||||
{
|
||||
|
|
|
@ -2301,6 +2301,27 @@ void pfnServerCommand( const char* str )
|
|||
else MsgDev( D_ERROR, "bad server command %s\n", str );
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
pfnServerExecute
|
||||
|
||||
=========
|
||||
*/
|
||||
void pfnServerExecute( void )
|
||||
{
|
||||
Cbuf_Execute();
|
||||
|
||||
if( svgame.config_executed )
|
||||
return;
|
||||
|
||||
// here we restore arhcived cvars only from game.dll
|
||||
host.apply_game_config = true;
|
||||
Cbuf_AddText( "exec config.cfg\n" );
|
||||
Cbuf_Execute();
|
||||
host.apply_game_config = false;
|
||||
svgame.config_executed = true;
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
pfnClientCommand
|
||||
|
@ -4418,7 +4439,7 @@ static enginefuncs_t gEngfuncs =
|
|||
pfnTraceSphere,
|
||||
pfnGetAimVector,
|
||||
pfnServerCommand,
|
||||
Cbuf_Execute,
|
||||
pfnServerExecute,
|
||||
pfnClientCommand,
|
||||
pfnParticleEffect,
|
||||
pfnLightStyle,
|
||||
|
|
|
@ -31,7 +31,7 @@ CVAR_DEFINE_AUTO( rcon_password, "", 0, "remote connect password" );
|
|||
CVAR_DEFINE_AUTO( sv_filterban, "1", 0, "filter banned users" );
|
||||
CVAR_DEFINE_AUTO( sv_cheats, "0", FCVAR_SERVER, "allow cheats on server" );
|
||||
CVAR_DEFINE_AUTO( sv_instancedbaseline, "1", 0, "allow to use instanced baselines to saves network overhead" );
|
||||
CVAR_DEFINE_AUTO( sv_contact, "1", FCVAR_ARCHIVE|FCVAR_SERVER, "server techincal support contact address or web-page" );
|
||||
CVAR_DEFINE_AUTO( sv_contact, "", FCVAR_ARCHIVE|FCVAR_SERVER, "server techincal support contact address or web-page" );
|
||||
CVAR_DEFINE_AUTO( sv_minupdaterate, "10.0", FCVAR_ARCHIVE, "minimal value for 'cl_updaterate' window" );
|
||||
CVAR_DEFINE_AUTO( sv_maxupdaterate, "30.0", FCVAR_ARCHIVE, "maximal value for 'cl_updaterate' window" );
|
||||
CVAR_DEFINE_AUTO( sv_minrate, "0", FCVAR_SERVER, "min bandwidth rate allowed on server, 0 == unlimited" );
|
||||
|
@ -698,7 +698,6 @@ void SV_Init( void )
|
|||
SV_InitHostCommands();
|
||||
|
||||
Cvar_Get ("protocol", va( "%i", PROTOCOL_VERSION ), FCVAR_READ_ONLY, "displays server protocol version" );
|
||||
Cvar_Get ("defaultmap", "", FCVAR_SERVER, "holds the multiplayer mapname" );
|
||||
Cvar_Get ("suitvolume", "0.25", FCVAR_ARCHIVE, "HEV suit volume" );
|
||||
Cvar_Get ("sv_background", "0", FCVAR_READ_ONLY, "indicate what background map is running" );
|
||||
Cvar_Get( "gamedir", GI->gamefolder, FCVAR_SERVER|FCVAR_READ_ONLY, "game folder" );
|
||||
|
@ -760,9 +759,9 @@ void SV_Init( void )
|
|||
Cvar_RegisterVariable (&sv_friction);
|
||||
Cvar_RegisterVariable (&sv_edgefriction);
|
||||
Cvar_RegisterVariable (&sv_stopspeed);
|
||||
sv_maxclients = Cvar_Get( "maxplayers", "1", FCVAR_LATCH|FCVAR_SERVER|FCVAR_UNLOGGED, "server max capacity" );
|
||||
sv_maxclients = Cvar_Get( "maxplayers", "1", FCVAR_LATCH, "server max capacity" );
|
||||
sv_check_errors = Cvar_Get( "sv_check_errors", "0", FCVAR_ARCHIVE, "check edicts for errors" );
|
||||
public_server = Cvar_Get ("public", "0", FCVAR_SERVER, "change server type from private to public" );
|
||||
public_server = Cvar_Get ("public", "0", 0, "change server type from private to public" );
|
||||
sv_lighting_modulate = Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "lightstyles modulate scale" );
|
||||
sv_reconnect_limit = Cvar_Get ("sv_reconnect_limit", "3", FCVAR_ARCHIVE, "max reconnect attempts" );
|
||||
Cvar_RegisterVariable (&sv_failuretime );
|
||||
|
|
|
@ -1067,6 +1067,7 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
|
|||
soundlist_t soundInfo[MAX_CHANNELS];
|
||||
string curtrack, looptrack;
|
||||
int soundCount = 0;
|
||||
byte decalFlags;
|
||||
|
||||
Q_snprintf( name, sizeof( name ), "save/%s.HL2", level );
|
||||
|
||||
|
@ -1110,12 +1111,13 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
|
|||
|
||||
nameSize = Q_strlen( entry->name ) + 1;
|
||||
decalScale = (entry->scale * 4096);
|
||||
decalFlags = entry->flags;
|
||||
|
||||
FS_Write( pFile, localPos, sizeof( localPos ));
|
||||
FS_Write( pFile, &nameSize, sizeof( nameSize ));
|
||||
FS_Write( pFile, entry->name, nameSize );
|
||||
FS_Write( pFile, &entry->entityIndex, sizeof( entry->entityIndex ));
|
||||
FS_Write( pFile, &entry->flags, sizeof( entry->flags ));
|
||||
FS_Write( pFile, &decalFlags, sizeof( decalFlags ));
|
||||
FS_Write( pFile, &decalScale, sizeof( decalScale ));
|
||||
FS_Write( pFile, entry->impactPlaneNormal, sizeof( entry->impactPlaneNormal ));
|
||||
|
||||
|
@ -1238,6 +1240,7 @@ void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboolean
|
|||
ClientSections_t sections;
|
||||
soundlist_t soundInfo[MAX_CHANNELS];
|
||||
int soundCount;
|
||||
byte decalFlags;
|
||||
|
||||
Q_snprintf( name, sizeof( name ), "save/%s.HL2", level );
|
||||
|
||||
|
@ -1286,7 +1289,7 @@ void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboolean
|
|||
FS_Read( pFile, &nameSize, sizeof( nameSize ));
|
||||
FS_Read( pFile, entry->name, nameSize );
|
||||
FS_Read( pFile, &entry->entityIndex, sizeof( entry->entityIndex ));
|
||||
FS_Read( pFile, &entry->flags, sizeof( entry->flags ));
|
||||
FS_Read( pFile, &decalFlags, sizeof( decalFlags ));
|
||||
FS_Read( pFile, &decalScale, sizeof( decalScale ));
|
||||
FS_Read( pFile, entry->impactPlaneNormal, sizeof( entry->impactPlaneNormal ));
|
||||
|
||||
|
@ -1295,6 +1298,7 @@ void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboolean
|
|||
else VectorCopy( localPos, entry->position );
|
||||
|
||||
entry->scale = ((float)decalScale / 4096.0f);
|
||||
entry->flags = decalFlags;
|
||||
|
||||
if( entry->flags & FDECAL_STUDIO )
|
||||
{
|
||||
|
|
|
@ -26,13 +26,19 @@ SPRITE MODELS
|
|||
*/
|
||||
|
||||
#define IDSPRITEHEADER (('P'<<24)+('S'<<16)+('D'<<8)+'I') // little-endian "IDSP"
|
||||
#define SPRITE_VERSION 2 // Half-Life sprites
|
||||
|
||||
#define SPRITE_VERSION_Q1 1 // Quake sprites
|
||||
#define SPRITE_VERSION_HL 2 // Half-Life sprites
|
||||
|
||||
// must match definition in alias.h
|
||||
#ifndef SYNCTYPE_T
|
||||
#define SYNCTYPE_T
|
||||
typedef enum
|
||||
{
|
||||
ST_SYNC = 0,
|
||||
ST_RAND
|
||||
} synctype_t;
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -64,6 +70,25 @@ typedef enum
|
|||
SPR_CULL_NONE, // oriented sprite will be draw back face too
|
||||
} facetype_t;
|
||||
|
||||
// generic helper
|
||||
typedef struct
|
||||
{
|
||||
int ident; // LittleLong 'ISPR'
|
||||
int version; // current version 2
|
||||
} dsprite_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ident; // LittleLong 'ISPR'
|
||||
int version; // current version 2
|
||||
int type; // camera align
|
||||
float boundingradius; // quick face culling
|
||||
int bounds[2]; // mins\maxs
|
||||
int numframes; // including groups
|
||||
float beamlength; // ???
|
||||
synctype_t synctype; // animation synctype
|
||||
} dsprite_q1_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ident; // LittleLong 'ISPR'
|
||||
|
@ -75,7 +100,7 @@ typedef struct
|
|||
int numframes; // including groups
|
||||
facetype_t facetype; // cullface (Xash3D ext)
|
||||
synctype_t synctype; // animation synctype
|
||||
} dsprite_t;
|
||||
} dsprite_hl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
|
@ -70,7 +70,7 @@ UI_Audio_GetConfig
|
|||
static void UI_Audio_GetConfig( void )
|
||||
{
|
||||
uiAudio.soundVolume.curValue = CVAR_GET_FLOAT( "volume" );
|
||||
uiAudio.musicVolume.curValue = CVAR_GET_FLOAT( "musicvolume" );
|
||||
uiAudio.musicVolume.curValue = CVAR_GET_FLOAT( "MP3Volume" );
|
||||
uiAudio.suitVolume.curValue = CVAR_GET_FLOAT( "suitvolume" );
|
||||
|
||||
if( CVAR_GET_FLOAT( "s_lerping" ))
|
||||
|
@ -93,7 +93,7 @@ UI_Audio_SetConfig
|
|||
static void UI_Audio_SetConfig( void )
|
||||
{
|
||||
CVAR_SET_FLOAT( "volume", uiAudio.soundVolume.curValue );
|
||||
CVAR_SET_FLOAT( "musicvolume", uiAudio.musicVolume.curValue );
|
||||
CVAR_SET_FLOAT( "MP3Volume", uiAudio.musicVolume.curValue );
|
||||
CVAR_SET_FLOAT( "suitvolume", uiAudio.suitVolume.curValue );
|
||||
CVAR_SET_FLOAT( "s_lerping", uiAudio.lerping.enabled );
|
||||
CVAR_SET_FLOAT( "dsp_off", uiAudio.noDSP.enabled );
|
||||
|
@ -107,7 +107,7 @@ UI_Audio_UpdateConfig
|
|||
static void UI_Audio_UpdateConfig( void )
|
||||
{
|
||||
CVAR_SET_FLOAT( "volume", uiAudio.soundVolume.curValue );
|
||||
CVAR_SET_FLOAT( "musicvolume", uiAudio.musicVolume.curValue );
|
||||
CVAR_SET_FLOAT( "MP3Volume", uiAudio.musicVolume.curValue );
|
||||
CVAR_SET_FLOAT( "suitvolume", uiAudio.suitVolume.curValue );
|
||||
CVAR_SET_FLOAT( "s_lerping", uiAudio.lerping.enabled );
|
||||
CVAR_SET_FLOAT( "dsp_off", uiAudio.noDSP.enabled );
|
||||
|
|
|
@ -36,8 +36,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define ID_MAXCLIENTS 7
|
||||
#define ID_HOSTNAME 8
|
||||
#define ID_PASSWORD 9
|
||||
#define ID_HLTV 10
|
||||
#define ID_DEDICATED 11
|
||||
#define ID_DEDICATED 10
|
||||
|
||||
#define ID_MSGBOX 12
|
||||
#define ID_MSGTEXT 13
|
||||
|
@ -64,7 +63,6 @@ typedef struct
|
|||
menuField_s maxClients;
|
||||
menuField_s hostName;
|
||||
menuField_s password;
|
||||
menuCheckBox_s hltv;
|
||||
menuCheckBox_s dedicatedServer;
|
||||
|
||||
// newgame prompt dialog
|
||||
|
@ -88,35 +86,35 @@ UI_CreateGame_Begin
|
|||
*/
|
||||
static void UI_CreateGame_Begin( void )
|
||||
{
|
||||
if( !MAP_IS_VALID( uiCreateGame.mapName[uiCreateGame.mapsList.curItem] ))
|
||||
char *pMapName = uiCreateGame.mapName[uiCreateGame.mapsList.curItem];
|
||||
int maxPlayers = atoi( uiCreateGame.maxClients.buffer );
|
||||
|
||||
if( !MAP_IS_VALID( pMapName ))
|
||||
return; // bad map
|
||||
|
||||
CVAR_SET_STRING( "hostname", uiCreateGame.hostName.buffer );
|
||||
HOST_WRITECONFIG ( "game.cfg" );
|
||||
|
||||
if( CVAR_GET_FLOAT( "host_serverstate" ) && CVAR_GET_FLOAT( "maxplayers" ) == 1 )
|
||||
HOST_ENDGAME( "end of the game" );
|
||||
|
||||
CVAR_SET_FLOAT( "deathmatch", 1.0f ); // start deathmatch as default
|
||||
CVAR_SET_FLOAT( "maxplayers", atoi( uiCreateGame.maxClients.buffer ));
|
||||
CVAR_SET_STRING( "hostname", uiCreateGame.hostName.buffer );
|
||||
CVAR_SET_STRING( "defaultmap", uiCreateGame.mapName[uiCreateGame.mapsList.curItem] );
|
||||
CVAR_SET_FLOAT( "hltv", uiCreateGame.hltv.enabled );
|
||||
|
||||
BACKGROUND_TRACK( NULL, NULL );
|
||||
HOST_WRITECONFIG ( "settings.rc" );
|
||||
CVAR_SET_FLOAT( "deathmatch", 1.0f ); // start deathmatch as default
|
||||
CVAR_SET_FLOAT( "maxplayers", maxPlayers );
|
||||
BACKGROUND_TRACK ( NULL, NULL );
|
||||
|
||||
// all done, start server
|
||||
if( uiCreateGame.dedicatedServer.enabled )
|
||||
{
|
||||
char cmd[128];
|
||||
sprintf( cmd, "#%s", gMenu.m_gameinfo.gamefolder );
|
||||
char cmd[128], msg[128];
|
||||
sprintf( cmd, "#%s +maxplayers %i +map %s", gMenu.m_gameinfo.gamefolder, maxPlayers, pMapName );
|
||||
sprintf( msg, "startup dedicated server from '%s'", gMenu.m_gameinfo.gamefolder );
|
||||
|
||||
// NOTE: dedicated server will be executed "defaultmap"
|
||||
// from engine after restarting
|
||||
HOST_CHANGEGAME( cmd, "Starting dedicated server...\n" );
|
||||
HOST_CHANGEGAME( cmd, msg );
|
||||
}
|
||||
else
|
||||
{
|
||||
char cmd[128];
|
||||
sprintf( cmd, "exec %s\nmap %s\n", "settings.rc", CVAR_GET_STRING( "defaultmap" ));
|
||||
sprintf( cmd, "map %s\n", pMapName );
|
||||
|
||||
CLIENT_COMMAND( FALSE, cmd );
|
||||
}
|
||||
|
@ -139,7 +137,6 @@ static void UI_PromptDialog( void )
|
|||
uiCreateGame.hostName.generic.flags ^= QMF_INACTIVE;
|
||||
uiCreateGame.password.generic.flags ^= QMF_INACTIVE;
|
||||
uiCreateGame.dedicatedServer.generic.flags ^= QMF_INACTIVE;
|
||||
uiCreateGame.hltv.generic.flags ^= QMF_INACTIVE;
|
||||
uiCreateGame.mapsList.generic.flags ^= QMF_INACTIVE;
|
||||
|
||||
uiCreateGame.msgBox.generic.flags ^= QMF_HIDDEN;
|
||||
|
@ -229,7 +226,6 @@ static void UI_CreateGame_Callback( void *self, int event )
|
|||
|
||||
switch( item->id )
|
||||
{
|
||||
case ID_HLTV:
|
||||
case ID_DEDICATED:
|
||||
if( event == QM_PRESSED )
|
||||
((menuCheckBox_s *)self)->focusPic = UI_CHECKBOX_PRESSED;
|
||||
|
@ -337,15 +333,6 @@ static void UI_CreateGame_Init( void )
|
|||
uiCreateGame.dedicatedServer.generic.callback = UI_CreateGame_Callback;
|
||||
uiCreateGame.dedicatedServer.generic.statusText = "faster, but you can't join the server from this machine";
|
||||
|
||||
uiCreateGame.hltv.generic.id = ID_HLTV;
|
||||
uiCreateGame.hltv.generic.type = QMTYPE_CHECKBOX;
|
||||
uiCreateGame.hltv.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW;
|
||||
uiCreateGame.hltv.generic.name = "HLTV";
|
||||
uiCreateGame.hltv.generic.x = 72;
|
||||
uiCreateGame.hltv.generic.y = 635;
|
||||
uiCreateGame.hltv.generic.callback = UI_CreateGame_Callback;
|
||||
uiCreateGame.hltv.generic.statusText = "enable hltv mode in multiplayer";
|
||||
|
||||
uiCreateGame.hintMessage.generic.id = ID_TABLEHINT;
|
||||
uiCreateGame.hintMessage.generic.type = QMTYPE_ACTION;
|
||||
uiCreateGame.hintMessage.generic.flags = QMF_INACTIVE|QMF_SMALLFONT;
|
||||
|
@ -454,7 +441,6 @@ static void UI_CreateGame_Init( void )
|
|||
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.hostName );
|
||||
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.password );
|
||||
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.dedicatedServer );
|
||||
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.hltv );
|
||||
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.hintMessage );
|
||||
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.mapsList );
|
||||
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.msgBox );
|
||||
|
|
Reference in New Issue