diff --git a/common/render_api.h b/common/render_api.h index 2e2fe7c1..d1cb53c0 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -48,7 +48,7 @@ GNU General Public License for more details. #define PARM_TEX_CACHEFRAME 12 // compare with worldmodel->needload #define PARM_TEX_GLFORMAT 13 // get a texture GL-format #define PARM_TEX_ENCODE 14 // custom encoding for DXT image -// reserved +#define PARM_TEX_MIPCOUNT 15 // count of mipmaps (0 - autogenerated, 1 - disabled of mipmapping) #define PARM_WORLD_VERSION 16 // return the version of bsp #define PARM_SKY_SPHERE 17 // sky is quake sphere ? #define PARM_MAP_HAS_MIRRORS 18 // current map has mirorrs diff --git a/engine/client/cl_pmove.c b/engine/client/cl_pmove.c index 9ef703ff..01015faa 100644 --- a/engine/client/cl_pmove.c +++ b/engine/client/cl_pmove.c @@ -351,6 +351,9 @@ void CL_SetSolidPlayers( int playernum ) if( !state->solid ) continue; // not solid + if( !state->movetype ) + continue; // dead + pe = &clgame.pmove->physents[clgame.pmove->numphysent]; if( CL_CopyEntityToPhysEnt( pe, ent )) clgame.pmove->numphysent++; diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 08ed48e0..a6c767c9 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -977,7 +977,13 @@ void GL_GenerateMipmaps( byte *buffer, rgbdata_t *pic, gltexture_t *tex, GLenum { int mipLevel; int dataType = GL_UNSIGNED_BYTE; - int w, h; + int w, h, maxdim; + + mipLevel = 0; + w = tex->width; + h = tex->height; + maxdim = max( w, h ); + tex->numMips = 1; // always have mip #0 // not needs if( tex->flags & TF_NOMIPMAP ) @@ -988,16 +994,13 @@ void GL_GenerateMipmaps( byte *buffer, rgbdata_t *pic, gltexture_t *tex, GLenum pglHint( GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST ); pglTexParameteri( glTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE ); pglGetError(); // clear error queue on mips generate + while( maxdim >>= 1 ) tex->numMips++; return; } // screen texture? if( !buffer ) return; - mipLevel = 0; - w = tex->width; - h = tex->height; - // software mipmap generator while( w > 1 || h > 1 ) { @@ -1007,6 +1010,7 @@ void GL_GenerateMipmaps( byte *buffer, rgbdata_t *pic, gltexture_t *tex, GLenum w = (w+1)>>1; h = (h+1)>>1; + tex->numMips++; mipLevel++; if( subImage ) pglTexSubImage2D( tex->target + side, mipLevel, 0, 0, w, h, inFormat, dataType, buffer ); @@ -1109,8 +1113,7 @@ static void GL_UploadTextureDXT( rgbdata_t *pic, gltexture_t *tex, qboolean subI GLenum inFormat, glTarget; uint width, height, depth; int texsize = 0, samples; - uint i, j, s, numSides; - int numMips, err; + uint i, j, s, err, numSides; ASSERT( pic != NULL && tex != NULL ); @@ -1158,7 +1161,7 @@ static void GL_UploadTextureDXT( rgbdata_t *pic, gltexture_t *tex, qboolean subI // determine target tex->target = glTarget = GL_TEXTURE_2D; - numMips = (pic->numMips > 0) ? pic->numMips : 1; + tex->numMips = (pic->numMips > 0) ? pic->numMips : 1; numSides = 1; if( pic->flags & IMAGE_CUBEMAP ) @@ -1215,7 +1218,7 @@ static void GL_UploadTextureDXT( rgbdata_t *pic, gltexture_t *tex, qboolean subI height = pic->height; depth = pic->depth; - for( j = 0; j < numMips; j++ ) + for( j = 0; j < tex->numMips; j++ ) { width = max( 1, ( pic->width >> j )); height = max( 1, ( pic->height >> j )); @@ -1268,6 +1271,8 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag tex->fogParams[2] = pic->fogParams[2]; tex->fogParams[3] = pic->fogParams[3]; + tex->numMips = pic->numMips; + // NOTE: normalmaps must be power of two or software mip generator will stop working GL_RoundImageDimensions( &tex->width, &tex->height, tex->flags, ( tex->flags & TF_NORMALMAP )); diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index 033e1440..a64a7b83 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -64,6 +64,7 @@ typedef struct gltexture_s word srcHeight; word width; // upload width\height word height; + byte numMips; // mipmap count uint cacheframe; // worldmodel->load_sequence @@ -422,10 +423,8 @@ void R_InitSky( struct mip_s *mt, struct texture_s *tx ); void R_AddSkyBoxSurface( msurface_t *fa ); void R_ClearSkyBox( void ); void R_DrawSkyBox( void ); -void EmitSkyLayers( msurface_t *fa ); -void EmitSkyPolys( msurface_t *fa ); +void R_DrawClouds( void ); void EmitWaterPolys( glpoly_t *polys, qboolean noCull ); -void R_DrawSkyChain( msurface_t *s ); // // gl_vidnt.c diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index 9e209550..632e2efb 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -1409,6 +1409,9 @@ static int GL_RenderGetParm( int parm, int arg ) case PARM_TEX_ENCODE: glt = R_GetTexture( arg ); return glt->encode; + case PARM_TEX_MIPCOUNT: + glt = R_GetTexture( arg ); + return glt->numMips; case PARM_TEX_SKYBOX: ASSERT( arg >= 0 && arg < 6 ); return tr.skyboxTextures[arg]; diff --git a/engine/client/gl_rsurf.c b/engine/client/gl_rsurf.c index b0466608..263745c4 100644 --- a/engine/client/gl_rsurf.c +++ b/engine/client/gl_rsurf.c @@ -1088,15 +1088,8 @@ void R_RenderBrushPoly( msurface_t *fa ) else r_stats.c_brush_polys++; if( fa->flags & SURF_DRAWSKY ) - { - if( world.sky_sphere ) - { - // warp texture, no lightmaps - EmitSkyLayers( fa ); - } - return; - } - + return; // already handled + t = R_TextureAnimation( fa->texinfo->texture, fa - RI.currententity->model->surfaces ); if( RP_NORMALPASS() && fa->flags & SURF_REFLECT ) @@ -1130,7 +1123,7 @@ void R_RenderBrushPoly( msurface_t *fa ) return; } - if( t->fb_texturenum ) + if( t->fb_texturenum && fa->polys ) { // HACKHACK: store fullbrights in poly->next (only for non-water surfaces) fa->polys->next = fullbright_polys[t->fb_texturenum]; @@ -1251,31 +1244,40 @@ void R_DrawTextureChains( void ) RI.currententity = clgame.entities; RI.currentmodel = RI.currententity->model; + if( world.sky_sphere ) + { + pglDisable( GL_TEXTURE_2D ); + pglColor3f( 1.0f, 1.0f, 1.0f ); + } + // clip skybox surfaces for( s = skychain; s != NULL; s = s->texturechain ) R_AddSkyBoxSurface( s ); + if( world.sky_sphere ) + { + pglEnable( GL_TEXTURE_2D ); + + if( skychain ) + R_DrawClouds(); + skychain = NULL; + } + for( i = 0; i < cl.worldmodel->numtextures; i++ ) { t = cl.worldmodel->textures[i]; if( !t ) continue; s = t->texturechain; - if( !s ) continue; - if( i == tr.skytexturenum ) - { - if( world.sky_sphere ) - R_DrawSkyChain( s ); - } - else - { - if(( s->flags & SURF_DRAWTURB ) && cl.refdef.movevars->wateralpha < 1.0f ) - continue; // draw translucent water later + if( !s || ( i == tr.skytexturenum )) + continue; - for( ; s != NULL; s = s->texturechain ) - R_RenderBrushPoly( s ); - } + if(( s->flags & SURF_DRAWTURB ) && cl.refdef.movevars->wateralpha < 1.0f ) + continue; // draw translucent water later + + for( ; s != NULL; s = s->texturechain ) + R_RenderBrushPoly( s ); t->texturechain = NULL; } @@ -1553,7 +1555,7 @@ void R_DrawStaticModel( cl_entity_t *e ) if( R_CullSurface( psurf, RI.clipFlags )) continue; - if( psurf->flags & SURF_DRAWSKY && !world.sky_sphere ) + if( psurf->flags & SURF_DRAWSKY ) { // make sky chain to right clip the skybox psurf->texturechain = skychain; @@ -1679,7 +1681,7 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags ) if( R_CullSurface( surf, clipflags )) continue; - if( surf->flags & SURF_DRAWSKY && !world.sky_sphere ) + if( surf->flags & SURF_DRAWSKY ) { // make sky chain to right clip the skybox surf->texturechain = skychain; @@ -2168,9 +2170,6 @@ void GL_BuildLightmaps( void ) if( m->surfaces[j].flags & SURF_DRAWTURB ) continue; - if( m->surfaces[j].flags & SURF_DRAWSKY && world.sky_sphere ) - continue; - GL_BuildPolygonFromSurface( m, m->surfaces + j ); } diff --git a/engine/client/gl_warp.c b/engine/client/gl_warp.c index a8ddd4f8..4c7a1061 100644 --- a/engine/client/gl_warp.c +++ b/engine/client/gl_warp.c @@ -19,9 +19,9 @@ GNU General Public License for more details. #include "com_model.h" #include "wadfile.h" +#define SKYCLOUDS_QUALITY 12 #define MAX_CLIP_VERTS 64 // skybox clip vertices #define TURBSCALE ( 256.0f / ( M_PI2 )) -static float speedscale; static const char* r_skyBoxSuffix[6] = { "rt", "bk", "lf", "ft", "up", "dn" }; static const int r_skyTexOrder[6] = { 0, 2, 1, 3, 4, 5 }; @@ -304,6 +304,7 @@ void R_AddSkyBoxSurface( msurface_t *fa ) { vec3_t verts[MAX_CLIP_VERTS]; glpoly_t *p; + float *v; int i; if( r_fastsky->integer ) @@ -319,6 +320,20 @@ void R_AddSkyBoxSurface( msurface_t *fa ) } } + if( world.sky_sphere && fa->polys ) + { + glpoly_t *p = fa->polys; + + // draw the sky poly + pglBegin( GL_POLYGON ); + for( i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE ) + { + pglTexCoord2f( v[3], v[4] ); + pglVertex3fv( v ); + } + pglEnd (); + } + // calculate vertex values for sky box for( p = fa->polys; p; p = p->next ) { @@ -470,6 +485,179 @@ void R_SetupSky( const char *skyboxname ) R_UnloadSkybox(); } +//============================================================================== +// +// RENDER CLOUDS +// +//============================================================================== +/* +============== +R_CloudVertex +============== +*/ +void R_CloudVertex( float s, float t, int axis, vec3_t v ) +{ + int j, k, farclip; + vec3_t b; + + farclip = RI.farClip; + + b[0] = s * (farclip >> 1); + b[1] = t * (farclip >> 1); + b[2] = (farclip >> 1); + + for( j = 0; j < 3; j++ ) + { + k = st_to_vec[axis][j]; + v[j] = (k < 0) ? -b[-k-1] : b[k-1]; + v[j] += RI.cullorigin[j]; + } +} + +/* +============= +R_CloudTexCoord +============= +*/ +void R_CloudTexCoord( vec3_t v, float speed, float *s, float *t ) +{ + float length, speedscale; + vec3_t dir; + + speedscale = cl.time * speed; + speedscale -= (int)speedscale & ~127; + + VectorSubtract( v, RI.vieworg, dir ); + dir[2] *= 3.0f; // flatten the sphere + + length = VectorLength( dir ); + length = 6.0f * 63.0f / length; + + *s = ( speedscale + dir[0] * length ) * (1.0f / 128.0f); + *t = ( speedscale + dir[1] * length ) * (1.0f / 128.0f); +} + +/* +=============== +Sky_DrawFaceQuad +=============== +*/ +void R_CloudDrawPoly( glpoly_t *p ) +{ + float s, t; + float *v; + int i; + + GL_SetRenderMode( kRenderNormal ); + GL_Bind( GL_TEXTURE0, tr.solidskyTexture ); + + pglBegin( GL_QUADS ); + for( i = 0, v = p->verts[0]; i < 4; i++, v += VERTEXSIZE ) + { + R_CloudTexCoord( v, 8.0f, &s, &t ); + pglTexCoord2f( s, t ); + pglVertex3fv( v ); + } + pglEnd(); + + GL_SetRenderMode( kRenderTransTexture ); + GL_Bind( GL_TEXTURE0, tr.alphaskyTexture ); + + pglBegin( GL_QUADS ); + for( i = 0, v = p->verts[0]; i < 4; i++, v += VERTEXSIZE ) + { + R_CloudTexCoord( v, 16.0f, &s, &t ); + pglTexCoord2f( s, t ); + pglVertex3fv( v ); + } + pglEnd(); + + pglDisable( GL_BLEND ); +} + +/* +============== +R_CloudRenderSide +============== +*/ +void R_CloudRenderSide( int axis ) +{ + vec3_t verts[4]; + float di, qi, dj, qj; + vec3_t vup, vright; + vec3_t temp, temp2; + glpoly_t p[1]; + int i, j; + + R_CloudVertex( -1.0f, -1.0f, axis, verts[0] ); + R_CloudVertex( -1.0f, 1.0f, axis, verts[1] ); + R_CloudVertex( 1.0f, 1.0f, axis, verts[2] ); + R_CloudVertex( 1.0f, -1.0f, axis, verts[3] ); + + VectorSubtract( verts[2], verts[3], vup ); + VectorSubtract( verts[2], verts[1], vright ); + + p->numverts = 4; + di = SKYCLOUDS_QUALITY; + qi = 1.0 / di; + dj = (axis < 4) ? di * 2 : di; //subdivide vertically more than horizontally on skybox sides + qj = 1.0 / dj; + + for( i = 0; i < di; i++ ) + { + for( j = 0; j < dj; j++ ) + { + if( i * qi < RI.skyMins[0][axis] / 2 + 0.5f - qi + || i * qi > RI.skyMaxs[0][axis] / 2 + 0.5f + || j * qj < RI.skyMins[1][axis] / 2 + 0.5f - qj + || j * qj > RI.skyMaxs[1][axis] / 2 + 0.5f ) + continue; + + VectorScale( vright, qi * i, temp ); + VectorScale( vup, qj * j, temp2 ); + VectorAdd( temp, temp2, temp ); + VectorAdd( verts[0], temp, p->verts[0] ); + + VectorScale( vup, qj, temp ); + VectorAdd( p->verts[0], temp, p->verts[1] ); + + VectorScale( vright, qi, temp ); + VectorAdd( p->verts[1], temp, p->verts[2] ); + + VectorAdd( p->verts[0], temp, p->verts[3] ); + + R_CloudDrawPoly( p ); + } + } +} + +/* +============== +R_DrawClouds + +Quake-style clouds +============== +*/ +void R_DrawClouds( void ) +{ + int i; + + RI.isSkyVisible = true; + + pglDepthFunc( GL_GEQUAL ); + pglDepthMask( 0 ); + + for( i = 0; i < 6; i++ ) + { + if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] ) + continue; + R_CloudRenderSide( i ); + } + + pglDepthMask( GL_TRUE ); + pglDepthFunc( GL_LEQUAL ); +} + /* ============= R_InitSky @@ -634,103 +822,4 @@ void EmitWaterPolys( glpoly_t *polys, qboolean noCull ) if( noCull ) pglEnable( GL_CULL_FACE ); GL_SetupFogColorForSurfaces(); -} - -/* -============= -EmitSkyPolys -============= -*/ -void EmitSkyPolys( msurface_t *fa ) -{ - glpoly_t *p; - float *v; - int i; - float s, t; - vec3_t dir; - float length; - - for( p = fa->polys; p; p = p->next ) - { - pglBegin( GL_POLYGON ); - - for( i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE ) - { - VectorSubtract( v, RI.vieworg, dir ); - dir[2] *= 3.0f; // flatten the sphere - - length = VectorLength( dir ); - length = 6.0f * 63.0f / length; - - dir[0] *= length; - dir[1] *= length; - - s = ( speedscale + dir[0] ) * (1.0f / 128.0f); - t = ( speedscale + dir[1] ) * (1.0f / 128.0f); - - pglTexCoord2f( s, t ); - pglVertex3fv( v ); - } - pglEnd (); - } -} - -/* -================= -R_DrawSkyChain -================= -*/ -void R_DrawSkyChain( msurface_t *s ) -{ - msurface_t *fa; - - GL_SetRenderMode( kRenderNormal ); - GL_Bind( GL_TEXTURE0, tr.solidskyTexture ); - - speedscale = cl.time * 8.0f; - speedscale -= (int)speedscale & ~127; - - for( fa = s; fa; fa = fa->texturechain ) - EmitSkyPolys( fa ); - - GL_SetRenderMode( kRenderTransTexture ); - GL_Bind( GL_TEXTURE0, tr.alphaskyTexture ); - - speedscale = cl.time * 16.0f; - speedscale -= (int)speedscale & ~127; - - for( fa = s; fa; fa = fa->texturechain ) - EmitSkyPolys( fa ); - - pglDisable( GL_BLEND ); -} - -/* -=============== -EmitBothSkyLayers - -Does a sky warp on the pre-fragmented glpoly_t chain -This will be called for brushmodels, the world -will have them chained together. -=============== -*/ -void EmitSkyLayers( msurface_t *fa ) -{ - GL_SetRenderMode( kRenderNormal ); - GL_Bind( GL_TEXTURE0, tr.solidskyTexture ); - - speedscale = cl.time * 8.0f; - speedscale -= (int)speedscale & ~127; - - EmitSkyPolys( fa ); - - GL_SetRenderMode( kRenderTransTexture ); - GL_Bind( GL_TEXTURE0, tr.alphaskyTexture ); - - speedscale = cl.time * 16.0f; - speedscale -= (int)speedscale & ~127; - - EmitSkyPolys( fa ); - - pglDisable( GL_BLEND ); } \ No newline at end of file diff --git a/engine/common/model.c b/engine/common/model.c index 234470ff..bb7a67b4 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -1726,7 +1726,7 @@ void Mod_BuildSurfacePolygons( msurface_t *surf, mextrasurf_t *info ) } // subdivide water or sky sphere for Quake1 maps - if(( surf->flags & SURF_DRAWTURB && !( surf->flags & SURF_REFLECT )) || ( surf->flags & SURF_DRAWSKY && world.loading && world.sky_sphere )) + if( surf->flags & SURF_DRAWTURB && !( surf->flags & SURF_REFLECT )) { Mod_SubdividePolygon( info, surf, surf->numedges, verts[0], 64.0f ); Mod_ConvertSurface( info, surf ); @@ -1905,9 +1905,6 @@ static void Mod_LoadSurfaces( const dlump_t *l ) if( host.features & ENGINE_BUILD_SURFMESHES && (( out->flags & SURF_DRAWTILED ) || !out->samples )) Mod_BuildSurfacePolygons( out, info ); - if( out->flags & SURF_DRAWSKY && world.loading && world.sky_sphere ) - GL_SubdivideSurface( out ); // cut up polygon for warps - if( out->flags & SURF_DRAWTURB ) GL_SubdivideSurface( out ); // cut up polygon for warps } diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index c9a7099f..9ae71da8 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -804,7 +804,11 @@ void Delta_Init( void ) Delta_AddField( "movevars_t", "bounce", DT_FLOAT|DT_SIGNED, 16, 8.0f, 1.0f ); Delta_AddField( "movevars_t", "stepsize", DT_FLOAT|DT_SIGNED, 16, 16.0f, 1.0f ); Delta_AddField( "movevars_t", "maxvelocity", DT_FLOAT|DT_SIGNED, 16, 8.0f, 1.0f ); - Delta_AddField( "movevars_t", "zmax", DT_FLOAT|DT_SIGNED, 18, 1.0f, 1.0f ); // no fractional part + + if( host.features & ENGINE_WRITE_LARGE_COORD ) + Delta_AddField( "movevars_t", "zmax", DT_FLOAT|DT_SIGNED, 18, 1.0f, 1.0f ); + else Delta_AddField( "movevars_t", "zmax", DT_FLOAT|DT_SIGNED, 16, 1.0f, 1.0f ); + Delta_AddField( "movevars_t", "waveHeight", DT_FLOAT|DT_SIGNED, 16, 16.0f, 8.0f ); Delta_AddField( "movevars_t", "skyName", DT_STRING, 1, 1.0f, 1.0f ); Delta_AddField( "movevars_t", "footsteps", DT_INTEGER, 1, 1.0f, 1.0f );