diff options
| author | Andrey Nazarov <skuller@skuller.net> | 2007-11-17 19:27:42 +0000 |
|---|---|---|
| committer | Andrey Nazarov <skuller@skuller.net> | 2007-11-17 19:27:42 +0000 |
| commit | b068abb528d8a705894cb3acd0696bd01ffa72d5 (patch) | |
| tree | f62c52328dbb701d49b1f99e4b770500642e895b | |
| parent | 4f6e8a36bdf9038bba73fafcba96c4438d8f7ce0 (diff) | |
Yet another batched update.
Fixed munmap() hang in OSS_Shutdown().
Added (crappy) SDL audio driver, but ALSA should work now.
Made r_maxfps and cl_maxfps really separate with cl_async 1.
This way, any configuration is allowed (e.g. r_maxfps 60, cl_maxfps 120).
Implemented water warping via fragment program, removed subdivision code.
Removed (crappy) dynamic lighting.
Removed surface sorting and batching.
Minimized vertex copying operations.
Implemented celshading.
Removed S_RawSamples and friends.
Smooth handling of smaller ladder steps (e.g. those on q2next2).
| -rw-r--r-- | build/q2pro.mk | 2 | ||||
| -rwxr-xr-x | configure | 2 | ||||
| -rw-r--r-- | source/cl_ents.c | 3 | ||||
| -rw-r--r-- | source/cl_input.c | 31 | ||||
| -rw-r--r-- | source/cl_local.h | 2 | ||||
| -rw-r--r-- | source/cl_main.c | 124 | ||||
| -rw-r--r-- | source/cl_parse.c | 6 | ||||
| -rw-r--r-- | source/cl_pred.c | 19 | ||||
| -rw-r--r-- | source/com_public.h | 2 | ||||
| -rw-r--r-- | source/cvar.c | 5 | ||||
| -rw-r--r-- | source/gl_images.c | 88 | ||||
| -rw-r--r-- | source/gl_local.h | 19 | ||||
| -rw-r--r-- | source/gl_main.c | 101 | ||||
| -rw-r--r-- | source/gl_mesh.c | 46 | ||||
| -rw-r--r-- | source/gl_state.c | 110 | ||||
| -rw-r--r-- | source/gl_surf.c | 212 | ||||
| -rw-r--r-- | source/gl_tess.c | 1074 | ||||
| -rw-r--r-- | source/gl_world.c | 186 | ||||
| -rw-r--r-- | source/q_shared.h | 11 | ||||
| -rw-r--r-- | source/qgl_api.c | 20 | ||||
| -rw-r--r-- | source/qgl_api.h | 10 | ||||
| -rw-r--r-- | source/r_shared.h | 1 | ||||
| -rw-r--r-- | source/snd_dx.c | 46 | ||||
| -rw-r--r-- | source/snd_local.h | 12 | ||||
| -rw-r--r-- | source/snd_main.c | 241 | ||||
| -rw-r--r-- | source/snd_mix.c | 348 | ||||
| -rw-r--r-- | source/snd_oss.c | 54 | ||||
| -rw-r--r-- | source/snd_sdl.c | 147 | ||||
| -rw-r--r-- | source/snd_wave.c | 32 | ||||
| -rw-r--r-- | source/sv_game.c | 2 |
30 files changed, 950 insertions, 2006 deletions
diff --git a/build/q2pro.mk b/build/q2pro.mk index 9dab12a..8beaa8b 100644 --- a/build/q2pro.mk +++ b/build/q2pro.mk @@ -117,7 +117,7 @@ ASMFILES+=snd_mixa.s LDFLAGS+=-ldl ifdef USE_SDL -SRCFILES+=vid_sdl.c +SRCFILES+=vid_sdl.c snd_sdl.c CFLAGS+=$(SDL_CFLAGS) LDFLAGS+=-lX11 $(SDL_LDFLAGS) endif @@ -297,6 +297,8 @@ if [ "$client" = "yes" ]; then libraries="$libraries mod_ui$libsuffix" fi fi +else + sdl="no" fi if [ "$server" = "yes" ]; then diff --git a/source/cl_ents.c b/source/cl_ents.c index aa9e6e3..07b1fd6 100644 --- a/source/cl_ents.c +++ b/source/cl_ents.c @@ -841,6 +841,9 @@ static void CL_CalcViewValues( void ) { // smooth out stair climbing delta = cls.realtime - cl.predicted_step_time; + if( cl.predicted_step < 16 ) { + delta <<= 1; // small steps + } if( delta < 100 ) { cl.refdef.vieworg[2] -= cl.predicted_step * ( 100 - delta ) * 0.01f; } diff --git a/source/cl_input.c b/source/cl_input.c index 6899bf3..eb5c475 100644 --- a/source/cl_input.c +++ b/source/cl_input.c @@ -434,11 +434,34 @@ static float CL_KeyState( kbutton_t *key ) { // FIXME: always discrete? static float CL_ImmKeyState( kbutton_t *key ) { +#if 0 if( key->state & 1 ) { return 1; } return 0; +#else + float val; + uint32 msec; + + msec = key->msec; + + if( key->state & 1 ) { + // still down + if( com_eventTime > key->downtime ) { + msec += com_eventTime - key->downtime; + } + } + + if( !frame_msec ) { + return 0; + } + val = ( float )msec / frame_msec; + + clamp( val, 0, 1 ); + + return val; +#endif } @@ -520,15 +543,15 @@ CL_AdjustAngles Moves the local angle positions ================ */ -static void CL_AdjustAngles (void) +static void CL_AdjustAngles (int msec) { float speed; float up, down; if (in_speed.state & 1) - speed = cls.frametime * cl_anglespeedkey->value; + speed = msec * cl_anglespeedkey->value * 0.001f; else - speed = cls.frametime; + speed = msec * 0.001f; if (!(in_strafe.state & 1)) { @@ -652,7 +675,7 @@ void CL_UpdateCmd( int msec ) { } // adjust viewangles - CL_AdjustAngles(); + CL_AdjustAngles( msec ); // get basic movement from keyboard CL_ImmBaseMove(); diff --git a/source/cl_local.h b/source/cl_local.h index 44f42e9..30499f6 100644 --- a/source/cl_local.h +++ b/source/cl_local.h @@ -173,7 +173,9 @@ typedef struct client_state_s { char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]; char mapname[MAX_QPATH]; // short format - q2dm1, etc +#if USE_AUTOREPLY int replyTime; +#endif char loadingString[MAX_QPATH]; diff --git a/source/cl_main.c b/source/cl_main.c index 840e776..53beca7 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -2474,6 +2474,7 @@ static void CL_MeasureFPS( void ) { cls.measureFramecount++; } +#if USE_AUTOREPLY /* ==================== CL_CheckForReply @@ -2494,6 +2495,22 @@ static void CL_CheckForReply( void ) { cl.replyTime = 0; } +#endif + +static void CL_CheckTimeout( void ) { + if( cls.netchan->last_received > com_localTime ) { + cls.netchan->last_received = com_localTime; + } + if( com_localTime - cls.netchan->last_received > cl_timeout->value * 1000 ) + { + // timeoutcount saves debugger + if ( ++cl.timeoutcount > 5 ) { + Com_Error( ERR_DISCONNECT, "Server connection timed out." ); + } + } else { + cl.timeoutcount = 0; + } +} /* @@ -2503,40 +2520,40 @@ CL_Frame ================== */ void CL_Frame( int msec ) { - static int main_extra; - static int phys_extra; - int main_msec; - int phys_msec; - qboolean phys_frame; + static int ref_extra, phys_extra, main_extra; + int ref_msec, phys_msec; + qboolean phys_frame, ref_frame; time_after_ref = time_before_ref = 0; if( !cl_running->integer ) { + // still run cmd buffer in dedicated mode if( cmd_buffer.waitCount > 0 ) { cmd_buffer.waitCount--; } return; } - main_extra += msec; + ref_extra += msec; + main_extra += msec; cls.realtime += msec; - main_msec = 1; + ref_msec = 1; if( cl_async->integer ) { phys_extra += msec; - phys_frame = qfalse; + phys_frame = qtrue; Cvar_ClampInteger( cl_maxfps, 10, 120 ); phys_msec = 1000 / cl_maxfps->integer; - if( phys_extra >= phys_msec ) { - phys_frame = qtrue; + if( phys_extra < phys_msec ) { + phys_frame = qfalse; } if( r_maxfps->integer ) { if( r_maxfps->integer < 10 ) { Cvar_Set( "r_maxfps", "10" ); } - main_msec = 1000 / r_maxfps->integer; + ref_msec = 1000 / r_maxfps->integer; } } else { phys_frame = qtrue; @@ -2544,10 +2561,11 @@ void CL_Frame( int msec ) { if( cl_maxfps->integer < 10 ) { Cvar_Set( "cl_maxfps", "10" ); } - main_msec = 1000 / cl_maxfps->integer; + ref_msec = 1000 / cl_maxfps->integer; } } - + + ref_frame = qtrue; if( !com_timedemo->integer ) { if( !sv_running->integer ) { if( !cls.appactive ) { @@ -2564,8 +2582,11 @@ void CL_Frame( int msec ) { } } } - if( main_extra < main_msec ) { - return; + if( ref_extra < ref_msec ) { + if( !cl_async->integer ) { + return; // everything ticks in sync with refresh + } + ref_frame = qfalse; } } @@ -2599,67 +2620,61 @@ void CL_Frame( int msec ) { // calculate local time CL_SetClientTime(); +#if USE_AUTOREPLY + // check for version reply CL_CheckForReply(); +#endif + + // resend a connection request if necessary + CL_CheckForResend(); - // read user intentions - CL_UpdateCmd( main_extra ); + // read user intentions + CL_UpdateCmd( main_extra ); - // finalize pending cmd - if( phys_frame || cl.sendPacketNow ) { - CL_FinalizeCmd(); - phys_extra = 0; - } + // finalize pending cmd + phys_frame |= cl.sendPacketNow; + if( phys_frame ) { + CL_FinalizeCmd(); + phys_extra = 0; + } - // send pending intentions - CL_SendCmd(); + // send pending cmds + CL_SendCmd(); // predict all unacknowledged movements CL_PredictMovement(); - // resend a connection request if necessary - CL_CheckForResend(); + if( ref_frame ) { + // update the screen + if ( host_speeds->integer ) + time_before_ref = Sys_Milliseconds(); - // update the screen - if ( host_speeds->integer ) - time_before_ref = Sys_Milliseconds(); + SCR_UpdateScreen(); - SCR_UpdateScreen(); + if ( host_speeds->integer ) + time_after_ref = Sys_Milliseconds(); - if ( host_speeds->integer ) - time_after_ref = Sys_Milliseconds(); + // update audio after the 3D view was drawn + S_Update(); - // update audio after the 3D view was drawn - S_Update(); + ref_extra = 0; + } // advance local effects for next frame CL_RunDLights(); CL_RunLightStyles(); Con_RunConsole(); + // check connection timeout + if( cls.netchan ) { + CL_CheckTimeout(); + } + CL_MeasureFPS(); - main_extra = 0; cls.framecount++; - // - // check timeout - // - if( !cls.netchan ) { - return; - } - - if( cls.netchan->last_received > com_localTime ) { - cls.netchan->last_received = com_localTime; - } - if( com_localTime - cls.netchan->last_received > cl_timeout->value * 1000 ) - { - // timeoutcount saves debugger - if ( ++cl.timeoutcount > 5 ) { - Com_Error( ERR_DISCONNECT, "Server connection timed out." ); - } - } else { - cl.timeoutcount = 0; - } + main_extra = 0; } //============================================================================ @@ -2705,7 +2720,6 @@ void CL_Init( void ) { #endif SZ_Init( &cls.demobuff, demo_buffer, sizeof( demo_buffer ) ); - cls.demobuff.allowoverflow = qtrue; UI_OpenMenu( UIMENU_MAIN ); diff --git a/source/cl_parse.c b/source/cl_parse.c index 4ead25a..ae87e4a 100644 --- a/source/cl_parse.c +++ b/source/cl_parse.c @@ -1032,7 +1032,7 @@ noskin: Com_sprintf( weapon_filename, sizeof( weapon_filename ), "players/%s/%s", model_name, cl.weaponModels[i] ); ci->weaponmodel[i] = ref.RegisterModel( weapon_filename ); - if( !ci->weaponmodel[i] && strcmp( model_name, "cyborg" ) == 0 ) { + if( !ci->weaponmodel[i] && !Q_stricmp( model_name, "cyborg" ) ) { // try male Com_sprintf( weapon_filename, sizeof( weapon_filename ), "players/male/%s", cl.weaponModels[i] ); @@ -1195,6 +1195,7 @@ static void CL_ParseReconnect( void ) { cls.connectCount = 0; } +#if USE_AUTOREPLY /* ==================== CL_CheckForVersion @@ -1222,6 +1223,7 @@ static void CL_CheckForVersion( const char *string ) { cl.replyTime = cls.realtime + 1024 + ( rand() & 1023 ); } +#endif /* @@ -1245,7 +1247,9 @@ static void CL_ParsePrint( void ) { return; } +#if USE_AUTOREPLY CL_CheckForVersion( string ); +#endif // disable notify if( !cl_chat_notify->integer ) { diff --git a/source/cl_pred.c b/source/cl_pred.c index f8dd9a1..5b40653 100644 --- a/source/cl_pred.c +++ b/source/cl_pred.c @@ -33,7 +33,7 @@ void CL_CheckPredictionError( void ) { int len; player_state_t *ps; - if( cls.demoplayback ) { + if( !cls.netchan ) { return; } @@ -51,6 +51,8 @@ void CL_CheckPredictionError( void ) { frame = cls.netchan->incoming_acknowledged & CMD_MASK; i = cl.history[frame].cmdNumber & CMD_MASK; + //if( cl.history[frame].cmdNumber>cl.predicted_step_frame) Com_Printf( "wtf?!!\n" ); + // compare what the server returned with what we had predicted it to be VectorSubtract( ps->pmove.origin, cl.predicted_origins[i], delta ); @@ -250,7 +252,7 @@ void CL_PredictMovement( void ) { return; } - if( !cl_async->integer && current == ack ) { + if( !cl.cmd.msec && current == ack ) { if( cl_showmiss->integer ) { Com_Printf( "%i: not moved\n", cl.frame.number ); } @@ -291,16 +293,13 @@ void CL_PredictMovement( void ) { frame = current - 1; } - oldz = cl.predicted_origins[frame & CMD_MASK][2]; + oldz = cl.predicted_origins[cl.predicted_step_frame & CMD_MASK][2]; step = pm.s.origin[2] - oldz; - if( cl.predicted_step_frame != frame && - step > 63 && step < 160 && - ( pm.s.pm_flags & PMF_ON_GROUND ) ) - { - cl.predicted_step = step * 0.125; - cl.predicted_step_time = cls.realtime - cls.frametime * 500; - cl.predicted_step_frame = frame; + if( step > 63 && step < 160 && ( pm.s.pm_flags & PMF_ON_GROUND ) ) { + cl.predicted_step = step * 0.125f; + cl.predicted_step_time = cls.realtime;/// - cls.frametime * 500; } + cl.predicted_step_frame = frame; // copy results out for rendering VectorScale( pm.s.origin, 0.125f, cl.predicted_origin ); diff --git a/source/com_public.h b/source/com_public.h index 26809d3..dc17047 100644 --- a/source/com_public.h +++ b/source/com_public.h @@ -94,7 +94,7 @@ typedef enum { #define CVAR_LATCHED 256 #define CVAR_USER_CREATED 512 #define CVAR_DEFAULTS_MIXED 1024 -#define CVAR_LOCAL 2048 +#define CVAR_GAME 2048 #define CVAR_INFOMASK (CVAR_USERINFO|CVAR_SERVERINFO) #define CVAR_EXTENDED_MASK (~31) diff --git a/source/cvar.c b/source/cvar.c index acb1911..5126164 100644 --- a/source/cvar.c +++ b/source/cvar.c @@ -250,7 +250,7 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { flags &= ~CVAR_USER_CREATED; } - var->flags |= flags; + var->flags |= flags & ~CVAR_GAME; return var; } @@ -622,6 +622,8 @@ void Cvar_GetLatchedVars( void ) { cvar_t *var; for( var = cvar_vars; var; var = var->next ) { + if( var->flags & CVAR_GAME ) + var->flags &= ~CVAR_SERVERINFO; if( !(var->flags & CVAR_LATCH) ) continue; if( var->flags & CVAR_LATCHED ) @@ -968,6 +970,7 @@ int Cvar_BitInfo( char *info, int bit ) { if( !( var->flags & bit ) ) { continue; } + if( !var->string[0] ) { continue; } diff --git a/source/gl_images.c b/source/gl_images.c index f023da0..5622ced 100644 --- a/source/gl_images.c +++ b/source/gl_images.c @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. image_t *r_notexture; image_t *r_particletexture; image_t *r_beamtexture; -image_t *r_dlightTex; +image_t *r_warptexture; image_t *r_whiteimage; int gl_filter_min; @@ -932,38 +932,7 @@ static void gl_gamma_changed( cvar_t *self ) { video.UpdateGamma( gammatable ); } -#define DLIGHT_TEXTURE_SIZE 16 - -static void GL_InitDlightTexture( void ) { - byte pixels[DLIGHT_TEXTURE_SIZE*DLIGHT_TEXTURE_SIZE*4]; - byte *dst; - float x, y, f; - int i, j; - - dst = pixels; - for( i = 0; i < DLIGHT_TEXTURE_SIZE; i++ ) { - for( j = 0; j < DLIGHT_TEXTURE_SIZE; j++ ) { - x = j - DLIGHT_TEXTURE_SIZE/2 + 0.5f; - y = i - DLIGHT_TEXTURE_SIZE/2 + 0.5f; - f = sqrt( x * x + y * y ); - f = 1.0f - f / ( DLIGHT_TEXTURE_SIZE/2 - 1.5f ); - if( f < 0 ) f = 0; - else if( f > 1 ) f = 1; - dst[0] = 255 * f; - dst[1] = 255 * f; - dst[2] = 255 * f; - dst[3] = 255; - dst += 4; - } - } - - r_dlightTex = R_CreateImage( "*dlightTexture", pixels, DLIGHT_TEXTURE_SIZE, - DLIGHT_TEXTURE_SIZE, it_pic, if_auto ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); -} - -static byte dottexture[8][8] = { +static const byte dottexture[8][8] = { {0,0,0,0,0,0,0,0}, {0,0,1,1,0,0,0,0}, {0,1,1,1,1,0,0,0}, @@ -1028,22 +997,21 @@ static void GL_InitWhiteImage( void ) { } } - r_whiteimage = R_CreateImage( "*whiteimage", pixels, 8, 8, it_pic, if_auto ); + r_whiteimage = R_CreateImage( "*whiteimage", pixels, 8, 8, + it_pic, if_auto ); } -#define BEAM_TEXTURE_SIZE 16 - static void GL_InitBeamTexture( void ) { - byte pixels[BEAM_TEXTURE_SIZE*BEAM_TEXTURE_SIZE*4]; + byte pixels[16*16*4]; byte *dst; float f; int i, j; dst = pixels; - for( i = 0; i < BEAM_TEXTURE_SIZE; i++ ) { - for( j = 0; j < BEAM_TEXTURE_SIZE; j++ ) { - f = fabs( j - BEAM_TEXTURE_SIZE/2 ) - 0.5f; - f = 1.0f - f / ( BEAM_TEXTURE_SIZE/2 - 2.5f ); + for( i = 0; i < 16; i++ ) { + for( j = 0; j < 16; j++ ) { + f = fabs( j - 16/2 ) - 0.5f; + f = 1.0f - f / ( 16/2 - 2.5f ); if( f < 0 ) f = 0; else if( f > 1 ) f = 1; dst[0] = 255 * f; @@ -1054,24 +1022,32 @@ static void GL_InitBeamTexture( void ) { } } - r_beamtexture = R_CreateImage( "*beamTexture", pixels, BEAM_TEXTURE_SIZE, - BEAM_TEXTURE_SIZE, it_pic, if_auto ); + r_beamtexture = R_CreateImage( "*beamTexture", pixels, 16, 16, + it_pic, if_auto ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - // qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); - // qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); - /* - { - float borderColor[4]; - - borderColor[0] = 1; - borderColor[1] = 1; - borderColor[2] = 1; - borderColor[3] = 0; +} - qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor ); +static void GL_InitWarpTexture( void ) { + byte pixels[8*8*4]; + byte *dst; + int i, j; + + dst = pixels; + for( i = 0; i < 8; i++ ) { + for( j = 0; j < 8; j++ ) { + dst[0] = rand() & 255; + dst[1] = rand() & 255; + dst[2] = 255; + dst[3] = 255; + dst += 4; + } } - */ + + r_warptexture = R_CreateImage( "*warpTexture", pixels, 8, 8, + it_pic, if_auto ); + qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); } /* @@ -1148,7 +1124,7 @@ void GL_InitImages( void ) { /* make sure r_notexture == &r_images[0] */ GL_InitDefaultTexture(); - GL_InitDlightTexture(); + GL_InitWarpTexture(); GL_InitParticleTexture(); GL_InitWhiteImage(); GL_InitBeamTexture(); diff --git a/source/gl_local.h b/source/gl_local.h index 9ed3dfb..2efd669 100644 --- a/source/gl_local.h +++ b/source/gl_local.h @@ -43,6 +43,7 @@ typedef struct { int maxTextureSize; qboolean registering; uint32 palette[256]; /* cinematic palette */ + GLuint prog_warp; } glStatic_t; typedef struct { @@ -81,17 +82,17 @@ typedef struct { extern statCounters_t c; +extern cvar_t *gl_celshading; extern cvar_t *gl_partscale; extern cvar_t *gl_znear; extern cvar_t *gl_zfar; extern cvar_t *gl_modulate; extern cvar_t *gl_showtris; extern cvar_t *gl_cull_nodes; +extern cvar_t *gl_bind; extern cvar_t *gl_clear; extern cvar_t *gl_novis; extern cvar_t *gl_lockpvs; -extern cvar_t *gl_primitives; -extern cvar_t *gl_sort; extern cvar_t *gl_subdivide; extern cvar_t *gl_fastsky; extern cvar_t *gl_dynamic; @@ -112,6 +113,8 @@ glCullResult_t GL_CullLocalBox( const vec3_t origin, vec3_t bounds[2] ); void GL_DrawBox( const vec3_t origin, vec3_t bounds[2] ); +void GL_ShowErrors( const char *func ); + /* * gl_model.c * @@ -252,6 +255,10 @@ void GL_Bits( glStateBits_t bits ); void GL_Setup2D( void ); void GL_Setup3D( void ); +void GL_SetDefaultState( void ); +void GL_InitPrograms( void ); +void GL_ShutdownPrograms( void ); + /* * gl_draw.c @@ -296,7 +303,7 @@ void Draw_Stats( void ); extern image_t *r_notexture; extern image_t *r_particletexture; extern image_t *r_beamtexture; -extern image_t *r_dlightTex; +extern image_t *r_warptexture; extern image_t *r_whiteimage; extern int gl_filter_min; @@ -333,13 +340,13 @@ typedef struct { int numIndices; int numFaces; vec_t vertices[4*TESS_MAX_VERTICES]; + vec_t normals[4*TESS_MAX_VERTICES]; byte colors[4*TESS_MAX_VERTICES]; tcoord_t tcoords[TESS_MAX_VERTICES]; tcoord_t lmtcoords[TESS_MAX_VERTICES]; int indices[TESS_MAX_INDICES]; bspSurface_t *faces[TESS_MAX_FACES]; int texnum; - int lightmapnum; qboolean istrans; } tesselator_t; @@ -350,9 +357,7 @@ void EndSurface_Single( void ); void Tess_DrawSurfaceTriangles( int *indices, int numIndices ); -void GL_AddBspSurface( bspSurface_t *surf ); -void GL_DrawSurfPoly( bspSurface_t *surf ); -void GL_SortAndDrawSurfs( qboolean doSort ); +void GL_DrawSurf( bspSurface_t *surf ); void GL_StretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, const byte *color, image_t *image ); void GL_Flush2D( void ); diff --git a/source/gl_main.c b/source/gl_main.c index ffc7c27..f4b1b25 100644 --- a/source/gl_main.c +++ b/source/gl_main.c @@ -47,6 +47,7 @@ cvar_t *gl_screenshot_quality; #if USE_PNG cvar_t *gl_screenshot_compression; #endif +cvar_t *gl_celshading; cvar_t *gl_znear; cvar_t *gl_zfar; cvar_t *gl_modulate; @@ -57,15 +58,15 @@ cvar_t *gl_showtris; cvar_t *gl_cull_nodes; cvar_t *gl_cull_models; cvar_t *gl_showstats; +cvar_t *gl_bind; cvar_t *gl_clear; cvar_t *gl_novis; cvar_t *gl_lockpvs; -cvar_t *gl_sort; -cvar_t *gl_primitives; -cvar_t *gl_sort; cvar_t *gl_subdivide; cvar_t *gl_fastsky; +#if USE_DYNAMIC cvar_t *gl_dynamic; +#endif cvar_t *gl_fullbright; cvar_t *gl_hwgamma; cvar_t *gl_fullscreen; @@ -423,9 +424,17 @@ static char *GL_ErrorString( GLenum err ) { return str; } -static void GL_RenderFrame( refdef_t *fd ) { +void GL_ShowErrors( const char *func ) { GLenum err; + if( gl_showerrors->integer ) { + while( ( err = qglGetError() ) != GL_NO_ERROR ) { + Com_EPrintf( "%s: %s\n", func, GL_ErrorString( err ) ); + } + } +} + +static void GL_RenderFrame( refdef_t *fd ) { GL_Flush2D(); if( !r_world.name[0] && !( fd->rdflags & RDF_NOWORLDMODEL ) ) { @@ -437,16 +446,11 @@ static void GL_RenderFrame( refdef_t *fd ) { glr.fd = *fd; glr.num_beams = 0; +#if USE_DYNAMIC if( !gl_dynamic->integer ) { glr.fd.num_dlights = 0; } - - AngleVectors( glr.fd.viewangles, glr.viewaxis[0], glr.viewaxis[1], glr.viewaxis[2] ); - VectorInverse( glr.viewaxis[1] ); - - glr.scroll = -64 * ( ( glr.fd.time / 40.0f ) - ( int )( glr.fd.time / 40.0f ) ); - if( glr.scroll == 0 ) - glr.scroll = -64.0f; +#endif GL_Setup3D(); @@ -473,16 +477,10 @@ static void GL_RenderFrame( refdef_t *fd ) { GL_Blend(); - if( gl_showerrors->integer ) { - while( ( err = qglGetError() ) != GL_NO_ERROR ) { - Com_EPrintf( "GL_RenderFrame: %s\n", GL_ErrorString( err ) ); - } - } + GL_ShowErrors( __func__ ); } static void GL_BeginFrame( void ) { - GLenum err; - if( gl_log->integer ) { QGL_LogNewFrame(); } @@ -495,16 +493,10 @@ static void GL_BeginFrame( void ) { qglClear( GL_COLOR_BUFFER_BIT ); } - if( gl_showerrors->integer ) { - while( ( err = qglGetError() ) != GL_NO_ERROR ) { - Com_EPrintf( "GL_BeginFrame: %s\n", GL_ErrorString( err ) ); - } - } + GL_ShowErrors( __func__ ); } static void GL_EndFrame( void ) { - GLenum err; - if( gl_showstats->integer ) { Draw_Stats(); } @@ -514,12 +506,9 @@ static void GL_EndFrame( void ) { QGL_EnableLogging( gl_log->integer ); gl_log->modified = qfalse; } + + GL_ShowErrors( __func__ ); - if( gl_showerrors->integer ) { - while( ( err = qglGetError() ) != GL_NO_ERROR ) { - Com_EPrintf( "GL_EndFrame: %s\n", GL_ErrorString( err ) ); - } - } video.EndFrame(); } @@ -692,6 +681,7 @@ static void GL_Register( void ) { #if USE_PNG gl_screenshot_compression = cvar.Get( "gl_screenshot_compression", "6", 0 ); #endif + gl_celshading = cvar.Get( "gl_celshading", "0", 0 ); gl_modulate = cvar.Get( "gl_modulate", "1", CVAR_ARCHIVE ); gl_hwgamma = cvar.Get( "vid_hwgamma", "0", CVAR_ARCHIVE|CVAR_LATCHED ); @@ -705,14 +695,15 @@ static void GL_Register( void ) { gl_showstats = cvar.Get( "gl_showstats", "0", 0 ); gl_cull_nodes = cvar.Get( "gl_cull_nodes", "1", 0 ); gl_cull_models = cvar.Get( "gl_cull_models", "1", 0 ); + gl_bind = cvar.Get( "gl_bind", "1", CVAR_CHEAT ); gl_clear = cvar.Get( "gl_clear", "0", 0 ); gl_novis = cvar.Get( "gl_novis", "0", 0 ); gl_lockpvs = cvar.Get( "gl_lockpvs", "0", CVAR_CHEAT ); - gl_primitives = cvar.Get( "gl_primitives", "0", 0 ); - gl_sort = cvar.Get( "gl_sort", "0", 0 ); gl_subdivide = cvar.Get( "gl_subdivide", "1", 0 ); gl_fastsky = cvar.Get( "gl_fastsky", "0", 0 ); +#if USE_DYNAMIC gl_dynamic = cvar.Get( "gl_dynamic", "2", CVAR_ARCHIVE ); +#endif gl_fullbright = cvar.Get( "r_fullbright", "0", CVAR_CHEAT ); gl_showerrors = cvar.Get( "gl_showerrors", "1", 0 ); @@ -760,7 +751,6 @@ static qboolean GL_SetupExtensions( void ) { Com_Printf( "...enabling GL_ARB_multitexture (%d texture units)\n", integer ); qglActiveTextureARB = ( PFNGLACTIVETEXTUREARBPROC )qwglGetProcAddress( "glActiveTextureARB" ); qglClientActiveTextureARB = ( PFNGLCLIENTACTIVETEXTUREARBPROC )qwglGetProcAddress( "glClientActiveTextureARB" ); - qglMultiTexCoord2fvARB = ( PFNGLMULTITEXCOORD2FVARBPROC )qwglGetProcAddress( "glMultiTexCoord2fvARB" ); if( integer > MAX_TMUS ) { integer = MAX_TMUS; } @@ -788,6 +778,17 @@ static qboolean GL_SetupExtensions( void ) { Com_Printf( "GL_EXT_texture_filter_anisotropic not found\n" ); } + if( strstr( extensions, "GL_ARB_fragment_program" ) ) { + Com_Printf( "...enabling GL_ARB_fragment_program\n" ); + qglProgramStringARB = ( PFNGLPROGRAMSTRINGARBPROC )qwglGetProcAddress( "glProgramStringARB" ); + qglBindProgramARB = ( PFNGLBINDPROGRAMARBPROC )qwglGetProcAddress( "glBindProgramARB" ); + qglDeleteProgramsARB = ( PFNGLDELETEPROGRAMSARBPROC )qwglGetProcAddress( "glDeleteProgramsARB" ); + qglGenProgramsARB = ( PFNGLGENPROGRAMSARBPROC )qwglGetProcAddress( "glGenProgramsARB" ); + qglProgramLocalParameter4fvARB = ( PFNGLPROGRAMLOCALPARAMETER4FVARBPROC )qwglGetProcAddress( "glProgramLocalParameter4fvARB" ); + } else { + Com_Printf( "GL_ARB_fragment_program not found\n" ); + } + if( !qglActiveTextureARB ) { return qfalse; } @@ -800,30 +801,7 @@ static qboolean GL_SetupExtensions( void ) { return qtrue; } -void GL_SetDefaultState( void ) { - qglDrawBuffer( GL_BACK ); - qglClearColor( 0, 0, 0, 1 ); - qglClearDepth( 1 ); - qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - qglEnable( GL_DEPTH_TEST ); - qglDepthFunc( GL_LEQUAL ); - qglDepthRange( 0, 1 ); - qglDepthMask( GL_TRUE ); - qglDisable( GL_BLEND ); - qglDisable( GL_ALPHA_TEST ); - qglAlphaFunc( GL_GREATER, 0.666f ); - qglHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); - qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - - qglEnableClientState( GL_VERTEX_ARRAY ); - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - GL_SelectTMU( 0 ); - qglEnable( GL_TEXTURE_2D ); - GL_Bits( GLS_DEFAULT ); -} - -static void GL_SetupRenderer( void ) { +static void GL_IdentifyRenderer( void ) { char renderer_buffer[MAX_STRING_CHARS]; Q_strncpyz( renderer_buffer, gl_config.rendererString, @@ -904,20 +882,19 @@ static qboolean GL_Init( qboolean total ) { Com_Printf( "Hardware gamma is not supported by this video driver\n" ); } - GL_SetupRenderer(); + GL_IdentifyRenderer(); QGL_EnableLogging( gl_log->integer ); gl_log->modified = qfalse; GL_PostInit(); + GL_InitPrograms(); + if( (( size_t )tess.vertices) & 15 ) { Com_WPrintf( "tess.vertices not 16 byte aligned\n" ); } - gl_sort = cvar.Get( "gl_sort", - gl_config.renderer == GL_RENDERER_MESADRI ? "1" : "0", 0 ); - Com_DPrintf( "Finished GL_Init\n" ); return qtrue; @@ -944,6 +921,8 @@ void GL_Shutdown( qboolean total ) { if( !total ) { return; } + + GL_ShutdownPrograms(); /* ** shut down OS specific OpenGL stuff like contexts, etc. diff --git a/source/gl_mesh.c b/source/gl_mesh.c index ec137ac..00d8f58 100644 --- a/source/gl_mesh.c +++ b/source/gl_mesh.c @@ -172,6 +172,7 @@ void GL_SetAliasColor( vec3_t origin, vec_t *color ) { } } +#define USE_CELSHADING 1 void GL_DrawAliasModel( model_t *model ) { entity_t *ent = glr.ent; @@ -187,6 +188,11 @@ void GL_DrawAliasModel( model_t *model ) { glStateBits_t bits; glCullResult_t cull; vec4_t color; +#if USE_CELSHADING + vec3_t dir; + float scale; +#endif + int back, front; newframeIdx = ent->frame; if( newframeIdx < 0 || newframeIdx >= model->numFrames ) { @@ -278,6 +284,15 @@ void GL_DrawAliasModel( model_t *model ) { tessFunc = Tess_LerpedMesh; } +#if USE_CELSHADING + scale = 0; + if( gl_celshading->value > 0 && ( ent->flags & RF_SHELL_MASK ) == 0 ) { + VectorSubtract( origin, glr.fd.vieworg, dir ); + scale = VectorLength( dir ); + scale = 1.0f - scale / 700.0f; + } +#endif + /* setup color */ GL_SetAliasColor( origin, color ); @@ -309,7 +324,12 @@ void GL_DrawAliasModel( model_t *model ) { qglScalef( -1, 1, 1 ); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_BACK ); - } + back = GL_BACK; + front = GL_FRONT; + } else { + back = GL_FRONT; + front = GL_BACK; + } qglColor4fv( color ); qglVertexPointer( 3, GL_FLOAT, 16, tess.vertices ); @@ -352,10 +372,28 @@ void GL_DrawAliasModel( model_t *model ) { qglLockArraysEXT( 0, mesh->numVerts ); } qglDrawElements( GL_TRIANGLES, mesh->numIndices, GL_UNSIGNED_INT, - mesh->indices ); + mesh->indices ); + +#if USE_CELSHADING + if( scale > 0 && scale <= 1 ) { + qglCullFace( front ); + qglPolygonMode( back, GL_LINE ); + qglDisable( GL_TEXTURE_2D ); + qglLineWidth( gl_celshading->value*scale ); + GL_Bits( bits | GLS_BLEND_BLEND ); + qglColor4f( 0, 0, 0, scale ); + qglDrawElements( GL_TRIANGLES, mesh->numIndices, GL_UNSIGNED_INT, + mesh->indices ); + qglCullFace( back ); + qglPolygonMode( back, GL_FILL ); + qglColor4fv( color ); + qglEnable( GL_TEXTURE_2D ); + } +#endif + if( gl_showtris->integer ) { - Tess_DrawSurfaceTriangles( ( int * )mesh->indices, - mesh->numIndices ); + //Tess_DrawSurfaceTriangles( ( int * )mesh->indices, + // mesh->numIndices ); } if( qglUnlockArraysEXT ) { qglUnlockArraysEXT(); diff --git a/source/gl_state.c b/source/gl_state.c index 6dbfbae..f1df0fc 100644 --- a/source/gl_state.c +++ b/source/gl_state.c @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gl_local.h" +#include "gl_arbfp.h" glState_t gls; @@ -26,6 +27,9 @@ void GL_BindTexture( int texnum ) { if( gls.texnum[gls.tmu] == texnum ) { return; } + if( !gl_bind->integer ) { + return; + } qglBindTexture( GL_TEXTURE_2D, texnum ); c.texSwitches++; @@ -170,35 +174,26 @@ void GL_Setup2D( void ) { GL_CullFace( GLS_CULL_DISABLE ); } -static inline void MYgluPerspective( GLdouble fovy, GLdouble aspect, - GLdouble zNear, GLdouble zFar ) -{ - GLdouble xmin, xmax, ymin, ymax; - - ymax = zNear * tan( fovy * M_PI / 360.0 ); - ymin = -ymax; - - xmin = ymin * aspect; - xmax = ymax * aspect; - - qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); -} - void GL_Setup3D( void ) { - float screenAspect; - int yb; + GLdouble xmin, xmax, ymin, ymax, aspect; + int yb = glr.fd.y + glr.fd.height; - yb = glr.fd.y + glr.fd.height; qglViewport( glr.fd.x, gl_config.vidHeight - yb, glr.fd.width, glr.fd.height ); - screenAspect = ( float )glr.fd.width / glr.fd.height; qglMatrixMode( GL_PROJECTION ); qglLoadIdentity(); - MYgluPerspective( glr.fd.fov_y, screenAspect, - gl_znear->value, gl_zfar->value ); + + ymax = gl_znear->value * tan( glr.fd.fov_y * M_PI / 360.0 ); + ymin = -ymax; + + aspect = ( GLdouble )glr.fd.width / glr.fd.height; + xmin = ymin * aspect; + xmax = ymax * aspect; + + qglFrustum( xmin, xmax, ymin, ymax, gl_znear->value, gl_zfar->value ); - qglMatrixMode( GL_MODELVIEW ); + qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity(); qglRotatef( -90, 1, 0, 0 ); /* put z axis up */ @@ -208,9 +203,82 @@ void GL_Setup3D( void ) { qglRotatef( -glr.fd.viewangles[YAW], 0, 0, 1 ); qglTranslatef( -glr.fd.vieworg[0], -glr.fd.vieworg[1], -glr.fd.vieworg[2] ); + AngleVectors( glr.fd.viewangles, + glr.viewaxis[0], glr.viewaxis[1], glr.viewaxis[2] ); + VectorInverse( glr.viewaxis[1] ); + + glr.scroll = -64 * ( ( glr.fd.time / 40.0f ) - ( int )( glr.fd.time / 40.0f ) ); + if( glr.scroll == 0 ) + glr.scroll = -64.0f; + + +#if 0 + { + vec4_t position, diffuse; + vec4_t ambient, material; + VectorMA( glr.fd.vieworg, 128, glr.viewaxis[0], position ); + position[3]=1; + VectorSet( diffuse, 1, 1, 1 ); + VectorSet( material, 1, 1, 1 ); + VectorSet( ambient, 0, 0, 0 ); + + qglLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient ); + qglMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, material ); + + qglLightfv( GL_LIGHT0, GL_POSITION, position ); + qglLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse ); + } + qglEnable(GL_LIGHTING); + qglEnable( GL_LIGHT0 ); +#endif + GL_Bits( GLS_DEFAULT ); GL_CullFace( GLS_CULL_FRONT ); qglClear( GL_DEPTH_BUFFER_BIT ); } +void GL_SetDefaultState( void ) { + qglDrawBuffer( GL_BACK ); + qglClearColor( 0, 0, 0, 1 ); + qglClearDepth( 1 ); + qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + qglEnable( GL_DEPTH_TEST ); + qglDepthFunc( GL_LEQUAL ); + qglDepthRange( 0, 1 ); + qglDepthMask( GL_TRUE ); + qglDisable( GL_BLEND ); + qglDisable( GL_ALPHA_TEST ); + qglAlphaFunc( GL_GREATER, 0.666f ); + qglHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); + qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + + qglEnableClientState( GL_VERTEX_ARRAY ); + qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); + + GL_SelectTMU( 0 ); + qglEnable( GL_TEXTURE_2D ); + GL_Bits( GLS_DEFAULT ); +} + +void GL_InitPrograms( void ) { + if( !qglProgramStringARB ) { + return; + } + qglGenProgramsARB( 1, &gl_static.prog_warp ); + qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, gl_static.prog_warp ); + qglProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + sizeof( gl_prog_warp ) - 1, gl_prog_warp ); + //Com_Printf( "%s\n", qglGetString( GL_PROGRAM_ERROR_STRING_ARB ) ); + + GL_ShowErrors( __func__ ); +} + +void GL_ShutdownPrograms( void ) { + if( !qglProgramStringARB ) { + return; + } + qglDeleteProgramsARB( 1, &gl_static.prog_warp ); +} + + diff --git a/source/gl_surf.c b/source/gl_surf.c index aadb720..5bcadb2 100644 --- a/source/gl_surf.c +++ b/source/gl_surf.c @@ -34,7 +34,7 @@ cvar_t *gl_modulate_hack; /* ============================================================================= -LIGHTMAP TEXTURES BUILDING +LIGHTMAPS BUILDING ============================================================================= */ @@ -187,7 +187,7 @@ static int LM_BuildSurfaceLightmap( bspSurface_t *surf ) { dst += LM_BLOCK_WIDTH * 4; } - surf->lightmapnum = lm.numMaps + 1; + surf->lightmapnum = lm.numMaps; s = ( s << 4 ) + 8; t = ( t << 4 ) + 8; @@ -266,9 +266,13 @@ static int GL_BuildSurfacePoly( bspSurface_t *surf ) { surf->polys = poly; texinfo = surf->texinfo; - if( !surf->lightmap || ( texinfo->flags & NOLIGHT_MASK ) || - gl_fullbright->integer ) - { + if( texinfo->flags & SURF_WARP ) { + if( qglProgramStringARB ) { + surf->type = DSURF_WARP; + } else { + surf->type = DSURF_NOLM; + } + } else if( !surf->lightmap || gl_fullbright->integer || ( texinfo->flags & NOLIGHT_MASK ) ) { surf->type = DSURF_NOLM; } else { surf->type = DSURF_POLY; @@ -286,7 +290,6 @@ static int GL_BuildSurfacePoly( bspSurface_t *surf ) { } if( index >= r_world.numEdges ) { - printf( "LoadFace: bad edge index" ); return -1; } @@ -296,10 +299,8 @@ static int GL_BuildSurfacePoly( bspSurface_t *surf ) { VectorCopy( src_vert->point, dst_vert ); /* texture coordinates */ - dst_vert[3] = DotProduct( dst_vert, texinfo->axis[0] ) + - texinfo->offset[0]; - dst_vert[4] = DotProduct( dst_vert, texinfo->axis[1] ) + - texinfo->offset[1]; + dst_vert[3] = DotProduct( dst_vert, texinfo->axis[0] ) + texinfo->offset[0]; + dst_vert[4] = DotProduct( dst_vert, texinfo->axis[1] ) + texinfo->offset[1]; /* lightmap coordinates */ dst_vert[5] = 0; @@ -312,200 +313,35 @@ static int GL_BuildSurfacePoly( bspSurface_t *surf ) { } -#define SUBDIVIDE_SIZE 64 -#define SUBDIVIDE_VERTS 64 - -static bspSurface_t *warpsurf; - -static void BoundPolygon( int numVerts, const vec_t *verts, - vec3_t mins, vec3_t maxs ) -{ - ClearBounds( mins, maxs ); - - while( numVerts-- ) { - AddPointToBounds( verts, mins, maxs ); - verts += 3; - } -} - - -static void SubdividePolygon_r( int numVerts, vec_t *verts ) { - int i, j; - vec3_t front[SUBDIVIDE_VERTS]; - vec3_t back[SUBDIVIDE_VERTS]; - vec_t dist[SUBDIVIDE_VERTS]; - vec3_t mins, maxs; - int f, b; - vec_t mid, frac, scale, *v; - bspPoly_t *poly; - vec3_t total; - vec_t total_s, total_t; - bspTexinfo_t *texinfo; - - if( numVerts > SUBDIVIDE_VERTS - 4 ) { - Com_Error( ERR_DROP, "SubdividePolygon_r: numVerts = %d", numVerts ); - } - - BoundPolygon( numVerts, verts, mins, maxs ); - - for( i = 0; i < 3; i++ ) { - mid = ( mins[i] + maxs[i] ) * 0.5f; - mid = SUBDIVIDE_SIZE * floor( mid / SUBDIVIDE_SIZE + 0.5f ); - if( mid - mins[i] < 8 ) { - continue; - } - if( maxs[i] - mid < 8 ) { - continue; - } - - v = verts + i; - for( j = 0; j < numVerts; j++, v += 3 ) { - dist[j] = *v - mid; - } - - dist[j] = dist[0]; - VectorCopy( verts, v - i ); - - f = b = 0; - v = verts; - for( j = 0; j < numVerts; j++, v += 3 ) { - if( dist[j] >= 0 ) { - VectorCopy( v, front[f] ); f++; - } - if( dist[j] <= 0 ) { - VectorCopy( v, back[b] ); b++; - } - if( dist[j] == 0 || dist[j+1] == 0 ) { - continue; - } - if( ( dist[j] > 0 ) != ( dist[j+1] > 0 ) ) { - frac = dist[j] / ( dist[j] - dist[j+1] ); - front[f][0] = back[b][0] = v[0] + frac * ( v[3+0] - v[0] ); - front[f][1] = back[b][1] = v[1] + frac * ( v[3+1] - v[1] ); - front[f][2] = back[b][2] = v[2] + frac * ( v[3+2] - v[2] ); - f++; b++; - } - } - - SubdividePolygon_r( f, front[0] ); - SubdividePolygon_r( b, back[0] ); - return; - } - - poly = sys.HunkAlloc( &r_world.pool, sizeof( *poly ) + - sizeof( vec_t ) * VERTEX_SIZE * numVerts ); - poly->next = warpsurf->polys; - poly->numVerts = numVerts + 1; - poly->numIndices = numVerts * 3; - warpsurf->polys = poly; - - texinfo = warpsurf->texinfo; - VectorClear( total ); - total_s = total_t = 0; - v = poly->vertices + VERTEX_SIZE; - for( i = 0; i < numVerts; i++ ) { - VectorCopy( verts, v ); - v[3] = DotProduct( verts, texinfo->axis[0] ); - v[4] = DotProduct( verts, texinfo->axis[1] ); - total_s += v[3]; - total_t += v[4]; - VectorAdd( total, verts, total ); - verts += 3; v += VERTEX_SIZE; - } - - /* middle point */ - v = poly->vertices; - scale = 1.0f / numVerts; - VectorScale( total, scale, v ); - v[3] = total_s * scale; - v[4] = total_t * scale; - -} - -static int GL_BuildSurfaceWarpPolys( bspSurface_t *surf ) { - int *src_surfedge; - dvertex_t *src_vert; - dedge_t *src_edge; - vec_t *dst_vert; - int i; - int index, vertIndex; - int numEdges = surf->numSurfEdges; - vec3_t verts[SUBDIVIDE_VERTS]; - - surf->polys = NULL; - surf->type = DSURF_WARP; - warpsurf = surf; - - src_surfedge = surf->firstSurfEdge; - dst_vert = verts[0]; - for( i = 0; i < numEdges; i++ ) { - index = *src_surfedge++; - - vertIndex = 0; - if( index < 0 ) { - index = -index; - vertIndex = 1; - } - - if( index >= r_world.numEdges ) { - printf( "LoadFace: bad edge index" ); - return -1; - } - - src_edge = r_world.edges + index; - src_vert = r_world.vertices + src_edge->v[vertIndex]; - - VectorCopy( src_vert->point, dst_vert ); - - dst_vert += 3; - } - - SubdividePolygon_r( numEdges, verts[0] ); - - return 0; - -} - static void GL_NormalizeSurfaceTexcoords( bspSurface_t *surf ) { bspTexinfo_t *texinfo = surf->texinfo; bspPoly_t *poly = surf->polys; vec_t *vert; - tcoord_t *tc; - int i; vec2_t scale; - - surf->normalizedTC = sys.HunkAlloc( &r_world.pool, sizeof( tcoord_t ) * poly->numVerts ); + int i; scale[0] = 1.0f / texinfo->image->width; scale[1] = 1.0f / texinfo->image->height; + if( texinfo->flags & SURF_WARP && qglBindProgramARB ) { + scale[0] *= 0.5f; + scale[1] *= 0.5f; + } - tc = surf->normalizedTC; vert = poly->vertices; for( i = 0; i < poly->numVerts; i++ ) { vert[3] *= scale[0]; vert[4] *= scale[1]; - tc->st[0] = DotProduct( vert, texinfo->normalizedAxis[0] ); - tc->st[1] = DotProduct( vert, texinfo->normalizedAxis[1] ); - - vert += VERTEX_SIZE; tc++; + vert += VERTEX_SIZE;; } } int GL_PostProcessSurface( bspSurface_t *surf ) { bspTexinfo_t *texinfo = surf->texinfo; - if( texinfo->flags & SURF_SKY ) { - } - if( ( texinfo->flags & SURF_WARP ) && gl_subdivide->integer ) { - if( GL_BuildSurfaceWarpPolys( surf ) ) { - return -1; - } - } else { - if( GL_BuildSurfacePoly( surf ) ) { - return -1; - } - GL_CalcSurfaceExtents( surf ); + if( GL_BuildSurfacePoly( surf ) ) { + return -1; } + GL_CalcSurfaceExtents( surf ); if( surf->type == DSURF_POLY ) { if( LM_BuildSurfaceLightmap( surf ) ) { @@ -513,14 +349,10 @@ int GL_PostProcessSurface( bspSurface_t *surf ) { } } - if( !( texinfo->flags & (SURF_SKY|SURF_WARP) ) ) { + if( !( texinfo->flags & SURF_SKY ) ) { GL_NormalizeSurfaceTexcoords( surf ); } - if( ( texinfo->flags & SURF_WARP ) && !gl_subdivide->integer ) { - GL_NormalizeSurfaceTexcoords( surf ); - } - return 0; } @@ -566,7 +398,7 @@ void GL_EndPostProcessing( void ) { } } - Com_DPrintf( "GL_EndPostProcessing: %d lightmaps built\n", lm.numMaps ); + Com_DPrintf( "%d lightmaps built\n", lm.numMaps ); } diff --git a/source/gl_tess.c b/source/gl_tess.c index ed115d3..122411a 100644 --- a/source/gl_tess.c +++ b/source/gl_tess.c @@ -22,848 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. tesselator_t tess; -/* -============================================================================== - -BSP surfaces sorting - -============================================================================== -*/ - -typedef struct { - uint32 key; - bspSurface_t *surf; -} drawSurf_t; - -#define MAX_DRAW_SURFS ( 1 << 16 ) -#define DRAW_SURFS_MASK ( MAX_DRAW_SURFS - 1 ) - -static drawSurf_t drawSurfs[MAX_DRAW_SURFS]; -static drawSurf_t drawSurfsBuffer[MAX_DRAW_SURFS]; -static int numDrawSurfs; - -image_t *GL_TextureAnimation( bspTexinfo_t *texinfo ) { - int count; - - if( !texinfo->animNext ) { - return texinfo->image; - } - - count = ( int )( glr.fd.time * 2 ) % texinfo->numFrames; - while( count ) { - texinfo = texinfo->animNext; - count--; - } - - return texinfo->image; -} - - -void GL_AddBspSurface( bspSurface_t *surf ) { - drawSurf_t *drawsurf; - bspTexinfo_t *texinfo = surf->texinfo; - int idx, istrans, texnum; - image_t *image; - - if( surf->type >= DSURF_NUM_TYPES ) { - Com_Error( ERR_FATAL, "GL_AddBspSurface: bad surf->type" ); - } - - if( surf->dlightframe != glr.drawframe ) { - surf->dlightbits = 0; - } - - istrans = 0; - if( texinfo->flags & SURF_SKY ) { - if( !gl_fastsky->integer ) { - R_AddSkySurface( surf ); - return; - } - texnum = r_whiteimage->texnum; - } else { - if( texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) { - if( texinfo->flags & SURF_TRANS33 ) { - istrans = 1; - } else { - istrans = 2; - } - } - image = GL_TextureAnimation( texinfo ); - texnum = image->texnum; - } - - idx = numDrawSurfs & DRAW_SURFS_MASK; - drawsurf = &drawSurfs[idx]; - drawsurf->key = ( istrans << 30 ) | ( texnum << 16 ) | surf->lightmapnum; - drawsurf->surf = surf; - - numDrawSurfs++; -} - -#define CopyDrawSurf( dst, src ) \ - ( (( uint32 * )dst)[0] = (( uint32 * )src)[0],\ - (( uint32 * )dst)[1] = (( uint32 * )src)[1] ) - -static void mergeArray( int left, int median, int right ) { - int count; - int i, j; - drawSurf_t *src, *dst; - - dst = drawSurfsBuffer; - i = left; - j = median + 1; - while( i <= median && j <= right ) { - if( drawSurfs[i].key < drawSurfs[j].key ) { - CopyDrawSurf( dst, &drawSurfs[i] ); i++; - } else { - CopyDrawSurf( dst, &drawSurfs[j] ); j++; - } - dst++; - } - - while( i <= median ) { - CopyDrawSurf( dst, &drawSurfs[i] ); i++; dst++; - } - - while( j <= right ) { - CopyDrawSurf( dst, &drawSurfs[j] ); j++; dst++; - } - - src = drawSurfsBuffer; - count = dst - src; - dst = drawSurfs + left; - while( count-- ) { - CopyDrawSurf( dst, src ); src++; dst++; - } -} - -static void mergeSort_r( int left, int right ) { - int median; - - if( left < right ) { - median = ( left + right ) >> 1; - - mergeSort_r( left, median ); - mergeSort_r( median + 1, right ); - - mergeArray( left, median, right ); - } -} - - -/* -============================================================================== - -Surface tesselation - -============================================================================== -*/ - -#define TURB_SCALE ( 256.0f / ( 2 * M_PI ) ) - -static float r_turbsin[256] = { - #include "warpsin.h" -}; - -static inline qboolean WouldOverflow( drawSurf_t *surf ) { - bspPoly_t *poly; - int numVerts, numIndices; - - if( tess.numFaces + 1 > TESS_MAX_FACES ) { - return qtrue; - } - - numVerts = tess.numVertices; - numIndices = tess.numIndices; - for( poly = surf->surf->polys; poly; poly = poly->next ) { - numVerts += poly->numVerts; - numIndices += poly->numIndices; - } - - if( numVerts > TESS_MAX_VERTICES ) { - return qtrue; - } - if( numIndices > TESS_MAX_INDICES ) { - return qtrue; - } - - return qfalse; -} - -static void Tess_SimplePoly( drawSurf_t *surf ) { - bspSurface_t *bspSurf = surf->surf; - bspPoly_t *poly = bspSurf->polys; - vec_t *src_vert, *dst_vert; - tcoord_t *dst_tc; - int *dst_indices; - int i, count, currentVert; - float scroll; - - scroll = 0; - if( bspSurf->texinfo->flags & SURF_FLOWING ) { - scroll = glr.scroll; - } - - src_vert = poly->vertices; - dst_vert = tess.vertices + tess.numVertices * 4; - dst_tc = tess.tcoords + tess.numVertices; - count = poly->numVerts; - for( i = 0; i < count; i++ ) { - VectorCopy( src_vert, dst_vert ); - dst_tc->st[0] = src_vert[3] + scroll; - dst_tc->st[1] = src_vert[4]; - src_vert += VERTEX_SIZE; dst_vert += 4; - dst_tc++; - } - - dst_indices = tess.indices + tess.numIndices; - count = poly->numVerts - 2; - currentVert = tess.numVertices; - for( i = 0; i < count; i++ ) { - dst_indices[0] = currentVert; - dst_indices[1] = currentVert + ( i + 1 ); - dst_indices[2] = currentVert + ( i + 2 ); - dst_indices += 3; - } - - tess.faces[ tess.numFaces++ ] = bspSurf; - tess.numVertices += poly->numVerts; - tess.numIndices += poly->numIndices; - tess.dlightbits |= bspSurf->dlightbits; - - c.trisDrawn += count; - -} - -static void Tess_LightmappedPoly( drawSurf_t *surf ) { - bspSurface_t *bspSurf = surf->surf; - bspPoly_t *poly = bspSurf->polys; - vec_t *src_vert, *dst_vert; - tcoord_t *dst_tc; - tcoord_t *dst_lmtc; - int *dst_indices; - int i, count, currentVert; - - src_vert = poly->vertices; - dst_vert = tess.vertices + tess.numVertices * 4; - dst_tc = tess.tcoords + tess.numVertices; - dst_lmtc = tess.lmtcoords + tess.numVertices; - count = poly->numVerts; - for( i = 0; i < count; i++ ) { - VectorCopy( src_vert, dst_vert ); - *( uint32 * )&dst_tc->st[0] = *( uint32 * )&src_vert[3]; - *( uint32 * )&dst_tc->st[1] = *( uint32 * )&src_vert[4]; - *( uint32 * )&dst_lmtc->st[0] = *( uint32 * )&src_vert[5]; - *( uint32 * )&dst_lmtc->st[1] = *( uint32 * )&src_vert[6]; - src_vert += VERTEX_SIZE; dst_vert += 4; - dst_tc++; dst_lmtc++; - } - - dst_indices = tess.indices + tess.numIndices; - count = poly->numVerts - 2; - currentVert = tess.numVertices; - for( i = 0; i < count; i++ ) { - dst_indices[0] = currentVert; - dst_indices[1] = currentVert + ( i + 1 ); - dst_indices[2] = currentVert + ( i + 2 ); - dst_indices += 3; - } - - tess.faces[ tess.numFaces++ ] = bspSurf; - tess.numVertices += poly->numVerts; - tess.numIndices += poly->numIndices; - tess.dlightbits |= bspSurf->dlightbits; - - c.trisDrawn += count; - -} - -#define DIV64 ( 1.0f / 64 ) - -static void Tess_WarpPolys( drawSurf_t *surf ) { - bspSurface_t *bspSurf = surf->surf; - bspPoly_t *poly = bspSurf->polys; - vec_t *src_vert, *dst_vert; - tcoord_t *dst_tc; - int *dst_indices; - int i, j, k, count, currentVert; - vec_t s, t; - float scroll; - - scroll = 0; - if( bspSurf->texinfo->flags & SURF_FLOWING ) { - scroll = glr.scroll; - } - - for( poly = bspSurf->polys; poly; poly = poly->next ) { - src_vert = poly->vertices; - dst_vert = tess.vertices + tess.numVertices * 4; - dst_tc = tess.tcoords + tess.numVertices; - count = poly->numVerts; - for( i = 0; i < count; i++ ) { - VectorCopy( src_vert, dst_vert ); - dst_vert += 4; - - s = src_vert[3]; - t = src_vert[4]; - src_vert += VERTEX_SIZE; - - j = Q_ftol( ( t * 0.125f + glr.fd.time ) * TURB_SCALE ); - k = Q_ftol( ( s * 0.125f + glr.fd.time ) * TURB_SCALE ); - s += r_turbsin[ j & 255 ]; - t += r_turbsin[ k & 255 ]; - - dst_tc->st[0] = s * DIV64 + scroll; - dst_tc->st[1] = t * DIV64; - dst_tc++; - } - - dst_indices = tess.indices + tess.numIndices; - count = poly->numVerts - 2; - currentVert = tess.numVertices; - for( i = 0; i < count; i++ ) { - dst_indices[0] = currentVert; - dst_indices[1] = currentVert + ( i + 1 ); - dst_indices[2] = currentVert + ( i + 2 ); - dst_indices += 3; - } - dst_indices[0] = currentVert; - dst_indices[1] = currentVert + ( i + 1 ); - dst_indices[2] = currentVert + 1; - dst_indices += 3; - - tess.numVertices += poly->numVerts; - tess.numIndices += poly->numIndices; - - c.trisDrawn += count + 1; - } - - tess.faces[ tess.numFaces++ ] = bspSurf; - tess.dlightbits |= bspSurf->dlightbits; - -} - -typedef void (*tesselatorFunc_t)( drawSurf_t * ); - -tesselatorFunc_t tessTable[DSURF_NUM_TYPES] = { - Tess_LightmappedPoly, /* DSURF_POLY */ - Tess_WarpPolys, /* DSURF_WARP */ - Tess_SimplePoly /* DSURF_NOLM */ -}; - -/* -============================================================================== - -Surface drawing - -============================================================================== -*/ - -void Tess_DrawSurfaceTriangles( int *indices, int numIndices ) { - qglDisable( GL_TEXTURE_2D ); - qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - GL_TexEnv( GL_REPLACE ); - qglDisable( GL_DEPTH_TEST ); - qglColor4f( 1, 1, 1, 1 ); - - qglDrawElements( GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, - indices ); - - qglEnable( GL_DEPTH_TEST ); - qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - qglEnable( GL_TEXTURE_2D ); - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); -} - -#if 0 -static void ProjectDlightTexture( void ) { - bspSurface_t *bspSurf; - bspTexinfo_t *texinfo; - cplane_t *plane; - vec3_t point; - vec2_t local; - vec_t dist, scale, f; - int i, j, faceNum, numIndices; - dlight_t *light; - tcoord_t *src_tc; - vec_t *dst_tc; -static vec_t tcArray[TESS_MAX_VERTICES*2]; -static byte colorsArray[TESS_MAX_VERTICES*4]; - int cfArray[TESS_MAX_VERTICES]; - int idxArray[TESS_MAX_INDICES]; - byte *dst_col; - int v1, v2, v3; - int *src_idx, *dst_idx; - int clipflags; - color_t color; - int currentVert, maxVert; - - GL_BindTexture( r_dlightTex->texnum ); -// qglVertexPointer( 3, GL_FLOAT, 16, tess.vertices ); - qglTexCoordPointer( 2, GL_FLOAT, 0, tcArray ); - qglEnableClientState( GL_COLOR_ARRAY ); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorsArray ); - - for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) { - currentVert = 0; - for( faceNum = 0; faceNum < tess.numFaces; faceNum++, currentVert = maxVert ) { - bspSurf = tess.faces[faceNum]; - maxVert = currentVert + bspSurf->polys->numVerts; - if( !( bspSurf->dlightbits & ( 1 << i ) ) ) { - //continue; - } - plane = bspSurf->plane; - switch( plane->type ) { - case PLANE_X: - dist = light->transformed[0] - plane->dist; - break; - case PLANE_Y: - dist = light->transformed[1] - plane->dist; - break; - case PLANE_Z: - dist = light->transformed[2] - plane->dist; - break; - default: - dist = DotProduct( light->transformed, plane->normal ) - plane->dist; - break; - } - - if( dist > light->intensity || dist < -light->intensity ) { - //continue; - } - - VectorMA( light->transformed, -dist, plane->normal, point ); - - texinfo = bspSurf->texinfo; - local[0] = DotProduct( point, texinfo->normalizedAxis[0] ); - local[1] = DotProduct( point, texinfo->normalizedAxis[1] ); - - scale = 1.0f / light->intensity; - - dist = fabs( dist ); - f = 1.0f - dist * scale; - if( f < 0 ) f = 0; - - color[0] = 255 * light->color[0] * f; - color[1] = 255 * light->color[1] * f; - color[2] = 255 * light->color[2] * f; - color[3] = 255; - - src_tc = bspSurf->normalizedTC; - dst_tc = tcArray + currentVert * 2; - dst_col = colorsArray + currentVert * 4; - for( j = currentVert; j < maxVert; j++ ) { - dst_tc[0] = ( src_tc->st[0] - local[0] ) * scale + 0.5f; - dst_tc[1] = ( src_tc->st[1] - local[1] ) * scale + 0.5f; - - /*clipflags = 0; - if( dst_tc[0] > 1 ) { - clipflags |= 1; - } else if( dst_tc[0] < 0 ) { - clipflags |= 2; - } - if( dst_tc[1] > 1 ) { - clipflags |= 4; - } else if( dst_tc[1] < 0 ) { - clipflags |= 8; - }*/ - - *( uint32 * )dst_col = *( uint32 * )color; - //cfArray[j] = clipflags; - - dst_col += 4; src_tc++; dst_tc += 2; - } - - } - -#if 0 - numIndices = 0; - src_idx = tess.indices; - dst_idx = idxArray; - for( faceNum = 0; faceNum < tess.numFaces; faceNum++ ) { - bspSurf = tess.faces[faceNum]; - if( !( bspSurf->dlightbits & ( 1 << i ) ) ) { - src_idx += bspSurf->polys->numIndices; - continue; - } - for( j = 0; j < bspSurf->polys->numVerts - 2; j++ ) { - v1 = src_idx[0]; - v2 = src_idx[1]; - v3 = src_idx[2]; - src_idx += 3; - if( cfArray[v1] & cfArray[v2] & cfArray[v3] ) { - continue; - } - dst_idx[0] = v1; - dst_idx[1] = v2; - dst_idx[2] = v3; - - dst_idx += 3; - numIndices += 3; - } - - } - - if( numIndices ) { - qglDrawElements( GL_TRIANGLES, numIndices, - GL_UNSIGNED_INT, idxArray ); - } -#endif - } - -// qglDisableClientState( GL_COLOR_ARRAY ); -} - -// f = ( l + d ) * t - -void EndSurface_Multitextured( void ) { - GL_TexEnv( GL_REPLACE ); - GL_BindTexture( lm.lightmaps[ tess.lightmapnum - 1 ]->texnum ); - qglTexCoordPointer( 2, GL_FLOAT, 0, tess.lmtcoords ); - - GL_SelectTMU( 1 ); - if( tess.dlightbits ) { - - qglEnable( GL_TEXTURE_2D ); - GL_TexEnv( GL_ADD ); - - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - /* if( gl_dynamic->integer == 2 ) { - GL_Bits( GLS_BLEND_MODULATE ); - } else { - GL_Bits( GLS_BLEND_ADD ); - }*/ - - ProjectDlightTexture(); - } - - /* enable texturing on TMU1 */ - GL_SelectTMU( 2 ); - qglEnable( GL_TEXTURE_2D ); - GL_BindTexture( tess.texnum ); - GL_TexEnv( GL_MODULATE ); - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - qglTexCoordPointer( 2, GL_FLOAT, 0, tess.tcoords ); - - qglVertexPointer( 3, GL_FLOAT, 16, tess.vertices ); - if( qglLockArraysEXT ) { - qglLockArraysEXT( 0, tess.numVertices ); - } - qglDrawElements( GL_TRIANGLES, tess.numIndices, GL_UNSIGNED_INT, - tess.indices ); - - /* disable texturing on TMU1 */ - qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - qglDisable( GL_TEXTURE_2D ); - GL_SelectTMU( 1 ); - - qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - qglDisableClientState( GL_COLOR_ARRAY ); - qglDisable( GL_TEXTURE_2D ); - GL_SelectTMU( 0 ); - - - if( gl_showtris->integer ) { - Tess_DrawSurfaceTriangles( tess.indices, tess.numIndices ); - } - - if( qglUnlockArraysEXT ) { - qglUnlockArraysEXT(); - } - - -} - -#else - -static void ProjectDlightTexture( void ) { - bspSurface_t *bspSurf; - bspTexinfo_t *texinfo; - cplane_t *plane; - vec3_t point; - vec2_t local; - vec_t dist, scale, f; - int i, j, faceNum, numIndices; - dlight_t *light; - tcoord_t *src_tc; - vec_t *dst_tc; - vec_t tcArray[TESS_MAX_VERTICES*2]; - int cfArray[TESS_MAX_VERTICES]; - int idxArray[TESS_MAX_INDICES]; - byte colorsArray[TESS_MAX_VERTICES*4]; - byte *dst_col; - int v1, v2, v3; - int *src_idx, *dst_idx; - int clipflags; - color_t color; - int currentVert, maxVert; - - GL_BindTexture( r_dlightTex->texnum ); - qglTexCoordPointer( 2, GL_FLOAT, 0, tcArray ); - qglEnableClientState( GL_COLOR_ARRAY ); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorsArray ); - - for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) { - currentVert = 0; - for( faceNum = 0; faceNum < tess.numFaces; faceNum++, currentVert = maxVert ) { - bspSurf = tess.faces[faceNum]; - maxVert = currentVert + bspSurf->polys->numVerts; - if( !( bspSurf->dlightbits & ( 1 << i ) ) ) { - continue; - } - plane = bspSurf->plane; - switch( plane->type ) { - case PLANE_X: - dist = light->transformed[0] - plane->dist; - break; - case PLANE_Y: - dist = light->transformed[1] - plane->dist; - break; - case PLANE_Z: - dist = light->transformed[2] - plane->dist; - break; - default: - dist = DotProduct( light->transformed, plane->normal ) - plane->dist; - break; - } - - if( dist > light->intensity || dist < -light->intensity ) { - continue; - } - - VectorMA( light->transformed, -dist, plane->normal, point ); - - texinfo = bspSurf->texinfo; - local[0] = DotProduct( point, texinfo->normalizedAxis[0] ); - local[1] = DotProduct( point, texinfo->normalizedAxis[1] ); - - scale = 1.0f / light->intensity; - - dist = fabs( dist ); - f = 1.0f - dist * scale; - - color[0] = 255 * light->color[0] * f; - color[1] = 255 * light->color[1] * f; - color[2] = 255 * light->color[2] * f; - color[3] = 255; - - src_tc = bspSurf->normalizedTC; - dst_tc = tcArray + currentVert * 2; - dst_col = colorsArray + currentVert * 4; - for( j = currentVert; j < maxVert; j++ ) { - dst_tc[0] = ( src_tc->st[0] - local[0] ) * scale + 0.5f; - dst_tc[1] = ( src_tc->st[1] - local[1] ) * scale + 0.5f; - - clipflags = 0; - if( dst_tc[0] > 1 ) { - clipflags |= 1; - } else if( dst_tc[0] < 0 ) { - clipflags |= 2; - } - if( dst_tc[1] > 1 ) { - clipflags |= 4; - } else if( dst_tc[1] < 0 ) { - clipflags |= 8; - } - - *( uint32 * )dst_col = *( uint32 * )color; - cfArray[j] = clipflags; - - dst_col += 4; src_tc++; dst_tc += 2; - } - - } - - numIndices = 0; - src_idx = tess.indices; - dst_idx = idxArray; - for( faceNum = 0; faceNum < tess.numFaces; faceNum++ ) { - bspSurf = tess.faces[faceNum]; - if( !( bspSurf->dlightbits & ( 1 << i ) ) ) { - src_idx += bspSurf->polys->numIndices; - continue; - } - for( j = 0; j < bspSurf->polys->numVerts - 2; j++ ) { - v1 = src_idx[0]; - v2 = src_idx[1]; - v3 = src_idx[2]; - src_idx += 3; - if( cfArray[v1] & cfArray[v2] & cfArray[v3] ) { - continue; - } - dst_idx[0] = v1; - dst_idx[1] = v2; - dst_idx[2] = v3; - - dst_idx += 3; - numIndices += 3; - } - - } - - if( numIndices ) { - qglDrawElements( GL_TRIANGLES, numIndices, - GL_UNSIGNED_INT, idxArray ); - } - } - - qglDisableClientState( GL_COLOR_ARRAY ); - -} - -void EndSurface_Multitextured( void ) { - GL_BindTexture( tess.texnum ); - qglTexCoordPointer( 2, GL_FLOAT, 0, tess.tcoords ); - - /* enable texturing on TMU1 */ - GL_SelectTMU( 1 ); - qglEnable( GL_TEXTURE_2D ); - GL_BindTexture( lm.lightmaps[ tess.lightmapnum - 1 ]->texnum ); - GL_TexEnv( GL_MODULATE ); - qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - qglTexCoordPointer( 2, GL_FLOAT, 0, tess.lmtcoords ); - - qglVertexPointer( 3, GL_FLOAT, 16, tess.vertices ); - if( qglLockArraysEXT ) { - qglLockArraysEXT( 0, tess.numVertices ); - } - qglDrawElements( GL_TRIANGLES, tess.numIndices, GL_UNSIGNED_INT, - tess.indices ); - - /* disable texturing on TMU1 */ - qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - qglDisable( GL_TEXTURE_2D ); - GL_SelectTMU( 0 ); - - if( gl_showtris->integer ) { - Tess_DrawSurfaceTriangles( tess.indices, tess.numIndices ); - } - - if( qglUnlockArraysEXT ) { - qglUnlockArraysEXT(); - } - - if( tess.dlightbits ) { - GL_TexEnv( GL_MODULATE ); - if( gl_dynamic->integer == 2 ) { - GL_Bits( GLS_BLEND_MODULATE ); - } else { - GL_Bits( GLS_BLEND_ADD ); - } - - ProjectDlightTexture(); - } - -} - -#endif - -void EndSurface_Single( void ) { - GL_BindTexture( tess.texnum ); - - qglTexCoordPointer( 2, GL_FLOAT, 0, tess.tcoords ); - qglVertexPointer( 3, GL_FLOAT, 16, tess.vertices ); - if( qglLockArraysEXT ) { - qglLockArraysEXT( 0, tess.numVertices ); - } - qglDrawElements( GL_TRIANGLES, tess.numIndices, GL_UNSIGNED_INT, - tess.indices ); - if( gl_showtris->integer ) { - Tess_DrawSurfaceTriangles( tess.indices, tess.numIndices ); - } - if( qglUnlockArraysEXT ) { - qglUnlockArraysEXT(); - } -} - -typedef void (*drawSurfFunc_t)( void ); - -static drawSurfFunc_t endSurfTable[DSURF_NUM_TYPES] = { - EndSurface_Multitextured, /* DSURF_POLY */ - EndSurface_Single, /* DSURF_WARP */ - EndSurface_Single /* DSURF_NOLM */ -}; - -static void EndSurface( drawSurf_t *surf ) { - int istrans = ( surf->key >> 30 ) & 3; - - if( istrans ) { - GL_Bits( GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE ); - if( istrans == 1 ) { - qglColor4f( 1, 1, 1, 0.33f ); - } else { - qglColor4f( 1, 1, 1, 0.66f ); - } - } else { - GL_Bits( GLS_DEFAULT ); - qglColor4f( 1, 1, 1, 1 ); - } - - GL_TexEnv( GL_MODULATE ); - - (*endSurfTable[surf->surf->type])(); - - tess.numFaces = 0; - tess.numVertices = 0; - tess.numIndices = 0; - tess.dlightbits = 0; - tess.texnum = 0; - - c.batchesDrawn++; -} - -static void BeginSurface( drawSurf_t *surf ) { - if( WouldOverflow( surf ) ) { - return; - } - - tess.texnum = ( surf->key >> 16 ) & 1023; - tess.lightmapnum = surf->key & 0xFFFF; - - (*tessTable[surf->surf->type])( surf ); -} - -void GL_SortAndDrawSurfs( qboolean doSort ) { - drawSurf_t *surf, *last; - int oldkey; - - if( !numDrawSurfs ) { - return; - } - - if( numDrawSurfs > MAX_DRAW_SURFS ) { - Com_DPrintf( "MAX_DRAW_SURFS exceeded\n" ); - numDrawSurfs = MAX_DRAW_SURFS; - } - - if( doSort && gl_sort->integer ) { - mergeSort_r( 0, numDrawSurfs - 1 ); - } - - surf = drawSurfs; - last = drawSurfs + numDrawSurfs; - oldkey = surf->key; - BeginSurface( surf ); - surf++; - - for( ; surf != last; surf++ ) { - if( oldkey == surf->key && !WouldOverflow( surf ) ) { - (*tessTable[surf->surf->type])( surf ); - continue; - } - - EndSurface( surf - 1 ); - - oldkey = surf->key; - BeginSurface( surf ); - } - - EndSurface( surf - 1 ); - - numDrawSurfs = 0; -} - void GL_Flush2D( void ) { glStateBits_t bits; @@ -878,51 +36,47 @@ void GL_Flush2D( void ) { bits |= GLS_ALPHATEST_ENABLE; } + GL_BindTexture( tess.texnum ); GL_TexEnv( GL_MODULATE ); GL_Bits( bits ); + qglEnableClientState( GL_COLOR_ARRAY ); - qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.colors ); - EndSurface_Single(); + qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.colors ); + qglTexCoordPointer( 2, GL_FLOAT, 0, tess.tcoords ); + qglVertexPointer( 3, GL_FLOAT, 16, tess.vertices ); + + qglDrawArrays( GL_QUADS, 0, tess.numVertices ); qglDisableClientState( GL_COLOR_ARRAY ); tess.numVertices = 0; - tess.numIndices = 0; tess.texnum = 0; tess.istrans = 0; - } void GL_StretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, const byte *color, image_t *image ) { - int currentVert, currentIdx; vec_t *dst_vert; - int *dst_idx; tcoord_t *dst_tc; uint32 *dst_color; if( tess.numVertices + 4 > TESS_MAX_VERTICES || - tess.numIndices + 6 > TESS_MAX_INDICES || ( tess.numVertices && tess.texnum != image->texnum ) ) { GL_Flush2D(); } - currentVert = tess.numVertices; - currentIdx = tess.numIndices; - tess.numVertices += 4; - tess.numIndices += 6; tess.texnum = image->texnum; - dst_vert = tess.vertices + currentVert * 4; - VectorSet( dst_vert + 0, x, y, 0 ); - VectorSet( dst_vert + 4, x + w, y, 0 ); + dst_vert = tess.vertices + tess.numVertices * 4; + VectorSet( dst_vert, x, y, 0 ); + VectorSet( dst_vert + 4, x + w, y, 0 ); VectorSet( dst_vert + 8, x + w, y + h, 0 ); - VectorSet( dst_vert + 12, x, y + h, 0 ); + VectorSet( dst_vert + 12, x, y + h, 0 ); - dst_color = ( uint32 * )tess.colors + currentVert; + dst_color = ( uint32 * )tess.colors + tess.numVertices; dst_color[0] = *( const uint32 * )color; dst_color[1] = *( const uint32 * )color; dst_color[2] = *( const uint32 * )color; @@ -939,20 +93,13 @@ void GL_StretchPic( float x, float y, float w, float h, tess.istrans |= 2; } - dst_tc = tess.tcoords + currentVert; + dst_tc = tess.tcoords + tess.numVertices; dst_tc[0].st[0] = s1; dst_tc[0].st[1] = t1; dst_tc[1].st[0] = s2; dst_tc[1].st[1] = t1; dst_tc[2].st[0] = s2; dst_tc[2].st[1] = t2; dst_tc[3].st[0] = s1; dst_tc[3].st[1] = t2; - dst_idx = tess.indices + currentIdx; - dst_idx[0] = currentVert; - dst_idx[1] = currentVert + 1; - dst_idx[2] = currentVert + 2; - dst_idx[3] = currentVert; - dst_idx[4] = currentVert + 2; - dst_idx[5] = currentVert + 3; - + tess.numVertices += 4; } void GL_DrawParticles( void ) { @@ -961,23 +108,25 @@ void GL_DrawParticles( void ) { vec3_t transformed; vec_t scale, dist; color_t color; - int currentVert; + int numVertices; vec_t *dst_vert; uint32 *dst_color; tcoord_t *dst_tc; - int *dst_idx; if( !glr.fd.num_particles ) { return; } + GL_BindTexture( r_particletexture->texnum ); GL_TexEnv( GL_MODULATE ); GL_Bits( GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE ); + qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.colors ); + qglTexCoordPointer( 2, GL_FLOAT, 0, tess.tcoords ); + qglVertexPointer( 3, GL_FLOAT, 16, tess.vertices ); - tess.texnum = r_particletexture->texnum; - currentVert = 0; + numVertices = 0; for( i = 0, p = glr.fd.particles; i < glr.fd.num_particles; i++, p++ ) { VectorSubtract( p->origin, glr.fd.vieworg, transformed ); dist = DotProduct( transformed, glr.viewaxis[0] ); @@ -994,43 +143,31 @@ void GL_DrawParticles( void ) { } color[3] = p->alpha * 255; - if( currentVert + 3 > TESS_MAX_VERTICES || - currentVert + 3 > TESS_MAX_INDICES ) - { - tess.numVertices = tess.numIndices = currentVert; - EndSurface_Single(); - currentVert = 0; + if( numVertices + 3 > TESS_MAX_VERTICES ) { + qglDrawArrays( GL_TRIANGLES, 0, numVertices ); + numVertices = 0; } - dst_vert = tess.vertices + currentVert * 4; + dst_vert = tess.vertices + numVertices * 4; // VectorMA( p->origin, -scale*0.5f, glr.viewaxis[2], dst_vert ); VectorMA( p->origin, scale*0.5f, glr.viewaxis[1], dst_vert ); VectorMA( dst_vert, scale, glr.viewaxis[2], dst_vert + 4 ); VectorMA( dst_vert, -scale, glr.viewaxis[1], dst_vert + 8 ); - dst_color = ( uint32 * )tess.colors + currentVert; + dst_color = ( uint32 * )tess.colors + numVertices; dst_color[0] = *( uint32 * )color; dst_color[1] = *( uint32 * )color; dst_color[2] = *( uint32 * )color; - dst_tc = tess.tcoords + currentVert; + dst_tc = tess.tcoords + numVertices; dst_tc[0].st[0] = 0.0625f; dst_tc[0].st[1] = 0.0625f; dst_tc[1].st[0] = 1.0625f; dst_tc[1].st[1] = 0.0625f; dst_tc[2].st[0] = 0.0625f; dst_tc[2].st[1] = 1.0625f; - dst_idx = tess.indices + currentVert; - dst_idx[0] = currentVert; - dst_idx[1] = currentVert + 1; - dst_idx[2] = currentVert + 2; - - currentVert += 3; + numVertices += 3; } - tess.numVertices = tess.numIndices = currentVert; - EndSurface_Single(); - tess.numVertices = tess.numIndices = 0; - tess.texnum = 0; - + qglDrawArrays( GL_TRIANGLES, 0, numVertices ); qglDisableClientState( GL_COLOR_ARRAY ); } @@ -1042,9 +179,8 @@ void GL_DrawBeams( void ) { vec_t *dst_vert; uint32 *dst_color; tcoord_t *dst_tc; - int *dst_idx; vec_t length; - int currentVert, currentIdx; + int numVertices; entity_t *ent; int i; @@ -1052,14 +188,15 @@ void GL_DrawBeams( void ) { return; } + GL_BindTexture( r_beamtexture->texnum ); GL_TexEnv( GL_MODULATE ); GL_Bits( GLS_BLEND_ADD | GLS_DEPTHMASK_FALSE ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.colors ); + qglTexCoordPointer( 2, GL_FLOAT, 0, tess.tcoords ); + qglVertexPointer( 3, GL_FLOAT, 16, tess.vertices ); - tess.texnum = r_beamtexture->texnum; - currentVert = 0; - currentIdx = 0; + numVertices = 0; for( i = 0, ent = glr.fd.entities; i < glr.fd.num_entities; i++, ent++ ) { if( !( ent->flags & RF_BEAM ) ) { continue; @@ -1082,111 +219,67 @@ void GL_DrawBeams( void ) { } color[3] = 255 * ent->alpha; - if( currentVert + 4 > TESS_MAX_VERTICES || - currentIdx + 6 > TESS_MAX_INDICES ) - { - tess.numVertices = currentVert; - tess.numIndices = currentIdx; - EndSurface_Single(); - currentVert = 0; - currentIdx = 0; + if( numVertices + 4 > TESS_MAX_VERTICES ) { + qglDrawArrays( GL_QUADS, 0, numVertices ); + numVertices = 0; } - dst_vert = tess.vertices + currentVert * 4; + dst_vert = tess.vertices + numVertices * 4; VectorAdd( start, d3, dst_vert ); VectorSubtract( start, d3, dst_vert + 4 ); VectorSubtract( end, d3, dst_vert + 8 ); VectorAdd( end, d3, dst_vert + 12 ); - dst_color = ( uint32 * )tess.colors + currentVert; + dst_color = ( uint32 * )tess.colors + numVertices; dst_color[0] = *( uint32 * )color; dst_color[1] = *( uint32 * )color; dst_color[2] = *( uint32 * )color; dst_color[3] = *( uint32 * )color; - dst_tc = tess.tcoords + currentVert; + dst_tc = tess.tcoords + numVertices; dst_tc[0].st[0] = 0; dst_tc[0].st[1] = 0; dst_tc[1].st[0] = 1; dst_tc[1].st[1] = 0; dst_tc[2].st[0] = 1; dst_tc[2].st[1] = length; dst_tc[3].st[0] = 0; dst_tc[3].st[1] = length; - dst_idx = tess.indices + currentIdx; - dst_idx[0] = currentVert + 0; - dst_idx[1] = currentVert + 1; - dst_idx[2] = currentVert + 2; - dst_idx[3] = currentVert + 2; - dst_idx[4] = currentVert + 3; - dst_idx[5] = currentVert + 0; - - currentVert += 4; - currentIdx += 6; + numVertices += 4; } - - tess.numVertices = currentVert; - tess.numIndices = currentIdx; - EndSurface_Single(); - tess.numVertices = tess.numIndices = 0; - tess.texnum = 0; - + + qglDrawArrays( GL_QUADS, 0, numVertices ); qglDisableClientState( GL_COLOR_ARRAY ); - - qglDisableClientState( GL_COLOR_ARRAY ); - } -static void GL_DrawWarpPolys( bspSurface_t *surf ) { - bspPoly_t *poly; - vec_t *vert; - int i, j, k; - vec_t s, t; - - for( poly = surf->polys; poly; poly = poly->next ) { - vert = poly->vertices; - qglBegin( GL_TRIANGLE_FAN ); - for( i = 0; i < poly->numVerts + 1; i++ ) { - if( i == poly->numVerts ) { - vert = poly->vertices + VERTEX_SIZE; - } +static void GL_DrawWarp( bspSurface_t *surf ) { + bspPoly_t *poly = surf->polys; + vec4_t param; - j = Q_ftol( ( vert[4] * 0.125 + glr.fd.time ) * TURB_SCALE ); - k = Q_ftol( ( vert[3] * 0.125 + glr.fd.time ) * TURB_SCALE ); - - s = vert[3] + r_turbsin[j & 255]; - s *= DIV64; + qglEnable( GL_FRAGMENT_PROGRAM_ARB ); + qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, gl_static.prog_warp ); + param[0] = glr.fd.time * 0.125f; + param[1] = glr.fd.time * 0.125f; + param[2] = param[3] = 0; + qglProgramLocalParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 0, param ); - t = vert[4] + r_turbsin[k & 255]; - t *= DIV64; + GL_SelectTMU( 1 ); + qglEnable( GL_TEXTURE_2D ); + //GL_TexEnv( GL_MODULATE ); + GL_BindTexture( r_warptexture->texnum ); - qglTexCoord2f( s, t ); - qglVertex3fv( vert ); + qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); + qglTexCoordPointer( 2, GL_FLOAT, 4*VERTEX_SIZE, poly->vertices + 3 ); - vert += VERTEX_SIZE; - } - qglEnd(); - } -} + qglDrawArrays( GL_POLYGON, 0, poly->numVerts ); -static void GL_DrawNolmPoly( bspSurface_t *surf ) { - bspPoly_t *poly = surf->polys; - vec_t *vert; - int i; + qglDisable( GL_TEXTURE_2D ); + qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); + GL_SelectTMU( 0 ); - qglBegin( GL_POLYGON ); - vert = poly->vertices; - for( i = 0; i < poly->numVerts; i++ ) { - qglTexCoord2fv( vert + 3 ); - qglVertex3fv( vert ); - vert += VERTEX_SIZE; - } - qglEnd(); + qglDisable( GL_FRAGMENT_PROGRAM_ARB ); } - -void GL_DrawSurfPoly( bspSurface_t *surf ) { +void GL_DrawSurf( bspSurface_t *surf ) { bspTexinfo_t *texinfo = surf->texinfo; - bspPoly_t *poly; - vec_t *vert; - int i; + bspPoly_t *poly = surf->polys; if( ( texinfo->flags & SURF_SKY ) && !gl_fastsky->integer ) { R_AddSkySurface( surf ); @@ -1200,43 +293,40 @@ void GL_DrawSurfPoly( bspSurface_t *surf ) { } else { qglColor4f( 1, 1, 1, 0.66f ); } + GL_TexEnv( GL_MODULATE ); } else { - qglColor4f( 1, 1, 1, 1 ); GL_Bits( GLS_DEFAULT ); - qglColor4ubv( colorWhite ); + GL_TexEnv( GL_REPLACE ); + qglColor4f( 1, 1, 1, 1 ); } - GL_TexEnv( GL_MODULATE ); GL_BindTexture( texinfo->image->texnum ); - if( surf->type == DSURF_WARP ) { - GL_DrawWarpPolys( surf ); - return; - } + qglVertexPointer( 3, GL_FLOAT, 4*VERTEX_SIZE, poly->vertices ); + qglTexCoordPointer( 2, GL_FLOAT, 4*VERTEX_SIZE, poly->vertices + 3 ); + + if( surf->type == DSURF_WARP ) { +// qglDrawArrays( GL_POLYGON, 0, poly->numVerts ); + GL_DrawWarp( surf ); + return; + } if( surf->type == DSURF_NOLM ) { - GL_DrawNolmPoly( surf ); + qglDrawArrays( GL_POLYGON, 0, poly->numVerts ); return; } GL_SelectTMU( 1 ); qglEnable( GL_TEXTURE_2D ); - GL_BindTexture( lm.lightmaps[ surf->lightmapnum - 1 ]->texnum ); GL_TexEnv( GL_MODULATE ); - - poly = surf->polys; - vert = poly->vertices; - qglBegin( GL_POLYGON ); - for( i = 0; i < poly->numVerts; i++ ) { - qglMultiTexCoord2fvARB( GL_TEXTURE0_ARB, vert + 3 ); - qglMultiTexCoord2fvARB( GL_TEXTURE1_ARB, vert + 5 ); - qglVertex3fv( vert ); - vert += VERTEX_SIZE; - - } - qglEnd(); + GL_BindTexture( lm.lightmaps[surf->lightmapnum]->texnum ); + qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); + qglTexCoordPointer( 2, GL_FLOAT, 4*VERTEX_SIZE, poly->vertices + 5 ); + + qglDrawArrays( GL_POLYGON, 0, poly->numVerts ); qglDisable( GL_TEXTURE_2D ); + qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); GL_SelectTMU( 0 ); } diff --git a/source/gl_world.c b/source/gl_world.c index ea05f5c..0626c41 100644 --- a/source/gl_world.c +++ b/source/gl_world.c @@ -22,10 +22,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. vec3_t modelViewOrigin; /* viewer origin in model space */ +#define FACE_HASH_SIZE 32 +#define FACE_HASH_MASK ( FACE_HASH_SIZE - 1 ) + static vec3_t lightcolor; +static bspSurface_t *alphaFaces; +//static bspSurface_t *warpFaces; +static bspSurface_t *faces_hash[FACE_HASH_SIZE]; static qboolean GL_LightPoint_r( bspNode_t *node, vec3_t start, vec3_t end ) { - cplane_t *plane; vec_t startFrac, endFrac, midFrac; vec3_t mid; int side; @@ -39,13 +44,13 @@ static qboolean GL_LightPoint_r( bspNode_t *node, vec3_t start, vec3_t end ) { int w1, w2, w3, w4; int color[3]; - if( !( plane = node->plane ) ) { + if( !node->plane ) { return qfalse; } /* calculate distancies */ - startFrac = DotProduct( plane->normal, start ) - plane->dist; - endFrac = DotProduct( plane->normal, end ) - plane->dist; + startFrac = PlaneDiffFast( start, node->plane ); + endFrac = PlaneDiffFast( end, node->plane ); side = ( startFrac < 0 ); if( ( endFrac < 0 ) == side ) { @@ -55,9 +60,7 @@ static qboolean GL_LightPoint_r( bspNode_t *node, vec3_t start, vec3_t end ) { /* find crossing point */ midFrac = startFrac / ( startFrac - endFrac ); - mid[0] = start[0] + ( end[0] - start[0] ) * midFrac; - mid[1] = start[1] + ( end[1] - start[1] ) * midFrac; - mid[2] = start[2] + ( end[2] - start[2] ) * midFrac; + LerpVector( start, end, midFrac, mid ); /* check near side */ ret = GL_LightPoint_r( node->children[side], start, mid ); @@ -114,15 +117,16 @@ static qboolean GL_LightPoint_r( bspNode_t *node, vec3_t start, vec3_t end ) { /* check far side */ return GL_LightPoint_r( node->children[side^1], mid, end ); - } void GL_LightPoint( vec3_t origin, vec3_t dest ) { extern cvar_t *gl_modulate_hack; vec3_t point; +#if USE_DYNAMIC dlight_t *light; vec3_t dir; vec_t dist, f; +#endif int i; if( !r_world.name[0] || gl_fullbright->integer ) { @@ -143,6 +147,7 @@ void GL_LightPoint( vec3_t origin, vec3_t dest ) { VectorScale( lightcolor, gl_modulate->value, lightcolor ); } +#if USE_DYNAMIC for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) { VectorSubtract( light->origin, origin, dir ); dist = VectorLength( dir ); @@ -152,6 +157,7 @@ void GL_LightPoint( vec3_t origin, vec3_t dest ) { f = 1.0f - dist / light->intensity; VectorMA( lightcolor, f, light->color, lightcolor ); } +#endif /* apply modulate twice to mimic original ref_gl behavior */ VectorScale( lightcolor, gl_modulate->value, lightcolor ); @@ -168,28 +174,15 @@ void GL_LightPoint( vec3_t origin, vec3_t dest ) { } +#if USE_DYNAMIC static void GL_MarkLights_r( bspNode_t *node, dlight_t *light ) { - cplane_t *plane; vec_t dot; - int lightbit, count; + int count; bspSurface_t *face; + int lightbit = 1 << light->index; - while( ( plane = node->plane ) != NULL ) { - switch( plane->type ) { - case PLANE_X: - dot = light->transformed[0] - plane->dist; - break; - case PLANE_Y: - dot = light->transformed[1] - plane->dist; - break; - case PLANE_Z: - dot = light->transformed[2] - plane->dist; - break; - default: - dot = DotProduct( light->transformed, plane->normal ) - plane->dist; - break; - } - + while( node->plane ) { + dot = PlaneDiffFast( light->transformed, node->plane ); if( dot > light->intensity ) { node = node->children[0]; continue; @@ -199,7 +192,6 @@ static void GL_MarkLights_r( bspNode_t *node, dlight_t *light ) { continue; } - lightbit = 1 << light->index; face = node->firstFace; count = node->numFaces; while( count-- ) { @@ -253,8 +245,8 @@ static void GL_TransformLights( bspSubmodel_t *model ) { GL_MarkLights_r( model->headnode, light ); } - } +#endif void GL_MarkLeaves( void ) { byte fatvis[MAX_MAP_LEAFS/8]; @@ -352,6 +344,25 @@ finish: } +static inline void GL_AddSurf( bspSurface_t *face ) { + if( face->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) { + face->next = alphaFaces; + alphaFaces = face; + } /*else if( face->type == SURF_WARP ) { + face->next = warpFaces; + warpFaces = face; + } */else { +#if 0 + GL_DrawSurf( face ); +#else + int i = ( face->texinfo->image->texnum ^ face->lightmapnum ) & FACE_HASH_MASK; + face->next = faces_hash[i]; + faces_hash[i] = face; +#endif + } + c.facesDrawn++; +} + #define NODE_CLIPPED 0 #define NODE_UNCLIPPED 15 @@ -378,15 +389,6 @@ static inline qboolean GL_ClipNodeToFrustum( bspNode_t *node, int *clipflags ) { return qtrue; } -typedef void (*drawFaceFunc_t)( bspSurface_t *surf ); - -static drawFaceFunc_t drawFaceFunc; -static drawFaceFunc_t drawFaceFuncTable[] = { - GL_AddBspSurface, - GL_DrawSurfPoly -}; - -static bspSurface_t *alphaFaces; #define BACKFACE_EPSILON 0.001f @@ -398,7 +400,6 @@ void GL_DrawBspModel( bspSubmodel_t *model ) { int count; vec3_t bounds[2]; vec_t dot; - cplane_t *plane; vec3_t temp; entity_t *ent = glr.ent; glCullResult_t cull; @@ -435,65 +436,45 @@ void GL_DrawBspModel( bspSubmodel_t *model ) { glr.drawframe++; +#if USE_DYNAMIC if( gl_dynamic->integer ) { GL_TransformLights( model ); } +#endif + + qglPushMatrix(); + qglTranslatef( ent->origin[0], ent->origin[1], ent->origin[2] ); + if( glr.entrotated ) { + qglRotatef( ent->angles[YAW], 0, 0, 1 ); + qglRotatef( ent->angles[PITCH], 0, 1, 0 ); + qglRotatef( ent->angles[ROLL], 1, 0, 0 ); + } /* draw visible faces */ /* FIXME: go by headnode instead? */ face = model->firstFace; count = model->numFaces; while( count-- ) { - plane = face->plane; - switch( plane->type ) { - case PLANE_X: - dot = modelViewOrigin[0] - plane->dist; - break; - case PLANE_Y: - dot = modelViewOrigin[1] - plane->dist; - break; - case PLANE_Z: - dot = modelViewOrigin[2] - plane->dist; - break; - default: - dot = DotProduct( modelViewOrigin, plane->normal ) - plane->dist; - break; - } + dot = PlaneDiffFast( modelViewOrigin, face->plane ); if( ( dot < -BACKFACE_EPSILON && face->side == SIDE_FRONT ) || ( dot > BACKFACE_EPSILON && face->side == SIDE_BACK ) ) { c.facesCulled++; } else { - if( face->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) { - face->next = alphaFaces; - alphaFaces = face; - } else { - GL_AddBspSurface( face ); - } - c.facesDrawn++; + /* FIXME: warp/trans surfaces are not supported */ + GL_DrawSurf( face ); } face++; } - qglPushMatrix(); - qglTranslatef( ent->origin[0], ent->origin[1], ent->origin[2] ); - if( glr.entrotated ) { - qglRotatef( ent->angles[YAW], 0, 0, 1 ); - qglRotatef( ent->angles[PITCH], 0, 1, 0 ); - qglRotatef( ent->angles[ROLL], 1, 0, 0 ); - } - GL_SortAndDrawSurfs( qtrue ); qglPopMatrix(); - } static void GL_WorldNode_r( bspNode_t *node, int clipflags ) { bspLeaf_t *leaf; bspSurface_t **leafFace, *face; int count, side, area; - cplane_t *plane; vec_t dot; - uint32 type; while( node->visframe == glr.visframe ) { if( gl_cull_nodes->integer && clipflags != NODE_UNCLIPPED && @@ -521,16 +502,9 @@ static void GL_WorldNode_r( bspNode_t *node, int clipflags ) { break; } - plane = node->plane; - type = plane->type; - if( type < 3 ) { - dot = modelViewOrigin[type] - plane->dist; - } else { - dot = DotProduct( modelViewOrigin, plane->normal ) - plane->dist; - } + dot = PlaneDiffFast( modelViewOrigin, node->plane ); + side = ( dot < 0 ); - side = dot < 0; - GL_WorldNode_r( node->children[side], clipflags ); face = node->firstFace; @@ -538,13 +512,7 @@ static void GL_WorldNode_r( bspNode_t *node, int clipflags ) { while( count-- ) { if( face->drawframe == glr.drawframe ) { if( face->side == side ) { - if( face->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) { - face->next = alphaFaces; - alphaFaces = face; - } else { - drawFaceFunc( face ); - } - c.facesDrawn++; + GL_AddSurf( face ); } else { c.facesCulled++; } @@ -560,47 +528,49 @@ static void GL_WorldNode_r( bspNode_t *node, int clipflags ) { } void GL_DrawWorld( void ) { + int i; + bspSurface_t *face; + GL_MarkLeaves(); +#if USE_DYNAMIC if( gl_dynamic->integer ) { GL_MarkLights(); } +#endif R_ClearSkyBox(); - drawFaceFunc = drawFaceFuncTable[gl_primitives->integer & 1]; - VectorCopy( glr.fd.vieworg, modelViewOrigin ); GL_WorldNode_r( r_world.nodes, NODE_CLIPPED ); - GL_SortAndDrawSurfs( qtrue ); + + for( i = 0; i < FACE_HASH_SIZE; i++ ) { + for( face = faces_hash[i]; face; face = face->next ) { + GL_DrawSurf( face ); + } + faces_hash[i] = NULL; + } if( !gl_fastsky->integer ) { R_DrawSkyBox(); } - } void GL_DrawAlphaFaces( void ) { bspSurface_t *face, *next; - face = alphaFaces; - if( !face ) { - return; - } - - drawFaceFunc = drawFaceFuncTable[gl_primitives->integer & 1]; - - do { - drawFaceFunc( face ); - /* Prevent loop condition in case the same face is included twice. - * This should never happen normally. */ - next = face->next; - face->next = NULL; - face = next; - } while( face ); + if( ( face = alphaFaces ) == NULL ) { + return; + } - GL_SortAndDrawSurfs( qfalse ); + do { + GL_DrawSurf( face ); + next = face->next; + face->next = NULL; + face = next; + } while( face ); - alphaFaces = NULL; + alphaFaces = NULL; } + diff --git a/source/q_shared.h b/source/q_shared.h index 53553aa..2c3a406 100644 --- a/source/q_shared.h +++ b/source/q_shared.h @@ -250,7 +250,7 @@ static inline float Q_fabs( float f ) { ((d)[0]=(a)[0]+(c)*((b)[0]-(a)[0]), \ (d)[1]=(a)[1]+(c)*((b)[1]-(a)[1]), \ (d)[2]=(a)[2]+(c)*((b)[2]-(a)[2])) - +#define PlaneDiff(v,p) (DotProduct(v,(p)->normal)-(p)->dist) #define Vector4Subtract(a,b,c) (c[0]=a[0]-b[0],c[1]=a[1]-b[1],c[2]=a[2]-b[2],c[3]=a[3]-b[3]) #define Vector4Add(a,b,c) (c[0]=a[0]+b[0],c[1]=a[1]+b[1],c[2]=a[2]+b[2],c[3]=a[3]+b[3]) @@ -734,6 +734,15 @@ static inline int BoxOnPlaneSideFast( vec3_t emins, vec3_t emaxs, cplane_t *p ) return BoxOnPlaneSide( emins, emaxs, p ); } +static inline vec_t PlaneDiffFast( vec3_t v, cplane_t *p ) { + // fast axial cases + if( p->type < 3 ) { + return v[p->type] - p->dist; + } + + // slow generic case + return PlaneDiff( v, p ); +} typedef struct csurface_s { diff --git a/source/qgl_api.c b/source/qgl_api.c index 1f24f30..a796ca5 100644 --- a/source/qgl_api.c +++ b/source/qgl_api.c @@ -382,12 +382,16 @@ void ( APIENTRY * qglUnlockArraysEXT) ( void ); void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value ); void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value ); void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * ); -void ( APIENTRY * qglSelectTextureSGIS)( GLenum ); -void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat ); -void ( APIENTRY * qglMultiTexCoord2fvARB)( GLenum, const GLfloat * ); + void ( APIENTRY * qglActiveTextureARB) ( GLenum ); void ( APIENTRY * qglClientActiveTextureARB) ( GLenum ); +void ( APIENTRY * qglProgramStringARB)( GLenum target, GLenum format, GLsizei len, const GLvoid *string ); +void ( APIENTRY * qglBindProgramARB)( GLenum target, GLuint program ); +void ( APIENTRY * qglDeleteProgramsARB)( GLsizei n, const GLuint *programs ); +void ( APIENTRY * qglGenProgramsARB)( GLsizei n, GLuint *programs ); +void ( APIENTRY * qglProgramLocalParameter4fvARB)( GLenum, GLuint, const GLfloat * ); + #ifdef _WIN32 PROC ( WINAPI * qwglGetProcAddress )( LPCSTR ); BOOL ( WINAPI * qwglSwapIntervalEXT )( int interval ); @@ -3327,12 +3331,16 @@ void QGL_Init( void ) { qglPointParameterfEXT = 0; qglPointParameterfvEXT = 0; qglColorTableEXT = 0; - qglSelectTextureSGIS = 0; - qglMTexCoord2fSGIS = 0; - qglMultiTexCoord2fvARB = 0; + qglActiveTextureARB = 0; qglClientActiveTextureARB = 0; + qglProgramStringARB = 0; + qglBindProgramARB = 0; + qglDeleteProgramsARB = 0; + qglGenProgramsARB = 0; + qglProgramLocalParameter4fvARB = 0; + #ifdef _WIN32 qwglGetProcAddress = GPA( "wglGetProcAddress" ); #endif diff --git a/source/qgl_api.h b/source/qgl_api.h index a63a5a4..91599c8 100644 --- a/source/qgl_api.h +++ b/source/qgl_api.h @@ -377,13 +377,15 @@ extern void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void extern void ( APIENTRY * qglLockArraysEXT) (int , int); extern void ( APIENTRY * qglUnlockArraysEXT) (void); -extern void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat ); -extern void ( APIENTRY * qglSelectTextureSGIS)( GLenum ); - -extern void ( APIENTRY * qglMultiTexCoord2fvARB)( GLenum, const GLfloat * ); extern void ( APIENTRY * qglActiveTextureARB)( GLenum ); extern void ( APIENTRY * qglClientActiveTextureARB)( GLenum ); +extern void ( APIENTRY * qglProgramStringARB)( GLenum target, GLenum format, GLsizei len, const GLvoid *string ); +extern void ( APIENTRY * qglBindProgramARB)( GLenum target, GLuint program ); +extern void ( APIENTRY * qglDeleteProgramsARB)( GLsizei n, const GLuint *programs ); +extern void ( APIENTRY * qglGenProgramsARB)( GLsizei n, GLuint *programs ); +extern void ( APIENTRY * qglProgramLocalParameter4fvARB)( GLenum, GLuint, const GLfloat * ); + // // OS-specific // diff --git a/source/r_shared.h b/source/r_shared.h index d9732a9..70a32da 100644 --- a/source/r_shared.h +++ b/source/r_shared.h @@ -222,7 +222,6 @@ typedef struct bspSurface_s { int extents[2]; #ifdef OPENGL_RENDERER - struct tcoord_s *normalizedTC; struct bspPoly_s *polys; int lightmapnum; diff --git a/source/snd_dx.c b/source/snd_dx.c index 660543c..3160aea 100644 --- a/source/snd_dx.c +++ b/source/snd_dx.c @@ -209,7 +209,7 @@ DS_Init Direct-Sound support ================== */ -static sndinitstat DS_Init (void) { +static sndinitstat_t DS_Init (void) { DSCAPS dscaps; HRESULT hresult; LPDIRECTSOUNDCREATE pDirectSoundCreate; @@ -298,49 +298,32 @@ static sndinitstat DS_Init (void) { /* ============== -DS_GetDMAPos +DS_BeginPainting + +Makes sure dma.buffer is valid. -return the current sample position (in mono samples read) +Returns the current sample position (in mono samples read) inside the recirculating dma buffer, so the mixing code will know how many sample are required to fill it up. =============== */ -static int DS_GetDMAPos(void) { - MMTIME mmtime; - int s; - DWORD dwWrite; - - if (!pDSBuf) { - return 0; - } - - mmtime.wType = TIME_SAMPLES; - IDirectSoundBuffer_GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite); - s = mmtime.u.sample - mmstarttime.u.sample; - - s >>= sample16; - s &= (dma.samples-1); - - return s; -} - -/* -============== -DS_BeginPainting - -Makes sure dma.buffer is valid -=============== -*/ static void DS_BeginPainting (void) { - int reps; + int reps, s; DWORD dwSize2; DWORD *pbuf, *pbuf2; HRESULT hresult; - DWORD dwStatus; + DWORD dwStatus, dwWrite; + MMTIME mmtime; if (!pDSBuf) return; + // get sample pos + mmtime.wType = TIME_SAMPLES; + IDirectSoundBuffer_GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite); + s = ( mmtime.u.sample - mmstarttime.u.sample ) >> sample16; + dma.samplepos = s & ( dma.samples - 1 ); + // if the buffer was lost or stopped, restore it and/or restart it if (IDirectSoundBuffer_GetStatus (pDSBuf, &dwStatus) != DS_OK) { Com_EPrintf ("DS_BeginPainting: Couldn't get sound buffer status\n"); @@ -417,7 +400,6 @@ static void DS_Activate (qboolean active) { void DS_FillAPI( snddmaAPI_t *api ) { api->Init = DS_Init; - api->GetDMAPos = DS_GetDMAPos; api->Shutdown = DS_Shutdown; api->BeginPainting = DS_BeginPainting; api->Submit = DS_Submit; diff --git a/source/snd_local.h b/source/snd_local.h index af0f1e1..51a84f9 100644 --- a/source/snd_local.h +++ b/source/snd_local.h @@ -98,17 +98,15 @@ typedef struct channel_s ==================================================================== */ -typedef enum { SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL } sndinitstat; +typedef enum { SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL } sndinitstat_t; typedef struct snddmaAPI_s { // initializes cycling through a DMA buffer and returns information on it - sndinitstat (*Init)( void ); - -// gets the current DMA position - int (*GetDMAPos)( void ); + sndinitstat_t (*Init)( void ); // shutdown the DMA xfer. void (*Shutdown)( void ); + void (*BeginPainting)( void ); void (*Submit)( void ); void (*Activate)( qboolean active ); @@ -122,13 +120,9 @@ extern snddmaAPI_t snddma; extern channel_t channels[MAX_CHANNELS]; extern int paintedtime; -extern int s_rawend; extern dma_t dma; extern playsound_t s_pendingplays; -#define MAX_RAW_SAMPLES 8192 -extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES]; - extern cvar_t *s_volume; extern cvar_t *s_khz; extern cvar_t *s_testsound; diff --git a/source/snd_main.c b/source/snd_main.c index ddc3362..4418b46 100644 --- a/source/snd_main.c +++ b/source/snd_main.c @@ -47,7 +47,6 @@ int listener_entnum; qboolean s_registering; -int soundtime; // sample PAIRS int paintedtime; // sample PAIRS // during registration it is possible to have more sounds @@ -76,44 +75,46 @@ static cvar_t *s_driver; static cvar_t *s_ambient; -int s_rawend; -portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES]; - snddmaAPI_t snddma; -#if (defined _WIN32) +#if USE_WAVE void WAVE_FillAPI( snddmaAPI_t *api ); +#endif + +#if USE_DSOUND void DS_FillAPI( snddmaAPI_t *api ); -#elif (defined __unix__) +#endif + +#if USE_OSS void OSS_FillAPI( snddmaAPI_t *api ); #endif -#if (defined _WIN32) && (defined USE_DSOUND) -#define DEFAULT_SOUND_DRIVER "dsound" -#else -#define DEFAULT_SOUND_DRIVER "" +#if USE_SDL +void QSDL_FillSoundAPI( snddmaAPI_t *api ); #endif -typedef struct sndDriver_s { - char *name; - void (*FillAPI)( snddmaAPI_t *api ); -} sndDriver_t; -static sndDriver_t s_driverTable[] = { - /* fallback driver should be present on all systems */ -#if (defined _WIN32) +// the first driver is the default one +static struct { + char name[16]; + void (*FillAPI)( snddmaAPI_t *api ); +} s_driverTable[] = { +#if USE_DSOUND + { "dsound", DS_FillAPI }, +#endif +#if USE_WAVE { "wave", WAVE_FillAPI }, -#elif (defined __unix__) +#endif +#if USE_OSS { "oss", OSS_FillAPI }, #endif - - /* DirectSound driver */ -#ifdef USE_DSOUND - { "dsound", DS_FillAPI }, +#if USE_SDL + { "sdl", QSDL_FillSoundAPI }, #endif }; -static int s_numDrivers = sizeof( s_driverTable ) / sizeof( s_driverTable[0] ); +static const int s_numDrivers = + sizeof( s_driverTable ) / sizeof( s_driverTable[0] ); /* ========================================================================== @@ -204,9 +205,8 @@ S_Init */ void S_Init( void ) { cvar_t *cv; - sndDriver_t *driver; - int i; - sndinitstat ret = SIS_FAILURE; + int i, j = 0; + sndinitstat_t ret; cv = Cvar_Get( "s_initsound", "1", 0 ); if( !cv->integer ) { @@ -217,48 +217,43 @@ void S_Init( void ) { Com_Printf( "------- S_Init -------\n" ); s_volume = Cvar_Get( "s_volume", "0.7", CVAR_ARCHIVE ); - s_khz = Cvar_Get( "s_khz", "11", CVAR_ARCHIVE ); + s_khz = Cvar_Get( "s_khz", "22", CVAR_ARCHIVE ); s_loadas8bit = Cvar_Get( "s_loadas8bit", "1", CVAR_ARCHIVE ); s_mixahead = Cvar_Get( "s_mixahead", "0.2", CVAR_ARCHIVE ); s_show = Cvar_Get( "s_show", "0", 0 ); s_testsound = Cvar_Get( "s_testsound", "0", 0 ); - s_driver = Cvar_Get( "s_driver", DEFAULT_SOUND_DRIVER, CVAR_LATCHED ); + s_driver = Cvar_Get( "s_driver", "", CVAR_LATCHED ); s_driver->subsystem = CVAR_SYSTEM_SOUND; s_ambient = Cvar_Get( "s_ambient", "1", 0 ); + // determine the first driver to try + if( s_driver->string[0] ) { + for( i = 0; i < s_numDrivers; i++ ) { + if( !strcmp( s_driver->string, s_driverTable[i].name ) ) { + j = i; + break; + } + } + } + + // cycle until usable driver is found + i = j; while( 1 ) { - if( s_driver->string[0] ) { - for( i = 0, driver = s_driverTable; i < s_numDrivers; i++, driver++ ) { - if( !strcmp( s_driver->string, driver->name ) ) { - break; - } - } - if( i == s_numDrivers ) { - Com_Printf( "Sound driver '%s' not found, falling back to default...\n", s_driver->string ); - Cvar_Set( "s_driver", "" ); - driver = &s_driverTable[0]; - } - } else { - driver = &s_driverTable[0]; - } - - driver->FillAPI( &snddma ); + s_driverTable[i].FillAPI( &snddma ); ret = snddma.Init(); if( ret == SIS_SUCCESS ) { break; } if( ret == SIS_NOTAVAIL ) { - Com_Printf( "Sound hardware already in use, sound disabled.\n" ); + Com_WPrintf( "Sound hardware already in use\n" ); return; } - if( !s_driver->string[0] ) { - Com_WPrintf( "Couldn't fall back to default sound driver!\n" ); - return; - } - - Com_Printf( "Failed to load sound driver, falling back to default...\n" ); - Cvar_Set( "s_driver", "" ); + i = ( i + 1 ) % s_numDrivers; + if( i == j ) { + Com_WPrintf( "No usable sound driver found\n" ); + return; + } } Cmd_Register( c_sound ); @@ -268,7 +263,6 @@ void S_Init( void ) { sound_started = qtrue; num_sfx = 0; - soundtime = 0; paintedtime = 0; s_registration_sequence = 1; @@ -854,8 +848,6 @@ void S_ClearBuffer (void) if (!sound_started) return; - s_rawend = 0; - if (dma.samplebits == 8) clear = 0x80; else @@ -993,142 +985,34 @@ void S_AddLoopSounds (void) } } -//============================================================================= - -/* -============ -S_RawSamples - -Cinematic streaming and voice over network -============ -*/ -void S_RawSamples (int samples, int rate, int width, int channels, byte *data) -{ - int i; - int src, dst; - float scale; - - if (!sound_started) - return; - - if (s_rawend < paintedtime) - s_rawend = paintedtime; - scale = (float)rate / dma.speed; - -//Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend); - if (channels == 2 && width == 2) - { - if (scale == 1.0) - { // optimized case - for (i=0 ; i<samples ; i++) - { - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = - LittleShort(((short *)data)[i*2]) << 8; - s_rawsamples[dst].right = - LittleShort(((short *)data)[i*2+1]) << 8; - } - } - else - { - for (i=0 ; ; i++) - { - src = i*scale; - if (src >= samples) - break; - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = - LittleShort(((short *)data)[src*2]) << 8; - s_rawsamples[dst].right = - LittleShort(((short *)data)[src*2+1]) << 8; - } - } - } - else if (channels == 1 && width == 2) - { - for (i=0 ; ; i++) - { - src = i*scale; - if (src >= samples) - break; - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = - LittleShort(((short *)data)[src]) << 8; - s_rawsamples[dst].right = - LittleShort(((short *)data)[src]) << 8; - } - } - else if (channels == 2 && width == 1) - { - for (i=0 ; ; i++) - { - src = i*scale; - if (src >= samples) - break; - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = - ((char *)data)[src*2] << 16; - s_rawsamples[dst].right = - ((char *)data)[src*2+1] << 16; - } - } - else if (channels == 1 && width == 1) - { - for (i=0 ; ; i++) - { - src = i*scale; - if (src >= samples) - break; - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = - (((byte *)data)[src]-128) << 16; - s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16; - } - } -} - // ======================================================================= // Update sound buffer // ======================================================================= -static void S_GetTime(void) -{ - int samplepos; +static int S_GetTime(void) { static int buffers; static int oldsamplepos; - int fullsamples; - - fullsamples = dma.samples / dma.channels; + int fullsamples = dma.samples / dma.channels; // it is possible to miscount buffers if it has wrapped twice between // calls to S_Update. Oh well. - samplepos = snddma.GetDMAPos(); - - if (samplepos < oldsamplepos) - { + if (dma.samplepos < oldsamplepos) { buffers++; // buffer wrapped - - if (paintedtime > 0x40000000) - { // time to chop things off to avoid 32 bit limits + if (paintedtime > 0x40000000) { + // time to chop things off to avoid 32 bit limits buffers = 0; paintedtime = fullsamples; - S_StopAllSounds (); + S_StopAllSounds(); } } - oldsamplepos = samplepos; + oldsamplepos = dma.samplepos; - soundtime = buffers*fullsamples + samplepos/dma.channels; + return buffers*fullsamples + dma.samplepos/dma.channels; } -static void S_Update_(void) -{ - unsigned endtime; - int samps; +static void S_Update_(void) { + int soundtime, endtime; + int samps; snddma.BeginPainting (); @@ -1136,11 +1020,10 @@ static void S_Update_(void) return; // Updates DMA time - S_GetTime(); + soundtime = S_GetTime(); // check to make sure that we haven't overshot - if (paintedtime < soundtime) - { + if (paintedtime < soundtime) { Com_DPrintf ("S_Update_ : overflow\n"); paintedtime = soundtime; } @@ -1150,8 +1033,8 @@ static void S_Update_(void) //endtime = (soundtime + 4096) & ~4095; // mix to an even submission block size - endtime = (endtime + dma.submission_chunk-1) - & ~(dma.submission_chunk-1); + endtime = (endtime + dma.submission_chunk - 1) + & ~(dma.submission_chunk - 1); samps = dma.samples >> (dma.channels-1); if (endtime - soundtime > samps) endtime = soundtime + samps; diff --git a/source/snd_mix.c b/source/snd_mix.c index aedbcc4..29e3def 100644 --- a/source/snd_mix.c +++ b/source/snd_mix.c @@ -29,13 +29,11 @@ int *snd_p, snd_linear_count, snd_vol; short *snd_out; #ifndef USE_ASM -void S_WriteLinearBlastStereo16 (void) -{ +static void S_WriteLinearBlastStereo16 (void) { int i; int val; - for (i=0 ; i<snd_linear_count ; i+=2) - { + for (i=0 ; i<snd_linear_count ; i+=2) { val = snd_p[i]>>8; if (val > 0x7fff) snd_out[i] = 0x7fff; @@ -57,16 +55,14 @@ void S_WriteLinearBlastStereo16 (void) void S_WriteLinearBlastStereo16 (void); #endif -void S_TransferStereo16 (unsigned long *pbuf, int endtime) -{ +static void S_TransferStereo16 (unsigned long *pbuf, int endtime) { int lpos; int lpaintedtime; snd_p = (int *) paintbuffer; lpaintedtime = paintedtime; - while (lpaintedtime < endtime) - { + while (lpaintedtime < endtime) { // handle recirculating buffer issues lpos = lpaintedtime & ((dma.samples>>1)-1); @@ -86,26 +82,57 @@ void S_TransferStereo16 (unsigned long *pbuf, int endtime) } } -/* -=================== -S_TransferPaintBuffer - -=================== -*/ -void S_TransferPaintBuffer(int endtime) -{ +static void S_TransferStereo( unsigned long *pbuf, int endtime ) { int out_idx; int count; int out_mask; int *p; int step; int val; - unsigned long *pbuf; - pbuf = (unsigned long *)dma.buffer; + p = (int *) paintbuffer; + count = (endtime - paintedtime) * dma.channels; + out_mask = dma.samples - 1; + out_idx = paintedtime * dma.channels & out_mask; + step = 3 - dma.channels; + + if (dma.samplebits == 16) { + short *out = (short *) pbuf; + while (count--) { + val = *p >> 8; + p+= step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < (short)0x8000) + val = (short)0x8000; + out[out_idx] = val; + out_idx = (out_idx + 1) & out_mask; + } + } else if (dma.samplebits == 8) { + unsigned char *out = (unsigned char *) pbuf; + while (count--) { + val = *p >> 8; + p+= step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < (short)0x8000) + val = (short)0x8000; + out[out_idx] = (val>>8) + 128; + out_idx = (out_idx + 1) & out_mask; + } + } +} + +/* +=================== +S_TransferPaintBuffer + +=================== +*/ +static void S_TransferPaintBuffer(int endtime) { + unsigned long *pbuf = (unsigned long *)dma.buffer; - if (s_testsound->integer) - { + if (s_testsound->integer) { int i; int count; @@ -115,49 +142,12 @@ void S_TransferPaintBuffer(int endtime) paintbuffer[i].left = paintbuffer[i].right = sin((paintedtime+i)*0.1)*20000*256; } - - if (dma.samplebits == 16 && dma.channels == 2) - { // optimized case + if (dma.samplebits == 16 && dma.channels == 2) { + // optimized case S_TransferStereo16 (pbuf, endtime); - } - else - { // general case - p = (int *) paintbuffer; - count = (endtime - paintedtime) * dma.channels; - out_mask = dma.samples - 1; - out_idx = paintedtime * dma.channels & out_mask; - step = 3 - dma.channels; - - if (dma.samplebits == 16) - { - short *out = (short *) pbuf; - while (count--) - { - val = *p >> 8; - p+= step; - if (val > 0x7fff) - val = 0x7fff; - else if (val < (short)0x8000) - val = (short)0x8000; - out[out_idx] = val; - out_idx = (out_idx + 1) & out_mask; - } - } - else if (dma.samplebits == 8) - { - unsigned char *out = (unsigned char *) pbuf; - while (count--) - { - val = *p >> 8; - p+= step; - if (val > 0x7fff) - val = 0x7fff; - else if (val < (short)0x8000) - val = (short)0x8000; - out[out_idx] = (val>>8) + 128; - out_idx = (out_idx + 1) & out_mask; - } - } + } else { + // general case + S_TransferStereo( pbuf, endtime ); } } @@ -170,11 +160,78 @@ CHANNEL MIXING =============================================================================== */ -void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime, int offset); -void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime, int offset); +static void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count, int offset) { + int data; + int *lscale, *rscale; + byte *sfx; + int i; + portable_samplepair_t *samp; + + if (ch->leftvol > 255) + ch->leftvol = 255; + if (ch->rightvol > 255) + ch->rightvol = 255; + + //ZOID-- >>11 has been changed to >>3, >>11 didn't make much sense + //as it would always be zero. + lscale = snd_scaletable[ ch->leftvol >> 3]; + rscale = snd_scaletable[ ch->rightvol >> 3]; + samp = &paintbuffer[offset]; + + sfx = sc->data + ch->pos * sc->channels; + + if( sc->channels == 2 ) { + for( i=0 ; i<count ; i++, samp++ ) { + samp->left += lscale[*sfx++]; + samp->right += rscale[*sfx++]; + } + } else { + for( i=0 ; i<count ; i++, samp++ ) { + data = *sfx++; + samp->left += lscale[data]; + samp->right += rscale[data]; + } + } + + ch->pos += count; +} + +static void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count, int offset) { + int data; + int left, right; + int leftvol, rightvol; + signed short *sfx; + int i; + portable_samplepair_t *samp; + + leftvol = ch->leftvol*snd_vol; + rightvol = ch->rightvol*snd_vol; + samp = &paintbuffer[offset]; + + sfx = (signed short *)sc->data + ch->pos * sc->channels; + + if( sc->channels == 2 ) { + for( i=0 ; i<count ; i++, samp++ ) { + left = ( *sfx++ * leftvol ) >> 8; + right = ( *sfx++ * rightvol ) >> 8; + samp->left += left; + samp->right += right; + } + } else { + for( i=0 ; i<count ; i++, samp++ ) { + data = *sfx++; + left = ( data * leftvol ) >> 8; + right = ( data * rightvol ) >> 8; + samp->left += left; + samp->right += right; + } + } + + ch->pos += count; +} + -void S_PaintChannels(int endtime) -{ +void S_PaintChannels(int endtime) { int i; int end; channel_t *ch; @@ -184,22 +241,18 @@ void S_PaintChannels(int endtime) snd_vol = s_volume->value*256; -//Com_Printf ("%i to %i\n", paintedtime, endtime); - while (paintedtime < endtime) - { - // if paintbuffer is smaller than DMA buffer + while (paintedtime < endtime) { + // if paintbuffer is smaller than DMA buffer end = endtime; - if (endtime - paintedtime > PAINTBUFFER_SIZE) + if (end - paintedtime > PAINTBUFFER_SIZE) end = paintedtime + PAINTBUFFER_SIZE; // start any playsounds - while (1) - { + while (1) { ps = s_pendingplays.next; if (ps == &s_pendingplays) break; // no more pending sounds - if (ps->begin <= paintedtime) - { + if (ps->begin <= paintedtime) { S_IssuePlaysound (ps); continue; } @@ -209,44 +262,15 @@ void S_PaintChannels(int endtime) break; } - // clear the paint buffer - if (s_rawend < paintedtime) - { -// Com_Printf ("clear\n"); - memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); - } - else - { // copy from the streaming sound source - int s; - int stop; - - stop = (end < s_rawend) ? end : s_rawend; - - for (i=paintedtime ; i<stop ; i++) - { - s = i&(MAX_RAW_SAMPLES-1); - paintbuffer[i-paintedtime] = s_rawsamples[s]; - } -// if (i != end) -// Com_Printf ("partial stream\n"); -// else -// Com_Printf ("full stream\n"); - for ( ; i<end ; i++) - { - paintbuffer[i-paintedtime].left = 0; - paintbuffer[i-paintedtime].right = 0; - } - } - + // clear the paint buffer + memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); - // paint in the channels. + // paint in the channels. ch = channels; - for (i=0; i<MAX_CHANNELS ; i++, ch++) - { + for (i=0; i<MAX_CHANNELS ; i++, ch++) { ltime = paintedtime; - while (ltime < end) - { + while (ltime < end) { if (!ch->sfx || (!ch->leftvol && !ch->rightvol) ) break; @@ -261,8 +285,7 @@ void S_PaintChannels(int endtime) if (!sc) break; - if (count > 0 && ch->sfx) - { + if (count > 0 && ch->sfx) { if (sc->width == 1)// FIXME; 8 bit asm is wrong now S_PaintChannelFrom8(ch, sc, count, ltime - paintedtime); else @@ -271,21 +294,17 @@ void S_PaintChannels(int endtime) ltime += count; } - // if at end of loop, restart - if (ltime >= ch->end) - { - if (ch->autosound) - { // autolooping sounds always go back to start + // if at end of loop, restart + if (ltime >= ch->end) { + if (ch->autosound) { + // autolooping sounds always go back to start ch->pos = 0; ch->end = ltime + sc->length; - } - else if (sc->loopstart >= 0) - { + } else if (sc->loopstart >= 0) { ch->pos = sc->loopstart; ch->end = ltime + sc->length - ch->pos; - } - else - { // channel just stopped + } else { + // channel just stopped ch->sfx = NULL; } } @@ -293,102 +312,23 @@ void S_PaintChannels(int endtime) } - // transfer out according to DMA format + // transfer out according to DMA format S_TransferPaintBuffer(end); paintedtime = end; } } -void S_InitScaletable (void) -{ +void S_InitScaletable (void) { int i, j; int scale; Cvar_ClampValue( s_volume, 0, 2 ); s_volume->modified = qfalse; - for (i=0 ; i<32 ; i++) - { + for (i=0 ; i<32 ; i++) { scale = i * 8 * 256 * s_volume->value; for (j=0 ; j<256 ; j++) snd_scaletable[i][j] = ((signed char)j) * scale; } } - - - -void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count, int offset) -{ - int data; - int *lscale, *rscale; - byte *sfx; - int i; - portable_samplepair_t *samp; - - if (ch->leftvol > 255) - ch->leftvol = 255; - if (ch->rightvol > 255) - ch->rightvol = 255; - - //ZOID-- >>11 has been changed to >>3, >>11 didn't make much sense - //as it would always be zero. - lscale = snd_scaletable[ ch->leftvol >> 3]; - rscale = snd_scaletable[ ch->rightvol >> 3]; - samp = &paintbuffer[offset]; - - sfx = sc->data + ch->pos * sc->channels; - - if( sc->channels == 2 ) { - for( i=0 ; i<count ; i++, samp++ ) { - samp->left += lscale[*sfx++]; - samp->right += rscale[*sfx++]; - } - } else { - for( i=0 ; i<count ; i++, samp++ ) { - data = *sfx++; - samp->left += lscale[data]; - samp->right += rscale[data]; - } - } - - ch->pos += count; -} - - - -void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count, int offset) -{ - int data; - int left, right; - int leftvol, rightvol; - signed short *sfx; - int i; - portable_samplepair_t *samp; - - leftvol = ch->leftvol*snd_vol; - rightvol = ch->rightvol*snd_vol; - samp = &paintbuffer[offset]; - - sfx = (signed short *)sc->data + ch->pos * sc->channels; - - if( sc->channels == 2 ) { - for( i=0 ; i<count ; i++, samp++ ) { - left = ( *sfx++ * leftvol ) >> 8; - right = ( *sfx++ * rightvol ) >> 8; - samp->left += left; - samp->right += right; - } - } else { - for( i=0 ; i<count ; i++, samp++ ) { - data = *sfx++; - left = ( data * leftvol ) >> 8; - right = ( data * rightvol ) >> 8; - samp->left += left; - samp->right += right; - } - } - - ch->pos += count; -} - diff --git a/source/snd_oss.c b/source/snd_oss.c index f47dd86..e1dd69c 100644 --- a/source/snd_oss.c +++ b/source/snd_oss.c @@ -33,7 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <stdio.h> #include <errno.h> -#include "cl_local.h" +#include "com_local.h" #include "snd_local.h" static int audio_fd; @@ -47,7 +47,7 @@ static cvar_t *snddevice; static int tryrates[] = { 22050, 11025, 44100, 48000, 8000 }; -static sndinitstat OSS_Init ( void ) { +static sndinitstat_t OSS_Init ( void ) { int rc; int fmt; int tmp; @@ -74,16 +74,6 @@ static sndinitstat OSS_Init ( void ) { return SIS_FAILURE; } -#if 0 - rc = ioctl ( audio_fd, SNDCTL_DSP_RESET, 0 ); - if ( rc < 0 ) { - perror ( snddevice->string ); - Com_Printf ( "Could not reset %s\n", snddevice->string ); - close ( audio_fd ); - return SIS_FAILURE; - } -#endif - if ( ioctl ( audio_fd, SNDCTL_DSP_GETCAPS, &caps ) == -1 ) { Com_WPrintf ( "Could not get caps of %s: %s\n", snddevice->string, strerror ( errno ) ); @@ -216,43 +206,39 @@ fail: return SIS_FAILURE; } -static int OSS_GetDMAPos ( void ) { +static void OSS_Shutdown ( void ) { + if ( snd_inited ) { + Com_Printf ( "Shutting down OSS\n" ); + ioctl ( audio_fd, SNDCTL_DSP_RESET ); + munmap ( dma.buffer, info.fragstotal * info.fragsize ); + close ( audio_fd ); + snd_inited = qfalse; + } +} + +static void OSS_BeginPainting ( void ) { struct count_info count; if ( !snd_inited ) - return 0; + return; - if ( ioctl ( audio_fd, SNDCTL_DSP_GETOPTR, &count ) ==-1 ) { + if ( ioctl ( audio_fd, SNDCTL_DSP_GETOPTR, &count ) == -1 ) { Com_EPrintf ( "SNDCTL_DSP_GETOPTR failed on %s: %s\n", snddevice->string, strerror ( errno ) ); - munmap ( dma.buffer, info.fragstotal * info.fragsize ); - close ( audio_fd ); - snd_inited = qfalse; - return 0; + OSS_Shutdown(); + return; } dma.samplepos = count.ptr / ( dma.samplebits >> 3 ); - - return dma.samplepos; } -static void OSS_Shutdown ( void ) { - if ( snd_inited ) { - Com_Printf ( "Shutting down OSS\n" ); - munmap ( dma.buffer, info.fragstotal * info.fragsize ); - close ( audio_fd ); - snd_inited = qfalse; - } +static void OSS_Submit ( void ) { } -static void OSS_Submit ( void ) {} - -static void OSS_BeginPainting ( void ) {} - -static void OSS_Activate ( qboolean active ) {} +static void OSS_Activate ( qboolean active ) { +} void OSS_FillAPI ( snddmaAPI_t *api ) { api->Init = OSS_Init; - api->GetDMAPos = OSS_GetDMAPos; api->Shutdown = OSS_Shutdown; api->BeginPainting = OSS_BeginPainting; api->Submit = OSS_Submit; diff --git a/source/snd_sdl.c b/source/snd_sdl.c new file mode 100644 index 0000000..f727718 --- /dev/null +++ b/source/snd_sdl.c @@ -0,0 +1,147 @@ +/* +Copyright (C) 2003-2007 Andrey Nazarov + +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 2 +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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// +// snd_sdl.c +// + +#include "com_local.h" +#include "snd_local.h" +#include <SDL.h> + +static void filler( void *userdata, Uint8 *stream, int len ) { + int size = dma.samples << 1; + int pos = dma.samplepos << 1; + int wrapped = pos + len - size; + + if( wrapped < 0 ) { + memcpy( stream, dma.buffer + pos, len ); + dma.samplepos += len >> 1; + } else { + int remaining = size - pos; + memcpy( stream, dma.buffer + pos, remaining ); + memcpy( stream + remaining, dma.buffer, wrapped ); + dma.samplepos = wrapped >> 1; + } +} + +static void QSDL_ShutdownSound( void ) { + Com_Printf( "Shutting down SDL audio\n" ); + + SDL_CloseAudio(); + if( SDL_WasInit( SDL_INIT_EVERYTHING ) == SDL_INIT_AUDIO ) { + SDL_Quit(); + } else { + SDL_QuitSubSystem( SDL_INIT_AUDIO ); + } + + if( dma.buffer ) { + Z_Free( dma.buffer ); + dma.buffer = NULL; + } +} + +static sndinitstat_t QSDL_InitSound( void ) { + SDL_AudioSpec desired, obtained; + char buffer[MAX_QPATH]; + int ret; + + if( SDL_WasInit( SDL_INIT_EVERYTHING ) == 0 ) { + ret = SDL_Init( SDL_INIT_AUDIO|SDL_INIT_NOPARACHUTE ); + } else { + ret = SDL_InitSubSystem( SDL_INIT_AUDIO ); + } + if( ret == -1 ) { + Com_EPrintf( "Couldn't initialize SDL audio: %s\n", SDL_GetError() ); + return SIS_FAILURE; + } + + memset( &desired, 0, sizeof( desired ) ); + switch( s_khz->integer ) { + case 48: + desired.freq = 48000; + break; + case 44: + desired.freq = 44100; + break; + case 22: + desired.freq = 22050; + break; + default: + desired.freq = 11025; + break; + } + + desired.format = AUDIO_S16LSB; + desired.samples = 512; + desired.channels = 2; + desired.callback = filler; + ret = SDL_OpenAudio( &desired, &obtained ); + if( ret == -1 ) { + Com_EPrintf( "Couldn't open SDL audio: %s\n", SDL_GetError() ); + return SIS_FAILURE; + } + + if( obtained.format != AUDIO_S16LSB ) { + Com_EPrintf( "SDL audio format %d unsupported\n", obtained.format ); + QSDL_ShutdownSound(); + return SIS_FAILURE; + } + + dma.speed = obtained.freq; + dma.channels = obtained.channels; + dma.samples = 2048 * obtained.channels; + dma.submission_chunk = 1; + dma.samplebits = 16; + dma.buffer = Z_Malloc( dma.samples * 2 ); + dma.samplepos = 0; + + Com_Printf( "Using SDL audio driver: %s\n", + SDL_AudioDriverName( buffer, sizeof( buffer ) ) ); + + SDL_PauseAudio( 0 ); + + return SIS_SUCCESS; +} + +static void QSDL_BeginPainting( void ) { + SDL_LockAudio(); +} + +static void QSDL_Submit( void ) { + SDL_UnlockAudio(); +} + +static void QSDL_ActivateSound( qboolean active ) { + if( active ) { + SDL_PauseAudio( 0 ); + } else { + SDL_PauseAudio( 1 ); + } +} + +void QSDL_FillSoundAPI ( snddmaAPI_t *api ) { + api->Init = QSDL_InitSound; + api->Shutdown = QSDL_ShutdownSound; + api->BeginPainting = QSDL_BeginPainting; + api->Submit = QSDL_Submit; + api->Activate = QSDL_ActivateSound; +} + diff --git a/source/snd_wave.c b/source/snd_wave.c index eadd895..f036b83 100644 --- a/source/snd_wave.c +++ b/source/snd_wave.c @@ -98,7 +98,7 @@ WAVE_Init Crappy windows multimedia base ================== */ -static sndinitstat WAVE_Init (void) { +static sndinitstat_t WAVE_Init (void) { WAVEFORMATEX format; int i; HRESULT hr; @@ -237,39 +237,26 @@ static sndinitstat WAVE_Init (void) { return SIS_SUCCESS; } - /* ============== -WAVE_GetDMAPos +WAVE_BeginPainting -return the current sample position (in mono samples read) +Makes sure dma.buffer is valid. + +Returns the current sample position (in mono samples read) inside the recirculating dma buffer, so the mixing code will know how many sample are required to fill it up. =============== */ -static int WAVE_GetDMAPos(void) { +static void WAVE_BeginPainting (void) { int s; if( !wav_init ) { - return 0; + return; } - s = snd_sent * WAV_BUFFER_SIZE; - - s >>= sample16; - s &= (dma.samples-1); - - return s; -} - -/* -============== -WAVE_BeginPainting - -Makes sure dma.buffer is valid -=============== -*/ -static void WAVE_BeginPainting (void) { + s = ( snd_sent * WAV_BUFFER_SIZE ) >> sample16; + dma.samplepos = s & ( dma.samples - 1 ); } /* @@ -344,7 +331,6 @@ static void WAVE_Activate (qboolean active) { void WAVE_FillAPI( snddmaAPI_t *api ) { api->Init = WAVE_Init; - api->GetDMAPos = WAVE_GetDMAPos; api->Shutdown = WAVE_Shutdown; api->BeginPainting = WAVE_BeginPainting; api->Submit = WAVE_Submit; diff --git a/source/sv_game.c b/source/sv_game.c index e7a6896..f25fb7c 100644 --- a/source/sv_game.c +++ b/source/sv_game.c @@ -714,7 +714,7 @@ static cvar_t *PF_cvar( const char *name, const char *value, int flags ) { flags &= ~CVAR_EXTENDED_MASK; } - var = Cvar_Get( name, value, flags ); + var = Cvar_Get( name, value, flags | CVAR_GAME ); if( !var->subsystem ) { var->subsystem = CVAR_SYSTEM_GAME; } |
