diff --git a/common/com_model.h b/common/com_model.h index 939209e9..7ad79c91 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -92,6 +92,20 @@ 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; @@ -197,15 +211,11 @@ 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 - vec3_t *vertices; // vertexes array - vec2_t *stcoords; // s\t coords array - vec2_t *lmcoords; // l\m coords array (unused for studio models) - vec3_t *normals; // normals array (identical for bsp polys, unique for studio models) - vec3_t *tangent; // tangent array (identical for bsp polys, unique for studio models) - vec3_t *binormal; // binormal array (identical for bsp polys, unique for studio models) - byte *colors; // colors array for vertex lighting (filling 0xFF by default) - unsigned short *indices; // indices + 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 diff --git a/common/render_api.h b/common/render_api.h index 5b5ce240..226d13aa 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -118,6 +118,8 @@ typedef enum TF_TEXTURE_RECTANGLE= (1<<22), // this is GL_TEXTURE_RECTANGLE TF_ALPHA_BORDER = (1<<23), // clamp to (0,0,0,255) (probably no difference) TF_IMAGE_PROGRAM = (1<<24), // enable image program support like in Doom3 + TF_ALPHACONTRAST = (1<<25), // special texture flags for internal usage + TF_FLOAT = (1<<26), // float textures } texFlags_t; typedef struct beam_s BEAM; @@ -246,6 +248,8 @@ typedef struct render_interface_s qboolean (*R_SpeedsMessage)( char *out, size_t size ); // replace with built-in R_DrawCubemapView for make skyshots or envshots qboolean (*R_DrawCubemapView)( const float *origin, const float *angles, int size ); + // alloc or destroy studiomodel custom data + void (*Mod_ProcessUserData)( model_t *mod, qboolean create ); } render_interface_t; #endif//RENDER_API_H \ No newline at end of file diff --git a/engine/client/cl_cmds.c b/engine/client/cl_cmds.c index ccabb293..caf87a3c 100644 --- a/engine/client/cl_cmds.c +++ b/engine/client/cl_cmds.c @@ -323,7 +323,7 @@ void CL_LevelShot_f( void ) cls.scrshot_request = scrshot_inactive; // check for exist - Q_sprintf( cls.shotname, "levelshots/%s.bmp", clgame.mapname ); + Q_sprintf( cls.shotname, "levelshots/%s_%s.bmp", clgame.mapname, glState.wideScreen ? "16x9" : "4x3" ); // make sure what entity patch is never than bsp ft1 = FS_FileTime( cl.worldmodel->name, false ); diff --git a/engine/client/cl_frame.c b/engine/client/cl_frame.c index f05a57a8..d1894a48 100644 --- a/engine/client/cl_frame.c +++ b/engine/client/cl_frame.c @@ -369,7 +369,6 @@ Set new weapon animation void CL_WeaponAnim( int iAnim, int body ) { cl_entity_t *view = &clgame.viewent; - static int viewmodel = -1; view->curstate.modelindex = cl.frame.local.client.viewmodel; diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 1fbeeac2..f7f4ef13 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -3846,6 +3846,7 @@ void CL_UnloadProgs( void ) CL_FreeViewBeams(); CL_FreeParticles(); CL_ClearAllRemaps(); + Mod_ClearUserData(); VGui_Shutdown(); // NOTE: HLFX 0.5 has strange bug: hanging on exit if no map was loaded diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index d2b08115..bada1163 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1572,7 +1572,7 @@ void CL_Escape_f( void ) if( UI_CreditsActive( )) return; if( cls.state == ca_cinematic ) - SCR_StopCinematic(); + SCR_NextMovie(); // jump to next movie else UI_SetActiveMenu( true ); } @@ -1787,9 +1787,9 @@ void CL_Init( void ) cls.initialized = true; cl.maxclients = 1; // allow to drawing player in menu + cls.demonum = -1; } - /* =============== CL_Shutdown diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 0b25e7c1..4fdb0210 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -611,7 +611,7 @@ void CL_ParseServerData( sizebuf_t *msg ) CL_InitEdicts (); // re-arrange edicts // get splash name - Cvar_Set( "cl_levelshot_name", va( "levelshots/%s", clgame.mapname )); + Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", clgame.mapname, glState.wideScreen ? "16x9" : "4x3" )); Cvar_SetFloat( "scr_loading", 0.0f ); // reset progress bar if(( cl_allow_levelshots->integer && !cls.changelevel ) || cl.background ) diff --git a/engine/client/client.h b/engine/client/client.h index d33549fa..1305b1f8 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -800,6 +800,7 @@ void SCR_InitCinematic( void ); void SCR_FreeCinematic( void ); qboolean SCR_PlayCinematic( const char *name ); qboolean SCR_DrawCinematic( void ); +qboolean SCR_NextMovie( void ); void SCR_RunCinematic( void ); void SCR_StopCinematic( void ); void CL_PlayVideo_f( void ); diff --git a/engine/client/gl_backend.c b/engine/client/gl_backend.c index a3a6841f..878a2a38 100644 --- a/engine/client/gl_backend.c +++ b/engine/client/gl_backend.c @@ -451,6 +451,9 @@ void VID_ImageAdjustGamma( byte *in, uint width, uint height ) byte r_gammaTable[256]; // adjust screenshot gamma byte *p = in; + if( !gl_compensate_gamma_screenshots->integer ) + return; + // rebuild the gamma table for( i = 0; i < 256; i++ ) { @@ -499,8 +502,16 @@ qboolean VID_ScreenShot( const char *filename, int shot_type ) break; case VID_LEVELSHOT: flags |= IMAGE_RESAMPLE; - height = 384; - width = 512; + if( glState.wideScreen ) + { + height = 480; + width = 800; + } + else + { + height = 480; + width = 640; + } break; case VID_MINISHOT: flags |= IMAGE_RESAMPLE; diff --git a/engine/client/gl_beams.c b/engine/client/gl_beams.c index a920b759..c3c1d5d3 100644 --- a/engine/client/gl_beams.c +++ b/engine/client/gl_beams.c @@ -2186,7 +2186,8 @@ void CL_ReadLineFile_f( void ) if( !CL_BeamPoints( p1, p2, modelIndex, 99999, 2, 0, 255, 0, 0, 0, 255.0f, 0.0f, 0.0f )) { - if( !modelIndex ) MsgDev( D_ERROR, "CL_ReadLineFile: no beam sprite!\n" ); + if( Mod_GetType( modelIndex ) != mod_sprite ) + MsgDev( D_ERROR, "CL_ReadLineFile: failed to load sprites/laserbeam.spr!\n" ); else MsgDev( D_ERROR, "CL_ReadLineFile: not enough free beams!\n" ); break; } diff --git a/engine/client/gl_decals.c b/engine/client/gl_decals.c index 4f33b926..6aa7ef97 100644 --- a/engine/client/gl_decals.c +++ b/engine/client/gl_decals.c @@ -536,11 +536,7 @@ msurfmesh_t *R_DecalCreateMesh( decalinfo_t *decalinfo, decal_t *pdecal, msurfac // allocate mesh numElems = (numVerts - 2) * 3; - // mesh + ( vertex, normal, (st + lmst) ) * numVerts + elem * numElems; - bufSize = sizeof( msurfmesh_t ) + numVerts * ( sizeof( vec3_t ) + sizeof( vec3_t ) + sizeof( vec4_t )) + numElems * sizeof( word ); - bufSize += numVerts * ( sizeof( vec3_t ) + sizeof( vec3_t )); // tangent and binormal - bufSize += numVerts * sizeof( rgba_t ); // color array - + bufSize = sizeof( msurfmesh_t ) + numVerts * sizeof( glvert_t ) + numElems * sizeof( word ); buffer = Mem_Alloc( cls.mempool, bufSize ); mesh = (msurfmesh_t *)buffer; @@ -549,22 +545,9 @@ msurfmesh_t *R_DecalCreateMesh( decalinfo_t *decalinfo, decal_t *pdecal, msurfac mesh->numElems = numElems; // setup pointers - mesh->vertices = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->stcoords = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->lmcoords = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->normals = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->tangent = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->binormal = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->colors = (byte *)buffer; - buffer += numVerts * sizeof( rgba_t ); - - mesh->indices = (word *)buffer; + 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 @@ -572,26 +555,29 @@ msurfmesh_t *R_DecalCreateMesh( decalinfo_t *decalinfo, decal_t *pdecal, msurfac // create indices for( i = 0; i < mesh->numVerts - 2; i++ ) { - mesh->indices[i*3+0] = 0; - mesh->indices[i*3+1] = i + 1; - mesh->indices[i*3+2] = i + 2; + mesh->elems[i*3+0] = 0; + mesh->elems[i*3+1] = i + 1; + mesh->elems[i*3+2] = i + 2; } - // clear colors (it can be used for vertex lighting) - Q_memset( mesh->colors, 0xFF, numVerts * sizeof( rgba_t )); - // fill the mesh for( i = 0; i < numVerts; i++, v += VERTEXSIZE ) { - VectorCopy( v, mesh->vertices[i] ); - VectorCopy( decalinfo->m_Basis[0], mesh->tangent[i] ); - VectorCopy( decalinfo->m_Basis[1], mesh->binormal[i] ); - VectorCopy( decalinfo->m_Basis[2], mesh->normals[i] ); + 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 ); - mesh->stcoords[i][0] = v[3]; - mesh->stcoords[i][1] = v[4]; - mesh->lmcoords[i][0] = v[5]; - mesh->lmcoords[i][1] = v[6]; + 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) + Q_memset( out->color, 0xFF, sizeof( out->color )); } pdecal->mesh = mesh; @@ -929,11 +915,13 @@ float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *o // 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 ) { - VectorCopy( pDecal->mesh->vertices[i], v ); - v[3] = pDecal->mesh->stcoords[i][0]; - v[4] = pDecal->mesh->stcoords[i][1]; - v[5] = pDecal->mesh->lmcoords[i][0]; - v[6] = pDecal->mesh->lmcoords[i][1]; + 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]; } // restore pointer diff --git a/engine/client/gl_export.h b/engine/client/gl_export.h index c2d312be..1cd28a1b 100644 --- a/engine/client/gl_export.h +++ b/engine/client/gl_export.h @@ -505,6 +505,40 @@ typedef float GLmatrix[16]; #define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F + +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F + //GL_ARB_vertex_buffer_object #define GL_ARRAY_BUFFER_ARB 0x8892 #define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 4c739a41..27917d04 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -199,7 +199,7 @@ void GL_TexFilter( gltexture_t *tex, qboolean update ) } // set texture anisotropy if available - if( GL_Support( GL_ANISOTROPY_EXT )) + if( GL_Support( GL_ANISOTROPY_EXT ) && !( tex->flags & TF_ALPHACONTRAST )) pglTexParameterf( tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_anisotropy->value ); // set texture LOD bias if available @@ -441,6 +441,30 @@ void R_TextureList_f( void ) case GL_DEPTH_COMPONENT: Msg( "DEPTH " ); break; + case GL_LUMINANCE16F_ARB: + Msg( "L16F " ); + break; + case GL_LUMINANCE32F_ARB: + Msg( "L32F " ); + break; + case GL_LUMINANCE_ALPHA16F_ARB: + Msg( "LA16F " ); + break; + case GL_LUMINANCE_ALPHA32F_ARB: + Msg( "LA32F " ); + break; + case GL_RGB16F_ARB: + Msg( "RGB16F" ); + break; + case GL_RGB32F_ARB: + Msg( "RGB32F" ); + break; + case GL_RGBA16F_ARB: + Msg( "RGBA16F" ); + break; + case GL_RGBA32F_ARB: + Msg( "RGBA32F" ); + break; default: Msg( "????? " ); break; @@ -638,6 +662,43 @@ static GLenum GL_TextureFormat( gltexture_t *tex, int *samples ) format = GL_DEPTH_COMPONENT; tex->flags &= ~TF_INTENSITY; } + else if( tex->flags & TF_FLOAT && GL_Support( GL_ARB_TEXTURE_FLOAT_EXT )) + { + int bits = glw_state.desktopBitsPixel; + + switch( *samples ) + { + case 1: + switch( bits ) + { + case 16: format = GL_LUMINANCE16F_ARB; break; + default: format = GL_LUMINANCE32F_ARB; break; + } + break; + case 2: + switch( bits ) + { + case 16: format = GL_LUMINANCE_ALPHA16F_ARB; break; + default: format = GL_LUMINANCE_ALPHA32F_ARB; break; + } + break; + case 3: + switch( bits ) + { + case 16: format = GL_RGB16F_ARB; break; + default: format = GL_RGB32F_ARB; break; + } + break; + case 4: + default: + switch( bits ) + { + case 16: format = GL_RGBA16F_ARB; break; + default: format = GL_RGBA32F_ARB; break; + } + break; + } + } else if( compress ) { switch( *samples ) @@ -895,7 +956,7 @@ void GL_GenerateMipmaps( byte *buffer, rgbdata_t *pic, gltexture_t *tex, GLenum if( tex->flags & TF_NOMIPMAP ) return; - if( GL_Support( GL_SGIS_MIPMAPS_EXT ) && !( tex->flags & TF_NORMALMAP )) + if( GL_Support( GL_SGIS_MIPMAPS_EXT ) && !( tex->flags & ( TF_NORMALMAP|TF_ALPHACONTRAST ))) { pglHint( GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST ); pglTexParameteri( glTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE ); @@ -914,7 +975,8 @@ void GL_GenerateMipmaps( byte *buffer, rgbdata_t *pic, gltexture_t *tex, GLenum while( w > 1 || h > 1 ) { // build the mipmap - GL_BuildMipMap( buffer, w, h, ( tex->flags & TF_NORMALMAP )); + if( tex->flags & TF_ALPHACONTRAST ) Q_memset( buffer, pic->width >> mipLevel, w * h * 4 ); + else GL_BuildMipMap( buffer, w, h, ( tex->flags & TF_NORMALMAP )); w = (w+1)>>1; h = (h+1)>>1; @@ -1144,11 +1206,11 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag } else { - if( GL_Support( GL_SGIS_MIPMAPS_EXT ) && !( tex->flags & TF_NORMALMAP )) + if( GL_Support( GL_SGIS_MIPMAPS_EXT ) && !( tex->flags & ( TF_NORMALMAP|TF_ALPHACONTRAST ))) 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 ) || ( tex->flags & TF_NORMALMAP )) + if( !GL_Support( GL_SGIS_MIPMAPS_EXT ) || ( tex->flags & ( TF_NORMALMAP|TF_ALPHACONTRAST ))) GL_GenerateMipmaps( data, pic, tex, glTarget, inFormat, i, subImage ); } @@ -2198,6 +2260,44 @@ static rgbdata_t *R_ClearPixels( rgbdata_t *in, qboolean clearAlpha ) return in; } +/* +================ +R_MovePixels + +move alpha-channel into color or back +================ +*/ +static rgbdata_t *R_MovePixels( rgbdata_t *in, qboolean alphaToColor ) +{ + byte *pic; + int i; + + // make sure what we processing RGBA images + in = R_ForceImageToRGBA( in ); + pic = in->buffer; + + if( alphaToColor ) + { + for( i = 0; ( i < in->width * in->height ) && ( in->flags & IMAGE_HAS_ALPHA ); i++ ) + { + pic[(i<<2)+0] = pic[(i<<2)+1] = pic[(i<<2)+2] = pic[(i<<2)+3]; // move from alpha to color + pic[(i<<2)+3] = 0xFF; // clear alpha channel + } + } + else + { + // clear color or greyscale image otherwise + for( i = 0; i < in->width * in->height; i++ ) + { + // convert to grayscale + pic[(i<<2)+3] = (pic[(i<<2)+0] * 0.32f) + (pic[(i<<2)+0] * 0.59f) + (pic[(i<<2)+0] * 0.09f); + pic[(i<<2)+0] = pic[(i<<2)+1] = pic[(i<<2)+2] = 0x00; // clear RGB channels + } + } + + return in; +} + /* ============================================================================== @@ -3326,6 +3426,64 @@ static rgbdata_t *R_ParseClearPixels( char **script, int *samples, texFlags_t *f return R_ClearPixels( pic, clearAlpha ); } +/* +================= +R_ParseMovePixels +================= +*/ +static rgbdata_t *R_ParseMovePixels( char **script, int *samples, texFlags_t *flags ) +{ + char token[256]; + qboolean alphaToColor; + rgbdata_t *pic; + + *script = COM_ParseFile( *script, token ); + if( Q_stricmp( token, "(" )) + { + MsgDev( D_WARN, "expected '(', found '%s' instead for 'movePixels'\n", token ); + return NULL; + } + + if(( *script = COM_ParseFile( *script, token )) == NULL ) + { + MsgDev( D_WARN, "missing parameters for 'movePixels'\n" ); + return NULL; + } + + pic = R_LoadImage( script, token, NULL, 0, samples, flags ); + if( !pic ) return NULL; + + *script = COM_ParseFile( *script, token ); + if( !Q_stricmp( token, "AlphaToColor" )) + { + *script = COM_ParseFile( *script, token ); + alphaToColor = true; + } + else if( !Q_stricmp( token, "ColorToAlpha" )) + { + *script = COM_ParseFile( *script, token ); + alphaToColor = false; + } + else if( !Q_stricmp( token, ")" )) + { + alphaToColor = true; // move alpha to color as default + } + else *script = COM_ParseFile( *script, token ); // skip unknown token + + if( Q_stricmp( token, ")" )) + { + MsgDev( D_WARN, "expected ')', found '%s' instead for 'movePixels'\n", token ); + FS_FreeImage( pic ); + return NULL; + } + + *samples = alphaToColor ? 3 : 1; + if( alphaToColor ) *flags &= ~TF_HAS_ALPHA; + *flags &= ~TF_INTENSITY; + + return R_MovePixels( pic, alphaToColor ); +} + /* ================= R_LoadImage @@ -3365,6 +3523,8 @@ static rgbdata_t *R_LoadImage( char **script, const char *name, const byte *buf, return R_ParseDepthmap( script, buf, size, samples, flags ); else if( !Q_stricmp( name, "clearPixels" )) return R_ParseClearPixels( script, samples, flags ); + else if( !Q_stricmp( name, "movePixels" )) + return R_ParseMovePixels( script, samples, flags ); else if( !Q_stricmp( name, "Studio" )) return R_ParseStudioSkin( script, buf, size, samples, flags ); else if( !Q_stricmp( name, "Sprite" )) @@ -3648,6 +3808,34 @@ static rgbdata_t *R_InitBlankBumpTexture( texFlags_t *flags ) return &r_image; } +/* +================== +R_InitBlankDeluxeTexture +================== +*/ +static rgbdata_t *R_InitBlankDeluxeTexture( 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] = 0; // light from ceiling + } + + *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 @@ -3959,6 +4147,29 @@ static rgbdata_t *R_InitWhiteCubemap( texFlags_t *flags ) return &r_image; } +/* +================== +R_InitAlphaContrast +================== +*/ +static rgbdata_t *R_InitAlphaContrast( texFlags_t *flags ) +{ + int size = 64; + byte *data = data2D; + + *flags = (TF_NOPICMIP|TF_UNCOMPRESSED|TF_ALPHACONTRAST|TF_INTENSITY); + + r_image.width = r_image.height = 64; + r_image.size = r_image.width * r_image.height * 4; + + Q_memset( data, size, r_image.size ); + + r_image.buffer = data2D; + r_image.type = PF_RGBA_32; + + return &r_image; +} + /* ================== R_InitBuiltinTextures @@ -3993,11 +4204,13 @@ static void R_InitBuiltinTextures( void ) { "*attnno", &tr.attenuationStubTexture, R_InitAttenuationTextureNoAtten, TEX_SYSTEM }, { "*normalize", &tr.normalizeTexture, R_InitNormalizeCubemap, TEX_CUBEMAP }, { "*blankbump", &tr.blankbumpTexture, R_InitBlankBumpTexture, TEX_SYSTEM }, + { "*blankdeluxe", &tr.blankdeluxeTexture, R_InitBlankDeluxeTexture, 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 }, + { "*alphaContrast", &tr.acontTexture, R_InitAlphaContrast, TEX_SYSTEM }, { NULL, NULL, NULL } }; size_t i, num_builtin_textures = sizeof( textures ) / sizeof( textures[0] ) - 1; diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index 7415dab4..a57e38f6 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -160,6 +160,7 @@ typedef struct int whiteTexture; int grayTexture; int blackTexture; + int acontTexture; int defaultTexture; // use for bad textures int particleTexture; // particle texture int particleTexture2; // unsmoothed particle texture @@ -174,6 +175,7 @@ typedef struct int attenuationTexture3D;// 3D attenuation int attenuationStubTexture; int blankbumpTexture; + int blankdeluxeTexture; int normalizeTexture; int dlightCubeTexture; // dynamic cubemap int grayCubeTexture; @@ -518,6 +520,7 @@ enum GL_CUSTOM_VERTEX_ARRAY_EXT, GL_TEXTURE_ENV_ADD_EXT, GL_CLAMP_TEXBORDER_EXT, + GL_ARB_TEXTURE_FLOAT_EXT, GL_DEPTH_TEXTURE, GL_SHADOW_EXT, GL_EXTCOUNT, // must be last @@ -621,6 +624,7 @@ extern convar_t *gl_texture_lodbias; extern convar_t *gl_showtextures; extern convar_t *gl_compress_textures; extern convar_t *gl_luminance_textures; +extern convar_t *gl_compensate_gamma_screenshots; extern convar_t *gl_keeptjunctions; extern convar_t *gl_detailscale; extern convar_t *gl_overview; // draw map in overview mode diff --git a/engine/client/gl_rmisc.c b/engine/client/gl_rmisc.c index a9f47eaf..15033ee4 100644 --- a/engine/client/gl_rmisc.c +++ b/engine/client/gl_rmisc.c @@ -408,6 +408,9 @@ void R_ClearStaticEntities( void ) { int i; + if( host.type == HOST_DEDICATED ) + return; + // clear out efrags in case the level hasn't been reloaded for( i = 0; i < cl.worldmodel->numleafs; i++ ) cl.worldmodel->leafs[i+1].efrags = NULL; diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index fe116ee2..74301015 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -1503,7 +1503,7 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *lightinfo ) VectorSubtract( dl->origin, origin, direction ); dist = VectorLength( direction ); - if( !dist || dist > dl->radius + ent->model->radius ) + if( !dist || dist > dl->radius + studio_radius ) continue; radius2 = dl->radius * dl->radius; // squared radius @@ -1589,7 +1589,7 @@ void R_StudioEntityLight( alight_t *lightinfo ) VectorSubtract( el->origin, origin, direction ); dist = VectorLength( direction ); - if( !dist || dist > el->radius + ent->model->radius ) + if( !dist || dist > el->radius + studio_radius ) continue; radius2 = el->radius * el->radius; // squared radius @@ -2020,6 +2020,7 @@ static void R_StudioDrawPoints( void ) else if( g_nFaceFlags & STUDIO_NF_TRANSPARENT ) { GL_SetRenderMode( kRenderTransAlpha ); + pglAlphaFunc( GL_GREATER, 0.0f ); alpha = 1.0f; } else if( g_nFaceFlags & STUDIO_NF_ADDITIVE ) @@ -2570,6 +2571,8 @@ static void R_StudioSetupRenderer( int rendermode ) if( glState.drawTrans && g_iRenderMode != kRenderTransAdd ) pglDepthMask( GL_TRUE ); + pglAlphaFunc( GL_GREATER, 0.0f ); + if( g_iBackFaceCull ) GL_FrontFace( true ); } diff --git a/engine/client/gl_vidnt.c b/engine/client/gl_vidnt.c index c608cd1c..3e1bb2ae 100644 --- a/engine/client/gl_vidnt.c +++ b/engine/client/gl_vidnt.c @@ -34,6 +34,7 @@ convar_t *gl_ignorehwgamma; convar_t *gl_texture_anisotropy; convar_t *gl_compress_textures; convar_t *gl_luminance_textures; +convar_t *gl_compensate_gamma_screenshots; convar_t *gl_keeptjunctions; convar_t *gl_texture_lodbias; convar_t *gl_showtextures; @@ -1517,6 +1518,7 @@ void GL_InitCommands( void ) gl_texture_lodbias = Cvar_Get( "gl_texture_lodbias", "0.0", CVAR_ARCHIVE, "LOD bias for mipmapped textures" ); gl_compress_textures = Cvar_Get( "gl_compress_textures", "0", CVAR_GLCONFIG, "compress textures to safe video memory" ); gl_luminance_textures = Cvar_Get( "gl_luminance_textures", "0", CVAR_GLCONFIG, "force all textures to luminance" ); + gl_compensate_gamma_screenshots = Cvar_Get( "gl_compensate_gamma_screenshots", "0", CVAR_ARCHIVE, "allow to apply gamma value for screenshots and snapshots" ); gl_keeptjunctions = Cvar_Get( "gl_keeptjunctions", "1", CVAR_ARCHIVE, "disable to reduce vertexes count but removing tjuncs causes blinking pixels" ); gl_allow_static = Cvar_Get( "gl_allow_static", "0", CVAR_ARCHIVE, "force to drawing non-moveable brushes as part of world (save FPS)" ); gl_allow_mirrors = Cvar_Get( "gl_allow_mirrors", "1", CVAR_ARCHIVE, "allow to draw mirror surfaces" ); @@ -1669,6 +1671,8 @@ void GL_InitExtensions( void ) GL_CheckExtension( "GL_ARB_depth_texture", NULL, "gl_depthtexture", GL_DEPTH_TEXTURE ); GL_CheckExtension( "GL_ARB_shadow", NULL, "gl_arb_shadow", GL_SHADOW_EXT ); + GL_CheckExtension( "GL_ARB_texture_float", NULL, "gl_arb_texture_float", GL_ARB_TEXTURE_FLOAT_EXT ); + // occlusion queries GL_CheckExtension( "GL_ARB_occlusion_query", occlusionfunc, "gl_occlusion_queries", GL_OCCLUSION_QUERIES_EXT ); diff --git a/engine/client/vox.h b/engine/client/vox.h index ce4df528..0eace31c 100644 --- a/engine/client/vox.h +++ b/engine/client/vox.h @@ -16,8 +16,7 @@ GNU General Public License for more details. #ifndef VOX_H #define VOX_H -#define CVOXWORDMAX 32 -#define CVOXSENTENCEMAX 24 +#define CVOXWORDMAX 64 #define CVOXZEROSCANMAX 255 // scan up to this many samples for next zero crossing #define MAX_SENTENCES 2048 #define SENTENCE_INDEX -99999 // unique sentence index diff --git a/engine/common/common.c b/engine/common/common.c index 244bc37d..8479b88d 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -422,14 +422,14 @@ Con_Printf */ void Con_Printf( char *szFmt, ... ) { - char buffer[2048]; // must support > 1k messages - va_list args; + static char buffer[16384]; // must support > 1k messages + va_list args; if( host.developer <= 0 ) return; va_start( args, szFmt ); - Q_vsnprintf( buffer, 2048, szFmt, args ); + Q_vsnprintf( buffer, 16384, szFmt, args ); va_end( args ); Sys_Print( buffer ); @@ -443,14 +443,14 @@ Con_DPrintf */ void Con_DPrintf( char *szFmt, ... ) { - char buffer[2048]; // must support > 1k messages - va_list args; + static char buffer[16384]; // must support > 1k messages + va_list args; if( host.developer < D_INFO ) return; va_start( args, szFmt ); - Q_vsnprintf( buffer, 2048, szFmt, args ); + Q_vsnprintf( buffer, 16384, szFmt, args ); va_end( args ); Sys_Print( buffer ); diff --git a/engine/common/imagelib/img_utils.c b/engine/common/imagelib/img_utils.c index 3d1d2741..18636ce8 100644 --- a/engine/common/imagelib/img_utils.c +++ b/engine/common/imagelib/img_utils.c @@ -553,6 +553,17 @@ qboolean Image_Copy8bitRGBA( const byte *in, byte *out, int pixels ) fin[i] = fin[i] < 224 ? fin[i] : 0; } + // check for color + for( i = 0; i < 256; i++ ) + { + col = (rgba_t *)image.d_currentpal[i]; + if( col[0] != col[1] || col[1] != col[2] ) + { + image.flags |= IMAGE_HAS_COLOR; + break; + } + } + while( pixels >= 8 ) { iout[0] = image.d_currentpal[in[0]]; @@ -564,10 +575,6 @@ qboolean Image_Copy8bitRGBA( const byte *in, byte *out, int pixels ) iout[6] = image.d_currentpal[in[6]]; iout[7] = image.d_currentpal[in[7]]; - col = (rgba_t *)iout; - if( col[0] != col[1] || col[1] != col[2] ) - image.flags |= IMAGE_HAS_COLOR; - in += 8; iout += 8; pixels -= 8; @@ -595,6 +602,7 @@ qboolean Image_Copy8bitRGBA( const byte *in, byte *out, int pixels ) iout[0] = image.d_currentpal[in[0]]; image.type = PF_RGBA_32; // update image type; + return true; } diff --git a/engine/common/keys.c b/engine/common/keys.c index c54bc01a..9a9a5c1b 100644 --- a/engine/common/keys.c +++ b/engine/common/keys.c @@ -589,6 +589,8 @@ void Key_Event( int key, qboolean down ) { kb = keys[key].binding; + if( cls.key_dest == key_game && ( key != K_ESCAPE )) + clgame.dllFuncs.pfnKey_Event( down, key, kb ); Key_AddKeyUpCommands( key, kb ); return; } diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 4065994c..4be7a0db 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -101,6 +101,7 @@ extern int bmodel_version; // only actual during loading void Mod_Init( void ); void Mod_ClearAll( void ); void Mod_Shutdown( void ); +void Mod_ClearUserData( void ); void Mod_PrintBSPFileSizes( void ); void Mod_SetupHulls( vec3_t mins[MAX_MAP_HULLS], vec3_t maxs[MAX_MAP_HULLS] ); void Mod_GetBounds( int handle, vec3_t mins, vec3_t maxs ); diff --git a/engine/common/model.c b/engine/common/model.c index beffca66..75c9f6d8 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -21,6 +21,7 @@ GNU General Public License for more details. #include "world.h" #include "gl_local.h" #include "features.h" +#include "client.h" #define MAX_SIDE_VERTS 512 // per one polygon @@ -475,6 +476,24 @@ void Mod_AmbientLevels( const vec3_t p, byte *pvolumes ) *(int *)pvolumes = *(int *)leaf->ambient_sound_level; } +/* +================ +Mod_FreeUserData +================ +*/ +static void Mod_FreeUserData( model_t *mod ) +{ + // already freed? + if( !mod || !mod->name[0] ) + return; + + if( clgame.drawFuncs.Mod_ProcessUserData != NULL ) + { + // let the client.dll free custom data + clgame.drawFuncs.Mod_ProcessUserData( mod, false ); + } +} + /* ================ Mod_FreeModel @@ -486,6 +505,8 @@ static void Mod_FreeModel( model_t *mod ) if( !mod || !mod->name[0] ) return; + Mod_FreeUserData( mod ); + // select the properly unloader switch( mod->type ) { @@ -536,6 +557,14 @@ void Mod_ClearAll( void ) cm_nummodels = 0; } +void Mod_ClearUserData( void ) +{ + int i; + + for( i = 0; i < cm_nummodels; i++ ) + Mod_FreeUserData( &cm_models[i] ); +} + void Mod_Shutdown( void ) { Mod_ClearAll(); @@ -1291,11 +1320,7 @@ static void Mod_BuildPolygon( mextrasurf_t *info, msurface_t *surf, int numVerts // allocate mesh numElems = (numVerts - 2) * 3; - // mesh + ( vertex, normal, (st + lmst) ) * numVerts + elem * numElems; - bufSize = sizeof( msurfmesh_t ) + numVerts * ( sizeof( vec3_t ) + sizeof( vec3_t ) + sizeof( vec4_t )) + numElems * sizeof( word ); - bufSize += numVerts * ( sizeof( vec3_t ) + sizeof( vec3_t )); // tangent and binormal - bufSize += numVerts * sizeof( rgba_t ); // color array - + bufSize = sizeof( msurfmesh_t ) + numVerts * sizeof( glvert_t ) + numElems * sizeof( word ); buffer = Mem_Alloc( loadmodel->mempool, bufSize ); mesh = (msurfmesh_t *)buffer; @@ -1315,22 +1340,9 @@ static void Mod_BuildPolygon( mextrasurf_t *info, msurface_t *surf, int numVerts VectorNormalize( binormal ); // setup pointers - mesh->vertices = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->stcoords = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->lmcoords = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->normals = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->tangent = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->binormal = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->colors = (byte *)buffer; - buffer += numVerts * sizeof( rgba_t ); - - mesh->indices = (word *)buffer; + mesh->verts = (glvert_t *)buffer; + buffer += numVerts * sizeof( glvert_t ); + mesh->elems = (word *)buffer; buffer += numElems * sizeof( word ); mesh->next = info->mesh; @@ -1340,21 +1352,20 @@ static void Mod_BuildPolygon( mextrasurf_t *info, msurface_t *surf, int numVerts // create indices for( i = 0; i < mesh->numVerts - 2; i++ ) { - mesh->indices[i*3+0] = 0; - mesh->indices[i*3+1] = i + 1; - mesh->indices[i*3+2] = i + 2; + mesh->elems[i*3+0] = 0; + mesh->elems[i*3+1] = i + 1; + mesh->elems[i*3+2] = i + 2; } - // clear colors (it can be used for vertex lighting) - Q_memset( mesh->colors, 0xFF, numVerts * sizeof( rgba_t )); - for( i = 0; i < numVerts; i++, verts += 3 ) { + glvert_t *out = &mesh->verts[i]; + // vertex - VectorCopy( verts, mesh->vertices[i] ); - VectorCopy( tangent, mesh->tangent[i] ); - VectorCopy( binormal, mesh->binormal[i] ); - VectorCopy( normal, mesh->normals[i] ); + 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]; @@ -1363,8 +1374,8 @@ static void Mod_BuildPolygon( mextrasurf_t *info, msurface_t *surf, int numVerts t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3]; t /= texinfo->texture->height; - mesh->stcoords[i][0] = s; - mesh->stcoords[i][1] = t; + out->stcoord[0] = s; + out->stcoord[1] = t; // lightmap texture coordinates s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3] - surf->texturemins[0]; @@ -1377,8 +1388,11 @@ static void Mod_BuildPolygon( mextrasurf_t *info, msurface_t *surf, int numVerts t += LM_SAMPLE_SIZE >> 1; t /= BLOCK_SIZE * LM_SAMPLE_SIZE; - mesh->lmcoords[i][0] = s; - mesh->lmcoords[i][1] = t; + out->lmcoord[0] = s; + out->lmcoord[1] = t; + + // clear colors (it can be used for vertex lighting) + Q_memset( out->color, 0xFF, sizeof( out->color )); } } @@ -1457,11 +1471,7 @@ static void Mod_SubdividePolygon( mextrasurf_t *info, msurface_t *surf, int numV return; } - // mesh + ( vertex, normal, (st + lmst) ) * ( numVerts + 2 ); - bufSize = sizeof( msurfmesh_t ) + (( numVerts + 2 ) * (( sizeof( vec3_t ) + sizeof( vec3_t ) + sizeof( vec4_t )))); - bufSize += ( numVerts + 2 ) * ( sizeof( vec3_t ) + sizeof( vec3_t )); // tangent and binormal - bufSize += ( numVerts + 2 ) * sizeof( rgba_t ); // color array - + bufSize = sizeof( msurfmesh_t ) + ( numVerts + 2 ) * sizeof( glvert_t ); // temp buffer has no indices buffer = Mem_Alloc( loadmodel->mempool, bufSize ); mesh = (msurfmesh_t *)buffer; @@ -1483,20 +1493,8 @@ static void Mod_SubdividePolygon( mextrasurf_t *info, msurface_t *surf, int numV VectorNormalize( binormal ); // setup pointers - mesh->vertices = (vec3_t *)buffer; - buffer += mesh->numVerts * sizeof( vec3_t ); - mesh->stcoords = (vec2_t *)buffer; - buffer += mesh->numVerts * sizeof( vec2_t ); - mesh->lmcoords = (vec2_t *)buffer; - buffer += mesh->numVerts * sizeof( vec2_t ); - mesh->normals = (vec3_t *)buffer; - buffer += mesh->numVerts * sizeof( vec3_t ); - mesh->tangent = (vec3_t *)buffer; - buffer += mesh->numVerts * sizeof( vec3_t ); - mesh->binormal = (vec3_t *)buffer; - buffer += mesh->numVerts * sizeof( vec3_t ); - mesh->colors = (byte *)buffer; - buffer += mesh->numVerts * sizeof( rgba_t ); + mesh->verts = (glvert_t *)buffer; + buffer += numVerts * sizeof( glvert_t ); VectorClear( vTotal ); VectorClear( nTotal ); @@ -1506,23 +1504,22 @@ static void Mod_SubdividePolygon( mextrasurf_t *info, msurface_t *surf, int numV totalST[0] = totalST[1] = 0; totalLM[0] = totalLM[1] = 0; - scale = (1.0f / tessSize ); - - // clear colors (it can be used for vertex lighting) - Q_memset( mesh->colors, 0xFF, mesh->numVerts * sizeof( rgba_t )); + scale = ( 1.0f / tessSize ); for( i = 0; i < numVerts; i++, verts += 3 ) { - // vertex - VectorCopy( verts, mesh->vertices[i+1] ); - VectorCopy( normal, mesh->normals[i+1] ); - VectorCopy( tangent, mesh->tangent[i+1] ); - VectorCopy( binormal, mesh->binormal[i+1] ); + glvert_t *out = &mesh->verts[i+1]; - VectorAdd( vTotal, mesh->vertices[i+1], vTotal ); - VectorAdd( nTotal, mesh->normals[i+1], nTotal ); - VectorAdd( tTotal, mesh->tangent[i+1], tTotal ); - VectorAdd( bTotal, mesh->binormal[i+1], bTotal ); + // 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 ) { @@ -1540,8 +1537,8 @@ static void Mod_SubdividePolygon( mextrasurf_t *info, msurface_t *surf, int numV t = DotProduct( verts, texinfo->vecs[1] ) * scale; } - mesh->stcoords[i+1][0] = s; - mesh->stcoords[i+1][1] = t; + out->stcoord[0] = s; + out->stcoord[1] = t; totalST[0] += s; totalST[1] += t; @@ -1564,40 +1561,38 @@ static void Mod_SubdividePolygon( mextrasurf_t *info, msurface_t *surf, int numV s = t = 0.0f; } - mesh->lmcoords[i+1][0] = s; - mesh->lmcoords[i+1][1] = t; + out->lmcoord[0] = s; + out->lmcoord[1] = t; totalLM[0] += s; totalLM[1] += t; + + // clear colors (it can be used for vertex lighting) + Q_memset( out->color, 0xFF, sizeof( out->color )); } // vertex oneDivVerts = ( 1.0f / (float)numVerts ); - VectorScale( vTotal, oneDivVerts, mesh->vertices[0] ); - VectorScale( nTotal, oneDivVerts, mesh->normals[0] ); - VectorScale( tTotal, oneDivVerts, mesh->tangent[0] ); - VectorScale( bTotal, oneDivVerts, mesh->binormal[0] ); + 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->normals[0] ); - VectorNormalize( mesh->tangent[0] ); - VectorNormalize( mesh->binormal[0] ); + VectorNormalize( mesh->verts[0].normal ); + VectorNormalize( mesh->verts[0].tangent ); + VectorNormalize( mesh->verts[0].binormal ); // texture coordinates - mesh->stcoords[0][0] = totalST[0] * oneDivVerts; - mesh->stcoords[0][1] = totalST[1] * oneDivVerts; + mesh->verts[0].stcoord[0] = totalST[0] * oneDivVerts; + mesh->verts[0].stcoord[1] = totalST[1] * oneDivVerts; // lightmap texture coordinates - mesh->lmcoords[0][0] = totalLM[0] * oneDivVerts; - mesh->lmcoords[0][1] = totalLM[1] * oneDivVerts; + mesh->verts[0].lmcoord[0] = totalLM[0] * oneDivVerts; + mesh->verts[0].lmcoord[1] = totalLM[1] * oneDivVerts; // copy first vertex to last - VectorCopy( mesh->vertices[1], mesh->vertices[i+1] ); - VectorCopy( mesh->normals[1], mesh->normals[i+1] ); - VectorCopy( mesh->tangent[1], mesh->tangent[i+1] ); - VectorCopy( mesh->binormal[1], mesh->binormal[i+1] ); - Vector2Copy( mesh->stcoords[1], mesh->stcoords[i+1] ); - Vector2Copy( mesh->lmcoords[1], mesh->lmcoords[i+1] ); + Q_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 @@ -1614,11 +1609,9 @@ turn the polychain into one subdivided surface static void Mod_ConvertSurface( mextrasurf_t *info, msurface_t *surf ) { msurfmesh_t *poly, *next, *mesh; - float *outSTcoords, *outLMcoords; - float *outTangent, *outBinorm; - float *outVerts, *outNorms; int numElems, numVerts; - word *outIndexes; + glvert_t *outVerts; + word *outElems; int i, bufSize; byte *buffer; @@ -1632,15 +1625,11 @@ static void Mod_ConvertSurface( mextrasurf_t *info, msurface_t *surf ) numVerts += poly->numVerts; } - // mesh + ( vertex, normal, (st + lmst) ) * numVerts + elem * numElems; - bufSize = sizeof( msurfmesh_t ) + numVerts * ( sizeof( vec3_t ) + sizeof( vec3_t ) + sizeof( vec4_t )) + numElems * sizeof( word ); - bufSize += numVerts * ( sizeof( vec3_t ) + sizeof( vec3_t )); // tangent and binormal - bufSize += numVerts * sizeof( rgba_t ); // color array - // 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; @@ -1650,73 +1639,34 @@ static void Mod_ConvertSurface( mextrasurf_t *info, msurface_t *surf ) mesh->numElems = numElems; // setup pointers - mesh->vertices = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->stcoords = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->lmcoords = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->normals = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->tangent = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->binormal = (vec3_t *)buffer; - buffer += numVerts * sizeof( vec3_t ); - mesh->colors = (byte *)buffer; - buffer += numVerts * sizeof( rgba_t ); - - mesh->indices = (word *)buffer; + mesh->verts = (glvert_t *)buffer; + buffer += numVerts * sizeof( glvert_t ); + mesh->elems = (word *)buffer; buffer += numElems * sizeof( word ); // setup moving pointers - outVerts = (float *)mesh->vertices; - outNorms = (float *)mesh->normals; - outTangent = (float *)mesh->tangent; - outBinorm = (float *)mesh->binormal; - outSTcoords = (float *)mesh->stcoords; - outLMcoords = (float *)mesh->lmcoords; - outIndexes = (word *)mesh->indices; + outVerts = (glvert_t *)mesh->verts; + outElems = (word *)mesh->elems; // store vertex data numElems = numVerts = 0; - // clear colors (it can be used for vertex lighting) - Q_memset( mesh->colors, 0xFF, numVerts * sizeof( rgba_t )); - for( poly = info->mesh; poly; poly = poly->next ) { // indexes - outIndexes = mesh->indices + numElems; - numElems += (poly->numVerts - 2) * 3; + outElems = mesh->elems + numElems; + outVerts = mesh->verts + numVerts; for( i = 0; i < poly->numVerts - 2; i++ ) { - outIndexes[i*3+0] = numVerts; - outIndexes[i*3+1] = numVerts + i + 1; - outIndexes[i*3+2] = numVerts + i + 2; + outElems[i*3+0] = numVerts; + outElems[i*3+1] = numVerts + i + 1; + outElems[i*3+2] = numVerts + i + 2; } - for( i = 0; i < poly->numVerts; i++ ) - { - // vertices - VectorCopy( poly->vertices[i], outVerts ); - VectorCopy( poly->normals[i], outNorms ); - VectorCopy( poly->tangent[i], outTangent ); - VectorCopy( poly->binormal[i], outBinorm ); - - outSTcoords[0] = poly->stcoords[i][0]; - outSTcoords[1] = poly->stcoords[i][1]; - outLMcoords[0] = poly->lmcoords[i][0]; - outLMcoords[1] = poly->lmcoords[i][1]; - - outVerts += 3; - outNorms += 3; - outBinorm += 3; - outTangent += 3; - outSTcoords += 2; - outLMcoords += 2; - } + Q_memcpy( outVerts, poly->verts, sizeof( glvert_t ) * poly->numVerts ); + numElems += (poly->numVerts - 2) * 3; numVerts += poly->numVerts; } @@ -2996,6 +2946,12 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash ) else MsgDev( D_ERROR, "Mod_ForName: %s couldn't load\n", tempname ); return NULL; } + else if( clgame.drawFuncs.Mod_ProcessUserData != NULL ) + { + // let the client.dll load custom data + clgame.drawFuncs.Mod_ProcessUserData( mod, true ); + } + return mod; } @@ -3028,6 +2984,8 @@ void Mod_LoadWorld( const char *name, uint *checksum, qboolean force ) // now replacement table is invalidate Q_memset( com_models, 0, sizeof( com_models )); + com_models[1] = cm_models; // make link to world + // update the lightmap blocksize if( host.features & ENGINE_LARGE_LIGHTMAPS ) world.block_size = BLOCK_SIZE_MAX; @@ -3036,7 +2994,6 @@ void Mod_LoadWorld( const char *name, uint *checksum, qboolean force ) if( !Q_stricmp( cm_models[0].name, name ) && !force ) { // singleplayer mode: server already loaded map - com_models[1] = cm_models; // make link to world if( checksum ) *checksum = world.checksum; // still have the right version @@ -3061,7 +3018,6 @@ void Mod_LoadWorld( const char *name, uint *checksum, qboolean force ) // load the newmap world.loading = true; worldmodel = Mod_ForName( name, true ); - com_models[1] = cm_models; // make link to world CRC32_MapFile( &world.checksum, worldmodel->name ); world.loading = false; diff --git a/game_launch/game.ncb b/game_launch/game.ncb index 321c09bd..0c3846f4 100644 Binary files a/game_launch/game.ncb and b/game_launch/game.ncb differ diff --git a/game_launch/game.opt b/game_launch/game.opt index 83526171..59eb66e5 100644 Binary files a/game_launch/game.opt and b/game_launch/game.opt differ diff --git a/game_launch/hl.exe b/game_launch/hl.exe new file mode 100644 index 00000000..e6339ac5 Binary files /dev/null and b/game_launch/hl.exe differ