diff --git a/change.log b/change.log index 3823f996..dd8e7164 100644 --- a/change.log +++ b/change.log @@ -1,3 +1,13 @@ +build 2402 + +Engine: added new feature flag for compensate stupid quake bug +Client: update the render interface, added usefully function GL_TextureTarget +Render: get support for GL_RECTANGLE textures +Client: fix playerangles in event receive (Paranoia bug with decals) +Render: fixed mipmap generation for normalmaps (TF_NORMALMAP) +Render: added two built-in textures: *blankbump and *whiteCube (self-explanatory names) +Engine: made better check for Half-Life alpha maps (version 29 with colored lighting) + build 2271 Client: fix message TE_GLOWSPRITE. The gaussgun in Xash Mod is properly worked now. diff --git a/common/features.h b/common/features.h index 14fd4cfa..39e8fa46 100644 --- a/common/features.h +++ b/common/features.h @@ -22,5 +22,6 @@ GNU General Public License for more details. #define ENGINE_BUILD_STVECTORS (1<<2) // build ST-vectors for surfmeshes. ENGINE_BUILD_SURFMESHES must be set! #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 +#define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed #endif//FEATURES_H \ No newline at end of file diff --git a/common/render_api.h b/common/render_api.h index 31918134..802de9a0 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -46,6 +46,7 @@ GNU General Public License for more details. #define PARM_TEX_TEXNUM 18 #define PARM_TEX_FLAGS 19 #define PARM_FEATURES 20 // same as movevars->features +#define PARM_ACTIVE_TMU 21 // for debug enum { @@ -82,6 +83,7 @@ typedef enum TF_BORDER = (1<<19), TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D TF_FLOAT = (1<<21), // use GL_FLOAT instead of GL_UNSIGNED_BYTE + TF_TEXTURE_RECTANGLE= (1<<22), // this is GL_TEXTURE_RECTANGLE } texFlags_t; typedef struct beam_s BEAM; @@ -169,6 +171,9 @@ typedef struct render_api_s // ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 26 void (*R_EntityRemoveDecals)( struct model_s *mod ); // remove all the decals from specified entity (BSP only) float *(*R_DecalSetupVerts)( struct decal_s *pDecal, struct msurface_s *surf, int texture, int *outCount ); + void (*R_StoreEfragsExt)( struct efrag_s **ppefrag, int framecount ); // store efrags for static entities + void (*GL_TextureTarget)( unsigned int target ); // change texture unit mode without bind texture + struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e ); // moved here to avoid incompatibility with IEngineStudio official iface } render_api_t; // render callbacks diff --git a/engine/client/cl_events.c b/engine/client/cl_events.c index 22ca81ec..f8a0bed4 100644 --- a/engine/client/cl_events.c +++ b/engine/client/cl_events.c @@ -373,8 +373,19 @@ void CL_ParseEvent( sizebuf_t *msg ) { if(( args.entindex - 1 ) == cl.playernum ) { - // get the predicted angles - VectorCopy( cl.refdef.cl_viewangles, args.angles ); + if( state && !CL_IsPredicted( )) + { + // restore viewangles from angles + args.angles[PITCH] = -state->angles[PITCH] * 3; + args.angles[YAW] = state->angles[YAW]; + args.angles[ROLL] = 0; // no roll + } + else + { + // get the predicted angles + VectorCopy( cl.refdef.cl_viewangles, args.angles ); + } + VectorCopy( cl.frame.local.client.origin, args.origin ); VectorCopy( cl.frame.local.client.velocity, args.velocity ); } diff --git a/engine/client/gl_backend.c b/engine/client/gl_backend.c index 4ede61b7..4b613151 100644 --- a/engine/client/gl_backend.c +++ b/engine/client/gl_backend.c @@ -234,6 +234,29 @@ void GL_MultiTexCoord2f( GLenum texture, GLfloat s, GLfloat t ) } } +/* +================= +GL_TextureTarget +================= +*/ +void GL_TextureTarget( uint target ) +{ + if( glState.activeTMU < 0 || glState.activeTMU >= glConfig.max_texture_units ) + { + MsgDev( D_ERROR, "GL_TextureTarget: bad tmu state %i\n", glState.activeTMU ); + return; + } + + if( glState.currentTextureTargets[glState.activeTMU] != target ) + { + if( glState.currentTextureTargets[glState.activeTMU] != GL_NONE ) + pglDisable( glState.currentTextureTargets[glState.activeTMU] ); + glState.currentTextureTargets[glState.activeTMU] = target; + if( target != GL_NONE ) + pglEnable( glState.currentTextureTargets[glState.activeTMU] ); + } +} + /* ================= GL_TexGen @@ -635,11 +658,17 @@ rebuild_page: pglBegin( GL_QUADS ); pglTexCoord2f( 0, 0 ); pglVertex2f( x, y ); - pglTexCoord2f( 1, 0 ); + if( image->flags & TF_TEXTURE_RECTANGLE ) + pglTexCoord2f( image->width, 0 ); + else pglTexCoord2f( 1, 0 ); pglVertex2f( x + w, y ); - pglTexCoord2f( 1, 1 ); + if( image->flags & TF_TEXTURE_RECTANGLE ) + pglTexCoord2f( image->width, image->height ); + else pglTexCoord2f( 1, 1 ); pglVertex2f( x + w, y + h ); - pglTexCoord2f( 0, 1 ); + if( image->flags & TF_TEXTURE_RECTANGLE ) + pglTexCoord2f( 0, image->height ); + else pglTexCoord2f( 0, 1 ); pglVertex2f( x, y + h ); pglEnd(); diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 972e80d5..725f5dd6 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -54,6 +54,8 @@ const char *GL_Target( GLenum target ) return "3D"; case GL_TEXTURE_CUBE_MAP_ARB: return "Cube"; + case GL_TEXTURE_RECTANGLE_EXT: + return "Rect"; } return "??"; } @@ -439,6 +441,9 @@ void R_TextureList_f( void ) case GL_TEXTURE_CUBE_MAP_ARB: Msg( "CUBE " ); break; + case GL_TEXTURE_RECTANGLE_EXT: + Msg( "RECT " ); + break; default: Msg( "???? " ); break; @@ -520,10 +525,21 @@ void GL_RoundImageDimensions( word *width, word *height, texFlags_t flags, qbool } else { - while( scaledWidth > glConfig.max_2d_texture_size || scaledHeight > glConfig.max_2d_texture_size ) + if( flags & TF_TEXTURE_RECTANGLE ) { - scaledWidth >>= 1; - scaledHeight >>= 1; + while( scaledWidth > glConfig.max_2d_rectangle_size || scaledHeight > glConfig.max_2d_rectangle_size ) + { + scaledWidth >>= 1; + scaledHeight >>= 1; + } + } + else + { + while( scaledWidth > glConfig.max_2d_texture_size || scaledHeight > glConfig.max_2d_texture_size ) + { + scaledWidth >>= 1; + scaledHeight >>= 1; + } } } @@ -958,7 +974,8 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag inFormat = GL_DEPTH_COMPONENT; dataType = GL_UNSIGNED_BYTE; } - else if( pic->flags & IMAGE_CUBEMAP ) + + if( pic->flags & IMAGE_CUBEMAP ) { if( GL_Support( GL_TEXTURECUBEMAP_EXT )) { @@ -984,6 +1001,12 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag // determine target tex->target = glTarget = GL_TEXTURE_1D; } + else if( tex->flags & TF_TEXTURE_RECTANGLE ) + { + if( glConfig.max_2d_rectangle_size ) + tex->target = glTarget = glConfig.texRectangle; + // or leave as GL_TEXTURE_2D + } else if( tex->flags & TF_TEXTURE_3D ) { // determine target @@ -1051,10 +1074,12 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag } else { - if( GL_Support( GL_SGIS_MIPMAPS_EXT )) GL_GenerateMipmaps( data, pic, tex, glTarget, inFormat, i, subImage ); + if( GL_Support( GL_SGIS_MIPMAPS_EXT ) && !( tex->flags & TF_NORMALMAP )) + GL_GenerateMipmaps( data, pic, tex, glTarget, inFormat, i, subImage ); if( subImage ) pglTexSubImage2D( tex->target, 0, 0, 0, tex->width, tex->height, inFormat, dataType, data ); else pglTexImage2D( tex->target, 0, outFormat, tex->width, tex->height, 0, inFormat, dataType, data ); - if( !GL_Support( GL_SGIS_MIPMAPS_EXT )) GL_GenerateMipmaps( data, pic, tex, glTarget, inFormat, i, subImage ); + if( !GL_Support( GL_SGIS_MIPMAPS_EXT ) || ( tex->flags & TF_NORMALMAP )) + GL_GenerateMipmaps( data, pic, tex, glTarget, inFormat, i, subImage ); } if( numSides > 1 ) buf += offset; @@ -1639,6 +1664,34 @@ static rgbdata_t *R_InitBlackTexture( texFlags_t *flags ) return R_InitSolidColorTexture( flags, 0 ); } +/* +================== +R_InitBlankBumpTexture +================== +*/ +static rgbdata_t *R_InitBlankBumpTexture( texFlags_t *flags ) +{ + int i; + + // default normalmap texture + for( i = 0; i < 256; i++ ) + { + data2D[i*4+0] = 127; + data2D[i*4+1] = 127; + data2D[i*4+2] = 255; + } + + *flags = TF_NORMALMAP|TF_UNCOMPRESSED; + + r_image.buffer = data2D; + r_image.width = r_image.height = 16; + r_image.size = r_image.width * r_image.height * 4; + r_image.flags = IMAGE_HAS_COLOR; + r_image.type = PF_RGBA_32; + + return &r_image; +} + /* ================== R_InitAttenuationTexture @@ -1923,6 +1976,33 @@ static rgbdata_t *R_InitGrayCubemap( texFlags_t *flags ) return &r_image; } +/* +================== +R_InitWhiteCubemap +================== +*/ +static rgbdata_t *R_InitWhiteCubemap( texFlags_t *flags ) +{ + int size = 4; + byte *dataCM = data2D; + + if( !GL_Support( GL_TEXTURECUBEMAP_EXT )) + return NULL; + + // white cubemap - just stub for pointlights + Q_memset( dataCM, 0xFF, size * size * 6 * 4 ); + + *flags = (TF_NOPICMIP|TF_NOMIPMAP|TF_UNCOMPRESSED|TF_CUBEMAP|TF_CLAMP); + + r_image.width = r_image.height = size; + r_image.size = r_image.width * r_image.height * 4 * 6; + r_image.flags |= (IMAGE_CUBEMAP|IMAGE_HAS_COLOR); // yes it's cubemap + r_image.buffer = data2D; + r_image.type = PF_RGBA_32; + + return &r_image; +} + /* ================== R_InitBuiltinTextures @@ -1956,8 +2036,10 @@ static void R_InitBuiltinTextures( void ) { "*atten3", &tr.attenuationTexture3, R_InitAttenuationTexture3, TEX_SYSTEM }, { "*attnno", &tr.attenuationStubTexture, R_InitAttenuationTextureNoAtten, TEX_SYSTEM }, { "*normalize", &tr.normalizeTexture, R_InitNormalizeCubemap, TEX_CUBEMAP }, + { "*blankbump", &tr.blankbumpTexture, R_InitBlankBumpTexture, TEX_SYSTEM }, { "*lightCube", &tr.dlightCubeTexture, R_InitDlightCubemap, TEX_CUBEMAP }, { "*grayCube", &tr.grayCubeTexture, R_InitGrayCubemap, TEX_CUBEMAP }, + { "*whiteCube", &tr.whiteCubeTexture, R_InitWhiteCubemap, TEX_CUBEMAP }, { "*atten3D", &tr.attenuationTexture3D, R_InitAttenTexture3D, TEX_SYSTEM }, { "*sky", &tr.skyTexture, R_InitSkyTexture, TEX_SYSTEM }, { NULL, NULL, NULL } diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index a331064c..c6ed4280 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -190,9 +190,11 @@ typedef struct int attenuationTexture3;// bright attenuation int attenuationTexture3D;// 3D attenuation int attenuationStubTexture; + int blankbumpTexture; int normalizeTexture; int dlightCubeTexture; // dynamic cubemap int grayCubeTexture; + int whiteCubeTexture; int skyboxTextures[6]; // skybox sides int mirrorTextures[MAX_MIRRORS]; int num_mirrors_used; // used mirror textures @@ -279,6 +281,7 @@ void GL_LoadIdentityTexMatrix( void ); void GL_DisableAllTexGens( void ); void GL_SetRenderMode( int mode ); void GL_FrontFace( GLenum front ); +void GL_TextureTarget( uint target ); void GL_Cull( GLenum cull ); void R_ShowTextures( void ); @@ -337,7 +340,7 @@ void R_FindMirrors( const ref_params_t *fd ); // // gl_refrag.c // -void R_StoreEfrags( efrag_t **ppefrag ); +void R_StoreEfrags( efrag_t **ppefrag, int framecount ); // // gl_rlight.c @@ -420,6 +423,7 @@ void R_DrawSpriteModel( cl_entity_t *e ); // void R_StudioInit( void ); void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded ); +struct mstudiotex_s *R_StudioGetTexture( cl_entity_t *e ); void R_DrawStudioModel( cl_entity_t *e ); // diff --git a/engine/client/gl_refrag.c b/engine/client/gl_refrag.c index 0f353e0c..c681e556 100644 --- a/engine/client/gl_refrag.c +++ b/engine/client/gl_refrag.c @@ -186,7 +186,7 @@ R_StoreEfrags ================ */ -void R_StoreEfrags( efrag_t **ppefrag ) +void R_StoreEfrags( efrag_t **ppefrag, int framecount ) { cl_entity_t *pent; model_t *clmodel; @@ -205,12 +205,12 @@ void R_StoreEfrags( efrag_t **ppefrag ) case mod_sprite: pent = pefrag->entity; - if( pent->visframe != tr.framecount ) + if( pent->visframe != framecount ) { if( CL_AddVisibleEntity( pent, ET_FRAGMENTED )) { // mark that we've recorded this entity for this frame - pent->visframe = tr.framecount; + pent->visframe = framecount; } } diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index 60428ae5..7aa0a286 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -1444,6 +1444,8 @@ static int GL_RenderGetParm( int parm, int arg ) return glt->flags; case PARM_FEATURES: return host.features; + case PARM_ACTIVE_TMU: + return glState.activeTMU; } return 0; } @@ -1562,6 +1564,11 @@ static int GL_LoadTextureNoFilter( const char *name, const byte *buf, size_t siz return GL_LoadTexture( name, buf, size, flags, NULL ); } +static void GL_StoreEfrags( efrag_t **ppefrag ) +{ + R_StoreEfrags( ppefrag, tr.framecount ); +} + static render_api_t gRenderAPI = { GL_RenderGetParm, @@ -1575,7 +1582,7 @@ static render_api_t gRenderAPI = R_SetCurrentEntity, R_SetCurrentModel, GL_SetWorldviewProjectionMatrix, - R_StoreEfrags, + GL_StoreEfrags, GL_FindTexture, GL_TextureName, GL_LoadTextureNoFilter, @@ -1604,6 +1611,9 @@ static render_api_t gRenderAPI = GL_TexGen, R_EntityRemoveDecals, R_DecalSetupVerts, + R_StoreEfrags, + GL_TextureTarget, + R_StudioGetTexture, // moved here to avoid incompatibility with official expanded interface of IEngineStduio (HLSDK Update at 30.08.2013) }; /* diff --git a/engine/client/gl_rsurf.c b/engine/client/gl_rsurf.c index 6d975062..03fea26d 100644 --- a/engine/client/gl_rsurf.c +++ b/engine/client/gl_rsurf.c @@ -1654,7 +1654,7 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags ) // deal with model fragments in this leaf if( pleaf->efrags ) - R_StoreEfrags( &pleaf->efrags ); + R_StoreEfrags( &pleaf->efrags, tr.framecount ); r_stats.c_world_leafs++; return; @@ -1747,7 +1747,7 @@ static void R_DrawTopViewLeaf( mleaf_t *pleaf, uint clipflags ) // deal with model fragments in this leaf if( pleaf->efrags ) - R_StoreEfrags( &pleaf->efrags ); + R_StoreEfrags( &pleaf->efrags, tr.framecount ); r_stats.c_world_leafs++; } diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index 146292a3..64d9668e 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -558,8 +558,8 @@ void R_StudioSetUpTransform( cl_entity_t *e ) } } - // stupid Half-Life bug - angles[PITCH] = -angles[PITCH]; + if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG )) + angles[PITCH] = -angles[PITCH]; // stupid quake bug // don't rotate clients, only aim if( e->player ) angles[PITCH] = 0.0f; diff --git a/engine/common/build.c b/engine/common/build.c index ba51433d..81a22118 100644 --- a/engine/common/build.c +++ b/engine/common/build.c @@ -48,6 +48,6 @@ int Q_buildnum( void ) return b; #else - return 2271; + return 2402; #endif } \ No newline at end of file diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index 38bbcd13..3245bd68 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -229,7 +229,9 @@ hull_t *Mod_HullForStudio( model_t *model, float frame, int sequence, vec3_t ang ASSERT( pBlendAPI != NULL ); VectorCopy( angles, angles2 ); - angles2[PITCH] = -angles2[PITCH]; // stupid quake bug + + if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG )) + angles2[PITCH] = -angles2[PITCH]; // stupid quake bug pBlendAPI->SV_StudioSetupBones( model, frame, sequence, angles2, origin, pcontroller, pblending, pEdict, -1 ); phitbox = (mstudiobbox_t *)((byte *)mod_studiohdr + mod_studiohdr->hitboxindex); @@ -753,7 +755,9 @@ void Mod_StudioGetAttachment( const edict_t *e, int iAttachment, float *origin, pAtt = (mstudioattachment_t *)((byte *)mod_studiohdr + mod_studiohdr->attachmentindex); VectorCopy( e->v.angles, angles2 ); - angles2[PITCH] = -angles2[PITCH]; + + if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG )) + angles2[PITCH] = -angles2[PITCH]; pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, angles2, e->v.origin, e->v.controller, e->v.blending, e, pAtt[iAttachment].bone ); diff --git a/engine/common/model.c b/engine/common/model.c index 32325130..c8449717 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -2679,8 +2679,8 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load Mod_LoadPlanes( &header->lumps[LUMP_PLANES] ); } - // Half-Life: alpha version has BSP version 29 and map version 220 - if( world.version <= 29 && world.mapversion == 220 ) + // Half-Life: alpha version has BSP version 29 and map version 220 (and lightdata is RGB) + if( world.version <= 29 && world.mapversion == 220 && (header->lumps[LUMP_LIGHTING].filelen % 3) == 0 ) world.version = bmodel_version = HLBSP_VERSION; Mod_LoadVertexes( &header->lumps[LUMP_VERTEXES] ); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index cec711e6..37483c91 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -1256,7 +1256,8 @@ void SV_Physics_Compound( edict_t *ent ) Matrix4x4_CreateFromEntity( end_l, parent->v.angles, parent->v.origin, 1.0f ); // stupid quake bug!!! - ent->v.angles[PITCH] = -ent->v.angles[PITCH]; + if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG )) + ent->v.angles[PITCH] = -ent->v.angles[PITCH]; // create child actual position Matrix4x4_CreateFromEntity( child, ent->v.angles, ent->v.origin, 1.0f ); @@ -1269,7 +1270,8 @@ void SV_Physics_Compound( edict_t *ent ) Matrix4x4_ConvertToEntity( child, ent->v.angles, ent->v.origin ); // stupid quake bug!!! - ent->v.angles[PITCH] = -ent->v.angles[PITCH]; + if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG )) + ent->v.angles[PITCH] = -ent->v.angles[PITCH]; } // notsolid ents never touch triggers diff --git a/mainui/menu_credits.cpp b/mainui/menu_credits.cpp index 512e1505..6c1bc5fa 100644 --- a/mainui/menu_credits.cpp +++ b/mainui/menu_credits.cpp @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static const char *uiCreditsDefault[] = { "", - "Copyright XashXT Group 2011 (C)", + "Copyright XashXT Group 2013 (C)", 0 };