diff --git a/src/client/cl_main.c b/src/client/cl_main.c
index 2e68f14f..e1082d7d 100644
--- a/src/client/cl_main.c
+++ b/src/client/cl_main.c
@@ -595,6 +595,7 @@ void CL_PlayDemo_f( void ) {
Con_Close();
cls.state = CA_CONNECTED;
+ clientIsConnected = qtrue;
clc.demoplaying = qtrue;
if ( Cvar_VariableValue( "cl_wavefilerecord" ) ) {
@@ -734,6 +735,7 @@ void CL_MapLoading( void ) {
// if we are already connected to the local host, stay connected
if ( cls.state >= CA_CONNECTED && !Q_stricmp( cls.servername, "localhost" ) ) {
cls.state = CA_CONNECTED; // so the connect screen is drawn
+ clientIsConnected = qtrue;
memset( cls.updateInfoString, 0, sizeof( cls.updateInfoString ) );
memset( clc.serverMessage, 0, sizeof( clc.serverMessage ) );
memset( &cl.gameState, 0, sizeof( cl.gameState ) );
@@ -821,6 +823,7 @@ void CL_Disconnect( qboolean showMainMenu ) {
CL_WritePacket();
CL_WritePacket();
CL_WritePacket();
+ clientIsConnected = qfalse;
}
CL_ClearState();
@@ -828,15 +831,31 @@ void CL_Disconnect( qboolean showMainMenu ) {
// wipe the client connection
memset( &clc, 0, sizeof( clc ) );
- cls.state = CA_DISCONNECTED;
+// L0 - Fix shutdowns ..
+ if (uivm && cls.state > CA_DISCONNECTED) {
+ cls.state = CA_DISCONNECTED;
+ clientIsConnected = qfalse;
+
+ // shutdown the UI
+ CL_ShutdownUI();
+
+ // init the UI
+ CL_InitUI();
+ }
+ else {
+ cls.state = CA_DISCONNECTED;
+ clientIsConnected = qfalse;
+ }
// allow cheats locally
Cvar_Set( "sv_cheats", "1" );
// not connected to a pure server anymore
cl_connectedToPureServer = qfalse;
-}
+ // L0 - Set this to off as well
+ clientIsConnected = qfalse;
+}
/*
===================
@@ -1588,6 +1607,7 @@ void CL_InitDownloads( void ) {
Q_strncpyz( autoupdateFilename, cl_updatefiles->string, sizeof( autoupdateFilename ) );
Q_strncpyz( clc.downloadList, va( "@%s/%s@%s/%s", dir, cl_updatefiles->string, dir, cl_updatefiles->string ), MAX_INFO_STRING );
cls.state = CA_CONNECTED;
+ clientIsConnected = qtrue;
CL_NextDownload();
return;
}
@@ -1607,6 +1627,7 @@ void CL_InitDownloads( void ) {
if ( *clc.downloadList ) {
// if autodownloading is not enabled on the server
cls.state = CA_CONNECTED;
+ clientIsConnected = qtrue;
CL_NextDownload();
return;
}
@@ -2006,6 +2027,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
Netchan_Setup( NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) );
cls.state = CA_CONNECTED;
clc.lastPacketSentTime = -9999; // send first packet immediately
+ clientIsConnected = qfalse;
return;
}
@@ -2199,6 +2221,7 @@ void CL_Frame( int msec ) {
// if disconnected, bring up the menu
S_StopAllSounds();
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
+ clientIsConnected = qfalse;
}
// if recording an avi, lock to a fixed fps
@@ -2604,6 +2627,7 @@ void CL_GetAutoUpdate( void ) {
if ( cls.autoupdateServer.type == NA_BAD ) {
Com_Printf( "Bad server address\n" );
cls.state = CA_DISCONNECTED;
+ clientIsConnected = qfalse;
return;
}
diff --git a/src/client/cl_scrn.c b/src/client/cl_scrn.c
index 655f34d7..2b695a81 100644
--- a/src/client/cl_scrn.c
+++ b/src/client/cl_scrn.c
@@ -474,6 +474,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
case CA_CONNECTING:
case CA_CHALLENGING:
case CA_CONNECTED:
+ clientIsConnected = qtrue; // L0 - Set this on..
// connecting clients will only show the connection dialog
// refresh to update the time
VM_Call( uivm, UI_REFRESH, cls.realtime );
diff --git a/src/game/game.vcxproj b/src/game/game.vcxproj
index 8d11e66e..d05fc668 100644
--- a/src/game/game.vcxproj
+++ b/src/game/game.vcxproj
@@ -311,7 +311,6 @@ copy $(SolutionDir)Builds\$(Configuration)\$(ProjectName)\$(TargetName)$(TargetE
-
diff --git a/src/game/game.vcxproj.filters b/src/game/game.vcxproj.filters
index b7e799f4..e64909b1 100644
--- a/src/game/game.vcxproj.filters
+++ b/src/game/game.vcxproj.filters
@@ -187,9 +187,6 @@
Source Files
-
- Source Files
-
Source Files
diff --git a/src/game/q_shared.h b/src/game/q_shared.h
index d66df38c..d320cc37 100644
--- a/src/game/q_shared.h
+++ b/src/game/q_shared.h
@@ -962,19 +962,18 @@ COLLISION DETECTION
// plane types are used to speed some tests
// 0-2 are axial planes
-#define PLANE_X 0
-#define PLANE_Y 1
-#define PLANE_Z 2
-#define PLANE_NON_AXIAL 3
-
+#define PLANE_X 0
+#define PLANE_Y 1
+#define PLANE_Z 2
+#define PLANE_NON_AXIAL 3
+#define PLANE_NON_PLANAR 4
/*
=================
PlaneTypeForNormal
=================
*/
-
-#define PlaneTypeForNormal( x ) ( x[0] == 1.0 ? PLANE_X : ( x[1] == 1.0 ? PLANE_Y : ( x[2] == 1.0 ? PLANE_Z : PLANE_NON_AXIAL ) ) )
+#define PlaneTypeForNormal( x ) ( x[0] == 1.0 ? PLANE_X : ( x[1] == 1.0 ? PLANE_Y : ( x[2] == 1.0 ? PLANE_Z : ( x[0] == 0.f && x[1] == 0.f && x[2] == 0.f ? PLANE_NON_PLANAR : PLANE_NON_AXIAL ) ) ) )
// plane_t structure
// !!! if this is changed, it must be changed in asm code too !!!
@@ -1539,6 +1538,11 @@ typedef enum {
CA_CINEMATIC // playing a cinematic or a static pic, not connected to a server
} connstate_t;
+// L0
+// Indicates if client is connected or not.
+// Deals with Bloom issues as well as just identifying if extra stuff should be ran..
+qboolean clientIsConnected;
+
// font support
#define GLYPH_START 0
diff --git a/src/qcommon/qfiles.h b/src/qcommon/qfiles.h
index 11297a4a..3e24fa67 100644
--- a/src/qcommon/qfiles.h
+++ b/src/qcommon/qfiles.h
@@ -692,12 +692,15 @@ typedef struct {
byte color[4];
} drawVert_t;
+#define drawVert_t_cleared(x) drawVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
+
typedef enum {
MST_BAD,
MST_PLANAR,
MST_PATCH,
MST_TRIANGLE_SOUP,
- MST_FLARE
+ MST_FLARE,
+ MST_FOLIAGE // L0 - TODO: add support for foliage surfaces
} mapSurfaceType_t;
typedef struct {
diff --git a/src/renderer/renderer.vcxproj b/src/renderer/renderer.vcxproj
index 5e891b27..82206e8a 100644
--- a/src/renderer/renderer.vcxproj
+++ b/src/renderer/renderer.vcxproj
@@ -351,6 +351,7 @@
true
MaxSpeed
+
Disabled
EnableFastChecks
diff --git a/src/renderer/renderer.vcxproj.filters b/src/renderer/renderer.vcxproj.filters
index a167dd17..928cd301 100644
--- a/src/renderer/renderer.vcxproj.filters
+++ b/src/renderer/renderer.vcxproj.filters
@@ -190,6 +190,9 @@
Source Files
+
+ Source Files
+
diff --git a/src/renderer/tr_backend.c b/src/renderer/tr_backend.c
index 37b06efd..98c241f7 100644
--- a/src/renderer/tr_backend.c
+++ b/src/renderer/tr_backend.c
@@ -483,6 +483,10 @@ void RB_BeginDrawingView( void ) {
qglClearColor( glfogsettings[FOG_CURRENT].color[0], glfogsettings[FOG_CURRENT].color[1], glfogsettings[FOG_CURRENT].color[2], glfogsettings[FOG_CURRENT].color[3] );
}
+ else if (!(r_portalsky->integer)) { // ydnar: portal skies have been manually turned off, clear bg color
+ clearBits |= GL_COLOR_BUFFER_BIT;
+ qglClearColor(0.5, 0.5, 0.5, 1.0);
+ }
}
} else { // world scene with no portal sky
clearBits |= GL_DEPTH_BUFFER_BIT;
@@ -513,6 +517,10 @@ void RB_BeginDrawingView( void ) {
}
}
+ // ydnar: don't clear the color buffer when no world model is specified
+ if (backEnd.refdef.rdflags & RDF_NOWORLDMODEL) {
+ clearBits &= ~GL_COLOR_BUFFER_BIT;
+ }
if ( clearBits ) {
qglClear( clearBits );
@@ -1140,6 +1148,7 @@ const void *RB_DrawSurfs( const void *data ) {
backEnd.refdef = cmd->refdef;
backEnd.viewParms = cmd->viewParms;
+ backEnd.doneSurfaces = qtrue;
RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs );
@@ -1281,6 +1290,8 @@ const void *RB_SwapBuffers( const void *data ) {
GLimp_EndFrame();
backEnd.projection2D = qfalse;
+ backEnd.doneBloom = qfalse;
+ backEnd.doneSurfaces = qfalse;
return (const void *)( cmd + 1 );
}
@@ -1310,6 +1321,7 @@ void RB_ExecuteRenderCommands( const void *data ) {
data = RB_SetColor( data );
break;
case RC_STRETCH_PIC:
+ R_BloomScreen();
data = RB_StretchPic( data );
break;
case RC_ROTATED_PIC:
@@ -1325,6 +1337,7 @@ void RB_ExecuteRenderCommands( const void *data ) {
data = RB_DrawBuffer( data );
break;
case RC_SWAP_BUFFERS:
+ R_BloomScreen();
data = RB_SwapBuffers( data );
break;
diff --git a/src/renderer/tr_bloom.c b/src/renderer/tr_bloom.c
new file mode 100644
index 00000000..c6890a8a
--- /dev/null
+++ b/src/renderer/tr_bloom.c
@@ -0,0 +1,371 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+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.
+
+*/
+// tr_bloom.c: 2D lighting post process effect
+
+#include "tr_local.h"
+
+static cvar_t *r_bloom;
+static cvar_t *r_bloom_sample_size;
+static cvar_t *r_bloom_fast_sample;
+static cvar_t *r_bloom_alpha;
+static cvar_t *r_bloom_darken;
+static cvar_t *r_bloom_intensity;
+static cvar_t *r_bloom_diamond_size;
+
+/*
+==============================================================================
+
+LIGHT BLOOMS
+
+==============================================================================
+*/
+
+static float Diamond8x[8][8] =
+{
+ { 0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f, },
+ { 0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f, },
+ { 0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f, },
+ { 0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f, },
+ { 0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f, },
+ { 0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f, },
+ { 0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f, },
+ { 0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f }
+};
+
+static float Diamond6x[6][6] =
+{
+ { 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, },
+ { 0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f, },
+ { 0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f, },
+ { 0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f, },
+ { 0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f, },
+ { 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f }
+};
+
+static float Diamond4x[4][4] =
+{
+ { 0.3f, 0.4f, 0.4f, 0.3f, },
+ { 0.4f, 0.9f, 0.9f, 0.4f, },
+ { 0.4f, 0.9f, 0.9f, 0.4f, },
+ { 0.3f, 0.4f, 0.4f, 0.3f }
+};
+
+static struct {
+ struct {
+ image_t *texture;
+ int width, height;
+ float readW, readH;
+ } effect;
+ struct {
+ image_t *texture;
+ int width, height;
+ float readW, readH;
+ } screen;
+ struct {
+ int width, height;
+ } work;
+ qboolean started;
+} bloom;
+
+static void ID_INLINE R_Bloom_Quad(int width, int height, float texX, float texY, float texWidth, float texHeight) {
+ int x = 0;
+ int y = 0;
+ x = 0;
+ y += glConfig.vidHeight - height;
+ width += x;
+ height += y;
+
+ texWidth += texX;
+ texHeight += texY;
+
+ qglBegin(GL_QUADS);
+ qglTexCoord2f(texX, texHeight);
+ qglVertex2f(x, y);
+
+ qglTexCoord2f(texX, texY);
+ qglVertex2f(x, height);
+
+ qglTexCoord2f(texWidth, texY);
+ qglVertex2f(width, height);
+
+ qglTexCoord2f(texWidth, texHeight);
+ qglVertex2f(width, y);
+ qglEnd();
+}
+
+
+/*
+=================
+R_Bloom_InitTextures
+=================
+*/
+static void R_Bloom_InitTextures(void)
+{
+ byte *data;
+
+ // find closer power of 2 to screen size
+ for (bloom.screen.width = 1; bloom.screen.width< glConfig.vidWidth; bloom.screen.width *= 2);
+ for (bloom.screen.height = 1; bloom.screen.height < glConfig.vidHeight; bloom.screen.height *= 2);
+
+ bloom.screen.readW = glConfig.vidWidth / (float)bloom.screen.width;
+ bloom.screen.readH = glConfig.vidHeight / (float)bloom.screen.height;
+
+ // find closer power of 2 to effect size
+ bloom.work.width = r_bloom_sample_size->integer;
+ bloom.work.height = bloom.work.width * (glConfig.vidWidth / glConfig.vidHeight);
+
+ for (bloom.effect.width = 1; bloom.effect.width < bloom.work.width; bloom.effect.width *= 2);
+ for (bloom.effect.height = 1; bloom.effect.height < bloom.work.height; bloom.effect.height *= 2);
+
+ bloom.effect.readW = bloom.work.width / (float)bloom.effect.width;
+ bloom.effect.readH = bloom.work.height / (float)bloom.effect.height;
+
+
+ // disable blooms if we can't handle a texture of that size
+ if (bloom.screen.width > glConfig.maxTextureSize ||
+ bloom.screen.height > glConfig.maxTextureSize ||
+ bloom.effect.width > glConfig.maxTextureSize ||
+ bloom.effect.height > glConfig.maxTextureSize ||
+ bloom.work.width > glConfig.vidWidth ||
+ bloom.work.height > glConfig.vidHeight
+ ) {
+ ri.Cvar_Set("r_bloom", "0");
+ Com_Printf(S_COLOR_YELLOW"WARNING: 'R_InitBloomTextures' too high resolution for light bloom, effect disabled\n");
+ return;
+ }
+
+ data = ri.Hunk_AllocateTempMemory(bloom.screen.width * bloom.screen.height * 4);
+ Com_Memset(data, 0, bloom.screen.width * bloom.screen.height * 4);
+ bloom.screen.texture = R_CreateImage("***bloom screen texture***", data, bloom.screen.width, bloom.screen.height, qfalse, qfalse, qfalse);
+ ri.Hunk_FreeTempMemory(data);
+
+ data = ri.Hunk_AllocateTempMemory(bloom.effect.width * bloom.effect.height * 4);
+ Com_Memset(data, 0, bloom.effect.width * bloom.effect.height * 4);
+ bloom.effect.texture = R_CreateImage("***bloom effect texture***", data, bloom.effect.width, bloom.effect.height, qfalse, qfalse, qfalse);
+ ri.Hunk_FreeTempMemory(data);
+ bloom.started = qtrue;
+}
+
+/*
+=================
+R_InitBloomTextures
+=================
+*/
+void R_InitBloomTextures(void)
+{
+ if (!r_bloom->integer)
+ return;
+ if (r_rmse->integer) // this breaks bloom
+ return;
+ memset(&bloom, 0, sizeof(bloom));
+ R_Bloom_InitTextures();
+}
+
+/*
+=================
+R_Bloom_DrawEffect
+=================
+*/
+static void R_Bloom_DrawEffect(void)
+{
+ GL_Bind(bloom.effect.texture);
+ GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
+ qglColor4f(r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f);
+ R_Bloom_Quad(glConfig.vidWidth, glConfig.vidHeight, 0, 0, bloom.effect.readW, bloom.effect.readW);
+}
+
+
+/*
+=================
+R_Bloom_GeneratexDiamonds
+=================
+*/
+static void R_Bloom_WarsowEffect(void) {
+ int i, j, k;
+ float intensity, scale, *diamond;
+
+ qglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ //Take the backup texture and downscale it
+ GL_Bind(bloom.screen.texture);
+ GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO);
+ R_Bloom_Quad(bloom.work.width, bloom.work.height, 0, 0, bloom.screen.readW, bloom.screen.readH);
+ //Copy downscaled framebuffer into a texture
+ GL_Bind(bloom.effect.texture);
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height);
+ // darkening passes with repeated filter
+ if (r_bloom_darken->integer) {
+ int i;
+ GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO);
+
+ for (i = 0; i < r_bloom_darken->integer; i++) {
+ R_Bloom_Quad(bloom.work.width, bloom.work.height,
+ 0, 0,
+ bloom.effect.readW, bloom.effect.readH);
+ }
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height);
+ }
+ /* Copy the result to the effect texture */
+ GL_Bind(bloom.effect.texture);
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height);
+
+ // bluring passes, warsow uses a repeated semi blend on a selectable diamond grid
+ qglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR);
+ if (r_bloom_diamond_size->integer > 7 || r_bloom_diamond_size->integer <= 3) {
+ if (r_bloom_diamond_size->integer != 8)
+ ri.Cvar_Set("r_bloom_diamond_size", "8");
+ }
+ else if (r_bloom_diamond_size->integer > 5) {
+ if (r_bloom_diamond_size->integer != 6)
+ ri.Cvar_Set("r_bloom_diamond_size", "6");
+ }
+ else if (r_bloom_diamond_size->integer > 3) {
+ if (r_bloom_diamond_size->integer != 4)
+ ri.Cvar_Set("r_bloom_diamond_size", "4");
+ }
+
+ switch (r_bloom_diamond_size->integer) {
+ case 4:
+ k = 2;
+ diamond = &Diamond4x[0][0];
+ scale = r_bloom_intensity->value * 0.8f;
+ break;
+ case 6:
+ k = 3;
+ diamond = &Diamond6x[0][0];
+ scale = r_bloom_intensity->value * 0.5f;
+ break;
+ default:
+ // case 8:
+ k = 4;
+ diamond = &Diamond8x[0][0];
+ scale = r_bloom_intensity->value * 0.3f;
+ break;
+ }
+
+ for (i = 0; i < r_bloom_diamond_size->integer; i++) {
+ for (j = 0; j < r_bloom_diamond_size->integer; j++, diamond++) {
+ float x, y;
+ intensity = *diamond * scale;
+ if (intensity < 0.01f)
+ continue;
+ qglColor4f(intensity, intensity, intensity, 1.0);
+ x = (i - k) * (2 / 640.0f) * bloom.effect.readW;
+ y = (j - k) * (2 / 480.0f) * bloom.effect.readH;
+
+ R_Bloom_Quad(bloom.work.width, bloom.work.height, x, y, bloom.effect.readW, bloom.effect.readH);
+ }
+ }
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height);
+}
+
+/*
+=================
+R_Bloom_BackupScreen
+Backup the full original screen to a texture for downscaling and later restoration
+=================
+*/
+static void R_Bloom_BackupScreen(void) {
+ GL_Bind(bloom.screen.texture);
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
+}
+/*
+=================
+R_Bloom_RestoreScreen
+Restore the temporary framebuffer section we used with the backup texture
+=================
+*/
+static void R_Bloom_RestoreScreen(void) {
+ GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO);
+ GL_Bind(bloom.screen.texture);
+ qglColor4f(1, 1, 1, 1);
+ R_Bloom_Quad(bloom.work.width, bloom.work.height, 0, 0,
+ bloom.work.width / (float)bloom.screen.width,
+ bloom.work.height / (float)bloom.screen.height);
+}
+
+/*
+=================
+R_BloomScreen
+=================
+*/
+void R_BloomScreen(void)
+{
+ if (!r_bloom->integer)
+ return;
+ if (r_rmse->integer) { // this breaks bloom
+ ri.Cvar_Set("r_bloom", "0");
+ Com_Printf(S_COLOR_YELLOW "WARNING: 'r_rmse' is not set to 0, bloom effect disabled\n");
+ return;
+ }
+ if (backEnd.doneBloom)
+ return;
+ if (!backEnd.doneSurfaces)
+ return;
+ if (!clientIsConnected)
+ return;
+ backEnd.doneBloom = qtrue;
+ if (!bloom.started) {
+ R_Bloom_InitTextures();
+ if (!bloom.started)
+ return;
+ }
+ if (!backEnd.projection2D)
+ RB_SetGL2D();
+#if 0
+ // set up full screen workspace
+ GL_TexEnv(GL_MODULATE);
+ qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
+ qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight);
+ qglMatrixMode(GL_PROJECTION);
+ qglLoadIdentity();
+ qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
+ qglMatrixMode(GL_MODELVIEW);
+ qglLoadIdentity();
+
+ GL_Cull(CT_TWO_SIDED);
+#endif
+
+ qglColor4f(1, 1, 1, 1);
+
+ //Backup the old screen in a texture
+ R_Bloom_BackupScreen();
+ // create the bloom texture using one of a few methods
+ R_Bloom_WarsowEffect();
+ // R_Bloom_CreateEffect();
+ // restore the screen-backup to the screen
+ R_Bloom_RestoreScreen();
+ // Do the final pass using the bloom texture for the final effect
+ R_Bloom_DrawEffect();
+}
+
+
+void R_BloomInit(void) {
+ memset(&bloom, 0, sizeof(bloom));
+
+ r_bloom = ri.Cvar_Get("r_bloom", "0", CVAR_ARCHIVE);
+ r_bloom_alpha = ri.Cvar_Get("r_bloom_alpha", "0.3", CVAR_ARCHIVE);
+ r_bloom_diamond_size = ri.Cvar_Get("r_bloom_diamond_size", "8", CVAR_ARCHIVE);
+ r_bloom_intensity = ri.Cvar_Get("r_bloom_intensity", "1.3", CVAR_ARCHIVE);
+ r_bloom_darken = ri.Cvar_Get("r_bloom_darken", "4", CVAR_ARCHIVE);
+ r_bloom_sample_size = ri.Cvar_Get("r_bloom_sample_size", "128", CVAR_ARCHIVE | CVAR_LATCH);
+ r_bloom_fast_sample = ri.Cvar_Get("r_bloom_fast_sample", "0", CVAR_ARCHIVE | CVAR_LATCH);
+}
+
diff --git a/src/renderer/tr_bsp.c b/src/renderer/tr_bsp.c
index 09088acf..ed09667f 100644
--- a/src/renderer/tr_bsp.c
+++ b/src/renderer/tr_bsp.c
@@ -141,7 +141,7 @@ R_LoadLightmaps
static void R_LoadLightmaps( lump_t *l ) {
byte *buf, *buf_p;
int len;
- MAC_STATIC byte image[LIGHTMAP_SIZE * LIGHTMAP_SIZE * 4];
+ byte image[LIGHTMAP_SIZE * LIGHTMAP_SIZE * 4];
int i, j;
float maxIntensity = 0;
double sumIntensity = 0;
@@ -179,7 +179,7 @@ static void R_LoadLightmaps( lump_t *l ) {
float g = buf_p[j * 3 + 1];
float b = buf_p[j * 3 + 2];
float intensity;
- float out[3];
+ float out[3] = {0.0, 0.0, 0.0};
intensity = 0.33f * r + 0.685f * g + 0.063f * b;
@@ -288,12 +288,6 @@ static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) {
lightmapNum = LIGHTMAP_BY_VERTEX;
}
-// JPW NERVE removed per atvi request
-/*
- if ( r_fullbright->integer ) {
- lightmapNum = LIGHTMAP_WHITEIMAGE;
- }
-*/
shader = R_FindShader( dsh->shader, lightmapNum, qtrue );
// if the shader had errors, just use default shader
@@ -378,7 +372,7 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int
numIndexes = LittleLong( ds->numIndexes );
// create the srfSurfaceFace_t
- sfaceSize = ( int ) &( (srfSurfaceFace_t *)0 )->points[numPoints];
+ sfaceSize = ( size_t )&((srfSurfaceFace_t *)0)->points[numPoints];
ofsIndexes = sfaceSize;
sfaceSize += sizeof( int ) * numIndexes;
@@ -428,7 +422,7 @@ static void ParseMesh( dsurface_t *ds, drawVert_t *verts, msurface_t *surf ) {
srfGridMesh_t *grid;
int i, j;
int width, height, numPoints;
- MAC_STATIC drawVert_t points[MAX_PATCH_SIZE * MAX_PATCH_SIZE];
+ drawVert_t points[MAX_PATCH_SIZE * MAX_PATCH_SIZE];
int lightmapNum;
vec3_t bounds[2];
vec3_t tmpVec;
@@ -1452,7 +1446,7 @@ void R_MovePatchSurfacesToHunk( void ) {
Com_Memcpy( hunkgrid->widthLodError, grid->widthLodError, grid->width * 4 );
hunkgrid->heightLodError = ri.Hunk_Alloc( grid->height * 4, h_low );
- Com_Memcpy( grid->heightLodError, grid->heightLodError, grid->height * 4 );
+ Com_Memcpy(hunkgrid->heightLodError, grid->heightLodError, grid->height * 4);
R_FreeSurfaceGridMesh( grid );
@@ -1568,6 +1562,9 @@ static void R_LoadSubmodels( lump_t *l ) {
model = R_AllocModel();
assert( model != NULL ); // this should never happen
+ if (model == NULL) {
+ ri.Error(ERR_DROP, "R_LoadSubmodels: R_AllocModel() failed");
+ }
model->type = MOD_BRUSH;
model->bmodel = out;
diff --git a/src/renderer/tr_cmds.c b/src/renderer/tr_cmds.c
index a853adb9..1daf0676 100644
--- a/src/renderer/tr_cmds.c
+++ b/src/renderer/tr_cmds.c
@@ -436,6 +436,15 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
r_textureMode->modified = qfalse;
}
+ //
+ // anisotropic filtering stuff
+ //
+ if (r_textureAnisotropy->modified) {
+ R_SyncRenderThread();
+ GL_TextureAnisotropy(r_textureAnisotropy->value);
+ r_textureAnisotropy->modified = qfalse;
+ }
+
//
// NVidia stuff
//
diff --git a/src/renderer/tr_curve.c b/src/renderer/tr_curve.c
index 35e672a2..a09ae2f8 100644
--- a/src/renderer/tr_curve.c
+++ b/src/renderer/tr_curve.c
@@ -120,7 +120,7 @@ static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZ
int i, j, k, dist;
vec3_t normal;
vec3_t sum;
- int count;
+ int count = 0;
vec3_t base;
vec3_t delta;
int x, y;
@@ -211,10 +211,6 @@ static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZ
VectorAdd( normal, sum, sum );
count++;
}
- if ( count == 0 ) {
-//printf("bad normal\n");
- count = 1;
- }
VectorNormalize2( sum, dv->normal );
}
}
@@ -367,11 +363,13 @@ R_SubdividePatchToGrid
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
int i, j, k, l;
- drawVert_t prev, next, mid;
+ drawVert_t_cleared(prev);
+ drawVert_t_cleared(next);
+ drawVert_t_cleared(mid);
float len, maxLen;
int dir;
int t;
- MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
+ drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
for ( i = 0 ; i < width ; i++ ) {
@@ -529,7 +527,7 @@ R_GridInsertColumn
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) {
int i, j;
int width, height, oldwidth;
- MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
+ drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
float lodRadius;
vec3_t lodOrigin;
@@ -585,7 +583,7 @@ R_GridInsertRow
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) {
int i, j;
int width, height, oldheight;
- MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
+ drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
float lodRadius;
vec3_t lodOrigin;
diff --git a/src/renderer/tr_flares.c b/src/renderer/tr_flares.c
index e40e079e..ea7a8d8c 100644
--- a/src/renderer/tr_flares.c
+++ b/src/renderer/tr_flares.c
@@ -83,17 +83,19 @@ typedef struct flare_s {
int windowX, windowY;
float eyeZ;
+ vec3_t origin;
vec3_t color;
float scale;
int id;
} flare_t;
-#define MAX_FLARES 128
+#define MAX_FLARES 256
flare_t r_flareStructs[MAX_FLARES];
flare_t *r_activeFlares, *r_inactiveFlares;
+int flareCoeff;
/*
==================
@@ -123,17 +125,26 @@ This is called at surface tesselation time
*/
void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, float scale, vec3_t normal, int id, qboolean cgvisible ) { //----(SA) added scale. added id. added visible
int i;
- flare_t *f, *oldest;
+ flare_t *f;
vec3_t local;
- float d;
+ float d = 1;
vec4_t eye, clip, normalized, window;
backEnd.pc.c_flareAdds++;
+ if (normal && (normal[0] || normal[1] || normal[2])) {
+ VectorSubtract(backEnd.viewParms. or .origin, point, local);
+ VectorNormalizeFast(local);
+ d = DotProduct(local, normal);
+
+ // If the viewer is behind the flare don't add it.
+ if (d < 0)
+ return;
+ }
+
// if the point is off the screen, don't bother adding it
// calculate screen coordinates and depth
- R_TransformModelToClip( point, backEnd.or.modelMatrix,
- backEnd.viewParms.projectionMatrix, eye, clip );
+ R_TransformModelToClip(point, backEnd. or .modelMatrix, backEnd.viewParms.projectionMatrix, eye, clip);
//ri.Printf(PRINT_ALL, "src: %f %f %f \n", point[0], point[1], point[2]);
//ri.Printf(PRINT_ALL, "eye: %f %f %f %f\n", eye[0], eye[1], eye[2], eye[3]);
@@ -155,8 +166,7 @@ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, float s
}
// see if a flare with a matching surface, scene, and view exists
- oldest = r_flareStructs;
- for ( f = r_activeFlares ; f ; f = f->next ) {
+ for ( f = r_activeFlares; f; f = f->next ) {
// if ( f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum && f->inPortal == backEnd.viewParms.isPortal ) {
// (SA) added back in more checks for different scenes
@@ -193,18 +203,14 @@ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, float s
f->addedFrame = backEnd.viewParms.frameCount;
f->fogNum = fogNum;
+ VectorCopy( point, f->origin );
VectorCopy( color, f->color );
f->scale = scale; //----(SA)
// fade the intensity of the flare down as the
// light surface turns away from the viewer
- if ( normal ) {
- VectorSubtract( backEnd.viewParms.or.origin, point, local );
- VectorNormalizeFast( local );
- d = DotProduct( local, normal );
- VectorScale( f->color, d, f->color );
- }
+ VectorScale(f->color, d, f->color);
// save info needed to test
f->windowX = backEnd.viewParms.viewportX + window[0];
@@ -219,36 +225,43 @@ RB_AddDlightFlares
==================
*/
void RB_AddDlightFlares( void ) {
- dlight_t *l;
+ dlight_t *l;
int i, j, k;
int id = 0;
- fog_t *fog;
+ fog_t *fog = NULL;
if ( r_flares->integer < 2 ) {
return;
}
l = backEnd.refdef.dlights;
- fog = tr.world->fogs;
- for ( i = 0 ; i < backEnd.refdef.num_dlights ; i++, l++ ) {
+ if (tr.world)
+ fog = tr.world->fogs;
+
+ for (i = 0; i < backEnd.refdef.num_dlights; i++, l++) {
// find which fog volume the light is in
- for ( j = 1 ; j < tr.world->numfogs ; j++ ) {
- fog = &tr.world->fogs[j];
- for ( k = 0 ; k < 3 ; k++ ) {
- if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) {
+ if (fog) {
+ // find which fog volume the light is in
+ for (j = 1; j < tr.world->numfogs; j++) {
+ fog = &tr.world->fogs[j];
+ for (k = 0; k < 3; k++) {
+ if (l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k]) {
+ break;
+ }
+ }
+ if (k == 3) {
break;
}
}
- if ( k == 3 ) {
- break;
+ if (j == tr.world->numfogs) {
+ j = 0;
}
}
- if ( j == tr.world->numfogs ) {
+ else
j = 0;
- }
- RB_AddFlare( (void *)l, j, l->origin, l->color, 1.0f, NULL, id++, qtrue ); //----(SA) also set scale
+ RB_AddFlare((void*)l, j, l->origin, l->color, 1.0f, NULL, id++, qtrue); //----(SA) also set scale
}
}
@@ -308,31 +321,11 @@ RB_TestFlare
==================
*/
void RB_TestFlare( flare_t *f ) {
-// float depth;
qboolean visible;
float fade;
-// float screenZ;
backEnd.pc.c_flareTests++;
- // doing a readpixels is as good as doing a glFinish(), so
- // don't bother with another sync
-// glState.finishCalled = qfalse;
-// glState.finishCalled = qtrue; // (SA) Hmm, shouldn't this be true?
-
- // read back the z buffer contents
-// qglReadPixels( f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
-// screenZ = backEnd.viewParms.projectionMatrix[14] /
-// ( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] );
-
- //----(SA) 24 was way to low tolerance. It gave Dan problems with free standing light fixtures
- //----(SA) I will monitor to see if changing this screws up any other situations
- //----(SA) and 2 was way to high tolerance
-// visible = ( -f->eyeZ - -screenZ ) < 2;
-// visible = ( -f->eyeZ - -screenZ ) < 24;
-// visible = ( -f->eyeZ - -screenZ ) < 6;
-
-// visible = qtrue;
visible = f->cgvisible;
if ( visible ) {
@@ -341,7 +334,8 @@ void RB_TestFlare( flare_t *f ) {
f->fadeTime = backEnd.refdef.time - 1;
}
fade = ( ( backEnd.refdef.time - f->fadeTime ) / 1000.0f ) * r_flareFade->value;
- } else {
+ }
+ else {
if ( f->visible ) {
f->visible = qfalse;
f->fadeTime = backEnd.refdef.time - 1;
@@ -359,7 +353,6 @@ void RB_TestFlare( flare_t *f ) {
f->drawIntensity = fade;
}
-
/*
==================
RB_RenderFlare
@@ -369,26 +362,64 @@ void RB_RenderFlare( flare_t *f ) {
float size;
vec3_t color;
int iColor[3];
+ float distance, intensity, factor;
+ byte fogFactors[3] = {255, 255, 255};
backEnd.pc.c_flareRenders++;
-//----(SA) changed to use alpha blend rather than additive blend
-// this is to accomidate the fact we can't right now do
-// additive blends and have them fog correctly with our distance fog.
-// /when/ we fix the blend problems with distance fog, this should
-// be changed back to additive since there's nearly no hit for that
-// but the alpha blend is noticably slower.
-
-// VectorScale( f->color, f->drawIntensity*tr.identityLight, color );
- VectorScale( f->color, tr.identityLight, color ); //----(SA) mod for alpha blend rather than additive
-
- iColor[0] = color[0] * 255;
- iColor[1] = color[1] * 255;
- iColor[2] = color[2] * 255;
+ // We don't want too big values anyways when dividing by distance.
+ if (f->eyeZ > -1.0f)
+ distance = 1.0f;
+ else
+ distance = -f->eyeZ;
+
+ // calculate the flare size..
+ size = backEnd.viewParms.viewportWidth * (r_flareSize->value / 640.0f + 8 / distance);
+
+ /*
+ * This is an alternative to intensity scaling. It changes the size of the flare on screen instead
+ * with growing distance. See in the description at the top why this is not the way to go.
+ // size will change ~ 1/r.
+ size = backEnd.viewParms.viewportWidth * (r_flareSize->value / (distance * -2.0f));
+ */
+
+ /*
+ * As flare sizes stay nearly constant with increasing distance we must decrease the intensity
+ * to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be
+ * got by considering the ratio of
+ * (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare)
+ * An important requirement is:
+ * intensity <= 1 for all distances.
+ *
+ * The formula used here to compute the intensity is as follows:
+ * intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2
+ * As you can see, the intensity will have a max. of 1 when the distance is 0.
+ * The coefficient flareCoeff will determine the falloff speed with increasing distance.
+ */
+
+ factor = distance + size * sqrt(flareCoeff);
+ intensity = flareCoeff * size * size / (factor * factor);
+
+ VectorScale(f->color, f->drawIntensity * intensity, color);
+
+ // Calculations for fogging
+ if (tr.world && f->fogNum > 0 && f->fogNum < tr.world->numfogs) {
+ tess.numVertexes = 1;
+ VectorCopy(f->origin, tess.xyz[0]);
+ tess.fogNum = f->fogNum;
+
+ RB_CalcModulateColorsByFog(fogFactors);
+
+ // We don't need to render the flare if colors are 0 anyways.
+ if (!(fogFactors[0] || fogFactors[1] || fogFactors[2]))
+ return;
+ }
- size = backEnd.viewParms.viewportWidth * ( ( r_flareSize->value * f->scale ) / 640.0 + 8 / -f->eyeZ );
+ iColor[0] = color[0] * fogFactors[0];
+ iColor[1] = color[1] * fogFactors[1];
+ iColor[2] = color[2] * fogFactors[2];
- RB_BeginSurface( tr.flareShader, f->fogNum );
+ RB_BeginSurface(tr.flareShader, f->fogNum);
// FIXME: use quadstamp?
tess.xyz[tess.numVertexes][0] = f->windowX - size;
@@ -470,6 +501,20 @@ void RB_RenderFlares( void ) {
return;
}
+ if (r_flareCoeff->modified) {
+ if (r_flareCoeff->value == 0.0f)
+ flareCoeff = atof(FLARE_STDCOEFF);
+ else
+ flareCoeff = r_flareCoeff->value;
+
+ r_flareCoeff->modified = qfalse;
+ }
+
+ // Reset currentEntity to world so that any previously referenced entities
+ // don't have influence on the rendering of these flares (i.e. RF_ renderer flags).
+ backEnd.currentEntity = &tr.worldEntity;
+ backEnd. or = backEnd.viewParms.world;
+
// (SA) turned light flares back on. must evaluate problem id had with this
RB_AddDlightFlares();
RB_AddCoronaFlares();
@@ -493,7 +538,8 @@ void RB_RenderFlares( void ) {
RB_TestFlare( f );
if ( f->drawIntensity ) {
draw = qtrue;
- } else {
+ }
+ else {
// this flare has completely faded out, so remove it from the chain
*prev = f->next;
f->next = r_inactiveFlares;
diff --git a/src/renderer/tr_image.c b/src/renderer/tr_image.c
index 18eb1b49..2dbe3aaf 100644
--- a/src/renderer/tr_image.c
+++ b/src/renderer/tr_image.c
@@ -57,6 +57,8 @@ static unsigned char s_gammatable[256];
int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
int gl_filter_max = GL_LINEAR;
+float gl_anisotropy = 1.0; // L0 - ET port
+
#define FILE_HASH_SIZE 4096
static image_t* hashTable[FILE_HASH_SIZE];
@@ -202,6 +204,38 @@ void GL_TextureMode( const char *string ) {
}
}
+/*
+===============
+L0 - ET port
+
+GL_TextureAnisotropy
+===============
+*/
+void GL_TextureAnisotropy(float anisotropy) {
+ int i;
+ image_t* glt;
+
+ if (r_ext_texture_filter_anisotropic->integer == 1) {
+ if (anisotropy < 1.0 || anisotropy > glConfig.maxAnisotropy) {
+ ri.Printf(PRINT_ALL, "anisotropy out of range\n");
+ return;
+ }
+ }
+
+ gl_anisotropy = anisotropy;
+
+ if (!glConfig.anisotropicAvailable) {
+ return;
+ }
+
+ // change all the existing texture objects
+ for (i = 0; i < tr.numImages; i++) {
+ glt = tr.images[i];
+ GL_Bind(glt);
+ qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropy);
+ }
+}
+
/*
===============
R_SumOfUsedImages
@@ -820,6 +854,10 @@ static void Upload32( unsigned *data,
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
+ if (glConfig.anisotropicAvailable) {
+ qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropy);
+ }
+
GL_CheckErrors();
//if ( scaledBuffer != 0 )
@@ -862,6 +900,11 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
noCompress = qtrue;
}
+ // ydnar: don't compress textures smaller or equal to 128x128 pixels
+ if ((width * height) <= (128 * 128)) {
+ noCompress = qtrue;
+ }
+
if ( tr.numImages == MAX_DRAWIMAGES ) {
ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n" );
}
@@ -869,14 +912,15 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
// Ridah
image = tr.images[tr.numImages] = R_CacheImageAlloc( sizeof( image_t ) );
- image->texnum = 1024 + tr.numImages;
-
// Ridah
if ( r_cacheShaders->integer ) {
R_FindFreeTexnum( image );
}
// done.
+ // ydnar: ok, let's try the recommended way
+ qglGenTextures(1, &image->texnum);
+
tr.numImages++;
image->mipmap = mipmap;
@@ -1120,12 +1164,16 @@ PCX LOADING
/*
==============
LoadPCX
+
+L0 - ET port (patched existing)
==============
*/
+#define DECODEPCX( b, d, r ) d = *b++; if ( ( d & 0xC0 ) == 0xC0 ) {r = d & 0x3F; d = *b++;} else {r = 1;}
+
static void LoadPCX( const char *filename, byte **pic, byte **palette, int *width, int *height ) {
byte *raw;
pcx_t *pcx;
- int x, y;
+ int x, y, lsize;
int len;
int dataByte, runLength;
byte *out, *pix;
@@ -1133,6 +1181,7 @@ static void LoadPCX( const char *filename, byte **pic, byte **palette, int *widt
*pic = NULL;
*palette = NULL;
+ runLength = 0;
//
// load the file
@@ -1180,23 +1229,24 @@ static void LoadPCX( const char *filename, byte **pic, byte **palette, int *widt
}
// FIXME: use bytes_per_line here?
- for ( y = 0 ; y <= ymax ; y++, pix += xmax + 1 )
- {
- for ( x = 0 ; x <= xmax ; )
- {
- dataByte = *raw++;
+ lsize = pcx->color_planes * pcx->bytes_per_line;
- if ( ( dataByte & 0xC0 ) == 0xC0 ) {
- runLength = dataByte & 0x3F;
- dataByte = *raw++;
- } else {
- runLength = 1;
- }
-
- while ( runLength-- > 0 )
+ // go scanline by scanline
+ for (y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1) {
+ // do a scanline
+ for (x = 0; x <= pcx->xmax;) {
+ DECODEPCX(raw, dataByte, runLength);
+ while (runLength-- > 0)
pix[x++] = dataByte;
}
+ // discard any other data
+ while (x < lsize) {
+ DECODEPCX(raw, dataByte, runLength);
+ x++;
+ }
+ while (runLength-- > 0)
+ x++;
}
if ( raw - (byte *)pcx > len ) {
@@ -1208,7 +1258,6 @@ static void LoadPCX( const char *filename, byte **pic, byte **palette, int *widt
ri.FS_FreeFile( pcx );
}
-
/*
==============
LoadPCX32
@@ -2293,11 +2342,23 @@ void R_SetColorMappings( void ) {
ri.Cvar_Set( "r_intensity", "1" );
}
- if ( r_gamma->value < 0.5f ) {
- ri.Cvar_Set( "r_gamma", "0.5" );
- } else if ( r_gamma->value > 3.0f ) {
- ri.Cvar_Set( "r_gamma", "3.0" );
+#ifdef __linux__
+ if (r_gamma->value != -1) {
+#endif
+ if (r_gamma->value < 0.5f) {
+ ri.Cvar_Set("r_gamma", "0.5");
+ }
+ else if (r_gamma->value > 3.0f) {
+ ri.Cvar_Set("r_gamma", "3.0");
+ }
+ g = r_gamma->value;
+
+#ifdef __linux__
+ }
+ else {
+ g = 1.0f;
}
+#endif
g = r_gamma->value;
@@ -2548,7 +2609,10 @@ qhandle_t RE_GetShaderFromModel( qhandle_t modelid, int surfnum, int withlightma
}
surf = bmodel->firstSurface + surfnum;
-// if(surf->shader->lightmapIndex != LIGHTMAP_NONE) {
+ // RF, check for null shader (can happen on func_explosive's with botclips attached)
+ if (!surf->shader) {
+ return 0;
+ }
if ( surf->shader->lightmapIndex > LIGHTMAP_NONE ) {
image_t *image;
long hash;
diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c
index 2cf79ad8..af5a56af 100644
--- a/src/renderer/tr_init.c
+++ b/src/renderer/tr_init.c
@@ -42,6 +42,7 @@ static void GfxInfo_f( void );
cvar_t *r_flareSize;
cvar_t *r_flareFade;
+cvar_t* r_flareCoeff;
cvar_t *r_railWidth;
cvar_t *r_railCoreWidth;
@@ -140,6 +141,7 @@ cvar_t *r_finish;
cvar_t *r_clear;
cvar_t *r_swapInterval;
cvar_t *r_textureMode;
+cvar_t *r_textureAnisotropy;
cvar_t *r_offsetFactor;
cvar_t *r_offsetUnits;
cvar_t *r_gamma;
@@ -371,18 +373,30 @@ typedef struct vidmode_s
vidmode_t r_vidModes[] =
{
- { "Mode 0: 320x240", 320, 240, 1 },
- { "Mode 1: 400x300", 400, 300, 1 },
- { "Mode 2: 512x384", 512, 384, 1 },
- { "Mode 3: 640x480", 640, 480, 1 },
- { "Mode 4: 800x600", 800, 600, 1 },
- { "Mode 5: 960x720", 960, 720, 1 },
- { "Mode 6: 1024x768", 1024, 768, 1 },
- { "Mode 7: 1152x864", 1152, 864, 1 },
- { "Mode 8: 1280x1024", 1280, 1024, 1 },
- { "Mode 9: 1600x1200", 1600, 1200, 1 },
- { "Mode 10: 2048x1536", 2048, 1536, 1 },
- { "Mode 11: 856x480 (wide)",856, 480, 1 }
+ // L0 - modifed and updated resolutions..
+ { "Mode 0: 320x240", 320, 240, 1 },
+ { "Mode 1: 400x300", 400, 300, 1 },
+ { "Mode 2: 512x384", 512, 384, 1 },
+ { "Mode 3: 640x480", 640, 480, 1 },
+ { "Mode 4: 800x600", 800, 600, 1 },
+ { "Mode 5: 856x480 (wide)", 856, 480, 1 },
+ { "Mode 6: 960x720", 960, 720, 1 },
+ { "Mode 7: 1024x768", 1024, 768, 1 },
+ { "Mode 8: 1152x864", 1152, 864, 1 },
+ { "Mode 9: 1280x720 (16:9)", 1280, 720, 1 },
+ { "Mode 10: 1280x768 (16:10)", 1280, 768, 1 },
+ { "Mode 11: 1280x800 (16:10)", 1280, 800, 1 },
+ { "Mode 12: 1280x1024", 1280, 1024, 1 },
+ { "Mode 13: 1360x768 (16:9)", 1360, 768, 1 },
+ { "Mode 14: 1440x900 (16:10)", 1440, 900, 1 },
+ { "Mode 15: 1680x1050 (16:10)", 1680, 1050, 1 },
+ { "Mode 16: 1600x1200", 1600, 1200, 1 },
+ { "Mode 17: 1920x1080 (FULL HD)", 1920, 1080, 1 },
+ { "Mode 18: 1920x1200", 1920, 1200, 1 },
+ { "Mode 19: 2048x1536", 2048, 1536, 1 },
+ { "Mode 20: 2560x1440 (QHD)", 2560, 1440, 1 },
+ { "Mode 21: 2560x1600 (16:10)", 2560, 1600, 1 },
+ { "Mode 22: 3840x2160 (UHD)", 3840, 2160, 1 }
};
static int s_numVidModes = ( sizeof( r_vidModes ) / sizeof( r_vidModes[0] ) );
@@ -751,6 +765,7 @@ void GL_SetDefaultState( void ) {
if ( qglActiveTextureARB ) {
GL_SelectTexture( 1 );
GL_TextureMode( r_textureMode->string );
+ GL_TextureAnisotropy(r_textureAnisotropy->value);
GL_TexEnv( GL_MODULATE );
qglDisable( GL_TEXTURE_2D );
GL_SelectTexture( 0 );
@@ -758,6 +773,7 @@ void GL_SetDefaultState( void ) {
qglEnable( GL_TEXTURE_2D );
GL_TextureMode( r_textureMode->string );
+ GL_TextureAnisotropy(r_textureAnisotropy->value);
GL_TexEnv( GL_MODULATE );
qglShadeModel( GL_SMOOTH );
@@ -834,9 +850,7 @@ void GfxInfo_f( void ) {
ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string );
ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string );
ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string );
- ri.Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string );
ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
- ri.Printf( PRINT_ALL, "GL_MAX_ACTIVE_TEXTURES_ARB: %d\n", glConfig.maxActiveTextures );
ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
if ( glConfig.displayFrequency ) {
@@ -885,6 +899,7 @@ void GfxInfo_f( void ) {
ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] );
ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] );
ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression != TC_NONE] );
+ ri.Printf( PRINT_ALL, "anisotropy: %s\n", r_textureAnisotropy->string );
ri.Printf( PRINT_ALL, "NV distance fog: %s\n", enablestrings[glConfig.NVFogAvailable != 0] );
if ( glConfig.NVFogAvailable ) {
@@ -947,7 +962,7 @@ void R_Register( void ) {
r_picmip = ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH ); //----(SA) mod for DM and DK for id build. was "1" // JPW NERVE pushed back to 1
r_roundImagesDown = ri.Cvar_Get( "r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_rmse = ri.Cvar_Get( "r_rmse", "0.0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_rmse = ri.Cvar_Get( "r_rmse", "0.0", CVAR_CHEAT);
r_colorMipLevels = ri.Cvar_Get( "r_colorMipLevels", "0", CVAR_LATCH );
AssertCvarRange( r_picmip, 0, 16, qtrue );
r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
@@ -962,7 +977,7 @@ void R_Register( void ) {
r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_overBrightBits = ri.Cvar_Get( "r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_mode = ri.Cvar_Get( "r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH );
+ r_mode = ri.Cvar_Get( "r_mode", "4", CVAR_ARCHIVE | CVAR_LATCH );
r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH );
r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH );
@@ -974,6 +989,10 @@ void R_Register( void ) {
#ifdef MACOS_X
// Default to using SMP on Mac OS X if we have multiple processors
r_smp = ri.Cvar_Get( "r_smp", Sys_ProcessorCount() > 1 ? "1" : "0", CVAR_ARCHIVE | CVAR_LATCH );
+#elif defined WIN32
+ // ydnar: r_smp is nonfunctional on windows
+ r_smp = ri.Cvar_Get("r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH | CVAR_ROM);
+ Cvar_Set("r_smp", "0");
#else
r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH );
#endif
@@ -1011,6 +1030,7 @@ void R_Register( void ) {
r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE );
r_finish = ri.Cvar_Get( "r_finish", "0", CVAR_ARCHIVE );
r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE );
+ r_textureAnisotropy = ri.Cvar_Get("r_textureAnisotropy", "1.0", CVAR_ARCHIVE);
r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0", CVAR_ARCHIVE );
#ifdef __MACOS__
r_gamma = ri.Cvar_Get( "r_gamma", "1.2", CVAR_ARCHIVE );
@@ -1043,7 +1063,7 @@ void R_Register( void ) {
// with r_cache enabled, non-win32 OSes were leaking 24Mb per R_Init..
r_cache = ri.Cvar_Get( "r_cache", "1", CVAR_LATCH ); // leaving it as this for backwards compability. but it caches models and shaders also
// TTimo show_bug.cgi?id=570
- r_cacheShaders = ri.Cvar_Get( "r_cacheShaders", "1", CVAR_LATCH );
+ r_cacheShaders = ri.Cvar_Get( "r_cacheShaders", "0", CVAR_LATCH );
r_cacheModels = ri.Cvar_Get( "r_cacheModels", "1", CVAR_LATCH );
r_compressModels = ri.Cvar_Get( "r_compressModels", "0", 0 ); // converts MD3 -> MDC at run-time
@@ -1065,6 +1085,7 @@ void R_Register( void ) {
r_flareSize = ri.Cvar_Get( "r_flareSize", "40", CVAR_CHEAT );
ri.Cvar_Set( "r_flareFade", "5" ); // to force this when people already have "7" in their config
r_flareFade = ri.Cvar_Get( "r_flareFade", "5", CVAR_CHEAT );
+ r_flareCoeff = ri.Cvar_Get("r_flareCoeff", FLARE_STDCOEFF, CVAR_CHEAT);
r_showSmp = ri.Cvar_Get( "r_showSmp", "0", CVAR_CHEAT );
r_skipBackEnd = ri.Cvar_Get( "r_skipBackEnd", "0", CVAR_CHEAT );
@@ -1174,6 +1195,8 @@ void R_Init( void ) {
R_Register();
+ R_BloomInit();
+
max_polys = r_maxpolys->integer;
if ( max_polys < MAX_POLYS ) {
max_polys = MAX_POLYS;
diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h
index 60219fed..f2731d06 100644
--- a/src/renderer/tr_local.h
+++ b/src/renderer/tr_local.h
@@ -25,9 +25,6 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
-
-
-
#ifndef TR_LOCAL_H
#define TR_LOCAL_H
@@ -923,6 +920,10 @@ typedef struct {
byte color2D[4];
qboolean vertexes2D; // shader needs to be finished
trRefEntity_t entity2D; // currentEntity will point at this when doing 2D rendering
+
+ // L0 - Bloom
+ qboolean doneBloom; // done bloom this frame
+ qboolean doneSurfaces; // done any 3d surfaces already
} backEndState_t;
/*
@@ -1048,6 +1049,8 @@ extern glstate_t glState; // outside of TR since it shouldn't be clear
//
extern cvar_t *r_flareSize;
extern cvar_t *r_flareFade;
+#define FLARE_STDCOEFF "150" // coefficient for the flare intensity falloff function.
+extern cvar_t* r_flareCoeff;
extern cvar_t *r_railWidth;
extern cvar_t *r_railCoreWidth;
@@ -1139,6 +1142,7 @@ extern cvar_t *r_glDriver;
extern cvar_t *r_glIgnoreWicked3D;
extern cvar_t *r_swapInterval;
extern cvar_t *r_textureMode;
+extern cvar_t *r_textureAnisotropy;
extern cvar_t *r_offsetFactor;
extern cvar_t *r_offsetUnits;
@@ -1241,6 +1245,7 @@ void GL_Bind( image_t *image );
void GL_SetDefaultState( void );
void GL_SelectTexture( int unit );
void GL_TextureMode( const char *string );
+void GL_TextureAnisotropy(float anisotropy);
void GL_CheckErrors( void );
void GL_State( unsigned long stateVector );
void GL_TexEnv( int env );
@@ -1410,6 +1415,7 @@ typedef struct shaderCommands_s
extern shaderCommands_t tess;
+void RB_SetGL2D(void);
void RB_BeginSurface( shader_t *shader, int fogNum );
void RB_EndSurface( void );
void RB_CheckOverflow( int verts, int indexes );
@@ -1737,6 +1743,10 @@ void R_InitFreeType();
void R_DoneFreeType();
void RE_RegisterFont( const char *fontName, int pointSize, fontInfo_t *font );
+// L0 - Bloom
+void R_BloomInit(void);
+void R_BloomScreen(void);
+
// Ridah, caching system
// NOTE: to disable this for development, set "r_cache 0" in autoexec.cfg
void R_InitTexnumImages( qboolean force );
diff --git a/src/renderer/tr_main.c b/src/renderer/tr_main.c
index b9efd737..4109ba1f 100644
--- a/src/renderer/tr_main.c
+++ b/src/renderer/tr_main.c
@@ -850,6 +850,12 @@ void R_SetupFrustum( void ) {
tr.viewParms.frustum[i].dist = DotProduct( tr.viewParms.or.origin, tr.viewParms.frustum[i].normal );
SetPlaneSignbits( &tr.viewParms.frustum[i] );
}
+
+ // ydnar: farplane (testing! use farplane for real)
+ VectorScale(tr.viewParms. or .axis[0], -1, tr.viewParms.frustum[4].normal);
+ tr.viewParms.frustum[4].dist = DotProduct(tr.viewParms. or .origin, tr.viewParms.frustum[4].normal) - tr.viewParms.zFar;
+ tr.viewParms.frustum[4].type = PLANE_NON_AXIAL;
+ SetPlaneSignbits(&tr.viewParms.frustum[4]);
}
diff --git a/src/renderer/tr_marks.c b/src/renderer/tr_marks.c
index 15667025..780a98d0 100644
--- a/src/renderer/tr_marks.c
+++ b/src/renderer/tr_marks.c
@@ -2,9 +2,9 @@
===========================================================================
Return to Castle Wolfenstein multiplayer GPL Source Code
-Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
+Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
-This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
+This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”).
RTCW MP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -49,19 +49,19 @@ Out must have space for two more vertexes than in
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
-static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON_POLY],
- int *numOutPoints, vec3_t outPoints[MAX_VERTS_ON_POLY],
- vec3_t normal, vec_t dist, vec_t epsilon ) {
+static void R_ChopPolyBehindPlane(int numInPoints, vec3_t inPoints[MAX_VERTS_ON_POLY],
+ int* numOutPoints, vec3_t outPoints[MAX_VERTS_ON_POLY],
+ vec3_t normal, vec_t dist, vec_t epsilon) {
float dists[MAX_VERTS_ON_POLY + 4];
int sides[MAX_VERTS_ON_POLY + 4];
int counts[3];
float dot;
int i, j;
- float *p1, *p2, *clip;
+ float* p1, * p2, * clip;
float d;
// don't clip if it might overflow
- if ( numInPoints >= MAX_VERTS_ON_POLY - 2 ) {
+ if (numInPoints >= MAX_VERTS_ON_POLY - 2) {
*numOutPoints = 0;
return;
}
@@ -69,15 +69,17 @@ static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
- for ( i = 0 ; i < numInPoints ; i++ ) {
- dot = DotProduct( inPoints[i], normal );
+ for (i = 0; i < numInPoints; i++) {
+ dot = DotProduct(inPoints[i], normal);
dot -= dist;
dists[i] = dot;
- if ( dot > epsilon ) {
+ if (dot > epsilon) {
sides[i] = SIDE_FRONT;
- } else if ( dot < -epsilon ) {
+ }
+ else if (dot < -epsilon) {
sides[i] = SIDE_BACK;
- } else {
+ }
+ else {
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
@@ -87,52 +89,53 @@ static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON
*numOutPoints = 0;
- if ( !counts[0] ) {
+ if (!counts[0]) {
return;
}
- if ( !counts[1] ) {
+ if (!counts[1]) {
*numOutPoints = numInPoints;
- memcpy( outPoints, inPoints, numInPoints * sizeof( vec3_t ) );
+ memcpy(outPoints, inPoints, numInPoints * sizeof(vec3_t));
return;
}
- for ( i = 0 ; i < numInPoints ; i++ ) {
+ for (i = 0; i < numInPoints; i++) {
p1 = inPoints[i];
- clip = outPoints[ *numOutPoints ];
+ clip = outPoints[*numOutPoints];
- if ( sides[i] == SIDE_ON ) {
- VectorCopy( p1, clip );
- ( *numOutPoints )++;
+ if (sides[i] == SIDE_ON) {
+ VectorCopy(p1, clip);
+ (*numOutPoints)++;
continue;
}
- if ( sides[i] == SIDE_FRONT ) {
- VectorCopy( p1, clip );
- ( *numOutPoints )++;
- clip = outPoints[ *numOutPoints ];
+ if (sides[i] == SIDE_FRONT) {
+ VectorCopy(p1, clip);
+ (*numOutPoints)++;
+ clip = outPoints[*numOutPoints];
}
- if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
+ if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) {
continue;
}
// generate a split point
- p2 = inPoints[ ( i + 1 ) % numInPoints ];
+ p2 = inPoints[(i + 1) % numInPoints];
d = dists[i] - dists[i + 1];
- if ( d == 0 ) {
+ if (d == 0) {
dot = 0;
- } else {
+ }
+ else {
dot = dists[i] / d;
}
// clip xyz
- for ( j = 0 ; j < 3 ; j++ ) {
- clip[j] = p1[j] + dot * ( p2[j] - p1[j] );
+ for (j = 0; j < 3; j++) {
+ clip[j] = p1[j] + dot * (p2[j] - p1[j]);
}
- ( *numOutPoints )++;
+ (*numOutPoints)++;
}
}
@@ -142,68 +145,75 @@ R_BoxSurfaces_r
=================
*/
-void R_BoxSurfaces_r( mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir ) {
+void R_BoxSurfaces_r(mnode_t* node, vec3_t mins, vec3_t maxs, surfaceType_t** list, int listsize, int* listlength, vec3_t dir) {
int s, c;
- msurface_t *surf, **mark;
+ msurface_t* surf, ** mark;
// RF, if this node hasn't been rendered recently, ignore it
- if ( node->visframe < tr.visCount - 2 ) { // allow us to be a few frames behind
+ if (node->visframe < tr.visCount - 2) { // allow us to be a few frames behind
return;
}
// do the tail recursion in a loop
- while ( node->contents == -1 ) {
- s = BoxOnPlaneSide( mins, maxs, node->plane );
- if ( s == 1 ) {
+ while (node->contents == -1) {
+ s = BoxOnPlaneSide(mins, maxs, node->plane);
+ if (s == 1) {
node = node->children[0];
- } else if ( s == 2 ) {
+ }
+ else if (s == 2) {
node = node->children[1];
- } else {
- R_BoxSurfaces_r( node->children[0], mins, maxs, list, listsize, listlength, dir );
+ }
+ else {
+ R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir);
node = node->children[1];
}
}
// Ridah, don't mark alpha surfaces
- if ( node->contents & CONTENTS_TRANSLUCENT ) {
+ if (node->contents & CONTENTS_TRANSLUCENT) {
return;
}
// add the individual surfaces
mark = node->firstmarksurface;
c = node->nummarksurfaces;
- while ( c-- ) {
+ while (c--) {
//
- if ( *listlength >= listsize ) {
+ if (*listlength >= listsize) {
break;
}
//
surf = *mark;
// check if the surface has NOIMPACT or NOMARKS set
- if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
- || ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
+ if ((surf->shader->surfaceFlags & (SURF_NOIMPACT | SURF_NOMARKS))
+ || (surf->shader->contentFlags & CONTENTS_FOG)) {
surf->viewCount = tr.viewCount;
}
// extra check for surfaces to avoid list overflows
- else if ( *( surf->data ) == SF_FACE ) {
- // the face plane should go through the box
- s = BoxOnPlaneSide( mins, maxs, &( ( srfSurfaceFace_t * ) surf->data )->plane );
- if ( s == 1 || s == 2 ) {
- surf->viewCount = tr.viewCount;
- } else if ( DotProduct( ( ( srfSurfaceFace_t * ) surf->data )->plane.normal, dir ) < -0.5 ) {
- // don't add faces that make sharp angles with the projection direction
- surf->viewCount = tr.viewCount;
+ else if (*(surf->data) == SF_FACE) {
+ if (((srfSurfaceFace_t*)surf->data)->plane.type != PLANE_NON_PLANAR) {
+ // the face plane should go through the box
+ s = BoxOnPlaneSide(mins, maxs, &((srfSurfaceFace_t*)surf->data)->plane);
+ if (s == 1 || s == 2) {
+ surf->viewCount = tr.viewCount;
+ }
+ else if (DotProduct(((srfSurfaceFace_t*)surf->data)->plane.normal, dir) < -0.5) {
+ // don't add faces that make sharp angles with the projection direction
+ surf->viewCount = tr.viewCount;
+ }
}
- } else if ( *( surfaceType_t * )( surf->data ) != SF_GRID ) {
+ }
+ else if (*(surfaceType_t*)(surf->data) != SF_GRID && *(surfaceType_t*)(surf->data) != SF_TRIANGLES) {
surf->viewCount = tr.viewCount;
+
}
// check the viewCount because the surface may have
// already been added if it spans multiple leafs
- if ( surf->viewCount != tr.viewCount ) {
+ if (surf->viewCount != tr.viewCount) {
surf->viewCount = tr.viewCount;
- list[*listlength] = (surfaceType_t *) surf->data;
- ( *listlength )++;
+ list[*listlength] = (surfaceType_t*)surf->data;
+ (*listlength)++;
}
mark++;
}
@@ -215,35 +225,35 @@ R_AddMarkFragments
=================
*/
-void R_AddMarkFragments( int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POLY],
- int numPlanes, vec3_t *normals, float *dists,
- int maxPoints, vec3_t pointBuffer,
- int maxFragments, markFragment_t *fragmentBuffer,
- int *returnedPoints, int *returnedFragments,
- vec3_t mins, vec3_t maxs ) {
+void R_AddMarkFragments(int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POLY],
+ int numPlanes, vec3_t* normals, float* dists,
+ int maxPoints, vec3_t pointBuffer,
+ int maxFragments, markFragment_t* fragmentBuffer,
+ int* returnedPoints, int* returnedFragments,
+ vec3_t mins, vec3_t maxs) {
int pingPong, i;
- markFragment_t *mf;
+ markFragment_t* mf;
// chop the surface by all the bounding planes of the to be projected polygon
pingPong = 0;
- for ( i = 0 ; i < numPlanes ; i++ ) {
+ for (i = 0; i < numPlanes; i++) {
- R_ChopPolyBehindPlane( numClipPoints, clipPoints[pingPong],
- &numClipPoints, clipPoints[!pingPong],
- normals[i], dists[i], 0.5 );
+ R_ChopPolyBehindPlane(numClipPoints, clipPoints[pingPong],
+ &numClipPoints, clipPoints[!pingPong],
+ normals[i], dists[i], 0.5);
pingPong ^= 1;
- if ( numClipPoints == 0 ) {
+ if (numClipPoints == 0) {
break;
}
}
// completely clipped away?
- if ( numClipPoints == 0 ) {
+ if (numClipPoints == 0) {
return;
}
// add this fragment to the returned list
- if ( numClipPoints + ( *returnedPoints ) > maxPoints ) {
+ if (numClipPoints + (*returnedPoints) > maxPoints) {
return; // not enough space for this polygon
}
/*
@@ -259,16 +269,16 @@ void R_AddMarkFragments( int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_PO
if (i < numClipPoints) return;
*/
- mf = fragmentBuffer + ( *returnedFragments );
- mf->firstPoint = ( *returnedPoints );
+ mf = fragmentBuffer + (*returnedFragments);
+ mf->firstPoint = (*returnedPoints);
mf->numPoints = numClipPoints;
//memcpy( pointBuffer + (*returnedPoints) * 3, clipPoints[pingPong], numClipPoints * sizeof(vec3_t) );
- for ( i = 0; i < numClipPoints; i++ ) {
- VectorCopy( clipPoints[pingPong][i], (float *)pointBuffer + 5 * ( *returnedPoints + i ) );
+ for (i = 0; i < numClipPoints; i++) {
+ VectorCopy(clipPoints[pingPong][i], (float*)pointBuffer + 5 * (*returnedPoints + i));
}
- ( *returnedPoints ) += numClipPoints;
- ( *returnedFragments )++;
+ (*returnedPoints) += numClipPoints;
+ (*returnedFragments)++;
}
/*
@@ -277,11 +287,11 @@ R_OldMarkFragments
=================
*/
-int R_OldMarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
- int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) {
+int R_OldMarkFragments(int numPoints, const vec3_t* points, const vec3_t projection,
+ int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer) {
int numsurfaces, numPlanes;
int i, j, k, m, n;
- surfaceType_t *surfaces[64];
+ surfaceType_t* surfaces[64];
vec3_t mins, maxs;
int returnedFragments;
int returnedPoints;
@@ -289,68 +299,68 @@ int R_OldMarkFragments( int numPoints, const vec3_t *points, const vec3_t projec
float dists[MAX_VERTS_ON_POLY + 2];
vec3_t clipPoints[2][MAX_VERTS_ON_POLY];
int numClipPoints;
- float *v;
- srfSurfaceFace_t *surf;
- srfGridMesh_t *cv;
- drawVert_t *dv;
+ float* v;
+ srfSurfaceFace_t* surf;
+ srfGridMesh_t* cv;
+ drawVert_t* dv;
vec3_t normal;
vec3_t projectionDir;
vec3_t v1, v2;
- int *indexes;
+ int* indexes;
//increment view count for double check prevention
tr.viewCount++;
//
- VectorNormalize2( projection, projectionDir );
+ VectorNormalize2(projection, projectionDir);
// find all the brushes that are to be considered
- ClearBounds( mins, maxs );
- for ( i = 0 ; i < numPoints ; i++ ) {
+ ClearBounds(mins, maxs);
+ for (i = 0; i < numPoints; i++) {
vec3_t temp;
- AddPointToBounds( points[i], mins, maxs );
- VectorAdd( points[i], projection, temp );
- AddPointToBounds( temp, mins, maxs );
+ AddPointToBounds(points[i], mins, maxs);
+ VectorAdd(points[i], projection, temp);
+ AddPointToBounds(temp, mins, maxs);
// make sure we get all the leafs (also the one(s) in front of the hit surface)
- VectorMA( points[i], -20, projectionDir, temp );
- AddPointToBounds( temp, mins, maxs );
+ VectorMA(points[i], -20, projectionDir, temp);
+ AddPointToBounds(temp, mins, maxs);
}
- if ( numPoints > MAX_VERTS_ON_POLY ) {
+ if (numPoints > MAX_VERTS_ON_POLY) {
numPoints = MAX_VERTS_ON_POLY;
}
// create the bounding planes for the to be projected polygon
- for ( i = 0 ; i < numPoints ; i++ ) {
- VectorSubtract( points[( i + 1 ) % numPoints], points[i], v1 );
- VectorAdd( points[i], projection, v2 );
- VectorSubtract( points[i], v2, v2 );
- CrossProduct( v1, v2, normals[i] );
- VectorNormalizeFast( normals[i] );
- dists[i] = DotProduct( normals[i], points[i] );
+ for (i = 0; i < numPoints; i++) {
+ VectorSubtract(points[(i + 1) % numPoints], points[i], v1);
+ VectorAdd(points[i], projection, v2);
+ VectorSubtract(points[i], v2, v2);
+ CrossProduct(v1, v2, normals[i]);
+ VectorNormalizeFast(normals[i]);
+ dists[i] = DotProduct(normals[i], points[i]);
}
// add near and far clipping planes for projection
- VectorCopy( projectionDir, normals[numPoints] );
- dists[numPoints] = DotProduct( normals[numPoints], points[0] ) - 32;
- VectorCopy( projectionDir, normals[numPoints + 1] );
- VectorInverse( normals[numPoints + 1] );
- dists[numPoints + 1] = DotProduct( normals[numPoints + 1], points[0] ) - 20;
+ VectorCopy(projectionDir, normals[numPoints]);
+ dists[numPoints] = DotProduct(normals[numPoints], points[0]) - 32;
+ VectorCopy(projectionDir, normals[numPoints + 1]);
+ VectorInverse(normals[numPoints + 1]);
+ dists[numPoints + 1] = DotProduct(normals[numPoints + 1], points[0]) - 20;
numPlanes = numPoints + 2;
numsurfaces = 0;
- R_BoxSurfaces_r( tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir );
+ R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir);
//assert(numsurfaces <= 64);
//assert(numsurfaces != 64);
returnedPoints = 0;
returnedFragments = 0;
- for ( i = 0 ; i < numsurfaces ; i++ ) {
+ for (i = 0; i < numsurfaces; i++) {
- if ( *surfaces[i] == SF_GRID ) {
+ if (*surfaces[i] == SF_GRID) {
- cv = (srfGridMesh_t *) surfaces[i];
- for ( m = 0 ; m < cv->height - 1 ; m++ ) {
- for ( n = 0 ; n < cv->width - 1 ; n++ ) {
+ cv = (srfGridMesh_t*)surfaces[i];
+ for (m = 0; m < cv->height - 1; m++) {
+ for (n = 0; n < cv->width - 1; n++) {
// We triangulate the grid and chop all triangles within
// the bounding planes of the to be projected polygon.
// LOD is not taken into account, not such a big deal though.
@@ -376,60 +386,61 @@ int R_OldMarkFragments( int numPoints, const vec3_t *points, const vec3_t projec
dv = cv->verts + m * cv->width + n;
- VectorCopy( dv[0].xyz, clipPoints[0][0] );
- VectorMA( clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0] );
- VectorCopy( dv[cv->width].xyz, clipPoints[0][1] );
- VectorMA( clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1] );
- VectorCopy( dv[1].xyz, clipPoints[0][2] );
- VectorMA( clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2] );
+ VectorCopy(dv[0].xyz, clipPoints[0][0]);
+ VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
+ VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
+ VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
+ VectorCopy(dv[1].xyz, clipPoints[0][2]);
+ VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
// check the normal of this triangle
- VectorSubtract( clipPoints[0][0], clipPoints[0][1], v1 );
- VectorSubtract( clipPoints[0][2], clipPoints[0][1], v2 );
- CrossProduct( v1, v2, normal );
- VectorNormalizeFast( normal );
- if ( DotProduct( normal, projectionDir ) < -0.1 ) {
+ VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
+ VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
+ CrossProduct(v1, v2, normal);
+ VectorNormalizeFast(normal);
+ if (DotProduct(normal, projectionDir) < -0.1) {
// add the fragments of this triangle
- R_AddMarkFragments( numClipPoints, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs );
+ R_AddMarkFragments(numClipPoints, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
- if ( returnedFragments == maxFragments ) {
+ if (returnedFragments == maxFragments) {
return returnedFragments; // not enough space for more fragments
}
}
- VectorCopy( dv[1].xyz, clipPoints[0][0] );
- VectorMA( clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0] );
- VectorCopy( dv[cv->width].xyz, clipPoints[0][1] );
- VectorMA( clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1] );
- VectorCopy( dv[cv->width + 1].xyz, clipPoints[0][2] );
- VectorMA( clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2] );
+ VectorCopy(dv[1].xyz, clipPoints[0][0]);
+ VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
+ VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
+ VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
+ VectorCopy(dv[cv->width + 1].xyz, clipPoints[0][2]);
+ VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2]);
// check the normal of this triangle
- VectorSubtract( clipPoints[0][0], clipPoints[0][1], v1 );
- VectorSubtract( clipPoints[0][2], clipPoints[0][1], v2 );
- CrossProduct( v1, v2, normal );
- VectorNormalizeFast( normal );
- if ( DotProduct( normal, projectionDir ) < -0.05 ) {
+ VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
+ VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
+ CrossProduct(v1, v2, normal);
+ VectorNormalizeFast(normal);
+ if (DotProduct(normal, projectionDir) < -0.05) {
// add the fragments of this triangle
- R_AddMarkFragments( numClipPoints, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs );
+ R_AddMarkFragments(numClipPoints, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
- if ( returnedFragments == maxFragments ) {
+ if (returnedFragments == maxFragments) {
return returnedFragments; // not enough space for more fragments
}
}
}
}
- } else if ( *surfaces[i] == SF_FACE ) {
+ }
+ else if (*surfaces[i] == SF_FACE) {
- surf = ( srfSurfaceFace_t * ) surfaces[i];
+ surf = (srfSurfaceFace_t*)surfaces[i];
// check the normal of this face
- if ( DotProduct( surf->plane.normal, projectionDir ) > -0.5 ) {
+ if (DotProduct(surf->plane.normal, projectionDir) > -0.5) {
continue;
}
@@ -440,24 +451,80 @@ int R_OldMarkFragments( int numPoints, const vec3_t *points, const vec3_t projec
VectorNormalize(normal);
if (DotProduct(normal, projectionDir) > -0.5) continue;
*/
- indexes = ( int * )( (byte *)surf + surf->ofsIndices );
- for ( k = 0 ; k < surf->numIndices ; k += 3 ) {
- for ( j = 0 ; j < 3 ; j++ ) {
+ indexes = (int*)((byte*)surf + surf->ofsIndices);
+ for (k = 0; k < surf->numIndices; k += 3) {
+ for (j = 0; j < 3; j++) {
v = surf->points[0] + VERTEXSIZE * indexes[k + j];;
- VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
+ VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]);
+ }
+ // add the fragments of this face
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
+ if (returnedFragments == maxFragments) {
+ return returnedFragments; // not enough space for more fragments
+ }
+ }
+ continue;
+ }
+ // Arnout: projection on models (mainly for terrain though)
+ else if (*surfaces[i] == SF_TRIANGLES) {
+
+#if 0
+ srfTriangles2_t* cts;
+ cts = (srfTriangles2_t*)surfaces[i];
+
+ indexes = cts->indexes;
+ for (k = 0; k < cts->numIndexes; k += 3) {
+ for (j = 0; j < 3; j++) {
+ VectorMA(cts->xyz[indexes[k + j]].v, MARKER_OFFSET, cts->normal[indexes[k + j]].v, clipPoints[0][j]);
+ }
+ // add the fragments of this face
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
+
+ if (returnedFragments == maxFragments) {
+ return returnedFragments; // not enough space for more fragments
+ }
+ }
+ continue;
+#else
+ srfTriangles_t* cts;
+ cts = (srfTriangles_t*)surfaces[i];
+
+ /*
+ VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
+ VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
+ CrossProduct(v1, v2, normal);
+ VectorNormalize(normal);
+ if (DotProduct(normal, projectionDir) > -0.5) continue;
+ */
+ indexes = cts->indexes;
+ for (k = 0; k < cts->numIndexes; k += 3) {
+ for (j = 0; j < 3; j++) {
+ v = cts->verts[indexes[k + j]].xyz;
+ VectorMA(v, MARKER_OFFSET, cts->verts[indexes[k + j]].normal, clipPoints[0][j]);
}
// add the fragments of this face
- R_AddMarkFragments( 3, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs );
- if ( returnedFragments == maxFragments ) {
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
+
+ if (returnedFragments == maxFragments) {
return returnedFragments; // not enough space for more fragments
}
}
continue;
- } else {
+#endif
+ }
+ else {
// ignore all other world surfaces
// might be cool to also project polygons on a triangle soup
// however this will probably create huge amounts of extra polys
@@ -474,11 +541,11 @@ R_MarkFragments
=================
*/
-int R_MarkFragments( int orientation, const vec3_t *points, const vec3_t projection,
- int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) {
+int R_MarkFragments(int orientation, const vec3_t* points, const vec3_t projection,
+ int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer) {
int numsurfaces, numPlanes;
int i, j, k, m, n;
- surfaceType_t *surfaces[4096];
+ surfaceType_t* surfaces[4096];
vec3_t mins, maxs;
int returnedFragments;
int returnedPoints;
@@ -486,14 +553,14 @@ int R_MarkFragments( int orientation, const vec3_t *points, const vec3_t project
float dists[MAX_VERTS_ON_POLY + 2];
vec3_t clipPoints[2][MAX_VERTS_ON_POLY];
int numClipPoints;
- float *v;
- srfSurfaceFace_t *surf;
- srfGridMesh_t *cv;
- drawVert_t *dv;
+ float* v;
+ srfSurfaceFace_t* surf;
+ srfGridMesh_t* cv;
+ drawVert_t* dv;
vec3_t normal;
vec3_t projectionDir;
vec3_t v1, v2;
- int *indexes;
+ int* indexes;
float radius;
vec3_t center; // center of original mark
//vec3_t bestCenter; // center point projected onto the closest surface
@@ -506,56 +573,56 @@ int R_MarkFragments( int orientation, const vec3_t *points, const vec3_t project
tr.viewCount++;
// RF, negative maxFragments means we want original mapping
- if ( maxFragments < 0 ) {
+ if (maxFragments < 0) {
maxFragments = -maxFragments;
//return R_OldMarkFragments( numPoints, points, projection, maxPoints, pointBuffer, maxFragments, fragmentBuffer );
oldMapping = qtrue;
}
- VectorClear( center );
- for ( i = 0 ; i < numPoints ; i++ ) {
- VectorAdd( points[i], center, center );
+ VectorClear(center);
+ for (i = 0; i < numPoints; i++) {
+ VectorAdd(points[i], center, center);
}
- VectorScale( center, 1.0 / numPoints, center );
+ VectorScale(center, 1.0 / numPoints, center);
//
- radius = VectorNormalize2( projection, projectionDir ) / 2.0;
+ radius = VectorNormalize2(projection, projectionDir) / 2.0;
bestdist = 0;
- VectorNegate( projectionDir, bestnormal );
+ VectorNegate(projectionDir, bestnormal);
// find all the brushes that are to be considered
- ClearBounds( mins, maxs );
- for ( i = 0 ; i < numPoints ; i++ ) {
+ ClearBounds(mins, maxs);
+ for (i = 0; i < numPoints; i++) {
vec3_t temp;
- AddPointToBounds( points[i], mins, maxs );
- VectorMA( points[i], 1 * ( 1 + oldMapping * radius * 4 ), projection, temp );
- AddPointToBounds( temp, mins, maxs );
+ AddPointToBounds(points[i], mins, maxs);
+ VectorMA(points[i], 1 * (1 + oldMapping * radius * 4), projection, temp);
+ AddPointToBounds(temp, mins, maxs);
// make sure we get all the leafs (also the one(s) in front of the hit surface)
- VectorMA( points[i], -20 * ( 1.0 + (float)oldMapping * ( radius / 20.0 ) * 4 ), projectionDir, temp );
- AddPointToBounds( temp, mins, maxs );
+ VectorMA(points[i], -20 * (1.0 + (float)oldMapping * (radius / 20.0) * 4), projectionDir, temp);
+ AddPointToBounds(temp, mins, maxs);
}
- if ( numPoints > MAX_VERTS_ON_POLY ) {
+ if (numPoints > MAX_VERTS_ON_POLY) {
numPoints = MAX_VERTS_ON_POLY;
}
// create the bounding planes for the to be projected polygon
- for ( i = 0 ; i < numPoints ; i++ ) {
- VectorSubtract( points[( i + 1 ) % numPoints], points[i], v1 );
- VectorAdd( points[i], projection, v2 );
- VectorSubtract( points[i], v2, v2 );
- CrossProduct( v1, v2, normals[i] );
- VectorNormalize( normals[i] );
- dists[i] = DotProduct( normals[i], points[i] );
+ for (i = 0; i < numPoints; i++) {
+ VectorSubtract(points[(i + 1) % numPoints], points[i], v1);
+ VectorAdd(points[i], projection, v2);
+ VectorSubtract(points[i], v2, v2);
+ CrossProduct(v1, v2, normals[i]);
+ VectorNormalize(normals[i]);
+ dists[i] = DotProduct(normals[i], points[i]);
}
// add near and far clipping planes for projection
- VectorCopy( projectionDir, normals[numPoints] );
- dists[numPoints] = DotProduct( normals[numPoints], points[0] ) - radius * ( 1 + oldMapping * 10 );
- VectorCopy( projectionDir, normals[numPoints + 1] );
- VectorInverse( normals[numPoints + 1] );
- dists[numPoints + 1] = DotProduct( normals[numPoints + 1], points[0] ) - radius * ( 1 + oldMapping * 10 );
+ VectorCopy(projectionDir, normals[numPoints]);
+ dists[numPoints] = DotProduct(normals[numPoints], points[0]) - radius * (1 + oldMapping * 10);
+ VectorCopy(projectionDir, normals[numPoints + 1]);
+ VectorInverse(normals[numPoints + 1]);
+ dists[numPoints + 1] = DotProduct(normals[numPoints + 1], points[0]) - radius * (1 + oldMapping * 10);
numPlanes = numPoints + 2;
numsurfaces = 0;
- R_BoxSurfaces_r( tr.world->nodes, mins, maxs, surfaces, 4096, &numsurfaces, projectionDir );
+ R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 4096, &numsurfaces, projectionDir);
//assert(numsurfaces <= 64);
//assert(numsurfaces != 64);
@@ -565,42 +632,42 @@ int R_MarkFragments( int orientation, const vec3_t *points, const vec3_t project
returnedFragments = 0;
// find the closest surface to center the decal there, and wrap around other surfaces
- if ( !oldMapping ) {
-/*
+ if (!oldMapping) {
+ /*
for ( i = 0 ; i < numsurfaces ; i++ ) {
- if (*surfaces[i] == SF_FACE) {
- surf = ( srfSurfaceFace_t * ) surfaces[i];
- // Ridah, check if this is the closest surface
- dot = DotProduct( center, surf->plane.normal );
- dot -= surf->plane.dist;
- if (!bestdist) {
- if (dot < 0)
- bestdist = fabs(dot) + 1000; // avoid this surface, since the point is behind it
- else
- bestdist = dot;
- VectorCopy( surf->plane.normal, bestnormal );
- VectorMA( center, -dot, surf->plane.normal, bestCenter );
- } else if (dot >= 0 && dot < bestdist) {
- bestdist = dot;
- VectorCopy( surf->plane.normal, bestnormal );
- VectorMA( center, -dot, surf->plane.normal, bestCenter );
- }
- }
+ if (*surfaces[i] == SF_FACE) {
+ surf = ( srfSurfaceFace_t * ) surfaces[i];
+ // Ridah, check if this is the closest surface
+ dot = DotProduct( center, surf->plane.normal );
+ dot -= surf->plane.dist;
+ if (!bestdist) {
+ if (dot < 0)
+ bestdist = fabs(dot) + 1000; // avoid this surface, since the point is behind it
+ else
+ bestdist = dot;
+ VectorCopy( surf->plane.normal, bestnormal );
+ VectorMA( center, -dot, surf->plane.normal, bestCenter );
+ } else if (dot >= 0 && dot < bestdist) {
+ bestdist = dot;
+ VectorCopy( surf->plane.normal, bestnormal );
+ VectorMA( center, -dot, surf->plane.normal, bestCenter );
+ }
+ }
}
// bestCenter is now the real center
VectorCopy( bestCenter, center );
-Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bestnormal[2] );
-*/
- VectorNegate( bestnormal, bestnormal );
+ Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bestnormal[2] );
+ */
+ VectorNegate(bestnormal, bestnormal);
}
- for ( i = 0 ; i < numsurfaces ; i++ ) {
+ for (i = 0; i < numsurfaces; i++) {
- if ( *surfaces[i] == SF_GRID ) {
+ if (*surfaces[i] == SF_GRID) {
- cv = (srfGridMesh_t *) surfaces[i];
- for ( m = 0 ; m < cv->height - 1 ; m++ ) {
- for ( n = 0 ; n < cv->width - 1 ; n++ ) {
+ cv = (srfGridMesh_t*)surfaces[i];
+ for (m = 0; m < cv->height - 1; m++) {
+ for (n = 0; n < cv->width - 1; n++) {
// We triangulate the grid and chop all triangles within
// the bounding planes of the to be projected polygon.
// LOD is not taken into account, not such a big deal though.
@@ -626,57 +693,58 @@ Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bes
dv = cv->verts + m * cv->width + n;
- VectorCopy( dv[0].xyz, clipPoints[0][0] );
- VectorMA( clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0] );
- VectorCopy( dv[cv->width].xyz, clipPoints[0][1] );
- VectorMA( clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1] );
- VectorCopy( dv[1].xyz, clipPoints[0][2] );
- VectorMA( clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2] );
+ VectorCopy(dv[0].xyz, clipPoints[0][0]);
+ VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
+ VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
+ VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
+ VectorCopy(dv[1].xyz, clipPoints[0][2]);
+ VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
// check the normal of this triangle
- VectorSubtract( clipPoints[0][0], clipPoints[0][1], v1 );
- VectorSubtract( clipPoints[0][2], clipPoints[0][1], v2 );
- CrossProduct( v1, v2, normal );
- VectorNormalize( normal );
- if ( DotProduct( normal, projectionDir ) < -0.1 ) {
+ VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
+ VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
+ CrossProduct(v1, v2, normal);
+ VectorNormalize(normal);
+ if (DotProduct(normal, projectionDir) < -0.1) {
// add the fragments of this triangle
- R_AddMarkFragments( numClipPoints, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs );
+ R_AddMarkFragments(numClipPoints, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
- if ( returnedFragments == maxFragments ) {
+ if (returnedFragments == maxFragments) {
return returnedFragments; // not enough space for more fragments
}
}
- VectorCopy( dv[1].xyz, clipPoints[0][0] );
- VectorMA( clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0] );
- VectorCopy( dv[cv->width].xyz, clipPoints[0][1] );
- VectorMA( clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1] );
- VectorCopy( dv[cv->width + 1].xyz, clipPoints[0][2] );
- VectorMA( clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2] );
+ VectorCopy(dv[1].xyz, clipPoints[0][0]);
+ VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
+ VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
+ VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
+ VectorCopy(dv[cv->width + 1].xyz, clipPoints[0][2]);
+ VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2]);
// check the normal of this triangle
- VectorSubtract( clipPoints[0][0], clipPoints[0][1], v1 );
- VectorSubtract( clipPoints[0][2], clipPoints[0][1], v2 );
- CrossProduct( v1, v2, normal );
- VectorNormalize( normal );
- if ( DotProduct( normal, projectionDir ) < -0.05 ) {
+ VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
+ VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
+ CrossProduct(v1, v2, normal);
+ VectorNormalize(normal);
+ if (DotProduct(normal, projectionDir) < -0.05) {
// add the fragments of this triangle
- R_AddMarkFragments( numClipPoints, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs );
+ R_AddMarkFragments(numClipPoints, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
- if ( returnedFragments == maxFragments ) {
+ if (returnedFragments == maxFragments) {
return returnedFragments; // not enough space for more fragments
}
}
}
}
- } else if ( *surfaces[i] == SF_FACE ) {
- extern float VectorDistance( vec3_t v1, vec3_t v2 );
+ }
+ else if (*surfaces[i] == SF_FACE) {
+ extern float VectorDistance(vec3_t v1, vec3_t v2);
vec3_t axis[3];
float texCoordScale, dot;
vec3_t originalPoints[4];
@@ -687,129 +755,297 @@ Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bes
vec3_t lnormals[MAX_VERTS_ON_POLY + 2];
float ldists[MAX_VERTS_ON_POLY + 2];
vec3_t lmins, lmaxs;
+ vec3_t surfnormal;
- surf = ( srfSurfaceFace_t * ) surfaces[i];
+ surf = (srfSurfaceFace_t*)surfaces[i];
+
+ if (surf->plane.type == PLANE_NON_PLANAR) {
+ VectorCopy(bestnormal, surfnormal);
+ }
+ else {
+ VectorCopy(surf->plane.normal, surfnormal);
+ }
- if ( !oldMapping ) {
+ if (!oldMapping) {
// Ridah, create a new clip box such that this decal surface is mapped onto
// the current surface without distortion. To find the center of the new clip box,
// we project the center of the original impact center out along the projection vector,
// onto the current surface
- // find the center of the new decal
- dot = DotProduct( center, surf->plane.normal );
- dot -= surf->plane.dist;
- // check the normal of this face
- if ( dot < -epsilon && DotProduct( surf->plane.normal, projectionDir ) >= 0.01 ) {
- continue;
- } else if ( fabs( dot ) > radius ) {
- continue;
+ if (surf->plane.type == PLANE_NON_PLANAR) {
+ VectorCopy(center, newCenter);
+ }
+ else {
+ // find the center of the new decal
+ dot = DotProduct(center, surfnormal);
+ dot -= surf->plane.dist;
+ // check the normal of this face
+ if (dot < -epsilon && DotProduct(surfnormal, projectionDir) >= 0.01) {
+ continue;
+ }
+ else if (fabs(dot) > radius) {
+ continue;
+ }
+ // if the impact point is behind the surface, subtract the projection, otherwise add it
+ VectorMA(center, -dot, bestnormal, newCenter);
}
- // if the impact point is behind the surface, subtract the projection, otherwise add it
- VectorMA( center, -dot, bestnormal, newCenter );
// recalc dot from the offset position
- dot = DotProduct( newCenter, surf->plane.normal );
+ dot = DotProduct(newCenter, surfnormal);
dot -= surf->plane.dist;
- VectorMA( newCenter, -dot, surf->plane.normal, newCenter );
+ VectorMA(newCenter, -dot, surfnormal, newCenter);
- VectorMA( newCenter, MARKER_OFFSET, surf->plane.normal, newCenter );
+ VectorMA(newCenter, MARKER_OFFSET, surfnormal, newCenter);
// create the texture axis
- VectorNormalize2( surf->plane.normal, axis[0] );
- PerpendicularVector( axis[1], axis[0] );
- RotatePointAroundVector( axis[2], axis[0], axis[1], (float)orientation );
- CrossProduct( axis[0], axis[2], axis[1] );
+ VectorNormalize2(surfnormal, axis[0]);
+ PerpendicularVector(axis[1], axis[0]);
+ RotatePointAroundVector(axis[2], axis[0], axis[1], (float)orientation);
+ CrossProduct(axis[0], axis[2], axis[1]);
texCoordScale = 0.5 * 1.0 / radius;
// create the full polygon
- for ( j = 0 ; j < 3 ; j++ ) {
+ for (j = 0; j < 3; j++) {
originalPoints[0][j] = newCenter[j] - radius * axis[1][j] - radius * axis[2][j];
originalPoints[1][j] = newCenter[j] + radius * axis[1][j] - radius * axis[2][j];
originalPoints[2][j] = newCenter[j] + radius * axis[1][j] + radius * axis[2][j];
originalPoints[3][j] = newCenter[j] - radius * axis[1][j] + radius * axis[2][j];
}
- ClearBounds( lmins, lmaxs );
+ ClearBounds(lmins, lmaxs);
// create the bounding planes for the to be projected polygon
- for ( j = 0 ; j < 4 ; j++ ) {
- AddPointToBounds( originalPoints[j], lmins, lmaxs );
-
- VectorSubtract( originalPoints[( j + 1 ) % numPoints], originalPoints[j], v1 );
- VectorSubtract( originalPoints[j], surf->plane.normal, v2 );
- VectorSubtract( originalPoints[j], v2, v2 );
- CrossProduct( v1, v2, lnormals[j] );
- VectorNormalize( lnormals[j] );
- ldists[j] = DotProduct( lnormals[j], originalPoints[j] );
+ for (j = 0; j < 4; j++) {
+ AddPointToBounds(originalPoints[j], lmins, lmaxs);
+
+ VectorSubtract(originalPoints[(j + 1) % numPoints], originalPoints[j], v1);
+ VectorSubtract(originalPoints[j], surfnormal, v2);
+ VectorSubtract(originalPoints[j], v2, v2);
+ CrossProduct(v1, v2, lnormals[j]);
+ VectorNormalize(lnormals[j]);
+ ldists[j] = DotProduct(lnormals[j], originalPoints[j]);
}
numPlanes = numPoints;
// done.
- indexes = ( int * )( (byte *)surf + surf->ofsIndices );
- for ( k = 0 ; k < surf->numIndices ; k += 3 ) {
- for ( j = 0 ; j < 3 ; j++ ) {
+ indexes = (int*)((byte*)surf + surf->ofsIndices);
+ for (k = 0; k < surf->numIndices; k += 3) {
+ for (j = 0; j < 3; j++) {
v = surf->points[0] + VERTEXSIZE * indexes[k + j];
- VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
+ VectorMA(v, MARKER_OFFSET, surfnormal, clipPoints[0][j]);
}
oldNumPoints = returnedPoints;
// add the fragments of this face
- R_AddMarkFragments( 3, clipPoints,
- numPlanes, lnormals, ldists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, lmins, lmaxs );
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, lnormals, ldists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, lmins, lmaxs);
- if ( oldNumPoints != returnedPoints ) {
+ if (oldNumPoints != returnedPoints) {
// flag this surface as already having computed ST's
fragmentBuffer[returnedFragments - 1].numPoints *= -1;
// Ridah, calculate ST's
- for ( j = 0 ; j < ( returnedPoints - oldNumPoints ) ; j++ ) {
- VectorSubtract( (float *)pointBuffer + 5 * ( oldNumPoints + j ), newCenter, delta );
- *( (float *)pointBuffer + 5 * ( oldNumPoints + j ) + 3 ) = 0.5 + DotProduct( delta, axis[1] ) * texCoordScale;
- *( (float *)pointBuffer + 5 * ( oldNumPoints + j ) + 4 ) = 0.5 + DotProduct( delta, axis[2] ) * texCoordScale;
+ for (j = 0; j < (returnedPoints - oldNumPoints); j++) {
+ VectorSubtract((float*)pointBuffer + 5 * (oldNumPoints + j), newCenter, delta);
+ *((float*)pointBuffer + 5 * (oldNumPoints + j) + 3) = 0.5 + DotProduct(delta, axis[1]) * texCoordScale;
+ *((float*)pointBuffer + 5 * (oldNumPoints + j) + 4) = 0.5 + DotProduct(delta, axis[2]) * texCoordScale;
}
}
- if ( returnedFragments == maxFragments ) {
+ if (returnedFragments == maxFragments) {
return returnedFragments; // not enough space for more fragments
}
}
- } else { // old mapping
+ }
+ else { // old mapping
// check the normal of this face
+ // Arnout: wolf code was disabled, but differs from q3 code (maybe wolf one was broken and fixed in q3?):
+ /* if (DotProduct(surf->plane.normal, projectionDir) > -0.5) {
+ continue;
+ }*/
+
+ // Wolf code:
//if (DotProduct(surf->plane.normal, projectionDir) > 0.0) {
// continue;
//}
- indexes = ( int * )( (byte *)surf + surf->ofsIndices );
- for ( k = 0 ; k < surf->numIndices ; k += 3 ) {
- for ( j = 0 ; j < 3 ; j++ ) {
+ indexes = (int*)((byte*)surf + surf->ofsIndices);
+ for (k = 0; k < surf->numIndices; k += 3) {
+ for (j = 0; j < 3; j++) {
v = surf->points[0] + VERTEXSIZE * indexes[k + j];;
- VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
+ VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]);
+ }
+ // add the fragments of this face
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
+ if (returnedFragments == maxFragments) {
+ return returnedFragments; // not enough space for more fragments
+ }
+ }
+ }
+
+ continue;
+ }
+ // Arnout: projection on models (mainly for terrain though)
+ else if (*surfaces[i] == SF_TRIANGLES) {
+
+#if 0
+ // duplicated so we don't mess with the original clips for the curved surfaces
+ vec3_t lnormals[MAX_VERTS_ON_POLY + 2];
+ float ldists[MAX_VERTS_ON_POLY + 2];
+
+ srfTriangles2_t* cts;
+ cts = (srfTriangles2_t*)surfaces[i];
+ if (!oldMapping) {
+ for (k = 0; k < numPoints; k++) {
+ VectorNegate(normals[k], lnormals[k]);
+ ldists[k] = -dists[k];
+ }
+ VectorNegate(normals[numPoints], lnormals[numPoints]);
+ ldists[numPoints] = dists[numPoints + 1];
+ VectorNegate(normals[numPoints + 1], lnormals[numPoints + 1]);
+ ldists[numPoints + 1] = dists[numPoints];
+
+ indexes = cts->indexes;
+ for (k = 0; k < cts->numIndexes; k += 3) {
+ for (j = 0; j < 3; j++) {
+ VectorMA(cts->xyz[indexes[k + j]].v, MARKER_OFFSET, cts->normal[indexes[k + j]].v, clipPoints[0][j]);
+ }
+ // add the fragments of this face
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, lnormals, ldists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
+
+ if (returnedFragments == maxFragments) {
+ return returnedFragments; // not enough space for more fragments
+ }
+ }
+ }
+ else {
+
+ indexes = cts->indexes;
+ for (k = 0; k < cts->numIndexes; k += 3) {
+ for (j = 0; j < 3; j++) {
+ VectorMA(cts->xyz[indexes[k + j]].v, MARKER_OFFSET, cts->normal[indexes[k + j]].v, clipPoints[0][j]);
+ }
+ // add the fragments of this face
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
+
+ if (returnedFragments == maxFragments) {
+ return returnedFragments; // not enough space for more fragments
+ }
+ }
+ }
+
+ continue;
+#else
+ // duplicated so we don't mess with the original clips for the curved surfaces
+ vec3_t lnormals[MAX_VERTS_ON_POLY + 2];
+ float ldists[MAX_VERTS_ON_POLY + 2];
+ //vec3_t lprojection, lprojectionDir;
+
+ srfTriangles_t* cts;
+ cts = (srfTriangles_t*)surfaces[i];
+ if (!oldMapping) {
+ /*VectorNegate( projection, lprojection );
+ VectorNormalize2( lprojection, lprojectionDir );
+
+ radius = VectorNormalize2( lprojection, lprojectionDir ) / 2.0;
+
+ // create the bounding planes for the to be projected polygon
+ for ( k = 0 ; k < numPoints ; k++ ) {
+ VectorSubtract(points[(k+1)%numPoints], points[k], v1);
+ VectorAdd(points[k], lprojection, v2);
+ VectorSubtract(points[k], v2, v2);
+ CrossProduct(v1, v2, lnormals[k]);
+ VectorNormalizeFast(lnormals[k]);
+ ldists[k] = DotProduct(lnormals[k], points[k]);
+ }
+
+ // add near and far clipping planes for projection
+ VectorCopy(lprojectionDir, lnormals[numPoints]);
+ ldists[numPoints] = DotProduct(lnormals[numPoints], points[0]) - radius;
+ VectorCopy(lprojectionDir, lnormals[numPoints+1]);
+ VectorInverse(lnormals[numPoints+1]);
+ ldists[numPoints+1] = DotProduct(lnormals[numPoints+1], points[0]) - radius;*/
+
+ for (k = 0; k < numPoints; k++) {
+ VectorNegate(normals[k], lnormals[k]);
+ ldists[k] = -dists[k];
+ }
+ VectorNegate(normals[numPoints], lnormals[numPoints]);
+ ldists[numPoints] = dists[numPoints + 1];
+ VectorNegate(normals[numPoints + 1], lnormals[numPoints + 1]);
+ ldists[numPoints + 1] = dists[numPoints];
+
+ indexes = cts->indexes;
+ for (k = 0; k < cts->numIndexes; k += 3) {
+ for (j = 0; j < 3; j++) {
+ v = cts->verts[indexes[k + j]].xyz;
+ VectorMA(v, MARKER_OFFSET, cts->verts[indexes[k + j]].normal, clipPoints[0][j]);
}
// add the fragments of this face
- R_AddMarkFragments( 3, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs );
- if ( returnedFragments == maxFragments ) {
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, lnormals, ldists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
+
+ if (returnedFragments == maxFragments) {
return returnedFragments; // not enough space for more fragments
}
}
+ }
+ else {
+
+ /*
+ VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
+ VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
+ CrossProduct(v1, v2, normal);
+ VectorNormalize(normal);
+ if (DotProduct(normal, projectionDir) > -0.5) continue;
+ */
+ indexes = cts->indexes;
+ for (k = 0; k < cts->numIndexes; k += 3) {
+ for (j = 0; j < 3; j++) {
+ v = cts->verts[indexes[k + j]].xyz;
+ VectorMA(v, MARKER_OFFSET, cts->verts[indexes[k + j]].normal, clipPoints[0][j]);
+ }
+ // add the fragments of this face
+ R_AddMarkFragments(3, clipPoints,
+ numPlanes, normals, dists,
+ maxPoints, pointBuffer,
+ maxFragments, fragmentBuffer,
+ &returnedPoints, &returnedFragments, mins, maxs);
+ if (returnedFragments == maxFragments) {
+ return returnedFragments; // not enough space for more fragments
+ }
+ }
}
continue;
- } else {
+#endif // 1
+ }
+ else {
// ignore all other world surfaces
// might be cool to also project polygons on a triangle soup
// however this will probably create huge amounts of extra polys
@@ -819,4 +1055,3 @@ Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bes
}
return returnedFragments;
}
-
diff --git a/src/renderer/tr_shade.c b/src/renderer/tr_shade.c
index 6a291fbb..8e84350b 100644
--- a/src/renderer/tr_shade.c
+++ b/src/renderer/tr_shade.c
@@ -425,7 +425,7 @@ static void ProjectDlightTexture( void ) {
float *texCoords;
byte *colors;
byte clipBits[SHADER_MAX_VERTEXES];
- MAC_STATIC float texCoordsArray[SHADER_MAX_VERTEXES][2];
+ float texCoordsArray[SHADER_MAX_VERTEXES][2];
byte colorArray[SHADER_MAX_VERTEXES][4];
unsigned hitIndexes[SHADER_MAX_INDEXES];
int numIndexes;
@@ -676,7 +676,13 @@ static void RB_FogPass( void ) {
fog_t *fog;
int i;
- if ( tr.refdef.rdflags & RDF_SNOOPERVIEW ) { // no fog pass in snooper
+ // no fog pass in snooper
+ if (tr.refdef.rdflags & RDF_SNOOPERVIEW || tess.shader->noFog || !r_wolffog->integer) {
+ return;
+ }
+
+ // ydnar: no world, no fogging
+ if (backEnd.refdef.rdflags & RDF_NOWORLDMODEL) {
return;
}
@@ -1152,11 +1158,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) {
//
// set state
//
- if ( pStage->bundle[0].vertexLightmap && ( ( r_vertexLight->integer && !r_uiFullScreen->integer ) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) {
- GL_Bind( tr.whiteImage );
- } else {
- R_BindAnimatedImage( &pStage->bundle[0] );
- }
+ R_BindAnimatedImage(&pStage->bundle[0]);
// Ridah, per stage fogging (detail textures)
if ( tess.shader->noFog && pStage->isFogged ) {
@@ -1202,10 +1204,20 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) {
tess.svars.colors[i][3] *= alphaval;
}
}
- } else {
- GL_State( pStage->stateBits );
}
//----(SA) end
+ // ydnar: lightmap stages should be GL_ONE GL_ZERO so they can be seen
+ else if (r_lightmap->integer && (pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap)) {
+ unsigned int stateBits;
+
+
+ stateBits = (pStage->stateBits & ~(GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS)) |
+ (GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO);
+ GL_State(stateBits);
+ }
+ else {
+ GL_State( pStage->stateBits );
+ }
//
// draw
diff --git a/src/renderer/tr_shade_calc.c b/src/renderer/tr_shade_calc.c
index 26bdfdd2..f52fe18e 100644
--- a/src/renderer/tr_shade_calc.c
+++ b/src/renderer/tr_shade_calc.c
@@ -666,7 +666,7 @@ void RB_CalcColorFromEntity( unsigned char *dstColors ) {
void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ) {
int i;
int *pColors = ( int * ) dstColors;
- unsigned char invModulate[3];
+ unsigned char invModulate[4]; // L0 - ioquake static buffer overflow fix.
int c;
if ( !backEnd.currentEntity ) {
diff --git a/src/renderer/tr_shader.c b/src/renderer/tr_shader.c
index 2cd8c2c9..83fe6218 100644
--- a/src/renderer/tr_shader.c
+++ b/src/renderer/tr_shader.c
@@ -1150,23 +1150,29 @@ skyParms
===============
*/
static void ParseSkyParms( char **text ) {
- char *token;
- static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
+ char* token;
+ static char* suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
char pathname[MAX_QPATH];
int i;
// outerbox
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 ) {
- ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
+ token = COM_ParseExt(text, qfalse);
+ if (token[0] == 0) {
+ ri.Printf(PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name);
return;
}
- if ( strcmp( token, "-" ) ) {
- for ( i = 0 ; i < 6 ; i++ ) {
- Com_sprintf( pathname, sizeof( pathname ), "%s_%s.tga"
- , token, suf[i] );
- shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_CLAMP );
- if ( !shader.sky.outerbox[i] ) {
+ if (strcmp(token, "-")) {
+ for (i = 0; i < 6; i++) {
+ Com_sprintf(pathname, sizeof(pathname), "%s_%s.tga"
+ , token, suf[i]);
+ // L0 - ioquake ATI skybox fix
+#ifdef GL_CLAMP_TO_EDGE
+ shader.sky.outerbox[i] = R_FindImageFile((char*)pathname, qtrue, qtrue, GL_CLAMP_TO_EDGE);
+#else
+ shader.sky.outerbox[i] = R_FindImageFile((char*)pathname, qtrue, qtrue, GL_CLAMP);
+#endif
+ // End
+ if (!shader.sky.outerbox[i]) {
shader.sky.outerbox[i] = tr.defaultImage;
}
}
@@ -1390,6 +1396,10 @@ static qboolean ParseShader( char **text ) {
}
// stage definition
else if ( token[0] == '{' ) {
+ if (s >= MAX_SHADER_STAGES) {
+ ri.Printf(PRINT_WARNING, "WARNING: too many stages in shader %s\n", shader.name);
+ return qfalse;
+ }
if ( !ParseStage( &stages[s], text ) ) {
return qfalse;
}
@@ -1533,7 +1543,7 @@ static qboolean ParseShader( char **text ) {
ri.Printf( PRINT_WARNING, "WARNING: missing shader name for 'sunshader'\n" );
continue;
}
- tr.sunShaderName = CopyString( token );
+ tr.sunShaderName = "sun";
}
//----(SA) added
else if ( !Q_stricmp( token, "lightgridmulamb" ) ) { // ambient multiplier for lightgrid
@@ -2340,7 +2350,7 @@ static shader_t *FinishShader( void ) {
shader.numUnfoggedPasses = stage;
// fogonly shaders don't have any normal passes
- if ( stage == 0 ) {
+ if (stage == 0 && !shader.isSky) {
shader.sort = SS_FOG;
}
@@ -2514,6 +2524,12 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag
lightmapIndex = LIGHTMAP_BY_VERTEX;
}
+ else if (lightmapIndex < LIGHTMAP_2D) {
+ // negative lightmap indexes cause stray pointers (think tr.lightmaps[lightmapIndex])
+ ri.Printf(PRINT_WARNING, "WARNING: shader '%s' has invalid lightmap index of %d\n", name, lightmapIndex);
+ lightmapIndex = LIGHTMAP_BY_VERTEX;
+ }
+
COM_StripExtension2( name, strippedName, sizeof( strippedName ) );
hash = generateHashValue( strippedName );
@@ -2521,25 +2537,6 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag
//
// see if the shader is already loaded
//
-#if 1
- for ( sh = hashTable[hash]; sh; sh = sh->next ) {
- // index by name
-
- // Ridah, modified this so we don't keep trying to load an invalid lightmap shader
-/*
- if ( sh->lightmapIndex == lightmapIndex &&
- !Q_stricmp(sh->name, strippedName)) {
- // match found
- return sh;
- }
-*/
- if ( ( ( sh->lightmapIndex == lightmapIndex ) || ( sh->lightmapIndex < 0 && lightmapIndex >= 0 ) ) &&
- !Q_stricmp( sh->name, strippedName ) ) {
- // match found
- return sh;
- }
- }
-#else
for ( sh = hashTable[hash]; sh; sh = sh->next ) {
// NOTE: if there was no shader or image available with the name strippedName
// then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
@@ -2551,7 +2548,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag
return sh;
}
}
-#endif
+
// make sure the render thread is stopped, because we are probably
// going to have to upload an image
@@ -2675,6 +2672,13 @@ qhandle_t RE_RegisterShaderFromImage( const char *name, int lightmapIndex, image
hash = generateHashValue( name );
+ // probably not necessary since this function
+ // only gets called from tr_font.c with lightmapIndex == LIGHTMAP_2D
+ // but better safe than sorry.
+ if (lightmapIndex >= tr.numLightmaps) {
+ lightmapIndex = LIGHTMAP_WHITEIMAGE;
+ }
+
//
// see if the shader is already loaded
//
@@ -3113,7 +3117,16 @@ static void CreateInternalShaders( void ) {
static void CreateExternalShaders( void ) {
tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue );
tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue );
-// tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue ); //----(SA) let sky shader set this
+ // Hack to make fogging work correctly on flares. Fog colors are calculated
+ // in tr_flare.c already.
+ if (!tr.flareShader->defaultShader) {
+ int index;
+
+ for (index = 0; index < tr.flareShader->numUnfoggedPasses; index++) {
+ tr.flareShader->stages[index]->adjustColorsForFog = ACFF_NONE;
+ tr.flareShader->stages[index]->stateBits |= GLS_DEPTHTEST_DISABLE;
+ }
+ }
tr.sunflareShader[0] = R_FindShader( "sunflare1", LIGHTMAP_NONE, qtrue );
tr.dlightShader = R_FindShader( "dlightshader", LIGHTMAP_NONE, qtrue );
}
diff --git a/src/renderer/tr_shadows.c b/src/renderer/tr_shadows.c
index 599b7067..eb28fc39 100644
--- a/src/renderer/tr_shadows.c
+++ b/src/renderer/tr_shadows.c
@@ -162,6 +162,7 @@ void RB_ShadowTessEnd( void ) {
int i;
int numTris;
vec3_t lightDir;
+ GLboolean rgba[4];
// we can only do this if we have enough space in the vertex buffers
if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) {
@@ -222,6 +223,7 @@ void RB_ShadowTessEnd( void ) {
qglColor3f( 0.2f, 0.2f, 0.2f );
// don't write to the color buffer
+ qglGetBooleanv(GL_COLOR_WRITEMASK, rgba);
qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
qglEnable( GL_STENCIL_TEST );
@@ -250,9 +252,8 @@ void RB_ShadowTessEnd( void ) {
R_RenderShadowEdges();
}
-
// reenable writing to the color buffer
- qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
+ qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
}
diff --git a/src/renderer/tr_sky.c b/src/renderer/tr_sky.c
index 91ce508f..889aa28c 100644
--- a/src/renderer/tr_sky.c
+++ b/src/renderer/tr_sky.c
@@ -576,6 +576,9 @@ static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean ad
tHeight = maxs[1] - mins[1] + 1;
sWidth = maxs[0] - mins[0] + 1;
+ // ydnar: overflow check
+ RB_CHECKOVERFLOW((maxs[0] - mins[0]) * (maxs[1] - mins[1]), (sWidth - 1) * (tHeight - 1) * 6);
+
for ( t = mins[1] + HALF_SKY_SUBDIVISIONS; t <= maxs[1] + HALF_SKY_SUBDIVISIONS; t++ )
{
for ( s = mins[0] + HALF_SKY_SUBDIVISIONS; s <= maxs[0] + HALF_SKY_SUBDIVISIONS; s++ )
@@ -716,7 +719,6 @@ static void FillCloudBox( const shader_t *shader, int stage ) {
** R_BuildCloudData
*/
void R_BuildCloudData( shaderCommands_t *input ) {
- int i;
shader_t *shader;
shader = input->shader;
@@ -731,13 +733,19 @@ void R_BuildCloudData( shaderCommands_t *input ) {
tess.numVertexes = 0;
if ( input->shader->sky.cloudHeight ) {
- for ( i = 0; i < MAX_SHADER_STAGES; i++ )
- {
- if ( !tess.xstages[i] ) {
+ // ok, this is really wierd. it's iterating through shader stages here,
+ // which is unecessary for a multi-stage sky shader, as far as i can tell
+ // nuking this
+#if 0
+ for (i = 0; i < MAX_SHADER_STAGES; i++) {
+ if (!tess.xstages[i]) {
break;
}
- FillCloudBox( input->shader, i );
+ FillCloudBox(input->shader, i);
}
+#else
+ FillCloudBox(input->shader, 0);
+#endif
}
}
@@ -826,6 +834,7 @@ void RB_DrawSun( void ) {
if ( !r_drawSun->integer ) {
return;
}
+ qglPushMatrix();
qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
qglTranslatef( backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2] );
@@ -850,58 +859,6 @@ void RB_DrawSun( void ) {
RB_BeginSurface( tr.sunShader, tess.fogNum );
RB_AddQuadStamp( origin, vec1, vec2, color );
-/*
- VectorCopy( origin, temp );
- VectorSubtract( temp, vec1, temp );
- VectorSubtract( temp, vec2, temp );
- VectorCopy( temp, tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = 0;
- tess.texCoords[tess.numVertexes][0][1] = 0;
- tess.vertexColors[tess.numVertexes][0] = 255;
- tess.vertexColors[tess.numVertexes][1] = 255;
- tess.vertexColors[tess.numVertexes][2] = 255;
- tess.numVertexes++;
-
- VectorCopy( origin, temp );
- VectorAdd( temp, vec1, temp );
- VectorSubtract( temp, vec2, temp );
- VectorCopy( temp, tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = 0;
- tess.texCoords[tess.numVertexes][0][1] = 1;
- tess.vertexColors[tess.numVertexes][0] = 255;
- tess.vertexColors[tess.numVertexes][1] = 255;
- tess.vertexColors[tess.numVertexes][2] = 255;
- tess.numVertexes++;
-
- VectorCopy( origin, temp );
- VectorAdd( temp, vec1, temp );
- VectorAdd( temp, vec2, temp );
- VectorCopy( temp, tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = 1;
- tess.texCoords[tess.numVertexes][0][1] = 1;
- tess.vertexColors[tess.numVertexes][0] = 255;
- tess.vertexColors[tess.numVertexes][1] = 255;
- tess.vertexColors[tess.numVertexes][2] = 255;
- tess.numVertexes++;
-
- VectorCopy( origin, temp );
- VectorSubtract( temp, vec1, temp );
- VectorAdd( temp, vec2, temp );
- VectorCopy( temp, tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = 1;
- tess.texCoords[tess.numVertexes][0][1] = 0;
- tess.vertexColors[tess.numVertexes][0] = 255;
- tess.vertexColors[tess.numVertexes][1] = 255;
- tess.vertexColors[tess.numVertexes][2] = 255;
- tess.numVertexes++;
-
- tess.indexes[tess.numIndexes++] = 0;
- tess.indexes[tess.numIndexes++] = 1;
- tess.indexes[tess.numIndexes++] = 2;
- tess.indexes[tess.numIndexes++] = 0;
- tess.indexes[tess.numIndexes++] = 2;
- tess.indexes[tess.numIndexes++] = 3;
-*/
RB_EndSurface();
@@ -936,12 +893,10 @@ void RB_DrawSun( void ) {
// back to normal depth range
qglDepthRange( 0.0, 1.0 );
+ qglPopMatrix();
}
-
-
extern void R_Fog( glfog_t *curfog );
-
/*
================
RB_StageIteratorSky
@@ -990,6 +945,8 @@ void RB_StageIteratorSky( void ) {
qglDepthRange( 1.0, 1.0 );
}
+ GL_Cull(CT_TWO_SIDED);
+
// draw the outer skybox
if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) {
qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
diff --git a/src/renderer/tr_surface.c b/src/renderer/tr_surface.c
index b444798e..7e60e460 100644
--- a/src/renderer/tr_surface.c
+++ b/src/renderer/tr_surface.c
@@ -464,6 +464,14 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f
vbase = tess.numVertexes;
+ // Gordon: configurable tile
+ if (backEnd.currentEntity->e.radius > 0) {
+ t = len / backEnd.currentEntity->e.radius;
+ }
+ else {
+ t = len / 256.f;
+ }
+
spanWidth2 = -spanWidth;
// FIXME: use quad stamp?
@@ -473,6 +481,7 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f
tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25;
tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25;
tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25;
+ tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3];
tess.numVertexes++;
VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] );
@@ -481,6 +490,7 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f
tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
+ tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3];
tess.numVertexes++;
VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] );
@@ -490,6 +500,7 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f
tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
+ tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3];
tess.numVertexes++;
VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] );
@@ -498,6 +509,7 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f
tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
+ tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3];
tess.numVertexes++;
tess.indexes[tess.numIndexes++] = vbase;
@@ -626,7 +638,7 @@ void RB_SurfaceRailCore( void ) {
CrossProduct( v1, v2, right );
VectorNormalize( right );
- DoRailCore( start, end, right, len, r_railCoreWidth->integer );
+ DoRailCore(start, end, right, len, e->frame > 0?e->frame:1);
}
/*
@@ -722,14 +734,12 @@ static void VectorArrayNormalize( vec4_t *normals, unsigned int count ) {
}
-
-
/*
** LerpMeshVertexes
*/
static void LerpMeshVertexes( md3Surface_t *surf, float backlerp ) {
- short *oldXyz, *newXyz, *oldNormals, *newNormals;
- float *outXyz, *outNormal;
+ short* oldXyz, * newXyz, * oldNormals, * newNormals;
+ float* outXyz, * outNormal;
float oldXyzScale, newXyzScale;
float oldNormalScale, newNormalScale;
int vertNum;
@@ -739,57 +749,58 @@ static void LerpMeshVertexes( md3Surface_t *surf, float backlerp ) {
outXyz = tess.xyz[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
- newXyz = ( short * )( (byte *)surf + surf->ofsXyzNormals )
- + ( backEnd.currentEntity->e.frame * surf->numVerts * 4 );
+ newXyz = (short*)((byte*)surf + surf->ofsXyzNormals)
+ + (backEnd.currentEntity->e.frame * surf->numVerts * 4);
newNormals = newXyz + 3;
- newXyzScale = MD3_XYZ_SCALE * ( 1.0 - backlerp );
+ newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
newNormalScale = 1.0 - backlerp;
numVerts = surf->numVerts;
- if ( backlerp == 0 ) {
+ if (backlerp == 0) {
//
// just copy the vertexes
//
- for ( vertNum = 0 ; vertNum < numVerts ; vertNum++,
- newXyz += 4, newNormals += 4,
- outXyz += 4, outNormal += 4 )
- {
+ for (vertNum = 0; vertNum < numVerts; vertNum++,
+ newXyz += 4, newNormals += 4,
+ outXyz += 4, outNormal += 4) {
outXyz[0] = newXyz[0] * newXyzScale;
outXyz[1] = newXyz[1] * newXyzScale;
outXyz[2] = newXyz[2] * newXyzScale;
- lat = ( newNormals[0] >> 8 ) & 0xff;
- lng = ( newNormals[0] & 0xff );
- lat *= ( FUNCTABLE_SIZE / 256 );
- lng *= ( FUNCTABLE_SIZE / 256 );
+ lat = (newNormals[0] >> 8) & 0xff;
+ lng = (newNormals[0] & 0xff);
+ lat *= (FUNCTABLE_SIZE / 256);
+ lng *= (FUNCTABLE_SIZE / 256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
- outNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng];
+ outNormal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng];
outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- outNormal[2] = tr.sinTable[( lng + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK];
+ outNormal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK];
}
- } else {
+ }
+ else {
//
// interpolate and copy the vertex and normal
//
- oldXyz = ( short * )( (byte *)surf + surf->ofsXyzNormals )
- + ( backEnd.currentEntity->e.oldframe * surf->numVerts * 4 );
+ oldXyz = (short*)((byte*)surf + surf->ofsXyzNormals)
+ + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
oldNormals = oldXyz + 3;
oldXyzScale = MD3_XYZ_SCALE * backlerp;
oldNormalScale = backlerp;
- for ( vertNum = 0 ; vertNum < numVerts ; vertNum++,
- oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
- outXyz += 4, outNormal += 4 )
- {
+ for (vertNum = 0; vertNum < numVerts; vertNum++,
+ oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
+ outXyz += 4, outNormal += 4) {
+#if 0
vec3_t uncompressedOldNormal, uncompressedNewNormal;
+#endif
// interpolate the xyz
outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
@@ -797,30 +808,44 @@ static void LerpMeshVertexes( md3Surface_t *surf, float backlerp ) {
outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
// FIXME: interpolate lat/long instead?
- lat = ( newNormals[0] >> 8 ) & 0xff;
- lng = ( newNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
- uncompressedNewNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng];
+ // ydnar: ok :)
+#if 0
+ lat = (newNormals[0] >> 8) & 0xff;
+ lng = (newNormals[0] & 0xff);
+ lat *= (FUNCTABLE_SIZE / 256);
+ lng *= (FUNCTABLE_SIZE / 256);
+ uncompressedNewNormal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- uncompressedNewNormal[2] = tr.sinTable[( lng + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK];
+ uncompressedNewNormal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK];
- lat = ( oldNormals[0] >> 8 ) & 0xff;
- lng = ( oldNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
+ lat = (oldNormals[0] >> 8) & 0xff;
+ lng = (oldNormals[0] & 0xff);
+ lat *= (FUNCTABLE_SIZE / 256);
+ lng *= (FUNCTABLE_SIZE / 256);
- uncompressedOldNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng];
+ uncompressedOldNormal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- uncompressedOldNormal[2] = tr.sinTable[( lng + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK];
+ uncompressedOldNormal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK];
outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
+#else
+ lat = myftol((((oldNormals[0] >> 8) & 0xFF) * (FUNCTABLE_SIZE / 256) * newNormalScale) +
+ (((oldNormals[0] >> 8) & 0xFF) * (FUNCTABLE_SIZE / 256) * oldNormalScale));
+ lng = myftol(((oldNormals[0] & 0xFF) * (FUNCTABLE_SIZE / 256) * newNormalScale) +
+ ((oldNormals[0] & 0xFF) * (FUNCTABLE_SIZE / 256) * oldNormalScale));
-// VectorNormalize (outNormal);
+ outNormal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng];
+ outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
+ outNormal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK];
+#endif
+
+ // VectorNormalize (outNormal);
}
- VectorArrayNormalize( (vec4_t *)tess.normal[tess.numVertexes], numVerts );
+
+ // ydnar: unecessary because of lat/lng lerping
+ //% VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes].v, numVerts);
}
}
@@ -960,8 +985,8 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) {
} else {
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
+ lat *= (FUNCTABLE_SIZE / 256); // was 4 :sigh:
+ lng *= (FUNCTABLE_SIZE / 256);
outNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng];
outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
@@ -1007,8 +1032,8 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) {
} else {
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
+ lat *= (FUNCTABLE_SIZE / 256); // was 4 :sigh:
+ lng *= (FUNCTABLE_SIZE / 256);
uncompressedNewNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
@@ -1022,8 +1047,8 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) {
} else {
lat = ( oldNormals[0] >> 8 ) & 0xff;
lng = ( oldNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
+ lat *= (FUNCTABLE_SIZE / 256); // was 4 :sigh:
+ lng *= (FUNCTABLE_SIZE / 256);
uncompressedOldNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
@@ -1155,9 +1180,9 @@ static float LodErrorForVolume( vec3_t local, float radius ) {
vec3_t world;
float d;
- // never let it go negative
- if ( r_lodCurveError->value < 0 ) {
- return 0;
+ // never let it go lower than 1
+ if (r_lodCurveError->value < 1) {
+ return 1;
}
world[0] = local[0] * backEnd.or.axis[0][0] + local[1] * backEnd.or.axis[1][0] +
diff --git a/src/renderer/tr_world.c b/src/renderer/tr_world.c
index 2d2120ae..e4a07776 100644
--- a/src/renderer/tr_world.c
+++ b/src/renderer/tr_world.c
@@ -141,19 +141,32 @@ static qboolean R_CullSurface( surfaceType_t *surface, shader_t *shader ) {
}
sface = ( srfSurfaceFace_t * ) surface;
- d = DotProduct( tr.or.viewOrigin, sface->plane.normal );
-
- // don't cull exactly on the plane, because there are levels of rounding
- // through the BSP, ICD, and hardware that may cause pixel gaps if an
- // epsilon isn't allowed here
- if ( shader->cullType == CT_FRONT_SIDED ) {
- if ( d < sface->plane.dist - 8 ) {
- return qtrue;
+ // L0 - ET Port
+ // plane cull
+ if (sface->plane.type != PLANE_NON_PLANAR && r_facePlaneCull->integer) {
+ d = DotProduct(tr. or .viewOrigin, sface->plane.normal) - sface->plane.dist;
+ /*
+ if (d > 0.0f) {
+ *frontFace = 1;
+ } */
+
+ // don't cull exactly on the plane, because there are levels of rounding
+ // through the BSP, ICD, and hardware that may cause pixel gaps if an
+ // epsilon isn't allowed here
+ if (shader->cullType == CT_FRONT_SIDED) {
+ if (d < -8.0f) {
+ //tr.pc.c_plane_cull_out++;
+ return qtrue;
+ }
}
- } else {
- if ( d > sface->plane.dist + 8 ) {
- return qtrue;
+ else if (shader->cullType == CT_BACK_SIDED) {
+ if (d > 8.0f) {
+ //tr.pc.c_plane_cull_out++;
+ return qtrue;
+ }
}
+
+ //tr.pc.c_plane_cull_in++;
}
return qfalse;
@@ -378,6 +391,7 @@ void R_AddBrushModelSurfaces( trRefEntity_t *ent ) {
return;
}
+ R_SetupEntityLighting(&tr.refdef, ent);
R_DlightBmodel( bmodel );
//----(SA) modified