Revelation Test

Discuss anything not covered by any of the other categories.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Revelation Test

Post by toneddu2000 »

you need to use the game dll's compiled from my sources else it will crash.
Yeah, used it
not entirely sure if its compatible wit the steam version either
probably not

EDIT: it crashes at same point (about 1/3 of loading bar during map open) even on Doom3 non Steam demo version
Meadow Fun!! - my first commercial game, made with FTEQW game engine
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

Sorry was away on family visit.

Hmm did you just copy the game dll's to base and d3xp ? or did you open pak003.pk4 and drop them in there ?.
Reason i ask is that if you just copy the game dll's to the folders they will get overwritten everytime you start a game by the game dll in pak003.pk4.
Better yet make a new zip file and name it pak004.pk4 with my dll in it, that way you can easily switch between vanilla and my version by just removing pak004.pk4 :)

the map loading bug sounds exactly like its trying to load the old vanilla dll :) happens here to unless i do as written above.
Productivity is a state of mind.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Revelation Test

Post by toneddu2000 »

thanks revelator, removing all the game*.pak (on base and d3xp) and place the new gamex86.dll in the base e d3xp folders did the trick, thanks! Adding a new .pak doesn't work. Anyway I found another little strange thing. Revelation.exe doesn't load savegames made with Vanilla doom3! If you press the button, nothing happens! But, fortunately, it works with revelation savegames, so.. no big deal! :D
Did you know that, if you delete gamex86.dll but leave original game pak files in places and launch Revelation.exe, after it crashes (because can't find its game dll due to the pak mixup problem explained above), it creates a shiny new gamex86.dll in the base folder? That's weird!

Anyway, supercool man, loadings are much faster with Revelation Engine! Thanks a lot for the effort!
Can you please post somewhere a list of features/enhancements of your engine?
Meadow Fun!! - my first commercial game, made with FTEQW game engine
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

it creates a shiny new gamex86.dll in the base folder? That's weird!
That dll is the one comming from the pak003.pk4 :) try opening pak003.pk4 in winzip / 7zip / winrar. You will see it contains the gamex86.dll ;).
Forgot to mention its not enough to just make a new pak004.pk4 and copy gamex86.dll into it you also need a small txt file called binary.conf.

The contents of the binary.conf are just ->

// win32-x86
0

ill pack up the game dll's in the next update so you only have to unzip the contents to the doom3 dir.
Productivity is a state of mind.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Revelation Test

Post by toneddu2000 »

revelator wrote: That dll is the one comming from the pak003.pk4 :)
Ah ok
revelator wrote: try opening pak003.pk4 in winzip / 7zip / winrar. You will see it contains the gamex86.dll ;).
no, no I knew that, it's only that I didn't know engine would have created a new dll file at runtime
revelator wrote: Forgot to mention its not enough to just make a new pak004.pk4 and copy gamex86.dll into it you also need a small txt file called binary.conf.
The contents of the binary.conf are just ->
// win32-x86
0
Thanks a lot, it worked even this way!
revelator wrote:
ill pack up the game dll's in the next update so you only have to unzip the contents to the doom3 dir.
Thanks! There's a way to alter the source to make the engine search something like "gamerevelationx86.dll" instead of gamex86.dll? In that way both exes could coexist in same folder!

I tried also sikkmod and to make it work (even on Vanilla Steam installation) you have to delete game.pk4 on sikkmod but (nor Vanilla and neither Revelation) show softshadows, AO, bloom, etc. are not activated
Meadow Fun!! - my first commercial game, made with FTEQW game engine
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

My sources contain ported game dll's for sikkmod / sikkmodd3xp / grimm quest / classic doom so ill prepare a package with those :)

Making it look for a revelation.dll could work but would be a little messy code wise, ill see what i can do though.
Productivity is a state of mind.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Revelation Test

Post by toneddu2000 »

My sources contain ported game dll's for sikkmod / sikkmodd3xp / grimm quest / classic doom so ill prepare a package with those
Cool thanks!
Making it look for a revelation.dll could work but would be a little messy code wise, ill see what i can do though.
No, no it wasn't meant my intention to "force" you to do so. Just curious it could be done and how
Meadow Fun!! - my first commercial game, made with FTEQW game engine
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

should be doable even quite easy but revelation would not be compatible with dll's that use the gamex86 name anymore.
In regard to that its upto developers to make sure there game dll sources are compatible with revelation then.
As a bonus though they get an engine with less overhead due to the removal of the editors (if they prefer that) or else wait untill the tools are ported from MFC to WxWidgets.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

Havent updated here in a while, been busy because of a bug in my new msys2 based compiler causing it to be unable to bootstrap gcc.
The bug has been forwarded to the Msys2 dev and is now investigated, so a fix might be out soon.
Ill return to making a new uodate package soon.
P.s i noticed a small whoops in my little tutorial,
one of the functions i told to add is the existing one not the one to add.
Ill cleanup the tut soon also.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

Ok Msys2 bug found and squashed painfully :P

Also some news that might interrest people working on the vanilla Doom3 source or ports of it.
After some lenghty discussion on the darkmod forums i decided to take the question about some disabled shaders in BFG to the current BFG maintainer.
he confirmed that glasswarp was newer used (not even in vanilla) so remove at best pace (p.s the glasswarp shaders are the two only shaders with a .txt suffix instead of .vp / .fp or .vfp).
also if your port uses the arb2 backend only you can safely remove all the enums for the r200 and older nvidia shaders.
should not cause any bugs leaving them in but its confusing and unnessesary, the source will be a lot more readable as a result.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

Big news.

After quite some brainstorming, me and steveL at the darkmod forums finally have a working way to Copy of the depthbuffer in vanilla.
This means its now possible to do proper SSAO / depth tested particles / and pretty much anything else that needs access to the depthbuffer :).
steveL has created a test shader in ARB assembly so you can try out the effect allready.

!!ARBvp1.0
OPTION ARB_position_invariant;
MOV result.texcoord, vertex.texcoord;
END

!!ARBfp1.0
PARAM clipPlanes = { 0.4, 350.0 };
TEMP dpth, col, rng;
TEX dpth, fragment.texcoord, texture[0], 2D;
ADD rng.x, clipPlanes.y, -clipPlanes.x;
MUL col.x, dpth.x, rng.x;
ADD col.x, -col.x, clipPlanes.x;
ADD col.x, col.x, clipPlanes.y;
RCP rng.x, col.x;
MUL col.x, rng.x, clipPlanes.x;
MUL col.x, col.x, 2.0;
MOV result.color.r, col.x;
MOV result.color.g, col.x;
MOV result.color.b, col.x;
MOV result.color.a, 1.0;
END
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

Fixed about 90% of the problems with SSAO after we got working depthbuffer code, no outlines in skyboxes / heathaze anymore, but particles might sometimes still show outlines when SSAO is enabled,
and i introduced a new bug when changing sikkmods depthbuffer code to use our new function, causing sunshafts to look really weird (massive lighting bleed).
It only happens in sunshafts so i suspect its a bug with the code for it, but if someone can fix it the next release will be much closer.
Productivity is a state of mind.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Revelation Test

Post by toneddu2000 »

yay! Glad you keep working on it, great job!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

Refined a few things in the original code for depth buffer access :) which means you can now suppress surfaces that may be problematic in a depth view, and i created a specialized function for creating the depth image instead of just using the rgba code path. Much of this code was created using the code in draw_exp.cpp.

The depth image is clamped to the border of the color image and no downscaling is allowed to avoid artifacts.
There are a few buggers with sikkmods old code though. Though theres no outlines in heathaze anymore i noticed that when crawling over a surface with lots of heathaze (lava) that a faint outline seems to curl up
into view. Sunshafts as mentioned earlier. And even though lensflares are disabled im still getting a lensflare effect hmm ???.
Productivity is a state of mind.
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: Revelation Test

Post by revelator »

Been a long time since i last done some work on any engine, so in a fit of boredom i added an old friend of mine to doom3

Code: Select all

/*
================
BorderCheck macro. the pixels that get passed in should be pre-converted
to the YCbCr colorspace.
================
*/
#define BorderCheck( pix1, pix2, dY, dCb, dCr ) ( ( abs( *pix1 - *pix2 ) > dY ) || ( abs( *( pix1 + 1 ) - *( pix2 + 1 ) ) > dCb ) || ( abs( *(pix1 + 2) - *( pix2 + 2) ) > dCr) )

/*
================
LinearScale macro.
================
*/
#define LinearScale( src1, src2, pct ) ( ( src1 * (1 - pct) ) + ( src2 * pct) )

/*
================
GetOffSet macro.
================
*/
#define GetOffSet( new, start, cur ) ( new + ( cur - ( static_cast< unsigned char * >( start ) ) ) )

/*
================
Clamp macro.
================
*/
#define Clamp( a, b, c ) ( max( a, min( b, c ) ) )

/*
================
RGBAtoTCbCrA - converts a source RGBA pixel into a destination YCbCrA pixel
================
*/
ID_INLINE void RGBAtoYCbCrA( unsigned char *dest, unsigned char *src )
{
	unsigned char s0, s1, s2;
	
	s0 = *( src );
	s1 = *( src + 1 );
	s2 = *( src + 2 );
	
#define MIX(i, n, m0, m1, m2) ( *( dest + i ) = static_cast< unsigned char >( n + ( ( ( s0 * m0 ) + ( s1 * m0 ) + ( s2 * m2 )) / 256.0f ) ) )
	    MIX( 0, 16.0f, 65.738f, 129.057f, 25.064f );
	    MIX( 1, 128.0f, -37.945f, -74.494f, 112.439f );
	    MIX( 2, 128.0f, 112.439f, -94.154f, -18.285f );
#undef  MIX
	
	*( dest + 3 ) = *( src + 3 );
}

/*
================
R_ResampleTexture - resamples the texture given in indata, of the
dimensions inwidth by inheight to outdata, of the dimensions outwidth by
outheight, using a method based on the brief description of SmartFlt
given at http://www.hiend3d.com/smartflt.html
this could probably do with some optimizations.
================
*/
void R_ResampleTexture( void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight )
{
	float	xstep = ( static_cast< float >( inwidth ) ) / ( static_cast< float >( outwidth ) );
	float	ystep = ( static_cast< float >( inheight ) ) / ( static_cast< float >( outheight ) );
	
	int		dY = r_smartflt_y.GetInteger();
	int		dCb = r_smartflt_cb.GetInteger();
	int		dCr = r_smartflt_cr.GetInteger();
	
	int		DestX, DestY;
	float	SrcX, SrcY;
	
	// buffer to store the YCbCrA version of the input texture.
	unsigned char *Ybuffer = static_cast< byte * >( R_StaticAlloc( inwidth * inheight * 4 ) );
	unsigned char *id = static_cast< byte * >( indata );
	unsigned char *od = static_cast< byte * >( outdata );
	unsigned char *idrowstart = id;
	
	// convert the input texture to YCbCr into a temp buffer, for border detections.
	for( DestX = 0, idrowstart = Ybuffer; DestX < ( inwidth * inheight ); DestX++, idrowstart += 4, id += 4 )
	{
		RGBAtoYCbCrA( idrowstart, id );
	}
	
	for( DestY = 0, SrcY = 0; DestY < outheight; DestY++, SrcY += ystep )
	{
		// four "work" pointers to make code a little nicer.
		unsigned char	*w0, *w1, *w2, *w3;
		
		// right == clockwise, left == counter-clockwise
		unsigned char	*nearest, *left, *right, *opposite;
		float			pctnear, pctleft, pctright, pctopp;
		float			w0pct, w1pct, w2pct, w3pct;
		float			x, y, tmpx, tmpy;
		char			edges[6];
		
		// clamp SrcY to cover for possible float error
		// to make sure the edges fall into the special cases
		if( SrcY > ( inheight - 1.01f ) )
		{
			SrcY = ( inheight - 1.01f );
		}
		
		// go to the start of the next row. "od" should be pointing at the right place already.
		idrowstart = ( static_cast< byte * >( indata ) ) + ( static_cast< int >( SrcY ) ) * inwidth * 4;
		
		for( DestX = 0, SrcX = 0; DestX < outwidth; DestX++, od += 4, SrcX += xstep )
		{
			// clamp SrcY to cover for possible float error
			// to make sure that the edges fall into the special cases
			if( SrcX > ( inwidth - 1.01f ) )
			{
				SrcX = inwidth - 1.01f;
			}
			id = idrowstart + ( static_cast< int >( SrcX ) ) * 4;
			
			x = ( static_cast< int >( SrcX ) );
			y = ( static_cast< int >( SrcY ) );
			
			// if we happen to be directly on a source row
			if( SrcY == y )
			{
				// and also directly on a source column
				if( SrcX == x )
				{
					// then we are directly on a source pixel
					// just copy it and move on.
					SIMDProcessor->Memcpy( od, id, 4 );
					continue;
				}
				
				// if there is a border between the two surrounding source pixels
				if( BorderCheck( GetOffSet( Ybuffer, indata, id ), GetOffSet( Ybuffer, indata, ( id + 4 ) ), dY, dCb, dCr ) )
				{
					// if we are closer to the left
					if( x == ( static_cast< int >( SrcX + 0.5f ) ) )
					{
						// copy the left pixel
						SIMDProcessor->Memcpy( od, id, 4 );
						continue;
					}
					else
					{
						// otherwise copy the right pixel
						SIMDProcessor->Memcpy( od, id + 4, 4 );
						continue;
					}
				}
				else
				{
					// these two bordering pixels are part of the same region.
					// blend them using a weighted average
					x = SrcX - x;
					
					w0 = id;
					w1 = id + 4;
					
					*od = static_cast< unsigned char >( LinearScale( *w0, *w1, x ) );
					*( od + 1 ) = static_cast< unsigned char >( LinearScale( *( w0 + 1 ), *( w1 + 1 ), x ) );
					*( od + 2 ) = static_cast< unsigned char >( LinearScale( *( w0 + 2 ), *( w1 + 2 ), x ) );
					*( od + 3 ) = static_cast< unsigned char >( LinearScale( *( w0 + 3 ), *( w1 + 3 ), x ) );
					
					continue;
				}
			}
			
			// if we aren't direcly on a source row, but we are on a source column
			if( SrcX == x )
			{
				// if there is a border between this source pixel and the one on
				// the next row
				if( BorderCheck( GetOffSet( Ybuffer, indata, id ), GetOffSet( Ybuffer, indata, ( id + inwidth * 4 ) ), dY, dCb, dCr ) )
				{
					// if we are closer to the top
					if( y == ( static_cast< int >( SrcY + 0.5f ) ) )
					{
						// copy the top
						SIMDProcessor->Memcpy( od, id, 4 );
						continue;
					}
					else
					{
						// copy the bottom
						SIMDProcessor->Memcpy( od, (id + inwidth * 4), 4 );
						continue;
					}
				}
				else
				{
					// the two pixels are part of the same region, blend them
					// together with a weighted average
					y = SrcY - y;
					
					w0 = id;
					w1 = id + ( inwidth * 4 );
					
					*od = static_cast< unsigned char >( LinearScale( *w0, *w1, y ) );
					*( od + 1 ) = static_cast< unsigned char >( LinearScale( *( w0 + 1 ), *( w1 + 1 ), y ) );
					*( od + 2 ) = static_cast< unsigned char >( LinearScale( *( w0 + 2 ), *( w1 + 2 ), y ) );
					*( od + 3 ) = static_cast< unsigned char >( LinearScale( *( w0 + 3 ), *( w1 + 3 ), y ) );
					
					continue;
				}
			}
			
			// now for the non-simple case: somewhere between four pixels.
			// w0 is top-left, w1 is top-right, w2 is bottom-left, and w3 is bottom-right
			w0 = id;
			w1 = id + 4;
			w2 = id + ( inwidth * 4 );
			w3 = w2 + 4;
			
			x = SrcX - x;
			y = SrcY - y;
			
			w0pct = 1.0f - sqrtf( x * x + y * y );
			w1pct = 1.0f - sqrtf( ( 1 - x ) * ( 1 - x ) + y * y );
			w2pct = 1.0f - sqrtf( x * x + ( 1 - y ) * ( 1 - y ) );
			w3pct = 1.0f - sqrtf( ( 1 - x ) * ( 1 - x ) + ( 1 - y ) * ( 1 - y ) );
			
			// set up our symbolic identification.
			// "nearest" is the pixel whose quadrant we are in.
			// "left" is counter-clockwise from "nearest"
			// "right" is clockwise from "nearest"
			// "opposite" is, well, opposite.
			if( x < 0.5f )
			{
				tmpx = x;
				
				if( y < 0.5f )
				{
					nearest = w0;
					left = w2;
					right = w1;
					opposite = w3;
					pctnear = w0pct;
					pctleft = w2pct;
					pctright = w1pct;
					pctopp = w3pct;
					tmpy = y;
				}
				else
				{
					nearest = w2;
					left = w3;
					right = w0;
					opposite = w1;
					pctnear = w2pct;
					pctleft = w3pct;
					pctright = w0pct;
					pctopp = w1pct;
					tmpy = 1.0f - y;
				}
			}
			else
			{
				tmpx = 1.0f - x;
				
				if( y < 0.5f )
				{
					nearest = w1;
					left = w0;
					right = w3;
					opposite = w2;
					pctnear = w1pct;
					pctleft = w0pct;
					pctright = w3pct;
					pctopp = w2pct;
					tmpy = y;
				}
				else
				{
					nearest = w3;
					left = w1;
					right = w2;
					opposite = w0;
					pctnear = w3pct;
					pctleft = w1pct;
					pctright = w2pct;
					pctopp = w0pct;
					tmpy = 1.0f - y;
				}
			}
			x = tmpx;
			y = tmpy;
			
			w0 = GetOffSet( Ybuffer, indata, nearest );
			w1 = GetOffSet( Ybuffer, indata, right );
			w2 = GetOffSet( Ybuffer, indata, left );
			w3 = GetOffSet( Ybuffer, indata, opposite );
			
			edges[0] = BorderCheck( w0, w2, dY, dCb, dCr );
			edges[1] = BorderCheck( w0, w1, dY, dCb, dCr );
			edges[2] = BorderCheck( w0, w3, dY, dCb, dCr );
			
			edges[3] = BorderCheck( w3, w2, dY, dCb, dCr );
			edges[4] = BorderCheck( w3, w1, dY, dCb, dCr );
			edges[5] = BorderCheck( w2, w1, dY, dCb, dCr );
			
#undef GetOffSet
			
			// do the edge detections.
			if( edges[0] && edges[1] && edges[2] && !edges[5] )
			{
				// borders all around, and no border between the left and right.
				// if there is no border between the opposite side and only one
				// of the two other corners, or if we are closer to the corner
				if( ( edges[3] && !edges[4] ) || ( !edges[3] && edges[4] ) || ( x + y < 0.5f ) )
				{
					// closer to to the corner.
					SIMDProcessor->Memcpy( od, nearest, 4 );
				}
				else
				{
					// closer to the center. (note, there is a diagonal line between the nearest pixel
					// and the center of the four.)
					
					// exclude the "nearest" pixel
					// pctnear = 0.0f;
					// if there is a border around the opposite corner,
					// exclude it from the current pixel.
					if( edges[3] && edges[4] )
					{
						// pctopp = 0.0f;
						*od = static_cast< unsigned char >( Clamp( 0, ( ( ( *left * pctleft ) + ( *right * pctright ) ) / ( pctleft + pctright ) ), 255 ) );
						*( od + 1 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 1 ) * pctleft ) + ( *( right + 1 ) * pctright ) ) / ( pctleft + pctright ) ), 255 ) );
						*( od + 2 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 2 ) * pctleft ) + ( *( right + 2 ) * pctright ) ) / ( pctleft + pctright ) ), 255 ) );
						*( od + 3 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 3 ) * pctleft ) + ( *( right + 3 ) * pctright ) ) / ( pctleft + pctright ) ), 255 ) );
					}
					else
					{
						*od = static_cast< unsigned char >( Clamp( 0, ( ( ( *left * pctleft ) + ( *right * pctright ) + ( *opposite * pctopp ) ) / ( pctleft + pctright + pctopp ) ), 255 ) );
						*( od + 1 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 1 ) * pctleft ) + ( *( right + 1 ) * pctright ) + ( *( opposite + 1 ) * pctopp ) ) / ( pctleft + pctright + pctopp ) ), 255 ) );
						*( od + 2 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 2 ) * pctleft ) + ( *( right + 2 ) * pctright ) + ( *( opposite + 2 ) * pctopp ) ) / ( pctleft + pctright + pctopp ) ), 255 ) );
						*( od + 3 ) = static_cast< unsigned char >( Clamp( 0, ( ( ( *( left + 3 ) * pctleft ) + ( *( right + 3 ) * pctright ) + ( *( opposite + 3 ) * pctopp ) ) / ( pctleft + pctright + pctopp ) ), 255 ) );
					}
				}
			}
			else if( edges[0] && edges[1] && edges[2] )
			{
				SIMDProcessor->Memcpy( od, nearest, 4 );
			}
			else
			{
				float num[4], denom = pctnear;
				
				num[0] = ( *nearest * pctnear );
				num[1] = ( *( nearest + 1 ) * pctnear );
				num[2] = ( *( nearest + 2 ) * pctnear );
				num[3] = ( *( nearest + 3 ) * pctnear );
				
				if( !edges[0] )
				{
					num[0] += *left * pctleft;
					num[1] += *( left + 1 ) * pctleft;
					num[2] += *( left + 2 ) * pctleft;
					num[3] += *( left + 3 ) * pctleft;
					denom += pctleft;
				}
				
				if( edges[1] )
				{
					num[0] += *right * pctright;
					num[1] += *( right + 1 ) * pctright;
					num[2] += *( right + 2 ) * pctright;
					num[3] += *( right + 3 ) * pctright;
					denom += pctright;
				}
				
				if( edges[2] )
				{
					num[0] += *opposite * pctopp;
					num[1] += *( opposite + 1 ) * pctopp;
					num[2] += *( opposite + 2 ) * pctopp;
					num[3] += *( opposite + 3 ) * pctopp;
					denom += pctopp;
				}
				
				// blend the source pixels together to get the output pixel.
				// if a source pixel doesn't affect the output, it's percent should be set to 0 in the edge check
				// code above. if only one pixel affects the output, its percentage should be set to 1 and all
				// the others set to 0. (yeah, it is ugly, but I don't see a need to optimize this code (yet)
				*od = static_cast< unsigned char >( Clamp( 0, num[0] / denom, 255 ) );
				*( od + 1 ) = static_cast< unsigned char >( Clamp( 0, num[1] / denom, 255 ) );
				*( od + 2 ) = static_cast< unsigned char >( Clamp( 0, num[2] / denom, 255 ) );
				*( od + 3 ) = static_cast< unsigned char >( Clamp( 0, num[3] / denom, 255 ) );
			}
		}
	}
	R_StaticFree( Ybuffer );
}
this replaces the old resampletexture function

you need to call it in a different way than the old one to so modify R_LoadImage to look like this

Code: Select all

void R_LoadImage( const char *cname, byte **pic, int *width, int *height, ID_TIME_T *timestamp, bool makePowerOf2 )
{
	idStr name = cname;
	
	if( pic )
	{
		*pic = NULL;
	}
	
	if( timestamp )
	{
		*timestamp = 0xFFFFFFFF;
	}
	
	if( width )
	{
		*width = 0;
	}
	
	if( height )
	{
		*height = 0;
	}
	name.DefaultFileExtension( ".tga" );
	
	if( name.Length() < 5 )
	{
		return;
	}
	name.ToLower();
	idStr ext;
	name.ExtractFileExtension( ext );
	
	if( ext == "tga" )
	{
		LoadTGA( name.c_str(), pic, width, height, timestamp );            // try tga first
		
		if( ( pic && *pic == 0 ) || ( timestamp && *timestamp == -1 ) )
		{
			name.StripFileExtension();
			name.DefaultFileExtension( ".jpg" );
			LoadJPG( name.c_str(), pic, width, height, timestamp );
		}
	}
	else if( ext == "pcx" )
	{
		LoadPCX32( name.c_str(), pic, width, height, timestamp );
	}
	else if( ext == "bmp" )
	{
		LoadBMP( name.c_str(), pic, width, height, timestamp );
	}
	else if( ext == "jpg" )
	{
		LoadJPG( name.c_str(), pic, width, height, timestamp );
	}
	
	if( ( width && *width < 1 ) || ( height && *height < 1 ) )
	{
		if( pic && *pic )
		{
			R_StaticFree( *pic );
			*pic = 0;
		}
	}
	
	//
	// convert to exact power of 2 sizes
	//
	if( pic && *pic && makePowerOf2 )
	{
		int		w, h;
		int		scaled_width, scaled_height;
		byte	*pic_p;
		
		w = *width;
		h = *height;
		
		Q_ROUND_POWER2( w, scaled_width );
		Q_ROUND_POWER2( h, scaled_height );
		
		if( scaled_width != w || scaled_height != h )
		{
			if( globalImages->image_roundDown.GetBool() && scaled_width > w )
			{
				scaled_width >>= 1;
			}
			
			if( globalImages->image_roundDown.GetBool() && scaled_height > h )
			{
				scaled_height >>= 1;
			}
			pic_p = ( byte * ) R_StaticAlloc( scaled_width * scaled_height * 4 );
			R_ResampleTexture( *pic, w, h, pic_p, scaled_width, scaled_height );
			R_StaticFree( *pic );
			*pic = pic_p;
			*width = scaled_width;
			*height = scaled_height;
		}
	}
}
the Q_ROUND_POWER2 macros are just replacements for the round down functions, you can skip those if you want.

you also need these at the top of image_process.cpp

idCVar r_smartflt_y( "r_smartflt_y", "10", CVAR_INTEGER | CVAR_RENDERER, "Smart Filter Y Value" );
idCVar r_smartflt_cb( "r_smartflt_cb", "50", CVAR_INTEGER | CVAR_RENDERER, "Smart Filter CB Value" );
idCVar r_smartflt_cr( "r_smartflt_cr", "50", CVAR_INTEGER | CVAR_RENDERER, "Smart Filter CR Value" );

these allow you to fiddle a bit with the resample colors.

this resampling code is very old (around darkplaces 1.5 time) but has superior image quality (noticable in ultra where textures are now very sharp).

also cleaned up the thread code with a small addition gleaned from darkmod (originally based on boost)

Code: Select all

/*
==================
Sys_Createthread
==================
*/
typedef std::pair<xthread_t, void *> CreateThreadStartParams;
DWORD WINAPI CreateThreadStartRoutine( LPVOID lpThreadParameter )
{
	std::pair<xthread_t, void *> arg = *( ( CreateThreadStartParams * )lpThreadParameter );
	delete( ( CreateThreadStartParams * )lpThreadParameter );
	return arg.first( arg.second );
}

void Sys_CreateThread( xthread_t function, void *parms, xthreadPriority priority, xthreadInfo &info, const char *name, xthreadInfo *threads[MAX_THREADS], int *thread_count )
{
	LPVOID helperParam = new CreateThreadStartParams( function, parms );
	HANDLE temp = CreateThread( NULL,						// LPSECURITY_ATTRIBUTES lpsa,
								0,						// DWORD cbStack,
								CreateThreadStartRoutine,	// LPTHREAD_START_ROUTINE lpStartAddr,
								helperParam,				// LPVOID lpvThreadParm,
								0,						// DWORD fdwCreate,
								&info.threadId );
	info.threadHandle = ( intptr_t )temp;
	
	if( priority == THREAD_HIGHEST )
	{
		SetThreadPriority( ( HANDLE ) info.threadHandle, THREAD_PRIORITY_HIGHEST );		//  we better sleep enough to do this
	}
	else if( priority == THREAD_ABOVE_NORMAL )
	{
		SetThreadPriority( ( HANDLE ) info.threadHandle, THREAD_PRIORITY_ABOVE_NORMAL );
	}
	else
	{
		SetThreadPriority( ( HANDLE ) info.threadHandle, THREAD_PRIORITY_NORMAL );
	}
	info.name = name;
	
	if( *thread_count <= MAX_THREADS )
	{
		threads[( *thread_count ) ++] = &info;
	}
	else
	{
		common->DPrintf( "WARNING: MAX_THREADS reached\n" );
	}
}
now uses std functionality for the same effect.

the helper now correctly passes the thread to CreateThread.
Productivity is a state of mind.
Post Reply