From dd3583d11a7a941e01314837bea0b6a4dcf65a11 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Tue, 14 Apr 2026 11:50:35 +0500 Subject: [PATCH] engine: move details textures parser to the engine --- engine/client/cl_parse.c | 3 + engine/client/cl_render.c | 1 + engine/common/mod_bmodel.c | 99 +++++++++++++++++++++++ engine/common/mod_local.h | 1 + engine/ref_api.h | 4 + ref/gl/gl_context.c | 56 ++++++++++++- ref/gl/gl_local.h | 4 - ref/gl/gl_rmisc.c | 161 ------------------------------------- ref/null/r_context.c | 14 ++++ ref/soft/r_context.c | 13 ++- 10 files changed, 187 insertions(+), 169 deletions(-) delete mode 100644 ref/gl/gl_rmisc.c diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index c5567a73..cbeeff42 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -15,6 +15,7 @@ GNU General Public License for more details. #include "common.h" #include "client.h" +#include "mod_local.h" #include "net_encode.h" #include "cl_tent.h" #include "shake.h" @@ -1738,6 +1739,8 @@ void CL_RegisterResources( sizebuf_t *msg, connprotocol_t proto ) // tell rendering system we have a new set of models. ref.dllFuncs.R_NewMap (); + Mod_LoadDetailTextures( cl.worldmodel ); + // check if this map must start from dark screen CL_StartDark (); diff --git a/engine/client/cl_render.c b/engine/client/cl_render.c index f6422070..938b80cb 100644 --- a/engine/client/cl_render.c +++ b/engine/client/cl_render.c @@ -295,6 +295,7 @@ qboolean R_InitRenderAPI( void ) // make sure what render functions is cleared memset( &clgame.drawFuncs, 0, sizeof( clgame.drawFuncs )); + gRenderAPI.GetDetailScaleForTexture = ref.dllFuncs.R_GetDetailScaleForTexture; gRenderAPI.GL_FindTexture = ref.dllFuncs.GL_FindTexture; gRenderAPI.GL_TextureName = ref.dllFuncs.GL_TextureName; gRenderAPI.GL_TextureData = ref.dllFuncs.GL_TextureData; diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index b5ce9123..7175cd22 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -2989,6 +2989,105 @@ static void Mod_LoadTextures( model_t *mod, dbspmodel_t *bmod ) Mod_SequenceAllAnimatedTextures( mod ); } +#if !XASH_DEDICATED +static void Mod_ParseDetailTextures( model_t *mod ) +{ + byte *afile; + char *pfile; + string token, texname; + string detail_texname; + string detail_path; + float xScale, yScale; + texture_t *tex; + int i; + + string filepath; + + Q_strncpy( filepath, mod->name, sizeof( filepath )); + COM_StripExtension( filepath ); + Q_strncat( filepath, "_detail.txt", sizeof( filepath )); + + afile = FS_LoadFile( filepath, NULL, false ); + if( !afile ) + return; + + pfile = (char *)afile; + + // format: 'texturename' 'detailtexture' 'xScale' 'yScale' + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) + { + texname[0] = '\0'; + detail_texname[0] = '\0'; + + // read texname + if( token[0] == '{' ) + { + // NOTE: COM_ParseFile handled some symbols seperately + // this code will be fix it + pfile = COM_ParseFile( pfile, token, sizeof( token )); + Q_snprintf( texname, sizeof( texname ), "{%s", token ); + } + else + Q_strncpy( texname, token, sizeof( texname )); + + // read detailtexture name + pfile = COM_ParseFile( pfile, token, sizeof( token )); + Q_strncpy( detail_texname, token, sizeof( detail_texname )); + + // trying the scales or '{' + pfile = COM_ParseFile( pfile, token, sizeof( token )); + + // read second part of detailtexture name + if( token[0] == '{' ) + { + Q_strncat( detail_texname, token, sizeof( detail_texname )); + pfile = COM_ParseFile( pfile, token, sizeof( token )); // read scales + Q_strncat( detail_texname, token, sizeof( detail_texname )); + pfile = COM_ParseFile( pfile, token, sizeof( token )); // parse scales + } + + Q_snprintf( detail_path, sizeof( detail_path ), "gfx/%s", detail_texname ); + + // read scales + xScale = Q_atof( token ); + + pfile = COM_ParseFile( pfile, token, sizeof( token )); + yScale = Q_atof( token ); + + if( xScale <= 0.0f || yScale <= 0.0f ) + continue; + + // search for existing texture and uploading detail texture + for( i = 0; i < mod->numtextures; i++ ) + { + tex = mod->textures[i]; + + if( Q_stricmp( tex->name, texname )) + continue; + + tex->dt_texturenum = ref.dllFuncs.GL_LoadTexture( detail_path, NULL, 0, TF_FORCE_COLOR|TF_NOFLIP_TGA ); + + if( tex->dt_texturenum ) + ref.dllFuncs.R_SetDetailScaleForTexture( tex->gl_texturenum, xScale, yScale ); + + break; + } + } + + Mem_Free( afile ); +} + +void Mod_LoadDetailTextures( model_t *mod ) +{ + convar_t *r_detailtextures = Cvar_FindVar( "r_detailtextures" ); + + if( !r_detailtextures || !r_detailtextures->value ) + return; + + Mod_ParseDetailTextures( mod ); +} +#endif // !XASH_DEDICATED + /* ================= Mod_LoadTexInfo diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 30b60c02..108d66f1 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -156,6 +156,7 @@ model_t *Mod_ForName( const char *name, qboolean crash, qboolean trackCRC ); qboolean Mod_ValidateCRC( const char *name, uint32_t crc ); void Mod_NeedCRC( const char *name, qboolean needCRC ); void Mod_FreeUnused( void ); +void Mod_LoadDetailTextures( model_t *mod ); // // mod_alias.c diff --git a/engine/ref_api.h b/engine/ref_api.h index 1e4ba8fd..096b0bd5 100644 --- a/engine/ref_api.h +++ b/engine/ref_api.h @@ -598,6 +598,10 @@ typedef struct ref_interface_s // Xash3D Render Interface int (*RefGetParm)( int parm, int arg ); // generic + // detail texture scale + void (*R_GetDetailScaleForTexture)( int texture, float *xScale, float *yScale ); + void (*R_SetDetailScaleForTexture)( int texture, float xScale, float yScale ); + // Texture tools (used by engine directly) int (*GL_FindTexture)( const char *name ); const char* (*GL_TextureName)( unsigned int texnum ); diff --git a/ref/gl/gl_context.c b/ref/gl/gl_context.c index 1d97e78e..055c137f 100644 --- a/ref/gl/gl_context.c +++ b/ref/gl/gl_context.c @@ -244,6 +244,14 @@ static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScal if( yScale ) *yScale = glt->yscale; } +static void R_SetDetailScaleForTexture( int texture, float xScale, float yScale ) +{ + gl_texture_t *glt = R_GetTexture( texture ); + + glt->xscale = xScale; + glt->yscale = yScale; +} + static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density ) { gl_texture_t *glt = R_GetTexture( texture ); @@ -413,9 +421,52 @@ static const char *R_GetConfigName( void ) return "opengl"; } +static void R_NewMap( void ) +{ + texture_t *tx; + int i; + + tr.worldmodel = gp_cl->models[1]; + + R_ClearDecals(); // clear all level decals + + R_StudioResetPlayerModels(); + + // clear out efrags in case the level hasn't been reloaded + for( i = 0; i < WORLDMODEL->numleafs; i++ ) + WORLDMODEL->leafs[i+1].efrags = NULL; + + glState.isFogEnabled = false; + tr.skytexturenum = -1; + pglDisable( GL_FOG ); + + // clearing texture chains + for( i = 0; i < WORLDMODEL->numtextures; i++ ) + { + if( !WORLDMODEL->textures[i] ) + continue; + + tx = WORLDMODEL->textures[i]; + + if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 )) + tr.skytexturenum = i; + + tx->texturechain = NULL; + } + + GL_BuildLightmaps (); + + R_ClearVBO(); + if( R_HasEnabledVBO( )) + R_GenerateVBO(); + R_ResetRipples(); + + if( gEngfuncs.drawFuncs->R_NewMap != NULL ) + gEngfuncs.drawFuncs->R_NewMap(); +} + static void R_FillRenderAPI( render_api_t *api ) { - api->GetDetailScaleForTexture = R_GetDetailScaleForTexture; api->GetExtraParmsForTexture = R_GetExtraParmsForTexture; api->GetFrameTime = R_GetFrameTime; api->R_SetCurrentEntity = R_SetCurrentEntity; @@ -520,6 +571,9 @@ const ref_interface_t gReffuncs = GL_RefGetParm, + R_GetDetailScaleForTexture, + R_SetDetailScaleForTexture, + GL_FindTexture, GL_TextureName, GL_TextureData, diff --git a/ref/gl/gl_local.h b/ref/gl/gl_local.h index 7e715f92..877d9141 100644 --- a/ref/gl/gl_local.h +++ b/ref/gl/gl_local.h @@ -369,10 +369,6 @@ void R_DrawFog( void ); int CL_FxBlend( cl_entity_t *e ); // -// gl_rmisc.c -// -void R_NewMap( void ); - // // gl_rsurf.c // diff --git a/ref/gl/gl_rmisc.c b/ref/gl/gl_rmisc.c deleted file mode 100644 index 6b43c185..00000000 --- a/ref/gl/gl_rmisc.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -gl_rmisc.c - renderer misceallaneous -Copyright (C) 2010 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 "gl_local.h" -#include "shake.h" -#include "screenfade.h" -#include "cdll_int.h" - -static void R_ParseDetailTextures( const char *filename ) -{ - byte *afile; - char *pfile; - string token, texname; - string detail_texname; - string detail_path; - float xScale, yScale; - texture_t *tex; - int i; - - afile = gEngfuncs.fsapi->LoadFile( filename, NULL, false ); - if( !afile ) return; - - pfile = (char *)afile; - - // format: 'texturename' 'detailtexture' 'xScale' 'yScale' - while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) - { - texname[0] = '\0'; - detail_texname[0] = '\0'; - - // read texname - if( token[0] == '{' ) - { - // NOTE: COM_ParseFile handled some symbols seperately - // this code will be fix it - pfile = COM_ParseFile( pfile, token, sizeof( token )); - Q_snprintf( texname, sizeof( texname ), "{%s", token ); - } - else Q_strncpy( texname, token, sizeof( texname )); - - // read detailtexture name - pfile = COM_ParseFile( pfile, token, sizeof( token )); - Q_strncpy( detail_texname, token, sizeof( detail_texname )); - - // trying the scales or '{' - pfile = COM_ParseFile( pfile, token, sizeof( token )); - - // read second part of detailtexture name - if( token[0] == '{' ) - { - Q_strncat( detail_texname, token, sizeof( detail_texname )); - pfile = COM_ParseFile( pfile, token, sizeof( token )); // read scales - Q_strncat( detail_texname, token, sizeof( detail_texname )); - pfile = COM_ParseFile( pfile, token, sizeof( token )); // parse scales - } - - Q_snprintf( detail_path, sizeof( detail_path ), "gfx/%s", detail_texname ); - - // read scales - xScale = Q_atof( token ); - - pfile = COM_ParseFile( pfile, token, sizeof( token )); - yScale = Q_atof( token ); - - if( xScale <= 0.0f || yScale <= 0.0f ) - continue; - - // search for existing texture and uploading detail texture - for( i = 0; i < WORLDMODEL->numtextures; i++ ) - { - tex = WORLDMODEL->textures[i]; - - if( Q_stricmp( tex->name, texname )) - continue; - - tex->dt_texturenum = GL_LoadTexture( detail_path, NULL, 0, TF_FORCE_COLOR|TF_NOFLIP_TGA ); - - // texture is loaded - if( tex->dt_texturenum ) - { - gl_texture_t *glt; - - glt = R_GetTexture( tex->gl_texturenum ); - glt->xscale = xScale; - glt->yscale = yScale; - } - break; - } - } - - Mem_Free( afile ); -} - -void R_NewMap( void ) -{ - texture_t *tx; - int i; - - tr.worldmodel = gp_cl->models[1]; - - R_ClearDecals(); // clear all level decals - - R_StudioResetPlayerModels(); - - // upload detailtextures - if( r_detailtextures.value ) - { - string mapname, filepath; - - Q_strncpy( mapname, WORLDMODEL->name, sizeof( mapname )); - COM_StripExtension( mapname ); - Q_snprintf( filepath, sizeof( filepath ), "%s_detail.txt", mapname ); - - R_ParseDetailTextures( filepath ); - } - - // clear out efrags in case the level hasn't been reloaded - for( i = 0; i < WORLDMODEL->numleafs; i++ ) - WORLDMODEL->leafs[i+1].efrags = NULL; - - glState.isFogEnabled = false; - tr.skytexturenum = -1; - pglDisable( GL_FOG ); - - // clearing texture chains - for( i = 0; i < WORLDMODEL->numtextures; i++ ) - { - if( !WORLDMODEL->textures[i] ) - continue; - - tx = WORLDMODEL->textures[i]; - - if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 )) - tr.skytexturenum = i; - - tx->texturechain = NULL; - } - - GL_BuildLightmaps (); - - R_ClearVBO(); - if( R_HasEnabledVBO( )) - R_GenerateVBO(); - R_ResetRipples(); - - if( gEngfuncs.drawFuncs->R_NewMap != NULL ) - gEngfuncs.drawFuncs->R_NewMap(); - -} diff --git a/ref/null/r_context.c b/ref/null/r_context.c index 3f3e6e31..91b20037 100644 --- a/ref/null/r_context.c +++ b/ref/null/r_context.c @@ -59,6 +59,17 @@ static void R_StudioSetDrawInterface( struct r_studio_interface_s *pDraw ) ; } +static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale ) +{ + if( xScale ) *xScale = 1.0f; + if( yScale ) *yScale = 1.0f; +} + +static void R_SetDetailScaleForTexture( int texture, float xScale, float yScale ) +{ + ; +} + static void R_FillRenderAPI( render_api_t *api ) { ; @@ -505,6 +516,9 @@ static const ref_interface_t gReffuncs = .RefGetParm = RefGetParm, + .R_GetDetailScaleForTexture = R_GetDetailScaleForTexture, + .R_SetDetailScaleForTexture = R_SetDetailScaleForTexture, + .GL_FindTexture = GL_FindTexture, .GL_TextureName = GL_TextureName, .GL_TextureData = GL_TextureData, diff --git a/ref/soft/r_context.c b/ref/soft/r_context.c index 70df530b..d9d37d52 100644 --- a/ref/soft/r_context.c +++ b/ref/soft/r_context.c @@ -198,8 +198,13 @@ static void GAME_EXPORT R_GetDetailScaleForTexture( int texture, float *xScale, { // details are not implemented in ref_soft - if( xScale ) *xScale = 0.0f; - if( yScale ) *yScale = 0.0f; + if( xScale ) *xScale = 1.0f; + if( yScale ) *yScale = 1.0f; +} + +static void GAME_EXPORT R_SetDetailScaleForTexture( int texture, float xScale, float yScale ) +{ + // details are not implemented in ref_soft } static void GAME_EXPORT R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density ) @@ -400,7 +405,6 @@ static void * GAME_EXPORT R_GetProcAddress( const char *name ) static void R_FillRenderAPI( render_api_t *api ) { - api->GetDetailScaleForTexture = R_GetDetailScaleForTexture; api->GetExtraParmsForTexture = R_GetExtraParmsForTexture; api->GetFrameTime = R_GetFrameTime; api->R_SetCurrentEntity = R_SetCurrentEntity; @@ -505,6 +509,9 @@ const ref_interface_t gReffuncs = GL_RefGetParm, + R_GetDetailScaleForTexture, + R_SetDetailScaleForTexture, + GL_FindTexture, GL_TextureName, GL_TextureData,